Skip to content

Commit 05cccdc

Browse files
committed
Auto merge of #88019 - inquisitivecrystal:macro-def, r=cjgillot
Treat macros as HIR items Macros have historically been treated differently from other items at the HIR level. This PR makes them just like normal items. There are a few special cases left over, which I've attempted to lay out below. By normalizing the treatment of macro items, this PR simplifies a fair bit of code and fixes some bugs at the same time. For more information, see #87406. r? `@cjgillot` ## Backwards incompatibility This is backwards incompatible in one small way. Due to a mistake, it was previously possible to apply stability attributes to an exported macro, even without enabling the `staged_api` feature. This never should have worked. After this PR, it will error, as it should. We could make it a warning instead, but that would require a special case for a feature that shouldn't ever have worked and is likely used by no or very few crates, so I'm not thrilled about the idea. ## Notes for reviewers ### Commit seperation I'd recommend reviewing this PR commit by commit. The commit chunking wasn't perfect, but it's better than looking at the combined diff, which is quite overwhelming. The compiler and standard library build after each commit, although tests do not necessarily pass and tools do not necessarily build till the end of the series. ### Special cases There are a few special cases that remain after this change. Here are the notable ones I remember: 1. Visibility works a bit differently for `macro_rules!` macros than other items, since they aren't generally marked with `pub` but instead with `#[macro_export]`. 2. Since `#[macro_export]` macros always have paths at the top level of the crate, some additional handling needs to be done on the reexport to top level. ### Performance impact I don't know for sure, but theses changes may slightly hurt performance. They create more work for the compiler in a few places. For instance, some operations that were previously run only for exported macros are now run for all macros. A perf run is probably advisable. For all I know we'll see performance improvements instead. :) ## Issues resolved This resolves #87406 (the tracking issue for this change). It also fixes several bugs: Fixes #59306. Fixes #73754. Fixes #87257.
2 parents 2031fd6 + b5a4141 commit 05cccdc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+338
-396
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -4146,6 +4146,7 @@ dependencies = [
41464146
name = "rustc_privacy"
41474147
version = "0.0.0"
41484148
dependencies = [
4149+
"rustc_ast",
41494150
"rustc_attr",
41504151
"rustc_data_structures",
41514152
"rustc_errors",

compiler/rustc_ast_lowering/src/item.rs

+6-24
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
170170
self.lower_item_id_use_tree(use_tree, i.id, &mut vec);
171171
vec
172172
}
173-
ItemKind::MacroDef(..) => SmallVec::new(),
174173
ItemKind::Fn(..) | ItemKind::Impl(box ImplKind { of_trait: None, .. }) => {
175174
smallvec![i.id]
176175
}
@@ -212,28 +211,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
212211
pub fn lower_item(&mut self, i: &Item) -> Option<hir::Item<'hir>> {
213212
let mut ident = i.ident;
214213
let mut vis = self.lower_visibility(&i.vis, None);
215-
216-
if let ItemKind::MacroDef(MacroDef { ref body, macro_rules }) = i.kind {
217-
if !macro_rules || self.sess.contains_name(&i.attrs, sym::macro_export) {
218-
let hir_id = self.lower_node_id(i.id);
219-
self.lower_attrs(hir_id, &i.attrs);
220-
let body = P(self.lower_mac_args(body));
221-
self.insert_macro_def(hir::MacroDef {
222-
ident,
223-
vis,
224-
def_id: hir_id.expect_owner(),
225-
span: i.span,
226-
ast: MacroDef { body, macro_rules },
227-
});
228-
} else {
229-
for a in i.attrs.iter() {
230-
let a = self.lower_attr(a);
231-
self.non_exported_macro_attrs.push(a);
232-
}
233-
}
234-
return None;
235-
}
236-
237214
let hir_id = self.lower_node_id(i.id);
238215
let attrs = self.lower_attrs(hir_id, &i.attrs);
239216
let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, &mut vis, &i.kind);
@@ -465,7 +442,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
465442
self.lower_generics(generics, ImplTraitContext::disallowed()),
466443
self.lower_param_bounds(bounds, ImplTraitContext::disallowed()),
467444
),
468-
ItemKind::MacroDef(..) | ItemKind::MacCall(..) => {
445+
ItemKind::MacroDef(MacroDef { ref body, macro_rules }) => {
446+
let body = P(self.lower_mac_args(body));
447+
448+
hir::ItemKind::Macro(ast::MacroDef { body, macro_rules })
449+
}
450+
ItemKind::MacCall(..) => {
469451
panic!("`TyMac` should have been expanded by now")
470452
}
471453
}

