How to use associated const in an associated type

(Related: post1, post2, post3)

I want to implement the following trait but failed:

trait DataSource {
    const LEN: usize;
    const DATA: [u8; Self::LEN];
}

This is infeasible in stable with the following error:

   Compiling playground v0.0.1 (/playground)
error: generic parameters may not be used in const operations
 --> src/lib.rs:5:22
  |
5 |     const DATA: [u8; Self::LEN];
  |                      ^^^^^^^^^ cannot perform const operation using `Self`
  |
  = note: type parameters may not be used in const expressions
  = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions

With the #![feature(generic_const_exprs)] flag mentioned in the related posts, this is still infeasible:

error: unconstrained generic constant
 --> src/lib.rs:5:5
  |
5 |     const DATA: [u8; Self::LEN];
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = help: try adding a `where` bound using this expression: `where [(); Self::LEN]:`

The help message here doesn't help me understand the problem.. If this is not supported by the language yet, a better help message will be appreciated.

As a background, what I want to achieve is to get a const/static array with different types and lens given a generic parameter. Appreciate if someone can get a good workaround for this.

#![feature(generic_const_items)]
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
trait DataSource {
    const LEN: usize;
    const DATA: [u8; Self::LEN] where [(); Self::LEN]:;
}

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=48ba28cb3d3e45cbf6c24d45b1fa8ac2

Dump some materials

3 Likes

Thanks for the promptly reply! What exactly does "where [(); Self::LEN]:" mean?

Well, the HackMD material explained this, thanks again!

Rust needs const wf (well-formedness), and that's the syntax to express it. You can click the HackMd link in my first reply.

And to support that syntax in associated const item (const xx: Type;), follow the generic_const_items feature issue and one of its PR, both of which are also given in my first reply.

A follow-up discussion, the necessity of the where [(); Self::LEN]: condition is to expose the constant in the public API, but in my case, the constant Self::LEN is already an associated constant, which must be in the API. Therefere, does it make sense to relax the requirement in this case?

Generally speaking, we have to read more materials/discussions/ect to know the reason of something.

I didn't follow up the whole story, and doesn't intend to. But from the following links

Proposal 1: Don't change anything in the compiler/lang just allow arbitrary expressions

...
Since the monomorphization of a function isn't deterministically triggered by a single other function, we can't show a "backtrace" for the error. You won't know where the function was invoked. This means all you get is

LL     let x = [u8; C - 2];
                    ^^^^^ overflow during evaluation of `1_usize - 2_usize`

Which may point into arbitrary internals of arbitrary crates that you depend on without any extra information.

...

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.