Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
668 views
in Technique[技术] by (71.8m points)

rust - What expressions are allowed as the array length N in [_; N]?

Please consider the following minimal example in Rust:

const FOOBAR: usize = 3;

trait Foo {
    const BAR: usize;
}

struct Fubar();

impl Foo for Fubar {
    const BAR: usize = 3;
}

struct Baz<T>(T);

trait Qux {
    fn print_bar();
}

impl<T: Foo> Qux for Baz<T> {
    fn print_bar() {
        println!("bar: {}", T::BAR);   // works
        println!("{:?}", [T::BAR; 3]); // works
        println!("{:?}", [1; FOOBAR]); // works
        println!("{:?}", [1; T::BAR]); // this gives an error
    }
}

fn main() {
    Baz::<Fubar>::print_bar();
}

The compiler gives the following error:

error[E0599]: no associated item named `BAR` found for type `T` in the current scope
  --> src/main.rs:24:30
   |
24 |         println!("{:?}", [1; T::BAR]); // this gives an error
   |                              ^^^^^^ associated item not found in `T`
   |
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `BAR`, perhaps you need to implement it:
           candidate #1: `Foo`

Whatever the answer to my question, this is not a particularly good error message because it suggests that T does implement Foo despite the latter being a trait bound. Only after burning a lot of time did it occur to me that in fact T::BAR is a perfectly valid expression in other contexts, just not as a length parameter to an array.

What are the rules that govern what kind of expressions can go there? Because arrays are Sized, I completely understand that the length are to be known at compile time. Coming from C++ myself, I would expect some restriction akin to constexpr but I have not come across that in the documentation where it just says

A fixed-size array, denoted [T; N], for the element type, T, and the non-negative compile-time constant size, N.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

As of Rust 1.24.1, the array length basically needs to either be a numeric literal or a "regular" constant that is a usize. There's a small amount of constant evaluation that exists today, but it's more-or-less limited to basic math.

a perfectly valid expression in other contexts, just not as a length parameter to an array

Array lengths don't support generic parameters. (#43408)

this is not a particularly good error message

Error message should be improved for associated consts in array lengths (#44168)

I would expect some restriction akin to constexpr

This is essentially the restriction, the problem is that what is allowed to be used in a const is highly restricted at the moment. Notably, these aren't allowed:

  • functions (except to construct enums or structs)
  • loops
  • multiple statements / blocks

Work on good constant / compile-time evaluation is still ongoing. There are a large amount of RFCs, issues, and PRs improving this. A sample:


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...