10

Consider the following snippet:

fn example(current_items: Vec<usize>, mut all_items: Vec<i32>) {
    for i in current_items.iter() {
        let mut result = all_items.get_mut(i);
    }
}

The compiler is complaining about i being &mut usize instead of usize:

error[E0277]: the trait bound `&usize: std::slice::SliceIndex<[()]>` is not satisfied
 --> src/lib.rs:3:36
  |
3 |         let mut result = all_items.get_mut(i);
  |                                    ^^^^^^^ slice indices are of type `usize` or ranges of `usize`
  |
  = help: the trait `std::slice::SliceIndex<[()]>` is not implemented for `&usize`

I've dug through the docs but the only way I see to satisfy the compiler is i.clone().

I'm definitely missing something obvious here. What's the idiomatic way to copy from primitive type reference by value?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Jacob Wang
  • 4,411
  • 5
  • 29
  • 43

3 Answers3

15

iter() on Vec<T> returns an iterator implementing Iterator<&T>, that is, this iterator will yield references into the vector. This is the most general behavior which allows convenient usage with non-copyable types.

However, primitive types (actually, any types which implement Copy trait) will be copied upon dereference anyway, so you just need this:

for i in current_items.iter() {
    let mut result = all_items.get_mut(*i);
}

Alternatively, you can use reference destructuring pattern:

for &i in current_items.iter() {
    let mut result = all_items.get_mut(i);
}

Now i is usize automatically and you don't need to dereference it manually.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Vladimir Matveev
  • 120,085
  • 34
  • 287
  • 296
  • Now, I swear I did that following all the docs I've read before, and compiler was complaining about unable to dereference `i` and now it compiles... well I must've missed something. Thanks! – Jacob Wang Sep 05 '14 at 12:20
13

What's the idiomatic way to copy from primitive type reference by value?

You need to use * to dereference a reference.

let my_usize: usize = 5;
let ref_to_my_usize: &usize = &my_usize;
let copy_of_my_usize: usize = *ref_to_my_usize;

You can also dereference directly in your loop:

for &x in myvec.iter() {
//  ^-- note the &
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Levans
  • 14,196
  • 3
  • 49
  • 53
  • Though somehow it didn't compile before (hence this question), but I did learn something new regarding the `&x` destructuring. Thanks! – Jacob Wang Sep 05 '14 at 12:21
2

Don't use iter if you need an &mut reference. Use iter_mut instead.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Steve Klabnik
  • 14,521
  • 4
  • 58
  • 99
  • 1
    I do apologize for my terrible snippet. In this case `current_items` contains the indices to items in `all_items`, so I'm using immutable reference (&uint) to access a mutable reference. – Jacob Wang Sep 05 '14 at 12:10