impl Trait returned from trait method without arguments not detected as 'static
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
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())
}
}
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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the reproducer at src/lib.rs:11 in the linked Rust Playground and compare the Box<dyn Fn()> and Box<dyn Fn() + '_> variants. Investigate how the compiler treats the impl Fn() return from a no-argument trait method and the E0310 suggestion. Done means the valid case is accepted and the diagnostic is actionable when it is not.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100