Skip to content

Commit 63bbdb3

Browse files
bors[bot]jonas-schievinkJonas Schievink
authored
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 #2248. Blocked on rust-analyzer/ungrammar#16. Co-authored-by: Jonas Schievink <[email protected]> Co-authored-by: Jonas Schievink <[email protected]>
2 parents 423f387 + d346116 commit 63bbdb3

File tree

23 files changed

+286
-68
lines changed

23 files changed

+286
-68
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/hir/src/code_model.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -970,7 +970,7 @@ impl MacroDef {
970970
/// defines this macro. The reasons for this is that macros are expanded
971971
/// early, in `hir_expand`, where modules simply do not exist yet.
972972
pub fn module(self, db: &dyn HirDatabase) -> Option<Module> {
973-
let krate = self.id.krate?;
973+
let krate = self.id.krate;
974974
let module_id = db.crate_def_map(krate).root;
975975
Some(Module::new(Crate { id: krate }, module_id))
976976
}

crates/hir/src/has_source.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ impl HasSource for TypeAlias {
110110
}
111111
}
112112
impl HasSource for MacroDef {
113-
type Ast = ast::MacroRules;
114-
fn source(self, db: &dyn HirDatabase) -> InFile<ast::MacroRules> {
113+
type Ast = ast::Macro;
114+
fn source(self, db: &dyn HirDatabase) -> InFile<ast::Macro> {
115115
InFile {
116116
file_id: self.id.ast_id.expect("MacroDef without ast_id").file_id,
117117
value: self.id.ast_id.expect("MacroDef without ast_id").to_node(db.upcast()),

crates/hir/src/semantics/source_to_def.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,8 @@ impl SourceToDefCtx<'_, '_> {
157157
let file_id = src.file_id.original_file(self.db.upcast());
158158
let krate = self.file_to_def(file_id)?.krate;
159159
let file_ast_id = self.db.ast_id_map(src.file_id).ast_id(&src.value);
160-
let ast_id = Some(AstId::new(src.file_id, file_ast_id));
161-
Some(MacroDefId { krate: Some(krate), ast_id, kind, local_inner: false })
160+
let ast_id = Some(AstId::new(src.file_id, file_ast_id.upcast()));
161+
Some(MacroDefId { krate, ast_id, kind, local_inner: false })
162162
}
163163

164164
pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> {

crates/hir_def/src/body/lower.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,10 @@ impl ExprCollector<'_> {
772772
| ast::Item::Module(_)
773773
| ast::Item::MacroCall(_) => return None,
774774
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)));
776779
}
777780
};
778781

@@ -800,7 +803,7 @@ impl ExprCollector<'_> {
800803
}
801804
Either::Right(e) => {
802805
let mac = MacroDefId {
803-
krate: Some(self.expander.module.krate),
806+
krate: self.expander.module.krate,
804807
ast_id: Some(self.expander.ast_id(&e)),
805808
kind: MacroDefKind::Declarative,
806809
local_inner: false,

crates/hir_def/src/item_scope.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ impl ItemInNs {
363363
ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db).krate,
364364
ModuleDefId::BuiltinType(_) => return None,
365365
},
366-
ItemInNs::Macros(id) => return id.krate,
366+
ItemInNs::Macros(id) => return Some(id.krate),
367367
})
368368
}
369369
}

