Borrowed value does not live long enough requiring static lifetime - rust

I'm getting this error with a sample code at this rust playground
Compiling playground v0.0.1 (/playground)
error[E0597]: `text` does not live long enough
--> src/main.rs:34:38
|
34 | let item = NotLongEnough { text: &text };
| ^^^^^ borrowed value does not live long enough
35 | let mut wrapper = Container { buf: Vec::new() };
36 | wrapper.add(Box::new(item));
| -------------- cast requires that `text` is borrowed for `'static`
...
40 | }
| - `text` dropped here while still borrowed
error: aborting due to previous error
For more information about this error, try `rustc --explain E0597`.
error: could not compile `playground`
To learn more, run the command again with --verbose.
The contents are:
trait TestTrait {
fn get_text(&self) -> &str;
}
#[derive(Copy, Clone)]
struct NotLongEnough<'a> {
text: &'a str,
}
impl<'a> TestTrait for NotLongEnough<'a> {
fn get_text(&self) -> &str {
self.text
}
}
struct Container {
buf: Vec<Box<dyn TestTrait>>,
}
impl Container {
pub fn add(&mut self, item: Box<dyn TestTrait>) {
self.buf.push(item);
}
pub fn output(&self) {
for item in &self.buf {
println!("{}", item.get_text());
}
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let text = "test".to_owned();
let item = NotLongEnough { text: &text };
let mut wrapper = Container { buf: Vec::new() };
wrapper.add(Box::new(item));
wrapper.output();
Ok(())
}
I have no clue why cast requires that text is borrowed for 'static
Could someone please help me with this? I've no idea what I've done wrong.

TLDR: Fixed version
The problem is in your Container definition:
struct Container {
buf: Vec<Box<dyn TestTrait>>,
}
The statement dyn TestTrait is equivalent to dyn TestTrait + 'static, meaning that your trait objects must not contain any references with lifetime less than 'static.
In order to fix the problem, you have to replace that trait bound with a less strict one:
struct Container<'a> {
buf: Vec<Box<dyn TestTrait + 'a>>,
}
Now instead of 'static, the container requires 'a. And you have to apply that change to the implementation as well:
pub fn add(&mut self, item: Box<dyn TestTrait + 'a>) { // notice the new trait-bound
self.buf.push(item);
}
Relevant resources:
Trait bounds

Related

Ensure that one lifetime outlives another in tree

