Why do I need 'static lifetime here and how to fix it? - rust

I have taken off all extra irrelevant code to come to this clean one to reproduce the error I am getting:
trait EventsHandler{}
struct Engine{}
struct Request{}
struct RequestHandler<'a> {
r: &'a mut Request
}
impl<'a> EventsHandler for RequestHandler<'a>{}
impl Engine {
pub fn exec(&mut self, script: &str, handler: Box<dyn EventsHandler>){ }
}
pub fn handle_request(script: &str, r: &mut Request) {
let r_h:RequestHandler =RequestHandler {r};
let handler = Box::new(r_h);
let mut engine = Engine{};
engine.exec(script, handler);
}
and the error is:
error: explicit lifetime required in the type of `r`
label: lifetime `'static` required
The error is pointing to the parameter 'handler' in the last line of code.
As far as I can see everything seems live long enough. I can't see why there is a need for static and how I can go and fix that need or rewrite the code to avoid that requirement.

Following Rust's lifetime elision rules for trait objects, a Box<dyn Trait> is in many cases shorthand for Box<dyn Trait + 'static>. The meaning of the lifetime 'a in Box<dyn Trait + 'a> is that all lifetime parameters of the type implementing Trait outlive 'a (see the reference).
The 'static can be relaxed by adding an explicit lifetime to the trait object. At minimum, this will entail an additional lifetime parameter on Engine::exec:
impl Engine {
pub fn exec<'b>(&mut self, script: &str, handler: Box<dyn EventsHandler + 'b>){ }
}
See an amended code listing on the playground

trait EventsHandler{}
struct Engine{}
pub struct Request{}
pub struct RequestHandler<'a> {
r: &'a mut Request
}
impl<'a> EventsHandler for RequestHandler<'a>{}
impl<'a> Engine {
pub fn exec(&'a mut self, script: &'a str, handler: Box<dyn EventsHandler + 'a>){ }
}
pub fn handle_request<'a>(script: &'a str, r: &'a mut Request){
let r_h:RequestHandler =RequestHandler {r};
let handler = Box::new(r_h);
let mut engine = Engine{};
engine.exec(script, handler);
}
I really don't know how to explain but this is what I did by following the tip in the error message. it can compile now.
Hope someone else can give a better explanation. :)
or you may take a look at: Box with a trait object requires static lifetime?

