问题
I'm trying to create a struct with a field, generic over F
where F
implements something like: Fn(&mut Compiler, &[Token]) -> &Token
. The only issue is, I'm not sure how I define lifetimes on the Fn
trait which satisfy the constraint that the returned &Token
references data in the &[Token]
slice supplied as an argument. Everything I've tried has thrown cryptic errors thus far.
Here is an MVCE which demonstrates the code (without any lifetimes):
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);
}
Naturally this fails to compile with the error:
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
I've attempted to add lifetimes specifiers here and there, moving things around but nothing seems to work. I would really appreciate any insight into the issue. Thanks!
回答1:
As per @Stargateur's comment, the solution was to add a Higher-Ranked Trait Bound to the Fn
trait declaration. The where for
clause is a piece of syntax completely specific to this use case.
Normal lifetime bounds don't work, because we don't know what lifetimes will be applied to the function's arguments until call time.
So we go from this:
struct Rule<F> where F: Fn(&mut Compiler, &[Token]) -> &Token {
func: F
}
To this:
struct Rule<F> where for<'a> F: Fn(&mut Compiler, &'a[Token]) -> &'a Token {
func: F
}
Which dictates that the trait bounds applied to function F
must satisfy all potential lifetimes of 'a
at call time. Magic!
来源:https://stackoverflow.com/questions/53566761/how-to-define-lifetimes-on-a-fn-trait-bound-returning-references