Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upRFC: Stabilize implementing panics as aborts #1513
Conversation
alexcrichton
added
the
T-lang
label
Feb 26, 2016
alexcrichton
self-assigned this
Feb 26, 2016
nagisa
reviewed
Feb 26, 2016
| * The compiler will have a [new stable flag](#new-compiler-flags), `-C panic` | ||
| which will configure how unwinding-related code is generated. | ||
| * [Two new unstable attributes](#panic-attributes) will be added to the | ||
| compiler, `#![needs_panic_runtime]` and `#![panic_runtime]`. The standard |
This comment has been minimized.
This comment has been minimized.
nagisa
Feb 26, 2016
Contributor
NIT: we already have a system for boolean configuration switches in attributes. That’s cfg. I strongly propose changing the needs_panic_runtime thing to a cfg.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
alexcrichton
Feb 26, 2016
Author
Member
@nagisa can you elaborate on what you're thinking? Given the way these attributes are defined below I'm not understanding how this could be implemented with #[cfg].
This comment has been minimized.
This comment has been minimized.
nagisa
Feb 26, 2016
Contributor
@alexcrichton This, not these. Turns out that this attribute is inverse of what I thought it is at first (i.e. it declares that crate wants a runtime, rather than describe the fact that runtime is needed). Never mind me here.
This comment has been minimized.
This comment has been minimized.
|
Okay, I have a bunch of thoughts which I won’t be posting inline, because of GitHub’s tendency to lose the comments in the long run. Overall, I think this RFC is incorrectly conflating what current
Right, so I have two points here: with this RFC you cannot disable codegen of cleanups and continue to use the unwinding panic – which is what
Similarly, previously any crate in the dependency tree could opt-out from cleanups (as an optimisation). One crate using That being said, I do see the necessity to only have a single panicking mechanism in a final artefact, so the comment basically boils down to lack of distinction between panicking mechanism and cleanup mechanism or lack thereof. Finally, as the one who landed the |
This comment has been minimized.
This comment has been minimized.
|
I have some minor reservations. This only accomplishes half of the goal of creating no-unwind builds because it still uses a libstd with landing pads. Eventually we're going to get to a place where if you want this you are going to be using either a provided no-unwind std or building it yourself. It's not clear to me how that future world will work with the new If we're going to continue the pattern of |
This comment has been minimized.
This comment has been minimized.
|
I like the overall thrust of this RFC, and am really excited to see abort semantics one step closer to reality! My biggest concern is with the final drawback (which I talked with @alexcrichton about privately):
In particular, my feeling is that typically applications should be the one to choose the strategy, and all of their dependencies must be compatible with that strategy. (In the RFC, if any crate in the graph has abort semantics, the entire artifact does.) It's not hard to imagine pulling in some indirect dependency that silently changes from unwinding to abort, and I don't think that crate authors should be required to explicitly |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
cc @jamwt, because Dropbox has long been a proponent of abort-on-panic. |
This comment has been minimized.
This comment has been minimized.
jamwt
commented
Feb 26, 2016
|
Yeah, I agree with having applications choose the strategy. As long as we're allowed to ensure that all panics abort (as users of various libraries but owners of the application), we're good. |
This comment has been minimized.
This comment has been minimized.
|
Oh wow, that was fast, thanks for the comments! It's true that this RFC is diverging from what I'd be fine leaving the
I'm not really sure how this is relevant, can you clarify? The whole point of the unwinding strategy on Unix today is that it's zero cost in the case where no exception is thrown, and if we had to register a handler every time we had a function call that... wouldn't be zero cost? I will say, however, that if this is just an alternate strategy of handling panics, this RFC should account for that. We would implement another
I suppose I didn't really discuss this as I'm not really sure what the discussion would be in the first place. My current interpretation of the state of MIR and such would be:
Does that make sense? Did you have other concerns? I'd definitely want to make sure that any MIR plans align well with this RFC!
I think that when rustup.rs is ready and we're distributing/managing multiple compiled modes of the standard library we'd still basically want almost everything in this RFC. The first alternative mentions this explicitly by indicating that one major change could be disallowing mixed panic modes in a DAG entirely (instead of allowing a panic runtime to link with crates compiled any which way). Are you thinking, however, that other parts of this RFC would change in the face of such a distribution mechanism? Also, the only drawback I know of with linking an unwinding libstd with an aborting application is that the object code in the standard library itself may have missed optimization opportunities based on the fact that functions will never unwind. Do you know of other drawbacks, however? Much of this RFC is foundationally built upon the idea that linking aborting applications to the libstd binaries we ship is good enough in basically all situations.
One critical portion of this RFC is the validation that the compiler performs to ensure that any sort of weird situations like this can't cause problems at runtime. For example the possible scenarios I see here are:
Basically, the compiler should always be able to provide a principled error message in these situations. Along those lines I'm not really sure what the negative interactions would be between Cargo and choosing the right libstd, but we should be able to relatively easy encourage the user to select an appropriate toolchain. Did you have other concerns in mind, however?
Yeah I'd be fine with basically anything here. I didn't put too much thought into it because they're unstable. I somewhat disagree that these will ever become defacto stable (in the panicking case). It's essentially impossible to write your own panic runtime without compiler support, so I don't think we'll see many of those any time soon. Writing a custom allocator, however, that may indeed hasten the defacto stability!
And to clarify, this RFC does allow for the case of any crate to explicitly choose a panic strategy via This, coupled with @brson's concerns, I believe, have convinced me that this needs to be a first class compiler error. Specifically if a final artifact is being produced the compiler will assert that the panic runtime selected is compiled in the same panic mode as the final artifact itself.
You can indeed! It should be as simple as: extern crate panic_abort;And then you're done! |
bstrie
reviewed
Feb 26, 2016
|
|
||
| * The current implementation of Cargo would mean that a native implementation of | ||
| the profile option would cause recompiles between `cargo build` and `cargo | ||
| test` for projects that specify `panic = 'unwind'`. Is this acceptable? Should |
This comment has been minimized.
This comment has been minimized.
bstrie
Feb 26, 2016
Contributor
Did you mean panic = abort here? (Also, did you mean "naive" instead of "native"?)
If not, then can you elaborate why specifying the same unwinding strategy as the default would force a recompile?
This comment has been minimized.
This comment has been minimized.
alexcrichton
Feb 26, 2016
Author
Member
Gah oops, this is a hilarious combination of multiple types. Correct on both counts!
This comment has been minimized.
This comment has been minimized.
|
To clarify, does I also agree that this pattern of paired |
This comment has been minimized.
This comment has been minimized.
|
Regarding the need to ship two versions of std: Hypothetically, if LLVM extended to other platforms the Windows model of outlining cleanups into separate funclets, those could be placed into separate sections, and stripped out by the linker when not needed. Edit: then again, the same could be achieved with |
This comment has been minimized.
This comment has been minimized.
That's part of it, but it also enables the logic in the compiler to auto-inject a runtime if one isn't found. This is essentially solving the case where so long as you never use the standard library there's no need for a panic runtime to ever get injected. |
This comment has been minimized.
This comment has been minimized.
Yes. As I mentioned, I don't see how the cargo option aligns with a world with custom stds. There will be some - yet undesigned - mechanism in the future to specify what combination of codegen/runtime features that users want the entire world to be compiled with. This new I am further concerned that baking the unwinding configuration into the crate's configuration that we are opening the door to crates being able to specify incompatible codegen/runtime options. Things that need to be specified globally in the future:
There are probably more I'm forgetting right now. These are all related and we should have a plan to solve this issue of custom codegen/runtime components generally, not piecewise.
Bloat. |
This comment has been minimized.
This comment has been minimized.
|
How does this interact with panic handlers? Will panic handlers be called before an abort? |
This comment has been minimized.
This comment has been minimized.
|
@Amanieu No, there is no unwinding, destructors, etc. involved (hence 'abort'). |
This comment has been minimized.
This comment has been minimized.
|
I would like to propose an alternative design for this feature, just to throw the idea out there. The main issue with
However we could make Benefits:
Drawbacks:
|
This comment has been minimized.
This comment has been minimized.
My main concern is conflation of panicking and cleanup strategies in this RFC. Every other major issue I have with the RFC stems from that.
Any crate at the branches of call tree could use the option of explicitly leaking resources as an optimisation. As stated in the RFC itself, the cleanups are not entirely free – they consume binary space in the final executable, they increase compilation times significantly. They also compete for CPU cache, decrease instruction locality and so on. I do not see e.g. numerics crate caring about a leaked vector or two if that helps to avoid generating a bunch of code near success pathes in computation-intensive functions.
My only point here that conflating panicking and cleanup strategy doesn’t make much sense. I didn’t intend to claim it is a sensible cleanup strategy though.
Right, so for some fictional
But we do not generate
I do not see how it makes sense to generate landing pads at all if we panic by |
sdroege
reviewed
Feb 27, 2016
| > from 18s) and 13% smaller (15MB to 13MB). Sizable gains! | ||
| Overall, the ability to recover panics is something that needs to be decided at | ||
| the application level rather than at the language level. Currently the compiler |
This comment has been minimized.
This comment has been minimized.
sdroege
Feb 27, 2016
At the application level can make sense, but what about libraries that want to opt-out because e.g. they can't recover from assertions. But what if you combine such library with applications that do want recoverable panics because they don't want to take the whole process down?
This comment has been minimized.
This comment has been minimized.
alexcrichton
Feb 28, 2016
Author
Member
Unfortunately that's essentially a situation which has no solution. The crate which wants to force panic=abort would link to panic_abort while the application forcing panic=unwind would link to panic_unwind. The compiler would detect this situation and generate an error.
I don't currently know of a way to make that kind of situation succeed to compile.
This comment has been minimized.
This comment has been minimized.
phil-opp
commented
Feb 27, 2016
|
Just a small nit: The PR summary comment uses a |
This comment has been minimized.
This comment has been minimized.
matthieu-m
commented
Feb 27, 2016
|
I have some concerns about the ability of an application to make an informed choice about the panic strategy. Specifically, I am thinking that as a crate author I could perfectly use speculative execution and catch panics in case of issue. Today, from a user's point of view, this is completely transparent. Tomorrow, if the user decides to specify Worse, of course, is when a crate that previously was never generating/catching a panic suddenly starts doing so; as an application, it means that I need to audit each new version of the crates I pull to ensure their compatibility with In essence:
To me, as a crate author, whether I am willing to commit to support |
This comment has been minimized.
This comment has been minimized.
|
Rust already never guarantees destructors run though, so you can't make that kind of assumption. And when setting panic to abort, isn't "halt her application" what she'd want in the first place? On Feb 27, 2016, 10:40 -0500, matthieu-mnotifications@github.com, wrote:
|
This comment has been minimized.
This comment has been minimized.
main--
commented
Feb 27, 2016
@matthieu-m Of course you can do so if - and only if - you choose to ignore the warning in the Perhaps "panic=abort mode" would finally provide a strong motivation against misusing Now to my general comments on the RFC:
It's unclear to me which direction this design really chooses: While some parts of the RFC ("There will currently be two supported strategies") suggest that the set of available is clearly defined and very definitely not arbitrarily user-extensible, some of the discussion (e.g. the part I'm quoting here) appeared to be about user-defined panic strategies. This second version is also implied by the general design around (seemingly) arbitrary crates. The major difference between this area and memory allocators is that the latter generally don't require any specific language support and hence can be implemented purely as libraries (crates). This approach doesn't really seem viable for panic strategies as these care about code generation (things like invoke vs call) and are therefore always tied to hardcoded paths in the compiler unless the design is powerful enough to allow each strategy crate to hook into these compiler paths on its own, e.g. by being loaded as a compiler plugin. So to sum things up, I don't see how the current design benefits (at all) from utilizing a generic crate-based solution (versus e.g. just a compiler flag and some special piece of crate metadata that can be checked for compatibility at link-time), so I obviously don't think the downsides (conflicts etc) are worth it. |
This comment has been minimized.
This comment has been minimized.
|
rustc would like to not use unwinding, but print a nice ICE message before aborting. Is that going to be supported? |
This comment has been minimized.
This comment has been minimized.
One of the biggest concerns I (and others) had with stabilizing I emphatically do not believe that crate authors should use The idea behind On the other hand, handleable errors are expressed using Is is a feature not a bug that this RFC discourages crate authors from using panics to represent handle-able errors. If |
This comment has been minimized.
This comment has been minimized.
|
I'm going to sound like a broken record here, but the confusion over whether |
This comment has been minimized.
This comment has been minimized.
|
I like that name On Feb 27, 2016, 21:30 -0500, Ben Striegelnotifications@github.com, wrote:
|
This comment has been minimized.
This comment has been minimized.
rillian
commented
Mar 28, 2016
Yes. It's perhaps worth distinguishing, though, between size issues and behaviour issues. It's easier to take special optimization steps on build infrastructure, so a higher bar is possible there. But as you say, this is something that can benefit many projects, so making it easy is advantageous. |
alexcrichton
removed
the
I-nominated
label
Mar 28, 2016
This comment has been minimized.
This comment has been minimized.
|
@rillian yeah I agree that separating them out is important. Behaviorally I believe Gecko needs no more than what this RFC provides. This provides a guaranteed ability to translate all Rust panics to aborts rather than stack unwinding (even through a custom method via your own panic runtime). The optimization steps, specifically for size, are tangential infrastructure related problems on our end which we intend to tackle eventually anyway :) |
This comment has been minimized.
This comment has been minimized.
|
The lang team did not have full quorum this week and will consider this RFC during next week's meeting; remaining in FCP until then. |
This comment has been minimized.
This comment has been minimized.
|
It seems that there is some kind of false genericity here - you can only really choose between two options, you can't plug in your own strategy. That would require some mechanism for augmenting the compiler (pluggable MIR pass?). I'm a bit unclear what would happen with However, as a step towards a fully generic mechanism, this RFC looks good. in particular, adopting a somewhat future proof compiler flag. The attributes sound like the right direction too, though it sounds like there will be some future discussion there. |
This comment has been minimized.
This comment has been minimized.
|
@nrc yeah this isn't intended to be any form of "truly general mechanism" or something like that, the compiler will reject any |
This comment has been minimized.
This comment has been minimized.
|
Will just libcore have |
This comment has been minimized.
This comment has been minimized.
|
No, the standard library will have that attribute as that's where panics are implemented. |
This comment has been minimized.
This comment has been minimized.
|
The additional lang items for core panics don't strike me as something we want forever. But if this RFC's proposals don't get stabilized until a more general needs/provides mechanism is investigated, I guess this is fine for now. edit heh and that's basically what I wrote a month ago #1513 (comment) So +1 for RFC if we tree treat it as experiment/stopgap. -1 for longterm as is: besides services pattern without proper support, rustc is now further entangled with std lib architecture which isn't something we generally want. |
This comment has been minimized.
This comment has been minimized.
|
WRT. the The idea is that a single downstream crate will be able to "bless" a particular trait implementation. Upstream crates will be able to implicitly use the yet-to-be-determined "blessed" implementation by simply calling the trait methods: This would normally be an error, because the compiler wouldn't be able to determine which implementation of The exact mechanism for blessing a trait could vary, but an easy option is to mirror the existing attributes: The advantages are extensibility and proper namespacing of blessed items. Additional fun could be had by allowing |
This comment has been minimized.
This comment has been minimized.
|
It's official! The @rust-lang/lang team has decided to accept this RFC. |
This comment has been minimized.
This comment has been minimized.
|
Tracking issue: rust-lang/rust#32837 If you'd like to keep following the development of this feature, please subscribe to that issue, thanks! :) |
alexcrichton commentedFeb 26, 2016
-Z no-landing-padsflag under the name-C panic=valimplementations of panic just before a final product is generated.
[profile.dev]option to Cargo to disable unwinding.Rendered