我试图更好地理解移动语义和Rust中Copy
类型的行为。
我知道&mut
T不是Copy
,正如here所解释的那样,因为复制&mut T
会创建一个别名的可变引用。但后来我不明白以下程序的行为:
fn my_ref_mut(the_ref_mut: &mut Vec<i32>) {
println!("{:?}", the_ref_mut);
}
fn main() {
let mut v: Vec<i32> = Vec::new();
let r: &mut Vec<i32> = &mut v;
my_ref_mut(r);
my_ref_mut(r); // Should not this be an `use after move` error?
}
由于E0382:use of moved value
错误,我原本期望上面的程序无法编译。 r
变量的行为就像Copy
一样。我试图通过以下程序更好地了解这种情况。它提供了两种不同的编译错误,具体取决于是否明确指定了类型(对我来说,确保我得到了预期的类型):
fn my_ref_mut(the_ref_mut: &mut Vec<i32>) {
println!("{:?}", the_ref_mut);
}
fn my_ref(the_ref: &Vec<i32>) {
println!("{:?}", the_ref);
}
fn main() {
let mut v: Vec<i32> = Vec::new();
{
let r: &mut Vec<i32> = &mut v;
my_ref_mut(r);
my_ref_mut(r);
}
{
let r1: &mut Vec<i32> = &mut v;
my_ref_mut(r1);
let r2 = r1;
my_ref_mut(r1);
}
{
let r: &Vec<i32> = &v;
my_ref(r);
my_ref(r);
}
{
let r1: &Vec<i32> = &v;
my_ref(r1);
let r2: &Vec<i32> = r1;
my_ref(r1);
}
}
错误是不言自明的:
error[E0382]: use of moved value: `*r1`
--> src/main.rs:20:20
|
19 | let r2 = r1;
| -- value moved here
20 | my_ref_mut(r1);
| ^^ value used here after move
|
= note: move occurs because `r1` has type `&mut std::vec::Vec<i32>`, which does not implement the `Copy` trait
我原本期望它是use of moved value: r1
,而不是*r1
,因为我移动了引用,而不是值本身。
通过将第19行更改为let r2: &mut Vec<i32> = r1;
,从而明确指定r2
的类型,错误变为E0499:
error[E0499]: cannot borrow `*r1` as mutable more than once at a time
--> src/main.rs:20:20
|
19 | let r2: &mut Vec<i32> = r1;
| -- first mutable borrow occurs here
20 | my_ref_mut(r1);
| ^^ second mutable borrow occurs here
21 | }
| - first borrow ends here
这个错误对我来说似乎也是错误的,因为*r1
的第一次借用应该是第17行(let r1: &mut Vec<i32> = &mut v;
)。我知道autoref和Deref
强制,但据我所知,它们在这里不适用。
我的结论是&T
是Copy
,正如预期的那样,正如上面的第二个例子所示,但我不能对&mut T
说同样的话。
我希望有人向我解释编译错误以及为什么&mut T
有时似乎表现得像Copy
。它是否也可能成为编译器错误?我的工具链是:
stable-x86_64-unknown-linux-gnu (default)
rustc 1.25.0 (84203cac6 2018-03-25)