rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
98.81k stars 12.77k forks source link

Diagnostics hint for const generics #80506

Open yoshuawuyts opened 3 years ago

yoshuawuyts commented 3 years ago

Current Behavior

Given the following code:

let mut combinations = (1..2).combinations();
assert_eq!(combinations.next(), None);

where Iterator::combinations is defined as:

fn combinations<const N: usize>(self) -> Combinations<Self, N>;

The following diagnostic is provided:

error[E0282]: type annotations needed
   --> src\lib.rs:144:32
    |
144 |         let mut combinations = (1..2).combinations();
    |                                ^^^^^^^^^^^^^^^^^^^^^
    |
    = note: unable to infer the value of a const parameter

Attempting a fix, and failing:

Naively I thought I could fix this by adding a turbofish, but that doesn't seem to help:

let mut combinations = (1..2).combinations::<[usize; 2]>();
assert_eq!(combinations.next(), None);
error[E0107]: wrong number of const arguments: expected 1, found 0
   --> src\lib.rs:144:39
    |
144 |         let mut combinations = (1..2).combinations::<[usize; 2]>();
    |                                       ^^^^^^^^^^^^ expected 1 const argument

error[E0107]: wrong number of type arguments: expected 0, found 1
   --> src\lib.rs:144:54
    |
144 |         let mut combinations = (1..2).combinations::<[usize; 2]>();
    |                                                      ^^^^^^^^^^ unexpected type argument

Expected behavior

Providing a hint on how to correctly define const generics would be immensely helpful. I'm sure I'll be able to figure out the syntax for this eventually (currently going through https://github.com/rust-lang/rust/pull/78460 among others), but given we're set for a 1.51 stabilization of min_const_generics I suspect more people will be running into this soon.

Further Considerations

I was looking at how hints work for e.g. missing type params in collect, and noticed no hints are provided there either. It only explains what to do, not showing how to do it. For something that's notoriously tricky to learn that seems like it could benefit from hints as well.

let x = (1..5).collect();
error[E0282]: type annotations needed
 --> src/main.rs:2:9
  |
2 |     let x = (1..5).collect();
  |         ^ consider giving `x` a type
yoshuawuyts commented 3 years ago

Found the solution to my bug by the way. This did the trick:

let mut combinations = (1..2).combinations::<2>();
assert_eq!(combinations.next(), None);

I think it's fair to say that the diagnostics were not a great help here. And in particular providing the wrong param ([usize; 2]) yielded confusing diagnostics.

lcnr commented 3 years ago
error[E0282]: type annotations needed --> src\lib.rs:144:32 144 let mut combinations = (1..2).combinations(); ^^^^^^^^^^^^^^^^^^^^^

= note: unable to infer the value of a const parameter

can you provide a full example for this? we should emit a suggestion to use a const arg here. For example in https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=dd05e205a3af777ec388a4dba98e66e8

yoshuawuyts commented 3 years ago

Oh wow, the diagnostics for array_windows is heaps better! A full implementation of const Iterator::combinations can be found here: https://github.com/yoshuawuyts/const-combinations/blob/main/src/lib.rs