Skip to content

Commit 5a1f2ec

Browse files
Rollup merge of #75180 - KodrAus:feat/error-by-ref, r=m-ou-se
Implement Error for &(impl Error) Opening this up just to see what it breaks. It's unfortunate that `&(impl Error)` doesn't actually implement `Error`. If this direct approach doesn't work out then I'll try something different, like an `Error::by_ref` method. **EDIT:** This is a super low-priority experiment so feel free to cancel it for more important crater runs! 🙂 ----- # Stabilization Report ## Why? We've been working for the last few years to try "fix" the `Error` trait, which is probably one of the most fundamental in the whole standard library. One of its issues is that we commonly expect you to work with abstract errors through `dyn Trait`, but references and smart pointers over `dyn Trait` don't actually implement the `Error` trait. If you have a `&dyn Error` or a `Box<dyn Error>` you simply can't pass it to a method that wants a `impl Error`. ## What does this do? This stabilizes the following trait impl: ```rust impl<'a, T: Error + ?Sized + 'static> Error for &'a T; ``` This means that `&dyn Error` will now satisfy a `impl Error` bound. It doesn't do anything with `Box<dyn Error>` directly. We discussed how we could do `Box<dyn Error>` in the thread here (and elsewhere in the past), but it seems like we need something like lattice-based specialization or a sprinkling of snowflake compiler magic to make that work. Having said that, with this new impl you _can_ now get a `impl Error` from a `Box<dyn Error>` by dereferencing it. ## What breaks? A crater run revealed a few crates broke with something like the following: ```rust // where e: &'short &'long dyn Error err.source() ``` previously we'd auto-deref that `&'short &'long dyn Error` to return a `Option<&'long dyn Error>` from `source`, but now will call directly on `&'short impl Error`, so will return a `Option<&'short dyn Error>`. The fix is to manually deref: ```rust // where e: &'short &'long dyn Error (*err).source() ``` In the recent Libs meeting we considered this acceptable breakage.
2 parents 9a9477f + bbf5001 commit 5a1f2ec

File tree

1 file changed

+21
-0
lines changed

1 file changed

+21
-0
lines changed

library/std/src/error.rs

+21
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,27 @@ impl<T: Error> Error for Box<T> {
486486
}
487487
}
488488

489+
#[stable(feature = "error_by_ref", since = "1.51.0")]
490+
impl<'a, T: Error + ?Sized> Error for &'a T {
491+
#[allow(deprecated, deprecated_in_future)]
492+
fn description(&self) -> &str {
493+
Error::description(&**self)
494+
}
495+
496+
#[allow(deprecated)]
497+
fn cause(&self) -> Option<&dyn Error> {
498+
Error::cause(&**self)
499+
}
500+
501+
fn source(&self) -> Option<&(dyn Error + 'static)> {
502+
Error::source(&**self)
503+
}
504+
505+
fn backtrace(&self) -> Option<&Backtrace> {
506+
Error::backtrace(&**self)
507+
}
508+
}
509+
489510
#[stable(feature = "fmt_error", since = "1.11.0")]
490511
impl Error for fmt::Error {
491512
#[allow(deprecated)]

0 commit comments

Comments
 (0)