Skip to content

Conversation

@clubby789
Copy link
Contributor

@clubby789 clubby789 commented Nov 18, 2025

Closes #149042

Attempts to be smarter about identifying 'real'/user-written unreachable code to raise the lint

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Nov 18, 2025
@rustbot
Copy link
Collaborator

rustbot commented Nov 18, 2025

r? @nnethercote

rustbot has assigned @nnethercote.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rust-log-analyzer

This comment has been minimized.

@cjgillot
Copy link
Contributor

Iirc some parts of mir building uses end_point for drop spans. Should this do the same?

@Zalathar
Copy link
Member

You'll probably need to bless the coverage tests with:

./x test coverage coverage-run-rustdoc --set=build.profiler=true --bless

Coverage instrumentation unfortunately relies on a bunch of fragile heuristics that get disturbed by changes like this one, but luckily the new output seems reasonable.

@clubby789
Copy link
Contributor Author

Iirc some parts of mir building uses end_point for drop spans. Should this do the same?

Some examples of diagnostic changes with this

error: unreachable expression
  --> $DIR/void-branch.rs:10:9
   |
LL |             std::mem::uninitialized::<Void>();
   |             --------------------------------- any code following this expression is unreachable
LL |         }
   |         ^ unreachable expression
LL | #[define_opaque(WithoutLt)]
LL | fn without_lt() -> impl for<'a> Trait<'a, Assoc = WithoutLt> {}
   |                             --                                ^
   |                             |
   |                             hidden type `&'a str` captures the lifetime `'a` as defined here

I'm not sure if there's any performance implications with using sourcemap parsing on a pretty hot path, I'll perf it

@rustbot
Copy link
Collaborator

rustbot commented Nov 18, 2025

Some changes occurred in coverage tests.

cc @Zalathar

@clubby789
Copy link
Contributor Author

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

rust-bors bot added a commit that referenced this pull request Nov 18, 2025
Use a more accurate span for the implicit block return assignment
@rust-bors

This comment has been minimized.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Nov 18, 2025
Copy link
Contributor

@nnethercote nnethercote left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first commit seems like a small improvement. The second commit touches a lot of test and coverage output for seemingly little gain, and doesn't seem worthwhile.

Supposedly this fixes #149042 but no test is added to cover that case. Seems like a test should be added?

View changes since this review

@rust-log-analyzer

This comment has been minimized.

@nnethercote nnethercote added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 18, 2025
@clubby789
Copy link
Contributor Author

clubby789 commented Nov 18, 2025

The second commit touches a lot of test and coverage output for seemingly little gain, and doesn't seem worthwhile.

Agree, I think I'll back it out (though the coverage changes were originally just not blessed with the first commit, so there's still going to be some sweeping changes there).

Seems like a test should be added?

Imo, tests/ui/uninhabited/void-branch.rs (which was added with the PR the lint change) demonstrates the span issue and fix well, do you think a dedicated test is needed?

@clubby789 clubby789 force-pushed the implicit-return-span branch 2 times, most recently from d1bc16c to aed6c5d Compare November 18, 2025 10:50
@nnethercote
Copy link
Contributor

do you think a dedicated test is needed?

#149042's description said a lint was issued in a case where it shouldn't be issued. void-branch.rs just sees some minor changes in output, which seems much less compelling. If you think it's good enough I will defer, it just seemed surprising.

@clubby789
Copy link
Contributor Author

Ah, this change is about turning

  |
7 |   fn check() -> () {
  |  __________________^
8 | |     make_never();
  | |     ------------ any code following this expression is unreachable
9 | | }
  | |_^ unreachable expression

into

8 |     make_never();
  |     ------------^ unreachable expression
  |     |
  |     any code following this expression is unreachable

I think there's a good argument to be made that the implicit void return should not be counted as 'code' that's unreachable. I'll see if that's feasible to reliably detect

@rust-bors
Copy link

rust-bors bot commented Nov 18, 2025

☀️ Try build successful (CI)
Build commit: b2b48b3 (b2b48b3941a98a5ab0c2d3f77d25a989ed59d04f, parent: 217cb73577ed6f30a2005dd75bab01d23ec4cd60)

@rust-timer

This comment has been minimized.

@rust-timer

This comment was marked as outdated.

@rustbot rustbot added perf-regression Performance regression. and removed S-waiting-on-perf Status: Waiting on a perf run to be completed. labels Nov 18, 2025
@clubby789 clubby789 force-pushed the implicit-return-span branch from aed6c5d to d793f62 Compare November 18, 2025 17:40
@clubby789 clubby789 removed the perf-regression Performance regression. label Nov 18, 2025
@clubby789 clubby789 changed the title Use a more accurate span for the implicit block return assignment Reduce confusing unreachable_code lints Nov 18, 2025
@clubby789
Copy link
Contributor Author

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Nov 18, 2025
std::mem::uninitialized::<Void>();
println!();
//~^ ERROR unreachable expression
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where does the error point on the unchanged test? Do you mind adding another if false block with the println an keep the original one?

Copy link
Contributor Author

@clubby789 clubby789 Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No error is raised within the block without the additional println (similarly to fn block in the other test I added).

Do you mind adding another if false block with the println an keep the original one?

Sorry, can you add an example? I'm not quite sure what this should look like


