diff options
| author | bors <bors@rust-lang.org> | 2022-06-08 23:07:22 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-06-08 23:07:22 +0000 |
| commit | 15f5622a53210099a19ab46ce2316494fb413d7c (patch) | |
| tree | 633084d6eb33de525f55ae47663320370d9e6fc0 /compiler/rustc_parse/src/parser | |
| parent | 7466d5492b2d28d2ba5114dbe71511a6502ac822 (diff) | |
| parent | cfc0677992662076f8fa65062a229aaae495f030 (diff) | |
| download | rust-15f5622a53210099a19ab46ce2316494fb413d7c.tar.gz rust-15f5622a53210099a19ab46ce2316494fb413d7c.zip | |
Auto merge of #97896 - compiler-errors:rollup-mrl7ng0, r=compiler-errors
Rollup of 9 pull requests Successful merges: - #97557 (Fix indices and remove some unwraps in arg mismatch algorithm) - #97830 (Add std::alloc::set_alloc_error_hook example) - #97856 (Don't suggest adding `let` in certain `if` conditions) - #97857 (Suggest escaping `box` as identifier) - #97871 (Suggest using `iter()` or `into_iter()` for `Vec`) - #97882 (Add regresion test for #67498) - #97883 (Remove `ignore-compare-mode-nll` annotations from tests) - #97891 (Update books) - #97894 (Fix polonius compare mode.) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler/rustc_parse/src/parser')
| -rw-r--r-- | compiler/rustc_parse/src/parser/pat.rs | 61 |
1 files changed, 57 insertions, 4 deletions
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 2ad3f3ec19d..ca7915ed17a 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -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)?; @@ -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(); |
