- Feature Name: elide_array_size
- Start Date: 2018-09-18
- RFC PR: (leave this empty)
- Rust Issue: (leave this empty)
In arrays declared in static
s, const
s and let
bindings with initializer,
allow to elide the size in the type and put an underscore there instead if it
can be inferred. For example: static BLORP_NUMBERS: [u32; _] = [0, 8, 15];
.
This will make it easier to set up static data. With the current syntax, one
needs to count the elements of an array manually to determine its size. Letting
the compiler find the size reduces the potential for error. In let
bindings
it also allows us to ascribe the array component type without requiring the
size (which is – perhaps surprisingly – not currently allowed).
Requiring to write [MyType; 42]
for a 42-element array gets tedious,
especially since the compiler already knows the size from the initializer. To
reduce the strain, Rust allows you to omit the 42
in those type ascriptions.
For example, you can write:
const CONST_CHARS: [u8; _] = *b"This is really a byte array";
static STATIC_MASKS: [u8; _] = [0, 1, 3, 7, 15, 31, 63, 127, 255];
fn main() {
let local_strs: [&'static str; _] = ["Hello", "Rust"];
..
}
In all other positions and on let
bindings without initializer, the exact
number keeps being required.
This feature is a simple extension of the parser plus AST transformation. In
its proposed form, there are no corner cases, because the only thing it enables
that is currently disallowed is to put a _
wildcard in place of the number of
elements in array types in let
s, const
s and static
s.
In the parser, at the array length position, we allow underscores. The AST
may need to be extended to allow underscore; In principle AnonConst
can
contain any expression, so _
could be represented by a Path
, or the whole
AnonConst
could be made Option
al.
To ensure locality of reasoning, this RFC proposes a lint for const
or
static
items with initializers other than ExprKind::Repeat
or
ExprKind::Array
.
The length can simply be inferred from the initializer. Care should be taken to keep the error messages useful.
There is a modicum of complexity to extend the parser and AST which needs to be done for every Rust parser in existence. However, the feature is minor, so the cost should be acceptable.
Also for longer array declarations the actual size may no longer be obvious from the code. However, putting any probable or improbable length in and observing the compiler error (if any) is enough to find out; also the author hopes that the programmers will put in the lengths if they are essential.
Finally, it's possible to add a clippy lint that suggests replacing the underscore with the actual length.
This feature is very useful and has been requested numerous times. A draft of this RFC actually proposed a very resticted type of inference, which would however clash with RFC #2000. So the solution is to add the restriction as a lint (either in rustc or clippy).
We could leave out the wildcard entirely, but [u32; ]
looks strange and could
possibly indicate an error, so it's better to use the more balanced [u32; _]
.
We could do nothing, and waste Rustacean's time by counting or parsing compiler errors (unless their accuracy of estimating array length is 100%. I'm sure mine isn't) or use a macro (see below).
We already allow wildcard lifetimes, which have been beneficial. I'll defer to RFC 2115 for more information.
Following the tradition of using macros to prototype language features, Alex Durka has built the counted-array crate which contains a macro to enable the proposed syntax.
Bikeshedding the lint name