Skip to content

Commit a594044

Browse files
committedSep 6, 2022
Auto merge of #101362 - compiler-errors:unnecessary-let, r=cjgillot
Suggest removing unnecessary prefix let in patterns Helps with #101291, though I think `@estebank` probably wants this: > Finally, I think it'd be nice if we could detect that we don't know for sure and "just" swallow the rest of the expression (find the next ; accounting for nested braces) or the end of the item (easier). ... to be implemented before we close that issue out completely.
2 parents 098cf88 + 91674cc commit a594044

File tree

6 files changed

+74
-1
lines changed

6 files changed

+74
-1
lines changed
 

‎compiler/rustc_ast/src/token.rs

+24
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,30 @@ impl Token {
398398
}
399399
}
400400

401+
/// Returns `true` if the token can appear at the start of an pattern.
402+
///
403+
/// Shamelessly borrowed from `can_begin_expr`, only used for diagnostics right now.
404+
pub fn can_begin_pattern(&self) -> bool {
405+
match self.uninterpolate().kind {
406+
Ident(name, is_raw) =>
407+
ident_can_begin_expr(name, self.span, is_raw), // value name or keyword
408+
| OpenDelim(Delimiter::Bracket | Delimiter::Parenthesis) // tuple or array
409+
| Literal(..) // literal
410+
| BinOp(Minus) // unary minus
411+
| BinOp(And) // reference
412+
| AndAnd // double reference
413+
// DotDotDot is no longer supported
414+
| DotDot | DotDotDot | DotDotEq // ranges
415+
| Lt | BinOp(Shl) // associated path
416+
| ModSep => true, // global path
417+
Interpolated(ref nt) => matches!(**nt, NtLiteral(..) |
418+
NtPat(..) |
419+
NtBlock(..) |
420+
NtPath(..)),
421+
_ => false,
422+
}
423+
}
424+
401425
/// Returns `true` if the token can appear at the start of a type.
402426
pub fn can_begin_type(&self) -> bool {
403427
match self.uninterpolate().kind {

‎compiler/rustc_error_messages/locales/en-US/parser.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -150,3 +150,6 @@ parser_dotdotdot = unexpected token: `...`
150150
151151
parser_left_arrow_operator = unexpected token: `<-`
152152
.suggestion = if you meant to write a comparison against a negative value, add a space in between `<` and `-`
153+
154+
parser_remove_let = expected pattern, found `let`
155+
.suggestion = remove the unnecessary `let` keyword

‎compiler/rustc_parse/src/parser/diagnostics.rs

+8
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,14 @@ pub(crate) struct LeftArrowOperator {
705705
pub span: Span,
706706
}
707707

708+
#[derive(SessionDiagnostic)]
709+
#[diag(parser::remove_let)]
710+
pub(crate) struct RemoveLet {
711+
#[primary_span]
712+
#[suggestion(applicability = "machine-applicable", code = "")]
713+
pub span: Span,
714+
}
715+
708716
// SnapshotParser is used to create a snapshot of the parser
709717
// without causing duplicate errors being emitted when the `Parser`
710718
// is dropped.

‎compiler/rustc_parse/src/parser/pat.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use super::{ForceCollect, Parser, PathStyle, TrailingToken};
2+
use crate::parser::diagnostics::RemoveLet;
23
use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
34
use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor};
45
use rustc_ast::ptr::P;
@@ -320,7 +321,13 @@ impl<'a> Parser<'a> {
320321
maybe_recover_from_interpolated_ty_qpath!(self, true);
321322
maybe_whole!(self, NtPat, |x| x);
322323

323-
let lo = self.token.span;
324+
let mut lo = self.token.span;
325+
326+
if self.token.is_keyword(kw::Let) && self.look_ahead(1, |tok| tok.can_begin_pattern()) {
327+
self.bump();
328+
self.sess.emit_err(RemoveLet { span: lo });
329+
lo = self.token.span;
330+
}
324331

325332
let pat = if self.check(&token::BinOp(token::And)) || self.token.kind == token::AndAnd {
326333
self.parse_pat_deref(expected)?

‎src/test/ui/parser/unnecessary-let.rs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
fn main() {
2+
for let x of [1, 2, 3] {}
3+
//~^ ERROR expected pattern, found `let`
4+
//~| ERROR missing `in` in `for` loop
5+
6+
match 1 {
7+
let 1 => {}
8+
//~^ ERROR expected pattern, found `let`
9+
_ => {}
10+
}
11+
}
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: expected pattern, found `let`
2+
--> $DIR/unnecessary-let.rs:2:9
3+
|
4+
LL | for let x of [1, 2, 3] {}
5+
| ^^^ help: remove the unnecessary `let` keyword
6+
7+
error: missing `in` in `for` loop
8+
--> $DIR/unnecessary-let.rs:2:15
9+
|
10+
LL | for let x of [1, 2, 3] {}
11+
| ^^ help: try using `in` here instead
12+
13+
error: expected pattern, found `let`
14+
--> $DIR/unnecessary-let.rs:7:9
15+
|
16+
LL | let 1 => {}
17+
| ^^^ help: remove the unnecessary `let` keyword
18+
19+
error: aborting due to 3 previous errors
20+

0 commit comments

Comments
 (0)
Please sign in to comment.