`在构建排序链表时无法移出`&mut`-pointer`的取消引用

`cannot move out of dereference of `&mut`-pointer` while building a sorted linked list

所以,我正在学习 Rust 并决定构建一个排序链表。在我到达 add 方法之前一切看起来都不错,这里是代码:

struct NodeItem<'a, V:'a + Ord> {
  value : V,
  next : Box<Option<NodeItem<'a,V>>> // '
}

impl <'a, V:'a + Ord> NodeItem<'a,V> { // '

  fn new(value : V) -> NodeItem<'a,V> { // '
    NodeItem { value : value, next : box None }
  }

  fn add(&mut self, value : V) {

    match self.value.cmp(&value) {
      Less => {
        self.next = box Some(NodeItem {value: self.value, next : self.next });
        self.value = value;
      },
      Equal | Greater => {
        match *self.next {
          Some(ref mut next) => next.add(value),
          None => self.next = box Some(NodeItem::new(value)),
        }
      },
    }

  }

}

编译器抱怨:

/home/mauricio/projects/rust/data_structures/src/lists/mod.rs:16:47: 16:51 error: cannot move out of dereference of `&mut`-pointer
/home/mauricio/projects/rust/data_structures/src/lists/mod.rs:16         self.next = box Some(NodeItem {value: self.value, next : self.next });
                                                                                                               ^~~~
/home/mauricio/projects/rust/data_structures/src/lists/mod.rs:16:66: 16:70 error: cannot move out of dereference of `&mut`-pointer
/home/mauricio/projects/rust/data_structures/src/lists/mod.rs:16         self.next = box Some(NodeItem {value: self.value, next : self.next });

这里到底有什么问题?我知道我正在将引用移动到其他地方,但是生命周期参数不应该显示这些项目有相关的 "life"?

这是从 2014 年 12 月 21 日开始的每晚使用。

这是一个similar example

enum E { Hello }
struct A(E);

fn main() {
    let mut a = A(E::Hello);
    let b = &mut a;
    let c = b.0;
}

错误:

<anon>:7:13: 7:14 error: cannot move out of dereference of `&mut`-pointer
<anon>:7     let c = b.0;
                     ^
<anon>:7:9: 7:10 note: attempting to move value to here
<anon>:7     let c = b.0;
                 ^
<anon>:7:9: 7:10 help: to prevent the move, use `ref c` or `ref mut c` to capture value by reference
<anon>:7     let c = b.0;
                 ^

请注意,编译器会告诉您如何避免这种情况下的错误。

问题是您的 self.value 不是 Copyable。这意味着当您分配它时,您将 将其移出 NodeItem (self),从而使其不再完全定义!这将是一件坏事,因此 Rust 会阻止您这样做。

您必须决定解决问题的正确方法是什么。最简单的方法是确保 T 是可复制的(或者 Cloneable, depending on your data). However, you probably don't want to be copying your data all around. I would investigate changing your code to prevent copying the node around and just updating entries. You may need to use something like swap.

我从探索一门新语言中获得所有乐趣

#[derive(Debug)]
struct Node<T> {
    v: T,
    next: Option<Box<Node<T>>>,
}

impl<T> Node<T> {
    fn new(v: T) -> Node<T> { Node { v: v, next: None } }

    fn push_front(self, head: T) -> Node<T> {
        Node {
            v: head,
            next: Some(Box::new(self)),
        }
    }

    fn push_back(&mut self, tail: T) {
        match self.next {
            Some(ref mut next) => next.push_back(tail), 
            None => self.next = Some(Box::new(Node::new(tail))),
        }
    }

    fn push_after(&mut self, v: T) {
        let old_next = self.next.take();

        let new_next = Node {
            v: v,
            next: old_next,
        };

        self.next = Some(Box::new(new_next));
    }
}

fn main() {
    let mut n = Node::new(2u8);
    n.push_back(3u8);
    let mut n = n.push_front(0u8);
    n.push_after(1u8);

    println!("{:?}", n);
}