I came across a strange trait bounds not satisified error while playing with an extension trait today, I reduced it to this minimum snippet (also playground):
/// basically `FnOnce(From)->To`
trait Mapper<From> {
type To;
fn map(self, from: From) -> Self::To;
}
trait OptionExt {
type T;
fn map2<F1, F2>(self, f1: F1, f2: F2) -> Option<<F2 as Mapper<F1::To>>::To>
where
F1: Mapper<Self::T>,
F2: Mapper<F1::To>;
}
impl<T> OptionExt for Option<T> {
type T = T;
fn map2<F1, F2>(self, f1: F1, f2: F2) -> Option<<F2 as Mapper<F1::To>>::To>
where
F1: Mapper<Self::T>,
F2: Mapper<F1::To>,
{
todo!()
}
}
error message:
error[E0277]: the trait bound `F1: Mapper<T>` is not satisfied
--> src/lib.rs:14:2
|
14 | / fn map2<F1, F2>(self, f1: F1, f2: F2) -> Option<<F2 as Mapper<F1::To>>::To>
15 | | where
16 | | F1: Mapper<Self::T>,
17 | | F2: Mapper<F1::To>,
| |___________________________^ the trait `Mapper<T>` is not implemented for `F1`
I use Option in this example, my original code is for a third party library type. for now, I can make it to compile by adding an equality constraint like this:
trait OptionExt {
type T;
fn map2_<T2, F1, F2>(self, f1: F1, f2: F2) -> Option<<F2 as Mapper<T2>>::To>
where
F1: Mapper<Self::T, To = T2>,
F2: Mapper<T2>;
}
anyone knows is this the best way (or only way) to work around this issue? what caused the error in the first place?
additional context: I encountered this problem when I update my code from using FnOnce to a custom trait (the Mapper in the above example) for more features. since the sugar syntax of FnOnce force me to name the intermediate type, this error didn't come up in the old code, which is also how I find the workaround.