# Proposal: \`'\<T\>\` lifetime

**URL:** <https://internals.rust-lang.org/t/proposal-t-lifetime/22977>\
**Category:** language design\
**Created:** [May 23, 2025, 6:20pm UTC](https://internals.rust-lang.org/t/proposal-t-lifetime/22977 "2025-05-23T18:20:29Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jules-Bertholet](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jules-bertholet/32/10671_2.png) [@Jules-Bertholet](https://internals.rust-lang.org/u/Jules-Bertholet)\
**Post date:** [May 23, 2025, 6:20pm UTC](https://internals.rust-lang.org/t/proposal-t-lifetime/22977/1 "2025-05-23T18:20:29Z")

</div>

# What it is

For any type `T`, `'<T>` (bikeshedabble ofc) denotes the longest lifetime `'a` for which `T: 'a` holds.

# Why it’s useful

## Eliminating early-bound lifetime parameters

The signature of `Box::leak()` contains an early-bound lifetime parameter:

```rust
impl<T: ?Sized> Box<T> {
    fn leak<'a>(b: Box<T>) -> &'a mut T { … }
}

```

This feature would allow eliminating that parameter:

```rust
impl<T: ?Sized> Box<T> {
    fn leak(b: Box<T>) -> &'<T> mut T { … }
}

```

## Self-referential lifetimes

Consider the following self-referential data structure (example taken from [Unsafe binder types - HackMD](https://hackmd.io/@compiler-errors/HkXwoBPaR)):

```rust
struct DataAndView<T> {
    x: Box<[T]>,
    element: &'static T,
    //~^ ERROR the parameter type `T` may not live long enough
}

```

This unnecessarily imposes a `'static` bound on `T`. With this feature, we can instead write:

```rust
struct DataAndView<T> {
    x: Box<[T]>,
    element: &'<T> T,
}

```

Avoiding this bound.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [May 23, 2025, 8:47pm UTC](https://internals.rust-lang.org/t/proposal-t-lifetime/22977/2 "2025-05-23T20:47:56Z")

</div>

> [@Jules-Bertholet](#):
>
> Eliminating early-bound lifetime parameters

Not _quite_; a function like `fn f<T>() -> T` with an output generic type can still get an effectively early-bound lifetime by using `'<T>`. This might make the difference between early-bound and late-bound clear enough to make their differing behavior more intuitive, but it can't eliminate the concept entirely.

> [@Jules-Bertholet](#):
>
> This feature would allow eliminating [the `Box::leak` lifetime] parameter:

Well, not _quite_, since the function already exists and can be referred to with the parameter explicitly provided.

> [@Jules-Bertholet](#):
>
> Self-referential lifetimes

This is better handled by [unsafe binder types](https://github.com/rust-lang/rust/issues/130516), e.g. `element: unsafe<'a> &'a T`.

* * *

Thus I don't really see sufficient motivation. Early-bound "output" generic lifetimes aren't any stranger to _users_ than "output" generic types are, ime, and adding this can't remove the compiler complexity around dealing with early-bound vs late-bound, since it'll always be possible to declare early-bound lifetimes in existing editions.

---

<div class="post-metadata">

**Author:** ![Jules-Bertholet](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jules-bertholet/32/10671_2.png) [@Jules-Bertholet](https://internals.rust-lang.org/u/Jules-Bertholet)\
**Post date:** [May 23, 2025, 9:30pm UTC](https://internals.rust-lang.org/t/proposal-t-lifetime/22977/3 "2025-05-23T21:30:42Z")

</div>

> [@CAD97](#):
>
> This is better handled by [unsafe binder types](https://github.com/rust-lang/rust/issues/130516), e.g. `element: unsafe<'a> &'a T`.

Yes, this is specifically intended as an alternative to that; I link to the unsafe binders HackMD in the post.

> [@CAD97](#):
>
> Well, not _quite_, since the function already exists and can be referred to with the parameter explicitly provided.

Yes, this is a limitation, but can be fixed over an edition.

> [@CAD97](#):
>
> Not _quite_; a function like `fn f<T>() -> T` with an output generic type can still get an effectively early-bound lifetime by using `'<T>`.

Well, yes, that is the point, the lifetime can now be derived from the type, so there is now only one early-bound parameter instead of two.

* * *

# Extension

We could extend this feature to allow specifying an list of types, such that the resultant lifetime is outlived by all types in the list:

```rust
fn leak<T, U>(b: Box<(T, U)>) -> &'<T, U> mut (T, U) { … }

```

Lifetimes could also be permitted:

```rust
fn leak<'a, T>(b: Box<(&'a i32, T)>) -> &'<'a, T> mut (&'a i32, T) { … }

```

---

<div class="post-metadata">

**Author:** ![quinedot](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/quinedot/32/7294_2.png) [@quinedot](https://internals.rust-lang.org/u/quinedot)\
**Post date:** [May 23, 2025, 10:12pm UTC](https://internals.rust-lang.org/t/proposal-t-lifetime/22977/4 "2025-05-23T22:12:59Z")

</div>

`'<(P1, P2, ..)>` would have been a sensible default `dyn` lifetime for those cases where the default for `dyn Trait<P1, P2, ..>` is currently `'static`, IMO.

Which brings us to a use case for structs that isn't tied to self-referencial structs:

```rust
struct DoNotWantStaticRequirementButPreferNotHavingLifetimeParam<T> {
    bx: Box<dyn Trait<T> + '<T>>,
}

```

Introducing constrained lifetimes would introduce [bivariant](https://github.com/lcnr/random-rust-snippets/issues/3) lifetimes in some sense. Whatever that's worth.

---

<div class="post-metadata">

**Author:** ![oli-obk](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/oli-obk/32/3168_2.png) [@oli-obk](https://internals.rust-lang.org/u/oli-obk)\
**Post date:** [May 24, 2025, 9:07am UTC](https://internals.rust-lang.org/t/proposal-t-lifetime/22977/5 "2025-05-24T09:07:44Z")

</div>

I don't think I can actually give a meaningful response to this proposal without doing the work of writing a full feature description and coming up with the edge cases myself. I'm pretty sure due to the nature of it taking lifetimes from a type you'll just run into conceptual cycles when other bounds on the type are involvee. That's even without any cycles in the type. Or you just bail and turn all variances in the most pessimistic variant, making the feature likely useless in the presence of mutable references

So at present I see this as a desire for a feature, not a proposal. It'll definitely need some explanation of why unsafe binders and late bound vars should be merged, not just stating that it could. Also some variance examples or usage examples would be helpful, as declarations by themselves do not explain semantics.

---

<div class="post-metadata">

**Author:** ![Jules-Bertholet](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jules-bertholet/32/10671_2.png) [@Jules-Bertholet](https://internals.rust-lang.org/u/Jules-Bertholet)\
**Post date:** [May 24, 2025, 3:55pm UTC](https://internals.rust-lang.org/t/proposal-t-lifetime/22977/6 "2025-05-24T15:55:07Z")

</div>

I don’t think it’s that complicated? `'<whatever>` is covariant in `whatever`. I don’t understand what else you think is missing?

---

<div class="post-metadata">

**Author:** ![beepster](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/beepster/32/7914_2.png) [@beepster](https://internals.rust-lang.org/u/beepster)\
**Post date:** [May 24, 2025, 7:18pm UTC](https://internals.rust-lang.org/t/proposal-t-lifetime/22977/7 "2025-05-24T19:18:25Z")

</div>

> [@Jules-Bertholet](#):
>
> ```rust
> struct DataAndView<T> {
> x: Box<[T]>,
> element: &'<T> T,
> //~^ ERROR the parameter type `T` may not live long enough
> }
> 
> ```

IMO, a big unstated benefit of unsafe binder types is that they very clearly show that the lifetimes they bind are unknown to the compiler and that one needs to proceed with caution when using them. They even require unsafe to use the inner type. This proposal does not do that.

---

<div class="post-metadata">

**Author:** ![Jules-Bertholet](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jules-bertholet/32/10671_2.png) [@Jules-Bertholet](https://internals.rust-lang.org/u/Jules-Bertholet)\
**Post date:** [May 24, 2025, 7:54pm UTC](https://internals.rust-lang.org/t/proposal-t-lifetime/22977/8 "2025-05-24T19:54:14Z")

</div>

> [@beepster](#):
>
> They even require unsafe to use the inner type. This proposal does not do that.

I agree that requiring `unsafe` is important. But [https://github.com/rust-lang/rfcs/pull/3458](https://github.com/rust-lang/rfcs/pull/3458) addresses the issue, and I’m not convinced that unsafe binders add much extra value on top.

---

<div class="post-metadata">

**Author:** ![197g](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/197g/32/7276_2.png) [@197g](https://internals.rust-lang.org/u/197g)\
**Post date:** [May 24, 2025, 8:31pm UTC](https://internals.rust-lang.org/t/proposal-t-lifetime/22977/9 "2025-05-24T20:31:57Z")

</div>

```rust
struct T<'lt> {
    inner: Rc<T<'<Self>>>,
}

```

Would there be semantic meaning to this? `'<T> = 'static`?

---

<div class="post-metadata">

**Author:** ![Jules-Bertholet](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jules-bertholet/32/10671_2.png) [@Jules-Bertholet](https://internals.rust-lang.org/u/Jules-Bertholet)\
**Post date:** [May 24, 2025, 8:40pm UTC](https://internals.rust-lang.org/t/proposal-t-lifetime/22977/10 "2025-05-24T20:40:16Z")

</div>

That’s an an error, as `'lt` is unused. (`struct Foo<'a>(*const Self);` also doesn’t work)

---

<div class="post-metadata">

**Author:** ![197g](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/197g/32/7276_2.png) [@197g](https://internals.rust-lang.org/u/197g)\
**Post date:** [May 25, 2025, 9:59am UTC](https://internals.rust-lang.org/t/proposal-t-lifetime/22977/11 "2025-05-25T09:59:27Z")

</div>

That was imprecise of me. I was getting at the explanations being very unclear about how lifetime solving would work algorithmically if we get to mention these. Let's restate it with `'lt` being covered for concreteness sake:

```rust
struct T<'lt> {
    inner: Rc<T<'<Self>>>,
    covers_lt: PhantomData<fn() -> &'lt ()>,
}

```

Note that any arbitrary assignment of `'<T<'lt>>` seem correct (as long as `'lt:'<T<'lt>>`? maybe? or maybe not?). Are we defining that the lifetime should be the maximum element in the lattice of solutions or the minimum?

And now consider the another case:

```rust
struct Foo<'lt> {
    my_head_hurts: &'Foo<'lt> dyn FnOnce() -> &'Foo<'lt> &'lt (),
}

```

The lifetime for `Foo` is now _at most_ `'lt` for the return value to be a well-formed type. But again, any arbitrary assignment shorter than `'lt` is _a_ correct solution, it's just incompatible with the alternate shorter solutions. So which one should the compiler choose?

Of course if we combine it just right we have unique solutions, only how do we find that uniqueness:

```rust
struct Foo<'lt> {
    my_head_hurts: &'lt dyn FnOnce() -> &'Foo<'lt> &'lt (),
}

```

---

<div class="post-metadata">

**Author:** ![Jules-Bertholet](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jules-bertholet/32/10671_2.png) [@Jules-Bertholet](https://internals.rust-lang.org/u/Jules-Bertholet)\
**Post date:** [May 25, 2025, 1:01pm UTC](https://internals.rust-lang.org/t/proposal-t-lifetime/22977/12 "2025-05-25T13:01:36Z")

</div>

> [@197g](#):
>
> Are we defining that the lifetime should be the maximum element in the lattice of solutions or the minimum?

The OP’s first sentence answers this question: we choose the _longest_ lifetime fulfilling the requirements. In this case, that’s `'lt`, so `'<Self>` is `'lt`. (In general, referencing `Self` in a field of a struct will never shorten the struct’s lifetime. This is true today, and the same rules apply to this feature.)

`'<Foo<'lt>>` is also `'lt` in your last two examples, for the same reasons.

---

<div class="post-metadata">

**Author:** ![197g](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/197g/32/7276_2.png) [@197g](https://internals.rust-lang.org/u/197g)\
**Post date:** [May 25, 2025, 3:12pm UTC](https://internals.rust-lang.org/t/proposal-t-lifetime/22977/13 "2025-05-25T15:12:02Z")

</div>

The sentence already supposes that there is a well-defined unique lifetime `'a` for every type `T` that is the longest possible choice. I'm asking to demonstrate that this is indeed the well-formed. As demonstrated the 'longest possible lifetime' is also a function of the lifetimes we assigned for other types `T: '<T>`.

I already fail to see the obviousness of how that is a monotonic lattice problem that can simply be hill-climbed to a maximum. In contrast to borrow checking, the lifetimes in the type system are supposed to be constants (as per said definition; we do not get a lower bound, we get _the_ lifetime). In borrow checking we can stop when there is _a_ feasible solution, we do not find the optimal one; also all variables in every instance are fresh which makes the problem local. I don't see how that problem is local within the whole type system where new definitions are added at later points. How and where do we diagnose errors? I think it comes down to pointing out at which points the lifetimes `'<T>` are treated as free variables and where they are not. Another well-formedness problem:

```rust
struct Foo<'a, 'c> { … };
struct Bar<'b, 'd> { … };

struct Explain<'a, 'b> {
    inner: &'<Foo<'a, 'b>> &'<Bar<'a, 'b>> ();
}

```

This requires `'<Bar<'a, 'b>>: '<Foo<'a, 'b>>`. Do we have to name `where '<Bar<'a, 'b>>: '<Foo<'a, b>>` as a bound on the type `Explain` even though it looks like a trivial bound (either true or false if we treat those as lifetimes constants)? If we do not, does it introduce implied bound? Of what form? For instance we may find: `'<Bar<'a, 'b>> <= min('a, 'b)` from the definition`Bar(&'a(), &'b())` and `'<Foo<'a, 'b>> <= 'a` for another reason. Does this introduce an implied bound `'b = 'a` by the well-formedness requirement? If we had to write one manually it may make the problem more locally solvable.

I'm asking for an algorithmic description since: How are programmers supposed to reason about code written with this feature, it seems like it requires internal analysis of types to use those lifetimes.

---

<div class="post-metadata">

**Author:** ![Jules-Bertholet](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jules-bertholet/32/10671_2.png) [@Jules-Bertholet](https://internals.rust-lang.org/u/Jules-Bertholet)\
**Post date:** [May 25, 2025, 3:38pm UTC](https://internals.rust-lang.org/t/proposal-t-lifetime/22977/14 "2025-05-25T15:38:35Z")

</div>

In this example, `'<Foo<'a, 'b>>`, `'<Bar<'a, 'b>>`, and `'<Explain<'a, 'b>>` are all equivalent to `'<'a, 'b>` (using the extension I describe in [this reply](https://internals.rust-lang.org/t/proposal-t-lifetime/22977/3)). More generally, for any type `T`, `'<T>` is the intersection of all lifetimes `T` mentions. (Again, this follows from the definition in OP and the current rules of Rust.)

---

<div class="post-metadata">

**Author:** ![Jules-Bertholet](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jules-bertholet/32/10671_2.png) [@Jules-Bertholet](https://internals.rust-lang.org/u/Jules-Bertholet)\
**Post date:** [May 25, 2025, 4:43pm UTC](https://internals.rust-lang.org/t/proposal-t-lifetime/22977/15 "2025-05-25T16:43:39Z")

</div>

This example actually exposes a weird quirk of Rust. Let’s simplify it to:

```rust
struct Explain<'a, 'b> {
    inner: &'<'a, 'b> ();
}

```

`'<'a, 'b>` is uniquely determined by `'a` and `'b`. However, the reverse is not true; given only the lifetime of `'<'a, 'b>`, you cannot infer what `'a` and `'b` are.

However, situations like this can already occur in today’s Rust. The compiler makes an angelic choice in such cases:

```rust
trait Gatt {
    type Gat<'a>
    where
        Self: 'a;
}

impl Gatt for () {
    type Gat<'a> = ();
}

#[derive(Clone, Copy)]
struct Foo<'lt>(<() as Gatt>::Gat<'lt>);

fn requires_static(_: Foo<'static>) {}

fn requires_not_static<'a>(_: Foo<'a>, _: &'a ()) {}

fn main() {
    let foo = Foo(());

    // Angelic choice:
    // commenting out either one of these two calls allows the program to compile
    requires_static(foo);
    requires_not_static(foo, &foo.0);
}

```

---

<div class="post-metadata">

**Author:** ![Jules-Bertholet](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jules-bertholet/32/10671_2.png) [@Jules-Bertholet](https://internals.rust-lang.org/u/Jules-Bertholet)\
**Post date:** [May 28, 2025, 2:29am UTC](https://internals.rust-lang.org/t/proposal-t-lifetime/22977/16 "2025-05-28T02:29:11Z")

</div>

Another use case is making more function pointer types possible. Currently, it’s impossible to turn this function into a function pointer without loss of generality:

```rust
fn leak_tuple<'a, 'b, 'c>(a: &'a mut (), b: &'b mut ()) -> &'c mut (&'a mut (), &'b mut ()) {
    Box::leak(Box::new((a, b)))
}

```

With this proposal, you could instead write the function as:

```rust
fn leak_tuple<'a, 'b>(a: &'a mut (), b: &'b mut ()) -> &'<'a, 'b> mut (&'a mut (), &'b mut ()) {
    Box::leak(Box::new((a, b)))
}

```

Which could become:

```rust
type FnPtr = for<'a, 'b> fn(&'a mut (), &'b mut ()) -> &'<'a, 'b> mut (&'a mut (), &'b mut ());

```

---

<div class="post-metadata">

**Author:** ![Jules-Bertholet](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jules-bertholet/32/10671_2.png) [@Jules-Bertholet](https://internals.rust-lang.org/u/Jules-Bertholet)\
**Post date:** [June 2, 2025, 10:06pm UTC](https://internals.rust-lang.org/t/proposal-t-lifetime/22977/17 "2025-06-02T22:06:11Z")

</div>

I just realized: this feature could entirely replace the new [“precise capturing” syntax](https://doc.rust-lang.org/reference/types/impl-trait.html#r-type.impl-trait.generic-capture.precise) (`use<…>`). Any `+ use<…>` would become `+ '<…>`.
