Skip to content

Commit

Permalink
Add suggestions for expressions in let patterns
Browse files Browse the repository at this point in the history
  • Loading branch information
ShE3py committed Jul 1, 2024
1 parent ae8f558 commit 5e2c8eb
Show file tree
Hide file tree
Showing 12 changed files with 101 additions and 16 deletions.
4 changes: 4 additions & 0 deletions compiler/rustc_parse/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,10 @@ parse_unexpected_expr_in_pat_create_guard_sugg = check the value in an arm guard
parse_unexpected_expr_in_pat_inline_const_sugg = wrap the expression in a inline const (requires `{"#"}![feature(inline_const_pat)]`)
parse_unexpected_expr_in_pat_remove_let_sugg = remove this `let`
parse_unexpected_expr_in_pat_replace_let_else_with_if_sugg = use an `if`
parse_unexpected_expr_in_pat_update_guard_sugg = check the value in the arm guard
parse_unexpected_if_with_if = unexpected `if` in the condition expression
Expand Down
22 changes: 22 additions & 0 deletions compiler/rustc_parse/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2492,6 +2492,28 @@ pub(crate) struct UnexpectedExpressionInPatternInlineConstSugg {
pub end_span: Span,
}

#[derive(Subdiagnostic)]
#[multipart_suggestion(
parse_unexpected_expr_in_pat_remove_let_sugg,
applicability = "maybe-incorrect"
)]
pub(crate) struct UnexpectedExpressionInPatternRemoveLetSugg {
#[suggestion_part(code = "")]
pub span: Span,
}

#[derive(Subdiagnostic)]
#[multipart_suggestion(
parse_unexpected_expr_in_pat_replace_let_else_with_if_sugg,
applicability = "maybe-incorrect"
)]
pub(crate) struct UnexpectedExpressionInPatternReplaceLetElseWithIfSugg {
#[suggestion_part(code = "if {init} != {pat}")]
pub span: Span,
pub init: String,
pub pat: String,
}

