# HRTB Sugar

**URL:** <https://internals.rust-lang.org/t/hrtb-sugar/15293>\
**Category:** Uncategorized\
**Created:** [September 7, 2021, 1:34am UTC](https://internals.rust-lang.org/t/hrtb-sugar/15293 "2021-09-07T01:34:23Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![ibraheemdev](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ibraheemdev/32/13406_2.png) [@ibraheemdev](https://internals.rust-lang.org/u/ibraheemdev)\
**Post date:** [September 7, 2021, 1:34am UTC](https://internals.rust-lang.org/t/hrtb-sugar/15293/1 "2021-09-07T01:34:23Z")

</div>

Now that GATs are close to stabilizing, HRTBs are going to be used much more for associated type bounds:

```rust
trait Foo {
    type Output<'a>;
    fn foo(&self) -> Self::Output<'_>;
}

fn foo<F>(foo: F)
where
    F: Foo,
    for<'a> F::Output<'a>: Clone,
{
    // ...
}

```

What if the elided lifetime could be used as a simpler version of this?

```rust
fn foo<F>(foo: F)
where
    F: Foo,
    F::Output<'_>: Clone,
{
    // ...
}

```

This could also interact nicely with `feature(associated_type_bounds)`:

```rust
fn foo<F>(foo: F)
where
    F: Foo<Output<'_>: Clone>,
{
    // ...
}

```

We'll also need some way to express HRTB bounds with type parameters:

```rust
trait Foo {
    type Output<T>;
    fn foo<T>(self) -> Self::Output<T>;
}

fn foo<F>(foo: F)
where
    F: Foo,
    for<T: Clone> F::Output<T>: Clone // <---
{
    // ...
}

```

And perhaps `_` could be used here as well as sugar, applying the bound on the associated type to the elided generic parameter as default behavior:

```rust
fn foo<F>(foo: F)
where
    F: Foo,
    F::Output<_>: Clone
    // => for<T: Clone> F::Output<T>: Clone
{
    // ...
}

```

Again, would work well with `feature(associated_type_bounds)`:

```rust
fn foo<F>(foo: F)
where
    F: Foo<Output<_>: Clone>,
{
    // ...
}

```

Note that neither `'_` or `_` are allowed in the proposed position, so this would be a non-breaking change.

_This idea originally came out of [thinking about async function syntax](https://internals.rust-lang.org/t/an-alternative-syntax-for-async-functions/15255)._

---

<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 7, 2021, 2:19am UTC](https://internals.rust-lang.org/t/hrtb-sugar/15293/2 "2021-09-07T02:19:32Z")

</div>

> [@ibraheemdev](#):
>
> And perhaps `_` could be used here as well as sugar, applying the bound on the associated type to the elided generic parameter as default behavior:

This is the only one I disagree with. While this follows the same logic as `#[derive]`, I'd personally more expect this syntax to mean

```rust
fn foo<F>(foo: F)
where
    F: Foo,
    F::Output<_>: Clone
    // => for<T> F::Output<T>: Clone
{
    // ...
}

```

with only the [implied bounds](https://rust-lang.github.io/rfcs/2089-implied-bounds.html) (once those are stable).

Due to the two valid interpretations (`#[derive]` style or `impl` style), I'd lean on not doing this one.

I'm generally green on allowing the elided lifetime for this purpose, though we should be careful that it cannot be confused with the original elided lifetime (from `&self` or the single input lifetime).

---

<div class="post-metadata">

**Author:** ![H2CO3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/h2co3/32/2849_2.png) [@H2CO3](https://internals.rust-lang.org/u/H2CO3)\
**Post date:** [September 7, 2021, 2:20am UTC](https://internals.rust-lang.org/t/hrtb-sugar/15293/3 "2021-09-07T02:20:19Z")

</div>

> [@ibraheemdev](#):
>
> so this would be a non-breaking change.

Maybe technically it wouldn't, but conceptually it's very different from what elided lifetimes mean currently. Lifetime elision is already problematic enough. Let's definitely not override identical syntax to mean implicit HRTBs, too.

---

<div class="post-metadata">

**Author:** ![ibraheemdev](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ibraheemdev/32/13406_2.png) [@ibraheemdev](https://internals.rust-lang.org/u/ibraheemdev)\
**Post date:** [September 7, 2021, 3:19am UTC](https://internals.rust-lang.org/t/hrtb-sugar/15293/4 "2021-09-07T03:19:22Z")

</div>

What implied bounds would there be for HRTBs?

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [September 7, 2021, 3:39am UTC](https://internals.rust-lang.org/t/hrtb-sugar/15293/5 "2021-09-07T03:39:09Z")

</div>

Another take on a potential meaning for `'_` in associated types is

> <https://github.com/rust-lang/rfcs/pull/2548>
>
> \[Rendered\](https://github.com/scottmcm/rfcs/blob/associated-type-lifetime-elisio…n/text/0000-associated-type-lifetime-elision.md)
> 
> \## Summary
> 
> This RFC extends lifetime elision to associated types, treating them as output positions using the existing rules.
> 
> This is particularly helpful for the usual \`IntoIterator\` pattern:
> \`\`\`rust
> impl\<T\> IntoIterator for &Container\<T\> {
> type Item = &T;
> type IntoIter = Iter\<'\_, T\>;
> fn into\_iter(self) -\> Self::IntoIter { self.iter() }
> }
> \`\`\`
> No \`'a\`s needed!
> 
> \## Thanks
> 
> To @Centril, @moxian, and @rkruppe for commenting on this on Discord.

I think the "associated types are outputs" from that is correct, though that RFC didn't address GATs.

---

<div class="post-metadata">

**Author:** ![robinm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/robinm/32/6255_2.png) [@robinm](https://internals.rust-lang.org/u/robinm)\
**Post date:** [September 8, 2021, 7:16am UTC](https://internals.rust-lang.org/t/hrtb-sugar/15293/6 "2021-09-08T07:16:42Z")

</div>

> [@ibraheemdev](#):
>
> ```rust
> for<T: Clone> F::Output<T>: Clone
> {
> 
> ```

I would personnaly prefer `F::Output<T: Clone>: Clone`. With the associated\_type\_bounds version being `F: Foo<Output<T: Clone>: Clone>`

---

<div class="post-metadata">

**Author:** ![ibraheemdev](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ibraheemdev/32/13406_2.png) [@ibraheemdev](https://internals.rust-lang.org/u/ibraheemdev)\
**Post date:** [September 8, 2021, 4:07pm UTC](https://internals.rust-lang.org/t/hrtb-sugar/15293/7 "2021-09-08T16:07:13Z")

</div>

> [@robinm](#):
>
> `F::Output<T: Clone>: Clone`

Maybe `F::Output<_: Clone>: Clone`?

---

<div class="post-metadata">

**Author:** ![robinm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/robinm/32/6255_2.png) [@robinm](https://internals.rust-lang.org/u/robinm)\
**Post date:** [September 8, 2021, 4:19pm UTC](https://internals.rust-lang.org/t/hrtb-sugar/15293/8 "2021-09-08T16:19:08Z")

</div>

Yes.

---

<div class="post-metadata">

**Author:** ![ratmice](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ratmice/32/4917_2.png) [@ratmice](https://internals.rust-lang.org/u/ratmice)\
**Post date:** [September 8, 2021, 5:02pm UTC](https://internals.rust-lang.org/t/hrtb-sugar/15293/9 "2021-09-08T17:02:43Z")

</div>

I haven't looked terribly closely or recently at this, bugs/features for it, or what would be involved; but last time I looked HRTB's weren't allowed on aliases... I'd probably rather see HRTBS on aliases work over some form of syntactic sugar personally... if possible.

---

<div class="post-metadata">

**Author:** ![ibraheemdev](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ibraheemdev/32/13406_2.png) [@ibraheemdev](https://internals.rust-lang.org/u/ibraheemdev)\
**Post date:** [September 8, 2021, 5:11pm UTC](https://internals.rust-lang.org/t/hrtb-sugar/15293/10 "2021-09-08T17:11:06Z")

</div>

Can you explain what you mean by this? How would HRTBs on type? aliases help here?

---

<div class="post-metadata">

**Author:** ![ratmice](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ratmice/32/4917_2.png) [@ratmice](https://internals.rust-lang.org/u/ratmice)\
**Post date:** [September 8, 2021, 5:50pm UTC](https://internals.rust-lang.org/t/hrtb-sugar/15293/11 "2021-09-08T17:50:39Z")

</div>

I can't find the example where I had tried to use HRTB's, but in general all bounds (even lower ranked) are currently ignored on type aliases, they do not currently help at all, because ` warning: bounds on generic parameters are not enforced in type aliases`

But here is one which shows where bounds in general don't work on aliases.

```rust
type Foo<A: Copy> = fn(A) -> A;

fn foo(f: Foo<()>) -> () {
    f(())
}

```

Does that help explain what I meant?

---

<div class="post-metadata">

**Author:** ![ibraheemdev](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ibraheemdev/32/13406_2.png) [@ibraheemdev](https://internals.rust-lang.org/u/ibraheemdev)\
**Post date:** [September 8, 2021, 6:42pm UTC](https://internals.rust-lang.org/t/hrtb-sugar/15293/12 "2021-09-08T18:42:00Z")

</div>

Ah, I see, but how does that fit in with higher ranked GAT bounds?

---

<div class="post-metadata">

**Author:** ![ratmice](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ratmice/32/4917_2.png) [@ratmice](https://internals.rust-lang.org/u/ratmice)\
**Post date:** [September 8, 2021, 7:18pm UTC](https://internals.rust-lang.org/t/hrtb-sugar/15293/13 "2021-09-08T19:18:24Z")

</div>

Honestly I'm just not a fan of implicit or implied syntax for most anything. My hope was that part of the problem with bounds is they tend to get repeated in places (GAT's probably less so however bounds are bounds higher ranged or otherwise).

Anyhow the hope was that alias bounds would just reduce the need for sugar all together, since you could just use the short alias rather than repeating the entire bound everywhere.

---

<div class="post-metadata">

**Author:** ![gasche](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/gasche/32/1930_2.png) [@gasche](https://internals.rust-lang.org/u/gasche)\
**Post date:** [September 10, 2021, 1:39pm UTC](https://internals.rust-lang.org/t/hrtb-sugar/15293/14 "2021-09-10T13:39:12Z")

</div>

As an outsider to the Rust community that is noneless interested in language design discussions, the acronyms here took some deciphering. (I would encourage people to expand them in the first post or so, to make it easier to follow out of context.)

I believe that:

- GAT means Generic Associated Types (see [RFCs#1598](https://github.com/rust-lang/rfcs/pull/1598)).
- for HRTB my guess would be Higher-Ranked Trait Bounds, see [the rustc dev guide](https://rustc-dev-guide.rust-lang.org/traits/hrtb.html).

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [December 9, 2021, 1:39pm UTC](https://internals.rust-lang.org/t/hrtb-sugar/15293/15 "2021-12-09T13:39:56Z")

</div>

Closed on December 9, 2021, 1:39pm UTC

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