-
Notifications
You must be signed in to change notification settings - Fork 13.5k
Use cold functions for panic formatting Option::expect, Result::unwra… #31116
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
Conversation
(rust_highfive has picked a reviewer for you, use r? to override) |
Playpen code to compare these in artificial setting: https://play.rust-lang.org/?gist=94e1ab9ed151c75a5a97&version=nightly
|
Looks pretty good to me (if not clear yet: I really, really like this :)). For EDIT: still needs same treatment for |
Seems like a good idea to me. (Though I still dislike |
With this change I might even become an Option.expect() convert. |
e03d5e5
to
9100917
Compare
#[cold] | ||
fn expect_failed(msg: &str) -> ! { | ||
panic!("{}", msg) | ||
} |
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.
Could this be moved outside of Option<T>
? That should mean it's not monomorphized and should be even smaller I believe
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.
Good catch, didn't think of that. It applies to everything I think.
Nice ideas! I had a few more other ideas about monomorphization and seeing if we can't codegen these in libstd, but otherwise I'm always excited about changes like these. |
Maybe Result's |
1a84e70
to
9ff3c2d
Compare
Neat find. |
👏 I like this |
@@ -685,7 +685,7 @@ impl<T, E: fmt::Debug> Result<T, E> { | |||
match self { | |||
Ok(t) => t, | |||
Err(e) => | |||
panic!("called `Result::unwrap()` on an `Err` value: {:?}", e) | |||
unwrap_failed("called `Result::unwrap()` on an `Err` value: {:?}", e), |
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.
I think the trailing {:?}
here can be removed
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.
(same below as well
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.
It's supposed to be more consistent with a trailing comma for every case. Not sure what rustfmt usually does.
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.
oh.. reading.. how do I?
I see. That's an important change.
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.
Oh I think that the trailing : {:?}
part of the string can be removed in both cases, that's covered by the format string at the very bottom
I will rebase to squash all the fixups together into one commit. |
…p etc Option::expect, Result::unwrap, unwrap_err, expect These methods are marked inline, but insert a big chunk of formatting code, as well as other error path related code, such as deallocating a std::io::Error if you have one. We can explicitly separate out that code path into a function that is never inline, since the panicking case should always be rare.
Move functions out of their impl blocks; avoids unnecessary monomorphization by type parameters that are irrelevant to the message output.
80766e6
to
257bff3
Compare
This is done, unless we want to measure the difference of something a bit more interesting. I don't really have the resources to build all of rust multiple times though. |
Use cold functions for panic formatting Option::expect, Result::unwrap, expect These methods are marked inline, but insert a big chunk of formatting code, as well as other error path related code, such as deallocating a std::io::Error if you have one. We can explicitly separate out that code path into a function that is never inline, since the panicking case should always be rare.
I realize this is a very old PR, but I wanted to point out one downside of this change: With this change, for Consider the two following code snippets: fn check(opt: Option<u32>) -> u32 {
opt.expect("This option should always be Some by the time this function is called.")
} fn check(opt: Option<u32>) -> u32 {
match opt {
Some(val) => return val,
None => panic!("This option should always be Some by the time this function is called.")
}
} I would typically assume these two functions should be identical, but in a binary with no panic handler only the former pays the code size cost of the message being embedded in the binary. Of course, in a binary that has many calls to |
Use cold functions for panic formatting Option::expect, Result::unwrap, expect
These methods are marked inline, but insert a big chunk of formatting
code, as well as other error path related code, such as
deallocating a std::io::Error if you have one.
We can explicitly separate out that code path into a function that is
never inline, since the panicking case should always be rare.