Though trait objects like dyn EventsHandler erase the type at runtime, they still need to have information about the lifetime of the type so that it can be used in the type system. You can specify the lifetime explicitly with dyn EventsHandler + 'lifetime, but it can also be elided, in which case Rust uses the following rule:
If the trait object is used as a type argument of a generic type then the containing type is first used to try to infer a bound.
If there is a unique bound from the containing type then that is the default
If there is more than one bound from the containing type then an explicit bound must be specified
If neither of those rules apply, then the bounds on the trait are used:
If the trait is defined with a single lifetime bound then that bound is used.
If 'static is used for any lifetime bound then 'static is used.
If the trait has no lifetime bounds, then the lifetime is inferred in expressions and is 'static outside of expressions.
(Source: Lifetime elision, Rust reference)
In this case, the containing type Box<_> has no lifetimes, the trait EventsHandler has no lifetime bounds, and the type Box<dyn EventsHandler> is used in a function signature (so outside of any expressions), so the lifetime is inferred as 'static. In other words, Box<dyn EventsHandler>, in this code, is equivalent to Box<dyn EventsHandler + 'static> by the above rules, and can only contain values with a 'static lifetime, which RequestHandler<'a> is not.
If you want your Box<dyn EventsHandler> to be able to contain values with a shorter lifetime than 'static, you should add an explicit lifetime:
pub fn exec<'h>(&mut self, script: &str, handler: Box<dyn EventsHandler + 'h>)
// ^^^^ ^^^^^
// alternatively:
pub fn exec(&mut self, script: &str, handler: Box<dyn EventsHandler + '_>)
// ^^^^^

Related

Difference between "Self" and elided lifetime

Don't know how to describe, but here is the minimal reproducing snippet (also on playground):
struct Ctx(Vec<Box<dyn Fn(&mut MockCtx)>>);
struct MockCtx<'a>(&'a mut Ctx);
impl MockCtx<'_> {
// this works
fn push<F: 'static + Fn(&mut MockCtx)>(&mut self, f: F) {
self.0.0.push(Box::new(f));
}
}
trait Push {
fn push<F: 'static + Fn(&mut Self)>(&mut self, f: F);
}
impl Push for MockCtx<'_> {
// fn push<F: 'static + Fn(&mut Self)>(&mut self, f: F) { (1)
fn push<F: 'static + Fn(&mut MockCtx)>(&mut self, f: F) { // (2)
MockCtx::push(self, f)
}
}
If I take (1), compiler reports
expected a `Fn<(&mut MockCtx<'_>,)>` closure, found `F`
and recommand to add explicit lifetime to restrict. If I do so or simply take (2), compiler reports
impl has stricter requirements than trait
The truth is I do not understand the problem from starting point... I understand what is lifetime and simple "outlive" rules, and to me compiler should have no worry about 'a for these code so far, because that can only be a thing when these Box<dyn Fn> actually get called.
Thanks for any replying and explaining!
This is understandably a little opaque, because several lifetimes are elided. It should become a little more clear if we write those out.
Let's first look at the container:
struct Ctx(Vec<Box<dyn Fn(&mut MockCtx)>>);
This is short for:
struct Ctx(Vec<Box<dyn for<'a, 'b> Fn(&'a mut MockCtx<'b>) + 'static>>);
The 'static requires that any closure you put in the container must own its data. It cannot refer to other data that depends on a lifetime. The elided lifetime is 'static because Box has no lifetime parameters.
The construct for<'a, 'b> Fn(&'a mut MockCtx<'b>) is a higher rank trait bound, or HRTB for short. This means that any closure you put in the container must be able to accept a mutable reference with any lifetime to a MockCtx<'_> with any lifetime parameter. Note for later that there are two lifetime parameters here.
Now, let's go to the impl:
impl MockCtx<'_> {
fn push<F: 'static + Fn(&mut MockCtx)>(&mut self, f: F);
}
This is short for:
impl MockCtx<'_> {
fn push<F: 'static + for<'a, 'b> Fn(&'a mut MockCtx<'b>)>(&mut self, f: F);
}
The requirements on the closure are the same as for the container. No conflicts. But note that the closure must accept types other than Self. It must accept a mutable reference to a MockCtx<'_> with a different lifetime.
Now let's go to the trait:
trait Push {
fn push<F: 'static + Fn(&mut Self)>(&mut self, f: F);
}
This is short for:
trait Push {
fn push<F: 'static + for<'a> Fn(&'a mut Self)>(&mut self, f: F);
}
This is going to conflict. A closure given to Push can only be called with a reference to Self, of any lifetime. But a closure that we store in our container must accept some types other than Self. There is a whole range of Self-like types that have different lifetime parameters that the closure needs to accept for our container.
Now, we can explain why the two attempts failed. #1 fails because the closure in the trait and the trait impl can only accept Self, but we're attempting to store it in a container that holds closures that can accept MockCtx<'_> of any lifetime. #2 fails because the trait only requires the closure accept Self, but our trait impl tries to accept a more restrictive set of closures that can accept MockCtx<'_> for any lifetime.
There are several ways to fix this, but they all amount to fixing this disagreement on the bounds for the argument of the closure.
One way is to explicitly accept the full range of types in the closure bound. You have to mention types other than Self. So, for example, you can mention the concrete types:
trait Push {
fn push<F: 'static + Fn(&mut MockCtx<'_>)>(&mut self, f: F);
}
See here.
Using a nightly feature of trait aliases, you could use a common name for all the requirements:
trait MockFn = 'static + Fn(&mut MockCtx<'_>);
trait Push {
fn push<F: MockFn>(&mut self, f: F);
}
See here.
Using a nightly feature of generic associated types, you could also make the trait slightly more general:
trait Push {
type SelfLike<'a>;
fn push<F: 'static + Fn(&mut Self::SelfLike<'_>)>(&mut self, f: F);
}
See here.
Alternatively, as #Jmb says in the comments, you can make the closure a generic parameter on the trait:
trait Push<F> {
fn push(&mut self, f: F);
}
See here.
This is a relatively clean approach. It is asserted in the comments that this is useless, but I don't think it is.

How do I return a reversed iterator?