I'm having a hard time figuring out the lifetime syntax that I need for the following code, which does not compile. The basic idea is that I'm creating an Abstract Syntax Tree, and each node must have a different type. Some node types must hold a reference to an external value. It's not possible to make this external value an owned type; it's actually a reference to disk file that must be shared by a number of nodes. Here's the code, as simple as I can make it:
trait Node {
fn init(&mut self, my_str: &str);
}
struct NodeParent {
pub children: Vec<Box<dyn Node>>,
}
impl Node for NodeParent {
fn init(&mut self, my_str: &str) {
for child in self.children.iter_mut() {
child.init(my_str);
}
}
}
struct NodeLeaf<'a> {
pub my_str: Option<&'a str>,
}
impl Node for NodeLeaf<'_> {
fn init(&mut self, my_str: &str) {
self.my_str = Some(my_str);
}
}
impl NodeLeaf<'_> {
pub fn new() -> Box<dyn Node> {
Box::new(NodeLeaf { my_str: None })
}
}
pub fn make_ast() {
let mut parent = NodeParent { children: vec![] };
let leaf = NodeLeaf::new();
parent.children.push(leaf);
let some_string = String::from("foo");
let my_str = some_string.as_str();
parent.init(my_str);
}
The error is:
error: lifetime may not live long enough
--> src/query/lifetime_test.rs:23:9
|
22 | fn init(&mut self, my_str: &str) {
| --------- - let's call the lifetime of this reference `'1`
| |
| has type `&mut NodeLeaf<'2>`
23 | self.my_str = Some(my_str);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2`
I know I need some kind of lifetime on &my_str everywhere it appears, but once I start taking the compiler's suggestion to start adding lifetimes here and there they proliferate, and I never get to code that compiles. I've also tried to Rc<>, but the code to make that work eludes me as well.
How do I specify that &my_str outlives the whole Node tree?
Link to the code on Rust Playground
Add a lifetime to Node:
trait Node<'a> {
fn init(&mut self, my_str: &'a str);
}
struct NodeParent<'a> {
pub children: Vec<Box<dyn Node<'a>>>,
}
impl<'a> Node<'a> for NodeParent<'a> {
fn init(&mut self, my_str: &'a str) {
for child in self.children.iter_mut() {
child.init(my_str);
}
}
}
struct NodeLeaf<'a> {
pub my_str: Option<&'a str>,
}
impl<'a> Node<'a> for NodeLeaf<'a> {
fn init(&mut self, my_str: &'a str) {
self.my_str = Some(my_str);
}
}
impl<'a> NodeLeaf<'a> {
pub fn new() -> Box<dyn Node<'a>> {
Box::new(NodeLeaf { my_str: None })
}
}
But this is not enough, because Box<dyn Node<'a>> is actually Box<dyn Node<'a> + 'static>, that is, it cannot contain any non-'static lifetime. You need to specify that it can contain lifetime 'a:
struct NodeParent<'a> {
pub children: Vec<Box<dyn Node<'a> + 'a>>,
}
impl<'a> NodeLeaf<'a> {
pub fn new() -> Box<dyn Node<'a> + 'a> {
Box::new(NodeLeaf { my_str: None })
}
}
Now you will get a different error:
error[E0597]: `some_string` does not live long enough
--> src/lib.rs:39:18
|
39 | let my_str = some_string.as_str();
| ^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
40 | parent.init(my_str);
41 | }
| -
| |
| `some_string` dropped here while still borrowed
| borrow might be used here, when `parent` is dropped and runs the destructor for type `NodeParent<'_>`
|
= note: values in a scope are dropped in the opposite order they are defined
Because Box<dyn Node> may have an arbitrary destructor, and it may access the stored string, we need to make sure it is still alive when the value is dropped. Do that by moving the string creation before the nodes:
pub fn make_ast() {
let some_string = String::from("foo");
let mut parent = NodeParent { children: vec![] };
let leaf = NodeLeaf::new();
parent.children.push(leaf);
let my_str = some_string.as_str();
parent.init(my_str);
}
Playground.

`*buf` was mutably borrowed here in the previous iteration of the loop?

This code:
pub struct Event<'a> {
_p: std::marker::PhantomData<&'a ()>,
}
pub fn foo<'a>(_buf: &'a mut Vec<u8>) -> Event<'a> {
todo!()
}
pub fn bar<'a>(buf: &'a mut Vec<u8>, event: &'a mut Event<'a>) {
loop {
*event = foo(buf);
}
}
Compile error:
error[E0499]: cannot borrow `*buf` as mutable more than once at a time
--> src/lib.rs:11:22
|
9 | pub fn bar<'a>(buf: &'a mut Vec<u8>, event: &'a mut Event<'a>) {
| -- lifetime `'a` defined here
10 | loop {
11 | *event = foo(buf);
| ----^^^-
| | |
| | `*buf` was mutably borrowed here in the previous iteration of the loop
| argument requires that `*buf` is borrowed for `'a`
For more information about this error, try `rustc --explain E0499`.
But remove the loop, the code will be passed, I want to know why to fix this compile error.
In the example you give, the compiler error is correct in terms of safety. In the first iteration, the buffer is passed into Event and then stored in *event. The next iteration cannot loan the buffer to as it is still owned by *event.
If however Event doesn't actually reference the buffer after the fact, you can introduce a new lifetime to show that:
pub struct Event<'a> {
_p: std::marker::PhantomData<&'a ()>,
}
pub fn foo<'a, 'b>(_buf: &'a mut Vec<u8>) -> Event<'b> {
todo!()
}
pub fn bar<'a>(buf: &'a mut Vec<u8>, event: &'a mut Event<'a>) {
loop {
*event = foo(buf);
}
}

How can I fix "cannot infer an appropriate lifetime for autoref" when implementing an iterator that returns mutable references?

I'm trying to write a mutable iterator for a linked list called Thread where each element implements Block.
trait Block<'a> {
fn next(&mut self) -> Option<&'a mut (dyn Block<'a> + 'a)> {
None
}
}
pub struct Thread<'a> {
head: Box<dyn Block<'a> + 'a>,
}
impl<'a> Thread<'a> {
fn iter_mut(&mut self) -> ThreadIterator<'a> {
ThreadIterator {
next: Some(self.head.as_mut()),
}
}
}
pub struct ThreadIterator<'a> {
next: Option<&'a mut (dyn Block<'a> + 'a)>,
}
impl<'a> Iterator for ThreadIterator<'a> {
type Item = &'a mut (dyn Block<'a> + 'a);
fn next(&mut self) -> Option<&'a mut (dyn Block<'a> + 'a)> {
self.next.take().map(|mut block| {
self.next = block.next();
block
})
}
}
Compiling this will output the error:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/lib.rs:14:34
|
14 | next: Some(self.head.as_mut()),
| ^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 12:5...
--> src/lib.rs:12:5
|
12 | / fn iter_mut(&mut self) -> ThreadIterator<'a> {
13 | | ThreadIterator {
14 | | next: Some(self.head.as_mut()),
15 | | }
16 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:14:24
|
14 | next: Some(self.head.as_mut()),
| ^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 11:6...
--> src/lib.rs:11:6
|
11 | impl<'a> Thread<'a> {
| ^^
note: ...so that the types are compatible
--> src/lib.rs:14:24
|
14 | next: Some(self.head.as_mut()),
| ^^^^^^^^^^^^^^^^^^
= note: expected `dyn Block<'_>`
found `dyn Block<'a>`
This is why I need the 'a requirement for all Blocks (they are borrowing a Runtime):
struct Runtime {}
struct ExampleBlock<'a> {
runtime: &'a Runtime,
next: Box<dyn Block<'a> + 'a>,
}
impl<'a> Block<'a> for ExampleBlock<'a> {
fn next(&mut self) -> Option<&'a mut (dyn Block<'a> + 'a)> {
Some(self.next.as_mut())
}
}
The first thing I tried was removing the mutable requirement from all references. Same errors.
I think the error is telling me that self.head.as_mut() is outliving self.head, so I must ensure that the lifetime of that reference is shorter than Thread<'a>. I thought I fulfilled this requirement with the 'a lifetime for ThreadIterator<'a>. In other words, you can't possibly drop Thread before ThreadIterator, right?
Edit:
I changed Block to a struct to simplify the code, though I need it to be a trait in the end.
struct Block {}
impl<'a> Block {
fn next(&mut self) -> Option<&'a mut Block> {
None
}
}
pub struct Thread {
head: Block,
}
impl<'a> Thread {
fn iter_mut(&mut self) -> ThreadIterator<'a> {
ThreadIterator {
next: Some(&mut self.head),
}
}
}
pub struct ThreadIterator<'a> {
next: Option<&'a mut Block>,
}
impl<'a> Iterator for ThreadIterator<'a> {
type Item = &'a mut Block;
fn next(&mut self) -> Option<&'a mut Block> {
self.next.take().map(|mut block| {
self.next = block.next();
block
})
}
}
It is based off of https://rust-unofficial.github.io/too-many-lists/second-iter-mut.html.
The answer to `cannot infer an appropriate lifetime for autoref due to conflicting requirements` but can't change anything due to trait definition constraints was to introduce a Option for the iterator, which I have done. Lifetime parameter problem in custom iterator over mutable references and Reimplementation of LinkedList: IterMut not compiling didn't answer my question, though I have a hard time connecting my code to theirs.
I finally found something that does work:
pub struct Block {}
impl<'a> Block {
fn next(&mut self) -> Option<&'a mut Block> {
None
}
}
pub struct Thread {
head: Block,
}
impl Thread {
fn iter_mut(&mut self) -> ThreadIterator<'_> { // The lifetime here is changed
ThreadIterator {
next: Some(&mut self.head),
}
}
}
pub struct ThreadIterator<'a> {
next: Option<&'a mut Block>,
}
impl<'a> Iterator for ThreadIterator<'a> {
type Item = &'a mut Block;
fn next(&mut self) -> Option<&'a mut Block> {
self.next.take().map(|mut block| {
self.next = block.next();
block
})
}
}
I'm having a hard time applying this to the original code, because there might be two different lifetimes, one for the iterator and one for the trait.
Answered by u/quixotrykd/:
The compiler seems to be choking here because it doesn't know how the lifetime on &mut self and ThreadIterator relate. As such, it has no way to guarantee that &mut self lives at least as long as the underlying borrow in ThreadIterator. Looking at your code here, that would be line 12 (note I've fixed your mistake in the above link).
You need to tell the compiler that the lifetime on the output ThreadIterator is the same as the input &mut self (or technically that it lasts at least as long, though you very likely want the same lifetime here), otherwise the compiler has no way to ensure that the "self" that's borrowed by &mut self stick around as long as the ThreadIterator's borrow. Looking at the rules for lifetime elision here, we can see that this doesn't apply to your code, and as such, you need to manually specify the lifetime on &mut self (otherwise it generates another, unrelated, anonymous lifetime, as indicated in the compiler's error message).
The fixed code:
pub trait Block<'a> { // Make public to resolve unrelated error
fn next(&mut self) -> Option<&'a mut (dyn Block<'a> + 'a)> {
None
}
}
pub struct Thread<'a> {
head: Box<dyn Block<'a> + 'a>,
}
impl<'a> Thread<'a> {
fn iter_mut(&'a mut self) -> ThreadIterator<'a> { // Add lifetime to &self
ThreadIterator {
next: Some(self.head.as_mut()),
}
}
}
pub struct ThreadIterator<'a> {
next: Option<&'a mut (dyn Block<'a> + 'a)>,
}
impl<'a> Iterator for ThreadIterator<'a> {
type Item = &'a mut (dyn Block<'a> + 'a);
fn next(&mut self) -> Option<&'a mut (dyn Block<'a> + 'a)> {
self.next.take().map(|mut block| {
self.next = block.next();
block
})
}
}

