Stream: project-error-handling

Topic: Stabilizing Backtrace / Core Error Proof of Concept


view this post on Zulip Jane Lusby (Sep 25 2020 at 17:56):

attempting to kick this back into motion as best as I can

for people looking for background: https://github.com/rust-lang/project-error-handling/issues/3

Right now we need to figure out how to fix the coherence issues around the From<&str> for Box<dyn Error + Send + Sync + 'a> impl in std`, which can no longer circumvent the orphan rule due to introduced crate boundaries. I feel like this might be an issue we need to communicate with the libs or lang teams to solve. cc @Ashley Mannix

view this post on Zulip Jane Lusby (Sep 25 2020 at 17:58):

the options I can think of are:

  1. Focus on pushing for a merge of std, alloc, and core
  2. some sort of negative impl to circumvent the orphan rule and "promise" that &str will never implement std::error::Error.
  3. Wait for specialization so that these impls can overlap

view this post on Zulip Josh Triplett (Sep 25 2020 at 17:59):

@Jane Lusby I get the distinct impression that merging std and alloc and core isn't incredibly hard, it's just not something anyone is prepared to pick up and run with.

view this post on Zulip Josh Triplett (Sep 25 2020 at 17:59):

(It's not easy, but the steps are more-or-less understood.)

view this post on Zulip Jane Lusby (Sep 25 2020 at 17:59):

cool!

view this post on Zulip Josh Triplett (Sep 25 2020 at 18:00):

If someone were prepared to take it on as their primary task for a couple of releases, I think it could be done without monumental effort.

view this post on Zulip Jane Lusby (Sep 25 2020 at 18:02):

I definitely want to wait until we've talked through all the possible solutions and decided that that's the best one but if that ends up being the best way forward for our error trait issues then I think I'd be happy to take that on or mentor/shepherd any contributors who want to drive it to completion

view this post on Zulip Jane Lusby (Sep 25 2020 at 18:03):

@Josh Triplett wait is the issue merging alloc and std or core and std?

view this post on Zulip Jane Lusby (Sep 25 2020 at 18:03):

or all three?

view this post on Zulip Josh Triplett (Sep 25 2020 at 18:03):

Alloc is "between" std and core. I don't think it'd be feasible to merge std and core without accounting for alloc.

view this post on Zulip Josh Triplett (Sep 25 2020 at 18:03):

And the same mechanisms that would allow merging std and core will extend to alloc.

view this post on Zulip Josh Triplett (Sep 25 2020 at 18:04):

The notion would be to have one crate for the standard library that has something like feature flags to determine whether it has core, core+alloc, or core+alloc+std.

view this post on Zulip Josh Triplett (Sep 25 2020 at 18:04):

(And, in the future, more fine-grained distinctions than that.)

view this post on Zulip Jane Lusby (Sep 25 2020 at 18:05):

gotchya

view this post on Zulip Josh Triplett (Sep 25 2020 at 18:05):

You may want to talk to @Eric Huss about cargo's -Zbuild-std features, which interact with this.

view this post on Zulip nagisa (Sep 25 2020 at 19:05):

The From<&str> for Box<dyn Error + Send + Sync + 'a> could go to the alloc crate, but it _still_ triggers coherence (wrongly?). Box<dyn Error ...> is after all a concrete type and Box is defined in the same crate.

view this post on Zulip nagisa (Sep 25 2020 at 19:07):

In particular the error message says:

//      = note: upstream crates may add a new impl of trait `core::error::Error` for type `&str` in future versions

but that seems irrelevant to me, whatever impls of the Error trait upstream or downstream crates add here do not matter because Box<dyn Error> is already a concrete type.

view this post on Zulip nagisa (Sep 25 2020 at 19:08):

Ah, my bad, forgot about impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + 'a>

view this post on Zulip Jane Lusby (Sep 25 2020 at 19:26):

I'm assuming we can't use #[feature(min_specialization)] to fix this one

view this post on Zulip Jane Lusby (Sep 25 2020 at 19:26):

tho if we could specialize the From<E> impl on Box<dyn Error> that would be huge

view this post on Zulip Jane Lusby (Sep 25 2020 at 19:27):

wait no nvm

view this post on Zulip Jane Lusby (Sep 25 2020 at 19:27):

that wouldn't be that big of a deal

view this post on Zulip Jane Lusby (Sep 25 2020 at 19:27):

the big one is From<T> for T

view this post on Zulip nagisa (Sep 25 2020 at 19:40):

I think I tried the trivial thing but it didn't work.

view this post on Zulip nagisa (Sep 25 2020 at 19:41):

(i.e. adding a default to the methods of impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + 'a>.

view this post on Zulip Sean Chen (he/him) (Sep 26 2020 at 00:24):

The primary difference between std and core is that core doesn't have access to alloc, right? I was always under the impression that the two were distinct on purpose. Is that actually not the case? Is eventually merging the two actually a desirable outcome?

view this post on Zulip Jane Lusby (Sep 26 2020 at 00:25):

The primary difference between std and core is that core doesn't have access to alloc, right?

I think this is accurate, though there are also a lot of OS integrations in std that aren't in core or alloc afaik

view this post on Zulip Jane Lusby (Sep 26 2020 at 00:26):

I don't know the decision making process behind the split originally but my understanding is that its regarded as a mistake now, or at least it's no longer necessary

view this post on Zulip Jane Lusby (Sep 26 2020 at 00:26):

If I had to guess I suspect the reason for the split was that we didn't have good support for conditionally compiling std

view this post on Zulip Ashley Mannix (Sep 26 2020 at 02:44):

I actually don’t remember when the split first came about... That might be a fun bit of spelunking 🙂 core is kind of weird because it’s a bit of an arbitrarily selected subset of the standard library that is platform agnostic and considered fundamental. It’s not everything that doesn’t depend on an OS or a heap allocator. There are things that could be in core but aren’t. You’d kind of hope the majority of the standard traits would be in core but there are glaring omissions (Error being the biggest). I would _love_ to be able to unify the standard library crates, avoid all the coherence sadness between them and the clumsy effort libraries need to go through to be maximally portable

view this post on Zulip Jakub Duchniewicz (Sep 26 2020 at 08:01):

Maybe I am speaking out of place here, but would merging alloc with core and std not be detrimental to the granularity with which developers can compose their Rust programs?
Nevertheless, Erroris a fundamental part of any language, and I strongly believe it would be useful to have it in core

view this post on Zulip Jane Lusby (Sep 26 2020 at 12:03):

@Jakub Duchniewicz not that I'm aware of

view this post on Zulip Jane Lusby (Sep 26 2020 at 12:05):

that said ive not done much no_std work

view this post on Zulip DPC (Sep 26 2020 at 12:37):

Nevertheless, Error is a fundamental part of any language, and I strongly believe it would be useful to have it in core

Definitely, but at the same time, Error is dependent on Display which is dependent on the Formatter and might not available in no_std environments

view this post on Zulip Ashley Mannix (Sep 26 2020 at 12:40):

@Jakub Duchniewicz Actually I think the result could be giving libraries finer granularity to depend on just the capabilities they need entirely internally. I think most libraries I work on end up being unconditionally no_std because I don’t usually need std. But using Cargo features to opt in/out of std or alloc doesn’t feel ideal, since cross-cutting concerns like platform capabilities can be tricky to represent for all dependencies with the tools Cargo manifests give us

view this post on Zulip Jane Lusby (Sep 26 2020 at 12:42):

@DPC isnt fmt already in core?

view this post on Zulip Ashley Mannix (Sep 26 2020 at 12:42):

@DPC Thankfully Display is actually available in core :relieved:

view this post on Zulip Ashley Mannix (Sep 26 2020 at 12:43):

It does definitely still leave you to figure out _how_ to implement fmt::Write though

view this post on Zulip Ashley Mannix (Sep 26 2020 at 12:48):

I guess most embedded code would format to like a serial port or something?

view this post on Zulip Ashley Mannix (Sep 26 2020 at 12:54):

@Jane Lusby Am I right in my understanding that stabilizing backtrace as-is isn’t painting ourselves into any deeper corners with respect to Error in core than we’re already in?

view this post on Zulip Ashley Mannix (Sep 26 2020 at 12:54):

I guess that’s what the prototypes aim to prove

view this post on Zulip Jane Lusby (Sep 26 2020 at 12:59):

@Ashley Mannix as far as I can tell stabilizing backtrace won't pose an issue but I should look at @nagisa's PR more closely

view this post on Zulip Jane Lusby (Sep 26 2020 at 13:01):

oh dang that branch removed bt

view this post on Zulip Jane Lusby (Sep 26 2020 at 13:01):

so yea I still need to prototype doing a backtrace impl based on hooks

view this post on Zulip Jane Lusby (Sep 26 2020 at 13:02):

I'm guessing that will still be necessary even with a core std merge otherwise the backtrace type might still depend on the alloc or os features

view this post on Zulip Jane Lusby (Sep 26 2020 at 13:03):

gonna try working on that today

view this post on Zulip Lokathor (Sep 26 2020 at 14:52):

One thing about Display and other format friends is that it's often very large on code size generated. To the point where people have crates with alternative formatting systems just to cut down on code size.

So throwing that requirement at all embedded folks is probably giving someone a pretty bad time.

view this post on Zulip Jane Lusby (Sep 26 2020 at 15:46):

@Lokathor I think the generic member access RFC can solve that issue just fine

view this post on Zulip Jane Lusby (Sep 26 2020 at 15:47):

hopefully doing empty unused Display and Debug impls isn't costly

view this post on Zulip Lokathor (Sep 26 2020 at 15:53):

I'm not familiar with that RFC

view this post on Zulip Jane Lusby (Sep 26 2020 at 15:53):

https://github.com/yaahc/rfcs/blob/master/text/0000-dyn-error-generic-member-access.md

view this post on Zulip Jane Lusby (Sep 26 2020 at 15:55):

its introduces a new type kinda like Any but with support for passing values and trait objects too and uses that to essentially add a generic function for requesting data from errors by the type, so you could go error.context::<&dyn ufmt::Display>() or w/e and get the error message via some other formatting trait

view this post on Zulip Jane Lusby (Sep 26 2020 at 15:56):

its a little out of date tho, nika did all the work on the type erasure, I originally was just using Any but I was sad about it not supporting slices and dyn traits, so she fixed it, more recently she updated it to be a much nicer implementation and that's living in a PR over here https://github.com/mystor/object-provider/pull/3

view this post on Zulip Jane Lusby (Sep 26 2020 at 15:57):

but in theory this method could supercede source, backtrace, Display, andDebug as a way to get access to inner values of the error

view this post on Zulip Jane Lusby (Sep 26 2020 at 15:58):

and it can be used for upcasting, which is what you'd be doing for an alternate fmt trait

view this post on Zulip Jane Lusby (Sep 26 2020 at 15:59):

            fn provide<'a>(&'a self, request: &mut Request<'a>) {
                request
                    .provide_ref::<&dyn MyFavoriteDisplayAlternative>(&self);
            }

view this post on Zulip Jane Lusby (Sep 26 2020 at 16:00):

back on topic tho, trying to figure out how to do this hook change and I'm quite lost ^_^

view this post on Zulip Jane Lusby (Sep 26 2020 at 16:00):

trying to figure out how the panic hooks in core are configured, but i expect its going to be quite a lot to dig into because I think they're built into the language

view this post on Zulip Jane Lusby (Sep 26 2020 at 16:00):

implemented

view this post on Zulip Jane Lusby (Sep 26 2020 at 16:00):

whatever

view this post on Zulip Lokathor (Sep 26 2020 at 16:01):

no you define your own

view this post on Zulip Jane Lusby (Sep 26 2020 at 16:01):

theres some fn's that you have to define right

view this post on Zulip Jane Lusby (Sep 26 2020 at 16:01):

im looking at this

view this post on Zulip Jane Lusby (Sep 26 2020 at 16:01):

extern "C" {
    fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static);

    /// `payload` is actually a `*mut &mut dyn BoxMeUp` but that would cause FFI warnings.
    /// It cannot be `Box<dyn BoxMeUp>` because the other end of this call does not depend
    /// on liballoc, and thus cannot use `Box`.
    #[unwind(allowed)]
    fn __rust_start_panic(payload: usize) -> u32;
}

