Problem with lifetimes and implementing Clone - rust

I'm trying to define a struct representing a function that can be composed using different arithmetic operations (only addition has been implemented).
I would like to implement Clone for my struct, however I can't seem to it to work:
use std::ops::Add;
use std::boxed::Box;
use std::clone::Clone;
type InputT = i32;
type OutputT = f64;
pub struct ComposableFn<'a> {
f: Box<dyn 'a + Fn(InputT) -> OutputT>,
}
impl<'a> ComposableFn<'a> {
pub fn new<F: 'a + Fn(InputT) -> OutputT>(f: F) -> Self {
Self {
f: Box::new(f)
}
}
pub fn compute(&self, x: InputT) -> OutputT {
(self.f)(x)
}
}
impl<'a> Add<&'a ComposableFn<'a>> for &'a ComposableFn<'a> {
type Output = ComposableFn<'a>;
fn add(self, rhs: &'a ComposableFn) -> Self::Output {
ComposableFn::new(move |x| self.compute(x) + rhs.compute(x))
}
}
impl<'a> Clone for ComposableFn<'a> {
fn clone(&'a self) -> Self {
ComposableFn::new(move |x| self.compute(x))
}
}
fn main() {
let id = ComposableFn::new(|x| x.into());
println!("{}", id.compute(12));
let double = &id + &id;
println!("{}", double.compute(7));
let triple = &double + &id;
println!("{}", triple.compute(3));
}
When compiling I get the following error:
error[E0308]: method not compatible with trait
--> src/main.rs:33:5
|
33 | fn clone(&'a self) -> Self {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected fn pointer `fn(&ComposableFn<'a>) -> ComposableFn<'_>`
found fn pointer `fn(&'a ComposableFn<'a>) -> ComposableFn<'_>`
note: the anonymous lifetime #1 defined on the method body at 33:5...
--> src/main.rs:33:5
|
33 | fn clone(&'a self) -> Self {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 32:6
--> src/main.rs:32:6
|
32 | impl<'a> Clone for ComposableFn<'a> {
| ^^
error: aborting due to previous error
Removing the 'a from fn clone(&'a self) results in the following error instead:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:34:27
|
34 | ComposableFn::new(move |x| self.compute(x))
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 33:5...
--> src/main.rs:33:5
|
33 | fn clone(&self) -> Self {
| ^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that the types are compatible
--> src/main.rs:34:27
|
34 | ComposableFn::new(move |x| self.compute(x))
| ^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `&ComposableFn<'_>`
found `&ComposableFn<'a>`
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 32:6...
--> src/main.rs:32:6
|
32 | impl<'a> Clone for ComposableFn<'a> {
| ^^
note: ...so that the expression is assignable
--> src/main.rs:34:9
|
34 | ComposableFn::new(move |x| self.compute(x))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `ComposableFn<'a>`
found `ComposableFn<'_>`
error: aborting due to previous error
Is there a way to fix this?

You cannot implement Clone this way. Clone requires the return type to match exactly, which means the exact same lifetime 'a. But you're trying to make a clone that references self which has a different lifetime.
The straightforward solution would be to just clone f. Unfortunately, you can't clone a Box<dyn...>, at least not without some help. See: How to clone a struct storing a boxed trait object?
The only direct solution would be to swap Box out with Rc so they share ownership:
use std::rc::Rc;
pub struct ComposableFn<'a> {
f: Rc<dyn 'a + Fn(InputT) -> OutputT>,
}
impl Clone for ComposableFn<'_> {
fn clone(&self) -> Self {
ComposableFn { f: self.f.clone() }
}
}

Related

Why does `|_| 1` not meet lifetime requirements

I have the following trait and generic implementation for Fn:
trait Provider<'a> {
type Out;
fn get(&'a self, state: &State) -> Self::Out;
}
impl<'a, F, T> Provider<'a> for F
where
F: Fn(&State) -> T,
{
type Out = T;
fn get(&'a self, state: &State) -> T {
self(state)
}
}
Now, I have some code that wants a for<'a> Provider<'a, Out = usize>. However, the most simple closure, |_| 1, does not qualify and instead provides this error message which I don't understand:
fn assert_usize_provider<P>(_: P)
where
P: for<'a> Provider<'a, Out = usize>,
{
}
fn main() {
assert_usize_provider(|_| 1);
}
error[E0308]: mismatched types
--> src/main.rs:27:5
|
27 | assert_usize_provider(|_| 1);
| ^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected type `FnOnce<(&State,)>`
found type `FnOnce<(&State,)>`
note: this closure does not fulfill the lifetime requirements
--> src/main.rs:27:27
|
27 | assert_usize_provider(|_| 1);
| ^^^^^
note: the lifetime requirement is introduced here
--> src/main.rs:22:29
|
22 | P: for<'a> Provider<'a, Out = usize>,
| ^^^^^^^^^^^
Playground link
Can someone explain what that error message means and how to get this code working?
I don't know why inference does not work in this case but you can add type annotation to get the code working.
assert_usize_provider(|_ : &State| 1);

cannot infer an appropriate lifetime for lifetime parameter with multiple references with the same lifetime inside a struct [E0495]

I had gotten an error in my code about lifetime inferrence, and I have been able to reduce the code to the following:
use std::collections::HashMap;
struct A<'a> {
x: &'a mut HashMap<&'a str, i32>,
}
impl<'a> A<'a> {
fn new(x: &'a mut HashMap<&'a str, i32>) -> Self {
Self { x }
}
fn test(&mut self) {
let a = A::new(self.x);
}
}
fn main() {
}
The error that results from this is
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> src/main.rs:13:17
|
13 | let a = A::new(self.x);
| ^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 12:5...
--> src/main.rs:12:5
|
12 | / fn test(&mut self) {
13 | | let a = A::new(self.x);
14 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:13:24
|
13 | let a = A::new(self.x);
| ^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 7:6...
--> src/main.rs:7:6
|
7 | impl<'a> A<'a> {
| ^^
note: ...so that the expression is assignable
--> src/main.rs:13:24
|
13 | let a = A::new(self.x);
| ^^^^^^
= note: expected `&mut std::collections::HashMap<&str, i32>`
found `&mut std::collections::HashMap<&'a str, i32>`
I do not understand what is the error in this case, but I did find that if I add a lifetime 'b to struct A, such that the str reference in the HashMap has a lifetime of 'b, the codes does compile. Here is how the code looks like after the aforementioned change:
use std::collections::HashMap;
struct A<'a, 'b> {
x: &'a mut HashMap<&'b str, i32>,
}
impl<'a, 'b> A<'a, 'b> {
fn new(x: &'a mut HashMap<&'b str, i32>) -> Self {
Self { x }
}
fn test(&mut self) {
let a = A::new(self.x);
}
}
fn main() {
}
However, I have no idea why that change works. To my understanding, having both lifetimes be 'a means that A must live as long as the HashMap, and the HashMap must live as long as the &strs that are used as its keys, which I see no issue with. I also do not see how the change adds any additional information for the compiler. Can anyone please shed some light for me on this situation?
Change the A::test() function into
fn test(&'a mut self) { // Add lifetime specification
let a = A::new(self.x);
}
and it should work.
The compiler said it cannot infer lifetime for A::new(), and the first note mentioned "anonymous lifetime", that means the compiler doesn't know the lifetime of self.x in A::new(self.x). So we just need to tell the compiler that self has a lifetime of 'a.

Proxy method for implementing Iterator, conflicting lifetime

I'm trying to implement an iterator which simply proxies the next method to another method on the struct itself.
struct Element<'a>(&'a str);
struct IterStruct<'a> {
name: &'a str,
}
impl<'a> IterStruct<'a> {
fn name(&mut self) -> Option<Element> {
Some(Element(self.name))
}
}
impl<'a> Iterator for IterStruct<'a> {
type Item = Element<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.name()
}
}
I'm getting the conflicting requirements for lifetime error though:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/lib.rs:16:14
|
16 | self.name()
| ^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 15:5...
--> src/lib.rs:15:5
|
15 | / fn next(&mut self) -> Option<Self::Item> {
16 | | self.name()
17 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:16:9
|
16 | self.name()
| ^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 13:6...
--> src/lib.rs:13:6
|
13 | impl<'a> Iterator for IterStruct<'a> {
| ^^
= note: ...so that the types are compatible:
expected std::iter::Iterator
found std::iter::Iterator
Playground
How can I resolve this?
One solution is to specify that name outlives the IterStruct it is contained in:
struct Element<'a>(&'a str);
struct IterStruct<'a> {
name: &'a str,
}
impl<'a> IterStruct<'a> {
fn name<'s>(&'s mut self) -> Option<Element<'a>>
where
'a: 's, // <- specify that name outlives self
{
Some(Element(self.name))
}
}
impl<'a> Iterator for IterStruct<'a> {
type Item = Element<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.name()
}
}
Well you need to give borrow checker a way to infer the lifetimes. What's essentially missing is one of the following line
impl<'a> IterStruct<'a> {
fn name(&mut self) -> Option<Element> {
// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Some(Element(self.name))
}
}
into fn name(&mut self) -> Option<Element<'a>>. The Rust borrow checker will take care of the rest [Playground link].
Compiler seems smart enough to infer 'a should outlive 'self.

