Skip to content

Commit 5193c21

Browse files
Do not coerce places if they do not constitute reads
1 parent 6371ef6 commit 5193c21

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
@@ -1038,7 +1044,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10381044
/// The expressions *must not* have any preexisting adjustments.
10391045
pub(crate) fn coerce(
10401046
&self,
1041-
expr: &hir::Expr<'_>,
1047+
expr: &'tcx hir::Expr<'tcx>,
10421048
expr_ty: Ty<'tcx>,
10431049
mut target: Ty<'tcx>,
10441050
allow_two_phase: AllowTwoPhase,
@@ -1055,7 +1061,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10551061

10561062
let cause =
10571063
cause.unwrap_or_else(|| self.cause(expr.span, ObligationCauseCode::ExprAssignable));
1058-
let coerce = Coerce::new(self, cause, allow_two_phase);
1064+
let coerce = Coerce::new(self, cause, allow_two_phase, self.expr_constitutes_read(expr));
10591065
let ok = self.commit_if_ok(|_| coerce.coerce(source, target))?;
10601066

10611067
let (adjustments, _) = self.register_infer_ok_obligations(ok);
@@ -1078,7 +1084,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10781084

10791085
let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable);
10801086
// We don't ever need two-phase here since we throw out the result of the coercion
1081-
let coerce = Coerce::new(self, cause, AllowTwoPhase::No);
1087+
let coerce = Coerce::new(self, cause, AllowTwoPhase::No, true);
10821088
self.probe(|_| {
10831089
let Ok(ok) = coerce.coerce(source, target) else {
10841090
return false;
@@ -1095,7 +1101,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10951101
pub(crate) fn deref_steps(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> Option<usize> {
10961102
let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable);
10971103
// We don't ever need two-phase here since we throw out the result of the coercion
1098-
let coerce = Coerce::new(self, cause, AllowTwoPhase::No);
1104+
let coerce = Coerce::new(self, cause, AllowTwoPhase::No, true);
10991105
coerce
11001106
.autoderef(DUMMY_SP, expr_ty)
11011107
.find_map(|(ty, steps)| self.probe(|_| coerce.unify(ty, target)).ok().map(|_| steps))
@@ -1252,7 +1258,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12521258
// probably aren't processing function arguments here and even if we were,
12531259
// they're going to get autorefed again anyway and we can apply 2-phase borrows
12541260
// at that time.
1255-
let mut coerce = Coerce::new(self, cause.clone(), AllowTwoPhase::No);
1261+
let mut coerce = Coerce::new(self, cause.clone(), AllowTwoPhase::No, true);
12561262
coerce.use_lub = true;
12571263

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

0 commit comments

Comments
 (0)