Open
Description
Hi, consider the following code (live version here), which basically implements heterogeneous lists:
#![feature(generic_const_exprs)]
#![feature(auto_traits)]
#![feature(negative_impls)]
#![feature(trait_alias)]
// =============
// === HList ===
// =============
pub struct Nil;
pub struct Cons<Head, Tail>(pub Head, pub Tail);
// ===============
// === NotZero ===
// ===============
struct PhantomConstUsize<const N: usize>;
auto trait NotZeroCheck {}
impl !NotZeroCheck for PhantomConstUsize<0> {}
trait NotZero<const N: usize> = where PhantomConstUsize<N>: NotZeroCheck;
// ==================
// === FieldIndex ===
// ==================
pub trait FieldIndex<const I: usize> {
type Type;
}
impl<H, T> FieldIndex<0> for Cons<H, T> {
type Type = H;
}
impl<H, T, const N: usize> FieldIndex<N> for Cons<H, T>
where
(): NotZero<N>,
T: FieldIndex<{ N - 1 }>,
{
type Type = <T as FieldIndex<{ N - 1 }>>::Type;
}
pub type FieldAt<const I: usize, T> = <T as FieldIndex<I>>::Type;
// =============
// === Tests ===
// =============
type Test0 = FieldAt<0, Cons<usize, Cons<usize, Cons<usize, Nil>>>>;
type Test1 = FieldAt<1, Cons<usize, Cons<usize, Cons<usize, Nil>>>>;
type Test2 = FieldAt<2, Cons<usize, Cons<usize, Cons<usize, Nil>>>>;
fn main() {
let t0: Test0 = 1; // WORKS OK
let t1: Test1 = 1; // WORKS OK
// let t2: Test2 = 1; // DOES NOT WORK
}
After uncommenting the last line we got an error:
the trait bound `Cons<usize, Cons<usize, Nil>>: FieldIndex<{ N - 1 }>` is not satisfied
Which is incorrect. Please note, that Rust was able to resolve it for N=0
and N=1
, but not for N=2
.
Another bug is that if we reverse the order of these lines:
(): NotZero<N>,
T: FieldIndex<{ N - 1 }>,
The code does not compile either.