Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Array length inference? #40269

Closed
SimonSapin opened this issue Mar 5, 2017 · 8 comments
Closed

Array length inference? #40269

SimonSapin opened this issue Mar 5, 2017 · 8 comments
Labels
A-const-fn Area: const fn foo(..) {..}. Pure functions which can be applied at compile time. A-inference Area: Type inference C-feature-request Category: A feature request, i.e: not implemented / a PR.

Comments

@SimonSapin
Copy link
Contributor

SimonSapin commented Mar 5, 2017

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 (b1e3176 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;
}
@eddyb
Copy link
Member

eddyb commented Mar 5, 2017

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.

@SimonSapin
Copy link
Contributor Author

When I wrote the above it didn’t 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.

@durka
Copy link
Contributor

durka commented Mar 5, 2017

See counted-array :)

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

@Mark-Simulacrum Mark-Simulacrum added A-const-fn Area: const fn foo(..) {..}. Pure functions which can be applied at compile time. A-inference Area: Type inference labels May 26, 2017
@Mark-Simulacrum Mark-Simulacrum added the C-feature-request Category: A feature request, i.e: not implemented / a PR. label Jul 27, 2017
@mqudsi
Copy link
Contributor

mqudsi commented Aug 12, 2018

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.

@eddyb
Copy link
Member

eddyb commented Aug 18, 2018

@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 rust-lang/rfcs#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.

@fiso
Copy link

fiso commented Mar 6, 2019

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?

@steveklabnik
Copy link
Member

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

@Centril
Copy link
Contributor

Centril commented Mar 7, 2019

cc rust-lang/rfcs#2545

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-const-fn Area: const fn foo(..) {..}. Pure functions which can be applied at compile time. A-inference Area: Type inference C-feature-request Category: A feature request, i.e: not implemented / a PR.
Projects
None yet
Development

No branches or pull requests

8 participants