rust: cannot move out of indexed context [duplicate] - rust

This question already has answers here:
What does "cannot move out of index of" mean?
(2 answers)
Closed 6 years ago.
I'm very new to rust, and am starting to get the hang of the ownership system and such, but am still having some hangups. For exmaple, I have the following code:
fn main() {
let mut t = vec![Box::new(4)];
let mut o = t[0];
*o = *o + 1;
t[0] = o;
println!("t[0]:{}", t[0]);
}
Which gives me the cannot move out of indexed content error for the line where I'm initializing o. I understand why this is happening, I think, but I can't figure out what I'm supposed to do instead to accomplish the same thing. This is a very simplified case, but any help would be greatly appreciated. Thanks!

The expression t[0] is equivalent to either *t.index(0) or *t.index_mut(0), based on context. These methods return an immutable reference and a mutable reference, respectively. The indexing operator automatically dereferences these.
Since you have a vector of Box<i32>, dereferencing is not valid, because that would try to move the value from the vector. But then, what do you put in the vector in its place?
Instead of trying to move the value, you need to use a reference to the value instead. Also, if you want to be able to add 1 to the value, you need a reference to the value, not a reference to the Box. You can do this by first dereferencing the box, then by taking a mutable reference to the result:
fn main() {
let mut t = vec![Box::new(4)];
{
let o = &mut *t[0];
*o = *o + 1;
}
println!("t[0]:{}", &t[0]);
}
I had to add a block here to make the mutable borrow end before the println!, otherwise the compiler complained with:
error: cannot borrow `t` as immutable because it is also borrowed as mutable
Also, notice how we don't need to put the updated value back in the vector, because we changed the value in the vector directly by using a reference to it.

Related

Rust `value borrowed here after move` when setting to Map

I want to put an object in a serde_json::Map where the key will be a value from inside that object.
use serde_json::{json, Map, Value};
fn main() {
let a = json!({
"x": "y"
});
let mut d: Map<String, Value> = Map::new();
d[&a["x"].to_string()] = a;
}
Error:
borrow of moved value: `a`
value borrowed here after moverustcE0382
main.rs(9, 30): value moved here
main.rs(4, 9): move occurs because `a` has type `Value`, which does not implement the `Copy` trait
Even if you solve this lifetime issue, the IndexMut implementation for Map cannot be used for inserting new elements into a map. It panics if the given key is not present.
Use the insert() method instead, which solves both problems:
d.insert(a["x"].to_string(), a);
Since the proper solution has already been answered, I am going to cover another perspective on this,
d[&a["x"].to_string()] = a;
Even if the mentioned bit panics when there is no entry against the passed index, what it is really saying is that, get me the value at index x and replace it with a, = is invoking Copy here, since a doesn't doesn't implement Copy trait the compiler is giving you error.
In the following case, a is simply moved, so no Copy is invoked.
d.insert(a["x"].to_string(), a);
Also, the equivalent in your case may be get or insert.
let entry = d.entry(a["x"].to_string()).or_insert(a);
To access the value from entry you just deref it as *entry

Immutable access in rust

