Vectors borrowing and ownership [duplicate] - rust

This question already has answers here:
What does it mean to pass in a vector into a `for` loop versus a reference to a vector?
(1 answer)
How can I solve "use of moved value" and "which does not implement the `Copy` trait"?
(1 answer)
What do I have to do to solve a "use of moved value" error?
(3 answers)
What does "cannot move out of index of" mean?
(2 answers)
Closed 2 years ago.
This doesn't work:
let vectors = vec![1, 2, 3, 4, 5, 6, 7];
for i in vectors {
println!("Element is {}", i);
}
let largest = vectors[0];
Error message:
error[E0382]: borrow of moved value: `vectors`
--> src/main.rs:8:19
|
2 | let vectors = vec![1, 2, 3, 4, 5, 6, 7];
| ------- move occurs because `vectors` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
3 |
4 | for i in vectors {
| -------
| |
| value moved here
| help: consider borrowing to avoid moving into the for loop: `&vectors`
...
8 | let largest = vectors[0];
| ^^^^^^^ value borrowed here after move
The vector has been moved into the loop. Its ownership — and that of its individual elements — has been transferred there permanently.
But this works:
let largest = vectors[0];
let largest2 = vectors[0];
I don't know why; the vectors[0] value should have been moved to largest and largest2 should then fail, but it didn't.

When you use vectors inside a for..in loop, Rust will call the IntoIterator::into_iter trait method of the Vec, which takes ownership of self. Therefore you cannot use vectors afterwards.
use std::iter::IntoIterator;
// these are equivalent
for i in vectors { /* ... */ }
for i in IntoIterator::into_iter(vectors) { /* ... */ }
The index operator, on the other hands, calls the Index::index trait method of the Vec, which takes self by reference. Additionally, it automatically dereferences the value, so that if the items inside the vector implement Copy, they will be copied out of the vector instead of borrowed (you need to explicitly borrow if you want a reference):
use std::ops::Index;
// these are equivalent
let x = vectors[0];
let x = *Index::index(&vectors, 0);
// these are equivalent
let x = &vectors[0];
let x = Index::index(&vectors, 0);

The type of the values (probably i32) in your Vec implement the Copy trait, which means that they do not get moved out when indexing the vector, they get copied instead.
A Vec of such Copy types still doesn't implement Copy itself, so it gets moved into the loop. You can avoid this e.g. by writing
for i in vectors.iter() {
println!("Element is {}", *i);
}
The dereference (*) gives you an owned value like you'd get in your original code sample. It isn't necessary for println!, but might be necessary for other uses.

Related

How to initialize [Option<Box<T>>; N] with None? [duplicate]

This question already has answers here:
Initialize a large, fixed-size array with non-Copy types
(8 answers)
Closed 1 year ago.
I now why the error below happens, you cannot copy a Box, because it's a "unique_ptr".
fn main() {
let array: [Option<Box<u32>>; 3] = [None; 3];
}
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=0da6902c0157df3015bc85a621079e18
I know I could do [None, None, None], but what about giant arrays? Is there a way to initialize them with None?
error[E0277]: the trait bound `Option<Box<u32>>: Copy` is not satisfied
--> src/main.rs:2:40
|
2 | let array: [Option<Box<u32>>; 3] = [None; 3];
| ^^^^^^^^^ the trait `Copy` is not implemented for `Option<Box<u32>>`
|
= help: the following implementations were found:
<Option<T> as Copy>
= note: the `Copy` trait is required because the repeated element will be copied
For arrays with a size not greater than 32 you could use:
let array: [Option<Box<u32>>; 32] = Default::default();
For even bigger arrays I would recommend using a crate like this or creating a simple macro.
I recommend reading this article: https://www.joshmcguigan.com/blog/array-initialization-rust/

Why is iterating over a collection via `for` loop considered a "move" in Rust?

I have the below Rust program.
fn main() {
let v = vec![100, 32, 57];
for i in v {
println!("{}", i);
}
println!("{:?}", v);
}
When I run it, I get:
error[E0382]: borrow of moved value: `v`
--> src\main.rs:7:22
|
2 | let v = vec![100, 32, 57];
| - move occurs because `v` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
3 | for i in v {
| -
| |
| value moved here
| help: consider borrowing to avoid moving into the for loop: `&v`
...
7 | println!("{:?}", v);
| ^ value borrowed here after move
The error states that there is a move happened at for i in v. But I'm just using the same variable v defined by let v = vec![100, 32, 57]. It's not something like let v2 = v; for i in v2 ..., which moved the value from v to v2. Could anyone help to explain a little bit?
As https://doc.rust-lang.org/reference/expressions/loop-expr.html#iterator-loops says,
A for expression is a syntactic construct for looping over elements provided by an implementation of std::iter::IntoIterator.
Vec implements IntoIterator, allowing you to own a Vec instance’s elements by consuming it:
Creates a consuming iterator, that is, one that moves each value out of the vector (from start to end). The vector cannot be used after calling this.
(As the error message notes, the way to fix this is to loop over &v instead of v, borrowing its elements instead of owning them. You can loop for &i in &v to maintain the type of i.)
It might seem unnecessary at a high level for you to own the elements of v, since they’re copyable, but there’s no special implementation allowing that information to be used here. IntoIterator.into_iter() takes self, meaning a for loop always consumes the value being iterated over.

Get value from map and modify map in same scope [duplicate]

This question already has answers here:
How can I borrow from a HashMap to read and write at the same time?
(2 answers)
Returning a reference from a HashMap or Vec causes a borrow to last beyond the scope it's in?
(1 answer)
Cannot borrow as mutable because it is also borrowed as immutable
(3 answers)
cannot borrow variable as mutable because it is also borrowed as immutable while building a self-referential HashMap
(1 answer)
Cannot borrow immutable borrowed content as mutable
(1 answer)
Closed 3 years ago.
Here is a simple program which looks up previous value in map and puts a new value into it. It won't compile as the first lookup immutably borrows map and insert wants to mutably borrow map.
use std::collections::HashMap;
fn main() {
let mut map: HashMap<i32, i32> = HashMap::new();
map.insert(0, 0);
(1..5).for_each(|x| {
let prev = map.get(&(x - 1)).unwrap();
map.insert(x, (prev + 1) * 10);
});
map.iter().for_each(|(k, v)| println!("{} -> {}", k, v));
}
The problem can be solved by using clone() on to get prev as
let prev = map.get(&(x - 1)).unwrap().clone();
and get the output as:
0 -> 0
1 -> 10
2 -> 110
3 -> 1110
4 -> 11110
What can I do to not use clone() here?
HashMap::get() returns Option<&V>, which you unwrap, getting &V, so you end up with prev being an immutable reference that points inside map. That's why you have an immutable borrow of map. The type of prev is &i32.
To solve your problem, you can dereference that reference:
let prev = *map.get(&(x - 1)).unwrap();
In this case, the type of prev is i32, and it is just a value on the stack. It does not point inside map => you don't borrow map immutably so you can borrow map mutably in the next line.
Your original code works just fine if you enable Rust 2018 edition, because of non-lexical lifetimes support.
Note that HashMap is not sorted, so the output lines are produced in arbitrary order. If you need sorting, you can consider using BTreeMap.
If you don't want to use either Copy (via *) or Clone at all, and don't want to switch to Rust 2018, you can do the following:
let value_to_insert = {
let prev = map.get(&(x - 1)).unwrap();
(prev + 1) * 10
}
map.insert(x, value_to_insert)
This is pretty much the same thing non-lexical lifetimes would do for you automatically in Rust 2018.

How to mutate a vector's elements while iterating through it? [duplicate]

This question already has answers here:
Efficiently mutate a vector while also iterating over the same vector
(2 answers)
Closed 4 years ago.
I'm iterating through a vector and I want to change one of the elements.
fn main() {
let mut vector = vec![1, 2, 3, 4];
for (i, el) in vector.iter().enumerate() {
if i == 0 {
continue;
}
vector[i - 1] += el
}
}
This gives me the compiler error:
error[E0502]: cannot borrow `vector` as mutable because it is also borrowed as immutable
--> src/main.rs:8:9
|
4 | for (i, el) in vector.iter().enumerate() {
| ------ immutable borrow occurs here
...
8 | vector[i - 1] += el
| ^^^^^^ mutable borrow occurs here
9 | }
| - immutable borrow ends here
I understand why this error occurs. I am borrowing vector as immutable for the lifetime of the enumeration scope and then trying to mutate the interior inside that scope thus breaking the borrowing rules. I just don't understand how to do this properly. I guess I need to borrow mutably for the enumeration?
I've tried various combinations of mut, &mut and I run into different compiler errors with each. I know I could make this a Vec<Cell<i32>> and mutate the contents that way, but this seems overkill for such a simple example.
Use indexing.
fn main() {
let mut vector = vec![1, 2, 3, 4];
for i in 1..vector.len() {
vector[i - 1] += vector[i];
}
println!("{:?}", vector);
}

How to fix an error with borrowing peekable iterator twice in Rust?

TLDR
How to make the following code compile?
let mut iter = (1..3).peekable();
let h = iter.peek();
iter.next();
Update: I read How to use Rust's Peekable?, that is a different question because
I don't even have a function here
I don't have move out of dereference of error here
Long Story With Background
I'm trying to implement merging of two sorted "streams": I have two iterators both of which produce ordered values, and I need to print values of both of them, also ordered.
For example,
(1, 2, 20)
(3, 4, 5, 7)
should produce
(1, 2, 3, 4, 5, 7, 20)
The algorithm is simple I compare heads, then print the smaller head and advance the corresponding iterator.
The problem is that I can't wrap my head around lifetimes.
I have some initial implementation which isn't compiling. In order to make my question simpler to answer, I reduced my original implementation to the smallest possible example which fails with the same error as the original.
let mut iter = (1..3).peekable();
let h = iter.peek();
iter.next();
The error is
error[E0499]: cannot borrow `iter` as mutable more than once at a time
--> src/main.rs:47:9
|
44 | let h = iter.peek();
| ---- first mutable borrow occurs here
...
47 | iter.next();
| ^^^^ second mutable borrow occurs here
...
114 | }
| - first borrow ends here
How to fix this error?
I tried to do different things: adding mut, &, .by_ref() everywhere, but obviously, it didn't work because I have no idea what I'm doing.
The Option::cloned(&self) method turns an Option<&T> into a Option<T>, given that T:Clone. It gets rid of the reference by making a copy of the value.
let mut iter = (1..3).peekable();
let h = iter.peek().cloned();
iter.next();

Resources