# Extending \`for\<'a\>\` construct

**URL:** <https://internals.rust-lang.org/t/extending-for-a-construct/16581>\
**Category:** language design\
**Created:** [May 5, 2022, 10:33am UTC](https://internals.rust-lang.org/t/extending-for-a-construct/16581 "2022-05-05T10:33:01Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![tema2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tema2/32/6498_2.png) [@tema2](https://internals.rust-lang.org/u/tema2)\
**Post date:** [May 5, 2022, 10:33am UTC](https://internals.rust-lang.org/t/extending-for-a-construct/16581/1 "2022-05-05T10:33:01Z")

</div>

## The goal: Allow bounded universal quantification;

The core problem current form has is that when inference tries to select a lifetime that'd fit `for<'a> ...` bound it always ends up with `'static`, which is very limiting.

### The imagined syntax:

`for<%list_of_introduced_parameters; %list_of contraints> %bound`

#### An example

`for<'c; 's: 'c> F: Fn(&'c Connection,&'s SqlStr) // 's is defined in containing scope`

#### Semantics

This construct signifies that its following bound is generic over all lifetimes **that statisfy a %list\_of\_constraints** - the bold is the difference with current form.

EDIT: Two ways of reading this:

First one is left to right: "for all `'c`, `'s` shall outlive `'c`" =\> from this `'s` = `'static` and `'c` still has no constraint of it. This way doesn't fit us.

Second way is right to left: "exists `'s` =\> exists a set of lifetimes `A`, such that for any `'a` є `A` holds the following: `'s : 'a`". This is the intended semantics.

#### Example motivation:

[Sabrina's recent post](https://sabrinajewson.org/blog/the-better-alternative-to-lifetime-gats#where-real-gats-fall-short) - it has great example in the very beginning:

```rust
fn print_items<I>(mut iter: I)
where
	I: LendingIterator,
	for<'a> I::Item<'a>: Debug, //(1)
{
	while let Some(item) = iter.next() {
		println!("{item:?}");
	}
}

```

With this extension, we could write it correctly:

```rust
fn print_items<'i,I>(mut iter: I)
where
	I: LendingIterator + 'i,
	for<'a; 'i: 'a> I::Item<'a>: Debug, //(2)
    //this means that for every lifetime that doesn't outlive the iterator,
    //`Item: Debug` is true.
{
	while let Some(item) = iter.next() {
		println!("{item:?}");
	}
}

```

The core point is that in this line:  
`print_items::<WindowsMut<'_, _, 2>>(windows_mut(&mut [1, 2, 3]));`  
the argument's associated lifetime isn't infered (and forced) to be `'static` by (1) and instead is only forced to be `'i` by (2).

Also, there are examples of APIs that are otherwise impossible [here](https://github.com/diesel-rs/diesel/issues/399).

---

<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 5, 2022, 12:42pm UTC](https://internals.rust-lang.org/t/extending-for-a-construct/16581/2 "2022-05-05T12:42:12Z")

</div>

Minor note: `for<'a, 'b: 'a>` should introduce two lifetimes, `'a` and `'b`. What you want is more `for<'a> where 'b: 'a`, which will require parentheticals, but should work.

A few potential ways of writing it:

```rust
where
    for<'a> where 'i: 'a, => I::Item<'a>: Debug,
    for<'a> (where 'i: 'a,) I::Item<'a>: Debug,
    for<'a> (I::Item<'a>: Debug where 'i: 'a,),
    for<'a> (I::Item<'a>: Debug) + 'i: 'a,

```

---

<div class="post-metadata">

**Author:** ![y86-dev](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/y86-dev/32/9867_2.png) [@y86-dev](https://internals.rust-lang.org/u/y86-dev)\
**Post date:** [May 5, 2022, 1:16pm UTC](https://internals.rust-lang.org/t/extending-for-a-construct/16581/3 "2022-05-05T13:16:31Z")

</div>

I think the syntax from the blog post also could be used (it also feels very intuitive to me and i once tried to use it like this, without knowing that it did not exist):

```rust
where
    for<'a where 'i: 'a> I::Item<'a>: Debug,

```

This lists the constraints right at the definition site, which i think is advantageous over

> [@CAD97](#):
>
> ```rust
> for<'a> (I::Item<'a>: Debug where 'i: 'a,),
> for<'a> (I::Item<'a>: Debug) + 'i: 'a,
> 
> ```

It also might be better for the parser, because it could reuse the existing `where`-clause parsing when it encounters the keyword inside of the `<>`.

---

<div class="post-metadata">

**Author:** ![cuviper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cuviper/32/1897_2.png) [@cuviper](https://internals.rust-lang.org/u/cuviper)\
**Post date:** [May 5, 2022, 5:00pm UTC](https://internals.rust-lang.org/t/extending-for-a-construct/16581/4 "2022-05-05T17:00:35Z")

</div>

If you do want to introduce multiple lifetimes, does one `where` go at the end?

```rust
    for <'a, 'b where 'i: 'a, 'j: 'b>

```

---

<div class="post-metadata">

**Author:** ![petrochenkov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/petrochenkov/32/2784_2.png) [@petrochenkov](https://internals.rust-lang.org/u/petrochenkov)\
**Post date:** [May 5, 2022, 5:15pm UTC](https://internals.rust-lang.org/t/extending-for-a-construct/16581/5 "2022-05-05T17:15:42Z")

</div>

What do `'b` and `'i` mean in these examples if they are never introduced?

If all lifetimes are introduced (which I suppose they must?), then the already existing `for<'a, 'b: 'a>` syntax is enough to express everything.

---

<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 5, 2022, 5:23pm UTC](https://internals.rust-lang.org/t/extending-for-a-construct/16581/6 "2022-05-05T17:23:44Z")

</div>

My assumption with `for<'a, 'b: 'a>` was that it would introduce both `'a` and `'b` (be `for<'a> for<'b: 'a>`) like with other lifetime introducers (e.g. `impl<'a, 'b: 'a>`).

The `'i` example was implicitly attached to `fn print_items<'i, I>(mut iter: I)` (from the OP).

---

<div class="post-metadata">

**Author:** ![tema2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tema2/32/6498_2.png) [@tema2](https://internals.rust-lang.org/u/tema2)\
**Post date:** [May 5, 2022, 5:38pm UTC](https://internals.rust-lang.org/t/extending-for-a-construct/16581/7 "2022-05-05T17:38:34Z")

</div>

> [@y86-dev](#):
>
> ```rust
> where
> for<'a where 'i: 'a> I::Item<'a>: Debug,
> 
> ```

That's indeed better!

> [@cuviper](#):
>
> If you do want to introduce multiple lifetimes, does one `where` go at the end?
> 
> ` for <'a, 'b where 'i: 'a, 'j: 'b>`

Yes, only one `where` here - it serves as readable delimiter.

> [@petrochenkov](#):
>
> If all lifetimes are introduced (which I suppose they must?), then the already existing `for<'a, 'b: 'a>` syntax is enough to express everything.

No, lifetimes are introduced before `where`, after it we put constraints on them.

Maybe we even want a must use property, so that bounds coming after `where` in `for<.. where ..>` must use (all of) introduced in clause lifetimes.

---

<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 5, 2022, 5:54pm UTC](https://internals.rust-lang.org/t/extending-for-a-construct/16581/8 "2022-05-05T17:54:13Z")

</div>

> [@tema2](#):
>
> Maybe we even want a must use property

I think it's reasonable to require the bounds to only put constraints on/involving the introduced lifetimes, but I think _requiring_ all of the introduced lifetimes to be bounded is unnecessary (and can be sidestepped anyway with `'a:` or `'a: 'static`).

---

<div class="post-metadata">

**Author:** ![LegionMammal978](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/legionmammal978/32/8985_2.png) [@LegionMammal978](https://internals.rust-lang.org/u/LegionMammal978)\
**Post date:** [May 5, 2022, 6:26pm UTC](https://internals.rust-lang.org/t/extending-for-a-construct/16581/9 "2022-05-05T18:26:49Z")

</div>

See also the discussion around [issue 25860](https://github.com/rust-lang/rust/issues/25860), which has another alternative syntax:

```rust
where
    for<'a> where<'i: 'a> I::Item<'a>: Debug,

```

Personally, I like the symmetry between the `for` and `where`.

---

<div class="post-metadata">

**Author:** ![y86-dev](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/y86-dev/32/9867_2.png) [@y86-dev](https://internals.rust-lang.org/u/y86-dev)\
**Post date:** [May 5, 2022, 8:37pm UTC](https://internals.rust-lang.org/t/extending-for-a-construct/16581/10 "2022-05-05T20:37:04Z")

</div>

> [@CAD97](#):
>
> I think it's reasonable to require the bounds to only put constraints on/involving the introduced lifetimes, but I think _requiring_ all of the introduced lifetimes to be bounded is unnecessary (and can be sidestepped anyway with `'a:` or `'a: 'static` ).

I agree, we still could later drop this requirement, but for the moment this seems good. (i think you meant `'static: 'a`)

> [@LegionMammal978](#):
>
> See also the discussion around [issue 25860](https://github.com/rust-lang/rust/issues/25860), which has another alternative syntax:
> 
> ```rust
> where
> for<'a> where<'i: 'a> I::Item<'a>: Debug,
> 
> ```
> 
> Personally, I like the symmetry between the `for` and `where` .

Hmm I find this syntax a little bit confusing, because it suggests, that such a `where` can also be used without the `for` (IIUC this is not possible/mentioned in the post).

---

<div class="post-metadata">

**Author:** ![LegionMammal978](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/legionmammal978/32/8985_2.png) [@LegionMammal978](https://internals.rust-lang.org/u/LegionMammal978)\
**Post date:** [May 5, 2022, 9:21pm UTC](https://internals.rust-lang.org/t/extending-for-a-construct/16581/11 "2022-05-05T21:21:08Z")

</div>

> [@y86-dev](#):
>
> Hmm I find this syntax a little bit confusing, because it suggests, that such a `where` can also be used without the `for` (IIUC this is not possible/mentioned in the post).

True, that is a potential issue. But I still see it as the most visually consistent option overall:

1. `for<...> where ... (sep) Bounds`: it can be difficult to tell apart the `where` bounds from the trait bounds at a glance. Also, it can introduce confusion between the inner and outer `where`.
2. `for<...; ...> Bounds`: the syntax difference between `,` and `;` is a bit too subtle for my liking.
3. `for<... where ...> Bounds`: this is workable, but it seems weird to see the lone `where` keyword inside the angle brackets. Currently, the only keywords within angle brackets are from trait objects (`Box<dyn Trait>`) and HRTBs (`impl<T: for<'a> Trait<'a>> ...`), both of which are visually attached to the following trait name.
4. `for<...> where<...> Bounds`: my preferred syntax. The angle brackets help distinguish the inner `where` from the outer `where`. No special parsing is needed for the interior of the brackets, since they contain an ordinary list of lifetime bounds. As you mentioned, there's a risk that the `where` could be seen as independent from the `for`, but I think this can be mitigated with a good error message.

Of course, I'd always be open to a new option. I recall the debates over how to name the `let ... else` construct, going through various permutations of `unless let` and `if !let` and `if not let`, before the current name was proposed and quickly adopted for the RFC.

---

<div class="post-metadata">

**Author:** ![y86-dev](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/y86-dev/32/9867_2.png) [@y86-dev](https://internals.rust-lang.org/u/y86-dev)\
**Post date:** [May 5, 2022, 9:40pm UTC](https://internals.rust-lang.org/t/extending-for-a-construct/16581/12 "2022-05-05T21:40:00Z")

</div>

1. also seems like it might be difficult for the parser (and really should not be used IMO)
2. yes definitely too subtle When comparing 3 and 4, look at how it looks with many bounds:

```rust
for<
    'a,
    'b,
    'c,
    'd,
    'e,
    'f,
    where
        'a: 'b,
        'c: 'f,
        'd: 'e,
> fn foo(...);
// vs
for<
    'a,
    'b,
    'c,
    'd,
    'e,
    'f,
> where<
    'a: 'b,
    'c: 'f,
    'd: 'e
> fn foo(...);

```

In option 3, i like that the `>` of the `for` is in front of `fn`, but the additonal indentation is not really nice (maybe indent the `where` by -1 and do not indent the bounds by +1). In option 4, i do not like the distance between the end of the `for<>` and `fn`. But overall I like option 4 more than putting the bounds even further away from the `for`. I think they should stay relatively close and be unambiguously connected.

---

<div class="post-metadata">

**Author:** ![cuviper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cuviper/32/1897_2.png) [@cuviper](https://internals.rust-lang.org/u/cuviper)\
**Post date:** [May 5, 2022, 10:46pm UTC](https://internals.rust-lang.org/t/extending-for-a-construct/16581/13 "2022-05-05T22:46:36Z")

</div>

(Realistically, something has gone wrong if you're juggling that many lifetimes at once...)

---

<div class="post-metadata">

**Author:** ![y86-dev](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/y86-dev/32/9867_2.png) [@y86-dev](https://internals.rust-lang.org/u/y86-dev)\
**Post date:** [May 6, 2022, 7:43am UTC](https://internals.rust-lang.org/t/extending-for-a-construct/16581/14 "2022-05-06T07:43:47Z")

</div>

Yes this might be a bit excessive, but if you use lifetimes with longer names, the construct would also be need to be indented (or if you set your linewidth to something short). So I think we need to consider it.

---

<div class="post-metadata">

**Author:** ![tema2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tema2/32/6498_2.png) [@tema2](https://internals.rust-lang.org/u/tema2)\
**Post date:** [May 6, 2022, 10:09am UTC](https://internals.rust-lang.org/t/extending-for-a-construct/16581/15 "2022-05-06T10:09:48Z")

</div>

Reallistically, the only difference [here](https://internals.rust-lang.org/t/extending-for-a-construct/16581/12) is `>` and `<` around the `where`:

> [@y86-dev](#):
>
> `> where <`

VS

> [@y86-dev](#):
>
> `where`

And thus,

> [@LegionMammal978](#):
>
> `for<... where ...> Bounds` : this is workable, but it seems weird to see the lone `where` keyword inside the angle brackets. Currently, the only keywords within angle brackets are from trait objects ( `Box<dyn Trait>` ) and HRTBs ( `impl<T: for<'a> Trait<'a>> ...` ), both of which are visually attached to the following trait name.

if we take fuller single line example:

- `impl<'b,T: for<'a where 'b: 'a > Trait> ...`
- `impl<'b,T: for<'a> where<'b: 'a > Trait> ...`

Isn't the first cleaner? The same applies for the multiline case.

---

<div class="post-metadata">

**Author:** ![y86-dev](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/y86-dev/32/9867_2.png) [@y86-dev](https://internals.rust-lang.org/u/y86-dev)\
**Post date:** [May 6, 2022, 10:42am UTC](https://internals.rust-lang.org/t/extending-for-a-construct/16581/16 "2022-05-06T10:42:26Z")

</div>

Lets just gauge the general opinion on this. If someone comes up with a different syntax that has majority support/introduces other benefits, then we can just use that, otherwise this could be baked into some rfc.

_Poll ([view on site](https://internals.rust-lang.org/t/extending-for-a-construct/16581/16))_

This of course assumes that adding the possibility for these bounds is indeed a welcome change (I think the majority of posts here reflect that it is).

---

<div class="post-metadata">

**Author:** ![jdahlstrom](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jdahlstrom/32/3351_2.png) [@jdahlstrom](https://internals.rust-lang.org/u/jdahlstrom)\
**Post date:** [May 6, 2022, 1:11pm UTC](https://internals.rust-lang.org/t/extending-for-a-construct/16581/17 "2022-05-06T13:11:29Z")

</div>

> [@LegionMammal978](#):
>
> ```rust
> where
> for<'a> where<'i: 'a> I::Item<'a>: Debug,
> 
> ```

This has the disadvantage of being inconsistent with `where` bounds in other contexts, eg.

```rust
    struct Foo<T> where T: Debug // not Foo<T> where<T: Debug>

```

---

<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 6, 2022, 9:00pm UTC](https://internals.rust-lang.org/t/extending-for-a-construct/16581/18 "2022-05-06T21:00:59Z")

</div>

If the only thing `for<>` constraints could do would be putting bounds on introduced parameters, I'd prefer `for<where>`. But something that gives me pause is the possibility of it being more general, for example perhaps [some way to declare free closure lifetimes or otherwise drive capture inference.](https://github.com/rust-lang/rfcs/pull/3216#issuecomment-1064219041) That is, things that might read weird _within_ a `for<>`.

I grant it's a rather vague concern, given that I haven't imagined or seen proposed any good way to declare these sorts of things at all.

---

<div class="post-metadata">

**Author:** ![tema2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tema2/32/6498_2.png) [@tema2](https://internals.rust-lang.org/u/tema2)\
**Post date:** [May 8, 2022, 12:36pm UTC](https://internals.rust-lang.org/t/extending-for-a-construct/16581/19 "2022-05-08T12:36:17Z")

</div>

Made [pull request](https://github.com/rust-lang/rfcs/pull/3261) into RFC repo, thanks for participating.

---

<div class="post-metadata">

**Author:** ![y86-dev](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/y86-dev/32/9867_2.png) [@y86-dev](https://internals.rust-lang.org/u/y86-dev)\
**Post date:** [May 8, 2022, 1:34pm UTC](https://internals.rust-lang.org/t/extending-for-a-construct/16581/20 "2022-05-08T13:34:13Z")

</div>

> [@quinedot](#):
>
> But something that gives me pause is the possibility of it being more general, for example perhaps [some way to declare free closure lifetimes or otherwise drive capture inference.](https://github.com/rust-lang/rfcs/pull/3216#issuecomment-1064219041) That is, things that might read weird _within_ a `for<>` .

Hmm that is an interesting point... But when we would have `exists<>` then we could also allow a `where` inside that one. Granted you would need to write multiple `where`, but when we reach that point, allowing a `where<>` might also not be too far fetched (you would allow multiple where clauses at different points, but I think that is not really a bad thing).

> [@tema2](#):
>
> Made [pull request](https://github.com/rust-lang/rfcs/pull/3261) into RFC repo, thanks for participating.

Nice, what I am also wondering, are we going to allow `for<'a: 'b>` as a shorthand for `for<'a where 'a: 'b>`? I think this seems very natural considering you can do it in `impl<'a: 'b>` and at type-def.

Edit: Of course this makes only sense, if we allow `for<'a where 'a: 'b>` in the first place

[Next page](https://internals.rust-lang.org/t/extending-for-a-construct/16581.md?page=2)