compiler/rustc_ast_lowering/src/lib.rs

-10
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@ struct LoweringContext<'a, 'hir: 'a> {
103103
/// The items being lowered are collected here.
104104
owners: IndexVec<LocalDefId, Option<hir::OwnerNode<'hir>>>,
105105
bodies: BTreeMap<hir::BodyId, hir::Body<'hir>>,
106-
non_exported_macro_attrs: Vec<ast::Attribute>,
107106

108107
trait_impls: BTreeMap<DefId, Vec<LocalDefId>>,
109108

@@ -330,7 +329,6 @@ pub fn lower_crate<'a, 'hir>(
330329
trait_impls: BTreeMap::new(),
331330
modules: BTreeMap::new(),
332331
attrs: BTreeMap::default(),
333-
non_exported_macro_attrs: Vec::new(),
334332
catch_scopes: Vec::new(),
335333
loop_scopes: Vec::new(),
336334
is_in_loop_condition: false,
@@ -551,7 +549,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
551549
}
552550

553551
let krate = hir::Crate {
554-
non_exported_macro_attrs: self.arena.alloc_from_iter(self.non_exported_macro_attrs),
555552
owners: self.owners,
556553
bodies: self.bodies,
557554
body_ids,
@@ -600,13 +597,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
600597
id
601598
}
602599

603-
fn insert_macro_def(&mut self, item: hir::MacroDef<'hir>) {
604-
let def_id = item.def_id;
605-
let item = self.arena.alloc(item);
606-
self.owners.ensure_contains_elem(def_id, || None);
607-
self.owners[def_id] = Some(hir::OwnerNode::MacroDef(item));
608-
}
609-
610600
fn allocate_hir_id_counter(&mut self, owner: NodeId) -> hir::HirId {
611601
// Set up the counter if needed.
612602
self.item_local_id_counters.entry(owner).or_insert(0);

compiler/rustc_ast_pretty/src/pprust/state.rs

+30-18
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,33 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
578578
}
579579
}
580580

581+
fn print_mac_def(
582+
&mut self,
583+
macro_def: &ast::MacroDef,
584+
ident: &Ident,
585+
sp: &Span,
586+
print_visibility: impl FnOnce(&mut Self),
587+
) {
588+
let (kw, has_bang) = if macro_def.macro_rules {
589+
("macro_rules", true)
590+
} else {
591+
print_visibility(self);
592+
("macro", false)
593+
};
594+
self.print_mac_common(
595+
Some(MacHeader::Keyword(kw)),
596+
has_bang,
597+
Some(*ident),
598+
macro_def.body.delim(),
599+
&macro_def.body.inner_tokens(),
600+
true,
601+
*sp,
602+
);
603+
if macro_def.body.need_semicolon() {
604+
self.word(";");
605+
}
606+
}
607+
581608
fn print_path(&mut self, path: &ast::Path, colons_before_params: bool, depth: usize) {
582609
self.maybe_print_comment(path.span.lo());
583610

@@ -1305,24 +1332,9 @@ impl<'a> State<'a> {
13051332
}
13061333
}
13071334
ast::ItemKind::MacroDef(ref macro_def) => {
1308-
let (kw, has_bang) = if macro_def.macro_rules {
1309-
("macro_rules", true)
1310-
} else {
1311-
self.print_visibility(&item.vis);
1312-
("macro", false)
1313-
};
1314-
self.print_mac_common(
1315-
Some(MacHeader::Keyword(kw)),
1316-
has_bang,
1317-
Some(item.ident),
1318-
macro_def.body.delim(),
1319-
&macro_def.body.inner_tokens(),
1320-
true,
1321-
item.span,
1322-
);
1323-
if macro_def.body.need_semicolon() {
1324-
self.word(";");
1325-
}
1335+
self.print_mac_def(macro_def, &item.ident, &item.span, |state| {
1336+
state.print_visibility(&item.vis)
1337+
});
13261338
}
13271339
}
13281340
self.ann.post(self, AnnNode::Item(item))

compiler/rustc_hir/src/arena.rs

