我的实际问题可以通过变通解决,但我不知道为什么变通可以解决,而原始版本却不能.

我有这些类型:

struct Lexer<'source> { ... }
impl<'source> Iterator for Lexer<'source> {
    type Item = Token<'source>;
    ...
}

struct Func<'source> { ... }

以下功能不起作用:

fn parse_tokens<'source>(lexer: &'source mut Lexer<'source>) -> Vec<Func> {
    let mut funcs = Vec::new();
    loop {
        let Some(t) = lexer.next() else { break; }
        funcs.push(parse_fn(lexer));
    }
    funcs
}
pub fn parse_fn<'source>(lexer: &'source mut Lexer<'source>) -> Func {
    // Get the name of the function.
    // TODO: replace all of these unwraps and panics with error handling.
    let t = lexer.next().unwrap();
    if t.kind != TokenKind::Identifier { panic!() }
    let ident = t.value;

    let mut body = Vec::new();
    loop {
        let Some(t) = lexer.next() else { break };
        match t.kind {
            TokenKind::Keyword(Keyword::End) => break,
            TokenKind::Int(num) => body.push(Op::PushInt(num)),
            kind => todo!("parsing of {kind:?}"),
        }
    }

    Func {
        ident,
        body
    }
}

编译失败,出现以下错误:

error[E0499]: cannot borrow `*lexer` as mutable more than once at a time
  --> src/parse.rs:44:23
   |
41 | pub fn parse_tokens<'source>(lexer: &'source mut Lexer<'source>) -> Vec<Func> {
   |                     ------- lifetime `'source` defined here
...
44 |         let Some(t) = lexer.next() else { break };
   |                       ^^^^^^^^^^^^ second mutable borrow occurs here
45 |         match t.kind {
46 |             TokenKind::Keyword(Keyword::Fn) => funcs.push(parse_fn(lexer)),
   |                                                           ---------------
   |                                                           |        |
   |                                                           |        first mutable borrow occurs here
   |                                                           argument requires that `*lexer` is borrowed for `'source`

error[E0499]: cannot borrow `*lexer` as mutable more than once at a time
  --> src/parse.rs:46:68
   |
41 | pub fn parse_tokens<'source>(lexer: &'source mut Lexer<'source>) -> Vec<Func> {
   |                     ------- lifetime `'source` defined here
...
46 |             TokenKind::Keyword(Keyword::Fn) => funcs.push(parse_fn(lexer)),
   |                                                           ---------^^^^^-
   |                                                           |        |
   |                                                           |        `*lexer` was mutably borrowed here in the previous iteration of the loop
   |                                                           argument requires that `*lexer` is borrowed for `'source`

然而--这是我感到奇怪的部分--如果我不使用可变的borrow ,而是来回传递所有权,代码就会按预期进行编译和工作.

特别是,通过如下方式更新函数及其签名:

pub fn parse_tokens<'source>(mut lexer: Lexer<'source>) -> Vec<Func> {
    ...
    TokenKind::Keyword(Keyword::Fn) => {
        let func;
        (lexer, func) = parse_fn(lexer);
        funcs.push(func);
    }
    ...
}
pub fn parse_fn<'source>(mut lexer: Lexer<'source>) -> (Lexer<'source>, Func) {
    ...
    (lexer, Func {
        ident,
        body
    })
}

我的印象是,第一个示例不起作用,因为borrow 判断器认为funcs将包含lexer指向的数据,而funcs比可变borrow 更持久.但考虑到编译后的版本,情况不可能是这样.

任何有助于理解这一点的帮助/解释都将不胜感激.

如果需要进一步的信息或完整的工作实例,我将很乐意提供.

推荐答案

问题是,你将两种不同的生命结合在一起:

fn parse_tokens<'source>(lexer: &'source mut Lexer<'source>) -> Vec<Func> {
    ...

pub fn parse_fn<'source>(lexer: &'source mut Lexer<'source>) -> Func {
    ...

&mut的生命周期 就是for which the 101 is borrowed的生命周期 .<>的生命周期 就是tokens borrow from的生命周期 .

通过对两者使用相同的生命周期参数,您可以说"只要Lexer的项是有效的,就会被借走".这产生的结果是,您只能使用它一次(有时甚至不能使用),然后它就会在其存在的剩余时间内被borrow .

一般来说,对于任何类型的Foo,您都应该写never&'a mut Foo<'a>;这将总是导致"在其存在的其余部分borrow "的效果.

(准确地说,这只发生在涉及invariance的情况下;通常,&'a mut TT中是不变的,这大致意味着T中的任何生命周期都不能被强迫为shorter.然而,这只适用于&mut,因此&'a Foo<'a>通常是可以接受的,如果不是可以接受的,这是因为您需要从&'a Foo<'b>中复制比'a更长的Foo<'b>;对于不返回、不借入或将它们传输到其他地方的函数的输入从来都不是问题.)

取而代之的是使用不同的生命周期:

fn parse_tokens<'lex, 'source>(lexer: &'lex mut Lexer<'source>) -> Vec<Func> {
    ...

pub fn parse_fn<'lex, 'source>(lexer: &'lex mut Lexer<'source>) -> Func {
    ...

事实上,您甚至可以完全省略其中一个或两个终身名称,因为在这种情况下,lifetime elision rules个名称做了正确的事情.("输入位置中的每个省略的生命周期 将成为不同的生命周期 参数.")

fn parse_tokens(lexer: &mut Lexer<'_>) -> Vec<Func> {
    ...

pub fn parse_fn(lexer: &mut Lexer<'_>) -> Func {
    ...

Rust相关问答推荐

如何定义使用拥有的字符串并返回拥有的Split的Rust函数?

在一个tauri协议处理程序中调用一个rectuc函数的推荐技术是什么?

当Option为None时,Option数组是否占用Rust中的内存?

制作一片连续整数的惯用Rust 方法?

正则表达式中的重叠匹配?(铁 rust 正则式发动机)

AXUM一路由多个不包括URL的参数类型

Rust ndarray:如何从索引中 Select 数组的行

为什么将易错函数的泛型结果作为泛型参数传递 infer ()?不应该是暧昧的吗?

如何执行数组文字的编译时串联?

Option<&T> 如何实现复制

‘&T as *const T as *mut T’ 在 ‘static mut’ 项目中合适吗?

std::vector::shrink_to_fit 如何在 Rust 中工作?

为什么不可变特征的实现可以是可变的?

Rust 中的方法调用有什么区别?

rust 中不同类型的工厂函数

是否可以在 Rust 中的特定字符上实现特征?

为什么-x试图解析为文字并在声明性宏中失败?

需要括号的宏调用中的不必要的括号警告 - 这是编写宏的糟糕方法吗?

编写 TOML 文件以反序列化为 struct 中的枚举

A 有一个函数,它在 Option<> 类型中时无法编译,但在 Option<> 类型之外会自行编译.为什么?