The magic type, _, doesn't work with arrays

Arrays are cool and all because they enable optimizations when size is known...

But you can't let the compiler infer the size anywhere. While that arguably makes sense in consts and statics, you can't even do it when using let - while with types it works fine!

What's the point of making let x: [(); _] = []; an error?! And a confusing one at that, too...

So it hasn't always been that bad. Doing a quick bisection on released versions of the compile. The error message on <=1.49 is:

error: expected expression, found reserved identifier `_`
 --> <source>:2:17
  |
2 |     let x: [(); _] = [];
  |         -       ^ expected expression
  |         |
  |         while parsing the type for `x`

While on versions >=1.50 the error is:

error[E0658]: destructuring assignments are unstable
 --> <source>:2:17
  |
2 |     let x: [(); _] = [];
  |                 ^
  |
  = note: see issue #71126 <https://github.com/rust-lang/rust/issues/71126> for more information

error: in expressions, `_` can only be used on the left-hand side of an assignment
 --> <source>:2:17
  |
2 |     let x: [(); _] = [];
  |                 ^ `_` not allowed here

So as you can see, this is mostly a regression on the error messages side. This probably (I don't know, haven't checked nor know where to check) is something to do with Const-Generics and might already be planned.

1 Like

This error message is probably caused by the destructuring assignments feature, since the error message links to it(Tracking Issue for `destructuring_assignment` · Issue #71126 · rust-lang/rust · GitHub)

Here is an example of a destructuring assignment, with the same error message: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=fdfd8a08c67387fc54f61c65386bf6c0

fn main(){
    _ = 0;
}
Compiling playground v0.0.1 (/playground)
error[E0658]: destructuring assignments are unstable
 --> src/main.rs:2:5
  |
2 |     _ = 0;
  |     ^
  |
  = note: see issue #71126 <https://github.com/rust-lang/rust/issues/71126> for more information

And: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=655b23b877bea8c62b38a762f8bdb88e

fn main(){
    _;
}
error[E0658]: destructuring assignments are unstable
 --> src/main.rs:2:5
  |
2 |     _;
  |     ^
  |
  = note: see issue #71126 <https://github.com/rust-lang/rust/issues/71126> for more information

error: in expressions, `_` can only be used on the left-hand side of an assignment
 --> src/main.rs:2:5
  |
2 |     _;
  |     ^ `_` not allowed here

1 Like

Well anyway can we make arrays less useless by letting the compiler infer their size? ^-^

Waiting on a project proposal that addresses concerns beyond just arrays ala the conversation in postponed RFC 2545.

1 Like

It should also be noted that _ is used to infer types while [(); /* is a const */] which can't (yet) be inferred.

error[E0747]: type provided when a constant was expected
 --> src/main.rs:5:11
  |
5 |     foo::<_>([(); 3]);
  |           ^
  |
  = help: const arguments cannot yet be inferred with `_`

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=eb09a38ce41925568fc5c938608f09a9

3 Likes

Idea: add a keyword, lol, which stands for the Length Of (array) Literal.

can only be used with literals (or macro-generated literals).

wouldn't that be breaking change?

// now valid rust would fail to compile
fn foo<const lol: usize>() -> &'static dyn Any {
    &[(); lol] as &dyn Any
}

nah that's what edition 2024 is for

Except it isn't, and never will be. Editions are not a mechanism to introduce breaking changes.

Editions are a mechanism to introduce keywords, at least.

1 Like