diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2025-09-24 23:25:29 +0000 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2025-09-27 00:42:11 +0000 |
| commit | bb48c162b62ce20c5f51b6a435ca2ba7bb918d7e (patch) | |
| tree | b9fb39dea4b8acabfb88168f49afcd3c3c8f68ea /compiler/rustc_parse/src | |
| parent | 43057698c12e8ceab1f49eff8a3e5a38cc05f7db (diff) | |
| download | rust-bb48c162b62ce20c5f51b6a435ca2ba7bb918d7e.tar.gz rust-bb48c162b62ce20c5f51b6a435ca2ba7bb918d7e.zip | |
Simplify logic slightly
Diffstat (limited to 'compiler/rustc_parse/src')
| -rw-r--r-- | compiler/rustc_parse/src/parser/expr.rs | 37 |
1 files changed, 22 insertions, 15 deletions
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 2f4158450d8..8046abcd70b 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -3612,20 +3612,36 @@ impl<'a> Parser<'a> { self.token.is_keyword(kw::Async) && self.is_gen_block(kw::Gen, 1) } + fn is_likely_struct_lit(&self) -> bool { + // `{ ident, ` and `{ ident: ` cannot start a block. + self.look_ahead(1, |t| t.is_ident()) + && self.look_ahead(2, |t| t == &token::Comma || t == &token::Colon) + } + fn maybe_parse_struct_expr( &mut self, qself: &Option<Box<ast::QSelf>>, path: &ast::Path, ) -> Option<PResult<'a, Box<Expr>>> { let struct_allowed = !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL); - let is_ident = self.look_ahead(1, |t| t.is_ident()); - let is_comma = self.look_ahead(2, |t| t == &token::Comma); - let is_colon = self.look_ahead(2, |t| t == &token::Colon); - match (struct_allowed, is_ident, is_comma, is_colon) { - (false, true, true, _) | (false, true, _, true) => { + match (struct_allowed, self.is_likely_struct_lit()) { + // A struct literal isn't expected and one is pretty much assured not to be present. The + // only situation that isn't detected is when a struct with a single field was attempted + // in a place where a struct literal wasn't expected, but regular parser errors apply. + // Happy path. + (false, false) => None, + (true, _) => { + // A struct is accepted here, try to parse it and rely on `parse_expr_struct` for + // any kind of recovery. Happy path. + if let Err(err) = self.expect(exp!(OpenBrace)) { + return Some(Err(err)); + } + Some(self.parse_expr_struct(qself.clone(), path.clone(), true)) + } + (false, true) => { // We have something like `match foo { bar,` or `match foo { bar:`, which means the // user might have meant to write a struct literal as part of the `match` - // discriminant. + // discriminant. This is done purely for error recovery. let snapshot = self.create_snapshot_for_diagnostic(); if let Err(err) = self.expect(exp!(OpenBrace)) { return Some(Err(err)); @@ -3651,15 +3667,6 @@ impl<'a> Parser<'a> { } } } - (true, _, _, _) => { - // A struct is accepted here, try to parse it and rely on `parse_expr_struct` for - // any kind of recovery. - if let Err(err) = self.expect(exp!(OpenBrace)) { - return Some(Err(err)); - } - Some(self.parse_expr_struct(qself.clone(), path.clone(), true)) - } - (false, _, _, _) => None, } } |
