Skip to content

Improve handling of expressions in patterns #118625

New issue

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

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

Already on GitHub? # to your account

Merged
merged 1 commit into from
Jan 29, 2024
Merged

Conversation

ShE3py
Copy link
Contributor

@ShE3py ShE3py commented Dec 4, 2023

Closes #112593.

Methodcalls' dots in patterns are silently recovered as commas (e.g. Foo("".len()) -> Foo("", len())) so extra diagnostics are emitted:

struct Foo(u8, String, u8);

fn bar(foo: Foo) -> bool {
    match foo {
        Foo(4, "yippee".yeet(), 7) => true,
        _ => false
    }
}
error: expected one of `)`, `,`, `...`, `..=`, `..`, or `|`, found `.`
 --> main.rs:5:24
  |
5 |         Foo(4, "yippee".yeet(), 7) => true,
  |                        ^
  |                        |
  |                        expected one of `)`, `,`, `...`, `..=`, `..`, or `|`
  |                        help: missing `,`

error[E0531]: cannot find tuple struct or tuple variant `yeet` in this scope
 --> main.rs:5:25
  |
5 |         Foo(4, "yippee".yeet(), 7) => true,
  |                         ^^^^ not found in this scope

error[E0023]: this pattern has 4 fields, but the corresponding tuple struct has 3 fields
 --> main.rs:5:13
  |
1 | struct Foo(u8, String, u8);
  |            --  ------  -- tuple struct has 3 fields
...
5 |         Foo(4, "yippee".yeet(), 7) => true,
  |             ^  ^^^^^^^^ ^^^^^^  ^ expected 3 fields, found 4

error: aborting due to 3 previous errors

This PR checks for patterns that ends with a dot and a lowercase ident (as structs/variants should be uppercase):

error: expected a pattern, found a method call
 --> main.rs:5:16
  |
5 |         Foo(4, "yippee".yeet(), 7) => true,
  |                ^^^^^^^^^^^^^^^ method calls are not allowed in patterns

error: aborting due to 1 previous error

Also check for expressions:

fn is_idempotent(x: f32) -> bool {
    match x {
        x * x => true,
        _ => false,
    }
}

fn main() {
    let mut t: [i32; 5];
    let t[0] = 1;
}
error: expected a pattern, found an expression
 --> main.rs:3:9
  |
3 |         x * x => true,
  |         ^^^^^ arbitrary expressions are not allowed in patterns

error: expected a pattern, found an expression
  --> main.rs:10:9
   |
10 |     let t[0] = 1;
   |         ^^^^ arbitrary expressions are not allowed in patterns

Would be cool if the compiler could suggest adding a guard for matches, but I've no idea how to do it.


@rustbot label +A-diagnostics +A-parser +A-patterns +C-enhancement

@rustbot
Copy link
Collaborator

rustbot commented Dec 4, 2023

r? @compiler-errors

(rustbot has picked a reviewer for you, use r? to override)

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. A-diagnostics Area: Messages for errors, warnings, and lints A-parser Area: The parsing of Rust source code to an AST A-patterns Relating to patterns and pattern matching C-enhancement Category: An issue proposing an enhancement or a PR with one. labels Dec 4, 2023
@compiler-errors
Copy link
Member

This is a draft so I'm marking it as waiting-on-author

@rustbot author

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Dec 5, 2023
@ShE3py ShE3py force-pushed the expr-in-pats branch 3 times, most recently from 52ee3eb to 6580704 Compare December 6, 2023 22:05
@bors
Copy link
Collaborator

bors commented Dec 8, 2023

☔ The latest upstream changes (presumably #118527) made this pull request unmergeable. Please resolve the merge conflicts.

@ShE3py ShE3py force-pushed the expr-in-pats branch 8 times, most recently from aed48be to c74db5a Compare December 11, 2023 17:29
@rust-log-analyzer

This comment has been minimized.

@ShE3py ShE3py changed the title [WIP] Improve handling of expressions in patterns Improve handling of expressions in patterns Dec 12, 2023
@ShE3py ShE3py marked this pull request as ready for review December 12, 2023 00:53
@ShE3py
Copy link
Contributor Author

ShE3py commented Dec 12, 2023

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Dec 12, 2023
@bors
Copy link
Collaborator

bors commented Jan 27, 2024

📌 Commit a13fbaa has been approved by WaffleLapkin

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 27, 2024
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Jan 28, 2024
Improve handling of expressions in patterns

Closes rust-lang#112593.

Methodcalls' dots in patterns are silently recovered as commas (e.g. `Foo("".len())` -> `Foo("", len())`) so extra diagnostics are emitted:
```rs
struct Foo(u8, String, u8);

fn bar(foo: Foo) -> bool {
    match foo {
        Foo(4, "yippee".yeet(), 7) => true,
        _ => false
    }
}
```
```
error: expected one of `)`, `,`, `...`, `..=`, `..`, or `|`, found `.`
 --> main.rs:5:24
  |
5 |         Foo(4, "yippee".yeet(), 7) => true,
  |                        ^
  |                        |
  |                        expected one of `)`, `,`, `...`, `..=`, `..`, or `|`
  |                        help: missing `,`

error[E0531]: cannot find tuple struct or tuple variant `yeet` in this scope
 --> main.rs:5:25
  |
5 |         Foo(4, "yippee".yeet(), 7) => true,
  |                         ^^^^ not found in this scope

error[E0023]: this pattern has 4 fields, but the corresponding tuple struct has 3 fields
 --> main.rs:5:13
  |
1 | struct Foo(u8, String, u8);
  |            --  ------  -- tuple struct has 3 fields
...
5 |         Foo(4, "yippee".yeet(), 7) => true,
  |             ^  ^^^^^^^^ ^^^^^^  ^ expected 3 fields, found 4

error: aborting due to 3 previous errors
```

