aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock51
-rw-r--r--Cargo.toml2
-rw-r--r--crates/assists/src/handlers/reorder_fields.rs129
-rw-r--r--crates/completion/src/render/macro_.rs6
-rw-r--r--crates/hir/src/code_model.rs8
-rw-r--r--crates/hir/src/from_id.rs17
-rw-r--r--crates/hir/src/has_source.rs16
-rw-r--r--crates/hir/src/semantics.rs53
-rw-r--r--crates/hir/src/semantics/source_to_def.rs26
-rw-r--r--crates/hir_def/src/adt.rs13
-rw-r--r--crates/hir_def/src/body/lower.rs246
-rw-r--r--crates/hir_def/src/generics.rs55
-rw-r--r--crates/hir_def/src/item_tree.rs22
-rw-r--r--crates/hir_def/src/item_tree/lower.rs29
-rw-r--r--crates/hir_def/src/keys.rs5
-rw-r--r--crates/hir_def/src/nameres/collector.rs65
-rw-r--r--crates/hir_def/src/path/lower.rs8
-rw-r--r--crates/hir_def/src/src.rs5
-rw-r--r--crates/hir_expand/src/builtin_macro.rs41
-rw-r--r--crates/hir_expand/src/db.rs4
-rw-r--r--crates/hir_expand/src/lib.rs2
-rw-r--r--crates/hir_expand/src/name.rs3
-rw-r--r--crates/hir_ty/src/tests/macros.rs1
-rw-r--r--crates/hir_ty/src/tests/regression.rs24
-rw-r--r--crates/ide/src/file_structure.rs14
-rw-r--r--crates/ide/src/references.rs117
-rw-r--r--crates/ide/src/syntax_highlighting.rs52
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html2
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_strings.html6
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlighting.html6
-rw-r--r--crates/ide_db/src/defs.rs2
-rw-r--r--crates/ide_db/src/search.rs15
-rw-r--r--crates/ide_db/src/symbol_index.rs8
-rw-r--r--crates/mbe/src/mbe_expander.rs2
-rw-r--r--crates/mbe/src/tests.rs4
-rw-r--r--crates/parser/src/grammar/items.rs44
-rw-r--r--crates/parser/src/syntax_kind/generated.rs7
-rw-r--r--crates/proc_macro_srv/Cargo.toml2
-rw-r--r--crates/proc_macro_srv/src/dylib.rs65
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs43
-rw-r--r--crates/syntax/src/ast/node_ext.rs17
-rw-r--r--crates/syntax/src/display.rs2
-rw-r--r--crates/syntax/src/parsing/text_tree_sink.rs4
-rw-r--r--crates/syntax/src/validation.rs14
-rw-r--r--crates/syntax/test_data/parser/err/0002_duplicate_shebang.rast14
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0062_mod_contents.rast7
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0096_no_semi_after_block.rast48
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0160_try_macro_rules.rast7
-rw-r--r--crates/syntax/test_data/parser/ok/0053_outer_attribute_on_macro_rules.rast7
-rw-r--r--docs/dev/style.md8
-rw-r--r--editors/code/.vscodeignore1
-rw-r--r--xtask/src/ast_src.rs4
52 files changed, 861 insertions, 492 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 8cb5fd7ad..ff2c33f45 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -89,7 +89,7 @@ dependencies = [
89 "cfg-if 1.0.0", 89 "cfg-if 1.0.0",
90 "libc", 90 "libc",
91 "miniz_oxide", 91 "miniz_oxide",
92 "object", 92 "object 0.22.0",
93 "rustc-demangle", 93 "rustc-demangle",
94] 94]
95 95
@@ -500,17 +500,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
500checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" 500checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce"
501 501
502[[package]] 502[[package]]
503name = "goblin"
504version = "0.2.3"
505source = "registry+https://github.com/rust-lang/crates.io-index"
506checksum = "d20fd25aa456527ce4f544271ae4fea65d2eda4a6561ea56f39fb3ee4f7e3884"
507dependencies = [
508 "log",
509 "plain",
510 "scroll",
511]
512
513[[package]]
514name = "hashbrown" 503name = "hashbrown"
515version = "0.9.1" 504version = "0.9.1"
516source = "registry+https://github.com/rust-lang/crates.io-index" 505source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1055,6 +1044,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1055checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397" 1044checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397"
1056 1045
1057[[package]] 1046[[package]]
1047name = "object"
1048version = "0.23.0"
1049source = "registry+https://github.com/rust-lang/crates.io-index"
1050checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4"
1051
1052[[package]]
1058name = "once_cell" 1053name = "once_cell"
1059version = "1.5.2" 1054version = "1.5.2"
1060source = "registry+https://github.com/rust-lang/crates.io-index" 1055source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1159,12 +1154,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1159checksum = "6b063f57ec186e6140e2b8b6921e5f1bd89c7356dda5b33acc5401203ca6131c" 1154checksum = "6b063f57ec186e6140e2b8b6921e5f1bd89c7356dda5b33acc5401203ca6131c"
1160 1155
1161[[package]] 1156[[package]]
1162name = "plain"
1163version = "0.2.3"
1164source = "registry+https://github.com/rust-lang/crates.io-index"
1165checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
1166
1167[[package]]
1168name = "proc-macro2" 1157name = "proc-macro2"
1169version = "1.0.24" 1158version = "1.0.24"
1170source = "registry+https://github.com/rust-lang/crates.io-index" 1159source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1192,10 +1181,10 @@ version = "0.0.0"
1192dependencies = [ 1181dependencies = [
1193 "cargo_metadata", 1182 "cargo_metadata",
1194 "difference", 1183 "difference",
1195 "goblin",
1196 "libloading", 1184 "libloading",
1197 "mbe", 1185 "mbe",
1198 "memmap", 1186 "memmap",
1187 "object 0.23.0",
1199 "proc_macro_api", 1188 "proc_macro_api",
1200 "proc_macro_test", 1189 "proc_macro_test",
1201 "serde_derive", 1190 "serde_derive",
@@ -1472,26 +1461,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1472checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 1461checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
1473 1462
1474[[package]] 1463[[package]]
1475name = "scroll"
1476version = "0.10.2"
1477source = "registry+https://github.com/rust-lang/crates.io-index"
1478checksum = "fda28d4b4830b807a8b43f7b0e6b5df875311b3e7621d84577188c175b6ec1ec"
1479dependencies = [
1480 "scroll_derive",
1481]
1482
1483[[package]]
1484name = "scroll_derive"
1485version = "0.10.4"
1486source = "registry+https://github.com/rust-lang/crates.io-index"
1487checksum = "b12bd20b94c7cdfda8c7ba9b92ad0d9a56e3fa018c25fca83b51aa664c9b4c0d"
1488dependencies = [
1489 "proc-macro2",
1490 "quote",
1491 "syn",
1492]
1493
1494[[package]]
1495name = "semver" 1464name = "semver"
1496version = "0.9.0" 1465version = "0.9.0"
1497source = "registry+https://github.com/rust-lang/crates.io-index" 1466source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1858,9 +1827,9 @@ checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
1858 1827
1859[[package]] 1828[[package]]
1860name = "ungrammar" 1829name = "ungrammar"
1861version = "1.1.4" 1830version = "1.2.2"
1862source = "registry+https://github.com/rust-lang/crates.io-index" 1831source = "registry+https://github.com/rust-lang/crates.io-index"
1863checksum = "df0cd89993af555540e2436fc6adb8479b0dbe386339a136397952e9c89e17a9" 1832checksum = "873186a460627379e7e28880a0d33b729c205634f6f021321f50b323235e62d7"
1864 1833
1865[[package]] 1834[[package]]
1866name = "unicase" 1835name = "unicase"
diff --git a/Cargo.toml b/Cargo.toml
index e30ef0e2f..59d36fbc1 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -25,3 +25,5 @@ debug = 0 # Set this to 1 or 2 to get more useful backtraces in debugger.
25# chalk-solve = { path = "../chalk/chalk-solve" } 25# chalk-solve = { path = "../chalk/chalk-solve" }
26# chalk-ir = { path = "../chalk/chalk-ir" } 26# chalk-ir = { path = "../chalk/chalk-ir" }
27# chalk-recursive = { path = "../chalk/chalk-recursive" } 27# chalk-recursive = { path = "../chalk/chalk-recursive" }
28
29# ungrammar = { path = "../ungrammar" }
diff --git a/crates/assists/src/handlers/reorder_fields.rs b/crates/assists/src/handlers/reorder_fields.rs
index 7c0f0f44e..fe5574242 100644
--- a/crates/assists/src/handlers/reorder_fields.rs
+++ b/crates/assists/src/handlers/reorder_fields.rs
@@ -4,6 +4,7 @@ use rustc_hash::FxHashMap;
4use hir::{Adt, ModuleDef, PathResolution, Semantics, Struct}; 4use hir::{Adt, ModuleDef, PathResolution, Semantics, Struct};
5use ide_db::RootDatabase; 5use ide_db::RootDatabase;
6use syntax::{algo, ast, match_ast, AstNode, SyntaxKind, SyntaxKind::*, SyntaxNode}; 6use syntax::{algo, ast, match_ast, AstNode, SyntaxKind, SyntaxKind::*, SyntaxNode};
7use test_utils::mark;
7 8
8use crate::{AssistContext, AssistId, AssistKind, Assists}; 9use crate::{AssistContext, AssistId, AssistKind, Assists};
9 10
@@ -38,6 +39,7 @@ fn reorder<R: AstNode>(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
38 }); 39 });
39 40
40 if sorted_fields == fields { 41 if sorted_fields == fields {
42 mark::hit!(reorder_sorted_fields);
41 return None; 43 return None;
42 } 44 }
43 45
@@ -107,22 +109,25 @@ fn compute_fields_ranks(path: &ast::Path, ctx: &AssistContext) -> Option<FxHashM
107 109
108#[cfg(test)] 110#[cfg(test)]
109mod tests { 111mod tests {
112 use test_utils::mark;
113
110 use crate::tests::{check_assist, check_assist_not_applicable}; 114 use crate::tests::{check_assist, check_assist_not_applicable};
111 115
112 use super::*; 116 use super::*;
113 117
114 #[test] 118 #[test]
115 fn not_applicable_if_sorted() { 119 fn reorder_sorted_fields() {
120 mark::check!(reorder_sorted_fields);
116 check_assist_not_applicable( 121 check_assist_not_applicable(
117 reorder_fields, 122 reorder_fields,
118 r#" 123 r#"
119 struct Foo { 124struct Foo {
120 foo: i32, 125 foo: i32,
121 bar: i32, 126 bar: i32,
122 } 127}
123 128
124 const test: Foo = <|>Foo { foo: 0, bar: 0 }; 129const test: Foo = <|>Foo { foo: 0, bar: 0 };
125 "#, 130"#,
126 ) 131 )
127 } 132 }
128 133
@@ -131,9 +136,9 @@ mod tests {
131 check_assist_not_applicable( 136 check_assist_not_applicable(
132 reorder_fields, 137 reorder_fields,
133 r#" 138 r#"
134 struct Foo {}; 139struct Foo {};
135 const test: Foo = <|>Foo {} 140const test: Foo = <|>Foo {}
136 "#, 141"#,
137 ) 142 )
138 } 143 }
139 144
@@ -142,13 +147,13 @@ mod tests {
142 check_assist( 147 check_assist(
143 reorder_fields, 148 reorder_fields,
144 r#" 149 r#"
145 struct Foo {foo: i32, bar: i32}; 150struct Foo {foo: i32, bar: i32};
146 const test: Foo = <|>Foo {bar: 0, foo: 1} 151const test: Foo = <|>Foo {bar: 0, foo: 1}
147 "#, 152"#,
148 r#" 153 r#"
149 struct Foo {foo: i32, bar: i32}; 154struct Foo {foo: i32, bar: i32};
150 const test: Foo = Foo {foo: 1, bar: 0} 155const test: Foo = Foo {foo: 1, bar: 0}
151 "#, 156"#,
152 ) 157 )
153 } 158 }
154 159
@@ -157,25 +162,25 @@ mod tests {
157 check_assist( 162 check_assist(
158 reorder_fields, 163 reorder_fields,
159 r#" 164 r#"
160 struct Foo { foo: i64, bar: i64, baz: i64 } 165struct Foo { foo: i64, bar: i64, baz: i64 }
161 166
162 fn f(f: Foo) -> { 167fn f(f: Foo) -> {
163 match f { 168 match f {
164 <|>Foo { baz: 0, ref mut bar, .. } => (), 169 <|>Foo { baz: 0, ref mut bar, .. } => (),
165 _ => () 170 _ => ()
166 } 171 }
167 } 172}
168 "#, 173"#,
169 r#" 174 r#"
170 struct Foo { foo: i64, bar: i64, baz: i64 } 175struct Foo { foo: i64, bar: i64, baz: i64 }
171 176
172 fn f(f: Foo) -> { 177fn f(f: Foo) -> {
173 match f { 178 match f {
174 Foo { ref mut bar, baz: 0, .. } => (), 179 Foo { ref mut bar, baz: 0, .. } => (),
175 _ => () 180 _ => ()
176 } 181 }
177 } 182}
178 "#, 183"#,
179 ) 184 )
180 } 185 }
181 186
@@ -184,39 +189,39 @@ mod tests {
184 check_assist( 189 check_assist(
185 reorder_fields, 190 reorder_fields,
186 r#" 191 r#"
187 struct Foo { 192struct Foo {
188 foo: String, 193 foo: String,
189 bar: String, 194 bar: String,
190 } 195}
191 196
192 impl Foo { 197impl Foo {
193 fn new() -> Foo { 198 fn new() -> Foo {
194 let foo = String::new(); 199 let foo = String::new();
195 <|>Foo { 200 <|>Foo {
196 bar: foo.clone(), 201 bar: foo.clone(),
197 extra: "Extra field", 202 extra: "Extra field",
198 foo, 203 foo,
199 } 204 }
200 } 205 }
201 } 206}
202 "#, 207"#,
203 r#" 208 r#"
204 struct Foo { 209struct Foo {
205 foo: String, 210 foo: String,
206 bar: String, 211 bar: String,
207 } 212}
208 213
209 impl Foo { 214impl Foo {
210 fn new() -> Foo { 215 fn new() -> Foo {
211 let foo = String::new(); 216 let foo = String::new();
212 Foo { 217 Foo {
213 foo, 218 foo,
214 bar: foo.clone(), 219 bar: foo.clone(),
215 extra: "Extra field", 220 extra: "Extra field",
216 } 221 }
217 } 222 }
218 } 223}
219 "#, 224"#,
220 ) 225 )
221 } 226 }
222} 227}
diff --git a/crates/completion/src/render/macro_.rs b/crates/completion/src/render/macro_.rs
index eb3209bee..6cfbd6c9b 100644
--- a/crates/completion/src/render/macro_.rs
+++ b/crates/completion/src/render/macro_.rs
@@ -144,7 +144,7 @@ mod tests {
144use foo::<|>; 144use foo::<|>;
145//- /foo/lib.rs crate:foo 145//- /foo/lib.rs crate:foo
146#[macro_export] 146#[macro_export]
147macro_rules frobnicate { () => () } 147macro_rules! frobnicate { () => () }
148"#, 148"#,
149 r#" 149 r#"
150use foo::frobnicate; 150use foo::frobnicate;
@@ -154,11 +154,11 @@ use foo::frobnicate;
154 check_edit( 154 check_edit(
155 "frobnicate!", 155 "frobnicate!",
156 r#" 156 r#"
157macro_rules frobnicate { () => () } 157macro_rules! frobnicate { () => () }
158fn main() { frob<|>!(); } 158fn main() { frob<|>!(); }
159"#, 159"#,
160 r#" 160 r#"
161macro_rules frobnicate { () => () } 161macro_rules! frobnicate { () => () }
162fn main() { frobnicate!(); } 162fn main() { frobnicate!(); }
163"#, 163"#,
164 ); 164 );
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index fcc42c6bb..42dc35b76 100644
--- a/crates/hir/src/code_model.rs
+++ b/crates/hir/src/code_model.rs
@@ -1250,6 +1250,14 @@ impl LifetimeParam {
1250 let params = db.generic_params(self.id.parent); 1250 let params = db.generic_params(self.id.parent);
1251 params.lifetimes[self.id.local_id].name.clone() 1251 params.lifetimes[self.id.local_id].name.clone()
1252 } 1252 }
1253
1254 pub fn module(self, db: &dyn HirDatabase) -> Module {
1255 self.id.parent.module(db.upcast()).into()
1256 }
1257
1258 pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
1259 self.id.parent.into()
1260 }
1253} 1261}
1254 1262
1255// FIXME: rename from `ImplDef` to `Impl` 1263// FIXME: rename from `ImplDef` to `Impl`
diff --git a/crates/hir/src/from_id.rs b/crates/hir/src/from_id.rs
index 265ef6d1f..dd3fcfe4a 100644
--- a/crates/hir/src/from_id.rs
+++ b/crates/hir/src/from_id.rs
@@ -41,6 +41,7 @@ from_id![
41 (hir_def::FunctionId, crate::Function), 41 (hir_def::FunctionId, crate::Function),
42 (hir_def::ImplId, crate::ImplDef), 42 (hir_def::ImplId, crate::ImplDef),
43 (hir_def::TypeParamId, crate::TypeParam), 43 (hir_def::TypeParamId, crate::TypeParam),
44 (hir_def::LifetimeParamId, crate::LifetimeParam),
44 (hir_expand::MacroDefId, crate::MacroDef) 45 (hir_expand::MacroDefId, crate::MacroDef)
45]; 46];
46 47
@@ -154,6 +155,22 @@ impl From<GenericDef> for GenericDefId {
154 } 155 }
155} 156}
156 157
158impl From<GenericDefId> for GenericDef {
159 fn from(def: GenericDefId) -> Self {
160 match def {
161 GenericDefId::FunctionId(it) => GenericDef::Function(it.into()),
162 GenericDefId::AdtId(it) => GenericDef::Adt(it.into()),
163 GenericDefId::TraitId(it) => GenericDef::Trait(it.into()),
164 GenericDefId::TypeAliasId(it) => GenericDef::TypeAlias(it.into()),
165 GenericDefId::ImplId(it) => GenericDef::ImplDef(it.into()),
166 GenericDefId::EnumVariantId(it) => {
167 GenericDef::EnumVariant(EnumVariant { parent: it.parent.into(), id: it.local_id })
168 }
169 GenericDefId::ConstId(it) => GenericDef::Const(it.into()),
170 }
171 }
172}
173
157impl From<Adt> for GenericDefId { 174impl From<Adt> for GenericDefId {
158 fn from(id: Adt) -> Self { 175 fn from(id: Adt) -> Self {
159 match id { 176 match id {
diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs
index c77494152..04845037f 100644
--- a/crates/hir/src/has_source.rs
+++ b/crates/hir/src/has_source.rs
@@ -10,8 +10,8 @@ use hir_expand::InFile;
10use syntax::ast; 10use syntax::ast;
11 11
12use crate::{ 12use crate::{
13 db::HirDatabase, Const, Enum, EnumVariant, Field, FieldSource, Function, ImplDef, MacroDef, 13 db::HirDatabase, Const, Enum, EnumVariant, Field, FieldSource, Function, ImplDef,
14 Module, Static, Struct, Trait, TypeAlias, TypeParam, Union, 14 LifetimeParam, MacroDef, Module, Static, Struct, Trait, TypeAlias, TypeParam, Union,
15}; 15};
16 16
17pub trait HasSource { 17pub trait HasSource {
@@ -110,8 +110,8 @@ impl HasSource for TypeAlias {
110 } 110 }
111} 111}
112impl HasSource for MacroDef { 112impl HasSource for MacroDef {
113 type Ast = ast::MacroCall; 113 type Ast = ast::MacroRules;
114 fn source(self, db: &dyn HirDatabase) -> InFile<ast::MacroCall> { 114 fn source(self, db: &dyn HirDatabase) -> InFile<ast::MacroRules> {
115 InFile { 115 InFile {
116 file_id: self.id.ast_id.expect("MacroDef without ast_id").file_id, 116 file_id: self.id.ast_id.expect("MacroDef without ast_id").file_id,
117 value: self.id.ast_id.expect("MacroDef without ast_id").to_node(db.upcast()), 117 value: self.id.ast_id.expect("MacroDef without ast_id").to_node(db.upcast()),
@@ -132,3 +132,11 @@ impl HasSource for TypeParam {
132 child_source.map(|it| it[self.id.local_id].clone()) 132 child_source.map(|it| it[self.id.local_id].clone())
133 } 133 }
134} 134}
135
136impl HasSource for LifetimeParam {
137 type Ast = ast::LifetimeParam;
138 fn source(self, db: &dyn HirDatabase) -> InFile<Self::Ast> {
139 let child_source = self.id.parent.child_source(db.upcast());
140 child_source.map(|it| it[self.id.local_id].clone())
141 }
142}
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 4bd22ed27..5959ac4ca 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -13,7 +13,11 @@ use hir_expand::{hygiene::Hygiene, name::AsName, ExpansionInfo};
13use hir_ty::associated_type_shorthand_candidates; 13use hir_ty::associated_type_shorthand_candidates;
14use itertools::Itertools; 14use itertools::Itertools;
15use rustc_hash::{FxHashMap, FxHashSet}; 15use rustc_hash::{FxHashMap, FxHashSet};
16use syntax::{algo::find_node_at_offset, ast, AstNode, SyntaxNode, SyntaxToken, TextSize}; 16use syntax::{
17 algo::find_node_at_offset,
18 ast::{self, GenericParamsOwner},
19 match_ast, AstNode, SyntaxNode, SyntaxToken, TextSize,
20};
17 21
18use crate::{ 22use crate::{
19 code_model::Access, 23 code_model::Access,
@@ -21,8 +25,9 @@ use crate::{
21 diagnostics::Diagnostic, 25 diagnostics::Diagnostic,
22 semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, 26 semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
23 source_analyzer::{resolve_hir_path, SourceAnalyzer}, 27 source_analyzer::{resolve_hir_path, SourceAnalyzer},
24 AssocItem, Callable, Crate, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, 28 AssocItem, Callable, Crate, Field, Function, HirFileId, ImplDef, InFile, LifetimeParam, Local,
25 Module, ModuleDef, Name, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, VariantDef, 29 MacroDef, Module, ModuleDef, Name, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam,
30 VariantDef,
26}; 31};
27 32
28#[derive(Debug, Clone, PartialEq, Eq)] 33#[derive(Debug, Clone, PartialEq, Eq)]
@@ -173,6 +178,11 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
173 self.imp.descend_node_at_offset(node, offset).find_map(N::cast) 178 self.imp.descend_node_at_offset(node, offset).find_map(N::cast)
174 } 179 }
175 180
181 // FIXME: Replace the SyntaxToken with a typed ast Node/Token
182 pub fn resolve_lifetime_param(&self, lifetime_token: &SyntaxToken) -> Option<LifetimeParam> {
183 self.imp.resolve_lifetime_param(lifetime_token)
184 }
185
176 pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> { 186 pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> {
177 self.imp.type_of_expr(expr) 187 self.imp.type_of_expr(expr)
178 } 188 }
@@ -392,16 +402,44 @@ impl<'db> SemanticsImpl<'db> {
392 .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len()) 402 .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len())
393 } 403 }
394 404
405 // FIXME: Replace the SyntaxToken with a typed ast Node/Token
406 fn resolve_lifetime_param(&self, lifetime_token: &SyntaxToken) -> Option<LifetimeParam> {
407 if lifetime_token.kind() != syntax::SyntaxKind::LIFETIME {
408 return None;
409 }
410 let lifetime_text = lifetime_token.text();
411 let lifetime_param = lifetime_token.parent().ancestors().find_map(|syn| {
412 let gpl = match_ast! {
413 match syn {
414 ast::Fn(it) => it.generic_param_list()?,
415 ast::TypeAlias(it) => it.generic_param_list()?,
416 ast::Struct(it) => it.generic_param_list()?,
417 ast::Enum(it) => it.generic_param_list()?,
418 ast::Union(it) => it.generic_param_list()?,
419 ast::Trait(it) => it.generic_param_list()?,
420 ast::Impl(it) => it.generic_param_list()?,
421 ast::WherePred(it) => it.generic_param_list()?,
422 ast::ForType(it) => it.generic_param_list()?,
423 _ => return None,
424 }
425 };
426 gpl.lifetime_params()
427 .find(|tp| tp.lifetime_token().as_ref().map(|lt| lt.text()) == Some(lifetime_text))
428 })?;
429 let src = self.find_file(lifetime_param.syntax().clone()).with_value(lifetime_param);
430 ToDef::to_def(self, src)
431 }
432
395 fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> { 433 fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> {
396 self.analyze(expr.syntax()).type_of_expr(self.db, &expr) 434 self.analyze(expr.syntax()).type_of_expr(self.db, expr)
397 } 435 }
398 436
399 fn type_of_pat(&self, pat: &ast::Pat) -> Option<Type> { 437 fn type_of_pat(&self, pat: &ast::Pat) -> Option<Type> {
400 self.analyze(pat.syntax()).type_of_pat(self.db, &pat) 438 self.analyze(pat.syntax()).type_of_pat(self.db, pat)
401 } 439 }
402 440
403 fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type> { 441 fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type> {
404 self.analyze(param.syntax()).type_of_self(self.db, &param) 442 self.analyze(param.syntax()).type_of_self(self.db, param)
405 } 443 }
406 444
407 fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> { 445 fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> {
@@ -684,7 +722,8 @@ to_def_impls![
684 (crate::Field, ast::TupleField, tuple_field_to_def), 722 (crate::Field, ast::TupleField, tuple_field_to_def),
685 (crate::EnumVariant, ast::Variant, enum_variant_to_def), 723 (crate::EnumVariant, ast::Variant, enum_variant_to_def),
686 (crate::TypeParam, ast::TypeParam, type_param_to_def), 724 (crate::TypeParam, ast::TypeParam, type_param_to_def),
687 (crate::MacroDef, ast::MacroCall, macro_call_to_def), // this one is dubious, not all calls are macros 725 (crate::LifetimeParam, ast::LifetimeParam, lifetime_param_to_def),
726 (crate::MacroDef, ast::MacroRules, macro_rules_to_def),
688 (crate::Local, ast::IdentPat, bind_pat_to_def), 727 (crate::Local, ast::IdentPat, bind_pat_to_def),
689]; 728];
690 729
diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs
index 66fc11611..a333d7aea 100644
--- a/crates/hir/src/semantics/source_to_def.rs
+++ b/crates/hir/src/semantics/source_to_def.rs
@@ -7,7 +7,8 @@ use hir_def::{
7 expr::PatId, 7 expr::PatId,
8 keys::{self, Key}, 8 keys::{self, Key},
9 ConstId, DefWithBodyId, EnumId, EnumVariantId, FieldId, FunctionId, GenericDefId, ImplId, 9 ConstId, DefWithBodyId, EnumId, EnumVariantId, FieldId, FunctionId, GenericDefId, ImplId,
10 ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, VariantId, 10 LifetimeParamId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId,
11 VariantId,
11}; 12};
12use hir_expand::{name::AsName, AstId, MacroDefKind}; 13use hir_expand::{name::AsName, AstId, MacroDefKind};
13use rustc_hash::FxHashMap; 14use rustc_hash::FxHashMap;
@@ -128,15 +129,30 @@ impl SourceToDefCtx<'_, '_> {
128 129
129 pub(super) fn type_param_to_def(&mut self, src: InFile<ast::TypeParam>) -> Option<TypeParamId> { 130 pub(super) fn type_param_to_def(&mut self, src: InFile<ast::TypeParam>) -> Option<TypeParamId> {
130 let container: ChildContainer = 131 let container: ChildContainer =
131 self.find_type_param_container(src.as_ref().map(|it| it.syntax()))?.into(); 132 self.find_generic_param_container(src.as_ref().map(|it| it.syntax()))?.into();
132 let db = self.db; 133 let db = self.db;
133 let dyn_map = 134 let dyn_map =
134 &*self.cache.entry(container).or_insert_with(|| container.child_by_source(db)); 135 &*self.cache.entry(container).or_insert_with(|| container.child_by_source(db));
135 dyn_map[keys::TYPE_PARAM].get(&src).copied() 136 dyn_map[keys::TYPE_PARAM].get(&src).copied()
136 } 137 }
137 138
139 pub(super) fn lifetime_param_to_def(
140 &mut self,
141 src: InFile<ast::LifetimeParam>,
142 ) -> Option<LifetimeParamId> {
143 let container: ChildContainer =
144 self.find_generic_param_container(src.as_ref().map(|it| it.syntax()))?.into();
145 let db = self.db;
146 let dyn_map =
147 &*self.cache.entry(container).or_insert_with(|| container.child_by_source(db));
148 dyn_map[keys::LIFETIME_PARAM].get(&src).copied()
149 }
150
138 // FIXME: use DynMap as well? 151 // FIXME: use DynMap as well?
139 pub(super) fn macro_call_to_def(&mut self, src: InFile<ast::MacroCall>) -> Option<MacroDefId> { 152 pub(super) fn macro_rules_to_def(
153 &mut self,
154 src: InFile<ast::MacroRules>,
155 ) -> Option<MacroDefId> {
140 let kind = MacroDefKind::Declarative; 156 let kind = MacroDefKind::Declarative;
141 let file_id = src.file_id.original_file(self.db.upcast()); 157 let file_id = src.file_id.original_file(self.db.upcast());
142 let krate = self.file_to_def(file_id)?.krate; 158 let krate = self.file_to_def(file_id)?.krate;
@@ -203,7 +219,7 @@ impl SourceToDefCtx<'_, '_> {
203 Some(def.into()) 219 Some(def.into())
204 } 220 }
205 221
206 fn find_type_param_container(&mut self, src: InFile<&SyntaxNode>) -> Option<GenericDefId> { 222 fn find_generic_param_container(&mut self, src: InFile<&SyntaxNode>) -> Option<GenericDefId> {
207 for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) { 223 for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) {
208 let res: GenericDefId = match_ast! { 224 let res: GenericDefId = match_ast! {
209 match (container.value) { 225 match (container.value) {
@@ -247,7 +263,7 @@ pub(crate) enum ChildContainer {
247 VariantId(VariantId), 263 VariantId(VariantId),
248 TypeAliasId(TypeAliasId), 264 TypeAliasId(TypeAliasId),
249 /// XXX: this might be the same def as, for example an `EnumId`. However, 265 /// XXX: this might be the same def as, for example an `EnumId`. However,
250 /// here the children generic parameters, and not, eg enum variants. 266 /// here the children are generic parameters, and not, eg enum variants.
251 GenericDefId(GenericDefId), 267 GenericDefId(GenericDefId),
252} 268}
253impl_from! { 269impl_from! {
diff --git a/crates/hir_def/src/adt.rs b/crates/hir_def/src/adt.rs
index 6539959c3..eafa3abb6 100644
--- a/crates/hir_def/src/adt.rs
+++ b/crates/hir_def/src/adt.rs
@@ -145,10 +145,12 @@ impl EnumData {
145 } 145 }
146} 146}
147 147
148impl HasChildSource for EnumId { 148impl HasChildSource<LocalEnumVariantId> for EnumId {
149 type ChildId = LocalEnumVariantId;
150 type Value = ast::Variant; 149 type Value = ast::Variant;
151 fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> { 150 fn child_source(
151 &self,
152 db: &dyn DefDatabase,
153 ) -> InFile<ArenaMap<LocalEnumVariantId, Self::Value>> {
152 let src = self.lookup(db).source(db); 154 let src = self.lookup(db).source(db);
153 let mut trace = Trace::new_for_map(); 155 let mut trace = Trace::new_for_map();
154 lower_enum(db, &mut trace, &src, self.lookup(db).container.module(db)); 156 lower_enum(db, &mut trace, &src, self.lookup(db).container.module(db));
@@ -212,11 +214,10 @@ impl VariantData {
212 } 214 }
213} 215}
214 216
215impl HasChildSource for VariantId { 217impl HasChildSource<LocalFieldId> for VariantId {
216 type ChildId = LocalFieldId;
217 type Value = Either<ast::TupleField, ast::RecordField>; 218 type Value = Either<ast::TupleField, ast::RecordField>;
218 219
219 fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> { 220 fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<LocalFieldId, Self::Value>> {
220 let (src, module_id) = match self { 221 let (src, module_id) = match self {
221 VariantId::EnumVariantId(it) => { 222 VariantId::EnumVariantId(it) => {
222 // I don't really like the fact that we call into parent source 223 // I don't really like the fact that we call into parent source
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 689a3274c..bdba4c33e 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -548,63 +548,70 @@ impl ExprCollector<'_> {
548 } 548 }
549 } 549 }
550 ast::Expr::MacroCall(e) => { 550 ast::Expr::MacroCall(e) => {
551 if let Some(name) = e.is_macro_rules().map(|it| it.as_name()) { 551 let mut ids = vec![];
552 let mac = MacroDefId { 552 self.collect_macro_call(e, syntax_ptr.clone(), |this, expansion| {
553 krate: Some(self.expander.module.krate), 553 ids.push(match expansion {
554 ast_id: Some(self.expander.ast_id(&e)), 554 Some(it) => this.collect_expr(it),
555 kind: MacroDefKind::Declarative, 555 None => this.alloc_expr(Expr::Missing, syntax_ptr.clone()),
556 local_inner: false, 556 })
557 }; 557 });
558 self.body.item_scope.define_legacy_macro(name, mac); 558 ids[0]
559 }
560 }
561 }
559 562
560 // FIXME: do we still need to allocate this as missing ? 563 fn collect_macro_call<F: FnMut(&mut Self, Option<T>), T: ast::AstNode>(
561 self.alloc_expr(Expr::Missing, syntax_ptr) 564 &mut self,
565 e: ast::MacroCall,
566 syntax_ptr: AstPtr<ast::Expr>,
567 mut collector: F,
568 ) {
569 // File containing the macro call. Expansion errors will be attached here.
570 let outer_file = self.expander.current_file_id;
571
572 let macro_call = self.expander.to_source(AstPtr::new(&e));
573 let res = self.expander.enter_expand(self.db, Some(&self.body.item_scope), e);
574
575 match &res.err {
576 Some(ExpandError::UnresolvedProcMacro) => {
577 self.source_map.diagnostics.push(BodyDiagnostic::UnresolvedProcMacro(
578 UnresolvedProcMacro {
579 file: outer_file,
580 node: syntax_ptr.into(),
581 precise_location: None,
582 macro_name: None,
583 },
584 ));
585 }
586 Some(err) => {
587 self.source_map.diagnostics.push(BodyDiagnostic::MacroError(MacroError {
588 file: outer_file,
589 node: syntax_ptr.into(),
590 message: err.to_string(),
591 }));
592 }
593 None => {}
594 }
595
596 match res.value {
597 Some((mark, expansion)) => {
598 // FIXME: Statements are too complicated to recover from error for now.
599 // It is because we don't have any hygenine for local variable expansion right now.
600 if T::can_cast(syntax::SyntaxKind::MACRO_STMTS) && res.err.is_some() {
601 self.expander.exit(self.db, mark);
602 collector(self, None);
562 } else { 603 } else {
563 // File containing the macro call. Expansion errors will be attached here. 604 self.source_map.expansions.insert(macro_call, self.expander.current_file_id);
564 let outer_file = self.expander.current_file_id;
565
566 let macro_call = self.expander.to_source(AstPtr::new(&e));
567 let res = self.expander.enter_expand(self.db, Some(&self.body.item_scope), e);
568
569 match res.err {
570 Some(ExpandError::UnresolvedProcMacro) => {
571 self.source_map.diagnostics.push(BodyDiagnostic::UnresolvedProcMacro(
572 UnresolvedProcMacro {
573 file: outer_file,
574 node: syntax_ptr.clone().into(),
575 precise_location: None,
576 macro_name: None,
577 },
578 ));
579 }
580 Some(err) => {
581 self.source_map.diagnostics.push(BodyDiagnostic::MacroError(
582 MacroError {
583 file: outer_file,
584 node: syntax_ptr.clone().into(),
585 message: err.to_string(),
586 },
587 ));
588 }
589 None => {}
590 }
591 605
592 match res.value { 606 let item_tree = self.db.item_tree(self.expander.current_file_id);
593 Some((mark, expansion)) => { 607 self.item_trees.insert(self.expander.current_file_id, item_tree);
594 self.source_map 608
595 .expansions 609 let id = collector(self, Some(expansion));
596 .insert(macro_call, self.expander.current_file_id); 610 self.expander.exit(self.db, mark);
597 611 id
598 let item_tree = self.db.item_tree(self.expander.current_file_id);
599 self.item_trees.insert(self.expander.current_file_id, item_tree);
600 let id = self.collect_expr(expansion);
601 self.expander.exit(self.db, mark);
602 id
603 }
604 None => self.alloc_expr(Expr::Missing, syntax_ptr),
605 }
606 } 612 }
607 } 613 }
614 None => collector(self, None),
608 } 615 }
609 } 616 }
610 617
@@ -642,44 +649,75 @@ impl ExprCollector<'_> {
642 } 649 }
643 } 650 }
644 651
645 fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId { 652 fn collect_stmt(&mut self, s: ast::Stmt) -> Option<Vec<Statement>> {
646 let syntax_node_ptr = AstPtr::new(&block.clone().into()); 653 let stmt =
647 self.collect_block_items(&block); 654 match s {
648 let statements = block 655 ast::Stmt::LetStmt(stmt) => {
649 .statements() 656 self.check_cfg(&stmt)?;
650 .filter_map(|s| {
651 let stmt = match s {
652 ast::Stmt::LetStmt(stmt) => {
653 self.check_cfg(&stmt)?;
654
655 let pat = self.collect_pat_opt(stmt.pat());
656 let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it));
657 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
658 Statement::Let { pat, type_ref, initializer }
659 }
660 ast::Stmt::ExprStmt(stmt) => {
661 self.check_cfg(&stmt)?;
662 657
663 Statement::Expr(self.collect_expr_opt(stmt.expr())) 658 let pat = self.collect_pat_opt(stmt.pat());
664 } 659 let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it));
665 ast::Stmt::Item(item) => { 660 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
666 self.check_cfg(&item)?; 661 vec![Statement::Let { pat, type_ref, initializer }]
662 }
663 ast::Stmt::ExprStmt(stmt) => {
664 self.check_cfg(&stmt)?;
665
666 // Note that macro could be expended to multiple statements
667 if let Some(ast::Expr::MacroCall(m)) = stmt.expr() {
668 let syntax_ptr = AstPtr::new(&stmt.expr().unwrap());
669 let mut stmts = vec![];
670
671 self.collect_macro_call(m, syntax_ptr.clone(), |this, expansion| {
672 match expansion {
673 Some(expansion) => {
674 let statements: ast::MacroStmts = expansion;
675 this.collect_stmts_items(statements.statements());
667 676
668 return None; 677 statements.statements().for_each(|stmt| {
678 if let Some(mut r) = this.collect_stmt(stmt) {
679 stmts.append(&mut r);
680 }
681 });
682 if let Some(expr) = statements.expr() {
683 stmts.push(Statement::Expr(this.collect_expr(expr)));
684 }
685 }
686 None => {
687 stmts.push(Statement::Expr(
688 this.alloc_expr(Expr::Missing, syntax_ptr.clone()),
689 ));
690 }
691 }
692 });
693 stmts
694 } else {
695 vec![Statement::Expr(self.collect_expr_opt(stmt.expr()))]
669 } 696 }
670 }; 697 }
671 Some(stmt) 698 ast::Stmt::Item(item) => {
672 }) 699 self.check_cfg(&item)?;
673 .collect(); 700
701 return None;
702 }
703 };
704
705 Some(stmt)
706 }
707
708 fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
709 let syntax_node_ptr = AstPtr::new(&block.clone().into());
710 self.collect_stmts_items(block.statements());
711 let statements =
712 block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect();
674 let tail = block.expr().map(|e| self.collect_expr(e)); 713 let tail = block.expr().map(|e| self.collect_expr(e));
675 self.alloc_expr(Expr::Block { statements, tail, label: None }, syntax_node_ptr) 714 self.alloc_expr(Expr::Block { statements, tail, label: None }, syntax_node_ptr)
676 } 715 }
677 716
678 fn collect_block_items(&mut self, block: &ast::BlockExpr) { 717 fn collect_stmts_items(&mut self, stmts: ast::AstChildren<ast::Stmt>) {
679 let container = ContainerId::DefWithBodyId(self.def); 718 let container = ContainerId::DefWithBodyId(self.def);
680 719
681 let items = block 720 let items = stmts
682 .statements()
683 .filter_map(|stmt| match stmt { 721 .filter_map(|stmt| match stmt {
684 ast::Stmt::Item(it) => Some(it), 722 ast::Stmt::Item(it) => Some(it),
685 ast::Stmt::LetStmt(_) | ast::Stmt::ExprStmt(_) => None, 723 ast::Stmt::LetStmt(_) | ast::Stmt::ExprStmt(_) => None,
@@ -733,26 +771,44 @@ impl ExprCollector<'_> {
733 | ast::Item::ExternCrate(_) 771 | ast::Item::ExternCrate(_)
734 | ast::Item::Module(_) 772 | ast::Item::Module(_)
735 | ast::Item::MacroCall(_) => return None, 773 | ast::Item::MacroCall(_) => return None,
774 ast::Item::MacroRules(def) => {
775 return Some(Either::Right(def));
776 }
736 }; 777 };
737 778
738 Some((def, name)) 779 Some(Either::Left((def, name)))
739 }) 780 })
740 .collect::<Vec<_>>(); 781 .collect::<Vec<_>>();
741 782
742 for (def, name) in items { 783 for either in items {
743 self.body.item_scope.define_def(def); 784 match either {
744 if let Some(name) = name { 785 Either::Left((def, name)) => {
745 let vis = crate::visibility::Visibility::Public; // FIXME determine correctly 786 self.body.item_scope.define_def(def);
746 let has_constructor = match def { 787 if let Some(name) = name {
747 ModuleDefId::AdtId(AdtId::StructId(s)) => { 788 let vis = crate::visibility::Visibility::Public; // FIXME determine correctly
748 self.db.struct_data(s).variant_data.kind() != StructKind::Record 789 let has_constructor = match def {
790 ModuleDefId::AdtId(AdtId::StructId(s)) => {
791 self.db.struct_data(s).variant_data.kind() != StructKind::Record
792 }
793 _ => true,
794 };
795 self.body.item_scope.push_res(
796 name.as_name(),
797 crate::per_ns::PerNs::from_def(def, vis, has_constructor),
798 );
749 } 799 }
750 _ => true, 800 }
751 }; 801 Either::Right(e) => {
752 self.body.item_scope.push_res( 802 let mac = MacroDefId {
753 name.as_name(), 803 krate: Some(self.expander.module.krate),
754 crate::per_ns::PerNs::from_def(def, vis, has_constructor), 804 ast_id: Some(self.expander.ast_id(&e)),
755 ); 805 kind: MacroDefKind::Declarative,
806 local_inner: false,
807 };
808 if let Some(name) = e.name() {
809 self.body.item_scope.define_legacy_macro(name.as_name(), mac);
810 }
811 }
756 } 812 }
757 } 813 }
758 } 814 }
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs
index 5189c7e9f..924046435 100644
--- a/crates/hir_def/src/generics.rs
+++ b/crates/hir_def/src/generics.rs
@@ -19,10 +19,10 @@ use crate::{
19 db::DefDatabase, 19 db::DefDatabase,
20 dyn_map::DynMap, 20 dyn_map::DynMap,
21 keys, 21 keys,
22 src::HasChildSource, 22 src::{HasChildSource, HasSource},
23 src::HasSource,
24 type_ref::{LifetimeRef, TypeBound, TypeRef}, 23 type_ref::{LifetimeRef, TypeBound, TypeRef},
25 AdtId, GenericDefId, LocalTypeParamId, Lookup, TypeParamId, 24 AdtId, GenericDefId, LifetimeParamId, LocalLifetimeParamId, LocalTypeParamId, Lookup,
25 TypeParamId,
26}; 26};
27 27
28/// Data about a generic parameter (to a function, struct, impl, ...). 28/// Data about a generic parameter (to a function, struct, impl, ...).
@@ -72,7 +72,11 @@ pub enum WherePredicateTypeTarget {
72 // FIXME: ForLifetime(Vec<LifetimeParamId>, TypeRef) 72 // FIXME: ForLifetime(Vec<LifetimeParamId>, TypeRef)
73} 73}
74 74
75type SourceMap = ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>; 75#[derive(Default)]
76pub(crate) struct SourceMap {
77 pub(crate) type_params: ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>,
78 lifetime_params: ArenaMap<LocalLifetimeParamId, ast::LifetimeParam>,
79}
76 80
77impl GenericParams { 81impl GenericParams {
78 pub(crate) fn generic_params_query( 82 pub(crate) fn generic_params_query(
@@ -131,7 +135,7 @@ impl GenericParams {
131 135
132 fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) { 136 fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) {
133 let mut generics = GenericParams::default(); 137 let mut generics = GenericParams::default();
134 let mut sm = ArenaMap::default(); 138 let mut sm = SourceMap::default();
135 139
136 // FIXME: add `: Sized` bound for everything except for `Self` in traits 140 // FIXME: add `: Sized` bound for everything except for `Self` in traits
137 let file_id = match def { 141 let file_id = match def {
@@ -174,7 +178,7 @@ impl GenericParams {
174 default: None, 178 default: None,
175 provenance: TypeParamProvenance::TraitSelf, 179 provenance: TypeParamProvenance::TraitSelf,
176 }); 180 });
177 sm.insert(self_param_id, Either::Left(src.value.clone())); 181 sm.type_params.insert(self_param_id, Either::Left(src.value.clone()));
178 // add super traits as bounds on Self 182 // add super traits as bounds on Self
179 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar 183 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
180 let self_param = TypeRef::Path(name![Self].into()); 184 let self_param = TypeRef::Path(name![Self].into());
@@ -250,7 +254,7 @@ impl GenericParams {
250 provenance: TypeParamProvenance::TypeParamList, 254 provenance: TypeParamProvenance::TypeParamList,
251 }; 255 };
252 let param_id = self.types.alloc(param); 256 let param_id = self.types.alloc(param);
253 sm.insert(param_id, Either::Right(type_param.clone())); 257 sm.type_params.insert(param_id, Either::Right(type_param.clone()));
254 258
255 let type_ref = TypeRef::Path(name.into()); 259 let type_ref = TypeRef::Path(name.into());
256 self.fill_bounds(&lower_ctx, &type_param, Either::Left(type_ref)); 260 self.fill_bounds(&lower_ctx, &type_param, Either::Left(type_ref));
@@ -260,7 +264,8 @@ impl GenericParams {
260 .lifetime_token() 264 .lifetime_token()
261 .map_or_else(Name::missing, |tok| Name::new_lifetime(&tok)); 265 .map_or_else(Name::missing, |tok| Name::new_lifetime(&tok));
262 let param = LifetimeParamData { name: name.clone() }; 266 let param = LifetimeParamData { name: name.clone() };
263 let _param_id = self.lifetimes.alloc(param); 267 let param_id = self.lifetimes.alloc(param);
268 sm.lifetime_params.insert(param_id, lifetime_param.clone());
264 let lifetime_ref = LifetimeRef::new_name(name); 269 let lifetime_ref = LifetimeRef::new_name(name);
265 self.fill_bounds(&lower_ctx, &lifetime_param, Either::Right(lifetime_ref)); 270 self.fill_bounds(&lower_ctx, &lifetime_param, Either::Right(lifetime_ref));
266 } 271 }
@@ -341,26 +346,42 @@ impl GenericParams {
341 } 346 }
342} 347}
343 348
344impl HasChildSource for GenericDefId { 349impl HasChildSource<LocalTypeParamId> for GenericDefId {
345 type ChildId = LocalTypeParamId;
346 type Value = Either<ast::Trait, ast::TypeParam>; 350 type Value = Either<ast::Trait, ast::TypeParam>;
347 fn child_source(&self, db: &dyn DefDatabase) -> InFile<SourceMap> { 351 fn child_source(
348 let (_, sm) = GenericParams::new(db, *self); 352 &self,
349 sm 353 db: &dyn DefDatabase,
354 ) -> InFile<ArenaMap<LocalTypeParamId, Self::Value>> {
355 GenericParams::new(db, *self).1.map(|source_maps| source_maps.type_params)
356 }
357}
358
359impl HasChildSource<LocalLifetimeParamId> for GenericDefId {
360 type Value = ast::LifetimeParam;
361 fn child_source(
362 &self,
363 db: &dyn DefDatabase,
364 ) -> InFile<ArenaMap<LocalLifetimeParamId, Self::Value>> {
365 GenericParams::new(db, *self).1.map(|source_maps| source_maps.lifetime_params)
350 } 366 }
351} 367}
352 368
353impl ChildBySource for GenericDefId { 369impl ChildBySource for GenericDefId {
354 fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { 370 fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap {
355 let mut res = DynMap::default(); 371 let mut res = DynMap::default();
356 let arena_map = self.child_source(db); 372 let (_, sm) = GenericParams::new(db, *self);
357 let arena_map = arena_map.as_ref(); 373
358 for (local_id, src) in arena_map.value.iter() { 374 let sm = sm.as_ref();
375 for (local_id, src) in sm.value.type_params.iter() {
359 let id = TypeParamId { parent: *self, local_id }; 376 let id = TypeParamId { parent: *self, local_id };
360 if let Either::Right(type_param) = src { 377 if let Either::Right(type_param) = src {
361 res[keys::TYPE_PARAM].insert(arena_map.with_value(type_param.clone()), id) 378 res[keys::TYPE_PARAM].insert(sm.with_value(type_param.clone()), id)
362 } 379 }
363 } 380 }
381 for (local_id, src) in sm.value.lifetime_params.iter() {
382 let id = LifetimeParamId { parent: *self, local_id };
383 res[keys::LIFETIME_PARAM].insert(sm.with_value(src.clone()), id);
384 }
364 res 385 res
365 } 386 }
366} 387}
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index b08167281..1c9babf37 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -94,6 +94,9 @@ impl ItemTree {
94 ast::MacroItems(items) => { 94 ast::MacroItems(items) => {
95 ctx.lower_module_items(&items) 95 ctx.lower_module_items(&items)
96 }, 96 },
97 ast::MacroStmts(stmts) => {
98 ctx.lower_inner_items(stmts.syntax())
99 },
97 // Macros can expand to expressions. We return an empty item tree in this case, but 100 // Macros can expand to expressions. We return an empty item tree in this case, but
98 // still need to collect inner items. 101 // still need to collect inner items.
99 ast::Expr(e) => { 102 ast::Expr(e) => {
@@ -139,6 +142,7 @@ impl ItemTree {
139 type_aliases, 142 type_aliases,
140 mods, 143 mods,
141 macro_calls, 144 macro_calls,
145 macro_rules,
142 exprs, 146 exprs,
143 vis, 147 vis,
144 generics, 148 generics,
@@ -159,6 +163,7 @@ impl ItemTree {
159 type_aliases.shrink_to_fit(); 163 type_aliases.shrink_to_fit();
160 mods.shrink_to_fit(); 164 mods.shrink_to_fit();
161 macro_calls.shrink_to_fit(); 165 macro_calls.shrink_to_fit();
166 macro_rules.shrink_to_fit();
162 exprs.shrink_to_fit(); 167 exprs.shrink_to_fit();
163 168
164 vis.arena.shrink_to_fit(); 169 vis.arena.shrink_to_fit();
@@ -277,6 +282,7 @@ struct ItemTreeData {
277 type_aliases: Arena<TypeAlias>, 282 type_aliases: Arena<TypeAlias>,
278 mods: Arena<Mod>, 283 mods: Arena<Mod>,
279 macro_calls: Arena<MacroCall>, 284 macro_calls: Arena<MacroCall>,
285 macro_rules: Arena<MacroRules>,
280 exprs: Arena<Expr>, 286 exprs: Arena<Expr>,
281 287
282 vis: ItemVisibilities, 288 vis: ItemVisibilities,
@@ -424,6 +430,7 @@ mod_items! {
424 TypeAlias in type_aliases -> ast::TypeAlias, 430 TypeAlias in type_aliases -> ast::TypeAlias,
425 Mod in mods -> ast::Module, 431 Mod in mods -> ast::Module,
426 MacroCall in macro_calls -> ast::MacroCall, 432 MacroCall in macro_calls -> ast::MacroCall,
433 MacroRules in macro_rules -> ast::MacroRules,
427} 434}
428 435
429macro_rules! impl_index { 436macro_rules! impl_index {
@@ -626,17 +633,22 @@ pub enum ModKind {
626 633
627#[derive(Debug, Clone, Eq, PartialEq)] 634#[derive(Debug, Clone, Eq, PartialEq)]
628pub struct MacroCall { 635pub struct MacroCall {
629 /// For `macro_rules!` declarations, this is the name of the declared macro.
630 pub name: Option<Name>,
631 /// Path to the called macro. 636 /// Path to the called macro.
632 pub path: ModPath, 637 pub path: ModPath,
638 pub ast_id: FileAstId<ast::MacroCall>,
639}
640
641#[derive(Debug, Clone, Eq, PartialEq)]
642pub struct MacroRules {
643 /// For `macro_rules!` declarations, this is the name of the declared macro.
644 pub name: Name,
633 /// Has `#[macro_export]`. 645 /// Has `#[macro_export]`.
634 pub is_export: bool, 646 pub is_export: bool,
635 /// Has `#[macro_export(local_inner_macros)]`. 647 /// Has `#[macro_export(local_inner_macros)]`.
636 pub is_local_inner: bool, 648 pub is_local_inner: bool,
637 /// Has `#[rustc_builtin_macro]`. 649 /// Has `#[rustc_builtin_macro]`.
638 pub is_builtin: bool, 650 pub is_builtin: bool,
639 pub ast_id: FileAstId<ast::MacroCall>, 651 pub ast_id: FileAstId<ast::MacroRules>,
640} 652}
641 653
642// NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array 654// NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array
@@ -667,7 +679,8 @@ impl ModItem {
667 | ModItem::Static(_) 679 | ModItem::Static(_)
668 | ModItem::Trait(_) 680 | ModItem::Trait(_)
669 | ModItem::Impl(_) 681 | ModItem::Impl(_)
670 | ModItem::Mod(_) => None, 682 | ModItem::Mod(_)
683 | ModItem::MacroRules(_) => None,
671 ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)), 684 ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)),
672 ModItem::Const(konst) => Some(AssocItem::Const(*konst)), 685 ModItem::Const(konst) => Some(AssocItem::Const(*konst)),
673 ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)), 686 ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)),
@@ -694,6 +707,7 @@ impl ModItem {
694 ModItem::TypeAlias(it) => tree[it.index].ast_id().upcast(), 707 ModItem::TypeAlias(it) => tree[it.index].ast_id().upcast(),
695 ModItem::Mod(it) => tree[it.index].ast_id().upcast(), 708 ModItem::Mod(it) => tree[it.index].ast_id().upcast(),
696 ModItem::MacroCall(it) => tree[it.index].ast_id().upcast(), 709 ModItem::MacroCall(it) => tree[it.index].ast_id().upcast(),
710 ModItem::MacroRules(it) => tree[it.index].ast_id().upcast(),
697 } 711 }
698 } 712 }
699} 713}
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index f7ce2e26d..b39d7fb7a 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -2,7 +2,6 @@
2 2
3use std::{collections::hash_map::Entry, mem, sync::Arc}; 3use std::{collections::hash_map::Entry, mem, sync::Arc};
4 4
5use arena::map::ArenaMap;
6use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, name::known, HirFileId}; 5use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, name::known, HirFileId};
7use smallvec::SmallVec; 6use smallvec::SmallVec;
8use syntax::{ 7use syntax::{
@@ -85,8 +84,7 @@ impl Ctx {
85 | ast::Item::Fn(_) 84 | ast::Item::Fn(_)
86 | ast::Item::TypeAlias(_) 85 | ast::Item::TypeAlias(_)
87 | ast::Item::Const(_) 86 | ast::Item::Const(_)
88 | ast::Item::Static(_) 87 | ast::Item::Static(_) => {
89 | ast::Item::MacroCall(_) => {
90 // Skip this if we're already collecting inner items. We'll descend into all nodes 88 // Skip this if we're already collecting inner items. We'll descend into all nodes
91 // already. 89 // already.
92 if !inner { 90 if !inner {
@@ -99,7 +97,11 @@ impl Ctx {
99 ast::Item::Trait(_) | ast::Item::Impl(_) | ast::Item::ExternBlock(_) => {} 97 ast::Item::Trait(_) | ast::Item::Impl(_) | ast::Item::ExternBlock(_) => {}
100 98
101 // These don't have inner items. 99 // These don't have inner items.
102 ast::Item::Module(_) | ast::Item::ExternCrate(_) | ast::Item::Use(_) => {} 100 ast::Item::Module(_)
101 | ast::Item::ExternCrate(_)
102 | ast::Item::Use(_)
103 | ast::Item::MacroCall(_)
104 | ast::Item::MacroRules(_) => {}
103 }; 105 };
104 106
105 let attrs = Attrs::new(item, &self.hygiene); 107 let attrs = Attrs::new(item, &self.hygiene);
@@ -119,6 +121,7 @@ impl Ctx {
119 )), 121 )),
120 ast::Item::ExternCrate(ast) => self.lower_extern_crate(ast).map(Into::into), 122 ast::Item::ExternCrate(ast) => self.lower_extern_crate(ast).map(Into::into),
121 ast::Item::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into), 123 ast::Item::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into),
124 ast::Item::MacroRules(ast) => self.lower_macro_rules(ast).map(Into::into),
122 ast::Item::ExternBlock(ast) => { 125 ast::Item::ExternBlock(ast) => {
123 Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>())) 126 Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>()))
124 } 127 }
@@ -526,9 +529,15 @@ impl Ctx {
526 } 529 }
527 530
528 fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> { 531 fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> {
529 let name = m.name().map(|it| it.as_name());
530 let attrs = Attrs::new(m, &self.hygiene);
531 let path = ModPath::from_src(m.path()?, &self.hygiene)?; 532 let path = ModPath::from_src(m.path()?, &self.hygiene)?;
533 let ast_id = self.source_ast_id_map.ast_id(m);
534 let res = MacroCall { path, ast_id };
535 Some(id(self.data().macro_calls.alloc(res)))
536 }
537
538 fn lower_macro_rules(&mut self, m: &ast::MacroRules) -> Option<FileItemTreeId<MacroRules>> {
539 let name = m.name().map(|it| it.as_name())?;
540 let attrs = Attrs::new(m, &self.hygiene);
532 541
533 let ast_id = self.source_ast_id_map.ast_id(m); 542 let ast_id = self.source_ast_id_map.ast_id(m);
534 543
@@ -548,8 +557,8 @@ impl Ctx {
548 }; 557 };
549 558
550 let is_builtin = attrs.by_key("rustc_builtin_macro").exists(); 559 let is_builtin = attrs.by_key("rustc_builtin_macro").exists();
551 let res = MacroCall { name, path, is_export, is_builtin, is_local_inner, ast_id }; 560 let res = MacroRules { name, is_export, is_builtin, is_local_inner, ast_id };
552 Some(id(self.data().macro_calls.alloc(res))) 561 Some(id(self.data().macro_rules.alloc(res)))
553 } 562 }
554 563
555 fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> { 564 fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> {
@@ -607,7 +616,7 @@ impl Ctx {
607 owner: GenericsOwner<'_>, 616 owner: GenericsOwner<'_>,
608 node: &impl ast::GenericParamsOwner, 617 node: &impl ast::GenericParamsOwner,
609 ) -> GenericParamsId { 618 ) -> GenericParamsId {
610 let mut sm = &mut ArenaMap::default(); 619 let mut sm = &mut Default::default();
611 let mut generics = GenericParams::default(); 620 let mut generics = GenericParams::default();
612 match owner { 621 match owner {
613 GenericsOwner::Function(func) => { 622 GenericsOwner::Function(func) => {
@@ -630,7 +639,7 @@ impl Ctx {
630 default: None, 639 default: None,
631 provenance: TypeParamProvenance::TraitSelf, 640 provenance: TypeParamProvenance::TraitSelf,
632 }); 641 });
633 sm.insert(self_param_id, Either::Left(trait_def.clone())); 642 sm.type_params.insert(self_param_id, Either::Left(trait_def.clone()));
634 // add super traits as bounds on Self 643 // add super traits as bounds on Self
635 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar 644 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
636 let self_param = TypeRef::Path(name![Self].into()); 645 let self_param = TypeRef::Path(name![Self].into());
diff --git a/crates/hir_def/src/keys.rs b/crates/hir_def/src/keys.rs
index 40a5d92b5..9c585de2c 100644
--- a/crates/hir_def/src/keys.rs
+++ b/crates/hir_def/src/keys.rs
@@ -8,8 +8,8 @@ use syntax::{ast, AstNode, AstPtr};
8 8
9use crate::{ 9use crate::{
10 dyn_map::{DynMap, Policy}, 10 dyn_map::{DynMap, Policy},
11 ConstId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, StaticId, StructId, TraitId, 11 ConstId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, LifetimeParamId, StaticId,
12 TypeAliasId, TypeParamId, UnionId, 12 StructId, TraitId, TypeAliasId, TypeParamId, UnionId,
13}; 13};
14 14
15pub type Key<K, V> = crate::dyn_map::Key<InFile<K>, V, AstPtrPolicy<K, V>>; 15pub type Key<K, V> = crate::dyn_map::Key<InFile<K>, V, AstPtrPolicy<K, V>>;
@@ -28,6 +28,7 @@ pub const VARIANT: Key<ast::Variant, EnumVariantId> = Key::new();
28pub const TUPLE_FIELD: Key<ast::TupleField, FieldId> = Key::new(); 28pub const TUPLE_FIELD: Key<ast::TupleField, FieldId> = Key::new();
29pub const RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new(); 29pub const RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new();
30pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new(); 30pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new();
31pub const LIFETIME_PARAM: Key<ast::LifetimeParam, LifetimeParamId> = Key::new();
31 32
32pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new(); 33pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new();
33 34
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 19cd713ba..85cc342c4 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -11,7 +11,7 @@ use hir_expand::{
11 ast_id_map::FileAstId, 11 ast_id_map::FileAstId,
12 builtin_derive::find_builtin_derive, 12 builtin_derive::find_builtin_derive,
13 builtin_macro::find_builtin_macro, 13 builtin_macro::find_builtin_macro,
14 name::{name, AsName, Name}, 14 name::{AsName, Name},
15 proc_macro::ProcMacroExpander, 15 proc_macro::ProcMacroExpander,
16 HirFileId, MacroCallId, MacroDefId, MacroDefKind, 16 HirFileId, MacroCallId, MacroDefId, MacroDefKind,
17}; 17};
@@ -25,7 +25,9 @@ use crate::{
25 attr::Attrs, 25 attr::Attrs,
26 db::DefDatabase, 26 db::DefDatabase,
27 item_scope::{ImportType, PerNsGlobImports}, 27 item_scope::{ImportType, PerNsGlobImports},
28 item_tree::{self, ItemTree, ItemTreeId, MacroCall, Mod, ModItem, ModKind, StructDefKind}, 28 item_tree::{
29 self, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind, StructDefKind,
30 },
29 nameres::{ 31 nameres::{
30 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, 32 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
31 BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode, 33 BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode,
@@ -972,7 +974,8 @@ impl ModCollector<'_, '_> {
972 status: PartialResolvedImport::Unresolved, 974 status: PartialResolvedImport::Unresolved,
973 }) 975 })
974 } 976 }
975 ModItem::MacroCall(mac) => self.collect_macro(&self.item_tree[mac]), 977 ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]),
978 ModItem::MacroRules(mac) => self.collect_macro_rules(&self.item_tree[mac]),
976 ModItem::Impl(imp) => { 979 ModItem::Impl(imp) => {
977 let module = ModuleId { 980 let module = ModuleId {
978 krate: self.def_collector.def_map.krate, 981 krate: self.def_collector.def_map.krate,
@@ -1276,45 +1279,37 @@ impl ModCollector<'_, '_> {
1276 self.def_collector.resolve_proc_macro(&macro_name); 1279 self.def_collector.resolve_proc_macro(&macro_name);
1277 } 1280 }
1278 1281
1279 fn collect_macro(&mut self, mac: &MacroCall) { 1282 fn collect_macro_rules(&mut self, mac: &MacroRules) {
1280 let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); 1283 let ast_id = InFile::new(self.file_id, mac.ast_id);
1281 1284
1282 // Case 0: builtin macros 1285 // Case 1: builtin macros
1283 if mac.is_builtin { 1286 if mac.is_builtin {
1284 if let Some(name) = &mac.name { 1287 let krate = self.def_collector.def_map.krate;
1285 let krate = self.def_collector.def_map.krate; 1288 if let Some(macro_id) = find_builtin_macro(&mac.name, krate, ast_id) {
1286 if let Some(macro_id) = find_builtin_macro(name, krate, ast_id.ast_id) {
1287 self.def_collector.define_macro(
1288 self.module_id,
1289 name.clone(),
1290 macro_id,
1291 mac.is_export,
1292 );
1293 return;
1294 }
1295 }
1296 }
1297
1298 // Case 1: macro rules, define a macro in crate-global mutable scope
1299 if is_macro_rules(&mac.path) {
1300 if let Some(name) = &mac.name {
1301 let macro_id = MacroDefId {
1302 ast_id: Some(ast_id.ast_id),
1303 krate: Some(self.def_collector.def_map.krate),
1304 kind: MacroDefKind::Declarative,
1305 local_inner: mac.is_local_inner,
1306 };
1307 self.def_collector.define_macro( 1289 self.def_collector.define_macro(
1308 self.module_id, 1290 self.module_id,
1309 name.clone(), 1291 mac.name.clone(),
1310 macro_id, 1292 macro_id,
1311 mac.is_export, 1293 mac.is_export,
1312 ); 1294 );
1295 return;
1313 } 1296 }
1314 return;
1315 } 1297 }
1316 1298
1317 // Case 2: try to resolve in legacy scope and expand macro_rules 1299 // Case 2: normal `macro_rules!` macro
1300 let macro_id = MacroDefId {
1301 ast_id: Some(ast_id),
1302 krate: Some(self.def_collector.def_map.krate),
1303 kind: MacroDefKind::Declarative,
1304 local_inner: mac.is_local_inner,
1305 };
1306 self.def_collector.define_macro(self.module_id, mac.name.clone(), macro_id, mac.is_export);
1307 }
1308
1309 fn collect_macro_call(&mut self, mac: &MacroCall) {
1310 let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone());
1311
1312 // Case 1: try to resolve in legacy scope and expand macro_rules
1318 if let Some(macro_call_id) = 1313 if let Some(macro_call_id) =
1319 ast_id.as_call_id(self.def_collector.db, self.def_collector.def_map.krate, |path| { 1314 ast_id.as_call_id(self.def_collector.db, self.def_collector.def_map.krate, |path| {
1320 path.as_ident().and_then(|name| { 1315 path.as_ident().and_then(|name| {
@@ -1332,7 +1327,7 @@ impl ModCollector<'_, '_> {
1332 return; 1327 return;
1333 } 1328 }
1334 1329
1335 // Case 3: resolve in module scope, expand during name resolution. 1330 // Case 2: resolve in module scope, expand during name resolution.
1336 // We rewrite simple path `macro_name` to `self::macro_name` to force resolve in module scope only. 1331 // We rewrite simple path `macro_name` to `self::macro_name` to force resolve in module scope only.
1337 if ast_id.path.is_ident() { 1332 if ast_id.path.is_ident() {
1338 ast_id.path.kind = PathKind::Super(0); 1333 ast_id.path.kind = PathKind::Super(0);
@@ -1370,10 +1365,6 @@ impl ModCollector<'_, '_> {
1370 } 1365 }
1371} 1366}
1372 1367
1373fn is_macro_rules(path: &ModPath) -> bool {
1374 path.as_ident() == Some(&name![macro_rules])
1375}
1376
1377#[cfg(test)] 1368#[cfg(test)]
1378mod tests { 1369mod tests {
1379 use crate::{db::DefDatabase, test_db::TestDB}; 1370 use crate::{db::DefDatabase, test_db::TestDB};
diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs
index 60fa7646b..609925012 100644
--- a/crates/hir_def/src/path/lower.rs
+++ b/crates/hir_def/src/path/lower.rs
@@ -122,11 +122,9 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
122 // https://github.com/rust-lang/rust/blob/614f273e9388ddd7804d5cbc80b8865068a3744e/src/librustc_resolve/macros.rs#L456 122 // https://github.com/rust-lang/rust/blob/614f273e9388ddd7804d5cbc80b8865068a3744e/src/librustc_resolve/macros.rs#L456
123 // We follow what it did anyway :) 123 // We follow what it did anyway :)
124 if segments.len() == 1 && kind == PathKind::Plain { 124 if segments.len() == 1 && kind == PathKind::Plain {
125 if let Some(macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) { 125 if let Some(_macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) {
126 if macro_call.is_bang() { 126 if let Some(crate_id) = hygiene.local_inner_macros() {
127 if let Some(crate_id) = hygiene.local_inner_macros() { 127 kind = PathKind::DollarCrate(crate_id);
128 kind = PathKind::DollarCrate(crate_id);
129 }
130 } 128 }
131 } 129 }
132 } 130 }
diff --git a/crates/hir_def/src/src.rs b/crates/hir_def/src/src.rs
index 7a79b0314..f67244b46 100644
--- a/crates/hir_def/src/src.rs
+++ b/crates/hir_def/src/src.rs
@@ -36,8 +36,7 @@ impl<N: ItemTreeNode> HasSource for ItemLoc<N> {
36 } 36 }
37} 37}
38 38
39pub trait HasChildSource { 39pub trait HasChildSource<ChildId> {
40 type ChildId;
41 type Value; 40 type Value;
42 fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>>; 41 fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<ChildId, Self::Value>>;
43} 42}
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs
index 477192a09..bd9223825 100644
--- a/crates/hir_expand/src/builtin_macro.rs
+++ b/crates/hir_expand/src/builtin_macro.rs
@@ -63,7 +63,7 @@ macro_rules! register_builtin {
63pub fn find_builtin_macro( 63pub fn find_builtin_macro(
64 ident: &name::Name, 64 ident: &name::Name,
65 krate: CrateId, 65 krate: CrateId,
66 ast_id: AstId<ast::MacroCall>, 66 ast_id: AstId<ast::MacroRules>,
67) -> Option<MacroDefId> { 67) -> Option<MacroDefId> {
68 let kind = find_by_name(ident)?; 68 let kind = find_by_name(ident)?;
69 69
@@ -88,12 +88,15 @@ register_builtin! {
88 (column, Column) => column_expand, 88 (column, Column) => column_expand,
89 (file, File) => file_expand, 89 (file, File) => file_expand,
90 (line, Line) => line_expand, 90 (line, Line) => line_expand,
91 (module_path, ModulePath) => module_path_expand,
91 (assert, Assert) => assert_expand, 92 (assert, Assert) => assert_expand,
92 (stringify, Stringify) => stringify_expand, 93 (stringify, Stringify) => stringify_expand,
93 (format_args, FormatArgs) => format_args_expand, 94 (format_args, FormatArgs) => format_args_expand,
94 // format_args_nl only differs in that it adds a newline in the end, 95 // format_args_nl only differs in that it adds a newline in the end,
95 // so we use the same stub expansion for now 96 // so we use the same stub expansion for now
96 (format_args_nl, FormatArgsNl) => format_args_expand, 97 (format_args_nl, FormatArgsNl) => format_args_expand,
98 (llvm_asm, LlvmAsm) => asm_expand,
99 (asm, Asm) => asm_expand,
97 100
98 EAGER: 101 EAGER:
99 (compile_error, CompileError) => compile_error_expand, 102 (compile_error, CompileError) => compile_error_expand,
@@ -105,6 +108,15 @@ register_builtin! {
105 (option_env, OptionEnv) => option_env_expand 108 (option_env, OptionEnv) => option_env_expand
106} 109}
107 110
111fn module_path_expand(
112 _db: &dyn AstDatabase,
113 _id: LazyMacroId,
114 _tt: &tt::Subtree,
115) -> ExpandResult<tt::Subtree> {
116 // Just return a dummy result.
117 ExpandResult::ok(quote! { "module::path" })
118}
119
108fn line_expand( 120fn line_expand(
109 _db: &dyn AstDatabase, 121 _db: &dyn AstDatabase,
110 _id: LazyMacroId, 122 _id: LazyMacroId,
@@ -261,6 +273,19 @@ fn format_args_expand(
261 ExpandResult::ok(expanded) 273 ExpandResult::ok(expanded)
262} 274}
263 275
276fn asm_expand(
277 _db: &dyn AstDatabase,
278 _id: LazyMacroId,
279 _tt: &tt::Subtree,
280) -> ExpandResult<tt::Subtree> {
281 // both asm and llvm_asm don't return anything, so we can expand them to nothing,
282 // for now
283 let expanded = quote! {
284 ()
285 };
286 ExpandResult::ok(expanded)
287}
288
264fn unquote_str(lit: &tt::Literal) -> Option<String> { 289fn unquote_str(lit: &tt::Literal) -> Option<String> {
265 let lit = ast::make::tokens::literal(&lit.to_string()); 290 let lit = ast::make::tokens::literal(&lit.to_string());
266 let token = ast::String::cast(lit)?; 291 let token = ast::String::cast(lit)?;
@@ -490,12 +515,16 @@ mod tests {
490 fn expand_builtin_macro(ra_fixture: &str) -> String { 515 fn expand_builtin_macro(ra_fixture: &str) -> String {
491 let (db, file_id) = TestDB::with_single_file(&ra_fixture); 516 let (db, file_id) = TestDB::with_single_file(&ra_fixture);
492 let parsed = db.parse(file_id); 517 let parsed = db.parse(file_id);
518 let macro_rules: Vec<_> =
519 parsed.syntax_node().descendants().filter_map(ast::MacroRules::cast).collect();
493 let macro_calls: Vec<_> = 520 let macro_calls: Vec<_> =
494 parsed.syntax_node().descendants().filter_map(ast::MacroCall::cast).collect(); 521 parsed.syntax_node().descendants().filter_map(ast::MacroCall::cast).collect();
495 522
496 let ast_id_map = db.ast_id_map(file_id.into()); 523 let ast_id_map = db.ast_id_map(file_id.into());
497 524
498 let expander = find_by_name(&macro_calls[0].name().unwrap().as_name()).unwrap(); 525 assert_eq!(macro_rules.len(), 1, "test must contain exactly 1 `macro_rules!`");
526 assert_eq!(macro_calls.len(), 1, "test must contain exactly 1 macro call");
527 let expander = find_by_name(&macro_rules[0].name().unwrap().as_name()).unwrap();
499 528
500 let krate = CrateId(0); 529 let krate = CrateId(0);
501 let file_id = match expander { 530 let file_id = match expander {
@@ -503,7 +532,7 @@ mod tests {
503 // the first one should be a macro_rules 532 // the first one should be a macro_rules
504 let def = MacroDefId { 533 let def = MacroDefId {
505 krate: Some(CrateId(0)), 534 krate: Some(CrateId(0)),
506 ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_calls[0]))), 535 ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_rules[0]))),
507 kind: MacroDefKind::BuiltIn(expander), 536 kind: MacroDefKind::BuiltIn(expander),
508 local_inner: false, 537 local_inner: false,
509 }; 538 };
@@ -513,7 +542,7 @@ mod tests {
513 krate, 542 krate,
514 kind: MacroCallKind::FnLike(AstId::new( 543 kind: MacroCallKind::FnLike(AstId::new(
515 file_id.into(), 544 file_id.into(),
516 ast_id_map.ast_id(&macro_calls[1]), 545 ast_id_map.ast_id(&macro_calls[0]),
517 )), 546 )),
518 }; 547 };
519 548
@@ -524,12 +553,12 @@ mod tests {
524 // the first one should be a macro_rules 553 // the first one should be a macro_rules
525 let def = MacroDefId { 554 let def = MacroDefId {
526 krate: Some(krate), 555 krate: Some(krate),
527 ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_calls[0]))), 556 ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_rules[0]))),
528 kind: MacroDefKind::BuiltInEager(expander), 557 kind: MacroDefKind::BuiltInEager(expander),
529 local_inner: false, 558 local_inner: false,
530 }; 559 };
531 560
532 let args = macro_calls[1].token_tree().unwrap(); 561 let args = macro_calls[0].token_tree().unwrap();
533 let parsed_args = mbe::ast_to_token_tree(&args).unwrap().0; 562 let parsed_args = mbe::ast_to_token_tree(&args).unwrap().0;
534 563
535 let arg_id = db.intern_eager_expansion({ 564 let arg_id = db.intern_eager_expansion({
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs
index ffb70f723..11b5b98c8 100644
--- a/crates/hir_expand/src/db.rs
+++ b/crates/hir_expand/src/db.rs
@@ -394,8 +394,8 @@ fn to_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind {
394 // FIXME: Handle Pattern 394 // FIXME: Handle Pattern
395 FragmentKind::Expr 395 FragmentKind::Expr
396 } 396 }
397 // FIXME: Expand to statements in appropriate positions; HIR lowering needs to handle that 397 EXPR_STMT => FragmentKind::Statements,
398 EXPR_STMT | BLOCK_EXPR => FragmentKind::Expr, 398 BLOCK_EXPR => FragmentKind::Expr,
399 ARG_LIST => FragmentKind::Expr, 399 ARG_LIST => FragmentKind::Expr,
400 TRY_EXPR => FragmentKind::Expr, 400 TRY_EXPR => FragmentKind::Expr,
401 TUPLE_EXPR => FragmentKind::Expr, 401 TUPLE_EXPR => FragmentKind::Expr,
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs
index 1a9428514..ae3086a95 100644
--- a/crates/hir_expand/src/lib.rs
+++ b/crates/hir_expand/src/lib.rs
@@ -228,7 +228,7 @@ pub struct MacroDefId {
228 // (which will probably require touching this code), we can instead use 228 // (which will probably require touching this code), we can instead use
229 // that (and also remove the hacks for resolving built-in derives). 229 // that (and also remove the hacks for resolving built-in derives).
230 pub krate: Option<CrateId>, 230 pub krate: Option<CrateId>,
231 pub ast_id: Option<AstId<ast::MacroCall>>, 231 pub ast_id: Option<AstId<ast::MacroRules>>,
232 pub kind: MacroDefKind, 232 pub kind: MacroDefKind,
233 233
234 pub local_inner: bool, 234 pub local_inner: bool,
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs
index 583ed6142..69d8e6803 100644
--- a/crates/hir_expand/src/name.rs
+++ b/crates/hir_expand/src/name.rs
@@ -188,6 +188,7 @@ pub mod known {
188 column, 188 column,
189 compile_error, 189 compile_error,
190 line, 190 line,
191 module_path,
191 assert, 192 assert,
192 stringify, 193 stringify,
193 concat, 194 concat,
@@ -198,6 +199,8 @@ pub mod known {
198 format_args_nl, 199 format_args_nl,
199 env, 200 env,
200 option_env, 201 option_env,
202 llvm_asm,
203 asm,
201 // Builtin derives 204 // Builtin derives
202 Copy, 205 Copy,
203 Clone, 206 Clone,
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs
index 597a195d0..de97ec3c2 100644
--- a/crates/hir_ty/src/tests/macros.rs
+++ b/crates/hir_ty/src/tests/macros.rs
@@ -413,7 +413,6 @@ fn infer_local_macro() {
413 expect![[r#" 413 expect![[r#"
414 !0..6 '1usize': usize 414 !0..6 '1usize': usize
415 10..89 '{ ...!(); }': () 415 10..89 '{ ...!(); }': ()
416 16..65 'macro_... }': {unknown}
417 74..76 '_a': usize 416 74..76 '_a': usize
418 "#]], 417 "#]],
419 ); 418 );
diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs
index da8170417..307a257b1 100644
--- a/crates/hir_ty/src/tests/regression.rs
+++ b/crates/hir_ty/src/tests/regression.rs
@@ -593,6 +593,30 @@ fn issue_4465_dollar_crate_at_type() {
593} 593}
594 594
595#[test] 595#[test]
596fn issue_6811() {
597 check_infer(
598 r#"
599 macro_rules! profile_function {
600 () => {
601 let _a = 1;
602 let _b = 1;
603 };
604 }
605 fn main() {
606 profile_function!();
607 }
608 "#,
609 expect![[r#"
610 !3..5 '_a': i32
611 !6..7 '1': i32
612 !11..13 '_b': i32
613 !14..15 '1': i32
614 103..131 '{ ...!(); }': ()
615 "#]],
616 );
617}
618
619#[test]
596fn issue_4053_diesel_where_clauses() { 620fn issue_4053_diesel_where_clauses() {
597 check_infer( 621 check_infer(
598 r#" 622 r#"
diff --git a/crates/ide/src/file_structure.rs b/crates/ide/src/file_structure.rs
index 415795e8c..c51531391 100644
--- a/crates/ide/src/file_structure.rs
+++ b/crates/ide/src/file_structure.rs
@@ -150,13 +150,7 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
150 }; 150 };
151 Some(node) 151 Some(node)
152 }, 152 },
153 ast::MacroCall(it) => { 153 ast::MacroRules(it) => decl(it),
154 match it.path().and_then(|it| it.segment()).and_then(|it| it.name_ref()) {
155 Some(path_segment) if path_segment.text() == "macro_rules"
156 => decl(it),
157 _ => None,
158 }
159 },
160 _ => None, 154 _ => None,
161 } 155 }
162 } 156 }
@@ -380,7 +374,7 @@ fn very_obsolete() {}
380 label: "mc", 374 label: "mc",
381 navigation_range: 284..286, 375 navigation_range: 284..286,
382 node_range: 271..303, 376 node_range: 271..303,
383 kind: MACRO_CALL, 377 kind: MACRO_RULES,
384 detail: None, 378 detail: None,
385 deprecated: false, 379 deprecated: false,
386 }, 380 },
@@ -389,7 +383,7 @@ fn very_obsolete() {}
389 label: "mcexp", 383 label: "mcexp",
390 navigation_range: 334..339, 384 navigation_range: 334..339,
391 node_range: 305..356, 385 node_range: 305..356,
392 kind: MACRO_CALL, 386 kind: MACRO_RULES,
393 detail: None, 387 detail: None,
394 deprecated: false, 388 deprecated: false,
395 }, 389 },
@@ -398,7 +392,7 @@ fn very_obsolete() {}
398 label: "mcexp", 392 label: "mcexp",
399 navigation_range: 387..392, 393 navigation_range: 387..392,
400 node_range: 358..409, 394 node_range: 358..409,
401 kind: MACRO_CALL, 395 kind: MACRO_RULES,
402 detail: None, 396 detail: None,
403 deprecated: false, 397 deprecated: false,
404 }, 398 },
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index 7395b81bd..675957fff 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -97,6 +97,9 @@ pub(crate) fn find_all_refs(
97 get_struct_def_name_for_struct_literal_search(&sema, &syntax, position) 97 get_struct_def_name_for_struct_literal_search(&sema, &syntax, position)
98 { 98 {
99 (Some(name), ReferenceKind::StructLiteral) 99 (Some(name), ReferenceKind::StructLiteral)
100 } else if let Some(name) = get_enum_def_name_for_struct_literal_search(&sema, &syntax, position)
101 {
102 (Some(name), ReferenceKind::EnumLiteral)
100 } else { 103 } else {
101 ( 104 (
102 sema.find_node_at_offset_with_descend::<ast::Name>(&syntax, position.offset), 105 sema.find_node_at_offset_with_descend::<ast::Name>(&syntax, position.offset),
@@ -198,6 +201,33 @@ fn get_struct_def_name_for_struct_literal_search(
198 None 201 None
199} 202}
200 203
204fn get_enum_def_name_for_struct_literal_search(
205 sema: &Semantics<RootDatabase>,
206 syntax: &SyntaxNode,
207 position: FilePosition,
208) -> Option<ast::Name> {
209 if let TokenAtOffset::Between(ref left, ref right) = syntax.token_at_offset(position.offset) {
210 if right.kind() != SyntaxKind::L_CURLY && right.kind() != SyntaxKind::L_PAREN {
211 return None;
212 }
213 if let Some(name) =
214 sema.find_node_at_offset_with_descend::<ast::Name>(&syntax, left.text_range().start())
215 {
216 return name.syntax().ancestors().find_map(ast::Enum::cast).and_then(|l| l.name());
217 }
218 if sema
219 .find_node_at_offset_with_descend::<ast::GenericParamList>(
220 &syntax,
221 left.text_range().start(),
222 )
223 .is_some()
224 {
225 return left.ancestors().find_map(ast::Enum::cast).and_then(|l| l.name());
226 }
227 }
228 None
229}
230
201fn try_find_self_references( 231fn try_find_self_references(
202 syntax: &SyntaxNode, 232 syntax: &SyntaxNode,
203 position: FilePosition, 233 position: FilePosition,
@@ -357,6 +387,91 @@ fn main() {
357 } 387 }
358 388
359 #[test] 389 #[test]
390 fn test_enum_after_space() {
391 check(
392 r#"
393enum Foo <|>{
394 A,
395 B,
396}
397fn main() {
398 let f: Foo;
399 f = Foo::A;
400}
401"#,
402 expect![[r#"
403 Foo ENUM FileId(0) 0..26 5..8 Other
404
405 FileId(0) 63..66 EnumLiteral
406 "#]],
407 );
408 }
409
410 #[test]
411 fn test_enum_before_space() {
412 check(
413 r#"
414enum Foo<|> {
415 A,
416 B,
417}
418fn main() {
419 let f: Foo;
420 f = Foo::A;
421}
422"#,
423 expect![[r#"
424 Foo ENUM FileId(0) 0..26 5..8 Other
425
426 FileId(0) 50..53 Other
427 FileId(0) 63..66 EnumLiteral
428 "#]],
429 );
430 }
431
432 #[test]
433 fn test_enum_with_generic_type() {
434 check(
435 r#"
436enum Foo<T> <|>{
437 A(T),
438 B,
439}
440fn main() {
441 let f: Foo<i8>;
442 f = Foo::A(1);
443}
444"#,
445 expect![[r#"
446 Foo ENUM FileId(0) 0..32 5..8 Other
447
448 FileId(0) 73..76 EnumLiteral
449 "#]],
450 );
451 }
452
453 #[test]
454 fn test_enum_for_tuple() {
455 check(
456 r#"
457enum Foo<|>{
458 A(i8),
459 B(i8),
460}
461fn main() {
462 let f: Foo;
463 f = Foo::A(1);
464}
465"#,
466 expect![[r#"
467 Foo ENUM FileId(0) 0..33 5..8 Other
468
469 FileId(0) 70..73 EnumLiteral
470 "#]],
471 );
472 }
473
474 #[test]
360 fn test_find_all_refs_for_local() { 475 fn test_find_all_refs_for_local() {
361 check( 476 check(
362 r#" 477 r#"
@@ -655,7 +770,7 @@ fn foo() {
655} 770}
656"#, 771"#,
657 expect![[r#" 772 expect![[r#"
658 m1 MACRO_CALL FileId(0) 0..46 29..31 Other 773 m1 MACRO_RULES FileId(0) 0..46 29..31 Other
659 774
660 FileId(0) 63..65 StructLiteral 775 FileId(0) 63..65 StructLiteral
661 FileId(0) 73..75 StructLiteral 776 FileId(0) 73..75 StructLiteral
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index f5c6eabef..990b0f7d9 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -74,6 +74,7 @@ pub(crate) fn highlight(
74 let mut stack = HighlightedRangeStack::new(); 74 let mut stack = HighlightedRangeStack::new();
75 75
76 let mut current_macro_call: Option<ast::MacroCall> = None; 76 let mut current_macro_call: Option<ast::MacroCall> = None;
77 let mut current_macro_rules: Option<ast::MacroRules> = None;
77 let mut format_string_highlighter = FormatStringHighlighter::default(); 78 let mut format_string_highlighter = FormatStringHighlighter::default();
78 let mut macro_rules_highlighter = MacroRulesHighlighter::default(); 79 let mut macro_rules_highlighter = MacroRulesHighlighter::default();
79 let mut inside_attribute = false; 80 let mut inside_attribute = false;
@@ -106,28 +107,26 @@ pub(crate) fn highlight(
106 binding_hash: None, 107 binding_hash: None,
107 }); 108 });
108 } 109 }
109 if let Some(name) = mc.is_macro_rules() {
110 macro_rules_highlighter.init();
111 if let Some((highlight, binding_hash)) = highlight_element(
112 &sema,
113 &mut bindings_shadow_count,
114 syntactic_name_ref_highlighting,
115 name.syntax().clone().into(),
116 ) {
117 stack.add(HighlightedRange {
118 range: name.syntax().text_range(),
119 highlight,
120 binding_hash,
121 });
122 }
123 }
124 current_macro_call = Some(mc.clone()); 110 current_macro_call = Some(mc.clone());
125 continue; 111 continue;
126 } 112 }
127 WalkEvent::Leave(Some(mc)) => { 113 WalkEvent::Leave(Some(mc)) => {
128 assert!(current_macro_call == Some(mc)); 114 assert_eq!(current_macro_call, Some(mc));
129 current_macro_call = None; 115 current_macro_call = None;
130 format_string_highlighter = FormatStringHighlighter::default(); 116 format_string_highlighter = FormatStringHighlighter::default();
117 }
118 _ => (),
119 }
120
121 match event.clone().map(|it| it.into_node().and_then(ast::MacroRules::cast)) {
122 WalkEvent::Enter(Some(mac)) => {
123 macro_rules_highlighter.init();
124 current_macro_rules = Some(mac);
125 continue;
126 }
127 WalkEvent::Leave(Some(mac)) => {
128 assert_eq!(current_macro_rules, Some(mac));
129 current_macro_rules = None;
131 macro_rules_highlighter = MacroRulesHighlighter::default(); 130 macro_rules_highlighter = MacroRulesHighlighter::default();
132 } 131 }
133 _ => (), 132 _ => (),
@@ -163,6 +162,12 @@ pub(crate) fn highlight(
163 162
164 let range = element.text_range(); 163 let range = element.text_range();
165 164
165 if current_macro_rules.is_some() {
166 if let Some(tok) = element.as_token() {
167 macro_rules_highlighter.advance(tok);
168 }
169 }
170
166 let element_to_highlight = if current_macro_call.is_some() && element.kind() != COMMENT { 171 let element_to_highlight = if current_macro_call.is_some() && element.kind() != COMMENT {
167 // Inside a macro -- expand it first 172 // Inside a macro -- expand it first
168 let token = match element.clone().into_token() { 173 let token = match element.clone().into_token() {
@@ -173,9 +178,6 @@ pub(crate) fn highlight(
173 let parent = token.parent(); 178 let parent = token.parent();
174 179
175 format_string_highlighter.check_for_format_string(&parent); 180 format_string_highlighter.check_for_format_string(&parent);
176 if let Some(tok) = element.as_token() {
177 macro_rules_highlighter.advance(tok);
178 }
179 181
180 // We only care Name and Name_ref 182 // We only care Name and Name_ref
181 match (token.kind(), parent.kind()) { 183 match (token.kind(), parent.kind()) {
@@ -386,10 +388,14 @@ impl HighlightedRangeStack {
386 let mut res = self.stack.pop().unwrap(); 388 let mut res = self.stack.pop().unwrap();
387 res.sort_by_key(|range| range.range.start()); 389 res.sort_by_key(|range| range.range.start());
388 // Check that ranges are sorted and disjoint 390 // Check that ranges are sorted and disjoint
389 assert!(res 391 for (left, right) in res.iter().zip(res.iter().skip(1)) {
390 .iter() 392 assert!(
391 .zip(res.iter().skip(1)) 393 left.range.end() <= right.range.start(),
392 .all(|(left, right)| left.range.end() <= right.range.start())); 394 "left: {:#?}, right: {:#?}",
395 left,
396 right
397 );
398 }
393 res 399 res
394 } 400 }
395} 401}
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
index 396fd46fb..920956b51 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
@@ -95,7 +95,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
95<span class="comment documentation">/// ```</span> 95<span class="comment documentation">/// ```</span>
96<span class="comment documentation">/// </span><span class="macro injected">noop!</span><span class="punctuation injected">(</span><span class="numeric_literal injected">1</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span><span class="punctuation injected"> 96<span class="comment documentation">/// </span><span class="macro injected">noop!</span><span class="punctuation injected">(</span><span class="numeric_literal injected">1</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span><span class="punctuation injected">
97</span><span class="comment documentation">/// ```</span> 97</span><span class="comment documentation">/// ```</span>
98<span class="macro">macro_rules!</span> <span class="macro declaration">noop</span> <span class="punctuation">{</span> 98<span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">noop</span> <span class="punctuation">{</span>
99 <span class="punctuation">(</span><span class="punctuation">$</span>expr<span class="punctuation">:</span>expr<span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span> 99 <span class="punctuation">(</span><span class="punctuation">$</span>expr<span class="punctuation">:</span>expr<span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span>
100 <span class="punctuation">$</span>expr 100 <span class="punctuation">$</span>expr
101 <span class="punctuation">}</span> 101 <span class="punctuation">}</span>
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
index d398e1ec8..c843b5085 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
@@ -35,13 +35,13 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
35 35
36.unresolved_reference { color: #FC5555; text-decoration: wavy underline; } 36.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
37</style> 37</style>
38<pre><code><span class="macro">macro_rules!</span> <span class="macro declaration">println</span> <span class="punctuation">{</span> 38<pre><code><span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">println</span> <span class="punctuation">{</span>
39 <span class="punctuation">(</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>arg<span class="punctuation">:</span>tt<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">(</span><span class="punctuation">{</span> 39 <span class="punctuation">(</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>arg<span class="punctuation">:</span>tt<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">(</span><span class="punctuation">{</span>
40 <span class="punctuation">$</span>crate<span class="punctuation">:</span><span class="punctuation">:</span>io<span class="punctuation">:</span><span class="punctuation">:</span>_print<span class="punctuation">(</span><span class="punctuation">$</span>crate<span class="punctuation">:</span><span class="punctuation">:</span>format_args_nl<span class="punctuation">!</span><span class="punctuation">(</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>arg<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">)</span><span class="punctuation">)</span><span class="punctuation">;</span> 40 <span class="punctuation">$</span>crate<span class="punctuation">:</span><span class="punctuation">:</span>io<span class="punctuation">:</span><span class="punctuation">:</span>_print<span class="punctuation">(</span><span class="punctuation">$</span>crate<span class="punctuation">:</span><span class="punctuation">:</span>format_args_nl<span class="punctuation">!</span><span class="punctuation">(</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>arg<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">)</span><span class="punctuation">)</span><span class="punctuation">;</span>
41 <span class="punctuation">}</span><span class="punctuation">)</span> 41 <span class="punctuation">}</span><span class="punctuation">)</span>
42<span class="punctuation">}</span> 42<span class="punctuation">}</span>
43#[rustc_builtin_macro] 43<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">rustc_builtin_macro</span><span class="attribute attribute">]</span>
44<span class="macro">macro_rules!</span> <span class="macro declaration">format_args_nl</span> <span class="punctuation">{</span> 44<span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">format_args_nl</span> <span class="punctuation">{</span>
45 <span class="punctuation">(</span><span class="punctuation">$</span>fmt<span class="punctuation">:</span>expr<span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span><span class="punctuation">{</span> <span class="comment">/* compiler built-in */</span> <span class="punctuation">}</span><span class="punctuation">}</span><span class="punctuation">;</span> 45 <span class="punctuation">(</span><span class="punctuation">$</span>fmt<span class="punctuation">:</span>expr<span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span><span class="punctuation">{</span> <span class="comment">/* compiler built-in */</span> <span class="punctuation">}</span><span class="punctuation">}</span><span class="punctuation">;</span>
46 <span class="punctuation">(</span><span class="punctuation">$</span>fmt<span class="punctuation">:</span>expr<span class="punctuation">,</span> <span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>args<span class="punctuation">:</span>tt<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span><span class="punctuation">{</span> <span class="comment">/* compiler built-in */</span> <span class="punctuation">}</span><span class="punctuation">}</span><span class="punctuation">;</span> 46 <span class="punctuation">(</span><span class="punctuation">$</span>fmt<span class="punctuation">:</span>expr<span class="punctuation">,</span> <span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>args<span class="punctuation">:</span>tt<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span><span class="punctuation">{</span> <span class="comment">/* compiler built-in */</span> <span class="punctuation">}</span><span class="punctuation">}</span><span class="punctuation">;</span>
47<span class="punctuation">}</span> 47<span class="punctuation">}</span>
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
index a3b4f20e8..0569cf1e5 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
@@ -125,7 +125,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
125 <span class="keyword">let</span> <span class="variable declaration">bar</span> <span class="operator">=</span> <span class="function">foobar</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> 125 <span class="keyword">let</span> <span class="variable declaration">bar</span> <span class="operator">=</span> <span class="function">foobar</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
126<span class="punctuation">}</span> 126<span class="punctuation">}</span>
127 127
128<span class="macro">macro_rules!</span> <span class="macro declaration">def_fn</span> <span class="punctuation">{</span> 128<span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">def_fn</span> <span class="punctuation">{</span>
129 <span class="punctuation">(</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>tt<span class="punctuation">:</span>tt<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>tt<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">}</span> 129 <span class="punctuation">(</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>tt<span class="punctuation">:</span>tt<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>tt<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">}</span>
130<span class="punctuation">}</span> 130<span class="punctuation">}</span>
131 131
@@ -135,13 +135,13 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
135 <span class="punctuation">}</span> 135 <span class="punctuation">}</span>
136<span class="punctuation">}</span> 136<span class="punctuation">}</span>
137 137
138<span class="macro">macro_rules!</span> <span class="macro declaration">noop</span> <span class="punctuation">{</span> 138<span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">noop</span> <span class="punctuation">{</span>
139 <span class="punctuation">(</span><span class="punctuation">$</span>expr<span class="punctuation">:</span>expr<span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span> 139 <span class="punctuation">(</span><span class="punctuation">$</span>expr<span class="punctuation">:</span>expr<span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span>
140 <span class="punctuation">$</span>expr 140 <span class="punctuation">$</span>expr
141 <span class="punctuation">}</span> 141 <span class="punctuation">}</span>
142<span class="punctuation">}</span> 142<span class="punctuation">}</span>
143 143
144<span class="macro">macro_rules!</span> <span class="macro declaration">keyword_frag</span> <span class="punctuation">{</span> 144<span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">keyword_frag</span> <span class="punctuation">{</span>
145 <span class="punctuation">(</span><span class="punctuation">$</span>type<span class="punctuation">:</span>ty<span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">(</span><span class="punctuation">$</span>type<span class="punctuation">)</span> 145 <span class="punctuation">(</span><span class="punctuation">$</span>type<span class="punctuation">:</span>ty<span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">(</span><span class="punctuation">$</span>type<span class="punctuation">)</span>
146<span class="punctuation">}</span> 146<span class="punctuation">}</span>
147 147
diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs
index 5d2cd30d1..d4a774261 100644
--- a/crates/ide_db/src/defs.rs
+++ b/crates/ide_db/src/defs.rs
@@ -217,7 +217,7 @@ impl NameClass {
217 let def: hir::TypeAlias = sema.to_def(&it)?; 217 let def: hir::TypeAlias = sema.to_def(&it)?;
218 Some(NameClass::Definition(Definition::ModuleDef(def.into()))) 218 Some(NameClass::Definition(Definition::ModuleDef(def.into())))
219 }, 219 },
220 ast::MacroCall(it) => { 220 ast::MacroRules(it) => {
221 let def = sema.to_def(&it)?; 221 let def = sema.to_def(&it)?;
222 Some(NameClass::Definition(Definition::Macro(def))) 222 Some(NameClass::Definition(Definition::Macro(def)))
223 }, 223 },
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs
index 607185ca9..3936c7390 100644
--- a/crates/ide_db/src/search.rs
+++ b/crates/ide_db/src/search.rs
@@ -32,6 +32,7 @@ pub enum ReferenceKind {
32 StructLiteral, 32 StructLiteral,
33 RecordFieldExprOrPat, 33 RecordFieldExprOrPat,
34 SelfKw, 34 SelfKw,
35 EnumLiteral,
35 Other, 36 Other,
36} 37}
37 38
@@ -284,6 +285,8 @@ impl<'a> FindUsages<'a> {
284 ReferenceKind::RecordFieldExprOrPat 285 ReferenceKind::RecordFieldExprOrPat
285 } else if is_record_lit_name_ref(&name_ref) || is_call_expr_name_ref(&name_ref) { 286 } else if is_record_lit_name_ref(&name_ref) || is_call_expr_name_ref(&name_ref) {
286 ReferenceKind::StructLiteral 287 ReferenceKind::StructLiteral
288 } else if is_enum_lit_name_ref(&name_ref) {
289 ReferenceKind::EnumLiteral
287 } else { 290 } else {
288 ReferenceKind::Other 291 ReferenceKind::Other
289 }; 292 };
@@ -402,3 +405,15 @@ fn is_record_field_expr_or_pat(name_ref: &ast::NameRef) -> bool {
402 false 405 false
403 } 406 }
404} 407}
408
409fn is_enum_lit_name_ref(name_ref: &ast::NameRef) -> bool {
410 name_ref
411 .syntax()
412 .ancestors()
413 .find_map(ast::PathExpr::cast)
414 .and_then(|p| p.path())
415 .and_then(|p| p.qualifier())
416 .and_then(|p| p.segment())
417 .map(|p| p.name_ref().as_ref() == Some(name_ref))
418 .unwrap_or(false)
419}
diff --git a/crates/ide_db/src/symbol_index.rs b/crates/ide_db/src/symbol_index.rs
index 654df898e..121063aea 100644
--- a/crates/ide_db/src/symbol_index.rs
+++ b/crates/ide_db/src/symbol_index.rs
@@ -404,13 +404,7 @@ fn to_symbol(node: &SyntaxNode) -> Option<(SmolStr, SyntaxNodePtr, TextRange)> {
404 ast::TypeAlias(it) => decl(it), 404 ast::TypeAlias(it) => decl(it),
405 ast::Const(it) => decl(it), 405 ast::Const(it) => decl(it),
406 ast::Static(it) => decl(it), 406 ast::Static(it) => decl(it),
407 ast::MacroCall(it) => { 407 ast::MacroRules(it) => decl(it),
408 if it.is_macro_rules().is_some() {
409 decl(it)
410 } else {
411 None
412 }
413 },
414 _ => None, 408 _ => None,
415 } 409 }
416 } 410 }
diff --git a/crates/mbe/src/mbe_expander.rs b/crates/mbe/src/mbe_expander.rs
index 97bce0536..a80b73db4 100644
--- a/crates/mbe/src/mbe_expander.rs
+++ b/crates/mbe/src/mbe_expander.rs
@@ -163,7 +163,7 @@ mod tests {
163 fn create_rules(macro_definition: &str) -> crate::MacroRules { 163 fn create_rules(macro_definition: &str) -> crate::MacroRules {
164 let source_file = ast::SourceFile::parse(macro_definition).ok().unwrap(); 164 let source_file = ast::SourceFile::parse(macro_definition).ok().unwrap();
165 let macro_definition = 165 let macro_definition =
166 source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); 166 source_file.syntax().descendants().find_map(ast::MacroRules::cast).unwrap();
167 167
168 let (definition_tt, _) = 168 let (definition_tt, _) =
169 ast_to_token_tree(&macro_definition.token_tree().unwrap()).unwrap(); 169 ast_to_token_tree(&macro_definition.token_tree().unwrap()).unwrap();
diff --git a/crates/mbe/src/tests.rs b/crates/mbe/src/tests.rs
index 843054fe8..dff6e98c2 100644
--- a/crates/mbe/src/tests.rs
+++ b/crates/mbe/src/tests.rs
@@ -48,7 +48,7 @@ mod rule_parsing {
48 let macro_definition = format!(" macro_rules! m {{ {} }} ", arm_definition); 48 let macro_definition = format!(" macro_rules! m {{ {} }} ", arm_definition);
49 let source_file = ast::SourceFile::parse(&macro_definition).ok().unwrap(); 49 let source_file = ast::SourceFile::parse(&macro_definition).ok().unwrap();
50 let macro_definition = 50 let macro_definition =
51 source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); 51 source_file.syntax().descendants().find_map(ast::MacroRules::cast).unwrap();
52 52
53 let (definition_tt, _) = 53 let (definition_tt, _) =
54 ast_to_token_tree(&macro_definition.token_tree().unwrap()).unwrap(); 54 ast_to_token_tree(&macro_definition.token_tree().unwrap()).unwrap();
@@ -1668,7 +1668,7 @@ impl MacroFixture {
1668fn parse_macro_to_tt(ra_fixture: &str) -> tt::Subtree { 1668fn parse_macro_to_tt(ra_fixture: &str) -> tt::Subtree {
1669 let source_file = ast::SourceFile::parse(ra_fixture).ok().unwrap(); 1669 let source_file = ast::SourceFile::parse(ra_fixture).ok().unwrap();
1670 let macro_definition = 1670 let macro_definition =
1671 source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); 1671 source_file.syntax().descendants().find_map(ast::MacroRules::cast).unwrap();
1672 1672
1673 let (definition_tt, _) = ast_to_token_tree(&macro_definition.token_tree().unwrap()).unwrap(); 1673 let (definition_tt, _) = ast_to_token_tree(&macro_definition.token_tree().unwrap()).unwrap();
1674 1674
diff --git a/crates/parser/src/grammar/items.rs b/crates/parser/src/grammar/items.rs
index ad29b82f7..8999829b4 100644
--- a/crates/parser/src/grammar/items.rs
+++ b/crates/parser/src/grammar/items.rs
@@ -232,6 +232,9 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
232 T![macro] => { 232 T![macro] => {
233 macro_def(p, m); 233 macro_def(p, m);
234 } 234 }
235 IDENT if p.at_contextual_kw("macro_rules") && p.nth(1) == BANG => {
236 macro_rules(p, m);
237 }
235 IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => { 238 IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => {
236 // test union_items 239 // test union_items
237 // union Foo {} 240 // union Foo {}
@@ -363,6 +366,34 @@ pub(crate) fn item_list(p: &mut Parser) {
363 m.complete(p, ITEM_LIST); 366 m.complete(p, ITEM_LIST);
364} 367}
365 368
369fn macro_rules(p: &mut Parser, m: Marker) {
370 assert!(p.at_contextual_kw("macro_rules"));
371 p.bump_remap(T![macro_rules]);
372 p.expect(T![!]);
373
374 if p.at(IDENT) {
375 name(p);
376 }
377 // Special-case `macro_rules! try`.
378 // This is a hack until we do proper edition support
379
380 // test try_macro_rules
381 // macro_rules! try { () => {} }
382 if p.at(T![try]) {
383 let m = p.start();
384 p.bump_remap(IDENT);
385 m.complete(p, NAME);
386 }
387
388 match p.current() {
389 T!['{'] => {
390 token_tree(p);
391 }
392 _ => p.error("expected `{`"),
393 }
394 m.complete(p, MACRO_RULES);
395}
396
366// test macro_def 397// test macro_def
367// macro m { ($i:ident) => {} } 398// macro m { ($i:ident) => {} }
368// macro m($i:ident) {} 399// macro m($i:ident) {}
@@ -394,19 +425,6 @@ fn macro_call(p: &mut Parser) -> BlockLike {
394 425
395pub(super) fn macro_call_after_excl(p: &mut Parser) -> BlockLike { 426pub(super) fn macro_call_after_excl(p: &mut Parser) -> BlockLike {
396 p.expect(T![!]); 427 p.expect(T![!]);
397 if p.at(IDENT) {
398 name(p);
399 }
400 // Special-case `macro_rules! try`.
401 // This is a hack until we do proper edition support
402
403 // test try_macro_rules
404 // macro_rules! try { () => {} }
405 if p.at(T![try]) {
406 let m = p.start();
407 p.bump_remap(IDENT);
408 m.complete(p, NAME);
409 }
410 428
411 match p.current() { 429 match p.current() {
412 T!['{'] => { 430 T!['{'] => {
diff --git a/crates/parser/src/syntax_kind/generated.rs b/crates/parser/src/syntax_kind/generated.rs
index 8bc6688f3..5d6ec17a4 100644
--- a/crates/parser/src/syntax_kind/generated.rs
+++ b/crates/parser/src/syntax_kind/generated.rs
@@ -106,6 +106,7 @@ pub enum SyntaxKind {
106 EXISTENTIAL_KW, 106 EXISTENTIAL_KW,
107 UNION_KW, 107 UNION_KW,
108 RAW_KW, 108 RAW_KW,
109 MACRO_RULES_KW,
109 INT_NUMBER, 110 INT_NUMBER,
110 FLOAT_NUMBER, 111 FLOAT_NUMBER,
111 CHAR, 112 CHAR,
@@ -135,6 +136,8 @@ pub enum SyntaxKind {
135 IMPL, 136 IMPL,
136 TYPE_ALIAS, 137 TYPE_ALIAS,
137 MACRO_CALL, 138 MACRO_CALL,
139 MACRO_RULES,
140 MACRO_ARM,
138 TOKEN_TREE, 141 TOKEN_TREE,
139 MACRO_DEF, 142 MACRO_DEF,
140 PAREN_TYPE, 143 PAREN_TYPE,
@@ -258,7 +261,7 @@ impl SyntaxKind {
258 | IMPL_KW | IN_KW | LET_KW | LOOP_KW | MACRO_KW | MATCH_KW | MOD_KW | MOVE_KW 261 | IMPL_KW | IN_KW | LET_KW | LOOP_KW | MACRO_KW | MATCH_KW | MOD_KW | MOVE_KW
259 | MUT_KW | PUB_KW | REF_KW | RETURN_KW | SELF_KW | STATIC_KW | STRUCT_KW | SUPER_KW 262 | MUT_KW | PUB_KW | REF_KW | RETURN_KW | SELF_KW | STATIC_KW | STRUCT_KW | SUPER_KW
260 | TRAIT_KW | TRUE_KW | TRY_KW | TYPE_KW | UNSAFE_KW | USE_KW | WHERE_KW | WHILE_KW 263 | TRAIT_KW | TRUE_KW | TRY_KW | TYPE_KW | UNSAFE_KW | USE_KW | WHERE_KW | WHILE_KW
261 | AUTO_KW | DEFAULT_KW | EXISTENTIAL_KW | UNION_KW | RAW_KW => true, 264 | AUTO_KW | DEFAULT_KW | EXISTENTIAL_KW | UNION_KW | RAW_KW | MACRO_RULES_KW => true,
262 _ => false, 265 _ => false,
263 } 266 }
264 } 267 }
@@ -361,4 +364,4 @@ impl SyntaxKind {
361 } 364 }
362} 365}
363#[macro_export] 366#[macro_export]
364macro_rules ! T { [;] => { $ crate :: SyntaxKind :: SEMICOLON } ; [,] => { $ crate :: SyntaxKind :: COMMA } ; ['('] => { $ crate :: SyntaxKind :: L_PAREN } ; [')'] => { $ crate :: SyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: SyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: SyntaxKind :: R_CURLY } ; ['['] => { $ crate :: SyntaxKind :: L_BRACK } ; [']'] => { $ crate :: SyntaxKind :: R_BRACK } ; [<] => { $ crate :: SyntaxKind :: L_ANGLE } ; [>] => { $ crate :: SyntaxKind :: R_ANGLE } ; [@] => { $ crate :: SyntaxKind :: AT } ; [#] => { $ crate :: SyntaxKind :: POUND } ; [~] => { $ crate :: SyntaxKind :: TILDE } ; [?] => { $ crate :: SyntaxKind :: QUESTION } ; [$] => { $ crate :: SyntaxKind :: DOLLAR } ; [&] => { $ crate :: SyntaxKind :: AMP } ; [|] => { $ crate :: SyntaxKind :: PIPE } ; [+] => { $ crate :: SyntaxKind :: PLUS } ; [*] => { $ crate :: SyntaxKind :: STAR } ; [/] => { $ crate :: SyntaxKind :: SLASH } ; [^] => { $ crate :: SyntaxKind :: CARET } ; [%] => { $ crate :: SyntaxKind :: PERCENT } ; [_] => { $ crate :: SyntaxKind :: UNDERSCORE } ; [.] => { $ crate :: SyntaxKind :: DOT } ; [..] => { $ crate :: SyntaxKind :: DOT2 } ; [...] => { $ crate :: SyntaxKind :: DOT3 } ; [..=] => { $ crate :: SyntaxKind :: DOT2EQ } ; [:] => { $ crate :: SyntaxKind :: COLON } ; [::] => { $ crate :: SyntaxKind :: COLON2 } ; [=] => { $ crate :: SyntaxKind :: EQ } ; [==] => { $ crate :: SyntaxKind :: EQ2 } ; [=>] => { $ crate :: SyntaxKind :: FAT_ARROW } ; [!] => { $ crate :: SyntaxKind :: BANG } ; [!=] => { $ crate :: SyntaxKind :: NEQ } ; [-] => { $ crate :: SyntaxKind :: MINUS } ; [->] => { $ crate :: SyntaxKind :: THIN_ARROW } ; [<=] => { $ crate :: SyntaxKind :: LTEQ } ; [>=] => { $ crate :: SyntaxKind :: GTEQ } ; [+=] => { $ crate :: SyntaxKind :: PLUSEQ } ; [-=] => { $ crate :: SyntaxKind :: MINUSEQ } ; [|=] => { $ crate :: SyntaxKind :: PIPEEQ } ; [&=] => { $ crate :: SyntaxKind :: AMPEQ } ; [^=] => { $ crate :: SyntaxKind :: CARETEQ } ; [/=] => { $ crate :: SyntaxKind :: SLASHEQ } ; [*=] => { $ crate :: SyntaxKind :: STAREQ } ; [%=] => { $ crate :: SyntaxKind :: PERCENTEQ } ; [&&] => { $ crate :: SyntaxKind :: AMP2 } ; [||] => { $ crate :: SyntaxKind :: PIPE2 } ; [<<] => { $ crate :: SyntaxKind :: SHL } ; [>>] => { $ crate :: SyntaxKind :: SHR } ; [<<=] => { $ crate :: SyntaxKind :: SHLEQ } ; [>>=] => { $ crate :: SyntaxKind :: SHREQ } ; [as] => { $ crate :: SyntaxKind :: AS_KW } ; [async] => { $ crate :: SyntaxKind :: ASYNC_KW } ; [await] => { $ crate :: SyntaxKind :: AWAIT_KW } ; [box] => { $ crate :: SyntaxKind :: BOX_KW } ; [break] => { $ crate :: SyntaxKind :: BREAK_KW } ; [const] => { $ crate :: SyntaxKind :: CONST_KW } ; [continue] => { $ crate :: SyntaxKind :: CONTINUE_KW } ; [crate] => { $ crate :: SyntaxKind :: CRATE_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [else] => { $ crate :: SyntaxKind :: ELSE_KW } ; [enum] => { $ crate :: SyntaxKind :: ENUM_KW } ; [extern] => { $ crate :: SyntaxKind :: EXTERN_KW } ; [false] => { $ crate :: SyntaxKind :: FALSE_KW } ; [fn] => { $ crate :: SyntaxKind :: FN_KW } ; [for] => { $ crate :: SyntaxKind :: FOR_KW } ; [if] => { $ crate :: SyntaxKind :: IF_KW } ; [impl] => { $ crate :: SyntaxKind :: IMPL_KW } ; [in] => { $ crate :: SyntaxKind :: IN_KW } ; [let] => { $ crate :: SyntaxKind :: LET_KW } ; [loop] => { $ crate :: SyntaxKind :: LOOP_KW } ; [macro] => { $ crate :: SyntaxKind :: MACRO_KW } ; [match] => { $ crate :: SyntaxKind :: MATCH_KW } ; [mod] => { $ crate :: SyntaxKind :: MOD_KW } ; [move] => { $ crate :: SyntaxKind :: MOVE_KW } ; [mut] => { $ crate :: SyntaxKind :: MUT_KW } ; [pub] => { $ crate :: SyntaxKind :: PUB_KW } ; [ref] => { $ crate :: SyntaxKind :: REF_KW } ; [return] => { $ crate :: SyntaxKind :: RETURN_KW } ; [self] => { $ crate :: SyntaxKind :: SELF_KW } ; [static] => { $ crate :: SyntaxKind :: STATIC_KW } ; [struct] => { $ crate :: SyntaxKind :: STRUCT_KW } ; [super] => { $ crate :: SyntaxKind :: SUPER_KW } ; [trait] => { $ crate :: SyntaxKind :: TRAIT_KW } ; [true] => { $ crate :: SyntaxKind :: TRUE_KW } ; [try] => { $ crate :: SyntaxKind :: TRY_KW } ; [type] => { $ crate :: SyntaxKind :: TYPE_KW } ; [unsafe] => { $ crate :: SyntaxKind :: UNSAFE_KW } ; [use] => { $ crate :: SyntaxKind :: USE_KW } ; [where] => { $ crate :: SyntaxKind :: WHERE_KW } ; [while] => { $ crate :: SyntaxKind :: WHILE_KW } ; [auto] => { $ crate :: SyntaxKind :: AUTO_KW } ; [default] => { $ crate :: SyntaxKind :: DEFAULT_KW } ; [existential] => { $ crate :: SyntaxKind :: EXISTENTIAL_KW } ; [union] => { $ crate :: SyntaxKind :: UNION_KW } ; [raw] => { $ crate :: SyntaxKind :: RAW_KW } ; [lifetime] => { $ crate :: SyntaxKind :: LIFETIME } ; [ident] => { $ crate :: SyntaxKind :: IDENT } ; [shebang] => { $ crate :: SyntaxKind :: SHEBANG } ; } 367macro_rules ! T { [;] => { $ crate :: SyntaxKind :: SEMICOLON } ; [,] => { $ crate :: SyntaxKind :: COMMA } ; ['('] => { $ crate :: SyntaxKind :: L_PAREN } ; [')'] => { $ crate :: SyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: SyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: SyntaxKind :: R_CURLY } ; ['['] => { $ crate :: SyntaxKind :: L_BRACK } ; [']'] => { $ crate :: SyntaxKind :: R_BRACK } ; [<] => { $ crate :: SyntaxKind :: L_ANGLE } ; [>] => { $ crate :: SyntaxKind :: R_ANGLE } ; [@] => { $ crate :: SyntaxKind :: AT } ; [#] => { $ crate :: SyntaxKind :: POUND } ; [~] => { $ crate :: SyntaxKind :: TILDE } ; [?] => { $ crate :: SyntaxKind :: QUESTION } ; [$] => { $ crate :: SyntaxKind :: DOLLAR } ; [&] => { $ crate :: SyntaxKind :: AMP } ; [|] => { $ crate :: SyntaxKind :: PIPE } ; [+] => { $ crate :: SyntaxKind :: PLUS } ; [*] => { $ crate :: SyntaxKind :: STAR } ; [/] => { $ crate :: SyntaxKind :: SLASH } ; [^] => { $ crate :: SyntaxKind :: CARET } ; [%] => { $ crate :: SyntaxKind :: PERCENT } ; [_] => { $ crate :: SyntaxKind :: UNDERSCORE } ; [.] => { $ crate :: SyntaxKind :: DOT } ; [..] => { $ crate :: SyntaxKind :: DOT2 } ; [...] => { $ crate :: SyntaxKind :: DOT3 } ; [..=] => { $ crate :: SyntaxKind :: DOT2EQ } ; [:] => { $ crate :: SyntaxKind :: COLON } ; [::] => { $ crate :: SyntaxKind :: COLON2 } ; [=] => { $ crate :: SyntaxKind :: EQ } ; [==] => { $ crate :: SyntaxKind :: EQ2 } ; [=>] => { $ crate :: SyntaxKind :: FAT_ARROW } ; [!] => { $ crate :: SyntaxKind :: BANG } ; [!=] => { $ crate :: SyntaxKind :: NEQ } ; [-] => { $ crate :: SyntaxKind :: MINUS } ; [->] => { $ crate :: SyntaxKind :: THIN_ARROW } ; [<=] => { $ crate :: SyntaxKind :: LTEQ } ; [>=] => { $ crate :: SyntaxKind :: GTEQ } ; [+=] => { $ crate :: SyntaxKind :: PLUSEQ } ; [-=] => { $ crate :: SyntaxKind :: MINUSEQ } ; [|=] => { $ crate :: SyntaxKind :: PIPEEQ } ; [&=] => { $ crate :: SyntaxKind :: AMPEQ } ; [^=] => { $ crate :: SyntaxKind :: CARETEQ } ; [/=] => { $ crate :: SyntaxKind :: SLASHEQ } ; [*=] => { $ crate :: SyntaxKind :: STAREQ } ; [%=] => { $ crate :: SyntaxKind :: PERCENTEQ } ; [&&] => { $ crate :: SyntaxKind :: AMP2 } ; [||] => { $ crate :: SyntaxKind :: PIPE2 } ; [<<] => { $ crate :: SyntaxKind :: SHL } ; [>>] => { $ crate :: SyntaxKind :: SHR } ; [<<=] => { $ crate :: SyntaxKind :: SHLEQ } ; [>>=] => { $ crate :: SyntaxKind :: SHREQ } ; [as] => { $ crate :: SyntaxKind :: AS_KW } ; [async] => { $ crate :: SyntaxKind :: ASYNC_KW } ; [await] => { $ crate :: SyntaxKind :: AWAIT_KW } ; [box] => { $ crate :: SyntaxKind :: BOX_KW } ; [break] => { $ crate :: SyntaxKind :: BREAK_KW } ; [const] => { $ crate :: SyntaxKind :: CONST_KW } ; [continue] => { $ crate :: SyntaxKind :: CONTINUE_KW } ; [crate] => { $ crate :: SyntaxKind :: CRATE_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [else] => { $ crate :: SyntaxKind :: ELSE_KW } ; [enum] => { $ crate :: SyntaxKind :: ENUM_KW } ; [extern] => { $ crate :: SyntaxKind :: EXTERN_KW } ; [false] => { $ crate :: SyntaxKind :: FALSE_KW } ; [fn] => { $ crate :: SyntaxKind :: FN_KW } ; [for] => { $ crate :: SyntaxKind :: FOR_KW } ; [if] => { $ crate :: SyntaxKind :: IF_KW } ; [impl] => { $ crate :: SyntaxKind :: IMPL_KW } ; [in] => { $ crate :: SyntaxKind :: IN_KW } ; [let] => { $ crate :: SyntaxKind :: LET_KW } ; [loop] => { $ crate :: SyntaxKind :: LOOP_KW } ; [macro] => { $ crate :: SyntaxKind :: MACRO_KW } ; [match] => { $ crate :: SyntaxKind :: MATCH_KW } ; [mod] => { $ crate :: SyntaxKind :: MOD_KW } ; [move] => { $ crate :: SyntaxKind :: MOVE_KW } ; [mut] => { $ crate :: SyntaxKind :: MUT_KW } ; [pub] => { $ crate :: SyntaxKind :: PUB_KW } ; [ref] => { $ crate :: SyntaxKind :: REF_KW } ; [return] => { $ crate :: SyntaxKind :: RETURN_KW } ; [self] => { $ crate :: SyntaxKind :: SELF_KW } ; [static] => { $ crate :: SyntaxKind :: STATIC_KW } ; [struct] => { $ crate :: SyntaxKind :: STRUCT_KW } ; [super] => { $ crate :: SyntaxKind :: SUPER_KW } ; [trait] => { $ crate :: SyntaxKind :: TRAIT_KW } ; [true] => { $ crate :: SyntaxKind :: TRUE_KW } ; [try] => { $ crate :: SyntaxKind :: TRY_KW } ; [type] => { $ crate :: SyntaxKind :: TYPE_KW } ; [unsafe] => { $ crate :: SyntaxKind :: UNSAFE_KW } ; [use] => { $ crate :: SyntaxKind :: USE_KW } ; [where] => { $ crate :: SyntaxKind :: WHERE_KW } ; [while] => { $ crate :: SyntaxKind :: WHILE_KW } ; [auto] => { $ crate :: SyntaxKind :: AUTO_KW } ; [default] => { $ crate :: SyntaxKind :: DEFAULT_KW } ; [existential] => { $ crate :: SyntaxKind :: EXISTENTIAL_KW } ; [union] => { $ crate :: SyntaxKind :: UNION_KW } ; [raw] => { $ crate :: SyntaxKind :: RAW_KW } ; [macro_rules] => { $ crate :: SyntaxKind :: MACRO_RULES_KW } ; [lifetime] => { $ crate :: SyntaxKind :: LIFETIME } ; [ident] => { $ crate :: SyntaxKind :: IDENT } ; [shebang] => { $ crate :: SyntaxKind :: SHEBANG } ; }
diff --git a/crates/proc_macro_srv/Cargo.toml b/crates/proc_macro_srv/Cargo.toml
index 729372968..1bfa6c3fc 100644
--- a/crates/proc_macro_srv/Cargo.toml
+++ b/crates/proc_macro_srv/Cargo.toml
@@ -10,7 +10,7 @@ edition = "2018"
10doctest = false 10doctest = false
11 11
12[dependencies] 12[dependencies]
13goblin = "0.2.1" 13object = { version = "0.23", default-features = false, features = ["std", "read_core", "elf", "macho", "pe", "unaligned"] }
14libloading = "0.6.0" 14libloading = "0.6.0"
15memmap = "0.7" 15memmap = "0.7"
16 16
diff --git a/crates/proc_macro_srv/src/dylib.rs b/crates/proc_macro_srv/src/dylib.rs
index f8f705da8..2afb973cc 100644
--- a/crates/proc_macro_srv/src/dylib.rs
+++ b/crates/proc_macro_srv/src/dylib.rs
@@ -1,14 +1,17 @@
1//! Handles dynamic library loading for proc macro 1//! Handles dynamic library loading for proc macro
2 2
3use crate::{proc_macro::bridge, rustc_server::TokenStream}; 3use std::{
4use std::fs::File; 4 fs::File,
5use std::path::{Path, PathBuf}; 5 io,
6 path::{Path, PathBuf},
7};
6 8
7use goblin::{mach::Mach, Object};
8use libloading::Library; 9use libloading::Library;
9use memmap::Mmap; 10use memmap::Mmap;
11use object::Object;
10use proc_macro_api::ProcMacroKind; 12use proc_macro_api::ProcMacroKind;
11use std::io; 13
14use crate::{proc_macro::bridge, rustc_server::TokenStream};
12 15
13const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_"; 16const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_";
14 17
@@ -23,40 +26,26 @@ fn is_derive_registrar_symbol(symbol: &str) -> bool {
23fn find_registrar_symbol(file: &Path) -> io::Result<Option<String>> { 26fn find_registrar_symbol(file: &Path) -> io::Result<Option<String>> {
24 let file = File::open(file)?; 27 let file = File::open(file)?;
25 let buffer = unsafe { Mmap::map(&file)? }; 28 let buffer = unsafe { Mmap::map(&file)? };
26 let object = Object::parse(&buffer).map_err(invalid_data_err)?;
27 29
28 let name = match object { 30 Ok(object::File::parse(&buffer)
29 Object::Elf(elf) => { 31 .map_err(invalid_data_err)?
30 let symbols = elf.dynstrtab.to_vec().map_err(invalid_data_err)?; 32 .exports()
31 symbols.into_iter().find(|s| is_derive_registrar_symbol(s)).map(&str::to_owned) 33 .map_err(invalid_data_err)?
32 } 34 .into_iter()
33 Object::PE(pe) => pe 35 .map(|export| export.name())
34 .exports 36 .filter_map(|sym| String::from_utf8(sym.into()).ok())
35 .iter() 37 .find(|sym| is_derive_registrar_symbol(sym))
36 .flat_map(|s| s.name) 38 .map(|sym| {
37 .find(|s| is_derive_registrar_symbol(s)) 39 // From MacOS docs:
38 .map(&str::to_owned), 40 // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dlsym.3.html
39 Object::Mach(Mach::Binary(binary)) => { 41 // Unlike other dyld API's, the symbol name passed to dlsym() must NOT be
40 let exports = binary.exports().map_err(invalid_data_err)?; 42 // prepended with an underscore.
41 exports 43 if cfg!(target_os = "macos") && sym.starts_with('_') {
42 .iter() 44 sym[1..].to_owned()
43 .map(|s| { 45 } else {
44 // In macos doc: 46 sym
45 // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dlsym.3.html 47 }
46 // Unlike other dyld API's, the symbol name passed to dlsym() must NOT be 48 }))
47 // prepended with an underscore.
48 if s.name.starts_with('_') {
49 &s.name[1..]
50 } else {
51 &s.name
52 }
53 })
54 .find(|s| is_derive_registrar_symbol(s))
55 .map(&str::to_owned)
56 }
57 _ => return Ok(None),
58 };
59 return Ok(name);
60} 49}
61 50
62/// Loads dynamic library in platform dependent manner. 51/// Loads dynamic library in platform dependent manner.
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
index 30d11b146..0ad75214f 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -128,7 +128,6 @@ pub struct MacroCall {
128 pub(crate) syntax: SyntaxNode, 128 pub(crate) syntax: SyntaxNode,
129} 129}
130impl ast::AttrsOwner for MacroCall {} 130impl ast::AttrsOwner for MacroCall {}
131impl ast::NameOwner for MacroCall {}
132impl MacroCall { 131impl MacroCall {
133 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } 132 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
134 pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) } 133 pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
@@ -273,6 +272,20 @@ impl Impl {
273 pub fn assoc_item_list(&self) -> Option<AssocItemList> { support::child(&self.syntax) } 272 pub fn assoc_item_list(&self) -> Option<AssocItemList> { support::child(&self.syntax) }
274} 273}
275#[derive(Debug, Clone, PartialEq, Eq, Hash)] 274#[derive(Debug, Clone, PartialEq, Eq, Hash)]
275pub struct MacroRules {
276 pub(crate) syntax: SyntaxNode,
277}
278impl ast::AttrsOwner for MacroRules {}
279impl ast::NameOwner for MacroRules {}
280impl ast::VisibilityOwner for MacroRules {}
281impl MacroRules {
282 pub fn macro_rules_token(&self) -> Option<SyntaxToken> {
283 support::token(&self.syntax, T![macro_rules])
284 }
285 pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
286 pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) }
287}
288#[derive(Debug, Clone, PartialEq, Eq, Hash)]
276pub struct Module { 289pub struct Module {
277 pub(crate) syntax: SyntaxNode, 290 pub(crate) syntax: SyntaxNode,
278} 291}
@@ -1318,6 +1331,7 @@ pub enum Item {
1318 Fn(Fn), 1331 Fn(Fn),
1319 Impl(Impl), 1332 Impl(Impl),
1320 MacroCall(MacroCall), 1333 MacroCall(MacroCall),
1334 MacroRules(MacroRules),
1321 Module(Module), 1335 Module(Module),
1322 Static(Static), 1336 Static(Static),
1323 Struct(Struct), 1337 Struct(Struct),
@@ -1374,7 +1388,6 @@ pub enum AssocItem {
1374 TypeAlias(TypeAlias), 1388 TypeAlias(TypeAlias),
1375} 1389}
1376impl ast::AttrsOwner for AssocItem {} 1390impl ast::AttrsOwner for AssocItem {}
1377impl ast::NameOwner for AssocItem {}
1378#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1391#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1379pub enum ExternItem { 1392pub enum ExternItem {
1380 Fn(Fn), 1393 Fn(Fn),
@@ -1383,7 +1396,6 @@ pub enum ExternItem {
1383 TypeAlias(TypeAlias), 1396 TypeAlias(TypeAlias),
1384} 1397}
1385impl ast::AttrsOwner for ExternItem {} 1398impl ast::AttrsOwner for ExternItem {}
1386impl ast::NameOwner for ExternItem {}
1387#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1399#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1388pub enum GenericParam { 1400pub enum GenericParam {
1389 ConstParam(ConstParam), 1401 ConstParam(ConstParam),
@@ -1666,6 +1678,17 @@ impl AstNode for Impl {
1666 } 1678 }
1667 fn syntax(&self) -> &SyntaxNode { &self.syntax } 1679 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1668} 1680}
1681impl AstNode for MacroRules {
1682 fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_RULES }
1683 fn cast(syntax: SyntaxNode) -> Option<Self> {
1684 if Self::can_cast(syntax.kind()) {
1685 Some(Self { syntax })
1686 } else {
1687 None
1688 }
1689 }
1690 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1691}
1669impl AstNode for Module { 1692impl AstNode for Module {
1670 fn can_cast(kind: SyntaxKind) -> bool { kind == MODULE } 1693 fn can_cast(kind: SyntaxKind) -> bool { kind == MODULE }
1671 fn cast(syntax: SyntaxNode) -> Option<Self> { 1694 fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3060,6 +3083,9 @@ impl From<Impl> for Item {
3060impl From<MacroCall> for Item { 3083impl From<MacroCall> for Item {
3061 fn from(node: MacroCall) -> Item { Item::MacroCall(node) } 3084 fn from(node: MacroCall) -> Item { Item::MacroCall(node) }
3062} 3085}
3086impl From<MacroRules> for Item {
3087 fn from(node: MacroRules) -> Item { Item::MacroRules(node) }
3088}
3063impl From<Module> for Item { 3089impl From<Module> for Item {
3064 fn from(node: Module) -> Item { Item::Module(node) } 3090 fn from(node: Module) -> Item { Item::Module(node) }
3065} 3091}
@@ -3084,8 +3110,8 @@ impl From<Use> for Item {
3084impl AstNode for Item { 3110impl AstNode for Item {
3085 fn can_cast(kind: SyntaxKind) -> bool { 3111 fn can_cast(kind: SyntaxKind) -> bool {
3086 match kind { 3112 match kind {
3087 CONST | ENUM | EXTERN_BLOCK | EXTERN_CRATE | FN | IMPL | MACRO_CALL | MODULE 3113 CONST | ENUM | EXTERN_BLOCK | EXTERN_CRATE | FN | IMPL | MACRO_CALL | MACRO_RULES
3088 | STATIC | STRUCT | TRAIT | TYPE_ALIAS | UNION | USE => true, 3114 | MODULE | STATIC | STRUCT | TRAIT | TYPE_ALIAS | UNION | USE => true,
3089 _ => false, 3115 _ => false,
3090 } 3116 }
3091 } 3117 }
@@ -3098,6 +3124,7 @@ impl AstNode for Item {
3098 FN => Item::Fn(Fn { syntax }), 3124 FN => Item::Fn(Fn { syntax }),
3099 IMPL => Item::Impl(Impl { syntax }), 3125 IMPL => Item::Impl(Impl { syntax }),
3100 MACRO_CALL => Item::MacroCall(MacroCall { syntax }), 3126 MACRO_CALL => Item::MacroCall(MacroCall { syntax }),
3127 MACRO_RULES => Item::MacroRules(MacroRules { syntax }),
3101 MODULE => Item::Module(Module { syntax }), 3128 MODULE => Item::Module(Module { syntax }),
3102 STATIC => Item::Static(Static { syntax }), 3129 STATIC => Item::Static(Static { syntax }),
3103 STRUCT => Item::Struct(Struct { syntax }), 3130 STRUCT => Item::Struct(Struct { syntax }),
@@ -3118,6 +3145,7 @@ impl AstNode for Item {
3118 Item::Fn(it) => &it.syntax, 3145 Item::Fn(it) => &it.syntax,
3119 Item::Impl(it) => &it.syntax, 3146 Item::Impl(it) => &it.syntax,
3120 Item::MacroCall(it) => &it.syntax, 3147 Item::MacroCall(it) => &it.syntax,
3148 Item::MacroRules(it) => &it.syntax,
3121 Item::Module(it) => &it.syntax, 3149 Item::Module(it) => &it.syntax,
3122 Item::Static(it) => &it.syntax, 3150 Item::Static(it) => &it.syntax,
3123 Item::Struct(it) => &it.syntax, 3151 Item::Struct(it) => &it.syntax,
@@ -3582,6 +3610,11 @@ impl std::fmt::Display for Impl {
3582 std::fmt::Display::fmt(self.syntax(), f) 3610 std::fmt::Display::fmt(self.syntax(), f)
3583 } 3611 }
3584} 3612}
3613impl std::fmt::Display for MacroRules {
3614 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3615 std::fmt::Display::fmt(self.syntax(), f)
3616 }
3617}
3585impl std::fmt::Display for Module { 3618impl std::fmt::Display for Module {
3586 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 3619 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3587 std::fmt::Display::fmt(self.syntax(), f) 3620 std::fmt::Display::fmt(self.syntax(), f)
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs
index 820af2d20..c59a29eab 100644
--- a/crates/syntax/src/ast/node_ext.rs
+++ b/crates/syntax/src/ast/node_ext.rs
@@ -382,21 +382,6 @@ impl ast::Visibility {
382 } 382 }
383} 383}
384 384
385impl ast::MacroCall {
386 pub fn is_macro_rules(&self) -> Option<ast::Name> {
387 let name_ref = self.path()?.segment()?.name_ref()?;
388 if name_ref.text() == "macro_rules" {
389 self.name()
390 } else {
391 None
392 }
393 }
394
395 pub fn is_bang(&self) -> bool {
396 self.is_macro_rules().is_none()
397 }
398}
399
400impl ast::LifetimeParam { 385impl ast::LifetimeParam {
401 pub fn lifetime_bounds(&self) -> impl Iterator<Item = SyntaxToken> { 386 pub fn lifetime_bounds(&self) -> impl Iterator<Item = SyntaxToken> {
402 self.syntax() 387 self.syntax()
@@ -476,5 +461,5 @@ impl ast::DocCommentsOwner for ast::Static {}
476impl ast::DocCommentsOwner for ast::Const {} 461impl ast::DocCommentsOwner for ast::Const {}
477impl ast::DocCommentsOwner for ast::TypeAlias {} 462impl ast::DocCommentsOwner for ast::TypeAlias {}
478impl ast::DocCommentsOwner for ast::Impl {} 463impl ast::DocCommentsOwner for ast::Impl {}
479impl ast::DocCommentsOwner for ast::MacroCall {} 464impl ast::DocCommentsOwner for ast::MacroRules {}
480impl ast::DocCommentsOwner for ast::Use {} 465impl ast::DocCommentsOwner for ast::Use {}
diff --git a/crates/syntax/src/display.rs b/crates/syntax/src/display.rs
index 8d2c7eae4..d33bde30c 100644
--- a/crates/syntax/src/display.rs
+++ b/crates/syntax/src/display.rs
@@ -76,7 +76,7 @@ pub fn type_label(node: &ast::TypeAlias) -> String {
76 label.trim().to_owned() 76 label.trim().to_owned()
77} 77}
78 78
79pub fn macro_label(node: &ast::MacroCall) -> String { 79pub fn macro_label(node: &ast::MacroRules) -> String {
80 let name = node.name().map(|name| name.syntax().text().to_string()).unwrap_or_default(); 80 let name = node.name().map(|name| name.syntax().text().to_string()).unwrap_or_default();
81 let vis = if node.has_atom_attr("macro_export") { "#[macro_export]\n" } else { "" }; 81 let vis = if node.has_atom_attr("macro_export") { "#[macro_export]\n" } else { "" };
82 format!("{}macro_rules! {}", vis, name) 82 format!("{}macro_rules! {}", vis, name)
diff --git a/crates/syntax/src/parsing/text_tree_sink.rs b/crates/syntax/src/parsing/text_tree_sink.rs
index 49842177a..ce27c3dd9 100644
--- a/crates/syntax/src/parsing/text_tree_sink.rs
+++ b/crates/syntax/src/parsing/text_tree_sink.rs
@@ -147,8 +147,8 @@ fn n_attached_trivias<'a>(
147 trivias: impl Iterator<Item = (SyntaxKind, &'a str)>, 147 trivias: impl Iterator<Item = (SyntaxKind, &'a str)>,
148) -> usize { 148) -> usize {
149 match kind { 149 match kind {
150 MACRO_CALL | CONST | TYPE_ALIAS | STRUCT | ENUM | VARIANT | FN | TRAIT | MODULE 150 MACRO_CALL | MACRO_RULES | CONST | TYPE_ALIAS | STRUCT | ENUM | VARIANT | FN | TRAIT
151 | RECORD_FIELD | STATIC | USE => { 151 | MODULE | RECORD_FIELD | STATIC | USE => {
152 let mut res = 0; 152 let mut res = 0;
153 let mut trivias = trivias.enumerate().peekable(); 153 let mut trivias = trivias.enumerate().peekable();
154 154
diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs
index 6f45149bf..2ddaeb176 100644
--- a/crates/syntax/src/validation.rs
+++ b/crates/syntax/src/validation.rs
@@ -3,7 +3,9 @@
3mod block; 3mod block;
4 4
5use crate::{ 5use crate::{
6 algo, ast, match_ast, AstNode, SyntaxError, 6 algo,
7 ast::{self, VisibilityOwner},
8 match_ast, AstNode, SyntaxError,
7 SyntaxKind::{CONST, FN, INT_NUMBER, TYPE_ALIAS}, 9 SyntaxKind::{CONST, FN, INT_NUMBER, TYPE_ALIAS},
8 SyntaxNode, SyntaxToken, TextSize, T, 10 SyntaxNode, SyntaxToken, TextSize, T,
9}; 11};
@@ -99,6 +101,7 @@ pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> {
99 ast::RefType(it) => validate_trait_object_ref_ty(it, &mut errors), 101 ast::RefType(it) => validate_trait_object_ref_ty(it, &mut errors),
100 ast::PtrType(it) => validate_trait_object_ptr_ty(it, &mut errors), 102 ast::PtrType(it) => validate_trait_object_ptr_ty(it, &mut errors),
101 ast::FnPtrType(it) => validate_trait_object_fn_ptr_ret_ty(it, &mut errors), 103 ast::FnPtrType(it) => validate_trait_object_fn_ptr_ret_ty(it, &mut errors),
104 ast::MacroRules(it) => validate_macro_rules(it, &mut errors),
102 _ => (), 105 _ => (),
103 } 106 }
104 } 107 }
@@ -350,3 +353,12 @@ fn validate_trait_object_ty(ty: ast::DynTraitType) -> Option<SyntaxError> {
350 } 353 }
351 None 354 None
352} 355}
356
357fn validate_macro_rules(mac: ast::MacroRules, errors: &mut Vec<SyntaxError>) {
358 if let Some(vis) = mac.visibility() {
359 errors.push(SyntaxError::new(
360 "visibilities are not allowed on `macro_rules!` items",
361 vis.syntax().text_range(),
362 ));
363 }
364}
diff --git a/crates/syntax/test_data/parser/err/0002_duplicate_shebang.rast b/crates/syntax/test_data/parser/err/0002_duplicate_shebang.rast
index 4cfd1bce4..9ad5b12b8 100644
--- a/crates/syntax/test_data/parser/err/0002_duplicate_shebang.rast
+++ b/crates/syntax/test_data/parser/err/0002_duplicate_shebang.rast
@@ -17,14 +17,17 @@ [email protected]
17 [email protected] "bin" 17 [email protected] "bin"
18 [email protected] 18 [email protected]
19 [email protected] "/" 19 [email protected] "/"
20 MACRO_CALL@32..41 20 MACRO_CALL@32..35
21 [email protected] 21 [email protected]
22 [email protected] 22 [email protected]
23 [email protected] 23 [email protected]
24 [email protected] "env" 24 [email protected] "env"
25 [email protected] " " 25 [email protected] " "
26 [email protected] 26 [email protected]
27 [email protected] "rusti" 27 [email protected]
28 [email protected]
29 [email protected]
30 [email protected] "rusti"
28 [email protected] "\n" 31 [email protected] "\n"
29error 23..23: expected `[` 32error 23..23: expected `[`
30error 23..23: expected an item 33error 23..23: expected an item
@@ -35,5 +38,8 @@ error 31..31: expected `{`, `[`, `(`
35error 31..31: expected SEMICOLON 38error 31..31: expected SEMICOLON
36error 31..31: expected an item 39error 31..31: expected an item
37error 35..35: expected BANG 40error 35..35: expected BANG
41error 35..35: expected `{`, `[`, `(`
42error 35..35: expected SEMICOLON
43error 41..41: expected BANG
38error 41..41: expected `{`, `[`, `(` 44error 41..41: expected `{`, `[`, `(`
39error 41..41: expected SEMICOLON 45error 41..41: expected SEMICOLON
diff --git a/crates/syntax/test_data/parser/inline/ok/0062_mod_contents.rast b/crates/syntax/test_data/parser/inline/ok/0062_mod_contents.rast
index de8217064..e4fb32de1 100644
--- a/crates/syntax/test_data/parser/inline/ok/0062_mod_contents.rast
+++ b/crates/syntax/test_data/parser/inline/ok/0062_mod_contents.rast
@@ -12,11 +12,8 @@ [email protected]
12 [email protected] "{" 12 [email protected] "{"
13 [email protected] "}" 13 [email protected] "}"
14 [email protected] "\n" 14 [email protected] "\n"
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected] "macro_rules"
17 [email protected]
18 [email protected]
19 [email protected] "macro_rules"
20 [email protected] "!" 17 [email protected] "!"
21 [email protected] " " 18 [email protected] " "
22 [email protected] 19 [email protected]
diff --git a/crates/syntax/test_data/parser/inline/ok/0096_no_semi_after_block.rast b/crates/syntax/test_data/parser/inline/ok/0096_no_semi_after_block.rast
index e757249f0..e84b9164f 100644
--- a/crates/syntax/test_data/parser/inline/ok/0096_no_semi_after_block.rast
+++ b/crates/syntax/test_data/parser/inline/ok/0096_no_semi_after_block.rast
@@ -82,32 +82,28 @@ [email protected]
82 [email protected] "{" 82 [email protected] "{"
83 [email protected] "}" 83 [email protected] "}"
84 [email protected] "\n " 84 [email protected] "\n "
85 [email protected] 85 [email protected]
86 [email protected] 86 [email protected] "macro_rules"
87 [email protected] 87 [email protected] "!"
88 [email protected] 88 [email protected] " "
89 [email protected] 89 [email protected]
90 [email protected] "macro_rules" 90 [email protected] "test"
91 [email protected] "!" 91 [email protected] " "
92 [email protected] " " 92 [email protected]
93 [email protected] 93 [email protected] "{"
94 [email protected] "test" 94 [email protected] "\n "
95 [email protected] " " 95 [email protected]
96 [email protected] 96 [email protected] "("
97 [email protected] "{" 97 [email protected] ")"
98 [email protected] "\n " 98 [email protected] " "
99 [email protected] 99 [email protected] "="
100 [email protected] "(" 100 [email protected] ">"
101 [email protected] ")" 101 [email protected] " "
102 [email protected] " " 102 [email protected]
103 [email protected] "=" 103 [email protected] "{"
104 [email protected] ">" 104 [email protected] "}"
105 [email protected] " " 105 [email protected] "\n "
106 [email protected] 106 [email protected] "}"
107 [email protected] "{"
108 [email protected] "}"
109 [email protected] "\n "
110 [email protected] "}"
111 [email protected] "\n " 107 [email protected] "\n "
112 [email protected] 108 [email protected]
113 [email protected] 109 [email protected]
diff --git a/crates/syntax/test_data/parser/inline/ok/0160_try_macro_rules.rast b/crates/syntax/test_data/parser/inline/ok/0160_try_macro_rules.rast
index 05b89d1c3..d1c22947b 100644
--- a/crates/syntax/test_data/parser/inline/ok/0160_try_macro_rules.rast
+++ b/crates/syntax/test_data/parser/inline/ok/0160_try_macro_rules.rast
@@ -1,9 +1,6 @@
1[email protected] 1[email protected]
2 [email protected] 2 [email protected]
3 [email protected] 3 [email protected] "macro_rules"
4 [email protected]
5 [email protected]
6 [email protected] "macro_rules"
7 [email protected] "!" 4 [email protected] "!"
8 [email protected] " " 5 [email protected] " "
9 [email protected] 6 [email protected]
diff --git a/crates/syntax/test_data/parser/ok/0053_outer_attribute_on_macro_rules.rast b/crates/syntax/test_data/parser/ok/0053_outer_attribute_on_macro_rules.rast
index be60f7a8e..87d8ebcba 100644
--- a/crates/syntax/test_data/parser/ok/0053_outer_attribute_on_macro_rules.rast
+++ b/crates/syntax/test_data/parser/ok/0053_outer_attribute_on_macro_rules.rast
@@ -1,5 +1,5 @@
1[email protected] 1[email protected]
2 MACRO_CALL@0..64 2 MACRO_RULES@0..64
3 [email protected] "/// Some docs" 3 [email protected] "/// Some docs"
4 [email protected] "\n" 4 [email protected] "\n"
5 [email protected] 5 [email protected]
@@ -11,10 +11,7 @@ [email protected]
11 [email protected] "macro_export" 11 [email protected] "macro_export"
12 [email protected] "]" 12 [email protected] "]"
13 [email protected] "\n" 13 [email protected] "\n"
14 [email protected] 14 [email protected] "macro_rules"
15 [email protected]
16 [email protected]
17 [email protected] "macro_rules"
18 [email protected] "!" 15 [email protected] "!"
19 [email protected] " " 16 [email protected] " "
20 [email protected] 17 [email protected]
diff --git a/docs/dev/style.md b/docs/dev/style.md
index c8d943142..13c6a2a16 100644
--- a/docs/dev/style.md
+++ b/docs/dev/style.md
@@ -96,19 +96,19 @@ When using multiline fixtures, use unindented raw string literals:
96 fn inline_field_shorthand() { 96 fn inline_field_shorthand() {
97 check_assist( 97 check_assist(
98 inline_local_variable, 98 inline_local_variable,
99 r" 99 r#"
100struct S { foo: i32} 100struct S { foo: i32}
101fn main() { 101fn main() {
102 let <|>foo = 92; 102 let <|>foo = 92;
103 S { foo } 103 S { foo }
104} 104}
105", 105"#,
106 r" 106 r#"
107struct S { foo: i32} 107struct S { foo: i32}
108fn main() { 108fn main() {
109 S { foo: 92 } 109 S { foo: 92 }
110} 110}
111", 111"#,
112 ); 112 );
113 } 113 }
114``` 114```
diff --git a/editors/code/.vscodeignore b/editors/code/.vscodeignore
index 7149ab799..5096ce4da 100644
--- a/editors/code/.vscodeignore
+++ b/editors/code/.vscodeignore
@@ -1,4 +1,5 @@
1** 1**
2!language-configuration.json
2!out/src/main.js 3!out/src/main.js
3!package.json 4!package.json
4!package-lock.json 5!package-lock.json
diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs
index 8ceaaf60e..72a4c10f5 100644
--- a/xtask/src/ast_src.rs
+++ b/xtask/src/ast_src.rs
@@ -70,7 +70,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
70 "match", "mod", "move", "mut", "pub", "ref", "return", "self", "static", "struct", "super", 70 "match", "mod", "move", "mut", "pub", "ref", "return", "self", "static", "struct", "super",
71 "trait", "true", "try", "type", "unsafe", "use", "where", "while", 71 "trait", "true", "try", "type", "unsafe", "use", "where", "while",
72 ], 72 ],
73 contextual_keywords: &["auto", "default", "existential", "union", "raw"], 73 contextual_keywords: &["auto", "default", "existential", "union", "raw", "macro_rules"],
74 literals: &["INT_NUMBER", "FLOAT_NUMBER", "CHAR", "BYTE", "STRING", "BYTE_STRING"], 74 literals: &["INT_NUMBER", "FLOAT_NUMBER", "CHAR", "BYTE", "STRING", "BYTE_STRING"],
75 tokens: &[ 75 tokens: &[
76 "ERROR", 76 "ERROR",
@@ -98,6 +98,8 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
98 "IMPL", 98 "IMPL",
99 "TYPE_ALIAS", 99 "TYPE_ALIAS",
100 "MACRO_CALL", 100 "MACRO_CALL",
101 "MACRO_RULES",
102 "MACRO_ARM",
101 "TOKEN_TREE", 103 "TOKEN_TREE",
102 "MACRO_DEF", 104 "MACRO_DEF",
103 "PAREN_TYPE", 105 "PAREN_TYPE",