Cannot move out of borrowed content [E0507]

2019-07-14 20:57发布

I'm writing a lexer in Rust to learn, but I'm stuck with two "cannot move out of borrowed content [E0507]" errors.

I tried all the solutions out there, but nothing seems to work: RefCell, clone(), by_ref(), changing the &mut self to self or &self or mut self, or dereferencing.

Here is my code:

struct Snapshot {
    Index: u32,
}

struct Tokenizable<'a, T: 'a>
    where T: Iterator
{
    Index: u32,
    Items: &'a T,
    Snapshots: Vec<Snapshot>,
}

impl<'a, T> Tokenizable<'a, T>
    where T: Iterator
{
    fn new(items: &'a T) -> Tokenizable<'a, T> {
        Tokenizable {
            Index: 0,
            Items: items,
            Snapshots: Vec::new(),
        }
    }

    fn end(&mut self) -> bool {
        match self.Items.peekable().peek() {
            Some(c) => false,
            None => true,
        }
    }

    fn peek(&mut self) -> Option<&T::Item> {
        match self.Items.peekable().peek() {
            Some(c) => Some(c),
            None => None,
        }
    }
}

fn main() {}
error: cannot move out of borrowed content [E0507]
         match self.Items.peekable().peek() {
               ^~~~~~~~~~
help: see the detailed explanation for E0507

error: borrowed value does not live long enough
         match self.Items.peekable().peek() {
               ^~~~~~~~~~~~~~~~~~~~~
note: reference must be valid for the anonymous lifetime #1 defined on the block at 32:43...
     fn peek(&mut self) -> Option<&T::Item> {
         match self.Items.peekable().peek() {
             Some(c) => Some(c),
             None => None,
         }
     }
note: ...but borrowed value is only valid for the block at 32:43
     fn peek(&mut self) -> Option<&T::Item> {
         match self.Items.peekable().peek() {
             Some(c) => Some(c),
             None => None,
         }
     }

error: cannot move out of borrowed content [E0507]
         match self.Items.peekable().peek() {
               ^~~~~~~~~~
help: see the detailed explanation for E0507

标签: rust
2条回答
姐就是有狂的资本
2楼-- · 2019-07-14 21:19

As you can see in the docs, the peekable function takes the iterator by value. Therefore it will only work if you own the iterator. However, in your code, Items is a shared reference to the iterator.

Solving this problem requires approaching it from a different angle. For instance, you could take the iterator by value in the constructor and adapt the struct to store the peekable iterator in the Items field.

查看更多
我命由我不由天
3楼-- · 2019-07-14 21:24

Basically, what is to be learned from here is the fact that over complicating things and over engineering things almost always does more harm than good.

Final fixed code:

use std::iter::Peekable;

struct Snapshot {
    index: u32
}

struct Tokenizable<T> where T: Iterator {
    index : u32,
    items : Peekable<T>,
    snapshots : Vec<Snapshot>,
}

impl<T> Tokenizable<T> where T: Iterator {
    fn new (items: T) -> Tokenizable<T>  {
        Tokenizable {
            index : 0,
            items : items.peekable (),
            snapshots : Vec::new (),
        }
    }

    fn end (&mut self) -> bool {
        match self.items.peek () {
            Some (c) => false,
            None => true
        }
    }

    fn peek (&mut self) -> Option<&<T as Iterator>::Item> {
        match self.items.peek () {
            Some (c) => Some (c),
            None => None
        }
    }
}

fn main () {
    let mut data = "Hello".chars ();
    let tokenizable = Tokenizable::new (data);
}
查看更多
登录 后发表回答