-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ macro_rules! arena_types {
3535
[few] inline_asm: rustc_hir::InlineAsm<$tcx>,
3636
[few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>,
3737
[] local: rustc_hir::Local<$tcx>,
38-
[few] macro_def: rustc_hir::MacroDef<$tcx>,
3938
[few] mod_: rustc_hir::Mod<$tcx>,
4039
[] param: rustc_hir::Param<$tcx>,
4140
[] pat: rustc_hir::Pat<$tcx>,

compiler/rustc_hir/src/hir.rs

+9-57
Original file line numberDiff line numberDiff line change
@@ -670,9 +670,6 @@ pub struct ModuleItems {
670670
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
671671
#[derive(Debug)]
672672
pub struct Crate<'hir> {
673-
// Attributes from non-exported macros, kept only for collecting the library feature list.
674-
pub non_exported_macro_attrs: &'hir [Attribute],
675-
676673
pub owners: IndexVec<LocalDefId, Option<OwnerNode<'hir>>>,
677674
pub bodies: BTreeMap<BodyId, Body<'hir>>,
678675
pub trait_impls: BTreeMap<DefId, Vec<LocalDefId>>,
@@ -743,7 +740,7 @@ impl Crate<'_> {
743740
OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item),
744741
OwnerNode::ImplItem(item) => visitor.visit_impl_item(item),
745742
OwnerNode::TraitItem(item) => visitor.visit_trait_item(item),
746-
OwnerNode::MacroDef(_) | OwnerNode::Crate(_) => {}
743+
OwnerNode::Crate(_) => {}
747744
}
748745
}
749746
}
@@ -758,7 +755,7 @@ impl Crate<'_> {
758755
Some(OwnerNode::ForeignItem(item)) => visitor.visit_foreign_item(item),
759756
Some(OwnerNode::ImplItem(item)) => visitor.visit_impl_item(item),
760757
Some(OwnerNode::TraitItem(item)) => visitor.visit_trait_item(item),
761-
Some(OwnerNode::MacroDef(_)) | Some(OwnerNode::Crate(_)) | None => {}
758+
Some(OwnerNode::Crate(_)) | None => {}
762759
})
763760
}
764761

@@ -768,32 +765,6 @@ impl Crate<'_> {
768765
_ => None,
769766
})
770767
}
771-
772-
pub fn exported_macros<'hir>(&'hir self) -> impl Iterator<Item = &'hir MacroDef<'hir>> + 'hir {
773-
self.owners.iter().filter_map(|owner| match owner {
774-
Some(OwnerNode::MacroDef(macro_def)) => Some(*macro_def),
775-
_ => None,
776-
})
777-
}
778-
}
779-
780-
/// A macro definition, in this crate or imported from another.
781-
///
782-
/// Not parsed directly, but created on macro import or `macro_rules!` expansion.
783-
#[derive(Debug)]
784-
pub struct MacroDef<'hir> {
785-
pub ident: Ident,
786-
pub vis: Visibility<'hir>,
787-
pub def_id: LocalDefId,
788-
pub span: Span,
789-
pub ast: ast::MacroDef,
790-
}
791-
792-
impl MacroDef<'_> {
793-
#[inline]
794-
pub fn hir_id(&self) -> HirId {
795-
HirId::make_owner(self.def_id)
796-
}
797768
}
798769

799770
/// A block of statements `{ .. }`, which may have a label (in this case the
@@ -2602,7 +2573,7 @@ pub struct PolyTraitRef<'hir> {
26022573

26032574
pub type Visibility<'hir> = Spanned<VisibilityKind<'hir>>;
26042575

2605-
#[derive(Debug)]
2576+
#[derive(Copy, Clone, Debug)]
26062577
pub enum VisibilityKind<'hir> {
26072578
Public,
26082579
Crate(CrateSugar),
@@ -2791,6 +2762,8 @@ pub enum ItemKind<'hir> {
27912762
Const(&'hir Ty<'hir>, BodyId),
27922763
/// A function declaration.
27932764
Fn(FnSig<'hir>, Generics<'hir>, BodyId),
2765+
/// A MBE macro definition (`macro_rules!` or `macro`).
2766+
Macro(ast::MacroDef),
27942767
/// A module.
27952768
Mod(Mod<'hir>),
27962769
/// An external module, e.g. `extern { .. }`.
@@ -2856,6 +2829,7 @@ impl ItemKind<'_> {
28562829
ItemKind::Static(..) => "static item",
28572830
ItemKind::Const(..) => "constant item",
28582831
ItemKind::Fn(..) => "function",
2832+
ItemKind::Macro(..) => "macro",
28592833
ItemKind::Mod(..) => "module",
28602834
ItemKind::ForeignMod { .. } => "extern block",
28612835
ItemKind::GlobalAsm(..) => "global asm item",
@@ -2996,7 +2970,6 @@ pub enum OwnerNode<'hir> {
29962970
ForeignItem(&'hir ForeignItem<'hir>),
29972971
TraitItem(&'hir TraitItem<'hir>),
29982972
ImplItem(&'hir ImplItem<'hir>),
2999-
MacroDef(&'hir MacroDef<'hir>),
30002973
Crate(&'hir Mod<'hir>),
30012974
}
30022975

