There's no Sized bound for &impl Error:
impl<'a, T: Error + ?Sized> Error for &'a T {
#[allow(deprecated)]
fn cause(&self) -> Option<&dyn Error> {
Error::cause(&**self)
}
fn source(&self) -> Option<&(dyn Error + 'static)> {
Error::source(&**self)
}
fn provide<'b>(&'b self, request: &mut Request<'b>) {
Error::provide(&**self, request);
}
}
Or for Arc<impl Error>:
impl<T: core::error::Error + ?Sized> core::error::Error for Arc<T> {
#[allow(deprecated)]
fn cause(&self) -> Option<&dyn core::error::Error> {
core::error::Error::cause(&**self)
}
fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
core::error::Error::source(&**self)
}
fn provide<'a>(&'a self, req: &mut core::error::Request<'a>) {
core::error::Error::provide(&**self, req);
}
}
But there is for Box<impl Error>:
impl<E: Error> Error for Box<E> {
#[allow(deprecated)]
fn cause(&self) -> Option<&dyn Error> {
Error::cause(&**self)
}
fn source(&self) -> Option<&(dyn Error + 'static)> {
Error::source(&**self)
}
fn provide<'b>(&'b self, request: &mut error::Request<'b>) {
Error::provide(&**self, request);
}
}
Just checking that there's a reason, else I assume I can create ACP
jofas
November 24, 2025, 9:34am
2
This is a known quirk of the Box API:
opened 06:14PM - 13 Jan 20 UTC
closed 09:11AM - 14 Jan 20 UTC
T-libs-api
A-error-handling
Currently the implementation of `Error for Box<T>` looks like this:
```rust
… #[stable(feature = "box_error", since = "1.8.0")]
// note the missing `+ ?Sized` bound.
impl<T: Error> Error for Box<T> {
fn description(&self) -> &str {
Error::description(&**self)
}
#[allow(deprecated)]
fn cause(&self) -> Option<&dyn Error> {
Error::cause(&**self)
}
fn source(&self) -> Option<&(dyn Error + 'static)> {
Error::source(&**self)
}
}
```
which in turn disallows passing in dynamic `Error` objects around as easily as it should be possible to:
```rust
fn main() {
let x: Box<dyn std::error::Error> = std::io::Error::last_os_error().into();
fn assert_error<E: std::error::Error>(x: E) {}
assert_error(x);
//^~ error[E0277]: the size for values of type `dyn std::error::Error` cannot be known at compilation time
}
```
`Error` by definition of being object safe is implementable for `Box<T: ?Sized>`. We should relax that bound, especially now that `Box<dyn Error>` is becoming the way in the ecosystem to pass around the type-erased error values.
---
I discovered this after I attempted to use an implementation that looks like this:
```rust
impl<F: std::error::Error + Send + Sync + 'static> From<F> for SomeWrapper {
fn from(f: F) -> Self {
SomeWrapper(Box::new(f))
}
}
```
You cannot add an implementation specialized for `Box<...>` either as that’s prevented by the coherence rules.
master ← GuillaumeGomez:impl_box_error
That's the [error](https://gist.github.com/GuillaumeGomez/ca1e875066fb9ea545d9) … I get by adding `?Sized`:
``` Rust
#[stable(feature = "box_error", since = "1.7.0")]
impl<T: Error + ?Sized> Error for Box<T> {
fn description(&self) -> &str {
Error::description(&**self)
}
fn cause(&self) -> Option<&Error> {
Error::cause(&**self)
}
}
```
I don't know if there is a language feature around today that wasn't back then that would allow adding the ?Sized bound without any conflicts, might be worth looking into.
You need specialization due to the existing implementations
impl<T> From<T> for T { ... }
impl<'e, E: Error + 'e> From<E> for Box<dyn Error + 'e> { ... }
overlapping if Box<dyn Error + '_>: Error.
1 Like