Why do I get "cannot move out of `item` because it is borrowed" for a custom type but not a Box?

Viewed 1159

Code:

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
        }
    }
}

Produce the compile-time error:

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();

I do not understand two things:

  1. Why does it complain about the borrow in the if branch while we in else branch? They are supposed to be mutually exclusive, and a borrow in one should not influence another.

  2. If I replace Vec in let mut items = Vec::<P<Item>>::new(); with Vec<Box<Item>> and uncomment line AAA and comment line BBB, then it compiles. Both Box and P implement Deref, so the item.node expression should be the same.

1 Answers
Related