diff options
| author | Nadrieril <nadrieril+git@gmail.com> | 2024-11-24 17:36:52 +0100 |
|---|---|---|
| committer | Nadrieril <nadrieril+git@gmail.com> | 2024-11-24 19:42:33 +0100 |
| commit | 962c0140c71f07642a7c39243c8a9a314dd26ba5 (patch) | |
| tree | d923138e49e35bc7f521b6acb77c69effbaae196 /compiler/rustc_parse/src/parser/expr.rs | |
| parent | f86915a6828b64abfa75936ab0f1cddf7fdf7fee (diff) | |
| download | rust-962c0140c71f07642a7c39243c8a9a314dd26ba5.tar.gz rust-962c0140c71f07642a7c39243c8a9a314dd26ba5.zip | |
parse guard patterns
Co-authored-by: Max Niederman <max@maxniederman.com>
Diffstat (limited to 'compiler/rustc_parse/src/parser/expr.rs')
| -rw-r--r-- | compiler/rustc_parse/src/parser/expr.rs | 52 |
1 files changed, 23 insertions, 29 deletions
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index a6c7c4e3bba..adbb6b44104 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2776,7 +2776,7 @@ impl<'a> Parser<'a> { }; // Try to parse the pattern `for ($PAT) in $EXPR`. let pat = match ( - self.parse_pat_no_top_guard( + self.parse_pat_allow_top_guard( None, RecoverComma::Yes, RecoverColon::Yes, @@ -3313,39 +3313,33 @@ impl<'a> Parser<'a> { fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (P<Pat>, Option<P<Expr>>)> { if self.token == token::OpenDelim(Delimiter::Parenthesis) { - // Detect and recover from `($pat if $cond) => $arm`. let left = self.token.span; - match self.parse_pat_no_top_guard( + let pat = self.parse_pat_no_top_guard( None, RecoverComma::Yes, RecoverColon::Yes, CommaRecoveryMode::EitherTupleOrPipe, - ) { - Ok(pat) => Ok((pat, self.parse_match_arm_guard()?)), - Err(err) - if let prev_sp = self.prev_token.span - && let true = self.eat_keyword(kw::If) => - { - // We know for certain we've found `($pat if` so far. - let mut cond = match self.parse_match_guard_condition() { - Ok(cond) => cond, - Err(cond_err) => { - cond_err.cancel(); - return Err(err); - } - }; - err.cancel(); - CondChecker::new(self).visit_expr(&mut cond); - self.eat_to_tokens(&[&token::CloseDelim(Delimiter::Parenthesis)]); - self.expect(&token::CloseDelim(Delimiter::Parenthesis))?; - let right = self.prev_token.span; - self.dcx().emit_err(errors::ParenthesesInMatchPat { - span: vec![left, right], - sugg: errors::ParenthesesInMatchPatSugg { left, right }, - }); - Ok((self.mk_pat(left.to(prev_sp), ast::PatKind::Wild), Some(cond))) - } - Err(err) => Err(err), + )?; + if let ast::PatKind::Paren(subpat) = &pat.kind + && let ast::PatKind::Guard(..) = &subpat.kind + { + // Detect and recover from `($pat if $cond) => $arm`. + // FIXME(guard_patterns): convert this to a normal guard instead + let span = pat.span; + let ast::PatKind::Paren(subpat) = pat.into_inner().kind else { unreachable!() }; + let ast::PatKind::Guard(_, mut cond) = subpat.into_inner().kind else { + unreachable!() + }; + self.psess.gated_spans.ungate_last(sym::guard_patterns, cond.span); + CondChecker::new(self).visit_expr(&mut cond); + let right = self.prev_token.span; + self.dcx().emit_err(errors::ParenthesesInMatchPat { + span: vec![left, right], + sugg: errors::ParenthesesInMatchPatSugg { left, right }, + }); + Ok((self.mk_pat(span, ast::PatKind::Wild), Some(cond))) + } else { + Ok((pat, self.parse_match_arm_guard()?)) } } else { // Regular parser flow: |
