aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml1
-rw-r--r--Cargo.lock11
-rw-r--r--crates/ra_assists/src/add_missing_impl_members.rs14
-rw-r--r--crates/ra_assists/src/ast_editor.rs116
-rw-r--r--crates/ra_assists/src/change_visibility.rs2
-rw-r--r--crates/ra_assists/src/fill_match_arms.rs195
-rw-r--r--crates/ra_batch/Cargo.toml3
-rw-r--r--crates/ra_batch/src/lib.rs10
-rw-r--r--crates/ra_hir/src/code_model.rs4
-rw-r--r--crates/ra_hir/src/diagnostics.rs36
-rw-r--r--crates/ra_hir/src/expr.rs43
-rw-r--r--crates/ra_hir/src/expr/validation.rs69
-rw-r--r--crates/ra_hir/src/name.rs2
-rw-r--r--crates/ra_hir/src/source_binder.rs8
-rw-r--r--crates/ra_hir/src/ty/infer.rs31
-rw-r--r--crates/ra_ide_api/src/completion.rs8
-rw-r--r--crates/ra_ide_api/src/completion/complete_dot.rs2
-rw-r--r--crates/ra_ide_api/src/completion/complete_record_literal.rs (renamed from crates/ra_ide_api/src/completion/complete_struct_literal.rs)14
-rw-r--r--crates/ra_ide_api/src/completion/complete_record_pattern.rs (renamed from crates/ra_ide_api/src/completion/complete_struct_pattern.rs)10
-rw-r--r--crates/ra_ide_api/src/completion/completion_context.rs16
-rw-r--r--crates/ra_ide_api/src/completion/presentation.rs2
-rw-r--r--crates/ra_ide_api/src/diagnostics.rs233
-rw-r--r--crates/ra_ide_api/src/display/navigation_target.rs4
-rw-r--r--crates/ra_ide_api/src/display/short_label.rs2
-rw-r--r--crates/ra_ide_api/src/display/structure.rs4
-rw-r--r--crates/ra_ide_api/src/extend_selection.rs8
-rw-r--r--crates/ra_ide_api/src/folding_ranges.rs10
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs12
-rw-r--r--crates/ra_ide_api/src/hover.rs2
-rw-r--r--crates/ra_ide_api/src/inlay_hints.rs10
-rw-r--r--crates/ra_ide_api/src/marks.rs2
-rw-r--r--crates/ra_ide_api/src/name_ref_kind.rs8
-rw-r--r--crates/ra_ide_api/src/syntax_highlighting.rs2
-rw-r--r--crates/ra_lsp_server/Cargo.toml2
-rw-r--r--crates/ra_lsp_server/src/conv.rs2
-rw-r--r--crates/ra_lsp_server/src/main_loop.rs2
-rw-r--r--crates/ra_lsp_server/src/world.rs10
-rw-r--r--crates/ra_mbe/src/tests.rs8
-rw-r--r--crates/ra_parser/src/grammar.rs4
-rw-r--r--crates/ra_parser/src/grammar/expressions.rs14
-rw-r--r--crates/ra_parser/src/grammar/expressions/atom.rs2
-rw-r--r--crates/ra_parser/src/grammar/items.rs4
-rw-r--r--crates/ra_parser/src/grammar/items/nominal.rs30
-rw-r--r--crates/ra_parser/src/grammar/patterns.rs65
-rw-r--r--crates/ra_parser/src/syntax_kind/generated.rs21
-rw-r--r--crates/ra_syntax/src/ast.rs12
-rw-r--r--crates/ra_syntax/src/ast/expr_extensions.rs6
-rw-r--r--crates/ra_syntax/src/ast/extensions.rs8
-rw-r--r--crates/ra_syntax/src/ast/generated.rs559
-rw-r--r--crates/ra_syntax/src/grammar.ron51
-rw-r--r--crates/ra_syntax/src/parsing/text_tree_sink.rs2
-rw-r--r--crates/ra_syntax/src/ptr.rs9
-rw-r--r--crates/ra_syntax/src/validation.rs2
-rw-r--r--crates/ra_syntax/test_data/parser/err/0000_struct_field_missing_comma.txt6
-rw-r--r--crates/ra_syntax/test_data/parser/err/0001_item_recovery_in_file.txt2
-rw-r--r--crates/ra_syntax/test_data/parser/err/0003_C++_semicolon.txt6
-rw-r--r--crates/ra_syntax/test_data/parser/err/0006_named_field_recovery.txt8
-rw-r--r--crates/ra_syntax/test_data/parser/err/0013_invalid_type.txt6
-rw-r--r--crates/ra_syntax/test_data/parser/err/0018_incomplete_fn.txt8
-rw-r--r--crates/ra_syntax/test_data/parser/err/0025_nope.txt16
-rw-r--r--crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.rs6
-rw-r--r--crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.txt95
-rw-r--r--crates/ra_syntax/test_data/parser/fuzz-failures/0000.rs4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0008_path_part.txt4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0040_crate_keyword_vis.txt8
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0054_record_field_attrs.rs (renamed from crates/ra_syntax/test_data/parser/inline/ok/0054_field_attrs.rs)0
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0054_record_field_attrs.txt (renamed from crates/ra_syntax/test_data/parser/inline/ok/0054_field_attrs.txt)4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0061_record_lit.rs (renamed from crates/ra_syntax/test_data/parser/inline/ok/0061_struct_lit.rs)0
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0061_record_lit.txt (renamed from crates/ra_syntax/test_data/parser/inline/ok/0061_struct_lit.txt)26
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.rs2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.txt65
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0068_union_items.txt8
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0083_struct_items.txt16
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0102_record_field_pat_list.rs (renamed from crates/ra_syntax/test_data/parser/inline/ok/0102_field_pat_list.rs)0
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0102_record_field_pat_list.txt (renamed from crates/ra_syntax/test_data/parser/inline/ok/0102_field_pat_list.txt)20
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.rs1
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.txt41
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0114_tuple_struct_where.txt8
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0115_tuple_field_attrs.rs (renamed from crates/ra_syntax/test_data/parser/inline/ok/0115_pos_field_attrs.rs)0
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0115_tuple_field_attrs.txt (renamed from crates/ra_syntax/test_data/parser/inline/ok/0115_pos_field_attrs.txt)4
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.rs (renamed from crates/ra_syntax/test_data/parser/inline/ok/0125_struct_literal_field_with_attr.rs)0
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.txt (renamed from crates/ra_syntax/test_data/parser/inline/ok/0125_struct_literal_field_with_attr.txt)6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0134_nocontentexpr_after_item.txt2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0138_expression_after_block.txt6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.rs5
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.txt109
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0001_struct_item.txt4
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0002_struct_item_field.txt4
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0008_mod_item.txt2
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0016_struct_flavors.txt16
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0018_struct_type_params.txt8
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0019_enums.txt14
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.txt4
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0040_raw_struct_item_field.txt4
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0043_complex_assignment.txt16
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0047_minus_in_inner_pattern.txt6
-rw-r--r--crates/ra_vfs_glob/Cargo.toml2
97 files changed, 1427 insertions, 852 deletions
diff --git a/.travis.yml b/.travis.yml
index 87b546442..52af05375 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -60,7 +60,6 @@ deploy:
60 github-token: $DOCS_TOKEN # Set in the settings page of your repository, as a secure variable 60 github-token: $DOCS_TOKEN # Set in the settings page of your repository, as a secure variable
61 keep-history: true 61 keep-history: true
62 local-dir: target/doc 62 local-dir: target/doc
63 branch: gh-pages
64 on: 63 on:
65 branch: master 64 branch: master
66 condition: $DEPLOY_DOCS = 1 65 condition: $DEPLOY_DOCS = 1
diff --git a/Cargo.lock b/Cargo.lock
index 84f9f8ccd..e2938b5f8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1080,12 +1080,13 @@ dependencies = [
1080name = "ra_batch" 1080name = "ra_batch"
1081version = "0.1.0" 1081version = "0.1.0"
1082dependencies = [ 1082dependencies = [
1083 "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
1083 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 1084 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
1084 "ra_db 0.1.0", 1085 "ra_db 0.1.0",
1085 "ra_hir 0.1.0", 1086 "ra_hir 0.1.0",
1086 "ra_ide_api 0.1.0", 1087 "ra_ide_api 0.1.0",
1087 "ra_project_model 0.1.0", 1088 "ra_project_model 0.1.0",
1088 "ra_vfs 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 1089 "ra_vfs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
1089 "ra_vfs_glob 0.1.0", 1090 "ra_vfs_glob 0.1.0",
1090 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1091 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
1091] 1092]
@@ -1191,7 +1192,7 @@ dependencies = [
1191 "ra_project_model 0.1.0", 1192 "ra_project_model 0.1.0",
1192 "ra_syntax 0.1.0", 1193 "ra_syntax 0.1.0",
1193 "ra_text_edit 0.1.0", 1194 "ra_text_edit 0.1.0",
1194 "ra_vfs 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 1195 "ra_vfs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
1195 "ra_vfs_glob 0.1.0", 1196 "ra_vfs_glob 0.1.0",
1196 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 1197 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
1197 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1198 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1300,7 +1301,7 @@ dependencies = [
1300 1301
1301[[package]] 1302[[package]]
1302name = "ra_vfs" 1303name = "ra_vfs"
1303version = "0.2.8" 1304version = "0.3.0"
1304source = "registry+https://github.com/rust-lang/crates.io-index" 1305source = "registry+https://github.com/rust-lang/crates.io-index"
1305dependencies = [ 1306dependencies = [
1306 "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 1307 "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1318,7 +1319,7 @@ name = "ra_vfs_glob"
1318version = "0.1.0" 1319version = "0.1.0"
1319dependencies = [ 1320dependencies = [
1320 "globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", 1321 "globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
1321 "ra_vfs 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 1322 "ra_vfs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
1322] 1323]
1323 1324
1324[[package]] 1325[[package]]
@@ -2120,7 +2121,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
2120"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" 2121"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
2121"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" 2122"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
2122"checksum ra_rustc_lexer 0.1.0-pre.3 (registry+https://github.com/rust-lang/crates.io-index)" = "04371af481820ff8d35c7d12b503eb09cf9e1bd246269bf4a33e3d8c54fa3a4a" 2123"checksum ra_rustc_lexer 0.1.0-pre.3 (registry+https://github.com/rust-lang/crates.io-index)" = "04371af481820ff8d35c7d12b503eb09cf9e1bd246269bf4a33e3d8c54fa3a4a"
2123"checksum ra_vfs 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "9e891866e1bb03f50a28cc01e3f244a62107c301ae674ba06b2e7a9b310ae75a" 2124"checksum ra_vfs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc8b709e0b7ceec822513451b610df1b9370b01953a8bc545a041a6b3bfef01"
2124"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" 2125"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
2125"checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c" 2126"checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c"
2126"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" 2127"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
diff --git a/crates/ra_assists/src/add_missing_impl_members.rs b/crates/ra_assists/src/add_missing_impl_members.rs
index 31c7d4e80..cbeb7054f 100644
--- a/crates/ra_assists/src/add_missing_impl_members.rs
+++ b/crates/ra_assists/src/add_missing_impl_members.rs
@@ -1,13 +1,14 @@
1use hir::{db::HirDatabase, HasSource};
2use ra_syntax::{
3 ast::{self, AstNode, NameOwner},
4 SmolStr,
5};
6
1use crate::{ 7use crate::{
2 ast_editor::{AstBuilder, AstEditor}, 8 ast_editor::{AstBuilder, AstEditor},
3 Assist, AssistCtx, AssistId, 9 Assist, AssistCtx, AssistId,
4}; 10};
5 11
6use hir::{db::HirDatabase, HasSource};
7use ra_db::FilePosition;
8use ra_syntax::ast::{self, AstNode, NameOwner};
9use ra_syntax::SmolStr;
10
11#[derive(PartialEq)] 12#[derive(PartialEq)]
12enum AddMissingImplMembersMode { 13enum AddMissingImplMembersMode {
13 DefaultMethodsOnly, 14 DefaultMethodsOnly,
@@ -43,8 +44,7 @@ fn add_missing_impl_members_inner(
43 44
44 let trait_def = { 45 let trait_def = {
45 let file_id = ctx.frange.file_id; 46 let file_id = ctx.frange.file_id;
46 let position = FilePosition { file_id, offset: impl_node.syntax().text_range().start() }; 47 let analyzer = hir::SourceAnalyzer::new(ctx.db, file_id, impl_node.syntax(), None);
47 let analyzer = hir::SourceAnalyzer::new(ctx.db, position.file_id, impl_node.syntax(), None);
48 48
49 resolve_target_trait_def(ctx.db, &analyzer, &impl_node)? 49 resolve_target_trait_def(ctx.db, &analyzer, &impl_node)?
50 }; 50 };
diff --git a/crates/ra_assists/src/ast_editor.rs b/crates/ra_assists/src/ast_editor.rs
index 95b871b30..6815638dc 100644
--- a/crates/ra_assists/src/ast_editor.rs
+++ b/crates/ra_assists/src/ast_editor.rs
@@ -1,6 +1,8 @@
1use std::{iter, ops::RangeInclusive}; 1use std::{iter, ops::RangeInclusive};
2 2
3use arrayvec::ArrayVec; 3use arrayvec::ArrayVec;
4use itertools::Itertools;
5
4use hir::Name; 6use hir::Name;
5use ra_fmt::leading_indent; 7use ra_fmt::leading_indent;
6use ra_syntax::{ 8use ra_syntax::{
@@ -17,7 +19,10 @@ pub struct AstEditor<N: AstNode> {
17} 19}
18 20
19impl<N: AstNode> AstEditor<N> { 21impl<N: AstNode> AstEditor<N> {
20 pub fn new(node: N) -> AstEditor<N> { 22 pub fn new(node: N) -> AstEditor<N>
23 where
24 N: Clone,
25 {
21 AstEditor { original_ast: node.clone(), ast: node } 26 AstEditor { original_ast: node.clone(), ast: node }
22 } 27 }
23 28
@@ -88,15 +93,15 @@ impl<N: AstNode> AstEditor<N> {
88 } 93 }
89} 94}
90 95
91impl AstEditor<ast::NamedFieldList> { 96impl AstEditor<ast::RecordFieldList> {
92 pub fn append_field(&mut self, field: &ast::NamedField) { 97 pub fn append_field(&mut self, field: &ast::RecordField) {
93 self.insert_field(InsertPosition::Last, field) 98 self.insert_field(InsertPosition::Last, field)
94 } 99 }
95 100
96 pub fn insert_field( 101 pub fn insert_field(
97 &mut self, 102 &mut self,
98 position: InsertPosition<&'_ ast::NamedField>, 103 position: InsertPosition<&'_ ast::RecordField>,
99 field: &ast::NamedField, 104 field: &ast::RecordField,
100 ) { 105 ) {
101 let is_multiline = self.ast().syntax().text().contains_char('\n'); 106 let is_multiline = self.ast().syntax().text().contains_char('\n');
102 let ws; 107 let ws;
@@ -168,8 +173,7 @@ impl AstEditor<ast::NamedFieldList> {
168 173
169impl AstEditor<ast::ItemList> { 174impl AstEditor<ast::ItemList> {
170 pub fn append_items(&mut self, items: impl Iterator<Item = ast::ImplItem>) { 175 pub fn append_items(&mut self, items: impl Iterator<Item = ast::ImplItem>) {
171 let n_existing_items = self.ast().impl_items().count(); 176 if !self.ast().syntax().text().contains_char('\n') {
172 if n_existing_items == 0 {
173 self.do_make_multiline(); 177 self.do_make_multiline();
174 } 178 }
175 items.for_each(|it| self.append_item(it)); 179 items.for_each(|it| self.append_item(it));
@@ -241,16 +245,16 @@ pub struct AstBuilder<N: AstNode> {
241 _phantom: std::marker::PhantomData<N>, 245 _phantom: std::marker::PhantomData<N>,
242} 246}
243 247
244impl AstBuilder<ast::NamedField> { 248impl AstBuilder<ast::RecordField> {
245 pub fn from_name(name: &Name) -> ast::NamedField { 249 pub fn from_name(name: &Name) -> ast::RecordField {
246 ast_node_from_file_text(&format!("fn f() {{ S {{ {}: (), }} }}", name)) 250 ast_node_from_file_text(&format!("fn f() {{ S {{ {}: (), }} }}", name))
247 } 251 }
248 252
249 fn from_text(text: &str) -> ast::NamedField { 253 fn from_text(text: &str) -> ast::RecordField {
250 ast_node_from_file_text(&format!("fn f() {{ S {{ {}, }} }}", text)) 254 ast_node_from_file_text(&format!("fn f() {{ S {{ {}, }} }}", text))
251 } 255 }
252 256
253 pub fn from_pieces(name: &ast::NameRef, expr: Option<&ast::Expr>) -> ast::NamedField { 257 pub fn from_pieces(name: &ast::NameRef, expr: Option<&ast::Expr>) -> ast::RecordField {
254 match expr { 258 match expr {
255 Some(expr) => Self::from_text(&format!("{}: {}", name.syntax(), expr.syntax())), 259 Some(expr) => Self::from_text(&format!("{}: {}", name.syntax(), expr.syntax())),
256 None => Self::from_text(&name.syntax().to_string()), 260 None => Self::from_text(&name.syntax().to_string()),
@@ -288,9 +292,97 @@ impl AstBuilder<ast::NameRef> {
288 } 292 }
289} 293}
290 294
295impl AstBuilder<ast::Path> {
296 fn from_text(text: &str) -> ast::Path {
297 ast_node_from_file_text(text)
298 }
299
300 pub fn from_pieces(enum_name: ast::Name, var_name: ast::Name) -> ast::Path {
301 Self::from_text(&format!("{}::{}", enum_name.syntax(), var_name.syntax()))
302 }
303}
304
305impl AstBuilder<ast::BindPat> {
306 fn from_text(text: &str) -> ast::BindPat {
307 ast_node_from_file_text(&format!("fn f({}: ())", text))
308 }
309
310 pub fn from_name(name: &ast::Name) -> ast::BindPat {
311 Self::from_text(name.text())
312 }
313}
314
315impl AstBuilder<ast::PlaceholderPat> {
316 fn from_text(text: &str) -> ast::PlaceholderPat {
317 ast_node_from_file_text(&format!("fn f({}: ())", text))
318 }
319
320 pub fn placeholder() -> ast::PlaceholderPat {
321 Self::from_text("_")
322 }
323}
324
325impl AstBuilder<ast::TupleStructPat> {
326 fn from_text(text: &str) -> ast::TupleStructPat {
327 ast_node_from_file_text(&format!("fn f({}: ())", text))
328 }
329
330 pub fn from_pieces(
331 path: &ast::Path,
332 pats: impl Iterator<Item = ast::Pat>,
333 ) -> ast::TupleStructPat {
334 let pats_str = pats.map(|p| p.syntax().to_string()).collect::<Vec<_>>().join(", ");
335 Self::from_text(&format!("{}({})", path.syntax(), pats_str))
336 }
337}
338
339impl AstBuilder<ast::RecordPat> {
340 fn from_text(text: &str) -> ast::RecordPat {
341 ast_node_from_file_text(&format!("fn f({}: ())", text))
342 }
343
344 pub fn from_pieces(path: &ast::Path, pats: impl Iterator<Item = ast::Pat>) -> ast::RecordPat {
345 let pats_str = pats.map(|p| p.syntax().to_string()).collect::<Vec<_>>().join(", ");
346 Self::from_text(&format!("{}{{ {} }}", path.syntax(), pats_str))
347 }
348}
349
350impl AstBuilder<ast::PathPat> {
351 fn from_text(text: &str) -> ast::PathPat {
352 ast_node_from_file_text(&format!("fn f({}: ())", text))
353 }
354
355 pub fn from_path(path: &ast::Path) -> ast::PathPat {
356 let path_str = path.syntax().text().to_string();
357 Self::from_text(path_str.as_str())
358 }
359}
360
361impl AstBuilder<ast::MatchArm> {
362 fn from_text(text: &str) -> ast::MatchArm {
363 ast_node_from_file_text(&format!("fn f() {{ match () {{{}}} }}", text))
364 }
365
366 pub fn from_pieces(pats: impl Iterator<Item = ast::Pat>, expr: &ast::Expr) -> ast::MatchArm {
367 let pats_str = pats.map(|p| p.syntax().to_string()).join(" | ");
368 Self::from_text(&format!("{} => {}", pats_str, expr.syntax()))
369 }
370}
371
372impl AstBuilder<ast::MatchArmList> {
373 fn from_text(text: &str) -> ast::MatchArmList {
374 ast_node_from_file_text(&format!("fn f() {{ match () {{{}}} }}", text))
375 }
376
377 pub fn from_arms(arms: impl Iterator<Item = ast::MatchArm>) -> ast::MatchArmList {
378 let arms_str = arms.map(|arm| format!("\n {}", arm.syntax())).join(",");
379 Self::from_text(&format!("{},\n", arms_str))
380 }
381}
382
291fn ast_node_from_file_text<N: AstNode>(text: &str) -> N { 383fn ast_node_from_file_text<N: AstNode>(text: &str) -> N {
292 let parse = SourceFile::parse(text); 384 let parse = SourceFile::parse(text);
293 let res = parse.tree().syntax().descendants().find_map(N::cast).unwrap().to_owned(); 385 let res = parse.tree().syntax().descendants().find_map(N::cast).unwrap();
294 res 386 res
295} 387}
296 388
diff --git a/crates/ra_assists/src/change_visibility.rs b/crates/ra_assists/src/change_visibility.rs
index d28cdd07b..60c74debc 100644
--- a/crates/ra_assists/src/change_visibility.rs
+++ b/crates/ra_assists/src/change_visibility.rs
@@ -38,7 +38,7 @@ fn add_vis(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
38 (vis_offset(&parent), keyword.text_range()) 38 (vis_offset(&parent), keyword.text_range())
39 } else { 39 } else {
40 let ident = ctx.token_at_offset().find(|leaf| leaf.kind() == IDENT)?; 40 let ident = ctx.token_at_offset().find(|leaf| leaf.kind() == IDENT)?;
41 let field = ident.parent().ancestors().find_map(ast::NamedFieldDef::cast)?; 41 let field = ident.parent().ancestors().find_map(ast::RecordFieldDef::cast)?;
42 if field.name()?.syntax().text_range() != ident.text_range() && field.visibility().is_some() 42 if field.name()?.syntax().text_range() != ident.text_range() && field.visibility().is_some()
43 { 43 {
44 return None; 44 return None;
diff --git a/crates/ra_assists/src/fill_match_arms.rs b/crates/ra_assists/src/fill_match_arms.rs
index 85ff5c052..cc3879562 100644
--- a/crates/ra_assists/src/fill_match_arms.rs
+++ b/crates/ra_assists/src/fill_match_arms.rs
@@ -1,97 +1,91 @@
1use itertools::Itertools; 1use std::iter;
2use std::fmt::Write;
3 2
4use hir::{db::HirDatabase, AdtDef, FieldSource, HasSource}; 3use hir::{db::HirDatabase, AdtDef, HasSource};
5use ra_syntax::ast::{self, AstNode}; 4use ra_syntax::ast::{self, AstNode, NameOwner};
6 5
7use crate::{Assist, AssistCtx, AssistId}; 6use crate::{ast_editor::AstBuilder, Assist, AssistCtx, AssistId};
8
9fn is_trivial_arm(arm: &ast::MatchArm) -> bool {
10 fn single_pattern(arm: &ast::MatchArm) -> Option<ast::Pat> {
11 let (pat,) = arm.pats().collect_tuple()?;
12 Some(pat)
13 }
14 match single_pattern(arm) {
15 Some(ast::Pat::PlaceholderPat(..)) => true,
16 _ => false,
17 }
18}
19 7
20pub(crate) fn fill_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 8pub(crate) fn fill_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
21 let match_expr = ctx.node_at_offset::<ast::MatchExpr>()?; 9 let match_expr = ctx.node_at_offset::<ast::MatchExpr>()?;
10 let match_arm_list = match_expr.match_arm_list()?;
22 11
23 // We already have some match arms, so we don't provide any assists. 12 // We already have some match arms, so we don't provide any assists.
24 // Unless if there is only one trivial match arm possibly created 13 // Unless if there is only one trivial match arm possibly created
25 // by match postfix complete. Trivial match arm is the catch all arm. 14 // by match postfix complete. Trivial match arm is the catch all arm.
26 if let Some(arm_list) = match_expr.match_arm_list() { 15 let mut existing_arms = match_arm_list.arms();
27 let mut arm_iter = arm_list.arms(); 16 if let Some(arm) = existing_arms.next() {
28 let first = arm_iter.next(); 17 if !is_trivial(&arm) || existing_arms.next().is_some() {
29 18 return None;
30 match &first {
31 // If there arm list is empty or there is only one trivial arm, then proceed.
32 Some(arm) if is_trivial_arm(arm) => {
33 if arm_iter.next() != None {
34 return None;
35 }
36 }
37 None => {}
38
39 _ => {
40 return None;
41 }
42 } 19 }
43 }; 20 };
44 21
45 let expr = match_expr.expr()?; 22 let expr = match_expr.expr()?;
46 let analyzer = hir::SourceAnalyzer::new(ctx.db, ctx.frange.file_id, expr.syntax(), None); 23 let enum_def = {
47 let match_expr_ty = analyzer.type_of(ctx.db, &expr)?; 24 let file_id = ctx.frange.file_id;
48 let enum_def = analyzer.autoderef(ctx.db, match_expr_ty).find_map(|ty| match ty.as_adt() { 25 let analyzer = hir::SourceAnalyzer::new(ctx.db, file_id, expr.syntax(), None);
49 Some((AdtDef::Enum(e), _)) => Some(e), 26 resolve_enum_def(ctx.db, &analyzer, &expr)?
50 _ => None, 27 };
51 })?; 28 let variant_list = enum_def.variant_list()?;
52 let enum_name = enum_def.name(ctx.db)?;
53 let db = ctx.db;
54 29
55 ctx.add_action(AssistId("fill_match_arms"), "fill match arms", |edit| { 30 ctx.add_action(AssistId("fill_match_arms"), "fill match arms", |edit| {
56 let mut buf = format!("match {} {{\n", expr.syntax().text().to_string()); 31 let variants = variant_list.variants();
57 let variants = enum_def.variants(db); 32 let arms = variants.into_iter().filter_map(build_pat).map(|pat| {
58 for variant in variants { 33 AstBuilder::<ast::MatchArm>::from_pieces(
59 let name = match variant.name(db) { 34 iter::once(pat),
60 Some(it) => it, 35 &AstBuilder::<ast::Expr>::unit(),
61 None => continue, 36 )
62 }; 37 });
63 write!(&mut buf, " {}::{}", enum_name, name.to_string()).unwrap(); 38 let new_arm_list = AstBuilder::<ast::MatchArmList>::from_arms(arms);
64
65 let pat = variant
66 .fields(db)
67 .into_iter()
68 .map(|field| {
69 let name = field.name(db).to_string();
70 let src = field.source(db);
71 match src.ast {
72 FieldSource::Named(_) => name,
73 FieldSource::Pos(_) => "_".to_string(),
74 }
75 })
76 .collect::<Vec<_>>();
77 39
78 match pat.first().map(|s| s.as_str()) {
79 Some("_") => write!(&mut buf, "({})", pat.join(", ")).unwrap(),
80 Some(_) => write!(&mut buf, "{{{}}}", pat.join(", ")).unwrap(),
81 None => (),
82 };
83
84 buf.push_str(" => (),\n");
85 }
86 buf.push_str("}");
87 edit.target(match_expr.syntax().text_range()); 40 edit.target(match_expr.syntax().text_range());
88 edit.set_cursor(expr.syntax().text_range().start()); 41 edit.set_cursor(expr.syntax().text_range().start());
89 edit.replace_node_and_indent(match_expr.syntax(), buf); 42 edit.replace_node_and_indent(match_arm_list.syntax(), new_arm_list.syntax().text());
90 }); 43 });
91 44
92 ctx.build() 45 ctx.build()
93} 46}
94 47
48fn is_trivial(arm: &ast::MatchArm) -> bool {
49 arm.pats().any(|pat| match pat {
50 ast::Pat::PlaceholderPat(..) => true,
51 _ => false,
52 })
53}
54
55fn resolve_enum_def(
56 db: &impl HirDatabase,
57 analyzer: &hir::SourceAnalyzer,
58 expr: &ast::Expr,
59) -> Option<ast::EnumDef> {
60 let expr_ty = analyzer.type_of(db, &expr)?;
61
62 analyzer.autoderef(db, expr_ty).find_map(|ty| match ty.as_adt() {
63 Some((AdtDef::Enum(e), _)) => Some(e.source(db).ast),
64 _ => None,
65 })
66}
67
68fn build_pat(var: ast::EnumVariant) -> Option<ast::Pat> {
69 let path = &AstBuilder::<ast::Path>::from_pieces(var.parent_enum().name()?, var.name()?);
70
71 let pat: ast::Pat = match var.kind() {
72 ast::StructKind::Tuple(field_list) => {
73 let pats = iter::repeat(AstBuilder::<ast::PlaceholderPat>::placeholder().into())
74 .take(field_list.fields().count());
75 AstBuilder::<ast::TupleStructPat>::from_pieces(path, pats).into()
76 }
77 ast::StructKind::Named(field_list) => {
78 let pats = field_list
79 .fields()
80 .map(|f| AstBuilder::<ast::BindPat>::from_name(&f.name().unwrap()).into());
81 AstBuilder::<ast::RecordPat>::from_pieces(path, pats).into()
82 }
83 ast::StructKind::Unit => AstBuilder::<ast::PathPat>::from_path(path).into(),
84 };
85
86 Some(pat)
87}
88
95#[cfg(test)] 89#[cfg(test)]
96mod tests { 90mod tests {
97 use crate::helpers::{check_assist, check_assist_target}; 91 use crate::helpers::{check_assist, check_assist_target};
@@ -108,7 +102,7 @@ mod tests {
108 Bs, 102 Bs,
109 Cs(String), 103 Cs(String),
110 Ds(String, String), 104 Ds(String, String),
111 Es{x: usize, y: usize} 105 Es{ x: usize, y: usize }
112 } 106 }
113 107
114 fn main() { 108 fn main() {
@@ -122,7 +116,7 @@ mod tests {
122 Bs, 116 Bs,
123 Cs(String), 117 Cs(String),
124 Ds(String, String), 118 Ds(String, String),
125 Es{x: usize, y: usize} 119 Es{ x: usize, y: usize }
126 } 120 }
127 121
128 fn main() { 122 fn main() {
@@ -132,7 +126,7 @@ mod tests {
132 A::Bs => (), 126 A::Bs => (),
133 A::Cs(_) => (), 127 A::Cs(_) => (),
134 A::Ds(_, _) => (), 128 A::Ds(_, _) => (),
135 A::Es{x, y} => (), 129 A::Es{ x, y } => (),
136 } 130 }
137 } 131 }
138 "#, 132 "#,
@@ -170,7 +164,7 @@ mod tests {
170 fill_match_arms, 164 fill_match_arms,
171 r#" 165 r#"
172 enum A { 166 enum A {
173 Es{x: usize, y: usize} 167 Es{ x: usize, y: usize }
174 } 168 }
175 169
176 fn foo(a: &mut A) { 170 fn foo(a: &mut A) {
@@ -180,57 +174,12 @@ mod tests {
180 "#, 174 "#,
181 r#" 175 r#"
182 enum A { 176 enum A {
183 Es{x: usize, y: usize} 177 Es{ x: usize, y: usize }
184 } 178 }
185 179
186 fn foo(a: &mut A) { 180 fn foo(a: &mut A) {
187 match <|>a { 181 match <|>a {
188 A::Es{x, y} => (), 182 A::Es{ x, y } => (),
189 }
190 }
191 "#,
192 );
193
194 check_assist(
195 fill_match_arms,
196 r#"
197 enum E { X, Y}
198
199 fn main() {
200 match &E::X<|>
201 }
202 "#,
203 r#"
204 enum E { X, Y}
205
206 fn main() {
207 match <|>&E::X {
208 E::X => (),
209 E::Y => (),
210 }
211 }
212 "#,
213 );
214 }
215
216 #[test]
217 fn fill_match_arms_no_body() {
218 check_assist(
219 fill_match_arms,
220 r#"
221 enum E { X, Y}
222
223 fn main() {
224 match E::X<|>
225 }
226 "#,
227 r#"
228 enum E { X, Y}
229
230 fn main() {
231 match <|>E::X {
232 E::X => (),
233 E::Y => (),
234 } 183 }
235 } 184 }
236 "#, 185 "#,
@@ -242,7 +191,7 @@ mod tests {
242 check_assist_target( 191 check_assist_target(
243 fill_match_arms, 192 fill_match_arms,
244 r#" 193 r#"
245 enum E { X, Y} 194 enum E { X, Y }
246 195
247 fn main() { 196 fn main() {
248 match E::X<|> {} 197 match E::X<|> {}
diff --git a/crates/ra_batch/Cargo.toml b/crates/ra_batch/Cargo.toml
index 8e23826a4..5fc2703ee 100644
--- a/crates/ra_batch/Cargo.toml
+++ b/crates/ra_batch/Cargo.toml
@@ -7,8 +7,9 @@ authors = ["rust-analyzer developers"]
7[dependencies] 7[dependencies]
8log = "0.4.5" 8log = "0.4.5"
9rustc-hash = "1.0" 9rustc-hash = "1.0"
10crossbeam-channel = "0.3.5"
10 11
11ra_vfs = "0.2.0" 12ra_vfs = "0.3.0"
12ra_vfs_glob = { path = "../ra_vfs_glob" } 13ra_vfs_glob = { path = "../ra_vfs_glob" }
13ra_db = { path = "../ra_db" } 14ra_db = { path = "../ra_db" }
14ra_ide_api = { path = "../ra_ide_api" } 15ra_ide_api = { path = "../ra_ide_api" }
diff --git a/crates/ra_batch/src/lib.rs b/crates/ra_batch/src/lib.rs
index f458ea300..4e5bad044 100644
--- a/crates/ra_batch/src/lib.rs
+++ b/crates/ra_batch/src/lib.rs
@@ -2,10 +2,11 @@ use std::{collections::HashSet, error::Error, path::Path};
2 2
3use rustc_hash::FxHashMap; 3use rustc_hash::FxHashMap;
4 4
5use crossbeam_channel::{unbounded, Receiver};
5use ra_db::{CrateGraph, FileId, SourceRootId}; 6use ra_db::{CrateGraph, FileId, SourceRootId};
6use ra_ide_api::{AnalysisChange, AnalysisHost, FeatureFlags}; 7use ra_ide_api::{AnalysisChange, AnalysisHost, FeatureFlags};
7use ra_project_model::{PackageRoot, ProjectWorkspace}; 8use ra_project_model::{PackageRoot, ProjectWorkspace};
8use ra_vfs::{RootEntry, Vfs, VfsChange}; 9use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask};
9use ra_vfs_glob::RustPackageFilterBuilder; 10use ra_vfs_glob::RustPackageFilterBuilder;
10 11
11type Result<T> = std::result::Result<T, Box<dyn Error + Send + Sync>>; 12type Result<T> = std::result::Result<T, Box<dyn Error + Send + Sync>>;
@@ -21,6 +22,8 @@ pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, FxHashMap<SourceRootId,
21 let root = std::env::current_dir()?.join(root); 22 let root = std::env::current_dir()?.join(root);
22 let ws = ProjectWorkspace::discover(root.as_ref())?; 23 let ws = ProjectWorkspace::discover(root.as_ref())?;
23 let project_roots = ws.to_roots(); 24 let project_roots = ws.to_roots();
25 let (sender, receiver) = unbounded();
26 let sender = Box::new(move |t| sender.send(t).unwrap());
24 let (mut vfs, roots) = Vfs::new( 27 let (mut vfs, roots) = Vfs::new(
25 project_roots 28 project_roots
26 .iter() 29 .iter()
@@ -33,6 +36,7 @@ pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, FxHashMap<SourceRootId,
33 ) 36 )
34 }) 37 })
35 .collect(), 38 .collect(),
39 sender,
36 ); 40 );
37 let crate_graph = ws.to_crate_graph(&mut |path: &Path| { 41 let crate_graph = ws.to_crate_graph(&mut |path: &Path| {
38 let vfs_file = vfs.load(path); 42 let vfs_file = vfs.load(path);
@@ -53,7 +57,7 @@ pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, FxHashMap<SourceRootId,
53 (source_root_id, project_root) 57 (source_root_id, project_root)
54 }) 58 })
55 .collect::<FxHashMap<_, _>>(); 59 .collect::<FxHashMap<_, _>>();
56 let host = load(&source_roots, crate_graph, &mut vfs); 60 let host = load(&source_roots, crate_graph, &mut vfs, receiver);
57 Ok((host, source_roots)) 61 Ok((host, source_roots))
58} 62}
59 63
@@ -61,6 +65,7 @@ pub fn load(
61 source_roots: &FxHashMap<SourceRootId, PackageRoot>, 65 source_roots: &FxHashMap<SourceRootId, PackageRoot>,
62 crate_graph: CrateGraph, 66 crate_graph: CrateGraph,
63 vfs: &mut Vfs, 67 vfs: &mut Vfs,
68 receiver: Receiver<VfsTask>,
64) -> AnalysisHost { 69) -> AnalysisHost {
65 let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok()); 70 let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok());
66 let mut host = AnalysisHost::new(lru_cap, FeatureFlags::default()); 71 let mut host = AnalysisHost::new(lru_cap, FeatureFlags::default());
@@ -68,7 +73,6 @@ pub fn load(
68 analysis_change.set_crate_graph(crate_graph); 73 analysis_change.set_crate_graph(crate_graph);
69 74
70 // wait until Vfs has loaded all roots 75 // wait until Vfs has loaded all roots
71 let receiver = vfs.task_receiver().clone();
72 let mut roots_loaded = HashSet::new(); 76 let mut roots_loaded = HashSet::new();
73 for task in receiver { 77 for task in receiver {
74 vfs.handle_task(task); 78 vfs.handle_task(task);
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 89fc1d1a1..66a58efed 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -318,8 +318,8 @@ pub struct StructField {
318 318
319#[derive(Debug)] 319#[derive(Debug)]
320pub enum FieldSource { 320pub enum FieldSource {
321 Named(ast::NamedFieldDef), 321 Named(ast::RecordFieldDef),
322 Pos(ast::PosFieldDef), 322 Pos(ast::TupleFieldDef),
323} 323}
324 324
325impl StructField { 325impl StructField {
diff --git a/crates/ra_hir/src/diagnostics.rs b/crates/ra_hir/src/diagnostics.rs
index f6240830f..475dd5766 100644
--- a/crates/ra_hir/src/diagnostics.rs
+++ b/crates/ra_hir/src/diagnostics.rs
@@ -79,7 +79,7 @@ impl<'a> DiagnosticSink<'a> {
79#[derive(Debug)] 79#[derive(Debug)]
80pub struct NoSuchField { 80pub struct NoSuchField {
81 pub file: HirFileId, 81 pub file: HirFileId,
82 pub field: AstPtr<ast::NamedField>, 82 pub field: AstPtr<ast::RecordField>,
83} 83}
84 84
85impl Diagnostic for NoSuchField { 85impl Diagnostic for NoSuchField {
@@ -118,7 +118,7 @@ impl Diagnostic for UnresolvedModule {
118#[derive(Debug)] 118#[derive(Debug)]
119pub struct MissingFields { 119pub struct MissingFields {
120 pub file: HirFileId, 120 pub file: HirFileId,
121 pub field_list: AstPtr<ast::NamedFieldList>, 121 pub field_list: AstPtr<ast::RecordFieldList>,
122 pub missed_fields: Vec<Name>, 122 pub missed_fields: Vec<Name>,
123} 123}
124 124
@@ -135,11 +135,39 @@ impl Diagnostic for MissingFields {
135} 135}
136 136
137impl AstDiagnostic for MissingFields { 137impl AstDiagnostic for MissingFields {
138 type AST = ast::NamedFieldList; 138 type AST = ast::RecordFieldList;
139 139
140 fn ast(&self, db: &impl HirDatabase) -> Self::AST { 140 fn ast(&self, db: &impl HirDatabase) -> Self::AST {
141 let root = db.parse_or_expand(self.source().file_id).unwrap(); 141 let root = db.parse_or_expand(self.source().file_id).unwrap();
142 let node = self.source().ast.to_node(&root); 142 let node = self.source().ast.to_node(&root);
143 ast::NamedFieldList::cast(node).unwrap() 143 ast::RecordFieldList::cast(node).unwrap()
144 }
145}
146
147#[derive(Debug)]
148pub struct MissingOkInTailExpr {
149 pub file: HirFileId,
150 pub expr: AstPtr<ast::Expr>,
151}
152
153impl Diagnostic for MissingOkInTailExpr {
154 fn message(&self) -> String {
155 "wrap return expression in Ok".to_string()
156 }
157 fn source(&self) -> Source<SyntaxNodePtr> {
158 Source { file_id: self.file, ast: self.expr.into() }
159 }
160 fn as_any(&self) -> &(dyn Any + Send + 'static) {
161 self
162 }
163}
164
165impl AstDiagnostic for MissingOkInTailExpr {
166 type AST = ast::Expr;
167
168 fn ast(&self, db: &impl HirDatabase) -> Self::AST {
169 let root = db.parse_or_expand(self.file).unwrap();
170 let node = self.source().ast.to_node(&root);
171 ast::Expr::cast(node).unwrap()
144 } 172 }
145} 173}
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 328d635d4..7cdc7555c 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -60,7 +60,7 @@ pub struct BodySourceMap {
60 expr_map_back: ArenaMap<ExprId, SyntaxNodePtr>, 60 expr_map_back: ArenaMap<ExprId, SyntaxNodePtr>,
61 pat_map: FxHashMap<PatPtr, PatId>, 61 pat_map: FxHashMap<PatPtr, PatId>,
62 pat_map_back: ArenaMap<PatId, PatPtr>, 62 pat_map_back: ArenaMap<PatId, PatPtr>,
63 field_map: FxHashMap<(ExprId, usize), AstPtr<ast::NamedField>>, 63 field_map: FxHashMap<(ExprId, usize), AstPtr<ast::RecordField>>,
64} 64}
65 65
66type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>; 66type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>;
@@ -148,7 +148,7 @@ impl BodySourceMap {
148 self.pat_map.get(&Either::A(AstPtr::new(node))).cloned() 148 self.pat_map.get(&Either::A(AstPtr::new(node))).cloned()
149 } 149 }
150 150
151 pub(crate) fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::NamedField> { 151 pub(crate) fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::RecordField> {
152 self.field_map[&(expr, field)] 152 self.field_map[&(expr, field)]
153 } 153 }
154} 154}
@@ -210,9 +210,9 @@ pub enum Expr {
210 Return { 210 Return {
211 expr: Option<ExprId>, 211 expr: Option<ExprId>,
212 }, 212 },
213 StructLit { 213 RecordLit {
214 path: Option<Path>, 214 path: Option<Path>,
215 fields: Vec<StructLitField>, 215 fields: Vec<RecordLitField>,
216 spread: Option<ExprId>, 216 spread: Option<ExprId>,
217 }, 217 },
218 Field { 218 Field {
@@ -316,7 +316,7 @@ pub struct MatchArm {
316} 316}
317 317
318#[derive(Debug, Clone, Eq, PartialEq)] 318#[derive(Debug, Clone, Eq, PartialEq)]
319pub struct StructLitField { 319pub struct RecordLitField {
320 pub name: Name, 320 pub name: Name,
321 pub expr: ExprId, 321 pub expr: ExprId,
322} 322}
@@ -388,7 +388,7 @@ impl Expr {
388 f(*expr); 388 f(*expr);
389 } 389 }
390 } 390 }
391 Expr::StructLit { fields, spread, .. } => { 391 Expr::RecordLit { fields, spread, .. } => {
392 for field in fields { 392 for field in fields {
393 f(field.expr); 393 f(field.expr);
394 } 394 }
@@ -474,7 +474,7 @@ impl BindingAnnotation {
474} 474}
475 475
476#[derive(Debug, Clone, Eq, PartialEq)] 476#[derive(Debug, Clone, Eq, PartialEq)]
477pub struct FieldPat { 477pub struct RecordFieldPat {
478 pub(crate) name: Name, 478 pub(crate) name: Name,
479 pub(crate) pat: PatId, 479 pub(crate) pat: PatId,
480} 480}
@@ -487,7 +487,7 @@ pub enum Pat {
487 Tuple(Vec<PatId>), 487 Tuple(Vec<PatId>),
488 Struct { 488 Struct {
489 path: Option<Path>, 489 path: Option<Path>,
490 args: Vec<FieldPat>, 490 args: Vec<RecordFieldPat>,
491 // FIXME: 'ellipsis' option 491 // FIXME: 'ellipsis' option
492 }, 492 },
493 Range { 493 Range {
@@ -746,14 +746,14 @@ where
746 let expr = e.expr().map(|e| self.collect_expr(e)); 746 let expr = e.expr().map(|e| self.collect_expr(e));
747 self.alloc_expr(Expr::Return { expr }, syntax_ptr) 747 self.alloc_expr(Expr::Return { expr }, syntax_ptr)
748 } 748 }
749 ast::Expr::StructLit(e) => { 749 ast::Expr::RecordLit(e) => {
750 let path = e.path().and_then(Path::from_ast); 750 let path = e.path().and_then(Path::from_ast);
751 let mut field_ptrs = Vec::new(); 751 let mut field_ptrs = Vec::new();
752 let struct_lit = if let Some(nfl) = e.named_field_list() { 752 let record_lit = if let Some(nfl) = e.record_field_list() {
753 let fields = nfl 753 let fields = nfl
754 .fields() 754 .fields()
755 .inspect(|field| field_ptrs.push(AstPtr::new(field))) 755 .inspect(|field| field_ptrs.push(AstPtr::new(field)))
756 .map(|field| StructLitField { 756 .map(|field| RecordLitField {
757 name: field 757 name: field
758 .name_ref() 758 .name_ref()
759 .map(|nr| nr.as_name()) 759 .map(|nr| nr.as_name())
@@ -776,12 +776,12 @@ where
776 }) 776 })
777 .collect(); 777 .collect();
778 let spread = nfl.spread().map(|s| self.collect_expr(s)); 778 let spread = nfl.spread().map(|s| self.collect_expr(s));
779 Expr::StructLit { path, fields, spread } 779 Expr::RecordLit { path, fields, spread }
780 } else { 780 } else {
781 Expr::StructLit { path, fields: Vec::new(), spread: None } 781 Expr::RecordLit { path, fields: Vec::new(), spread: None }
782 }; 782 };
783 783
784 let res = self.alloc_expr(struct_lit, syntax_ptr); 784 let res = self.alloc_expr(record_lit, syntax_ptr);
785 for (i, ptr) in field_ptrs.into_iter().enumerate() { 785 for (i, ptr) in field_ptrs.into_iter().enumerate() {
786 self.source_map.field_map.insert((res, i), ptr); 786 self.source_map.field_map.insert((res, i), ptr);
787 } 787 }
@@ -994,25 +994,25 @@ where
994 Pat::Tuple(args) 994 Pat::Tuple(args)
995 } 995 }
996 ast::Pat::PlaceholderPat(_) => Pat::Wild, 996 ast::Pat::PlaceholderPat(_) => Pat::Wild,
997 ast::Pat::StructPat(p) => { 997 ast::Pat::RecordPat(p) => {
998 let path = p.path().and_then(Path::from_ast); 998 let path = p.path().and_then(Path::from_ast);
999 let field_pat_list = 999 let record_field_pat_list =
1000 p.field_pat_list().expect("every struct should have a field list"); 1000 p.record_field_pat_list().expect("every struct should have a field list");
1001 let mut fields: Vec<_> = field_pat_list 1001 let mut fields: Vec<_> = record_field_pat_list
1002 .bind_pats() 1002 .bind_pats()
1003 .filter_map(|bind_pat| { 1003 .filter_map(|bind_pat| {
1004 let ast_pat = 1004 let ast_pat =
1005 ast::Pat::cast(bind_pat.syntax().clone()).expect("bind pat is a pat"); 1005 ast::Pat::cast(bind_pat.syntax().clone()).expect("bind pat is a pat");
1006 let pat = self.collect_pat(ast_pat); 1006 let pat = self.collect_pat(ast_pat);
1007 let name = bind_pat.name()?.as_name(); 1007 let name = bind_pat.name()?.as_name();
1008 Some(FieldPat { name, pat }) 1008 Some(RecordFieldPat { name, pat })
1009 }) 1009 })
1010 .collect(); 1010 .collect();
1011 let iter = field_pat_list.field_pats().filter_map(|f| { 1011 let iter = record_field_pat_list.record_field_pats().filter_map(|f| {
1012 let ast_pat = f.pat()?; 1012 let ast_pat = f.pat()?;
1013 let pat = self.collect_pat(ast_pat); 1013 let pat = self.collect_pat(ast_pat);
1014 let name = f.name()?.as_name(); 1014 let name = f.name()?.as_name();
1015 Some(FieldPat { name, pat }) 1015 Some(RecordFieldPat { name, pat })
1016 }); 1016 });
1017 fields.extend(iter); 1017 fields.extend(iter);
1018 1018
@@ -1020,6 +1020,7 @@ where
1020 } 1020 }
1021 1021
1022 // FIXME: implement 1022 // FIXME: implement
1023 ast::Pat::BoxPat(_) => Pat::Missing,
1023 ast::Pat::LiteralPat(_) => Pat::Missing, 1024 ast::Pat::LiteralPat(_) => Pat::Missing,
1024 ast::Pat::SlicePat(_) | ast::Pat::RangePat(_) => Pat::Missing, 1025 ast::Pat::SlicePat(_) | ast::Pat::RangePat(_) => Pat::Missing,
1025 }; 1026 };
diff --git a/crates/ra_hir/src/expr/validation.rs b/crates/ra_hir/src/expr/validation.rs
index 82a06ca25..5d9d59ff8 100644
--- a/crates/ra_hir/src/expr/validation.rs
+++ b/crates/ra_hir/src/expr/validation.rs
@@ -1,16 +1,19 @@
1use rustc_hash::FxHashSet; 1use rustc_hash::FxHashSet;
2use std::sync::Arc; 2use std::sync::Arc;
3 3
4use ra_syntax::ast::{AstNode, StructLit}; 4use ra_syntax::ast::{AstNode, RecordLit};
5 5
6use super::{Expr, ExprId, StructLitField}; 6use super::{Expr, ExprId, RecordLitField};
7use crate::{ 7use crate::{
8 adt::AdtDef, 8 adt::AdtDef,
9 diagnostics::{DiagnosticSink, MissingFields}, 9 diagnostics::{DiagnosticSink, MissingFields, MissingOkInTailExpr},
10 expr::AstPtr, 10 expr::AstPtr,
11 ty::InferenceResult, 11 name,
12 Function, HasSource, HirDatabase, Name, Path, 12 path::{PathKind, PathSegment},
13 ty::{ApplicationTy, InferenceResult, Ty, TypeCtor},
14 Function, HasSource, HirDatabase, ModuleDef, Name, Path, PerNs, Resolution,
13}; 15};
16use ra_syntax::ast;
14 17
15pub(crate) struct ExprValidator<'a, 'b: 'a> { 18pub(crate) struct ExprValidator<'a, 'b: 'a> {
16 func: Function, 19 func: Function,
@@ -29,18 +32,24 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
29 32
30 pub(crate) fn validate_body(&mut self, db: &impl HirDatabase) { 33 pub(crate) fn validate_body(&mut self, db: &impl HirDatabase) {
31 let body = self.func.body(db); 34 let body = self.func.body(db);
35
32 for e in body.exprs() { 36 for e in body.exprs() {
33 if let (id, Expr::StructLit { path, fields, spread }) = e { 37 if let (id, Expr::RecordLit { path, fields, spread }) = e {
34 self.validate_struct_literal(id, path, fields, *spread, db); 38 self.validate_record_literal(id, path, fields, *spread, db);
35 } 39 }
36 } 40 }
41
42 let body_expr = &body[body.body_expr()];
43 if let Expr::Block { statements: _, tail: Some(t) } = body_expr {
44 self.validate_results_in_tail_expr(*t, db);
45 }
37 } 46 }
38 47
39 fn validate_struct_literal( 48 fn validate_record_literal(
40 &mut self, 49 &mut self,
41 id: ExprId, 50 id: ExprId,
42 _path: &Option<Path>, 51 _path: &Option<Path>,
43 fields: &[StructLitField], 52 fields: &[RecordLitField],
44 spread: Option<ExprId>, 53 spread: Option<ExprId>,
45 db: &impl HirDatabase, 54 db: &impl HirDatabase,
46 ) { 55 ) {
@@ -76,8 +85,8 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
76 if let Some(field_list_node) = source_map 85 if let Some(field_list_node) = source_map
77 .expr_syntax(id) 86 .expr_syntax(id)
78 .map(|ptr| ptr.to_node(source_file.syntax())) 87 .map(|ptr| ptr.to_node(source_file.syntax()))
79 .and_then(StructLit::cast) 88 .and_then(RecordLit::cast)
80 .and_then(|lit| lit.named_field_list()) 89 .and_then(|lit| lit.record_field_list())
81 { 90 {
82 let field_list_ptr = AstPtr::new(&field_list_node); 91 let field_list_ptr = AstPtr::new(&field_list_node);
83 self.sink.push(MissingFields { 92 self.sink.push(MissingFields {
@@ -87,4 +96,42 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
87 }) 96 })
88 } 97 }
89 } 98 }
99
100 fn validate_results_in_tail_expr(&mut self, id: ExprId, db: &impl HirDatabase) {
101 let mismatch = match self.infer.type_mismatch_for_expr(id) {
102 Some(m) => m,
103 None => return,
104 };
105
106 let std_result_path = Path {
107 kind: PathKind::Abs,
108 segments: vec![
109 PathSegment { name: name::STD, args_and_bindings: None },
110 PathSegment { name: name::RESULT_MOD, args_and_bindings: None },
111 PathSegment { name: name::RESULT_TYPE, args_and_bindings: None },
112 ],
113 };
114
115 let resolver = self.func.resolver(db);
116 let std_result_enum =
117 match resolver.resolve_path_segments(db, &std_result_path).into_fully_resolved() {
118 PerNs { types: Some(Resolution::Def(ModuleDef::Enum(e))), .. } => e,
119 _ => return,
120 };
121
122 let std_result_ctor = TypeCtor::Adt(AdtDef::Enum(std_result_enum));
123 let params = match &mismatch.expected {
124 Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &std_result_ctor => parameters,
125 _ => return,
126 };
127
128 if params.len() == 2 && &params[0] == &mismatch.actual {
129 let source_map = self.func.body_source_map(db);
130 let file_id = self.func.source(db).file_id;
131
132 if let Some(expr) = source_map.expr_syntax(id).and_then(|n| n.cast::<ast::Expr>()) {
133 self.sink.push(MissingOkInTailExpr { file: file_id, expr });
134 }
135 }
136 }
90} 137}
diff --git a/crates/ra_hir/src/name.rs b/crates/ra_hir/src/name.rs
index 6d14eea8e..9c4822d91 100644
--- a/crates/ra_hir/src/name.rs
+++ b/crates/ra_hir/src/name.rs
@@ -120,6 +120,8 @@ pub(crate) const TRY: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Try")
120pub(crate) const OK: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"Ok")); 120pub(crate) const OK: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"Ok"));
121pub(crate) const FUTURE_MOD: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"future")); 121pub(crate) const FUTURE_MOD: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"future"));
122pub(crate) const FUTURE_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Future")); 122pub(crate) const FUTURE_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Future"));
123pub(crate) const RESULT_MOD: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"result"));
124pub(crate) const RESULT_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Result"));
123pub(crate) const OUTPUT: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Output")); 125pub(crate) const OUTPUT: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Output"));
124 126
125fn resolve_name(text: &SmolStr) -> SmolStr { 127fn resolve_name(text: &SmolStr) -> SmolStr {
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index e86716d74..56ff7da3a 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -278,13 +278,13 @@ impl SourceAnalyzer {
278 self.infer.as_ref()?.field_resolution(expr_id) 278 self.infer.as_ref()?.field_resolution(expr_id)
279 } 279 }
280 280
281 pub fn resolve_struct_literal(&self, struct_lit: &ast::StructLit) -> Option<crate::VariantDef> { 281 pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option<crate::VariantDef> {
282 let expr_id = self.body_source_map.as_ref()?.node_expr(&struct_lit.clone().into())?; 282 let expr_id = self.body_source_map.as_ref()?.node_expr(&record_lit.clone().into())?;
283 self.infer.as_ref()?.variant_resolution_for_expr(expr_id) 283 self.infer.as_ref()?.variant_resolution_for_expr(expr_id)
284 } 284 }
285 285
286 pub fn resolve_struct_pattern(&self, struct_pat: &ast::StructPat) -> Option<crate::VariantDef> { 286 pub fn resolve_record_pattern(&self, record_pat: &ast::RecordPat) -> Option<crate::VariantDef> {
287 let pat_id = self.body_source_map.as_ref()?.node_pat(&struct_pat.clone().into())?; 287 let pat_id = self.body_source_map.as_ref()?.node_pat(&record_pat.clone().into())?;
288 self.infer.as_ref()?.variant_resolution_for_pat(pat_id) 288 self.infer.as_ref()?.variant_resolution_for_pat(pat_id)
289 } 289 }
290 290
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index cca59538a..d94e8154b 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -37,8 +37,8 @@ use crate::{
37 code_model::{ModuleDef::Trait, TypeAlias}, 37 code_model::{ModuleDef::Trait, TypeAlias},
38 diagnostics::DiagnosticSink, 38 diagnostics::DiagnosticSink,
39 expr::{ 39 expr::{
40 self, Array, BinaryOp, BindingAnnotation, Body, Expr, ExprId, FieldPat, Literal, Pat, 40 self, Array, BinaryOp, BindingAnnotation, Body, Expr, ExprId, Literal, Pat, PatId,
41 PatId, Statement, UnaryOp, 41 RecordFieldPat, Statement, UnaryOp,
42 }, 42 },
43 generics::{GenericParams, HasGenericParams}, 43 generics::{GenericParams, HasGenericParams},
44 name, 44 name,
@@ -106,6 +106,13 @@ impl Default for BindingMode {
106 } 106 }
107} 107}
108 108
109/// A mismatch between an expected and an inferred type.
110#[derive(Clone, PartialEq, Eq, Debug, Hash)]
111pub struct TypeMismatch {
112 pub expected: Ty,
113 pub actual: Ty,
114}
115
109/// The result of type inference: A mapping from expressions and patterns to types. 116/// The result of type inference: A mapping from expressions and patterns to types.
110#[derive(Clone, PartialEq, Eq, Debug, Default)] 117#[derive(Clone, PartialEq, Eq, Debug, Default)]
111pub struct InferenceResult { 118pub struct InferenceResult {
@@ -120,6 +127,7 @@ pub struct InferenceResult {
120 diagnostics: Vec<InferenceDiagnostic>, 127 diagnostics: Vec<InferenceDiagnostic>,
121 pub(super) type_of_expr: ArenaMap<ExprId, Ty>, 128 pub(super) type_of_expr: ArenaMap<ExprId, Ty>,
122 pub(super) type_of_pat: ArenaMap<PatId, Ty>, 129 pub(super) type_of_pat: ArenaMap<PatId, Ty>,
130 pub(super) type_mismatches: ArenaMap<ExprId, TypeMismatch>,
123} 131}
124 132
125impl InferenceResult { 133impl InferenceResult {
@@ -141,6 +149,9 @@ impl InferenceResult {
141 pub fn assoc_resolutions_for_pat(&self, id: PatId) -> Option<ImplItem> { 149 pub fn assoc_resolutions_for_pat(&self, id: PatId) -> Option<ImplItem> {
142 self.assoc_resolutions.get(&id.into()).copied() 150 self.assoc_resolutions.get(&id.into()).copied()
143 } 151 }
152 pub fn type_mismatch_for_expr(&self, expr: ExprId) -> Option<&TypeMismatch> {
153 self.type_mismatches.get(expr)
154 }
144 pub(crate) fn add_diagnostics( 155 pub(crate) fn add_diagnostics(
145 &self, 156 &self,
146 db: &impl HirDatabase, 157 db: &impl HirDatabase,
@@ -705,10 +716,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
705 ty 716 ty
706 } 717 }
707 718
708 fn infer_struct_pat( 719 fn infer_record_pat(
709 &mut self, 720 &mut self,
710 path: Option<&Path>, 721 path: Option<&Path>,
711 subpats: &[FieldPat], 722 subpats: &[RecordFieldPat],
712 expected: &Ty, 723 expected: &Ty,
713 default_bm: BindingMode, 724 default_bm: BindingMode,
714 id: PatId, 725 id: PatId,
@@ -800,7 +811,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
800 self.infer_tuple_struct_pat(p.as_ref(), subpats, expected, default_bm) 811 self.infer_tuple_struct_pat(p.as_ref(), subpats, expected, default_bm)
801 } 812 }
802 Pat::Struct { path: ref p, args: ref fields } => { 813 Pat::Struct { path: ref p, args: ref fields } => {
803 self.infer_struct_pat(p.as_ref(), fields, expected, default_bm, pat) 814 self.infer_record_pat(p.as_ref(), fields, expected, default_bm, pat)
804 } 815 }
805 Pat::Path(path) => { 816 Pat::Path(path) => {
806 // FIXME use correct resolver for the surrounding expression 817 // FIXME use correct resolver for the surrounding expression
@@ -1103,7 +1114,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1103 } 1114 }
1104 Ty::simple(TypeCtor::Never) 1115 Ty::simple(TypeCtor::Never)
1105 } 1116 }
1106 Expr::StructLit { path, fields, spread } => { 1117 Expr::RecordLit { path, fields, spread } => {
1107 let (ty, def_id) = self.resolve_variant(path.as_ref()); 1118 let (ty, def_id) = self.resolve_variant(path.as_ref());
1108 if let Some(variant) = def_id { 1119 if let Some(variant) = def_id {
1109 self.write_variant_resolution(tgt_expr.into(), variant); 1120 self.write_variant_resolution(tgt_expr.into(), variant);
@@ -1345,9 +1356,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1345 }; 1356 };
1346 // use a new type variable if we got Ty::Unknown here 1357 // use a new type variable if we got Ty::Unknown here
1347 let ty = self.insert_type_vars_shallow(ty); 1358 let ty = self.insert_type_vars_shallow(ty);
1348 self.unify(&ty, &expected.ty); 1359 let could_unify = self.unify(&ty, &expected.ty);
1349 let ty = self.resolve_ty_as_possible(&mut vec![], ty); 1360 let ty = self.resolve_ty_as_possible(&mut vec![], ty);
1350 self.write_expr_ty(tgt_expr, ty.clone()); 1361 self.write_expr_ty(tgt_expr, ty.clone());
1362 if !could_unify {
1363 self.result.type_mismatches.insert(
1364 tgt_expr,
1365 TypeMismatch { expected: expected.ty.clone(), actual: ty.clone() },
1366 );
1367 }
1351 ty 1368 ty
1352 } 1369 }
1353 1370
diff --git a/crates/ra_ide_api/src/completion.rs b/crates/ra_ide_api/src/completion.rs
index a6b68be75..a4f080adc 100644
--- a/crates/ra_ide_api/src/completion.rs
+++ b/crates/ra_ide_api/src/completion.rs
@@ -3,8 +3,8 @@ mod completion_context;
3mod presentation; 3mod presentation;
4 4
5mod complete_dot; 5mod complete_dot;
6mod complete_struct_literal; 6mod complete_record_literal;
7mod complete_struct_pattern; 7mod complete_record_pattern;
8mod complete_pattern; 8mod complete_pattern;
9mod complete_fn_param; 9mod complete_fn_param;
10mod complete_keyword; 10mod complete_keyword;
@@ -65,8 +65,8 @@ pub(crate) fn completions(db: &db::RootDatabase, position: FilePosition) -> Opti
65 complete_path::complete_path(&mut acc, &ctx); 65 complete_path::complete_path(&mut acc, &ctx);
66 complete_scope::complete_scope(&mut acc, &ctx); 66 complete_scope::complete_scope(&mut acc, &ctx);
67 complete_dot::complete_dot(&mut acc, &ctx); 67 complete_dot::complete_dot(&mut acc, &ctx);
68 complete_struct_literal::complete_struct_literal(&mut acc, &ctx); 68 complete_record_literal::complete_record_literal(&mut acc, &ctx);
69 complete_struct_pattern::complete_struct_pattern(&mut acc, &ctx); 69 complete_record_pattern::complete_record_pattern(&mut acc, &ctx);
70 complete_pattern::complete_pattern(&mut acc, &ctx); 70 complete_pattern::complete_pattern(&mut acc, &ctx);
71 complete_postfix::complete_postfix(&mut acc, &ctx); 71 complete_postfix::complete_postfix(&mut acc, &ctx);
72 Some(acc) 72 Some(acc)
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs
index d43ff2eec..27256f879 100644
--- a/crates/ra_ide_api/src/completion/complete_dot.rs
+++ b/crates/ra_ide_api/src/completion/complete_dot.rs
@@ -45,7 +45,7 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
45 // FIXME unions 45 // FIXME unions
46 TypeCtor::Tuple { .. } => { 46 TypeCtor::Tuple { .. } => {
47 for (i, ty) in a_ty.parameters.iter().enumerate() { 47 for (i, ty) in a_ty.parameters.iter().enumerate() {
48 acc.add_pos_field(ctx, i, ty); 48 acc.add_tuple_field(ctx, i, ty);
49 } 49 }
50 } 50 }
51 _ => {} 51 _ => {}
diff --git a/crates/ra_ide_api/src/completion/complete_struct_literal.rs b/crates/ra_ide_api/src/completion/complete_record_literal.rs
index 6aa41f498..6b929a8ac 100644
--- a/crates/ra_ide_api/src/completion/complete_struct_literal.rs
+++ b/crates/ra_ide_api/src/completion/complete_record_literal.rs
@@ -3,11 +3,11 @@ use hir::Substs;
3use crate::completion::{CompletionContext, Completions}; 3use crate::completion::{CompletionContext, Completions};
4 4
5/// Complete fields in fields literals. 5/// Complete fields in fields literals.
6pub(super) fn complete_struct_literal(acc: &mut Completions, ctx: &CompletionContext) { 6pub(super) fn complete_record_literal(acc: &mut Completions, ctx: &CompletionContext) {
7 let (ty, variant) = match ctx.struct_lit_syntax.as_ref().and_then(|it| { 7 let (ty, variant) = match ctx.record_lit_syntax.as_ref().and_then(|it| {
8 Some(( 8 Some((
9 ctx.analyzer.type_of(ctx.db, &it.clone().into())?, 9 ctx.analyzer.type_of(ctx.db, &it.clone().into())?,
10 ctx.analyzer.resolve_struct_literal(it)?, 10 ctx.analyzer.resolve_record_literal(it)?,
11 )) 11 ))
12 }) { 12 }) {
13 Some(it) => it, 13 Some(it) => it,
@@ -30,7 +30,7 @@ mod tests {
30 } 30 }
31 31
32 #[test] 32 #[test]
33 fn test_struct_literal_field() { 33 fn test_record_literal_field() {
34 let completions = complete( 34 let completions = complete(
35 r" 35 r"
36 struct A { the_field: u32 } 36 struct A { the_field: u32 }
@@ -54,7 +54,7 @@ mod tests {
54 } 54 }
55 55
56 #[test] 56 #[test]
57 fn test_struct_literal_enum_variant() { 57 fn test_record_literal_enum_variant() {
58 let completions = complete( 58 let completions = complete(
59 r" 59 r"
60 enum E { 60 enum E {
@@ -80,7 +80,7 @@ mod tests {
80 } 80 }
81 81
82 #[test] 82 #[test]
83 fn test_struct_literal_two_structs() { 83 fn test_record_literal_two_structs() {
84 let completions = complete( 84 let completions = complete(
85 r" 85 r"
86 struct A { a: u32 } 86 struct A { a: u32 }
@@ -106,7 +106,7 @@ mod tests {
106 } 106 }
107 107
108 #[test] 108 #[test]
109 fn test_struct_literal_generic_struct() { 109 fn test_record_literal_generic_struct() {
110 let completions = complete( 110 let completions = complete(
111 r" 111 r"
112 struct A<T> { a: T } 112 struct A<T> { a: T }
diff --git a/crates/ra_ide_api/src/completion/complete_struct_pattern.rs b/crates/ra_ide_api/src/completion/complete_record_pattern.rs
index d0dde5930..8c8b47ea4 100644
--- a/crates/ra_ide_api/src/completion/complete_struct_pattern.rs
+++ b/crates/ra_ide_api/src/completion/complete_record_pattern.rs
@@ -2,11 +2,11 @@ use hir::Substs;
2 2
3use crate::completion::{CompletionContext, Completions}; 3use crate::completion::{CompletionContext, Completions};
4 4
5pub(super) fn complete_struct_pattern(acc: &mut Completions, ctx: &CompletionContext) { 5pub(super) fn complete_record_pattern(acc: &mut Completions, ctx: &CompletionContext) {
6 let (ty, variant) = match ctx.struct_lit_pat.as_ref().and_then(|it| { 6 let (ty, variant) = match ctx.record_lit_pat.as_ref().and_then(|it| {
7 Some(( 7 Some((
8 ctx.analyzer.type_of_pat(ctx.db, &it.clone().into())?, 8 ctx.analyzer.type_of_pat(ctx.db, &it.clone().into())?,
9 ctx.analyzer.resolve_struct_pattern(it)?, 9 ctx.analyzer.resolve_record_pattern(it)?,
10 )) 10 ))
11 }) { 11 }) {
12 Some(it) => it, 12 Some(it) => it,
@@ -29,7 +29,7 @@ mod tests {
29 } 29 }
30 30
31 #[test] 31 #[test]
32 fn test_struct_pattern_field() { 32 fn test_record_pattern_field() {
33 let completions = complete( 33 let completions = complete(
34 r" 34 r"
35 struct S { foo: u32 } 35 struct S { foo: u32 }
@@ -56,7 +56,7 @@ mod tests {
56 } 56 }
57 57
58 #[test] 58 #[test]
59 fn test_struct_pattern_enum_variant() { 59 fn test_record_pattern_enum_variant() {
60 let completions = complete( 60 let completions = complete(
61 r" 61 r"
62 enum E { 62 enum E {
diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs
index dfaa9ce69..7139947b3 100644
--- a/crates/ra_ide_api/src/completion/completion_context.rs
+++ b/crates/ra_ide_api/src/completion/completion_context.rs
@@ -20,8 +20,8 @@ pub(crate) struct CompletionContext<'a> {
20 pub(super) module: Option<hir::Module>, 20 pub(super) module: Option<hir::Module>,
21 pub(super) function_syntax: Option<ast::FnDef>, 21 pub(super) function_syntax: Option<ast::FnDef>,
22 pub(super) use_item_syntax: Option<ast::UseItem>, 22 pub(super) use_item_syntax: Option<ast::UseItem>,
23 pub(super) struct_lit_syntax: Option<ast::StructLit>, 23 pub(super) record_lit_syntax: Option<ast::RecordLit>,
24 pub(super) struct_lit_pat: Option<ast::StructPat>, 24 pub(super) record_lit_pat: Option<ast::RecordPat>,
25 pub(super) is_param: bool, 25 pub(super) is_param: bool,
26 /// If a name-binding or reference to a const in a pattern. 26 /// If a name-binding or reference to a const in a pattern.
27 /// Irrefutable patterns (like let) are excluded. 27 /// Irrefutable patterns (like let) are excluded.
@@ -60,8 +60,8 @@ impl<'a> CompletionContext<'a> {
60 module, 60 module,
61 function_syntax: None, 61 function_syntax: None,
62 use_item_syntax: None, 62 use_item_syntax: None,
63 struct_lit_syntax: None, 63 record_lit_syntax: None,
64 struct_lit_pat: None, 64 record_lit_pat: None,
65 is_param: false, 65 is_param: false,
66 is_pat_binding: false, 66 is_pat_binding: false,
67 is_trivial_path: false, 67 is_trivial_path: false,
@@ -120,8 +120,8 @@ impl<'a> CompletionContext<'a> {
120 self.is_param = true; 120 self.is_param = true;
121 return; 121 return;
122 } 122 }
123 if name.syntax().ancestors().find_map(ast::FieldPatList::cast).is_some() { 123 if name.syntax().ancestors().find_map(ast::RecordFieldPatList::cast).is_some() {
124 self.struct_lit_pat = 124 self.record_lit_pat =
125 find_node_at_offset(original_parse.tree().syntax(), self.offset); 125 find_node_at_offset(original_parse.tree().syntax(), self.offset);
126 } 126 }
127 } 127 }
@@ -129,8 +129,8 @@ impl<'a> CompletionContext<'a> {
129 129
130 fn classify_name_ref(&mut self, original_file: SourceFile, name_ref: ast::NameRef) { 130 fn classify_name_ref(&mut self, original_file: SourceFile, name_ref: ast::NameRef) {
131 let name_range = name_ref.syntax().text_range(); 131 let name_range = name_ref.syntax().text_range();
132 if name_ref.syntax().parent().and_then(ast::NamedField::cast).is_some() { 132 if name_ref.syntax().parent().and_then(ast::RecordField::cast).is_some() {
133 self.struct_lit_syntax = find_node_at_offset(original_file.syntax(), self.offset); 133 self.record_lit_syntax = find_node_at_offset(original_file.syntax(), self.offset);
134 } 134 }
135 135
136 let top_node = name_ref 136 let top_node = name_ref
diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs
index 2b3f98482..147ceda0c 100644
--- a/crates/ra_ide_api/src/completion/presentation.rs
+++ b/crates/ra_ide_api/src/completion/presentation.rs
@@ -28,7 +28,7 @@ impl Completions {
28 .add_to(self); 28 .add_to(self);
29 } 29 }
30 30
31 pub(crate) fn add_pos_field(&mut self, ctx: &CompletionContext, field: usize, ty: &hir::Ty) { 31 pub(crate) fn add_tuple_field(&mut self, ctx: &CompletionContext, field: usize, ty: &hir::Ty) {
32 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), field.to_string()) 32 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), field.to_string())
33 .kind(CompletionItemKind::Field) 33 .kind(CompletionItemKind::Field)
34 .detail(ty.display(ctx.db).to_string()) 34 .detail(ty.display(ctx.db).to_string())
diff --git a/crates/ra_ide_api/src/diagnostics.rs b/crates/ra_ide_api/src/diagnostics.rs
index 98b840b26..1a4882824 100644
--- a/crates/ra_ide_api/src/diagnostics.rs
+++ b/crates/ra_ide_api/src/diagnostics.rs
@@ -9,7 +9,7 @@ use ra_assists::ast_editor::{AstBuilder, AstEditor};
9use ra_db::SourceDatabase; 9use ra_db::SourceDatabase;
10use ra_prof::profile; 10use ra_prof::profile;
11use ra_syntax::{ 11use ra_syntax::{
12 ast::{self, AstNode, NamedField}, 12 ast::{self, AstNode, RecordField},
13 Location, SyntaxNode, TextRange, T, 13 Location, SyntaxNode, TextRange, T,
14}; 14};
15use ra_text_edit::{TextEdit, TextEditBuilder}; 15use ra_text_edit::{TextEdit, TextEditBuilder};
@@ -62,7 +62,7 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic>
62 let node = d.ast(db); 62 let node = d.ast(db);
63 let mut ast_editor = AstEditor::new(node); 63 let mut ast_editor = AstEditor::new(node);
64 for f in d.missed_fields.iter() { 64 for f in d.missed_fields.iter() {
65 ast_editor.append_field(&AstBuilder::<NamedField>::from_name(f)); 65 ast_editor.append_field(&AstBuilder::<RecordField>::from_name(f));
66 } 66 }
67 67
68 let mut builder = TextEditBuilder::default(); 68 let mut builder = TextEditBuilder::default();
@@ -75,6 +75,19 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic>
75 severity: Severity::Error, 75 severity: Severity::Error,
76 fix: Some(fix), 76 fix: Some(fix),
77 }) 77 })
78 })
79 .on::<hir::diagnostics::MissingOkInTailExpr, _>(|d| {
80 let node = d.ast(db);
81 let mut builder = TextEditBuilder::default();
82 let replacement = format!("Ok({})", node.syntax());
83 builder.replace(node.syntax().text_range(), replacement);
84 let fix = SourceChange::source_file_edit_from("wrap with ok", file_id, builder.finish());
85 res.borrow_mut().push(Diagnostic {
86 range: d.highlight_range(),
87 message: d.message(),
88 severity: Severity::Error,
89 fix: Some(fix),
90 })
78 }); 91 });
79 if let Some(m) = source_binder::module_from_file_id(db, file_id) { 92 if let Some(m) = source_binder::module_from_file_id(db, file_id) {
80 m.diagnostics(db, &mut sink); 93 m.diagnostics(db, &mut sink);
@@ -141,20 +154,20 @@ fn check_struct_shorthand_initialization(
141 file_id: FileId, 154 file_id: FileId,
142 node: &SyntaxNode, 155 node: &SyntaxNode,
143) -> Option<()> { 156) -> Option<()> {
144 let struct_lit = ast::StructLit::cast(node.clone())?; 157 let record_lit = ast::RecordLit::cast(node.clone())?;
145 let named_field_list = struct_lit.named_field_list()?; 158 let record_field_list = record_lit.record_field_list()?;
146 for named_field in named_field_list.fields() { 159 for record_field in record_field_list.fields() {
147 if let (Some(name_ref), Some(expr)) = (named_field.name_ref(), named_field.expr()) { 160 if let (Some(name_ref), Some(expr)) = (record_field.name_ref(), record_field.expr()) {
148 let field_name = name_ref.syntax().text().to_string(); 161 let field_name = name_ref.syntax().text().to_string();
149 let field_expr = expr.syntax().text().to_string(); 162 let field_expr = expr.syntax().text().to_string();
150 if field_name == field_expr { 163 if field_name == field_expr {
151 let mut edit_builder = TextEditBuilder::default(); 164 let mut edit_builder = TextEditBuilder::default();
152 edit_builder.delete(named_field.syntax().text_range()); 165 edit_builder.delete(record_field.syntax().text_range());
153 edit_builder.insert(named_field.syntax().text_range().start(), field_name); 166 edit_builder.insert(record_field.syntax().text_range().start(), field_name);
154 let edit = edit_builder.finish(); 167 let edit = edit_builder.finish();
155 168
156 acc.push(Diagnostic { 169 acc.push(Diagnostic {
157 range: named_field.syntax().text_range(), 170 range: record_field.syntax().text_range(),
158 message: "Shorthand struct initialization".to_string(), 171 message: "Shorthand struct initialization".to_string(),
159 severity: Severity::WeakWarning, 172 severity: Severity::WeakWarning,
160 fix: Some(SourceChange::source_file_edit( 173 fix: Some(SourceChange::source_file_edit(
@@ -171,10 +184,11 @@ fn check_struct_shorthand_initialization(
171#[cfg(test)] 184#[cfg(test)]
172mod tests { 185mod tests {
173 use insta::assert_debug_snapshot_matches; 186 use insta::assert_debug_snapshot_matches;
187 use join_to_string::join;
174 use ra_syntax::SourceFile; 188 use ra_syntax::SourceFile;
175 use test_utils::assert_eq_text; 189 use test_utils::assert_eq_text;
176 190
177 use crate::mock_analysis::single_file; 191 use crate::mock_analysis::{analysis_and_position, single_file};
178 192
179 use super::*; 193 use super::*;
180 194
@@ -203,6 +217,48 @@ mod tests {
203 assert_eq_text!(after, &actual); 217 assert_eq_text!(after, &actual);
204 } 218 }
205 219
220 /// Takes a multi-file input fixture with annotated cursor positions,
221 /// and checks that:
222 /// * a diagnostic is produced
223 /// * this diagnostic touches the input cursor position
224 /// * that the contents of the file containing the cursor match `after` after the diagnostic fix is applied
225 fn check_apply_diagnostic_fix_from_position(fixture: &str, after: &str) {
226 let (analysis, file_position) = analysis_and_position(fixture);
227 let diagnostic = analysis.diagnostics(file_position.file_id).unwrap().pop().unwrap();
228 let mut fix = diagnostic.fix.unwrap();
229 let edit = fix.source_file_edits.pop().unwrap().edit;
230 let target_file_contents = analysis.file_text(file_position.file_id).unwrap();
231 let actual = edit.apply(&target_file_contents);
232
233 // Strip indent and empty lines from `after`, to match the behaviour of
234 // `parse_fixture` called from `analysis_and_position`.
235 let margin = fixture
236 .lines()
237 .filter(|it| it.trim_start().starts_with("//-"))
238 .map(|it| it.len() - it.trim_start().len())
239 .next()
240 .expect("empty fixture");
241 let after = join(after.lines().filter_map(|line| {
242 if line.len() > margin {
243 Some(&line[margin..])
244 } else {
245 None
246 }
247 }))
248 .separator("\n")
249 .suffix("\n")
250 .to_string();
251
252 assert_eq_text!(&after, &actual);
253 assert!(
254 diagnostic.range.start() <= file_position.offset
255 && diagnostic.range.end() >= file_position.offset,
256 "diagnostic range {} does not touch cursor position {}",
257 diagnostic.range,
258 file_position.offset
259 );
260 }
261
206 fn check_apply_diagnostic_fix(before: &str, after: &str) { 262 fn check_apply_diagnostic_fix(before: &str, after: &str) {
207 let (analysis, file_id) = single_file(before); 263 let (analysis, file_id) = single_file(before);
208 let diagnostic = analysis.diagnostics(file_id).unwrap().pop().unwrap(); 264 let diagnostic = analysis.diagnostics(file_id).unwrap().pop().unwrap();
@@ -212,6 +268,14 @@ mod tests {
212 assert_eq_text!(after, &actual); 268 assert_eq_text!(after, &actual);
213 } 269 }
214 270
271 /// Takes a multi-file input fixture with annotated cursor position and checks that no diagnostics
272 /// apply to the file containing the cursor.
273 fn check_no_diagnostic_for_target_file(fixture: &str) {
274 let (analysis, file_position) = analysis_and_position(fixture);
275 let diagnostics = analysis.diagnostics(file_position.file_id).unwrap();
276 assert_eq!(diagnostics.len(), 0);
277 }
278
215 fn check_no_diagnostic(content: &str) { 279 fn check_no_diagnostic(content: &str) {
216 let (analysis, file_id) = single_file(content); 280 let (analysis, file_id) = single_file(content);
217 let diagnostics = analysis.diagnostics(file_id).unwrap(); 281 let diagnostics = analysis.diagnostics(file_id).unwrap();
@@ -219,6 +283,155 @@ mod tests {
219 } 283 }
220 284
221 #[test] 285 #[test]
286 fn test_wrap_return_type() {
287 let before = r#"
288 //- /main.rs
289 use std::{string::String, result::Result::{self, Ok, Err}};
290
291 fn div(x: i32, y: i32) -> Result<i32, String> {
292 if y == 0 {
293 return Err("div by zero".into());
294 }
295 x / y<|>
296 }
297
298 //- /std/lib.rs
299 pub mod string {
300 pub struct String { }
301 }
302 pub mod result {
303 pub enum Result<T, E> { Ok(T), Err(E) }
304 }
305 "#;
306 let after = r#"
307 use std::{string::String, result::Result::{self, Ok, Err}};
308
309 fn div(x: i32, y: i32) -> Result<i32, String> {
310 if y == 0 {
311 return Err("div by zero".into());
312 }
313 Ok(x / y)
314 }
315 "#;
316 check_apply_diagnostic_fix_from_position(before, after);
317 }
318
319 #[test]
320 fn test_wrap_return_type_handles_generic_functions() {
321 let before = r#"
322 //- /main.rs
323 use std::result::Result::{self, Ok, Err};
324
325 fn div<T>(x: T) -> Result<T, i32> {
326 if x == 0 {
327 return Err(7);
328 }
329 <|>x
330 }
331
332 //- /std/lib.rs
333 pub mod result {
334 pub enum Result<T, E> { Ok(T), Err(E) }
335 }
336 "#;
337 let after = r#"
338 use std::result::Result::{self, Ok, Err};
339
340 fn div<T>(x: T) -> Result<T, i32> {
341 if x == 0 {
342 return Err(7);
343 }
344 Ok(x)
345 }
346 "#;
347 check_apply_diagnostic_fix_from_position(before, after);
348 }
349
350 #[test]
351 fn test_wrap_return_type_handles_type_aliases() {
352 let before = r#"
353 //- /main.rs
354 use std::{string::String, result::Result::{self, Ok, Err}};
355
356 type MyResult<T> = Result<T, String>;
357
358 fn div(x: i32, y: i32) -> MyResult<i32> {
359 if y == 0 {
360 return Err("div by zero".into());
361 }
362 x <|>/ y
363 }
364
365 //- /std/lib.rs
366 pub mod string {
367 pub struct String { }
368 }
369 pub mod result {
370 pub enum Result<T, E> { Ok(T), Err(E) }
371 }
372 "#;
373 let after = r#"
374 use std::{string::String, result::Result::{self, Ok, Err}};
375
376 type MyResult<T> = Result<T, String>;
377 fn div(x: i32, y: i32) -> MyResult<i32> {
378 if y == 0 {
379 return Err("div by zero".into());
380 }
381 Ok(x / y)
382 }
383 "#;
384 check_apply_diagnostic_fix_from_position(before, after);
385 }
386
387 #[test]
388 fn test_wrap_return_type_not_applicable_when_expr_type_does_not_match_ok_type() {
389 let content = r#"
390 //- /main.rs
391 use std::{string::String, result::Result::{self, Ok, Err}};
392
393 fn foo() -> Result<String, i32> {
394 0<|>
395 }
396
397 //- /std/lib.rs
398 pub mod string {
399 pub struct String { }
400 }
401 pub mod result {
402 pub enum Result<T, E> { Ok(T), Err(E) }
403 }
404 "#;
405 check_no_diagnostic_for_target_file(content);
406 }
407
408 #[test]
409 fn test_wrap_return_type_not_applicable_when_return_type_is_not_result() {
410 let content = r#"
411 //- /main.rs
412 use std::{string::String, result::Result::{self, Ok, Err}};
413
414 enum SomeOtherEnum {
415 Ok(i32),
416 Err(String),
417 }
418
419 fn foo() -> SomeOtherEnum {
420 0<|>
421 }
422
423 //- /std/lib.rs
424 pub mod string {
425 pub struct String { }
426 }
427 pub mod result {
428 pub enum Result<T, E> { Ok(T), Err(E) }
429 }
430 "#;
431 check_no_diagnostic_for_target_file(content);
432 }
433
434 #[test]
222 fn test_fill_struct_fields_empty() { 435 fn test_fill_struct_fields_empty() {
223 let before = r" 436 let before = r"
224 struct TestStruct { 437 struct TestStruct {
diff --git a/crates/ra_ide_api/src/display/navigation_target.rs b/crates/ra_ide_api/src/display/navigation_target.rs
index 84fabdb9e..c85214bb3 100644
--- a/crates/ra_ide_api/src/display/navigation_target.rs
+++ b/crates/ra_ide_api/src/display/navigation_target.rs
@@ -314,7 +314,7 @@ pub(crate) fn docs_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option
314 .visit(|it: ast::TypeAliasDef| it.doc_comment_text()) 314 .visit(|it: ast::TypeAliasDef| it.doc_comment_text())
315 .visit(|it: ast::ConstDef| it.doc_comment_text()) 315 .visit(|it: ast::ConstDef| it.doc_comment_text())
316 .visit(|it: ast::StaticDef| it.doc_comment_text()) 316 .visit(|it: ast::StaticDef| it.doc_comment_text())
317 .visit(|it: ast::NamedFieldDef| it.doc_comment_text()) 317 .visit(|it: ast::RecordFieldDef| it.doc_comment_text())
318 .visit(|it: ast::EnumVariant| it.doc_comment_text()) 318 .visit(|it: ast::EnumVariant| it.doc_comment_text())
319 .visit(|it: ast::MacroCall| it.doc_comment_text()) 319 .visit(|it: ast::MacroCall| it.doc_comment_text())
320 .accept(&node)? 320 .accept(&node)?
@@ -336,7 +336,7 @@ pub(crate) fn description_from_symbol(db: &RootDatabase, symbol: &FileSymbol) ->
336 .visit(|node: ast::TypeAliasDef| node.short_label()) 336 .visit(|node: ast::TypeAliasDef| node.short_label())
337 .visit(|node: ast::ConstDef| node.short_label()) 337 .visit(|node: ast::ConstDef| node.short_label())
338 .visit(|node: ast::StaticDef| node.short_label()) 338 .visit(|node: ast::StaticDef| node.short_label())
339 .visit(|node: ast::NamedFieldDef| node.short_label()) 339 .visit(|node: ast::RecordFieldDef| node.short_label())
340 .visit(|node: ast::EnumVariant| node.short_label()) 340 .visit(|node: ast::EnumVariant| node.short_label())
341 .accept(&node)? 341 .accept(&node)?
342} 342}
diff --git a/crates/ra_ide_api/src/display/short_label.rs b/crates/ra_ide_api/src/display/short_label.rs
index 825a033ee..b16d504e1 100644
--- a/crates/ra_ide_api/src/display/short_label.rs
+++ b/crates/ra_ide_api/src/display/short_label.rs
@@ -53,7 +53,7 @@ impl ShortLabel for ast::StaticDef {
53 } 53 }
54} 54}
55 55
56impl ShortLabel for ast::NamedFieldDef { 56impl ShortLabel for ast::RecordFieldDef {
57 fn short_label(&self) -> Option<String> { 57 fn short_label(&self) -> Option<String> {
58 short_label_from_ascribed_node(self, "") 58 short_label_from_ascribed_node(self, "")
59 } 59 }
diff --git a/crates/ra_ide_api/src/display/structure.rs b/crates/ra_ide_api/src/display/structure.rs
index b026dfa59..a2025ed59 100644
--- a/crates/ra_ide_api/src/display/structure.rs
+++ b/crates/ra_ide_api/src/display/structure.rs
@@ -124,7 +124,7 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
124 let ty = td.type_ref(); 124 let ty = td.type_ref();
125 decl_with_type_ref(td, ty) 125 decl_with_type_ref(td, ty)
126 }) 126 })
127 .visit(decl_with_ascription::<ast::NamedFieldDef>) 127 .visit(decl_with_ascription::<ast::RecordFieldDef>)
128 .visit(decl_with_ascription::<ast::ConstDef>) 128 .visit(decl_with_ascription::<ast::ConstDef>)
129 .visit(decl_with_ascription::<ast::StaticDef>) 129 .visit(decl_with_ascription::<ast::StaticDef>)
130 .visit(|im: ast::ImplBlock| { 130 .visit(|im: ast::ImplBlock| {
@@ -222,7 +222,7 @@ fn very_obsolete() {}
222 label: "x", 222 label: "x",
223 navigation_range: [18; 19), 223 navigation_range: [18; 19),
224 node_range: [18; 24), 224 node_range: [18; 24),
225 kind: NAMED_FIELD_DEF, 225 kind: RECORD_FIELD_DEF,
226 detail: Some( 226 detail: Some(
227 "i32", 227 "i32",
228 ), 228 ),
diff --git a/crates/ra_ide_api/src/extend_selection.rs b/crates/ra_ide_api/src/extend_selection.rs
index edbf622c1..e990eb0d1 100644
--- a/crates/ra_ide_api/src/extend_selection.rs
+++ b/crates/ra_ide_api/src/extend_selection.rs
@@ -18,11 +18,11 @@ pub(crate) fn extend_selection(db: &RootDatabase, frange: FileRange) -> TextRang
18fn try_extend_selection(root: &SyntaxNode, range: TextRange) -> Option<TextRange> { 18fn try_extend_selection(root: &SyntaxNode, range: TextRange) -> Option<TextRange> {
19 let string_kinds = [COMMENT, STRING, RAW_STRING, BYTE_STRING, RAW_BYTE_STRING]; 19 let string_kinds = [COMMENT, STRING, RAW_STRING, BYTE_STRING, RAW_BYTE_STRING];
20 let list_kinds = [ 20 let list_kinds = [
21 FIELD_PAT_LIST, 21 RECORD_FIELD_PAT_LIST,
22 MATCH_ARM_LIST, 22 MATCH_ARM_LIST,
23 NAMED_FIELD_DEF_LIST, 23 RECORD_FIELD_DEF_LIST,
24 POS_FIELD_DEF_LIST, 24 TUPLE_FIELD_DEF_LIST,
25 NAMED_FIELD_LIST, 25 RECORD_FIELD_LIST,
26 ENUM_VARIANT_LIST, 26 ENUM_VARIANT_LIST,
27 USE_TREE_LIST, 27 USE_TREE_LIST,
28 TYPE_PARAM_LIST, 28 TYPE_PARAM_LIST,
diff --git a/crates/ra_ide_api/src/folding_ranges.rs b/crates/ra_ide_api/src/folding_ranges.rs
index e60ae8cf6..3ab6c195e 100644
--- a/crates/ra_ide_api/src/folding_ranges.rs
+++ b/crates/ra_ide_api/src/folding_ranges.rs
@@ -81,8 +81,14 @@ fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> {
81 match kind { 81 match kind {
82 COMMENT => Some(FoldKind::Comment), 82 COMMENT => Some(FoldKind::Comment),
83 USE_ITEM => Some(FoldKind::Imports), 83 USE_ITEM => Some(FoldKind::Imports),
84 NAMED_FIELD_DEF_LIST | FIELD_PAT_LIST | ITEM_LIST | EXTERN_ITEM_LIST | USE_TREE_LIST 84 RECORD_FIELD_DEF_LIST
85 | BLOCK | ENUM_VARIANT_LIST | TOKEN_TREE => Some(FoldKind::Block), 85 | RECORD_FIELD_PAT_LIST
86 | ITEM_LIST
87 | EXTERN_ITEM_LIST
88 | USE_TREE_LIST
89 | BLOCK
90 | ENUM_VARIANT_LIST
91 | TOKEN_TREE => Some(FoldKind::Block),
86 _ => None, 92 _ => None,
87 } 93 }
88} 94}
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index ddd55a9c1..28529a2de 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -178,7 +178,7 @@ fn named_target(file_id: FileId, node: &SyntaxNode) -> Option<NavigationTarget>
178 node.short_label(), 178 node.short_label(),
179 ) 179 )
180 }) 180 })
181 .visit(|node: ast::NamedFieldDef| { 181 .visit(|node: ast::RecordFieldDef| {
182 NavigationTarget::from_named( 182 NavigationTarget::from_named(
183 file_id, 183 file_id,
184 &node, 184 &node,
@@ -344,13 +344,13 @@ mod tests {
344 foo.spam<|>; 344 foo.spam<|>;
345 } 345 }
346 ", 346 ",
347 "spam NAMED_FIELD_DEF FileId(1) [17; 26) [17; 21)", 347 "spam RECORD_FIELD_DEF FileId(1) [17; 26) [17; 21)",
348 ); 348 );
349 } 349 }
350 350
351 #[test] 351 #[test]
352 fn goto_definition_works_for_named_fields() { 352 fn goto_definition_works_for_record_fields() {
353 covers!(goto_definition_works_for_named_fields); 353 covers!(goto_definition_works_for_record_fields);
354 check_goto( 354 check_goto(
355 " 355 "
356 //- /lib.rs 356 //- /lib.rs
@@ -364,7 +364,7 @@ mod tests {
364 } 364 }
365 } 365 }
366 ", 366 ",
367 "spam NAMED_FIELD_DEF FileId(1) [17; 26) [17; 21)", 367 "spam RECORD_FIELD_DEF FileId(1) [17; 26) [17; 21)",
368 ); 368 );
369 } 369 }
370 #[test] 370 #[test]
@@ -473,7 +473,7 @@ mod tests {
473 field<|>: string, 473 field<|>: string,
474 } 474 }
475 "#, 475 "#,
476 "field NAMED_FIELD_DEF FileId(1) [17; 30) [17; 22)", 476 "field RECORD_FIELD_DEF FileId(1) [17; 30) [17; 22)",
477 ); 477 );
478 478
479 check_goto( 479 check_goto(
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs
index 2a5ac7821..1981e62d3 100644
--- a/crates/ra_ide_api/src/hover.rs
+++ b/crates/ra_ide_api/src/hover.rs
@@ -197,7 +197,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
197 .visit(|node: ast::TraitDef| { 197 .visit(|node: ast::TraitDef| {
198 hover_text(node.doc_comment_text(), node.short_label()) 198 hover_text(node.doc_comment_text(), node.short_label())
199 }) 199 })
200 .visit(|node: ast::NamedFieldDef| { 200 .visit(|node: ast::RecordFieldDef| {
201 hover_text(node.doc_comment_text(), node.short_label()) 201 hover_text(node.doc_comment_text(), node.short_label())
202 }) 202 })
203 .visit(|node: ast::Module| hover_text(node.doc_comment_text(), node.short_label())) 203 .visit(|node: ast::Module| hover_text(node.doc_comment_text(), node.short_label()))
diff --git a/crates/ra_ide_api/src/inlay_hints.rs b/crates/ra_ide_api/src/inlay_hints.rs
index 735f3166c..61ccb74b6 100644
--- a/crates/ra_ide_api/src/inlay_hints.rs
+++ b/crates/ra_ide_api/src/inlay_hints.rs
@@ -125,13 +125,13 @@ fn get_leaf_pats(root_pat: ast::Pat) -> Vec<ast::Pat> {
125 pats_to_process.push_back(arg_pat); 125 pats_to_process.push_back(arg_pat);
126 } 126 }
127 } 127 }
128 ast::Pat::StructPat(struct_pat) => { 128 ast::Pat::RecordPat(record_pat) => {
129 if let Some(pat_list) = struct_pat.field_pat_list() { 129 if let Some(pat_list) = record_pat.record_field_pat_list() {
130 pats_to_process.extend( 130 pats_to_process.extend(
131 pat_list 131 pat_list
132 .field_pats() 132 .record_field_pats()
133 .filter_map(|field_pat| { 133 .filter_map(|record_field_pat| {
134 field_pat 134 record_field_pat
135 .pat() 135 .pat()
136 .filter(|pat| pat.syntax().kind() != SyntaxKind::BIND_PAT) 136 .filter(|pat| pat.syntax().kind() != SyntaxKind::BIND_PAT)
137 }) 137 })
diff --git a/crates/ra_ide_api/src/marks.rs b/crates/ra_ide_api/src/marks.rs
index 9cb991de5..c3752cc54 100644
--- a/crates/ra_ide_api/src/marks.rs
+++ b/crates/ra_ide_api/src/marks.rs
@@ -3,7 +3,7 @@ test_utils::marks!(
3 goto_definition_works_for_macros 3 goto_definition_works_for_macros
4 goto_definition_works_for_methods 4 goto_definition_works_for_methods
5 goto_definition_works_for_fields 5 goto_definition_works_for_fields
6 goto_definition_works_for_named_fields 6 goto_definition_works_for_record_fields
7 call_info_bad_offset 7 call_info_bad_offset
8 dont_complete_current_use 8 dont_complete_current_use
9 dont_complete_primitive_in_use 9 dont_complete_primitive_in_use
diff --git a/crates/ra_ide_api/src/name_ref_kind.rs b/crates/ra_ide_api/src/name_ref_kind.rs
index f7db6c826..34a8bcc36 100644
--- a/crates/ra_ide_api/src/name_ref_kind.rs
+++ b/crates/ra_ide_api/src/name_ref_kind.rs
@@ -54,12 +54,12 @@ pub(crate) fn classify_name_ref(
54 } 54 }
55 55
56 // It could also be a named field 56 // It could also be a named field
57 if let Some(field_expr) = name_ref.syntax().parent().and_then(ast::NamedField::cast) { 57 if let Some(field_expr) = name_ref.syntax().parent().and_then(ast::RecordField::cast) {
58 tested_by!(goto_definition_works_for_named_fields); 58 tested_by!(goto_definition_works_for_record_fields);
59 59
60 let struct_lit = field_expr.syntax().ancestors().find_map(ast::StructLit::cast); 60 let record_lit = field_expr.syntax().ancestors().find_map(ast::RecordLit::cast);
61 61
62 if let Some(ty) = struct_lit.and_then(|lit| analyzer.type_of(db, &lit.into())) { 62 if let Some(ty) = record_lit.and_then(|lit| analyzer.type_of(db, &lit.into())) {
63 if let Some((hir::AdtDef::Struct(s), _)) = ty.as_adt() { 63 if let Some((hir::AdtDef::Struct(s), _)) = ty.as_adt() {
64 let hir_path = hir::Path::from_name_ref(name_ref); 64 let hir_path = hir::Path::from_name_ref(name_ref);
65 let hir_name = hir_path.as_ident().unwrap(); 65 let hir_name = hir_path.as_ident().unwrap();
diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs
index 448acffc8..06ccf0728 100644
--- a/crates/ra_ide_api/src/syntax_highlighting.rs
+++ b/crates/ra_ide_api/src/syntax_highlighting.rs
@@ -165,7 +165,7 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa
165 TYPE_PARAM | STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_ALIAS_DEF => { 165 TYPE_PARAM | STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_ALIAS_DEF => {
166 "type" 166 "type"
167 } 167 }
168 NAMED_FIELD_DEF => "field", 168 RECORD_FIELD_DEF => "field",
169 _ => "function", 169 _ => "function",
170 }) 170 })
171 .unwrap_or("function") 171 .unwrap_or("function")
diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml
index afeac0d8a..e271c257b 100644
--- a/crates/ra_lsp_server/Cargo.toml
+++ b/crates/ra_lsp_server/Cargo.toml
@@ -16,7 +16,7 @@ lsp-types = { version = "0.60.0", features = ["proposed"] }
16rustc-hash = "1.0" 16rustc-hash = "1.0"
17parking_lot = "0.9.0" 17parking_lot = "0.9.0"
18 18
19ra_vfs = "0.2.7" 19ra_vfs = "0.3.0"
20thread_worker = { path = "../thread_worker" } 20thread_worker = { path = "../thread_worker" }
21ra_syntax = { path = "../ra_syntax" } 21ra_syntax = { path = "../ra_syntax" }
22ra_text_edit = { path = "../ra_text_edit" } 22ra_text_edit = { path = "../ra_text_edit" }
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs
index 0ad2ea10f..5fa52ec1b 100644
--- a/crates/ra_lsp_server/src/conv.rs
+++ b/crates/ra_lsp_server/src/conv.rs
@@ -42,7 +42,7 @@ impl Conv for SyntaxKind {
42 SyntaxKind::TRAIT_DEF => SymbolKind::Interface, 42 SyntaxKind::TRAIT_DEF => SymbolKind::Interface,
43 SyntaxKind::MODULE => SymbolKind::Module, 43 SyntaxKind::MODULE => SymbolKind::Module,
44 SyntaxKind::TYPE_ALIAS_DEF => SymbolKind::TypeParameter, 44 SyntaxKind::TYPE_ALIAS_DEF => SymbolKind::TypeParameter,
45 SyntaxKind::NAMED_FIELD_DEF => SymbolKind::Field, 45 SyntaxKind::RECORD_FIELD_DEF => SymbolKind::Field,
46 SyntaxKind::STATIC_DEF => SymbolKind::Constant, 46 SyntaxKind::STATIC_DEF => SymbolKind::Constant,
47 SyntaxKind::CONST_DEF => SymbolKind::Constant, 47 SyntaxKind::CONST_DEF => SymbolKind::Constant,
48 SyntaxKind::IMPL_BLOCK => SymbolKind::Object, 48 SyntaxKind::IMPL_BLOCK => SymbolKind::Object,
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs
index ce25ff162..45bd52769 100644
--- a/crates/ra_lsp_server/src/main_loop.rs
+++ b/crates/ra_lsp_server/src/main_loop.rs
@@ -217,7 +217,7 @@ fn main_loop_inner(
217 Err(RecvError) => Err("client exited without shutdown")?, 217 Err(RecvError) => Err("client exited without shutdown")?,
218 }, 218 },
219 recv(task_receiver) -> task => Event::Task(task.unwrap()), 219 recv(task_receiver) -> task => Event::Task(task.unwrap()),
220 recv(state.vfs.read().task_receiver()) -> task => match task { 220 recv(state.task_receiver) -> task => match task {
221 Ok(task) => Event::Vfs(task), 221 Ok(task) => Event::Vfs(task),
222 Err(RecvError) => Err("vfs died")?, 222 Err(RecvError) => Err("vfs died")?,
223 }, 223 },
diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs
index 6696dff71..cc7964469 100644
--- a/crates/ra_lsp_server/src/world.rs
+++ b/crates/ra_lsp_server/src/world.rs
@@ -3,6 +3,7 @@ use std::{
3 sync::Arc, 3 sync::Arc,
4}; 4};
5 5
6use crossbeam_channel::{unbounded, Receiver};
6use gen_lsp_server::ErrorCode; 7use gen_lsp_server::ErrorCode;
7use lsp_types::Url; 8use lsp_types::Url;
8use parking_lot::RwLock; 9use parking_lot::RwLock;
@@ -10,7 +11,7 @@ use ra_ide_api::{
10 Analysis, AnalysisChange, AnalysisHost, CrateGraph, FeatureFlags, FileId, LibraryData, 11 Analysis, AnalysisChange, AnalysisHost, CrateGraph, FeatureFlags, FileId, LibraryData,
11 SourceRootId, 12 SourceRootId,
12}; 13};
13use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot}; 14use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask};
14use ra_vfs_glob::{Glob, RustPackageFilterBuilder}; 15use ra_vfs_glob::{Glob, RustPackageFilterBuilder};
15use relative_path::RelativePathBuf; 16use relative_path::RelativePathBuf;
16 17
@@ -39,6 +40,7 @@ pub struct WorldState {
39 pub workspaces: Arc<Vec<ProjectWorkspace>>, 40 pub workspaces: Arc<Vec<ProjectWorkspace>>,
40 pub analysis_host: AnalysisHost, 41 pub analysis_host: AnalysisHost,
41 pub vfs: Arc<RwLock<Vfs>>, 42 pub vfs: Arc<RwLock<Vfs>>,
43 pub task_receiver: Receiver<VfsTask>,
42 pub latest_requests: Arc<RwLock<LatestRequests>>, 44 pub latest_requests: Arc<RwLock<LatestRequests>>,
43} 45}
44 46
@@ -80,8 +82,9 @@ impl WorldState {
80 RootEntry::new(pkg_root.path().clone(), filter.into_vfs_filter()) 82 RootEntry::new(pkg_root.path().clone(), filter.into_vfs_filter())
81 })); 83 }));
82 } 84 }
83 85 let (task_sender, task_receiver) = unbounded();
84 let (mut vfs, vfs_roots) = Vfs::new(roots); 86 let task_sender = Box::new(move |t| task_sender.send(t).unwrap());
87 let (mut vfs, vfs_roots) = Vfs::new(roots, task_sender);
85 let roots_to_scan = vfs_roots.len(); 88 let roots_to_scan = vfs_roots.len();
86 for r in vfs_roots { 89 for r in vfs_roots {
87 let vfs_root_path = vfs.root2path(r); 90 let vfs_root_path = vfs.root2path(r);
@@ -109,6 +112,7 @@ impl WorldState {
109 workspaces: Arc::new(workspaces), 112 workspaces: Arc::new(workspaces),
110 analysis_host, 113 analysis_host,
111 vfs: Arc::new(RwLock::new(vfs)), 114 vfs: Arc::new(RwLock::new(vfs)),
115 task_receiver,
112 latest_requests: Default::default(), 116 latest_requests: Default::default(),
113 } 117 }
114 } 118 }
diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs
index 192e9007d..1dbf22997 100644
--- a/crates/ra_mbe/src/tests.rs
+++ b/crates/ra_mbe/src/tests.rs
@@ -419,9 +419,9 @@ MACRO_ITEMS@[0; 40)
419 STRUCT_KW@[0; 6) "struct" 419 STRUCT_KW@[0; 6) "struct"
420 NAME@[6; 9) 420 NAME@[6; 9)
421 IDENT@[6; 9) "Foo" 421 IDENT@[6; 9) "Foo"
422 NAMED_FIELD_DEF_LIST@[9; 20) 422 RECORD_FIELD_DEF_LIST@[9; 20)
423 L_CURLY@[9; 10) "{" 423 L_CURLY@[9; 10) "{"
424 NAMED_FIELD_DEF@[10; 19) 424 RECORD_FIELD_DEF@[10; 19)
425 NAME@[10; 15) 425 NAME@[10; 15)
426 IDENT@[10; 15) "field" 426 IDENT@[10; 15) "field"
427 COLON@[15; 16) ":" 427 COLON@[15; 16) ":"
@@ -435,9 +435,9 @@ MACRO_ITEMS@[0; 40)
435 STRUCT_KW@[20; 26) "struct" 435 STRUCT_KW@[20; 26) "struct"
436 NAME@[26; 29) 436 NAME@[26; 29)
437 IDENT@[26; 29) "Bar" 437 IDENT@[26; 29) "Bar"
438 NAMED_FIELD_DEF_LIST@[29; 40) 438 RECORD_FIELD_DEF_LIST@[29; 40)
439 L_CURLY@[29; 30) "{" 439 L_CURLY@[29; 30) "{"
440 NAMED_FIELD_DEF@[30; 39) 440 RECORD_FIELD_DEF@[30; 39)
441 NAME@[30; 35) 441 NAME@[30; 35)
442 IDENT@[30; 35) "field" 442 IDENT@[30; 35) "field"
443 COLON@[35; 36) ":" 443 COLON@[35; 36) ":"
diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs
index beedac457..dee3a229d 100644
--- a/crates/ra_parser/src/grammar.rs
+++ b/crates/ra_parser/src/grammar.rs
@@ -150,8 +150,8 @@ pub(crate) fn reparser(
150) -> Option<fn(&mut Parser)> { 150) -> Option<fn(&mut Parser)> {
151 let res = match node { 151 let res = match node {
152 BLOCK => expressions::block, 152 BLOCK => expressions::block,
153 NAMED_FIELD_DEF_LIST => items::named_field_def_list, 153 RECORD_FIELD_DEF_LIST => items::record_field_def_list,
154 NAMED_FIELD_LIST => items::named_field_list, 154 RECORD_FIELD_LIST => items::record_field_list,
155 ENUM_VARIANT_LIST => items::enum_variant_list, 155 ENUM_VARIANT_LIST => items::enum_variant_list,
156 MATCH_ARM_LIST => items::match_arm_list, 156 MATCH_ARM_LIST => items::match_arm_list,
157 USE_TREE_LIST => items::use_tree_list, 157 USE_TREE_LIST => items::use_tree_list,
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs
index 0495f34ae..783d6a6f0 100644
--- a/crates/ra_parser/src/grammar/expressions.rs
+++ b/crates/ra_parser/src/grammar/expressions.rs
@@ -559,8 +559,8 @@ fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) {
559 paths::expr_path(p); 559 paths::expr_path(p);
560 match p.current() { 560 match p.current() {
561 T!['{'] if !r.forbid_structs => { 561 T!['{'] if !r.forbid_structs => {
562 named_field_list(p); 562 record_field_list(p);
563 (m.complete(p, STRUCT_LIT), BlockLike::NotBlock) 563 (m.complete(p, RECORD_LIT), BlockLike::NotBlock)
564 } 564 }
565 T![!] => { 565 T![!] => {
566 let block_like = items::macro_call_after_excl(p); 566 let block_like = items::macro_call_after_excl(p);
@@ -570,20 +570,20 @@ fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) {
570 } 570 }
571} 571}
572 572
573// test struct_lit 573// test record_lit
574// fn foo() { 574// fn foo() {
575// S {}; 575// S {};
576// S { x, y: 32, }; 576// S { x, y: 32, };
577// S { x, y: 32, ..Default::default() }; 577// S { x, y: 32, ..Default::default() };
578// TupleStruct { 0: 1 }; 578// TupleStruct { 0: 1 };
579// } 579// }
580pub(crate) fn named_field_list(p: &mut Parser) { 580pub(crate) fn record_field_list(p: &mut Parser) {
581 assert!(p.at(T!['{'])); 581 assert!(p.at(T!['{']));
582 let m = p.start(); 582 let m = p.start();
583 p.bump(); 583 p.bump();
584 while !p.at(EOF) && !p.at(T!['}']) { 584 while !p.at(EOF) && !p.at(T!['}']) {
585 match p.current() { 585 match p.current() {
586 // test struct_literal_field_with_attr 586 // test record_literal_field_with_attr
587 // fn main() { 587 // fn main() {
588 // S { #[cfg(test)] field: 1 } 588 // S { #[cfg(test)] field: 1 }
589 // } 589 // }
@@ -594,7 +594,7 @@ pub(crate) fn named_field_list(p: &mut Parser) {
594 if p.eat(T![:]) { 594 if p.eat(T![:]) {
595 expr(p); 595 expr(p);
596 } 596 }
597 m.complete(p, NAMED_FIELD); 597 m.complete(p, RECORD_FIELD);
598 } 598 }
599 T![..] => { 599 T![..] => {
600 p.bump(); 600 p.bump();
@@ -608,5 +608,5 @@ pub(crate) fn named_field_list(p: &mut Parser) {
608 } 608 }
609 } 609 }
610 p.expect(T!['}']); 610 p.expect(T!['}']);
611 m.complete(p, NAMED_FIELD_LIST); 611 m.complete(p, RECORD_FIELD_LIST);
612} 612}
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs
index ab8fb9f6e..bc942ae01 100644
--- a/crates/ra_parser/src/grammar/expressions/atom.rs
+++ b/crates/ra_parser/src/grammar/expressions/atom.rs
@@ -414,8 +414,6 @@ pub(crate) fn match_arm_list(p: &mut Parser) {
414// X | Y if Z => (), 414// X | Y if Z => (),
415// | X | Y if Z => (), 415// | X | Y if Z => (),
416// | X => (), 416// | X => (),
417// box X => (),
418// Some(box X) => (),
419// }; 417// };
420// } 418// }
421fn match_arm(p: &mut Parser) -> BlockLike { 419fn match_arm(p: &mut Parser) -> BlockLike {
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs
index b7da44758..6d426206e 100644
--- a/crates/ra_parser/src/grammar/items.rs
+++ b/crates/ra_parser/src/grammar/items.rs
@@ -4,8 +4,8 @@ mod traits;
4mod use_item; 4mod use_item;
5 5
6pub(crate) use self::{ 6pub(crate) use self::{
7 expressions::{match_arm_list, named_field_list}, 7 expressions::{match_arm_list, record_field_list},
8 nominal::{enum_variant_list, named_field_def_list}, 8 nominal::{enum_variant_list, record_field_def_list},
9 traits::{impl_item_list, trait_item_list}, 9 traits::{impl_item_list, trait_item_list},
10 use_item::use_tree_list, 10 use_item::use_tree_list,
11}; 11};
diff --git a/crates/ra_parser/src/grammar/items/nominal.rs b/crates/ra_parser/src/grammar/items/nominal.rs
index bd4edab89..54f02c7c9 100644
--- a/crates/ra_parser/src/grammar/items/nominal.rs
+++ b/crates/ra_parser/src/grammar/items/nominal.rs
@@ -13,7 +13,7 @@ pub(super) fn struct_def(p: &mut Parser, m: Marker, kind: SyntaxKind) {
13 T![;] => { 13 T![;] => {
14 p.bump(); 14 p.bump();
15 } 15 }
16 T!['{'] => named_field_def_list(p), 16 T!['{'] => record_field_def_list(p),
17 _ => { 17 _ => {
18 //FIXME: special case `(` error message 18 //FIXME: special case `(` error message
19 p.error("expected `;` or `{`"); 19 p.error("expected `;` or `{`");
@@ -23,9 +23,9 @@ pub(super) fn struct_def(p: &mut Parser, m: Marker, kind: SyntaxKind) {
23 T![;] if kind == T![struct] => { 23 T![;] if kind == T![struct] => {
24 p.bump(); 24 p.bump();
25 } 25 }
26 T!['{'] => named_field_def_list(p), 26 T!['{'] => record_field_def_list(p),
27 T!['('] if kind == T![struct] => { 27 T!['('] if kind == T![struct] => {
28 pos_field_def_list(p); 28 tuple_field_def_list(p);
29 // test tuple_struct_where 29 // test tuple_struct_where
30 // struct Test<T>(T) where T: Clone; 30 // struct Test<T>(T) where T: Clone;
31 // struct Test<T>(T); 31 // struct Test<T>(T);
@@ -70,8 +70,8 @@ pub(crate) fn enum_variant_list(p: &mut Parser) {
70 if p.at(IDENT) { 70 if p.at(IDENT) {
71 name(p); 71 name(p);
72 match p.current() { 72 match p.current() {
73 T!['{'] => named_field_def_list(p), 73 T!['{'] => record_field_def_list(p),
74 T!['('] => pos_field_def_list(p), 74 T!['('] => tuple_field_def_list(p),
75 T![=] => { 75 T![=] => {
76 p.bump(); 76 p.bump();
77 expressions::expr(p); 77 expressions::expr(p);
@@ -91,7 +91,7 @@ pub(crate) fn enum_variant_list(p: &mut Parser) {
91 m.complete(p, ENUM_VARIANT_LIST); 91 m.complete(p, ENUM_VARIANT_LIST);
92} 92}
93 93
94pub(crate) fn named_field_def_list(p: &mut Parser) { 94pub(crate) fn record_field_def_list(p: &mut Parser) {
95 assert!(p.at(T!['{'])); 95 assert!(p.at(T!['{']));
96 let m = p.start(); 96 let m = p.start();
97 p.bump(); 97 p.bump();
@@ -100,17 +100,17 @@ pub(crate) fn named_field_def_list(p: &mut Parser) {
100 error_block(p, "expected field"); 100 error_block(p, "expected field");
101 continue; 101 continue;
102 } 102 }
103 named_field_def(p); 103 record_field_def(p);
104 if !p.at(T!['}']) { 104 if !p.at(T!['}']) {
105 p.expect(T![,]); 105 p.expect(T![,]);
106 } 106 }
107 } 107 }
108 p.expect(T!['}']); 108 p.expect(T!['}']);
109 m.complete(p, NAMED_FIELD_DEF_LIST); 109 m.complete(p, RECORD_FIELD_DEF_LIST);
110 110
111 fn named_field_def(p: &mut Parser) { 111 fn record_field_def(p: &mut Parser) {
112 let m = p.start(); 112 let m = p.start();
113 // test field_attrs 113 // test record_field_attrs
114 // struct S { 114 // struct S {
115 // #[serde(with = "url_serde")] 115 // #[serde(with = "url_serde")]
116 // pub uri: Uri, 116 // pub uri: Uri,
@@ -121,7 +121,7 @@ pub(crate) fn named_field_def_list(p: &mut Parser) {
121 name(p); 121 name(p);
122 p.expect(T![:]); 122 p.expect(T![:]);
123 types::type_(p); 123 types::type_(p);
124 m.complete(p, NAMED_FIELD_DEF); 124 m.complete(p, RECORD_FIELD_DEF);
125 } else { 125 } else {
126 m.abandon(p); 126 m.abandon(p);
127 p.err_and_bump("expected field declaration"); 127 p.err_and_bump("expected field declaration");
@@ -129,7 +129,7 @@ pub(crate) fn named_field_def_list(p: &mut Parser) {
129 } 129 }
130} 130}
131 131
132fn pos_field_def_list(p: &mut Parser) { 132fn tuple_field_def_list(p: &mut Parser) {
133 assert!(p.at(T!['('])); 133 assert!(p.at(T!['(']));
134 let m = p.start(); 134 let m = p.start();
135 if !p.expect(T!['(']) { 135 if !p.expect(T!['(']) {
@@ -137,7 +137,7 @@ fn pos_field_def_list(p: &mut Parser) {
137 } 137 }
138 while !p.at(T![')']) && !p.at(EOF) { 138 while !p.at(T![')']) && !p.at(EOF) {
139 let m = p.start(); 139 let m = p.start();
140 // test pos_field_attrs 140 // test tuple_field_attrs
141 // struct S ( 141 // struct S (
142 // #[serde(with = "url_serde")] 142 // #[serde(with = "url_serde")]
143 // pub Uri, 143 // pub Uri,
@@ -154,12 +154,12 @@ fn pos_field_def_list(p: &mut Parser) {
154 break; 154 break;
155 } 155 }
156 types::type_(p); 156 types::type_(p);
157 m.complete(p, POS_FIELD_DEF); 157 m.complete(p, TUPLE_FIELD_DEF);
158 158
159 if !p.at(T![')']) { 159 if !p.at(T![')']) {
160 p.expect(T![,]); 160 p.expect(T![,]);
161 } 161 }
162 } 162 }
163 p.expect(T![')']); 163 p.expect(T![')']);
164 m.complete(p, POS_FIELD_DEF_LIST); 164 m.complete(p, TUPLE_FIELD_DEF_LIST);
165} 165}
diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs
index 1f6a6fd48..eae70ab85 100644
--- a/crates/ra_parser/src/grammar/patterns.rs
+++ b/crates/ra_parser/src/grammar/patterns.rs
@@ -56,37 +56,33 @@ const PAT_RECOVERY_SET: TokenSet =
56 token_set![LET_KW, IF_KW, WHILE_KW, LOOP_KW, MATCH_KW, R_PAREN, COMMA]; 56 token_set![LET_KW, IF_KW, WHILE_KW, LOOP_KW, MATCH_KW, R_PAREN, COMMA];
57 57
58fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> { 58fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> {
59 let la0 = p.nth(0); 59 // Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro
60 let la1 = p.nth(1); 60 // (T![x]).
61 if la0 == T![ref] 61 let is_path_or_macro_pat =
62 || la0 == T![mut] 62 |la1| la1 == T![::] || la1 == T!['('] || la1 == T!['{'] || la1 == T![!];
63 || la0 == T![box]
64 || (la0 == IDENT && !(la1 == T![::] || la1 == T!['('] || la1 == T!['{'] || la1 == T![!]))
65 {
66 return Some(bind_pat(p, true));
67 }
68 if paths::is_use_path_start(p) {
69 return Some(path_pat(p));
70 }
71 63
72 if is_literal_pat_start(p) { 64 let m = match p.nth(0) {
73 return Some(literal_pat(p)); 65 T![box] => box_pat(p),
74 } 66 T![ref] | T![mut] | IDENT if !is_path_or_macro_pat(p.nth(1)) => bind_pat(p, true),
67
68 _ if paths::is_use_path_start(p) => path_pat(p),
69 _ if is_literal_pat_start(p) => literal_pat(p),
75 70
76 let m = match la0 {
77 T![_] => placeholder_pat(p), 71 T![_] => placeholder_pat(p),
78 T![&] => ref_pat(p), 72 T![&] => ref_pat(p),
79 T!['('] => tuple_pat(p), 73 T!['('] => tuple_pat(p),
80 T!['['] => slice_pat(p), 74 T!['['] => slice_pat(p),
75
81 _ => { 76 _ => {
82 p.err_recover("expected pattern", recovery_set); 77 p.err_recover("expected pattern", recovery_set);
83 return None; 78 return None;
84 } 79 }
85 }; 80 };
81
86 Some(m) 82 Some(m)
87} 83}
88 84
89fn is_literal_pat_start(p: &mut Parser) -> bool { 85fn is_literal_pat_start(p: &Parser) -> bool {
90 p.at(T![-]) && (p.nth(1) == INT_NUMBER || p.nth(1) == FLOAT_NUMBER) 86 p.at(T![-]) && (p.nth(1) == INT_NUMBER || p.nth(1) == FLOAT_NUMBER)
91 || p.at_ts(expressions::LITERAL_FIRST) 87 || p.at_ts(expressions::LITERAL_FIRST)
92} 88}
@@ -127,8 +123,8 @@ fn path_pat(p: &mut Parser) -> CompletedMarker {
127 TUPLE_STRUCT_PAT 123 TUPLE_STRUCT_PAT
128 } 124 }
129 T!['{'] => { 125 T!['{'] => {
130 field_pat_list(p); 126 record_field_pat_list(p);
131 STRUCT_PAT 127 RECORD_PAT
132 } 128 }
133 _ => PATH_PAT, 129 _ => PATH_PAT,
134 }; 130 };
@@ -149,22 +145,25 @@ fn tuple_pat_fields(p: &mut Parser) {
149 p.expect(T![')']); 145 p.expect(T![')']);
150} 146}
151 147
152// test field_pat_list 148// test record_field_pat_list
153// fn foo() { 149// fn foo() {
154// let S {} = (); 150// let S {} = ();
155// let S { f, ref mut g } = (); 151// let S { f, ref mut g } = ();
156// let S { h: _, ..} = (); 152// let S { h: _, ..} = ();
157// let S { h: _, } = (); 153// let S { h: _, } = ();
158// } 154// }
159fn field_pat_list(p: &mut Parser) { 155fn record_field_pat_list(p: &mut Parser) {
160 assert!(p.at(T!['{'])); 156 assert!(p.at(T!['{']));
161 let m = p.start(); 157 let m = p.start();
162 p.bump(); 158 p.bump();
163 while !p.at(EOF) && !p.at(T!['}']) { 159 while !p.at(EOF) && !p.at(T!['}']) {
164 match p.current() { 160 match p.current() {
165 T![..] => p.bump(), 161 T![..] => p.bump(),
166 IDENT if p.nth(1) == T![:] => field_pat(p), 162 IDENT if p.nth(1) == T![:] => record_field_pat(p),
167 T!['{'] => error_block(p, "expected ident"), 163 T!['{'] => error_block(p, "expected ident"),
164 T![box] => {
165 box_pat(p);
166 }
168 _ => { 167 _ => {
169 bind_pat(p, false); 168 bind_pat(p, false);
170 } 169 }
@@ -174,10 +173,10 @@ fn field_pat_list(p: &mut Parser) {
174 } 173 }
175 } 174 }
176 p.expect(T!['}']); 175 p.expect(T!['}']);
177 m.complete(p, FIELD_PAT_LIST); 176 m.complete(p, RECORD_FIELD_PAT_LIST);
178} 177}
179 178
180fn field_pat(p: &mut Parser) { 179fn record_field_pat(p: &mut Parser) {
181 assert!(p.at(IDENT)); 180 assert!(p.at(IDENT));
182 assert!(p.nth(1) == T![:]); 181 assert!(p.nth(1) == T![:]);
183 182
@@ -185,7 +184,7 @@ fn field_pat(p: &mut Parser) {
185 name(p); 184 name(p);
186 p.bump(); 185 p.bump();
187 pattern(p); 186 pattern(p);
188 m.complete(p, FIELD_PAT); 187 m.complete(p, RECORD_FIELD_PAT);
189} 188}
190 189
191// test placeholder_pat 190// test placeholder_pat
@@ -261,11 +260,9 @@ fn pat_list(p: &mut Parser, ket: SyntaxKind) {
261// let ref mut d = (); 260// let ref mut d = ();
262// let e @ _ = (); 261// let e @ _ = ();
263// let ref mut f @ g @ _ = (); 262// let ref mut f @ g @ _ = ();
264// let box i = Box::new(1i32);
265// } 263// }
266fn bind_pat(p: &mut Parser, with_at: bool) -> CompletedMarker { 264fn bind_pat(p: &mut Parser, with_at: bool) -> CompletedMarker {
267 let m = p.start(); 265 let m = p.start();
268 p.eat(T![box]);
269 p.eat(T![ref]); 266 p.eat(T![ref]);
270 p.eat(T![mut]); 267 p.eat(T![mut]);
271 name(p); 268 name(p);
@@ -274,3 +271,17 @@ fn bind_pat(p: &mut Parser, with_at: bool) -> CompletedMarker {
274 } 271 }
275 m.complete(p, BIND_PAT) 272 m.complete(p, BIND_PAT)
276} 273}
274
275// test box_pat
276// fn main() {
277// let box i = ();
278// let box Outer { box i, j: box Inner(box &x) } = ();
279// let box ref mut i = ();
280// }
281fn box_pat(p: &mut Parser) -> CompletedMarker {
282 assert!(p.at(T![box]));
283 let m = p.start();
284 p.bump();
285 pattern(p);
286 m.complete(p, BOX_PAT)
287}
diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs
index 3a67d7ddd..8ba29ebf8 100644
--- a/crates/ra_parser/src/syntax_kind/generated.rs
+++ b/crates/ra_parser/src/syntax_kind/generated.rs
@@ -149,12 +149,13 @@ pub enum SyntaxKind {
149 IMPL_TRAIT_TYPE, 149 IMPL_TRAIT_TYPE,
150 DYN_TRAIT_TYPE, 150 DYN_TRAIT_TYPE,
151 REF_PAT, 151 REF_PAT,
152 BOX_PAT,
152 BIND_PAT, 153 BIND_PAT,
153 PLACEHOLDER_PAT, 154 PLACEHOLDER_PAT,
154 PATH_PAT, 155 PATH_PAT,
155 STRUCT_PAT, 156 RECORD_PAT,
156 FIELD_PAT_LIST, 157 RECORD_FIELD_PAT_LIST,
157 FIELD_PAT, 158 RECORD_FIELD_PAT,
158 TUPLE_STRUCT_PAT, 159 TUPLE_STRUCT_PAT,
159 TUPLE_PAT, 160 TUPLE_PAT,
160 SLICE_PAT, 161 SLICE_PAT,
@@ -179,9 +180,9 @@ pub enum SyntaxKind {
179 MATCH_ARM_LIST, 180 MATCH_ARM_LIST,
180 MATCH_ARM, 181 MATCH_ARM,
181 MATCH_GUARD, 182 MATCH_GUARD,
182 STRUCT_LIT, 183 RECORD_LIT,
183 NAMED_FIELD_LIST, 184 RECORD_FIELD_LIST,
184 NAMED_FIELD, 185 RECORD_FIELD,
185 TRY_BLOCK_EXPR, 186 TRY_BLOCK_EXPR,
186 BOX_EXPR, 187 BOX_EXPR,
187 CALL_EXPR, 188 CALL_EXPR,
@@ -199,10 +200,10 @@ pub enum SyntaxKind {
199 EXTERN_BLOCK, 200 EXTERN_BLOCK,
200 EXTERN_ITEM_LIST, 201 EXTERN_ITEM_LIST,
201 ENUM_VARIANT, 202 ENUM_VARIANT,
202 NAMED_FIELD_DEF_LIST, 203 RECORD_FIELD_DEF_LIST,
203 NAMED_FIELD_DEF, 204 RECORD_FIELD_DEF,
204 POS_FIELD_DEF_LIST, 205 TUPLE_FIELD_DEF_LIST,
205 POS_FIELD_DEF, 206 TUPLE_FIELD_DEF,
206 ENUM_VARIANT_LIST, 207 ENUM_VARIANT_LIST,
207 ITEM_LIST, 208 ITEM_LIST,
208 ATTR, 209 ATTR,
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index afdfca66e..a2f862869 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -25,15 +25,23 @@ pub use self::{
25/// conversion itself has zero runtime cost: ast and syntax nodes have exactly 25/// conversion itself has zero runtime cost: ast and syntax nodes have exactly
26/// the same representation: a pointer to the tree root and a pointer to the 26/// the same representation: a pointer to the tree root and a pointer to the
27/// node itself. 27/// node itself.
28pub trait AstNode: Clone { 28pub trait AstNode {
29 fn can_cast(kind: SyntaxKind) -> bool; 29 fn can_cast(kind: SyntaxKind) -> bool
30 where
31 Self: Sized;
30 32
31 fn cast(syntax: SyntaxNode) -> Option<Self> 33 fn cast(syntax: SyntaxNode) -> Option<Self>
32 where 34 where
33 Self: Sized; 35 Self: Sized;
36
34 fn syntax(&self) -> &SyntaxNode; 37 fn syntax(&self) -> &SyntaxNode;
35} 38}
36 39
40#[test]
41fn assert_ast_is_object_safe() {
42 fn _f(_: &dyn AstNode, _: &dyn NameOwner) {}
43}
44
37/// Like `AstNode`, but wraps tokens rather than interior nodes. 45/// Like `AstNode`, but wraps tokens rather than interior nodes.
38pub trait AstToken { 46pub trait AstToken {
39 fn cast(token: SyntaxToken) -> Option<Self> 47 fn cast(token: SyntaxToken) -> Option<Self>
diff --git a/crates/ra_syntax/src/ast/expr_extensions.rs b/crates/ra_syntax/src/ast/expr_extensions.rs
index cf5b6f251..d7ea4354d 100644
--- a/crates/ra_syntax/src/ast/expr_extensions.rs
+++ b/crates/ra_syntax/src/ast/expr_extensions.rs
@@ -296,8 +296,8 @@ fn test_literal_with_attr() {
296 assert_eq!(lit.token().text(), r#""Hello""#); 296 assert_eq!(lit.token().text(), r#""Hello""#);
297} 297}
298 298
299impl ast::NamedField { 299impl ast::RecordField {
300 pub fn parent_struct_lit(&self) -> ast::StructLit { 300 pub fn parent_record_lit(&self) -> ast::RecordLit {
301 self.syntax().ancestors().find_map(ast::StructLit::cast).unwrap() 301 self.syntax().ancestors().find_map(ast::RecordLit::cast).unwrap()
302 } 302 }
303} 303}
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs
index e0ea3e5ab..d3a375f87 100644
--- a/crates/ra_syntax/src/ast/extensions.rs
+++ b/crates/ra_syntax/src/ast/extensions.rs
@@ -195,16 +195,16 @@ impl ast::ImplBlock {
195 195
196#[derive(Debug, Clone, PartialEq, Eq)] 196#[derive(Debug, Clone, PartialEq, Eq)]
197pub enum StructKind { 197pub enum StructKind {
198 Tuple(ast::PosFieldDefList), 198 Tuple(ast::TupleFieldDefList),
199 Named(ast::NamedFieldDefList), 199 Named(ast::RecordFieldDefList),
200 Unit, 200 Unit,
201} 201}
202 202
203impl StructKind { 203impl StructKind {
204 fn from_node<N: AstNode>(node: &N) -> StructKind { 204 fn from_node<N: AstNode>(node: &N) -> StructKind {
205 if let Some(nfdl) = child_opt::<_, ast::NamedFieldDefList>(node) { 205 if let Some(nfdl) = child_opt::<_, ast::RecordFieldDefList>(node) {
206 StructKind::Named(nfdl) 206 StructKind::Named(nfdl)
207 } else if let Some(pfl) = child_opt::<_, ast::PosFieldDefList>(node) { 207 } else if let Some(pfl) = child_opt::<_, ast::TupleFieldDefList>(node) {
208 StructKind::Tuple(pfl) 208 StructKind::Tuple(pfl)
209 } else { 209 } else {
210 StructKind::Unit 210 StructKind::Unit
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index 9c5789701..90480b6ca 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -307,6 +307,33 @@ impl BlockExpr {
307 } 307 }
308} 308}
309#[derive(Debug, Clone, PartialEq, Eq, Hash)] 309#[derive(Debug, Clone, PartialEq, Eq, Hash)]
310pub struct BoxPat {
311 pub(crate) syntax: SyntaxNode,
312}
313impl AstNode for BoxPat {
314 fn can_cast(kind: SyntaxKind) -> bool {
315 match kind {
316 BOX_PAT => true,
317 _ => false,
318 }
319 }
320 fn cast(syntax: SyntaxNode) -> Option<Self> {
321 if Self::can_cast(syntax.kind()) {
322 Some(Self { syntax })
323 } else {
324 None
325 }
326 }
327 fn syntax(&self) -> &SyntaxNode {
328 &self.syntax
329 }
330}
331impl BoxPat {
332 pub fn pat(&self) -> Option<Pat> {
333 AstChildren::new(&self.syntax).next()
334 }
335}
336#[derive(Debug, Clone, PartialEq, Eq, Hash)]
310pub struct BreakExpr { 337pub struct BreakExpr {
311 pub(crate) syntax: SyntaxNode, 338 pub(crate) syntax: SyntaxNode,
312} 339}
@@ -607,7 +634,7 @@ pub enum Expr {
607 BlockExpr(BlockExpr), 634 BlockExpr(BlockExpr),
608 ReturnExpr(ReturnExpr), 635 ReturnExpr(ReturnExpr),
609 MatchExpr(MatchExpr), 636 MatchExpr(MatchExpr),
610 StructLit(StructLit), 637 RecordLit(RecordLit),
611 CallExpr(CallExpr), 638 CallExpr(CallExpr),
612 IndexExpr(IndexExpr), 639 IndexExpr(IndexExpr),
613 MethodCallExpr(MethodCallExpr), 640 MethodCallExpr(MethodCallExpr),
@@ -698,9 +725,9 @@ impl From<MatchExpr> for Expr {
698 Expr::MatchExpr(node) 725 Expr::MatchExpr(node)
699 } 726 }
700} 727}
701impl From<StructLit> for Expr { 728impl From<RecordLit> for Expr {
702 fn from(node: StructLit) -> Expr { 729 fn from(node: RecordLit) -> Expr {
703 Expr::StructLit(node) 730 Expr::RecordLit(node)
704 } 731 }
705} 732}
706impl From<CallExpr> for Expr { 733impl From<CallExpr> for Expr {
@@ -778,7 +805,7 @@ impl AstNode for Expr {
778 match kind { 805 match kind {
779 TUPLE_EXPR | ARRAY_EXPR | PAREN_EXPR | PATH_EXPR | LAMBDA_EXPR | IF_EXPR 806 TUPLE_EXPR | ARRAY_EXPR | PAREN_EXPR | PATH_EXPR | LAMBDA_EXPR | IF_EXPR
780 | LOOP_EXPR | FOR_EXPR | WHILE_EXPR | CONTINUE_EXPR | BREAK_EXPR | LABEL 807 | LOOP_EXPR | FOR_EXPR | WHILE_EXPR | CONTINUE_EXPR | BREAK_EXPR | LABEL
781 | BLOCK_EXPR | RETURN_EXPR | MATCH_EXPR | STRUCT_LIT | CALL_EXPR | INDEX_EXPR 808 | BLOCK_EXPR | RETURN_EXPR | MATCH_EXPR | RECORD_LIT | CALL_EXPR | INDEX_EXPR
782 | METHOD_CALL_EXPR | FIELD_EXPR | AWAIT_EXPR | TRY_EXPR | TRY_BLOCK_EXPR 809 | METHOD_CALL_EXPR | FIELD_EXPR | AWAIT_EXPR | TRY_EXPR | TRY_BLOCK_EXPR
783 | CAST_EXPR | REF_EXPR | PREFIX_EXPR | RANGE_EXPR | BIN_EXPR | LITERAL | MACRO_CALL => { 810 | CAST_EXPR | REF_EXPR | PREFIX_EXPR | RANGE_EXPR | BIN_EXPR | LITERAL | MACRO_CALL => {
784 true 811 true
@@ -803,7 +830,7 @@ impl AstNode for Expr {
803 BLOCK_EXPR => Expr::BlockExpr(BlockExpr { syntax }), 830 BLOCK_EXPR => Expr::BlockExpr(BlockExpr { syntax }),
804 RETURN_EXPR => Expr::ReturnExpr(ReturnExpr { syntax }), 831 RETURN_EXPR => Expr::ReturnExpr(ReturnExpr { syntax }),
805 MATCH_EXPR => Expr::MatchExpr(MatchExpr { syntax }), 832 MATCH_EXPR => Expr::MatchExpr(MatchExpr { syntax }),
806 STRUCT_LIT => Expr::StructLit(StructLit { syntax }), 833 RECORD_LIT => Expr::RecordLit(RecordLit { syntax }),
807 CALL_EXPR => Expr::CallExpr(CallExpr { syntax }), 834 CALL_EXPR => Expr::CallExpr(CallExpr { syntax }),
808 INDEX_EXPR => Expr::IndexExpr(IndexExpr { syntax }), 835 INDEX_EXPR => Expr::IndexExpr(IndexExpr { syntax }),
809 METHOD_CALL_EXPR => Expr::MethodCallExpr(MethodCallExpr { syntax }), 836 METHOD_CALL_EXPR => Expr::MethodCallExpr(MethodCallExpr { syntax }),
@@ -839,7 +866,7 @@ impl AstNode for Expr {
839 Expr::BlockExpr(it) => &it.syntax, 866 Expr::BlockExpr(it) => &it.syntax,
840 Expr::ReturnExpr(it) => &it.syntax, 867 Expr::ReturnExpr(it) => &it.syntax,
841 Expr::MatchExpr(it) => &it.syntax, 868 Expr::MatchExpr(it) => &it.syntax,
842 Expr::StructLit(it) => &it.syntax, 869 Expr::RecordLit(it) => &it.syntax,
843 Expr::CallExpr(it) => &it.syntax, 870 Expr::CallExpr(it) => &it.syntax,
844 Expr::IndexExpr(it) => &it.syntax, 871 Expr::IndexExpr(it) => &it.syntax,
845 Expr::MethodCallExpr(it) => &it.syntax, 872 Expr::MethodCallExpr(it) => &it.syntax,
@@ -946,64 +973,6 @@ impl FieldExpr {
946 } 973 }
947} 974}
948#[derive(Debug, Clone, PartialEq, Eq, Hash)] 975#[derive(Debug, Clone, PartialEq, Eq, Hash)]
949pub struct FieldPat {
950 pub(crate) syntax: SyntaxNode,
951}
952impl AstNode for FieldPat {
953 fn can_cast(kind: SyntaxKind) -> bool {
954 match kind {
955 FIELD_PAT => true,
956 _ => false,
957 }
958 }
959 fn cast(syntax: SyntaxNode) -> Option<Self> {
960 if Self::can_cast(syntax.kind()) {
961 Some(Self { syntax })
962 } else {
963 None
964 }
965 }
966 fn syntax(&self) -> &SyntaxNode {
967 &self.syntax
968 }
969}
970impl ast::NameOwner for FieldPat {}
971impl FieldPat {
972 pub fn pat(&self) -> Option<Pat> {
973 AstChildren::new(&self.syntax).next()
974 }
975}
976#[derive(Debug, Clone, PartialEq, Eq, Hash)]
977pub struct FieldPatList {
978 pub(crate) syntax: SyntaxNode,
979}
980impl AstNode for FieldPatList {
981 fn can_cast(kind: SyntaxKind) -> bool {
982 match kind {
983 FIELD_PAT_LIST => true,
984 _ => false,
985 }
986 }
987 fn cast(syntax: SyntaxNode) -> Option<Self> {
988 if Self::can_cast(syntax.kind()) {
989 Some(Self { syntax })
990 } else {
991 None
992 }
993 }
994 fn syntax(&self) -> &SyntaxNode {
995 &self.syntax
996 }
997}
998impl FieldPatList {
999 pub fn field_pats(&self) -> AstChildren<FieldPat> {
1000 AstChildren::new(&self.syntax)
1001 }
1002 pub fn bind_pats(&self) -> AstChildren<BindPat> {
1003 AstChildren::new(&self.syntax)
1004 }
1005}
1006#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1007pub struct FnDef { 976pub struct FnDef {
1008 pub(crate) syntax: SyntaxNode, 977 pub(crate) syntax: SyntaxNode,
1009} 978}
@@ -1942,121 +1911,6 @@ impl AstNode for NameRef {
1942} 1911}
1943impl NameRef {} 1912impl NameRef {}
1944#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1913#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1945pub struct NamedField {
1946 pub(crate) syntax: SyntaxNode,
1947}
1948impl AstNode for NamedField {
1949 fn can_cast(kind: SyntaxKind) -> bool {
1950 match kind {
1951 NAMED_FIELD => true,
1952 _ => false,
1953 }
1954 }
1955 fn cast(syntax: SyntaxNode) -> Option<Self> {
1956 if Self::can_cast(syntax.kind()) {
1957 Some(Self { syntax })
1958 } else {
1959 None
1960 }
1961 }
1962 fn syntax(&self) -> &SyntaxNode {
1963 &self.syntax
1964 }
1965}
1966impl NamedField {
1967 pub fn name_ref(&self) -> Option<NameRef> {
1968 AstChildren::new(&self.syntax).next()
1969 }
1970 pub fn expr(&self) -> Option<Expr> {
1971 AstChildren::new(&self.syntax).next()
1972 }
1973}
1974#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1975pub struct NamedFieldDef {
1976 pub(crate) syntax: SyntaxNode,
1977}
1978impl AstNode for NamedFieldDef {
1979 fn can_cast(kind: SyntaxKind) -> bool {
1980 match kind {
1981 NAMED_FIELD_DEF => true,
1982 _ => false,
1983 }
1984 }
1985 fn cast(syntax: SyntaxNode) -> Option<Self> {
1986 if Self::can_cast(syntax.kind()) {
1987 Some(Self { syntax })
1988 } else {
1989 None
1990 }
1991 }
1992 fn syntax(&self) -> &SyntaxNode {
1993 &self.syntax
1994 }
1995}
1996impl ast::VisibilityOwner for NamedFieldDef {}
1997impl ast::NameOwner for NamedFieldDef {}
1998impl ast::AttrsOwner for NamedFieldDef {}
1999impl ast::DocCommentsOwner for NamedFieldDef {}
2000impl ast::TypeAscriptionOwner for NamedFieldDef {}
2001impl NamedFieldDef {}
2002#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2003pub struct NamedFieldDefList {
2004 pub(crate) syntax: SyntaxNode,
2005}
2006impl AstNode for NamedFieldDefList {
2007 fn can_cast(kind: SyntaxKind) -> bool {
2008 match kind {
2009 NAMED_FIELD_DEF_LIST => true,
2010 _ => false,
2011 }
2012 }
2013 fn cast(syntax: SyntaxNode) -> Option<Self> {
2014 if Self::can_cast(syntax.kind()) {
2015 Some(Self { syntax })
2016 } else {
2017 None
2018 }
2019 }
2020 fn syntax(&self) -> &SyntaxNode {
2021 &self.syntax
2022 }
2023}
2024impl NamedFieldDefList {
2025 pub fn fields(&self) -> AstChildren<NamedFieldDef> {
2026 AstChildren::new(&self.syntax)
2027 }
2028}
2029#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2030pub struct NamedFieldList {
2031 pub(crate) syntax: SyntaxNode,
2032}
2033impl AstNode for NamedFieldList {
2034 fn can_cast(kind: SyntaxKind) -> bool {
2035 match kind {
2036 NAMED_FIELD_LIST => true,
2037 _ => false,
2038 }
2039 }
2040 fn cast(syntax: SyntaxNode) -> Option<Self> {
2041 if Self::can_cast(syntax.kind()) {
2042 Some(Self { syntax })
2043 } else {
2044 None
2045 }
2046 }
2047 fn syntax(&self) -> &SyntaxNode {
2048 &self.syntax
2049 }
2050}
2051impl NamedFieldList {
2052 pub fn fields(&self) -> AstChildren<NamedField> {
2053 AstChildren::new(&self.syntax)
2054 }
2055 pub fn spread(&self) -> Option<Expr> {
2056 AstChildren::new(&self.syntax).next()
2057 }
2058}
2059#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2060pub struct NeverType { 1914pub struct NeverType {
2061 pub(crate) syntax: SyntaxNode, 1915 pub(crate) syntax: SyntaxNode,
2062} 1916}
@@ -2236,10 +2090,11 @@ impl ParenType {
2236#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2090#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2237pub enum Pat { 2091pub enum Pat {
2238 RefPat(RefPat), 2092 RefPat(RefPat),
2093 BoxPat(BoxPat),
2239 BindPat(BindPat), 2094 BindPat(BindPat),
2240 PlaceholderPat(PlaceholderPat), 2095 PlaceholderPat(PlaceholderPat),
2241 PathPat(PathPat), 2096 PathPat(PathPat),
2242 StructPat(StructPat), 2097 RecordPat(RecordPat),
2243 TupleStructPat(TupleStructPat), 2098 TupleStructPat(TupleStructPat),
2244 TuplePat(TuplePat), 2099 TuplePat(TuplePat),
2245 SlicePat(SlicePat), 2100 SlicePat(SlicePat),
@@ -2251,6 +2106,11 @@ impl From<RefPat> for Pat {
2251 Pat::RefPat(node) 2106 Pat::RefPat(node)
2252 } 2107 }
2253} 2108}
2109impl From<BoxPat> for Pat {
2110 fn from(node: BoxPat) -> Pat {
2111 Pat::BoxPat(node)
2112 }
2113}
2254impl From<BindPat> for Pat { 2114impl From<BindPat> for Pat {
2255 fn from(node: BindPat) -> Pat { 2115 fn from(node: BindPat) -> Pat {
2256 Pat::BindPat(node) 2116 Pat::BindPat(node)
@@ -2266,9 +2126,9 @@ impl From<PathPat> for Pat {
2266 Pat::PathPat(node) 2126 Pat::PathPat(node)
2267 } 2127 }
2268} 2128}
2269impl From<StructPat> for Pat { 2129impl From<RecordPat> for Pat {
2270 fn from(node: StructPat) -> Pat { 2130 fn from(node: RecordPat) -> Pat {
2271 Pat::StructPat(node) 2131 Pat::RecordPat(node)
2272 } 2132 }
2273} 2133}
2274impl From<TupleStructPat> for Pat { 2134impl From<TupleStructPat> for Pat {
@@ -2299,18 +2159,19 @@ impl From<LiteralPat> for Pat {
2299impl AstNode for Pat { 2159impl AstNode for Pat {
2300 fn can_cast(kind: SyntaxKind) -> bool { 2160 fn can_cast(kind: SyntaxKind) -> bool {
2301 match kind { 2161 match kind {
2302 REF_PAT | BIND_PAT | PLACEHOLDER_PAT | PATH_PAT | STRUCT_PAT | TUPLE_STRUCT_PAT 2162 REF_PAT | BOX_PAT | BIND_PAT | PLACEHOLDER_PAT | PATH_PAT | RECORD_PAT
2303 | TUPLE_PAT | SLICE_PAT | RANGE_PAT | LITERAL_PAT => true, 2163 | TUPLE_STRUCT_PAT | TUPLE_PAT | SLICE_PAT | RANGE_PAT | LITERAL_PAT => true,
2304 _ => false, 2164 _ => false,
2305 } 2165 }
2306 } 2166 }
2307 fn cast(syntax: SyntaxNode) -> Option<Self> { 2167 fn cast(syntax: SyntaxNode) -> Option<Self> {
2308 let res = match syntax.kind() { 2168 let res = match syntax.kind() {
2309 REF_PAT => Pat::RefPat(RefPat { syntax }), 2169 REF_PAT => Pat::RefPat(RefPat { syntax }),
2170 BOX_PAT => Pat::BoxPat(BoxPat { syntax }),
2310 BIND_PAT => Pat::BindPat(BindPat { syntax }), 2171 BIND_PAT => Pat::BindPat(BindPat { syntax }),
2311 PLACEHOLDER_PAT => Pat::PlaceholderPat(PlaceholderPat { syntax }), 2172 PLACEHOLDER_PAT => Pat::PlaceholderPat(PlaceholderPat { syntax }),
2312 PATH_PAT => Pat::PathPat(PathPat { syntax }), 2173 PATH_PAT => Pat::PathPat(PathPat { syntax }),
2313 STRUCT_PAT => Pat::StructPat(StructPat { syntax }), 2174 RECORD_PAT => Pat::RecordPat(RecordPat { syntax }),
2314 TUPLE_STRUCT_PAT => Pat::TupleStructPat(TupleStructPat { syntax }), 2175 TUPLE_STRUCT_PAT => Pat::TupleStructPat(TupleStructPat { syntax }),
2315 TUPLE_PAT => Pat::TuplePat(TuplePat { syntax }), 2176 TUPLE_PAT => Pat::TuplePat(TuplePat { syntax }),
2316 SLICE_PAT => Pat::SlicePat(SlicePat { syntax }), 2177 SLICE_PAT => Pat::SlicePat(SlicePat { syntax }),
@@ -2323,10 +2184,11 @@ impl AstNode for Pat {
2323 fn syntax(&self) -> &SyntaxNode { 2184 fn syntax(&self) -> &SyntaxNode {
2324 match self { 2185 match self {
2325 Pat::RefPat(it) => &it.syntax, 2186 Pat::RefPat(it) => &it.syntax,
2187 Pat::BoxPat(it) => &it.syntax,
2326 Pat::BindPat(it) => &it.syntax, 2188 Pat::BindPat(it) => &it.syntax,
2327 Pat::PlaceholderPat(it) => &it.syntax, 2189 Pat::PlaceholderPat(it) => &it.syntax,
2328 Pat::PathPat(it) => &it.syntax, 2190 Pat::PathPat(it) => &it.syntax,
2329 Pat::StructPat(it) => &it.syntax, 2191 Pat::RecordPat(it) => &it.syntax,
2330 Pat::TupleStructPat(it) => &it.syntax, 2192 Pat::TupleStructPat(it) => &it.syntax,
2331 Pat::TuplePat(it) => &it.syntax, 2193 Pat::TuplePat(it) => &it.syntax,
2332 Pat::SlicePat(it) => &it.syntax, 2194 Pat::SlicePat(it) => &it.syntax,
@@ -2551,13 +2413,13 @@ impl PointerType {
2551 } 2413 }
2552} 2414}
2553#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2415#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2554pub struct PosFieldDef { 2416pub struct PrefixExpr {
2555 pub(crate) syntax: SyntaxNode, 2417 pub(crate) syntax: SyntaxNode,
2556} 2418}
2557impl AstNode for PosFieldDef { 2419impl AstNode for PrefixExpr {
2558 fn can_cast(kind: SyntaxKind) -> bool { 2420 fn can_cast(kind: SyntaxKind) -> bool {
2559 match kind { 2421 match kind {
2560 POS_FIELD_DEF => true, 2422 PREFIX_EXPR => true,
2561 _ => false, 2423 _ => false,
2562 } 2424 }
2563 } 2425 }
@@ -2572,21 +2434,19 @@ impl AstNode for PosFieldDef {
2572 &self.syntax 2434 &self.syntax
2573 } 2435 }
2574} 2436}
2575impl ast::VisibilityOwner for PosFieldDef {} 2437impl PrefixExpr {
2576impl ast::AttrsOwner for PosFieldDef {} 2438 pub fn expr(&self) -> Option<Expr> {
2577impl PosFieldDef {
2578 pub fn type_ref(&self) -> Option<TypeRef> {
2579 AstChildren::new(&self.syntax).next() 2439 AstChildren::new(&self.syntax).next()
2580 } 2440 }
2581} 2441}
2582#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2442#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2583pub struct PosFieldDefList { 2443pub struct RangeExpr {
2584 pub(crate) syntax: SyntaxNode, 2444 pub(crate) syntax: SyntaxNode,
2585} 2445}
2586impl AstNode for PosFieldDefList { 2446impl AstNode for RangeExpr {
2587 fn can_cast(kind: SyntaxKind) -> bool { 2447 fn can_cast(kind: SyntaxKind) -> bool {
2588 match kind { 2448 match kind {
2589 POS_FIELD_DEF_LIST => true, 2449 RANGE_EXPR => true,
2590 _ => false, 2450 _ => false,
2591 } 2451 }
2592 } 2452 }
@@ -2601,19 +2461,38 @@ impl AstNode for PosFieldDefList {
2601 &self.syntax 2461 &self.syntax
2602 } 2462 }
2603} 2463}
2604impl PosFieldDefList { 2464impl RangeExpr {}
2605 pub fn fields(&self) -> AstChildren<PosFieldDef> { 2465#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2606 AstChildren::new(&self.syntax) 2466pub struct RangePat {
2467 pub(crate) syntax: SyntaxNode,
2468}
2469impl AstNode for RangePat {
2470 fn can_cast(kind: SyntaxKind) -> bool {
2471 match kind {
2472 RANGE_PAT => true,
2473 _ => false,
2474 }
2475 }
2476 fn cast(syntax: SyntaxNode) -> Option<Self> {
2477 if Self::can_cast(syntax.kind()) {
2478 Some(Self { syntax })
2479 } else {
2480 None
2481 }
2482 }
2483 fn syntax(&self) -> &SyntaxNode {
2484 &self.syntax
2607 } 2485 }
2608} 2486}
2487impl RangePat {}
2609#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2488#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2610pub struct PrefixExpr { 2489pub struct RecordField {
2611 pub(crate) syntax: SyntaxNode, 2490 pub(crate) syntax: SyntaxNode,
2612} 2491}
2613impl AstNode for PrefixExpr { 2492impl AstNode for RecordField {
2614 fn can_cast(kind: SyntaxKind) -> bool { 2493 fn can_cast(kind: SyntaxKind) -> bool {
2615 match kind { 2494 match kind {
2616 PREFIX_EXPR => true, 2495 RECORD_FIELD => true,
2617 _ => false, 2496 _ => false,
2618 } 2497 }
2619 } 2498 }
@@ -2628,19 +2507,22 @@ impl AstNode for PrefixExpr {
2628 &self.syntax 2507 &self.syntax
2629 } 2508 }
2630} 2509}
2631impl PrefixExpr { 2510impl RecordField {
2511 pub fn name_ref(&self) -> Option<NameRef> {
2512 AstChildren::new(&self.syntax).next()
2513 }
2632 pub fn expr(&self) -> Option<Expr> { 2514 pub fn expr(&self) -> Option<Expr> {
2633 AstChildren::new(&self.syntax).next() 2515 AstChildren::new(&self.syntax).next()
2634 } 2516 }
2635} 2517}
2636#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2518#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2637pub struct RangeExpr { 2519pub struct RecordFieldDef {
2638 pub(crate) syntax: SyntaxNode, 2520 pub(crate) syntax: SyntaxNode,
2639} 2521}
2640impl AstNode for RangeExpr { 2522impl AstNode for RecordFieldDef {
2641 fn can_cast(kind: SyntaxKind) -> bool { 2523 fn can_cast(kind: SyntaxKind) -> bool {
2642 match kind { 2524 match kind {
2643 RANGE_EXPR => true, 2525 RECORD_FIELD_DEF => true,
2644 _ => false, 2526 _ => false,
2645 } 2527 }
2646 } 2528 }
@@ -2655,15 +2537,20 @@ impl AstNode for RangeExpr {
2655 &self.syntax 2537 &self.syntax
2656 } 2538 }
2657} 2539}
2658impl RangeExpr {} 2540impl ast::VisibilityOwner for RecordFieldDef {}
2541impl ast::NameOwner for RecordFieldDef {}
2542impl ast::AttrsOwner for RecordFieldDef {}
2543impl ast::DocCommentsOwner for RecordFieldDef {}
2544impl ast::TypeAscriptionOwner for RecordFieldDef {}
2545impl RecordFieldDef {}
2659#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2546#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2660pub struct RangePat { 2547pub struct RecordFieldDefList {
2661 pub(crate) syntax: SyntaxNode, 2548 pub(crate) syntax: SyntaxNode,
2662} 2549}
2663impl AstNode for RangePat { 2550impl AstNode for RecordFieldDefList {
2664 fn can_cast(kind: SyntaxKind) -> bool { 2551 fn can_cast(kind: SyntaxKind) -> bool {
2665 match kind { 2552 match kind {
2666 RANGE_PAT => true, 2553 RECORD_FIELD_DEF_LIST => true,
2667 _ => false, 2554 _ => false,
2668 } 2555 }
2669 } 2556 }
@@ -2678,7 +2565,159 @@ impl AstNode for RangePat {
2678 &self.syntax 2565 &self.syntax
2679 } 2566 }
2680} 2567}
2681impl RangePat {} 2568impl RecordFieldDefList {
2569 pub fn fields(&self) -> AstChildren<RecordFieldDef> {
2570 AstChildren::new(&self.syntax)
2571 }
2572}
2573#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2574pub struct RecordFieldList {
2575 pub(crate) syntax: SyntaxNode,
2576}
2577impl AstNode for RecordFieldList {
2578 fn can_cast(kind: SyntaxKind) -> bool {
2579 match kind {
2580 RECORD_FIELD_LIST => true,
2581 _ => false,
2582 }
2583 }
2584 fn cast(syntax: SyntaxNode) -> Option<Self> {
2585 if Self::can_cast(syntax.kind()) {
2586 Some(Self { syntax })
2587 } else {
2588 None
2589 }
2590 }
2591 fn syntax(&self) -> &SyntaxNode {
2592 &self.syntax
2593 }
2594}
2595impl RecordFieldList {
2596 pub fn fields(&self) -> AstChildren<RecordField> {
2597 AstChildren::new(&self.syntax)
2598 }
2599 pub fn spread(&self) -> Option<Expr> {
2600 AstChildren::new(&self.syntax).next()
2601 }
2602}
2603#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2604pub struct RecordFieldPat {
2605 pub(crate) syntax: SyntaxNode,
2606}
2607impl AstNode for RecordFieldPat {
2608 fn can_cast(kind: SyntaxKind) -> bool {
2609 match kind {
2610 RECORD_FIELD_PAT => true,
2611 _ => false,
2612 }
2613 }
2614 fn cast(syntax: SyntaxNode) -> Option<Self> {
2615 if Self::can_cast(syntax.kind()) {
2616 Some(Self { syntax })
2617 } else {
2618 None
2619 }
2620 }
2621 fn syntax(&self) -> &SyntaxNode {
2622 &self.syntax
2623 }
2624}
2625impl ast::NameOwner for RecordFieldPat {}
2626impl RecordFieldPat {
2627 pub fn pat(&self) -> Option<Pat> {
2628 AstChildren::new(&self.syntax).next()
2629 }
2630}
2631#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2632pub struct RecordFieldPatList {
2633 pub(crate) syntax: SyntaxNode,
2634}
2635impl AstNode for RecordFieldPatList {
2636 fn can_cast(kind: SyntaxKind) -> bool {
2637 match kind {
2638 RECORD_FIELD_PAT_LIST => true,
2639 _ => false,
2640 }
2641 }
2642 fn cast(syntax: SyntaxNode) -> Option<Self> {
2643 if Self::can_cast(syntax.kind()) {
2644 Some(Self { syntax })
2645 } else {
2646 None
2647 }
2648 }
2649 fn syntax(&self) -> &SyntaxNode {
2650 &self.syntax
2651 }
2652}
2653impl RecordFieldPatList {
2654 pub fn record_field_pats(&self) -> AstChildren<RecordFieldPat> {
2655 AstChildren::new(&self.syntax)
2656 }
2657 pub fn bind_pats(&self) -> AstChildren<BindPat> {
2658 AstChildren::new(&self.syntax)
2659 }
2660}
2661#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2662pub struct RecordLit {
2663 pub(crate) syntax: SyntaxNode,
2664}
2665impl AstNode for RecordLit {
2666 fn can_cast(kind: SyntaxKind) -> bool {
2667 match kind {
2668 RECORD_LIT => true,
2669 _ => false,
2670 }
2671 }
2672 fn cast(syntax: SyntaxNode) -> Option<Self> {
2673 if Self::can_cast(syntax.kind()) {
2674 Some(Self { syntax })
2675 } else {
2676 None
2677 }
2678 }
2679 fn syntax(&self) -> &SyntaxNode {
2680 &self.syntax
2681 }
2682}
2683impl RecordLit {
2684 pub fn path(&self) -> Option<Path> {
2685 AstChildren::new(&self.syntax).next()
2686 }
2687 pub fn record_field_list(&self) -> Option<RecordFieldList> {
2688 AstChildren::new(&self.syntax).next()
2689 }
2690}
2691#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2692pub struct RecordPat {
2693 pub(crate) syntax: SyntaxNode,
2694}
2695impl AstNode for RecordPat {
2696 fn can_cast(kind: SyntaxKind) -> bool {
2697 match kind {
2698 RECORD_PAT => true,
2699 _ => false,
2700 }
2701 }
2702 fn cast(syntax: SyntaxNode) -> Option<Self> {
2703 if Self::can_cast(syntax.kind()) {
2704 Some(Self { syntax })
2705 } else {
2706 None
2707 }
2708 }
2709 fn syntax(&self) -> &SyntaxNode {
2710 &self.syntax
2711 }
2712}
2713impl RecordPat {
2714 pub fn record_field_pat_list(&self) -> Option<RecordFieldPatList> {
2715 AstChildren::new(&self.syntax).next()
2716 }
2717 pub fn path(&self) -> Option<Path> {
2718 AstChildren::new(&self.syntax).next()
2719 }
2720}
2682#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2721#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2683pub struct RefExpr { 2722pub struct RefExpr {
2684 pub(crate) syntax: SyntaxNode, 2723 pub(crate) syntax: SyntaxNode,
@@ -3018,13 +3057,13 @@ impl ast::AttrsOwner for StructDef {}
3018impl ast::DocCommentsOwner for StructDef {} 3057impl ast::DocCommentsOwner for StructDef {}
3019impl StructDef {} 3058impl StructDef {}
3020#[derive(Debug, Clone, PartialEq, Eq, Hash)] 3059#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3021pub struct StructLit { 3060pub struct TokenTree {
3022 pub(crate) syntax: SyntaxNode, 3061 pub(crate) syntax: SyntaxNode,
3023} 3062}
3024impl AstNode for StructLit { 3063impl AstNode for TokenTree {
3025 fn can_cast(kind: SyntaxKind) -> bool { 3064 fn can_cast(kind: SyntaxKind) -> bool {
3026 match kind { 3065 match kind {
3027 STRUCT_LIT => true, 3066 TOKEN_TREE => true,
3028 _ => false, 3067 _ => false,
3029 } 3068 }
3030 } 3069 }
@@ -3039,22 +3078,15 @@ impl AstNode for StructLit {
3039 &self.syntax 3078 &self.syntax
3040 } 3079 }
3041} 3080}
3042impl StructLit { 3081impl TokenTree {}
3043 pub fn path(&self) -> Option<Path> {
3044 AstChildren::new(&self.syntax).next()
3045 }
3046 pub fn named_field_list(&self) -> Option<NamedFieldList> {
3047 AstChildren::new(&self.syntax).next()
3048 }
3049}
3050#[derive(Debug, Clone, PartialEq, Eq, Hash)] 3082#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3051pub struct StructPat { 3083pub struct TraitDef {
3052 pub(crate) syntax: SyntaxNode, 3084 pub(crate) syntax: SyntaxNode,
3053} 3085}
3054impl AstNode for StructPat { 3086impl AstNode for TraitDef {
3055 fn can_cast(kind: SyntaxKind) -> bool { 3087 fn can_cast(kind: SyntaxKind) -> bool {
3056 match kind { 3088 match kind {
3057 STRUCT_PAT => true, 3089 TRAIT_DEF => true,
3058 _ => false, 3090 _ => false,
3059 } 3091 }
3060 } 3092 }
@@ -3069,22 +3101,25 @@ impl AstNode for StructPat {
3069 &self.syntax 3101 &self.syntax
3070 } 3102 }
3071} 3103}
3072impl StructPat { 3104impl ast::VisibilityOwner for TraitDef {}
3073 pub fn field_pat_list(&self) -> Option<FieldPatList> { 3105impl ast::NameOwner for TraitDef {}
3074 AstChildren::new(&self.syntax).next() 3106impl ast::AttrsOwner for TraitDef {}
3075 } 3107impl ast::DocCommentsOwner for TraitDef {}
3076 pub fn path(&self) -> Option<Path> { 3108impl ast::TypeParamsOwner for TraitDef {}
3109impl ast::TypeBoundsOwner for TraitDef {}
3110impl TraitDef {
3111 pub fn item_list(&self) -> Option<ItemList> {
3077 AstChildren::new(&self.syntax).next() 3112 AstChildren::new(&self.syntax).next()
3078 } 3113 }
3079} 3114}
3080#[derive(Debug, Clone, PartialEq, Eq, Hash)] 3115#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3081pub struct TokenTree { 3116pub struct TryBlockExpr {
3082 pub(crate) syntax: SyntaxNode, 3117 pub(crate) syntax: SyntaxNode,
3083} 3118}
3084impl AstNode for TokenTree { 3119impl AstNode for TryBlockExpr {
3085 fn can_cast(kind: SyntaxKind) -> bool { 3120 fn can_cast(kind: SyntaxKind) -> bool {
3086 match kind { 3121 match kind {
3087 TOKEN_TREE => true, 3122 TRY_BLOCK_EXPR => true,
3088 _ => false, 3123 _ => false,
3089 } 3124 }
3090 } 3125 }
@@ -3099,15 +3134,16 @@ impl AstNode for TokenTree {
3099 &self.syntax 3134 &self.syntax
3100 } 3135 }
3101} 3136}
3102impl TokenTree {} 3137impl ast::TryBlockBodyOwner for TryBlockExpr {}
3138impl TryBlockExpr {}
3103#[derive(Debug, Clone, PartialEq, Eq, Hash)] 3139#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3104pub struct TraitDef { 3140pub struct TryExpr {
3105 pub(crate) syntax: SyntaxNode, 3141 pub(crate) syntax: SyntaxNode,
3106} 3142}
3107impl AstNode for TraitDef { 3143impl AstNode for TryExpr {
3108 fn can_cast(kind: SyntaxKind) -> bool { 3144 fn can_cast(kind: SyntaxKind) -> bool {
3109 match kind { 3145 match kind {
3110 TRAIT_DEF => true, 3146 TRY_EXPR => true,
3111 _ => false, 3147 _ => false,
3112 } 3148 }
3113 } 3149 }
@@ -3122,25 +3158,19 @@ impl AstNode for TraitDef {
3122 &self.syntax 3158 &self.syntax
3123 } 3159 }
3124} 3160}
3125impl ast::VisibilityOwner for TraitDef {} 3161impl TryExpr {
3126impl ast::NameOwner for TraitDef {} 3162 pub fn expr(&self) -> Option<Expr> {
3127impl ast::AttrsOwner for TraitDef {}
3128impl ast::DocCommentsOwner for TraitDef {}
3129impl ast::TypeParamsOwner for TraitDef {}
3130impl ast::TypeBoundsOwner for TraitDef {}
3131impl TraitDef {
3132 pub fn item_list(&self) -> Option<ItemList> {
3133 AstChildren::new(&self.syntax).next() 3163 AstChildren::new(&self.syntax).next()
3134 } 3164 }
3135} 3165}
3136#[derive(Debug, Clone, PartialEq, Eq, Hash)] 3166#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3137pub struct TryBlockExpr { 3167pub struct TupleExpr {
3138 pub(crate) syntax: SyntaxNode, 3168 pub(crate) syntax: SyntaxNode,
3139} 3169}
3140impl AstNode for TryBlockExpr { 3170impl AstNode for TupleExpr {
3141 fn can_cast(kind: SyntaxKind) -> bool { 3171 fn can_cast(kind: SyntaxKind) -> bool {
3142 match kind { 3172 match kind {
3143 TRY_BLOCK_EXPR => true, 3173 TUPLE_EXPR => true,
3144 _ => false, 3174 _ => false,
3145 } 3175 }
3146 } 3176 }
@@ -3155,16 +3185,19 @@ impl AstNode for TryBlockExpr {
3155 &self.syntax 3185 &self.syntax
3156 } 3186 }
3157} 3187}
3158impl ast::TryBlockBodyOwner for TryBlockExpr {} 3188impl TupleExpr {
3159impl TryBlockExpr {} 3189 pub fn exprs(&self) -> AstChildren<Expr> {
3190 AstChildren::new(&self.syntax)
3191 }
3192}
3160#[derive(Debug, Clone, PartialEq, Eq, Hash)] 3193#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3161pub struct TryExpr { 3194pub struct TupleFieldDef {
3162 pub(crate) syntax: SyntaxNode, 3195 pub(crate) syntax: SyntaxNode,
3163} 3196}
3164impl AstNode for TryExpr { 3197impl AstNode for TupleFieldDef {
3165 fn can_cast(kind: SyntaxKind) -> bool { 3198 fn can_cast(kind: SyntaxKind) -> bool {
3166 match kind { 3199 match kind {
3167 TRY_EXPR => true, 3200 TUPLE_FIELD_DEF => true,
3168 _ => false, 3201 _ => false,
3169 } 3202 }
3170 } 3203 }
@@ -3179,19 +3212,21 @@ impl AstNode for TryExpr {
3179 &self.syntax 3212 &self.syntax
3180 } 3213 }
3181} 3214}
3182impl TryExpr { 3215impl ast::VisibilityOwner for TupleFieldDef {}
3183 pub fn expr(&self) -> Option<Expr> { 3216impl ast::AttrsOwner for TupleFieldDef {}
3217impl TupleFieldDef {
3218 pub fn type_ref(&self) -> Option<TypeRef> {
3184 AstChildren::new(&self.syntax).next() 3219 AstChildren::new(&self.syntax).next()
3185 } 3220 }
3186} 3221}
3187#[derive(Debug, Clone, PartialEq, Eq, Hash)] 3222#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3188pub struct TupleExpr { 3223pub struct TupleFieldDefList {
3189 pub(crate) syntax: SyntaxNode, 3224 pub(crate) syntax: SyntaxNode,
3190} 3225}
3191impl AstNode for TupleExpr { 3226impl AstNode for TupleFieldDefList {
3192 fn can_cast(kind: SyntaxKind) -> bool { 3227 fn can_cast(kind: SyntaxKind) -> bool {
3193 match kind { 3228 match kind {
3194 TUPLE_EXPR => true, 3229 TUPLE_FIELD_DEF_LIST => true,
3195 _ => false, 3230 _ => false,
3196 } 3231 }
3197 } 3232 }
@@ -3206,8 +3241,8 @@ impl AstNode for TupleExpr {
3206 &self.syntax 3241 &self.syntax
3207 } 3242 }
3208} 3243}
3209impl TupleExpr { 3244impl TupleFieldDefList {
3210 pub fn exprs(&self) -> AstChildren<Expr> { 3245 pub fn fields(&self) -> AstChildren<TupleFieldDef> {
3211 AstChildren::new(&self.syntax) 3246 AstChildren::new(&self.syntax)
3212 } 3247 }
3213} 3248}
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index 26efeeba9..1836862fe 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -158,12 +158,13 @@ Grammar(
158 "DYN_TRAIT_TYPE", 158 "DYN_TRAIT_TYPE",
159 159
160 "REF_PAT", 160 "REF_PAT",
161 "BOX_PAT",
161 "BIND_PAT", 162 "BIND_PAT",
162 "PLACEHOLDER_PAT", 163 "PLACEHOLDER_PAT",
163 "PATH_PAT", 164 "PATH_PAT",
164 "STRUCT_PAT", 165 "RECORD_PAT",
165 "FIELD_PAT_LIST", 166 "RECORD_FIELD_PAT_LIST",
166 "FIELD_PAT", 167 "RECORD_FIELD_PAT",
167 "TUPLE_STRUCT_PAT", 168 "TUPLE_STRUCT_PAT",
168 "TUPLE_PAT", 169 "TUPLE_PAT",
169 "SLICE_PAT", 170 "SLICE_PAT",
@@ -190,9 +191,9 @@ Grammar(
190 "MATCH_ARM_LIST", 191 "MATCH_ARM_LIST",
191 "MATCH_ARM", 192 "MATCH_ARM",
192 "MATCH_GUARD", 193 "MATCH_GUARD",
193 "STRUCT_LIT", 194 "RECORD_LIT",
194 "NAMED_FIELD_LIST", 195 "RECORD_FIELD_LIST",
195 "NAMED_FIELD", 196 "RECORD_FIELD",
196 "TRY_BLOCK_EXPR", 197 "TRY_BLOCK_EXPR",
197 "BOX_EXPR", 198 "BOX_EXPR",
198 199
@@ -216,10 +217,10 @@ Grammar(
216 "EXTERN_BLOCK", 217 "EXTERN_BLOCK",
217 "EXTERN_ITEM_LIST", 218 "EXTERN_ITEM_LIST",
218 "ENUM_VARIANT", 219 "ENUM_VARIANT",
219 "NAMED_FIELD_DEF_LIST", 220 "RECORD_FIELD_DEF_LIST",
220 "NAMED_FIELD_DEF", 221 "RECORD_FIELD_DEF",
221 "POS_FIELD_DEF_LIST", 222 "TUPLE_FIELD_DEF_LIST",
222 "POS_FIELD_DEF", 223 "TUPLE_FIELD_DEF",
223 "ENUM_VARIANT_LIST", 224 "ENUM_VARIANT_LIST",
224 "ITEM_LIST", 225 "ITEM_LIST",
225 "ATTR", 226 "ATTR",
@@ -286,8 +287,8 @@ Grammar(
286 "DocCommentsOwner" 287 "DocCommentsOwner"
287 ] 288 ]
288 ), 289 ),
289 "NamedFieldDefList": (collections: [("fields", "NamedFieldDef")]), 290 "RecordFieldDefList": (collections: [("fields", "RecordFieldDef")]),
290 "NamedFieldDef": ( 291 "RecordFieldDef": (
291 traits: [ 292 traits: [
292 "VisibilityOwner", 293 "VisibilityOwner",
293 "NameOwner", 294 "NameOwner",
@@ -296,8 +297,8 @@ Grammar(
296 "TypeAscriptionOwner" 297 "TypeAscriptionOwner"
297 ] 298 ]
298 ), 299 ),
299 "PosFieldDefList": (collections: [("fields", "PosFieldDef")]), 300 "TupleFieldDefList": (collections: [("fields", "TupleFieldDef")]),
300 "PosFieldDef": ( traits: ["VisibilityOwner", "AttrsOwner"], options: ["TypeRef"]), 301 "TupleFieldDef": ( traits: ["VisibilityOwner", "AttrsOwner"], options: ["TypeRef"]),
301 "EnumDef": ( traits: [ 302 "EnumDef": ( traits: [
302 "VisibilityOwner", 303 "VisibilityOwner",
303 "NameOwner", 304 "NameOwner",
@@ -461,12 +462,12 @@ Grammar(
461 traits: [ "AttrsOwner" ] 462 traits: [ "AttrsOwner" ]
462 ), 463 ),
463 "MatchGuard": (options: ["Expr"]), 464 "MatchGuard": (options: ["Expr"]),
464 "StructLit": (options: ["Path", "NamedFieldList"]), 465 "RecordLit": (options: ["Path", "RecordFieldList"]),
465 "NamedFieldList": ( 466 "RecordFieldList": (
466 collections: [ ("fields", "NamedField") ], 467 collections: [ ("fields", "RecordField") ],
467 options: [["spread", "Expr"]] 468 options: [["spread", "Expr"]]
468 ), 469 ),
469 "NamedField": (options: ["NameRef", "Expr"]), 470 "RecordField": (options: ["NameRef", "Expr"]),
470 "CallExpr": ( 471 "CallExpr": (
471 traits: ["ArgListOwner"], 472 traits: ["ArgListOwner"],
472 options: [ "Expr" ], 473 options: [ "Expr" ],
@@ -504,7 +505,7 @@ Grammar(
504 "BlockExpr", 505 "BlockExpr",
505 "ReturnExpr", 506 "ReturnExpr",
506 "MatchExpr", 507 "MatchExpr",
507 "StructLit", 508 "RecordLit",
508 "CallExpr", 509 "CallExpr",
509 "IndexExpr", 510 "IndexExpr",
510 "MethodCallExpr", 511 "MethodCallExpr",
@@ -523,20 +524,21 @@ Grammar(
523 ), 524 ),
524 525
525 "RefPat": ( options: [ "Pat" ]), 526 "RefPat": ( options: [ "Pat" ]),
527 "BoxPat": ( options: [ "Pat" ]),
526 "BindPat": ( 528 "BindPat": (
527 options: [ "Pat" ], 529 options: [ "Pat" ],
528 traits: ["NameOwner"] 530 traits: ["NameOwner"]
529 ), 531 ),
530 "PlaceholderPat": (), 532 "PlaceholderPat": (),
531 "PathPat": ( options: [ "Path" ] ), 533 "PathPat": ( options: [ "Path" ] ),
532 "StructPat": ( options: ["FieldPatList", "Path"] ), 534 "RecordPat": ( options: ["RecordFieldPatList", "Path"] ),
533 "FieldPatList": ( 535 "RecordFieldPatList": (
534 collections: [ 536 collections: [
535 ("field_pats", "FieldPat"), 537 ("record_field_pats", "RecordFieldPat"),
536 ("bind_pats", "BindPat"), 538 ("bind_pats", "BindPat"),
537 ] 539 ]
538 ), 540 ),
539 "FieldPat": ( 541 "RecordFieldPat": (
540 traits: ["NameOwner"], 542 traits: ["NameOwner"],
541 options: ["Pat"] 543 options: ["Pat"]
542 ), 544 ),
@@ -552,10 +554,11 @@ Grammar(
552 "Pat": ( 554 "Pat": (
553 enum: [ 555 enum: [
554 "RefPat", 556 "RefPat",
557 "BoxPat",
555 "BindPat", 558 "BindPat",
556 "PlaceholderPat", 559 "PlaceholderPat",
557 "PathPat", 560 "PathPat",
558 "StructPat", 561 "RecordPat",
559 "TupleStructPat", 562 "TupleStructPat",
560 "TuplePat", 563 "TuplePat",
561 "SlicePat", 564 "SlicePat",
diff --git a/crates/ra_syntax/src/parsing/text_tree_sink.rs b/crates/ra_syntax/src/parsing/text_tree_sink.rs
index bf1b35c95..f59c559e9 100644
--- a/crates/ra_syntax/src/parsing/text_tree_sink.rs
+++ b/crates/ra_syntax/src/parsing/text_tree_sink.rs
@@ -145,7 +145,7 @@ fn n_attached_trivias<'a>(
145) -> usize { 145) -> usize {
146 match kind { 146 match kind {
147 CONST_DEF | TYPE_ALIAS_DEF | STRUCT_DEF | ENUM_DEF | ENUM_VARIANT | FN_DEF | TRAIT_DEF 147 CONST_DEF | TYPE_ALIAS_DEF | STRUCT_DEF | ENUM_DEF | ENUM_VARIANT | FN_DEF | TRAIT_DEF
148 | MODULE | NAMED_FIELD_DEF => { 148 | MODULE | RECORD_FIELD_DEF => {
149 let mut res = 0; 149 let mut res = 0;
150 for (i, (kind, text)) in trivias.enumerate() { 150 for (i, (kind, text)) in trivias.enumerate() {
151 match kind { 151 match kind {
diff --git a/crates/ra_syntax/src/ptr.rs b/crates/ra_syntax/src/ptr.rs
index 8665c8976..992034ef0 100644
--- a/crates/ra_syntax/src/ptr.rs
+++ b/crates/ra_syntax/src/ptr.rs
@@ -31,6 +31,13 @@ impl SyntaxNodePtr {
31 pub fn kind(self) -> SyntaxKind { 31 pub fn kind(self) -> SyntaxKind {
32 self.kind 32 self.kind
33 } 33 }
34
35 pub fn cast<N: AstNode>(self) -> Option<AstPtr<N>> {
36 if !N::can_cast(self.kind()) {
37 return None;
38 }
39 Some(AstPtr { raw: self, _ty: PhantomData })
40 }
34} 41}
35 42
36/// Like `SyntaxNodePtr`, but remembers the type of node 43/// Like `SyntaxNodePtr`, but remembers the type of node
@@ -80,7 +87,7 @@ fn test_local_syntax_ptr() {
80 use crate::{ast, AstNode, SourceFile}; 87 use crate::{ast, AstNode, SourceFile};
81 88
82 let file = SourceFile::parse("struct Foo { f: u32, }").ok().unwrap(); 89 let file = SourceFile::parse("struct Foo { f: u32, }").ok().unwrap();
83 let field = file.syntax().descendants().find_map(ast::NamedFieldDef::cast).unwrap(); 90 let field = file.syntax().descendants().find_map(ast::RecordFieldDef::cast).unwrap();
84 let ptr = SyntaxNodePtr::new(field.syntax()); 91 let ptr = SyntaxNodePtr::new(field.syntax());
85 let field_syntax = ptr.to_node(file.syntax()); 92 let field_syntax = ptr.to_node(file.syntax());
86 assert_eq!(field.syntax(), &field_syntax); 93 assert_eq!(field.syntax(), &field_syntax);
diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs
index a8c789e0c..ee8797410 100644
--- a/crates/ra_syntax/src/validation.rs
+++ b/crates/ra_syntax/src/validation.rs
@@ -99,7 +99,7 @@ pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> {
99 .visit::<ast::Literal, _>(validate_literal) 99 .visit::<ast::Literal, _>(validate_literal)
100 .visit::<ast::Block, _>(block::validate_block_node) 100 .visit::<ast::Block, _>(block::validate_block_node)
101 .visit::<ast::FieldExpr, _>(|it, errors| validate_numeric_name(it.name_ref(), errors)) 101 .visit::<ast::FieldExpr, _>(|it, errors| validate_numeric_name(it.name_ref(), errors))
102 .visit::<ast::NamedField, _>(|it, errors| validate_numeric_name(it.name_ref(), errors)) 102 .visit::<ast::RecordField, _>(|it, errors| validate_numeric_name(it.name_ref(), errors))
103 .accept(&node); 103 .accept(&node);
104 } 104 }
105 errors 105 errors
diff --git a/crates/ra_syntax/test_data/parser/err/0000_struct_field_missing_comma.txt b/crates/ra_syntax/test_data/parser/err/0000_struct_field_missing_comma.txt
index 0dbbfe853..dc143945a 100644
--- a/crates/ra_syntax/test_data/parser/err/0000_struct_field_missing_comma.txt
+++ b/crates/ra_syntax/test_data/parser/err/0000_struct_field_missing_comma.txt
@@ -5,10 +5,10 @@ SOURCE_FILE@[0; 34)
5 NAME@[7; 8) 5 NAME@[7; 8)
6 IDENT@[7; 8) "S" 6 IDENT@[7; 8) "S"
7 WHITESPACE@[8; 9) " " 7 WHITESPACE@[8; 9) " "
8 NAMED_FIELD_DEF_LIST@[9; 34) 8 RECORD_FIELD_DEF_LIST@[9; 34)
9 L_CURLY@[9; 10) "{" 9 L_CURLY@[9; 10) "{"
10 WHITESPACE@[10; 15) "\n " 10 WHITESPACE@[10; 15) "\n "
11 NAMED_FIELD_DEF@[15; 21) 11 RECORD_FIELD_DEF@[15; 21)
12 NAME@[15; 16) 12 NAME@[15; 16)
13 IDENT@[15; 16) "a" 13 IDENT@[15; 16) "a"
14 COLON@[16; 17) ":" 14 COLON@[16; 17) ":"
@@ -19,7 +19,7 @@ SOURCE_FILE@[0; 34)
19 NAME_REF@[18; 21) 19 NAME_REF@[18; 21)
20 IDENT@[18; 21) "u32" 20 IDENT@[18; 21) "u32"
21 WHITESPACE@[21; 26) "\n " 21 WHITESPACE@[21; 26) "\n "
22 NAMED_FIELD_DEF@[26; 32) 22 RECORD_FIELD_DEF@[26; 32)
23 NAME@[26; 27) 23 NAME@[26; 27)
24 IDENT@[26; 27) "b" 24 IDENT@[26; 27) "b"
25 COLON@[27; 28) ":" 25 COLON@[27; 28) ":"
diff --git a/crates/ra_syntax/test_data/parser/err/0001_item_recovery_in_file.txt b/crates/ra_syntax/test_data/parser/err/0001_item_recovery_in_file.txt
index 7cfb54ef8..181bcdb9e 100644
--- a/crates/ra_syntax/test_data/parser/err/0001_item_recovery_in_file.txt
+++ b/crates/ra_syntax/test_data/parser/err/0001_item_recovery_in_file.txt
@@ -11,7 +11,7 @@ SOURCE_FILE@[0; 21)
11 NAME@[17; 18) 11 NAME@[17; 18)
12 IDENT@[17; 18) "S" 12 IDENT@[17; 18) "S"
13 WHITESPACE@[18; 19) " " 13 WHITESPACE@[18; 19) " "
14 NAMED_FIELD_DEF_LIST@[19; 21) 14 RECORD_FIELD_DEF_LIST@[19; 21)
15 L_CURLY@[19; 20) "{" 15 L_CURLY@[19; 20) "{"
16 R_CURLY@[20; 21) "}" 16 R_CURLY@[20; 21) "}"
17error 0: expected an item 17error 0: expected an item
diff --git a/crates/ra_syntax/test_data/parser/err/0003_C++_semicolon.txt b/crates/ra_syntax/test_data/parser/err/0003_C++_semicolon.txt
index 857826037..58d005902 100644
--- a/crates/ra_syntax/test_data/parser/err/0003_C++_semicolon.txt
+++ b/crates/ra_syntax/test_data/parser/err/0003_C++_semicolon.txt
@@ -5,10 +5,10 @@ SOURCE_FILE@[0; 40)
5 NAME@[7; 8) 5 NAME@[7; 8)
6 IDENT@[7; 8) "S" 6 IDENT@[7; 8) "S"
7 WHITESPACE@[8; 9) " " 7 WHITESPACE@[8; 9) " "
8 NAMED_FIELD_DEF_LIST@[9; 39) 8 RECORD_FIELD_DEF_LIST@[9; 39)
9 L_CURLY@[9; 10) "{" 9 L_CURLY@[9; 10) "{"
10 WHITESPACE@[10; 15) "\n " 10 WHITESPACE@[10; 15) "\n "
11 NAMED_FIELD_DEF@[15; 21) 11 RECORD_FIELD_DEF@[15; 21)
12 NAME@[15; 16) 12 NAME@[15; 16)
13 IDENT@[15; 16) "a" 13 IDENT@[15; 16) "a"
14 COLON@[16; 17) ":" 14 COLON@[16; 17) ":"
@@ -20,7 +20,7 @@ SOURCE_FILE@[0; 40)
20 IDENT@[18; 21) "i32" 20 IDENT@[18; 21) "i32"
21 COMMA@[21; 22) "," 21 COMMA@[21; 22) ","
22 WHITESPACE@[22; 27) "\n " 22 WHITESPACE@[22; 27) "\n "
23 NAMED_FIELD_DEF@[27; 36) 23 RECORD_FIELD_DEF@[27; 36)
24 NAME@[27; 28) 24 NAME@[27; 28)
25 IDENT@[27; 28) "b" 25 IDENT@[27; 28) "b"
26 COLON@[28; 29) ":" 26 COLON@[28; 29) ":"
diff --git a/crates/ra_syntax/test_data/parser/err/0006_named_field_recovery.txt b/crates/ra_syntax/test_data/parser/err/0006_named_field_recovery.txt
index 6143e68f1..5f5198b31 100644
--- a/crates/ra_syntax/test_data/parser/err/0006_named_field_recovery.txt
+++ b/crates/ra_syntax/test_data/parser/err/0006_named_field_recovery.txt
@@ -5,10 +5,10 @@ SOURCE_FILE@[0; 74)
5 NAME@[7; 8) 5 NAME@[7; 8)
6 IDENT@[7; 8) "S" 6 IDENT@[7; 8) "S"
7 WHITESPACE@[8; 9) " " 7 WHITESPACE@[8; 9) " "
8 NAMED_FIELD_DEF_LIST@[9; 73) 8 RECORD_FIELD_DEF_LIST@[9; 73)
9 L_CURLY@[9; 10) "{" 9 L_CURLY@[9; 10) "{"
10 WHITESPACE@[10; 15) "\n " 10 WHITESPACE@[10; 15) "\n "
11 NAMED_FIELD_DEF@[15; 21) 11 RECORD_FIELD_DEF@[15; 21)
12 NAME@[15; 16) 12 NAME@[15; 16)
13 IDENT@[15; 16) "f" 13 IDENT@[15; 16) "f"
14 COLON@[16; 17) ":" 14 COLON@[16; 17) ":"
@@ -35,7 +35,7 @@ SOURCE_FILE@[0; 74)
35 ERROR@[42; 43) 35 ERROR@[42; 43)
36 STAR@[42; 43) "*" 36 STAR@[42; 43) "*"
37 WHITESPACE@[43; 48) "\n " 37 WHITESPACE@[43; 48) "\n "
38 NAMED_FIELD_DEF@[48; 58) 38 RECORD_FIELD_DEF@[48; 58)
39 VISIBILITY@[48; 51) 39 VISIBILITY@[48; 51)
40 PUB_KW@[48; 51) "pub" 40 PUB_KW@[48; 51) "pub"
41 WHITESPACE@[51; 52) " " 41 WHITESPACE@[51; 52) " "
@@ -50,7 +50,7 @@ SOURCE_FILE@[0; 74)
50 IDENT@[55; 58) "u32" 50 IDENT@[55; 58) "u32"
51 COMMA@[58; 59) "," 51 COMMA@[58; 59) ","
52 WHITESPACE@[59; 64) "\n " 52 WHITESPACE@[59; 64) "\n "
53 NAMED_FIELD_DEF@[64; 70) 53 RECORD_FIELD_DEF@[64; 70)
54 NAME@[64; 65) 54 NAME@[64; 65)
55 IDENT@[64; 65) "z" 55 IDENT@[64; 65) "z"
56 COLON@[65; 66) ":" 56 COLON@[65; 66) ":"
diff --git a/crates/ra_syntax/test_data/parser/err/0013_invalid_type.txt b/crates/ra_syntax/test_data/parser/err/0013_invalid_type.txt
index bef286b37..4907bac6d 100644
--- a/crates/ra_syntax/test_data/parser/err/0013_invalid_type.txt
+++ b/crates/ra_syntax/test_data/parser/err/0013_invalid_type.txt
@@ -7,10 +7,10 @@ SOURCE_FILE@[0; 86)
7 WHITESPACE@[10; 11) " " 7 WHITESPACE@[10; 11) " "
8 NAME@[11; 16) 8 NAME@[11; 16)
9 IDENT@[11; 16) "Cache" 9 IDENT@[11; 16) "Cache"
10 POS_FIELD_DEF_LIST@[16; 72) 10 TUPLE_FIELD_DEF_LIST@[16; 72)
11 L_PAREN@[16; 17) "(" 11 L_PAREN@[16; 17) "("
12 WHITESPACE@[17; 22) "\n " 12 WHITESPACE@[17; 22) "\n "
13 POS_FIELD_DEF@[22; 68) 13 TUPLE_FIELD_DEF@[22; 68)
14 PATH_TYPE@[22; 68) 14 PATH_TYPE@[22; 68)
15 PATH@[22; 68) 15 PATH@[22; 68)
16 PATH_SEGMENT@[22; 68) 16 PATH_SEGMENT@[22; 68)
@@ -47,7 +47,7 @@ SOURCE_FILE@[0; 86)
47 ERROR@[67; 68) 47 ERROR@[67; 68)
48 AT@[67; 68) "@" 48 AT@[67; 68) "@"
49 WHITESPACE@[68; 69) " " 49 WHITESPACE@[68; 69) " "
50 POS_FIELD_DEF@[69; 72) 50 TUPLE_FIELD_DEF@[69; 72)
51 PATH_TYPE@[69; 72) 51 PATH_TYPE@[69; 72)
52 PATH@[69; 72) 52 PATH@[69; 72)
53 PATH_SEGMENT@[69; 72) 53 PATH_SEGMENT@[69; 72)
diff --git a/crates/ra_syntax/test_data/parser/err/0018_incomplete_fn.txt b/crates/ra_syntax/test_data/parser/err/0018_incomplete_fn.txt
index 51def2d8f..52eb7d5e2 100644
--- a/crates/ra_syntax/test_data/parser/err/0018_incomplete_fn.txt
+++ b/crates/ra_syntax/test_data/parser/err/0018_incomplete_fn.txt
@@ -75,16 +75,16 @@ SOURCE_FILE@[0; 183)
75 IDENT@[106; 110) "push" 75 IDENT@[106; 110) "push"
76 ARG_LIST@[110; 155) 76 ARG_LIST@[110; 155)
77 L_PAREN@[110; 111) "(" 77 L_PAREN@[110; 111) "("
78 STRUCT_LIT@[111; 154) 78 RECORD_LIT@[111; 154)
79 PATH@[111; 120) 79 PATH@[111; 120)
80 PATH_SEGMENT@[111; 120) 80 PATH_SEGMENT@[111; 120)
81 NAME_REF@[111; 120) 81 NAME_REF@[111; 120)
82 IDENT@[111; 120) "ScopeData" 82 IDENT@[111; 120) "ScopeData"
83 WHITESPACE@[120; 121) " " 83 WHITESPACE@[120; 121) " "
84 NAMED_FIELD_LIST@[121; 154) 84 RECORD_FIELD_LIST@[121; 154)
85 L_CURLY@[121; 122) "{" 85 L_CURLY@[121; 122) "{"
86 WHITESPACE@[122; 123) " " 86 WHITESPACE@[122; 123) " "
87 NAMED_FIELD@[123; 135) 87 RECORD_FIELD@[123; 135)
88 NAME_REF@[123; 129) 88 NAME_REF@[123; 129)
89 IDENT@[123; 129) "parent" 89 IDENT@[123; 129) "parent"
90 COLON@[129; 130) ":" 90 COLON@[129; 130) ":"
@@ -96,7 +96,7 @@ SOURCE_FILE@[0; 183)
96 IDENT@[131; 135) "None" 96 IDENT@[131; 135) "None"
97 COMMA@[135; 136) "," 97 COMMA@[135; 136) ","
98 WHITESPACE@[136; 137) " " 98 WHITESPACE@[136; 137) " "
99 NAMED_FIELD@[137; 152) 99 RECORD_FIELD@[137; 152)
100 NAME_REF@[137; 144) 100 NAME_REF@[137; 144)
101 IDENT@[137; 144) "entries" 101 IDENT@[137; 144) "entries"
102 COLON@[144; 145) ":" 102 COLON@[144; 145) ":"
diff --git a/crates/ra_syntax/test_data/parser/err/0025_nope.txt b/crates/ra_syntax/test_data/parser/err/0025_nope.txt
index 0a3952dc9..7b228a8ed 100644
--- a/crates/ra_syntax/test_data/parser/err/0025_nope.txt
+++ b/crates/ra_syntax/test_data/parser/err/0025_nope.txt
@@ -28,9 +28,9 @@ SOURCE_FILE@[0; 575)
28 ENUM_VARIANT@[50; 62) 28 ENUM_VARIANT@[50; 62)
29 NAME@[50; 54) 29 NAME@[50; 54)
30 IDENT@[50; 54) "Var2" 30 IDENT@[50; 54) "Var2"
31 POS_FIELD_DEF_LIST@[54; 62) 31 TUPLE_FIELD_DEF_LIST@[54; 62)
32 L_PAREN@[54; 55) "(" 32 L_PAREN@[54; 55) "("
33 POS_FIELD_DEF@[55; 61) 33 TUPLE_FIELD_DEF@[55; 61)
34 PATH_TYPE@[55; 61) 34 PATH_TYPE@[55; 61)
35 PATH@[55; 61) 35 PATH@[55; 61)
36 PATH_SEGMENT@[55; 61) 36 PATH_SEGMENT@[55; 61)
@@ -43,10 +43,10 @@ SOURCE_FILE@[0; 575)
43 NAME@[72; 76) 43 NAME@[72; 76)
44 IDENT@[72; 76) "Var3" 44 IDENT@[72; 76) "Var3"
45 WHITESPACE@[76; 77) " " 45 WHITESPACE@[76; 77) " "
46 NAMED_FIELD_DEF_LIST@[77; 145) 46 RECORD_FIELD_DEF_LIST@[77; 145)
47 L_CURLY@[77; 78) "{" 47 L_CURLY@[77; 78) "{"
48 WHITESPACE@[78; 91) "\n " 48 WHITESPACE@[78; 91) "\n "
49 NAMED_FIELD_DEF@[91; 95) 49 RECORD_FIELD_DEF@[91; 95)
50 NAME@[91; 94) 50 NAME@[91; 94)
51 IDENT@[91; 94) "abc" 51 IDENT@[91; 94) "abc"
52 COLON@[94; 95) ":" 52 COLON@[94; 95) ":"
@@ -108,10 +108,10 @@ SOURCE_FILE@[0; 575)
108 NAME@[250; 259) 108 NAME@[250; 259)
109 IDENT@[250; 259) "StillFine" 109 IDENT@[250; 259) "StillFine"
110 WHITESPACE@[259; 260) " " 110 WHITESPACE@[259; 260) " "
111 NAMED_FIELD_DEF_LIST@[260; 293) 111 RECORD_FIELD_DEF_LIST@[260; 293)
112 L_CURLY@[260; 261) "{" 112 L_CURLY@[260; 261) "{"
113 WHITESPACE@[261; 274) "\n " 113 WHITESPACE@[261; 274) "\n "
114 NAMED_FIELD_DEF@[274; 282) 114 RECORD_FIELD_DEF@[274; 282)
115 NAME@[274; 277) 115 NAME@[274; 277)
116 IDENT@[274; 277) "def" 116 IDENT@[274; 277) "def"
117 COLON@[277; 278) ":" 117 COLON@[277; 278) ":"
@@ -147,9 +147,9 @@ SOURCE_FILE@[0; 575)
147 ENUM_VARIANT@[363; 372) 147 ENUM_VARIANT@[363; 372)
148 NAME@[363; 367) 148 NAME@[363; 367)
149 IDENT@[363; 367) "Nope" 149 IDENT@[363; 367) "Nope"
150 POS_FIELD_DEF_LIST@[367; 372) 150 TUPLE_FIELD_DEF_LIST@[367; 372)
151 L_PAREN@[367; 368) "(" 151 L_PAREN@[367; 368) "("
152 POS_FIELD_DEF@[368; 371) 152 TUPLE_FIELD_DEF@[368; 371)
153 PATH_TYPE@[368; 371) 153 PATH_TYPE@[368; 371)
154 PATH@[368; 371) 154 PATH@[368; 371)
155 PATH_SEGMENT@[368; 371) 155 PATH_SEGMENT@[368; 371)
diff --git a/crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.rs b/crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.rs
new file mode 100644
index 000000000..d3fa2e468
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.rs
@@ -0,0 +1,6 @@
1fn main() {
2 let ref box i = ();
3 let mut box i = ();
4 let ref mut box i = ();
5}
6
diff --git a/crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.txt b/crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.txt
new file mode 100644
index 000000000..0cdca4b55
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.txt
@@ -0,0 +1,95 @@
1SOURCE_FILE@[0; 91)
2 FN_DEF@[0; 89)
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@[10; 89)
12 L_CURLY@[10; 11) "{"
13 WHITESPACE@[11; 16) "\n "
14 LET_STMT@[16; 27)
15 LET_KW@[16; 19) "let"
16 WHITESPACE@[19; 20) " "
17 BIND_PAT@[20; 27)
18 REF_KW@[20; 23) "ref"
19 WHITESPACE@[23; 24) " "
20 ERROR@[24; 27)
21 BOX_KW@[24; 27) "box"
22 WHITESPACE@[27; 28) " "
23 EXPR_STMT@[28; 35)
24 BIN_EXPR@[28; 34)
25 PATH_EXPR@[28; 29)
26 PATH@[28; 29)
27 PATH_SEGMENT@[28; 29)
28 NAME_REF@[28; 29)
29 IDENT@[28; 29) "i"
30 WHITESPACE@[29; 30) " "
31 EQ@[30; 31) "="
32 WHITESPACE@[31; 32) " "
33 TUPLE_EXPR@[32; 34)
34 L_PAREN@[32; 33) "("
35 R_PAREN@[33; 34) ")"
36 SEMI@[34; 35) ";"
37 WHITESPACE@[35; 40) "\n "
38 LET_STMT@[40; 51)
39 LET_KW@[40; 43) "let"
40 WHITESPACE@[43; 44) " "
41 BIND_PAT@[44; 51)
42 MUT_KW@[44; 47) "mut"
43 WHITESPACE@[47; 48) " "
44 ERROR@[48; 51)
45 BOX_KW@[48; 51) "box"
46 WHITESPACE@[51; 52) " "
47 EXPR_STMT@[52; 59)
48 BIN_EXPR@[52; 58)
49 PATH_EXPR@[52; 53)
50 PATH@[52; 53)
51 PATH_SEGMENT@[52; 53)
52 NAME_REF@[52; 53)
53 IDENT@[52; 53) "i"
54 WHITESPACE@[53; 54) " "
55 EQ@[54; 55) "="
56 WHITESPACE@[55; 56) " "
57 TUPLE_EXPR@[56; 58)
58 L_PAREN@[56; 57) "("
59 R_PAREN@[57; 58) ")"
60 SEMI@[58; 59) ";"
61 WHITESPACE@[59; 64) "\n "
62 LET_STMT@[64; 79)
63 LET_KW@[64; 67) "let"
64 WHITESPACE@[67; 68) " "
65 BIND_PAT@[68; 79)
66 REF_KW@[68; 71) "ref"
67 WHITESPACE@[71; 72) " "
68 MUT_KW@[72; 75) "mut"
69 WHITESPACE@[75; 76) " "
70 ERROR@[76; 79)
71 BOX_KW@[76; 79) "box"
72 WHITESPACE@[79; 80) " "
73 EXPR_STMT@[80; 87)
74 BIN_EXPR@[80; 86)
75 PATH_EXPR@[80; 81)
76 PATH@[80; 81)
77 PATH_SEGMENT@[80; 81)
78 NAME_REF@[80; 81)
79 IDENT@[80; 81) "i"
80 WHITESPACE@[81; 82) " "
81 EQ@[82; 83) "="
82 WHITESPACE@[83; 84) " "
83 TUPLE_EXPR@[84; 86)
84 L_PAREN@[84; 85) "("
85 R_PAREN@[85; 86) ")"
86 SEMI@[86; 87) ";"
87 WHITESPACE@[87; 88) "\n"
88 R_CURLY@[88; 89) "}"
89 WHITESPACE@[89; 91) "\n\n"
90error 24: expected a name
91error 27: expected SEMI
92error 48: expected a name
93error 51: expected SEMI
94error 76: expected a name
95error 79: expected SEMI
diff --git a/crates/ra_syntax/test_data/parser/fuzz-failures/0000.rs b/crates/ra_syntax/test_data/parser/fuzz-failures/0000.rs
index e0437d163..0e6e0ccc3 100644
--- a/crates/ra_syntax/test_data/parser/fuzz-failures/0000.rs
+++ b/crates/ra_syntax/test_data/parser/fuzz-failures/0000.rs
@@ -86,7 +86,7 @@ fn find_reparsable_node(node: SyntaxNodeRef, range: TextRange) -> Option<(Syntax
86 fn reparser(node: SyntaxNodeRef) -> Option<fn(&mut Parser)> { 86 fn reparser(node: SyntaxNodeRef) -> Option<fn(&mut Parser)> {
87 let res = match node.kind() { 87 let res = match node.kind() {
88 BLOCK => grammar::block, 88 BLOCK => grammar::block,
89 NAMED_FIELD_DEF_LIST => grammar::named_field_def_list, 89 RECORD_FIELD_DEF_LIST => grammar::record_field_def_list,
90 _ => return None, 90 _ => return None,
91 }; 91 };
92 Some(res) 92 Some(res)
@@ -138,7 +138,7 @@ fn find_reparsable_node(node: SyntaxNodeRef, range: TextRange) -> Option<(Syntax
138 let res = match node.kind() { 138 let res = match node.kind() {
139 ; 139 ;
140 let end = u32::from(range.end()) as usize; 140 let end = u32::from(range.end()) as usize;
141 text.replaT => grammar::named_field_def_list, 141 text.replaT => grammar::record_field_def_list,
142 _ => return None, 142 _ => return None,
143 }; 143 };
144 Some(res) 144 Some(res)
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0008_path_part.txt b/crates/ra_syntax/test_data/parser/inline/ok/0008_path_part.txt
index 0c6be485e..4108762e5 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0008_path_part.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0008_path_part.txt
@@ -52,13 +52,13 @@ SOURCE_FILE@[0; 103)
52 LET_STMT@[58; 78) 52 LET_STMT@[58; 78)
53 LET_KW@[58; 61) "let" 53 LET_KW@[58; 61) "let"
54 WHITESPACE@[61; 62) " " 54 WHITESPACE@[61; 62) " "
55 STRUCT_PAT@[62; 72) 55 RECORD_PAT@[62; 72)
56 PATH@[62; 65) 56 PATH@[62; 65)
57 PATH_SEGMENT@[62; 65) 57 PATH_SEGMENT@[62; 65)
58 NAME_REF@[62; 65) 58 NAME_REF@[62; 65)
59 IDENT@[62; 65) "Bar" 59 IDENT@[62; 65) "Bar"
60 WHITESPACE@[65; 66) " " 60 WHITESPACE@[65; 66) " "
61 FIELD_PAT_LIST@[66; 72) 61 RECORD_FIELD_PAT_LIST@[66; 72)
62 L_CURLY@[66; 67) "{" 62 L_CURLY@[66; 67) "{"
63 WHITESPACE@[67; 68) " " 63 WHITESPACE@[67; 68) " "
64 DOTDOT@[68; 70) ".." 64 DOTDOT@[68; 70) ".."
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0040_crate_keyword_vis.txt b/crates/ra_syntax/test_data/parser/inline/ok/0040_crate_keyword_vis.txt
index fb8246174..882e4a9ae 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0040_crate_keyword_vis.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0040_crate_keyword_vis.txt
@@ -22,10 +22,10 @@ SOURCE_FILE@[0; 71)
22 NAME@[27; 28) 22 NAME@[27; 28)
23 IDENT@[27; 28) "S" 23 IDENT@[27; 28) "S"
24 WHITESPACE@[28; 29) " " 24 WHITESPACE@[28; 29) " "
25 NAMED_FIELD_DEF_LIST@[29; 49) 25 RECORD_FIELD_DEF_LIST@[29; 49)
26 L_CURLY@[29; 30) "{" 26 L_CURLY@[29; 30) "{"
27 WHITESPACE@[30; 31) " " 27 WHITESPACE@[30; 31) " "
28 NAMED_FIELD_DEF@[31; 47) 28 RECORD_FIELD_DEF@[31; 47)
29 VISIBILITY@[31; 36) 29 VISIBILITY@[31; 36)
30 CRATE_KW@[31; 36) "crate" 30 CRATE_KW@[31; 36) "crate"
31 WHITESPACE@[36; 37) " " 31 WHITESPACE@[36; 37) " "
@@ -46,9 +46,9 @@ SOURCE_FILE@[0; 71)
46 WHITESPACE@[56; 57) " " 46 WHITESPACE@[56; 57) " "
47 NAME@[57; 58) 47 NAME@[57; 58)
48 IDENT@[57; 58) "T" 48 IDENT@[57; 58) "T"
49 POS_FIELD_DEF_LIST@[58; 69) 49 TUPLE_FIELD_DEF_LIST@[58; 69)
50 L_PAREN@[58; 59) "(" 50 L_PAREN@[58; 59) "("
51 POS_FIELD_DEF@[59; 68) 51 TUPLE_FIELD_DEF@[59; 68)
52 VISIBILITY@[59; 64) 52 VISIBILITY@[59; 64)
53 CRATE_KW@[59; 64) "crate" 53 CRATE_KW@[59; 64) "crate"
54 WHITESPACE@[64; 65) " " 54 WHITESPACE@[64; 65) " "
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0054_field_attrs.rs b/crates/ra_syntax/test_data/parser/inline/ok/0054_record_field_attrs.rs
index 4744d8ac0..4744d8ac0 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0054_field_attrs.rs
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0054_record_field_attrs.rs
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0054_field_attrs.txt b/crates/ra_syntax/test_data/parser/inline/ok/0054_record_field_attrs.txt
index f214d1d47..56aeba768 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0054_field_attrs.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0054_record_field_attrs.txt
@@ -5,10 +5,10 @@ SOURCE_FILE@[0; 64)
5 NAME@[7; 8) 5 NAME@[7; 8)
6 IDENT@[7; 8) "S" 6 IDENT@[7; 8) "S"
7 WHITESPACE@[8; 9) " " 7 WHITESPACE@[8; 9) " "
8 NAMED_FIELD_DEF_LIST@[9; 63) 8 RECORD_FIELD_DEF_LIST@[9; 63)
9 L_CURLY@[9; 10) "{" 9 L_CURLY@[9; 10) "{"
10 WHITESPACE@[10; 15) "\n " 10 WHITESPACE@[10; 15) "\n "
11 NAMED_FIELD_DEF@[15; 60) 11 RECORD_FIELD_DEF@[15; 60)
12 ATTR@[15; 43) 12 ATTR@[15; 43)
13 POUND@[15; 16) "#" 13 POUND@[15; 16) "#"
14 TOKEN_TREE@[16; 43) 14 TOKEN_TREE@[16; 43)
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0061_struct_lit.rs b/crates/ra_syntax/test_data/parser/inline/ok/0061_record_lit.rs
index 6285e5549..6285e5549 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0061_struct_lit.rs
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0061_record_lit.rs
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0061_struct_lit.txt b/crates/ra_syntax/test_data/parser/inline/ok/0061_record_lit.txt
index d06594cae..1c915ea0c 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0061_struct_lit.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0061_record_lit.txt
@@ -12,33 +12,33 @@ SOURCE_FILE@[0; 112)
12 L_CURLY@[9; 10) "{" 12 L_CURLY@[9; 10) "{"
13 WHITESPACE@[10; 15) "\n " 13 WHITESPACE@[10; 15) "\n "
14 EXPR_STMT@[15; 20) 14 EXPR_STMT@[15; 20)
15 STRUCT_LIT@[15; 19) 15 RECORD_LIT@[15; 19)
16 PATH@[15; 16) 16 PATH@[15; 16)
17 PATH_SEGMENT@[15; 16) 17 PATH_SEGMENT@[15; 16)
18 NAME_REF@[15; 16) 18 NAME_REF@[15; 16)
19 IDENT@[15; 16) "S" 19 IDENT@[15; 16) "S"
20 WHITESPACE@[16; 17) " " 20 WHITESPACE@[16; 17) " "
21 NAMED_FIELD_LIST@[17; 19) 21 RECORD_FIELD_LIST@[17; 19)
22 L_CURLY@[17; 18) "{" 22 L_CURLY@[17; 18) "{"
23 R_CURLY@[18; 19) "}" 23 R_CURLY@[18; 19) "}"
24 SEMI@[19; 20) ";" 24 SEMI@[19; 20) ";"
25 WHITESPACE@[20; 25) "\n " 25 WHITESPACE@[20; 25) "\n "
26 EXPR_STMT@[25; 41) 26 EXPR_STMT@[25; 41)
27 STRUCT_LIT@[25; 40) 27 RECORD_LIT@[25; 40)
28 PATH@[25; 26) 28 PATH@[25; 26)
29 PATH_SEGMENT@[25; 26) 29 PATH_SEGMENT@[25; 26)
30 NAME_REF@[25; 26) 30 NAME_REF@[25; 26)
31 IDENT@[25; 26) "S" 31 IDENT@[25; 26) "S"
32 WHITESPACE@[26; 27) " " 32 WHITESPACE@[26; 27) " "
33 NAMED_FIELD_LIST@[27; 40) 33 RECORD_FIELD_LIST@[27; 40)
34 L_CURLY@[27; 28) "{" 34 L_CURLY@[27; 28) "{"
35 WHITESPACE@[28; 29) " " 35 WHITESPACE@[28; 29) " "
36 NAMED_FIELD@[29; 30) 36 RECORD_FIELD@[29; 30)
37 NAME_REF@[29; 30) 37 NAME_REF@[29; 30)
38 IDENT@[29; 30) "x" 38 IDENT@[29; 30) "x"
39 COMMA@[30; 31) "," 39 COMMA@[30; 31) ","
40 WHITESPACE@[31; 32) " " 40 WHITESPACE@[31; 32) " "
41 NAMED_FIELD@[32; 37) 41 RECORD_FIELD@[32; 37)
42 NAME_REF@[32; 33) 42 NAME_REF@[32; 33)
43 IDENT@[32; 33) "y" 43 IDENT@[32; 33) "y"
44 COLON@[33; 34) ":" 44 COLON@[33; 34) ":"
@@ -51,21 +51,21 @@ SOURCE_FILE@[0; 112)
51 SEMI@[40; 41) ";" 51 SEMI@[40; 41) ";"
52 WHITESPACE@[41; 46) "\n " 52 WHITESPACE@[41; 46) "\n "
53 EXPR_STMT@[46; 83) 53 EXPR_STMT@[46; 83)
54 STRUCT_LIT@[46; 82) 54 RECORD_LIT@[46; 82)
55 PATH@[46; 47) 55 PATH@[46; 47)
56 PATH_SEGMENT@[46; 47) 56 PATH_SEGMENT@[46; 47)
57 NAME_REF@[46; 47) 57 NAME_REF@[46; 47)
58 IDENT@[46; 47) "S" 58 IDENT@[46; 47) "S"
59 WHITESPACE@[47; 48) " " 59 WHITESPACE@[47; 48) " "
60 NAMED_FIELD_LIST@[48; 82) 60 RECORD_FIELD_LIST@[48; 82)
61 L_CURLY@[48; 49) "{" 61 L_CURLY@[48; 49) "{"
62 WHITESPACE@[49; 50) " " 62 WHITESPACE@[49; 50) " "
63 NAMED_FIELD@[50; 51) 63 RECORD_FIELD@[50; 51)
64 NAME_REF@[50; 51) 64 NAME_REF@[50; 51)
65 IDENT@[50; 51) "x" 65 IDENT@[50; 51) "x"
66 COMMA@[51; 52) "," 66 COMMA@[51; 52) ","
67 WHITESPACE@[52; 53) " " 67 WHITESPACE@[52; 53) " "
68 NAMED_FIELD@[53; 58) 68 RECORD_FIELD@[53; 58)
69 NAME_REF@[53; 54) 69 NAME_REF@[53; 54)
70 IDENT@[53; 54) "y" 70 IDENT@[53; 54) "y"
71 COLON@[54; 55) ":" 71 COLON@[54; 55) ":"
@@ -94,16 +94,16 @@ SOURCE_FILE@[0; 112)
94 SEMI@[82; 83) ";" 94 SEMI@[82; 83) ";"
95 WHITESPACE@[83; 88) "\n " 95 WHITESPACE@[83; 88) "\n "
96 EXPR_STMT@[88; 109) 96 EXPR_STMT@[88; 109)
97 STRUCT_LIT@[88; 108) 97 RECORD_LIT@[88; 108)
98 PATH@[88; 99) 98 PATH@[88; 99)
99 PATH_SEGMENT@[88; 99) 99 PATH_SEGMENT@[88; 99)
100 NAME_REF@[88; 99) 100 NAME_REF@[88; 99)
101 IDENT@[88; 99) "TupleStruct" 101 IDENT@[88; 99) "TupleStruct"
102 WHITESPACE@[99; 100) " " 102 WHITESPACE@[99; 100) " "
103 NAMED_FIELD_LIST@[100; 108) 103 RECORD_FIELD_LIST@[100; 108)
104 L_CURLY@[100; 101) "{" 104 L_CURLY@[100; 101) "{"
105 WHITESPACE@[101; 102) " " 105 WHITESPACE@[101; 102) " "
106 NAMED_FIELD@[102; 106) 106 RECORD_FIELD@[102; 106)
107 NAME_REF@[102; 103) 107 NAME_REF@[102; 103)
108 INT_NUMBER@[102; 103) "0" 108 INT_NUMBER@[102; 103) "0"
109 COLON@[103; 104) ":" 109 COLON@[103; 104) ":"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.rs b/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.rs
index 2d476278d..9e009e24f 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.rs
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.rs
@@ -5,7 +5,5 @@ fn foo() {
5 X | Y if Z => (), 5 X | Y if Z => (),
6 | X | Y if Z => (), 6 | X | Y if Z => (),
7 | X => (), 7 | X => (),
8 box X => (),
9 Some(box X) => (),
10 }; 8 };
11} 9}
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 28d501459..c2f256ac3 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
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 215) 1SOURCE_FILE@[0; 167)
2 FN_DEF@[0; 214) 2 FN_DEF@[0; 166)
3 FN_KW@[0; 2) "fn" 3 FN_KW@[0; 2) "fn"
4 WHITESPACE@[2; 3) " " 4 WHITESPACE@[2; 3) " "
5 NAME@[3; 6) 5 NAME@[3; 6)
@@ -8,18 +8,18 @@ SOURCE_FILE@[0; 215)
8 L_PAREN@[6; 7) "(" 8 L_PAREN@[6; 7) "("
9 R_PAREN@[7; 8) ")" 9 R_PAREN@[7; 8) ")"
10 WHITESPACE@[8; 9) " " 10 WHITESPACE@[8; 9) " "
11 BLOCK@[9; 214) 11 BLOCK@[9; 166)
12 L_CURLY@[9; 10) "{" 12 L_CURLY@[9; 10) "{"
13 WHITESPACE@[10; 15) "\n " 13 WHITESPACE@[10; 15) "\n "
14 EXPR_STMT@[15; 212) 14 EXPR_STMT@[15; 164)
15 MATCH_EXPR@[15; 211) 15 MATCH_EXPR@[15; 163)
16 MATCH_KW@[15; 20) "match" 16 MATCH_KW@[15; 20) "match"
17 WHITESPACE@[20; 21) " " 17 WHITESPACE@[20; 21) " "
18 TUPLE_EXPR@[21; 23) 18 TUPLE_EXPR@[21; 23)
19 L_PAREN@[21; 22) "(" 19 L_PAREN@[21; 22) "("
20 R_PAREN@[22; 23) ")" 20 R_PAREN@[22; 23) ")"
21 WHITESPACE@[23; 24) " " 21 WHITESPACE@[23; 24) " "
22 MATCH_ARM_LIST@[24; 211) 22 MATCH_ARM_LIST@[24; 163)
23 L_CURLY@[24; 25) "{" 23 L_CURLY@[24; 25) "{"
24 WHITESPACE@[25; 34) "\n " 24 WHITESPACE@[25; 34) "\n "
25 MATCH_ARM@[34; 41) 25 MATCH_ARM@[34; 41)
@@ -49,14 +49,14 @@ SOURCE_FILE@[0; 215)
49 WHITESPACE@[60; 61) " " 49 WHITESPACE@[60; 61) " "
50 R_ANGLE@[61; 62) ">" 50 R_ANGLE@[61; 62) ">"
51 WHITESPACE@[62; 63) " " 51 WHITESPACE@[62; 63) " "
52 STRUCT_LIT@[63; 77) 52 RECORD_LIT@[63; 77)
53 PATH@[63; 67) 53 PATH@[63; 67)
54 PATH_SEGMENT@[63; 67) 54 PATH_SEGMENT@[63; 67)
55 NAME_REF@[63; 67) 55 NAME_REF@[63; 67)
56 IDENT@[63; 67) "Test" 56 IDENT@[63; 67) "Test"
57 NAMED_FIELD_LIST@[67; 77) 57 RECORD_FIELD_LIST@[67; 77)
58 L_CURLY@[67; 68) "{" 58 L_CURLY@[67; 68) "{"
59 NAMED_FIELD@[68; 76) 59 RECORD_FIELD@[68; 76)
60 NAME_REF@[68; 73) 60 NAME_REF@[68; 73)
61 IDENT@[68; 73) "field" 61 IDENT@[68; 73) "field"
62 COLON@[73; 74) ":" 62 COLON@[73; 74) ":"
@@ -141,44 +141,9 @@ SOURCE_FILE@[0; 215)
141 L_PAREN@[154; 155) "(" 141 L_PAREN@[154; 155) "("
142 R_PAREN@[155; 156) ")" 142 R_PAREN@[155; 156) ")"
143 COMMA@[156; 157) "," 143 COMMA@[156; 157) ","
144 WHITESPACE@[157; 166) "\n " 144 WHITESPACE@[157; 162) "\n "
145 MATCH_ARM@[166; 177) 145 R_CURLY@[162; 163) "}"
146 BIND_PAT@[166; 171) 146 SEMI@[163; 164) ";"
147 BOX_KW@[166; 169) "box" 147 WHITESPACE@[164; 165) "\n"
148 WHITESPACE@[169; 170) " " 148 R_CURLY@[165; 166) "}"
149 NAME@[170; 171) 149 WHITESPACE@[166; 167) "\n"
150 IDENT@[170; 171) "X"
151 WHITESPACE@[171; 172) " "
152 FAT_ARROW@[172; 174) "=>"
153 WHITESPACE@[174; 175) " "
154 TUPLE_EXPR@[175; 177)
155 L_PAREN@[175; 176) "("
156 R_PAREN@[176; 177) ")"
157 COMMA@[177; 178) ","
158 WHITESPACE@[178; 187) "\n "
159 MATCH_ARM@[187; 204)
160 TUPLE_STRUCT_PAT@[187; 198)
161 PATH@[187; 191)
162 PATH_SEGMENT@[187; 191)
163 NAME_REF@[187; 191)
164 IDENT@[187; 191) "Some"
165 L_PAREN@[191; 192) "("
166 BIND_PAT@[192; 197)
167 BOX_KW@[192; 195) "box"
168 WHITESPACE@[195; 196) " "
169 NAME@[196; 197)
170 IDENT@[196; 197) "X"
171 R_PAREN@[197; 198) ")"
172 WHITESPACE@[198; 199) " "
173 FAT_ARROW@[199; 201) "=>"
174 WHITESPACE@[201; 202) " "
175 TUPLE_EXPR@[202; 204)
176 L_PAREN@[202; 203) "("
177 R_PAREN@[203; 204) ")"
178 COMMA@[204; 205) ","
179 WHITESPACE@[205; 210) "\n "
180 R_CURLY@[210; 211) "}"
181 SEMI@[211; 212) ";"
182 WHITESPACE@[212; 213) "\n"
183 R_CURLY@[213; 214) "}"
184 WHITESPACE@[214; 215) "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0068_union_items.txt b/crates/ra_syntax/test_data/parser/inline/ok/0068_union_items.txt
index 4b653317b..f9ace02ee 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0068_union_items.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0068_union_items.txt
@@ -5,7 +5,7 @@ SOURCE_FILE@[0; 51)
5 NAME@[6; 9) 5 NAME@[6; 9)
6 IDENT@[6; 9) "Foo" 6 IDENT@[6; 9) "Foo"
7 WHITESPACE@[9; 10) " " 7 WHITESPACE@[9; 10) " "
8 NAMED_FIELD_DEF_LIST@[10; 12) 8 RECORD_FIELD_DEF_LIST@[10; 12)
9 L_CURLY@[10; 11) "{" 9 L_CURLY@[10; 11) "{"
10 R_CURLY@[11; 12) "}" 10 R_CURLY@[11; 12) "}"
11 WHITESPACE@[12; 13) "\n" 11 WHITESPACE@[12; 13) "\n"
@@ -15,10 +15,10 @@ SOURCE_FILE@[0; 51)
15 NAME@[19; 22) 15 NAME@[19; 22)
16 IDENT@[19; 22) "Foo" 16 IDENT@[19; 22) "Foo"
17 WHITESPACE@[22; 23) " " 17 WHITESPACE@[22; 23) " "
18 NAMED_FIELD_DEF_LIST@[23; 50) 18 RECORD_FIELD_DEF_LIST@[23; 50)
19 L_CURLY@[23; 24) "{" 19 L_CURLY@[23; 24) "{"
20 WHITESPACE@[24; 29) "\n " 20 WHITESPACE@[24; 29) "\n "
21 NAMED_FIELD_DEF@[29; 35) 21 RECORD_FIELD_DEF@[29; 35)
22 NAME@[29; 30) 22 NAME@[29; 30)
23 IDENT@[29; 30) "a" 23 IDENT@[29; 30) "a"
24 COLON@[30; 31) ":" 24 COLON@[30; 31) ":"
@@ -30,7 +30,7 @@ SOURCE_FILE@[0; 51)
30 IDENT@[32; 35) "i32" 30 IDENT@[32; 35) "i32"
31 COMMA@[35; 36) "," 31 COMMA@[35; 36) ","
32 WHITESPACE@[36; 41) "\n " 32 WHITESPACE@[36; 41) "\n "
33 NAMED_FIELD_DEF@[41; 47) 33 RECORD_FIELD_DEF@[41; 47)
34 NAME@[41; 42) 34 NAME@[41; 42)
35 IDENT@[41; 42) "b" 35 IDENT@[41; 42) "b"
36 COLON@[42; 43) ":" 36 COLON@[42; 43) ":"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0083_struct_items.txt b/crates/ra_syntax/test_data/parser/inline/ok/0083_struct_items.txt
index 62d93512b..e909f2b78 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0083_struct_items.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0083_struct_items.txt
@@ -12,7 +12,7 @@ SOURCE_FILE@[0; 106)
12 NAME@[19; 22) 12 NAME@[19; 22)
13 IDENT@[19; 22) "Foo" 13 IDENT@[19; 22) "Foo"
14 WHITESPACE@[22; 23) " " 14 WHITESPACE@[22; 23) " "
15 NAMED_FIELD_DEF_LIST@[23; 25) 15 RECORD_FIELD_DEF_LIST@[23; 25)
16 L_CURLY@[23; 24) "{" 16 L_CURLY@[23; 24) "{"
17 R_CURLY@[24; 25) "}" 17 R_CURLY@[24; 25) "}"
18 WHITESPACE@[25; 26) "\n" 18 WHITESPACE@[25; 26) "\n"
@@ -21,7 +21,7 @@ SOURCE_FILE@[0; 106)
21 WHITESPACE@[32; 33) " " 21 WHITESPACE@[32; 33) " "
22 NAME@[33; 36) 22 NAME@[33; 36)
23 IDENT@[33; 36) "Foo" 23 IDENT@[33; 36) "Foo"
24 POS_FIELD_DEF_LIST@[36; 38) 24 TUPLE_FIELD_DEF_LIST@[36; 38)
25 L_PAREN@[36; 37) "(" 25 L_PAREN@[36; 37) "("
26 R_PAREN@[37; 38) ")" 26 R_PAREN@[37; 38) ")"
27 SEMI@[38; 39) ";" 27 SEMI@[38; 39) ";"
@@ -31,9 +31,9 @@ SOURCE_FILE@[0; 106)
31 WHITESPACE@[46; 47) " " 31 WHITESPACE@[46; 47) " "
32 NAME@[47; 50) 32 NAME@[47; 50)
33 IDENT@[47; 50) "Foo" 33 IDENT@[47; 50) "Foo"
34 POS_FIELD_DEF_LIST@[50; 65) 34 TUPLE_FIELD_DEF_LIST@[50; 65)
35 L_PAREN@[50; 51) "(" 35 L_PAREN@[50; 51) "("
36 POS_FIELD_DEF@[51; 57) 36 TUPLE_FIELD_DEF@[51; 57)
37 PATH_TYPE@[51; 57) 37 PATH_TYPE@[51; 57)
38 PATH@[51; 57) 38 PATH@[51; 57)
39 PATH_SEGMENT@[51; 57) 39 PATH_SEGMENT@[51; 57)
@@ -41,7 +41,7 @@ SOURCE_FILE@[0; 106)
41 IDENT@[51; 57) "String" 41 IDENT@[51; 57) "String"
42 COMMA@[57; 58) "," 42 COMMA@[57; 58) ","
43 WHITESPACE@[58; 59) " " 43 WHITESPACE@[58; 59) " "
44 POS_FIELD_DEF@[59; 64) 44 TUPLE_FIELD_DEF@[59; 64)
45 PATH_TYPE@[59; 64) 45 PATH_TYPE@[59; 64)
46 PATH@[59; 64) 46 PATH@[59; 64)
47 PATH_SEGMENT@[59; 64) 47 PATH_SEGMENT@[59; 64)
@@ -56,10 +56,10 @@ SOURCE_FILE@[0; 106)
56 NAME@[74; 77) 56 NAME@[74; 77)
57 IDENT@[74; 77) "Foo" 57 IDENT@[74; 77) "Foo"
58 WHITESPACE@[77; 78) " " 58 WHITESPACE@[77; 78) " "
59 NAMED_FIELD_DEF_LIST@[78; 105) 59 RECORD_FIELD_DEF_LIST@[78; 105)
60 L_CURLY@[78; 79) "{" 60 L_CURLY@[78; 79) "{"
61 WHITESPACE@[79; 84) "\n " 61 WHITESPACE@[79; 84) "\n "
62 NAMED_FIELD_DEF@[84; 90) 62 RECORD_FIELD_DEF@[84; 90)
63 NAME@[84; 85) 63 NAME@[84; 85)
64 IDENT@[84; 85) "a" 64 IDENT@[84; 85) "a"
65 COLON@[85; 86) ":" 65 COLON@[85; 86) ":"
@@ -71,7 +71,7 @@ SOURCE_FILE@[0; 106)
71 IDENT@[87; 90) "i32" 71 IDENT@[87; 90) "i32"
72 COMMA@[90; 91) "," 72 COMMA@[90; 91) ","
73 WHITESPACE@[91; 96) "\n " 73 WHITESPACE@[91; 96) "\n "
74 NAMED_FIELD_DEF@[96; 102) 74 RECORD_FIELD_DEF@[96; 102)
75 NAME@[96; 97) 75 NAME@[96; 97)
76 IDENT@[96; 97) "b" 76 IDENT@[96; 97) "b"
77 COLON@[97; 98) ":" 77 COLON@[97; 98) ":"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0102_field_pat_list.rs b/crates/ra_syntax/test_data/parser/inline/ok/0102_record_field_pat_list.rs
index da3412fa8..da3412fa8 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0102_field_pat_list.rs
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0102_record_field_pat_list.rs
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0102_field_pat_list.txt b/crates/ra_syntax/test_data/parser/inline/ok/0102_record_field_pat_list.txt
index a2af4fc60..22db72c12 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0102_field_pat_list.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0102_record_field_pat_list.txt
@@ -14,13 +14,13 @@ SOURCE_FILE@[0; 119)
14 LET_STMT@[15; 29) 14 LET_STMT@[15; 29)
15 LET_KW@[15; 18) "let" 15 LET_KW@[15; 18) "let"
16 WHITESPACE@[18; 19) " " 16 WHITESPACE@[18; 19) " "
17 STRUCT_PAT@[19; 23) 17 RECORD_PAT@[19; 23)
18 PATH@[19; 20) 18 PATH@[19; 20)
19 PATH_SEGMENT@[19; 20) 19 PATH_SEGMENT@[19; 20)
20 NAME_REF@[19; 20) 20 NAME_REF@[19; 20)
21 IDENT@[19; 20) "S" 21 IDENT@[19; 20) "S"
22 WHITESPACE@[20; 21) " " 22 WHITESPACE@[20; 21) " "
23 FIELD_PAT_LIST@[21; 23) 23 RECORD_FIELD_PAT_LIST@[21; 23)
24 L_CURLY@[21; 22) "{" 24 L_CURLY@[21; 22) "{"
25 R_CURLY@[22; 23) "}" 25 R_CURLY@[22; 23) "}"
26 WHITESPACE@[23; 24) " " 26 WHITESPACE@[23; 24) " "
@@ -34,13 +34,13 @@ SOURCE_FILE@[0; 119)
34 LET_STMT@[34; 62) 34 LET_STMT@[34; 62)
35 LET_KW@[34; 37) "let" 35 LET_KW@[34; 37) "let"
36 WHITESPACE@[37; 38) " " 36 WHITESPACE@[37; 38) " "
37 STRUCT_PAT@[38; 56) 37 RECORD_PAT@[38; 56)
38 PATH@[38; 39) 38 PATH@[38; 39)
39 PATH_SEGMENT@[38; 39) 39 PATH_SEGMENT@[38; 39)
40 NAME_REF@[38; 39) 40 NAME_REF@[38; 39)
41 IDENT@[38; 39) "S" 41 IDENT@[38; 39) "S"
42 WHITESPACE@[39; 40) " " 42 WHITESPACE@[39; 40) " "
43 FIELD_PAT_LIST@[40; 56) 43 RECORD_FIELD_PAT_LIST@[40; 56)
44 L_CURLY@[40; 41) "{" 44 L_CURLY@[40; 41) "{"
45 WHITESPACE@[41; 42) " " 45 WHITESPACE@[41; 42) " "
46 BIND_PAT@[42; 43) 46 BIND_PAT@[42; 43)
@@ -68,16 +68,16 @@ SOURCE_FILE@[0; 119)
68 LET_STMT@[67; 90) 68 LET_STMT@[67; 90)
69 LET_KW@[67; 70) "let" 69 LET_KW@[67; 70) "let"
70 WHITESPACE@[70; 71) " " 70 WHITESPACE@[70; 71) " "
71 STRUCT_PAT@[71; 84) 71 RECORD_PAT@[71; 84)
72 PATH@[71; 72) 72 PATH@[71; 72)
73 PATH_SEGMENT@[71; 72) 73 PATH_SEGMENT@[71; 72)
74 NAME_REF@[71; 72) 74 NAME_REF@[71; 72)
75 IDENT@[71; 72) "S" 75 IDENT@[71; 72) "S"
76 WHITESPACE@[72; 73) " " 76 WHITESPACE@[72; 73) " "
77 FIELD_PAT_LIST@[73; 84) 77 RECORD_FIELD_PAT_LIST@[73; 84)
78 L_CURLY@[73; 74) "{" 78 L_CURLY@[73; 74) "{"
79 WHITESPACE@[74; 75) " " 79 WHITESPACE@[74; 75) " "
80 FIELD_PAT@[75; 79) 80 RECORD_FIELD_PAT@[75; 79)
81 NAME@[75; 76) 81 NAME@[75; 76)
82 IDENT@[75; 76) "h" 82 IDENT@[75; 76) "h"
83 COLON@[76; 77) ":" 83 COLON@[76; 77) ":"
@@ -99,16 +99,16 @@ SOURCE_FILE@[0; 119)
99 LET_STMT@[95; 116) 99 LET_STMT@[95; 116)
100 LET_KW@[95; 98) "let" 100 LET_KW@[95; 98) "let"
101 WHITESPACE@[98; 99) " " 101 WHITESPACE@[98; 99) " "
102 STRUCT_PAT@[99; 110) 102 RECORD_PAT@[99; 110)
103 PATH@[99; 100) 103 PATH@[99; 100)
104 PATH_SEGMENT@[99; 100) 104 PATH_SEGMENT@[99; 100)
105 NAME_REF@[99; 100) 105 NAME_REF@[99; 100)
106 IDENT@[99; 100) "S" 106 IDENT@[99; 100) "S"
107 WHITESPACE@[100; 101) " " 107 WHITESPACE@[100; 101) " "
108 FIELD_PAT_LIST@[101; 110) 108 RECORD_FIELD_PAT_LIST@[101; 110)
109 L_CURLY@[101; 102) "{" 109 L_CURLY@[101; 102) "{"
110 WHITESPACE@[102; 103) " " 110 WHITESPACE@[102; 103) " "
111 FIELD_PAT@[103; 107) 111 RECORD_FIELD_PAT@[103; 107)
112 NAME@[103; 104) 112 NAME@[103; 104)
113 IDENT@[103; 104) "h" 113 IDENT@[103; 104) "h"
114 COLON@[104; 105) ":" 114 COLON@[104; 105) ":"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.rs b/crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.rs
index 5a93469af..820a9e72c 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.rs
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.rs
@@ -5,5 +5,4 @@ fn main() {
5 let ref mut d = (); 5 let ref mut d = ();
6 let e @ _ = (); 6 let e @ _ = ();
7 let ref mut f @ g @ _ = (); 7 let ref mut f @ g @ _ = ();
8 let box i = Box::new(1i32);
9} 8}
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.txt b/crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.txt
index 189254a19..ab0f88507 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 178) 1SOURCE_FILE@[0; 146)
2 FN_DEF@[0; 177) 2 FN_DEF@[0; 145)
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,7 +8,7 @@ SOURCE_FILE@[0; 178)
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@[10; 177) 11 BLOCK@[10; 145)
12 L_CURLY@[10; 11) "{" 12 L_CURLY@[10; 11) "{"
13 WHITESPACE@[11; 16) "\n " 13 WHITESPACE@[11; 16) "\n "
14 LET_STMT@[16; 27) 14 LET_STMT@[16; 27)
@@ -122,35 +122,6 @@ SOURCE_FILE@[0; 178)
122 L_PAREN@[140; 141) "(" 122 L_PAREN@[140; 141) "("
123 R_PAREN@[141; 142) ")" 123 R_PAREN@[141; 142) ")"
124 SEMI@[142; 143) ";" 124 SEMI@[142; 143) ";"
125 WHITESPACE@[143; 148) "\n " 125 WHITESPACE@[143; 144) "\n"
126 LET_STMT@[148; 175) 126 R_CURLY@[144; 145) "}"
127 LET_KW@[148; 151) "let" 127 WHITESPACE@[145; 146) "\n"
128 WHITESPACE@[151; 152) " "
129 BIND_PAT@[152; 157)
130 BOX_KW@[152; 155) "box"
131 WHITESPACE@[155; 156) " "
132 NAME@[156; 157)
133 IDENT@[156; 157) "i"
134 WHITESPACE@[157; 158) " "
135 EQ@[158; 159) "="
136 WHITESPACE@[159; 160) " "
137 CALL_EXPR@[160; 174)
138 PATH_EXPR@[160; 168)
139 PATH@[160; 168)
140 PATH@[160; 163)
141 PATH_SEGMENT@[160; 163)
142 NAME_REF@[160; 163)
143 IDENT@[160; 163) "Box"
144 COLONCOLON@[163; 165) "::"
145 PATH_SEGMENT@[165; 168)
146 NAME_REF@[165; 168)
147 IDENT@[165; 168) "new"
148 ARG_LIST@[168; 174)
149 L_PAREN@[168; 169) "("
150 LITERAL@[169; 173)
151 INT_NUMBER@[169; 173) "1i32"
152 R_PAREN@[173; 174) ")"
153 SEMI@[174; 175) ";"
154 WHITESPACE@[175; 176) "\n"
155 R_CURLY@[176; 177) "}"
156 WHITESPACE@[177; 178) "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0114_tuple_struct_where.txt b/crates/ra_syntax/test_data/parser/inline/ok/0114_tuple_struct_where.txt
index 8534592b9..f5de01405 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0114_tuple_struct_where.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0114_tuple_struct_where.txt
@@ -10,9 +10,9 @@ SOURCE_FILE@[0; 53)
10 NAME@[12; 13) 10 NAME@[12; 13)
11 IDENT@[12; 13) "T" 11 IDENT@[12; 13) "T"
12 R_ANGLE@[13; 14) ">" 12 R_ANGLE@[13; 14) ">"
13 POS_FIELD_DEF_LIST@[14; 17) 13 TUPLE_FIELD_DEF_LIST@[14; 17)
14 L_PAREN@[14; 15) "(" 14 L_PAREN@[14; 15) "("
15 POS_FIELD_DEF@[15; 16) 15 TUPLE_FIELD_DEF@[15; 16)
16 PATH_TYPE@[15; 16) 16 PATH_TYPE@[15; 16)
17 PATH@[15; 16) 17 PATH@[15; 16)
18 PATH_SEGMENT@[15; 16) 18 PATH_SEGMENT@[15; 16)
@@ -51,9 +51,9 @@ SOURCE_FILE@[0; 53)
51 NAME@[46; 47) 51 NAME@[46; 47)
52 IDENT@[46; 47) "T" 52 IDENT@[46; 47) "T"
53 R_ANGLE@[47; 48) ">" 53 R_ANGLE@[47; 48) ">"
54 POS_FIELD_DEF_LIST@[48; 51) 54 TUPLE_FIELD_DEF_LIST@[48; 51)
55 L_PAREN@[48; 49) "(" 55 L_PAREN@[48; 49) "("
56 POS_FIELD_DEF@[49; 50) 56 TUPLE_FIELD_DEF@[49; 50)
57 PATH_TYPE@[49; 50) 57 PATH_TYPE@[49; 50)
58 PATH@[49; 50) 58 PATH@[49; 50)
59 PATH_SEGMENT@[49; 50) 59 PATH_SEGMENT@[49; 50)
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0115_pos_field_attrs.rs b/crates/ra_syntax/test_data/parser/inline/ok/0115_tuple_field_attrs.rs
index 635b9ac21..635b9ac21 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0115_pos_field_attrs.rs
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0115_tuple_field_attrs.rs
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0115_pos_field_attrs.txt b/crates/ra_syntax/test_data/parser/inline/ok/0115_tuple_field_attrs.txt
index 6dd3a9b93..cb6d9f76d 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0115_pos_field_attrs.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0115_tuple_field_attrs.txt
@@ -5,10 +5,10 @@ SOURCE_FILE@[0; 60)
5 NAME@[7; 8) 5 NAME@[7; 8)
6 IDENT@[7; 8) "S" 6 IDENT@[7; 8) "S"
7 WHITESPACE@[8; 9) " " 7 WHITESPACE@[8; 9) " "
8 POS_FIELD_DEF_LIST@[9; 58) 8 TUPLE_FIELD_DEF_LIST@[9; 58)
9 L_PAREN@[9; 10) "(" 9 L_PAREN@[9; 10) "("
10 WHITESPACE@[10; 15) "\n " 10 WHITESPACE@[10; 15) "\n "
11 POS_FIELD_DEF@[15; 55) 11 TUPLE_FIELD_DEF@[15; 55)
12 ATTR@[15; 43) 12 ATTR@[15; 43)
13 POUND@[15; 16) "#" 13 POUND@[15; 16) "#"
14 TOKEN_TREE@[16; 43) 14 TOKEN_TREE@[16; 43)
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0125_struct_literal_field_with_attr.rs b/crates/ra_syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.rs
index a6c7760c7..a6c7760c7 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0125_struct_literal_field_with_attr.rs
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.rs
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0125_struct_literal_field_with_attr.txt b/crates/ra_syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.txt
index f9c5ec124..8fdf3756f 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0125_struct_literal_field_with_attr.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.txt
@@ -11,16 +11,16 @@ SOURCE_FILE@[0; 46)
11 BLOCK@[10; 45) 11 BLOCK@[10; 45)
12 L_CURLY@[10; 11) "{" 12 L_CURLY@[10; 11) "{"
13 WHITESPACE@[11; 16) "\n " 13 WHITESPACE@[11; 16) "\n "
14 STRUCT_LIT@[16; 43) 14 RECORD_LIT@[16; 43)
15 PATH@[16; 17) 15 PATH@[16; 17)
16 PATH_SEGMENT@[16; 17) 16 PATH_SEGMENT@[16; 17)
17 NAME_REF@[16; 17) 17 NAME_REF@[16; 17)
18 IDENT@[16; 17) "S" 18 IDENT@[16; 17) "S"
19 WHITESPACE@[17; 18) " " 19 WHITESPACE@[17; 18) " "
20 NAMED_FIELD_LIST@[18; 43) 20 RECORD_FIELD_LIST@[18; 43)
21 L_CURLY@[18; 19) "{" 21 L_CURLY@[18; 19) "{"
22 WHITESPACE@[19; 20) " " 22 WHITESPACE@[19; 20) " "
23 NAMED_FIELD@[20; 41) 23 RECORD_FIELD@[20; 41)
24 ATTR@[20; 32) 24 ATTR@[20; 32)
25 POUND@[20; 21) "#" 25 POUND@[20; 21) "#"
26 TOKEN_TREE@[21; 32) 26 TOKEN_TREE@[21; 32)
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0134_nocontentexpr_after_item.txt b/crates/ra_syntax/test_data/parser/inline/ok/0134_nocontentexpr_after_item.txt
index 50d3b5def..64cbf4632 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0134_nocontentexpr_after_item.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0134_nocontentexpr_after_item.txt
@@ -53,7 +53,7 @@ SOURCE_FILE@[0; 111)
53 NAME@[103; 104) 53 NAME@[103; 104)
54 IDENT@[103; 104) "S" 54 IDENT@[103; 104) "S"
55 WHITESPACE@[104; 105) " " 55 WHITESPACE@[104; 105) " "
56 NAMED_FIELD_DEF_LIST@[105; 107) 56 RECORD_FIELD_DEF_LIST@[105; 107)
57 L_CURLY@[105; 106) "{" 57 L_CURLY@[105; 106) "{"
58 R_CURLY@[106; 107) "}" 58 R_CURLY@[106; 107) "}"
59 SEMI@[107; 108) ";" 59 SEMI@[107; 108) ";"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0138_expression_after_block.txt b/crates/ra_syntax/test_data/parser/inline/ok/0138_expression_after_block.txt
index 08128f365..c4db9da40 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0138_expression_after_block.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0138_expression_after_block.txt
@@ -22,14 +22,14 @@ SOURCE_FILE@[0; 52)
22 WHITESPACE@[23; 24) " " 22 WHITESPACE@[23; 24) " "
23 EQ@[24; 25) "=" 23 EQ@[24; 25) "="
24 WHITESPACE@[25; 26) " " 24 WHITESPACE@[25; 26) " "
25 STRUCT_LIT@[26; 33) 25 RECORD_LIT@[26; 33)
26 PATH@[26; 27) 26 PATH@[26; 27)
27 PATH_SEGMENT@[26; 27) 27 PATH_SEGMENT@[26; 27)
28 NAME_REF@[26; 27) 28 NAME_REF@[26; 27)
29 IDENT@[26; 27) "F" 29 IDENT@[26; 27) "F"
30 NAMED_FIELD_LIST@[27; 33) 30 RECORD_FIELD_LIST@[27; 33)
31 L_CURLY@[27; 28) "{" 31 L_CURLY@[27; 28) "{"
32 NAMED_FIELD@[28; 32) 32 RECORD_FIELD@[28; 32)
33 NAME_REF@[28; 29) 33 NAME_REF@[28; 29)
34 IDENT@[28; 29) "x" 34 IDENT@[28; 29) "x"
35 COLON@[29; 30) ":" 35 COLON@[29; 30) ":"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.rs b/crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.rs
new file mode 100644
index 000000000..9d458aa1e
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.rs
@@ -0,0 +1,5 @@
1fn main() {
2 let box i = ();
3 let box Outer { box i, j: box Inner(box &x) } = ();
4 let box ref mut i = ();
5}
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.txt b/crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.txt
new file mode 100644
index 000000000..f0db58143
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.txt
@@ -0,0 +1,109 @@
1SOURCE_FILE@[0; 118)
2 FN_DEF@[0; 117)
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@[10; 117)
12 L_CURLY@[10; 11) "{"
13 WHITESPACE@[11; 16) "\n "
14 LET_STMT@[16; 31)
15 LET_KW@[16; 19) "let"
16 WHITESPACE@[19; 20) " "
17 BOX_PAT@[20; 25)
18 BOX_KW@[20; 23) "box"
19 WHITESPACE@[23; 24) " "
20 BIND_PAT@[24; 25)
21 NAME@[24; 25)
22 IDENT@[24; 25) "i"
23 WHITESPACE@[25; 26) " "
24 EQ@[26; 27) "="
25 WHITESPACE@[27; 28) " "
26 TUPLE_EXPR@[28; 30)
27 L_PAREN@[28; 29) "("
28 R_PAREN@[29; 30) ")"
29 SEMI@[30; 31) ";"
30 WHITESPACE@[31; 36) "\n "
31 LET_STMT@[36; 87)
32 LET_KW@[36; 39) "let"
33 WHITESPACE@[39; 40) " "
34 BOX_PAT@[40; 81)
35 BOX_KW@[40; 43) "box"
36 WHITESPACE@[43; 44) " "
37 RECORD_PAT@[44; 81)
38 PATH@[44; 49)
39 PATH_SEGMENT@[44; 49)
40 NAME_REF@[44; 49)
41 IDENT@[44; 49) "Outer"
42 WHITESPACE@[49; 50) " "
43 RECORD_FIELD_PAT_LIST@[50; 81)
44 L_CURLY@[50; 51) "{"
45 WHITESPACE@[51; 52) " "
46 BOX_PAT@[52; 57)
47 BOX_KW@[52; 55) "box"
48 WHITESPACE@[55; 56) " "
49 BIND_PAT@[56; 57)
50 NAME@[56; 57)
51 IDENT@[56; 57) "i"
52 COMMA@[57; 58) ","
53 WHITESPACE@[58; 59) " "
54 RECORD_FIELD_PAT@[59; 79)
55 NAME@[59; 60)
56 IDENT@[59; 60) "j"
57 COLON@[60; 61) ":"
58 WHITESPACE@[61; 62) " "
59 BOX_PAT@[62; 79)
60 BOX_KW@[62; 65) "box"
61 WHITESPACE@[65; 66) " "
62 TUPLE_STRUCT_PAT@[66; 79)
63 PATH@[66; 71)
64 PATH_SEGMENT@[66; 71)
65 NAME_REF@[66; 71)
66 IDENT@[66; 71) "Inner"
67 L_PAREN@[71; 72) "("
68 BOX_PAT@[72; 78)
69 BOX_KW@[72; 75) "box"
70 WHITESPACE@[75; 76) " "
71 REF_PAT@[76; 78)
72 AMP@[76; 77) "&"
73 BIND_PAT@[77; 78)
74 NAME@[77; 78)
75 IDENT@[77; 78) "x"
76 R_PAREN@[78; 79) ")"
77 WHITESPACE@[79; 80) " "
78 R_CURLY@[80; 81) "}"
79 WHITESPACE@[81; 82) " "
80 EQ@[82; 83) "="
81 WHITESPACE@[83; 84) " "
82 TUPLE_EXPR@[84; 86)
83 L_PAREN@[84; 85) "("
84 R_PAREN@[85; 86) ")"
85 SEMI@[86; 87) ";"
86 WHITESPACE@[87; 92) "\n "
87 LET_STMT@[92; 115)
88 LET_KW@[92; 95) "let"
89 WHITESPACE@[95; 96) " "
90 BOX_PAT@[96; 109)
91 BOX_KW@[96; 99) "box"
92 WHITESPACE@[99; 100) " "
93 BIND_PAT@[100; 109)
94 REF_KW@[100; 103) "ref"
95 WHITESPACE@[103; 104) " "
96 MUT_KW@[104; 107) "mut"
97 WHITESPACE@[107; 108) " "
98 NAME@[108; 109)
99 IDENT@[108; 109) "i"
100 WHITESPACE@[109; 110) " "
101 EQ@[110; 111) "="
102 WHITESPACE@[111; 112) " "
103 TUPLE_EXPR@[112; 114)
104 L_PAREN@[112; 113) "("
105 R_PAREN@[113; 114) ")"
106 SEMI@[114; 115) ";"
107 WHITESPACE@[115; 116) "\n"
108 R_CURLY@[116; 117) "}"
109 WHITESPACE@[117; 118) "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0001_struct_item.txt b/crates/ra_syntax/test_data/parser/ok/0001_struct_item.txt
index c6653cf25..fdc2d6768 100644
--- a/crates/ra_syntax/test_data/parser/ok/0001_struct_item.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0001_struct_item.txt
@@ -20,10 +20,10 @@ SOURCE_FILE@[0; 32)
20 IDENT@[12; 16) "Copy" 20 IDENT@[12; 16) "Copy"
21 R_ANGLE@[16; 17) ">" 21 R_ANGLE@[16; 17) ">"
22 WHITESPACE@[17; 18) " " 22 WHITESPACE@[17; 18) " "
23 NAMED_FIELD_DEF_LIST@[18; 31) 23 RECORD_FIELD_DEF_LIST@[18; 31)
24 L_CURLY@[18; 19) "{" 24 L_CURLY@[18; 19) "{"
25 WHITESPACE@[19; 24) "\n " 25 WHITESPACE@[19; 24) "\n "
26 NAMED_FIELD_DEF@[24; 28) 26 RECORD_FIELD_DEF@[24; 28)
27 NAME@[24; 25) 27 NAME@[24; 25)
28 IDENT@[24; 25) "f" 28 IDENT@[24; 25) "f"
29 COLON@[25; 26) ":" 29 COLON@[25; 26) ":"
diff --git a/crates/ra_syntax/test_data/parser/ok/0002_struct_item_field.txt b/crates/ra_syntax/test_data/parser/ok/0002_struct_item_field.txt
index d0565ea83..ef34702fd 100644
--- a/crates/ra_syntax/test_data/parser/ok/0002_struct_item_field.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0002_struct_item_field.txt
@@ -5,10 +5,10 @@ SOURCE_FILE@[0; 25)
5 NAME@[7; 8) 5 NAME@[7; 8)
6 IDENT@[7; 8) "S" 6 IDENT@[7; 8) "S"
7 WHITESPACE@[8; 9) " " 7 WHITESPACE@[8; 9) " "
8 NAMED_FIELD_DEF_LIST@[9; 25) 8 RECORD_FIELD_DEF_LIST@[9; 25)
9 L_CURLY@[9; 10) "{" 9 L_CURLY@[9; 10) "{"
10 WHITESPACE@[10; 15) "\n " 10 WHITESPACE@[10; 15) "\n "
11 NAMED_FIELD_DEF@[15; 23) 11 RECORD_FIELD_DEF@[15; 23)
12 NAME@[15; 18) 12 NAME@[15; 18)
13 IDENT@[15; 18) "foo" 13 IDENT@[15; 18) "foo"
14 COLON@[18; 19) ":" 14 COLON@[18; 19) ":"
diff --git a/crates/ra_syntax/test_data/parser/ok/0008_mod_item.txt b/crates/ra_syntax/test_data/parser/ok/0008_mod_item.txt
index 9152d6eb6..5c16d0be6 100644
--- a/crates/ra_syntax/test_data/parser/ok/0008_mod_item.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0008_mod_item.txt
@@ -46,7 +46,7 @@ SOURCE_FILE@[0; 118)
46 NAME@[59; 60) 46 NAME@[59; 60)
47 IDENT@[59; 60) "S" 47 IDENT@[59; 60) "S"
48 WHITESPACE@[60; 61) " " 48 WHITESPACE@[60; 61) " "
49 NAMED_FIELD_DEF_LIST@[61; 63) 49 RECORD_FIELD_DEF_LIST@[61; 63)
50 L_CURLY@[61; 62) "{" 50 L_CURLY@[61; 62) "{"
51 R_CURLY@[62; 63) "}" 51 R_CURLY@[62; 63) "}"
52 WHITESPACE@[63; 64) "\n" 52 WHITESPACE@[63; 64) "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0016_struct_flavors.txt b/crates/ra_syntax/test_data/parser/ok/0016_struct_flavors.txt
index ac44093e8..3fbd14d7b 100644
--- a/crates/ra_syntax/test_data/parser/ok/0016_struct_flavors.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0016_struct_flavors.txt
@@ -12,7 +12,7 @@ SOURCE_FILE@[0; 97)
12 NAME@[17; 18) 12 NAME@[17; 18)
13 IDENT@[17; 18) "B" 13 IDENT@[17; 18) "B"
14 WHITESPACE@[18; 19) " " 14 WHITESPACE@[18; 19) " "
15 NAMED_FIELD_DEF_LIST@[19; 21) 15 RECORD_FIELD_DEF_LIST@[19; 21)
16 L_CURLY@[19; 20) "{" 16 L_CURLY@[19; 20) "{"
17 R_CURLY@[20; 21) "}" 17 R_CURLY@[20; 21) "}"
18 WHITESPACE@[21; 22) "\n" 18 WHITESPACE@[21; 22) "\n"
@@ -21,7 +21,7 @@ SOURCE_FILE@[0; 97)
21 WHITESPACE@[28; 29) " " 21 WHITESPACE@[28; 29) " "
22 NAME@[29; 30) 22 NAME@[29; 30)
23 IDENT@[29; 30) "C" 23 IDENT@[29; 30) "C"
24 POS_FIELD_DEF_LIST@[30; 32) 24 TUPLE_FIELD_DEF_LIST@[30; 32)
25 L_PAREN@[30; 31) "(" 25 L_PAREN@[30; 31) "("
26 R_PAREN@[31; 32) ")" 26 R_PAREN@[31; 32) ")"
27 SEMI@[32; 33) ";" 27 SEMI@[32; 33) ";"
@@ -32,10 +32,10 @@ SOURCE_FILE@[0; 97)
32 NAME@[42; 43) 32 NAME@[42; 43)
33 IDENT@[42; 43) "D" 33 IDENT@[42; 43) "D"
34 WHITESPACE@[43; 44) " " 34 WHITESPACE@[43; 44) " "
35 NAMED_FIELD_DEF_LIST@[44; 74) 35 RECORD_FIELD_DEF_LIST@[44; 74)
36 L_CURLY@[44; 45) "{" 36 L_CURLY@[44; 45) "{"
37 WHITESPACE@[45; 50) "\n " 37 WHITESPACE@[45; 50) "\n "
38 NAMED_FIELD_DEF@[50; 56) 38 RECORD_FIELD_DEF@[50; 56)
39 NAME@[50; 51) 39 NAME@[50; 51)
40 IDENT@[50; 51) "a" 40 IDENT@[50; 51) "a"
41 COLON@[51; 52) ":" 41 COLON@[51; 52) ":"
@@ -47,7 +47,7 @@ SOURCE_FILE@[0; 97)
47 IDENT@[53; 56) "u32" 47 IDENT@[53; 56) "u32"
48 COMMA@[56; 57) "," 48 COMMA@[56; 57) ","
49 WHITESPACE@[57; 62) "\n " 49 WHITESPACE@[57; 62) "\n "
50 NAMED_FIELD_DEF@[62; 72) 50 RECORD_FIELD_DEF@[62; 72)
51 VISIBILITY@[62; 65) 51 VISIBILITY@[62; 65)
52 PUB_KW@[62; 65) "pub" 52 PUB_KW@[62; 65) "pub"
53 WHITESPACE@[65; 66) " " 53 WHITESPACE@[65; 66) " "
@@ -68,9 +68,9 @@ SOURCE_FILE@[0; 97)
68 WHITESPACE@[82; 83) " " 68 WHITESPACE@[82; 83) " "
69 NAME@[83; 84) 69 NAME@[83; 84)
70 IDENT@[83; 84) "E" 70 IDENT@[83; 84) "E"
71 POS_FIELD_DEF_LIST@[84; 95) 71 TUPLE_FIELD_DEF_LIST@[84; 95)
72 L_PAREN@[84; 85) "(" 72 L_PAREN@[84; 85) "("
73 POS_FIELD_DEF@[85; 90) 73 TUPLE_FIELD_DEF@[85; 90)
74 VISIBILITY@[85; 88) 74 VISIBILITY@[85; 88)
75 PUB_KW@[85; 88) "pub" 75 PUB_KW@[85; 88) "pub"
76 WHITESPACE@[88; 89) " " 76 WHITESPACE@[88; 89) " "
@@ -81,7 +81,7 @@ SOURCE_FILE@[0; 97)
81 IDENT@[89; 90) "x" 81 IDENT@[89; 90) "x"
82 COMMA@[90; 91) "," 82 COMMA@[90; 91) ","
83 WHITESPACE@[91; 92) " " 83 WHITESPACE@[91; 92) " "
84 POS_FIELD_DEF@[92; 93) 84 TUPLE_FIELD_DEF@[92; 93)
85 PATH_TYPE@[92; 93) 85 PATH_TYPE@[92; 93)
86 PATH@[92; 93) 86 PATH@[92; 93)
87 PATH_SEGMENT@[92; 93) 87 PATH_SEGMENT@[92; 93)
diff --git a/crates/ra_syntax/test_data/parser/ok/0018_struct_type_params.txt b/crates/ra_syntax/test_data/parser/ok/0018_struct_type_params.txt
index 3f06f20f9..1e4e58dd3 100644
--- a/crates/ra_syntax/test_data/parser/ok/0018_struct_type_params.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0018_struct_type_params.txt
@@ -23,9 +23,9 @@ SOURCE_FILE@[0; 290)
23 NAME@[24; 25) 23 NAME@[24; 25)
24 IDENT@[24; 25) "T" 24 IDENT@[24; 25) "T"
25 R_ANGLE@[25; 26) ">" 25 R_ANGLE@[25; 26) ">"
26 POS_FIELD_DEF_LIST@[26; 31) 26 TUPLE_FIELD_DEF_LIST@[26; 31)
27 L_PAREN@[26; 27) "(" 27 L_PAREN@[26; 27) "("
28 POS_FIELD_DEF@[27; 30) 28 TUPLE_FIELD_DEF@[27; 30)
29 PATH_TYPE@[27; 30) 29 PATH_TYPE@[27; 30)
30 PATH@[27; 30) 30 PATH@[27; 30)
31 PATH_SEGMENT@[27; 30) 31 PATH_SEGMENT@[27; 30)
@@ -46,10 +46,10 @@ SOURCE_FILE@[0; 290)
46 IDENT@[43; 44) "T" 46 IDENT@[43; 44) "T"
47 R_ANGLE@[44; 45) ">" 47 R_ANGLE@[44; 45) ">"
48 WHITESPACE@[45; 46) " " 48 WHITESPACE@[45; 46) " "
49 NAMED_FIELD_DEF_LIST@[46; 56) 49 RECORD_FIELD_DEF_LIST@[46; 56)
50 L_CURLY@[46; 47) "{" 50 L_CURLY@[46; 47) "{"
51 WHITESPACE@[47; 48) " " 51 WHITESPACE@[47; 48) " "
52 NAMED_FIELD_DEF@[48; 54) 52 RECORD_FIELD_DEF@[48; 54)
53 NAME@[48; 49) 53 NAME@[48; 49)
54 IDENT@[48; 49) "u" 54 IDENT@[48; 49) "u"
55 COLON@[49; 50) ":" 55 COLON@[49; 50) ":"
diff --git a/crates/ra_syntax/test_data/parser/ok/0019_enums.txt b/crates/ra_syntax/test_data/parser/ok/0019_enums.txt
index 37753a7d0..9d4a47a51 100644
--- a/crates/ra_syntax/test_data/parser/ok/0019_enums.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0019_enums.txt
@@ -86,10 +86,10 @@ SOURCE_FILE@[0; 182)
86 NAME@[101; 102) 86 NAME@[101; 102)
87 IDENT@[101; 102) "C" 87 IDENT@[101; 102) "C"
88 WHITESPACE@[102; 103) " " 88 WHITESPACE@[102; 103) " "
89 NAMED_FIELD_DEF_LIST@[103; 146) 89 RECORD_FIELD_DEF_LIST@[103; 146)
90 L_CURLY@[103; 104) "{" 90 L_CURLY@[103; 104) "{"
91 WHITESPACE@[104; 113) "\n " 91 WHITESPACE@[104; 113) "\n "
92 NAMED_FIELD_DEF@[113; 119) 92 RECORD_FIELD_DEF@[113; 119)
93 NAME@[113; 114) 93 NAME@[113; 114)
94 IDENT@[113; 114) "a" 94 IDENT@[113; 114) "a"
95 COLON@[114; 115) ":" 95 COLON@[114; 115) ":"
@@ -101,7 +101,7 @@ SOURCE_FILE@[0; 182)
101 IDENT@[116; 119) "u32" 101 IDENT@[116; 119) "u32"
102 COMMA@[119; 120) "," 102 COMMA@[119; 120) ","
103 WHITESPACE@[120; 129) "\n " 103 WHITESPACE@[120; 129) "\n "
104 NAMED_FIELD_DEF@[129; 139) 104 RECORD_FIELD_DEF@[129; 139)
105 VISIBILITY@[129; 132) 105 VISIBILITY@[129; 132)
106 PUB_KW@[129; 132) "pub" 106 PUB_KW@[129; 132) "pub"
107 WHITESPACE@[132; 133) " " 107 WHITESPACE@[132; 133) " "
@@ -123,7 +123,7 @@ SOURCE_FILE@[0; 182)
123 NAME@[152; 153) 123 NAME@[152; 153)
124 IDENT@[152; 153) "F" 124 IDENT@[152; 153) "F"
125 WHITESPACE@[153; 154) " " 125 WHITESPACE@[153; 154) " "
126 NAMED_FIELD_DEF_LIST@[154; 156) 126 RECORD_FIELD_DEF_LIST@[154; 156)
127 L_CURLY@[154; 155) "{" 127 L_CURLY@[154; 155) "{"
128 R_CURLY@[155; 156) "}" 128 R_CURLY@[155; 156) "}"
129 COMMA@[156; 157) "," 129 COMMA@[156; 157) ","
@@ -131,9 +131,9 @@ SOURCE_FILE@[0; 182)
131 ENUM_VARIANT@[162; 169) 131 ENUM_VARIANT@[162; 169)
132 NAME@[162; 163) 132 NAME@[162; 163)
133 IDENT@[162; 163) "D" 133 IDENT@[162; 163) "D"
134 POS_FIELD_DEF_LIST@[163; 169) 134 TUPLE_FIELD_DEF_LIST@[163; 169)
135 L_PAREN@[163; 164) "(" 135 L_PAREN@[163; 164) "("
136 POS_FIELD_DEF@[164; 167) 136 TUPLE_FIELD_DEF@[164; 167)
137 PATH_TYPE@[164; 167) 137 PATH_TYPE@[164; 167)
138 PATH@[164; 167) 138 PATH@[164; 167)
139 PATH_SEGMENT@[164; 167) 139 PATH_SEGMENT@[164; 167)
@@ -146,7 +146,7 @@ SOURCE_FILE@[0; 182)
146 ENUM_VARIANT@[175; 178) 146 ENUM_VARIANT@[175; 178)
147 NAME@[175; 176) 147 NAME@[175; 176)
148 IDENT@[175; 176) "E" 148 IDENT@[175; 176) "E"
149 POS_FIELD_DEF_LIST@[176; 178) 149 TUPLE_FIELD_DEF_LIST@[176; 178)
150 L_PAREN@[176; 177) "(" 150 L_PAREN@[176; 177) "("
151 R_PAREN@[177; 178) ")" 151 R_PAREN@[177; 178) ")"
152 COMMA@[178; 179) "," 152 COMMA@[178; 179) ","
diff --git a/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.txt b/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.txt
index c89b591e9..c13ebfe37 100644
--- a/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.txt
@@ -1564,10 +1564,10 @@ SOURCE_FILE@[0; 3813)
1564 LIFETIME@[2863; 2869) "\'union" 1564 LIFETIME@[2863; 2869) "\'union"
1565 R_ANGLE@[2869; 2870) ">" 1565 R_ANGLE@[2869; 2870) ">"
1566 WHITESPACE@[2870; 2871) " " 1566 WHITESPACE@[2870; 2871) " "
1567 NAMED_FIELD_DEF_LIST@[2871; 2904) 1567 RECORD_FIELD_DEF_LIST@[2871; 2904)
1568 L_CURLY@[2871; 2872) "{" 1568 L_CURLY@[2871; 2872) "{"
1569 WHITESPACE@[2872; 2873) " " 1569 WHITESPACE@[2872; 2873) " "
1570 NAMED_FIELD_DEF@[2873; 2901) 1570 RECORD_FIELD_DEF@[2873; 2901)
1571 NAME@[2873; 2878) 1571 NAME@[2873; 2878)
1572 IDENT@[2873; 2878) "union" 1572 IDENT@[2873; 2878) "union"
1573 COLON@[2878; 2879) ":" 1573 COLON@[2878; 2879) ":"
diff --git a/crates/ra_syntax/test_data/parser/ok/0040_raw_struct_item_field.txt b/crates/ra_syntax/test_data/parser/ok/0040_raw_struct_item_field.txt
index 3c717555d..05f2c656f 100644
--- a/crates/ra_syntax/test_data/parser/ok/0040_raw_struct_item_field.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0040_raw_struct_item_field.txt
@@ -5,10 +5,10 @@ SOURCE_FILE@[0; 27)
5 NAME@[7; 8) 5 NAME@[7; 8)
6 IDENT@[7; 8) "S" 6 IDENT@[7; 8) "S"
7 WHITESPACE@[8; 9) " " 7 WHITESPACE@[8; 9) " "
8 NAMED_FIELD_DEF_LIST@[9; 27) 8 RECORD_FIELD_DEF_LIST@[9; 27)
9 L_CURLY@[9; 10) "{" 9 L_CURLY@[9; 10) "{"
10 WHITESPACE@[10; 15) "\n " 10 WHITESPACE@[10; 15) "\n "
11 NAMED_FIELD_DEF@[15; 25) 11 RECORD_FIELD_DEF@[15; 25)
12 NAME@[15; 20) 12 NAME@[15; 20)
13 IDENT@[15; 20) "r#foo" 13 IDENT@[15; 20) "r#foo"
14 COLON@[20; 21) ":" 14 COLON@[20; 21) ":"
diff --git a/crates/ra_syntax/test_data/parser/ok/0043_complex_assignment.txt b/crates/ra_syntax/test_data/parser/ok/0043_complex_assignment.txt
index ef47521bf..1f2456afa 100644
--- a/crates/ra_syntax/test_data/parser/ok/0043_complex_assignment.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0043_complex_assignment.txt
@@ -7,10 +7,10 @@ SOURCE_FILE@[0; 160)
7 NAME@[69; 73) 7 NAME@[69; 73)
8 IDENT@[69; 73) "Repr" 8 IDENT@[69; 73) "Repr"
9 WHITESPACE@[73; 74) " " 9 WHITESPACE@[73; 74) " "
10 NAMED_FIELD_DEF_LIST@[74; 90) 10 RECORD_FIELD_DEF_LIST@[74; 90)
11 L_CURLY@[74; 75) "{" 11 L_CURLY@[74; 75) "{"
12 WHITESPACE@[75; 76) " " 12 WHITESPACE@[75; 76) " "
13 NAMED_FIELD_DEF@[76; 88) 13 RECORD_FIELD_DEF@[76; 88)
14 NAME@[76; 79) 14 NAME@[76; 79)
15 IDENT@[76; 79) "raw" 15 IDENT@[76; 79) "raw"
16 COLON@[79; 80) ":" 16 COLON@[79; 80) ":"
@@ -46,16 +46,16 @@ SOURCE_FILE@[0; 160)
46 BIN_EXPR@[107; 135) 46 BIN_EXPR@[107; 135)
47 INDEX_EXPR@[107; 131) 47 INDEX_EXPR@[107; 131)
48 FIELD_EXPR@[107; 128) 48 FIELD_EXPR@[107; 128)
49 STRUCT_LIT@[107; 124) 49 RECORD_LIT@[107; 124)
50 PATH@[107; 111) 50 PATH@[107; 111)
51 PATH_SEGMENT@[107; 111) 51 PATH_SEGMENT@[107; 111)
52 NAME_REF@[107; 111) 52 NAME_REF@[107; 111)
53 IDENT@[107; 111) "Repr" 53 IDENT@[107; 111) "Repr"
54 WHITESPACE@[111; 112) " " 54 WHITESPACE@[111; 112) " "
55 NAMED_FIELD_LIST@[112; 124) 55 RECORD_FIELD_LIST@[112; 124)
56 L_CURLY@[112; 113) "{" 56 L_CURLY@[112; 113) "{"
57 WHITESPACE@[113; 114) " " 57 WHITESPACE@[113; 114) " "
58 NAMED_FIELD@[114; 122) 58 RECORD_FIELD@[114; 122)
59 NAME_REF@[114; 117) 59 NAME_REF@[114; 117)
60 IDENT@[114; 117) "raw" 60 IDENT@[114; 117) "raw"
61 COLON@[117; 118) ":" 61 COLON@[117; 118) ":"
@@ -83,14 +83,14 @@ SOURCE_FILE@[0; 160)
83 WHITESPACE@[136; 141) "\n " 83 WHITESPACE@[136; 141) "\n "
84 EXPR_STMT@[141; 157) 84 EXPR_STMT@[141; 157)
85 CALL_EXPR@[141; 156) 85 CALL_EXPR@[141; 156)
86 STRUCT_LIT@[141; 154) 86 RECORD_LIT@[141; 154)
87 PATH@[141; 145) 87 PATH@[141; 145)
88 PATH_SEGMENT@[141; 145) 88 PATH_SEGMENT@[141; 145)
89 NAME_REF@[141; 145) 89 NAME_REF@[141; 145)
90 IDENT@[141; 145) "Repr" 90 IDENT@[141; 145) "Repr"
91 NAMED_FIELD_LIST@[145; 154) 91 RECORD_FIELD_LIST@[145; 154)
92 L_CURLY@[145; 146) "{" 92 L_CURLY@[145; 146) "{"
93 NAMED_FIELD@[146; 153) 93 RECORD_FIELD@[146; 153)
94 NAME_REF@[146; 149) 94 NAME_REF@[146; 149)
95 IDENT@[146; 149) "raw" 95 IDENT@[146; 149) "raw"
96 COLON@[149; 150) ":" 96 COLON@[149; 150) ":"
diff --git a/crates/ra_syntax/test_data/parser/ok/0047_minus_in_inner_pattern.txt b/crates/ra_syntax/test_data/parser/ok/0047_minus_in_inner_pattern.txt
index 917b50ddf..136e2aae1 100644
--- a/crates/ra_syntax/test_data/parser/ok/0047_minus_in_inner_pattern.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0047_minus_in_inner_pattern.txt
@@ -268,9 +268,9 @@ SOURCE_FILE@[0; 395)
268 ENUM_VARIANT@[356; 365) 268 ENUM_VARIANT@[356; 365)
269 NAME@[356; 357) 269 NAME@[356; 357)
270 IDENT@[356; 357) "B" 270 IDENT@[356; 357) "B"
271 POS_FIELD_DEF_LIST@[357; 365) 271 TUPLE_FIELD_DEF_LIST@[357; 365)
272 L_PAREN@[357; 358) "(" 272 L_PAREN@[357; 358) "("
273 POS_FIELD_DEF@[358; 360) 273 TUPLE_FIELD_DEF@[358; 360)
274 PATH_TYPE@[358; 360) 274 PATH_TYPE@[358; 360)
275 PATH@[358; 360) 275 PATH@[358; 360)
276 PATH_SEGMENT@[358; 360) 276 PATH_SEGMENT@[358; 360)
@@ -278,7 +278,7 @@ SOURCE_FILE@[0; 395)
278 IDENT@[358; 360) "i8" 278 IDENT@[358; 360) "i8"
279 COMMA@[360; 361) "," 279 COMMA@[360; 361) ","
280 WHITESPACE@[361; 362) " " 280 WHITESPACE@[361; 362) " "
281 POS_FIELD_DEF@[362; 364) 281 TUPLE_FIELD_DEF@[362; 364)
282 PATH_TYPE@[362; 364) 282 PATH_TYPE@[362; 364)
283 PATH@[362; 364) 283 PATH@[362; 364)
284 PATH_SEGMENT@[362; 364) 284 PATH_SEGMENT@[362; 364)
diff --git a/crates/ra_vfs_glob/Cargo.toml b/crates/ra_vfs_glob/Cargo.toml
index 0390d7da1..09ba3d3bf 100644
--- a/crates/ra_vfs_glob/Cargo.toml
+++ b/crates/ra_vfs_glob/Cargo.toml
@@ -5,5 +5,5 @@ version = "0.1.0"
5authors = ["rust-analyzer developers"] 5authors = ["rust-analyzer developers"]
6 6
7[dependencies] 7[dependencies]
8ra_vfs = "0.2.0" 8ra_vfs = "0.3.0"
9globset = "0.4.4" 9globset = "0.4.4"