I was writing some code where I want to use an iterator, or its reversed version depending on a flag, but the straightforward code gives an error
pub fn eggs<I,T>(iter:I)->Box<dyn Iterator<Item=T>>
where I:Iterator<Item=T>+DoubleEndedIterator
{
Box::new(iter.rev())
}
pub fn bacon<I,T>(iter:I, reverse:bool) -> Box<dyn Iterator<Item=T>>
where I:Iterator<Item=T>+DoubleEndedIterator
{
if reverse {
Box::new(iter.rev())
} else {
Box::new(iter)
}
}
fn main()
{
let pants:String = "pants".into();
eggs(pants.chars());
}
fails to compile:
error[E0310]: the parameter type `I` may not live long enough
--> src/main.rs:5:5
|
2 | pub fn eggs<I,T>(iter:I)->Box<dyn Iterator<Item=T>>
| - help: consider adding an explicit lifetime bound...: `I: 'static`
...
5 | Box::new(iter.rev())
| ^^^^^^^^^^^^^^^^^^^^ ...so that the type `Rev<I>` will meet its required lifetime bounds
With my limited understanding of Rust, I'm not sure where those lifetime bounds are coming from. There aren't any on the Iterator trait, or the Rev struct, and the parameter is being moved.
What is the proper way to declare these sorts of functions given that 'static isn't really an option.
rust playground
This doesn't have to do with .rev() at all, but with returning Box<dyn Iterator>:
// error[E0310]: the parameter type `I` may not live long enough
fn boxed_iter<I, T>(iter: I) -> Box<dyn Iterator<Item = T>>
// - help: consider adding an explicit lifetime bound...: `I: 'static`
where
I: Iterator<Item = T>,
{
Box::new(iter)
// ^^^^^^^^^^^^^^ ...so that the type `I` will meet its required lifetime bounds
}
The reason for this is that trait objects like Box<dyn Trait> have an implicit 'static lifetime if not specified. So when the compiler tries to cast Box<I> to Box<dyn Iterator>, it fails if I is does not also have a 'static lifetime. (There are some more specific rules if the trait contains lifetimes itself; you can read about those in more detail here.)
If you instead want a shorter lifetime, you need to specify it explicitly as Box<dyn 'a + Trait>. So for example:
fn boxed_iter<'a, I, T>(iter: I) -> Box<dyn 'a + Iterator<Item = T>>
where
I: 'a + Iterator<Item = T>,
{
Box::new(iter)
}
Frxstrem's answer is excellent. I just want to add that, if you know that the return value of your function has a specific concrete type, you can use the special impl trait syntax.
In the case of your eggs function, the return type is probably something like Rev<I>. That type, on its own, isn't very illuminating, but we know that such a type exists and the only thing we care about is that it's an iterator, so we can write
pub fn eggs<I,T>(iter:I) -> impl Iterator<Item=T> + DoubleEndedIterator
where I: Iterator<Item=T> + DoubleEndedIterator {
iter.rev()
}
Now the compiler still understands that there is a single concrete type and will act accordingly (no need to box the value or have dynamic dispatch), but we as the programmers still only have to care about the Iterator and DoubleEndedIterator aspects of it. Zero-cost abstraction at its finest.
Your bacon function can't benefit from this, as it could return either an I or a Rev<I> depending on input, so the dynamic dispatch is actually necessary. In that case, you'll need to follow Frxstrem's answer to correctly box your iterator.

TryFrom<&[u8]> trait bound in trait

