Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upGitHub is where the world builds software
Millions of developers and companies build, ship, and maintain their software on GitHub — the largest and most advanced development platform in the world.
Stabilize the backtrace feature. #72981
Conversation
r? @kennytm (rust_highfive has picked a reviewer for you, use r? to override) |
@rfcbot fcp merge |
Team member @withoutboats has proposed to merge this. The next step is review by the rest of the tagged team members: Concerns:
Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
acbcf8d
to
e610f54
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
Thanks for the write-up! The one thing I would add is trait impls to the list of stabilized APIs. |
|
@bors r- (just noting this until end of full final comment period, so non team members can raise concerns) |
The comments on how the I would like to see an implementation or at least a detailed design of the hooks that would enable backtrace support in libcore before we stabilize this. @rfcbot concern Error in core |
Can you provide a positive statement of why the backtrace functionality would provide some unique difficulty? Asking others to prove a negative feels unfair. I'm certainly not going to design hooks for this, though I think they would be useful even beyond getting this stabilized (presumably embedded devs do actually want backtraces and can sometimes have them). It's a big project it's not on anyone's roadmap. Meanwhile, real users are currently regressed. The inherent impl issue is a much bigger blocker for moving Error to core. Despite the claim that we could "hack coherence" around it being accepted as a handwave solution, @sfackler has expressed concern about actually doing this and I agree. I certainly am not comfortable ending up in a situation where std defines inherent impls for core types, but they are separate crates, in any permanent capacity. I would be comfortable with that maybe only if it were strongly motivated by user need and coupled with an ongoing plan to merge core and std and remove the coherence hacks. |
I'm would be happy to do a proof of concept to show how this would potentially work to verify that we could infact move Error to core to prove that it works. Am I correct though in assuming that this solution would still require coherence hacks for Assuming we can show with reasonable confidence that we'd be able to move Error to core with |
|
An update on
|
More or less. I'm like 90% confident that we'll not have any issues moving backtrace to core but 100% positive that I'll be able to fill in the missing 10% before any stabilization could possibly finish. |
We discussed this in the Libs meeting today and felt that stabilizing the backtrace API didn’t necessarily need to be blocked on moving the There’s a pressing need to make this API available for users currently unable to get backtraces on stable Rust using If we still don’t feel comfortable stabilizing the @Amanieu is that enough to satisfy your original blocking concern? |
One thing I am wondering about wrt. the Is there something about the API of that type that is insufficient for libstd's own needs? If so, maybe that should be fixed before stabilizing. I assume printing the backtrace in a custom panic handler would be a prime usecase for |
@RalfJung Good question! I have no idea. But will poke around with the |
@KodrAus FYI, @bjorn3 left a hint at #71706 (comment). |
So we do have reasons to want to keep the capturing for panic backtraces in We can make them consistent by either always calling I also don't think we need to block stabilization on that formatting difference. |
That would be throwing away useful information (which symbols share a frame), so I don't think that would be a good idea. |
@RalfJung That seems to have been the case for panic backtraces for at least the last few years. If we’re concerned about losing that information through the format though then we can go the other way and use a single |
I have no issues with a @rfcbot resolve Error in core |
|
Before this stabilization is merged, I'd like to get #79002 merged, as its changes to the |
Do we specify whether addresses will be resolved to symbols during the capture step vs during the formatting step? |
Stabilization Report
This is a proposal to stabilize the
backtrace
feature in libstd. It would make these additional APIs available on stable:The behavior of the backtrace type, especially as it connects to certain environment variables, is better documented in the module documentation: https://doc.rust-lang.org/std/backtrace/index.html
The internal details of how backtraces are captured and represented are platform specific and unspecified. A platform may not support backtraces at all. Libstd's backtrace type will do its best to report a backtrace to the caller of
Backtrace::capture
andBacktrace::force_capture
.Background and Motivation
This API was proposed as part of RFC 2504, which was merged in August 2018. The API was based on experience with the failure crate, released November 2017, and motivated by a longstanding user request for a standardized way to access backtraces, especially in connection with errors that have been raised. This API was implemented actually in September 2019.
In late 2019, many users began migrating from the
failure
crate to crates based onstd::error::Error
, because most of the API changes proposed in RFC 2504 had been stabilized, and new crates similar to failure but based on std Error had been implemented, most notably thiserror and anyhow by dtolnay. In early 2020, the failure crate was deprecated, and users were recommended to use anyhow and thiserror instead.However, on stable, the user experience of anyhow and thiserror is not equivalent to the user experience of failure, because the backtrace component of RFC 2504 has not been stabilized. Some users have been left in the frustrating and confusing experience of watching the ecosystem move around them to a solution that does not have feature parity for them, because they were depending on the backtrace feature of failure. They are forced to either migrate from stable to nightly or manage compatibility issues with the rest of the ecosystem while staying on failure.
Even the anyhow crate only has meaningful backtraces with the backtrace feature of the crate turned on, which in turn depends on the backtrace feature of std.
Unresolved questions from RFC
One unresolved question was left over from the RFC regarding the API of
capture
: some proposed that rather than have backtraces which return a non-Captured
status, the capture API return an Option. This was discussed at length on the RFC, and the RFC was ultimately merged with an unresolved question to confirm that the current design worked well. There has since been no discussion of that aspect of the RFC.Two aspects complicate the idea of having a backtrace's non-pressence indicated with an option:
Error::backtrace
introduce a third reason a backtrace wouldn't be present: the concrete implementation did not try to capture a backtrace.Combined we would be looking at an API like
fn backtrace(&self) -> Option<&Result<Backtrace, BacktraceError>>
, which becomes very unwieldy. For users who need to interrogate a backtrace's materiality, theBacktraceStatus
provides a means of determining if the backtrace they've captured is not meaningful and why.Issues raised during implementation period
Fmt representation #65280
Changes were made to the representation of the backtrace type, removing the header from the display representation & providing a debug implementation which is consistent with other Debug implementations.
However, #65280 also proposes providing a means of limiting the backtrace using something like the precision syntax. This has not been implemented. I propose that this is a desirable feature, but it is strictly add-on and it should not be a blocker on stabilizing backtrace.
Backtrace and Error in core
The main issue raised during implementation was the relationship of
Error::backtrace
andError
not being in core. TheError
trait is already not in core for another reason: an inherent method ondyn Error
requires theBox
type, which is not in core, but stabilizingError::backtrace
would add a second dependence on a non-core type.It is desirable for the
Error
trait to be available from core, and therefore users have expressed concern about adding a new dependency on a non-core type. However, this stabilization would not present any new challenge that could not be resolved as easily as the existing challenges:Because the existing issue with Error would already require a language-level change to allow std to add an inherent method to
dyn Error
, which multiple team members (me included) have expressed concern about doing, this does not seem to me to present a substantial increase in the amount of work needed to make Error available in core.RFC 2895 and "generic member access"
Finally, there is the idea that RFC 2895 could supercede the Error::backtrace method. RFC 2895 provides an API for essentially a specialized dynamically dispatched "generic member" that errors could have, which is core-compatible. Such an API could then be used to provide the backtrace, or any other dynamically dispatched type, that an error could contain.
However, this RFC is not merged or in FCP, and is still in the early phases of design. We have already soft-regressed users, who have been relying on an existing API that has been in design for several years. Blocking the resolution of those users' problems on an RFC in early design stages would not be prudent.
The basic motivation of RFC 2895 is that it allows errors to provide many different kinds of contexts, not just a backtrace, and in a way which is open ended and extensible. This may be a desirable property for the std error trait, and RFC 2895 may eventually be merged, stabilized, etc. However, I would contend that even in such a case, preferential treatment for backtraces is still desirable. Backtraces are a standard feature provided not only in Rust but in many language ecosystems, which users have come to expect. Providing a first-class method for getting the backtrace, called backtrace, even if it delegates to a more generic "request for context" method in the long term, makes sense for the optimal user experience.
Future work
Other than the future work on the error trait discussed above, there is future work to be done on the backtrace type. In particular, the backtrace type currently provides no method of analysis other than debug and display printing the backtrace. It would be beneficial to provide a platform agnostic, standard API for iterating over the frames of the backtrace and the members of the frames in the long term. Such an API would justify a separate RFC.