What happens when a Rust struct contains a lifetimed trait?

Ok, so I'm a total Rust newbie, and I'm experimenting with Rocket. That web framework passes a Form<MyStruct>, and I want to transfer that MyStruct into my own custom struct.
struct Consumer<T> {
d: T,
}
impl<T> Consumer<T> {
fn new(form: Form<T>) -> Self {
Consumer { d: form.into_inner() }
}
}
That doesn't work of course, I get:
the trait `rocket::request::FromForm<'_>` is not implemented for `T`
Next attempt:
impl<T> Consumer<T> where T: FromForm {
fn new(form: Form<T>) -> Self {
Consumer { d: form.into_inner }
}
}
Uh oh:
impl<T> Consumer<T> where T: FromForm {
^^^^^^^^ expected lifetime parameter
So now I find myself completely unable to fix this! The best I can come up with is:
impl<'f, T> Consumer<T> where T: FromForm<'f> {
fn new(form: Form<T>) -> Self {
Consumer { d: form.into_inner }
}
}
But that results in this error:
51 | fn new(form: Form<T>) -> Self {
| _________^
52 | | Consumer { d: form.into_inner }
53 | | }
| |_________^ lifetime mismatch
= note: expected type `rocket::request::FromForm<'_>`
found type `rocket::request::FromForm<'f>`
Verifiable example: https://hastebin.com/eqihaqodux.makefile
Form also has a lifetime parameter. If you tie it to the lifetime of FromForm, then you'll move forward a little:
impl<'f, T> Consumer<T> where T: FromForm<'f> {
fn new(form: Form<'f, T>) -> Self {
Consumer(form.into_inner())
}
fn get(&self) -> &T {
&self.0
}
}
As a general rule, if you return an object that depends on data in another object, then you'll need to link their lifetimes together like this.
At this point, you'll see another error, which conveniently gives you all the information you need to fix it:
error[E0310]: the parameter type `T` may not live long enough
--> src/main.rs:50:17
|
48 | impl<'f, T> Consumer<T> where T: FromForm<'f> {
| - help: consider adding an explicit lifetime bound `T: 'static`...
49 | fn new(form: Form<'f, T>) -> Self {
50 | Consumer(form.into_inner())
| ^^^^^^^^^^
|
note: ...so that the type `T` will meet its required lifetime bounds
--> src/main.rs:50:17
|
50 | Consumer(form.into_inner())
| ^^^^^^^^^^
The into_inner method on Form requires that it's type parameter T has the 'static lifetime, and the error message suggests adding this constraint.
With these changes, it will compile:
impl<'f, T: 'static> Consumer<T> where T: FromForm<'f> {
fn new(form: Form<'f, T>) -> Self {
Consumer(form.into_inner())
}
fn get(&self) -> &T {
&self.0
}
}

A smart constructor for an iterator with a reference to a closure inside

Consider the following code for a (greatly simplified) iterator with a reference to a closure inside:
struct IteratorState<'a, T: 'a + Fn(i32) -> i32> {
closure: &'a T,
}
impl<'a, T: 'a + Fn(i32) -> i32> Iterator for IteratorState<'a, T> {
type Item = i32;
fn next(&mut self) -> Option<i32> {
None
}
}
It compiles and I can construct IteratorStates directly. However, I also need a smart constructor to hide some details of the implementation (not shown in the MCVE). The following attempt does not compile:
fn mk_iter<'a, T: Fn(i32) -> i32>(closure: &'a T) -> impl Iterator<Item = i32> {
IteratorState { closure }
}
The error is
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> src/lib.rs:14:5
|
14 | IteratorState { closure }
| ^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 13:1...
--> src/lib.rs:13:1
|
13 | fn mk_iter<'a, T: Fn(i32) -> i32>(closure: &'a T) -> impl Iterator<Item = i32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:14:21
|
14 | IteratorState { closure }
| ^^^^^^^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that return value is valid for the call
--> src/lib.rs:13:54
|
13 | fn mk_iter<'a, T: Fn(i32) -> i32>(closure: &'a T) -> impl Iterator<Item = i32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
I think I understand what the problem is: there's no guarantee that constructed IteratorState won't outlive the contained reference (please correct me if I got this wrong), but I'm not quite sure how to fix it.
The impl Trait syntax supports adding lifetimes to the return type:
fn mk_iter<'a, T: Fn(i32) -> i32>(closure: &'a T) -> impl Iterator<Item = i32> + 'a {
// here ^^^^
IteratorState {
closure
}
}
(link to playground)

Resources