I'm trying to implement common trait for a bunch of types created from binary data (read from a disk). Majority of trait methods could use default implementations and only conversions etc. would be needed to be implemented separately. I would like to use TryFrom<&[u8]> trait for conversions from binary data to my types but I don't know how to express (in the context of trait) that lifetime of &[u8] and lifetimes of values of my types created from it are not related. Here is minimal example of the problem.
use std::convert::TryFrom;
struct Foo;
// Value of Foo can be created from &[u8] but it doesn't borrow anything.
impl TryFrom<&[u8]> for Foo {
type Error = ();
fn try_from(v: &[u8]) -> Result<Self, ()> {
Ok(Foo)
}
}
trait Bar<'a>
where
Self: TryFrom<&'a [u8], Error = ()>, // `&` without an explicit lifetime name cannot be used here
{
fn baz() -> Self {
let vec = Vec::new();
Self::try_from(&vec).unwrap() // ERROR: vec does not live long enough (nothing is borrowed)
}
}
Alternative solution would be to make conversions as trait methods but it would be nicer to use common std traits. Is there a way to achieve this? (Or I could use const generics but I don't want to rely on nightly compiler.)
What you want are "higher ranked trait bounds" (HRTB, or simply hearty boy). They look like this: for<'a> T: 'a. This example just means: "for every possible lifetime 'a, T must ...". In your case:
trait Bar
where
Self: for<'a> TryFrom<&'a [u8], Error = ()>,
You can also specify that requirement as super trait bound directly instead of where clause:
trait Bar: for<'a> TryFrom<&'a [u8], Error = ()> { ... }
And yes, now it just means that all implementors of Bar have to implement TryFrom<&'a [u8], Error = ()> for all possible lifetimes. That's what you want.
Working Playground

How to infer an appropriate lifetime for an implementation using lifetimes for structs and impl?

How do I resolve this error? What exactly am I telling the compiler when I use the "anonymous lifetime" in impl?
struct LineHandlerInfo<'a> {
label: &'a str,
match_literal: &'a str,
f: fn(&str) -> Option<&str>,
}
struct Game<'a> {
handlers: Vec<LineHandlerInfo<'a>>,
}
impl Game<'_> {
fn match_str<'a>(
&'a mut self,
label: &'a str,
match_literal: &'a str,
mut f: fn(&str) -> Option<&str>,
) {
let mut lh = LineHandlerInfo {
label,
match_literal,
f,
};
self.handlers.push(lh);
}
}
fn main() {
let mut g = Game {
handlers: Vec::new(),
};
g.match_str("echo hello", "hello", |s| {
println!("{}", s);
None
});
}
When I attempt to compile, I get the following error:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> src/main.rs:18:22
|
18 | let mut lh = LineHandlerInfo {
| ^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime 'a as defined on the method body at 12:18...
--> src/main.rs:12:18
|
12 | fn match_str<'a>(
| ^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:19:13
|
19 | label,
| ^^^^^
note: but, the lifetime must be valid for the lifetime '_ as defined on the impl at 11:11...
--> src/main.rs:11:11
|
11 | impl Game<'_> {
| ^^
= note: ...so that the expression is assignable:
expected LineHandlerInfo<'_>
found LineHandlerInfo<'_>
How do I resolve this error and what exactly am I telling the compiler when I specify a lifetime on impl Game when I already have a lifetime on the struct?
How do I resolve this error and what exactly am I telling the compiler when I specify a lifetime on impl Game when I already have a lifetime on the struct?
I suspect your confusion stems from an incomplete understanding of the way in which lifetimes are declared and used in Rust.
Struct Lifetimes
In order to use a lifetime on a struct, you declare the lifetime inside the <> adjacent to the name of the struct you are declaring, and then refer to that lifetime inside the struct definition. Importantly, note that the lifetime declared there is scoped to the struct definition - it has no meaning outside.
For example (using the MRE that #Shepmaster provided):
struct Game<'a> {
handlers: Vec<&'a str>,
}
The struct Game contains a vector of references to strings, and the strings which are referenced must last at least as long as the Game struct.
Impl Lifetimes
When using a lifetime specifier on an impl block, you declare the lifetime inside the <> adjacent to the impl keyword, after which you may refer to the lifetime both in the struct being implemented, and inside the implementation itself, like this:
impl<'b> Game<'b> {
fn match_str(&mut self, label: &'b str) {
self.handlers.push(label);
}
}
Note that I am using an entirely different lifetime name here ('b) to illustrate that the the lifetime declaration on the struct is independent of the one on the impl block.
Breaking this down:
impl<'b>
This means that we are defining an implementation for a struct, and within that definition we will use the lifetime 'b
Game<'b> {
This means that the impl is for the struct Game with lifetime 'b - so any references to self inside this implementation are going to automatically have lifetime 'b as well.
fn match_str(&mut self, label: &'b str) {
Here we define the method match_str which takes an argument label. label is a string slice which also has the lifetime 'b - so it must last at least as long as the self that the method is called on.
In your original code, you had something like this:
impl Game<'_> {
fn match_str<'a>(&mut self, label: &'a str) {
...
}
}
This was telling the compiler:
That you are starting a new impl block that, and there are no lifetimes declared at impl level
That the implementation is for the struct Game; this struct has a lifetime parameter but we don't care about it and we are not going to tie it to any element of the implementation
We are defining a method match_str, and we are declaring a lifetime 'a which we can refer to in the rest of the function signature
We have an argument label which has the lifetime a, but we aren't relating this lifetime to anything else
More information:
Rust Book - Lifetime Annotations in Struct Definitions
Rust Book - Lifetime Annotations in Method Definitions
How do I resolve this error?
Remove the generic lifetime from the function, provide a name for the lifetime on the impl block instead of using the anonymous lifetime, then use the named lifetime in the function arguments. Remove the lifetime from &self:
impl<'a> Game<'a> {
fn match_str(&mut self, label: &'a str, match_literal: &'a str, f: fn(&str) -> Option<&str>) {
self.handlers.push(LineHandlerInfo {
label,
match_literal,
f,
});
}
}
See also:
Cannot borrow as mutable more than once at a time in one code - but can in another very similar
What exactly am I doing when I use the "anonymous lifetime" in impl?
You are effectively stating "I know there's a lifetime here, but I don't care about it". However, that's not true for your case; you do care about the lifetime that parameterizes the type because that's what your variables need to match.
See also:
'_, the anonymous lifetime in the Edition Guide
for a struct with a function pointer in it
This has nothing to do with function pointers. When encountering problems while programing, I recommend creating a minimal, reproducible example, stripping out things that don't make the error go away. This allows you to focus on exactly the problem at hand. For example, this reproduces the same error:
struct Game<'a> {
handlers: Vec<&'a str>,
}
impl Game<'_> {
fn match_str<'a>(&mut self, label: &'a str) {
self.handlers.push(label);
}
}

