aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/assists/src/assist_context.rs13
-rw-r--r--crates/assists/src/handlers/extract_module_to_file.rs133
-rw-r--r--crates/assists/src/handlers/invert_if.rs9
-rw-r--r--crates/assists/src/handlers/remove_unused_param.rs81
-rw-r--r--crates/assists/src/lib.rs2
-rw-r--r--crates/assists/src/tests.rs28
-rw-r--r--crates/assists/src/tests/generated.rs15
-rw-r--r--crates/assists/src/utils.rs8
-rw-r--r--crates/hir/src/code_model.rs1
-rw-r--r--crates/hir_def/src/generics.rs37
-rw-r--r--crates/hir_ty/src/lower.rs18
-rw-r--r--crates/hir_ty/src/utils.rs9
-rw-r--r--crates/ide/src/diagnostics.rs1
-rw-r--r--crates/ide/src/diagnostics/fixes.rs1
-rw-r--r--crates/ide/src/goto_definition.rs28
-rw-r--r--crates/ide/src/references.rs48
-rw-r--r--crates/ide_db/src/source_change.rs2
-rw-r--r--crates/mbe/src/tests.rs12
-rw-r--r--crates/parser/src/grammar.rs2
-rw-r--r--crates/parser/src/grammar/expressions/atom.rs8
-rw-r--r--crates/parser/src/grammar/params.rs17
-rw-r--r--crates/parser/src/grammar/type_params.rs2
-rw-r--r--crates/parser/src/grammar/types.rs26
-rw-r--r--crates/parser/src/lib.rs2
-rw-r--r--crates/rust-analyzer/src/config.rs34
-rw-r--r--crates/rust-analyzer/src/diagnostics/to_proto.rs4
-rw-r--r--crates/rust-analyzer/src/to_proto.rs37
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rast20
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rast43
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0154_tuple_attrs.rast50
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0154_tuple_attrs.rs1
-rw-r--r--crates/syntax/test_data/parser/ok/0051_parameter_attrs.rast222
-rw-r--r--crates/syntax/test_data/parser/ok/0063_variadic_fun.rast28
34 files changed, 717 insertions, 226 deletions
diff --git a/crates/assists/src/assist_context.rs b/crates/assists/src/assist_context.rs
index 69499ea32..80cf9aba1 100644
--- a/crates/assists/src/assist_context.rs
+++ b/crates/assists/src/assist_context.rs
@@ -4,10 +4,10 @@ use std::mem;
4 4
5use algo::find_covering_element; 5use algo::find_covering_element;
6use hir::Semantics; 6use hir::Semantics;
7use ide_db::base_db::{FileId, FileRange}; 7use ide_db::base_db::{AnchoredPathBuf, FileId, FileRange};
8use ide_db::{ 8use ide_db::{
9 label::Label, 9 label::Label,
10 source_change::{SourceChange, SourceFileEdit}, 10 source_change::{FileSystemEdit, SourceChange, SourceFileEdit},
11 RootDatabase, 11 RootDatabase,
12}; 12};
13use syntax::{ 13use syntax::{
@@ -209,6 +209,7 @@ pub(crate) struct AssistBuilder {
209 file_id: FileId, 209 file_id: FileId,
210 is_snippet: bool, 210 is_snippet: bool,
211 source_file_edits: Vec<SourceFileEdit>, 211 source_file_edits: Vec<SourceFileEdit>,
212 file_system_edits: Vec<FileSystemEdit>,
212} 213}
213 214
214impl AssistBuilder { 215impl AssistBuilder {
@@ -218,6 +219,7 @@ impl AssistBuilder {
218 file_id, 219 file_id,
219 is_snippet: false, 220 is_snippet: false,
220 source_file_edits: Vec::default(), 221 source_file_edits: Vec::default(),
222 file_system_edits: Vec::default(),
221 } 223 }
222 } 224 }
223 225
@@ -282,12 +284,17 @@ impl AssistBuilder {
282 algo::diff(&node, &new).into_text_edit(&mut self.edit); 284 algo::diff(&node, &new).into_text_edit(&mut self.edit);
283 } 285 }
284 } 286 }
287 pub(crate) fn create_file(&mut self, dst: AnchoredPathBuf, content: impl Into<String>) {
288 let file_system_edit =
289 FileSystemEdit::CreateFile { dst: dst.clone(), initial_contents: content.into() };
290 self.file_system_edits.push(file_system_edit);
291 }
285 292
286 fn finish(mut self) -> SourceChange { 293 fn finish(mut self) -> SourceChange {
287 self.commit(); 294 self.commit();
288 SourceChange { 295 SourceChange {
289 source_file_edits: mem::take(&mut self.source_file_edits), 296 source_file_edits: mem::take(&mut self.source_file_edits),
290 file_system_edits: Default::default(), 297 file_system_edits: mem::take(&mut self.file_system_edits),
291 is_snippet: self.is_snippet, 298 is_snippet: self.is_snippet,
292 } 299 }
293 } 300 }
diff --git a/crates/assists/src/handlers/extract_module_to_file.rs b/crates/assists/src/handlers/extract_module_to_file.rs
new file mode 100644
index 000000000..3e67fdca2
--- /dev/null
+++ b/crates/assists/src/handlers/extract_module_to_file.rs
@@ -0,0 +1,133 @@
1use ast::edit::IndentLevel;
2use ide_db::base_db::AnchoredPathBuf;
3use syntax::{
4 ast::{self, edit::AstNodeEdit, NameOwner},
5 AstNode,
6};
7
8use crate::{AssistContext, AssistId, AssistKind, Assists};
9
10// Assist: extract_module_to_file
11//
12// This assist extract module to file.
13//
14// ```
15// mod foo {<|>
16// fn t() {}
17// }
18// ```
19// ->
20// ```
21// mod foo;
22// ```
23pub(crate) fn extract_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
24 let module_ast = ctx.find_node_at_offset::<ast::Module>()?;
25 let module_name = module_ast.name()?;
26
27 let module_def = ctx.sema.to_def(&module_ast)?;
28 let parent_module = module_def.parent(ctx.db())?;
29
30 let module_items = module_ast.item_list()?;
31 let target = module_ast.syntax().text_range();
32 let anchor_file_id = ctx.frange.file_id;
33
34 acc.add(
35 AssistId("extract_module_to_file", AssistKind::RefactorExtract),
36 "Extract module to file",
37 target,
38 |builder| {
39 let path = {
40 let dir = match parent_module.name(ctx.db()) {
41 Some(name) if !parent_module.is_mod_rs(ctx.db()) => format!("{}/", name),
42 _ => String::new(),
43 };
44 format!("./{}{}.rs", dir, module_name)
45 };
46 let contents = {
47 let items = module_items.dedent(IndentLevel(1)).to_string();
48 let mut items =
49 items.trim_start_matches('{').trim_end_matches('}').trim().to_string();
50 if !items.is_empty() {
51 items.push('\n');
52 }
53 items
54 };
55
56 builder.replace(target, format!("mod {};", module_name));
57
58 let dst = AnchoredPathBuf { anchor: anchor_file_id, path };
59 builder.create_file(dst, contents);
60 },
61 )
62}
63
64#[cfg(test)]
65mod tests {
66 use crate::tests::check_assist;
67
68 use super::*;
69
70 #[test]
71 fn extract_from_root() {
72 check_assist(
73 extract_module_to_file,
74 r#"
75mod tests {<|>
76 #[test] fn t() {}
77}
78"#,
79 r#"
80//- /main.rs
81mod tests;
82//- /tests.rs
83#[test] fn t() {}
84"#,
85 );
86 }
87
88 #[test]
89 fn extract_from_submodule() {
90 check_assist(
91 extract_module_to_file,
92 r#"
93//- /main.rs
94mod submodule;
95//- /submodule.rs
96mod inner<|> {
97 fn f() {}
98}
99fn g() {}
100"#,
101 r#"
102//- /submodule.rs
103mod inner;
104fn g() {}
105//- /submodule/inner.rs
106fn f() {}
107"#,
108 );
109 }
110
111 #[test]
112 fn extract_from_mod_rs() {
113 check_assist(
114 extract_module_to_file,
115 r#"
116//- /main.rs
117mod submodule;
118//- /submodule/mod.rs
119mod inner<|> {
120 fn f() {}
121}
122fn g() {}
123"#,
124 r#"
125//- /submodule/mod.rs
126mod inner;
127fn g() {}
128//- /submodule/inner.rs
129fn f() {}
130"#,
131 );
132 }
133}
diff --git a/crates/assists/src/handlers/invert_if.rs b/crates/assists/src/handlers/invert_if.rs
index 91e2f5c8c..f9c33b3f7 100644
--- a/crates/assists/src/handlers/invert_if.rs
+++ b/crates/assists/src/handlers/invert_if.rs
@@ -78,6 +78,15 @@ mod tests {
78 } 78 }
79 79
80 #[test] 80 #[test]
81 fn invert_if_remove_not_parentheses() {
82 check_assist(
83 invert_if,
84 "fn f() { i<|>f !(x == 3 || x == 4 || x == 5) { 3 * 2 } else { 1 } }",
85 "fn f() { if x == 3 || x == 4 || x == 5 { 1 } else { 3 * 2 } }",
86 )
87 }
88
89 #[test]
81 fn invert_if_remove_inequality() { 90 fn invert_if_remove_inequality() {
82 check_assist( 91 check_assist(
83 invert_if, 92 invert_if,
diff --git a/crates/assists/src/handlers/remove_unused_param.rs b/crates/assists/src/handlers/remove_unused_param.rs
index 1ff5e92b0..f72dd49ed 100644
--- a/crates/assists/src/handlers/remove_unused_param.rs
+++ b/crates/assists/src/handlers/remove_unused_param.rs
@@ -2,9 +2,10 @@ use ide_db::{defs::Definition, search::Reference};
2use syntax::{ 2use syntax::{
3 algo::find_node_at_range, 3 algo::find_node_at_range,
4 ast::{self, ArgListOwner}, 4 ast::{self, ArgListOwner},
5 AstNode, SyntaxNode, TextRange, T, 5 AstNode, SyntaxKind, SyntaxNode, TextRange, T,
6}; 6};
7use test_utils::mark; 7use test_utils::mark;
8use SyntaxKind::WHITESPACE;
8 9
9use crate::{ 10use crate::{
10 assist_context::AssistBuilder, utils::next_prev, AssistContext, AssistId, AssistKind, Assists, 11 assist_context::AssistBuilder, utils::next_prev, AssistContext, AssistId, AssistKind, Assists,
@@ -56,7 +57,7 @@ pub(crate) fn remove_unused_param(acc: &mut Assists, ctx: &AssistContext) -> Opt
56 "Remove unused parameter", 57 "Remove unused parameter",
57 param.syntax().text_range(), 58 param.syntax().text_range(),
58 |builder| { 59 |builder| {
59 builder.delete(range_with_coma(param.syntax())); 60 builder.delete(range_to_remove(param.syntax()));
60 for usage in fn_def.usages(&ctx.sema).all() { 61 for usage in fn_def.usages(&ctx.sema).all() {
61 process_usage(ctx, builder, usage, param_position); 62 process_usage(ctx, builder, usage, param_position);
62 } 63 }
@@ -80,19 +81,34 @@ fn process_usage(
80 let arg = call_expr.arg_list()?.args().nth(arg_to_remove)?; 81 let arg = call_expr.arg_list()?.args().nth(arg_to_remove)?;
81 82
82 builder.edit_file(usage.file_range.file_id); 83 builder.edit_file(usage.file_range.file_id);
83 builder.delete(range_with_coma(arg.syntax())); 84 builder.delete(range_to_remove(arg.syntax()));
84 85
85 Some(()) 86 Some(())
86} 87}
87 88
88fn range_with_coma(node: &SyntaxNode) -> TextRange { 89fn range_to_remove(node: &SyntaxNode) -> TextRange {
89 let up_to = next_prev().find_map(|dir| { 90 let up_to_comma = next_prev().find_map(|dir| {
90 node.siblings_with_tokens(dir) 91 node.siblings_with_tokens(dir)
91 .filter_map(|it| it.into_token()) 92 .filter_map(|it| it.into_token())
92 .find(|it| it.kind() == T![,]) 93 .find(|it| it.kind() == T![,])
94 .map(|it| (dir, it))
93 }); 95 });
94 let up_to = up_to.map_or(node.text_range(), |it| it.text_range()); 96 if let Some((dir, token)) = up_to_comma {
95 node.text_range().cover(up_to) 97 if node.next_sibling().is_some() {
98 let up_to_space = token
99 .siblings_with_tokens(dir)
100 .skip(1)
101 .take_while(|it| it.kind() == WHITESPACE)
102 .last()
103 .and_then(|it| it.into_token());
104 return node
105 .text_range()
106 .cover(up_to_space.map_or(token.text_range(), |it| it.text_range()));
107 }
108 node.text_range().cover(token.text_range())
109 } else {
110 node.text_range()
111 }
96} 112}
97 113
98#[cfg(test)] 114#[cfg(test)]
@@ -119,6 +135,57 @@ fn b() { foo(9, ) }
119 } 135 }
120 136
121 #[test] 137 #[test]
138 fn remove_unused_first_param() {
139 check_assist(
140 remove_unused_param,
141 r#"
142fn foo(<|>x: i32, y: i32) { y; }
143fn a() { foo(1, 2) }
144fn b() { foo(1, 2,) }
145"#,
146 r#"
147fn foo(y: i32) { y; }
148fn a() { foo(2) }
149fn b() { foo(2,) }
150"#,
151 );
152 }
153
154 #[test]
155 fn remove_unused_single_param() {
156 check_assist(
157 remove_unused_param,
158 r#"
159fn foo(<|>x: i32) { 0; }
160fn a() { foo(1) }
161fn b() { foo(1, ) }
162"#,
163 r#"
164fn foo() { 0; }
165fn a() { foo() }
166fn b() { foo( ) }
167"#,
168 );
169 }
170
171 #[test]
172 fn remove_unused_surrounded_by_parms() {
173 check_assist(
174 remove_unused_param,
175 r#"
176fn foo(x: i32, <|>y: i32, z: i32) { x; }
177fn a() { foo(1, 2, 3) }
178fn b() { foo(1, 2, 3,) }
179"#,
180 r#"
181fn foo(x: i32, z: i32) { x; }
182fn a() { foo(1, 3) }
183fn b() { foo(1, 3,) }
184"#,
185 );
186 }
187
188 #[test]
122 fn remove_unused_qualified_call() { 189 fn remove_unused_qualified_call() {
123 check_assist( 190 check_assist(
124 remove_unused_param, 191 remove_unused_param,
diff --git a/crates/assists/src/lib.rs b/crates/assists/src/lib.rs
index 6e736ccb3..6b89b2d04 100644
--- a/crates/assists/src/lib.rs
+++ b/crates/assists/src/lib.rs
@@ -129,6 +129,7 @@ mod handlers {
129 mod convert_integer_literal; 129 mod convert_integer_literal;
130 mod early_return; 130 mod early_return;
131 mod expand_glob_import; 131 mod expand_glob_import;
132 mod extract_module_to_file;
132 mod extract_struct_from_enum_variant; 133 mod extract_struct_from_enum_variant;
133 mod extract_variable; 134 mod extract_variable;
134 mod fill_match_arms; 135 mod fill_match_arms;
@@ -179,6 +180,7 @@ mod handlers {
179 convert_integer_literal::convert_integer_literal, 180 convert_integer_literal::convert_integer_literal,
180 early_return::convert_to_guarded_return, 181 early_return::convert_to_guarded_return,
181 expand_glob_import::expand_glob_import, 182 expand_glob_import::expand_glob_import,
183 extract_module_to_file::extract_module_to_file,
182 extract_struct_from_enum_variant::extract_struct_from_enum_variant, 184 extract_struct_from_enum_variant::extract_struct_from_enum_variant,
183 extract_variable::extract_variable, 185 extract_variable::extract_variable,
184 fill_match_arms::fill_match_arms, 186 fill_match_arms::fill_match_arms,
diff --git a/crates/assists/src/tests.rs b/crates/assists/src/tests.rs
index 709a34d03..b41f4874a 100644
--- a/crates/assists/src/tests.rs
+++ b/crates/assists/src/tests.rs
@@ -2,6 +2,7 @@ mod generated;
2 2
3use hir::Semantics; 3use hir::Semantics;
4use ide_db::base_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt}; 4use ide_db::base_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt};
5use ide_db::source_change::FileSystemEdit;
5use ide_db::RootDatabase; 6use ide_db::RootDatabase;
6use syntax::TextRange; 7use syntax::TextRange;
7use test_utils::{assert_eq_text, extract_offset, extract_range}; 8use test_utils::{assert_eq_text, extract_offset, extract_range};
@@ -47,7 +48,7 @@ fn check_doc_test(assist_id: &str, before: &str, after: &str) {
47 let before = db.file_text(file_id).to_string(); 48 let before = db.file_text(file_id).to_string();
48 let frange = FileRange { file_id, range: selection.into() }; 49 let frange = FileRange { file_id, range: selection.into() };
49 50
50 let mut assist = Assist::resolved(&db, &AssistConfig::default(), frange) 51 let assist = Assist::resolved(&db, &AssistConfig::default(), frange)
51 .into_iter() 52 .into_iter()
52 .find(|assist| assist.assist.id.0 == assist_id) 53 .find(|assist| assist.assist.id.0 == assist_id)
53 .unwrap_or_else(|| { 54 .unwrap_or_else(|| {
@@ -63,9 +64,12 @@ fn check_doc_test(assist_id: &str, before: &str, after: &str) {
63 }); 64 });
64 65
65 let actual = { 66 let actual = {
66 let change = assist.source_change.source_file_edits.pop().unwrap();
67 let mut actual = before; 67 let mut actual = before;
68 change.edit.apply(&mut actual); 68 for source_file_edit in assist.source_change.source_file_edits {
69 if source_file_edit.file_id == file_id {
70 source_file_edit.edit.apply(&mut actual)
71 }
72 }
69 actual 73 actual
70 }; 74 };
71 assert_eq_text!(&after, &actual); 75 assert_eq_text!(&after, &actual);
@@ -99,7 +103,8 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label:
99 (Some(assist), ExpectedResult::After(after)) => { 103 (Some(assist), ExpectedResult::After(after)) => {
100 let mut source_change = assist.source_change; 104 let mut source_change = assist.source_change;
101 assert!(!source_change.source_file_edits.is_empty()); 105 assert!(!source_change.source_file_edits.is_empty());
102 let skip_header = source_change.source_file_edits.len() == 1; 106 let skip_header = source_change.source_file_edits.len() == 1
107 && source_change.file_system_edits.len() == 0;
103 source_change.source_file_edits.sort_by_key(|it| it.file_id); 108 source_change.source_file_edits.sort_by_key(|it| it.file_id);
104 109
105 let mut buf = String::new(); 110 let mut buf = String::new();
@@ -115,6 +120,21 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label:
115 buf.push_str(&text); 120 buf.push_str(&text);
116 } 121 }
117 122
123 for file_system_edit in source_change.file_system_edits.clone() {
124 match file_system_edit {
125 FileSystemEdit::CreateFile { dst, initial_contents } => {
126 let sr = db.file_source_root(dst.anchor);
127 let sr = db.source_root(sr);
128 let mut base = sr.path_for_file(&dst.anchor).unwrap().clone();
129 base.pop();
130 let created_file_path = format!("{}{}", base.to_string(), &dst.path[1..]);
131 format_to!(buf, "//- {}\n", created_file_path);
132 buf.push_str(&initial_contents);
133 }
134 _ => (),
135 }
136 }
137
118 assert_eq_text!(after, &buf); 138 assert_eq_text!(after, &buf);
119 } 139 }
120 (Some(assist), ExpectedResult::Target(target)) => { 140 (Some(assist), ExpectedResult::Target(target)) => {
diff --git a/crates/assists/src/tests/generated.rs b/crates/assists/src/tests/generated.rs
index cc7c4a343..e9093ec53 100644
--- a/crates/assists/src/tests/generated.rs
+++ b/crates/assists/src/tests/generated.rs
@@ -236,6 +236,21 @@ fn qux(bar: Bar, baz: Baz) {}
236} 236}
237 237
238#[test] 238#[test]
239fn doctest_extract_module_to_file() {
240 check_doc_test(
241 "extract_module_to_file",
242 r#####"
243mod foo {<|>
244 fn t() {}
245}
246"#####,
247 r#####"
248mod foo;
249"#####,
250 )
251}
252
253#[test]
239fn doctest_extract_struct_from_enum_variant() { 254fn doctest_extract_struct_from_enum_variant() {
240 check_doc_test( 255 check_doc_test(
241 "extract_struct_from_enum_variant", 256 "extract_struct_from_enum_variant",
diff --git a/crates/assists/src/utils.rs b/crates/assists/src/utils.rs
index f2cacf7c8..d41084b59 100644
--- a/crates/assists/src/utils.rs
+++ b/crates/assists/src/utils.rs
@@ -232,7 +232,13 @@ fn invert_special_case(expr: &ast::Expr) -> Option<ast::Expr> {
232 }; 232 };
233 Some(make::expr_method_call(receiver, method, arg_list)) 233 Some(make::expr_method_call(receiver, method, arg_list))
234 } 234 }
235 ast::Expr::PrefixExpr(pe) if pe.op_kind()? == ast::PrefixOp::Not => pe.expr(), 235 ast::Expr::PrefixExpr(pe) if pe.op_kind()? == ast::PrefixOp::Not => {
236 if let ast::Expr::ParenExpr(parexpr) = pe.expr()? {
237 parexpr.expr()
238 } else {
239 pe.expr()
240 }
241 }
236 // FIXME: 242 // FIXME:
237 // ast::Expr::Literal(true | false ) 243 // ast::Expr::Literal(true | false )
238 _ => None, 244 _ => None,
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index dbc937e4f..1d7e5ddd7 100644
--- a/crates/hir/src/code_model.rs
+++ b/crates/hir/src/code_model.rs
@@ -1272,7 +1272,6 @@ impl LifetimeParam {
1272 } 1272 }
1273} 1273}
1274 1274
1275// FIXME: rename from `ImplDef` to `Impl`
1276#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 1275#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1277pub struct Impl { 1276pub struct Impl {
1278 pub(crate) id: ImplId, 1277 pub(crate) id: ImplId,
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs
index 41134d23b..bb8fca009 100644
--- a/crates/hir_def/src/generics.rs
+++ b/crates/hir_def/src/generics.rs
@@ -62,6 +62,7 @@ pub struct GenericParams {
62pub enum WherePredicate { 62pub enum WherePredicate {
63 TypeBound { target: WherePredicateTypeTarget, bound: TypeBound }, 63 TypeBound { target: WherePredicateTypeTarget, bound: TypeBound },
64 Lifetime { target: LifetimeRef, bound: LifetimeRef }, 64 Lifetime { target: LifetimeRef, bound: LifetimeRef },
65 ForLifetime { lifetimes: Box<[Name]>, target: WherePredicateTypeTarget, bound: TypeBound },
65} 66}
66 67
67#[derive(Clone, PartialEq, Eq, Debug)] 68#[derive(Clone, PartialEq, Eq, Debug)]
@@ -69,7 +70,6 @@ pub enum WherePredicateTypeTarget {
69 TypeRef(TypeRef), 70 TypeRef(TypeRef),
70 /// For desugared where predicates that can directly refer to a type param. 71 /// For desugared where predicates that can directly refer to a type param.
71 TypeParam(LocalTypeParamId), 72 TypeParam(LocalTypeParamId),
72 // FIXME: ForLifetime(Vec<LifetimeParamId>, TypeRef)
73} 73}
74 74
75#[derive(Default)] 75#[derive(Default)]
@@ -234,7 +234,7 @@ impl GenericParams {
234 for bound in 234 for bound in
235 node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds()) 235 node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds())
236 { 236 {
237 self.add_where_predicate_from_bound(lower_ctx, bound, target.clone()); 237 self.add_where_predicate_from_bound(lower_ctx, bound, None, target.clone());
238 } 238 }
239 } 239 }
240 240
@@ -279,8 +279,25 @@ impl GenericParams {
279 } else { 279 } else {
280 continue; 280 continue;
281 }; 281 };
282
283 let lifetimes: Option<Box<_>> = pred.generic_param_list().map(|param_list| {
284 // Higher-Ranked Trait Bounds
285 param_list
286 .lifetime_params()
287 .map(|lifetime_param| {
288 lifetime_param
289 .lifetime()
290 .map_or_else(Name::missing, |lt| Name::new_lifetime(&lt))
291 })
292 .collect()
293 });
282 for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) { 294 for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) {
283 self.add_where_predicate_from_bound(lower_ctx, bound, target.clone()); 295 self.add_where_predicate_from_bound(
296 lower_ctx,
297 bound,
298 lifetimes.as_ref(),
299 target.clone(),
300 );
284 } 301 }
285 } 302 }
286 } 303 }
@@ -289,6 +306,7 @@ impl GenericParams {
289 &mut self, 306 &mut self,
290 lower_ctx: &LowerCtx, 307 lower_ctx: &LowerCtx,
291 bound: ast::TypeBound, 308 bound: ast::TypeBound,
309 hrtb_lifetimes: Option<&Box<[Name]>>,
292 target: Either<TypeRef, LifetimeRef>, 310 target: Either<TypeRef, LifetimeRef>,
293 ) { 311 ) {
294 if bound.question_mark_token().is_some() { 312 if bound.question_mark_token().is_some() {
@@ -297,9 +315,16 @@ impl GenericParams {
297 } 315 }
298 let bound = TypeBound::from_ast(lower_ctx, bound); 316 let bound = TypeBound::from_ast(lower_ctx, bound);
299 let predicate = match (target, bound) { 317 let predicate = match (target, bound) {
300 (Either::Left(type_ref), bound) => WherePredicate::TypeBound { 318 (Either::Left(type_ref), bound) => match hrtb_lifetimes {
301 target: WherePredicateTypeTarget::TypeRef(type_ref), 319 Some(hrtb_lifetimes) => WherePredicate::ForLifetime {
302 bound, 320 lifetimes: hrtb_lifetimes.clone(),
321 target: WherePredicateTypeTarget::TypeRef(type_ref),
322 bound,
323 },
324 None => WherePredicate::TypeBound {
325 target: WherePredicateTypeTarget::TypeRef(type_ref),
326 bound,
327 },
303 }, 328 },
304 (Either::Right(lifetime), TypeBound::Lifetime(bound)) => { 329 (Either::Right(lifetime), TypeBound::Lifetime(bound)) => {
305 WherePredicate::Lifetime { target: lifetime, bound } 330 WherePredicate::Lifetime { target: lifetime, bound }
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index 8392cb770..8da56cd11 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -675,7 +675,8 @@ impl GenericPredicate {
675 where_predicate: &'a WherePredicate, 675 where_predicate: &'a WherePredicate,
676 ) -> impl Iterator<Item = GenericPredicate> + 'a { 676 ) -> impl Iterator<Item = GenericPredicate> + 'a {
677 match where_predicate { 677 match where_predicate {
678 WherePredicate::TypeBound { target, bound } => { 678 WherePredicate::ForLifetime { target, bound, .. }
679 | WherePredicate::TypeBound { target, bound } => {
679 let self_ty = match target { 680 let self_ty = match target {
680 WherePredicateTypeTarget::TypeRef(type_ref) => Ty::from_hir(ctx, type_ref), 681 WherePredicateTypeTarget::TypeRef(type_ref) => Ty::from_hir(ctx, type_ref),
681 WherePredicateTypeTarget::TypeParam(param_id) => { 682 WherePredicateTypeTarget::TypeParam(param_id) => {
@@ -888,14 +889,13 @@ pub(crate) fn generic_predicates_for_param_query(
888 .where_predicates_in_scope() 889 .where_predicates_in_scope()
889 // we have to filter out all other predicates *first*, before attempting to lower them 890 // we have to filter out all other predicates *first*, before attempting to lower them
890 .filter(|pred| match pred { 891 .filter(|pred| match pred {
891 WherePredicate::TypeBound { 892 WherePredicate::ForLifetime { target, .. }
892 target: WherePredicateTypeTarget::TypeRef(type_ref), 893 | WherePredicate::TypeBound { target, .. } => match target {
893 .. 894 WherePredicateTypeTarget::TypeRef(type_ref) => {
894 } => Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id), 895 Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id)
895 WherePredicate::TypeBound { 896 }
896 target: WherePredicateTypeTarget::TypeParam(local_id), 897 WherePredicateTypeTarget::TypeParam(local_id) => *local_id == param_id.local_id,
897 .. 898 },
898 } => *local_id == param_id.local_id,
899 WherePredicate::Lifetime { .. } => false, 899 WherePredicate::Lifetime { .. } => false,
900 }) 900 })
901 .flat_map(|pred| { 901 .flat_map(|pred| {
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs
index af880c065..65b79df0d 100644
--- a/crates/hir_ty/src/utils.rs
+++ b/crates/hir_ty/src/utils.rs
@@ -5,7 +5,9 @@ use std::sync::Arc;
5use hir_def::{ 5use hir_def::{
6 adt::VariantData, 6 adt::VariantData,
7 db::DefDatabase, 7 db::DefDatabase,
8 generics::{GenericParams, TypeParamData, TypeParamProvenance, WherePredicateTypeTarget}, 8 generics::{
9 GenericParams, TypeParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
10 },
9 path::Path, 11 path::Path,
10 resolver::{HasResolver, TypeNs}, 12 resolver::{HasResolver, TypeNs},
11 type_ref::TypeRef, 13 type_ref::TypeRef,
@@ -27,7 +29,8 @@ fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
27 .where_predicates 29 .where_predicates
28 .iter() 30 .iter()
29 .filter_map(|pred| match pred { 31 .filter_map(|pred| match pred {
30 hir_def::generics::WherePredicate::TypeBound { target, bound } => match target { 32 WherePredicate::ForLifetime { target, bound, .. }
33 | WherePredicate::TypeBound { target, bound } => match target {
31 WherePredicateTypeTarget::TypeRef(TypeRef::Path(p)) 34 WherePredicateTypeTarget::TypeRef(TypeRef::Path(p))
32 if p == &Path::from(name![Self]) => 35 if p == &Path::from(name![Self]) =>
33 { 36 {
@@ -38,7 +41,7 @@ fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
38 } 41 }
39 _ => None, 42 _ => None,
40 }, 43 },
41 hir_def::generics::WherePredicate::Lifetime { .. } => None, 44 WherePredicate::Lifetime { .. } => None,
42 }) 45 })
43 .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path.mod_path()) { 46 .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path.mod_path()) {
44 Some(TypeNs::TraitId(t)) => Some(t), 47 Some(TypeNs::TraitId(t)) => Some(t),
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs
index 049f808dc..3ad30f0c9 100644
--- a/crates/ide/src/diagnostics.rs
+++ b/crates/ide/src/diagnostics.rs
@@ -619,6 +619,7 @@ fn test_fn() {
619 ), 619 ),
620 path: "foo.rs", 620 path: "foo.rs",
621 }, 621 },
622 initial_contents: "",
622 }, 623 },
623 ], 624 ],
624 is_snippet: false, 625 is_snippet: false,
diff --git a/crates/ide/src/diagnostics/fixes.rs b/crates/ide/src/diagnostics/fixes.rs
index e8b896623..d79f5c170 100644
--- a/crates/ide/src/diagnostics/fixes.rs
+++ b/crates/ide/src/diagnostics/fixes.rs
@@ -40,6 +40,7 @@ impl DiagnosticWithFix for UnresolvedModule {
40 anchor: self.file.original_file(sema.db), 40 anchor: self.file.original_file(sema.db),
41 path: self.candidate.clone(), 41 path: self.candidate.clone(),
42 }, 42 },
43 initial_contents: "".to_string(),
43 } 44 }
44 .into(), 45 .into(),
45 unresolved_module.syntax().text_range(), 46 unresolved_module.syntax().text_range(),
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index 7a12e9965..431da5d9c 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -1077,4 +1077,32 @@ fn foo<'foobar>(_: &'foobar ()) {
1077}"#, 1077}"#,
1078 ) 1078 )
1079 } 1079 }
1080
1081 #[test]
1082 #[ignore] // requires the HIR to somehow track these hrtb lifetimes
1083 fn goto_lifetime_hrtb() {
1084 check(
1085 r#"trait Foo<T> {}
1086fn foo<T>() where for<'a> T: Foo<&'a<|> (u8, u16)>, {}
1087 //^^
1088"#,
1089 );
1090 check(
1091 r#"trait Foo<T> {}
1092fn foo<T>() where for<'a<|>> T: Foo<&'a (u8, u16)>, {}
1093 //^^
1094"#,
1095 );
1096 }
1097
1098 #[test]
1099 #[ignore] // requires ForTypes to be implemented
1100 fn goto_lifetime_hrtb_for_type() {
1101 check(
1102 r#"trait Foo<T> {}
1103fn foo<T>() where T: for<'a> Foo<&'a<|> (u8, u16)>, {}
1104 //^^
1105"#,
1106 );
1107 }
1080} 1108}
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index 18ea19305..33b7358f7 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -147,20 +147,20 @@ fn find_name(
147) -> Option<RangeInfo<Definition>> { 147) -> Option<RangeInfo<Definition>> {
148 if let Some(name) = opt_name { 148 if let Some(name) = opt_name {
149 let def = NameClass::classify(sema, &name)?.referenced_or_defined(sema.db); 149 let def = NameClass::classify(sema, &name)?.referenced_or_defined(sema.db);
150 let range = name.syntax().text_range(); 150 let FileRange { range, .. } = sema.original_range(name.syntax());
151 return Some(RangeInfo::new(range, def)); 151 return Some(RangeInfo::new(range, def));
152 } 152 }
153 153
154 let (text_range, def) = if let Some(lifetime) = 154 let (FileRange { range, .. }, def) = if let Some(lifetime) =
155 sema.find_node_at_offset_with_descend::<ast::Lifetime>(&syntax, position.offset) 155 sema.find_node_at_offset_with_descend::<ast::Lifetime>(&syntax, position.offset)
156 { 156 {
157 if let Some(def) = NameRefClass::classify_lifetime(sema, &lifetime) 157 if let Some(def) = NameRefClass::classify_lifetime(sema, &lifetime)
158 .map(|class| NameRefClass::referenced(class, sema.db)) 158 .map(|class| NameRefClass::referenced(class, sema.db))
159 { 159 {
160 (lifetime.syntax().text_range(), def) 160 (sema.original_range(lifetime.syntax()), def)
161 } else { 161 } else {
162 ( 162 (
163 lifetime.syntax().text_range(), 163 sema.original_range(lifetime.syntax()),
164 NameClass::classify_lifetime(sema, &lifetime)?.referenced_or_defined(sema.db), 164 NameClass::classify_lifetime(sema, &lifetime)?.referenced_or_defined(sema.db),
165 ) 165 )
166 } 166 }
@@ -168,11 +168,11 @@ fn find_name(
168 let name_ref = 168 let name_ref =
169 sema.find_node_at_offset_with_descend::<ast::NameRef>(&syntax, position.offset)?; 169 sema.find_node_at_offset_with_descend::<ast::NameRef>(&syntax, position.offset)?;
170 ( 170 (
171 name_ref.syntax().text_range(), 171 sema.original_range(name_ref.syntax()),
172 NameRefClass::classify(sema, &name_ref)?.referenced(sema.db), 172 NameRefClass::classify(sema, &name_ref)?.referenced(sema.db),
173 ) 173 )
174 }; 174 };
175 Some(RangeInfo::new(text_range, def)) 175 Some(RangeInfo::new(range, def))
176} 176}
177 177
178fn decl_access(def: &Definition, syntax: &SyntaxNode, range: TextRange) -> Option<ReferenceAccess> { 178fn decl_access(def: &Definition, syntax: &SyntaxNode, range: TextRange) -> Option<ReferenceAccess> {
@@ -1086,4 +1086,40 @@ impl<'a> Foo<'a> for &'a () {
1086 "#]], 1086 "#]],
1087 ); 1087 );
1088 } 1088 }
1089
1090 #[test]
1091 fn test_map_range_to_original() {
1092 check(
1093 r#"
1094macro_rules! foo {($i:ident) => {$i} }
1095fn main() {
1096 let a<|> = "test";
1097 foo!(a);
1098}
1099"#,
1100 expect![[r#"
1101 a Local FileId(0) 59..60 Other
1102
1103 FileId(0) 80..81 Other Read
1104 "#]],
1105 );
1106 }
1107
1108 #[test]
1109 fn test_map_range_to_original_ref() {
1110 check(
1111 r#"
1112macro_rules! foo {($i:ident) => {$i} }
1113fn main() {
1114 let a = "test";
1115 foo!(a<|>);
1116}
1117"#,
1118 expect![[r#"
1119 a Local FileId(0) 59..60 Other
1120
1121 FileId(0) 80..81 Other Read
1122 "#]],
1123 );
1124 }
1089} 1125}
diff --git a/crates/ide_db/src/source_change.rs b/crates/ide_db/src/source_change.rs
index e87d98dad..10c0abdac 100644
--- a/crates/ide_db/src/source_change.rs
+++ b/crates/ide_db/src/source_change.rs
@@ -44,7 +44,7 @@ impl From<Vec<SourceFileEdit>> for SourceChange {
44 44
45#[derive(Debug, Clone)] 45#[derive(Debug, Clone)]
46pub enum FileSystemEdit { 46pub enum FileSystemEdit {
47 CreateFile { dst: AnchoredPathBuf }, 47 CreateFile { dst: AnchoredPathBuf, initial_contents: String },
48 MoveFile { src: FileId, dst: AnchoredPathBuf }, 48 MoveFile { src: FileId, dst: AnchoredPathBuf },
49} 49}
50 50
diff --git a/crates/mbe/src/tests.rs b/crates/mbe/src/tests.rs
index f10e7a9b6..451fa1456 100644
--- a/crates/mbe/src/tests.rs
+++ b/crates/mbe/src/tests.rs
@@ -1004,6 +1004,18 @@ fn test_underscore() {
1004} 1004}
1005 1005
1006#[test] 1006#[test]
1007fn test_vertical_bar_with_pat() {
1008 parse_macro(
1009 r#"
1010 macro_rules! foo {
1011 (| $pat:pat | ) => { 0 }
1012 }
1013 "#,
1014 )
1015 .assert_expand_items(r#"foo! { | x | }"#, r#"0"#);
1016}
1017
1018#[test]
1007fn test_lifetime() { 1019fn test_lifetime() {
1008 parse_macro( 1020 parse_macro(
1009 r#" 1021 r#"
diff --git a/crates/parser/src/grammar.rs b/crates/parser/src/grammar.rs
index 1a078f6b4..f08c8bab7 100644
--- a/crates/parser/src/grammar.rs
+++ b/crates/parser/src/grammar.rs
@@ -55,7 +55,7 @@ pub(crate) mod fragments {
55 use super::*; 55 use super::*;
56 56
57 pub(crate) use super::{ 57 pub(crate) use super::{
58 expressions::block_expr, paths::type_path as path, patterns::pattern, types::type_, 58 expressions::block_expr, paths::type_path as path, patterns::pattern_single, types::type_,
59 }; 59 };
60 60
61 pub(crate) fn expr(p: &mut Parser) { 61 pub(crate) fn expr(p: &mut Parser) {
diff --git a/crates/parser/src/grammar/expressions/atom.rs b/crates/parser/src/grammar/expressions/atom.rs
index 18b63feb7..e897d5a52 100644
--- a/crates/parser/src/grammar/expressions/atom.rs
+++ b/crates/parser/src/grammar/expressions/atom.rs
@@ -156,11 +156,13 @@ fn tuple_expr(p: &mut Parser) -> CompletedMarker {
156 let mut saw_expr = false; 156 let mut saw_expr = false;
157 while !p.at(EOF) && !p.at(T![')']) { 157 while !p.at(EOF) && !p.at(T![')']) {
158 saw_expr = true; 158 saw_expr = true;
159 if !p.at_ts(EXPR_FIRST) { 159
160 p.error("expected expression"); 160 // test tuple_attrs
161 // const A: (i64, i64) = (1, #[cfg(test)] 2);
162 if !expr_with_attrs(p) {
161 break; 163 break;
162 } 164 }
163 expr(p); 165
164 if !p.at(T![')']) { 166 if !p.at(T![')']) {
165 saw_comma = true; 167 saw_comma = true;
166 p.expect(T![,]); 168 p.expect(T![,]);
diff --git a/crates/parser/src/grammar/params.rs b/crates/parser/src/grammar/params.rs
index 3ee4e4fca..2d006a1d5 100644
--- a/crates/parser/src/grammar/params.rs
+++ b/crates/parser/src/grammar/params.rs
@@ -47,20 +47,23 @@ fn list_(p: &mut Parser, flavor: Flavor) {
47 if let FnDef = flavor { 47 if let FnDef = flavor {
48 // test self_param_outer_attr 48 // test self_param_outer_attr
49 // fn f(#[must_use] self) {} 49 // fn f(#[must_use] self) {}
50 let m = p.start();
50 attributes::outer_attrs(p); 51 attributes::outer_attrs(p);
51 opt_self_param(p); 52 opt_self_param(p, m);
52 } 53 }
53 54
54 while !p.at(EOF) && !p.at(ket) { 55 while !p.at(EOF) && !p.at(ket) {
55 // test param_outer_arg 56 // test param_outer_arg
56 // fn f(#[attr1] pat: Type) {} 57 // fn f(#[attr1] pat: Type) {}
58 let m = p.start();
57 attributes::outer_attrs(p); 59 attributes::outer_attrs(p);
58 60
59 if !p.at_ts(PARAM_FIRST) { 61 if !p.at_ts(PARAM_FIRST) {
60 p.error("expected value parameter"); 62 p.error("expected value parameter");
63 m.abandon(p);
61 break; 64 break;
62 } 65 }
63 let param = param(p, flavor); 66 let param = param(p, m, flavor);
64 if !p.at(ket) { 67 if !p.at(ket) {
65 p.expect(T![,]); 68 p.expect(T![,]);
66 } 69 }
@@ -77,9 +80,8 @@ const PARAM_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYPE_FIRST);
77 80
78struct Variadic(bool); 81struct Variadic(bool);
79 82
80fn param(p: &mut Parser, flavor: Flavor) -> Variadic { 83fn param(p: &mut Parser, m: Marker, flavor: Flavor) -> Variadic {
81 let mut res = Variadic(false); 84 let mut res = Variadic(false);
82 let m = p.start();
83 match flavor { 85 match flavor {
84 // test param_list_vararg 86 // test param_list_vararg
85 // extern "C" { fn printf(format: *const i8, ...) -> i32; } 87 // extern "C" { fn printf(format: *const i8, ...) -> i32; }
@@ -151,10 +153,8 @@ fn variadic_param(p: &mut Parser) -> bool {
151// fn d(&'a mut self, x: i32) {} 153// fn d(&'a mut self, x: i32) {}
152// fn e(mut self) {} 154// fn e(mut self) {}
153// } 155// }
154fn opt_self_param(p: &mut Parser) { 156fn opt_self_param(p: &mut Parser, m: Marker) {
155 let m;
156 if p.at(T![self]) || p.at(T![mut]) && p.nth(1) == T![self] { 157 if p.at(T![self]) || p.at(T![mut]) && p.nth(1) == T![self] {
157 m = p.start();
158 p.eat(T![mut]); 158 p.eat(T![mut]);
159 p.eat(T![self]); 159 p.eat(T![self]);
160 // test arb_self_types 160 // test arb_self_types
@@ -174,9 +174,8 @@ fn opt_self_param(p: &mut Parser) {
174 (T![&], T![mut], T![self], _) => 3, 174 (T![&], T![mut], T![self], _) => 3,
175 (T![&], LIFETIME_IDENT, T![self], _) => 3, 175 (T![&], LIFETIME_IDENT, T![self], _) => 3,
176 (T![&], LIFETIME_IDENT, T![mut], T![self]) => 4, 176 (T![&], LIFETIME_IDENT, T![mut], T![self]) => 4,
177 _ => return, 177 _ => return m.abandon(p),
178 }; 178 };
179 m = p.start();
180 p.bump_any(); 179 p.bump_any();
181 if p.at(LIFETIME_IDENT) { 180 if p.at(LIFETIME_IDENT) {
182 lifetime(p); 181 lifetime(p);
diff --git a/crates/parser/src/grammar/type_params.rs b/crates/parser/src/grammar/type_params.rs
index 9c3f7c28a..4aeccd193 100644
--- a/crates/parser/src/grammar/type_params.rs
+++ b/crates/parser/src/grammar/type_params.rs
@@ -113,7 +113,7 @@ fn type_bound(p: &mut Parser) -> bool {
113 p.eat(T![?]); 113 p.eat(T![?]);
114 match p.current() { 114 match p.current() {
115 LIFETIME_IDENT => lifetime(p), 115 LIFETIME_IDENT => lifetime(p),
116 T![for] => types::for_type(p), 116 T![for] => types::for_type(p, false),
117 _ if paths::is_use_path_start(p) => types::path_type_(p, false), 117 _ if paths::is_use_path_start(p) => types::path_type_(p, false),
118 _ => { 118 _ => {
119 m.abandon(p); 119 m.abandon(p);
diff --git a/crates/parser/src/grammar/types.rs b/crates/parser/src/grammar/types.rs
index 36a15eace..94cbf7d85 100644
--- a/crates/parser/src/grammar/types.rs
+++ b/crates/parser/src/grammar/types.rs
@@ -44,7 +44,7 @@ fn type_with_bounds_cond(p: &mut Parser, allow_bounds: bool) {
44 T![&] => ref_type(p), 44 T![&] => ref_type(p),
45 T![_] => infer_type(p), 45 T![_] => infer_type(p),
46 T![fn] | T![unsafe] | T![extern] => fn_ptr_type(p), 46 T![fn] | T![unsafe] | T![extern] => fn_ptr_type(p),
47 T![for] => for_type(p), 47 T![for] => for_type(p, allow_bounds),
48 T![impl] => impl_trait_type(p), 48 T![impl] => impl_trait_type(p),
49 T![dyn] => dyn_trait_type(p), 49 T![dyn] => dyn_trait_type(p),
50 // Some path types are not allowed to have bounds (no plus) 50 // Some path types are not allowed to have bounds (no plus)
@@ -227,7 +227,7 @@ pub(super) fn for_binder(p: &mut Parser) {
227// type A = for<'a> fn() -> (); 227// type A = for<'a> fn() -> ();
228// type B = for<'a> unsafe extern "C" fn(&'a ()) -> (); 228// type B = for<'a> unsafe extern "C" fn(&'a ()) -> ();
229// type Obj = for<'a> PartialEq<&'a i32>; 229// type Obj = for<'a> PartialEq<&'a i32>;
230pub(super) fn for_type(p: &mut Parser) { 230pub(super) fn for_type(p: &mut Parser, allow_bounds: bool) {
231 assert!(p.at(T![for])); 231 assert!(p.at(T![for]));
232 let m = p.start(); 232 let m = p.start();
233 for_binder(p); 233 for_binder(p);
@@ -240,7 +240,13 @@ pub(super) fn for_type(p: &mut Parser) {
240 } 240 }
241 } 241 }
242 type_no_bounds(p); 242 type_no_bounds(p);
243 m.complete(p, FOR_TYPE); 243 let completed = m.complete(p, FOR_TYPE);
244
245 // test no_dyn_trait_leading_for
246 // type A = for<'a> Test<'a> + Send;
247 if allow_bounds {
248 opt_type_bounds_as_dyn_trait_type(p, completed);
249 }
244} 250}
245 251
246// test impl_trait_type 252// test impl_trait_type
@@ -290,7 +296,7 @@ fn path_or_macro_type_(p: &mut Parser, allow_bounds: bool) {
290 let path = m.complete(p, kind); 296 let path = m.complete(p, kind);
291 297
292 if allow_bounds { 298 if allow_bounds {
293 opt_path_type_bounds_as_dyn_trait_type(p, path); 299 opt_type_bounds_as_dyn_trait_type(p, path);
294 } 300 }
295} 301}
296 302
@@ -304,19 +310,23 @@ pub(super) fn path_type_(p: &mut Parser, allow_bounds: bool) {
304 // fn foo() -> Box<dyn T + 'f> {} 310 // fn foo() -> Box<dyn T + 'f> {}
305 let path = m.complete(p, PATH_TYPE); 311 let path = m.complete(p, PATH_TYPE);
306 if allow_bounds { 312 if allow_bounds {
307 opt_path_type_bounds_as_dyn_trait_type(p, path); 313 opt_type_bounds_as_dyn_trait_type(p, path);
308 } 314 }
309} 315}
310 316
311/// This turns a parsed PATH_TYPE optionally into a DYN_TRAIT_TYPE 317/// This turns a parsed PATH_TYPE or FOR_TYPE optionally into a DYN_TRAIT_TYPE
312/// with a TYPE_BOUND_LIST 318/// with a TYPE_BOUND_LIST
313fn opt_path_type_bounds_as_dyn_trait_type(p: &mut Parser, path_type_marker: CompletedMarker) { 319fn opt_type_bounds_as_dyn_trait_type(p: &mut Parser, type_marker: CompletedMarker) {
320 assert!(matches!(
321 type_marker.kind(),
322 SyntaxKind::PATH_TYPE | SyntaxKind::FOR_TYPE | SyntaxKind::MACRO_CALL
323 ));
314 if !p.at(T![+]) { 324 if !p.at(T![+]) {
315 return; 325 return;
316 } 326 }
317 327
318 // First create a TYPE_BOUND from the completed PATH_TYPE 328 // First create a TYPE_BOUND from the completed PATH_TYPE
319 let m = path_type_marker.precede(p).complete(p, TYPE_BOUND); 329 let m = type_marker.precede(p).complete(p, TYPE_BOUND);
320 330
321 // Next setup a marker for the TYPE_BOUND_LIST 331 // Next setup a marker for the TYPE_BOUND_LIST
322 let m = m.precede(p); 332 let m = m.precede(p);
diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs
index ab8e4c70e..811e740f9 100644
--- a/crates/parser/src/lib.rs
+++ b/crates/parser/src/lib.rs
@@ -112,7 +112,7 @@ pub fn parse_fragment(
112 FragmentKind::Path => grammar::fragments::path, 112 FragmentKind::Path => grammar::fragments::path,
113 FragmentKind::Expr => grammar::fragments::expr, 113 FragmentKind::Expr => grammar::fragments::expr,
114 FragmentKind::Type => grammar::fragments::type_, 114 FragmentKind::Type => grammar::fragments::type_,
115 FragmentKind::Pattern => grammar::fragments::pattern, 115 FragmentKind::Pattern => grammar::fragments::pattern_single,
116 FragmentKind::Item => grammar::fragments::item, 116 FragmentKind::Item => grammar::fragments::item,
117 FragmentKind::Block => grammar::fragments::block_expr, 117 FragmentKind::Block => grammar::fragments::block_expr,
118 FragmentKind::Visibility => grammar::fragments::opt_visibility, 118 FragmentKind::Visibility => grammar::fragments::opt_visibility,
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 1f4b5c24c..11cdae57f 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -33,7 +33,7 @@ config_data! {
33 callInfo_full: bool = "true", 33 callInfo_full: bool = "true",
34 34
35 /// Automatically refresh project info via `cargo metadata` on 35 /// Automatically refresh project info via `cargo metadata` on
36 /// Cargo.toml changes. 36 /// `Cargo.toml` changes.
37 cargo_autoreload: bool = "true", 37 cargo_autoreload: bool = "true",
38 /// Activate all available features. 38 /// Activate all available features.
39 cargo_allFeatures: bool = "false", 39 cargo_allFeatures: bool = "false",
@@ -52,7 +52,7 @@ config_data! {
52 /// Run specified `cargo check` command for diagnostics on save. 52 /// Run specified `cargo check` command for diagnostics on save.
53 checkOnSave_enable: bool = "true", 53 checkOnSave_enable: bool = "true",
54 /// Check with all features (will be passed as `--all-features`). 54 /// Check with all features (will be passed as `--all-features`).
55 /// Defaults to `rust-analyzer.cargo.allFeatures`. 55 /// Defaults to `#rust-analyzer.cargo.allFeatures#`.
56 checkOnSave_allFeatures: Option<bool> = "null", 56 checkOnSave_allFeatures: Option<bool> = "null",
57 /// Check all targets and tests (will be passed as `--all-targets`). 57 /// Check all targets and tests (will be passed as `--all-targets`).
58 checkOnSave_allTargets: bool = "true", 58 checkOnSave_allTargets: bool = "true",
@@ -61,12 +61,12 @@ config_data! {
61 /// Do not activate the `default` feature. 61 /// Do not activate the `default` feature.
62 checkOnSave_noDefaultFeatures: Option<bool> = "null", 62 checkOnSave_noDefaultFeatures: Option<bool> = "null",
63 /// Check for a specific target. Defaults to 63 /// Check for a specific target. Defaults to
64 /// `rust-analyzer.cargo.target`. 64 /// `#rust-analyzer.cargo.target#`.
65 checkOnSave_target: Option<String> = "null", 65 checkOnSave_target: Option<String> = "null",
66 /// Extra arguments for `cargo check`. 66 /// Extra arguments for `cargo check`.
67 checkOnSave_extraArgs: Vec<String> = "[]", 67 checkOnSave_extraArgs: Vec<String> = "[]",
68 /// List of features to activate. Defaults to 68 /// List of features to activate. Defaults to
69 /// `rust-analyzer.cargo.features`. 69 /// `#rust-analyzer.cargo.features#`.
70 checkOnSave_features: Option<Vec<String>> = "null", 70 checkOnSave_features: Option<Vec<String>> = "null",
71 /// Advanced option, fully override the command rust-analyzer uses for 71 /// Advanced option, fully override the command rust-analyzer uses for
72 /// checking. The command should include `--message-format=json` or 72 /// checking. The command should include `--message-format=json` or
@@ -80,7 +80,7 @@ config_data! {
80 /// Whether to show postfix snippets like `dbg`, `if`, `not`, etc. 80 /// Whether to show postfix snippets like `dbg`, `if`, `not`, etc.
81 completion_postfix_enable: bool = "true", 81 completion_postfix_enable: bool = "true",
82 /// Toggles the additional completions that automatically add imports when completed. 82 /// Toggles the additional completions that automatically add imports when completed.
83 /// Note that your client have to specify the `additionalTextEdits` LSP client capability to truly have this feature enabled. 83 /// Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
84 completion_autoimport_enable: bool = "true", 84 completion_autoimport_enable: bool = "true",
85 85
86 /// Whether to show native rust-analyzer diagnostics. 86 /// Whether to show native rust-analyzer diagnostics.
@@ -90,13 +90,13 @@ config_data! {
90 diagnostics_enableExperimental: bool = "true", 90 diagnostics_enableExperimental: bool = "true",
91 /// List of rust-analyzer diagnostics to disable. 91 /// List of rust-analyzer diagnostics to disable.
92 diagnostics_disabled: FxHashSet<String> = "[]", 92 diagnostics_disabled: FxHashSet<String> = "[]",
93 /// List of warnings that should be displayed with info severity.\nThe 93 /// List of warnings that should be displayed with info severity.\n\nThe
94 /// warnings will be indicated by a blue squiggly underline in code and 94 /// warnings will be indicated by a blue squiggly underline in code and
95 /// a blue icon in the problems panel. 95 /// a blue icon in the `Problems Panel`.
96 diagnostics_warningsAsHint: Vec<String> = "[]", 96 diagnostics_warningsAsHint: Vec<String> = "[]",
97 /// List of warnings that should be displayed with hint severity.\nThe 97 /// List of warnings that should be displayed with hint severity.\n\nThe
98 /// warnings will be indicated by faded text or three dots in code and 98 /// warnings will be indicated by faded text or three dots in code and
99 /// will not show up in the problems panel. 99 /// will not show up in the `Problems Panel`.
100 diagnostics_warningsAsInfo: Vec<String> = "[]", 100 diagnostics_warningsAsInfo: Vec<String> = "[]",
101 101
102 /// Controls file watching implementation. 102 /// Controls file watching implementation.
@@ -121,7 +121,7 @@ config_data! {
121 121
122 /// Whether to show inlay type hints for method chains. 122 /// Whether to show inlay type hints for method chains.
123 inlayHints_chainingHints: bool = "true", 123 inlayHints_chainingHints: bool = "true",
124 /// Maximum length for inlay hints. 124 /// Maximum length for inlay hints. Default is unlimited.
125 inlayHints_maxLength: Option<usize> = "null", 125 inlayHints_maxLength: Option<usize> = "null",
126 /// Whether to show function parameter name inlay hints at the call 126 /// Whether to show function parameter name inlay hints at the call
127 /// site. 127 /// site.
@@ -145,27 +145,27 @@ config_data! {
145 lens_methodReferences: bool = "false", 145 lens_methodReferences: bool = "false",
146 146
147 /// Disable project auto-discovery in favor of explicitly specified set 147 /// Disable project auto-discovery in favor of explicitly specified set
148 /// of projects. \nElements must be paths pointing to Cargo.toml, 148 /// of projects.\n\nElements must be paths pointing to `Cargo.toml`,
149 /// rust-project.json, or JSON objects in rust-project.json format. 149 /// `rust-project.json`, or JSON objects in `rust-project.json` format.
150 linkedProjects: Vec<ManifestOrProjectJson> = "[]", 150 linkedProjects: Vec<ManifestOrProjectJson> = "[]",
151 /// Number of syntax trees rust-analyzer keeps in memory. 151 /// Number of syntax trees rust-analyzer keeps in memory. Defaults to 128.
152 lruCapacity: Option<usize> = "null", 152 lruCapacity: Option<usize> = "null",
153 /// Whether to show `can't find Cargo.toml` error message. 153 /// Whether to show `can't find Cargo.toml` error message.
154 notifications_cargoTomlNotFound: bool = "true", 154 notifications_cargoTomlNotFound: bool = "true",
155 /// Enable Proc macro support, cargo.loadOutDirsFromCheck must be 155 /// Enable Proc macro support, `#rust-analyzer.cargo.loadOutDirsFromCheck#` must be
156 /// enabled. 156 /// enabled.
157 procMacro_enable: bool = "false", 157 procMacro_enable: bool = "false",
158 158
159 /// Command to be executed instead of 'cargo' for runnables. 159 /// Command to be executed instead of 'cargo' for runnables.
160 runnables_overrideCargo: Option<String> = "null", 160 runnables_overrideCargo: Option<String> = "null",
161 /// Additional arguments to be passed to cargo for runnables such as 161 /// Additional arguments to be passed to cargo for runnables such as
162 /// tests or binaries.\nFor example, it may be '--release'. 162 /// tests or binaries.\nFor example, it may be `--release`.
163 runnables_cargoExtraArgs: Vec<String> = "[]", 163 runnables_cargoExtraArgs: Vec<String> = "[]",
164 164
165 /// Path to the rust compiler sources, for usage in rustc_private projects. 165 /// Path to the rust compiler sources, for usage in rustc_private projects.
166 rustcSource : Option<String> = "null", 166 rustcSource : Option<String> = "null",
167 167
168 /// Additional arguments to rustfmt. 168 /// Additional arguments to `rustfmt`.
169 rustfmt_extraArgs: Vec<String> = "[]", 169 rustfmt_extraArgs: Vec<String> = "[]",
170 /// Advanced option, fully override the command rust-analyzer uses for 170 /// Advanced option, fully override the command rust-analyzer uses for
171 /// formatting. 171 /// formatting.
@@ -758,7 +758,7 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
758 ], 758 ],
759 "enumDescriptions": [ 759 "enumDescriptions": [
760 "Insert import paths relative to the current module, using up to one `super` prefix if the parent module contains the requested item.", 760 "Insert import paths relative to the current module, using up to one `super` prefix if the parent module contains the requested item.",
761 "Prefix all import paths with `self` if they don't begin with `self`, `super`, `crate` or a crate name", 761 "Prefix all import paths with `self` if they don't begin with `self`, `super`, `crate` or a crate name.",
762 "Force import paths to be absolute by always starting them with `crate` or the crate name they refer to." 762 "Force import paths to be absolute by always starting them with `crate` or the crate name they refer to."
763 ], 763 ],
764 }, 764 },
diff --git a/crates/rust-analyzer/src/diagnostics/to_proto.rs b/crates/rust-analyzer/src/diagnostics/to_proto.rs
index f16f97131..540759198 100644
--- a/crates/rust-analyzer/src/diagnostics/to_proto.rs
+++ b/crates/rust-analyzer/src/diagnostics/to_proto.rs
@@ -319,6 +319,10 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
319 message: "original diagnostic".to_string(), 319 message: "original diagnostic".to_string(),
320 }; 320 };
321 for info in &related_information { 321 for info in &related_information {
322 // Filter out empty/non-existent messages, as they greatly confuse VS Code.
323 if info.message.is_empty() {
324 continue;
325 }
322 diagnostics.push(MappedRustDiagnostic { 326 diagnostics.push(MappedRustDiagnostic {
323 url: info.location.uri.clone(), 327 url: info.location.uri.clone(),
324 fixes: fixes.clone(), // share fixes to make them easier to apply 328 fixes: fixes.clone(), // share fixes to make them easier to apply
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index e0561b5a7..5a1ae96aa 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -634,30 +634,47 @@ pub(crate) fn snippet_text_document_edit(
634 Ok(lsp_ext::SnippetTextDocumentEdit { text_document, edits }) 634 Ok(lsp_ext::SnippetTextDocumentEdit { text_document, edits })
635} 635}
636 636
637pub(crate) fn resource_op( 637pub(crate) fn snippet_text_document_ops(
638 snap: &GlobalStateSnapshot, 638 snap: &GlobalStateSnapshot,
639 file_system_edit: FileSystemEdit, 639 file_system_edit: FileSystemEdit,
640) -> lsp_types::ResourceOp { 640) -> Vec<lsp_ext::SnippetDocumentChangeOperation> {
641 let mut ops = Vec::new();
641 match file_system_edit { 642 match file_system_edit {
642 FileSystemEdit::CreateFile { dst } => { 643 FileSystemEdit::CreateFile { dst, initial_contents } => {
643 let uri = snap.anchored_path(&dst); 644 let uri = snap.anchored_path(&dst);
644 lsp_types::ResourceOp::Create(lsp_types::CreateFile { 645 let create_file = lsp_types::ResourceOp::Create(lsp_types::CreateFile {
645 uri, 646 uri: uri.clone(),
646 options: None, 647 options: None,
647 annotation_id: None, 648 annotation_id: None,
648 }) 649 });
650 ops.push(lsp_ext::SnippetDocumentChangeOperation::Op(create_file));
651 if !initial_contents.is_empty() {
652 let text_document =
653 lsp_types::OptionalVersionedTextDocumentIdentifier { uri, version: None };
654 let range = range(&LineIndex::new(""), TextRange::empty(TextSize::from(0)));
655 let text_edit = lsp_ext::SnippetTextEdit {
656 range,
657 new_text: initial_contents,
658 insert_text_format: Some(lsp_types::InsertTextFormat::PlainText),
659 };
660 let edit_file =
661 lsp_ext::SnippetTextDocumentEdit { text_document, edits: vec![text_edit] };
662 ops.push(lsp_ext::SnippetDocumentChangeOperation::Edit(edit_file));
663 }
649 } 664 }
650 FileSystemEdit::MoveFile { src, dst } => { 665 FileSystemEdit::MoveFile { src, dst } => {
651 let old_uri = snap.file_id_to_url(src); 666 let old_uri = snap.file_id_to_url(src);
652 let new_uri = snap.anchored_path(&dst); 667 let new_uri = snap.anchored_path(&dst);
653 lsp_types::ResourceOp::Rename(lsp_types::RenameFile { 668 let rename_file = lsp_types::ResourceOp::Rename(lsp_types::RenameFile {
654 old_uri, 669 old_uri,
655 new_uri, 670 new_uri,
656 options: None, 671 options: None,
657 annotation_id: None, 672 annotation_id: None,
658 }) 673 });
674 ops.push(lsp_ext::SnippetDocumentChangeOperation::Op(rename_file))
659 } 675 }
660 } 676 }
677 ops
661} 678}
662 679
663pub(crate) fn snippet_workspace_edit( 680pub(crate) fn snippet_workspace_edit(
@@ -666,8 +683,8 @@ pub(crate) fn snippet_workspace_edit(
666) -> Result<lsp_ext::SnippetWorkspaceEdit> { 683) -> Result<lsp_ext::SnippetWorkspaceEdit> {
667 let mut document_changes: Vec<lsp_ext::SnippetDocumentChangeOperation> = Vec::new(); 684 let mut document_changes: Vec<lsp_ext::SnippetDocumentChangeOperation> = Vec::new();
668 for op in source_change.file_system_edits { 685 for op in source_change.file_system_edits {
669 let op = resource_op(&snap, op); 686 let ops = snippet_text_document_ops(snap, op);
670 document_changes.push(lsp_ext::SnippetDocumentChangeOperation::Op(op)); 687 document_changes.extend_from_slice(&ops);
671 } 688 }
672 for edit in source_change.source_file_edits { 689 for edit in source_change.source_file_edits {
673 let edit = snippet_text_document_edit(&snap, source_change.is_snippet, edit)?; 690 let edit = snippet_text_document_edit(&snap, source_change.is_snippet, edit)?;
diff --git a/crates/syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rast b/crates/syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rast
index 6403ff8d5..d3219f0b2 100644
--- a/crates/syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rast
+++ b/crates/syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rast
@@ -6,16 +6,16 @@ [email protected]
6 [email protected] "f" 6 [email protected] "f"
7 [email protected] 7 [email protected]
8 [email protected] "(" 8 [email protected] "("
9 ATT[email protected]6 9 SELF_PARAM@5..21
10 POUND@5..6 "#" 10 ATTR@5..16
11 L_BRACK@6..7 "[" 11 POUND@5..6 "#"
12 PATH@7..15 12 L_BRACK@6..7 "["
13 PATH_SEGMENT@7..15 13 [email protected]
14 NAME_REF@7..15 14 PATH_SEGMENT@7..15
15 IDENT@7..15 "must_use" 15 NAME_REF@7..15
16 R_BRACK@15..16 "]" 16 IDENT@7..15 "must_use"
17 WHITESPACE@16..17 " " 17 R_BRACK@15..16 "]"
18 SELF_PARAM@17..21 18 WHITESPACE@16..17 " "
19 [email protected] "self" 19 [email protected] "self"
20 [email protected] ")" 20 [email protected] ")"
21 [email protected] " " 21 [email protected] " "
diff --git a/crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rast b/crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rast
new file mode 100644
index 000000000..edfcb288c
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rast
@@ -0,0 +1,43 @@
1[email protected]
2 [email protected]
3 [email protected] "type"
4 [email protected] " "
5 [email protected]
6 [email protected] "A"
7 [email protected] " "
8 [email protected] "="
9 [email protected] " "
10 [email protected]
11 [email protected]
12 [email protected]
13 [email protected]
14 [email protected] "for"
15 [email protected]
16 [email protected] "<"
17 [email protected]
18 [email protected]
19 [email protected] "\'a"
20 [email protected] ">"
21 [email protected] " "
22 [email protected]
23 [email protected]
24 [email protected]
25 [email protected]
26 [email protected] "Test"
27 [email protected]
28 [email protected] "<"
29 [email protected]
30 [email protected]
31 [email protected] "\'a"
32 [email protected] ">"
33 [email protected] " "
34 [email protected] "+"
35 [email protected] " "
36 [email protected]
37 [email protected]
38 [email protected]
39 [email protected]
40 [email protected]
41 [email protected] "Send"
42 [email protected] ";"
43 [email protected] "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rs b/crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rs
new file mode 100644
index 000000000..47a71fd19
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rs
@@ -0,0 +1 @@
type A = for<'a> Test<'a> + Send;
diff --git a/crates/syntax/test_data/parser/inline/ok/0154_tuple_attrs.rast b/crates/syntax/test_data/parser/inline/ok/0154_tuple_attrs.rast
new file mode 100644
index 000000000..d34b21abe
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0154_tuple_attrs.rast
@@ -0,0 +1,50 @@
1[email protected]
2 [email protected]
3 [email protected] "const"
4 [email protected] " "
5 [email protected]
6 [email protected] "A"
7 [email protected] ":"
8 [email protected] " "
9 [email protected]
10 [email protected] "("
11 [email protected]
12 [email protected]
13 [email protected]
14 [email protected]
15 [email protected] "i64"
16 [email protected] ","
17 [email protected] " "
18 [email protected]
19 [email protected]
20 [email protected]
21 [email protected]
22 [email protected] "i64"
23 [email protected] ")"
24 [email protected] " "
25 [email protected] "="
26 [email protected] " "
27 [email protected]
28 [email protected] "("
29 [email protected]
30 [email protected] "1"
31 [email protected] ","
32 [email protected] " "
33 [email protected]
34 [email protected]
35 [email protected] "#"
36 [email protected] "["
37 [email protected]
38 [email protected]
39 [email protected]
40 [email protected] "cfg"
41 [email protected]
42 [email protected] "("
43 [email protected] "test"
44 [email protected] ")"
45 [email protected] "]"
46 [email protected] " "
47 [email protected] "2"
48 [email protected] ")"
49 [email protected] ";"
50 [email protected] "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0154_tuple_attrs.rs b/crates/syntax/test_data/parser/inline/ok/0154_tuple_attrs.rs
new file mode 100644
index 000000000..f84b7ab31
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0154_tuple_attrs.rs
@@ -0,0 +1 @@
const A: (i64, i64) = (1, #[cfg(test)] 2);
diff --git a/crates/syntax/test_data/parser/ok/0051_parameter_attrs.rast b/crates/syntax/test_data/parser/ok/0051_parameter_attrs.rast
index 8974f9e40..3fed11838 100644
--- a/crates/syntax/test_data/parser/ok/0051_parameter_attrs.rast
+++ b/crates/syntax/test_data/parser/ok/0051_parameter_attrs.rast
@@ -107,16 +107,16 @@ [email protected]
107 [email protected] "i8" 107 [email protected] "i8"
108 [email protected] "," 108 [email protected] ","
109 [email protected] " " 109 [email protected] " "
110 ATT[email protected]3 110 PARAM@106..117
111 POUND@106..107 "#" 111 ATTR@106..113
112 L_BRACK@107..108 "[" 112 POUND@106..107 "#"
113 PATH@108..112 113 L_BRACK@107..108 "["
114 PATH_SEGMENT@108..112 114 [email protected]
115 NAME_REF@108..112 115 PATH_SEGMENT@108..112
116 IDENT@108..112 "attr" 116 NAME_REF@108..112
117 R_BRACK@112..113 "]" 117 IDENT@108..112 "attr"
118 WHITESPACE@113..114 " " 118 R_BRACK@112..113 "]"
119 PARAM@114..117 119 WHITESPACE@113..114 " "
120 [email protected] "..." 120 [email protected] "..."
121 [email protected] ")" 121 [email protected] ")"
122 [email protected] " " 122 [email protected] " "
@@ -153,16 +153,16 @@ [email protected]
153 [email protected] "FnMut" 153 [email protected] "FnMut"
154 [email protected] 154 [email protected]
155 [email protected] "(" 155 [email protected] "("
156 ATT[email protected]53 156 PARAM@146..166
157 POUND@146..147 "#" 157 ATTR@146..153
158 L_BRACK@147..148 "[" 158 POUND@146..147 "#"
159 PATH@148..152 159 L_BRACK@147..148 "["
160 PATH_SEGMENT@148..152 160 [email protected]
161 NAME_REF@148..152 161 PATH_SEGMENT@148..152
162 IDENT@148..152 "attr" 162 NAME_REF@148..152
163 R_BRACK@152..153 "]" 163 IDENT@148..152 "attr"
164 WHITESPACE@153..154 " " 164 R_BRACK@152..153 "]"
165 PARAM@154..166 165 WHITESPACE@153..154 " "
166 [email protected] 166 [email protected]
167 [email protected] "&" 167 [email protected] "&"
168 [email protected] "mut" 168 [email protected] "mut"
@@ -224,17 +224,17 @@ [email protected]
224 [email protected] "u64" 224 [email protected] "u64"
225 [email protected] "," 225 [email protected] ","
226 [email protected] " " 226 [email protected] " "
227 ATT[email protected]1 227 PARAM@213..232
228 POUND@213..214 "#" 228 ATTR@213..221
229 WHITESPACE@214..215 " " 229 POUND@213..214 "#"
230 L_BRACK@215..216 "[" 230 WHITESPACE@214..215 " "
231 PATH@216..220 231 L_BRACK@215..216 "["
232 PATH_SEGMENT@216..220 232 [email protected]
233 NAME_REF@216..220 233 PATH_SEGMENT@216..220
234 IDENT@216..220 "attr" 234 NAME_REF@216..220
235 R_BRACK@220..221 "]" 235 IDENT@216..220 "attr"
236 WHITESPACE@221..222 " " 236 R_BRACK@220..221 "]"
237 PARAM@222..232 237 WHITESPACE@221..222 " "
238 [email protected] 238 [email protected]
239 [email protected] "mut" 239 [email protected] "mut"
240 [email protected] " " 240 [email protected] " "
@@ -271,16 +271,16 @@ [email protected]
271 [email protected] "f" 271 [email protected] "f"
272 [email protected] 272 [email protected]
273 [email protected] "(" 273 [email protected] "("
274 ATT[email protected]68 274 SELF_PARAM@257..273
275 POUND@257..258 "#" 275 ATTR@257..268
276 L_BRACK@258..259 "[" 276 POUND@257..258 "#"
277 PATH@259..267 277 L_BRACK@258..259 "["
278 PATH_SEGMENT@259..267 278 [email protected]
279 NAME_REF@259..267 279 PATH_SEGMENT@259..267
280 IDENT@259..267 "must_use" 280 NAME_REF@259..267
281 R_BRACK@267..268 "]" 281 IDENT@259..267 "must_use"
282 WHITESPACE@268..269 " " 282 R_BRACK@267..268 "]"
283 SELF_PARAM@269..273 283 WHITESPACE@268..269 " "
284 [email protected] "self" 284 [email protected] "self"
285 [email protected] ")" 285 [email protected] ")"
286 [email protected] " " 286 [email protected] " "
@@ -295,16 +295,16 @@ [email protected]
295 [email protected] "g1" 295 [email protected] "g1"
296 [email protected] 296 [email protected]
297 [email protected] "(" 297 [email protected] "("
298 ATTR@289..296 298 SELF_PARAM@289..301
299 POUND@289..290 "#" 299 ATTR@289..296
300 L_BRACK@290..291 "[" 300 POUND@289..290 "#"
301 PATH@291..295 301 L_BRACK@290..291 "["
302 PATH_SEGMENT@291..295 302 [email protected]
303 NAME_REF@291..295 303 PATH_SEGMENT@291..295
304 IDENT@291..295 "attr" 304 NAME_REF@291..295
305 R_BRACK@295..296 "]" 305 IDENT@291..295 "attr"
306 WHITESPACE@296..297 " " 306 R_BRACK@295..296 "]"
307 SELF_PARAM@297..301 307 WHITESPACE@296..297 " "
308 [email protected] "self" 308 [email protected] "self"
309 [email protected] ")" 309 [email protected] ")"
310 [email protected] " " 310 [email protected] " "
@@ -319,16 +319,16 @@ [email protected]
319 [email protected] "g2" 319 [email protected] "g2"
320 [email protected] 320 [email protected]
321 [email protected] "(" 321 [email protected] "("
322 ATT[email protected]24 322 SELF_PARAM@317..330
323 POUND@317..318 "#" 323 ATTR@317..324
324 L_BRACK@318..319 "[" 324 POUND@317..318 "#"
325 PATH@319..323 325 L_BRACK@318..319 "["
326 PATH_SEGMENT@319..323 326 [email protected]
327 NAME_REF@319..323 327 PATH_SEGMENT@319..323
328 IDENT@319..323 "attr" 328 NAME_REF@319..323
329 R_BRACK@323..324 "]" 329 IDENT@319..323 "attr"
330 WHITESPACE@324..325 " " 330 R_BRACK@323..324 "]"
331 SELF_PARAM@325..330 331 WHITESPACE@324..325 " "
332 [email protected] "&" 332 [email protected] "&"
333 [email protected] "self" 333 [email protected] "self"
334 [email protected] ")" 334 [email protected] ")"
@@ -350,16 +350,16 @@ [email protected]
350 [email protected] ">" 350 [email protected] ">"
351 [email protected] 351 [email protected]
352 [email protected] "(" 352 [email protected] "("
353 ATT[email protected]57 353 SELF_PARAM@350..367
354 POUND@350..351 "#" 354 ATTR@350..357
355 L_BRACK@351..352 "[" 355 POUND@350..351 "#"
356 PATH@352..356 356 L_BRACK@351..352 "["
357 PATH_SEGMENT@352..356 357 [email protected]
358 NAME_REF@352..356 358 PATH_SEGMENT@352..356
359 IDENT@352..356 "attr" 359 NAME_REF@352..356
360 R_BRACK@356..357 "]" 360 IDENT@352..356 "attr"
361 WHITESPACE@357..358 " " 361 R_BRACK@356..357 "]"
362 SELF_PARAM@358..367 362 WHITESPACE@357..358 " "
363 [email protected] "&" 363 [email protected] "&"
364 [email protected] "mut" 364 [email protected] "mut"
365 [email protected] " " 365 [email protected] " "
@@ -383,16 +383,16 @@ [email protected]
383 [email protected] ">" 383 [email protected] ">"
384 [email protected] 384 [email protected]
385 [email protected] "(" 385 [email protected] "("
386 ATTR@387..394 386 SELF_PARAM@387..403
387 POUND@387..388 "#" 387 ATTR@387..394
388 L_BRACK@388..389 "[" 388 POUND@387..388 "#"
389 PATH@389..393 389 L_BRACK@388..389 "["
390 PATH_SEGMENT@389..393 390 [email protected]
391 NAME_REF@389..393 391 PATH_SEGMENT@389..393
392 IDENT@389..393 "attr" 392 NAME_REF@389..393
393 R_BRACK@393..394 "]" 393 IDENT@389..393 "attr"
394 WHITESPACE@394..395 " " 394 R_BRACK@393..394 "]"
395 SELF_PARAM@395..403 395 WHITESPACE@394..395 " "
396 [email protected] "&" 396 [email protected] "&"
397 [email protected] 397 [email protected]
398 [email protected] "\'a" 398 [email protected] "\'a"
@@ -417,16 +417,16 @@ [email protected]
417 [email protected] ">" 417 [email protected] ">"
418 [email protected] 418 [email protected]
419 [email protected] "(" 419 [email protected] "("
420 ATT[email protected]0 420 SELF_PARAM@423..443
421 POUND@423..424 "#" 421 ATTR@423..430
422 L_BRACK@424..425 "[" 422 POUND@423..424 "#"
423 PATH@425..429 423 L_BRACK@424..425 "["
424 PATH_SEGMENT@425..429 424 [email protected]
425 NAME_REF@425..429 425 PATH_SEGMENT@425..429
426 IDENT@425..429 "attr" 426 NAME_REF@425..429
427 R_BRACK@429..430 "]" 427 IDENT@425..429 "attr"
428 WHITESPACE@430..431 " " 428 R_BRACK@429..430 "]"
429 SELF_PARAM@431..443 429 WHITESPACE@430..431 " "
430 [email protected] "&" 430 [email protected] "&"
431 [email protected] 431 [email protected]
432 [email protected] "\'a" 432 [email protected] "\'a"
@@ -447,16 +447,16 @@ [email protected]
447 [email protected] "c" 447 [email protected] "c"
448 [email protected] 448 [email protected]
449 [email protected] "(" 449 [email protected] "("
450 ATT[email protected]5 450 SELF_PARAM@458..476
451 POUND@458..459 "#" 451 ATTR@458..465
452 L_BRACK@459..460 "[" 452 POUND@458..459 "#"
453 PATH@460..464 453 L_BRACK@459..460 "["
454 PATH_SEGMENT@460..464 454 [email protected]
455 NAME_REF@460..464 455 PATH_SEGMENT@460..464
456 IDENT@460..464 "attr" 456 NAME_REF@460..464
457 R_BRACK@464..465 "]" 457 IDENT@460..464 "attr"
458 WHITESPACE@465..466 " " 458 R_BRACK@464..465 "]"
459 SELF_PARAM@466..476 459 WHITESPACE@465..466 " "
460 [email protected] "self" 460 [email protected] "self"
461 [email protected] ":" 461 [email protected] ":"
462 [email protected] " " 462 [email protected] " "
@@ -478,16 +478,16 @@ [email protected]
478 [email protected] "d" 478 [email protected] "d"
479 [email protected] 479 [email protected]
480 [email protected] "(" 480 [email protected] "("
481 ATTR@491..498 481 SELF_PARAM@491..513
482 POUND@491..492 "#" 482 ATTR@491..498
483 L_BRACK@492..493 "[" 483 POUND@491..492 "#"
484 PATH@493..497 484 L_BRACK@492..493 "["
485 PATH_SEGMENT@493..497 485 [email protected]
486 NAME_REF@493..497 486 PATH_SEGMENT@493..497
487 IDENT@493..497 "attr" 487 NAME_REF@493..497
488 R_BRACK@497..498 "]" 488 IDENT@493..497 "attr"
489 WHITESPACE@498..499 " " 489 R_BRACK@497..498 "]"
490 SELF_PARAM@499..513 490 WHITESPACE@498..499 " "
491 [email protected] "self" 491 [email protected] "self"
492 [email protected] ":" 492 [email protected] ":"
493 [email protected] " " 493 [email protected] " "
diff --git a/crates/syntax/test_data/parser/ok/0063_variadic_fun.rast b/crates/syntax/test_data/parser/ok/0063_variadic_fun.rast
index 4009b3ff8..f7c094898 100644
--- a/crates/syntax/test_data/parser/ok/0063_variadic_fun.rast
+++ b/crates/syntax/test_data/parser/ok/0063_variadic_fun.rast
@@ -92,20 +92,20 @@ [email protected]
92 [email protected] "u8" 92 [email protected] "u8"
93 [email protected] "," 93 [email protected] ","
94 [email protected] " " 94 [email protected] " "
95 ATT[email protected]5 95 PARAM@92..120
96 POUND@92..93 "#" 96 ATTR@92..105
97 L_BRACK@93..94 "[" 97 POUND@92..93 "#"
98 PATH@94..97 98 L_BRACK@93..94 "["
99 PATH_SEGMENT@94..97 99 [email protected]
100 NAME_REF@94..97 100 PATH_SEGMENT@94..97
101 IDENT@94..97 "cfg" 101 NAME_REF@94..97
102 TOKEN_TREE@97..104 102 IDENT@94..97 "cfg"
103 L_PAREN@97..98 "(" 103 TOKEN_TREE@97..104
104 IDENT@98..103 "never" 104 L_PAREN@97..98 "("
105 R_PAREN@103..104 ")" 105 IDENT@98..103 "never"
106 R_BRACK@104..105 "]" 106 R_PAREN@103..104 ")"
107 WHITESPACE@105..106 " " 107 R_BRACK@104..105 "]"
108 PARAM@106..120 108 WHITESPACE@105..106 " "
109 [email protected] 109 [email protected]
110 [email protected] "[" 110 [email protected] "["
111 [email protected] 111 [email protected]