Skip to content

Commit f97c37f

Browse files
committed
coerce_inner: use initial expected_ty
1 parent 3964a55 commit f97c37f

3 files changed

+63
-2
lines changed

src/librustc_typeck/check/coercion.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -1289,8 +1289,20 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
12891289
}
12901290

12911291
// Error possibly reported in `check_assign` so avoid emitting error again.
1292-
err.emit_unless(expression.filter(|e| fcx.is_assign_to_bool(e, expected))
1293-
.is_some());
1292+
let assign_to_bool = expression
1293+
// #67273: Use initial expected type as opposed to `expected`.
1294+
// Otherwise we end up using prior coercions in e.g. a `match` expression:
1295+
// ```
1296+
// match i {
1297+
// 0 => true, // Because of this...
1298+
// 1 => i = 1, // ...`expected == bool` now, but not when checking `i = 1`.
1299+
// _ => (),
1300+
// };
1301+
// ```
1302+
.filter(|e| fcx.is_assign_to_bool(e, self.expected_ty()))
1303+
.is_some();
1304+
1305+
err.emit_unless(assign_to_bool);
12941306

12951307
self.final_ty = Some(fcx.tcx.types.err);
12961308
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
fn main() {
2+
let mut i: i64;
3+
// Expected type is an inference variable `?T`
4+
// because the `match` is used as a statement.
5+
// This is the "initial" type of the `coercion`.
6+
match i {
7+
// Add `bool` to the overall `coercion`.
8+
0 => true,
9+
10+
// Necessary to cause the ICE:
11+
1 => true,
12+
13+
// Suppose that we had `let _: bool = match i { ... }`.
14+
// In that case, as the expected type would be `bool`,
15+
// we would suggest `i == 1` as a fix.
16+
//
17+
// However, no type error happens when checking `i = 1` because `expected == ?T`,
18+
// which will unify with `typeof(i = 1) == ()`.
19+
//
20+
// However, in #67273, we would delay the unification of this arm with the above
21+
// because we used the hitherto accumulated coercion as opposed to the "initial" type.
22+
2 => i = 1,
23+
//~^ ERROR match arms have incompatible types
24+
25+
_ => (),
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0308]: match arms have incompatible types
2+
--> $DIR/issue-67273-assignment-match-prior-arm-bool-expected-unit.rs:22:14
3+
|
4+
LL | / match i {
5+
LL | | // Add `bool` to the overall `coercion`.
6+
LL | | 0 => true,
7+
| | ---- this is found to be of type `bool`
8+
LL | |
9+
LL | | // Necessary to cause the ICE:
10+
LL | | 1 => true,
11+
| | ---- this is found to be of type `bool`
12+
... |
13+
LL | | 2 => i = 1,
14+
| | ^^^^^ expected `bool`, found `()`
15+
... |
16+
LL | | _ => (),
17+
LL | | }
18+
| |_____- `match` arms have incompatible types
19+
20+
error: aborting due to previous error
21+
22+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)