# Implementable trait aliases

**URL:** <https://internals.rust-lang.org/t/implementable-trait-aliases/18806>\
**Category:** language design\
**Created:** [May 10, 2023, 5:10am UTC](https://internals.rust-lang.org/t/implementable-trait-aliases/18806 "2023-05-10T05:10:15Z")\
**Posts on this page:** 11\
**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 10, 2023, 5:10am UTC](https://internals.rust-lang.org/t/implementable-trait-aliases/18806/1 "2023-05-10T05:10:15Z")

</div>

With the stabilization of GATs, there has been some discussion on how some standard library traits, like `Iterator` and `FnMut`, could be backward-compatibly GATified. [This recent blog post](https://smallcultfollowing.com/babysteps/blog/2023/05/09/giving-lending-and-async-closures/), for example. This is challenging because we can't break existing trait bounds.

This post proposes a possible solution, that I haven't seen discussed anywhere before.

1. Allow writing `impl` blocks for certain trait aliases, that only alias to a single trait plus some number of `where` clauses. For example,

```rust
trait Foo {
    type Assoc;
}

#[bikeshed::implementable_alias]
trait Bar = Foo where Self::Assoc: Copy;

impl Bar for u32 {
    type Assoc = u32;
}

```

1. Add `LendingIterator` (or `LendingFnMut`, etc) to the standard library, as a new trait.

```rust
pub trait LendingIterator {
    type Item<'a>;
    fn next(&mut self) -> Self::Item<'a>;

    // ...
}

```

1. Add some form of [variance bounds](https://internals.rust-lang.org/t/associated-type-variance-bounds/17598) to the language.

2. Delete the existing `Iterator` (or `FnMut`, etc) trait entirely, and replace it with an implementable alias.

```rust
#[bikeshed::implementable_alias]
pub trait Iterator = LendingIterator
where // bikesheddable
    for<'a> Self::Item<'a>: bivariant_in<'a>;

```

1. Allow omitting lifetime parameters in signatures when those parameters are determined to be bivariant.

* * *

Under this scheme, existing `impl` blocks keep their meaning, and so do existing trait bounds. The meaning of `Iterator` and `Iterator::Item` doesn't change at all, but APIs that want to start accepting `LendingIterator` can do so fully backwards-compatibly. Because there is only one trait, there are no coherence issues.

---

<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:** [May 10, 2023, 6:54am UTC](https://internals.rust-lang.org/t/implementable-trait-aliases/18806/2 "2023-05-10T06:54:39Z")

</div>

[Here’s](https://rust-lang.zulipchat.com/#narrow/stream/187312-wg-async/topic/trait.20Async.20without.20specialization/near/271035909) a rough idea I’ve had before that I want to develop further, eventually.

My idea was not to use trait aliases but still actual traits, while de-coupling the implementation from the trait itself. The `trait template` idea could also be useful if someone wanted to define e.g. convenient ways of implementing trait hierarchies without boilerplate (and without macros), e.g. someone might want to be able to implement `Eq + PartialEq + Ord + PartialOrd` all with a single `impl` defining the single method `cmp`, and this could become convenient with a `trait template OrdEq` that implies all of `Eq + PartialEq + Ord + PartialOrd`, implementing the missing methods such as `eq` _in terms_ of `cmp`.

A benefit of having `Iterator` still be an ordinary (yet no longer directly implementable) trait would be that it’s easy to avoid any need to new ideas like the “`bivariant_in`” you proposed. In the linked post, the `Async` and `Future` traits are analogues to the `LendinIterator` and `Iterator` traits in this case, respectively.

---

<div class="post-metadata">

**Author:** ![afetisov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/afetisov/32/8508_2.png) [@afetisov](https://internals.rust-lang.org/u/afetisov)\
**Post date:** [May 10, 2023, 9:55am UTC](https://internals.rust-lang.org/t/implementable-trait-aliases/18806/3 "2023-05-10T09:55:45Z")

</div>

`LendingIterator::next` is supposed to have the signature

```rust
fn next<'a>(&'a mut self) -> Option<Self::Item<'a>>

```

That's the point - you can borrow data from the specific `next` invokation. I don't see how your proposal helps to disentangle the input and output lifetimes, so that it would reduce to `Iterator`.

I also don't see how that's different from allowing defaulted lifetimes and associated types.

---

<div class="post-metadata">

**Author:** ![2e71828](https://avatars.discourse-cdn.com/v4/letter/2/3e96dc/32.png) [@2e71828](https://internals.rust-lang.org/u/2e71828)\
**Post date:** [May 10, 2023, 10:41am UTC](https://internals.rust-lang.org/t/implementable-trait-aliases/18806/4 "2023-05-10T10:41:06Z")

</div>

In the case that the definition of `Item<'a>` doesn't actually depend on `'a` for a particular `impl`, it can still be returned from `LendingIterator::next` without issue in a generic context. If there's a bound that represents this non-dependence property, then `Iterator` is equivalent to `LendingIterator where for<'a> Self::Item<'a>: DoesNotActuallyUse<'a>`.

---

<div class="post-metadata">

**Author:** ![afetisov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/afetisov/32/8508_2.png) [@afetisov](https://internals.rust-lang.org/u/afetisov)\
**Post date:** [May 10, 2023, 10:46am UTC](https://internals.rust-lang.org/t/implementable-trait-aliases/18806/5 "2023-05-10T10:46:50Z")

</div>

Kinda. But we don't have a way to express such bounds in current Rust. It looks like something fundamental and a bit like specialization (and thus may have problematic soundness).

Anyway, the trait syntax isn't the issue here.

---

<div class="post-metadata">

**Author:** ![2e71828](https://avatars.discourse-cdn.com/v4/letter/2/3e96dc/32.png) [@2e71828](https://internals.rust-lang.org/u/2e71828)\
**Post date:** [May 10, 2023, 12:04pm UTC](https://internals.rust-lang.org/t/implementable-trait-aliases/18806/6 "2023-05-10T12:04:13Z")

</div>

It is sort-of possible to express today, except that it only works for `'static` types due to the requirement for `where Self:'a` on GATs:

```rust
trait LendingIterator {
    type Item<'a> where Self:'a;
    fn next<'a>(&'a mut self)->Option<Self::Item<'a>>;
}

trait MyIterator {
    type Item;
    fn next(&mut self)->Option<Self::Item>;
}

impl<I,T> MyIterator for I where for<'a> I:'a + LendingIterator<Item<'a>=T> {
    type Item = T;
    fn next(&mut self)->Option<T> {
        <Self as LendingIterator>::next(self)
    }
}

struct A(i32);

impl LendingIterator for A {
    type Item<'a> = i32 where Self:'a;
    fn next<'a>(&'a mut self)->Option<i32> { unimplemented!() }
}

fn main() {
    let _:Box<dyn MyIterator<Item=i32>> = Box::new(A(42));
}

```

> **[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=d4a4d17f8ab1ba016cdfc34e3372ddd5)**
>
> A browser interface to the Rust compiler to experiment with the language

---

<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 10, 2023, 1:12pm UTC](https://internals.rust-lang.org/t/implementable-trait-aliases/18806/7 "2023-05-10T13:12:25Z")

</div>

I previously sketched out the idea of "variance bounds" [here](https://internals.rust-lang.org/t/associated-type-variance-bounds/17598). But it's not a unique idea; Niko's blog post has a version of it, for example ("`for<'a> LendingIterator<Item<'a> = U>`"). I didn't go into much detail here, because even alternative schemes will probably need something like it.

---

<div class="post-metadata">

**Author:** ![afetisov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/afetisov/32/8508_2.png) [@afetisov](https://internals.rust-lang.org/u/afetisov)\
**Post date:** [May 10, 2023, 2:23pm UTC](https://internals.rust-lang.org/t/implementable-trait-aliases/18806/8 "2023-05-10T14:23:09Z")

</div>

I don't see how that's relevant. The problem isn't variance, but the constraint on input and output lifetime parameters. Do you want to use `Self::Item` variance to arbitrarily expand the output lifetime at call site? This looks like a way stronger requirement than necessary, and also doesn't solve the issue at hand (the interface still isn't satisfied).

---

<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 10, 2023, 6:13pm UTC](https://internals.rust-lang.org/t/implementable-trait-aliases/18806/9 "2023-05-10T18:13:08Z")

</div>

> [@afetisov](#):
>
> Do you want to use `Self::Item` variance to arbitrarily expand the output lifetime at call site?

Yes, exactly. The point of variance bounds is to allow the borrow checker to make use of the information they encode. There isn't much reason to have them otherwise.

---

<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, 2023, 12:01am UTC](https://internals.rust-lang.org/t/implementable-trait-aliases/18806/10 "2023-05-25T00:01:09Z")

</div>

RFC posted: [RFC: Implementable trait aliases by Jules-Bertholet · Pull Request #3437 · rust-lang/rfcs · GitHub](https://github.com/rust-lang/rfcs/pull/3437)

---

<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:** [August 23, 2023, 12:01am UTC](https://internals.rust-lang.org/t/implementable-trait-aliases/18806/11 "2023-08-23T00:01:42Z")

</div>

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