aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src')
-rw-r--r--crates/hir_def/src/body/lower.rs7
-rw-r--r--crates/hir_def/src/item_scope.rs2
-rw-r--r--crates/hir_def/src/item_tree.rs20
-rw-r--r--crates/hir_def/src/item_tree/lower.rs16
-rw-r--r--crates/hir_def/src/nameres/collector.rs45
-rw-r--r--crates/hir_def/src/nameres/tests/macros.rs31
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
436macro_rules! impl_index { 440macro_rules! impl_index {
@@ -640,7 +644,7 @@ pub struct MacroCall {
640 644
641#[derive(Debug, Clone, Eq, PartialEq)] 645#[derive(Debug, Clone, Eq, PartialEq)]
642pub struct MacroRules { 646pub 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)]
660pub 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;
633fn expand_derive() { 633fn 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]
654fn resolve_builtin_derive() {
655 check(
656 r#"
657//- /main.rs crate:main deps:core
658use core::*;
659
660//- /core.rs crate:core
661#[rustc_builtin_macro]
662pub macro Clone {}
663
664pub trait Clone {}
665"#,
666 expect![[r#"
667 crate
668 Clone: t m
669 "#]],
670 );
671}
672
673#[test]
645fn macro_expansion_overflow() { 674fn macro_expansion_overflow() {
646 mark::check!(macro_expansion_overflow); 675 mark::check!(macro_expansion_overflow);
647 check( 676 check(