【问题标题】:How to define lifetimes on a Fn trait bound returning references?如何在 Fn 特征绑定返回引用上定义生命周期?
【发布时间】:2018-12-01 23:40:47
【问题描述】:

我正在尝试创建一个带有字段的结构,该字段在 F 上是通用的,其中 F 实现类似:Fn(&mut Compiler, &[Token]) -> &Token。唯一的问题是,我不确定如何在 Fn 特征上定义生命周期,它满足返回的 &Token 引用 &[Token] 切片中作为参数提供的数据的约束。到目前为止,我尝试过的一切都引发了神秘的错误。

这是一个演示代码的 MVCE(没有任何生命周期):

struct Compiler;
#[derive(Debug)]
struct Token(usize);

impl Compiler {
    // missing lifetime paramters here
    fn meth(&mut self, tokens: &[Token]) -> &Token {
        tokens.get(0).unwrap()
    }
}

// missing lifetime paramters here    
struct Rule<F> where F: Fn(&mut Compiler, &[Token]) -> &Token {
    func: F
}

fn main() {
    let mut c = Compiler;
    let tokens = vec![Token(0), Token(1), Token(2)];
    let r = Rule { func: Compiler::meth };
    (r.func)(&mut c, &tokens);
}

自然编译失败,报错:

   Compiling playground v0.0.1 (/playground)
error[E0106]: missing lifetime specifier
  --> src/main.rs:11:56
   |
11 | struct Rule<F> where F: Fn(&mut Compiler, &[Token]) -> &Token {
   |                                                        ^ expected lifetime parameter
   |
   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2

我尝试在这里和那里添加生命周期说明符,四处移动,但似乎没有任何效果。我真的很感激对这个问题的任何见解。谢谢!

【问题讨论】:

标签: rust traits lifetime


【解决方案1】:

根据@Stargateur 的评论,解决方案是将Higher-Ranked Trait Bound 添加到Fn 特征声明中。 where for 子句是完全特定于此用例的语法。

正常的生命周期边界不起作用,因为直到调用时我们才知道函数的参数将应用什么样的生命周期。

所以我们从这里开始:

struct Rule<F> where F: Fn(&mut Compiler, &[Token]) -> &Token {
    func: F
}

到这里:

struct Rule<F> where for<'a> F: Fn(&mut Compiler, &'a[Token]) -> &'a Token {
    func: F
}

这规定应用于函数F 的特征边界必须满足'a 的所有潜在生命周期在调用时。魔法!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-22
    • 1970-01-01
    • 2018-03-18
    • 2018-11-13
    • 2021-11-16
    • 1970-01-01
    • 1970-01-01
    • 2022-08-22
    相关资源
    最近更新 更多