Skip to content

impl Trait returned from trait method without arguments not detected as 'static #119773

Open
@hniksic

Description

@hniksic

I tried this code:

trait Original {
    fn f() -> impl Fn();
}

// provide a type-erased helper trait for Original
trait Erased {
    fn f(&self) -> Box<dyn Fn()>;
}

impl<T: Original> Erased for T {
    fn f(&self) -> Box<dyn Fn()> {
        Box::new(<T as Original>::f())
    }
}

Playground

I expected the code to compile successfully, but it failed on Rust 1.75.0 with the following error:

error[E0310]: the associated type `<T as Original>::{opaque#0}` may not live long enough
  --> src/lib.rs:11:9
   |
11 |         Box::new(<T as Original>::f())
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |         |
   |         the associated type `<T as Original>::{opaque#0}` must be valid for the static lifetime...
   |         ...so that the type `impl Fn()` will meet its required lifetime bounds
   |
help: consider adding an explicit lifetime bound
   |
10 |     fn f(&self) -> Box<dyn Fn()> where <T as Original>::{opaque#0}: 'static {
   |                                  ++++++++++++++++++++++++++++++++++++++++++

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

I understand that Box<dyn Fn()> is sugar for Box<dyn Fn() + 'static>, but in this case the impl Fn() return is 'static. It has to be, because Original::f() takes no arguments, so the value it returns cannot reference any non-static lifetime.

The workaround is to change the return type of Erased::f() from Box<dyn Fn()> to Box<dyn Fn() + '_>, which is allows the code to compile. (Playground.) (Another workaround is to change the definition of Original::f() to return impl Fn() + 'static, but in the original code Original is provided by a different crate and cannot be modified.)

A second, and minor issue is that the compiler's suggestion is not actionable because the opaque type returned from Original::f() cannot be named.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsA-lifetimesArea: Lifetimes / regionsC-bugCategory: This is a bug.D-invalid-suggestionDiagnostics: A structured suggestion resulting in incorrect code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions