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?
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..])
}
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.