Specialization and Associated Types

⚓ Rust    📅 2026-01-02    👤 surdeus    👁️ 1      

surdeus

I'm working on a Heterogenous Set backed by an HList and for that i needed a Remove<T> trait that would remove all instances of T from the list and seemed to be forced into using specialization.

Here's my code for the Remove<T> trait and it's implementations:

#![feature(specialization)]
#![feature(associated_type_defaults)]

// HList
struct Nil;
struct Cons<Head, Tail>(Head, Tail);

// Index
trait Index: Sized {
    type There: Index = There<Self>;
}

struct Here;
struct There<T>(T);

impl Index for Here {}
impl<T: Index> Index for There<T> {}

// Index HList
trait IndexList: Sized {
    type There: IndexList;
}

impl IndexList for Nil {
    type There = Nil;
}
impl<Head: Index, Tail: IndexList> IndexList for Cons<Head, Tail> {
    type There = Cons<Head::There, Tail::There>;
}

// Remove trait
trait Remove<T>: Sized {
    type Indices: IndexList;
    type Remainder: HList;
    fn remove(self) -> Self::Remainder;
}

impl<T> Remove<T> for Nil {
    type Indices = Nil;
    type Remainder = Nil;
    fn remove(self) -> Self::Remainder {
        Nil
    }
}

// Removing T when its the Head and is part of the Tail is just Tail::Remainder
impl<Head, Tail> Remove<Head> for Cons<Head, Tail>
where
    Tail: Remove<Head>,
{
    type Indices = Cons<Here, <Tail::Indices as IndexList>::There>;
    type Remainder = Tail::Remainder;

    fn remove(self) -> Self::Remainder {
        Tail::remove(self.1)
    }
}

// Removing T when it's only part of the Tail is Cons<Head, Tail::Remainder>
impl<Head, Tail, T> Remove<T> for Cons<Head, Tail>
where
    Tail: Remove<T>,
{
    default type Indices = <Tail::Indices as IndexList>::There;
    default type Remainder = Cons<Head, Tail::Remainder>;

    default fn remove(self) -> Self::Remainder {
        Cons(self.0, Tail::remove(self.1))
    }
}

// Removing T when it's not part of the list is the list itself 
impl<Head, Tail, T> Remove<T> for Cons<Head, Tail> {
    default type Indices = Nil;
    default type Remainder = Cons<Head, Tail>;

    default fn remove(self) -> Self::Remainder {
        self
    }
}

This in theory should compile fine but i get the following error:

error[E0308]: mismatched types
  --> src/lib.rs:68:9
   |
65 |     default type Remainder = Cons<Head, Tail::Remainder>;
   |     ---------------------- associated type is `default` and may be overridden
66 |
67 |     default fn remove(self) -> Self::Remainder {
   |                                --------------- expected `<Cons<Head, Tail> as Remove<T>>::Remainder` because of return type
68 |         Cons(self.0, Tail::remove(self.1))
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `Cons<Head, ...>`
   |
   = note: expected associated type `<Cons<Head, Tail> as Remove<T>>::Remainder`
                       found struct `Cons<Head, <Tail as Remove<T>>::Remainder>`

error[E0308]: mismatched types
  --> src/lib.rs:78:9
   |
75 |     default type Remainder = Cons<Head, Tail>;
   |     ---------------------- associated type is `default` and may be overridden
76 |
77 |     default fn remove(self) -> Self::Remainder {
   |                                --------------- expected `<Cons<Head, Tail> as Remove<T>>::Remainder` because of return type
78 |         self
   |         ^^^^ expected associated type, found `Cons<Head, Tail>`
   |
   = note: expected associated type `<Cons<Head, Tail> as Remove<T>>::Remainder`
                       found struct `Cons<Head, Tail>`

How are the types missmatched?

2 posts - 2 participants

Read full topic

🏷️ Rust_feed