AlexeyKarasev
AlexeyKarasev

Reputation: 520

How do I specify a closure that takes a reference and returns any type implementing a trait with the same lifetime as the reference?

I need to tell the compiler that F returns something that implements SomeTrait with the lifetime 'a:

trait SomeTrait {}

fn foo<P, Q, F>(func: F)
where
    Q: SomeTrait,
    F: for<'a> Fn(&'a P) -> Q + 'a,
{}

But I get this error:

error[E0261]: use of undeclared lifetime name `'a`
 --> src/main.rs:6:33
  |
6 |     F: for<'a> Fn(&'a P) -> Q + 'a,
  |                                 ^^ undeclared lifetime

It is like it doesn't understand Q + 'a.

Upvotes: 3

Views: 175

Answers (2)

Stefan
Stefan

Reputation: 5530

Q is not a trait, it is a type; something like T: Q + 'a doesn't make sense.

If you try F: for<'a> Fn(&'a P) -> (Q + 'a) you'll get:

error[E0404]: expected trait, found type parameter `Q`

Your example actually parses like F: (for<'a> Fn(&'a P) -> Q) + 'a - and it should be obvious why that doesn't work.

Now to:

I need to tell the compiler that F returns something that implements SomeTrait with lifetime 'a.

Your function can't return different types depending on (passed) lifetimes apart from using those lifetimes for references or generic lifetime parameters. You could write a Rust compiler that simply ignores lifetimes completely, and if the original program was valid it would still do the same thing.

There is no way yet to specify type parameters that take generic parameters, for either lifetimes or types.

If there was, it could look like this:

trait SomeTrait {}

fn foo<P, for<'a> Q<'a>, F>(func: F)
where
    for<'a> Q<'a>: SomeTrait,
    for<'a> F: Fn(&'a P) -> Q<'a>,
{
}

Upvotes: 4

EvilTak
EvilTak

Reputation: 7579

Lifetimes can only be given to references. Changing the line to this works:

F: for<'a> Fn(&'a P) -> &'a Q

An object by itself does not have a "lifetime" as such - it lives until it is dropped. The borrow checker, however, must be informed of how long the object thst a reference points to lives relative to other referenced objects. That's where lifetimes come in.

Upvotes: 1

Related Questions