Trait which returns iterator with lifetime bounded by the lifetime of an argument

I have a trait which says that any implementation of Foo needs to provide a method bar which returns an object of some type which implements Iterator<Item = u32>:
trait Foo {
type FooIterator: Iterator<Item = u32>;
fn bar(&self) -> FooIterator;
}
For this case, I believe that the default lifetime elision means that the iterator returned by bar is required to live on its own, without being tied to the lifetime of the Foo it is iterating over. User Habnabit on #rust irc suggested the following way to say that the lifetime of the FooIterator is less than the lifetime of the Foo. i.e. it allows the implementation of the FooIterator to keep a reference to the Foo that it comes from:
trait Foo<'a> {
type FooIterator: Iterator<Item = u32> + 'a;
fn bar<'b: 'a>(&'b self) -> Self::FooIterator;
}
What I really want is the case where the function bar takes an additional argument, and the implementation of FooIterator is allowed to keep a reference to both the Foo and the additional argument. i.e. the lifetime of FooIterator is bounded by the lifetime of the Foo and the lifetime of the additional argument.
My literal translation of this idea would be
trait Zip {}
trait Foo<'a, 'c> {
type FooIterator: Iterator<Item = u32> + 'a + 'c;
// Foo.bar() returns an iterator that has a lifetime less than the Foo
fn bar<'b: 'a, 'd: 'c>(&'b self, &'d Zip) -> Self::FooIterator;
}
But I was told there there is no "good" way to do this. What would be the best way to implement this idiom? What would the above code do exactly?
What you're looking for is associated type constructors, a planned feature that is not yet implemented in Rust. With associated type constructors, your code would look like this:
trait Zip {}
trait Foo {
type FooIterator<'a, 'c>: Iterator<Item = u32> + 'a + 'c;
// Foo.bar() returns an iterator that has a lifetime less than the Foo
fn bar<'a, 'b: 'a, 'c, 'd: 'c>(&'b self, &'d Zip) -> Self::FooIterator<'a, 'c>;
}
Actually, I'm not sure all those lifetimes are necessary, because a &'a T can be coerced to a &'b T where 'a: 'b. Thus, the following might be good enough:
trait Zip {}
trait Foo {
type FooIterator<'a, 'c>: Iterator<Item = u32> + 'a + 'c;
// Foo.bar() returns an iterator that has a lifetime less than the Foo
fn bar<'a, 'c>(&'a self, &'c Zip) -> Self::FooIterator<'a, 'c>;
}
Depending on how you want to use this trait, you may be able to make it work by implementing it for &'a Struct instead of for Struct, thus "hoisting" the responsibility for finding the right lifetime from the trait into the caller.
Remove the lifetime annotation from the trait and change bar so it takes self, plus another argument of the same lifetime:
trait Foo {
type FooIterator: Iterator<Item = u32>;
fn bar(self, other: Self) -> Self::FooIterator;
}
(Removing 'a from the trait is possible because bar consumes the reference instead of reborrowing it -- self doesn't have to outlive the return value anymore because it's been moved into it.)
Then impl it for a reference of lifetime 'a:
impl<'a> Foo for &'a Vec<u32> {
type FooIterator = ...; // something presumably containing 'a
fn bar(self, other: Self) -> Self::FooIterator {
...
}
}
This works because the compiler can limit the lifetime 'a to one for which the impl applies.
Here's a playground link where bar is basically a wrapper around .chain().
I'm ignoring the Zip trait for now because how to incorporate it depends on what it provides. Instead, I suppose that bar only accepts an argument of the same type as Self. However, you can probably add it as well, maybe using the same technique if you need to.

Resources