Specialization and Associated Types
⚓ Rust 📅 2026-01-02 👤 surdeus 👁️ 1I'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
🏷️ Rust_feed