Rust借用编译错误

时间:2016-07-04 22:47:39

标签: compiler-errors rust borrow-checker

我试图通过写一个简单的词法分析器来学习Rust。这是我到目前为止所拥有的......

use std::fs::File;
use std::io::Read;
use std::str::Chars;

pub struct Lexer<'a> {
    file_name: String,
    file_contents: String,
    iterator: Option<Chars<'a>>,
}

impl<'a> Lexer<'a> {

    fn new(fname: &str) -> Lexer {
        Lexer {
            file_name: fname.to_string(),
            file_contents: String::new(),
            iterator: None,
        }
    }


    // Reads the file contents and creates iterator
    fn init(&'a mut self) { 

        // Open the file
        let mut f = File::open(&self.file_name).expect("Couldn't open file");

        // Read the contents
        f.read_to_string(&mut self.file_contents).expect("Couldn't read file contents");

        self.iterator = Some(self.file_contents.chars());

    }

    // Gets the next character
    fn get_next(&mut self) -> Option<char> {

        self.iterator.unwrap().next()

    }

}

fn main() {

    let mut lexer = Lexer::new("test.txt");
    lexer.init();

    // Assuming the file "text.txt" contains "Hello World" 
    // then the following two lines should print "H" then "e"

    println!("{}", lexer.get_next().unwrap());
    println!("{}", lexer.get_next().unwrap());

}

但是当我尝试编译它时,我得到以下两个错误:

cannot move out of borrowed content [E0507]
main.rs:38          self.iterator.unwrap().next()

cannot borrow `lexer` as mutable more than once at a time [E0499]
main.rs:49      println!("{}", lexer.get_next().unwrap());

Google的第一个错误显示Clone() - ing是这种错误的可能解决方案,但我相信在这种情况下这不会起作用,因为迭代器状态需要每次都更新next()被称为。{/ p>

有没有人对如何克服这些问题并将其编译进行任何建议?

1 个答案:

答案 0 :(得分:2)

最终,你正试图store a value and a reference to that value in the same struct。与其他配方不同,这个特定的案例允许您“引用”引用的结,但可能不会做您想要的。例如,在致电init后,您永远无法移动Lexer,因为移动它会使参考无效。

它还解释了“再次借用”错误。因为生命周期适用于self,并且它是一个可变引用,lexer本身将永远保留可变引用,这意味着没有其他任何东西可以改变它,包括它自己。

简短的回答是:不要那样组织你的代码。无论出于何种原因,解析和lexing是Rust社区中的一个流行问题。看看其他图书馆是如何做到的。

或者查看迭代器的工作原理。迭代的项目保持不变,并返回一个引用原始项目的单独迭代器。

将您的代码拆分为相同的两个部分可能是最好的方向。