为什么& mut T看起来像复制类型?

时间:2018-04-02 14:52:25

标签: reference rust move-semantics

我试图更好地理解移动语义和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?
}

由于E0382use 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强制,但据我所知,它们在这里不适用。

我的结论是&TCopy,正如预期的那样,正如上面的第二个例子所示,但我不能对&mut T说同样的话。

我希望有人向我解释编译错误以及为什么&mut T有时似乎表现得像Copy。它是否也可能成为编译器错误?我的工具链是:

stable-x86_64-unknown-linux-gnu (default)
rustc 1.25.0 (84203cac6 2018-03-25)

0 个答案:

没有答案