#[derive(Diagnostic)]
#[diag(parse_unexpected_paren_in_range_pat)]
pub(crate) struct UnexpectedParenInRangePat {
Expand Down
41 changes: 33 additions & 8 deletions compiler/rustc_parse/src/parser/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ use crate::errors::{
TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg, TrailingVertNotAllowed,
UnexpectedExpressionInPattern, UnexpectedExpressionInPatternArmSugg,
UnexpectedExpressionInPatternConstSugg, UnexpectedExpressionInPatternInlineConstSugg,
UnexpectedLifetimeInPattern, UnexpectedParenInRangePat, UnexpectedParenInRangePatSugg,
UnexpectedExpressionInPatternRemoveLetSugg,
UnexpectedExpressionInPatternReplaceLetElseWithIfSugg, UnexpectedLifetimeInPattern,
UnexpectedParenInRangePat, UnexpectedParenInRangePatSugg,
UnexpectedVertVertBeforeFunctionParam, UnexpectedVertVertInPattern,
};
use crate::parser::expr::{could_be_unclosed_char_literal, DestructuredFloat, LhsExpr};
Expand All @@ -26,7 +28,7 @@ use rustc_errors::{Applicability, Diag, PResult, StashKey};
use rustc_session::errors::ExprParenthesesNeeded;
use rustc_span::source_map::{respan, Spanned};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{ErrorGuaranteed, Span};
use rustc_span::{BytePos, ErrorGuaranteed, Span};
use thin_vec::{thin_vec, ThinVec};

#[derive(PartialEq, Copy, Clone)]
Expand Down Expand Up @@ -497,15 +499,38 @@ impl<'a> Parser<'a> {
err.span.replace(stash_span, expr_span);

if let StmtKind::Let(local) = &stmt.kind {
// If we have an `ExprInPat`, the user tried to assign a value to another value,
// which doesn't makes much sense.
match &local.kind {
LocalKind::Decl => {}
LocalKind::Init(_) => {}
LocalKind::InitElse(_, _) => {}
// help: remove this `let`
LocalKind::Decl | LocalKind::Init(_) => {
err.subdiagnostic(
UnexpectedExpressionInPatternRemoveLetSugg {
// HACK: retrieves `let`'s span
span: local
.span
.shrink_to_lo()
.with_hi(local.span.lo() + BytePos(3)),
},
);
}
// help: replace the `let` with an `if`
LocalKind::InitElse(init, els) => {
err.subdiagnostic(
UnexpectedExpressionInPatternReplaceLetElseWithIfSugg {
span: local.span.shrink_to_lo().until(els.span),
init: self
.parser
.span_to_snippet(init.span)
.unwrap(),
pat: self
.parser
.span_to_snippet(local.pat.span)
.unwrap(),
},
);
}
}
} else {
// help: use an arm guard `if val == expr`
// help: check the value in an arm guard
if let Some(arm) = &self.arm {
let (ident, ident_span) = match self.field {
Some(field) => (
Expand Down
4 changes: 3 additions & 1 deletion tests/ui/parser/bad-name.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ error: expected a pattern, found an expression
--> $DIR/bad-name.rs:4:7
|
LL | let x.y::<isize>.z foo;
| ^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
| --- ^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
| |
| help: remove this `let`

error: expected one of `(`, `.`, `::`, `:`, `;`, `=`, `?`, `|`, or an operator, found `foo`
--> $DIR/bad-name.rs:4:22
Expand Down
4 changes: 3 additions & 1 deletion tests/ui/parser/issues/issue-24197.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ error: expected a pattern, found an expression
--> $DIR/issue-24197.rs:2:9
|
LL | let buf[0] = 0;
| ^^^^^^ arbitrary expressions are not allowed in patterns
| --- ^^^^^^ arbitrary expressions are not allowed in patterns
| |
| help: remove this `let`

error: aborting due to 1 previous error

4 changes: 3 additions & 1 deletion tests/ui/parser/pat-lt-bracket-5.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ error: expected a pattern, found an expression
--> $DIR/pat-lt-bracket-5.rs:2:9
|
LL | let v[0] = v[1];
| ^^^^ arbitrary expressions are not allowed in patterns
| --- ^^^^ arbitrary expressions are not allowed in patterns
| |
| help: remove this `let`

error[E0425]: cannot find value `v` in this scope
--> $DIR/pat-lt-bracket-5.rs:2:16
Expand Down
4 changes: 3 additions & 1 deletion tests/ui/parser/pat-lt-bracket-6.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ error: expected a pattern, found an expression
--> $DIR/pat-lt-bracket-6.rs:5:14
|
LL | let Test(&desc[..]) = x;
| ^^^^^^^^^ arbitrary expressions are not allowed in patterns
| --- ^^^^^^^^^ arbitrary expressions are not allowed in patterns
| |
| help: remove this `let`

error[E0308]: mismatched types
--> $DIR/pat-lt-bracket-6.rs:10:30
Expand Down
8 changes: 6 additions & 2 deletions tests/ui/parser/pat-ranges-3.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ error: expected a pattern range bound, found an expression
--> $DIR/pat-ranges-3.rs:4:16
|
LL | let 10 ..= 10 + 3 = 12;
| ^^^^^^ arbitrary expressions are not allowed in patterns
| --- ^^^^^^ arbitrary expressions are not allowed in patterns
| |
| help: remove this `let`

error: expected a pattern range bound, found an expression
--> $DIR/pat-ranges-3.rs:7:9
|
LL | let 10 - 3 ..= 10 = 8;
| ^^^^^^ arbitrary expressions are not allowed in patterns
| --- ^^^^^^ arbitrary expressions are not allowed in patterns
| |
| help: remove this `let`

error: aborting due to 2 previous errors

4 changes: 3 additions & 1 deletion tests/ui/parser/recover/recover-pat-exprs.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,9 @@ error: expected a pattern, found an expression
--> $DIR/recover-pat-exprs.rs:71:9
|
LL | let 1 + 1 = 2;
| ^^^^^ arbitrary expressions are not allowed in patterns
| --- ^^^^^ arbitrary expressions are not allowed in patterns
| |
| help: remove this `let`

error: expected one of `)`, `,`, `@`, or `|`, found `*`
--> $DIR/recover-pat-exprs.rs:74:28
Expand Down
7 changes: 7 additions & 0 deletions tests/ui/parser/recover/recover-pat-lets.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
fn main() {
let x = Some(2);

let Some(1 + 1) = x else { //~ error: expected a pattern, found an expression
return;
};
}
11 changes: 11 additions & 0 deletions tests/ui/parser/recover/recover-pat-lets.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error: expected a pattern, found an expression
--> $DIR/recover-pat-lets.rs:4:14
|
LL | let Some(1 + 1) = x else {
| ---------^^^^^-----------
| | |
| | arbitrary expressions are not allowed in patterns
| help: use an `if`: `if x != Some(1 + 1)`

error: aborting due to 1 previous error

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ error: expected a pattern, found an expression
--> $DIR/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.rs:2:31
|
LL | let str::<{fn str() { let str::T>>::as_bytes; }}, T>::as_bytes;
| ^^^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
| --- ^^^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
| |
| help: remove this `let`

error[E0412]: cannot find type `T` in this scope
--> $DIR/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.rs:2:55
Expand Down

0 comments on commit 5e2c8eb

Please sign in to comment.