Storing Fn types gives error: cast requires that ... is borrowed for 'static`

Here is a small code sample representing the problem I currently have. CmdMap stores some logic from Trait types that should be triggered by a String key. This logic requires a context that is provided with the Arg instance. In this Arg instance, we may need mutable references to some objects (represented here by Printer).
Here's the code:
use std::collections::HashMap;
struct Cmd {}
pub trait Trait<T> {
fn execute(args: T) -> Result<(), String>;
}
impl<'a> Trait<Arg<'a>> for Cmd {
fn execute(arg: Arg) -> Result<(), String> {
arg.printer.print("execute".to_string());
Ok(())
}
}
struct Printer {
name: String,
}
impl Printer {
pub fn print(&mut self, msg: String) {
self.name = "print".to_string();
println!("{}: {}", self.name, msg);
}
}
struct Arg<'a> {
pub printer: &'a mut Printer,
}
type Callback<T> = dyn Fn(T) -> Result<(), String>;
struct CmdMap<T> {
pub map: HashMap<String, Box<Callback<T>>>,
}
impl<T> CmdMap<T> {
pub fn try_execute(&self, name: String, arg: T) {
self.map[&name](arg);
}
}
fn test() {
let mut map: CmdMap<Arg> = CmdMap {
map: HashMap::new(),
};
map.map.insert("test".to_string(), Box::new(Cmd::execute));
let mut printer: Printer = Printer {
name: "".to_string(),
};
loop {
map.try_execute(
"test".to_string(),
Arg {
printer: &mut printer,
},
);
}
}
The compiler complains:
error[E0499]: cannot borrow `printer` as mutable more than once at a time
--> src/lib.rs:57:26
|
47 | map.map.insert("test".to_string(), Box::new(Cmd::execute));
| ---------------------- cast requires that `printer` is borrowed for `'static`
...
57 | printer: &mut printer,
| ^^^^^^^^^^^^ mutable borrow starts here in previous iteration of loop
...
58 | map.try_execute("test".to_string(), Arg { printer: &mut printer });
| ^^^^^^^^^^^^ mutable borrow starts here in previous iteration of loop
I don't undersand why the compiler complains here. The first error cast requires that printer is borrowed for 'static, doesn't make sense to me as I'm storing Fn types that need to borrow printer for the time of their execution only.
Am I missing something?

