Skip to content

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

Open
@AnthonyMikh

Description

@AnthonyMikh

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsC-bugCategory: This is a bug.D-invalid-suggestionDiagnostics: A structured suggestion resulting in incorrect code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions