Consider arm to diverge if guard diverges
This commit is contained in:
parent
32c8a9f49d
commit
a6a707169d
3 changed files with 39 additions and 5 deletions
|
@ -77,12 +77,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let mut prior_non_diverging_arms = vec![]; // Used only for diagnostics.
|
let mut prior_non_diverging_arms = vec![]; // Used only for diagnostics.
|
||||||
let mut prior_arm = None;
|
let mut prior_arm = None;
|
||||||
for arm in arms {
|
for arm in arms {
|
||||||
|
self.diverges.set(Diverges::Maybe);
|
||||||
|
|
||||||
if let Some(e) = &arm.guard {
|
if let Some(e) = &arm.guard {
|
||||||
self.diverges.set(Diverges::Maybe);
|
|
||||||
self.check_expr_has_type_or_error(e, tcx.types.bool, |_| {});
|
self.check_expr_has_type_or_error(e, tcx.types.bool, |_| {});
|
||||||
|
|
||||||
|
// FIXME: If this is the first arm and the pattern is irrefutable,
|
||||||
|
// e.g. `_` or `x`, and the guard diverges, then the whole match
|
||||||
|
// may also be considered to diverge. We should warn on all subsequent
|
||||||
|
// arms, too, just like we do for diverging scrutinees above.
|
||||||
}
|
}
|
||||||
|
|
||||||
self.diverges.set(Diverges::Maybe);
|
// N.B. We don't reset diverges here b/c we want to warn in the arm
|
||||||
|
// if the guard diverges, like: `x if { loop {} } => f()`, and we
|
||||||
|
// also want to consider the arm to diverge itself.
|
||||||
|
|
||||||
let arm_ty = self.check_expr_with_expectation(arm.body, expected);
|
let arm_ty = self.check_expr_with_expectation(arm.body, expected);
|
||||||
all_arms_diverge &= self.diverges.get();
|
all_arms_diverge &= self.diverges.get();
|
||||||
|
|
|
@ -21,9 +21,13 @@ fn d() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn e() {
|
fn e() {
|
||||||
// Here the compiler fails to figure out that the `println` is dead.
|
match () {
|
||||||
match () { () if return => (), () => return }
|
() if return => (),
|
||||||
|
//~^ ERROR unreachable expression
|
||||||
|
() => return,
|
||||||
|
}
|
||||||
println!("I am dead");
|
println!("I am dead");
|
||||||
|
//~^ ERROR unreachable statement
|
||||||
}
|
}
|
||||||
|
|
||||||
fn f() {
|
fn f() {
|
||||||
|
|
|
@ -23,5 +23,27 @@ LL | println!("I am dead");
|
||||||
|
|
|
|
||||||
= note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: unreachable expression
|
||||||
|
--> $DIR/expr_match.rs:25:25
|
||||||
|
|
|
||||||
|
LL | () if return => (),
|
||||||
|
| ------ ^^ unreachable expression
|
||||||
|
| |
|
||||||
|
| any code following this expression is unreachable
|
||||||
|
|
||||||
|
error: unreachable statement
|
||||||
|
--> $DIR/expr_match.rs:29:5
|
||||||
|
|
|
||||||
|
LL | / match () {
|
||||||
|
LL | | () if return => (),
|
||||||
|
LL | |
|
||||||
|
LL | | () => return,
|
||||||
|
LL | | }
|
||||||
|
| |_____- any code following this `match` expression is unreachable, as all arms diverge
|
||||||
|
LL | println!("I am dead");
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^ unreachable statement
|
||||||
|
|
|
||||||
|
= note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue