Skip to content

Commit 7dc3c93

Browse files
authored
Rollup merge of rust-lang#63693 - Centril:polish-parse-or-pats, r=estebank
Fully implement or-pattern parsing Builds upon the initial parsing in rust-lang#61708 to fully implement or-pattern (`p | q`) parsing as specified in [the grammar section of RFC 2535](https://github.com/rust-lang/rfcs/blob/master/text/2535-or-patterns.md#grammar). Noteworthy: - We allow or-patterns in `[p | q, ...]`. - We allow or-patterns in `let` statements and `for` expressions including with leading `|`. - We improve recovery for `p || q` (+ tests for that in `multiple-pattern-typo.rs`). - We improve recovery for `| p | q` in inner patterns (tests in `or-patterns-syntactic-fail.rs`). - We rigorously test or-pattern parsing (in `or-patterns-syntactic-{pass,fail}.rs`). - We harden the feature gating tests. - We do **_not_** change `ast.rs`. That is, `ExprKind::Let.0` and `Arm.pats` still accept `Vec<P<Pat>>`. I was starting work on that but it would be cleaner to do this in a separate PR so this one has a narrower scope. cc @dlrobertson cc the tracking issue rust-lang#54883. r? @estebank
2 parents 44cfa78 + 2bd27fb commit 7dc3c93

File tree

67 files changed

+1081
-226
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+1081
-226
lines changed

src/libsyntax/parse/parser.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -971,15 +971,12 @@ impl<'a> Parser<'a> {
971971
/// Skips unexpected attributes and doc comments in this position and emits an appropriate
972972
/// error.
973973
/// This version of parse arg doesn't necessarily require identifier names.
974-
fn parse_arg_general<F>(
974+
fn parse_arg_general(
975975
&mut self,
976976
is_trait_item: bool,
977977
allow_c_variadic: bool,
978-
is_name_required: F,
979-
) -> PResult<'a, Arg>
980-
where
981-
F: Fn(&token::Token) -> bool
982-
{
978+
is_name_required: impl Fn(&token::Token) -> bool,
979+
) -> PResult<'a, Arg> {
983980
let lo = self.token.span;
984981
let attrs = self.parse_arg_attributes()?;
985982
if let Some(mut arg) = self.parse_self_arg()? {
@@ -991,7 +988,7 @@ impl<'a> Parser<'a> {
991988
let (pat, ty) = if is_name_required || self.is_named_argument() {
992989
debug!("parse_arg_general parse_pat (is_name_required:{})", is_name_required);
993990

994-
let pat = self.parse_pat(Some("argument name"))?;
991+
let pat = self.parse_fn_param_pat()?;
995992
if let Err(mut err) = self.expect(&token::Colon) {
996993
if let Some(ident) = self.argument_without_type(
997994
&mut err,

src/libsyntax/parse/parser/expr.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use super::{Parser, PResult, Restrictions, PrevTokenKind, TokenType, PathStyle};
22
use super::{BlockMode, SemiColonMode};
33
use super::{SeqSep, TokenExpectType};
4+
use super::pat::{GateOr, PARAM_EXPECTED};
45

56
use crate::maybe_recover_from_interpolated_ty_qpath;
67
use crate::ptr::P;
@@ -1175,7 +1176,7 @@ impl<'a> Parser<'a> {
11751176
fn parse_fn_block_arg(&mut self) -> PResult<'a, Arg> {
11761177
let lo = self.token.span;
11771178
let attrs = self.parse_arg_attributes()?;
1178-
let pat = self.parse_pat(Some("argument name"))?;
1179+
let pat = self.parse_pat(PARAM_EXPECTED)?;
11791180
let t = if self.eat(&token::Colon) {
11801181
self.parse_ty()?
11811182
} else {
@@ -1241,19 +1242,20 @@ impl<'a> Parser<'a> {
12411242
Ok(cond)
12421243
}
12431244

1244-
/// Parses a `let $pats = $expr` pseudo-expression.
1245+
/// Parses a `let $pat = $expr` pseudo-expression.
12451246
/// The `let` token has already been eaten.
12461247
fn parse_let_expr(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
12471248
let lo = self.prev_span;
1248-
let pats = self.parse_pats()?;
1249+
// FIXME(or_patterns, Centril | dlrobertson): use `parse_top_pat` instead.
1250+
let pat = self.parse_top_pat_unpack(GateOr::No)?;
12491251
self.expect(&token::Eq)?;
12501252
let expr = self.with_res(
12511253
Restrictions::NO_STRUCT_LITERAL,
12521254
|this| this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into())
12531255
)?;
12541256
let span = lo.to(expr.span);
12551257
self.sess.gated_spans.let_chains.borrow_mut().push(span);
1256-
Ok(self.mk_expr(span, ExprKind::Let(pats, expr), attrs))
1258+
Ok(self.mk_expr(span, ExprKind::Let(pat, expr), attrs))
12571259
}
12581260

12591261
/// `else` token already eaten
@@ -1283,7 +1285,7 @@ impl<'a> Parser<'a> {
12831285
_ => None,
12841286
};
12851287

1286-
let pat = self.parse_top_level_pat()?;
1288+
let pat = self.parse_top_pat(GateOr::Yes)?;
12871289
if !self.eat_keyword(kw::In) {
12881290
let in_span = self.prev_span.between(self.token.span);
12891291
self.struct_span_err(in_span, "missing `in` in `for` loop")
@@ -1387,7 +1389,8 @@ impl<'a> Parser<'a> {
13871389
crate fn parse_arm(&mut self) -> PResult<'a, Arm> {
13881390
let attrs = self.parse_outer_attributes()?;
13891391
let lo = self.token.span;
1390-
let pats = self.parse_pats()?;
1392+
// FIXME(or_patterns, Centril | dlrobertson): use `parse_top_pat` instead.
1393+
let pat = self.parse_top_pat_unpack(GateOr::No)?;
13911394
let guard = if self.eat_keyword(kw::If) {
13921395
Some(self.parse_expr()?)
13931396
} else {
@@ -1448,7 +1451,7 @@ impl<'a> Parser<'a> {
14481451

14491452
Ok(ast::Arm {
14501453
attrs,
1451-
pats,
1454+
pats: pat, // FIXME(or_patterns, Centril | dlrobertson): this should just be `pat,`.
14521455
guard,
14531456
body: expr,
14541457
span: lo.to(hi),

0 commit comments

Comments
 (0)