Skip to content

Error message for trying to bind range of units to unit suggests invalid code #93122

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

Open
AnthonyMikh opened this issue Jan 20, 2022 · 1 comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug. D-invalid-suggestion Diagnostics: A structured suggestion resulting in incorrect code. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@AnthonyMikh
Copy link
Contributor

AnthonyMikh commented Jan 20, 2022

Given the following code:

fn g() {
    let () = ()..;
    let () = ..();
    let () = ..=();
    let () = ()..();
    let () = ()..=();
}

The current output is:

error[E0308]: mismatched types
 --> src/lib.rs:2:9
  |
2 |     let () = ()..;
  |         ^^   ---- this expression has type `RangeFrom<()>`
  |         |
  |         expected struct `RangeFrom`, found `()`
  |
  = note: expected struct `RangeFrom<()>`
          found unit type `()`
help: you might have meant to use field `start` whose type is `()`
  |
2 |     let () = ()...start;
  |              ~~~~~~~~~~

error[E0308]: mismatched types
 --> src/lib.rs:3:9
  |
3 |     let () = ..();
  |         ^^   ---- this expression has type `RangeTo<()>`
  |         |
  |         expected struct `RangeTo`, found `()`
  |
  = note: expected struct `RangeTo<()>`
          found unit type `()`
help: you might have meant to use field `end` whose type is `()`
  |
3 |     let () = ..().end;
  |              ~~~~~~~~

error[E0308]: mismatched types
 --> src/lib.rs:4:9
  |
4 |     let () = ..=();
  |         ^^   ----- this expression has type `RangeToInclusive<()>`
  |         |
  |         expected struct `RangeToInclusive`, found `()`
  |
  = note: expected struct `RangeToInclusive<()>`
          found unit type `()`
help: you might have meant to use field `end` whose type is `()`
  |
4 |     let () = ..=().end;
  |              ~~~~~~~~~

error[E0308]: mismatched types
 --> src/lib.rs:5:9
  |
5 |     let () = ()..();
  |         ^^   ------ this expression has type `std::ops::Range<()>`
  |         |
  |         expected struct `std::ops::Range`, found `()`
  |
  = note: expected struct `std::ops::Range<()>`
          found unit type `()`
help: you might have meant to use field `start` whose type is `()`
  |
5 |     let () = ()..().start;
  |              ~~~~~~~~~~~~

error[E0308]: mismatched types
 --> src/lib.rs:6:9
  |
6 |     let () = ()..=();
  |         ^^   ------- this expression has type `RangeInclusive<()>`
  |         |
  |         expected struct `RangeInclusive`, found `()`
  |
  = note: expected struct `RangeInclusive<()>`
          found unit type `()`
help: you might have meant to use field `start` whose type is `()`
  |
6 |     let () = ()..=().start;
  |              ~~~~~~~~~~~~~

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` due to 5 previous errors

Blindly applying all the suggestions would lead to:

fn g() {
    let () = ()...start;
    let () = ..().end;
    let () = ..=().end;
    let () = ()..().start;
    let () = ()..=().start;
}

...which is obviously syntactically invalid.

Ideally the output should account for required parenthesis and look like:

error[E0308]: mismatched types
 --> src/lib.rs:2:9
  |
2 |     let () = ()..;
  |         ^^   ---- this expression has type `RangeFrom<()>`
  |         |
  |         expected struct `RangeFrom`, found `()`
  |
  = note: expected struct `RangeFrom<()>`
          found unit type `()`
help: you might have meant to use field `start` whose type is `()`
  |
2 |     let () = (()..).start;
  |              ~~~~~~~~~~~~

error[E0308]: mismatched types
 --> src/lib.rs:3:9
  |
3 |     let () = ..();
  |         ^^   ---- this expression has type `RangeTo<()>`
  |         |
  |         expected struct `RangeTo`, found `()`
  |
  = note: expected struct `RangeTo<()>`
          found unit type `()`
help: you might have meant to use field `end` whose type is `()`
  |
3 |     let () = (..()).end;
  |              ~~~~~~~~~~

error[E0308]: mismatched types
 --> src/lib.rs:4:9
  |
4 |     let () = ..=();
  |         ^^   ----- this expression has type `RangeToInclusive<()>`
  |         |
  |         expected struct `RangeToInclusive`, found `()`
  |
  = note: expected struct `RangeToInclusive<()>`
          found unit type `()`
help: you might have meant to use field `end` whose type is `()`
  |
4 |     let () = (..=()).end;
  |              ~~~~~~~~~~~

error[E0308]: mismatched types
 --> src/lib.rs:5:9
  |
5 |     let () = ()..();
  |         ^^   ------ this expression has type `std::ops::Range<()>`
  |         |
  |         expected struct `std::ops::Range`, found `()`
  |
  = note: expected struct `std::ops::Range<()>`
          found unit type `()`
help: you might have meant to use field `start` whose type is `()`
  |
5 |     let () = (()..()).start;
  |              ~~~~~~~~~~~~~~

error[E0308]: mismatched types
 --> src/lib.rs:6:9
  |
6 |     let () = ()..=();
  |         ^^   ------- this expression has type `RangeInclusive<()>`
  |         |
  |         expected struct `RangeInclusive`, found `()`
  |
  = note: expected struct `RangeInclusive<()>`
          found unit type `()`
help: you might have meant to use field `start` whose type is `()`
  |
6 |     let () = (()..=()).start;
  |              ~~~~~~~~~~~~~~~

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` due to 5 previous errors

This issue is reproducible on stable versions from 1.51.0 to 1.58.0, latest beta (rustc 1.59.0-beta.1 (7c0b25092 2022-01-13)) and latest nightly (rustc 1.60.0-nightly (9ad5d82f8 2022-01-18)) at the moment.

Some other things about this bug
  • Running compiler on "fixed" program leads to error message which suggests adding even more field accesses.
  • It seems like it is required to bind value to unit pattern in order to trigger the bug. Other ways to require unit value that I tried (binding to a wildcard pattern with unit type type ascription, calling with a function with excepts a unit argument, returning range from a unit returning function) do not work.
  • It seems like it breaks only with units and not with any other type.
@AnthonyMikh AnthonyMikh added A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jan 20, 2022
@terrarier2111
Copy link
Contributor

@rustbot claim

@terrarier2111 terrarier2111 removed their assignment Feb 25, 2022
@JohnTitor JohnTitor added C-bug Category: This is a bug. D-invalid-suggestion Diagnostics: A structured suggestion resulting in incorrect code. labels May 29, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug. D-invalid-suggestion Diagnostics: A structured suggestion resulting in incorrect code. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
3 participants