Skip to content

Commit 822393d

Browse files
committed
Point at original span when emitting unreachable lint
Fixes #64590 When we emit an 'unreachable' lint, we now add a note pointing at the expression that actually causes the code to be unreachable (e.g. `return`, `break`, `panic`). This is especially useful when macros are involved, since a diverging expression might be hidden inside of a macro invocation.
1 parent eceec57 commit 822393d

37 files changed

+328
-11
lines changed

src/librustc_typeck/check/_match.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
4343

4444
// If there are no arms, that is a diverging match; a special case.
4545
if arms.is_empty() {
46-
self.diverges.set(self.diverges.get() | Diverges::Always);
46+
self.diverges.set(self.diverges.get() | Diverges::Always(expr.span));
4747
return tcx.types.never;
4848
}
4949

@@ -69,7 +69,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
6969
// warnings).
7070
match all_pats_diverge {
7171
Diverges::Maybe => Diverges::Maybe,
72-
Diverges::Always | Diverges::WarnedAlways => Diverges::WarnedAlways,
72+
Diverges::Always(..) | Diverges::WarnedAlways => Diverges::WarnedAlways,
7373
}
7474
}).collect();
7575

src/librustc_typeck/check/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
170170

171171
// Any expression that produces a value of type `!` must have diverged
172172
if ty.is_never() {
173-
self.diverges.set(self.diverges.get() | Diverges::Always);
173+
self.diverges.set(self.diverges.get() | Diverges::Always(expr.span));
174174
}
175175

176176
// Record the type, which applies it effects.

src/librustc_typeck/check/mod.rs

