rust - 为什么我得到 "cannot move out of ` item` 因为它是为自定义类型而不是 Box 借来的?

标签 rust

代码:

use std::collections::HashSet;
use std::{mem, ptr, fmt};
use std::ops::Deref;

enum Unsafety {
    Normal
}
enum ImplPolarity { Positive }
struct TraitRef;
struct Ty;
struct ImplItem;

enum ItemKind {
    Impl(Unsafety,
             ImplPolarity,
             Option<TraitRef>, // (optional) trait this impl implements
         Box<Ty>, // self
    ),
}

struct Item {
    node: ItemKind,
}

pub struct P<T: ?Sized> {
    ptr: Box<T>
}

impl<T: 'static> P<T> {
    pub fn unwrap(self) -> T {
        *self.ptr
    }
}

impl<T: ?Sized> Deref for P<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.ptr
    }
}

fn main() {

    let mut items = Vec::<P<Item>>::new();

    let mut item2: Item;

    for item in items.drain(..) {

        if let ItemKind::Impl(Unsafety::Normal,
                                   ImplPolarity::Positive,
                                   Some(ref trait_type),
                                   ref for_type) = item.node {
        } else {
//            item2 = *item; // AAA
            item2 = item.unwrap(); // BBB
        }
    }
}

产生编译时错误:

error[E0505]: cannot move out of `item` because it is borrowed
  --> /home/xxx/.emacs.d/rust-playground/at-2017-07-29-204629/snippet.rs:64:21
   |
61 |                                    ref for_type) = item.node {
   |                                                    ---- borrow of `item` occurs here
...
64 |             item2 = item.unwrap();

我不明白两件事:

  1. 为什么它会提示 if 中的借用我们在 else 时分支分支?它们应该是相互排斥的,其中一个的借用不应影响另一个。

  2. 如果我替换 Veclet mut items = Vec::<P<Item>>::new();Vec<Box<Item>>并取消注释行 AAA和评论行 BBB ,然后编译。两者 BoxP实现 Deref , 所以 item.node表达式应该相同。

最佳答案

这是一个更清晰的例子:

struct Item;

struct P<T> {
    ptr: Box<T>,
}

impl<T> P<T> {
    fn new(v: T) -> Self {
        P { ptr: Box::new(v) }
    }
}

impl<T> std::ops::Deref for P<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.ptr
    }
}

fn main() {
    let mut item = P::new(Item);
    // let mut item = Box::new(Item);

    *item;
}

Both Box and P implement Deref, so the item.node expression should be the same.

硬道理时间:移出 Boxspecial-cased in the compiler .它使用Deref。移出 Box 会释放内存并为您提供所有权。我们自己无法实现这种特殊能力。

也许在未来的某个时候,将添加假设的特征,如DerefMove。这种特质很难得到正确的。有一个number of attempts for an RFC for it , 但目前都没有开放。

另见:

关于rust - 为什么我得到 "cannot move out of ` item` 因为它是为自定义类型而不是 Box 借来的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45392688/

相关文章:

kotlin - 如何解决 Rust 中的继承问题?

rust - 我必须将我的闭包装箱以将其保存为结构中的字段吗?

rust - 如何以毫秒为单位获取当前时间?

rust - 如何模仿效用函数的可变参数?

oop - 为什么 Rust 不支持特征对象向上转换?

rust - 如何根据运行时信息有条件地跳过测试?

rust - 将 Rust 中的 Vec<String> 传递给 C 中的 char**

generics - Rust 中通用结构的向量

fold - Rust 中的折叠问题

rust - 是否有可能在 Rust 的不同源文件中有一个模块