Skip to content
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

Further improve diagnostics for expressions in pattern position #123877

Merged
merged 2 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
fmease marked this conversation as resolved.
Show resolved Hide resolved
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}")]
fmease marked this conversation as resolved.
Show resolved Hide resolved
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
Loading