Skip to content

Commit

Permalink
Consider arm to diverge if guard diverges
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Dec 24, 2024
1 parent 32c8a9f commit a6a7071
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 5 deletions.
12 changes: 10 additions & 2 deletions compiler/rustc_hir_typeck/src/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut prior_non_diverging_arms = vec![]; // Used only for diagnostics.
let mut prior_arm = None;
for arm in arms {
self.diverges.set(Diverges::Maybe);

if let Some(e) = &arm.guard {
self.diverges.set(Diverges::Maybe);
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);
all_arms_diverge &= self.diverges.get();
Expand Down
8 changes: 6 additions & 2 deletions tests/ui/reachable/expr_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,13 @@ fn d() {
}

fn e() {
// Here the compiler fails to figure out that the `println` is dead.
match () { () if return => (), () => return }
match () {
() if return => (),
//~^ ERROR unreachable expression
() => return,
}
println!("I am dead");
//~^ ERROR unreachable statement
}

fn f() {
Expand Down
24 changes: 23 additions & 1 deletion tests/ui/reachable/expr_match.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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)

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

0 comments on commit a6a7071

Please sign in to comment.