Reputation: 48068
Accessing a slice is straightforward using slice syntax: slice = vector[i..j]
In the case where the range is stored however, from what I can tell you can't do:
struct StructWithRange {
range: std::ops::Range<usize>,
}
fn test_slice(s: &StructWithRange, vector: &Vec<i32>) {
let slice = &vector[s.range];
println!("{:?}", slice); // prints [2, 3]
}
fn main() {
let vector = vec![1,2,3,4,5];
let s = StructWithRange {
range: 1..3
};
test_slice(&s, &vector);
}
This gives the error:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:6:25
|
6 | let slice = &vector[s.range];
| ^ cannot move out of borrowed content
Is there a way to get the slice from a range without expanding it?
eg: vector[s.range.start..s.range.end]
If a usize
in a struct can be used for an index lookup, why can't a Range<usize>
be used in the same way?
Upvotes: 3
Views: 899
Reputation: 22203
Since Index
is a trait requiring the following function:
fn index(&self, index: Idx) -> &Self::Output
It consumes/moves the value used for indexing (index
). In your case you are attempting to index the slice using a Range
from a borrowed struct, but since you are only passing a reference and the range doesn't implement Copy
, this fails.
You can fix it by e.g. changing the definition of test_slice
to consume StructWithRange
or clone()
ing the s.range
in the index.
Upvotes: 5
Reputation: 299950
The error message occurs because Range
does not implement Copy
and Index
consumes its index.
It can be solved by adding a call to .clone()
: &vector[s.range.clone()]
.
If you check the code, it links to the rejected proposal to add Copy
to Range
in the case where its parameter is Copy
here.
The rejection reason is:
These don't have it because they're iterators.
The choice of removing Copy impls instead of adjusted for loop desugaring or linting was made to prevent this problematic case:
let mut iter = 0..n; for i in iter { if i > 2 { break; } } iter.collect()
Here iter is actually not mutated, but copied.
for i in &mut iter
is required to mutate the iterator.We could switch to linting against using an iterator variable after it was copied by a for loop, but there was no decision towards that.
Upvotes: 4