Meta Marker Traits: Traits to classify rust type system

I recently came into a situation where I wanted my generic T to be restricted to trait only types. This kind of got me thinking : would it be possible to introduce a meta trait system for the rust type system to model the language elements of rust like struct, enum, trait etc. It would allow me to do something like:

use meta;

struct Object<T> where meta T: meta::Trait, T: OtherTraitBounds {
    data: Box<dyn T>

Java does something like this in its compiler module: java.compiler (Java SE 11 & JDK 11 )

Just curious on this idea and how it would be perceived by the rust community. Please share feedback on this idea ?

What's the intended use case? It sounds like the XY problem at first glance.

Possible as a trait bound on unstable.

1 Like

I've run into this limitation before when trying to build a dynamic dispatch system similar to COM's IUnknown in Rust. If I remember correctly, I never found a good solution to something like the following signature:

trait Unknown {
    fn query_interface<T: trait>(&self) -> Option<&dyn T>;

I think there ended up being some... questionable casting in macros going on to make it work.



This can be solved/by-passed using something like:

You need to model the return type as a concrete type.

Why does this need to be restricted to dyn Trait in the interface though? Couldn't this just be:

trait Unknown {
    fn query_interface<T: ?Sized>(&self) -> Option<&T>;

The size of the result changes depending on whether T is Sized or not, but the body of the function is a bunch of "does the TypeId of T equal the TypeId of trait X?" checks. You can't use regular, safe casting, so you have to resort to transmutes. The compiler really doesn't like it when you combine transmutes and inconsistently sized generic types.

I forget how I implemented it in the end, but there was some amount of hiding things inside boxes of sized types and then un-boxing them later with unsafe transmutes inside a macro... it wasn't pretty.

@DanielKeep @SkiFire130 provided an alternate brilliant solution that I am yet to fully grasp. You can take a look into it: Cross casting of `dyn Any` trait objects for object safe traits - #20 by SkiFire13 - help - The Rust Programming Language Forum

Although the ability to write methods generic over a trait could be useful, traits are not types. For any trait X, dyn X is a type, but X itself is not a type. As such, I think it would make more sense to use a syntax like struct Object<trait T: ParentTrait> { data: Box<dyn T> }, to parallel struct Object<const N: usize> { data: [u8; N] }.

A related issue is that there's no way to implement something for all of dyn Trait, dyn Trait + Send, dyn Trait + Send + Sync etc with a single impl block.

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