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:
Then
SomeSub<'o>is a valid type that includes the lifetime, so this compiles:Playground
Alternatively, you can emulate a trait alias using the technique shown in this answer:
Then your original
get_closure()that returnsBox<dyn SomeSub + 'o>compiles.Playground