If I try to implement the trait Frob for functions like foo as follows:
fn foo<'b>(state: &'b mut i32) -> impl FnMut(&str) -> i32 + 'b {
move |i| *state
}
trait Frob<S, I, O> {
fn frob(self, state: &mut S, input: I) -> O;
}
impl<S, I, O, F, G> Frob<S, I, O> for F
where
F: FnMut(&mut S) -> G,
G: FnMut(I) -> O,
{
fn frob(mut self, state: &mut S, input: I) -> O {
self(state)(input)
}
}
fn bar() {
foo.frob(&mut 1, "hi");
}
I get the error
error[E0599]: the method `frob` exists for fn item `for<'b> fn(&'b mut i32) -> impl for<'b, 'r> FnMut<(&'r str,)> {foo}`,
but its trait bounds were not satisfied
...
= note: the following trait bounds were not satisfied:
`<for<'b> fn(&'b mut i32) -> impl for<'b, 'r> FnMut<(&'r str,)> {foo} as FnOnce<(&mut _,)>>::Output = _`
which is required by `for<'b> fn(&'b mut i32) -> impl for<'b, 'r> FnMut<(&'r str,)> {foo}: Frob<_, _, _>`
`<&for<'b> fn(&'b mut i32) -> impl for<'b, 'r> FnMut<(&'r str,)> {foo} as FnOnce<(&mut _,)>>::Output = _`
which is required by `&for<'b> fn(&'b mut i32) -> impl for<'b, 'r> FnMut<(&'r str,)> {foo}: Frob<_, _, _>`
`<&mut for<'b> fn(&'b mut i32) -> impl for<'b, 'r> FnMut<(&'r str,)> {foo} as FnOnce<(&mut _,)>>::Output = _`
which is required by `&mut for<'b> fn(&'b mut i32) -> impl for<'b, 'r> FnMut<(&'r str,)> {foo}: Frob<_, _, _>`
First of all, how do I interpret this error message? Second, how do I write the trait bound correctly? Presumably the problem has something to do with the returned closure hanging on to state, but I can't find a place to specify a lifetime for G.
First of all, how do I interpret this error message?
Yes, it is a tad cryptic isn't it? Two things to recognise:
<for<'b> fn(&'b mut i32) -> impl for<'b, 'r> FnMut<(&'r str,)> {foo} is the compiler's very wordy way of expressing the type of function foo; and
the same note is repeated for that function type, a shared reference to that function type, and a mutable reference to that function type—this happens when the compiler attempts automatic referencing in method call syntax such as you have in foo.frob(...).
So we can quickly distill the error message down to:
error[E0599]: the method `frob` exists for fn item `{foo}`,
but its trait bounds were not satisfied
...
= note: the following trait bounds were not satisfied:
`<{foo} as FnOnce<(&mut _,)>>::Output = _`
which is required by `{foo}: Frob<_, _, _>`
The compiler is telling us that it found a potential frob method on {foo} but in order for it to be applicable, {foo}'s return type must match the constraints of the Frob trait (but it doesn't).
Second, how do I write the trait bound correctly? Presumably the problem has something to do with the returned closure hanging on to
state, but I can't find a place to specify a lifetime forG.
You need to add the lifetime constraint to the trait (playground):
trait Frob<'b, S, I, O> {
fn frob(self, state: &'b mut S, input: I) -> O;
}
impl<'b, S: 'b, I, O, F, G> Frob<'b, S, I, O> for F
where
F: FnMut(&'b mut S) -> G,
G: 'b + FnMut(I) -> O,
{
fn frob(mut self, state: &'b mut S, input: I) -> O {
self(state)(input)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With