Why does one non-consuming builder compile while another does not? - rust

I read the builder pattern and then tried to build 2 different builders (Header and Request) as follows:
use std::ascii::AsciiExt;
#[derive(PartialEq, Debug)]
pub struct Headers<'a> (pub Vec<(&'a str, String)>);
impl<'a> Headers<'a> {
pub fn replace(&'a mut self, name: &'a str, value:&str) -> &mut Headers<'a> {
self.0.retain(|&(key, _)|!name.eq_ignore_ascii_case(key));
self.0.push((name, value.to_string()));
self
}
}
#[derive(PartialEq, Debug)]
pub struct Request<'a> {
pub headers: Headers<'a>,
}
impl<'a> Request<'a> {
pub fn header(&'a mut self, name: &'a str, value:&'a str) -> &mut Request<'a> {
self.headers.replace(name, value);
self
}
}
Why does Header compile fine but Request fails with:
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/api.rs:154:9
|
153 | self.headers.replace(name, value);
| ------------ first mutable borrow occurs here
154 | self
| ^^^^ second mutable borrow occurs here
155 | }
| - first borrow ends here

You have an issue with your lifetimes: you are re-using the same lifetime ('a) for too many different things, so that when the compiler attempts to use a single lifetime for all those 'a you get a confusing error message.
The solution is simple: do not use 'a everywhere you can put a lifetime, but only where it's necessary.
It is unnecessary to use &'a mut self, the instance (self) does not need to have the same lifetime as the &str it contains! (and actually, cannot really):
impl<'a> Headers<'a> {
pub fn replace(&mut self, name: &'a str, value: &str) -> &mut Headers<'a> {
self.0.retain(|&(key, _)|!name.eq_ignore_ascii_case(key));
self.0.push((name, value.to_string()));
self
}
}
impl<'a> Request<'a> {
pub fn header(&mut self, name: &'a str, value: &str) -> &mut Request<'a> {
self.headers.replace(name, value);
self
}
}

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.

How to allow immutable and mutable borrows to coexist in a function with explicit lifetimes?

For context: I'm implementing an Entity, basically a thin wrapper around a heterogenous map, and trying to implement an update method:
struct Entity {
pub id: u64,
data: HashMap<TypeId, Box<dyn Any>>,
}
impl Entity {
pub fn new(id: u64) -> Self {
Entity { id, data: HashMap::new() }
}
pub fn get_atom<T: Any>(&self) -> Option<&T> {
self.data.get(&TypeId::of::<T>())?.downcast_ref()
}
pub fn set_atom<T: Any>(&mut self, value: T) {
self.data.insert(TypeId::of::<T>(), Box::new(value));
}
pub fn update<T: Any, R: Any>(&mut self, f: impl Fn(&T) -> R)
{
if let Some(val) = self.get_atom() {
self.set_atom(f(val));
}
}
}
This works, but gives a warning:
warning: cannot borrow `*self` as mutable because it is also borrowed as immutable
--> src/entity.rs:71:13
|
70 | if let Some(val) = self.get_atom() {
| --------------- immutable borrow occurs here
71 | self.set_atom(f(val));
| ^^^^^^^^^^^^^^^^---^^
| | |
| | immutable borrow later used here
| mutable borrow occurs here
OK, that's fixable like this, which removes the warning.
pub fn update<T: Any, R: Any>(&mut self, f: impl Fn(&T) -> R)
{
let maybe : Option<R> = self.get_atom().map(f);
if let Some(val) = maybe {
self.set_atom(val);
}
}
The problem I have is when I introduce a trait for abstracting over getting stuff out of the entity (which permits me to abstract over arity: getting a tuple returns a value if each of the components is in the entity):
trait GetComponent<'a, T> {
fn get_component(entity: &'a Entity) -> Option<T>;
}
// sample atom impl
impl <'a> GetComponent<'a, &'a u32> for &'a u32 {
fn get_component(entity: &'a Entity) -> Option<&'a u32> {
entity.get_atom()
}
}
// sample composite impl
impl <'a, A, B> GetComponent<'a, (A, B)> for (A, B) where
A: GetComponent<'a, A>,
B: GetComponent<'a, B>,
{
fn get_component(entity: &'a Entity) -> Option<(A, B)> {
Some((A::get_component(entity)?, B::get_component(entity)?))
}
}
impl Entity {
<in addition to the above>
pub fn get<'a, T: GetComponent<'a, T>>(&'a self) -> Option<T> {
T::get_component(self)
}
pub fn update<'a, T: 'a, R: Any>(&'a mut self, f: impl Fn(&T) -> R)
where &'a T: GetComponent<'a, &'a T>
{
let maybe : Option<R> = self.get().map(f);
if let Some(val) = maybe {
self.set_atom(val);
}
}
}
The trait requires me to be explicit about lifetimes, and everything else I've tried to do so far with the entity seems to be just fine. But this update method gives this compile error (not a warning this time):
error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
--> src/entity.rs:56:13
|
51 | pub fn update<'a, T: 'a, R: Any>(&'a mut self, f: impl Fn(&T) -> R)
| -- lifetime `'a` defined here
...
54 | let maybe : Option<R> = self.get().map(f);
| ----------
| |
| immutable borrow occurs here
| argument requires that `*self` is borrowed for `'a`
55 | if let Some(val) = maybe {
56 | self.set_atom(val);
| ^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
Now, as far as I can see, there's no reason why I shouldn't be able to immutably borrow for a shorter period, so the immutable borrow "expires" before I do the mutation - just like in the version without explicit lifetimes used prior to the trait.
But I can't for the life of me work out how to make this work.
You can solve this with a higher-rank trait bound (HRTB):
pub fn update<T, R: Any>(&mut self, f: impl Fn(&T) -> R)
where for <'a> &'a T: GetComponent<'a, &'a T>
This says that for any possible lifetime 'a, T must satisfy the given bound. This allows you to specify how the various lifetimes on the type T relate to each other without binding them to a specific lifetime, such as that of &mut self.
(Playground)

Satisfying lifetimes for traits that are required by one another

Im trying to write a basic nary tree, where I have several traits that are all intended to work on structs which will form the nodes of the tree. These structs will have mutable references to the other nodes of the tree, so I have included lifetime parameters in my trait definitions.
For instance, this is the trait which all the structs will implement:
pub trait Node<'a>: NodeClone {
fn value(&self) -> String;
fn parent(&self) -> Option<Box<dyn Node>>;
fn children(&self) -> Vec<Box<dyn Node>>;
fn set_parent(&mut self, parent: &mut Box<dyn Node>);
fn push_child(&mut self, child: &mut Box<dyn Node>);
fn to_string(&self, current: &mut String) -> String;
}
Anything which implements Node must also implement NodeClone, which looks like:
pub trait NodeClone {
fn clone_box(&self) -> Box<dyn Node>;
}
impl<'a, T> NodeClone for T where T: 'static + Node<'a> + Clone, {
fn clone_box(&self) -> Box<dyn Node> {
return Box::new(self.clone());
}
}
impl<'a> Clone for Box<dyn Node<'a>> {
fn clone(&self) -> Box<dyn Node<'a>> {
return self.clone_box();
}
}
This is one of the structs which will form the tree:
#[derive(Clone)]
pub struct Operation<'a> {
pub parent: Option<&'a mut Box<dyn Node<'a>>>,
pub children: Vec<&'a mut Box<dyn Node<'a>>>
}
When I then try and implement Node for Operation like:
impl<'a> Node<'a> for Operation<'a>
I get the error that:
error[E0477]: the type `Operation<'a>` does not fulfill the required lifetime
--> src/language/components/node/operation.rs:31:10
|
31 | impl<'a> Node<'a> for Operation<'a> {
| ^^^^^^^^
|
note: type must satisfy the static lifetime as required by this binding
--> src/language/components/node.rs:15:21
|
15 | pub trait Node<'a>: NodeClone {
|
When I change the implementation of Operation to include a static lifetime:
impl<'a> Node<'a> for Operation<'static>
The fields of my struct Operation give me the error that:
the trait bound `&mut Box<(dyn Node<'_> + 'static)>: Clone` is not satisfied
Im not sure which lifetime I should change and where to solve this. Please help!

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

Cannot borrow variable as mutable more than once at a time after calling a &'a mut self method

I have a problem with lifetimes/borrowing with my Graph object.
fn main() {
let mut g = Graph {
nodePointer: &mut 0,
edgePointer: &mut 0,
nodes: &mut Vec::new(),
edges: &mut Vec::new(),
};
let node1 = g.add_node((1, 1));
let node2 = g.get_node(0);
}
pub struct Graph<'a> {
pub nodePointer: &'a mut usize,
pub edgePointer: &'a mut usize,
pub nodes: &'a mut Vec<Node>,
pub edges: &'a mut Vec<Edge>,
}
impl<'a> Graph<'a> {
pub fn add_node(&'a mut self, data: (u64, u64)) -> usize {
let id: usize = *self.nodePointer;
self.nodes.push(Node {
id: id,
datum: data,
});
*self.nodePointer += 1;
return id;
}
pub fn get_node(&'a mut self, id: usize) -> &'a Node {
return &self.nodes[id];
}
pub fn add_edge(&'a mut self, source: u64, target: u64, weight: u16) -> usize {
let id: usize = *self.nodePointer;
self.edges.push(Edge {
id: id,
source,
target,
weight,
});
*self.edgePointer = *self.edgePointer + 1;
return id;
}
}
pub struct Node {
pub id: usize,
pub datum: (u64, u64),
}
pub struct Edge {
pub id: usize,
pub source: u64,
pub target: u64,
pub weight: u16,
}
error[E0499]: cannot borrow `g` as mutable more than once at a time
--> src/main.rs:9:17
|
8 | let node1 = g.add_node((1, 1));
| - first mutable borrow occurs here
9 | let node2 = g.get_node(0);
| ^ second mutable borrow occurs here
10 | }
| - first borrow ends here
Your problem arises from a misuse of lifetimes, specifically in your signature of add_node:
pub fn add_node(&'a mut self, data: (u64, u64)) -> usize
In this signature, you are stating that add_node takes an &'a mut self on a Graph<'a>; in other words, you are telling Rust that this method needs to take a mutable borrow on the graph that can't be dropped before the end of the Graph's lifetime, 'a. But since it's the graph itself holding a reference to the graph, the only time that reference will be dropped is when the graph itself is dropped.
Since add_node doesn't require you to return a reference to any object within the struct, holding onto that borrow is irrelevant. If you alter your add_node method to remove the explicit lifetime:
pub fn add_node(&mut self, data: (u64, u64)) -> usize
then your example no longer raises an error, because add_node is now only borrowing self until it's finished with the function. (Under the hood, this effectively creates a second lifetime 'b and makes the signature into &'b mut self)
See the playground for proof.
Consider this :
struct Foo<'a> {
x: &'a i32,
}
As the book states:
So why do we need a lifetime here? We need to ensure that any reference to a Foo cannot outlive the reference to an i32 it contains.
If you write something like:
impl<'a> Graph<'a> {
pub fn add_node(&'a mut self, data: (u64, u64)) -> usize {
...
the lifetime declaration &'a mut self is not for the purpose of relating the lifetime of Graph instance with the contained references,
but for declaring that for mutable self references hold the same lifetime 'a declared for Graph field references:
fn main() {
let mut g = Graph { // <------------
nodePointer: &mut 0, // |
edgePointer: &mut 0, // lifetime |
nodes: &mut Vec::new(), // of Graph | 'a
edges: &mut Vec::new(), // references |
}; // |
let node1 = Graph::add_node(&mut g, (1, 1)); // |
let node2 = Graph::get_node(&mut g, 0); // |
} //<-------------
Where g.get_node(0) has been rewritten as Graph::get_node(&mut g, 0) just for explicitly exposing the &mut reference
Looking at the lifetime of 'a it is clear that the reference &mut g is borrowed mutably more than once, and this causes the error.

Resources