如何在 Fn 特征绑定返回引用上定义生命周期?
How to define lifetimes on a Fn trait bound returning references?
我正在尝试创建一个带有字段的结构,该字段在 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
我尝试在各处添加生命周期说明符,四处移动,但似乎没有任何效果。我真的很感激对这个问题的任何见解。谢谢!
根据@Stargateur 的评论,解决方案是在 Fn
特征声明中添加 Higher-Ranked Trait Bound。 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
在调用时 的所有潜在生命周期。魔法!
我正在尝试创建一个带有字段的结构,该字段在 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
我尝试在各处添加生命周期说明符,四处移动,但似乎没有任何效果。我真的很感激对这个问题的任何见解。谢谢!
根据@Stargateur 的评论,解决方案是在 Fn
特征声明中添加 Higher-Ranked Trait Bound。 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
在调用时 的所有潜在生命周期。魔法!