Skip to content

Commit

Permalink
Suggest escaping box as identifier
Browse files Browse the repository at this point in the history
  • Loading branch information
ChayimFriedman2 authored Jun 8, 2022
1 parent 50b0025 commit c1b1ec7
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 8 deletions.
61 changes: 57 additions & 4 deletions compiler/rustc_parse/src/parser/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,10 +360,7 @@ impl<'a> Parser<'a> {
let mutbl = self.parse_mutability();
self.parse_pat_ident(BindingMode::ByRef(mutbl))?
} else if self.eat_keyword(kw::Box) {
// Parse `box pat`
let pat = self.parse_pat_with_range_pat(false, None)?;
self.sess.gated_spans.gate(sym::box_patterns, lo.to(self.prev_token.span));
PatKind::Box(pat)
self.parse_pat_box()?
} else if self.check_inline_const(0) {
// Parse `const pat`
let const_expr = self.parse_const_block(lo.to(self.token.span), true)?;
Expand Down Expand Up @@ -915,6 +912,62 @@ impl<'a> Parser<'a> {
Ok(PatKind::TupleStruct(qself, path, fields))
}

/// Are we sure this could not possibly be the start of a pattern?
///
/// Currently, this only accounts for tokens that can follow identifiers
/// in patterns, but this can be extended as necessary.
fn isnt_pattern_start(&self) -> bool {
[
token::Eq,
token::Colon,
token::Comma,
token::Semi,
token::At,
token::OpenDelim(Delimiter::Brace),
token::CloseDelim(Delimiter::Brace),
token::CloseDelim(Delimiter::Parenthesis),
]
.contains(&self.token.kind)
}

/// Parses `box pat`
fn parse_pat_box(&mut self) -> PResult<'a, PatKind> {
let box_span = self.prev_token.span;

if self.isnt_pattern_start() {
self.struct_span_err(
self.token.span,
format!("expected pattern, found {}", super::token_descr(&self.token)),
)
.span_note(box_span, "`box` is a reserved keyword")
.span_suggestion_verbose(
box_span.shrink_to_lo(),
"escape `box` to use it as an identifier",
"r#",
Applicability::MaybeIncorrect,
)
.emit();

// We cannot use `parse_pat_ident()` since it will complain `box`
// is not an identifier.
let sub = if self.eat(&token::At) {
Some(self.parse_pat_no_top_alt(Some("binding pattern"))?)
} else {
None
};

Ok(PatKind::Ident(
BindingMode::ByValue(Mutability::Not),
Ident::new(kw::Box, box_span),
sub,
))
} else {
let pat = self.parse_pat_with_range_pat(false, None)?;
self.sess.gated_spans.gate(sym::box_patterns, box_span.to(self.prev_token.span));
Ok(PatKind::Box(pat))
}
}

/// Parses the fields of a struct-like pattern.
fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<PatField>, bool)> {
let mut fields = Vec::new();
Expand Down
9 changes: 8 additions & 1 deletion src/test/ui/parser/keyword-box-as-identifier.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
fn main() {
let box = "foo"; //~ error: expected pattern, found `=`
let box = 0;
//~^ ERROR expected pattern, found `=`
let box: bool;
//~^ ERROR expected pattern, found `:`
let mut box = 0;
//~^ ERROR expected pattern, found `=`
let (box,) = (0,);
//~^ ERROR expected pattern, found `,`
}
64 changes: 61 additions & 3 deletions src/test/ui/parser/keyword-box-as-identifier.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,66 @@
error: expected pattern, found `=`
--> $DIR/keyword-box-as-identifier.rs:2:13
|
LL | let box = "foo";
| ^ expected pattern
LL | let box = 0;
| ^
|
note: `box` is a reserved keyword
--> $DIR/keyword-box-as-identifier.rs:2:9
|
LL | let box = 0;
| ^^^
help: escape `box` to use it as an identifier
|
LL | let r#box = 0;
| ++

error: expected pattern, found `:`
--> $DIR/keyword-box-as-identifier.rs:4:12
|
LL | let box: bool;
| ^
|
note: `box` is a reserved keyword
--> $DIR/keyword-box-as-identifier.rs:4:9
|
LL | let box: bool;
| ^^^
help: escape `box` to use it as an identifier
|
LL | let r#box: bool;
| ++

error: expected pattern, found `=`
--> $DIR/keyword-box-as-identifier.rs:6:17
|
LL | let mut box = 0;
| ^
|
note: `box` is a reserved keyword
--> $DIR/keyword-box-as-identifier.rs:6:13
|
LL | let mut box = 0;
| ^^^
help: escape `box` to use it as an identifier
|
LL | let mut r#box = 0;
| ++

error: expected pattern, found `,`
--> $DIR/keyword-box-as-identifier.rs:8:13
|
LL | let (box,) = (0,);
| ^
|
note: `box` is a reserved keyword
--> $DIR/keyword-box-as-identifier.rs:8:10
|
LL | let (box,) = (0,);
| ^^^
help: escape `box` to use it as an identifier
|
LL | let (r#box,) = (0,);
| ++

error: aborting due to previous error
error: aborting due to 4 previous errors

0 comments on commit c1b1ec7

Please sign in to comment.