-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Never return uninhabited values at all #59639
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
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