I am new to rust from python and have used the functional style in python extensively.
What I am trying to do is to take in a string (slice) (or any iterable) and iterate with a reference to the current index and the next index. Here is my attempt:
fn main() {
// intentionally immutable, this should not change
let x = "this is a
multiline string
with more
then 3 lines.";
// initialize multiple (mutable) iterators over the slice
let mut lineiter = x.chars();
let mut afteriter = x.chars();
// to have some reason to do this
afteriter.skip(1);
// zip them together, comparing the current line with the next line
let mut zipped = lineiter.zip(afteriter);
for (char1, char2) in zipped {
println!("{:?} {:?}", char1, char2);
}
}
I think it should be possible to get different iterators that have different positions in the slice but are referring to the same parts of memory without having to copy the string, but the error I get is as follows:
error[E0382]: use of moved value: `afteriter`
--> /home/alex/Documents/projects/simple-game-solver/src/src.rs:15:35
|
10 | let afteriter = x.chars();
| --------- move occurs because `afteriter` has type `std::str::Chars<'_>`, which does not implement the `Copy` trait
11 | // to have some reason to do this
12 | afteriter.skip(1);
| --------- value moved here
...
15 | let mut zipped = lineiter.zip(afteriter);
| ^^^^^^^^^ value used here after move
I also get a warning telling me that zipped does not need to be mutable.
Is it possible to instantiate multiple iterators over a single variable and if so how can it be done?
Is it possible to instantiate multiple iterators over a single variable and if so how can it be done?
If you check the signature and documentation for Iterator::skip:
fn skip(self, n: usize) -> Skip<Self>
Creates an iterator that skips the first n elements.
After they have been consumed, the rest of the elements are yielded. Rather than overriding this method directly, instead override the nth method.
You can see that it takes self by value (consumes the input iterator) and returns a new iterator. This is not a method which consumes the first n elements of the iterator in-place, it's one which converts the existing iterator into one which skips the first n elements.
So instead of:
let mut afteriter = x.chars();
afteriter.skip(1);
you just write:
let mut afteriter = x.chars().skip(1);
I also get a warning telling me that zipped does not need to be mutable.
That's because Rust for loop uses the IntoIterator trait, which moves the iterable into the loop. It's not creating a mutable reference, it's just consuming whatever the RHS is.
Therefore it doesn't care what the mutability of the variable. You do need mut if you iterate explicitly, or if you call some other "terminal" method (e.g. nth or try_fold or all), or if you want to iterate on the mutable reference (that's mostly useful for collections though), but not to hand off iterators to some other combinator method, or to a for loop.
A for loop takes self, if you will. Just as for_each does in fact.
Thanks to #Stargateur for giving me the solution. The .skip(1) takes ownership of afteriter and returns ownership to a version without the first element. What was happening before was ownership was lost on the .skip and so the variable could not be mutated anymore (I am pretty sure)

Iterating through a Vec within a struct - cannot move out of borrowed content

