Skip to content

Commit

Permalink
Rollup merge of #67278 - Centril:67273, r=oli-obk
Browse files Browse the repository at this point in the history
`coerce_inner`: use initial `expected_ty`

Fixes #67273.
Follow-up to #59439.

r? @oli-obk
  • Loading branch information
Centril authored Dec 13, 2019
2 parents 83536a5 + f97c37f commit 0f30462
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 2 deletions.
16 changes: 14 additions & 2 deletions src/librustc_typeck/check/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1289,8 +1289,20 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
}

// Error possibly reported in `check_assign` so avoid emitting error again.
err.emit_unless(expression.filter(|e| fcx.is_assign_to_bool(e, expected))
.is_some());
let assign_to_bool = expression
// #67273: Use initial expected type as opposed to `expected`.
// Otherwise we end up using prior coercions in e.g. a `match` expression:
// ```
// match i {
// 0 => true, // Because of this...
// 1 => i = 1, // ...`expected == bool` now, but not when checking `i = 1`.
// _ => (),
// };
// ```
.filter(|e| fcx.is_assign_to_bool(e, self.expected_ty()))
.is_some();

err.emit_unless(assign_to_bool);

self.final_ty = Some(fcx.tcx.types.err);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
fn main() {
let mut i: i64;
// Expected type is an inference variable `?T`
// because the `match` is used as a statement.
// This is the "initial" type of the `coercion`.
match i {
// Add `bool` to the overall `coercion`.
0 => true,

// Necessary to cause the ICE:
1 => true,

// Suppose that we had `let _: bool = match i { ... }`.
// In that case, as the expected type would be `bool`,
// we would suggest `i == 1` as a fix.
//
// However, no type error happens when checking `i = 1` because `expected == ?T`,
// which will unify with `typeof(i = 1) == ()`.
//
// However, in #67273, we would delay the unification of this arm with the above
// because we used the hitherto accumulated coercion as opposed to the "initial" type.
2 => i = 1,
//~^ ERROR match arms have incompatible types

_ => (),
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
error[E0308]: match arms have incompatible types
--> $DIR/issue-67273-assignment-match-prior-arm-bool-expected-unit.rs:22:14
|
LL | / match i {
LL | | // Add `bool` to the overall `coercion`.
LL | | 0 => true,
| | ---- this is found to be of type `bool`
LL | |
LL | | // Necessary to cause the ICE:
LL | | 1 => true,
| | ---- this is found to be of type `bool`
... |
LL | | 2 => i = 1,
| | ^^^^^ expected `bool`, found `()`
... |
LL | | _ => (),
LL | | }
| |_____- `match` arms have incompatible types

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.

0 comments on commit 0f30462

Please sign in to comment.