Thank you, that is very nice! I didn't even know one can use Self
in a where
clause.
I tried the approach with a lifetime first and experimented how far I get.
Some context: I want to use these kinds of trait bounds to implement an abstraction over a container that allows the container to specify its own iterator types. The iterator type should/has to borrow the container to function.
Here is a minimal (not) working code example:
trait A {
fn a(&self) -> i32;
}
trait B {
type ReturnType;
fn b(self) -> Self::ReturnType;
}
trait Meta<'a> where &'a Self: B, Self: 'a, Self: A {}
impl<'a, T: 'a> Meta<'a> for T where
T: A,
&'a T: B {}
fn f<'a, Argument: Meta<'a>>(argument: &'a Argument) -> <&'a Argument as B>::ReturnType { // where &'a Argument: B {
argument.b()
}
(Playground)
From my current understanding, this should work. Meta
is bounded by A
and for &'a Self
it is bounded by B
. Nevertheless I get the following error (both on stable and today's nightly):
error[E0277]: the trait bound `&'a Argument: B` is not satisfied
--> src/lib.rs:16:1
|
16 | / fn f<'a, Argument: Meta<'a>>(argument: &'a Argument) -> <&'a Argument as B>::ReturnType { // where &'a Argument: B {
17 | | argument.b()
18 | | }
| |_^ the trait `B` is not implemented for `&'a Argument`
Adding where &'a Argument: B
to f
solves the compiler error, but that defies the purpose of Meta
.
Am I doing something wrong here, or does the compiler not propagate all the where clause conditions on traits in some cases?
(Edit: Made example minimal)
Another edit: HRTBs
It seems like the same problem persists with HRTBs, see the following example:
trait A {
fn a(&self) -> i32;
}
trait B {
type ReturnType;
fn b(self) -> Self::ReturnType;
}
trait Meta where for<'a> &'a Self: B, Self: A {}
impl<T> Meta for T where
T: A,
for<'a> &'a T: B {}
fn f<Argument: Meta>(argument: &Argument) -> <&Argument as B>::ReturnType { // where for<'a> &'a Argument: B {
argument.b()
}
(Playground)
This time a similar error message again. Both of these errors are solved again by adding the where
clause to f
.
error[E0277]: the trait bound `for<'a> &'a Argument: B` is not satisfied
--> src/lib.rs:16:16
|
11 | trait Meta where for<'a> &'a Self: B, Self: A {}
| --------------------------------------------- required by `Meta`
...
16 | fn f<Argument: Meta>(argument: &Argument) -> <&Argument as B>::ReturnType { // where for<'a> &'a Argument: B {
| ^^^^ the trait `for<'a> B` is not implemented for `&'a Argument`
error[E0277]: the trait bound `&Argument: B` is not satisfied
--> src/lib.rs:16:46
|
16 | fn f<Argument: Meta>(argument: &Argument) -> <&Argument as B>::ReturnType { // where for<'a> &'a Argument: B {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `B` is not implemented for `&Argument`