Elided early-bound lifetime parameters (due to associated types) can be turbofished
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
Normally, a function with elided lifetime parameters cannot be turbofished, since elided lifetime parameters are normally late-bound, and late-bound parameters cannot be turbofished. However, using associated types, it is seemingly possible to have an elided early-bound ilifetime parameter, which can then be turbofished, such as in the following code.
// compiles without errors
trait Trait {
type Assoc<'a>;
}
// zero explicit generic lifetimes
fn do_thing<T: Trait>(_: Option<<T as Trait>::Assoc<'_>>) -> &i32 {
todo!()
}
fn foo<T: Trait>() {
// one explicit generic lifetime
do_thing::<'static, T>(None);
}
In the above code, there is a turbofish specifying a lifetime parameter. The parameter being specified is an elided lifetime parameter. This seems wrong, and is especially confusing when there's also an explicit lifetime parameter, such as in the following code.
// compiles without errors
trait Trait {
type Assoc<'a>;
}
// one explicit generic lifetime
fn do_thing<'b, T: Trait>(_: Option<<T as Trait>::Assoc<'_>>) -> (&i32, &'b i64) {
todo!()
}
fn foo<T: Trait>() {
// two explicit generic lifetimes
do_thing::<'static, 'static, T>(None);
}
In the above code, it is not obvious which of the two lifetimes specified as 'static corresponds to the 'b lifetime vs the elided lifetime. (I think the first 'static corresponds to 'b, and the second 'static corresponds to the elided lifetime.) This seems undesirable.
For some reason, a return type with an elided lifetime is seemingly required for this weirdness to happen. See the following code.
// fails to compile
trait Trait {
type Assoc<'a>;
}
// zero explicit generic lifetimes
fn do_thing<T: Trait>(_: Option<<T as Trait>::Assoc<'_>>) -> i32 {
todo!()
}
fn foo<T: Trait>() {
// one explicit generic lifetime
do_thing::<'static, T>(None);
}
error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> src/lib.rs:14:16
|
14 | do_thing::<'static, T>(None);
| ^^^^^^^
|
note: the late bound lifetime parameter is introduced here
--> src/lib.rs:8:53
|
8 | fn do_thing<T: Trait>(_: Option<<T as Trait>::Assoc<'_>>) -> i32 {
| ^^
For more information about this error, try `rustc --explain E0794`.
Here are some other variations of the weirdness:
Using a trait associated function instead of a top-level function
// compiles without errors
trait Trait {
type Assoc<'a>;
// zero explicit generic lifetimes
fn do_thing(_: Option<Self::Assoc<'_>>) -> &i32 {
todo!()
}
}
fn foo<T: Trait>() {
// one explicit generic lifetime
<T as Trait>::do_thing::<'static>(None);
}
Using a normal associated type instead of a GAT
// compiles without errors
trait Trait {
type Assoc;
}
// zero explicit generic lifetimes
fn do_thing<T>(_: Option<<&T as Trait>::Assoc>) -> &i32
where
for<'c> &'c T: Trait,
{
todo!()
}
fn foo<T: 'static>()
where
for<'c> &'c T: Trait,
{
// one explicit generic lifetime
do_thing::<'static, T>(None);
}
Implementing a trait with a method with an elided early-bound lifetime parameter
// compiles without errors
trait Trait {
type Assoc<'a>;
// zero explicit generic lifetimes
fn do_thing(_: Option<Self::Assoc<'_>>) -> &i32;
}
impl Trait for i32 {
type Assoc<'a> = i64;
// one explicit generic lifetime
fn do_thing<'b>(_: Option<i64>) -> &'b i32 {
todo!()
}
}
cc @lcnr
Meta
Reproducible on the playground with version 1.96.0-nightly (2026-03-26 23903d01c237d7c7d4fb)
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
Reproduce the examples in src/lib.rs with the reported rustc nightly version, starting with the cases that compile and the E0794 case. Compare how lifetime parameters are classified when associated types and elided return lifetimes are present. Done requires an agreed rule for these turbofish arguments and compiler coverage for the reported variations.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100