let term = bb.terminator();
match term.kind {
TerminatorKind::Goto { .. } | TerminatorKind::Return => None,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mind adding a comment explaining why we return None here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// No user code in this bb, and our goto target may be reachable via other paths
There may be other cases where we shouldn't lint and/or should label with something other than "expression" but this was sufficient for the motivating examples

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm skeptical about the goto. What about some kind of if a { panic!() } else { unreachable!() }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current (nightly) error Two errors, each highlighting the if and else blocks respectively
warning: unreachable expression
 --> poc.rs:6:14
  |
6 |       if false {
  |  ______________^
7 | |     //~^ ERROR unreachable expression
8 | |         infallible();
  | |         ------------ any code following this expression is unreachable
9 | |     } else {
  | |_____^ unreachable expression
  |
warning: unreachable expression
  --> poc.rs:9:12
   |
 9 |       } else {
   |  ____________^
10 | |     //~^ ERROR unreachable expression
11 | |         infallible();
   | |         ------------ any code following this expression is unreachable
12 | |     }
   | |_____^ unreachable expression

With the current PR no error is emitted at all.

With the `Goto` arm removed

Two errors, both highlighting the entire if/else

warning: unreachable expression
  --> poc.rs:6:5
   |
 6 | /     if false {
 7 | |     //~^ ERROR unreachable expression
 8 | |         infallible();
   | |         ------------ any code following this expression is unreachable
 9 | |     } else {
10 | |     //~^ ERROR unreachable expression
11 | |         infallible();
12 | |     }
   | |_____^ unreachable expression
   |

warning: unreachable expression
  --> poc.rs:6:5
   |
 6 | /     if false {
 7 | |     //~^ ERROR unreachable expression
 8 | |         infallible();
 9 | |     } else {
10 | |     //~^ ERROR unreachable expression
11 | |         infallible();
   | |         ------------ any code following this expression is unreachable
12 | |     }
   | |_____^ unreachable expression

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r=me with a test illustrating this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a test for the current behaviour.

@nnethercote
Copy link
Contributor

This seems ok to me once @cjgillot's questions are addressed.

@clubby789 clubby789 force-pushed the implicit-return-span branch from d793f62 to 2d9cd22 Compare November 19, 2025 10:48
@nnethercote
Copy link
Contributor

At this point I think we should just r? @cjgillot

@rustbot rustbot assigned cjgillot and unassigned nnethercote Nov 19, 2025
@clubby789 clubby789 force-pushed the implicit-return-span branch from 2d9cd22 to 98141e0 Compare November 21, 2025 16:08
@clubby789
Copy link
Contributor Author

@bors r=cjgillot

@bors
Copy link
Collaborator

bors commented Nov 21, 2025

📌 Commit 98141e0 has been approved by cjgillot

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 21, 2025
@bors
Copy link
Collaborator

bors commented Nov 22, 2025

⌛ Testing commit 98141e0 with merge af17d59...

@bors
Copy link
Collaborator

bors commented Nov 22, 2025

☀️ Test successful - checks-actions
Approved by: cjgillot
Pushing af17d59 to main...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Nov 22, 2025
@bors bors merged commit af17d59 into rust-lang:main Nov 22, 2025
12 checks passed
@rustbot rustbot added this to the 1.93.0 milestone Nov 22, 2025
@github-actions
Copy link
Contributor

What is this? This is an experimental post-merge analysis report that shows differences in test outcomes between the merged PR and its parent PR.

Comparing ea98522 (parent) -> af17d59 (this PR)

Test differences

Show 4 test diffs

Stage 1

  • [ui] tests/ui/uninhabited/unreachable.rs: [missing] -> pass (J1)

Stage 2

  • [ui] tests/ui/uninhabited/unreachable.rs: [missing] -> pass (J0)

Additionally, 2 doctest diffs were found. These are ignored, as they are noisy.

Job group index

Test dashboard

Run

cargo run --manifest-path src/ci/citool/Cargo.toml -- \
    test-dashboard af17d59d71cd344fb34caab3e96c88b7c137f872 --output-dir test-dashboard

And then open test-dashboard/index.html in your browser to see an overview of all executed tests.

Job duration changes

  1. aarch64-apple: 7197.0s -> 8134.8s (+13.0%)
  2. x86_64-msvc-ext3: 5830.5s -> 6567.0s (+12.6%)
  3. x86_64-gnu-miri: 3953.6s -> 4422.6s (+11.9%)
  4. dist-arm-linux-gnueabi: 5333.9s -> 4896.4s (-8.2%)
  5. dist-aarch64-msvc: 6082.5s -> 5649.5s (-7.1%)
  6. x86_64-gnu-llvm-20-2: 6038.8s -> 5618.5s (-7.0%)
  7. dist-x86_64-freebsd: 5007.6s -> 4661.6s (-6.9%)
  8. dist-x86_64-illumos: 5675.5s -> 6060.0s (+6.8%)
  9. dist-aarch64-apple: 6436.0s -> 6017.9s (-6.5%)
  10. dist-x86_64-netbsd: 5154.1s -> 4880.0s (-5.3%)
How to interpret the job duration changes?

Job durations can vary a lot, based on the actual runner instance
that executed the job, system noise, invalidated caches, etc. The table above is provided
mostly for t-infra members, for simpler debugging of potential CI slow-downs.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (af17d59): comparison URL.

Overall result: ✅ improvements - no action needed

@rustbot label: -perf-regression

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-0.6% [-0.6%, -0.6%] 3
All ❌✅ (primary) - - 0

Max RSS (memory usage)

This benchmark run did not return any relevant results for this metric.

Cycles

This benchmark run did not return any relevant results for this metric.

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 472.807s -> 469.465s (-0.71%)
Artifact size: 388.29 MiB -> 388.29 MiB (0.00%)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

unreachable_code lint falsely warns entire function body is unreachable

9 participants