aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_assists/src/handlers/fill_match_arms.rs6
-rw-r--r--crates/ra_assists/src/handlers/merge_match_arms.rs8
-rw-r--r--crates/ra_assists/src/handlers/move_guard.rs6
-rw-r--r--crates/ra_hir_def/src/body/lower.rs15
-rw-r--r--crates/ra_hir_def/src/body/scope.rs4
-rw-r--r--crates/ra_hir_def/src/expr.rs5
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs4
-rw-r--r--crates/ra_hir_ty/src/infer/pat.rs12
-rw-r--r--crates/ra_ide/src/inlay_hints.rs5
-rw-r--r--crates/ra_parser/src/grammar/expressions/atom.rs4
-rw-r--r--crates/ra_parser/src/grammar/params.rs4
-rw-r--r--crates/ra_parser/src/grammar/patterns.rs67
-rw-r--r--crates/ra_parser/src/syntax_kind/generated.rs2
-rw-r--r--crates/ra_syntax/src/ast/generated.rs81
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0030_cond.txt86
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.txt38
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.rs3
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.txt62
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0156_or_pattern.rs8
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0156_or_pattern.txt112
20 files changed, 420 insertions, 112 deletions
diff --git a/crates/ra_assists/src/handlers/fill_match_arms.rs b/crates/ra_assists/src/handlers/fill_match_arms.rs
index 0908fc246..ae2437ed3 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<Assist> {
75} 75}
76 76
77fn is_trivial(arm: &ast::MatchArm) -> bool { 77fn is_trivial(arm: &ast::MatchArm) -> bool {
78 arm.pats().any(|pat| match pat { 78 match arm.pat() {
79 ast::Pat::PlaceholderPat(..) => true, 79 Some(ast::Pat::PlaceholderPat(..)) => true,
80 _ => false, 80 _ => false,
81 }) 81 }
82} 82}
83 83
84fn resolve_enum_def( 84fn 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 670614dd8..b2a194cb5 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<Assist> {
75 } else { 75 } else {
76 arms_to_merge 76 arms_to_merge
77 .iter() 77 .iter()
78 .flat_map(ast::MatchArm::pats) 78 .filter_map(ast::MatchArm::pat)
79 .map(|x| x.syntax().to_string()) 79 .map(|x| x.syntax().to_string())
80 .collect::<Vec<String>>() 80 .collect::<Vec<String>>()
81 .join(" | ") 81 .join(" | ")
@@ -96,10 +96,10 @@ pub(crate) fn merge_match_arms(ctx: AssistCtx) -> Option<Assist> {
96} 96}
97 97
98fn contains_placeholder(a: &ast::MatchArm) -> bool { 98fn contains_placeholder(a: &ast::MatchArm) -> bool {
99 a.pats().any(|x| match x { 99 match a.pat() {
100 ra_syntax::ast::Pat::PlaceholderPat(..) => true, 100 Some(ra_syntax::ast::Pat::PlaceholderPat(..)) => true,
101 _ => false, 101 _ => false,
102 }) 102 }
103} 103}
104 104
105fn next_arm(arm: &ast::MatchArm) -> Option<ast::MatchArm> { 105fn next_arm(arm: &ast::MatchArm) -> Option<ast::MatchArm> {
diff --git a/crates/ra_assists/src/handlers/move_guard.rs b/crates/ra_assists/src/handlers/move_guard.rs
index 2b91ce7c4..a61a2ba3e 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<Assist> {
90// ``` 90// ```
91pub(crate) fn move_arm_cond_to_match_guard(ctx: AssistCtx) -> Option<Assist> { 91pub(crate) fn move_arm_cond_to_match_guard(ctx: AssistCtx) -> Option<Assist> {
92 let match_arm: MatchArm = ctx.find_node_at_offset::<MatchArm>()?; 92 let match_arm: MatchArm = ctx.find_node_at_offset::<MatchArm>()?;
93 let last_match_pat = match_arm.pats().last()?; 93 let match_pat = match_arm.pat()?;
94 94
95 let arm_body = match_arm.expr()?; 95 let arm_body = match_arm.expr()?;
96 let if_expr: IfExpr = IfExpr::cast(arm_body.syntax().clone())?; 96 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<Assist> {
122 _ => edit.replace(if_expr.syntax().text_range(), then_block.syntax().text()), 122 _ => edit.replace(if_expr.syntax().text_range(), then_block.syntax().text()),
123 } 123 }
124 124
125 edit.insert(last_match_pat.syntax().text_range().end(), buf); 125 edit.insert(match_pat.syntax().text_range().end(), buf);
126 edit.set_cursor(last_match_pat.syntax().text_range().end() + TextUnit::from(1)); 126 edit.set_cursor(match_pat.syntax().text_range().end() + TextUnit::from(1));
127 }, 127 },
128 ) 128 )
129} 129}
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index e656f9a41..fe0973fc7 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -164,9 +164,9 @@ where
164 let match_expr = self.collect_expr_opt(condition.expr()); 164 let match_expr = self.collect_expr_opt(condition.expr());
165 let placeholder_pat = self.missing_pat(); 165 let placeholder_pat = self.missing_pat();
166 let arms = vec![ 166 let arms = vec![
167 MatchArm { pats: vec![pat], expr: then_branch, guard: None }, 167 MatchArm { pat, expr: then_branch, guard: None },
168 MatchArm { 168 MatchArm {
169 pats: vec![placeholder_pat], 169 pat: placeholder_pat,
170 expr: else_branch.unwrap_or_else(|| self.empty_block()), 170 expr: else_branch.unwrap_or_else(|| self.empty_block()),
171 guard: None, 171 guard: None,
172 }, 172 },
@@ -203,8 +203,8 @@ where
203 let placeholder_pat = self.missing_pat(); 203 let placeholder_pat = self.missing_pat();
204 let break_ = self.alloc_expr_desugared(Expr::Break { expr: None }); 204 let break_ = self.alloc_expr_desugared(Expr::Break { expr: None });
205 let arms = vec![ 205 let arms = vec![
206 MatchArm { pats: vec![pat], expr: body, guard: None }, 206 MatchArm { pat, expr: body, guard: None },
207 MatchArm { pats: vec![placeholder_pat], expr: break_, guard: None }, 207 MatchArm { pat: placeholder_pat, expr: break_, guard: None },
208 ]; 208 ];
209 let match_expr = 209 let match_expr =
210 self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms }); 210 self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms });
@@ -250,7 +250,7 @@ where
250 match_arm_list 250 match_arm_list
251 .arms() 251 .arms()
252 .map(|arm| MatchArm { 252 .map(|arm| MatchArm {
253 pats: arm.pats().map(|p| self.collect_pat(p)).collect(), 253 pat: self.collect_pat_opt(arm.pat()),
254 expr: self.collect_expr_opt(arm.expr()), 254 expr: self.collect_expr_opt(arm.expr()),
255 guard: arm 255 guard: arm
256 .guard() 256 .guard()
@@ -587,6 +587,11 @@ where
587 let path = p.path().and_then(|path| self.expander.parse_path(path)); 587 let path = p.path().and_then(|path| self.expander.parse_path(path));
588 path.map(Pat::Path).unwrap_or(Pat::Missing) 588 path.map(Pat::Path).unwrap_or(Pat::Missing)
589 } 589 }
590 ast::Pat::OrPat(p) => {
591 let pats = p.pats().map(|p| self.collect_pat(p)).collect();
592 Pat::Or(pats)
593 }
594 ast::Pat::ParenPat(p) => return self.collect_pat_opt(p.pat()),
590 ast::Pat::TuplePat(p) => { 595 ast::Pat::TuplePat(p) => {
591 let args = p.args().map(|p| self.collect_pat(p)).collect(); 596 let args = p.args().map(|p| self.collect_pat(p)).collect();
592 Pat::Tuple(args) 597 Pat::Tuple(args)
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs
index 5d0279945..a58a7b21f 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
158 compute_expr_scopes(*expr, body, scopes, scope); 158 compute_expr_scopes(*expr, body, scopes, scope);
159 for arm in arms { 159 for arm in arms {
160 let scope = scopes.new_scope(scope); 160 let scope = scopes.new_scope(scope);
161 for pat in &arm.pats { 161 scopes.add_bindings(body, scope, arm.pat);
162 scopes.add_bindings(body, scope, *pat);
163 }
164 scopes.set_scope(arm.expr, scope); 162 scopes.set_scope(arm.expr, scope);
165 compute_expr_scopes(arm.expr, body, scopes, scope); 163 compute_expr_scopes(arm.expr, body, scopes, scope);
166 } 164 }
diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs
index a75ef9970..5a84e08ed 100644
--- a/crates/ra_hir_def/src/expr.rs
+++ b/crates/ra_hir_def/src/expr.rs
@@ -202,7 +202,7 @@ pub enum Array {
202 202
203#[derive(Debug, Clone, Eq, PartialEq)] 203#[derive(Debug, Clone, Eq, PartialEq)]
204pub struct MatchArm { 204pub struct MatchArm {
205 pub pats: Vec<PatId>, 205 pub pat: PatId,
206 pub guard: Option<ExprId>, 206 pub guard: Option<ExprId>,
207 pub expr: ExprId, 207 pub expr: ExprId,
208} 208}
@@ -382,6 +382,7 @@ pub enum Pat {
382 Missing, 382 Missing,
383 Wild, 383 Wild,
384 Tuple(Vec<PatId>), 384 Tuple(Vec<PatId>),
385 Or(Vec<PatId>),
385 Record { 386 Record {
386 path: Option<Path>, 387 path: Option<Path>,
387 args: Vec<RecordFieldPat>, 388 args: Vec<RecordFieldPat>,
@@ -420,7 +421,7 @@ impl Pat {
420 Pat::Bind { subpat, .. } => { 421 Pat::Bind { subpat, .. } => {
421 subpat.iter().copied().for_each(f); 422 subpat.iter().copied().for_each(f);
422 } 423 }
423 Pat::Tuple(args) | Pat::TupleStruct { args, .. } => { 424 Pat::Or(args) | Pat::Tuple(args) | Pat::TupleStruct { args, .. } => {
424 args.iter().copied().for_each(f); 425 args.iter().copied().for_each(f);
425 } 426 }
426 Pat::Ref { pat, .. } => f(*pat), 427 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 3c9c02d03..186857b8b 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> {
168 let mut result_ty = self.table.new_maybe_never_type_var(); 168 let mut result_ty = self.table.new_maybe_never_type_var();
169 169
170 for arm in arms { 170 for arm in arms {
171 for &pat in &arm.pats { 171 let _pat_ty = self.infer_pat(arm.pat, &input_ty, BindingMode::default());
172 let _pat_ty = self.infer_pat(pat, &input_ty, BindingMode::default());
173 }
174 if let Some(guard_expr) = arm.guard { 172 if let Some(guard_expr) = arm.guard {
175 self.infer_expr( 173 self.infer_expr(
176 guard_expr, 174 guard_expr,
diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs
index e7283f24c..a5dfdf6c4 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> {
82 82
83 let is_non_ref_pat = match &body[pat] { 83 let is_non_ref_pat = match &body[pat] {
84 Pat::Tuple(..) 84 Pat::Tuple(..)
85 | Pat::Or(..)
85 | Pat::TupleStruct { .. } 86 | Pat::TupleStruct { .. }
86 | Pat::Record { .. } 87 | Pat::Record { .. }
87 | Pat::Range { .. } 88 | Pat::Range { .. }
@@ -126,6 +127,17 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
126 127
127 Ty::apply(TypeCtor::Tuple { cardinality: args.len() as u16 }, Substs(inner_tys)) 128 Ty::apply(TypeCtor::Tuple { cardinality: args.len() as u16 }, Substs(inner_tys))
128 } 129 }
130 Pat::Or(ref pats) => {
131 if let Some((first_pat, rest)) = pats.split_first() {
132 let ty = self.infer_pat(*first_pat, expected, default_bm);
133 for pat in rest {
134 self.infer_pat(*pat, expected, default_bm);
135 }
136 ty
137 } else {
138 Ty::Unknown
139 }
140 }
129 Pat::Ref { pat, mutability } => { 141 Pat::Ref { pat, mutability } => {
130 let expectation = match expected.as_reference() { 142 let expectation = match expected.as_reference() {
131 Some((inner_ty, exp_mut)) => { 143 Some((inner_ty, exp_mut)) => {
diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs
index 6b0d3d996..2ae97e65f 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(
80 }, 80 },
81 ast::MatchArmList(it) => { 81 ast::MatchArmList(it) => {
82 it.arms() 82 it.arms()
83 .map(|match_arm| match_arm.pats()) 83 .filter_map(|match_arm| match_arm.pat())
84 .flatten()
85 .for_each(|root_pat| get_pat_type_hints(acc, db, &analyzer, root_pat, true, max_inlay_hint_length)); 84 .for_each(|root_pat| get_pat_type_hints(acc, db, &analyzer, root_pat, true, max_inlay_hint_length));
86 }, 85 },
87 ast::CallExpr(it) => { 86 ast::CallExpr(it) => {
@@ -202,6 +201,7 @@ fn get_leaf_pats(root_pat: ast::Pat) -> Vec<ast::Pat> {
202 Some(pat) => pats_to_process.push_back(pat), 201 Some(pat) => pats_to_process.push_back(pat),
203 _ => leaf_pats.push(maybe_leaf_pat), 202 _ => leaf_pats.push(maybe_leaf_pat),
204 }, 203 },
204 ast::Pat::OrPat(ref_pat) => pats_to_process.extend(ref_pat.pats()),
205 ast::Pat::TuplePat(tuple_pat) => pats_to_process.extend(tuple_pat.args()), 205 ast::Pat::TuplePat(tuple_pat) => pats_to_process.extend(tuple_pat.args()),
206 ast::Pat::RecordPat(record_pat) => { 206 ast::Pat::RecordPat(record_pat) => {
207 if let Some(pat_list) = record_pat.record_field_pat_list() { 207 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> {
222 ast::Pat::TupleStructPat(tuple_struct_pat) => { 222 ast::Pat::TupleStructPat(tuple_struct_pat) => {
223 pats_to_process.extend(tuple_struct_pat.args()) 223 pats_to_process.extend(tuple_struct_pat.args())
224 } 224 }
225 ast::Pat::ParenPat(inner_pat) => pats_to_process.extend(inner_pat.pat()),
225 ast::Pat::RefPat(ref_pat) => pats_to_process.extend(ref_pat.pat()), 226 ast::Pat::RefPat(ref_pat) => pats_to_process.extend(ref_pat.pat()),
226 _ => (), 227 _ => (),
227 } 228 }
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs
index f154077a8..b72d2e9e6 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<Marker>) -> CompletedMarker {
336fn cond(p: &mut Parser) { 336fn cond(p: &mut Parser) {
337 let m = p.start(); 337 let m = p.start();
338 if p.eat(T![let]) { 338 if p.eat(T![let]) {
339 patterns::pattern_list(p); 339 patterns::pattern_top(p);
340 p.expect(T![=]); 340 p.expect(T![=]);
341 } 341 }
342 expr_no_struct(p); 342 expr_no_struct(p);
@@ -430,7 +430,7 @@ fn match_arm(p: &mut Parser) -> BlockLike {
430 // } 430 // }
431 attributes::outer_attributes(p); 431 attributes::outer_attributes(p);
432 432
433 patterns::pattern_list_r(p, TokenSet::EMPTY); 433 patterns::pattern_top_r(p, TokenSet::EMPTY);
434 if p.at(T![if]) { 434 if p.at(T![if]) {
435 match_guard(p); 435 match_guard(p);
436 } 436 }
diff --git a/crates/ra_parser/src/grammar/params.rs b/crates/ra_parser/src/grammar/params.rs
index 94edc7f35..ed4f93347 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) {
116 // type Qux = fn(baz: Bar::Baz); 116 // type Qux = fn(baz: Bar::Baz);
117 Flavor::FnPointer => { 117 Flavor::FnPointer => {
118 if p.at(IDENT) && p.nth(1) == T![:] && !p.nth_at(1, T![::]) { 118 if p.at(IDENT) && p.nth(1) == T![:] && !p.nth_at(1, T![::]) {
119 patterns::pattern(p); 119 patterns::pattern_single(p);
120 types::ascription(p); 120 types::ascription(p);
121 } else { 121 } else {
122 types::type_(p); 122 types::type_(p);
@@ -127,7 +127,7 @@ fn value_parameter(p: &mut Parser, flavor: Flavor) {
127 // let foo = |bar, baz: Baz, qux: Qux::Quux| (); 127 // let foo = |bar, baz: Baz, qux: Qux::Quux| ();
128 // } 128 // }
129 Flavor::Closure => { 129 Flavor::Closure => {
130 patterns::pattern(p); 130 patterns::pattern_single(p);
131 if p.at(T![:]) && !p.at(T![::]) { 131 if p.at(T![:]) && !p.at(T![::]) {
132 types::ascription(p); 132 types::ascription(p);
133 } 133 }
diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs
index 422a4e3dc..3afbaa82b 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) {
11} 11}
12 12
13/// Parses a pattern list separated by pipes `|` 13/// Parses a pattern list separated by pipes `|`
14pub(super) fn pattern_list(p: &mut Parser) { 14pub(super) fn pattern_top(p: &mut Parser) {
15 pattern_list_r(p, PAT_RECOVERY_SET) 15 pattern_top_r(p, PAT_RECOVERY_SET)
16}
17
18pub(crate) fn pattern_single(p: &mut Parser) {
19 pattern_single_r(p, PAT_RECOVERY_SET);
16} 20}
17 21
18/// Parses a pattern list separated by pipes `|` 22/// Parses a pattern list separated by pipes `|`
19/// using the given `recovery_set` 23/// using the given `recovery_set`
20pub(super) fn pattern_list_r(p: &mut Parser, recovery_set: TokenSet) { 24pub(super) fn pattern_top_r(p: &mut Parser, recovery_set: TokenSet) {
21 p.eat(T![|]); 25 p.eat(T![|]);
22 pattern_r(p, recovery_set); 26 pattern_r(p, recovery_set);
27}
23 28
29/// Parses a pattern list separated by pipes `|`, with no leading `|`,using the
30/// given `recovery_set`
31// test or_pattern
32// fn main() {
33// match () {
34// (_ | _) => (),
35// &(_ | _) => (),
36// (_ | _,) => (),
37// [_ | _,] => (),
38// }
39// }
40fn pattern_r(p: &mut Parser, recovery_set: TokenSet) {
41 let m = p.start();
42 pattern_single_r(p, recovery_set);
43
44 if !p.at(T![|]) {
45 m.abandon(p);
46 return;
47 }
24 while p.eat(T![|]) { 48 while p.eat(T![|]) {
25 pattern_r(p, recovery_set); 49 pattern_single_r(p, recovery_set);
26 } 50 }
51 m.complete(p, OR_PAT);
27} 52}
28 53
29pub(super) fn pattern_r(p: &mut Parser, recovery_set: TokenSet) { 54fn pattern_single_r(p: &mut Parser, recovery_set: TokenSet) {
30 if let Some(lhs) = atom_pat(p, recovery_set) { 55 if let Some(lhs) = atom_pat(p, recovery_set) {
31 // test range_pat 56 // test range_pat
32 // fn main() { 57 // fn main() {
@@ -258,19 +283,41 @@ fn ref_pat(p: &mut Parser) -> CompletedMarker {
258 let m = p.start(); 283 let m = p.start();
259 p.bump(T![&]); 284 p.bump(T![&]);
260 p.eat(T![mut]); 285 p.eat(T![mut]);
261 pattern(p); 286 pattern_single(p);
262 m.complete(p, REF_PAT) 287 m.complete(p, REF_PAT)
263} 288}
264 289
265// test tuple_pat 290// test tuple_pat
266// fn main() { 291// fn main() {
267// let (a, b, ..) = (); 292// let (a, b, ..) = ();
293// let (a,) = ();
294// let (..) = ();
295// let () = ();
268// } 296// }
269fn tuple_pat(p: &mut Parser) -> CompletedMarker { 297fn tuple_pat(p: &mut Parser) -> CompletedMarker {
270 assert!(p.at(T!['('])); 298 assert!(p.at(T!['(']));
271 let m = p.start(); 299 let m = p.start();
272 tuple_pat_fields(p); 300 p.bump(T!['(']);
273 m.complete(p, TUPLE_PAT) 301 let mut has_comma = false;
302 let mut has_pat = false;
303 let mut has_rest = false;
304 while !p.at(EOF) && !p.at(T![')']) {
305 has_pat = true;
306 if !p.at_ts(PATTERN_FIRST) {
307 p.error("expected a pattern");
308 break;
309 }
310 has_rest |= p.at(T![..]);
311
312 pattern(p);
313 if !p.at(T![')']) {
314 has_comma = true;
315 p.expect(T![,]);
316 }
317 }
318 p.expect(T![')']);
319
320 m.complete(p, if !has_comma && !has_rest && has_pat { PAREN_PAT } else { TUPLE_PAT })
274} 321}
275 322
276// test slice_pat 323// test slice_pat
@@ -315,7 +362,7 @@ fn bind_pat(p: &mut Parser, with_at: bool) -> CompletedMarker {
315 p.eat(T![mut]); 362 p.eat(T![mut]);
316 name(p); 363 name(p);
317 if with_at && p.eat(T![@]) { 364 if with_at && p.eat(T![@]) {
318 pattern(p); 365 pattern_single(p);
319 } 366 }
320 m.complete(p, BIND_PAT) 367 m.complete(p, BIND_PAT)
321} 368}
@@ -330,6 +377,6 @@ fn box_pat(p: &mut Parser) -> CompletedMarker {
330 assert!(p.at(T![box])); 377 assert!(p.at(T![box]));
331 let m = p.start(); 378 let m = p.start();
332 p.bump(T![box]); 379 p.bump(T![box]);
333 pattern(p); 380 pattern_single(p);
334 m.complete(p, BOX_PAT) 381 m.complete(p, BOX_PAT)
335} 382}
diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs
index e27b27ffa..1068da0a0 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 {
151 FOR_TYPE, 151 FOR_TYPE,
152 IMPL_TRAIT_TYPE, 152 IMPL_TRAIT_TYPE,
153 DYN_TRAIT_TYPE, 153 DYN_TRAIT_TYPE,
154 OR_PAT,
155 PAREN_PAT,
154 REF_PAT, 156 REF_PAT,
155 BOX_PAT, 157 BOX_PAT,
156 BIND_PAT, 158 BIND_PAT,
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index 435135f92..8d640642d 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 {
1759} 1759}
1760impl ast::AttrsOwner for MatchArm {} 1760impl ast::AttrsOwner for MatchArm {}
1761impl MatchArm { 1761impl MatchArm {
1762 pub fn pats(&self) -> AstChildren<Pat> { 1762 pub fn pat(&self) -> Option<Pat> {
1763 AstChildren::new(&self.syntax) 1763 AstChildren::new(&self.syntax).next()
1764 } 1764 }
1765 pub fn guard(&self) -> Option<MatchGuard> { 1765 pub fn guard(&self) -> Option<MatchGuard> {
1766 AstChildren::new(&self.syntax).next() 1766 AstChildren::new(&self.syntax).next()
@@ -1887,6 +1887,60 @@ impl RecordField {
1887 } 1887 }
1888} 1888}
1889#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1889#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1890pub struct OrPat {
1891 pub(crate) syntax: SyntaxNode,
1892}
1893impl AstNode for OrPat {
1894 fn can_cast(kind: SyntaxKind) -> bool {
1895 match kind {
1896 OR_PAT => true,
1897 _ => false,
1898 }
1899 }
1900 fn cast(syntax: SyntaxNode) -> Option<Self> {
1901 if Self::can_cast(syntax.kind()) {
1902 Some(Self { syntax })
1903 } else {
1904 None
1905 }
1906 }
1907 fn syntax(&self) -> &SyntaxNode {
1908 &self.syntax
1909 }
1910}
1911impl OrPat {
1912 pub fn pats(&self) -> AstChildren<Pat> {
1913 AstChildren::new(&self.syntax)
1914 }
1915}
1916#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1917pub struct ParenPat {
1918 pub(crate) syntax: SyntaxNode,
1919}
1920impl AstNode for ParenPat {
1921 fn can_cast(kind: SyntaxKind) -> bool {
1922 match kind {
1923 PAREN_PAT => true,
1924 _ => false,
1925 }
1926 }
1927 fn cast(syntax: SyntaxNode) -> Option<Self> {
1928 if Self::can_cast(syntax.kind()) {
1929 Some(Self { syntax })
1930 } else {
1931 None
1932 }
1933 }
1934 fn syntax(&self) -> &SyntaxNode {
1935 &self.syntax
1936 }
1937}
1938impl ParenPat {
1939 pub fn pat(&self) -> Option<Pat> {
1940 AstChildren::new(&self.syntax).next()
1941 }
1942}
1943#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1890pub struct RefPat { 1944pub struct RefPat {
1891 pub(crate) syntax: SyntaxNode, 1945 pub(crate) syntax: SyntaxNode,
1892} 1946}
@@ -3900,6 +3954,8 @@ impl AstNode for Expr {
3900} 3954}
3901#[derive(Debug, Clone, PartialEq, Eq, Hash)] 3955#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3902pub enum Pat { 3956pub enum Pat {
3957 OrPat(OrPat),
3958 ParenPat(ParenPat),
3903 RefPat(RefPat), 3959 RefPat(RefPat),
3904 BoxPat(BoxPat), 3960 BoxPat(BoxPat),
3905 BindPat(BindPat), 3961 BindPat(BindPat),
@@ -3913,6 +3969,16 @@ pub enum Pat {
3913 RangePat(RangePat), 3969 RangePat(RangePat),
3914 LiteralPat(LiteralPat), 3970 LiteralPat(LiteralPat),
3915} 3971}
3972impl From<OrPat> for Pat {
3973 fn from(node: OrPat) -> Pat {
3974 Pat::OrPat(node)
3975 }
3976}
3977impl From<ParenPat> for Pat {
3978 fn from(node: ParenPat) -> Pat {
3979 Pat::ParenPat(node)
3980 }
3981}
3916impl From<RefPat> for Pat { 3982impl From<RefPat> for Pat {
3917 fn from(node: RefPat) -> Pat { 3983 fn from(node: RefPat) -> Pat {
3918 Pat::RefPat(node) 3984 Pat::RefPat(node)
@@ -3976,15 +4042,16 @@ impl From<LiteralPat> for Pat {
3976impl AstNode for Pat { 4042impl AstNode for Pat {
3977 fn can_cast(kind: SyntaxKind) -> bool { 4043 fn can_cast(kind: SyntaxKind) -> bool {
3978 match kind { 4044 match kind {
3979 REF_PAT | BOX_PAT | BIND_PAT | PLACEHOLDER_PAT | DOT_DOT_PAT | PATH_PAT 4045 OR_PAT | PAREN_PAT | REF_PAT | BOX_PAT | BIND_PAT | PLACEHOLDER_PAT | DOT_DOT_PAT
3980 | RECORD_PAT | TUPLE_STRUCT_PAT | TUPLE_PAT | SLICE_PAT | RANGE_PAT | LITERAL_PAT => { 4046 | PATH_PAT | RECORD_PAT | TUPLE_STRUCT_PAT | TUPLE_PAT | SLICE_PAT | RANGE_PAT
3981 true 4047 | LITERAL_PAT => true,
3982 }
3983 _ => false, 4048 _ => false,
3984 } 4049 }
3985 } 4050 }
3986 fn cast(syntax: SyntaxNode) -> Option<Self> { 4051 fn cast(syntax: SyntaxNode) -> Option<Self> {
3987 let res = match syntax.kind() { 4052 let res = match syntax.kind() {
4053 OR_PAT => Pat::OrPat(OrPat { syntax }),
4054 PAREN_PAT => Pat::ParenPat(ParenPat { syntax }),
3988 REF_PAT => Pat::RefPat(RefPat { syntax }), 4055 REF_PAT => Pat::RefPat(RefPat { syntax }),
3989 BOX_PAT => Pat::BoxPat(BoxPat { syntax }), 4056 BOX_PAT => Pat::BoxPat(BoxPat { syntax }),
3990 BIND_PAT => Pat::BindPat(BindPat { syntax }), 4057 BIND_PAT => Pat::BindPat(BindPat { syntax }),
@@ -4003,6 +4070,8 @@ impl AstNode for Pat {
4003 } 4070 }
4004 fn syntax(&self) -> &SyntaxNode { 4071 fn syntax(&self) -> &SyntaxNode {
4005 match self { 4072 match self {
4073 Pat::OrPat(it) => &it.syntax,
4074 Pat::ParenPat(it) => &it.syntax,
4006 Pat::RefPat(it) => &it.syntax, 4075 Pat::RefPat(it) => &it.syntax,
4007 Pat::BoxPat(it) => &it.syntax, 4076 Pat::BoxPat(it) => &it.syntax,
4008 Pat::BindPat(it) => &it.syntax, 4077 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 4028ca243..6fd49c7bc 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)
63 CONDITION@[56; 84) 63 CONDITION@[56; 84)
64 LET_KW@[56; 59) "let" 64 LET_KW@[56; 59) "let"
65 WHITESPACE@[59; 60) " " 65 WHITESPACE@[59; 60) " "
66 TUPLE_STRUCT_PAT@[60; 67) 66 OR_PAT@[60; 77)
67 PATH@[60; 64) 67 TUPLE_STRUCT_PAT@[60; 67)
68 PATH_SEGMENT@[60; 64) 68 PATH@[60; 64)
69 NAME_REF@[60; 64) 69 PATH_SEGMENT@[60; 64)
70 IDENT@[60; 64) "Some" 70 NAME_REF@[60; 64)
71 L_PAREN@[64; 65) "(" 71 IDENT@[60; 64) "Some"
72 PLACEHOLDER_PAT@[65; 66) 72 L_PAREN@[64; 65) "("
73 UNDERSCORE@[65; 66) "_" 73 PLACEHOLDER_PAT@[65; 66)
74 R_PAREN@[66; 67) ")" 74 UNDERSCORE@[65; 66) "_"
75 WHITESPACE@[67; 68) " " 75 R_PAREN@[66; 67) ")"
76 PIPE@[68; 69) "|" 76 WHITESPACE@[67; 68) " "
77 WHITESPACE@[69; 70) " " 77 PIPE@[68; 69) "|"
78 TUPLE_STRUCT_PAT@[70; 77) 78 WHITESPACE@[69; 70) " "
79 PATH@[70; 74) 79 TUPLE_STRUCT_PAT@[70; 77)
80 PATH_SEGMENT@[70; 74) 80 PATH@[70; 74)
81 NAME_REF@[70; 74) 81 PATH_SEGMENT@[70; 74)
82 IDENT@[70; 74) "Some" 82 NAME_REF@[70; 74)
83 L_PAREN@[74; 75) "(" 83 IDENT@[70; 74) "Some"
84 PLACEHOLDER_PAT@[75; 76) 84 L_PAREN@[74; 75) "("
85 UNDERSCORE@[75; 76) "_" 85 PLACEHOLDER_PAT@[75; 76)
86 R_PAREN@[76; 77) ")" 86 UNDERSCORE@[75; 76) "_"
87 R_PAREN@[76; 77) ")"
87 WHITESPACE@[77; 78) " " 88 WHITESPACE@[77; 78) " "
88 EQ@[78; 79) "=" 89 EQ@[78; 79) "="
89 WHITESPACE@[79; 80) " " 90 WHITESPACE@[79; 80) " "
@@ -137,27 +138,28 @@ SOURCE_FILE@[0; 197)
137 CONDITION@[129; 157) 138 CONDITION@[129; 157)
138 LET_KW@[129; 132) "let" 139 LET_KW@[129; 132) "let"
139 WHITESPACE@[132; 133) " " 140 WHITESPACE@[132; 133) " "
140 TUPLE_STRUCT_PAT@[133; 140) 141 OR_PAT@[133; 150)
141 PATH@[133; 137) 142 TUPLE_STRUCT_PAT@[133; 140)
142 PATH_SEGMENT@[133; 137) 143 PATH@[133; 137)
143 NAME_REF@[133; 137) 144 PATH_SEGMENT@[133; 137)
144 IDENT@[133; 137) "Some" 145 NAME_REF@[133; 137)
145 L_PAREN@[137; 138) "(" 146 IDENT@[133; 137) "Some"
146 PLACEHOLDER_PAT@[138; 139) 147 L_PAREN@[137; 138) "("
147 UNDERSCORE@[138; 139) "_" 148 PLACEHOLDER_PAT@[138; 139)
148 R_PAREN@[139; 140) ")" 149 UNDERSCORE@[138; 139) "_"
149 WHITESPACE@[140; 141) " " 150 R_PAREN@[139; 140) ")"
150 PIPE@[141; 142) "|" 151 WHITESPACE@[140; 141) " "
151 WHITESPACE@[142; 143) " " 152 PIPE@[141; 142) "|"
152 TUPLE_STRUCT_PAT@[143; 150) 153 WHITESPACE@[142; 143) " "
153 PATH@[143; 147) 154 TUPLE_STRUCT_PAT@[143; 150)
154 PATH_SEGMENT@[143; 147) 155 PATH@[143; 147)
155 NAME_REF@[143; 147) 156 PATH_SEGMENT@[143; 147)
156 IDENT@[143; 147) "Some" 157 NAME_REF@[143; 147)
157 L_PAREN@[147; 148) "(" 158 IDENT@[143; 147) "Some"
158 PLACEHOLDER_PAT@[148; 149) 159 L_PAREN@[147; 148) "("
159 UNDERSCORE@[148; 149) "_" 160 PLACEHOLDER_PAT@[148; 149)
160 R_PAREN@[149; 150) ")" 161 UNDERSCORE@[148; 149) "_"
162 R_PAREN@[149; 150) ")"
161 WHITESPACE@[150; 151) " " 163 WHITESPACE@[150; 151) " "
162 EQ@[151; 152) "=" 164 EQ@[151; 152) "="
163 WHITESPACE@[152; 153) " " 165 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 87272917b..2f07af4e1 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)
74 COMMA@[83; 84) "," 74 COMMA@[83; 84) ","
75 WHITESPACE@[84; 93) "\n " 75 WHITESPACE@[84; 93) "\n "
76 MATCH_ARM@[93; 109) 76 MATCH_ARM@[93; 109)
77 BIND_PAT@[93; 94) 77 OR_PAT@[93; 98)
78 NAME@[93; 94) 78 BIND_PAT@[93; 94)
79 IDENT@[93; 94) "X" 79 NAME@[93; 94)
80 WHITESPACE@[94; 95) " " 80 IDENT@[93; 94) "X"
81 PIPE@[95; 96) "|" 81 WHITESPACE@[94; 95) " "
82 WHITESPACE@[96; 97) " " 82 PIPE@[95; 96) "|"
83 BIND_PAT@[97; 98) 83 WHITESPACE@[96; 97) " "
84 NAME@[97; 98) 84 BIND_PAT@[97; 98)
85 IDENT@[97; 98) "Y" 85 NAME@[97; 98)
86 IDENT@[97; 98) "Y"
86 WHITESPACE@[98; 99) " " 87 WHITESPACE@[98; 99) " "
87 MATCH_GUARD@[99; 103) 88 MATCH_GUARD@[99; 103)
88 IF_KW@[99; 101) "if" 89 IF_KW@[99; 101) "if"
@@ -103,15 +104,16 @@ SOURCE_FILE@[0; 167)
103 MATCH_ARM@[119; 137) 104 MATCH_ARM@[119; 137)
104 PIPE@[119; 120) "|" 105 PIPE@[119; 120) "|"
105 WHITESPACE@[120; 121) " " 106 WHITESPACE@[120; 121) " "
106 BIND_PAT@[121; 122) 107 OR_PAT@[121; 126)
107 NAME@[121; 122) 108 BIND_PAT@[121; 122)
108 IDENT@[121; 122) "X" 109 NAME@[121; 122)
109 WHITESPACE@[122; 123) " " 110 IDENT@[121; 122) "X"
110 PIPE@[123; 124) "|" 111 WHITESPACE@[122; 123) " "
111 WHITESPACE@[124; 125) " " 112 PIPE@[123; 124) "|"
112 BIND_PAT@[125; 126) 113 WHITESPACE@[124; 125) " "
113 NAME@[125; 126) 114 BIND_PAT@[125; 126)
114 IDENT@[125; 126) "Y" 115 NAME@[125; 126)
116 IDENT@[125; 126) "Y"
115 WHITESPACE@[126; 127) " " 117 WHITESPACE@[126; 127) " "
116 MATCH_GUARD@[127; 131) 118 MATCH_GUARD@[127; 131)
117 IF_KW@[127; 129) "if" 119 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 f785acd36..ba719879d 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 @@
1fn main() { 1fn main() {
2 let (a, b, ..) = (); 2 let (a, b, ..) = ();
3 let (a,) = ();
4 let (..) = ();
5 let () = ();
3} 6}
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 674dec493..4680c267e 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 @@
1SOURCE_FILE@[0; 39) 1SOURCE_FILE@[0; 94)
2 FN_DEF@[0; 38) 2 FN_DEF@[0; 93)
3 FN_KW@[0; 2) "fn" 3 FN_KW@[0; 2) "fn"
4 WHITESPACE@[2; 3) " " 4 WHITESPACE@[2; 3) " "
5 NAME@[3; 7) 5 NAME@[3; 7)
@@ -8,8 +8,8 @@ SOURCE_FILE@[0; 39)
8 L_PAREN@[7; 8) "(" 8 L_PAREN@[7; 8) "("
9 R_PAREN@[8; 9) ")" 9 R_PAREN@[8; 9) ")"
10 WHITESPACE@[9; 10) " " 10 WHITESPACE@[9; 10) " "
11 BLOCK_EXPR@[10; 38) 11 BLOCK_EXPR@[10; 93)
12 BLOCK@[10; 38) 12 BLOCK@[10; 93)
13 L_CURLY@[10; 11) "{" 13 L_CURLY@[10; 11) "{"
14 WHITESPACE@[11; 16) "\n " 14 WHITESPACE@[11; 16) "\n "
15 LET_STMT@[16; 36) 15 LET_STMT@[16; 36)
@@ -37,6 +37,54 @@ SOURCE_FILE@[0; 39)
37 L_PAREN@[33; 34) "(" 37 L_PAREN@[33; 34) "("
38 R_PAREN@[34; 35) ")" 38 R_PAREN@[34; 35) ")"
39 SEMI@[35; 36) ";" 39 SEMI@[35; 36) ";"
40 WHITESPACE@[36; 37) "\n" 40 WHITESPACE@[36; 41) "\n "
41 R_CURLY@[37; 38) "}" 41 LET_STMT@[41; 55)
42 WHITESPACE@[38; 39) "\n" 42 LET_KW@[41; 44) "let"
43 WHITESPACE@[44; 45) " "
44 TUPLE_PAT@[45; 49)
45 L_PAREN@[45; 46) "("
46 BIND_PAT@[46; 47)
47 NAME@[46; 47)
48 IDENT@[46; 47) "a"
49 COMMA@[47; 48) ","
50 R_PAREN@[48; 49) ")"
51 WHITESPACE@[49; 50) " "
52 EQ@[50; 51) "="
53 WHITESPACE@[51; 52) " "
54 TUPLE_EXPR@[52; 54)
55 L_PAREN@[52; 53) "("
56 R_PAREN@[53; 54) ")"
57 SEMI@[54; 55) ";"
58 WHITESPACE@[55; 60) "\n "
59 LET_STMT@[60; 74)
60 LET_KW@[60; 63) "let"
61 WHITESPACE@[63; 64) " "
62 TUPLE_PAT@[64; 68)
63 L_PAREN@[64; 65) "("
64 DOT_DOT_PAT@[65; 67)
65 DOTDOT@[65; 67) ".."
66 R_PAREN@[67; 68) ")"
67 WHITESPACE@[68; 69) " "
68 EQ@[69; 70) "="
69 WHITESPACE@[70; 71) " "
70 TUPLE_EXPR@[71; 73)
71 L_PAREN@[71; 72) "("
72 R_PAREN@[72; 73) ")"
73 SEMI@[73; 74) ";"
74 WHITESPACE@[74; 79) "\n "
75 LET_STMT@[79; 91)
76 LET_KW@[79; 82) "let"
77 WHITESPACE@[82; 83) " "
78 TUPLE_PAT@[83; 85)
79 L_PAREN@[83; 84) "("
80 R_PAREN@[84; 85) ")"
81 WHITESPACE@[85; 86) " "
82 EQ@[86; 87) "="
83 WHITESPACE@[87; 88) " "
84 TUPLE_EXPR@[88; 90)
85 L_PAREN@[88; 89) "("
86 R_PAREN@[89; 90) ")"
87 SEMI@[90; 91) ";"
88 WHITESPACE@[91; 92) "\n"
89 R_CURLY@[92; 93) "}"
90 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 000000000..a26316605
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0156_or_pattern.rs
@@ -0,0 +1,8 @@
1fn main() {
2 match () {
3 (_ | _) => (),
4 &(_ | _) => (),
5 (_ | _,) => (),
6 [_ | _,] => (),
7 }
8}
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 000000000..3a196d3c0
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0156_or_pattern.txt
@@ -0,0 +1,112 @@
1SOURCE_FILE@[0; 130)
2 FN_DEF@[0; 129)
3 FN_KW@[0; 2) "fn"
4 WHITESPACE@[2; 3) " "
5 NAME@[3; 7)
6 IDENT@[3; 7) "main"
7 PARAM_LIST@[7; 9)
8 L_PAREN@[7; 8) "("
9 R_PAREN@[8; 9) ")"
10 WHITESPACE@[9; 10) " "
11 BLOCK_EXPR@[10; 129)
12 BLOCK@[10; 129)
13 L_CURLY@[10; 11) "{"
14 WHITESPACE@[11; 16) "\n "
15 MATCH_EXPR@[16; 127)
16 MATCH_KW@[16; 21) "match"
17 WHITESPACE@[21; 22) " "
18 TUPLE_EXPR@[22; 24)
19 L_PAREN@[22; 23) "("
20 R_PAREN@[23; 24) ")"
21 WHITESPACE@[24; 25) " "
22 MATCH_ARM_LIST@[25; 127)
23 L_CURLY@[25; 26) "{"
24 WHITESPACE@[26; 35) "\n "
25 MATCH_ARM@[35; 48)
26 PAREN_PAT@[35; 42)
27 L_PAREN@[35; 36) "("
28 OR_PAT@[36; 41)
29 PLACEHOLDER_PAT@[36; 37)
30 UNDERSCORE@[36; 37) "_"
31 WHITESPACE@[37; 38) " "
32 PIPE@[38; 39) "|"
33 WHITESPACE@[39; 40) " "
34 PLACEHOLDER_PAT@[40; 41)
35 UNDERSCORE@[40; 41) "_"
36 R_PAREN@[41; 42) ")"
37 WHITESPACE@[42; 43) " "
38 FAT_ARROW@[43; 45) "=>"
39 WHITESPACE@[45; 46) " "
40 TUPLE_EXPR@[46; 48)
41 L_PAREN@[46; 47) "("
42 R_PAREN@[47; 48) ")"
43 COMMA@[48; 49) ","
44 WHITESPACE@[49; 58) "\n "
45 MATCH_ARM@[58; 72)
46 REF_PAT@[58; 66)
47 AMP@[58; 59) "&"
48 PAREN_PAT@[59; 66)
49 L_PAREN@[59; 60) "("
50 OR_PAT@[60; 65)
51 PLACEHOLDER_PAT@[60; 61)
52 UNDERSCORE@[60; 61) "_"
53 WHITESPACE@[61; 62) " "
54 PIPE@[62; 63) "|"
55 WHITESPACE@[63; 64) " "
56 PLACEHOLDER_PAT@[64; 65)
57 UNDERSCORE@[64; 65) "_"
58 R_PAREN@[65; 66) ")"
59 WHITESPACE@[66; 67) " "
60 FAT_ARROW@[67; 69) "=>"
61 WHITESPACE@[69; 70) " "
62 TUPLE_EXPR@[70; 72)
63 L_PAREN@[70; 71) "("
64 R_PAREN@[71; 72) ")"
65 COMMA@[72; 73) ","
66 WHITESPACE@[73; 82) "\n "
67 MATCH_ARM@[82; 96)
68 TUPLE_PAT@[82; 90)
69 L_PAREN@[82; 83) "("
70 OR_PAT@[83; 88)
71 PLACEHOLDER_PAT@[83; 84)
72 UNDERSCORE@[83; 84) "_"
73 WHITESPACE@[84; 85) " "
74 PIPE@[85; 86) "|"
75 WHITESPACE@[86; 87) " "
76 PLACEHOLDER_PAT@[87; 88)
77 UNDERSCORE@[87; 88) "_"
78 COMMA@[88; 89) ","
79 R_PAREN@[89; 90) ")"
80 WHITESPACE@[90; 91) " "
81 FAT_ARROW@[91; 93) "=>"
82 WHITESPACE@[93; 94) " "
83 TUPLE_EXPR@[94; 96)
84 L_PAREN@[94; 95) "("
85 R_PAREN@[95; 96) ")"
86 COMMA@[96; 97) ","
87 WHITESPACE@[97; 106) "\n "
88 MATCH_ARM@[106; 120)
89 SLICE_PAT@[106; 114)
90 L_BRACK@[106; 107) "["
91 OR_PAT@[107; 112)
92 PLACEHOLDER_PAT@[107; 108)
93 UNDERSCORE@[107; 108) "_"
94 WHITESPACE@[108; 109) " "
95 PIPE@[109; 110) "|"
96 WHITESPACE@[110; 111) " "
97 PLACEHOLDER_PAT@[111; 112)
98 UNDERSCORE@[111; 112) "_"
99 COMMA@[112; 113) ","
100 R_BRACK@[113; 114) "]"
101 WHITESPACE@[114; 115) " "
102 FAT_ARROW@[115; 117) "=>"
103 WHITESPACE@[117; 118) " "
104 TUPLE_EXPR@[118; 120)
105 L_PAREN@[118; 119) "("
106 R_PAREN@[119; 120) ")"
107 COMMA@[120; 121) ","
108 WHITESPACE@[121; 126) "\n "
109 R_CURLY@[126; 127) "}"
110 WHITESPACE@[127; 128) "\n"
111 R_CURLY@[128; 129) "}"
112 WHITESPACE@[129; 130) "\n"