Something of a beginner at Rust here. I'm trying to implement a trait, Ring, for functions that map data types that map types implementingRings to themselves. Ring looks like this:
trait Ring {
fn plus(&self, other: &Self) -> Self;
fn times(&self, other: &Self) -> Self;
fn negate(&self) -> Self;
}
And my attempted implementation looks like this:
impl <R: Ring> Ring for Box<dyn Fn(&R) -> R> {
//(f+g)(a) = f(a) + g(a)
fn plus(&self, other: &Self) -> Self {
Box::new(move |x: &R| -> R {self(x).plus(&other(x))})
}
//(fg)(a) = f(g(a))
fn times(&self, other: &Self) -> Self {
Box::new(move |x: &R| -> R {self(&other(x))})
}
//(-f)(a) = -(f(a))
fn negate(&self) -> Self {
Box::new(move |a: &R| -> R {self(a).negate()})
}
}
Note that I'm using Box<dyn Fn(&R) -> R in place of the syntactically nicer impl Fn(&R) -> R because the compiler forbids using impl Trait here.
The error message provided is:
error: lifetime may not live long enough
--> src/main.rs:73:9
|
72 | fn plus(&self, other: &Self) -> Self {
| - let's call the lifetime of this reference `'1`
73 | Box::new(move |x: &R| -> R {self(x).plus(&other(x))})
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`
Some things I have tried in response:
i) Adding a generic lifetime annotation to the methods. This makes the Ring trait no longer recognize them as implementing the methods it needs to. Attempting to edit Ring itself to include these annotations produces an error message telling me that my lifetime name shadows a preexisting one.
ii) Boxing dyn Fn(&R) -> R + 'static in place of dyn Fn(&R) -> R, and annotating self as static as well. This produces a lifetime mismatch.
iii) Verifying that plus, times, and negate work as intended with no compiler errors when restated outside of the implementation block-- they do.
How can I ensure that the lifetime of &self is indeed as long as I need it to be?