All I was trying to do is copy a vector to another vector by iterating through it. I am getting the error borrowed value does not live long enough. And I get it why I am seeing this, that's because the invalid memory reference must not live outside scope. My question is, how can I destroy the reference as well in the scope after using it?
fn main() {
let x: Vec<&str> = vec!["a","b","c","d"];
let mut y: Vec<&str> = vec![];
let z: String = String::from("xy");
let p: &String = &z;
for i in x {
let k = [i, p].concat();
let q: &str = &k;
y.push(q);
}
println!("{:?}",y);
}
I want to keep Vec<&str> for mut y. I don't want to change it to Vec<String> although that's possible, because I want to keep it on the stack, not heap. Is that possible?
k is getting allocated on the heap regardless of how you define your Vec, the problem is the scope of k.
for i in x {
let k = [i, p].concat();
let q: &str = &k;
y.push(q);
} // <- k goes out of scope at the end of each iteration.
y can not hold a reference to k because it will not exist when the loop finishes.
As you pointed out, Vec<String> will solve your issue because String Is an owned value, where &str is a borrowed one, and you are attempting to borrow from a String (k) that has a shorter lifetime than y.
Related
I'm wondering if someone can help me understand why this program behaves as it does:
fn main() {
let mut x = 456;
{
let mut y = Box::new(&x);
y = Box::new(&mut y);
println!("GOT {}",*y);
}
}
This program compiles under rust 1.35.0 (both 2015 and 2018 editions), and prints
GOT 456
But, I'm confused what's going on here. I'm guessing that this is an example of an auto-dereference. So, in reality, it looks like this:
fn main() {
let mut x = 456;
{
let mut y = Box::new(&x);
y = Box::new(&mut *y);
println!("GOT {}",*y);
}
}
Is that it?
This is a case of deref coercion, but one that is obfuscated by a few other unnecessary parts of the code. The following improvements should be made here:
The mut modifier on variable x is not needed because it is never modified.
The borrow of y in Box::new(&mut y) does not have to be mutable because the variable holds an immutable reference.
The println! implementation also knows to print values behind references, so the explicit * is not needed.
Then, we get the following code:
fn main() {
let x = 456;
{
let mut y = Box::new(&x);
y = Box::new(&y);
println!("GOT {}", y);
}
}
y is a variable of type Box<&i32> which is initially bound to a box created in the outer scope. The subsequent assignment to a new box works because the &y, of type &Box<&i32>, is coerced to &&i32, which can then be put in the box by automatically dereferencing the first borrow. This coercion is required because the variable x can only be assigned values of the same Box<&i32> type.
The lifetime of the reference inside both boxes also ended up being the same, because they refer to the same value in x.
See also:
What is the relation between auto-dereferencing and deref coercion?
I'm trying to understand how & and ref correspond. Here's an example where I thought these were equivalent, but one works and the other doesn't:
fn main() {
let t = "
aoeu
aoeu
aoeu
a";
let ls = t.lines();
dbg!(ls.clone().map(|l| &l[..]).collect::<Vec<&str>>().join("\n")); // works
dbg!(ls.clone().map(|ref l| l[..]).collect::<Vec<&str>>().join("\n")); // doesn't work
dbg!(ls.clone().map(|ref l| &l[..]).collect::<Vec<&str>>().join("\n")); // works again!
}
From the docs:
// A `ref` borrow on the left side of an assignment is equivalent to
// an `&` borrow on the right side.
let ref ref_c1 = c;
let ref_c2 = &c;
println!("ref_c1 equals ref_c2: {}", *ref_c1 == *ref_c2);
What would the equivalent to |l| &l[..] be with |ref l|? How does it correspond to the assignment examples in the docs?
Taking a look at the docs page for Lines(The iterator adapter for producing lines from a str), we can see that the item produced by it is:
type Item = &'a str;
Therefore the following happens when trying to do the "doesn't work" version:
dbg!(ls.clone().map(|ref l| l[..]).collect::<Vec<&str>>().join("\n")); # doesn't work
//Can become:
let temp = ls
.clone()
.map(|ref l| l[..])
.collect::<Vec<&str>>()
.join("\n");
println!("{}", temp);
Here we can see a crucial problem. l if of type &&str (Which I will explain below) so indexing into it will create a str, which is unsized and therefore cannot be outside of a pointer of some sort.
Now, onto the real thing you wanted to learn: What a ref pattern does:
When doing pattern matching or destructuring via the let binding, the ref keyword can be used to take references to the fields of a struct/tuple.
What this does is the following:
When we have let ref x = y, we take a reference to y.
When pattern matching on something (Like in your closure arguments you showed) we have a slightly different effect: the value under the reference is moved into the scope and then taken reference to while exposing a way to take the value under the reference. For example:
fn foo(ref x: String) {}
let y: fn(String) = foo;
This works because what is essentially being done is this:
fn foo(x: String) {
let x: &String = &x;
}
So what ref x does is take ownership of x and produce a reference to it.
On the other hand
When we have let &x = y we move a value out of y.
This is the opposite of ref, in that we take ownership of the value under y if we can. For example:
let x = 2;
let y = &x;
let &z = y; //Ok, we're moving a `Copy` type
This is only ok for copy types though as though this isn't exactly the same as let x = *y which would work for owned Boxes.
I have the following code:
fn main() {
let mut vec = Vec::new();
vec.push(String::from("Foo"));
let mut row = vec.get_mut(0).unwrap();
row.push('!');
println!("{}", vec[0])
}
It prints out "Foo!", but the compiler tells me:
warning: variable does not need to be mutable
--> src/main.rs:4:9
|
4 | let mut row = vec.get_mut(0).unwrap();
| ----^^^
| |
| help: remove this `mut`
Surprisingly, removing the mut works. This raises a few questions:
Why does this work?
Why doesn't this work when I use vec.get instead of vec.get_mut, regardless of whether I use let or let mut?
Why doesn't vec work in the same way, i.e. when I use let vec = Vec::new(), why can't I call vec.push()?
vec.get_mut(0) returns an Option<&mut String>, so when you unwrap that value you will have a mutable borrow of a String. Remember, that a let statement's left side is using pattern matching, so when your pattern is just a variable name you essentially say match whatever is on the right and call it name. Thus row matches against &mut String so it already is mutable.
Here's a much simpler and more straightforward example to illustrate the case (which you can try in the playground):
fn main() {
let mut x = 55i32;
dbg!(&x);
let y = &mut x; // <-- y's type is `&mut i32`
*y = 12;
dbg!(&x);
}
How could know the type of a binding if I use auto type deduction when creating a binding? what if the expression on the right side is a borrow(like let x = &5;), will it be value or a borrow? What will happen if I re-assign a borrow or a value?
Just for check, I do can re-assign a borrow if I use let mut x: &mut T = &mut T{}; or let mut x:&T = & T{};, right?
I sense some confusion between binding and assigning:
Binding introduces a new variable, and associates it to a value,
Assigning overwrites a value with another.
This can be illustrated in two simple lines:
let mut x = 5; // Binding
x = 10; // Assigning
A binding may appear in multiple places in Rust:
let statements,
if let/while let conditions,
cases in a match expression,
and even in a for expression, on the left side of in.
Whenever there is a binding, Rust's grammar also allows pattern matching:
in the case of let statements and for expressions, the patterns must be irrefutable,
in the case of if let, while let and match cases, the patterns may fail to match.
Pattern matching means that the type of the variable introduced by the binding differs based on how the binding is made:
let x = &5; // x: &i32
let &y = &5; // y: i32
Assigning always requires using =, the assignment operator.
When assigning, the former value is overwritten, and drop is called on it if it implements Drop.
let mut x = 5;
x = 6;
// Now x == 6, drop was not called because it's a i32.
let mut s = String::from("Hello, World!");
s = String::from("Hello, 神秘德里克!");
// Now s == "Hello, 神秘德里克!", drop was called because it's a String.
The value that is overwritten may be as simple as an integer or float, a more involved struct or enum, or a reference.
let mut r = &5;
r = &6;
// Now r points to 6, drop was not called as it's a reference.
Overwriting a reference does not overwrite the value pointed to by the reference, but the reference itself. The original value still lives on, and will be dropped when it's ready.
To overwrite the pointed to value, one needs to use *, the dereference operator:
let mut x = 5;
let r = &mut x;
*r = 6;
// r still points to x, and now x = 6.
If the type of the dereferenced value requires it, drop will be called:
let mut s = String::from("Hello, World!");
let r = &mut s;
*r = String::from("Hello, 神秘德里克!");
// r still points to s, and now s = "Hello, 神秘德里克!".
I invite you to use to playground to and toy around, you can start from here:
fn main() {
let mut s = String::from("Hello, World!");
{
let r = &mut s;
*r = String::from("Hello, 神秘德里克!");
}
println!("{}", s);
}
Hopefully, things should be a little clearer now, so let's check your samples.
let x = &5;
x is a reference to i32 (&i32). What happens is that the compiler will introduce a temporary in which 5 is stored, and then borrow this temporary.
let mut x: &mut T = T{};
Is impossible. The type of T{} is T not &mut T, so this fails to compile. You could change it to let mut x: &mut T = &mut T{};.
And your last example is similar.
I would like to use the Scan iterator to construct a vector in a declarative fashion. It is clear how to achieve this by copying the intermediate state. The following expression compiles and produced the desired series:
let vec = (0..10).scan(0, |state, current| {
*state = *state + current;
Some(*state)
}).collect::<Vec<_>>();
However, if I try to achieve the same behavior by moving the state instead of copying it, I get in trouble with lifetimes. For example, when working with vectors instead of integers, one cannot move the state out of the closure and reuse it in the next iteration. The expression
let vec = (0..10).map(|x| vec![x]).scan(vec![0], |state, current| {
*state = vec![state[0] + current[0]];
Some(*state)
}).collect::<Vec<_>>();
fails to compile due to
error: cannot move out of borrowed content [E0507]
Some(*state)
^~~~~~
see for example this MVCE.
Borrowing the state instead of moving would also be an option:
let start = &vec![0];
let vec = (0..10).map(|x| vec![x]).scan(start, |state, current| {
*state = &vec![state[0] + current[0]];
Some(*state)
}).collect::<Vec<_>>();
but this fails because the new value falls out of scope when the state is returned.
error: borrowed value does not live long enough
*state = &vec![state[0] + current[0]]
What I ended up doing is using the for loop
let xs = &mut Vec::<Vec<i32>>::with_capacity(10);
xs.push[vec!(0)];
for x in 1..10 {
let z = vec![xs.last().unwrap()[0] + x];
xs.push(z);
};
but I wold prefer a chaining solution.
Let's check the definition of scan:
fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F>
where F: FnMut(&mut St, Self::Item) -> Option<B>
Note that B is distinct from St. The idea of scan is that:
you keep an accumulator of type St
at each iteration, you produce a value of type B
and indeed it is not quite suited to returning values of type St because you are only borrowing St and do not control its lifetime.
scan is made for you to return a brand new value each time:
let xs = (0..10).scan(0, |state, current| {
*state += current;
Some(NonCopy::new(*state))
}).collect::<Vec<_>>();
and that's it!
A note on efficiency.
The state of scan is a sunk cost so it is best to use a cheap state (a single integer here).
If you need a larger type X and wish to "get your memory back", then you can pass an &mut Option<X> and then use .take() after the scan:
let mut x = Some(NonCopy::new(0));
let xs = (0..10).scan(&mut x, |state, current| {
let i: &mut i32 = &mut state.as_mut().unwrap().value;
*i += current;
Some(NonCopy::new(*i))
}).collect::<Vec<_>>();
let _ = x.take();
It's not as elegant, of course.
I don't think it is possible to do it without cloning value using scan method.
When you return a non-Copy value from the closure, you lose ownership of that value. And it's not possible to keep any reference to it, because it's new owner could move the value in memory anywhere it wants (for example, during vector resizing), and Rust is intended to protect against this kind of errors.
By chaining solution, do you mean this?
let vec = (0..10)
.fold((Vec::with_capacity(10), 0), |(mut vec, previous), x| {
vec.push(vec![previous + x]);
(vec, previous + x)
})
.0;