Giter Site home page Giter Site logo

Comments (8)

jquesada2016 avatar jquesada2016 commented on June 7, 2024 1

If you like, I can give ErrorFrame a try.

If I understood you correctly, ErrorFrame would do what I suggested above, but lazily when the error is being debugged, requested, etc. i.e., it would only walk down the error source chain when needed, rather than on .into_report().

from hash.

jquesada2016 avatar jquesada2016 commented on June 7, 2024 1

@nonparibus I have not had a chance to give this a shot, but have not forgotten about it either.

from hash.

TimDiekmann avatar TimDiekmann commented on June 7, 2024

Hi @jquesada2016 and thanks for filing this issue!

I really like the idea, but sadly I don't see how this could be implemented. Error::source returns a reference to another error with the lifetime bound to the error itself. When calling .into_report(), the error is moved into the Report, but we cannot move out the errors returned from source() and store them alongside in the Report. That way, it's neither possible to add them as attachments, nor as context frames (I prefer the latter).

One way how this could be possible is to not store the source errors in the report but install a Debug hook for the errors and print the sources as well. This, however, has two downsides:

  1. It's neither rendered as an attachment nor as context, which would be preferred.
  2. The Error::provide method would not be called when printing

Anyway, this would require installing a debug hook for each error, which you are expecting, which is obviously unviable. Sadly, to my knowledge, it's not possible to use the Provider API to get all objects, which are implementing a certain trait (i.e. Error).
However, we could wrap the error, where .into_report() is called on, and provide a custom debug implementation, which supports this feature, or even add some special handling for this (as Error is a major trait we are supporting). I don't know if this is achievable easily, but it's definitely worth a try!

It's likely, that this method will require a nightly compiler to work.

What do you think?

from hash.

jquesada2016 avatar jquesada2016 commented on June 7, 2024

The last option you suggested might be the best option out of the ones you proposed.

What if .into_report() wrapped the Box<dyn Error> in Rc, so we can have each source as it's own context frame? The way this might work may be:

  1. wrap the error in Rc to make it a Rc<dyn Error>.
  2. For each .source() which yields Some(_), we clone the Rc along with the depth it was at to get to it's source error, and add that as a context frame, something like:
struct IntoReportFrame {
   depth: usize,
   error: Rc<dyn Error>,
}

The advantages to this, is that providing and downcasting would work just fine! We'd just need to check for two types:

a) the original T type
b) the possible Rc type

The biggest downside to this approach would be performance on errors, since you would need to walk down the error source chain for each level.

from hash.

TimDiekmann avatar TimDiekmann commented on June 7, 2024

Your approach most likely would work, however, we would need to use Arc instead of Rc as otherwise, the Context would not be Send + Sync. Personally, I'd prefer to avoid this because, as you mentioned, this requires traversing the list of sources of the errors on error creation. I think achieving this behavior is possible by special-casing an ErrorFrame (name to be decided on, but it's hidden anyway) when traversing the Report but this, obviously, is harder to implement.

The biggest issue, currently, is to detect if the Report is created from an Error or from any other Context as T: Error has just a blanket implementation for Context. The ideal solution would be to use #![feature(specialization)], but as min_specialization is not enough in this case, this is not really an option. The other option is to implement a hidden fn __source(&self) -> Option<&impl Context> { None } on the Context trait, which is only filled by the blanket implementation. We are considering removing the Context trait entirely and replacing it with Error, but as Error is not available in core (without a nightly toolchain), we can't do this yet. I will look into this as soon as I can find the time.

from hash.

TimDiekmann avatar TimDiekmann commented on June 7, 2024

If you like, I can give ErrorFrame a try.

Sure, why not! 🎉
Feel free to ping me if you need any help. It's not a problem to open a half-baked or draft PR.

Generally, this consists of two parts:

  1. Detecting, if the frame to be added is an Error or, by faking it, a hidden method on Context, which is only implemented on the blanket Error implementation. If you, however, can come up with a nicer way to solve this, I'd love to see that! (Note, that we try to keep the output on stable and nightly the same. Even though we don't have SemVer-guarantees for the output it would be nice to have a unified format)
  2. (probably the easiest solution) modifying the traversal logic of the Report::frames() method to return the sources of the errors as well. I, however, don't know if we can/want to expose the additional traversal as frames_mut probably cannot be adjusted.

from hash.

nonparibus avatar nonparibus commented on June 7, 2024

Hi @jquesada2016, I was curious about this, and wanted to check in to see if you'd been able to give it any kind of a look. Thanks!

from hash.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.