# Idea: Existential trait bounds

**URL:** <https://internals.rust-lang.org/t/idea-existential-trait-bounds/12868>\
**Category:** language design\
**Created:** [August 10, 2020, 4:52pm UTC](https://internals.rust-lang.org/t/idea-existential-trait-bounds/12868 "2020-08-10T16:52:26Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![josh65536](https://avatars.discourse-cdn.com/v4/letter/j/a587f6/32.png) [@josh65536](https://internals.rust-lang.org/u/josh65536)\
**Post date:** [August 10, 2020, 4:52pm UTC](https://internals.rust-lang.org/t/idea-existential-trait-bounds/12868/1 "2020-08-10T16:52:26Z")

</div>

I've run into a problem with unconstrained type parameters where it turns out that the unconstrained type parameter is never even used. Let's say we have code like this:

```rust
trait Trait {
    type Assoc: AssocTrait;
    // items
}

trait SuperTrait {
    fn super_fn() -> Self;
}

trait AssocTrait {
    fn assoc_fn() -> Self;
}

trait Hktrait<T>: SuperTrait { /* items */ }

struct Struct<A: AssocTrait, U> {
    a: A,
    u: U,
}

impl<T: Trait, U: Hktrait<T>> SuperTrait for Struct<T::Assoc, U>
where
    T::Assoc: AssocTrait
{
    fn super_fn() -> Self {
        Self {
            a: T::Assoc::assoc_fn(),
            u: U::super_fn(),
        }
    }
}

```

The type parameter `T` is unconstrained. If the same type `U` implements `Hktrait<T>` for two different types `T`, then the compiler would have to guess what `T` is, so [RFC #447](https://github.com/rust-lang/rfcs/blob/master/text/0447-no-unused-impl-parameters.md) was made to avoid that. However, in this case, `T` is never used. The implementation can almost be written as

```rust
impl<A: AssocTrait, U: Hktrait<T>> SuperTrait for Struct<A, U>
{
    fn super_fn() -> Self {
        Self {
            a: A::assoc_fn(),
            u: <U as SuperTrait>::super_fn(), // expanded for emphasis
        }
    }
}

```

After all, `T::Assoc` is just `A`, and `U` has just one implementation of `SuperTrait` no matter how many implementations it has of `Hktrait<T>` for different `T`. Unfortunately, there's still a pesky little `T` in the `impl` type parameters. If we could write something like

```rust
impl<A: AssocTrait, U: exists<T> Hktrait<T>> SuperTrait for Struct<A, U>
{
    fn super_fn() -> Self {
        Self {
            a: A::assoc_fn(),
            u: U::super_fn(),
        }
    }
}

```

and then enforce that the implementation cannot depend on `T`, that would solve the issue and even allow us to constrain `U` in `Struct` without a `PhantomData`:

```rust
struct Struct<A: AssocTrait, U: exists<T> Hktrait<T>> {
    a: A,
    u: U,
}

```

and then still be able to write an implementation of some other trait `Hktrait2<T>` for `Struct<T::Assoc, U>`.

However, the issue could just as well be solved by relaxing the bound on the implementation of `SuperTrait` to `U: SuperTrait` instead of `U: Hktrait<T>`. In addition, it introduces new syntax, and the logic for checking whether a type parameter satisfies an existential trait bound, especially if it satisfies another existential trait bound, would need to be figured out. So is this feature interesting and useful enough for an RFC?

For context, the problem was encountered in `cgmath` attempting to implement `One` for `Decomposed`. It turned out in that case that since `Mul` needed to be implemented too and that implementation depended on `T`, this wouldn't work in that case.

---

<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:** [August 10, 2020, 5:07pm UTC](https://internals.rust-lang.org/t/idea-existential-trait-bounds/12868/2 "2020-08-10T17:07:38Z")

</div>

> [@josh65536](#):
>
> However, the issue could just as well be solved by relaxing the bound on the implementation of `SuperTrait` to `U: SuperTrait` instead of `U: Hktrait<T>` .

Seems like exactly what you’d want here.

* * *

> [@josh65536](#):
>
> So is this feature interesting and useful enough for an RFC?

I think your feature just doesn’t work. What would `U: exists<T> Hktrait<T>` offer you in a function definition? Sure, all the supertraits that don’t mention `T` anymore, but you could just write those supertraits instead then. Anything else? One could think, maybe methods of `Hktrait` that don’t mention `T`, but that won’t work since the implementation of those can still depend on the choice of `T`. One case that _I think should_ work is when we have `U: Hktrait<T>` for all `T`, since then there’s the canonical choice of just using methods from the generic (over `T`) implementation (even in the presence of specialization), but I don’t think that was your intention in the example. Or, if `U: Hktrait<T>` is only implemented for a single `T` per `U`, you can make `T` an associated type.

Having talked about generic implementations, I think there is a case to be had for a feature allowing `U: for<T> Hktrait<T>`, especially for `Fn`-traits, where this would go hand in hand with support for generic closures.

---

<div class="post-metadata">

**Author:** ![josh65536](https://avatars.discourse-cdn.com/v4/letter/j/a587f6/32.png) [@josh65536](https://internals.rust-lang.org/u/josh65536)\
**Post date:** [August 11, 2020, 3:31am UTC](https://internals.rust-lang.org/t/idea-existential-trait-bounds/12868/3 "2020-08-11T03:31:06Z")

</div>

About generic closures, I saw the [RFC pull request](https://github.com/rust-lang/rfcs/pull/1650) for that, and it seems like it was blocked by not having HRTBs for types and a trait checking revamp. Would it be a good idea to write a draft about how `U: for<T> Hktrait<T>` should work?

---

<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:** [August 13, 2020, 4:18pm UTC](https://internals.rust-lang.org/t/idea-existential-trait-bounds/12868/4 "2020-08-13T16:18:17Z")

</div>

> [@steffahn](#):
>
> Having talked about generic implementations, I think there is a case to be had for a feature allowing `U: for<T> Hktrait<T>` , especially for `Fn` -traits, where this would go hand in hand with support for generic closures.

I’ve wanted this a few times when defining supertraits. If I have a trait definition like this:

```rust
trait Trait {
    type Result;
    fn foo<T:OtherTrait>(&self, t:T)->Self::Result;
}

```

It would be nice to be able to lift the type parameter up to the trait level so that `Result` can be dependent on `T` and we have a trait that can be object-safe:

```rust
trait Trait: for<T:OtherTrait> Foo<T> {}
trait Foo<T:OtherTrait> {
    type Result;
    fn foo(&self, t:T)->Self::Result;
}

```

---

<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:** [August 13, 2020, 5:19pm UTC](https://internals.rust-lang.org/t/idea-existential-trait-bounds/12868/5 "2020-08-13T17:19:49Z")

</div>

> [@2e71828](#):
>
> It would be nice to be able to lift the type parameter up to the trait level so that `Result` can be dependent on `T` and we have a trait that can be object-safe

Or you could just use a blanket implementation

```rust
trait Trait {
    type Result;
    fn foo<T:OtherTrait>(this: &Self, t:T)->Self::Result // no `self` to avoid name conflict
    where Self: Sized; // if you don’t like this constraint, you could put `Result` into a common supertrait of `Trait` and `Foo`
}

trait Foo<T: OtherTrait>: Trait {
	fn foo(&self, t: T) -> Self::Result;
}

impl<T: OtherTrait, This: Trait> Foo<T> for This {
    fn foo(&self, t: T) -> Self::Result { Trait::foo(self, t) }
}

fn main() {
    let x: Box<dyn Foo<u8, Result = i32>> = todo!();
}

```

Also, in your second code example `Result` depends on `T`, while it doesn’t in the first example.

---

<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:** [August 13, 2020, 5:41pm UTC](https://internals.rust-lang.org/t/idea-existential-trait-bounds/12868/6 "2020-08-13T17:41:39Z")

</div>

> [@steffahn](#):
>
> in your second code example `Result` depends on `T` , while it doesn’t in the first example.

That’s usually what I want, but I end up compromising that to ensure all `Trait` implementors can call `foo` with any of the valid arguments. The concrete case I ended up with was something like this:

```rust
trait Relation {
    type Row;
    type Ordered: Relation<Row=Self::Row>;
    fn order_by<SortKey: From<&Self::Row>+Ord>(self)->Self::Ordered;
}

```

This works, but I’d prefer to keep track of the sort order in the type system so that redundant sorts can be bypassed at compile time. That takes a backseat to ensuring that every `Relation` supports `order_by` on all relevant types, though.

---

<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:** [November 11, 2020, 5:41pm UTC](https://internals.rust-lang.org/t/idea-existential-trait-bounds/12868/7 "2020-11-11T17:41:53Z")

</div>

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