# RPIT Question for the 2024 edition

**URL:** <https://internals.rust-lang.org/t/rpit-question-for-the-2024-edition/21631>\
**Category:** language design\
**Created:** [September 30, 2024, 3:14pm UTC](https://internals.rust-lang.org/t/rpit-question-for-the-2024-edition/21631 "2024-09-30T15:14:24Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![viktorlott](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/viktorlott/32/11282_2.png) [@viktorlott](https://internals.rust-lang.org/u/viktorlott)\
**Post date:** [September 30, 2024, 3:14pm UTC](https://internals.rust-lang.org/t/rpit-question-for-the-2024-edition/21631/1 "2024-09-30T15:14:24Z")

</div>

Let me clarify what I'm asking:

```rust
fn t1<'a, T>(data: Vec<T>) -> impl Iterator<Item = T> + 'a {
   data.into_iterator()
}

```

It should implicitly be `T: 'a` because we specified an associated type binding.

And if we don't specify an associated type binding, we are required to explicitly do a lifetime constrain the captured `T` in the `hidden type`:

```rust
fn t2<'a, T>(data: Vec<T>) -> impl Iterator + 'a where T: 'a {
   data.into_iterator()
}

```

Wouldn't this default make sense?

Let's just also clarify these things.

`T: 'lifetime` tells us two things.

1. `T` cannot outlive `'lifetime`.
2. All references inside `T` must live at least as long as `'lifetime`

`impl Trait + 'lifetime` tells us only one thing.

1. `impl Trait` cannot outlive `'lifetime`, i.e. the `opaque type` cannot outlive `'lifetime`.

`impl Trait + use<'lifetime>` means the hidden type is allowed to use the `'lifetime`. However, it doesn't imply that the hidden type must capture the lifetime unless it's actually needed. It also means that we only capture `'lifetime`, so if we have another lifetime that the hidden type captures, it will not allow it.

Am I wrong?

> **Old post**
>
> My understanding about this change might not be fully informed, so feel free to correct me if I'm getting something wrong.
> 
> The new change will by default capture all in-scope type params + lifetimes.
> 
> Is there a reason why RPITs with associated type bindings (e.g. `Item = T` in `impl Iterator<Item = T>`), and a lifetime bound (e.g. `+ 'lifetime`)--don't automatically also constrain associated type bindings with said lifetime?
> 
> For concrete (w/o generics) type with lifetime bounds (e.g. `ConcreteType<T>: 'lifetime`), all of the parameters of that type get the same lifetime implicitly. We can even use covariance to implicity do lifetime bounds (e.g `PhantomData<T>: 'lifetime`).
> 
> I understand that the difference is because RPITs are opaque types, so they have different semantics than concrete types. But that only makes sense if we don't specify any associated type bindings.
> 
> If we have specified them, wouldn't it make more sense that they also get implicit lifetime bounds?
> 
> Let me give an example of what I mean.
> 
> 1. `-> impl Iterator<Item = T> + 'a`
> 2. `-> impl Iterator + 'a`
> 
> For me, when I see #1 I interpret it as if T has an implicit lifetime bound because of the explicit associated type binding (i.e Item = T), but that is not the case currently.
> 
> #2 would then work like it does now, it is an opaque type, so any outlive bound would just apply to the opaque type, nothing propagates down like it would do for concrete types.
> 
> This would work with the new `ùse<>` syntax.

---

<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:** [September 30, 2024, 5:48pm UTC](https://internals.rust-lang.org/t/rpit-question-for-the-2024-edition/21631/2 "2024-09-30T17:48:05Z")

</div>

EDIT: wait I think I misunderstood the question here whoops. Associated types in RPIT don't get implicitly bound because they don't need to be. There's nothing wrong with `&'a &'static T`. _Input_ types get implicitly lifetime bound because that's more permissive to the _caller_ by being more _restrictive_ to the bound impl.

> [@viktorlott](#):
>
> and a lifetime bound (e.g. `+ 'lifetime`)

The underlying reason is that `+ 'a` and `+ use<'a>` mean different things. The difference is very subtle, because for a single covariant lifetime there isn't one.

To explain it simply:

- `+ 'a` means the object can validly live for _at least_ `'a`. You can use the object as long as _any_ lifetime bound to it in this manner is still live.
- `+ use<'a>` means the object is live for _at most_ `'a`. You can use the object as long as _all_ lifetimes captured by it in this manner are still live.

To explain by example: Every RPIT is `+ use<'static>` (except that this would turn off the implicit capture). If you capture a lifetime (`+ use<'a>`) you can't be `+ 'static`. e.g. `&'a T` works with `+ use<'outlives_a>` but not with `+ 'outlives_a`.

A different example: `impl 'a` means usable by `T: 'a`. `+ use<'a>` means not usable outside of lifetime `'a`.

For a more involved explanation, see the blog post about the RPIT changes.

---

<div class="post-metadata">

**Author:** ![viktorlott](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/viktorlott/32/11282_2.png) [@viktorlott](https://internals.rust-lang.org/u/viktorlott)\
**Post date:** [October 1, 2024, 10:49am UTC](https://internals.rust-lang.org/t/rpit-question-for-the-2024-edition/21631/3 "2024-10-01T10:49:14Z")

</div>

EDIT: I've updated my post. Please take a look.

---

<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:** [October 1, 2024, 5:16pm UTC](https://internals.rust-lang.org/t/rpit-question-for-the-2024-edition/21631/4 "2024-10-01T17:16:23Z")

</div>

> [@viktorlott](#):
>
> EDIT: I've updated my post. Please take a look.

Significant and multiple edits\[1\] and "please reread from scratch" don't work well on this forum. Just write a new comment next time.

> [@viktorlott](#):
>
> Wouldn't this default make sense?

Your example doesn't really make sense (it introduces a lifetime pulled out of nowhere for no reason),\[2\] so it's hard to know why you think it does. Or why you think it's a 2024 edition specific thing.

> [@viktorlott](#):
>
> `T: 'lifetime` tells us two things.
> 
> 1. `T` cannot outlive `'lifetime`.
> 2. All references inside `T` must live at least as long as `'lifetime`

The first bullet point is incorrect. If that's all some piece of code knows, it can't assume otherwise, but lifetime bounds on types aren't an upper limit (they're a lower limit). The second bullet point is true (indirectly).

`+ 'lifetime` in RPIT is an outlives bound on the opaque type. If that's all the caller knows (e.g. there's no other, longer lifetime bound), the caller can't assume it lives longer. It still means there are no references longer than `'lifetime` in the opaque type.

> [@viktorlott](#):
>
> `impl Trait + use<'lifetime>` means the hidden type is allowed to use the `'lifetime`. However, it doesn't imply that the hidden type must capture the lifetime unless it's actually needed. It also means that we only capture `'lifetime`, so if we have another lifetime that the hidden type captures, it will not allow it.
> 
> Am I wrong?

You'd probably have to define your terms better to get a great answer. `use<>`-ing is often called capturing.

`use<>`-ing a lifetime means the opaque type is considered parameterized by the lifetime,\[3\] and that the lifetime may be used in the definition of the hidden type (but doesn't have to be). It's analogous to a GAT parameter.\[4\]

Variance can allow you to do things like have multiple lifetimes on multiple inputs, return all the inputs, and still only parameterize the opaque type by one lifetime.

If all of the parameters of the opaque type are known to outlive some lifetime `'x`, the opaque type itself is known to outlive `'x`.

* * *

1. I currently see 7 on the OP and 5 on this one 

2. and `into_iterator` isn't a method 

3. if the lifetime differs, the opaque type differs, from the caller's perspective 

4. Note that opaque types never normalize, unlike GATs.

---

<div class="post-metadata">

**Author:** ![viktorlott](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/viktorlott/32/11282_2.png) [@viktorlott](https://internals.rust-lang.org/u/viktorlott)\
**Post date:** [October 2, 2024, 4:02pm UTC](https://internals.rust-lang.org/t/rpit-question-for-the-2024-edition/21631/5 "2024-10-02T16:02:19Z")

</div>

> [@quinedot](#):
>
> Significant and multiple edits[[1]](#footnote-138495-1) and "please reread from scratch" don't work well on this forum. Just write a new comment next time.

Yeah my bad, I will keep that in mind next time.

> [@quinedot](#):
>
> Your example doesn't really make sense (it introduces a lifetime pulled out of nowhere for no reason),[[2]](#footnote-138495-2) so it's hard to know why you think it does. Or why you think it's a 2024 edition specific thing.

I know that it's not easy to understand at first glance, so I will try to restate it further down.

> [@quinedot](#):
>
> The first bullet point is incorrect. If that's all some piece of code knows, it can't assume otherwise, but lifetime bounds on types aren't an upper limit (they're a lower limit). The second bullet point is true (indirectly).
> 
> `+ 'lifetime` in RPIT is an outlives bound on the opaque type. If that's all the caller knows (e.g. there's no other, longer lifetime bound), the caller can't assume it lives longer. It still means there are no references longer than `'lifetime` in the opaque type.

It seems that we have different interpretations of how to express a generic lifetime bound.

You mention that the first bullet point is incorrect because lifetime bounds on types aren't an upper limit but a lower limit, which is a valid observation. However, my point is more general (or based on a different premiss).

When I say "`T` cannot outlive `'lifetime`," I'm referring to the fact that any references within `T` are constrained by `'lifetime`. In other words, the validity of `T` depends on those references being valid for at least `'lifetime`, which effectively prevents `T` from outliving that bound when it comes to the lifetimes of its references.

I'm saying, a `T` cannot outlive its references.

You are saying, `T` must live at least as long as its references.

They lead to different conclusions.

So I think we are basically saying the same thing, but with different axioms?

I agree that this doesn't imply that `T` can't live longer in other contexts, but in terms of the references within `T`, the lifetime bound does ensure that `T` cannot outlive `'lifetime`.

---

<div class="post-metadata">

**Author:** ![kpreid](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kpreid/32/8484_2.png) [@kpreid](https://internals.rust-lang.org/u/kpreid)\
**Post date:** [October 2, 2024, 4:44pm UTC](https://internals.rust-lang.org/t/rpit-question-for-the-2024-edition/21631/6 "2024-10-02T16:44:15Z")

</div>

I think there is some confusion over quantification, i.e. which cases are being considered, here. If we have a generic parameter `<T: 'a>`, then:

- A valid concrete type to substitute for `T` is any type whose contained references all live for at least `'a`.

- A valid _usage of_ the type parameter `T`, within the generic item, is one which _does not assume_ that `T` lives longer than `'a`.

Both of these are true, but they are different perspectives on `T`; one is about the set of types that can be substituted for `T`, by the _caller/instantiator_ of the generic code, and the other is about the things that can be done with `T` as a whole, by the _callee/implementor_, the generic code itself.

These work oppositely in the same way that a rule of “_x_ must be less than _y_” has two opposite perspectives: if you are choosing _x_ then you can make it smaller than required if you like, and if you are choosing _y_ then you can make it bigger than required if you like.

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [March 26, 2026, 4:44pm UTC](https://internals.rust-lang.org/t/rpit-question-for-the-2024-edition/21631/7 "2026-03-26T16:44:15Z")

</div>

This topic was automatically closed 540 days after the last reply. New replies are no longer allowed.
