首页 > 解决方案 > 如何在不破坏借用规则的情况下包装可窥视的迭代器

问题描述

我正在尝试制作一个适用于Peekable迭代器的简单词法分析器。当没有更多字符可以迭代时,我返回 EOF 而不是使用unwrap_or().

而不是不断地打字iter.peek().unwrap_or(&EOF),我有一个功能peek_or_eof。我尝试使用这样的功能:

use std::iter::Peekable;

const EOF: char = '\0';

enum Token {
    Identifier(String),
}

pub struct Lexer<I>
where
    I: Iterator<Item = char>,
{
    stream: Peekable<I>,
}

impl<I> Lexer<I>
where
    I: Iterator<Item = char>,
{
    fn peek_or_eof(stream: &mut Peekable<I>) -> &char {
        stream.peek().unwrap_or(&EOF)
    }

    fn read_identifier(stream: &mut Peekable<I>) -> Option<Token> {
        // ...

        let mut identifier = String::new();

        let mut next = Lexer::peek_or_eof(stream);
        while next.is_alphanumeric() || next == &'_' {
            identifier.push(stream.next().unwrap());
            next = Lexer::peek_or_eof(stream);
        }

        // ...
        None
    }
}

fn main() {
    println!("Hello, world!");
}

操场

上面的代码导致错误:

error[E0499]: cannot borrow `*stream` as mutable more than once at a time
  --> src/main.rs:31:29
   |
29 |         let mut next = Lexer::peek_or_eof(stream);
   |                                           ------ first mutable borrow occurs here
30 |         while next.is_alphanumeric() || next == &'_' {
31 |             identifier.push(stream.next().unwrap());
   |                             ^^^^^^ second mutable borrow occurs here
...
37 |     }
   |     - first borrow ends here

如果我理解正确,借用生命周期与返回的字符引用相同,在本例中为next. 但是,在检查 while 循环中的条件后,我实际上并没有使用 next ,并且next会在循环的下一次迭代之前被新值覆盖。

我犯了更大的错误吗?如何让编译器知道流上的可变借用已完成并且允许另一个可变借用是安全的?

标签: rustlifetimeborrow-checker

解决方案


推荐阅读