@@ -3006,8 +2979,7 @@ impl<'hir> OwnerNode<'hir> {
30062979
OwnerNode::Item(Item { ident, .. })
30072980
| OwnerNode::ForeignItem(ForeignItem { ident, .. })
30082981
| OwnerNode::ImplItem(ImplItem { ident, .. })
3009-
| OwnerNode::TraitItem(TraitItem { ident, .. })
3010-
| OwnerNode::MacroDef(MacroDef { ident, .. }) => Some(*ident),
2982+
| OwnerNode::TraitItem(TraitItem { ident, .. }) => Some(*ident),
30112983
OwnerNode::Crate(..) => None,
30122984
}
30132985
}
@@ -3018,7 +2990,6 @@ impl<'hir> OwnerNode<'hir> {
30182990
| OwnerNode::ForeignItem(ForeignItem { span, .. })
30192991
| OwnerNode::ImplItem(ImplItem { span, .. })
30202992
| OwnerNode::TraitItem(TraitItem { span, .. })
3021-
| OwnerNode::MacroDef(MacroDef { span, .. })
30222993
| OwnerNode::Crate(Mod { inner: span, .. }) => *span,
30232994
}
30242995
}
@@ -3062,8 +3033,7 @@ impl<'hir> OwnerNode<'hir> {
30623033
OwnerNode::Item(Item { def_id, .. })
30633034
| OwnerNode::TraitItem(TraitItem { def_id, .. })
30643035
| OwnerNode::ImplItem(ImplItem { def_id, .. })
3065-
| OwnerNode::ForeignItem(ForeignItem { def_id, .. })
3066-
| OwnerNode::MacroDef(MacroDef { def_id, .. }) => *def_id,
3036+
| OwnerNode::ForeignItem(ForeignItem { def_id, .. }) => *def_id,
30673037
OwnerNode::Crate(..) => crate::CRATE_HIR_ID.owner,
30683038
}
30693039
}
@@ -3095,13 +3065,6 @@ impl<'hir> OwnerNode<'hir> {
30953065
_ => panic!(),
30963066
}
30973067
}
3098-
3099-
pub fn expect_macro_def(self) -> &'hir MacroDef<'hir> {
3100-
match self {
3101-
OwnerNode::MacroDef(n) => n,
3102-
_ => panic!(),
3103-
}
3104-
}
31053068
}
31063069

31073070
impl<'hir> Into<OwnerNode<'hir>> for &'hir Item<'hir> {
@@ -3128,20 +3091,13 @@ impl<'hir> Into<OwnerNode<'hir>> for &'hir TraitItem<'hir> {
31283091
}
31293092
}
31303093

3131-
impl<'hir> Into<OwnerNode<'hir>> for &'hir MacroDef<'hir> {
3132-
fn into(self) -> OwnerNode<'hir> {
3133-
OwnerNode::MacroDef(self)
3134-
}
3135-
}
3136-
31373094
impl<'hir> Into<Node<'hir>> for OwnerNode<'hir> {
31383095
fn into(self) -> Node<'hir> {
31393096
match self {
31403097
OwnerNode::Item(n) => Node::Item(n),
31413098
OwnerNode::ForeignItem(n) => Node::ForeignItem(n),
31423099
OwnerNode::ImplItem(n) => Node::ImplItem(n),
31433100
OwnerNode::TraitItem(n) => Node::TraitItem(n),
3144-
OwnerNode::MacroDef(n) => Node::MacroDef(n),
31453101
OwnerNode::Crate(n) => Node::Crate(n),
31463102
}
31473103
}
@@ -3167,7 +3123,6 @@ pub enum Node<'hir> {
31673123
Arm(&'hir Arm<'hir>),
31683124
Block(&'hir Block<'hir>),
31693125
Local(&'hir Local<'hir>),
3170-
MacroDef(&'hir MacroDef<'hir>),
31713126

