snafu: Cannot create a recursive error type

#[derive(Debug, Snafu)]
pub enum Error {
    #[snafu(display("{}", source))]
    Any { source: Box<Error> },
}
error[E0277]: the trait bound `std::boxed::Box<Error>: std::borrow::Borrow<dyn std::error::Error>` is not satisfied
 --> src/main.rs:3:17
  |
3 | #[derive(Debug, Snafu)]
  |                 ^^^^^ the trait `std::borrow::Borrow<dyn std::error::Error>` is not implemented for `std::boxed::Box<Error>`
  |
  = help: the following implementations were found:
            <std::boxed::Box<T> as std::borrow::Borrow<T>>
  = note: required by `std::borrow::Borrow::borrow`

Reported by @BurntSushi (#46)

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 15 (10 by maintainers)

Commits related to this issue

Most upvoted comments

I’m not likely to be able to push out a new version in the next week or so, but I do see an (ugly) workaround to enable you to move forward.

If you implement Borrow yourself and use foo().map_err(Box::new).context(Selector), you can use the created functions. The autogenerated implementation of Borrow will look something like:

impl/*<...>*/ std::borrow::Borrow<std::error::Error> for std::boxed::Box<Error>
where
    Self: std::error::Error + 'static,
    /* ... */
{
    fn borrow(&self) -> &(std::error::Error + 'static) {
        self
    }
}

In the code for mdBook, they had some similar code to box the error to save space (not sure why, I haven’t dug into it yet).

Yeah I do the same sometimes if benchmarking guides me there. For example: https://github.com/BurntSushi/rust-csv/blob/366c07528af626318c1cc8c172e3242b7fe12570/src/error.rs#L28

Basically the idea is that boxing an error is very inexpensive in most scenarios, since in most scenarios, errors rarely occur. But the error type itself can become quite large, which in turn makes Result<T, Error> large, which in turn results in more time spent in memcpy’ing that stuff around. Using a box can drastically reduce that size and improve overall performance.