From 8c62fa057527fc07afabb201bb31428409ef4d8a Mon Sep 17 00:00:00 2001 From: inquisitivecrystal <22333129+inquisitivecrystal@users.noreply.github.com> Date: Fri, 30 Jul 2021 23:50:57 -0700 Subject: [PATCH] Treat macros as HIR items --- Cargo.lock | 1 + compiler/rustc_ast_lowering/src/item.rs | 30 +---- compiler/rustc_ast_lowering/src/lib.rs | 10 -- compiler/rustc_ast_pretty/src/pprust/state.rs | 48 +++++--- compiler/rustc_hir/src/arena.rs | 1 - compiler/rustc_hir/src/hir.rs | 34 +----- compiler/rustc_hir/src/intravisit.rs | 12 +- compiler/rustc_hir/src/stable_hash_impls.rs | 17 +-- compiler/rustc_hir/src/target.rs | 1 + compiler/rustc_hir_pretty/src/lib.rs | 5 + compiler/rustc_lint/src/builtin.rs | 19 +-- compiler/rustc_lint/src/late.rs | 4 - compiler/rustc_lint/src/levels.rs | 3 - compiler/rustc_metadata/src/rmeta/decoder.rs | 8 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 17 +-- .../rustc_middle/src/hir/map/collector.rs | 14 --- compiler/rustc_middle/src/hir/map/mod.rs | 13 +- .../rustc_mir/src/monomorphize/collector.rs | 1 + compiler/rustc_passes/src/check_attr.rs | 21 ++-- compiler/rustc_passes/src/diagnostic_items.rs | 4 - compiler/rustc_passes/src/hir_stats.rs | 5 - compiler/rustc_passes/src/lib_features.rs | 4 +- compiler/rustc_passes/src/reachable.rs | 1 + compiler/rustc_passes/src/stability.rs | 18 --- compiler/rustc_privacy/Cargo.toml | 1 + compiler/rustc_privacy/src/lib.rs | 114 ++++++++++-------- compiler/rustc_resolve/src/late/lifetimes.rs | 1 + compiler/rustc_save_analysis/src/sig.rs | 8 ++ compiler/rustc_typeck/src/collect.rs | 1 + compiler/rustc_typeck/src/collect/type_of.rs | 1 + .../clippy/clippy_lints/src/missing_doc.rs | 1 + 31 files changed, 162 insertions(+), 256 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cef4f11da801d..af23324cbefdb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4146,6 +4146,7 @@ dependencies = [ name = "rustc_privacy" version = "0.0.0" dependencies = [ + "rustc_ast", "rustc_attr", "rustc_data_structures", "rustc_errors", diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 3acf69ec2b7d0..cc87078d54b3f 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -170,7 +170,6 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_item_id_use_tree(use_tree, i.id, &mut vec); vec } - ItemKind::MacroDef(..) => SmallVec::new(), ItemKind::Fn(..) | ItemKind::Impl(box ImplKind { of_trait: None, .. }) => { smallvec![i.id] } @@ -212,28 +211,6 @@ impl<'hir> LoweringContext<'_, 'hir> { pub fn lower_item(&mut self, i: &Item) -> Option> { let mut ident = i.ident; let mut vis = self.lower_visibility(&i.vis, None); - - if let ItemKind::MacroDef(MacroDef { ref body, macro_rules }) = i.kind { - if !macro_rules || self.sess.contains_name(&i.attrs, sym::macro_export) { - let hir_id = self.lower_node_id(i.id); - self.lower_attrs(hir_id, &i.attrs); - let body = P(self.lower_mac_args(body)); - self.insert_macro_def(hir::MacroDef { - ident, - vis, - def_id: hir_id.expect_owner(), - span: i.span, - ast: MacroDef { body, macro_rules }, - }); - } else { - for a in i.attrs.iter() { - let a = self.lower_attr(a); - self.non_exported_macro_attrs.push(a); - } - } - return None; - } - let hir_id = self.lower_node_id(i.id); let attrs = self.lower_attrs(hir_id, &i.attrs); 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> { self.lower_generics(generics, ImplTraitContext::disallowed()), self.lower_param_bounds(bounds, ImplTraitContext::disallowed()), ), - ItemKind::MacroDef(..) | ItemKind::MacCall(..) => { + ItemKind::MacroDef(MacroDef { ref body, macro_rules }) => { + let body = P(self.lower_mac_args(body)); + + hir::ItemKind::Macro(ast::MacroDef { body, macro_rules }) + } + ItemKind::MacCall(..) => { panic!("`TyMac` should have been expanded by now") } } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 948d74e3bf8eb..bd2c9f41a5378 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -103,7 +103,6 @@ struct LoweringContext<'a, 'hir: 'a> { /// The items being lowered are collected here. owners: IndexVec>>, bodies: BTreeMap>, - non_exported_macro_attrs: Vec, trait_impls: BTreeMap>, @@ -330,7 +329,6 @@ pub fn lower_crate<'a, 'hir>( trait_impls: BTreeMap::new(), modules: BTreeMap::new(), attrs: BTreeMap::default(), - non_exported_macro_attrs: Vec::new(), catch_scopes: Vec::new(), loop_scopes: Vec::new(), is_in_loop_condition: false, @@ -551,7 +549,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } let krate = hir::Crate { - non_exported_macro_attrs: self.arena.alloc_from_iter(self.non_exported_macro_attrs), owners: self.owners, bodies: self.bodies, body_ids, @@ -600,13 +597,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { id } - fn insert_macro_def(&mut self, item: hir::MacroDef<'hir>) { - let def_id = item.def_id; - let item = self.arena.alloc(item); - self.owners.ensure_contains_elem(def_id, || None); - self.owners[def_id] = Some(hir::OwnerNode::MacroDef(item)); - } - fn allocate_hir_id_counter(&mut self, owner: NodeId) -> hir::HirId { // Set up the counter if needed. self.item_local_id_counters.entry(owner).or_insert(0); diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index b09c668273aa8..f729973ddc62e 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -578,6 +578,33 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere } } + fn print_mac_def( + &mut self, + macro_def: &ast::MacroDef, + ident: &Ident, + sp: &Span, + print_visibility: impl FnOnce(&mut Self), + ) { + let (kw, has_bang) = if macro_def.macro_rules { + ("macro_rules", true) + } else { + print_visibility(self); + ("macro", false) + }; + self.print_mac_common( + Some(MacHeader::Keyword(kw)), + has_bang, + Some(*ident), + macro_def.body.delim(), + ¯o_def.body.inner_tokens(), + true, + *sp, + ); + if macro_def.body.need_semicolon() { + self.word(";"); + } + } + fn print_path(&mut self, path: &ast::Path, colons_before_params: bool, depth: usize) { self.maybe_print_comment(path.span.lo()); @@ -1305,24 +1332,9 @@ impl<'a> State<'a> { } } ast::ItemKind::MacroDef(ref macro_def) => { - let (kw, has_bang) = if macro_def.macro_rules { - ("macro_rules", true) - } else { - self.print_visibility(&item.vis); - ("macro", false) - }; - self.print_mac_common( - Some(MacHeader::Keyword(kw)), - has_bang, - Some(item.ident), - macro_def.body.delim(), - ¯o_def.body.inner_tokens(), - true, - item.span, - ); - if macro_def.body.need_semicolon() { - self.word(";"); - } + self.print_mac_def(macro_def, &item.ident, &item.span, |state| { + state.print_visibility(&item.vis) + }); } } self.ann.post(self, AnnNode::Item(item)) diff --git a/compiler/rustc_hir/src/arena.rs b/compiler/rustc_hir/src/arena.rs index c4cff79f6c525..0801a1bde2264 100644 --- a/compiler/rustc_hir/src/arena.rs +++ b/compiler/rustc_hir/src/arena.rs @@ -35,7 +35,6 @@ macro_rules! arena_types { [few] inline_asm: rustc_hir::InlineAsm<$tcx>, [few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>, [] local: rustc_hir::Local<$tcx>, - [few] macro_def: rustc_hir::MacroDef<$tcx>, [few] mod_: rustc_hir::Mod<$tcx>, [] param: rustc_hir::Param<$tcx>, [] pat: rustc_hir::Pat<$tcx>, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 551e6a57b32bf..a166337c0dfc3 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -670,9 +670,6 @@ pub struct ModuleItems { /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html #[derive(Debug)] pub struct Crate<'hir> { - // Attributes from non-exported macros, kept only for collecting the library feature list. - pub non_exported_macro_attrs: &'hir [Attribute], - pub owners: IndexVec>>, pub bodies: BTreeMap>, pub trait_impls: BTreeMap>, @@ -768,32 +765,6 @@ impl Crate<'_> { _ => None, }) } - - pub fn exported_macros<'hir>(&'hir self) -> impl Iterator> + 'hir { - self.owners.iter().filter_map(|owner| match owner { - Some(OwnerNode::MacroDef(macro_def)) => Some(*macro_def), - _ => None, - }) - } -} - -/// A macro definition, in this crate or imported from another. -/// -/// Not parsed directly, but created on macro import or `macro_rules!` expansion. -#[derive(Debug)] -pub struct MacroDef<'hir> { - pub ident: Ident, - pub vis: Visibility<'hir>, - pub def_id: LocalDefId, - pub span: Span, - pub ast: ast::MacroDef, -} - -impl MacroDef<'_> { - #[inline] - pub fn hir_id(&self) -> HirId { - HirId::make_owner(self.def_id) - } } /// A block of statements `{ .. }`, which may have a label (in this case the @@ -2602,7 +2573,7 @@ pub struct PolyTraitRef<'hir> { pub type Visibility<'hir> = Spanned>; -#[derive(Debug)] +#[derive(Copy, Clone, Debug)] pub enum VisibilityKind<'hir> { Public, Crate(CrateSugar), @@ -2791,6 +2762,8 @@ pub enum ItemKind<'hir> { Const(&'hir Ty<'hir>, BodyId), /// A function declaration. Fn(FnSig<'hir>, Generics<'hir>, BodyId), + /// A MBE macro definition (`macro_rules!` or `macro`). + Macro(ast::MacroDef), /// A module. Mod(Mod<'hir>), /// An external module, e.g. `extern { .. }`. @@ -2856,6 +2829,7 @@ impl ItemKind<'_> { ItemKind::Static(..) => "static item", ItemKind::Const(..) => "constant item", ItemKind::Fn(..) => "function", + ItemKind::Macro(..) => "macro", ItemKind::Mod(..) => "module", ItemKind::ForeignMod { .. } => "extern block", ItemKind::GlobalAsm(..) => "global asm item", diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 7f153867596ec..f4fbfd2692ca5 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -466,9 +466,6 @@ pub trait Visitor<'v>: Sized { walk_assoc_type_binding(self, type_binding) } fn visit_attribute(&mut self, _id: HirId, _attr: &'v Attribute) {} - fn visit_macro_def(&mut self, macro_def: &'v MacroDef<'v>) { - walk_macro_def(self, macro_def) - } fn visit_vis(&mut self, vis: &'v Visibility<'v>) { walk_vis(self, vis) } @@ -484,7 +481,6 @@ pub trait Visitor<'v>: Sized { pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate<'v>) { let top_mod = krate.module(); visitor.visit_mod(top_mod, top_mod.inner, CRATE_HIR_ID); - walk_list!(visitor, visit_macro_def, krate.exported_macros()); for (&id, attrs) in krate.attrs.iter() { for a in *attrs { visitor.visit_attribute(id, a) @@ -492,11 +488,6 @@ pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate<'v>) { } } -pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef<'v>) { - visitor.visit_id(macro_def.hir_id()); - visitor.visit_ident(macro_def.ident); -} - pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod<'v>, mod_hir_id: HirId) { visitor.visit_id(mod_hir_id); 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>) { item.span, item.hir_id(), ), + ItemKind::Macro(_) => { + visitor.visit_id(item.hir_id()); + } ItemKind::Mod(ref module) => { // `visit_mod()` takes care of visiting the `Item`'s `HirId`. visitor.visit_mod(module, item.span, item.hir_id()) diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs index 560607528330b..422a1064874c5 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -1,8 +1,8 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; use crate::hir::{ - BodyId, Expr, ForeignItem, ForeignItemId, ImplItem, ImplItemId, Item, ItemId, MacroDef, Mod, - TraitItem, TraitItemId, Ty, VisibilityKind, + BodyId, Expr, ForeignItem, ForeignItemId, ImplItem, ImplItemId, Item, ItemId, Mod, TraitItem, + TraitItemId, Ty, VisibilityKind, }; use crate::hir_id::{HirId, ItemLocalId}; use rustc_span::def_id::DefPathHash; @@ -190,16 +190,3 @@ impl HashStable for Item<'_> { }); } } - -impl HashStable for MacroDef<'_> { - fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { - let MacroDef { ident, def_id: _, ref ast, ref vis, span } = *self; - - hcx.hash_hir_item_like(|hcx| { - ident.name.hash_stable(hcx, hasher); - ast.hash_stable(hcx, hasher); - vis.hash_stable(hcx, hasher); - span.hash_stable(hcx, hasher); - }); - } -} diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs index 473477bf22da2..29c948fe31845 100644 --- a/compiler/rustc_hir/src/target.rs +++ b/compiler/rustc_hir/src/target.rs @@ -111,6 +111,7 @@ impl Target { ItemKind::Static(..) => Target::Static, ItemKind::Const(..) => Target::Const, ItemKind::Fn(..) => Target::Fn, + ItemKind::Macro(..) => Target::MacroDef, ItemKind::Mod(..) => Target::Mod, ItemKind::ForeignMod { .. } => Target::ForeignMod, ItemKind::GlobalAsm(..) => Target::GlobalAsm, diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 9c286ad5ccfe9..89e7f8c1de6b2 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -642,6 +642,11 @@ impl<'a> State<'a> { self.end(); // need to close a box self.ann.nested(self, Nested::Body(body)); } + hir::ItemKind::Macro(ref macro_def) => { + self.print_mac_def(macro_def, &item.ident, &item.span, |state| { + state.print_visibility(&item.vis) + }); + } hir::ItemKind::Mod(ref _mod) => { self.head(visibility_qualified(&item.vis, "mod")); self.print_ident(item.ident); diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 8f848f54aad63..a5b4fa15921b8 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -585,24 +585,6 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { fn check_crate(&mut self, cx: &LateContext<'_>, krate: &hir::Crate<'_>) { self.check_missing_docs_attrs(cx, CRATE_DEF_ID, krate.module().inner, "the", "crate"); - - for macro_def in krate.exported_macros() { - // Non exported macros should be skipped, since `missing_docs` only - // applies to externally visible items. - if !cx.access_levels.is_exported(macro_def.def_id) { - continue; - } - - let attrs = cx.tcx.hir().attrs(macro_def.hir_id()); - let has_doc = attrs.iter().any(has_doc); - if !has_doc { - cx.struct_span_lint( - MISSING_DOCS, - cx.tcx.sess.source_map().guess_head_span(macro_def.span), - |lint| lint.build("missing documentation for macro").emit(), - ); - } - } } fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { @@ -636,6 +618,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { hir::ItemKind::TyAlias(..) | hir::ItemKind::Fn(..) + | hir::ItemKind::Macro(..) | hir::ItemKind::Mod(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 052efa851f7cf..30400da86b4b0 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -453,10 +453,6 @@ fn late_lint_pass_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, pass: T) lint_callback!(cx, check_crate, krate); hir_visit::walk_crate(cx, krate); - for attr in krate.non_exported_macro_attrs { - // This HIR ID is a lie, since the macro ID isn't available. - cx.visit_attribute(hir::CRATE_HIR_ID, attr); - } lint_callback!(cx, check_crate_post, krate); }) diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index e6cbfa0c9e29d..90bf34ee863b8 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -37,9 +37,6 @@ fn lint_levels(tcx: TyCtxt<'_>, (): ()) -> LintLevelMap { let push = builder.levels.push(tcx.hir().attrs(hir::CRATE_HIR_ID), &store, true); builder.levels.register_id(hir::CRATE_HIR_ID); - for macro_def in krate.exported_macros() { - builder.levels.register_id(macro_def.hir_id()); - } intravisit::walk_crate(&mut builder, krate); builder.levels.pop(push); diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 4e591b28f6087..dd44e0cb1fa90 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1100,7 +1100,13 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { let vis = self.get_visibility(child_index); let def_id = self.local_def_id(child_index); let res = Res::Def(kind, def_id); - callback(Export { res, ident, vis, span }); + + // FIXME: Macros are currently encoded twice, once as items and once as + // reexports. We ignore the items here and only use the reexports. + if !matches!(kind, DefKind::Macro(..)) { + callback(Export { res, ident, vis, span }); + } + // For non-re-export structs and variants add their constructors to children. // Re-export lists automatically contain constructors when necessary. match kind { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 1c243f8bd5148..2cd4fe3b70621 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -448,9 +448,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } krate.visit_all_item_likes(&mut self.as_deep_visitor()); - for macro_def in krate.exported_macros() { - self.visit_macro_def(macro_def); - } } fn encode_def_path_table(&mut self) { @@ -1385,6 +1382,9 @@ impl EncodeContext<'a, 'tcx> { EntryKind::Fn(self.lazy(data)) } + hir::ItemKind::Macro(ref macro_def) => { + EntryKind::MacroDef(self.lazy(macro_def.clone())) + } hir::ItemKind::Mod(ref m) => { return self.encode_info_for_mod(item.def_id, m); } @@ -1539,13 +1539,6 @@ impl EncodeContext<'a, 'tcx> { } } - /// Serialize the text of exported macros - fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef<'_>) { - let def_id = macro_def.def_id.to_def_id(); - record!(self.tables.kind[def_id] <- EntryKind::MacroDef(self.lazy(macro_def.ast.clone()))); - self.encode_ident_span(def_id, macro_def.ident); - } - fn encode_info_for_generic_param(&mut self, def_id: DefId, kind: EntryKind, encode_type: bool) { record!(self.tables.kind[def_id] <- kind); if encode_type { @@ -1915,9 +1908,6 @@ impl Visitor<'tcx> for EncodeContext<'a, 'tcx> { intravisit::walk_generics(self, generics); self.encode_info_for_generics(generics); } - fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef<'tcx>) { - self.encode_info_for_macro_def(macro_def); - } } impl EncodeContext<'a, 'tcx> { @@ -1972,6 +1962,7 @@ impl EncodeContext<'a, 'tcx> { hir::ItemKind::Static(..) | hir::ItemKind::Const(..) | hir::ItemKind::Fn(..) + | hir::ItemKind::Macro(..) | hir::ItemKind::Mod(..) | hir::ItemKind::ForeignMod { .. } | hir::ItemKind::GlobalAsm(..) diff --git a/compiler/rustc_middle/src/hir/map/collector.rs b/compiler/rustc_middle/src/hir/map/collector.rs index 5c166c74004a3..1351b4950f143 100644 --- a/compiler/rustc_middle/src/hir/map/collector.rs +++ b/compiler/rustc_middle/src/hir/map/collector.rs @@ -394,20 +394,6 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } } - fn visit_macro_def(&mut self, macro_def: &'hir MacroDef<'hir>) { - // Exported macros are visited directly from the crate root, - // so they do not have `parent_node` set. - // Find the correct enclosing module from their DefKey. - let def_key = self.definitions.def_key(macro_def.def_id); - let parent = def_key.parent.map_or(hir::CRATE_HIR_ID, |local_def_index| { - self.definitions.local_def_id_to_hir_id(LocalDefId { local_def_index }) - }); - self.insert_owner(macro_def.def_id, OwnerNode::MacroDef(macro_def)); - self.with_parent(parent, |this| { - this.insert_nested(macro_def.def_id); - }); - } - fn visit_variant(&mut self, v: &'hir Variant<'hir>, g: &'hir Generics<'hir>, item_id: HirId) { self.insert(v.span, v.id, Node::Variant(v)); self.with_parent(v.id, |this| { diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index c313146b07222..82c2f32b82418 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -10,7 +10,6 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; use rustc_hir::intravisit; -use rustc_hir::intravisit::Visitor; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::*; use rustc_index::vec::Idx; @@ -218,6 +217,7 @@ impl<'hir> Map<'hir> { ItemKind::Static(..) => DefKind::Static, ItemKind::Const(..) => DefKind::Const, ItemKind::Fn(..) => DefKind::Fn, + ItemKind::Macro(..) => DefKind::Macro(MacroKind::Bang), ItemKind::Mod(..) => DefKind::Mod, ItemKind::OpaqueTy(..) => DefKind::OpaqueTy, ItemKind::TyAlias(..) => DefKind::TyAlias, @@ -543,15 +543,6 @@ impl<'hir> Map<'hir> { } } - pub fn visit_exported_macros_in_krate(&self, visitor: &mut V) - where - V: Visitor<'hir>, - { - for macro_def in self.krate().exported_macros() { - visitor.visit_macro_def(macro_def); - } - } - /// Returns an iterator for the nodes in the ancestor tree of the `current_id` /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`. pub fn parent_iter(&self, current_id: HirId) -> ParentHirIterator<'_, 'hir> { @@ -1013,7 +1004,6 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { source_file_names.hash_stable(&mut hcx, &mut stable_hasher); tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher); tcx.sess.local_stable_crate_id().hash_stable(&mut hcx, &mut stable_hasher); - tcx.untracked_crate.non_exported_macro_attrs.hash_stable(&mut hcx, &mut stable_hasher); let crate_hash: Fingerprint = stable_hasher.finish(); Svh::new(crate_hash.to_smaller_hash()) @@ -1062,6 +1052,7 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId) -> String { ItemKind::Static(..) => "static", ItemKind::Const(..) => "const", ItemKind::Fn(..) => "fn", + ItemKind::Macro(..) => "macro", ItemKind::Mod(..) => "mod", ItemKind::ForeignMod { .. } => "foreign mod", ItemKind::GlobalAsm(..) => "global asm", diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs index f03036267acfa..4cb362238c1c5 100644 --- a/compiler/rustc_mir/src/monomorphize/collector.rs +++ b/compiler/rustc_mir/src/monomorphize/collector.rs @@ -1149,6 +1149,7 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> { match item.kind { hir::ItemKind::ExternCrate(..) | hir::ItemKind::Use(..) + | hir::ItemKind::Macro(..) | hir::ItemKind::ForeignMod { .. } | hir::ItemKind::TyAlias(..) | hir::ItemKind::Trait(..) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index d0ddad1c1a334..d3dac35d2c9e5 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1723,6 +1723,16 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> { } fn visit_item(&mut self, item: &'tcx Item<'tcx>) { + // Historically we've run more checks on non-exported than exported macros, + // so this lets us continue to run them while maintaining backwards compatibility. + // In the long run, the checks should be harmonized. + if let ItemKind::Macro(ref macro_def) = item.kind { + let def_id = item.def_id.to_def_id(); + if macro_def.macro_rules && !self.tcx.has_attr(def_id, sym::macro_export) { + check_non_exported_macro_for_invalid_attrs(self.tcx, item); + } + } + let target = Target::from_item(item); self.check_attributes(item.hir_id(), &item.span, target, Some(ItemLike::Item(item))); intravisit::walk_item(self, item) @@ -1795,11 +1805,6 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> { intravisit::walk_variant(self, variant, generics, item_id) } - fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef<'tcx>) { - self.check_attributes(macro_def.hir_id(), ¯o_def.span, Target::MacroDef, None); - intravisit::walk_macro_def(self, macro_def); - } - fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { self.check_attributes(param.hir_id, ¶m.span, Target::Param, None); @@ -1848,7 +1853,9 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { } } -fn check_invalid_macro_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { +fn check_non_exported_macro_for_invalid_attrs(tcx: TyCtxt<'_>, item: &Item<'_>) { + let attrs = tcx.hir().attrs(item.hir_id()); + for attr in attrs { if attr.has_name(sym::inline) { struct_span_err!( @@ -1869,8 +1876,6 @@ fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { if module_def_id.is_top_level_module() { check_attr_visitor.check_attributes(CRATE_HIR_ID, &DUMMY_SP, Target::Mod, None); check_invalid_crate_level_attr(tcx, tcx.hir().krate_attrs()); - tcx.hir().visit_exported_macros_in_krate(check_attr_visitor); - check_invalid_macro_level_attr(tcx, tcx.hir().krate().non_exported_macro_attrs); } } diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs index e43abda713351..3f12a744be0e8 100644 --- a/compiler/rustc_passes/src/diagnostic_items.rs +++ b/compiler/rustc_passes/src/diagnostic_items.rs @@ -107,10 +107,6 @@ fn diagnostic_items<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> FxHashMap hir_visit::Visitor<'v> for StatCollector<'v> { fn visit_attribute(&mut self, _: hir::HirId, attr: &'v ast::Attribute) { self.record("Attribute", Id::Attr(attr.id), attr); } - - fn visit_macro_def(&mut self, macro_def: &'v hir::MacroDef<'v>) { - self.record("MacroDef", Id::Node(macro_def.hir_id()), macro_def); - hir_visit::walk_macro_def(self, macro_def) - } } impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs index 605b52f18913f..7d15ca1e8f798 100644 --- a/compiler/rustc_passes/src/lib_features.rs +++ b/compiler/rustc_passes/src/lib_features.rs @@ -127,9 +127,7 @@ impl Visitor<'tcx> for LibFeatureCollector<'tcx> { fn get_lib_features(tcx: TyCtxt<'_>, (): ()) -> LibFeatures { let mut collector = LibFeatureCollector::new(tcx); let krate = tcx.hir().krate(); - for attr in krate.non_exported_macro_attrs { - collector.visit_attribute(rustc_hir::CRATE_HIR_ID, attr); - } + intravisit::walk_crate(&mut collector, krate); collector.lib_features } diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 5ca098c22878b..7d22426609c14 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -263,6 +263,7 @@ impl<'tcx> ReachableContext<'tcx> { | hir::ItemKind::Use(..) | hir::ItemKind::OpaqueTy(..) | hir::ItemKind::TyAlias(..) + | hir::ItemKind::Macro(..) | hir::ItemKind::Mod(..) | hir::ItemKind::ForeignMod { .. } | hir::ItemKind::Impl { .. } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index b64dcb0bbf03b..a88393cea8285 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -538,19 +538,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { ); } - fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) { - self.annotate( - md.def_id, - md.span, - None, - AnnotationKind::Required, - InheritDeprecation::Yes, - InheritConstStability::No, - InheritStability::No, - |_| {}, - ); - } - fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) { let kind = match &p.kind { // Allow stability attributes on default generic arguments. @@ -662,11 +649,6 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { self.check_missing_stability(i.def_id, i.span); intravisit::walk_foreign_item(self, i); } - - fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) { - self.check_missing_stability(md.def_id, md.span); - } - // Note that we don't need to `check_missing_stability` for default generic parameters, // as we assume that any default generic parameters without attributes are automatically // stable (assuming they have not inherited instability from their parent). diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml index 85a53b1bde224..6ac2915c34526 100644 --- a/compiler/rustc_privacy/Cargo.toml +++ b/compiler/rustc_privacy/Cargo.toml @@ -5,6 +5,7 @@ edition = "2018" [dependencies] rustc_middle = { path = "../rustc_middle" } +rustc_ast = { path = "../rustc_ast" } rustc_attr = { path = "../rustc_attr" } rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 6fe68a0c17a5d..079a9ed878a7f 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -6,6 +6,7 @@ #![feature(associated_type_defaults)] #![recursion_limit = "256"] +use rustc_ast::MacroDef; use rustc_attr as attr; use rustc_data_structures::fx::FxHashSet; use rustc_errors::struct_span_err; @@ -26,7 +27,7 @@ use rustc_middle::ty::subst::{InternalSubsts, Subst}; use rustc_middle::ty::{self, Const, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeFoldable}; use rustc_session::lint; use rustc_span::hygiene::Transparency; -use rustc_span::symbol::{kw, Ident}; +use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Span; use rustc_trait_selection::traits::const_evaluatable::{self, AbstractConst}; @@ -462,6 +463,43 @@ impl EmbargoVisitor<'tcx> { } } + // We have to make sure that the items that macros might reference + // are reachable, since they might be exported transitively. + fn update_reachability_from_macro(&mut self, local_def_id: LocalDefId, md: &MacroDef) { + // Non-opaque macros cannot make other items more accessible than they already are. + + let hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id); + let attrs = self.tcx.hir().attrs(hir_id); + if attr::find_transparency(&attrs, md.macro_rules).0 != Transparency::Opaque { + return; + } + + let item_def_id = local_def_id.to_def_id(); + let macro_module_def_id = + ty::DefIdTree::parent(self.tcx, item_def_id).unwrap().expect_local(); + if self.tcx.hir().opt_def_kind(macro_module_def_id) != Some(DefKind::Mod) { + // The macro's parent doesn't correspond to a `mod`, return early (#63164, #65252). + return; + } + + if self.get(local_def_id).is_none() { + return; + } + + // Since we are starting from an externally visible module, + // all the parents in the loop below are also guaranteed to be modules. + let mut module_def_id = macro_module_def_id; + loop { + let changed_reachability = + self.update_macro_reachable(module_def_id, macro_module_def_id); + if changed_reachability || module_def_id == CRATE_DEF_ID { + break; + } + module_def_id = + ty::DefIdTree::parent(self.tcx, module_def_id.to_def_id()).unwrap().expect_local(); + } + } + /// Updates the item as being reachable through a macro defined in the given /// module. Returns `true` if the level has changed. fn update_macro_reachable( @@ -511,16 +549,26 @@ impl EmbargoVisitor<'tcx> { } match def_kind { // No type privacy, so can be directly marked as reachable. - DefKind::Const - | DefKind::Macro(_) - | DefKind::Static - | DefKind::TraitAlias - | DefKind::TyAlias => { + DefKind::Const | DefKind::Static | DefKind::TraitAlias | DefKind::TyAlias => { if vis.is_accessible_from(module.to_def_id(), self.tcx) { self.update(def_id, level); } } + // Hygine isn't really implemented for `macro_rules!` macros at the + // moment. Accordingly, marking them as reachable is unwise. `macro` macros + // have normal hygine, so we can treat them like other items without type + // privacy and mark them reachable. + DefKind::Macro(_) => { + let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); + let item = self.tcx.hir().expect_item(hir_id); + if let hir::ItemKind::Macro(MacroDef { macro_rules: false, .. }) = item.kind { + if vis.is_accessible_from(module.to_def_id(), self.tcx) { + self.update(def_id, level); + } + } + } + // We can't use a module name as the final segment of a path, except // in use statements. Since re-export checking doesn't consider // hygiene these don't need to be marked reachable. The contents of @@ -644,6 +692,12 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { hir::ItemKind::Impl { .. } => { Option::::of_impl(item.def_id, self.tcx, &self.access_levels) } + // Only exported `macro_rules!` items are public, but they always are. + hir::ItemKind::Macro(MacroDef { macro_rules: true, .. }) => { + let def_id = item.def_id.to_def_id(); + let is_macro_export = self.tcx.has_attr(def_id, sym::macro_export); + if is_macro_export { Some(AccessLevel::Public) } else { None } + } // Foreign modules inherit level from parents. hir::ItemKind::ForeignMod { .. } => self.prev_level, // Other `pub` items inherit levels from parents. @@ -652,6 +706,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { | hir::ItemKind::ExternCrate(..) | hir::ItemKind::GlobalAsm(..) | hir::ItemKind::Fn(..) + | hir::ItemKind::Macro(..) | hir::ItemKind::Mod(..) | hir::ItemKind::Static(..) | hir::ItemKind::Struct(..) @@ -708,6 +763,9 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { } } } + hir::ItemKind::Macro(ref macro_def) => { + self.update_reachability_from_macro(item.def_id, macro_def); + } hir::ItemKind::ForeignMod { items, .. } => { for foreign_item in items { if foreign_item.vis.node.is_pub() { @@ -715,6 +773,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { } } } + hir::ItemKind::OpaqueTy(..) | hir::ItemKind::Use(..) | hir::ItemKind::Static(..) @@ -730,7 +789,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { // Mark all items in interfaces of reachable items as reachable. match item.kind { // The interface is empty. - hir::ItemKind::ExternCrate(..) => {} + hir::ItemKind::Macro(..) | hir::ItemKind::ExternCrate(..) => {} // All nested items are checked by `visit_item`. hir::ItemKind::Mod(..) => {} // Re-exports are handled in `visit_mod`. However, in order to avoid looping over @@ -885,45 +944,6 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { intravisit::walk_mod(self, m, id); } - - fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) { - // Non-opaque macros cannot make other items more accessible than they already are. - let attrs = self.tcx.hir().attrs(md.hir_id()); - if attr::find_transparency(&attrs, md.ast.macro_rules).0 != Transparency::Opaque { - // `#[macro_export]`-ed `macro_rules!` are `Public` since they - // ignore their containing path to always appear at the crate root. - if md.ast.macro_rules { - self.update(md.def_id, Some(AccessLevel::Public)); - } - return; - } - - let macro_module_def_id = - ty::DefIdTree::parent(self.tcx, md.def_id.to_def_id()).unwrap().expect_local(); - if self.tcx.hir().opt_def_kind(macro_module_def_id) != Some(DefKind::Mod) { - // The macro's parent doesn't correspond to a `mod`, return early (#63164, #65252). - return; - } - - let level = if md.vis.node.is_pub() { self.get(macro_module_def_id) } else { None }; - let new_level = self.update(md.def_id, level); - if new_level.is_none() { - return; - } - - // Since we are starting from an externally visible module, - // all the parents in the loop below are also guaranteed to be modules. - let mut module_def_id = macro_module_def_id; - loop { - let changed_reachability = - self.update_macro_reachable(module_def_id, macro_module_def_id); - if changed_reachability || module_def_id == CRATE_DEF_ID { - break; - } - module_def_id = - ty::DefIdTree::parent(self.tcx, module_def_id.to_def_id()).unwrap().expect_local(); - } - } } impl ReachEverythingInTheInterfaceVisitor<'_, 'tcx> { @@ -1981,7 +2001,7 @@ impl<'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'tcx> { // Checked in resolve. hir::ItemKind::Use(..) => {} // No subitems. - hir::ItemKind::GlobalAsm(..) => {} + hir::ItemKind::Macro(..) | hir::ItemKind::GlobalAsm(..) => {} // Subitems of these items have inherited publicity. hir::ItemKind::Const(..) | hir::ItemKind::Static(..) diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 882d15cf8920f..bc2c46ec0aa7c 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -740,6 +740,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) + | hir::ItemKind::Macro(..) | hir::ItemKind::Mod(..) | hir::ItemKind::ForeignMod { .. } | hir::ItemKind::GlobalAsm(..) => { diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs index c3bc1c191ff09..7864b47ab0a7f 100644 --- a/compiler/rustc_save_analysis/src/sig.rs +++ b/compiler/rustc_save_analysis/src/sig.rs @@ -416,6 +416,14 @@ impl<'hir> Sig for hir::Item<'hir> { Ok(sig) } + hir::ItemKind::Macro(_) => { + let mut text = "macro".to_owned(); + let name = self.ident.to_string(); + text.push_str(&name); + text.push_str(&"! {}"); + + Ok(text_sig(text)) + } hir::ItemKind::Mod(ref _mod) => { let mut text = "mod ".to_owned(); let name = self.ident.to_string(); diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index b514176ad529d..145a0c5413bb8 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -746,6 +746,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { // These don't define types. hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) + | hir::ItemKind::Macro(_) | hir::ItemKind::Mod(_) | hir::ItemKind::GlobalAsm(_) => {} hir::ItemKind::ForeignMod { items, .. } => { diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 9bce5ee0da263..41277b22da0e0 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -427,6 +427,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } ItemKind::Trait(..) | ItemKind::TraitAlias(..) + | ItemKind::Macro(..) | ItemKind::Mod(..) | ItemKind::ForeignMod { .. } | ItemKind::GlobalAsm(..) diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs index d358e9fb876a7..da86d28ee0b2d 100644 --- a/src/tools/clippy/clippy_lints/src/missing_doc.rs +++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs @@ -123,6 +123,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { hir::ItemKind::Const(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Mod(..) + | hir::ItemKind::Macro(..) | hir::ItemKind::Static(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Trait(..)