Specify that lifetime of argument lasts for function call

I have a trait with a function that takes a reference to an iterator:
#[derive(Clone)]
struct Dog {
name: &'static str,
}
trait DogListAction<'a, I>
where
I: Iterator<Item = &'a Dog>,
{
fn on_dog_list(&mut self, dog_list: I);
}
struct DogListActionExample {}
impl<'a, I> DogListAction<'a, I> for DogListActionExample
where
I: Iterator<Item = &'a Dog>,
{
fn on_dog_list(&mut self, dog_list: I) {
for dog in dog_list {
println!("{}", dog.name);
}
}
}
fn main() {
let dogs = vec![Dog { name: "Pluto" }, Dog { name: "Lilly" }];
let mut action_example = DogListActionExample {};
let mut dog_list_actions: Vec<Box<DogListAction<_>>> = vec![Box::new(action_example)];
loop {
let dog_clone = dogs.clone();
for dog_list_action in &mut dog_list_actions {
dog_list_action.on_dog_list(dog_clone.iter());
}
}
}
playground
It does not take any reference to the elements, so there is no need for it to last for more time than the function call.
Due to my limited understanding of lifetimes, I do not know yet how to express this. Calling this function causes a compilation error:
error[E0597]: `dog_clone` does not live long enough
--> src/main.rs:33:41
|
33 | dog_list_action.on_dog_list(dog_clone.iter());
| ^^^^^^^^^ borrowed value does not live long enough
34 | }
35 | }
| - `dog_clone` dropped here while still borrowed
36 | }
| - borrowed value needs to live until here
I guess the borrow checker thinks that data in dog_clone may be referenced after the function ends, but this is not the case.
The problem here is that the code can potentially save short-lived references to dog_clone elements in the longer-lived dog_list_actions. We need to tell the compiler that we will not be saving references the iterator produces. It can be done like this:
trait DogListAction {
fn on_dog_list<'a, I>(&'a mut self, dog_list: I)
where
I: Iterator<Item = &'a Dog>;
}
Now Item's can live for the duration of on_dog_list call. In the original code they must live for longer duration.
But this code creates another problem: we can't box the trait DogListAction anymore as it includes generic function. The usual approach here is to use a trait object:
trait DogListAction {
fn on_dog_list<'a>(&'a mut self, dog_list: Box<dyn Iterator<Item = &'a Dog> + 'a>);
}
Note the second 'a in Box<dyn Iterator<Item = &'a Dog> + 'a>. Rust adds a 'static trait bound to boxed trait objects by default and we don't want 'static here.
#[derive(Clone)]
struct Dog {
name: &'static str,
}
trait DogListAction {
fn on_dog_list<'a>(&'a mut self, dog_list: Box<dyn Iterator<Item = &'a Dog> + 'a>);
}
struct DogListActionExample {}
impl DogListAction for DogListActionExample {
fn on_dog_list<'a>(&'a mut self, dog_list: Box<dyn Iterator<Item = &'a Dog> + 'a>) {
for dog in dog_list {
println!("{}", dog.name);
}
}
}
fn main() {
let dogs = vec![Dog { name: "Pluto" }, Dog { name: "Lilly" }];
let action_example = DogListActionExample {};
let mut dog_list_actions: Vec<Box<DogListAction>> = vec![Box::new(action_example)];
{
let dogs_clone = dogs.clone();
for dog_list_action in &mut dog_list_actions {
dog_list_action.on_dog_list(Box::new(dogs_clone.iter()));
}
}
}
Playground

Resources