Rust: Array length inference?

Created on 5 Mar 2017  路  8Comments  路  Source: rust-lang/rust

It would be nice if _ were allowed instead of an expression for the length in array types and array expressions, in cases where the length can be inferred based on context:

fn main() {
    let a: [u8; 4] = [0; _];
    let b: [u8; _] = a;
}

rustc 1.17.0-nightly (b1e31766d 2017-03-03)

error: expected expression, found `_`
 --> a.rs:2:26
  |
2 |     let a: [u8; 4] = [0; _];
  |                          ^

error: expected expression, found `_`
 --> a.rs:3:17
  |
3 |     let b: [u8; _] = a;
  |                 ^

error: aborting due to 2 previous error

In comparison, the item type in array expressions and array types can be inferred today:

fn main() {
    let a: [u8; 4] = ["0".parse::<_>().unwrap(); 4];
    let b: [_; 4] = a;
}
A-const-fn A-inference C-feature-request

Most helpful comment

Given that this pretty clearly requires an RFC, I'm going to give it a close.

All 8 comments

This would have to be a part of rust-lang/rfcs#1931, you should leave a comment there perhaps.

The reason is that whenever you have a generic parameter (lifetime / type / const), you need inference variables to instantiate, at least in the (slightly modified) HM typesystem we use.
A simple example is that Vec::new is <Vec<_>>::new, and _ creates an unique type inference variable.
Similarly, if Vec had a from_array method with a const parameter, Vec::from_array would require a const inference variable, at least internally in the compiler, and so would any trait impl.

Now, we could just not provide a surface syntax for this, but I think reusing _ is probably fine.

When I wrote the above it didn鈥檛 feel like an entirely new language feature, just a "simple" extension of the existing inference mechanism. But I can imagine how from an compiler internals point of view it could require most of the plumbing for const parameters in types.

See counted-array :)

counted_array!(let local_arr: [i32; _] = [4, 5, 6]);

This is definitely something that should be part of the language spec - definitely not somewhere macros shine.

A particular pain point with rust arrays comes when adding a member to a previously declared array or when declaring an array without knowing in that moment how long it will be.

For example:

const ARRAY: [u8; 2] = [1, 2];

Coming back to it later and adding 3 to the array requires changing two places. This is quite obvious in this example, but when dealing with arrays with many (complex) elements spanning multiple lines or even pages, remembering to go up and change the signature is challenging.

Additionally, when sitting down to write code for the first time, it is often the case that you don't know until you finish writing it how many members your array will have. For example,

const VALID_EXTENSIONS: [String, _] = [
    "ext1",
    "ext2",
    "ext3",
    // let's stop and think for a while. What other extensions could we include here?
    // oh yes!
    "ext4",
    "ext5",
}

Only having reached the end of the list does one know how many they'll have. Painful.

@mqudsi In the general case, const generics will have to include _ for values, at least internally in the implementation (so we could easily support the _ syntax as well).

However, in your example, it's also like https://github.com/rust-lang/rfcs/pull/2010, in that the type is inferred from the RHS.
cc @Centril Maybe we can revisit that RFC? I think some of the concerns were overblown.

The use-case for this seems incredibly clear. Am I understanding you all correctly when I interpret the counter-point as being that the meaning of the _-symbol would become less clear and coherent across the language? If so then could the problem just be solved by using an alternative syntax?

How about simply:

const VALID_EXTENSIONS: [String] = [
    "ext1",
    "ext2",
    "ext3",
    "ext4",
    "ext5",
}

Or alternatively, introduce a new symbol that carries no problematic baggage and use that in place of _ for this kind of situation.

Or am I just misunderstanding the objections?

Given that this pretty clearly requires an RFC, I'm going to give it a close.

Was this page helpful?
0 / 5 - 0 ratings