Skip to content

Commit

Permalink
Auto merge of #123877 - ShE3py:expr-in-pats-2, r=fmease
Browse files Browse the repository at this point in the history
Further improve diagnostics for expressions in pattern position

Follow-up of #118625, see #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
  • Loading branch information
bors committed Sep 19, 2024
2 parents a5cf8bb + db09345 commit df7f778
Show file tree
Hide file tree
Showing 27 changed files with 1,813 additions and 412 deletions.
2 changes: 2 additions & 0 deletions compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,8 @@ pub enum StashKey {
/// Query cycle detected, stashing in favor of a better error.
Cycle,
UndeterminedMacroResolution,
/// Used by `Parser::maybe_recover_trailing_expr`
ExprInPat,
}

fn default_track_diagnostic<R>(diag: DiagInner, f: &mut dyn FnMut(DiagInner) -> R) -> R {
Expand Down
18 changes: 10 additions & 8 deletions compiler/rustc_parse/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -803,15 +803,17 @@ parse_unexpected_expr_in_pat =
expected {$is_bound ->
[true] a pattern range bound
*[false] a pattern
}, found {$is_method_call ->
[true] a method call
*[false] an expression
}
}, found an expression
.label = arbitrary expressions are not allowed in patterns
parse_unexpected_expr_in_pat_const_sugg = consider extracting the expression into a `const`
parse_unexpected_expr_in_pat_create_guard_sugg = consider moving the expression to a match arm guard
parse_unexpected_expr_in_pat_inline_const_sugg = consider wrapping the expression in an inline `const` (requires `{"#"}![feature(inline_const_pat)]`)
.label = {$is_method_call ->
[true] method calls
*[false] arbitrary expressions
} are not allowed in patterns
parse_unexpected_expr_in_pat_update_guard_sugg = consider moving the expression to the match arm guard
parse_unexpected_if_with_if = unexpected `if` in the condition expression
.suggestion = remove the `if`
Expand Down
79 changes: 77 additions & 2 deletions compiler/rustc_parse/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// ignore-tidy-filelength

use std::borrow::Cow;

use rustc_ast::token::Token;
Expand Down Expand Up @@ -2592,13 +2594,86 @@ pub(crate) struct ExpectedCommaAfterPatternField {
#[derive(Diagnostic)]
#[diag(parse_unexpected_expr_in_pat)]
pub(crate) struct UnexpectedExpressionInPattern {
/// The unexpected expr's span.
#[primary_span]
#[label]
pub span: Span,
/// Was a `RangePatternBound` expected?
pub is_bound: bool,
/// Was the unexpected expression a `MethodCallExpression`?
pub is_method_call: bool,
/// The unexpected expr's precedence (used in match arm guard suggestions).
pub expr_precedence: i8,
}

#[derive(Subdiagnostic)]
pub(crate) enum UnexpectedExpressionInPatternSugg {
#[multipart_suggestion(
parse_unexpected_expr_in_pat_create_guard_sugg,
applicability = "maybe-incorrect"
)]
CreateGuard {
/// Where to put the suggested identifier.
#[suggestion_part(code = "{ident}")]
ident_span: Span,
/// Where to put the match arm.
#[suggestion_part(code = " if {ident} == {expr}")]
pat_hi: Span,
/// The suggested identifier.
ident: String,
/// The unexpected expression.
expr: String,
},

#[multipart_suggestion(
parse_unexpected_expr_in_pat_update_guard_sugg,
applicability = "maybe-incorrect"
)]
UpdateGuard {
/// Where to put the suggested identifier.
#[suggestion_part(code = "{ident}")]
ident_span: Span,
/// The beginning of the match arm guard's expression (insert a `(` if `Some`).
#[suggestion_part(code = "(")]
guard_lo: Option<Span>,
/// The end of the match arm guard's expression.
#[suggestion_part(code = "{guard_hi_paren} && {ident} == {expr}")]
guard_hi: Span,
/// Either `")"` or `""`.
guard_hi_paren: &'static str,
/// The suggested identifier.
ident: String,
/// The unexpected expression.
expr: String,
},

#[multipart_suggestion(
parse_unexpected_expr_in_pat_const_sugg,
applicability = "has-placeholders"
)]
Const {
/// Where to put the extracted constant declaration.
#[suggestion_part(code = "{indentation}const {ident}: /* Type */ = {expr};\n")]
stmt_lo: Span,
/// Where to put the suggested identifier.
#[suggestion_part(code = "{ident}")]
ident_span: Span,
/// The suggested identifier.
ident: String,
/// The unexpected expression.
expr: String,
/// The statement's block's indentation.
indentation: String,
},

#[multipart_suggestion(
parse_unexpected_expr_in_pat_inline_const_sugg,
applicability = "maybe-incorrect"
)]
InlineConst {
#[suggestion_part(code = "const {{ ")]
start_span: Span,
#[suggestion_part(code = " }}")]
end_span: Span,
},
}

#[derive(Diagnostic)]
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ use super::{
use crate::{errors, maybe_recover_from_interpolated_ty_qpath};

#[derive(Debug)]
enum DestructuredFloat {
pub(super) enum DestructuredFloat {
/// 1e2
Single(Symbol, Span),
/// 1.
Expand Down Expand Up @@ -1041,7 +1041,7 @@ impl<'a> Parser<'a> {
// support pushing "future tokens" (would be also helpful to `break_and_eat`), or
// we should break everything including floats into more basic proc-macro style
// tokens in the lexer (probably preferable).
fn break_up_float(&self, float: Symbol, span: Span) -> DestructuredFloat {
pub(super) fn break_up_float(&self, float: Symbol, span: Span) -> DestructuredFloat {
#[derive(Debug)]
enum FloatComponent {
IdentLike(String),
Expand Down
Loading

0 comments on commit df7f778

Please sign in to comment.