aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-04-11 22:33:17 +0100
committerAleksey Kladov <[email protected]>2020-04-11 23:00:15 +0100
commit5e5eb6a108b00c573455d8d088742592012707be (patch)
tree49146b7e25835f21c09f75ec56e129367f56cab0
parent6b49e774e23c04a04ff5f377fc8dae25b5c69bb0 (diff)
Align grammar for record patterns and literals
The grammar now looks like this [name_ref :] pat
-rw-r--r--crates/ra_assists/src/handlers/reorder_fields.rs32
-rw-r--r--crates/ra_hir_def/src/body/lower.rs2
-rw-r--r--crates/ra_hir_expand/src/name.rs9
-rw-r--r--crates/ra_hir_ty/src/tests/patterns.rs3
-rw-r--r--crates/ra_ide/src/completion/complete_pattern.rs4
-rw-r--r--crates/ra_ide/src/completion/complete_record.rs2
-rw-r--r--crates/ra_ide/src/completion/complete_unqualified_path.rs9
-rw-r--r--crates/ra_ide/src/completion/completion_context.rs12
-rw-r--r--crates/ra_parser/src/grammar/patterns.rs50
-rw-r--r--crates/ra_syntax/src/ast.rs4
-rw-r--r--crates/ra_syntax/src/ast/extensions.rs30
-rw-r--r--crates/ra_syntax/src/ast/generated/nodes.rs2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0102_record_field_pat_list.rast26
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.rast15
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0145_record_field_pat.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0063_trait_fn_patterns.rast14
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0064_impl_fn_params.rast14
-rw-r--r--xtask/src/ast_src.rs2
18 files changed, 145 insertions, 90 deletions
diff --git a/crates/ra_assists/src/handlers/reorder_fields.rs b/crates/ra_assists/src/handlers/reorder_fields.rs
index 692dd1315..a43e53a11 100644
--- a/crates/ra_assists/src/handlers/reorder_fields.rs
+++ b/crates/ra_assists/src/handlers/reorder_fields.rs
@@ -1,20 +1,20 @@
1use std::collections::HashMap; 1use std::collections::HashMap;
2 2
3use itertools::Itertools;
4
5use hir::{Adt, ModuleDef, PathResolution, Semantics, Struct}; 3use hir::{Adt, ModuleDef, PathResolution, Semantics, Struct};
4use itertools::Itertools;
6use ra_ide_db::RootDatabase; 5use ra_ide_db::RootDatabase;
7use ra_syntax::{ 6use ra_syntax::{
8 algo, ast, 7 algo,
9 ast::{Name, Path, RecordLit, RecordPat}, 8 ast::{self, Path, RecordLit, RecordPat},
10 AstNode, SyntaxKind, SyntaxNode, 9 match_ast, AstNode, SyntaxKind,
10 SyntaxKind::*,
11 SyntaxNode,
11}; 12};
12 13
13use crate::{ 14use crate::{
14 assist_ctx::{Assist, AssistCtx}, 15 assist_ctx::{Assist, AssistCtx},
15 AssistId, 16 AssistId,
16}; 17};
17use ra_syntax::ast::{Expr, NameRef};
18 18
19// Assist: reorder_fields 19// Assist: reorder_fields
20// 20//
@@ -59,7 +59,6 @@ fn reorder<R: AstNode>(ctx: AssistCtx) -> Option<Assist> {
59} 59}
60 60
61fn get_fields_kind(node: &SyntaxNode) -> Vec<SyntaxKind> { 61fn get_fields_kind(node: &SyntaxNode) -> Vec<SyntaxKind> {
62 use SyntaxKind::*;
63 match node.kind() { 62 match node.kind() {
64 RECORD_LIT => vec![RECORD_FIELD], 63 RECORD_LIT => vec![RECORD_FIELD],
65 RECORD_PAT => vec![RECORD_FIELD_PAT, BIND_PAT], 64 RECORD_PAT => vec![RECORD_FIELD_PAT, BIND_PAT],
@@ -68,19 +67,14 @@ fn get_fields_kind(node: &SyntaxNode) -> Vec<SyntaxKind> {
68} 67}
69 68
70fn get_field_name(node: &SyntaxNode) -> String { 69fn get_field_name(node: &SyntaxNode) -> String {
71 use SyntaxKind::*; 70 let res = match_ast! {
72 match node.kind() { 71 match node {
73 RECORD_FIELD => { 72 ast::RecordField(field) => { field.field_name().map(|it| it.to_string()) },
74 if let Some(name) = node.children().find_map(NameRef::cast) { 73 ast::RecordFieldPat(field) => { field.field_name().map(|it| it.to_string()) },
75 return name.to_string(); 74 _ => None,
76 }
77 node.children().find_map(Expr::cast).map(|expr| expr.to_string()).unwrap_or_default()
78 }
79 BIND_PAT | RECORD_FIELD_PAT => {
80 node.children().find_map(Name::cast).map(|n| n.to_string()).unwrap_or_default()
81 } 75 }
82 _ => String::new(), 76 };
83 } 77 res.unwrap_or_default()
84} 78}
85 79
86fn get_fields(record: &SyntaxNode) -> Vec<SyntaxNode> { 80fn get_fields(record: &SyntaxNode) -> Vec<SyntaxNode> {
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index c057dc8f2..6caa87db4 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -637,7 +637,7 @@ impl ExprCollector<'_> {
637 let iter = record_field_pat_list.record_field_pats().filter_map(|f| { 637 let iter = record_field_pat_list.record_field_pats().filter_map(|f| {
638 let ast_pat = f.pat()?; 638 let ast_pat = f.pat()?;
639 let pat = self.collect_pat(ast_pat); 639 let pat = self.collect_pat(ast_pat);
640 let name = f.name()?.as_name(); 640 let name = f.field_name()?.as_name();
641 Some(RecordFieldPat { name, pat }) 641 Some(RecordFieldPat { name, pat })
642 }); 642 });
643 fields.extend(iter); 643 fields.extend(iter);
diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs
index 25cc1e9fc..fecce224e 100644
--- a/crates/ra_hir_expand/src/name.rs
+++ b/crates/ra_hir_expand/src/name.rs
@@ -83,6 +83,15 @@ impl AsName for ast::Name {
83 } 83 }
84} 84}
85 85
86impl AsName for ast::NameOrNameRef {
87 fn as_name(&self) -> Name {
88 match self {
89 ast::NameOrNameRef::Name(it) => it.as_name(),
90 ast::NameOrNameRef::NameRef(it) => it.as_name(),
91 }
92 }
93}
94
86impl AsName for tt::Ident { 95impl AsName for tt::Ident {
87 fn as_name(&self) -> Name { 96 fn as_name(&self) -> Name {
88 Name::resolve(&self.text) 97 Name::resolve(&self.text)
diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs
index 6e5d2247c..07cbc521a 100644
--- a/crates/ra_hir_ty/src/tests/patterns.rs
+++ b/crates/ra_hir_ty/src/tests/patterns.rs
@@ -1,7 +1,8 @@
1use super::{infer, infer_with_mismatches};
2use insta::assert_snapshot; 1use insta::assert_snapshot;
3use test_utils::covers; 2use test_utils::covers;
4 3
4use super::{infer, infer_with_mismatches};
5
5#[test] 6#[test]
6fn infer_pattern() { 7fn infer_pattern() {
7 assert_snapshot!( 8 assert_snapshot!(
diff --git a/crates/ra_ide/src/completion/complete_pattern.rs b/crates/ra_ide/src/completion/complete_pattern.rs
index 1b7d3122f..a8b4ce114 100644
--- a/crates/ra_ide/src/completion/complete_pattern.rs
+++ b/crates/ra_ide/src/completion/complete_pattern.rs
@@ -7,6 +7,10 @@ pub(super) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
7 if !ctx.is_pat_binding_or_const { 7 if !ctx.is_pat_binding_or_const {
8 return; 8 return;
9 } 9 }
10 if ctx.record_pat_syntax.is_some() {
11 return;
12 }
13
10 // FIXME: ideally, we should look at the type we are matching against and 14 // FIXME: ideally, we should look at the type we are matching against and
11 // suggest variants + auto-imports 15 // suggest variants + auto-imports
12 ctx.scope().process_all_names(&mut |name, res| { 16 ctx.scope().process_all_names(&mut |name, res| {
diff --git a/crates/ra_ide/src/completion/complete_record.rs b/crates/ra_ide/src/completion/complete_record.rs
index f46bcee5c..83a553155 100644
--- a/crates/ra_ide/src/completion/complete_record.rs
+++ b/crates/ra_ide/src/completion/complete_record.rs
@@ -2,7 +2,7 @@
2use crate::completion::{CompletionContext, Completions}; 2use crate::completion::{CompletionContext, Completions};
3 3
4pub(super) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> { 4pub(super) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
5 let missing_fields = match (ctx.record_lit_pat.as_ref(), ctx.record_lit_syntax.as_ref()) { 5 let missing_fields = match (ctx.record_pat_syntax.as_ref(), ctx.record_lit_syntax.as_ref()) {
6 (None, None) => return None, 6 (None, None) => return None,
7 (Some(_), Some(_)) => unreachable!("A record cannot be both a literal and a pattern"), 7 (Some(_), Some(_)) => unreachable!("A record cannot be both a literal and a pattern"),
8 (Some(record_pat), _) => ctx.sema.record_pattern_missing_fields(record_pat), 8 (Some(record_pat), _) => ctx.sema.record_pattern_missing_fields(record_pat),
diff --git a/crates/ra_ide/src/completion/complete_unqualified_path.rs b/crates/ra_ide/src/completion/complete_unqualified_path.rs
index 0b0da6ee4..2d8e0776c 100644
--- a/crates/ra_ide/src/completion/complete_unqualified_path.rs
+++ b/crates/ra_ide/src/completion/complete_unqualified_path.rs
@@ -3,7 +3,14 @@
3use crate::completion::{CompletionContext, Completions}; 3use crate::completion::{CompletionContext, Completions};
4 4
5pub(super) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) { 5pub(super) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) {
6 if !(ctx.is_trivial_path && !ctx.is_pat_binding_or_const && !ctx.record_lit_syntax.is_some()) { 6 if !ctx.is_trivial_path {
7 return;
8 }
9
10 if ctx.is_pat_binding_or_const
11 || ctx.record_lit_syntax.is_some()
12 || ctx.record_pat_syntax.is_some()
13 {
7 return; 14 return;
8 } 15 }
9 16
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs
index 14a4a14d7..8b3401595 100644
--- a/crates/ra_ide/src/completion/completion_context.rs
+++ b/crates/ra_ide/src/completion/completion_context.rs
@@ -30,7 +30,7 @@ pub(crate) struct CompletionContext<'a> {
30 pub(super) function_syntax: Option<ast::FnDef>, 30 pub(super) function_syntax: Option<ast::FnDef>,
31 pub(super) use_item_syntax: Option<ast::UseItem>, 31 pub(super) use_item_syntax: Option<ast::UseItem>,
32 pub(super) record_lit_syntax: Option<ast::RecordLit>, 32 pub(super) record_lit_syntax: Option<ast::RecordLit>,
33 pub(super) record_lit_pat: Option<ast::RecordPat>, 33 pub(super) record_pat_syntax: Option<ast::RecordPat>,
34 pub(super) impl_def: Option<ast::ImplDef>, 34 pub(super) impl_def: Option<ast::ImplDef>,
35 pub(super) is_param: bool, 35 pub(super) is_param: bool,
36 /// If a name-binding or reference to a const in a pattern. 36 /// If a name-binding or reference to a const in a pattern.
@@ -93,7 +93,7 @@ impl<'a> CompletionContext<'a> {
93 function_syntax: None, 93 function_syntax: None,
94 use_item_syntax: None, 94 use_item_syntax: None,
95 record_lit_syntax: None, 95 record_lit_syntax: None,
96 record_lit_pat: None, 96 record_pat_syntax: None,
97 impl_def: None, 97 impl_def: None,
98 is_param: false, 98 is_param: false,
99 is_pat_binding_or_const: false, 99 is_pat_binding_or_const: false,
@@ -182,6 +182,11 @@ impl<'a> CompletionContext<'a> {
182 self.is_param = true; 182 self.is_param = true;
183 return; 183 return;
184 } 184 }
185 // FIXME: remove this (V) duplication and make the check more precise
186 if name_ref.syntax().ancestors().find_map(ast::RecordFieldPatList::cast).is_some() {
187 self.record_pat_syntax =
188 self.sema.find_node_at_offset_with_macros(&original_file, offset);
189 }
185 self.classify_name_ref(original_file, name_ref, offset); 190 self.classify_name_ref(original_file, name_ref, offset);
186 } 191 }
187 192
@@ -211,8 +216,9 @@ impl<'a> CompletionContext<'a> {
211 self.is_param = true; 216 self.is_param = true;
212 return; 217 return;
213 } 218 }
219 // FIXME: remove this (^) duplication and make the check more precise
214 if name.syntax().ancestors().find_map(ast::RecordFieldPatList::cast).is_some() { 220 if name.syntax().ancestors().find_map(ast::RecordFieldPatList::cast).is_some() {
215 self.record_lit_pat = 221 self.record_pat_syntax =
216 self.sema.find_node_at_offset_with_macros(&original_file, offset); 222 self.sema.find_node_at_offset_with_macros(&original_file, offset);
217 } 223 }
218 } 224 }
diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs
index 936d27575..68fb2fc73 100644
--- a/crates/ra_parser/src/grammar/patterns.rs
+++ b/crates/ra_parser/src/grammar/patterns.rs
@@ -192,14 +192,30 @@ fn record_field_pat_list(p: &mut Parser) {
192 match p.current() { 192 match p.current() {
193 // A trailing `..` is *not* treated as a DOT_DOT_PAT. 193 // A trailing `..` is *not* treated as a DOT_DOT_PAT.
194 T![.] if p.at(T![..]) => p.bump(T![..]), 194 T![.] if p.at(T![..]) => p.bump(T![..]),
195
196 IDENT | INT_NUMBER if p.nth(1) == T![:] => record_field_pat(p),
197 T!['{'] => error_block(p, "expected ident"), 195 T!['{'] => error_block(p, "expected ident"),
198 T![box] => { 196
199 box_pat(p); 197 c => {
200 } 198 let m = p.start();
201 _ => { 199 match c {
202 bind_pat(p, false); 200 // test record_field_pat
201 // fn foo() {
202 // let S { 0: 1 } = ();
203 // let S { x: 1 } = ();
204 // }
205 IDENT | INT_NUMBER if p.nth(1) == T![:] => {
206 name_ref_or_index(p);
207 p.bump(T![:]);
208 pattern(p);
209 }
210 T![box] => {
211 // FIXME: not all box patterns should be allowed
212 box_pat(p);
213 }
214 _ => {
215 bind_pat(p, false);
216 }
217 }
218 m.complete(p, RECORD_FIELD_PAT);
203 } 219 }
204 } 220 }
205 if !p.at(T!['}']) { 221 if !p.at(T!['}']) {
@@ -210,26 +226,6 @@ fn record_field_pat_list(p: &mut Parser) {
210 m.complete(p, RECORD_FIELD_PAT_LIST); 226 m.complete(p, RECORD_FIELD_PAT_LIST);
211} 227}
212 228
213// test record_field_pat
214// fn foo() {
215// let S { 0: 1 } = ();
216// let S { x: 1 } = ();
217// }
218fn record_field_pat(p: &mut Parser) {
219 assert!(p.at(IDENT) || p.at(INT_NUMBER));
220 assert!(p.nth(1) == T![:]);
221
222 let m = p.start();
223
224 if !p.eat(INT_NUMBER) {
225 name(p)
226 }
227
228 p.bump_any();
229 pattern(p);
230 m.complete(p, RECORD_FIELD_PAT);
231}
232
233// test placeholder_pat 229// test placeholder_pat
234// fn main() { let _ = (); } 230// fn main() { let _ = (); }
235fn placeholder_pat(p: &mut Parser) -> CompletedMarker { 231fn placeholder_pat(p: &mut Parser) -> CompletedMarker {
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index 99c6b7219..7fca5661e 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -18,8 +18,8 @@ use crate::{
18pub use self::{ 18pub use self::{
19 expr_extensions::{ArrayExprKind, BinOp, ElseBranch, LiteralKind, PrefixOp, RangeOp}, 19 expr_extensions::{ArrayExprKind, BinOp, ElseBranch, LiteralKind, PrefixOp, RangeOp},
20 extensions::{ 20 extensions::{
21 AttrKind, FieldKind, PathSegmentKind, SelfParamKind, SlicePatComponents, StructKind, 21 AttrKind, FieldKind, NameOrNameRef, PathSegmentKind, SelfParamKind, SlicePatComponents,
22 TypeBoundKind, VisibilityKind, 22 StructKind, TypeBoundKind, VisibilityKind,
23 }, 23 },
24 generated::{nodes::*, tokens::*}, 24 generated::{nodes::*, tokens::*},
25 tokens::*, 25 tokens::*,
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs
index 63e272fbf..f2ea5088e 100644
--- a/crates/ra_syntax/src/ast/extensions.rs
+++ b/crates/ra_syntax/src/ast/extensions.rs
@@ -1,6 +1,8 @@
1//! Various extension methods to ast Nodes, which are hard to code-generate. 1//! Various extension methods to ast Nodes, which are hard to code-generate.
2//! Extensions for various expressions live in a sibling `expr_extensions` module. 2//! Extensions for various expressions live in a sibling `expr_extensions` module.
3 3
4use std::fmt;
5
4use itertools::Itertools; 6use itertools::Itertools;
5use ra_parser::SyntaxKind; 7use ra_parser::SyntaxKind;
6 8
@@ -217,6 +219,34 @@ impl ast::RecordField {
217 } 219 }
218} 220}
219 221
222pub enum NameOrNameRef {
223 Name(ast::Name),
224 NameRef(ast::NameRef),
225}
226
227impl fmt::Display for NameOrNameRef {
228 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
229 match self {
230 NameOrNameRef::Name(it) => fmt::Display::fmt(it, f),
231 NameOrNameRef::NameRef(it) => fmt::Display::fmt(it, f),
232 }
233 }
234}
235
236impl ast::RecordFieldPat {
237 /// Deals with field init shorthand
238 pub fn field_name(&self) -> Option<NameOrNameRef> {
239 if let Some(name_ref) = self.name_ref() {
240 return Some(NameOrNameRef::NameRef(name_ref));
241 }
242 if let Some(ast::Pat::BindPat(pat)) = self.pat() {
243 let name = pat.name()?;
244 return Some(NameOrNameRef::Name(name));
245 }
246 None
247 }
248}
249
220impl ast::EnumVariant { 250impl ast::EnumVariant {
221 pub fn parent_enum(&self) -> ast::EnumDef { 251 pub fn parent_enum(&self) -> ast::EnumDef {
222 self.syntax() 252 self.syntax()
diff --git a/crates/ra_syntax/src/ast/generated/nodes.rs b/crates/ra_syntax/src/ast/generated/nodes.rs
index f1098755b..188f0df96 100644
--- a/crates/ra_syntax/src/ast/generated/nodes.rs
+++ b/crates/ra_syntax/src/ast/generated/nodes.rs
@@ -1806,8 +1806,8 @@ impl AstNode for RecordFieldPat {
1806 fn syntax(&self) -> &SyntaxNode { &self.syntax } 1806 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1807} 1807}
1808impl ast::AttrsOwner for RecordFieldPat {} 1808impl ast::AttrsOwner for RecordFieldPat {}
1809impl ast::NameOwner for RecordFieldPat {}
1810impl RecordFieldPat { 1809impl RecordFieldPat {
1810 pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
1811 pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) } 1811 pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
1812 pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } 1812 pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
1813} 1813}
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0102_record_field_pat_list.rast b/crates/ra_syntax/test_data/parser/inline/ok/0102_record_field_pat_list.rast
index c2614543c..fcd099de9 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0102_record_field_pat_list.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0102_record_field_pat_list.rast
@@ -44,18 +44,20 @@ SOURCE_FILE@[0; 119)
44 RECORD_FIELD_PAT_LIST@[40; 56) 44 RECORD_FIELD_PAT_LIST@[40; 56)
45 L_CURLY@[40; 41) "{" 45 L_CURLY@[40; 41) "{"
46 WHITESPACE@[41; 42) " " 46 WHITESPACE@[41; 42) " "
47 BIND_PAT@[42; 43) 47 RECORD_FIELD_PAT@[42; 43)
48 NAME@[42; 43) 48 BIND_PAT@[42; 43)
49 IDENT@[42; 43) "f" 49 NAME@[42; 43)
50 IDENT@[42; 43) "f"
50 COMMA@[43; 44) "," 51 COMMA@[43; 44) ","
51 WHITESPACE@[44; 45) " " 52 WHITESPACE@[44; 45) " "
52 BIND_PAT@[45; 54) 53 RECORD_FIELD_PAT@[45; 54)
53 REF_KW@[45; 48) "ref" 54 BIND_PAT@[45; 54)
54 WHITESPACE@[48; 49) " " 55 REF_KW@[45; 48) "ref"
55 MUT_KW@[49; 52) "mut" 56 WHITESPACE@[48; 49) " "
56 WHITESPACE@[52; 53) " " 57 MUT_KW@[49; 52) "mut"
57 NAME@[53; 54) 58 WHITESPACE@[52; 53) " "
58 IDENT@[53; 54) "g" 59 NAME@[53; 54)
60 IDENT@[53; 54) "g"
59 WHITESPACE@[54; 55) " " 61 WHITESPACE@[54; 55) " "
60 R_CURLY@[55; 56) "}" 62 R_CURLY@[55; 56) "}"
61 WHITESPACE@[56; 57) " " 63 WHITESPACE@[56; 57) " "
@@ -79,7 +81,7 @@ SOURCE_FILE@[0; 119)
79 L_CURLY@[73; 74) "{" 81 L_CURLY@[73; 74) "{"
80 WHITESPACE@[74; 75) " " 82 WHITESPACE@[74; 75) " "
81 RECORD_FIELD_PAT@[75; 79) 83 RECORD_FIELD_PAT@[75; 79)
82 NAME@[75; 76) 84 NAME_REF@[75; 76)
83 IDENT@[75; 76) "h" 85 IDENT@[75; 76) "h"
84 COLON@[76; 77) ":" 86 COLON@[76; 77) ":"
85 WHITESPACE@[77; 78) " " 87 WHITESPACE@[77; 78) " "
@@ -110,7 +112,7 @@ SOURCE_FILE@[0; 119)
110 L_CURLY@[101; 102) "{" 112 L_CURLY@[101; 102) "{"
111 WHITESPACE@[102; 103) " " 113 WHITESPACE@[102; 103) " "
112 RECORD_FIELD_PAT@[103; 107) 114 RECORD_FIELD_PAT@[103; 107)
113 NAME@[103; 104) 115 NAME_REF@[103; 104)
114 IDENT@[103; 104) "h" 116 IDENT@[103; 104) "h"
115 COLON@[104; 105) ":" 117 COLON@[104; 105) ":"
116 WHITESPACE@[105; 106) " " 118 WHITESPACE@[105; 106) " "
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.rast b/crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.rast
index f75673070..1d245f8f3 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.rast
@@ -44,16 +44,17 @@ SOURCE_FILE@[0; 118)
44 RECORD_FIELD_PAT_LIST@[50; 81) 44 RECORD_FIELD_PAT_LIST@[50; 81)
45 L_CURLY@[50; 51) "{" 45 L_CURLY@[50; 51) "{"
46 WHITESPACE@[51; 52) " " 46 WHITESPACE@[51; 52) " "
47 BOX_PAT@[52; 57) 47 RECORD_FIELD_PAT@[52; 57)
48 BOX_KW@[52; 55) "box" 48 BOX_PAT@[52; 57)
49 WHITESPACE@[55; 56) " " 49 BOX_KW@[52; 55) "box"
50 BIND_PAT@[56; 57) 50 WHITESPACE@[55; 56) " "
51 NAME@[56; 57) 51 BIND_PAT@[56; 57)
52 IDENT@[56; 57) "i" 52 NAME@[56; 57)
53 IDENT@[56; 57) "i"
53 COMMA@[57; 58) "," 54 COMMA@[57; 58) ","
54 WHITESPACE@[58; 59) " " 55 WHITESPACE@[58; 59) " "
55 RECORD_FIELD_PAT@[59; 79) 56 RECORD_FIELD_PAT@[59; 79)
56 NAME@[59; 60) 57 NAME_REF@[59; 60)
57 IDENT@[59; 60) "j" 58 IDENT@[59; 60) "j"
58 COLON@[60; 61) ":" 59 COLON@[60; 61) ":"
59 WHITESPACE@[61; 62) " " 60 WHITESPACE@[61; 62) " "
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0145_record_field_pat.rast b/crates/ra_syntax/test_data/parser/inline/ok/0145_record_field_pat.rast
index 0d786f597..cac2ffdcf 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0145_record_field_pat.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0145_record_field_pat.rast
@@ -25,7 +25,8 @@ SOURCE_FILE@[0; 63)
25 L_CURLY@[21; 22) "{" 25 L_CURLY@[21; 22) "{"
26 WHITESPACE@[22; 23) " " 26 WHITESPACE@[22; 23) " "
27 RECORD_FIELD_PAT@[23; 27) 27 RECORD_FIELD_PAT@[23; 27)
28 INT_NUMBER@[23; 24) "0" 28 NAME_REF@[23; 24)
29 INT_NUMBER@[23; 24) "0"
29 COLON@[24; 25) ":" 30 COLON@[24; 25) ":"
30 WHITESPACE@[25; 26) " " 31 WHITESPACE@[25; 26) " "
31 LITERAL_PAT@[26; 27) 32 LITERAL_PAT@[26; 27)
@@ -54,7 +55,7 @@ SOURCE_FILE@[0; 63)
54 L_CURLY@[46; 47) "{" 55 L_CURLY@[46; 47) "{"
55 WHITESPACE@[47; 48) " " 56 WHITESPACE@[47; 48) " "
56 RECORD_FIELD_PAT@[48; 52) 57 RECORD_FIELD_PAT@[48; 52)
57 NAME@[48; 49) 58 NAME_REF@[48; 49)
58 IDENT@[48; 49) "x" 59 IDENT@[48; 49) "x"
59 COLON@[49; 50) ":" 60 COLON@[49; 50) ":"
60 WHITESPACE@[50; 51) " " 61 WHITESPACE@[50; 51) " "
diff --git a/crates/ra_syntax/test_data/parser/ok/0063_trait_fn_patterns.rast b/crates/ra_syntax/test_data/parser/ok/0063_trait_fn_patterns.rast
index 9b5954ebd..d0623ba90 100644
--- a/crates/ra_syntax/test_data/parser/ok/0063_trait_fn_patterns.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0063_trait_fn_patterns.rast
@@ -68,14 +68,16 @@ SOURCE_FILE@[0; 170)
68 RECORD_FIELD_PAT_LIST@[59; 67) 68 RECORD_FIELD_PAT_LIST@[59; 67)
69 L_CURLY@[59; 60) "{" 69 L_CURLY@[59; 60) "{"
70 WHITESPACE@[60; 61) " " 70 WHITESPACE@[60; 61) " "
71 BIND_PAT@[61; 62) 71 RECORD_FIELD_PAT@[61; 62)
72 NAME@[61; 62) 72 BIND_PAT@[61; 62)
73 IDENT@[61; 62) "a" 73 NAME@[61; 62)
74 IDENT@[61; 62) "a"
74 COMMA@[62; 63) "," 75 COMMA@[62; 63) ","
75 WHITESPACE@[63; 64) " " 76 WHITESPACE@[63; 64) " "
76 BIND_PAT@[64; 65) 77 RECORD_FIELD_PAT@[64; 65)
77 NAME@[64; 65) 78 BIND_PAT@[64; 65)
78 IDENT@[64; 65) "b" 79 NAME@[64; 65)
80 IDENT@[64; 65) "b"
79 WHITESPACE@[65; 66) " " 81 WHITESPACE@[65; 66) " "
80 R_CURLY@[66; 67) "}" 82 R_CURLY@[66; 67) "}"
81 COLON@[67; 68) ":" 83 COLON@[67; 68) ":"
diff --git a/crates/ra_syntax/test_data/parser/ok/0064_impl_fn_params.rast b/crates/ra_syntax/test_data/parser/ok/0064_impl_fn_params.rast
index b30030de3..5e96b695b 100644
--- a/crates/ra_syntax/test_data/parser/ok/0064_impl_fn_params.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0064_impl_fn_params.rast
@@ -71,14 +71,16 @@ SOURCE_FILE@[0; 137)
71 RECORD_FIELD_PAT_LIST@[58; 66) 71 RECORD_FIELD_PAT_LIST@[58; 66)
72 L_CURLY@[58; 59) "{" 72 L_CURLY@[58; 59) "{"
73 WHITESPACE@[59; 60) " " 73 WHITESPACE@[59; 60) " "
74 BIND_PAT@[60; 61) 74 RECORD_FIELD_PAT@[60; 61)
75 NAME@[60; 61) 75 BIND_PAT@[60; 61)
76 IDENT@[60; 61) "a" 76 NAME@[60; 61)
77 IDENT@[60; 61) "a"
77 COMMA@[61; 62) "," 78 COMMA@[61; 62) ","
78 WHITESPACE@[62; 63) " " 79 WHITESPACE@[62; 63) " "
79 BIND_PAT@[63; 64) 80 RECORD_FIELD_PAT@[63; 64)
80 NAME@[63; 64) 81 BIND_PAT@[63; 64)
81 IDENT@[63; 64) "b" 82 NAME@[63; 64)
83 IDENT@[63; 64) "b"
82 WHITESPACE@[64; 65) " " 84 WHITESPACE@[64; 65) " "
83 R_CURLY@[65; 66) "}" 85 R_CURLY@[65; 66) "}"
84 COLON@[66; 67) ":" 86 COLON@[66; 67) ":"
diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs
index 69cba9168..9c02f7c6f 100644
--- a/xtask/src/ast_src.rs
+++ b/xtask/src/ast_src.rs
@@ -511,7 +511,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
511 T![..], 511 T![..],
512 T!['}'] 512 T!['}']
513 } 513 }
514 struct RecordFieldPat: AttrsOwner, NameOwner { T![:], Pat } 514 struct RecordFieldPat: AttrsOwner { NameRef, T![:], Pat }
515 515
516 struct TupleStructPat { Path, T!['('], args: [Pat], T![')'] } 516 struct TupleStructPat { Path, T!['('], args: [Pat], T![')'] }
517 struct TuplePat { T!['('], args: [Pat], T![')'] } 517 struct TuplePat { T!['('], args: [Pat], T![')'] }