-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Never return uninhabited values at all #59639
Conversation
@bors r+ |
📌 Commit fb575c0 has been approved by |
Never return uninhabited values at all Functions with uninhabited return values are already marked `noreturn`, but we were still generating return instructions for this. When running with `C passes=lint`, LLVM prints: Unusual: Return statement in function with noreturn attribute The LLVM manual makes a stronger statement about `noreturn` though: > This produces undefined behavior at runtime if the function ever does dynamically return. We now mark such return values with a new `IgnoreMode::Uninhabited`, and emit an `abort` anywhere that would have returned. Fixes rust-lang#48227 cc rust-lang#7463 rust-lang#48229 r? @eddyb
Rollup of 5 pull requests Successful merges: - #59076 (Include trailing comma in multiline Debug representation) - #59619 (wasi: Implement more of the standard library) - #59639 (Never return uninhabited values at all) - #59643 (std: Upgrade `compiler_builtins` to fix wasi linkage) - #59664 (Updated the documentation of spin_loop and spin_loop_hint) Failed merges: r? @ghost
Never return uninhabited values at all Functions with uninhabited return values are already marked `noreturn`, but we were still generating return instructions for this. When running with `C passes=lint`, LLVM prints: Unusual: Return statement in function with noreturn attribute The LLVM manual makes a stronger statement about `noreturn` though: > This produces undefined behavior at runtime if the function ever does dynamically return. We now mark such return values with a new `IgnoreMode::Uninhabited`, and emit an `abort` anywhere that would have returned. Fixes rust-lang#48227 cc rust-lang#7463 rust-lang#48229 r? @eddyb
@bors r- (please do not r+ PRs assigned to me without first trying to ping me on IRC or Discord PM) |
😪 I'm awake I'm awake |
💡 This pull request was already approved, no need to approve it again.
|
📌 Commit fb575c0 has been approved by |
Oh bors is just extremely confusable. @bors r- |
Functions with uninhabited return values are already marked `noreturn`, but we were still generating return instructions for this. When running with `-C passes=lint`, LLVM prints: Unusual: Return statement in function with noreturn attribute The LLVM manual makes a stronger statement about `noreturn` though: > This produces undefined behavior at runtime if the function ever does dynamically return. We now emit an `abort` anywhere that would have tried to return an uninhabited value.
fb575c0
to
c2e0d7f
Compare
OK, I updated |
Thanks! @bors r+ |
📌 Commit c2e0d7f has been approved by |
So we are fine with not letting LLVM remove these branches entirely as being dead code? I recall @cramertj asking for more aggressive dead code removal around uninhabited types. |
As can be seen on codegen tests, we generate unreachable for uninhabited types after this PR. This should allow LLVM to optimize. (Whether LLVM in fact optimizes is a different question though.) |
Never return uninhabited values at all Functions with uninhabited return values are already marked `noreturn`, but we were still generating return instructions for this. When running with `-C passes=lint`, LLVM prints: Unusual: Return statement in function with noreturn attribute The LLVM manual makes a stronger statement about `noreturn` though: > This produces undefined behavior at runtime if the function ever does dynamically return. We now emit an `abort` anywhere that would have tried to return an uninhabited value. Fixes rust-lang#48227 cc rust-lang#7463 rust-lang#48229 r? @eddyb
Never return uninhabited values at all Functions with uninhabited return values are already marked `noreturn`, but we were still generating return instructions for this. When running with `-C passes=lint`, LLVM prints: Unusual: Return statement in function with noreturn attribute The LLVM manual makes a stronger statement about `noreturn` though: > This produces undefined behavior at runtime if the function ever does dynamically return. We now emit an `abort` anywhere that would have tried to return an uninhabited value. Fixes rust-lang#48227 cc rust-lang#7463 rust-lang#48229 r? @eddyb
We generate |
Never return uninhabited values at all Functions with uninhabited return values are already marked `noreturn`, but we were still generating return instructions for this. When running with `-C passes=lint`, LLVM prints: Unusual: Return statement in function with noreturn attribute The LLVM manual makes a stronger statement about `noreturn` though: > This produces undefined behavior at runtime if the function ever does dynamically return. We now emit an `abort` anywhere that would have tried to return an uninhabited value. Fixes rust-lang#48227 cc rust-lang#7463 rust-lang#48229 r? @eddyb
Never return uninhabited values at all Functions with uninhabited return values are already marked `noreturn`, but we were still generating return instructions for this. When running with `-C passes=lint`, LLVM prints: Unusual: Return statement in function with noreturn attribute The LLVM manual makes a stronger statement about `noreturn` though: > This produces undefined behavior at runtime if the function ever does dynamically return. We now emit an `abort` anywhere that would have tried to return an uninhabited value. Fixes rust-lang#48227 cc rust-lang#7463 rust-lang#48229 r? @eddyb
Never return uninhabited values at all Functions with uninhabited return values are already marked `noreturn`, but we were still generating return instructions for this. When running with `-C passes=lint`, LLVM prints: Unusual: Return statement in function with noreturn attribute The LLVM manual makes a stronger statement about `noreturn` though: > This produces undefined behavior at runtime if the function ever does dynamically return. We now emit an `abort` anywhere that would have tried to return an uninhabited value. Fixes rust-lang#48227 cc rust-lang#7463 rust-lang#48229 r? @eddyb
@RalfJung Can you open an issue? It's not clear to me what effect this has, AFAIK we produce an |
Rollup of 8 pull requests Successful merges: - #59470 (Document std::fs::File close behavior ignoring errors) - #59555 (update miri) - #59556 (update stdsimd) - #59596 (Forward formatter settings to bounds of `Range<T>` in `fmt::Debug` impl) - #59639 (Never return uninhabited values at all) - #59671 (Make some of lexer's API private) - #59685 (Add description for -Os and -Oz in rustc.1) - #59686 (Temporarily disable stack probing for gnux32.) Failed merges: r? @ghost
I'll happily investigate any bad codegen from this. I would think that any paths that would reach one of these really ought to be statically unreachable anyway, such that LLVM will still know that even the |
The nightlies before and after this change are:
I looked at the I also did a crude search for
That's a fair increase, although we can't immediately tell if those are in performance sensitive areas, and they may just be from normal new code. (For more, 2019-04-03 had 76947, and beta 70510.) Here is the perf report before and after the #59695 rollup PR that included this. |
It serves as the block terminator, if nothing else. https://llvm.org/docs/LangRef.html#unreachable-instruction
|
The I opened an issue at #59793 where I also demonstrate the effect of this. |
Which exact example did you use for this? I cannot reproduce. |
Yes, but a
Now, we could change this to just
From #48227: #![crate_type = "lib"]
pub fn lines<'a>(left: &'a str) {
iter(left.lines());
}
fn iter<I, T>(left: I)
where
I: Clone + Iterator<Item = T> + DoubleEndedIterator,
T: PartialEq,
{
let _left_count = left.clone().count();
}
Optimization removes it:
From #48229: fn main() {
(1 .. 9).filter(|_| true).sum::<u32>();
}
Optimization removes it:
|
FWIW, both of those example traps come from the blanket rust/src/libcore/iter/traits/iterator.rs Lines 1681 to 1685 in 3750348
|
Ah, those are truly unreachable traps get removed -- LLVM statically proves that that line cannot be reached. That has nothing to do with the
I see. That's a bit weird but whatever, if that's how LLVM works that's fine for me. ;) My point was that the |
Functions with uninhabited return values are already marked
noreturn
,but we were still generating return instructions for this. When running
with
-C passes=lint
, LLVM prints:The LLVM manual makes a stronger statement about
noreturn
though:We now emit an
abort
anywhere that would have tried to return anuninhabited value.
Fixes #48227
cc #7463 #48229
r? @eddyb