-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Start working on proof of concept for exposing Backtrace in core #77384
Conversation
r? @cramertj (rust_highfive has picked a reviewer for you, use r? to override) |
@rustbot assign @kw-fn |
2116576
to
4d45f69
Compare
This comment has been minimized.
This comment has been minimized.
Another thing I've been thinking about. I'm worried that a proof of concept is an insufficient step in proving that backtrace can be moved to core, and that we might also end up wasting effort or never see this project finished. As such I feel like this PR should aim to be the prototype and then eventually the final implementation that we merge. Possibly with an RFC based on the first pass implementation to approve the full design. |
UpdateI talked to the libs team today about this and have a plan now. More or less based on what I've said above I'm going to start with trying to aim straight for what I think the final implementation should look like, and not just for backtrace but also for the error trait in core. The plan is:
The hope is that, given what we know now, we think this should be a relatively small amount of work. If everything goes according to plan this shouldn't delay the backtrace stabilization, and would get us |
f09eb25
to
748d09f
Compare
This comment has been minimized.
This comment has been minimized.
748d09f
to
d0e156d
Compare
This comment has been minimized.
This comment has been minimized.
library/core/src/backtrace.rs
Outdated
let imp: &dyn RawBacktrace = unsafe { &*self.inner }; | ||
fmt::Display::fmt(imp, fmt) | ||
} | ||
} |
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.
nit: missing trailing newline
// perma(?)-unstable | ||
#[unstable(feature = "backtrace", issue = "74465")] | ||
/// | ||
pub trait RawBacktrace: fmt::Debug + fmt::Display + 'static { |
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.
Can you add a Send and Sync bound?
@yaahc - Are you still working on this PR? If not, I'd be interested in continuing work on it. |
@Aaron1011 Right now this PR is on pause because we figured the next step would be to write an RFC based on this design. @JDuchniewicz has started working on that RFC here: https://github.com/JDuchniewicz/rfcs/blob/backtrace-in-core/0000-backtrace-in-core.md That said, I'd love to have any help we can get pushing this PR into a more complete state, I'm just worried that it may be for naught if we end up rejecting this design. |
From the RFC:
How will these be generated? #86844 tries to remove the allocator shim allowing |
Not sure. This is one of the areas I was worried about and figured might tank this design. I don't really have a solution and was hoping people with more familiarity with linking would be able to help me figure out if it was viable. |
Weak linkage would be the standard answer to implement this in different languages I think. There are some targets supported by rustc that don't support weak linkage though I believe. |
Yea, that's the same thing I ran into when trying weak linkage early in the process. I think I need to get a better idea of how this approach could cause issues for |
Closing this as no longer necessary. May re-open in the future if we end up deciding to keep |
@yaahc can you summarize the decision for people not intimately familiar with all the discussions? Is rust not going to get support for backtraces outside of nightly? |
Oh, sure. Apologies for not doing so here. I'd left an explanation in the associated RFC but didn't think to reproduce it here: rust-lang/rfcs#3156 (comment) from the above link
The current status is that we don't intend to merge this RFC. It was written as one of the potential paths to moving error into core assuming generic member access didn't work out but at this point it seems extremely likely that we will merge the generic member access RFC once we finish the provider RFC. That RFC provides a superset of the functionality provided by For context:
So to summarize the summary. We will have support for extracting backtraces from fn extract_backtrace(error: &dyn Error) -> Option<&Backtrace> {
error.backtrace()
} We will use this: fn extract_backtrace(error: &dyn Error) -> Option<&Backtrace> {
error.context_ref::<Backtrace>()
} |
Hmmm, the first example I believe I could/would guess. I don't believe I would ever guess the second.... Likely contributing to increasing the Rust-lang reputation as difficult or at least unintuitive? |
I appreciate the feedback, and yea, this is something I've been worried about. I'll keep trying to think about what I can do to make it easier to learn / understand / intuit, but I'm not really sure what I can do other than focus on documentation and learning resources. I think there may also possibly be a more intuitive / descriptive name than And even ignoring the |
Not sure if this has been discussed (I didn't see it here) - but might it be a good idea to provide a |
The problem is that if |
Perhaps |
I don't think this has to be overanalyzed. The main goal is that people can finally debug their applications without compiling with nightly and then realizing that some dependency did not capture a backtrace, then having to clone/patch the crate and unwrap all the ?'s. It doesn't have to be beginner friendly to access the Backtrace as all beginners want to do is {} or {:?} |
I think the most important things are to have backtrace-aware exception loggers, and as an added bonus where possible error reporting service hooks (e.g. Airbrake, Datadog, LogRocket, Sentry, Rollbar) which can accept a structured backtrace as part of an error report. Ideally one should not be handrolling code to spelunk through a
👍 |
Agreed. "There are no solutions, only trade-offs" Here perhaps the doc's can motivate the novice by presenting an example exhibiting the power? Showing they have head room, and trust they'll be able to recognize the forthcoming "Productivity" or "Performance" the example demonstrates. If a new user is looking at Rust - Performance. Reliability. Productivity. - they likely have performance on their priority list. Hence, they may be open to accepting the tradeoff if they are a little less productive to start with. |
I also don't think rust is that hard for beginners, even though it has that rap. You can clone your way out of lifetime issues, ownership is quite an intuitive concept, and the type system is built in a way that you can learn over time. Contrasting it with Haskell for example where everything is built with monads and transformers and applicative monoids. Either you know what all those things are or you'll have a hard time with reading Haskell code. |
This is a great idea! And no, I don't recall anyone who has proposed it, people have suggested adding an extension trait but this seems like the much more obviously correct answer IMO now that you mention it. There are currently a couple of technical hurdles in the way. We already have something like this for Edit: I just talked to @lcnr about this and he brought up that the compiler team has previously discussed making lang items apply to the crates themselves rather than the individual impls so you can put inherent impls across any of the three crates we have, and he's also indicated that he thinks this will be a relatively easy change and plans to do it this week, so we should absolutely be able to do this, thank you for the suggestion @Alxandr! |
AFAIK rustc does allow it. The float types are primitives and thus not defined in any existing crate. They have inherent impls in both libcore and liballoc. |
That is consistent with my understanding but the issue is we need libcore, liballoc, and libstd, not just libcore and liballoc. I tried double checking the impl and it looks like it is still only two impls to me, though surprisingly the second one appears to be in libstd not liballoc, but either way I don't understand how rustc would allow this. from compiler/rustc_hir/src/lang_items.rs: F32, sym::f32, f32_impl, Target::Impl, GenericRequirement::None;
F64, sym::f64, f64_impl, Target::Impl, GenericRequirement::None;
F32Runtime, sym::f32_runtime, f32_runtime_impl, Target::Impl, GenericRequirement::None;
F64Runtime, sym::f64_runtime, f64_runtime_impl, Target::Impl, GenericRequirement::None; from compiler/rustc_typeck/src/coherence/inherent_impls.rs: ty::Float(ty::FloatTy::F32) => {
self.check_primitive_impl(
item.def_id,
lang_items.f32_impl(),
lang_items.f32_runtime_impl(),
"f32",
"f32",
item.span,
assoc_items,
);
} from library/std/src/f32.rs: #[cfg(not(test))]
#[lang = "f32_runtime"]
impl f32 { from library/core/src/num/f32.rs #[lang = "f32"]
#[cfg(not(test))]
impl f32 { The limiting factor as I understand it is the signature of fn check_primitive_impl(
&self,
impl_def_id: LocalDefId,
lang_def_id: Option<DefId>,
lang_def_id2: Option<DefId>,
lang: &str,
ty: &str,
span: Span,
assoc_items: &[hir::ImplItemRef],
) { |
You can add an extra paramater to |
Ah, yea that was my original plan until @lcnr said he and the compiler team had a better plan that would supercede these impl lang items entirely. If that ends up running into issues though adding a parameter to the method will definitely be the approach I end up taking here. |
opened rust-lang/compiler-team#487 and will work on implementing this over the next weeks |
I used to think the 'Only two things in CS are hard...' quip was a pointed jab. Until I had to do it :) Caveat: GitHub doesn't show any code for functions To my mind If the docs say that If not, and fn extract_backtrace(error: &dyn Error) -> Option<&Backtrace> {
error.background_ref::<Backtrace>()
} |
@taqtiqa-mark ah, yea,
The Suggestion, stderr, and spantrace are all relevant to the error being reported here, but they are potentially too big to fit into the error messages themselves, so we're adding the |
Implementation of the proof of concept described in rust-lang/project-error-handling#3