Lifetime error when creating mutable iterator - rust

I had some problems when I tried to create a custom iterator. The non-mutable version worked fine but when copying the same function to create a mutable version, a lifetime error appeared. This is a simplified version of my problem:
struct Test {
map: HashMap<u32, String>
}
impl Test {
pub fn iter(&self, start: u32, end: u32) -> impl Iterator<Item = &String> {
(start..=end).filter_map(move |i| {
self.map.get(&i)
})
}
pub fn iter_mut(&mut self, start: u32, end: u32) -> impl Iterator<Item = &mut String> {
(start..=end).filter_map(move |i| {
self.map.get_mut(&i)
})
}
}
The iter function works fine but the iter_mut function doesn't compile with this error:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/main.rs:21:22
|
21 | self.map.get_mut(&i)
| ^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'_` as defined on the body at 20:34...
--> src/main.rs:20:34
|
20 | (start..=end).filter_map(|i| {
| ^^^
note: ...so that closure can access `self`
--> src/main.rs:21:13
|
21 | self.map.get_mut(&i)
| ^^^^^^^^
note: but, the lifetime must be valid for the anonymous lifetime defined on the method body at 19:21...
--> src/main.rs:19:21
|
19 | pub fn iter_mut(&mut self, start: u32, end: u32) -> impl Iterator<Item = &mut String> {
| ^^^^^^^^^
note: ...so that the types are compatible
--> src/main.rs:19:57
|
19 | pub fn iter_mut(&mut self, start: u32, end: u32) -> impl Iterator<Item = &mut String> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `std::option::Option<&mut std::string::String>`
found `std::option::Option<&mut std::string::String>`

As said Todd, compile error on iter_mut likely occurs due to creation many mutable references to the same HashMap, but I'm not sure about that. You can do something like that:
struct Test {
map: HashMap<u32, String>
}
impl Test {
pub fn iter(&self, start: u32, end: u32) -> impl Iterator<Item=&String> {
self.map
.iter()
.filter_map(move |k| {
if (start..=end).contains(k.0) {
Some(k.1)
} else {
None
}
})
}
pub fn iter_mut(&mut self, start: u32, end: u32) -> impl Iterator<Item=&mut String> {
self.map
.iter_mut()
.filter_map(move |k| {
if (start..=end).contains(k.0) {
Some(k.1)
} else {
None
}
})
}
}

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.

conflicting lifetime requirements on implementing Clone for simple struct

I'm designing a simple type to hold either a Vec<u8> or a slice (mut or not mut). I'm having problems on lifetime constraints and this time I don't know why there are conflicting requirements:
use std::vec::Vec;
pub enum EncodedPacket<'a> {
Owned(Vec<u8>),
Ref(&'a [u8]),
RefMut(&'a mut [u8])
}
impl<'a> EncodedPacket<'a> {
pub fn new_ref(slice: &'a [u8]) -> EncodedPacket<'a> {
EncodedPacket::Ref(slice)
}
pub fn new_ref_mut(slice: &'a mut [u8]) -> EncodedPacket<'a> {
EncodedPacket::RefMut(slice)
}
pub fn new_owned(vec: Vec<u8>) -> EncodedPacket<'a> {
EncodedPacket::Owned(vec)
}
}
impl<'a> Clone for EncodedPacket<'a> {
fn clone(&self) -> Self {
match self {
EncodedPacket::Owned(vec)=> EncodedPacket::new_owned(*vec),
EncodedPacket::Ref(slice) => EncodedPacket::new_ref(*slice),
EncodedPacket::RefMut(slice) => EncodedPacket::new_ref_mut(*slice)
}
}
}
Playground
Error:
Compiling playground v0.0.1 (/playground)
error[E0495]: cannot infer an appropriate lifetime for pattern due to conflicting requirements
--> src/lib.rs:28:35
|
28 | EncodedPacket::RefMut(slice) => EncodedPacket::new_ref_mut(*slice)
| ^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined on the method body at 24:14...
--> src/lib.rs:24:14
|
24 | fn clone(&self) -> Self {
| ^^^^^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:28:35
|
28 | EncodedPacket::RefMut(slice) => EncodedPacket::new_ref_mut(*slice)
| ^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 23:6...
--> src/lib.rs:23:6
|
23 | impl<'a> Clone for EncodedPacket<'a> {
| ^^
note: ...so that the expression is assignable
--> src/lib.rs:25:9
|
25 | / match self {
26 | | EncodedPacket::Owned(vec)=> EncodedPacket::new_owned(*vec),
27 | | EncodedPacket::Ref(slice) => EncodedPacket::new_ref(*slice),
28 | | EncodedPacket::RefMut(slice) => EncodedPacket::new_ref_mut(*slice)
29 | | }
| |_________^
= note: expected `EncodedPacket<'a>`
found `EncodedPacket<'_>`
I'm just recreating EncodedPacket with the same internal things, I don't see why there are conflicting lifetime requirements at all.
You cannot clone a mutable reference. One way of doing this would be to wrap it in Rc and Rc<RefCell>:
use std::vec::Vec;
use std::cell::RefCell;
use std::rc::Rc;
#[derive(Clone)]
pub enum EncodedPacket<'a> {
Owned(Vec<u8>),
Ref(Rc<&'a [u8]>),
RefMut(Rc<RefCell<&'a mut [u8]>>)
}
impl<'a> EncodedPacket<'a> {
pub fn new_ref(slice: &'a [u8]) -> EncodedPacket<'a> {
EncodedPacket::Ref(Rc::new(slice))
}
pub fn new_ref_mut(slice: &'a mut [u8]) -> EncodedPacket<'a> {
EncodedPacket::RefMut(Rc::new(RefCell::new(slice)))
}
pub fn new_owned(vec: Vec<u8>) -> EncodedPacket<'a> {
EncodedPacket::Owned(vec)
}
}
Playground

How to hold an iterator inside a struct in rust

I'm trying to do this
struct RwindIter {
iter: Box<dyn Iterator<Item = String>>,
}
fn build(i: impl Iterator<Item = String>) -> RwindIter {
RwindIter { iter: Box::new(i) }
}
But I got this error
Compiling myml v0.1.0 (/Users/gecko/code/myml)
error[E0310]: the parameter type `impl Iterator<Item = String>` may not live long enough
--> src/main.rs:47:23
|
47 | RwindIter { iter: Box::new(i) }
| ^^^^^^^^^^^
|
note: ...so that the type `impl Iterator<Item = String>` will meet its required lifetime bounds
--> src/main.rs:47:23
|
47 | RwindIter { iter: Box::new(i) }
| ^^^^^^^^^^^
help: consider adding an explicit lifetime bound `'static` to `impl Iterator<Item = String>`...
|
46 | fn build(i: impl Iterator<Item = String> + 'static) -> RwindIter {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0310`.
error: could not compile `myml`.
To learn more, run the command again with --verbose.
I was expecting that Box::new(x) would take the onwership of x so I can't figure out what the error message means. Any ideas?
Update
Okay I know it's some limitation around impl syntax. This works
struct I {}
impl Iterator for I {
type Item = String;
fn next(&mut self) -> Option<String> {
None
}
}
fn build(i: I) -> RwindIter {
RwindIter { iter: Box::new(i) }
}
I would recommend just using a regular generic to solve the issue.
pub struct FooIter<I> {
iter: I,
}
impl<I> FooIter<I> {
pub fn new(iter: I) -> Self {
FooIter { iter }
}
}
impl<I: Iterator<Item=String>> Iterator for FooIter<I> {
type Item = String;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
}
However you can still use a dyn Iterator<Item=String> so long as you provide a lifetime bound. However it could lead to a massive mess of lifetimes later on during implementation depending on how you interact with this struct.
pub struct FooIter<'a> {
iter: Box<dyn Iterator<Item=String> + 'a>,
}
impl<'a> FooIter<'a> {
pub fn new(iter: impl Iterator<Item=String> + 'a) -> Self {
FooIter {
iter: Box::new(iter),
}
}
}
impl<'a> Iterator for FooIter<'a> {
type Item = String;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
}

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
})
}
}

How do I fix a lifetime issue when returning an iterator of all combinations between a newly received value and cached values?

I am trying to return an iterator of all combinations between a newly received value and cached values, but I got a lifetime issue.
use std::collections::HashMap;
pub struct Status {
// <i,Vec<u>>
old: HashMap<usize, Vec<usize>>,
}
impl<'a> Status {
pub fn new() -> Self {
Status {
old: HashMap::new(),
}
}
pub fn gen(&mut self, u: usize, i: usize) -> UserPairIter<'a> {
let entry: &'a mut Vec<usize> = self.old.entry(i).or_insert(Vec::new());
UserPairIter::new(entry, u)
}
}
struct UserPairIter<'a> {
data: &'a mut Vec<usize>,
u: usize,
index: usize,
}
impl<'a> UserPairIter<'a> {
pub fn new(data: &'a mut Vec<usize>, u: usize) -> Self {
UserPairIter { data, u, index: 0 }
}
}
impl<'a> Iterator for UserPairIter<'a> {
type Item = (usize, usize);
fn next(&mut self) -> Option<Self::Item> {
if self.index >= self.data.len() {
self.data.push(self.u);
return None;
}
let result = (self.u, self.data[self.index]);
self.index += 1;
Some(result)
}
}
fn main() {}
When I compile, I get the following error message:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/main.rs:16:50
|
16 | let entry: &'a mut Vec<usize> = self.old.entry(i).or_insert(Vec::new());
| ^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 15:5...
--> src/main.rs:15:5
|
15 | / pub fn gen(&mut self, u: usize, i: usize) -> UserPairIter<'a> {
16 | | let entry: &'a mut Vec<usize> = self.old.entry(i).or_insert(Vec::new());
17 | | UserPairIter::new(entry, u)
18 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:16:41
|
16 | let entry: &'a mut Vec<usize> = self.old.entry(i).or_insert(Vec::new());
| ^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 8:1...
--> src/main.rs:8:1
|
8 | / impl<'a> Status {
9 | | pub fn new() -> Self {
10 | | Status {
11 | | old: HashMap::new(),
... |
18 | | }
19 | | }
| |_^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:16:41
|
16 | let entry: &'a mut Vec<usize> = self.old.entry(i).or_insert(Vec::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
First of all, do not put the lifetime generic in Status. If you need genericity in a function, put this parameter in function:
impl Status {
pub fn new() -> Self {
Status {
old: HashMap::new(),
}
}
pub fn gen<'a>(&mut self, u: usize, i: usize) -> UserPairIter<'a> {
let entry: &'a mut Vec<usize> = self.old.entry(i).or_insert(Vec::new());
UserPairIter::new(entry, u)
}
}
Then the compiler says that it cannot infer a lifetime for self.old. Just give it the hint with &'a mut self so that the compiler understands that the lifetime of the UserPairIter is the same as the lifetime of Status:
impl Status {
pub fn new() -> Self {
Status {
old: HashMap::new(),
}
}
pub fn gen<'a>(&'a mut self, u: usize, i: usize) -> UserPairIter<'a> {
let entry: &'a mut Vec<usize> = self.old.entry(i).or_insert(Vec::new());
UserPairIter::new(entry, u)
}
}
And that is ok!
You do not need to say the type of entry, the compiler can infer it with the function signature:
pub fn gen<'a>(&'a mut self, u: usize, i: usize) -> UserPairIter<'a> {
let entry = self.old.entry(i).or_insert(Vec::new());
UserPairIter::new(entry, u)
}

Resources