+17-8
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,10 @@ pub enum Diverges {
450450

451451
/// Definitely known to diverge and therefore
452452
/// not reach the next sibling or its parent.
453-
Always,
453+
/// The `Span` points to the expression
454+
/// that caused us to diverge
455+
/// (e.g. `return`, `break`, etc)
456+
Always(Span),
454457

455458
/// Same as `Always` but with a reachability
456459
/// warning already emitted.
@@ -487,7 +490,7 @@ impl ops::BitOrAssign for Diverges {
487490

488491
impl Diverges {
489492
fn always(self) -> bool {
490-
self >= Diverges::Always
493+
self >= Diverges::Always(DUMMY_SP)
491494
}
492495
}
493496

@@ -2307,17 +2310,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23072310
/// Produces warning on the given node, if the current point in the
23082311
/// function is unreachable, and there hasn't been another warning.
23092312
fn warn_if_unreachable(&self, id: hir::HirId, span: Span, kind: &str) {
2310-
if self.diverges.get() == Diverges::Always &&
2313+
// FIXME: Combine these two 'if' expressions into one once
2314+
// let chains are implemented
2315+
if let Diverges::Always(orig_span) = self.diverges.get() {
23112316
// If span arose from a desugaring of `if` or `while`, then it is the condition itself,
23122317
// which diverges, that we are about to lint on. This gives suboptimal diagnostics.
23132318
// Instead, stop here so that the `if`- or `while`-expression's block is linted instead.
2314-
!span.is_desugaring(DesugaringKind::CondTemporary) {
2315-
self.diverges.set(Diverges::WarnedAlways);
2319+
if !span.is_desugaring(DesugaringKind::CondTemporary) {
2320+
self.diverges.set(Diverges::WarnedAlways);
23162321

2317-
debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind);
2322+
debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind);
23182323

2319-
let msg = format!("unreachable {}", kind);
2320-
self.tcx().lint_hir(lint::builtin::UNREACHABLE_CODE, id, span, &msg);
2324+
let msg = format!("unreachable {}", kind);
2325+
let mut err = self.tcx().struct_span_lint_hir(lint::builtin::UNREACHABLE_CODE,
2326+
id, span, &msg);
2327+
err.span_note(orig_span, "any code following this expression is unreachable");
2328+
err.emit();
2329+
}
23212330
}
23222331
}
23232332

src/test/ui/dead-code-ret.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ note: lint level defined here
99
|
1010
LL | #![deny(unreachable_code)]
1111
| ^^^^^^^^^^^^^^^^
12+
note: any code following this expression is unreachable
13+
--> $DIR/dead-code-ret.rs:6:5
14+
|
15+
LL | return;
16+
| ^^^^^^
1217
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
1318

1419
error: aborting due to previous error

src/test/ui/if-ret.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,9 @@ LL | fn foo() { if (return) { } }
55
| ^^^
66
|
77
= note: `#[warn(unreachable_code)]` on by default
8+
note: any code following this expression is unreachable
9+
--> $DIR/if-ret.rs:6:15
10+
|
11+
LL | fn foo() { if (return) { } }
12+
| ^^^^^^^^
813

src/test/ui/issues/issue-2150.stderr

+6
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ note: lint level defined here
99
|
1010
LL | #![deny(unreachable_code)]
1111
| ^^^^^^^^^^^^^^^^
12+
note: any code following this expression is unreachable
13+
--> $DIR/issue-2150.rs:7:5
14+
|
15+
LL | panic!();
16+
| ^^^^^^^^^
17+
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
1218

1319
error: aborting due to previous error
1420

src/test/ui/issues/issue-7246.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ note: lint level defined here
99
|
1010
LL | #![deny(unreachable_code)]
1111
| ^^^^^^^^^^^^^^^^
12+
note: any code following this expression is unreachable
13+
--> $DIR/issue-7246.rs:6:5
14+
|
15+
LL | return;
16+
| ^^^^^^
1217

1318
error: aborting due to previous error
1419

src/test/ui/lint/lint-attr-non-item-node.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ note: lint level defined here
99
|
1010
LL | #[deny(unreachable_code)]
1111
| ^^^^^^^^^^^^^^^^
12+
note: any code following this expression is unreachable
13+
--> $DIR/lint-attr-non-item-node.rs:6:9
14+
|
15+
LL | break;
16+
| ^^^^^
1217

1318
error: aborting due to previous error
1419

src/test/ui/liveness/liveness-unused.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ note: lint level defined here
1010
LL | #![warn(unused)]
1111
| ^^^^^^
1212
= note: `#[warn(unreachable_code)]` implied by `#[warn(unused)]`
13+
note: any code following this expression is unreachable
14+
--> $DIR/liveness-unused.rs:91:9
15+
|
16+
LL | continue;
17+
| ^^^^^^^^
1318

1419
error: unused variable: `x`
1520
--> $DIR/liveness-unused.rs:8:7

src/test/ui/match/match-no-arms-unreachable-after.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ note: lint level defined here
99
|
1010
LL | #![deny(unreachable_code)]
1111
| ^^^^^^^^^^^^^^^^
12+
note: any code following this expression is unreachable
13+
--> $DIR/match-no-arms-unreachable-after.rs:7:5
14+
|
15+
LL | match v { }
16+
| ^^^^^^^^^^^
1217

1318
error: aborting due to previous error
1419

src/test/ui/never-assign-dead-code.stderr

+12
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,24 @@ note: lint level defined here
1010
LL | #![warn(unused)]
1111
| ^^^^^^
1212
= note: `#[warn(unreachable_code)]` implied by `#[warn(unused)]`
13+
note: any code following this expression is unreachable
14+
--> $DIR/never-assign-dead-code.rs:9:16
15+
|
16+
LL | let x: ! = panic!("aah");
17+
| ^^^^^^^^^^^^^
18+
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
1319

1420
warning: unreachable call
1521
--> $DIR/never-assign-dead-code.rs:10:5
1622
|
1723
LL | drop(x);
1824
| ^^^^
25+
|
26+
note: any code following this expression is unreachable
27+
--> $DIR/never-assign-dead-code.rs:10:10
28+
|
29+
LL | drop(x);
30+
| ^
1931

2032
warning: unused variable: `x`
2133
--> $DIR/never-assign-dead-code.rs:9:9

src/test/ui/reachable/expr_add.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ note: lint level defined here
99
|
1010
LL | #![deny(unreachable_code)]
1111
| ^^^^^^^^^^^^^^^^
12+
note: any code following this expression is unreachable
13+
--> $DIR/expr_add.rs:17:19
14+
|
15+
LL | let x = Foo + return;
16+
| ^^^^^^
1217

1318
error: aborting due to previous error
1419

src/test/ui/reachable/expr_again.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ note: lint level defined here
99
|
1010
LL | #![deny(unreachable_code)]
1111
| ^^^^^^^^^^^^^^^^
12+
note: any code following this expression is unreachable
13+
--> $DIR/expr_again.rs:7:9
14+
|
15+
LL | continue;
16+
| ^^^^^^^^
1217
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
1318

1419
error: aborting due to previous error

src/test/ui/reachable/expr_array.stderr

+11
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,23 @@ note: lint level defined here
99
|
1010
LL | #![deny(unreachable_code)]
1111
| ^^^^^^^^^^^^^^^^
12+
note: any code following this expression is unreachable
13+
--> $DIR/expr_array.rs:9:26
14+
|
15+
LL | let x: [usize; 2] = [return, 22];
16+
| ^^^^^^
1217

1318
error: unreachable expression
1419
--> $DIR/expr_array.rs:14:25
1520
|
1621
LL | let x: [usize; 2] = [22, return];
1722
| ^^^^^^^^^^^^
23+
|
24+
note: any code following this expression is unreachable
25+
--> $DIR/expr_array.rs:14:30
26+
|
27+
LL | let x: [usize; 2] = [22, return];
28+
| ^^^^^^
1829

1930
error: aborting due to 2 previous errors
2031

src/test/ui/reachable/expr_assign.stderr

+17
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,35 @@ note: lint level defined here
99
|
1010
LL | #![deny(unreachable_code)]
1111
| ^^^^^^^^^^^^^^^^
12+
note: any code following this expression is unreachable
13+
--> $DIR/expr_assign.rs:10:9
14+
|
15+
LL | x = return;
16+
| ^^^^^^
1217

1318
error: unreachable expression
1419
--> $DIR/expr_assign.rs:20:14
1520
|
1621
LL | *p = return;
1722
| ^^^^^^
23+
|
24+
note: any code following this expression is unreachable
25+
--> $DIR/expr_assign.rs:20:9
26+
|
27+
LL | *p = return;
28+
| ^^
1829

1930
error: unreachable expression
2031
--> $DIR/expr_assign.rs:26:15
2132
|
2233
LL | *{return; &mut i} = 22;
2334
| ^^^^^^
35+
|
36+
note: any code following this expression is unreachable
37+
--> $DIR/expr_assign.rs:26:7
38+
|
39+
LL | *{return; &mut i} = 22;
40+
| ^^^^^^
2441

2542
error: aborting due to 3 previous errors
2643

src/test/ui/reachable/expr_block.stderr

+10
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,23 @@ note: lint level defined here
99
|
1010
LL | #![deny(unreachable_code)]
1111
| ^^^^^^^^^^^^^^^^
12+
note: any code following this expression is unreachable
13+
--> $DIR/expr_block.rs:9:9
14+
|
15+
LL | return;
16+
| ^^^^^^
1217

1318
error: unreachable statement
1419
--> $DIR/expr_block.rs:25:9
1520
|
1621
LL | println!("foo");
1722
| ^^^^^^^^^^^^^^^^
1823
|
24+
note: any code following this expression is unreachable
25+
--> $DIR/expr_block.rs:24:9
26+
|
27+
LL | return;
28+
| ^^^^^^
1929
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
2030

2131
error: aborting due to 2 previous errors

src/test/ui/reachable/expr_box.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ note: lint level defined here
99
|
1010
LL | #![deny(unreachable_code)]
1111
| ^^^^^^^^^^^^^^^^
12+
note: any code following this expression is unreachable
13+
--> $DIR/expr_box.rs:6:17
14+
|
15+
LL | let x = box return;
16+
| ^^^^^^
1217

1318
error: aborting due to previous error
1419

src/test/ui/reachable/expr_call.stderr

+11
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,23 @@ note: lint level defined here
99
|
1010
LL | #![deny(unreachable_code)]
1111
| ^^^^^^^^^^^^^^^^
12+
note: any code following this expression is unreachable
13+
--> $DIR/expr_call.rs:13:9
14+
|
15+
LL | foo(return, 22);
16+
| ^^^^^^
1217

1318
error: unreachable call
1419
--> $DIR/expr_call.rs:18:5
1520
|
1621
LL | bar(return);
1722
| ^^^
23+
|
24+
note: any code following this expression is unreachable
25+
--> $DIR/expr_call.rs:18:9
26+
|
27+
LL | bar(return);
28+
| ^^^^^^
1829

1930
error: aborting due to 2 previous errors
2031

src/test/ui/reachable/expr_cast.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ note: lint level defined here
99
|
1010
LL | #![deny(unreachable_code)]
1111
| ^^^^^^^^^^^^^^^^
12+
note: any code following this expression is unreachable
13+
--> $DIR/expr_cast.rs:9:14
14+
|
15+
LL | let x = {return} as !;
16+
| ^^^^^^
1217

1318
error: aborting due to previous error
1419

src/test/ui/reachable/expr_if.stderr

+10
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,23 @@ note: lint level defined here
1212
|
1313
LL | #![deny(unreachable_code)]
1414
| ^^^^^^^^^^^^^^^^
15+
note: any code following this expression is unreachable
16+
--> $DIR/expr_if.rs:7:9
17+
|
18+
LL | if {return} {
19+
| ^^^^^^
1520

1621
error: unreachable statement
1722
--> $DIR/expr_if.rs:27:5
1823
|
1924
LL | println!("But I am.");
2025
| ^^^^^^^^^^^^^^^^^^^^^^
2126
|
27+
note: any code following this expression is unreachable
28+
--> $DIR/expr_if.rs:21:9
29+
|
30+
LL | return;
31+
| ^^^^^^
2232
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
2333

2434
error: aborting due to 2 previous errors

0 commit comments

Comments
 (0)