0

The following code won't compile:

#[derive(Debug)]
struct Foo {
    x: i32,
}

pub fn main() {
    let a = vec![Foo { x: 1 }, Foo { x: 2 }];
    match a.get(0) {
        Some(&x) => println!("ref {:?}", x),
        None => {}
    }
}

Throws this error:

error[E0507]: cannot move out of a shared reference
 --> src/main.rs:8:11
  |
8 |     match a.get(0) {
  |           ^^^^^^^^
9 |         Some(&x) => println!("ref {:?}", x),
  |               -
  |               |
  |               data moved here
  |               move occurs because `x` has type `Foo`, which does not implement the `Copy` trait

I thought std::Vec<T>::get returns Some(&T) on success. Doesn't that mean an ampersand should be used in pattern matching?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
ji chengde
  • 81
  • 4

1 Answers1

3

I thought std::Vec<T>::get returns Some(&T) on success

Yes, you get an Option over a reference. Said otherwise, x, in Some(x) is a reference over the Foo instance.

But you do want a reference: the only way to print the element without removing it from the vector is to pass a reference to println, not the element itself. That's why

Some(x) => println!("ref {:?}", x),

is the right way.

When you do

Some(&x) => println!("ref {:?}", x),

on the other way, as &x is the reference over the Foo instance, x is the Foo instance, and thus you'd be moving it out of the vector when matching, which you can't do with a shared reference you got with get (and something you certainly don't want to do anyway).

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758