This PR checks for patterns that ends with a dot and a lowercase ident (as structs/variants should be uppercase):
```
error: expected a pattern, found a method call
 --> main.rs:5:16
  |
5 |         Foo(4, "yippee".yeet(), 7) => true,
  |                ^^^^^^^^^^^^^^^ method calls are not allowed in patterns

error: aborting due to 1 previous error
```

Also check for expressions:
```rs
fn is_idempotent(x: f32) -> bool {
    match x {
        x * x => true,
        _ => false,
    }
}

fn main() {
    let mut t: [i32; 5];
    let t[0] = 1;
}
```
```
error: expected a pattern, found an expression
 --> main.rs:3:9
  |
3 |         x * x => true,
  |         ^^^^^ arbitrary expressions are not allowed in patterns

error: expected a pattern, found an expression
  --> main.rs:10:9
   |
10 |     let t[0] = 1;
   |         ^^^^ arbitrary expressions are not allowed in patterns
```

Would be cool if the compiler could suggest adding a guard for `match`es, but I've no idea how to do it.

---
`@rustbot` label +A-diagnostics +A-parser +A-patterns +C-enhancement
@matthiaskrgr
Copy link
Member

@bors r-
I suspect this needs another rebase :(
#120436

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Jan 28, 2024
@ShE3py
Copy link
Contributor Author

ShE3py commented Jan 28, 2024

Blessed:

 error[E0658]: exclusive range pattern syntax is experimental
   --> $DIR/range_pat_interactions1.rs:30:17
    |
 LL |             y @ ..-7 => assert_eq!(y, -8),
    |                 ^^^^
    |
    = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
    = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: use an inclusive range pattern, like N..=M

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jan 28, 2024
@WaffleLapkin
Copy link
Member

@bors r+

@bors
Copy link
Collaborator

bors commented Jan 28, 2024

📌 Commit 6f014a8 has been approved by WaffleLapkin

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 28, 2024
bors added a commit to rust-lang-ci/rust that referenced this pull request Jan 29, 2024
Rollup of 9 pull requests

Successful merges:

 - rust-lang#116677 (References refer to allocated objects)
 - rust-lang#118625 (Improve handling of expressions in patterns)
 - rust-lang#120266 (Improve documentation for [A]Rc::into_inner)
 - rust-lang#120373 (Adjust Behaviour of `read_dir` and `ReadDir` in Windows Implementation: Check Whether Path to Search In Exists)
 - rust-lang#120390 (Borrow check inline const patterns)
 - rust-lang#120420 (Stop using derivative in rustc_pattern_analysis)
 - rust-lang#120428 (hir: Two preparatory changes for rust-lang#120206)
 - rust-lang#120453 (Fix incorrect comment in normalize_newlines)
 - rust-lang#120462 (Clean dead code)

r? `@ghost`
`@rustbot` modify labels: rollup
bors added a commit to rust-lang-ci/rust that referenced this pull request Jan 29, 2024
Rollup of 9 pull requests

Successful merges:

 - rust-lang#116677 (References refer to allocated objects)
 - rust-lang#118625 (Improve handling of expressions in patterns)
 - rust-lang#120266 (Improve documentation for [A]Rc::into_inner)
 - rust-lang#120373 (Adjust Behaviour of `read_dir` and `ReadDir` in Windows Implementation: Check Whether Path to Search In Exists)
 - rust-lang#120390 (Borrow check inline const patterns)
 - rust-lang#120420 (Stop using derivative in rustc_pattern_analysis)
 - rust-lang#120428 (hir: Two preparatory changes for rust-lang#120206)
 - rust-lang#120453 (Fix incorrect comment in normalize_newlines)
 - rust-lang#120462 (Clean dead code)

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit 0138151 into rust-lang:master Jan 29, 2024
@rustbot rustbot added this to the 1.77.0 milestone Jan 29, 2024
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Jan 29, 2024
Rollup merge of rust-lang#118625 - ShE3py:expr-in-pats, r=WaffleLapkin

Improve handling of expressions in patterns

Closes rust-lang#112593.

Methodcalls' dots in patterns are silently recovered as commas (e.g. `Foo("".len())` -> `Foo("", len())`) so extra diagnostics are emitted:
```rs
struct Foo(u8, String, u8);

fn bar(foo: Foo) -> bool {
    match foo {
        Foo(4, "yippee".yeet(), 7) => true,
        _ => false
    }
}
```
```
error: expected one of `)`, `,`, `...`, `..=`, `..`, or `|`, found `.`
 --> main.rs:5:24
  |
5 |         Foo(4, "yippee".yeet(), 7) => true,
  |                        ^
  |                        |
  |                        expected one of `)`, `,`, `...`, `..=`, `..`, or `|`
  |                        help: missing `,`

error[E0531]: cannot find tuple struct or tuple variant `yeet` in this scope
 --> main.rs:5:25
  |
5 |         Foo(4, "yippee".yeet(), 7) => true,
  |                         ^^^^ not found in this scope

error[E0023]: this pattern has 4 fields, but the corresponding tuple struct has 3 fields
 --> main.rs:5:13
  |
1 | struct Foo(u8, String, u8);
  |            --  ------  -- tuple struct has 3 fields
...
5 |         Foo(4, "yippee".yeet(), 7) => true,
  |             ^  ^^^^^^^^ ^^^^^^  ^ expected 3 fields, found 4

error: aborting due to 3 previous errors
```

