Skip to content

Commit af17d59

Browse files
committed
Auto merge of rust-lang#149044 - clubby789:implicit-return-span, r=cjgillot
Reduce confusing `unreachable_code` lints Closes rust-lang#149042 Attempts to be smarter about identifying 'real'/user-written unreachable code to raise the lint
2 parents ea98522 + 98141e0 commit af17d59

File tree

4 files changed

+87
-28
lines changed

4 files changed

+87
-28
lines changed

compiler/rustc_mir_build/src/builder/mod.rs

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -861,20 +861,46 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
861861
}
862862
}
863863

864+
/// Starting at a target unreachable block, find some user code to lint as unreachable
865+
fn find_unreachable_code_from(
866+
bb: BasicBlock,
867+
bbs: &IndexVec<BasicBlock, BasicBlockData<'_>>,
868+
) -> Option<(SourceInfo, &'static str)> {
869+
let bb = &bbs[bb];
870+
for stmt in &bb.statements {
871+
match &stmt.kind {
872+
// Ignore the implicit `()` return place assignment for unit functions/blocks
873+
StatementKind::Assign(box (_, Rvalue::Use(Operand::Constant(const_))))
874+
if const_.ty().is_unit() =>
875+
{
876+
continue;
877+
}
878+
StatementKind::StorageLive(_) | StatementKind::StorageDead(_) => {
879+
continue;
880+
}
881+
StatementKind::FakeRead(..) => return Some((stmt.source_info, "definition")),
882+
_ => return Some((stmt.source_info, "expression")),
883+
}
884+
}
885+
886+
let term = bb.terminator();
887+
match term.kind {
888+
// No user code in this bb, and our goto target may be reachable via other paths
889+
TerminatorKind::Goto { .. } | TerminatorKind::Return => None,
890+
_ => Some((term.source_info, "expression")),
891+
}
892+
}
893+
864894
for (target_bb, orig_ty, orig_span) in lints {
865895
if orig_span.in_external_macro(self.tcx.sess.source_map()) {
866896
continue;
867897
}
868-
let target_bb = &self.cfg.basic_blocks[target_bb];
869-
let (target_loc, descr) = target_bb
870-
.statements
871-
.iter()
872-
.find_map(|stmt| match stmt.kind {
873-
StatementKind::StorageLive(_) | StatementKind::StorageDead(_) => None,
874-
StatementKind::FakeRead(..) => Some((stmt.source_info, "definition")),
875-
_ => Some((stmt.source_info, "expression")),
876-
})
877-
.unwrap_or_else(|| (target_bb.terminator().source_info, "expression"));
898+
899+
let Some((target_loc, descr)) =
900+
find_unreachable_code_from(target_bb, &self.cfg.basic_blocks)
901+
else {
902+
continue;
903+
};
878904
let lint_root = self.source_scopes[target_loc.scope]
879905
.local_data
880906
.as_ref()
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//! Test that a diverging function as the final expression in a block does not
2+
//! raise an 'unreachable code' lint.
3+
4+
//@ check-pass
5+
#![deny(unreachable_code)]
6+
7+
enum Never {}
8+
9+
fn make_never() -> Never {
10+
loop {}
11+
}
12+
13+
fn func() {
14+
make_never();
15+
}
16+
17+
fn block() {
18+
{
19+
make_never();
20+
}
21+
}
22+
23+
fn branchy() {
24+
if false {
25+
make_never();
26+
} else {
27+
make_never();
28+
}
29+
}
30+
31+
fn main() {
32+
func();
33+
block();
34+
}

tests/ui/uninhabited/void-branch.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ enum Void {}
66
fn with_void() {
77
if false {
88
unsafe {
9-
//~^ ERROR unreachable expression
109
std::mem::uninitialized::<Void>();
10+
println!();
11+
//~^ ERROR unreachable expression
1112
}
1213
}
1314

@@ -20,8 +21,9 @@ fn infallible() -> std::convert::Infallible {
2021

2122
fn with_infallible() {
2223
if false {
23-
//~^ ERROR unreachable expression
2424
infallible();
25+
println!()
26+
//~^ ERROR unreachable expression
2527
}
2628

2729
println!()
Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
error: unreachable expression
2-
--> $DIR/void-branch.rs:8:9
2+
--> $DIR/void-branch.rs:10:13
33
|
4-
LL | / unsafe {
5-
LL | |
6-
LL | | std::mem::uninitialized::<Void>();
7-
| | --------------------------------- any code following this expression is unreachable
8-
LL | | }
9-
| |_________^ unreachable expression
4+
LL | std::mem::uninitialized::<Void>();
5+
| --------------------------------- any code following this expression is unreachable
6+
LL | println!();
7+
| ^^^^^^^^^^ unreachable expression
108
|
119
note: this expression has type `Void`, which is uninhabited
12-
--> $DIR/void-branch.rs:10:13
10+
--> $DIR/void-branch.rs:9:13
1311
|
1412
LL | std::mem::uninitialized::<Void>();
1513
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -18,23 +16,22 @@ note: the lint level is defined here
1816
|
1917
LL | #![deny(unreachable_code)]
2018
| ^^^^^^^^^^^^^^^^
19+
= note: this error originates in the macro `$crate::format_args` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
2120

2221
error: unreachable expression
23-
--> $DIR/void-branch.rs:22:14
22+
--> $DIR/void-branch.rs:25:9
2423
|
25-
LL | if false {
26-
| ______________^
27-
LL | |
28-
LL | | infallible();
29-
| | ------------ any code following this expression is unreachable
30-
LL | | }
31-
| |_____^ unreachable expression
24+
LL | infallible();
25+
| ------------ any code following this expression is unreachable
26+
LL | println!()
27+
| ^^^^^^^^^^ unreachable expression
3228
|
3329
note: this expression has type `Infallible`, which is uninhabited
3430
--> $DIR/void-branch.rs:24:9
3531
|
3632
LL | infallible();
3733
| ^^^^^^^^^^^^
34+
= note: this error originates in the macro `$crate::format_args` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
3835

3936
error: aborting due to 2 previous errors
4037

0 commit comments

Comments
 (0)