diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-12-16 16:52:46 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2020-12-16 16:52:46 +0000 |
commit | 63bbdb31e5148c804bbf940963c9c8f3481ad258 (patch) | |
tree | 2732cd2c3878257d9b55447830bc824447332c98 /crates/hir_def/src | |
parent | 423f3872246f1a67b49e248f3437cb46fdfc8138 (diff) | |
parent | d34611633b3b2404188b9e12b08c5def589808c2 (diff) |
Merge #6897
6897: Basic support for macros 2.0 r=jonas-schievink a=jonas-schievink
This adds support for (built-in-only) macros 2.0, and removes some hacks used for builtin derives, which are declared via macros 2.0 in libcore.
First steps for https://github.com/rust-analyzer/rust-analyzer/issues/2248.
Blocked on https://github.com/rust-analyzer/ungrammar/pull/16.
Co-authored-by: Jonas Schievink <[email protected]>
Co-authored-by: Jonas Schievink <[email protected]>
Diffstat (limited to 'crates/hir_def/src')
-rw-r--r-- | crates/hir_def/src/body/lower.rs | 7 | ||||
-rw-r--r-- | crates/hir_def/src/item_scope.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 20 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 16 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 45 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests/macros.rs | 31 |
6 files changed, 102 insertions, 19 deletions
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index bdba4c33e..23e2fd764 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -772,7 +772,10 @@ impl ExprCollector<'_> { | |||
772 | | ast::Item::Module(_) | 772 | | ast::Item::Module(_) |
773 | | ast::Item::MacroCall(_) => return None, | 773 | | ast::Item::MacroCall(_) => return None, |
774 | ast::Item::MacroRules(def) => { | 774 | ast::Item::MacroRules(def) => { |
775 | return Some(Either::Right(def)); | 775 | return Some(Either::Right(ast::Macro::from(def))); |
776 | } | ||
777 | ast::Item::MacroDef(def) => { | ||
778 | return Some(Either::Right(ast::Macro::from(def))); | ||
776 | } | 779 | } |
777 | }; | 780 | }; |
778 | 781 | ||
@@ -800,7 +803,7 @@ impl ExprCollector<'_> { | |||
800 | } | 803 | } |
801 | Either::Right(e) => { | 804 | Either::Right(e) => { |
802 | let mac = MacroDefId { | 805 | let mac = MacroDefId { |
803 | krate: Some(self.expander.module.krate), | 806 | krate: self.expander.module.krate, |
804 | ast_id: Some(self.expander.ast_id(&e)), | 807 | ast_id: Some(self.expander.ast_id(&e)), |
805 | kind: MacroDefKind::Declarative, | 808 | kind: MacroDefKind::Declarative, |
806 | local_inner: false, | 809 | local_inner: false, |
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs index a8b3fe844..62ab3b2bd 100644 --- a/crates/hir_def/src/item_scope.rs +++ b/crates/hir_def/src/item_scope.rs | |||
@@ -363,7 +363,7 @@ impl ItemInNs { | |||
363 | ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db).krate, | 363 | ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db).krate, |
364 | ModuleDefId::BuiltinType(_) => return None, | 364 | ModuleDefId::BuiltinType(_) => return None, |
365 | }, | 365 | }, |
366 | ItemInNs::Macros(id) => return id.krate, | 366 | ItemInNs::Macros(id) => return Some(id.krate), |
367 | }) | 367 | }) |
368 | } | 368 | } |
369 | } | 369 | } |
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 1c9babf37..8cd0b18cc 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -143,6 +143,7 @@ impl ItemTree { | |||
143 | mods, | 143 | mods, |
144 | macro_calls, | 144 | macro_calls, |
145 | macro_rules, | 145 | macro_rules, |
146 | macro_defs, | ||
146 | exprs, | 147 | exprs, |
147 | vis, | 148 | vis, |
148 | generics, | 149 | generics, |
@@ -164,6 +165,7 @@ impl ItemTree { | |||
164 | mods.shrink_to_fit(); | 165 | mods.shrink_to_fit(); |
165 | macro_calls.shrink_to_fit(); | 166 | macro_calls.shrink_to_fit(); |
166 | macro_rules.shrink_to_fit(); | 167 | macro_rules.shrink_to_fit(); |
168 | macro_defs.shrink_to_fit(); | ||
167 | exprs.shrink_to_fit(); | 169 | exprs.shrink_to_fit(); |
168 | 170 | ||
169 | vis.arena.shrink_to_fit(); | 171 | vis.arena.shrink_to_fit(); |
@@ -283,6 +285,7 @@ struct ItemTreeData { | |||
283 | mods: Arena<Mod>, | 285 | mods: Arena<Mod>, |
284 | macro_calls: Arena<MacroCall>, | 286 | macro_calls: Arena<MacroCall>, |
285 | macro_rules: Arena<MacroRules>, | 287 | macro_rules: Arena<MacroRules>, |
288 | macro_defs: Arena<MacroDef>, | ||
286 | exprs: Arena<Expr>, | 289 | exprs: Arena<Expr>, |
287 | 290 | ||
288 | vis: ItemVisibilities, | 291 | vis: ItemVisibilities, |
@@ -431,6 +434,7 @@ mod_items! { | |||
431 | Mod in mods -> ast::Module, | 434 | Mod in mods -> ast::Module, |
432 | MacroCall in macro_calls -> ast::MacroCall, | 435 | MacroCall in macro_calls -> ast::MacroCall, |
433 | MacroRules in macro_rules -> ast::MacroRules, | 436 | MacroRules in macro_rules -> ast::MacroRules, |
437 | MacroDef in macro_defs -> ast::MacroDef, | ||
434 | } | 438 | } |
435 | 439 | ||
436 | macro_rules! impl_index { | 440 | macro_rules! impl_index { |
@@ -640,7 +644,7 @@ pub struct MacroCall { | |||
640 | 644 | ||
641 | #[derive(Debug, Clone, Eq, PartialEq)] | 645 | #[derive(Debug, Clone, Eq, PartialEq)] |
642 | pub struct MacroRules { | 646 | pub struct MacroRules { |
643 | /// For `macro_rules!` declarations, this is the name of the declared macro. | 647 | /// The name of the declared macro. |
644 | pub name: Name, | 648 | pub name: Name, |
645 | /// Has `#[macro_export]`. | 649 | /// Has `#[macro_export]`. |
646 | pub is_export: bool, | 650 | pub is_export: bool, |
@@ -651,6 +655,16 @@ pub struct MacroRules { | |||
651 | pub ast_id: FileAstId<ast::MacroRules>, | 655 | pub ast_id: FileAstId<ast::MacroRules>, |
652 | } | 656 | } |
653 | 657 | ||
658 | /// "Macros 2.0" macro definition. | ||
659 | #[derive(Debug, Clone, Eq, PartialEq)] | ||
660 | pub struct MacroDef { | ||
661 | pub name: Name, | ||
662 | pub visibility: RawVisibilityId, | ||
663 | /// Has `#[rustc_builtin_macro]`. | ||
664 | pub is_builtin: bool, | ||
665 | pub ast_id: FileAstId<ast::MacroDef>, | ||
666 | } | ||
667 | |||
654 | // NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array | 668 | // NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array |
655 | // lengths, but we don't do much with them yet. | 669 | // lengths, but we don't do much with them yet. |
656 | #[derive(Debug, Clone, Eq, PartialEq)] | 670 | #[derive(Debug, Clone, Eq, PartialEq)] |
@@ -680,7 +694,8 @@ impl ModItem { | |||
680 | | ModItem::Trait(_) | 694 | | ModItem::Trait(_) |
681 | | ModItem::Impl(_) | 695 | | ModItem::Impl(_) |
682 | | ModItem::Mod(_) | 696 | | ModItem::Mod(_) |
683 | | ModItem::MacroRules(_) => None, | 697 | | ModItem::MacroRules(_) |
698 | | ModItem::MacroDef(_) => None, | ||
684 | ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)), | 699 | ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)), |
685 | ModItem::Const(konst) => Some(AssocItem::Const(*konst)), | 700 | ModItem::Const(konst) => Some(AssocItem::Const(*konst)), |
686 | ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)), | 701 | ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)), |
@@ -708,6 +723,7 @@ impl ModItem { | |||
708 | ModItem::Mod(it) => tree[it.index].ast_id().upcast(), | 723 | ModItem::Mod(it) => tree[it.index].ast_id().upcast(), |
709 | ModItem::MacroCall(it) => tree[it.index].ast_id().upcast(), | 724 | ModItem::MacroCall(it) => tree[it.index].ast_id().upcast(), |
710 | ModItem::MacroRules(it) => tree[it.index].ast_id().upcast(), | 725 | ModItem::MacroRules(it) => tree[it.index].ast_id().upcast(), |
726 | ModItem::MacroDef(it) => tree[it.index].ast_id().upcast(), | ||
711 | } | 727 | } |
712 | } | 728 | } |
713 | } | 729 | } |
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index b39d7fb7a..1dc06a211 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs | |||
@@ -101,7 +101,8 @@ impl Ctx { | |||
101 | | ast::Item::ExternCrate(_) | 101 | | ast::Item::ExternCrate(_) |
102 | | ast::Item::Use(_) | 102 | | ast::Item::Use(_) |
103 | | ast::Item::MacroCall(_) | 103 | | ast::Item::MacroCall(_) |
104 | | ast::Item::MacroRules(_) => {} | 104 | | ast::Item::MacroRules(_) |
105 | | ast::Item::MacroDef(_) => {} | ||
105 | }; | 106 | }; |
106 | 107 | ||
107 | let attrs = Attrs::new(item, &self.hygiene); | 108 | let attrs = Attrs::new(item, &self.hygiene); |
@@ -122,6 +123,7 @@ impl Ctx { | |||
122 | ast::Item::ExternCrate(ast) => self.lower_extern_crate(ast).map(Into::into), | 123 | ast::Item::ExternCrate(ast) => self.lower_extern_crate(ast).map(Into::into), |
123 | ast::Item::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into), | 124 | 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), | 125 | ast::Item::MacroRules(ast) => self.lower_macro_rules(ast).map(Into::into), |
126 | ast::Item::MacroDef(ast) => self.lower_macro_def(ast).map(Into::into), | ||
125 | ast::Item::ExternBlock(ast) => { | 127 | ast::Item::ExternBlock(ast) => { |
126 | Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>())) | 128 | Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>())) |
127 | } | 129 | } |
@@ -561,6 +563,18 @@ impl Ctx { | |||
561 | Some(id(self.data().macro_rules.alloc(res))) | 563 | Some(id(self.data().macro_rules.alloc(res))) |
562 | } | 564 | } |
563 | 565 | ||
566 | fn lower_macro_def(&mut self, m: &ast::MacroDef) -> Option<FileItemTreeId<MacroDef>> { | ||
567 | let name = m.name().map(|it| it.as_name())?; | ||
568 | let attrs = Attrs::new(m, &self.hygiene); | ||
569 | |||
570 | let ast_id = self.source_ast_id_map.ast_id(m); | ||
571 | let visibility = self.lower_visibility(m); | ||
572 | |||
573 | let is_builtin = attrs.by_key("rustc_builtin_macro").exists(); | ||
574 | let res = MacroDef { name, is_builtin, ast_id, visibility }; | ||
575 | Some(id(self.data().macro_defs.alloc(res))) | ||
576 | } | ||
577 | |||
564 | fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> { | 578 | fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> { |
565 | block.extern_item_list().map_or(Vec::new(), |list| { | 579 | block.extern_item_list().map_or(Vec::new(), |list| { |
566 | list.extern_items() | 580 | list.extern_items() |
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 85cc342c4..785895277 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -309,13 +309,13 @@ impl DefCollector<'_> { | |||
309 | let macro_def = match self.proc_macros.iter().find(|(n, _)| n == name) { | 309 | let macro_def = match self.proc_macros.iter().find(|(n, _)| n == name) { |
310 | Some((_, expander)) => MacroDefId { | 310 | Some((_, expander)) => MacroDefId { |
311 | ast_id: None, | 311 | ast_id: None, |
312 | krate: Some(self.def_map.krate), | 312 | krate: self.def_map.krate, |
313 | kind: MacroDefKind::ProcMacro(*expander), | 313 | kind: MacroDefKind::ProcMacro(*expander), |
314 | local_inner: false, | 314 | local_inner: false, |
315 | }, | 315 | }, |
316 | None => MacroDefId { | 316 | None => MacroDefId { |
317 | ast_id: None, | 317 | ast_id: None, |
318 | krate: Some(self.def_map.krate), | 318 | krate: self.def_map.krate, |
319 | kind: MacroDefKind::ProcMacro(ProcMacroExpander::dummy(self.def_map.krate)), | 319 | kind: MacroDefKind::ProcMacro(ProcMacroExpander::dummy(self.def_map.krate)), |
320 | local_inner: false, | 320 | local_inner: false, |
321 | }, | 321 | }, |
@@ -784,14 +784,6 @@ impl DefCollector<'_> { | |||
784 | directive: &DeriveDirective, | 784 | directive: &DeriveDirective, |
785 | path: &ModPath, | 785 | path: &ModPath, |
786 | ) -> Option<MacroDefId> { | 786 | ) -> Option<MacroDefId> { |
787 | if let Some(name) = path.as_ident() { | ||
788 | // FIXME this should actually be handled with the normal name | ||
789 | // resolution; the std lib defines built-in stubs for the derives, | ||
790 | // but these are new-style `macro`s, which we don't support yet | ||
791 | if let Some(def_id) = find_builtin_derive(name) { | ||
792 | return Some(def_id); | ||
793 | } | ||
794 | } | ||
795 | let resolved_res = self.def_map.resolve_path_fp_with_macro( | 787 | let resolved_res = self.def_map.resolve_path_fp_with_macro( |
796 | self.db, | 788 | self.db, |
797 | ResolveMode::Other, | 789 | ResolveMode::Other, |
@@ -976,6 +968,35 @@ impl ModCollector<'_, '_> { | |||
976 | } | 968 | } |
977 | ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]), | 969 | ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]), |
978 | ModItem::MacroRules(mac) => self.collect_macro_rules(&self.item_tree[mac]), | 970 | ModItem::MacroRules(mac) => self.collect_macro_rules(&self.item_tree[mac]), |
971 | ModItem::MacroDef(id) => { | ||
972 | let mac = &self.item_tree[id]; | ||
973 | let ast_id = InFile::new(self.file_id, mac.ast_id.upcast()); | ||
974 | |||
975 | // "Macro 2.0" is not currently supported by rust-analyzer, but libcore uses it | ||
976 | // to define builtin macros, so we support at least that part. | ||
977 | if mac.is_builtin { | ||
978 | let krate = self.def_collector.def_map.krate; | ||
979 | let macro_id = find_builtin_macro(&mac.name, krate, ast_id) | ||
980 | .or_else(|| find_builtin_derive(&mac.name, krate, ast_id)); | ||
981 | if let Some(macro_id) = macro_id { | ||
982 | let vis = self | ||
983 | .def_collector | ||
984 | .def_map | ||
985 | .resolve_visibility( | ||
986 | self.def_collector.db, | ||
987 | self.module_id, | ||
988 | &self.item_tree[mac.visibility], | ||
989 | ) | ||
990 | .unwrap_or(Visibility::Public); | ||
991 | self.def_collector.update( | ||
992 | self.module_id, | ||
993 | &[(Some(mac.name.clone()), PerNs::macros(macro_id, vis))], | ||
994 | vis, | ||
995 | ImportType::Named, | ||
996 | ); | ||
997 | } | ||
998 | } | ||
999 | } | ||
979 | ModItem::Impl(imp) => { | 1000 | ModItem::Impl(imp) => { |
980 | let module = ModuleId { | 1001 | let module = ModuleId { |
981 | krate: self.def_collector.def_map.krate, | 1002 | krate: self.def_collector.def_map.krate, |
@@ -1280,7 +1301,7 @@ impl ModCollector<'_, '_> { | |||
1280 | } | 1301 | } |
1281 | 1302 | ||
1282 | fn collect_macro_rules(&mut self, mac: &MacroRules) { | 1303 | fn collect_macro_rules(&mut self, mac: &MacroRules) { |
1283 | let ast_id = InFile::new(self.file_id, mac.ast_id); | 1304 | let ast_id = InFile::new(self.file_id, mac.ast_id.upcast()); |
1284 | 1305 | ||
1285 | // Case 1: builtin macros | 1306 | // Case 1: builtin macros |
1286 | if mac.is_builtin { | 1307 | if mac.is_builtin { |
@@ -1299,7 +1320,7 @@ impl ModCollector<'_, '_> { | |||
1299 | // Case 2: normal `macro_rules!` macro | 1320 | // Case 2: normal `macro_rules!` macro |
1300 | let macro_id = MacroDefId { | 1321 | let macro_id = MacroDefId { |
1301 | ast_id: Some(ast_id), | 1322 | ast_id: Some(ast_id), |
1302 | krate: Some(self.def_collector.def_map.krate), | 1323 | krate: self.def_collector.def_map.krate, |
1303 | kind: MacroDefKind::Declarative, | 1324 | kind: MacroDefKind::Declarative, |
1304 | local_inner: mac.is_local_inner, | 1325 | local_inner: mac.is_local_inner, |
1305 | }; | 1326 | }; |
diff --git a/crates/hir_def/src/nameres/tests/macros.rs b/crates/hir_def/src/nameres/tests/macros.rs index 305fca0f9..6fe2ee78a 100644 --- a/crates/hir_def/src/nameres/tests/macros.rs +++ b/crates/hir_def/src/nameres/tests/macros.rs | |||
@@ -633,15 +633,44 @@ pub struct bar; | |||
633 | fn expand_derive() { | 633 | fn expand_derive() { |
634 | let map = compute_crate_def_map( | 634 | let map = compute_crate_def_map( |
635 | " | 635 | " |
636 | //- /main.rs | 636 | //- /main.rs crate:main deps:core |
637 | use core::*; | ||
638 | |||
637 | #[derive(Copy, Clone)] | 639 | #[derive(Copy, Clone)] |
638 | struct Foo; | 640 | struct Foo; |
641 | |||
642 | //- /core.rs crate:core | ||
643 | #[rustc_builtin_macro] | ||
644 | pub macro Copy {} | ||
645 | |||
646 | #[rustc_builtin_macro] | ||
647 | pub macro Clone {} | ||
639 | ", | 648 | ", |
640 | ); | 649 | ); |
641 | assert_eq!(map.modules[map.root].scope.impls().len(), 2); | 650 | assert_eq!(map.modules[map.root].scope.impls().len(), 2); |
642 | } | 651 | } |
643 | 652 | ||
644 | #[test] | 653 | #[test] |
654 | fn resolve_builtin_derive() { | ||
655 | check( | ||
656 | r#" | ||
657 | //- /main.rs crate:main deps:core | ||
658 | use core::*; | ||
659 | |||
660 | //- /core.rs crate:core | ||
661 | #[rustc_builtin_macro] | ||
662 | pub macro Clone {} | ||
663 | |||
664 | pub trait Clone {} | ||
665 | "#, | ||
666 | expect![[r#" | ||
667 | crate | ||
668 | Clone: t m | ||
669 | "#]], | ||
670 | ); | ||
671 | } | ||
672 | |||
673 | #[test] | ||
645 | fn macro_expansion_overflow() { | 674 | fn macro_expansion_overflow() { |
646 | mark::check!(macro_expansion_overflow); | 675 | mark::check!(macro_expansion_overflow); |
647 | check( | 676 | check( |