Cannot satisfy `'static` lifetime requirement - rust

I am trying to create an app with yew. I have a list of players and i want to toggle their state from active to inactive but i struggle with object lifetime. rustc tells me that the self in my view function needs 'static lifetime requirement but i don't know how to achieve this. How can i satisfy this lifetime requirement?
error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
pub struct App {
state: State,
}
pub struct State {
pub players: Vec<Player>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Player {
pub name: String,
pub score: usize,
pub is_active: bool,
}
impl Component for App {
//... Omitted some boilerplate code for create and update
fn view(&self, ctx: &Context<Self>) -> Html {
// This gives us a component's "`Scope`" which allows us to send messages, etc to the component.
let link = ctx.link();
html! {
<div>
<button onclick={link.callback(|_| Msg::AddOne)}>{ "+1" }</button>
<div id="players">
{
self.state.players.iter().map(|p| {
html!{
<div key={p.name.as_str()}>
<input
type="checkbox"
class="toggle"
checked={p.is_active}
onclick={link.callback(move |_| Msg::Toggle(p.name))}
/>
{ format!("Hello, I'am {}!",p.name) }</div>
}
}).collect::<Html>()
}
</div>
</div>
}
}
}
Full diagnostic message:
error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
--> src/main.rs:69:40
|
60 | fn view(&self, ctx: &Context<Self>) -> Html {
| ----- this data with an anonymous lifetime `'_`...
...
69 | self.state.players.iter().map(|p| {
| ------------------ ^^^^
| |
| ...is used here...
...
77 | onclick={link.callback(move |_| Msg::Toggle(p.name))}
| -------- ...and is required to live as long as `'static` here
|
note: `'static` lifetime requirement introduced by this bound
--> /Users/benny.gaechter/.cargo/registry/src/github.com-1ecc6299db9ec823/yew-0.20.0/src/html/component/scope.rs:144:26
|
144 | F: Fn(IN) -> M + 'static,
| ^^^^^^^

As it says in the error message: The argument given to .callback() needs to be some Fn(IN) -> M + 'static, that is, a function that takes some IN as an argument, returns some M as a result, and as a whole is 'static (has no lifetimes shorter than 'static).
A plain function pointer is 'static, and so are closures that capture context no shorter than 'static. But the closure move |_| Msg::Toggle(p.name) captures p.name, where p comes from self.state.players, and self in self.state.players comes from fn view(&self, ...). The argument &self to view() is not 'static, and this is what the compiler complains about: The only way to make the closure passed to callback() 'static is for view() to be fn view(&'static self, ...).
An fn view(&'static self, ...) is probably not what you want to do or can do, but the compiler doesn't know that.
What you need to do is make the closure move |_| Msg::Toggle(p.name) 'static by disentangling it from the locally bound p. It may be enough to .clone() p.name and move the clone into the closure. As the clone is an owned String which has no lifetimes shorter than 'static, the closure itself becomes 'static, satisfying the requirement of .callback(). This, however, would mean that Player::name could change independently of what the callback has. If that is a possibility in your code, use a Rc/Arc and .clone() that; same argument: As the Rc/Arc owned by the closure is 'static, the closure itself becomes 'static.

Related

How to wrap an iterator returned by a method with an anonymous `'_` lifetime into a struct containing the same iterator?

I'm trying to expose the quiche library over to JS using the napi-rs framework. There are some limitations on its macro #[napi].
I have a struct like this:
#[napi(iterator)]
pub struct PathStatsIter(pub (crate) Box<dyn Iterator<Item = quiche::PathStats>>);
There's a method in a third party library quiche that has a method:
quiche::Connection
pub fn path_stats(&self) -> impl Iterator<Item = PathStats> + '_
I've created my own method in a separate struct that tries to return a wrapped iterator:
#[napi]
pub struct Connect(pub (crate) quiche::Connection);
#[napi]
impl Connection {
#[napi]
pub fn path_stats(&self) -> path::PathStatsIter {
return path::PathStatsIter(Box::new(self.0.path_stats()));
}
}
However the compiler complains that:
error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
--> src/connection.rs:1024:48
|
1023 | pub fn path_stats(&self) -> path::PathStatsIter {
| ----- this data with an anonymous lifetime `'_`...
1024 | return path::PathStatsIter(Box::new(self.0.path_stats()));
| ------ ^^^^^^^^^^
| |
| ...is used and required to live as long as `'static` here
The compiler error disappears if I use &'static self, but I'm not entirely sure if that makes sense, since the object isn't likely to stay around for the lifetime of the program.
My understanding is that self is necessary to produce this path_stats() iterator, so is this telling me that me trying to put it into a struct is incorrect because the struct (PathStatsIter)'s field may exist for longer than the lifetime of the connection struct?
The napi-rs macros doesn't allow me to provide lifetime annotation parameters on the methods. In JS, if I created an iterator that iterated off some parent object, and the parent object stopped existing, then the iterator would just fail. Alternatively the parent object would be GCed after the iterator itself goes away.

Rust - Lifetimes - Understanding Lifetime Error for mutable reference to self

I'm sure this is a duplicate, but I can't find a question which matches my question, exactly since I have a couple extra requirements because I have to adhere to some traits that I can't control.
Here is my code. I apologize for the sort of convoluted example, but this was the most I could minimize it as I am trying to implement a custom serialization format using the serde library.
// Doesn't really matter what this struct contains, it just needs an owning method
struct SideStruct;
impl SideStruct {
fn something_side<A: TraitA>(&self, aval: A) {
println!("something sideways :)");
aval.something_a(42)
}
}
trait TraitA {
fn something_a(&mut self, data: u32); // this would be the meat of my logic
}
// Note that this struct has an explicit lifetime
struct MainStruct<'a> {
refr: &'a mut u32
}
// Note that I implement for a mutable reference to MainStruct
impl<'a> TraitA for &'a mut MainStruct<'a> {
fn something_a(&mut self, data: u32) {
// Completely arbitrary, can safely ignore this function body
*self.refr += data;
println!("We're finally doing something: {}", self.refr);
}
}
// Implementing for MainStruct itself
impl<'a> MainStruct<'a> {
// Note, I can't change the signature for this function because it implements a trait
fn something_indirect(&mut self, ss: &SideStruct) {
// here is where the error occurs!
ss.something_side(self)
}
}
fn main() {
let mut base_val: u32 = 42;
let ss = SideStruct {};
let mut main_val = MainStruct { refr: &mut base_val };
main_val.something_indirect(&ss);
}
This is the error I got:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:28:27
|
28 | ss.something_side(self)
| ^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined here...
--> src/main.rs:27:27
|
27 | fn something_indirect(&mut self, ss: &SideStruct) {
| ^^^^^^^^^
note: ...so that the expression is assignable
--> src/main.rs:28:27
|
28 | ss.something_side(self)
| ^^^^
= note: expected `&mut MainStruct<'a>`
found `&mut MainStruct<'a>`
note: but, the lifetime must be valid for the lifetime `'a` as defined here...
--> src/main.rs:26:6
|
26 | impl<'a> MainStruct<'a> {
| ^^
note: ...so that the types are compatible
--> src/main.rs:28:12
|
28 | ss.something_side(self)
| ^^^^^^^^^^^^^^
= note: expected `<&mut MainStruct<'a> as TraitA>`
found `<&mut MainStruct<'_> as TraitA>`
For more information about this error, try `rustc --explain E0495`.
I don't know what the compiler means when it states that note: first, the lifetime cannot outlive the anonymous lifetime defined here.... Does it mean that some constraint forces self to not outlast the method something_indirect? That makes no sense. Also the message so that the expression is assignable confuses me. MainStruct should not be assigned when something_side is called on it right? Since I implemented TraitA for a mutable reference to MainStruct, shouldn't I be able to call something_side with a mutable reference to MainStruct by passing self? Anyways, thanks for the help, and have a great day!
The trouble is that in order to use the method defined, you must borrow the MainStruct as mutable with an anonymous lifetime. In the code you wrote, you not only borrow the things within MainStruct for 'a, but also MainStruct itself. This is unnecessary since the borrow has an inferred lifetime. You can fix this by removing the 'a in the trait impl
impl<'a> TraitA for &mut MainStruct<'a> {
/*...*/
}
This should do the exact same thing, but removes the bug. The bug is trying to tell you that the code you wrote is buggy, because it borrows MainStruct using a lifetime in the struct itself.

Returning a higher-kinded closure that captures a reference

I'm trying to write a method on a struct that returns a closure. This closure should take a &[u8] with an arbitrary lifetime 'inner as an argument and return the same type, &'inner [u8]. To perform its function, the closure also needs a (shared) reference to a member of the struct &self. Here is my code:
#![warn(clippy::pedantic)]
// placeholder for a large type that I can't afford to clone
struct Opaque(usize);
struct MyStruct<'a>(Vec<&'a Opaque>);
impl<'a> MyStruct<'a> {
pub fn get_func_for_index(
&'a self,
n: usize,
) -> Option<impl for<'inner> Fn(&'inner [u8]) -> &'inner [u8] + 'a> {
// the reference to the struct member, captured by the closure
let opaque: &'a Opaque = *self.0.get(n)?;
Some(move |i: &[u8]| {
// placeholder: do something with the input using the &Opaque
&i[opaque.0..]
})
}
}
fn main() {
let o1 = Opaque(1);
let o5 = Opaque(5);
let o7 = Opaque(7);
let x = MyStruct(vec![&o1, &o5, &o7]);
let drop_five = x.get_func_for_index(1 /*Opaque(5)*/).unwrap();
let data: Vec<u8> = Vec::from(&b"testing"[..]);
assert_eq!(drop_five(&data[..]), b"ng");
}
If I try to compile it with rustc 1.54.0 (a178d0322 2021-07-26), I get the following error:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> /tmp/lifetimes.rs:16:14
|
16 | &i[opaque.0..]
| ^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 14:14...
--> /tmp/lifetimes.rs:14:14
|
14 | Some(move |i: &[u8]| {
| ______________^
15 | | // placeholder: do something with the input using the &Opaque
16 | | &i[opaque.0..]
17 | | })
| |_________^
note: ...so that reference does not outlive borrowed content
--> /tmp/lifetimes.rs:16:14
|
16 | &i[opaque.0..]
| ^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 6:6...
--> /tmp/lifetimes.rs:6:6
|
6 | impl<'a> MyStruct<'a> {
| ^^
note: ...so that return value is valid for the call
--> /tmp/lifetimes.rs:10:17
|
10 | ) -> Option<impl for<'inner> Fn(&'inner [u8]) -> &'inner [u8] + 'a> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: higher-ranked subtype error
--> /tmp/lifetimes.rs:7:5
|
7 | / pub fn get_func_for_index(
8 | | &'a self,
9 | | n: usize,
10 | | ) -> Option<impl for<'inner> Fn(&'inner [u8]) -> &'inner [u8] + 'a> {
| |_______________________________________________________________________^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0495`.
It's quite a mouthful and I don't really understand what it's trying to tell me. The first part (first, the lifetime...) makes sense to me, the returned slice must not outlive the closure argument. The second part (but, the lifetime...) however seems weird to me - the + 'a annotation in the method signature refers to the closure itself (because it captures &'a self.foo), not to the value the closure returns.
Is it possible to change the code to model this correctly in rust, or is this construct just not supported at this time?
The problem is here:
Some(move |i: &[u8]| {
Every & has a lifetime on it, explicit or not. What is the lifetime of &[u8]? Clearly it should be "a lifetime chosen by the caller of the closure" (that is, a higher-ranked lifetime). But when the compiler encounters a reference type with a free lifetime parameter, even in the argument list of a closure, it will not assume that the lifetime is higher-ranked. The error message you get about the "anonymous lifetime #1" is the compiler confusedly trying to make a non-higher-ranked lifetime work.
The compiler could, in theory, work "backwards" from the impl Fn in the return type and recognize that the type of the closure needs to have this higher ranked lifetime. It's not quite clever enough to do that in this case, but there is a way to convince it: use a local function with a bounded type parameter to constrain the type of the closure to exactly the bound you want.
pub fn get_func_for_index(
&self, // note 1
n: usize,
) -> Option<impl 'a + for<'inner> Fn(&'inner [u8]) -> &'inner [u8]> { // note 2
// the reference to the struct member, captured by the closure
let opaque: &'a Opaque = *self.0.get(n)?;
// helper function to constrain the closure type
fn check<F: Fn(&[u8]) -> &[u8]>(f: F) -> F { // note 3
f
}
Some(check(move |i| {
// placeholder: do something with the input using the &Opaque
&i[opaque.0..]
}))
}
Playground
Please note the following:
&'a self is too conservative for this function because 'a is the lifetime parameter of the reference self contains, not the lifetime for which self is borrowed. In general, you should almost never write &'a self or &'a mut self where 'a is a named lifetime from an outer scope.
I find the + 'a easy to miss at the end of a long trait, especially a Fn trait with a return type. I recommend fronting the lifetime (putting it first) in cases like this to make clear that it relates more to the impl than to the &'inner [u8]. This is a stylistic choice.
Fn(&[u8]) -> &[u8] is actually exactly the same as for<'inner> Fn(&'inner [u8]) -> &'inner [u8], because the elision rules for Fn traits are the same as for regular functions. Either way is fine; I find the shorter version easier to read.
Similar questions
Expected bound lifetime parameter, found concrete lifetime [E0271]
How to declare a higher-ranked lifetime for a closure argument?
Why does this closure require inlining or `dyn`? What does `dyn` do here?

Borrow checker insists on the lifetime of a dereferenced value

Here's a minimal example of the issue I'm having:
struct S<'a> {
value: &'a mut Option<()>,
}
impl<'a> S<'a> {
fn f<'b>(&'b mut self) {
*self.value = Some(());
let value: &'a () = self.value.as_ref().unwrap();
}
}
Playground
Error:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/lib.rs:8:34
|
8 | let value: &'a () = self.value.as_ref().unwrap();
| ^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'b` as defined on the method body at 6:7...
--> src/lib.rs:6:7
|
6 | fn f<'b>(&'b mut self) {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:8:23
|
8 | let value: &'a () = self.value.as_ref().unwrap();
| ^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 5:6...
--> src/lib.rs:5:6
|
5 | impl<'a> S<'a> {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:8:23
|
8 | let value: &'a () = self.value.as_ref().unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The issue is that I'm expecting f's value variable to have the lifetime 'a as I've annotated, but the borrow checker is only content if it's 'b. I need it to be 'a because in my real code I derive a value from it that expects the 'a lifetime. And it also makes sense to me that it should be 'a because (and this is the crux of my confusion:) in self.value I've dereferenced 'b away and should be left with &'a mut Option<()>, i.e. a value with (just) the lifetime 'a.
I can solve it by specifying 'b: 'a but it's actually the opposite (if anything I need 'a: 'b); and also if 'b: 'a then this function mutably borrows indefinitely and I can't touch the S after calling f which is a problem Playground.
I'm not sure if it's overconservative or if I'm actually trying to do something unsound. Looking at the lifetimes at the call-site it makes perfect sense though.
Some information about my real use case: what I have is a buffer of type B, and from that buffer I can derive a value of type T. T isn't just derived from B, it also has a reference to it (imagine fn derive<'a>(self: &'a B) -> T<'a>). T values expire and require management, so I made a manager struct M, and this is where the trouble is: M contains a mutable reference to a B and a cached T. Therefore inside M, the B reference has some lifetime, and T has it too since T refers to B. It's something like this:
struct B { ... }
struct T<'a> { ... }
struct M<'a> {
b: &mut 'a Option<B>,
t: T<'a>,
}
So as in my minimal example, I try to obtain the reference of the B (which I expected to have the lifetime of the buffer but it has the lifetime of M) so I could derive from it and then assign the result to the cached T, but I don't have the right lifetime.

Can I limit the lifetime pollution from a struct?

I have a struct which contains some stuff. I implement the Iterator trait for that struct, and return a tuple of references to internal data in the struct. That necessitates that I annotate at least some things with lifetimes. What I want is to minimize the lifetime annotation, especially when it comes to other structs which have the original struct as a member.
some code:
pub struct LogReader<'a> {
data:String,
next_fn:fn(&mut LogReader)->Option<(&'a str,&'a [ConvertedValue])>,
//...
}
pub struct LogstreamProcessor {
reader: LogReader, // doesn't work without polluting LogstreamProcessor with lifetimes
//...
}
impl<'a> Iterator for LogReader<'a > {
type Item = (&'a str,&'a[ConvertedValue]);
fn next(&mut self) -> Option<(&'a str,&'a[ConvertedValue])>{(self.next_fn)(self)}
}
impl <'a> LogReader<'a> {
pub fn new(textFile:Option<bool>) -> LogReader<'a> {
LogReader {
next_fn:if textFile.unwrap_or(false) { LogReader::readNextText }else{ LogReader::readNextRaw },
data: "blah".to_string()
}
}
fn readNextText(&mut self)->Option<(&str,&[ConvertedValue])>{unimplemented!();}
fn readNextRaw(&mut self)->Option<(&str,&[ConvertedValue])>{unimplemented!();}
}
Can I limit the lifetime pollution from a struct?
Generically, if you're using them in any of your struct's fields, then you can't. They are made explicit for very good reasons (see Why are explicit lifetimes needed in Rust?), and once you have a struct containing objects that require explicit lifetimes, then they must be propagated.
Note that usually this isn't a concern to consumers of the struct, since the concrete lifetimes are then imposed by the compiler:
struct NameRef<'a>(&'a str);
let name = NameRef("Jake"); // 'a is 'static
One could also slightly mitigate the "noise" on the implementation of next by using the definition of Self::Item.
impl<'a> Iterator for LogReader<'a > {
type Item = (&'a str,&'a[ConvertedValue]);
fn next(&mut self) -> Option<Self::Item> {
(self.next_fn)(self)
}
}
However, your concern actually hides a more serious issue: Unlike you've mentioned, the values returned from next are not necessarily internal data from the struct. They actually live for as long as the generic lifetime 'a, and nothing inside LogReader is actually bound by that lifetime.
This means two things:
(1) I could pass a function that gives something completely different, and it would work just fine:
static NO_DATA: &[()] = &[()];
fn my_next_fn<'a>(reader: &mut LogReader<'a>) -> Option<(&'a str, &'a[ConvertedValue])> {
Some(("wat", NO_DATA))
}
(2) Even if I wanted my function to return something from the log reader's internal data, it wouldn't work because the lifetimes do not match at all. Let's try it out anyway to see what happens:
static DATA: &[()] = &[()];
fn my_next_fn<'a>(reader: &mut LogReader<'a>) -> Option<(&'a str, &'a[ConvertedValue])> {
Some((&reader.data[0..4], DATA))
}
fn main() {
let mut a = LogReader {
data: "This is DATA!".to_owned(),
next_fn: my_next_fn
};
println!("{:?}", a.next());
}
The compiler would throw you this:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/main.rs:26:12
|
26 | Some((&reader.data[0..4], DATA))
| ^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 25:88...
--> src/main.rs:25:89
|
25 | fn my_next_fn<'a>(reader: &mut LogReader<'a>) -> Option<(&'a str, &'a[ConvertedValue])> {
| _________________________________________________________________________________________^ starting here...
26 | | Some((&reader.data[0..4], DATA))
27 | | }
| |_^ ...ending here
note: ...so that reference does not outlive borrowed content
--> src/main.rs:26:12
|
26 | Some((&reader.data[0..4], DATA))
| ^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the body at 25:88...
--> src/main.rs:25:89
|
25 | fn my_next_fn<'a>(reader: &mut LogReader<'a>) -> Option<(&'a str, &'a[ConvertedValue])> {
| _________________________________________________________________________________________^ starting here...
26 | | Some((&reader.data[0..4], DATA))
27 | | }
| |_^ ...ending here
note: ...so that expression is assignable (expected std::option::Option<(&'a str, &'a [()])>, found std::option::Option<(&str, &[()])>)
--> src/main.rs:26:5
|
26 | Some((&reader.data[0..4], DATA))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...where the anonymous lifetime #1 is the log reader's lifetime. Forcing &mut LogReader to also have a lifetime 'a (&'a mut LogReader<'a>) would lead to further lifetime issues when attempting to implement Iterator. This basically narrows down to the fact that 'a is incompatible with references to values of LogReader themselves.
So, how should we fix that?
but that doesn't change the fact that the return type has references and so lifetime annotations come into it
Although that is not accurate (since lifetime elision can occur in some cases), that gives a hint to the solution: either avoid returning references at all or delegate data to a separate object, so that 'a can be bound to that object's lifetime. The final part of the answer to your question is in Iterator returning items by reference, lifetime issue.

Resources