为什么对于自定义类型而不是 Box,我会得到“无法移出`item`,因为它是借来的”?

use*_*932 3 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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

产生编译时错误:

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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我不明白两件事:

  1. 为什么它if在我们在else分行时抱怨分行借用?它们应该是相互排斥的,一个借用不应影响另一个。

  2. 如果我替换Veclet mut items = Vec::<P<Item>>::new();Vec<Box<Item>>和取消注释行AAA和注释行BBB,然后再编译。都BoxPimplement Deref,所以item.node表达式应该是一样的。

She*_*ter 5

这是一个更清晰的例子:

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;
}
Run Code Online (Sandbox Code Playgroud)

BoxPimplement Deref,所以item.node表达式应该是一样的。

硬道理:搬出Box编译器中的特殊情况。它并没有使用Deref。移出 a 会Box释放内存并赋予您所有权。自己无法实现这种特殊能力。

也许在未来的某个时候会添加一个假设的特征DerefMove。这种特质很难正确。已经为它的 RFC 进行多次尝试,但目前都没有开放。

也可以看看: