How to add lifetime Parameter to Box<> with dyn type alias

65 views Asked by At

I have an type alias for a Fn trait like type SomeSub = dyn for<'a> Fn(&'a str) -> &'a str; which I would like to use with a Box with an explicit lifetime like Box<SomeSub + 'b>. Unfortunately this doesn't compile:

type SomeSub = dyn for<'a> Fn(&'a str) -> &'a str;

struct SomeBuilder(pub usize);

impl SomeBuilder {
    // --> this gets rejected with "type aliases cannot be used as traits"
    fn get_closure<'o>(
        &'o self
    ) -> Box<dyn SomeSub + 'o> {
        Box::new(|s| &s[self.0..])
    }

    // This works, but duplicates the code of the type alias
    fn get_closure_long<'o>(
        &'o self
    ) -> Box<dyn for<'a> Fn(&'a str) -> &'a str + 'o> {
        Box::new(|s| &s[self.0..])
    }
}

While the second method get_closure_long() compiles, get_closure() results in the error:

error[E0404]: expected trait, found type alias `SomeSub`
 --> src/lib.rs:8:18
  |
8 |     ) -> Box<dyn SomeSub + 'o> {
  |                  ^^^^^^^ type aliases cannot be used as traits

Leaving out the dyn like -> Box<SomeSub + 'o> will be rejected with "type aliases cannot be used as traits". Using Box<SomeSub> works bot doesn't allow the closure to capture any references.

What is the correct way to combine a closure type alias with a Box and an explicit lifetime for that box?

1

There are 1 answers

0
user4815162342 On BEST ANSWER

You can make the type alias generic:

type SomeSub<'b> = dyn for<'a> Fn(&'a str) -> &'a str + 'b;

Then SomeSub<'o> is a valid type that includes the lifetime, so this compiles:

fn get_closure<'o>(&'o self) -> Box<SomeSub<'o>> {
    Box::new(|s| &s[self.0..])
}

Playground

Alternatively, you can emulate a trait alias using the technique shown in this answer:

trait SomeSub: for<'a> Fn(&'a str) -> &'a str {}

impl<T> SomeSub for T where T: for<'a> Fn(&'a str) -> &'a str {}

Then your original get_closure() that returns Box<dyn SomeSub + 'o> compiles.

Playground