Hi all!
I'm trying to write a simple library function that takes a closure as argument, does its own stuff, repacks errors from the closure and retunrs them.
I've been banging my head into problems with this function for more than a week now, and now I'm stuck again.
In the user code I want to have as simple error handling as possible, so I'm using type AnyError = Box<dyn std::error::Error + 'static>;
. So for my library function I've created an error type that wraps anything implementing error and was hoping it would just contain the boxed errors and behave well.
Unfortunately the compiler complaints about not knowing size at compile time ... I don't understand why, because I was expecting to be just saving Boxes of the unsized types ...
Can you please help me understand this puzzle?
Here's a minimalized version of the problem:
////////////////////////////// lib.rs
#[derive(Debug)]
enum Err <E1>
where
E1: std::error::Error + 'static,
{
X {source: E1},
}
impl <E1> std::fmt::Display for Err<E1>
where
E1: std::error::Error + 'static,
{
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "Err::X") }
}
impl <E1> std::error::Error for Err<E1>
where
E1: std::error::Error + 'static, {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::X{source} => Some(source)
}
}
}
fn library_function<F1, E1>(f1: F1) -> Result<(), Err<E1>>
where
F1: FnOnce() -> Result<(), E1>,
E1: std::error::Error + 'static,
{
f1().map_err(|source| Err::X { source })?;
Ok(())
}
////////////////////////////// user.rs
type AnyError = Box<dyn std::error::Error + 'static>;
type SimpleResult = Result<(), AnyError>;
fn main() -> SimpleResult {
library_function(|| -> SimpleResult { Ok(()) })
}
Errors:
Compiling playground v0.0.1 (/playground)
error[E0277]: the size for values of type `(dyn std::error::Error + 'static)` cannot be known at compilation time
--> src/main.rs:42:5
|
27 | fn library_function<F1, E1>(f1: F1) -> Result<(), Err<E1>>
| ----------------
...
30 | E1: std::error::Error + 'static,
| ----------------- required by this bound in `library_function`
...
42 | library_function(|| -> SimpleResult { Ok(()) })
| ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `(dyn std::error::Error + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: required because of the requirements on the impl of `std::error::Error` for `std::boxed::Box<(dyn std::error::Error + 'static)>`
error[E0308]: mismatched types
--> src/main.rs:42:5
|
41 | fn main() -> SimpleResult {
| ------------ expected `std::result::Result<(), std::boxed::Box<(dyn std::error::Error + 'static)>>` because of return type
42 | library_function(|| -> SimpleResult { Ok(()) })
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `Err`
|
= note: expected enum `std::result::Result<_, std::boxed::Box<_>>`
found enum `std::result::Result<_, Err<std::boxed::Box<_>>>`
error[E0277]: the size for values of type `(dyn std::error::Error + 'static)` cannot be known at compilation time
--> src/main.rs:42:5
|
3 | / enum Err <E1>
4 | | where
5 | | E1: std::error::Error + 'static,
6 | | {
7 | | X {source: E1},
8 | | }
| |_- required by `Err`
...
42 | library_function(|| -> SimpleResult { Ok(()) })
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `(dyn std::error::Error + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: required because of the requirements on the impl of `std::error::Error` for `std::boxed::Box<(dyn std::error::Error + 'static)>`
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
error: could not compile `playground`.
To learn more, run the command again with --verbose.