Lifetime error while trying to simulate trait alias in a stable version of compiler

I would like to make a trait alias for Fn trait. I need an alias because I have a struct Container to keep an instance of Fn and the definition of the trait is used in several places: struct definition, struct constructors and using full definition of Fn makes code very verbose.

I use stable version of the compiler and I tried to define new trait AliasFn as an alias for the Fn and implement it for all implementors of the Fn(&i32). The following code snipped demonstrates the approach (link to the Rust playground):

trait AliasFn : Fn(&i32) {}
impl<F: Fn(&i32)> AliasFn for F {}

struct Container {
    func: Box<dyn AliasFn>,
}

impl Container {
    fn new<F: 'static + AliasFn>(func: F) -> Self {
        Self{ func: Box::new(func) }
    }
}

fn main() {
    Container::new(|arg| {});
}

The code doesn't compile:

   Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
  --> src/main.rs:15:5
   |
15 |     Container::new(|arg| {});
   |     ^^^^^^^^^^^^^^ lifetime mismatch
   |
   = note: expected type `for<'r> Fn<(&'r i32,)>`
              found type `Fn<(&i32,)>`
note: this closure does not fulfill the lifetime requirements
  --> src/main.rs:15:20
   |
15 |     Container::new(|arg| {});
   |                    ^^^^^^^^
note: the lifetime requirement is introduced here
  --> src/main.rs:9:25
   |
9  |     fn new<F: 'static + AliasFn>(func: F) -> Self {
   |                         ^^^^^^^

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` due to previous error

Code works well when the full definition of Fn is used instead of AliasFn.

Is it possible to use super trait approach to create an alias for a trait? What is the lifetime issue here?

HRTB in closures strike again.

I don't know why it happens in this specific case, and have no interest in trying to understand, but changing |arg| {} to |arg: &_| {} works (and usually so).

1 Like

Thanks @chrefr, after adding specific type after args it compiles!

Yes, the trait alias "hack" workaround is currently limited w.r.t. not imbuing literal closures with the necessary higher-order signature.

Feel free to look at the documentation of

for more info about this and a general-purpose workaround.


In practice

Try to duplicate the function bound in the constructor:

impl Container {
    fn new<F: 'static + AliasFn>(func: F) -> Self
+  where
+      F : Fn(&i32),
    {
        Self{ func: Box::new(func) }
    }
}

that way callers won't be required to either specify the &_ in the parameter argument.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.