-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Add unsafe Option::unwrap_unchecked() #1095
Conversation
bike-shedding). It is implemented quite simply by using the | ||
`unreachable` intrinsic to indicate that the `Option` cannot be `None` | ||
and then calling `unwrap()`. I expect that the compiler can them | ||
optimize out the conditional. A prototype implement can be found |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you verified that the compiler does in fact optimize it away?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is dependent on a lot of different cases. If I build a library as follows:
#![feature(core)]
use std::intrinsics;
pub fn my_unwrap(o: Option<i32>) -> i32 {
match o {
Some(v) => v,
None => panic!("panic")
}
}
pub unsafe fn my_unwrap_unsafe(o: Option<i32>) -> i32 {
match o {
Some(v) => v,
None => intrinsics::unreachable()
}
}
$ rustc -O --crate-type=lib unwrap.rs
$ objdump -d libunwrap.rlib
0000000000000000 <_ZN16my_unwrap_unsafe20h8f4545557bc4e296MaaE>:
0: 48 c1 ef 20 shr $0x20,%rdi
4: 89 f8 mov %edi,%eax
6: c3 retq
You can see no conditionals in the unwrap_unsafe asm. Further testing on the actual standard library implementation would be needed to confirm, but at least one method of implementing it seems to work as I expect.
Other possible alternative: If we added branch weights, such as |
One benefit of adding this is that it would allow stable users to (unsafely) express unreachability without needing the unstable |
I've definitely wanted this before for expressing the invariants in data structures (stuff like "if I'm at this point in the program the root/parent must not be null"). Not for any particularly profiled reason, though. Just a vague sense of "I don't like having the code think it can panic here". However if the intrinsic was properly exposed I believe this could just be written as |
I'm interested to see specific code in std where this optimization helps. |
@brson How is what you're asking different from what is already in the RFC? The example I provided is from std. |
You can also use |
As far as I can tell this can be done in a library outside of |
@SimonSapin That can be said for all things in the standard library. :) |
I actually think the explicit match is desireable. It would be much better if we suggested this pattern: let inner_value = match opt {
Some(x) => x,
None => debug_assert_unreachable("This is a bug"),
}; I.e. we encourage the user to check their assumptions in the code with debug assertions, this particular macro or function after reem's model would behave like debug_assert!() in debug builds and be the unreachable intrinsic in release builds. |
@bluss One could make a functions which does exactly this to encourage the pattern. :) |
This RFC is now entering the final-comment-period for one week. |
@SimonSapin yeah, I was just thinking that we'd want to pursue stabilizing that intrinsic (in a different location) instead of stabilizing a one-off method on |
I am unconvinced that I'd even want to do this optimization at all. It's such a tiny gain (avoids a single, trivially predictable branch), and the consequences for getting it wrong (i.e., the value being I am even less convinced that this optimization needs to be codified in a method in I'd appreciate hard data (i.e., well-done benchmarks) showing a measurable performance gain in any non-pathological code --- ideally, a real library or application. But even with that I'd be inclined to say "well that's nice but you can do the same thing yourself, so why bake it into std for all eternity?" Overall, 👎 |
Also of note: you can now have an unreachable optimization hint in stable code through the |
Uh, that looks crazy magic to me. Does the complier really eliminate branches that cause transmuting to |
@SimonSapin it works because rustc emits an unreachable hint after all calls to diverging functions. |
@SimonSapin rustc's part of the magic is this, it simply emits unreachable when matching an empty enum: fn unreachable(v: Void) -> ! {
match v { /* empty */ }
} |
I see, thanks for the explanation! |
Thanks again for the RFC @dschatzberg! The consensus of the library subteam is to not merge this RFC at this time due to the worries about composability and how stabilizing an |
Thanks for the response, @alexcrichton. Could you clarify what the worries about |
Ah it's what I meant in a previous comment about how an |
No description provided.