Open shepmaster opened 1 year ago
As more-or-less expected, with the increased flexibility of the generics, certain pieces of code now become ambigous. For example, this code is no longer valid because nothing constrains e
to a specific type:
let e = trigger().context(SomeSnafu).unwrap_err();
ErrorCompat::backtrace(&e)
As another attempt, I looked at making the trait closer in concept to std::ops::Add
, where we take in a source error, add context to it, then get an output error:
// Library code
pub trait IntoError<C> {
type Error;
fn into_error(self, context: C) -> Self::Error;
}
struct NoneError;
// User code
#[derive(Debug)]
struct GenericError<T> {
value: T,
}
// Generated code
struct GenericSnafu<__T0> {
value: __T0,
}
impl<T, __T0> IntoError<GenericSnafu<__T0>> for NoneError
where
__T0: ::core::convert::Into<T>,
{
type Error = GenericError<T>;
#[track_caller]
fn into_error(self, context: GenericSnafu<__T0>) -> Self::Error {
GenericError {
value: ::core::convert::Into::into(context.value),
}
}
}
Unfortunately, that runs into a compiler error:
error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
--> src/lib.rs:24:6
|
24 | impl<T, __T0> IntoError<GenericSnafu<__T0>> for NoneError
| ^ unconstrained type parameter
In #398, we discussed the possibility of changing
IntoError
to look something likeI think this would be needed to support having multiple
#[snafu(from)]
attributes.