Long term RFC: Associated traits / Trait generics / ConstraintKinds


#1

I’ve started a dedicated repository for preparing, planning, scheming and writing an RFC for {-# LANGUAGE ConstraintKinds #-} which would allow you to parameterize things by traits (trait generics) as well as have associated traits in traits.

What we wish to enable

A Map trait with associated traits

pub trait Map<K: Self::Key, V: Self::Value> {
    trait Key;
    trait Value;
    
    ...
}

impl<K: Hash, V> Map<K, V> for HashMap<K, V> {
    trait Key = Hash;
    trait Value = ();
    
    ...
}

A generic trait object type alias

type FooBox<trait Extra = ()> = Box<dyn Foo + Extra>;

Here, = () means that FooBox is the same as Box<dyn Foo> while FooBox<Send> is the same as Box<dyn Foo + Send>. That is, () is the “unit constraint”, see issue 5 for bikeshedding.

ExactSizeIterator passing

We want to have the same “leakage” as we get with auto traits for -> impl Trait.

The output type is Extra if the input type is Extra:


fn foo<trait Extra = ()>
   (iter: impl Iterator + Extra)
       -> impl Iterator + Extra
{
    ...
}

Schedule: End of 2018

The goal is to write and design the RFC slowly but surely. So the plan is long term. The intent is to have a bullet proof RFC ready by the end of 2018 or at the beginning of 2019 for consideration.

Landing “ConstraintKinds” will largly require the integration of the chalk_engine into rustc to be complete. Then we can have a more rigoruous understanding of what impact this new feature will have and how we preserve soundness and how this interacts with type inference.

I need your help

I would like your help with identifying:

  • use cases and motivations
  • how to teach users about the contents of the RFC
  • corner cases
  • technical problems & implementation concerns
  • how type inference works if at all
  • writing the RFC
  • etc.

To help out, please, if you can, write and file:

Thank you.

What are ConstraintKinds?

Here’s a friendly explanation:

What is a constraint?

A constraint or a bound is a logical requirement on a type. A type satisfies a certain constraint if it satisfies the requirement to for example, have a certain set of methods.

In Rust, a constraint is of the form: MyType: MyTrait where MyType is of the kind type, and MyTrait of the kind type -> constraint. If we apply a type to the kind level function type -> constraint, we get constraint back.

GHC and Haskell

ConstraintKinds are a feature implemented in GHC, the Glasgow Haskell Compiler. Conceptually, they let you talk about bounds or constraints as kinds.