I am writing a function for a struct which contains a Vec where I attempt to iterate through the Vec:
struct Object {
pub v: Vec<f32>,
}
impl Object {
pub fn sum(&self) -> f32 {
let mut sum = 0.0;
for e in self.v {
sum += e;
}
sum
}
}
However I get the following error:
error[E0507]: cannot move out of borrowed content
--> src/lib.rs:8:18
|
8 | for e in self.v {
| ^^^^ cannot move out of borrowed content
My understanding is that since self is borrowed and that the for loop iteration is attempting to move the elements of v out into e.
From the error code, I read that a potential solution is to take ownership but I'm not quite certain how to do that.
I'm not trying to modify the vector or its elements. I just want to use the elements to run some computation.
The line: for e in self.v is essentially saying for e in (*self).v; you're attempting to iterate over the vector by move, invoking its IntoIterator trait. This would destroy the vector completely, moving all the numbers out of it forever, which is not only not what you want, but also not allowed in this context because you're only allowed to read it.
You actually want to iterate over it by reference. There are two ways to do this:
for e in &self.v {
// ...
}
This is essentially saying &((*self).v), since the . auto-dereferences you need to tell the compiler that you actually just want to borrow the vector.
or
for e in self.v.iter() {
// ...
}
This may look funny because iter takes an &self. Why? Well, the compiler also auto-references if you call a function on a value that takes a reference. This is essentially (&((*self).v)).iter(), but that would suck to write so the compiler helps out.
So why doesn't it auto-reference in the for loop? Well, for x in self.v is a valid statement, and that may be what you intended to write. It's usually more important for the compiler to tell you that what you want want is impossible than assume you wanted something else. With the auto (de-)referencing above, no such ambiguity exists.
The former solution is preferred, but the latter is necessary if you want to use an iterator adapter.
Speaking of which, your sum already exists: just write self.v.iter().sum().

What is difference between `mut a: &T` and `a: &mut T`? [duplicate]

This question already has answers here:
What's the difference between placing "mut" before a variable name and after the ":"?
(4 answers)
Closed 7 years ago.
Could someone explain what is the difference between these two and when is mut a: &T most often used?
Function parameters and let bindings in Rust are proper patterns, like those at the left of => in match (except that let and parameter patterns must be irrefutable, that is, they must always match). mut a is just a part of pattern syntax and it means that a is a mutable binding. &mut T/&T, on the other hand, is a type - mutable or immutable reference.
There are four possible combinations of mut in references and patterns:
a: &T // immutable binding of immutable reference
mut a: &T // mutable binding of immutable reference
a: &mut T // immutable binding of mutable reference
mut a: &mut T // mutable binding of mutable reference
The first variant is absolutely immutable (without taking internal mutability of Cell and such into account) - you can neither change what a points to nor the object it currently references.
The second variant allows you to change a to point somewhere else but it doesn't allow you to change the object it points to.
The third variant does not allow to change a to point to something else but it allows mutating the value it references.
And the last variant allows both changing a to reference something else and mutating the value this reference is currently pointing at.
Taking the above into account you can see where mut a: &T can be used. For example, you can write a search of a part of a string in a loop for the further usage like this:
let mut s: &str = source;
loop {
// ... whatever
s = &source[i..j];
}
// use the found s here

Why does the compiler tell me to consider using a `let` binding" when I already am?

What is my error and how to fix it?
fn get_m() -> Vec<i8> {
vec![1, 2, 3]
}
fn main() {
let mut vals = get_m().iter().peekable();
println!("Saw a {:?}", vals.peek());
}
(playground)
The compiler's error suggests "consider using a let binding" — but I already am:
error[E0597]: borrowed value does not live long enough
--> src/main.rs:6:45
|
6 | let mut vals = get_m().iter().peekable();
| ------- ^ temporary value dropped here while still borrowed
| |
| temporary value created here
7 | println!("Saw a {:?}", vals.peek());
8 | }
| - temporary value needs to live until here
|
= note: consider using a `let` binding to increase its lifetime
This is obviously a newbie question -- though I thought I'd written enough Rust at this point that I had a handle on the borrow checker... apparently I haven't.
This question is similar to Using a `let` binding to increase value lifetime, but doesn't involve breaking down an expression into multiple statements, so I don't think the problem is identical.
The problem is that the Peekable iterator lives to the end of the function, but it holds a reference to the vector returned by get_m, which only lasts as long as the statement containing that call.
There are actually a lot of things going on here, so let's take it step by step:
get_m allocates and returns a vector, of type Vec<i8>.
We make the call .iter(). Surprisingly, Vec<i8> has no iter method, nor does it implement any trait that has one. So there are three sub-steps here:
Any method call checks whether its self value implements the Deref trait, and applies it if necessary. Vec<i8> does implement Deref, so we implicitly call its deref method. However, deref takes its self argument by reference, which means that get_m() is now an rvalue appearing in an lvalue context. In this situation, Rust creates a temporary to hold the value, and passes a reference to that. (Keep an eye on this temporary!)
We call deref, yielding a slice of type &[i8] borrowing the vector's elements.
This slice implements the SliceExt trait, which does have an iter method. Finally! This iter also takes its self argument by reference, and returns a std::slice::Iter holding a reference to the slice.
We make the call .peekable(). As before, std::slice::Iter has no peekable method, but it does implement Iterator; IteratorExt is implemented for every Iterator; and IteratorExt does have a peekable method. This takes its self by value, so the Iter is consumed, and we get a std::iter::Peekable back in return, again holding a reference to the slice.
This Peekable is then bound to the variable vals, which lives to the end of the function.
The temporary holding the original Vec<i8>, to whose elements the Peekable refers, now dies. Oops. This is the borrowed value not living long enough.
But the temporary dies there only because that's the rule for temporaries. If we give it a name, then it lasts as long as its name is in scope:
let vec = get_m();
let mut peekable = vec.iter().peekable();
println!("Saw a {:?}", vals.peek());
I think that's the story. What still confuses me, though, is why that temporary doesn't live longer, even without a name. The Rust reference says, "A temporary's lifetime equals the largest lifetime of any reference that points to it." But that's clearly not the case here.
This is happening because you are trying to run your .iter().peekable() on the actual vector inside of get_m(), which is getting re-referenced by vals.
Basically, you want something like this:
fn get_m() -> Vec<i8> {
vec![1, 2, 3]
}
fn main() {
let vals = get_m();
let mut val = vals.iter().peekable();
println!("Saw a {:?}", val.peek());
}
(Playground)
Result:
Saw a Some(1)

Resources