Hi! In attempt to implement HList with unique types via specialization I ran upon a strange error:
error[E0308]: mismatched types
--> src/main.rs:34:5
|
34 | / assert_type_eq!(
35 | | <Continue<i32, Start<i64>, frunk::indices::Here> as Test>::List,
36 | | HCons<i32, HCons<i64, HNil>>
37 | | );
| | ^
| | |
| |______expected associated type, found struct `frunk::HCons`
| this expression has type `MatchingType<<Continue<i32, Start<i64>, Here> as Test>::List>`
|
= note: expected struct `MatchingType<<Continue<i32, Start<i64>, Here> as Test>::List>`
found struct `MatchingType<frunk::HCons<i32, frunk::HCons<i64, frunk::HNil>>>`
= help: consider constraining the associated type `<Continue<i32, Start<i64>, Here> as Test>::List` to `frunk::HCons<i32, frunk::HCons<i64, frunk::HNil>>` or calling a method that returns `<Continue<i32, Start<i64>, Here> as Test>::List`
This happens if I try to specialize over different Test
trait impls, one for when type is present in HList
by provided index, and one for when it doesn't (default impl).
When trying to use default
keyword not on associated type, but rather on whole impl block, I got a different error:
error[E0275]: overflow evaluating the requirement `Continue<_, _, _>: Test`
|
= help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`yay`)
= note: required because of the requirements on the impl of `Test` for `Continue<_, _, _>`
= note: 127 redundant requirements hidden
= note: required because of the requirements on the impl of `Test` for `Continue<_, _, _>`
Removing specialization as a whole (leaving only impl without Selector
bound) leads to successful compilation (comment in code).
Is this my mistake or an issue with specialization?
Code:
#![feature(specialization)]
use assert_type_eq::assert_type_eq;
use frunk::{HCons, HNil, hlist::Selector};
trait Test {
type List;
}
struct Start<Item>(Item);
impl<Item> Test for Start<Item> {
type List = HCons<Item, HNil>;
}
struct Continue<Item, Inner, HListIndex>(Item, Inner, HListIndex);
impl<Item, Inner, HListIndex> Test for Continue<Item, Inner, HListIndex>
where
Inner: Test
{
default type List = HCons<Item, Inner::List>;
}
impl<Item, Inner, HListIndex> Test for Continue<Item, Inner, HListIndex>
where
Inner: Test,
<Inner as Test>::List: Selector<Item, HListIndex>
{
type List = Inner::List;
}
fn main() {
// Compiles if specialized impl is removed, and `default` keyword removed too
assert_type_eq!(
<Continue<i32, Start<i64>, frunk::indices::Here> as Test>::List,
HCons<i32, HCons<i64, HNil>>
);
}
Dependencies:
[dependencies]
assert-type-eq = "0.1"
frunk = "0.3"
rustc version: rustc 1.54.0-nightly (e4ca1662f 2021-05-22)