diff --git a/crates/ra_assists/src/handlers/fill_match_arms.rs b/crates/ra_assists/src/handlers/fill_match_arms.rs index 0908fc2469..ae2437ed32 100644 --- a/crates/ra_assists/src/handlers/fill_match_arms.rs +++ b/crates/ra_assists/src/handlers/fill_match_arms.rs @@ -75,10 +75,10 @@ pub(crate) fn fill_match_arms(ctx: AssistCtx) -> Option { } fn is_trivial(arm: &ast::MatchArm) -> bool { - arm.pats().any(|pat| match pat { - ast::Pat::PlaceholderPat(..) => true, + match arm.pat() { + Some(ast::Pat::PlaceholderPat(..)) => true, _ => false, - }) + } } fn resolve_enum_def( diff --git a/crates/ra_assists/src/handlers/merge_match_arms.rs b/crates/ra_assists/src/handlers/merge_match_arms.rs index 670614dd83..b2a194cb5f 100644 --- a/crates/ra_assists/src/handlers/merge_match_arms.rs +++ b/crates/ra_assists/src/handlers/merge_match_arms.rs @@ -75,7 +75,7 @@ pub(crate) fn merge_match_arms(ctx: AssistCtx) -> Option { } else { arms_to_merge .iter() - .flat_map(ast::MatchArm::pats) + .filter_map(ast::MatchArm::pat) .map(|x| x.syntax().to_string()) .collect::>() .join(" | ") @@ -96,10 +96,10 @@ pub(crate) fn merge_match_arms(ctx: AssistCtx) -> Option { } fn contains_placeholder(a: &ast::MatchArm) -> bool { - a.pats().any(|x| match x { - ra_syntax::ast::Pat::PlaceholderPat(..) => true, + match a.pat() { + Some(ra_syntax::ast::Pat::PlaceholderPat(..)) => true, _ => false, - }) + } } fn next_arm(arm: &ast::MatchArm) -> Option { diff --git a/crates/ra_assists/src/handlers/move_guard.rs b/crates/ra_assists/src/handlers/move_guard.rs index 2b91ce7c4d..a61a2ba3e1 100644 --- a/crates/ra_assists/src/handlers/move_guard.rs +++ b/crates/ra_assists/src/handlers/move_guard.rs @@ -90,7 +90,7 @@ pub(crate) fn move_guard_to_arm_body(ctx: AssistCtx) -> Option { // ``` pub(crate) fn move_arm_cond_to_match_guard(ctx: AssistCtx) -> Option { let match_arm: MatchArm = ctx.find_node_at_offset::()?; - let last_match_pat = match_arm.pats().last()?; + let match_pat = match_arm.pat()?; let arm_body = match_arm.expr()?; let if_expr: IfExpr = IfExpr::cast(arm_body.syntax().clone())?; @@ -122,8 +122,8 @@ pub(crate) fn move_arm_cond_to_match_guard(ctx: AssistCtx) -> Option { _ => edit.replace(if_expr.syntax().text_range(), then_block.syntax().text()), } - edit.insert(last_match_pat.syntax().text_range().end(), buf); - edit.set_cursor(last_match_pat.syntax().text_range().end() + TextUnit::from(1)); + edit.insert(match_pat.syntax().text_range().end(), buf); + edit.set_cursor(match_pat.syntax().text_range().end() + TextUnit::from(1)); }, ) } diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index e656f9a41b..fe0973fc76 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -164,9 +164,9 @@ where let match_expr = self.collect_expr_opt(condition.expr()); let placeholder_pat = self.missing_pat(); let arms = vec![ - MatchArm { pats: vec![pat], expr: then_branch, guard: None }, + MatchArm { pat, expr: then_branch, guard: None }, MatchArm { - pats: vec![placeholder_pat], + pat: placeholder_pat, expr: else_branch.unwrap_or_else(|| self.empty_block()), guard: None, }, @@ -203,8 +203,8 @@ where let placeholder_pat = self.missing_pat(); let break_ = self.alloc_expr_desugared(Expr::Break { expr: None }); let arms = vec![ - MatchArm { pats: vec![pat], expr: body, guard: None }, - MatchArm { pats: vec![placeholder_pat], expr: break_, guard: None }, + MatchArm { pat, expr: body, guard: None }, + MatchArm { pat: placeholder_pat, expr: break_, guard: None }, ]; let match_expr = self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms }); @@ -250,7 +250,7 @@ where match_arm_list .arms() .map(|arm| MatchArm { - pats: arm.pats().map(|p| self.collect_pat(p)).collect(), + pat: self.collect_pat_opt(arm.pat()), expr: self.collect_expr_opt(arm.expr()), guard: arm .guard() @@ -587,6 +587,11 @@ where let path = p.path().and_then(|path| self.expander.parse_path(path)); path.map(Pat::Path).unwrap_or(Pat::Missing) } + ast::Pat::OrPat(p) => { + let pats = p.pats().map(|p| self.collect_pat(p)).collect(); + Pat::Or(pats) + } + ast::Pat::ParenPat(p) => return self.collect_pat_opt(p.pat()), ast::Pat::TuplePat(p) => { let args = p.args().map(|p| self.collect_pat(p)).collect(); Pat::Tuple(args) diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs index 5d02799450..a58a7b21f9 100644 --- a/crates/ra_hir_def/src/body/scope.rs +++ b/crates/ra_hir_def/src/body/scope.rs @@ -158,9 +158,7 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope compute_expr_scopes(*expr, body, scopes, scope); for arm in arms { let scope = scopes.new_scope(scope); - for pat in &arm.pats { - scopes.add_bindings(body, scope, *pat); - } + scopes.add_bindings(body, scope, arm.pat); scopes.set_scope(arm.expr, scope); compute_expr_scopes(arm.expr, body, scopes, scope); } diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs index a75ef9970d..5a84e08ede 100644 --- a/crates/ra_hir_def/src/expr.rs +++ b/crates/ra_hir_def/src/expr.rs @@ -202,7 +202,7 @@ pub enum Array { #[derive(Debug, Clone, Eq, PartialEq)] pub struct MatchArm { - pub pats: Vec, + pub pat: PatId, pub guard: Option, pub expr: ExprId, } @@ -382,6 +382,7 @@ pub enum Pat { Missing, Wild, Tuple(Vec), + Or(Vec), Record { path: Option, args: Vec, @@ -420,7 +421,7 @@ impl Pat { Pat::Bind { subpat, .. } => { subpat.iter().copied().for_each(f); } - Pat::Tuple(args) | Pat::TupleStruct { args, .. } => { + Pat::Or(args) | Pat::Tuple(args) | Pat::TupleStruct { args, .. } => { args.iter().copied().for_each(f); } Pat::Ref { pat, .. } => f(*pat), diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 3c9c02d03e..186857b8b2 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs @@ -168,9 +168,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let mut result_ty = self.table.new_maybe_never_type_var(); for arm in arms { - for &pat in &arm.pats { - let _pat_ty = self.infer_pat(pat, &input_ty, BindingMode::default()); - } + let _pat_ty = self.infer_pat(arm.pat, &input_ty, BindingMode::default()); if let Some(guard_expr) = arm.guard { self.infer_expr( guard_expr, diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs index e7283f24cd..a5dfdf6c4b 100644 --- a/crates/ra_hir_ty/src/infer/pat.rs +++ b/crates/ra_hir_ty/src/infer/pat.rs @@ -82,6 +82,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let is_non_ref_pat = match &body[pat] { Pat::Tuple(..) + | Pat::Or(..) | Pat::TupleStruct { .. } | Pat::Record { .. } | Pat::Range { .. } @@ -126,6 +127,17 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Ty::apply(TypeCtor::Tuple { cardinality: args.len() as u16 }, Substs(inner_tys)) } + Pat::Or(ref pats) => { + if let Some((first_pat, rest)) = pats.split_first() { + let ty = self.infer_pat(*first_pat, expected, default_bm); + for pat in rest { + self.infer_pat(*pat, expected, default_bm); + } + ty + } else { + Ty::Unknown + } + } Pat::Ref { pat, mutability } => { let expectation = match expected.as_reference() { Some((inner_ty, exp_mut)) => { diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index 6b0d3d996f..2ae97e65f5 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs @@ -80,8 +80,7 @@ fn get_inlay_hints( }, ast::MatchArmList(it) => { it.arms() - .map(|match_arm| match_arm.pats()) - .flatten() + .filter_map(|match_arm| match_arm.pat()) .for_each(|root_pat| get_pat_type_hints(acc, db, &analyzer, root_pat, true, max_inlay_hint_length)); }, ast::CallExpr(it) => { @@ -202,6 +201,7 @@ fn get_leaf_pats(root_pat: ast::Pat) -> Vec { Some(pat) => pats_to_process.push_back(pat), _ => leaf_pats.push(maybe_leaf_pat), }, + ast::Pat::OrPat(ref_pat) => pats_to_process.extend(ref_pat.pats()), ast::Pat::TuplePat(tuple_pat) => pats_to_process.extend(tuple_pat.args()), ast::Pat::RecordPat(record_pat) => { if let Some(pat_list) = record_pat.record_field_pat_list() { @@ -222,6 +222,7 @@ fn get_leaf_pats(root_pat: ast::Pat) -> Vec { ast::Pat::TupleStructPat(tuple_struct_pat) => { pats_to_process.extend(tuple_struct_pat.args()) } + ast::Pat::ParenPat(inner_pat) => pats_to_process.extend(inner_pat.pat()), ast::Pat::RefPat(ref_pat) => pats_to_process.extend(ref_pat.pat()), _ => (), } diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs index f154077a86..b72d2e9e64 100644 --- a/crates/ra_parser/src/grammar/expressions/atom.rs +++ b/crates/ra_parser/src/grammar/expressions/atom.rs @@ -336,7 +336,7 @@ fn for_expr(p: &mut Parser, m: Option) -> CompletedMarker { fn cond(p: &mut Parser) { let m = p.start(); if p.eat(T![let]) { - patterns::pattern_list(p); + patterns::pattern_top(p); p.expect(T![=]); } expr_no_struct(p); @@ -430,7 +430,7 @@ fn match_arm(p: &mut Parser) -> BlockLike { // } attributes::outer_attributes(p); - patterns::pattern_list_r(p, TokenSet::EMPTY); + patterns::pattern_top_r(p, TokenSet::EMPTY); if p.at(T![if]) { match_guard(p); } diff --git a/crates/ra_parser/src/grammar/params.rs b/crates/ra_parser/src/grammar/params.rs index 94edc7f35d..ed4f93347a 100644 --- a/crates/ra_parser/src/grammar/params.rs +++ b/crates/ra_parser/src/grammar/params.rs @@ -116,7 +116,7 @@ fn value_parameter(p: &mut Parser, flavor: Flavor) { // type Qux = fn(baz: Bar::Baz); Flavor::FnPointer => { if p.at(IDENT) && p.nth(1) == T![:] && !p.nth_at(1, T![::]) { - patterns::pattern(p); + patterns::pattern_single(p); types::ascription(p); } else { types::type_(p); @@ -127,7 +127,7 @@ fn value_parameter(p: &mut Parser, flavor: Flavor) { // let foo = |bar, baz: Baz, qux: Qux::Quux| (); // } Flavor::Closure => { - patterns::pattern(p); + patterns::pattern_single(p); if p.at(T![:]) && !p.at(T![::]) { types::ascription(p); } diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs index 422a4e3dc1..3afbaa82b8 100644 --- a/crates/ra_parser/src/grammar/patterns.rs +++ b/crates/ra_parser/src/grammar/patterns.rs @@ -11,22 +11,47 @@ pub(crate) fn pattern(p: &mut Parser) { } /// Parses a pattern list separated by pipes `|` -pub(super) fn pattern_list(p: &mut Parser) { - pattern_list_r(p, PAT_RECOVERY_SET) +pub(super) fn pattern_top(p: &mut Parser) { + pattern_top_r(p, PAT_RECOVERY_SET) +} + +pub(crate) fn pattern_single(p: &mut Parser) { + pattern_single_r(p, PAT_RECOVERY_SET); } /// Parses a pattern list separated by pipes `|` /// using the given `recovery_set` -pub(super) fn pattern_list_r(p: &mut Parser, recovery_set: TokenSet) { +pub(super) fn pattern_top_r(p: &mut Parser, recovery_set: TokenSet) { p.eat(T![|]); pattern_r(p, recovery_set); - - while p.eat(T![|]) { - pattern_r(p, recovery_set); - } } -pub(super) fn pattern_r(p: &mut Parser, recovery_set: TokenSet) { +/// Parses a pattern list separated by pipes `|`, with no leading `|`,using the +/// given `recovery_set` +// test or_pattern +// fn main() { +// match () { +// (_ | _) => (), +// &(_ | _) => (), +// (_ | _,) => (), +// [_ | _,] => (), +// } +// } +fn pattern_r(p: &mut Parser, recovery_set: TokenSet) { + let m = p.start(); + pattern_single_r(p, recovery_set); + + if !p.at(T![|]) { + m.abandon(p); + return; + } + while p.eat(T![|]) { + pattern_single_r(p, recovery_set); + } + m.complete(p, OR_PAT); +} + +fn pattern_single_r(p: &mut Parser, recovery_set: TokenSet) { if let Some(lhs) = atom_pat(p, recovery_set) { // test range_pat // fn main() { @@ -258,19 +283,41 @@ fn ref_pat(p: &mut Parser) -> CompletedMarker { let m = p.start(); p.bump(T![&]); p.eat(T![mut]); - pattern(p); + pattern_single(p); m.complete(p, REF_PAT) } // test tuple_pat // fn main() { // let (a, b, ..) = (); +// let (a,) = (); +// let (..) = (); +// let () = (); // } fn tuple_pat(p: &mut Parser) -> CompletedMarker { assert!(p.at(T!['('])); let m = p.start(); - tuple_pat_fields(p); - m.complete(p, TUPLE_PAT) + p.bump(T!['(']); + let mut has_comma = false; + let mut has_pat = false; + let mut has_rest = false; + while !p.at(EOF) && !p.at(T![')']) { + has_pat = true; + if !p.at_ts(PATTERN_FIRST) { + p.error("expected a pattern"); + break; + } + has_rest |= p.at(T![..]); + + pattern(p); + if !p.at(T![')']) { + has_comma = true; + p.expect(T![,]); + } + } + p.expect(T![')']); + + m.complete(p, if !has_comma && !has_rest && has_pat { PAREN_PAT } else { TUPLE_PAT }) } // test slice_pat @@ -315,7 +362,7 @@ fn bind_pat(p: &mut Parser, with_at: bool) -> CompletedMarker { p.eat(T![mut]); name(p); if with_at && p.eat(T![@]) { - pattern(p); + pattern_single(p); } m.complete(p, BIND_PAT) } @@ -330,6 +377,6 @@ fn box_pat(p: &mut Parser) -> CompletedMarker { assert!(p.at(T![box])); let m = p.start(); p.bump(T![box]); - pattern(p); + pattern_single(p); m.complete(p, BOX_PAT) } diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs index e27b27ffab..1068da0a06 100644 --- a/crates/ra_parser/src/syntax_kind/generated.rs +++ b/crates/ra_parser/src/syntax_kind/generated.rs @@ -151,6 +151,8 @@ pub enum SyntaxKind { FOR_TYPE, IMPL_TRAIT_TYPE, DYN_TRAIT_TYPE, + OR_PAT, + PAREN_PAT, REF_PAT, BOX_PAT, BIND_PAT, diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 435135f92d..8d640642d2 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs @@ -1759,8 +1759,8 @@ impl AstNode for MatchArm { } impl ast::AttrsOwner for MatchArm {} impl MatchArm { - pub fn pats(&self) -> AstChildren { - AstChildren::new(&self.syntax) + pub fn pat(&self) -> Option { + AstChildren::new(&self.syntax).next() } pub fn guard(&self) -> Option { AstChildren::new(&self.syntax).next() @@ -1887,6 +1887,60 @@ impl RecordField { } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct OrPat { + pub(crate) syntax: SyntaxNode, +} +impl AstNode for OrPat { + fn can_cast(kind: SyntaxKind) -> bool { + match kind { + OR_PAT => true, + _ => false, + } + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } +} +impl OrPat { + pub fn pats(&self) -> AstChildren { + AstChildren::new(&self.syntax) + } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ParenPat { + pub(crate) syntax: SyntaxNode, +} +impl AstNode for ParenPat { + fn can_cast(kind: SyntaxKind) -> bool { + match kind { + PAREN_PAT => true, + _ => false, + } + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } +} +impl ParenPat { + pub fn pat(&self) -> Option { + AstChildren::new(&self.syntax).next() + } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RefPat { pub(crate) syntax: SyntaxNode, } @@ -3900,6 +3954,8 @@ impl AstNode for Expr { } #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Pat { + OrPat(OrPat), + ParenPat(ParenPat), RefPat(RefPat), BoxPat(BoxPat), BindPat(BindPat), @@ -3913,6 +3969,16 @@ pub enum Pat { RangePat(RangePat), LiteralPat(LiteralPat), } +impl From for Pat { + fn from(node: OrPat) -> Pat { + Pat::OrPat(node) + } +} +impl From for Pat { + fn from(node: ParenPat) -> Pat { + Pat::ParenPat(node) + } +} impl From for Pat { fn from(node: RefPat) -> Pat { Pat::RefPat(node) @@ -3976,15 +4042,16 @@ impl From for Pat { impl AstNode for Pat { fn can_cast(kind: SyntaxKind) -> bool { match kind { - REF_PAT | BOX_PAT | BIND_PAT | PLACEHOLDER_PAT | DOT_DOT_PAT | PATH_PAT - | RECORD_PAT | TUPLE_STRUCT_PAT | TUPLE_PAT | SLICE_PAT | RANGE_PAT | LITERAL_PAT => { - true - } + OR_PAT | PAREN_PAT | REF_PAT | BOX_PAT | BIND_PAT | PLACEHOLDER_PAT | DOT_DOT_PAT + | PATH_PAT | RECORD_PAT | TUPLE_STRUCT_PAT | TUPLE_PAT | SLICE_PAT | RANGE_PAT + | LITERAL_PAT => true, _ => false, } } fn cast(syntax: SyntaxNode) -> Option { let res = match syntax.kind() { + OR_PAT => Pat::OrPat(OrPat { syntax }), + PAREN_PAT => Pat::ParenPat(ParenPat { syntax }), REF_PAT => Pat::RefPat(RefPat { syntax }), BOX_PAT => Pat::BoxPat(BoxPat { syntax }), BIND_PAT => Pat::BindPat(BindPat { syntax }), @@ -4003,6 +4070,8 @@ impl AstNode for Pat { } fn syntax(&self) -> &SyntaxNode { match self { + Pat::OrPat(it) => &it.syntax, + Pat::ParenPat(it) => &it.syntax, Pat::RefPat(it) => &it.syntax, Pat::BoxPat(it) => &it.syntax, Pat::BindPat(it) => &it.syntax, diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0030_cond.txt b/crates/ra_syntax/test_data/parser/inline/ok/0030_cond.txt index 4028ca2437..6fd49c7bc6 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0030_cond.txt +++ b/crates/ra_syntax/test_data/parser/inline/ok/0030_cond.txt @@ -63,27 +63,28 @@ SOURCE_FILE@[0; 197) CONDITION@[56; 84) LET_KW@[56; 59) "let" WHITESPACE@[59; 60) " " - TUPLE_STRUCT_PAT@[60; 67) - PATH@[60; 64) - PATH_SEGMENT@[60; 64) - NAME_REF@[60; 64) - IDENT@[60; 64) "Some" - L_PAREN@[64; 65) "(" - PLACEHOLDER_PAT@[65; 66) - UNDERSCORE@[65; 66) "_" - R_PAREN@[66; 67) ")" - WHITESPACE@[67; 68) " " - PIPE@[68; 69) "|" - WHITESPACE@[69; 70) " " - TUPLE_STRUCT_PAT@[70; 77) - PATH@[70; 74) - PATH_SEGMENT@[70; 74) - NAME_REF@[70; 74) - IDENT@[70; 74) "Some" - L_PAREN@[74; 75) "(" - PLACEHOLDER_PAT@[75; 76) - UNDERSCORE@[75; 76) "_" - R_PAREN@[76; 77) ")" + OR_PAT@[60; 77) + TUPLE_STRUCT_PAT@[60; 67) + PATH@[60; 64) + PATH_SEGMENT@[60; 64) + NAME_REF@[60; 64) + IDENT@[60; 64) "Some" + L_PAREN@[64; 65) "(" + PLACEHOLDER_PAT@[65; 66) + UNDERSCORE@[65; 66) "_" + R_PAREN@[66; 67) ")" + WHITESPACE@[67; 68) " " + PIPE@[68; 69) "|" + WHITESPACE@[69; 70) " " + TUPLE_STRUCT_PAT@[70; 77) + PATH@[70; 74) + PATH_SEGMENT@[70; 74) + NAME_REF@[70; 74) + IDENT@[70; 74) "Some" + L_PAREN@[74; 75) "(" + PLACEHOLDER_PAT@[75; 76) + UNDERSCORE@[75; 76) "_" + R_PAREN@[76; 77) ")" WHITESPACE@[77; 78) " " EQ@[78; 79) "=" WHITESPACE@[79; 80) " " @@ -137,27 +138,28 @@ SOURCE_FILE@[0; 197) CONDITION@[129; 157) LET_KW@[129; 132) "let" WHITESPACE@[132; 133) " " - TUPLE_STRUCT_PAT@[133; 140) - PATH@[133; 137) - PATH_SEGMENT@[133; 137) - NAME_REF@[133; 137) - IDENT@[133; 137) "Some" - L_PAREN@[137; 138) "(" - PLACEHOLDER_PAT@[138; 139) - UNDERSCORE@[138; 139) "_" - R_PAREN@[139; 140) ")" - WHITESPACE@[140; 141) " " - PIPE@[141; 142) "|" - WHITESPACE@[142; 143) " " - TUPLE_STRUCT_PAT@[143; 150) - PATH@[143; 147) - PATH_SEGMENT@[143; 147) - NAME_REF@[143; 147) - IDENT@[143; 147) "Some" - L_PAREN@[147; 148) "(" - PLACEHOLDER_PAT@[148; 149) - UNDERSCORE@[148; 149) "_" - R_PAREN@[149; 150) ")" + OR_PAT@[133; 150) + TUPLE_STRUCT_PAT@[133; 140) + PATH@[133; 137) + PATH_SEGMENT@[133; 137) + NAME_REF@[133; 137) + IDENT@[133; 137) "Some" + L_PAREN@[137; 138) "(" + PLACEHOLDER_PAT@[138; 139) + UNDERSCORE@[138; 139) "_" + R_PAREN@[139; 140) ")" + WHITESPACE@[140; 141) " " + PIPE@[141; 142) "|" + WHITESPACE@[142; 143) " " + TUPLE_STRUCT_PAT@[143; 150) + PATH@[143; 147) + PATH_SEGMENT@[143; 147) + NAME_REF@[143; 147) + IDENT@[143; 147) "Some" + L_PAREN@[147; 148) "(" + PLACEHOLDER_PAT@[148; 149) + UNDERSCORE@[148; 149) "_" + R_PAREN@[149; 150) ")" WHITESPACE@[150; 151) " " EQ@[151; 152) "=" WHITESPACE@[152; 153) " " diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.txt b/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.txt index 87272917b1..2f07af4e19 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.txt +++ b/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.txt @@ -74,15 +74,16 @@ SOURCE_FILE@[0; 167) COMMA@[83; 84) "," WHITESPACE@[84; 93) "\n " MATCH_ARM@[93; 109) - BIND_PAT@[93; 94) - NAME@[93; 94) - IDENT@[93; 94) "X" - WHITESPACE@[94; 95) " " - PIPE@[95; 96) "|" - WHITESPACE@[96; 97) " " - BIND_PAT@[97; 98) - NAME@[97; 98) - IDENT@[97; 98) "Y" + OR_PAT@[93; 98) + BIND_PAT@[93; 94) + NAME@[93; 94) + IDENT@[93; 94) "X" + WHITESPACE@[94; 95) " " + PIPE@[95; 96) "|" + WHITESPACE@[96; 97) " " + BIND_PAT@[97; 98) + NAME@[97; 98) + IDENT@[97; 98) "Y" WHITESPACE@[98; 99) " " MATCH_GUARD@[99; 103) IF_KW@[99; 101) "if" @@ -103,15 +104,16 @@ SOURCE_FILE@[0; 167) MATCH_ARM@[119; 137) PIPE@[119; 120) "|" WHITESPACE@[120; 121) " " - BIND_PAT@[121; 122) - NAME@[121; 122) - IDENT@[121; 122) "X" - WHITESPACE@[122; 123) " " - PIPE@[123; 124) "|" - WHITESPACE@[124; 125) " " - BIND_PAT@[125; 126) - NAME@[125; 126) - IDENT@[125; 126) "Y" + OR_PAT@[121; 126) + BIND_PAT@[121; 122) + NAME@[121; 122) + IDENT@[121; 122) "X" + WHITESPACE@[122; 123) " " + PIPE@[123; 124) "|" + WHITESPACE@[124; 125) " " + BIND_PAT@[125; 126) + NAME@[125; 126) + IDENT@[125; 126) "Y" WHITESPACE@[126; 127) " " MATCH_GUARD@[127; 131) IF_KW@[127; 129) "if" diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.rs b/crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.rs index f785acd36d..ba719879d4 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.rs +++ b/crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.rs @@ -1,3 +1,6 @@ fn main() { let (a, b, ..) = (); + let (a,) = (); + let (..) = (); + let () = (); } diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.txt b/crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.txt index 674dec4937..4680c267e7 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.txt +++ b/crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.txt @@ -1,5 +1,5 @@ -SOURCE_FILE@[0; 39) - FN_DEF@[0; 38) +SOURCE_FILE@[0; 94) + FN_DEF@[0; 93) FN_KW@[0; 2) "fn" WHITESPACE@[2; 3) " " NAME@[3; 7) @@ -8,8 +8,8 @@ SOURCE_FILE@[0; 39) L_PAREN@[7; 8) "(" R_PAREN@[8; 9) ")" WHITESPACE@[9; 10) " " - BLOCK_EXPR@[10; 38) - BLOCK@[10; 38) + BLOCK_EXPR@[10; 93) + BLOCK@[10; 93) L_CURLY@[10; 11) "{" WHITESPACE@[11; 16) "\n " LET_STMT@[16; 36) @@ -37,6 +37,54 @@ SOURCE_FILE@[0; 39) L_PAREN@[33; 34) "(" R_PAREN@[34; 35) ")" SEMI@[35; 36) ";" - WHITESPACE@[36; 37) "\n" - R_CURLY@[37; 38) "}" - WHITESPACE@[38; 39) "\n" + WHITESPACE@[36; 41) "\n " + LET_STMT@[41; 55) + LET_KW@[41; 44) "let" + WHITESPACE@[44; 45) " " + TUPLE_PAT@[45; 49) + L_PAREN@[45; 46) "(" + BIND_PAT@[46; 47) + NAME@[46; 47) + IDENT@[46; 47) "a" + COMMA@[47; 48) "," + R_PAREN@[48; 49) ")" + WHITESPACE@[49; 50) " " + EQ@[50; 51) "=" + WHITESPACE@[51; 52) " " + TUPLE_EXPR@[52; 54) + L_PAREN@[52; 53) "(" + R_PAREN@[53; 54) ")" + SEMI@[54; 55) ";" + WHITESPACE@[55; 60) "\n " + LET_STMT@[60; 74) + LET_KW@[60; 63) "let" + WHITESPACE@[63; 64) " " + TUPLE_PAT@[64; 68) + L_PAREN@[64; 65) "(" + DOT_DOT_PAT@[65; 67) + DOTDOT@[65; 67) ".." + R_PAREN@[67; 68) ")" + WHITESPACE@[68; 69) " " + EQ@[69; 70) "=" + WHITESPACE@[70; 71) " " + TUPLE_EXPR@[71; 73) + L_PAREN@[71; 72) "(" + R_PAREN@[72; 73) ")" + SEMI@[73; 74) ";" + WHITESPACE@[74; 79) "\n " + LET_STMT@[79; 91) + LET_KW@[79; 82) "let" + WHITESPACE@[82; 83) " " + TUPLE_PAT@[83; 85) + L_PAREN@[83; 84) "(" + R_PAREN@[84; 85) ")" + WHITESPACE@[85; 86) " " + EQ@[86; 87) "=" + WHITESPACE@[87; 88) " " + TUPLE_EXPR@[88; 90) + L_PAREN@[88; 89) "(" + R_PAREN@[89; 90) ")" + SEMI@[90; 91) ";" + WHITESPACE@[91; 92) "\n" + R_CURLY@[92; 93) "}" + WHITESPACE@[93; 94) "\n" diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0156_or_pattern.rs b/crates/ra_syntax/test_data/parser/inline/ok/0156_or_pattern.rs new file mode 100644 index 0000000000..a263166055 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0156_or_pattern.rs @@ -0,0 +1,8 @@ +fn main() { + match () { + (_ | _) => (), + &(_ | _) => (), + (_ | _,) => (), + [_ | _,] => (), + } +} diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0156_or_pattern.txt b/crates/ra_syntax/test_data/parser/inline/ok/0156_or_pattern.txt new file mode 100644 index 0000000000..3a196d3c03 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0156_or_pattern.txt @@ -0,0 +1,112 @@ +SOURCE_FILE@[0; 130) + FN_DEF@[0; 129) + FN_KW@[0; 2) "fn" + WHITESPACE@[2; 3) " " + NAME@[3; 7) + IDENT@[3; 7) "main" + PARAM_LIST@[7; 9) + L_PAREN@[7; 8) "(" + R_PAREN@[8; 9) ")" + WHITESPACE@[9; 10) " " + BLOCK_EXPR@[10; 129) + BLOCK@[10; 129) + L_CURLY@[10; 11) "{" + WHITESPACE@[11; 16) "\n " + MATCH_EXPR@[16; 127) + MATCH_KW@[16; 21) "match" + WHITESPACE@[21; 22) " " + TUPLE_EXPR@[22; 24) + L_PAREN@[22; 23) "(" + R_PAREN@[23; 24) ")" + WHITESPACE@[24; 25) " " + MATCH_ARM_LIST@[25; 127) + L_CURLY@[25; 26) "{" + WHITESPACE@[26; 35) "\n " + MATCH_ARM@[35; 48) + PAREN_PAT@[35; 42) + L_PAREN@[35; 36) "(" + OR_PAT@[36; 41) + PLACEHOLDER_PAT@[36; 37) + UNDERSCORE@[36; 37) "_" + WHITESPACE@[37; 38) " " + PIPE@[38; 39) "|" + WHITESPACE@[39; 40) " " + PLACEHOLDER_PAT@[40; 41) + UNDERSCORE@[40; 41) "_" + R_PAREN@[41; 42) ")" + WHITESPACE@[42; 43) " " + FAT_ARROW@[43; 45) "=>" + WHITESPACE@[45; 46) " " + TUPLE_EXPR@[46; 48) + L_PAREN@[46; 47) "(" + R_PAREN@[47; 48) ")" + COMMA@[48; 49) "," + WHITESPACE@[49; 58) "\n " + MATCH_ARM@[58; 72) + REF_PAT@[58; 66) + AMP@[58; 59) "&" + PAREN_PAT@[59; 66) + L_PAREN@[59; 60) "(" + OR_PAT@[60; 65) + PLACEHOLDER_PAT@[60; 61) + UNDERSCORE@[60; 61) "_" + WHITESPACE@[61; 62) " " + PIPE@[62; 63) "|" + WHITESPACE@[63; 64) " " + PLACEHOLDER_PAT@[64; 65) + UNDERSCORE@[64; 65) "_" + R_PAREN@[65; 66) ")" + WHITESPACE@[66; 67) " " + FAT_ARROW@[67; 69) "=>" + WHITESPACE@[69; 70) " " + TUPLE_EXPR@[70; 72) + L_PAREN@[70; 71) "(" + R_PAREN@[71; 72) ")" + COMMA@[72; 73) "," + WHITESPACE@[73; 82) "\n " + MATCH_ARM@[82; 96) + TUPLE_PAT@[82; 90) + L_PAREN@[82; 83) "(" + OR_PAT@[83; 88) + PLACEHOLDER_PAT@[83; 84) + UNDERSCORE@[83; 84) "_" + WHITESPACE@[84; 85) " " + PIPE@[85; 86) "|" + WHITESPACE@[86; 87) " " + PLACEHOLDER_PAT@[87; 88) + UNDERSCORE@[87; 88) "_" + COMMA@[88; 89) "," + R_PAREN@[89; 90) ")" + WHITESPACE@[90; 91) " " + FAT_ARROW@[91; 93) "=>" + WHITESPACE@[93; 94) " " + TUPLE_EXPR@[94; 96) + L_PAREN@[94; 95) "(" + R_PAREN@[95; 96) ")" + COMMA@[96; 97) "," + WHITESPACE@[97; 106) "\n " + MATCH_ARM@[106; 120) + SLICE_PAT@[106; 114) + L_BRACK@[106; 107) "[" + OR_PAT@[107; 112) + PLACEHOLDER_PAT@[107; 108) + UNDERSCORE@[107; 108) "_" + WHITESPACE@[108; 109) " " + PIPE@[109; 110) "|" + WHITESPACE@[110; 111) " " + PLACEHOLDER_PAT@[111; 112) + UNDERSCORE@[111; 112) "_" + COMMA@[112; 113) "," + R_BRACK@[113; 114) "]" + WHITESPACE@[114; 115) " " + FAT_ARROW@[115; 117) "=>" + WHITESPACE@[117; 118) " " + TUPLE_EXPR@[118; 120) + L_PAREN@[118; 119) "(" + R_PAREN@[119; 120) ")" + COMMA@[120; 121) "," + WHITESPACE@[121; 126) "\n " + R_CURLY@[126; 127) "}" + WHITESPACE@[127; 128) "\n" + R_CURLY@[128; 129) "}" + WHITESPACE@[129; 130) "\n" diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs index 67d1f41bca..3f530e4899 100644 --- a/xtask/src/ast_src.rs +++ b/xtask/src/ast_src.rs @@ -120,6 +120,8 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { "FOR_TYPE", "IMPL_TRAIT_TYPE", "DYN_TRAIT_TYPE", + "OR_PAT", + "PAREN_PAT", "REF_PAT", "BOX_PAT", "BIND_PAT", @@ -412,7 +414,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { struct MatchExpr { Expr, MatchArmList } struct MatchArmList: AttrsOwner { arms: [MatchArm] } struct MatchArm: AttrsOwner { - pats: [Pat], + pat: Pat, guard: MatchGuard, Expr, } @@ -425,6 +427,8 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { } struct RecordField { NameRef, Expr } + struct OrPat { pats: [Pat] } + struct ParenPat { Pat } struct RefPat { Pat } struct BoxPat { Pat } struct BindPat: NameOwner { Pat } @@ -601,6 +605,8 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { } enum Pat { + OrPat, + ParenPat, RefPat, BoxPat, BindPat,