# Genericity over traits

**URL:** <https://internals.rust-lang.org/t/genericity-over-traits/4115>\
**Category:** language design\
**Created:** [September 22, 2016, 7:05am UTC](https://internals.rust-lang.org/t/genericity-over-traits/4115 "2016-09-22T07:05:50Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![plietar](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/plietar/32/2591_2.png) [@plietar](https://internals.rust-lang.org/u/plietar)\
**Post date:** [September 22, 2016, 7:05am UTC](https://internals.rust-lang.org/t/genericity-over-traits/4115/1 "2016-09-22T07:05:50Z")

</div>

(Sorry if this has been discussed before, this combination of keywords obviously returns a lot of results about existing features)

I’ve sometimes needed a function to be generic over a trait, rather than a type. One use case is transmuting a trait object reference to a `std::raw::TraitObject`, in a generic fashion.

```rust
fn foo<T: ?Sized>(x: &T) -> TraitObject {
    transmute(x)
}

```

This doesn’t work as `T` could be sized, or another DST (slice or `str`). The compiler complains that x might have the wrong size (one word, rather than 2 for `TraitObject`). `transmute_copy` can be used as a workaround, but is very much UB if `T` is not a trait object.

My suggestion is to allow `T` to be restricted to a trait :

```rust
fn foo<trait T>(x: &T);

```

I think the syntax fits nicely with the various `const x: u32` generics proposals. The keyword before the variable refers to the style (avoiding the words type and kind on purpose here) of variable, and can be either `const`, `trait`, `type` (the default) or an apostrophe for lifetimes.

```rust
fn foo<'a, trait T: Debug, type U: T, const x: u32>(data: [U; x]) {
    println!("{:?}", data);
}

```

(Just to be clear, this proposal is orthogonal to value generics proposed by RFC 1657 and others, the syntax just fits well)

---

<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:** [September 22, 2016, 8:27am UTC](https://internals.rust-lang.org/t/genericity-over-traits/4115/2 "2016-09-22T08:27:37Z")

</div>

Another example is a generic “constraint checker”:

```rust
fn check_is_trait<Trait, T: Trait>() {}

check_is_trait<Clone, u8>();
check_is_trait<Copy, String>();

```

instead of

```rust
fn check_is_clone<T: Clone>() {}
fn check_is_copy<T: Copy>() {}

check_is_clone<u8>();
check_is_copy<String>();

```

---

<div class="post-metadata">

**Author:** ![DanielKeep](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/danielkeep/32/1332_2.png) [@DanielKeep](https://internals.rust-lang.org/u/DanielKeep)\
**Post date:** [September 22, 2016, 8:33am UTC](https://internals.rust-lang.org/t/genericity-over-traits/4115/3 "2016-09-22T08:33:10Z")

</div>

Another another example is dynamic code loading and objects, where you want to be able to do something like `obj.cast_to::<Interface>()`.

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [September 22, 2016, 8:39am UTC](https://internals.rust-lang.org/t/genericity-over-traits/4115/4 "2016-09-22T08:39:23Z")

</div>

These are all very different features from one another.

---

<div class="post-metadata">

**Author:** ![DanielKeep](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/danielkeep/32/1332_2.png) [@DanielKeep](https://internals.rust-lang.org/u/DanielKeep)\
**Post date:** [September 22, 2016, 2:55pm UTC](https://internals.rust-lang.org/t/genericity-over-traits/4115/5 "2016-09-22T14:55:14Z")

</div>

> [@withoutboats](#):
>
> These are all very different features from one another.

How? All three examples are doing the same thing as far as I can tell: being able to pass a trait as a generic parameter. They're just being applied to different problems.

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [September 22, 2016, 6:13pm UTC](https://internals.rust-lang.org/t/genericity-over-traits/4115/6 "2016-09-22T18:13:38Z")

</div>

They’re using the same syntax to mean three different and incomptible things.

- The first is signalling that this type is a trait object.
- The second is adding a new kind to Rust, which is a trait constraint, allowing you to parameterize types by a term which appears in a different position from lifetimes and types.
- The third is (I believe) downcasting one trait object to another. This is similar to the first proposal but would also require additional RTTI if I understand correctly.

The first and second are definitely incompatible. I think the first, if we wanted to do it, is better solved by a new special marker trait like `Virtual` which all trait objects implement and no other types do.

---

<div class="post-metadata">

**Author:** ![steven099](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steven099/32/3871_2.png) [@steven099](https://internals.rust-lang.org/u/steven099)\
**Post date:** [September 23, 2016, 4:46am UTC](https://internals.rust-lang.org/t/genericity-over-traits/4115/7 "2016-09-23T04:46:58Z")

</div>

> [@withoutboats](#):
>
> The first and second are definitely incompatible.

Just to elaborate on this because it took me a minute to realize why this is, the problem is that only some traits are object safe, so it's not generally true that an arbitrary trait could be used in a type position as an object type. A `trait` kind would therefore be orthogonal to a `Virtual` (or `Object`) bound applied to a type parameter.

[removed: Maybe if you could write `fn foo<trait Trait: Virtual>(...)`, then `Trait` could be treated as a type as well as a bound, though this would require `Virtual` to be deeply understood by the compiler.]

Edit: Had the meaning of `<trait T: U>` wrong.

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [September 23, 2016, 6:38am UTC](https://internals.rust-lang.org/t/genericity-over-traits/4115/8 "2016-09-23T06:38:52Z")

</div>

Its even more fundamental than that. For any object safe trait called `Trait`, there also exists a _type_ called `Trait` which is the trait object for that trait. But one of these is a trait and the other is a type, so they are different things which have the same name.

For example, the syntax you just wrote - `<trait T: Virtual>` - doesn’t have a single _obvious_ meaning. In particular, traits don’t implement other traits. So my inference, which may not be yours, is that its the same thing as `trait Foo: Bar { }`; this is called a “supertrait,” but all it really is is a trait constraint on the `Self` type for that trait (that is, no different from writing `trait Foo where Self: Bar { }`.

If this is what it means, its very different from what I wrote, because `Virtual` is implemented by _every trait object_, but its not a supertrait for _every object safe trait_. All of their non-trait object implementing types do not implement `Virtual`.

---

<div class="post-metadata">

**Author:** ![steven099](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steven099/32/3871_2.png) [@steven099](https://internals.rust-lang.org/u/steven099)\
**Post date:** [September 23, 2016, 6:53am UTC](https://internals.rust-lang.org/t/genericity-over-traits/4115/9 "2016-09-23T06:53:13Z")

</div>

Right, that doesn’t make sense. I was trying to handwave and it backfired. You’d have to write `fn foo<Trait: Virtual>(...)` and then have the compiler somehow understand that `Trait` is dual-kinded. Or introduce an intersecting kind `fn foo<trait+type Trait>(...)`, in which case, you could just define

```
impl<trait+type Trait> Virtual for Trait {}

```

in order to be able to get the basic “is an object type” bound.

I get that the object type and the trait are two separate entities in one sense, but they’re very closely related entities. If for whatever reason you wanted both, you’d need to be able to capture both in a single parameter in order to ensure that they’re interoperable. Though I’m not sure what such a case would look like.

---

<div class="post-metadata">

**Author:** ![mpol](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mpol/32/4056_2.png) [@mpol](https://internals.rust-lang.org/u/mpol)\
**Post date:** [September 23, 2016, 8:03am UTC](https://internals.rust-lang.org/t/genericity-over-traits/4115/10 "2016-09-23T08:03:40Z")

</div>

> [@withoutboats](#):
>
> Its even more fundamental than that. For any object safe trait called Trait, there also exists a type called Trait which is the trait object for that trait. But one of these is a trait and the other is a type, so they are different things which have the same name.

Given the frequent confusion, was it ever suggested (for Rust 2.0?) to not give the trait object type the same name as the trait?

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [September 23, 2016, 8:04am UTC](https://internals.rust-lang.org/t/genericity-over-traits/4115/11 "2016-09-23T08:04:33Z")

</div>

Yes, a lot of folks think the current syntax for trait objects is a mistake for various reasons.

---

<div class="post-metadata">

**Author:** ![eddyb](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/eddyb/32/8411_2.png) [@eddyb](https://internals.rust-lang.org/u/eddyb)\
**Post date:** [September 26, 2016, 5:15pm UTC](https://internals.rust-lang.org/t/genericity-over-traits/4115/12 "2016-09-26T17:15:01Z")

</div>

Sorry for not noticing this earlier.

[_There is_ a way](https://doc.rust-lang.org/nightly/std/marker/trait.Unsize.html) to do this in unstable Rust, and it has been there for a while. Some people have used them to build collections such as “ring buffer” double-ended queues of trait objects without indirection to the data.

You could use it with `fn foo<T: Unsize<Trait>, Trait: ?Sized>`, for example. The caveat is that it will _actually_ work with all DSTs, not just trait objects, and there’s some subtlety here:

You _can’t_ be generic over traits specifically, and there is no good reason for it. Unsafely accessing the vtable is unnecessary, given `drop_in_place` and `{align,size}_of_val` (and of course the actual virtual methods).

That means that a `DstDeque<[T]>` would also work if `DstDeque<Trait>` does, _and it makes sense_ (“double-ended queue of slices”).

---

<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:** [March 25, 2019, 8:27am UTC](https://internals.rust-lang.org/t/genericity-over-traits/4115/13 "2019-03-25T08:27:01Z")

</div>

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