0

I am exploring the use of const generics in Rust. I have constructed the following toy example, which I believe should compile.

#![feature(generic_const_exprs)]

trait A {
    const N: usize;
}
trait B: A {
    fn f() -> [bool; Self::N];
}

struct S<T> where T: A, [bool; T::N]: Sized {
    a: [bool; T::N]
}
impl<T> A for S<T> where T: A, [bool; T::N]: Sized {
    const N: usize = T::N;
}

impl<T> B for S<T> where T: A, [bool; T::N]: Sized {
    fn f() -> [bool; Self::N] {
        panic!()
    }
}

struct U;
impl A for U {
    const N: usize = 0;
}

fn main() {
    println!("{}", S::<U>::N);
}

However, this fails to compile.

error[E0391]: cycle detected when building an abstract representation for <impl at src/main.rs:17:1: 17:19>::f::{constant#0}
  --> src/main.rs:18:22
   |
18 |     fn f() -> [bool; Self::N] {
   |                      ^^^^^^^
   |
note: ...which requires building THIR for `<impl at src/main.rs:17:1: 17:19>::f::{constant#0}`...
  --> src/main.rs:18:22
   |
18 |     fn f() -> [bool; Self::N] {
   |                      ^^^^^^^
note: ...which requires type-checking `<impl at src/main.rs:17:1: 17:19>::f::{constant#0}`...
  --> src/main.rs:18:22
   |
18 |     fn f() -> [bool; Self::N] {
   |                      ^^^^^^^
   = note: ...which requires evaluating trait selection obligation `S<T>: A`...
   = note: ...which again requires building an abstract representation for <impl at src/main.rs:17:1: 17:19>::f::{constant#0}, completing the cycle
note: cycle used when checking that `<impl at src/main.rs:17:1: 17:19>::f` is well-formed
  --> src/main.rs:18:5
   |
18 |     fn f() -> [bool; Self::N] {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^

If I remove the impl B for S, the program compiles and works as expected.

I think I understand the error except for the last implication. Why does evaluating the trait selection obligation S<T>: A require building a representation for the impl B for S? It seems to me like S<T>: A has nothing to do with whether or not S impls B.

More generally, is there any way to make this pattern compilable? I would like a trait with a const, a generic type over that trait implementing the trait and using the const in its members, and a function on that generic type using the const.

In case it matters, I am using rust 1.66.0-nightly (8b0c05d9a 2022-10-07).

deaton.dg
  • 1,282
  • 9
  • 21

0 Answers0