31723127
/// `Ctor` refers to the constructor of an enum variant or struct. Only tuple or unit variants
31733128
/// with synthesized constructors.
@@ -3204,7 +3159,6 @@ impl<'hir> Node<'hir> {
32043159
| Node::ForeignItem(ForeignItem { ident, .. })
32053160
| Node::Field(FieldDef { ident, .. })
32063161
| Node::Variant(Variant { ident, .. })
3207-
| Node::MacroDef(MacroDef { ident, .. })
32083162
| Node::Item(Item { ident, .. })
32093163
| Node::PathSegment(PathSegment { ident, .. }) => Some(*ident),
32103164
Node::Lifetime(lt) => Some(lt.name.ident()),
@@ -3265,8 +3219,7 @@ impl<'hir> Node<'hir> {
32653219
Node::Item(Item { def_id, .. })
32663220
| Node::TraitItem(TraitItem { def_id, .. })
32673221
| Node::ImplItem(ImplItem { def_id, .. })
3268-
| Node::ForeignItem(ForeignItem { def_id, .. })
3269-
| Node::MacroDef(MacroDef { def_id, .. }) => Some(HirId::make_owner(*def_id)),
3222+
| Node::ForeignItem(ForeignItem { def_id, .. }) => Some(HirId::make_owner(*def_id)),
32703223
Node::Field(FieldDef { hir_id, .. })
32713224
| Node::AnonConst(AnonConst { hir_id, .. })
32723225
| Node::Expr(Expr { hir_id, .. })
@@ -3326,7 +3279,6 @@ impl<'hir> Node<'hir> {
33263279
Node::ForeignItem(i) => Some(OwnerNode::ForeignItem(i)),
33273280
Node::TraitItem(i) => Some(OwnerNode::TraitItem(i)),
33283281
Node::ImplItem(i) => Some(OwnerNode::ImplItem(i)),
3329-
Node::MacroDef(i) => Some(OwnerNode::MacroDef(i)),
33303282
Node::Crate(i) => Some(OwnerNode::Crate(i)),
33313283
_ => None,
33323284
}

compiler/rustc_hir/src/intravisit.rs

+3-9
Original file line numberDiff line numberDiff line change
@@ -466,9 +466,6 @@ pub trait Visitor<'v>: Sized {
466466
walk_assoc_type_binding(self, type_binding)
467467
}
468468
fn visit_attribute(&mut self, _id: HirId, _attr: &'v Attribute) {}
469-
fn visit_macro_def(&mut self, macro_def: &'v MacroDef<'v>) {
470-
walk_macro_def(self, macro_def)
471-
}
472469
fn visit_vis(&mut self, vis: &'v Visibility<'v>) {
473470
walk_vis(self, vis)
474471
}
@@ -484,19 +481,13 @@ pub trait Visitor<'v>: Sized {
484481
pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate<'v>) {
485482
let top_mod = krate.module();
486483
visitor.visit_mod(top_mod, top_mod.inner, CRATE_HIR_ID);
487-
walk_list!(visitor, visit_macro_def, krate.exported_macros());
488484
for (&id, attrs) in krate.attrs.iter() {
489485
for a in *attrs {
490486
visitor.visit_attribute(id, a)
491487
}
492488
}
493489
}
494490

495-
pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef<'v>) {
496-
visitor.visit_id(macro_def.hir_id());
497-
visitor.visit_ident(macro_def.ident);
498-
}
499-
500491
pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod<'v>, mod_hir_id: HirId) {
501492
visitor.visit_id(mod_hir_id);
502493
for &item_id in module.item_ids {
@@ -586,6 +577,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
586577
item.span,
587578
item.hir_id(),
588579
),
580+
ItemKind::Macro(_) => {
581+
visitor.visit_id(item.hir_id());
582+
}
589583
ItemKind::Mod(ref module) => {
590584
// `visit_mod()` takes care of visiting the `Item`'s `HirId`.
591585
visitor.visit_mod(module, item.span, item.hir_id())

0 commit comments

Comments
 (0)