Skip to content

Commit d04b116

Browse files
Do not coerce places if they do not constitute reads
1 parent 45f830a commit d04b116

File tree

1 file changed

+13
-7
lines changed

1 file changed

+13
-7
lines changed

compiler/rustc_hir_typeck/src/coercion.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ struct Coerce<'a, 'tcx> {
8282
/// See #47489 and #48598
8383
/// See docs on the "AllowTwoPhase" type for a more detailed discussion
8484
allow_two_phase: AllowTwoPhase,
85+
coerce_never: bool,
8586
}
8687

8788
impl<'a, 'tcx> Deref for Coerce<'a, 'tcx> {
@@ -125,8 +126,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
125126
fcx: &'f FnCtxt<'f, 'tcx>,
126127
cause: ObligationCause<'tcx>,
127128
allow_two_phase: AllowTwoPhase,
129+
coerce_never: bool,
128130
) -> Self {
129-
Coerce { fcx, cause, allow_two_phase, use_lub: false }
131+
Coerce { fcx, cause, allow_two_phase, use_lub: false, coerce_never }
130132
}
131133

132134
fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> {
@@ -177,7 +179,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
177179

178180
// Coercing from `!` to any type is allowed:
179181
if a.is_never() {
180-
return success(simple(Adjust::NeverToAny)(b), b, vec![]);
182+
if self.coerce_never {
183+
return success(simple(Adjust::NeverToAny)(b), b, vec![]);
184+
} else {
185+
return self.unify_and(a, b, identity);
186+
}
181187
}
182188

183189
// Coercing *from* an unresolved inference variable means that
@@ -979,7 +985,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
979985
/// The expressions *must not* have any preexisting adjustments.
980986
pub(crate) fn coerce(
981987
&self,
982-
expr: &hir::Expr<'_>,
988+
expr: &'tcx hir::Expr<'tcx>,
983989
expr_ty: Ty<'tcx>,
984990
mut target: Ty<'tcx>,
985991
allow_two_phase: AllowTwoPhase,
@@ -996,7 +1002,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
9961002

9971003
let cause =
9981004
cause.unwrap_or_else(|| self.cause(expr.span, ObligationCauseCode::ExprAssignable));
999-
let coerce = Coerce::new(self, cause, allow_two_phase);
1005+
let coerce = Coerce::new(self, cause, allow_two_phase, self.expr_constitutes_read(expr));
10001006
let ok = self.commit_if_ok(|_| coerce.coerce(source, target))?;
10011007

10021008
let (adjustments, _) = self.register_infer_ok_obligations(ok);
@@ -1019,7 +1025,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10191025

10201026
let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable);
10211027
// We don't ever need two-phase here since we throw out the result of the coercion
1022-
let coerce = Coerce::new(self, cause, AllowTwoPhase::No);
1028+
let coerce = Coerce::new(self, cause, AllowTwoPhase::No, true);
10231029
self.probe(|_| {
10241030
let Ok(ok) = coerce.coerce(source, target) else {
10251031
return false;
@@ -1036,7 +1042,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10361042
pub(crate) fn deref_steps(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> Option<usize> {
10371043
let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable);
10381044
// We don't ever need two-phase here since we throw out the result of the coercion
1039-
let coerce = Coerce::new(self, cause, AllowTwoPhase::No);
1045+
let coerce = Coerce::new(self, cause, AllowTwoPhase::No, true);
10401046
coerce
10411047
.autoderef(DUMMY_SP, expr_ty)
10421048
.find_map(|(ty, steps)| self.probe(|_| coerce.unify(ty, target)).ok().map(|_| steps))
@@ -1193,7 +1199,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11931199
// probably aren't processing function arguments here and even if we were,
11941200
// they're going to get autorefed again anyway and we can apply 2-phase borrows
11951201
// at that time.
1196-
let mut coerce = Coerce::new(self, cause.clone(), AllowTwoPhase::No);
1202+
let mut coerce = Coerce::new(self, cause.clone(), AllowTwoPhase::No, true);
11971203
coerce.use_lub = true;
11981204

11991205
// First try to coerce the new expression to the type of the previous ones,

0 commit comments

Comments
 (0)