crates/hir_def/src/item_tree.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ impl ItemTree {
143143
mods,
144144
macro_calls,
145145
macro_rules,
146+
macro_defs,
146147
exprs,
147148
vis,
148149
generics,
@@ -164,6 +165,7 @@ impl ItemTree {
164165
mods.shrink_to_fit();
165166
macro_calls.shrink_to_fit();
166167
macro_rules.shrink_to_fit();
168+
macro_defs.shrink_to_fit();
167169
exprs.shrink_to_fit();
168170

169171
vis.arena.shrink_to_fit();
@@ -283,6 +285,7 @@ struct ItemTreeData {
283285
mods: Arena<Mod>,
284286
macro_calls: Arena<MacroCall>,
285287
macro_rules: Arena<MacroRules>,
288+
macro_defs: Arena<MacroDef>,
286289
exprs: Arena<Expr>,
287290

288291
vis: ItemVisibilities,
@@ -431,6 +434,7 @@ mod_items! {
431434
Mod in mods -> ast::Module,
432435
MacroCall in macro_calls -> ast::MacroCall,
433436
MacroRules in macro_rules -> ast::MacroRules,
437+
MacroDef in macro_defs -> ast::MacroDef,
434438
}
435439

436440
macro_rules! impl_index {
@@ -640,7 +644,7 @@ pub struct MacroCall {
640644

641645
#[derive(Debug, Clone, Eq, PartialEq)]
642646
pub struct MacroRules {
643-
/// For `macro_rules!` declarations, this is the name of the declared macro.
647+
/// The name of the declared macro.
644648
pub name: Name,
645649
/// Has `#[macro_export]`.
646650
pub is_export: bool,
@@ -651,6 +655,16 @@ pub struct MacroRules {
651655
pub ast_id: FileAstId<ast::MacroRules>,
652656
}
653657

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+
654668
// NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array
655669
// lengths, but we don't do much with them yet.
656670
#[derive(Debug, Clone, Eq, PartialEq)]
@@ -680,7 +694,8 @@ impl ModItem {
680694
| ModItem::Trait(_)
681695
| ModItem::Impl(_)
682696
| ModItem::Mod(_)
683-
| ModItem::MacroRules(_) => None,
697+
| ModItem::MacroRules(_)
698+
| ModItem::MacroDef(_) => None,
684699
ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)),
685700
ModItem::Const(konst) => Some(AssocItem::Const(*konst)),
686701
ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)),
@@ -708,6 +723,7 @@ impl ModItem {
708723
ModItem::Mod(it) => tree[it.index].ast_id().upcast(),
709724
ModItem::MacroCall(it) => tree[it.index].ast_id().upcast(),
710725
ModItem::MacroRules(it) => tree[it.index].ast_id().upcast(),
726+
ModItem::MacroDef(it) => tree[it.index].ast_id().upcast(),
711727
}
712728
}
713729
}

crates/hir_def/src/item_tree/lower.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ impl Ctx {
101101
| ast::Item::ExternCrate(_)
102102
| ast::Item::Use(_)
103103
| ast::Item::MacroCall(_)
104-
| ast::Item::MacroRules(_) => {}
104+
| ast::Item::MacroRules(_)
105+
| ast::Item::MacroDef(_) => {}
105106
};
106107

107108
let attrs = Attrs::new(item, &self.hygiene);
@@ -122,6 +123,7 @@ impl Ctx {
122123
ast::Item::ExternCrate(ast) => self.lower_extern_crate(ast).map(Into::into),
123124
ast::Item::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into),
124125
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),
125127
ast::Item::ExternBlock(ast) => {
126128
Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>()))
127129
}
@@ -561,6 +563,18 @@ impl Ctx {
561563
Some(id(self.data().macro_rules.alloc(res)))
562564
}
563565

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+
564578
fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> {
565579
block.extern_item_list().map_or(Vec::new(), |list| {
566580
list.extern_items()

crates/hir_def/src/nameres/collector.rs

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -309,13 +309,13 @@ impl DefCollector<'_> {
309309
let macro_def = match self.proc_macros.iter().find(|(n, _)| n == name) {
310310
Some((_, expander)) => MacroDefId {
311311
ast_id: None,
312-
krate: Some(self.def_map.krate),
312+
krate: self.def_map.krate,
313313
kind: MacroDefKind::ProcMacro(*expander),
314314
local_inner: false,
315315
},
316316
None => MacroDefId {
317317
ast_id: None,
318-
krate: Some(self.def_map.krate),
318+
krate: self.def_map.krate,
319319
kind: MacroDefKind::ProcMacro(ProcMacroExpander::dummy(self.def_map.krate)),
320320
local_inner: false,
321321
},
@@ -784,14 +784,6 @@ impl DefCollector<'_> {
784784
directive: &DeriveDirective,
785785
path: &ModPath,
786786
) -> 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-
}
795787
let resolved_res = self.def_map.resolve_path_fp_with_macro(
796788
self.db,
797789
ResolveMode::Other,
@@ -976,6 +968,35 @@ impl ModCollector<'_, '_> {
976968
}
977969
ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]),
978970
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+
}
9791000
ModItem::Impl(imp) => {
9801001
let module = ModuleId {
9811002
krate: self.def_collector.def_map.krate,
@@ -1280,7 +1301,7 @@ impl ModCollector<'_, '_> {
12801301
}
12811302

12821303
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());
12841305

12851306
// Case 1: builtin macros
12861307
if mac.is_builtin {
@@ -1299,7 +1320,7 @@ impl ModCollector<'_, '_> {
12991320
// Case 2: normal `macro_rules!` macro
13001321
let macro_id = MacroDefId {
13011322
ast_id: Some(ast_id),
1302-
krate: Some(self.def_collector.def_map.krate),
1323+
krate: self.def_collector.def_map.krate,
13031324
kind: MacroDefKind::Declarative,
13041325
local_inner: mac.is_local_inner,
13051326
};

crates/hir_def/src/nameres/tests/macros.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -633,14 +633,43 @@ pub struct bar;
633633
fn expand_derive() {
634634
let map = compute_crate_def_map(
635635
"
636-
//- /main.rs
636+
//- /main.rs crate:main deps:core
637+
use core::*;
638+
637639
#[derive(Copy, Clone)]
638640
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 {}
639648
",
640649
);
641650
assert_eq!(map.modules[map.root].scope.impls().len(), 2);
642651
}
643652

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+
644673
#[test]
645674
fn macro_expansion_overflow() {
646675
mark::check!(macro_expansion_overflow);

0 commit comments

Comments
 (0)