Skip to content

Commit df7f778

Browse files
committed
Auto merge of #123877 - ShE3py:expr-in-pats-2, r=fmease
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
2 parents a5cf8bb + db09345 commit df7f778

27 files changed

+1813
-412
lines changed

Diff for: compiler/rustc_errors/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,8 @@ pub enum StashKey {
571571
/// Query cycle detected, stashing in favor of a better error.
572572
Cycle,
573573
UndeterminedMacroResolution,
574+
/// Used by `Parser::maybe_recover_trailing_expr`
575+
ExprInPat,
574576
}
575577

576578
fn default_track_diagnostic<R>(diag: DiagInner, f: &mut dyn FnMut(DiagInner) -> R) -> R {

Diff for: compiler/rustc_parse/messages.ftl

+10-8
Original file line numberDiff line numberDiff line change
@@ -803,15 +803,17 @@ parse_unexpected_expr_in_pat =
803803
expected {$is_bound ->
804804
[true] a pattern range bound
805805
*[false] a pattern
806-
}, found {$is_method_call ->
807-
[true] a method call
808-
*[false] an expression
809-
}
806+
}, found an expression
807+
808+
.label = arbitrary expressions are not allowed in patterns
809+
810+
parse_unexpected_expr_in_pat_const_sugg = consider extracting the expression into a `const`
811+
812+
parse_unexpected_expr_in_pat_create_guard_sugg = consider moving the expression to a match arm guard
813+
814+
parse_unexpected_expr_in_pat_inline_const_sugg = consider wrapping the expression in an inline `const` (requires `{"#"}![feature(inline_const_pat)]`)
810815
811-
.label = {$is_method_call ->
812-
[true] method calls
813-
*[false] arbitrary expressions
814-
} are not allowed in patterns
816+
parse_unexpected_expr_in_pat_update_guard_sugg = consider moving the expression to the match arm guard
815817
816818
parse_unexpected_if_with_if = unexpected `if` in the condition expression
817819
.suggestion = remove the `if`

Diff for: compiler/rustc_parse/src/errors.rs

+77-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// ignore-tidy-filelength
2+
13
use std::borrow::Cow;
24

35
use rustc_ast::token::Token;
@@ -2592,13 +2594,86 @@ pub(crate) struct ExpectedCommaAfterPatternField {
25922594
#[derive(Diagnostic)]
25932595
#[diag(parse_unexpected_expr_in_pat)]
25942596
pub(crate) struct UnexpectedExpressionInPattern {
2597+
/// The unexpected expr's span.
25952598
#[primary_span]
25962599
#[label]
25972600
pub span: Span,
25982601
/// Was a `RangePatternBound` expected?
25992602
pub is_bound: bool,
2600-
/// Was the unexpected expression a `MethodCallExpression`?
2601-
pub is_method_call: bool,
2603+
/// The unexpected expr's precedence (used in match arm guard suggestions).
2604+
pub expr_precedence: i8,
2605+
}
2606+
2607+
#[derive(Subdiagnostic)]
2608+
pub(crate) enum UnexpectedExpressionInPatternSugg {
2609+
#[multipart_suggestion(
2610+
parse_unexpected_expr_in_pat_create_guard_sugg,
2611+
applicability = "maybe-incorrect"
2612+
)]
2613+
CreateGuard {
2614+
/// Where to put the suggested identifier.
2615+
#[suggestion_part(code = "{ident}")]
2616+
ident_span: Span,
2617+
/// Where to put the match arm.
2618+
#[suggestion_part(code = " if {ident} == {expr}")]
2619+
pat_hi: Span,
2620+
/// The suggested identifier.
2621+
ident: String,
2622+
/// The unexpected expression.
2623+
expr: String,
2624+
},
2625+
2626+
#[multipart_suggestion(
2627+
parse_unexpected_expr_in_pat_update_guard_sugg,
2628+
applicability = "maybe-incorrect"
2629+
)]
2630+
UpdateGuard {
2631+
/// Where to put the suggested identifier.
2632+
#[suggestion_part(code = "{ident}")]
2633+
ident_span: Span,
2634+
/// The beginning of the match arm guard's expression (insert a `(` if `Some`).
2635+
#[suggestion_part(code = "(")]
2636+
guard_lo: Option<Span>,
2637+
/// The end of the match arm guard's expression.
2638+
#[suggestion_part(code = "{guard_hi_paren} && {ident} == {expr}")]
2639+
guard_hi: Span,
2640+
/// Either `")"` or `""`.
2641+
guard_hi_paren: &'static str,
2642+
/// The suggested identifier.
2643+
ident: String,
2644+
/// The unexpected expression.
2645+
expr: String,
2646+
},
2647+
2648+
#[multipart_suggestion(
2649+
parse_unexpected_expr_in_pat_const_sugg,
2650+
applicability = "has-placeholders"
2651+
)]
2652+
Const {
2653+
/// Where to put the extracted constant declaration.
2654+
#[suggestion_part(code = "{indentation}const {ident}: /* Type */ = {expr};\n")]
2655+
stmt_lo: Span,
2656+
/// Where to put the suggested identifier.
2657+
#[suggestion_part(code = "{ident}")]
2658+
ident_span: Span,
2659+
/// The suggested identifier.
2660+
ident: String,
2661+
/// The unexpected expression.
2662+
expr: String,
2663+
/// The statement's block's indentation.
2664+
indentation: String,
2665+
},
2666+
2667+
#[multipart_suggestion(
2668+
parse_unexpected_expr_in_pat_inline_const_sugg,
2669+
applicability = "maybe-incorrect"
2670+
)]
2671+
InlineConst {
2672+
#[suggestion_part(code = "const {{ ")]
2673+
start_span: Span,
2674+
#[suggestion_part(code = " }}")]
2675+
end_span: Span,
2676+
},
26022677
}
26032678

26042679
#[derive(Diagnostic)]

Diff for: compiler/rustc_parse/src/parser/expr.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ use super::{
4141
use crate::{errors, maybe_recover_from_interpolated_ty_qpath};
4242

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

0 commit comments

Comments
 (0)