Timeout designation for the close argument

I would like to compile the following code:

struct Provider {} impl Provider { fn get_string<'a>(&'a self) -> &'a str { "this is a string" } } fn main() { let provider = Provider{}; let mut vec: Vec<&str> = Vec::new(); // PROBLEM: how do I say that this reference s here // needs to live as long as vec? let fun = |s: &str| { vec.push(s); }; fun(provider.get_string()); } 

Playground

This is the compilation error I get:

 error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements --> src/main.rs:9:22 | 9 | let mut vec: Vec<&str> = Vec::new(); | ^^^^ | note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the block at 11:24... --> src/main.rs:11:25 | 11| let fun = |s: &str| { | ^ note: ...so that reference does not outlive borrowed content --> src/main.rs:12:18 | 12| vec.push(s); | ^ note: but, the lifetime must be valid for the block suffix following statement 2 at 13:6... --> src/main.rs:13:7 | 13| }; | ^ note: ...so that variable is valid at time of its declaration --> src/main.rs:11:9 | 11| let fun = |s: &str| { | ^^^ 
+6
source share
2 answers

Your code works just fine if you delete all annotations for life and allow the compiler to do its job:

 struct Provider; impl Provider { fn get_string(&self) -> &str { "this is a string" } } fn main() { let provider = Provider; let mut vec = Vec::new(); let mut fun = |s| { vec.push(s); }; fun(provider.get_string()); } 

In short, there is no way to explicitly refer to the lifetime of a local variable, only function arguments. The compiler knows how to do this.

If you really need it, you can create a function to annotate the lifetime:

 fn thing<'a>(provider: &'a Provider) -> Vec<&'a str> { let mut vec: Vec<&'a str> = Vec::new(); { let mut fun = |s: &'a str| vec.push(s); fun(provider.get_string()); } // End mutable borrow of `vec` vec } fn main() { let provider = Provider; thing(&provider); } 

Why did the original annotations stop working?

In particular, this is a bit:

 let fun = |s: &str| { vec.push(s); }; 

This announces a new lifetime at closing. Using the prepared syntax (you cannot declare lifetimes with closing arguments ), this will be equivalent to:

 let fun = <'a> |s: &'a str| { vec.push(s); }; 

This is why the compiler has an error:

life time cannot survive the anonymous life time # 1 defined on the [block circuit]

There is no connection between the generated lifetime and the Provider . Leaving this, the compiler can insert the desired, but not verifiable, lifetime.

+6
source

Here is the version that compiles:

 use std::marker::PhantomData; struct Provider<'a> { _dummy: PhantomData<&'a ()>, } impl<'a> Provider<'a> { fn get_string(&self) -> &'a str { "this is a string" } } fn f<'b>() { let provider = Provider { _dummy: PhantomData }; let mut vec: Vec<&str> = Vec::new(); // PROBLEM: how do I say that this reference s here // needs to live as long as vec? let mut fun = |s: &'b str| { vec.push(s); }; fun(provider.get_string()); } fn main() { f() } 

Playground

I made the following changes:

  • Add a lifespan to the Provider (I added PhantomData , but I think your provider already owns some of the data that it will provide).
  • Update the get_string method to show that it returns something with the provider lifetime, not the input lifetime (i.e. based on the Provider time parameter).
  • Add a new lifetime parameter 'b to the function (which I renamed to f() , since main() cannot have it), which I use to name the lifetime of the close parameter.

The latter is a bit confusing, because, apparently, just adding a name for life (without any visible additions of any restrictions) made it work.

I think (but I would like for me to have some kind of documentation) that this is because of a lifetime solution. Closing is really a hidden struct using the fn call(&self, s: &str) method (in this case). In accordance with the rules of life elimination, the parameter s receives the same lifetime as &self , which is the closure itself. In this case, a closure is declared after vec , so the lifetime is too short. The explicit lifetime means that it is separate from its own closing time.

+2
source

Source: https://habr.com/ru/post/1014412/


All Articles