This PR checks for patterns that ends with a dot and a lowercase ident (as structs/variants should be uppercase):
```
error: expected a pattern, found a method call
 --> main.rs:5:16
  |
5 |         Foo(4, "yippee".yeet(), 7) => true,
  |                ^^^^^^^^^^^^^^^ method calls are not allowed in patterns

error: aborting due to 1 previous error
```

Also check for expressions:
```rs
fn is_idempotent(x: f32) -> bool {
    match x {
        x * x => true,
        _ => false,
    }
}

fn main() {
    let mut t: [i32; 5];
    let t[0] = 1;
}
```
```
error: expected a pattern, found an expression
 --> main.rs:3:9
  |
3 |         x * x => true,
  |         ^^^^^ arbitrary expressions are not allowed in patterns

error: expected a pattern, found an expression
  --> main.rs:10:9
   |
10 |     let t[0] = 1;
   |         ^^^^ arbitrary expressions are not allowed in patterns
```

Would be cool if the compiler could suggest adding a guard for `match`es, but I've no idea how to do it.

---
`@rustbot` label +A-diagnostics +A-parser +A-patterns +C-enhancement
lnicola pushed a commit to lnicola/rust-analyzer that referenced this pull request Apr 7, 2024
Add `PatKind::Err` to AST/HIR

#116715 added `thir::PatKind::Error`; this PR adds `hir::PatKind::Err` and `ast::PatKind::Err` (see rust-lang/rust#118625 (comment).)

---

``@rustbot`` label +A-patterns
r? WaffleLapkin
RalfJung pushed a commit to RalfJung/rust-analyzer that referenced this pull request Apr 27, 2024
Add `PatKind::Err` to AST/HIR

#116715 added `thir::PatKind::Error`; this PR adds `hir::PatKind::Err` and `ast::PatKind::Err` (see rust-lang/rust#118625 (comment).)

---

``@rustbot`` label +A-patterns
r? WaffleLapkin
bors added a commit to rust-lang-ci/rust that referenced this pull request Sep 19, 2024
Further improve diagnostics for expressions in pattern position

Follow-up of rust-lang#118625, see rust-lang#121697.

```rs
fn main() {
    match 'b' {
        y.0.0.1.z().f()? as u32 => {},
    }
}
```
Before:
```
error: expected one of `=>`, ``@`,` `if`, or `|`, found `.`
 --> src/main.rs:3:10
  |
3 |         y.0.0.1.z().f()? as u32 => {},
  |          ^ expected one of `=>`, ``@`,` `if`, or `|`
```
After:
```
error: expected a pattern, found an expression
 --> src/main.rs:3:9
  |
3 |         y.0.0.1.z().f()? as u32 => {},
  |         ^^^^^^^^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
  |
help: consider moving the expression to a match arm guard
  |
3 |         val if val == y.0.0.1.z().f()? as u32 => {},
  |         ~~~ +++++++++++++++++++++++++++++++++
help: consider extracting the expression into a `const`
  |
2 +     const VAL: /* Type */ = y.0.0.1.z().f()? as u32;
3 ~     match 'b' {
4 ~         VAL => {},
  |
help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
  |
3 |         const { y.0.0.1.z().f()? as u32 } => {},
  |         +++++++                         +
```

---

r? fmease
`@rustbot` label +A-diagnostics +A-parser +A-patterns +C-enhancement
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-parser Area: The parsing of Rust source code to an AST A-patterns Relating to patterns and pattern matching C-enhancement Category: An issue proposing an enhancement or a PR with one. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

unfriendly error diagnostic when using expressions in pattern
8 participants