view this post on Zulip Jane Lusby (Sep 26 2020 at 16:02):

TIL libpanic is its own thing

view this post on Zulip Lokathor (Sep 26 2020 at 16:03):

neat

view this post on Zulip Jane Lusby (Sep 26 2020 at 16:04):

oh theres two
libpanic_abort and libpanic_unwind

view this post on Zulip Jane Lusby (Sep 26 2020 at 16:05):

that must be how they switch the panic behaviour based on the config

view this post on Zulip Jane Lusby (Sep 26 2020 at 16:05):

but that also means I'm probably too far, because libpanic_abort's impl doesn't seem to pass the payload into any other functions

view this post on Zulip Jane Lusby (Sep 26 2020 at 16:05):

and I'm 99% sure panic handlers still get called before abort

view this post on Zulip Jane Lusby (Sep 26 2020 at 16:05):

so there must be something else that is happening first, gonna start tracing down thru the panic macro I guess

view this post on Zulip Jane Lusby (Sep 26 2020 at 16:08):

there it is, this is the lang item i was looking for

view this post on Zulip Jane Lusby (Sep 26 2020 at 16:08):

extern "Rust" {
    #[lang = "panic_impl"]
    fn panic_impl(pi: &PanicInfo<'_>) -> !;
}

view this post on Zulip Jane Lusby (Sep 26 2020 at 16:11):

i have no idea where this goes, can't find an instance of it being implemented in std D:

view this post on Zulip Jane Lusby (Sep 26 2020 at 16:12):


view this post on Zulip Jane Lusby (Sep 26 2020 at 16:13):

1. In `src/librustc_middle/middle/weak_lang_items.rs`, `panic_impl` is declared as 'weak lang item',
   with the symbol `rust_begin_unwind`. This is used in `librustc_typeck/collect.rs`
   to set the actual symbol name to `rust_begin_unwind`.

   Note that `panic_impl` is declared in an `extern "Rust"` block,
   which means that libcore will attempt to call a foreign symbol called `rust_begin_unwind`
   (to be resolved at link time)

view this post on Zulip Jane Lusby (Sep 26 2020 at 16:32):

here's my extremely vague guess at what has to be done https://github.com/rust-lang/project-error-handling/issues/3#issuecomment-699516309

view this post on Zulip Jane Lusby (Sep 26 2020 at 16:32):

I think im going to explore the global allocator stuff now

view this post on Zulip Jane Lusby (Sep 26 2020 at 16:32):

since its apparently similar

view this post on Zulip Jane Lusby (Sep 26 2020 at 16:33):

maybe its easier to understand or closer to what we need for backtrace

view this post on Zulip Lokathor (Sep 26 2020 at 17:06):

So in no_std, the panic_handler is called as soon as the panic starts, and it's up to the panic handler to never return (aborting is one way you might do this).

view this post on Zulip Lokathor (Sep 26 2020 at 17:08):

in std, i believe the ordering is that the panic starts, then the runtime's built in panic_handler calls the panic hook (which prints your panic message to stderr by default), then the runtime's panic_handler will either abort or unwind after the panic_hook returns.

view this post on Zulip Jubilee (Sep 28 2020 at 17:45):

examples of libs that Lokathor is talking about:

view this post on Zulip Jubilee (Sep 28 2020 at 17:52):

At the risk of sounding silly, I feel like part of the problem is that we want viewable errors to have whatever encoding works for the platform, but they should still be parseable. In some computers, historically, that has been a series of beeps. However, fmt::Display is entangled with a concept of specifically text formatting, which is very important, but not the same.

view this post on Zulip Jane Lusby (Oct 01 2020 at 02:46):

still early days but I've started working on the proof of concept :D https://github.com/rust-lang/rust/pull/77384/files

view this post on Zulip Jane Lusby (Oct 01 2020 at 02:46):

rn it doesn't even compile let alone work but I'll hopefully get it in a working state tomorrow

view this post on Zulip oliver (Oct 02 2020 at 22:58):

Any progress :smile:

view this post on Zulip oliver (Oct 02 2020 at 23:00):

I'm having trouble adding core_backtrace to the symbols proc macro

view this post on Zulip oliver (Oct 02 2020 at 23:01):

error: Symbol `compile_error` must precede `core_backtrace`
error: proc macro panicked
    --> compiler/rustc_span/src/symbol.rs:22:1
     |
22   | / symbols! {
23   | |     // After modifying this list adjust `is_special`, `is_used_keyword`/`is_unused_keyword`,
24   | |     // this should be rarely necessary though if the keywords are kept in alphabetic order.
25   | |     Keywords {
...    |
1196 | |     }
1197 | | }
     | |_^
     |
     = help: message: errors in `Keywords` and/or `Symbols`

view this post on Zulip oliver (Oct 02 2020 at 23:02):

ez fix :laughing:

view this post on Zulip Jane Lusby (Oct 03 2020 at 00:10):

i got some more work done yesterday so now it has that core_backtrace feature and it compiles but doesn't pass tests, but I haven't done any more work today and probably wont due to some pretty fked up air quality and heat in SF today

view this post on Zulip Jane Lusby (Oct 03 2020 at 00:11):

extremely hard to focus when I have to close all the windows in an apartment with no air conditioning, its rather miserable in here today

view this post on Zulip oliver (Oct 03 2020 at 00:25):

Yeah I've been hearing about it from friends

view this post on Zulip Ashley Mannix (Oct 03 2020 at 01:43):

Oh yikes! Stay safe :sweat: Bushfires are the pits


Last updated: Jan 29 2022 at 10:01 UTC