How to declare a higher-ranked lifetime for a closure argument?

As originally pointed out by DK., you can use a function to apply extra constraints to a closure’s arguments and return values:

fn constrain<F>(f: F) -> F
where
    F: for<'a> Fn(&'a mut SplitWhitespace) -> Result<&'a str, ParserError>,
{
    f
}

This gives you the full abilities of the where clause; in this case you can use higher-ranked trait bounds (for <...>) to say that the closure must return a reference of the same lifetime as the argument.

let nt = constrain(|t| t.next().ok_or(missing_token(line_number)));

Ultimately, this is caused due to limitations in Rust’s type inference. Specifically, if a closure is passed immediately to a function that uses it, the compiler can infer what the argument and return types are. Unfortunately, when it is stored in a variable before being used, the compiler does not perform the same level of inference.

This workaround works because it immediately passes the closure to a function, nailing down the types and lifetime references.

Leave a Comment