Reputation: 972
I'm new to Rust and I find some behavior in Rust is not intuitive
say we have the code below:
struct User {
name: String,
email:String
}
fn main() {
let some_vec = vec![String::from("value1"),String::from("value2")];
let _v = some_vec[0];
let user = User {
name:String::from("name"),
email:String::from("email")
};
let user_ref = &user;
let _name = user_ref.name;
let _email = user.email;
}
and the compiler complains that :
error[E0507]: cannot move out of index of `Vec<String>`
--> src/main.rs:19:14
|
19 | let _v = some_vec[0];
| ^^^^^^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait
|
help: consider borrowing here
|
19 | let _v = &some_vec[0];
| +
error[E0507]: cannot move out of `user_ref.name` which is behind a shared reference
--> src/main.rs:28:17
|
28 | let _name = user_ref.name;
| ^^^^^^^^^^^^^ move occurs because `user_ref.name` has type `String`, which does not implement the `Copy` trait
|
help: consider borrowing here
|
28 | let _name = &user_ref.name;
| +
Vec
and Struct
are alike in grouping value together.
so I thought if we can't move String from vec via index, we can't move String from struct field, either. but there is no error in let _email = user.email;
let v = vec![1, 2, 3];
let v_ref: &Vec<i32> = &v;
let v2 = *v_ref;// move occurs because `*v_ref` has type `Vec<i32>`, which does not implement the `Copy` trait
so the code let _name = user_ref.name
is actually let _name = (*user_ref).name
after the compiler dereference automatically ? it is a similar way to move out of a reference like the code above?
Upvotes: 0
Views: 72
Reputation: 42342
I think Vec and Struct are alike in grouping value together.
They are not, because a "struct" is "transparent" to the compiler, as in the compiler is able to sus out different fields of a struct, that is not the case with indexing vec
, which is an opaque operation. That is why you can uniquely borrow different fields of a struct, but not different indices of a vec.
there is no error in
let _email = user.email;
That's because it's performing a partial move out of the struct, afterwards you can neither pass around user
itself as a unit (e.g. as a parameter to a function):
error[E0382]: use of partially moved value:
user
nor access user.email
:
error[E0382]: use of moved value:
user.email
you can only access the other fields of the structure.
so the code let _name = user_ref.name is actually
let _name = (*user_ref).name
after the compiler dereference automatically ?
That is what automatic dereference means, yes. It dereferences, automatically.
Upvotes: 2