Skip to content

Commit a6a7071

Browse files
Consider arm to diverge if guard diverges
1 parent 32c8a9f commit a6a7071

File tree

3 files changed

+39
-5
lines changed

3 files changed

+39
-5
lines changed

Diff for: compiler/rustc_hir_typeck/src/_match.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7777
let mut prior_non_diverging_arms = vec![]; // Used only for diagnostics.
7878
let mut prior_arm = None;
7979
for arm in arms {
80+
self.diverges.set(Diverges::Maybe);
81+
8082
if let Some(e) = &arm.guard {
81-
self.diverges.set(Diverges::Maybe);
8283
self.check_expr_has_type_or_error(e, tcx.types.bool, |_| {});
84+
85+
// FIXME: If this is the first arm and the pattern is irrefutable,
86+
// e.g. `_` or `x`, and the guard diverges, then the whole match
87+
// may also be considered to diverge. We should warn on all subsequent
88+
// arms, too, just like we do for diverging scrutinees above.
8389
}
8490

85-
self.diverges.set(Diverges::Maybe);
91+
// N.B. We don't reset diverges here b/c we want to warn in the arm
92+
// if the guard diverges, like: `x if { loop {} } => f()`, and we
93+
// also want to consider the arm to diverge itself.
8694

8795
let arm_ty = self.check_expr_with_expectation(arm.body, expected);
8896
all_arms_diverge &= self.diverges.get();

Diff for: tests/ui/reachable/expr_match.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,13 @@ fn d() {
2121
}
2222

2323
fn e() {
24-
// Here the compiler fails to figure out that the `println` is dead.
25-
match () { () if return => (), () => return }
24+
match () {
25+
() if return => (),
26+
//~^ ERROR unreachable expression
27+
() => return,
28+
}
2629
println!("I am dead");
30+
//~^ ERROR unreachable statement
2731
}
2832

2933
fn f() {

Diff for: tests/ui/reachable/expr_match.stderr

+23-1
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,27 @@ LL | println!("I am dead");
2323
|
2424
= note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
2525

26-
error: aborting due to 2 previous errors
26+
error: unreachable expression
27+
--> $DIR/expr_match.rs:25:25
28+
|
29+
LL | () if return => (),
30+
| ------ ^^ unreachable expression
31+
| |
32+
| any code following this expression is unreachable
33+
34+
error: unreachable statement
35+
--> $DIR/expr_match.rs:29:5
36+
|
37+
LL | / match () {
38+
LL | | () if return => (),
39+
LL | |
40+
LL | | () => return,
41+
LL | | }
42+
| |_____- any code following this `match` expression is unreachable, as all arms diverge
43+
LL | println!("I am dead");
44+
| ^^^^^^^^^^^^^^^^^^^^^ unreachable statement
45+
|
46+
= note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
47+
48+
error: aborting due to 4 previous errors
2749

0 commit comments

Comments
 (0)