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 7b0188755710b..6309610f9c8a7 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_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/def.rs b/compiler/rustc_hir/src/def.rs index 3816888db1062..1fdf02513bbdc 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -218,6 +218,13 @@ impl DefKind { | DefKind::Impl => None, } } + + pub fn is_macro(self) -> bool { + match self { + DefKind::Macro(..) => true, + _ => false, + } + } } /// The resolution of a path or export. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 888d1c1832b09..3fc112cb2634c 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>, @@ -743,7 +740,7 @@ impl Crate<'_> { OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item), OwnerNode::ImplItem(item) => visitor.visit_impl_item(item), OwnerNode::TraitItem(item) => visitor.visit_trait_item(item), - OwnerNode::MacroDef(_) | OwnerNode::Crate(_) => {} + OwnerNode::Crate(_) => {} } } } @@ -758,7 +755,7 @@ impl Crate<'_> { Some(OwnerNode::ForeignItem(item)) => visitor.visit_foreign_item(item), Some(OwnerNode::ImplItem(item)) => visitor.visit_impl_item(item), Some(OwnerNode::TraitItem(item)) => visitor.visit_trait_item(item), - Some(OwnerNode::MacroDef(_)) | Some(OwnerNode::Crate(_)) | None => {} + Some(OwnerNode::Crate(_)) | None => {} }) } @@ -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 @@ -2601,7 +2572,7 @@ pub struct PolyTraitRef<'hir> { pub type Visibility<'hir> = Spanned>; -#[derive(Debug)] +#[derive(Copy, Clone, Debug)] pub enum VisibilityKind<'hir> { Public, Crate(CrateSugar), @@ -2794,6 +2765,8 @@ pub enum ItemKind<'hir> { Mod(Mod<'hir>), /// An external module, e.g. `extern { .. }`. ForeignMod { abi: Abi, items: &'hir [ForeignItemRef<'hir>] }, + /// A MBE macro (`macro_rules!` or `macro`). + Macro(ast::MacroDef), /// Module-level inline assembly (from `global_asm!`). GlobalAsm(&'hir InlineAsm<'hir>), /// A type alias, e.g., `type Foo = Bar`. @@ -2857,6 +2830,7 @@ impl ItemKind<'_> { ItemKind::Fn(..) => "function", ItemKind::Mod(..) => "module", ItemKind::ForeignMod { .. } => "extern block", + ItemKind::Macro(..) => "macro", ItemKind::GlobalAsm(..) => "global asm item", ItemKind::TyAlias(..) => "type alias", ItemKind::OpaqueTy(..) => "opaque type", @@ -2995,7 +2969,6 @@ pub enum OwnerNode<'hir> { ForeignItem(&'hir ForeignItem<'hir>), TraitItem(&'hir TraitItem<'hir>), ImplItem(&'hir ImplItem<'hir>), - MacroDef(&'hir MacroDef<'hir>), Crate(&'hir Mod<'hir>), } @@ -3005,8 +2978,7 @@ impl<'hir> OwnerNode<'hir> { OwnerNode::Item(Item { ident, .. }) | OwnerNode::ForeignItem(ForeignItem { ident, .. }) | OwnerNode::ImplItem(ImplItem { ident, .. }) - | OwnerNode::TraitItem(TraitItem { ident, .. }) - | OwnerNode::MacroDef(MacroDef { ident, .. }) => Some(*ident), + | OwnerNode::TraitItem(TraitItem { ident, .. }) => Some(*ident), OwnerNode::Crate(..) => None, } } @@ -3017,7 +2989,6 @@ impl<'hir> OwnerNode<'hir> { | OwnerNode::ForeignItem(ForeignItem { span, .. }) | OwnerNode::ImplItem(ImplItem { span, .. }) | OwnerNode::TraitItem(TraitItem { span, .. }) - | OwnerNode::MacroDef(MacroDef { span, .. }) | OwnerNode::Crate(Mod { inner: span, .. }) => *span, } } @@ -3061,8 +3032,7 @@ impl<'hir> OwnerNode<'hir> { OwnerNode::Item(Item { def_id, .. }) | OwnerNode::TraitItem(TraitItem { def_id, .. }) | OwnerNode::ImplItem(ImplItem { def_id, .. }) - | OwnerNode::ForeignItem(ForeignItem { def_id, .. }) - | OwnerNode::MacroDef(MacroDef { def_id, .. }) => *def_id, + | OwnerNode::ForeignItem(ForeignItem { def_id, .. }) => *def_id, OwnerNode::Crate(..) => crate::CRATE_HIR_ID.owner, } } @@ -3094,13 +3064,6 @@ impl<'hir> OwnerNode<'hir> { _ => panic!(), } } - - pub fn expect_macro_def(self) -> &'hir MacroDef<'hir> { - match self { - OwnerNode::MacroDef(n) => n, - _ => panic!(), - } - } } impl<'hir> Into> for &'hir Item<'hir> { @@ -3127,12 +3090,6 @@ impl<'hir> Into> for &'hir TraitItem<'hir> { } } -impl<'hir> Into> for &'hir MacroDef<'hir> { - fn into(self) -> OwnerNode<'hir> { - OwnerNode::MacroDef(self) - } -} - impl<'hir> Into> for OwnerNode<'hir> { fn into(self) -> Node<'hir> { match self { @@ -3140,7 +3097,6 @@ impl<'hir> Into> for OwnerNode<'hir> { OwnerNode::ForeignItem(n) => Node::ForeignItem(n), OwnerNode::ImplItem(n) => Node::ImplItem(n), OwnerNode::TraitItem(n) => Node::TraitItem(n), - OwnerNode::MacroDef(n) => Node::MacroDef(n), OwnerNode::Crate(n) => Node::Crate(n), } } @@ -3166,7 +3122,6 @@ pub enum Node<'hir> { Arm(&'hir Arm<'hir>), Block(&'hir Block<'hir>), Local(&'hir Local<'hir>), - MacroDef(&'hir MacroDef<'hir>), /// `Ctor` refers to the constructor of an enum variant or struct. Only tuple or unit variants /// with synthesized constructors. @@ -3189,7 +3144,6 @@ impl<'hir> Node<'hir> { | Node::ForeignItem(ForeignItem { ident, .. }) | Node::Field(FieldDef { ident, .. }) | Node::Variant(Variant { ident, .. }) - | Node::MacroDef(MacroDef { ident, .. }) | Node::Item(Item { ident, .. }) => Some(*ident), _ => None, } @@ -3233,8 +3187,7 @@ impl<'hir> Node<'hir> { Node::Item(Item { def_id, .. }) | Node::TraitItem(TraitItem { def_id, .. }) | Node::ImplItem(ImplItem { def_id, .. }) - | Node::ForeignItem(ForeignItem { def_id, .. }) - | Node::MacroDef(MacroDef { def_id, .. }) => Some(HirId::make_owner(*def_id)), + | Node::ForeignItem(ForeignItem { def_id, .. }) => Some(HirId::make_owner(*def_id)), Node::Field(FieldDef { hir_id, .. }) | Node::AnonConst(AnonConst { hir_id, .. }) | Node::Expr(Expr { hir_id, .. }) @@ -3294,7 +3247,6 @@ impl<'hir> Node<'hir> { Node::ForeignItem(i) => Some(OwnerNode::ForeignItem(i)), Node::TraitItem(i) => Some(OwnerNode::TraitItem(i)), Node::ImplItem(i) => Some(OwnerNode::ImplItem(i)), - Node::MacroDef(i) => Some(OwnerNode::MacroDef(i)), Node::Crate(i) => Some(OwnerNode::Crate(i)), _ => None, } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 7f153867596ec..43fbb675ef290 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 { @@ -594,6 +585,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) { visitor.visit_id(item.hir_id()); walk_list!(visitor, visit_foreign_item_ref, items); } + ItemKind::Macro(_) => { + visitor.visit_id(item.hir_id()); + } ItemKind::GlobalAsm(asm) => { visitor.visit_id(item.hir_id()); walk_inline_asm(visitor, asm); 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..dabdccbe77ef2 100644 --- a/compiler/rustc_hir/src/target.rs +++ b/compiler/rustc_hir/src/target.rs @@ -113,6 +113,7 @@ impl Target { ItemKind::Fn(..) => Target::Fn, ItemKind::Mod(..) => Target::Mod, ItemKind::ForeignMod { .. } => Target::ForeignMod, + ItemKind::Macro(..) => Target::MacroDef, ItemKind::GlobalAsm(..) => Target::GlobalAsm, ItemKind::TyAlias(..) => Target::TyAlias, ItemKind::OpaqueTy(..) => Target::OpaqueTy, diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 9c286ad5ccfe9..2fccb7986c847 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -4,6 +4,7 @@ use rustc_ast as ast; use rustc_ast::util::parser::{self, AssocOp, Fixity}; use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent}; use rustc_ast_pretty::pp::{self, Breaks}; +use rustc_ast_pretty::pprust::state::MacHeader; use rustc_ast_pretty::pprust::{Comments, PrintState}; use rustc_hir as hir; use rustc_hir::{GenericArg, GenericParam, GenericParamKind, Node}; @@ -120,7 +121,6 @@ impl<'a> State<'a> { // printing. Node::Ctor(..) => panic!("cannot print isolated Ctor"), Node::Local(a) => self.print_local_decl(&a), - Node::MacroDef(_) => panic!("cannot print MacroDef"), Node::Crate(..) => panic!("cannot print Crate"), } } @@ -660,6 +660,28 @@ impl<'a> State<'a> { } self.bclose(item.span); } + hir::ItemKind::Macro(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(";"); + } + } hir::ItemKind::GlobalAsm(ref asm) => { self.head(visibility_qualified(&item.vis, "global_asm!")); self.print_inline_asm(asm); diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index afa2cfca1880f..df4433373463f 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<'_>) { @@ -637,6 +619,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { hir::ItemKind::TyAlias(..) | hir::ItemKind::Fn(..) | hir::ItemKind::Mod(..) + | hir::ItemKind::Macro(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) 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..f4b25dfc4a0b0 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1036,6 +1036,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.local_def_id(def_index), ); let ident = self.item_ident(def_index, sess); + callback(Export { ident, res, vis: ty::Visibility::Public, span: ident.span }); } } @@ -1100,7 +1101,9 @@ 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 }); + // 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..4e906cee1913b 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) { @@ -1389,6 +1386,9 @@ impl EncodeContext<'a, 'tcx> { return self.encode_info_for_mod(item.def_id, m); } hir::ItemKind::ForeignMod { .. } => EntryKind::ForeignMod, + hir::ItemKind::Macro(ref macro_def) => { + EntryKind::MacroDef(self.lazy(macro_def.clone())) + } hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm, hir::ItemKind::TyAlias(..) => EntryKind::Type, hir::ItemKind::OpaqueTy(..) => { @@ -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> { @@ -1974,6 +1964,7 @@ impl EncodeContext<'a, 'tcx> { | hir::ItemKind::Fn(..) | hir::ItemKind::Mod(..) | hir::ItemKind::ForeignMod { .. } + | hir::ItemKind::Macro(..) | hir::ItemKind::GlobalAsm(..) | hir::ItemKind::ExternCrate(..) | hir::ItemKind::Use(..) 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..8da8024c7bd54 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; @@ -229,6 +228,7 @@ impl<'hir> Map<'hir> { ItemKind::ExternCrate(_) => DefKind::ExternCrate, ItemKind::Use(..) => DefKind::Use, ItemKind::ForeignMod { .. } => DefKind::ForeignMod, + ItemKind::Macro(..) => DefKind::Macro(MacroKind::Bang), ItemKind::GlobalAsm(..) => DefKind::GlobalAsm, ItemKind::Impl { .. } => DefKind::Impl, }, @@ -266,7 +266,6 @@ impl<'hir> Map<'hir> { ExprKind::Closure(.., Some(_)) => DefKind::Generator, _ => bug!("def_kind: unsupported node: {}", self.node_to_string(hir_id)), }, - Node::MacroDef(_) => DefKind::Macro(MacroKind::Bang), Node::GenericParam(param) => match param.kind { GenericParamKind::Lifetime { .. } => DefKind::LifetimeParam, GenericParamKind::Type { .. } => DefKind::TyParam, @@ -543,15 +542,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> { @@ -645,8 +635,6 @@ impl<'hir> Map<'hir> { /// in a module, trait, or impl. pub fn get_parent_item(&self, hir_id: HirId) -> HirId { if let Some((hir_id, _node)) = self.parent_owner_iter(hir_id).next() { - // A MacroDef does not have children. - debug_assert!(!matches!(_node, OwnerNode::MacroDef(_))); hir_id } else { CRATE_HIR_ID @@ -774,13 +762,6 @@ impl<'hir> Map<'hir> { } } - pub fn expect_macro_def(&self, id: HirId) -> &'hir MacroDef<'hir> { - match self.tcx.hir_owner(id.expect_owner()) { - Some(Owner { node: OwnerNode::MacroDef(macro_def) }) => macro_def, - _ => bug!("expected macro def, found {}", self.node_to_string(id)), - } - } - pub fn expect_expr(&self, id: HirId) -> &'hir Expr<'hir> { match self.find(id) { Some(Node::Expr(expr)) => expr, @@ -800,7 +781,6 @@ impl<'hir> Map<'hir> { Node::GenericParam(param) => param.name.ident().name, Node::Binding(&Pat { kind: PatKind::Binding(_, _, l, _), .. }) => l.name, Node::Ctor(..) => self.name(self.get_parent_item(id)), - Node::MacroDef(md) => md.ident.name, _ => return None, }) } @@ -867,7 +847,6 @@ impl<'hir> Map<'hir> { Node::Infer(i) => i.span, Node::Visibility(v) => bug!("unexpected Visibility {:?}", v), Node::Local(local) => local.span, - Node::MacroDef(macro_def) => macro_def.span, Node::Crate(item) => item.inner, }; Some(span) @@ -1013,7 +992,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()) @@ -1064,6 +1042,7 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId) -> String { ItemKind::Fn(..) => "fn", ItemKind::Mod(..) => "mod", ItemKind::ForeignMod { .. } => "foreign mod", + ItemKind::Macro(..) => "macro", ItemKind::GlobalAsm(..) => "global asm", ItemKind::TyAlias(..) => "ty", ItemKind::OpaqueTy(..) => "opaque type", @@ -1118,7 +1097,6 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId) -> String { Some(Node::Lifetime(_)) => node_str("lifetime"), Some(Node::GenericParam(ref param)) => format!("generic_param {:?}{}", param, id_str), Some(Node::Visibility(ref vis)) => format!("visibility {:?}{}", vis, id_str), - Some(Node::MacroDef(_)) => format!("macro {}{}", path_str(), id_str), Some(Node::Crate(..)) => String::from("root_crate"), None => format!("unknown node{}", id_str), } diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs index 95c4237f38396..c6fd9eaf1a836 100644 --- a/compiler/rustc_mir/src/monomorphize/collector.rs +++ b/compiler/rustc_mir/src/monomorphize/collector.rs @@ -1150,6 +1150,7 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> { hir::ItemKind::ExternCrate(..) | hir::ItemKind::Use(..) | hir::ItemKind::ForeignMod { .. } + | hir::ItemKind::Macro(..) | hir::ItemKind::TyAlias(..) | hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) 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..3898ce22d9c25 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -265,6 +265,7 @@ impl<'tcx> ReachableContext<'tcx> { | hir::ItemKind::TyAlias(..) | hir::ItemKind::Mod(..) | hir::ItemKind::ForeignMod { .. } + | hir::ItemKind::Macro(..) | hir::ItemKind::Impl { .. } | hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) @@ -309,8 +310,7 @@ impl<'tcx> ReachableContext<'tcx> { | Node::Ctor(..) | Node::Field(_) | Node::Ty(_) - | Node::Crate(_) - | Node::MacroDef(_) => {} + | Node::Crate(_) => {} _ => { bug!( "found unexpected node kind in worklist: {} ({:?})", 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/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index d84175724cc32..e5642ba7da0ca 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -26,7 +26,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}; @@ -507,11 +507,7 @@ 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); } @@ -566,6 +562,7 @@ impl EmbargoVisitor<'tcx> { | DefKind::ExternCrate | DefKind::Use | DefKind::ForeignMod + | DefKind::Macro(_) | DefKind::AnonConst | DefKind::Field | DefKind::GlobalAsm @@ -642,6 +639,21 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { } // Foreign modules inherit level from parents. hir::ItemKind::ForeignMod { .. } => self.prev_level, + hir::ItemKind::Macro(ref macro_def) => { + let def_id = item.def_id.to_def_id(); + let is_macro_export = self.tcx.has_attr(def_id, sym::macro_export); + match (macro_def.macro_rules, is_macro_export) { + (true, true) => Some(AccessLevel::Public), + (true, false) => None, + (false, _) => { + if item.vis.node.is_pub() { + self.prev_level + } else { + None + } + } + } + } // Other `pub` items inherit levels from parents. hir::ItemKind::Const(..) | hir::ItemKind::Enum(..) @@ -711,6 +723,43 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { } } } + hir::ItemKind::Macro(ref md) => { + // We have to make sure that the items that macros might reference + // are reachable, since they might be exported transitively. + + // Non-opaque macros cannot make other items more accessible than they already are. + let attrs = self.tcx.hir().attrs(item.hir_id()); + if attr::find_transparency(&attrs, md.macro_rules).0 != Transparency::Opaque { + return; + } + + let item_def_id = item.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(item.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(); + } + } + hir::ItemKind::OpaqueTy(..) | hir::ItemKind::Use(..) | hir::ItemKind::Static(..) @@ -726,7 +775,8 @@ 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 @@ -881,45 +931,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> { @@ -1977,7 +1988,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/imports.rs b/compiler/rustc_resolve/src/imports.rs index dfb6d89a0d126..7be264a9f2d89 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -16,7 +16,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::ptr_key::PtrKey; use rustc_errors::{pluralize, struct_span_err, Applicability}; use rustc_hir::def::{self, PartialRes}; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_middle::hir::exports::Export; use rustc_middle::span_bug; use rustc_middle::ty; @@ -1392,9 +1392,23 @@ impl<'a, 'b> ImportResolver<'a, 'b> { // FIXME: Implement actual cross-crate hygiene. let is_good_import = binding.is_import() && !binding.is_ambiguity() && !ident.span.from_expansion(); - if is_good_import || binding.is_macro_def() { - let res = binding.res().map_id(|id| this.local_def_id(id)); - if res != def::Res::Err { + let res = binding.res(); + if res == Res::Err { + // Do not insert failed resolutions. + return; + } else if is_good_import { + let res = res.map_id(|id| this.local_def_id(id)); + reexports.push(Export { ident, res, span: binding.span, vis: binding.vis }); + } else if let NameBindingKind::Res(Res::Def(def_kind, macro_def_id), true) = + binding.kind + { + let macro_is_at_root = macro_def_id + .as_local() + .and_then(|macro_def_id| this.definitions.def_key(macro_def_id).parent) + == Some(CRATE_DEF_INDEX); + // Insert a re-export at crate root for exported macro_rules defined elsewhere. + if module.parent.is_none() && !macro_is_at_root { + let res = def::Res::Def(def_kind, macro_def_id); reexports.push(Export { ident, res, span: binding.span, vis: binding.vis }); } } diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 882d15cf8920f..d55ce24e69a7d 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -742,6 +742,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { | hir::ItemKind::Use(..) | hir::ItemKind::Mod(..) | hir::ItemKind::ForeignMod { .. } + | hir::ItemKind::Macro(..) | hir::ItemKind::GlobalAsm(..) => { // These sorts of items have no lifetime parameters at all. intravisit::walk_item(self, item); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index e308ea1a1be5b..7cbea6e88ccad 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -815,10 +815,6 @@ impl<'a> NameBinding<'a> { ) } - fn is_macro_def(&self) -> bool { - matches!(self.kind, NameBindingKind::Res(Res::Def(DefKind::Macro(..), _), _)) - } - fn macro_kind(&self) -> Option { self.res().macro_kind() } diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs index c3bc1c191ff09..4ac6e8e6dc471 100644 --- a/compiler/rustc_save_analysis/src/sig.rs +++ b/compiler/rustc_save_analysis/src/sig.rs @@ -430,6 +430,14 @@ impl<'hir> Sig for hir::Item<'hir> { Ok(Signature { text, defs, refs: vec![] }) } + 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::TyAlias(ref ty, ref generics) => { let text = "type ".to_owned(); let mut sig = diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 1c6fd5983cb59..e9846a0f4bd0a 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -751,6 +751,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) | hir::ItemKind::Mod(_) + | hir::ItemKind::Macro(..) | hir::ItemKind::GlobalAsm(_) => {} hir::ItemKind::ForeignMod { items, .. } => { for item in items { diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index e63c3346e02b1..8cd0b8ccc9c7c 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -404,6 +404,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { | ItemKind::TraitAlias(..) | ItemKind::Mod(..) | ItemKind::ForeignMod { .. } + | ItemKind::Macro(..) | ItemKind::GlobalAsm(..) | ItemKind::ExternCrate(..) | ItemKind::Use(..) => { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index b6ff3890c584e..640acffb114d9 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -91,7 +91,6 @@ impl Clean for doctree::Module<'_> { items.extend(self.foreigns.iter().map(|x| x.clean(cx))); items.extend(self.mods.iter().map(|x| x.clean(cx))); items.extend(self.items.iter().map(|x| x.clean(cx)).flatten()); - items.extend(self.macros.iter().map(|x| x.clean(cx))); // determine if we should display the inner contents or // the outer `mod` item for the source code. @@ -1861,6 +1860,10 @@ impl Clean> for (&hir::Item<'_>, Option) { ItemKind::Fn(ref sig, ref generics, body_id) => { clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx) } + ItemKind::Macro(ref macro_def) => MacroItem(Macro { + source: display_macro_source(cx, name, ¯o_def, def_id, &item.vis), + imported_from: None, + }), ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => { let items = item_ids .iter() @@ -2138,24 +2141,6 @@ impl Clean for (&hir::ForeignItem<'_>, Option) { } } -impl Clean for (&hir::MacroDef<'_>, Option) { - fn clean(&self, cx: &mut DocContext<'_>) -> Item { - let (item, renamed) = self; - let name = renamed.unwrap_or(item.ident.name); - let def_id = item.def_id.to_def_id(); - - Item::from_hir_id_and_parts( - item.hir_id(), - Some(name), - MacroItem(Macro { - source: display_macro_source(cx, name, &item.ast, def_id, &item.vis), - imported_from: None, - }), - cx, - ) - } -} - impl Clean for hir::TypeBinding<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> TypeBinding { TypeBinding { name: self.ident.name, kind: self.kind.clean(cx) } diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 083d82cb414d8..bf14a17c07693 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -1171,10 +1171,21 @@ impl<'a, 'hir, 'tcx> intravisit::Visitor<'hir> for HirCollector<'a, 'hir, 'tcx> } fn visit_item(&mut self, item: &'hir hir::Item<'_>) { - let name = if let hir::ItemKind::Impl(impl_) = &item.kind { - rustc_hir_pretty::id_to_string(&self.map, impl_.self_ty.hir_id) - } else { - item.ident.to_string() + let name = match &item.kind { + hir::ItemKind::Macro(ref macro_def) => { + // FIXME(#88038): Non exported macros have historically not been tested, + // but we really ought to start testing them. + let def_id = item.def_id.to_def_id(); + if macro_def.macro_rules && !self.tcx.has_attr(def_id, sym::macro_export) { + intravisit::walk_item(self, item); + return; + } + item.ident.to_string() + } + hir::ItemKind::Impl(impl_) => { + rustc_hir_pretty::id_to_string(&self.map, impl_.self_ty.hir_id) + } + _ => item.ident.to_string(), }; self.visit_testable(name, item.hir_id(), item.span, |this| { @@ -1216,15 +1227,6 @@ impl<'a, 'hir, 'tcx> intravisit::Visitor<'hir> for HirCollector<'a, 'hir, 'tcx> intravisit::walk_field_def(this, f); }); } - - fn visit_macro_def(&mut self, macro_def: &'hir hir::MacroDef<'_>) { - self.visit_testable( - macro_def.ident.to_string(), - macro_def.hir_id(), - macro_def.span, - |_| (), - ); - } } #[cfg(test)] diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index eadac89f79ef2..8f1e8f277c5fe 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -5,6 +5,7 @@ use rustc_span::{self, Span, Symbol}; use rustc_hir as hir; +#[derive(Debug)] crate struct Module<'hir> { crate name: Symbol, crate where_inner: Span, @@ -13,20 +14,11 @@ crate struct Module<'hir> { // (item, renamed) crate items: Vec<(&'hir hir::Item<'hir>, Option)>, crate foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option)>, - crate macros: Vec<(&'hir hir::MacroDef<'hir>, Option)>, } impl Module<'hir> { crate fn new(name: Symbol, id: hir::HirId, where_inner: Span) -> Module<'hir> { - Module { - name, - id, - where_inner, - mods: Vec::new(), - items: Vec::new(), - foreigns: Vec::new(), - macros: Vec::new(), - } + Module { name, id, where_inner, mods: Vec::new(), items: Vec::new(), foreigns: Vec::new() } } crate fn where_outer(&self, tcx: TyCtxt<'_>) -> Span { diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index e28910355357b..43cf94387add5 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -9,7 +9,7 @@ use rustc_hir::Node; use rustc_middle::middle::privacy::AccessLevel; use rustc_middle::ty::TyCtxt; use rustc_span; -use rustc_span::def_id::LOCAL_CRATE; +use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE}; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Symbol}; @@ -79,50 +79,25 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { &krate.module(), self.cx.tcx.crate_name(LOCAL_CRATE), ); - // Attach the crate's exported macros to the top-level module. - // In the case of macros 2.0 (`pub macro`), and for built-in `derive`s or attributes as - // well (_e.g._, `Copy`), these are wrongly bundled in there too, so we need to fix that by - // moving them back to their correct locations. - 'exported_macros: for def in krate.exported_macros() { - // The `def` of a macro in `exported_macros` should correspond to either: - // - a `#[macro_export] macro_rules!` macro, - // - a built-in `derive` (or attribute) macro such as the ones in `::core`, - // - a `pub macro`. - // Only the last two need to be fixed, thus: - if def.ast.macro_rules { - top_level_module.macros.push((def, None)); - continue 'exported_macros; - } - let tcx = self.cx.tcx; - // Note: this is not the same as `.parent_module()`. Indeed, the latter looks - // for the closest module _ancestor_, which is not necessarily a direct parent - // (since a direct parent isn't necessarily a module, c.f. #77828). - let macro_parent_def_id = { - use rustc_middle::ty::DefIdTree; - tcx.parent(def.def_id.to_def_id()).unwrap() - }; - let macro_parent_path = tcx.def_path(macro_parent_def_id); - // HACK: rustdoc has no way to lookup `doctree::Module`s by their HirId. Instead, - // lookup the module by its name, by looking at each path segment one at a time. - let mut cur_mod = &mut top_level_module; - for path_segment in macro_parent_path.data { - // Path segments may refer to a module (in which case they belong to the type - // namespace), which is _necessary_ for the macro to be accessible outside it - // (no "associated macros" as of yet). Else we bail with an outer `continue`. - let path_segment_ty_ns = match path_segment.data { - rustc_hir::definitions::DefPathData::TypeNs(symbol) => symbol, - _ => continue 'exported_macros, - }; - // Descend into the child module that matches this path segment (if any). - match cur_mod.mods.iter_mut().find(|child| child.name == path_segment_ty_ns) { - Some(child_mod) => cur_mod = &mut *child_mod, - None => continue 'exported_macros, + + // `#[macro_export] macro_rules!` items are reexported at the top level of the + // crate, regardless of where they're defined. We want to document the + // top level rexport of the macro, not its original definition, since + // the rexport defines the path that a user will actually see. Accordingly, + // we add the rexport as an item here, and then skip over the original + // definition in `visit_item()` below. + for export in self.cx.tcx.module_exports(CRATE_DEF_ID).unwrap_or(&[]) { + if let Res::Def(DefKind::Macro(_), def_id) = export.res { + if let Some(local_def_id) = def_id.as_local() { + if self.cx.tcx.has_attr(def_id, sym::macro_export) { + let hir_id = self.cx.tcx.hir().local_def_id_to_hir_id(local_def_id); + let item = self.cx.tcx.hir().expect_item(hir_id); + top_level_module.items.push((item, None)); + } } } - let cur_mod_def_id = tcx.hir().local_def_id(cur_mod.id).to_def_id(); - assert_eq!(cur_mod_def_id, macro_parent_def_id); - cur_mod.macros.push((def, None)); } + self.cx.cache.exact_paths = self.exact_paths; top_level_module } @@ -238,10 +213,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { self.inlining = prev; true } - Node::MacroDef(def) if !glob => { - om.macros.push((def, renamed)); - true - } _ => false, }; self.view_item_stack.remove(&res_hir_id); @@ -257,7 +228,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { debug!("visiting item {:?}", item); let name = renamed.unwrap_or(item.ident.name); - if item.vis.node.is_pub() { + let def_id = item.def_id.to_def_id(); + let is_pub = item.vis.node.is_pub() || self.cx.tcx.has_attr(def_id, sym::macro_export); + + if is_pub { self.store_path(item.def_id.to_def_id()); } @@ -269,7 +243,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } } // If we're inlining, skip private items. - _ if self.inlining && !item.vis.node.is_pub() => {} + _ if self.inlining && !is_pub => {} hir::ItemKind::GlobalAsm(..) => {} hir::ItemKind::Use(_, hir::UseKind::ListStem) => {} hir::ItemKind::Use(ref path, kind) => { @@ -285,7 +259,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { // If there was a private module in the current path then don't bother inlining // anything as it will probably be stripped anyway. - if item.vis.node.is_pub() && self.inside_public_path { + if is_pub && self.inside_public_path { let please_inline = attrs.iter().any(|item| match item.meta_item_list() { Some(ref list) if item.has_name(sym::doc) => { list.iter().any(|i| i.has_name(sym::inline)) @@ -310,6 +284,26 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { hir::ItemKind::Mod(ref m) => { om.mods.push(self.visit_mod_contents(&item.vis, item.hir_id(), m, name)); } + hir::ItemKind::Macro(ref macro_def) => { + // `#[macro_export] macro_rules!` items are handled seperately in `visit()`, + // above, since they need to be documented at the module top level. Accordingly, + // we only want to handle macros if one of three conditions holds: + // + // 1. This macro was defined by `macro`, and thus isn't covered by the case + // above. + // 2. This macro isn't marked with `#[macro_export]`, and thus isn't covered + // by the case above. + // 3. We're inlining, since a reexport where inlining has been requested + // should be inlined even if it is also documented at the top level. + + let def_id = item.def_id.to_def_id(); + let is_macro_2_0 = !macro_def.macro_rules; + let nonexported = !self.cx.tcx.has_attr(def_id, sym::macro_export); + + if is_macro_2_0 || nonexported || self.inlining { + om.items.push((item, renamed)); + } + } hir::ItemKind::Fn(..) | hir::ItemKind::ExternCrate(..) | hir::ItemKind::Enum(..) diff --git a/src/test/rustdoc-ui/deny-missing-docs-macro.stderr b/src/test/rustdoc-ui/deny-missing-docs-macro.stderr index a564006e74f48..0867b08183e2d 100644 --- a/src/test/rustdoc-ui/deny-missing-docs-macro.stderr +++ b/src/test/rustdoc-ui/deny-missing-docs-macro.stderr @@ -1,4 +1,4 @@ -error: missing documentation for macro +error: missing documentation for a macro --> $DIR/deny-missing-docs-macro.rs:6:1 | LL | macro_rules! foo { diff --git a/src/test/rustdoc/macro-document-private.rs b/src/test/rustdoc/macro-document-private.rs new file mode 100644 index 0000000000000..d2496913ffcf2 --- /dev/null +++ b/src/test/rustdoc/macro-document-private.rs @@ -0,0 +1,19 @@ +// Checks that private macros are documented when `--document-private-items` +// is present. +// +// This is a regression test for issue #73754. +// +// compile-flags: --document-private-items + +#![feature(decl_macro)] + + +// @has macro_document_private/macro.some_macro.html +macro some_macro { + (a: tt) => {} +} + +// @has macro_document_private/macro.another_macro.html +macro_rules! another_macro { + (a: tt) => {} +} diff --git a/src/test/rustdoc/macro-indirect-use.rs b/src/test/rustdoc/macro-indirect-use.rs new file mode 100644 index 0000000000000..b2d9336cffc81 --- /dev/null +++ b/src/test/rustdoc/macro-indirect-use.rs @@ -0,0 +1,16 @@ +// Checks that it is possible to make a macro public through a `pub use` of its +// parent module. +// +// This is a regression test for issue #87257. + +#![feature(decl_macro)] + +mod outer { + pub mod inner { + pub macro some_macro() {} + } +} + +// @has macro_indirect_use/inner/index.html +// @has macro_indirect_use/inner/macro.some_macro.html +pub use outer::inner; diff --git a/src/test/ui/lint/lint-level-macro-def.rs b/src/test/ui/lint/lint-level-macro-def.rs new file mode 100644 index 0000000000000..720f4b453abf5 --- /dev/null +++ b/src/test/ui/lint/lint-level-macro-def.rs @@ -0,0 +1,17 @@ +// Checks that you can set a lint level specficially for a macro definition. +// +// This is a regression test for issue #59306. +// +// check-pass + + +#[deny(missing_docs)] +mod module { + #[allow(missing_docs)] + #[macro_export] + macro_rules! hello { + () => () + } +} + +fn main() {} diff --git a/src/test/ui/lint/missing-doc-private-macro.rs b/src/test/ui/lint/missing-doc-private-macro.rs index 8d1d5c568803b..0d4332ed08b26 100644 --- a/src/test/ui/lint/missing-doc-private-macro.rs +++ b/src/test/ui/lint/missing-doc-private-macro.rs @@ -29,13 +29,13 @@ mod submodule { #[macro_export] macro_rules! exported_to_top_level { - //~^ ERROR missing documentation for macro + //~^ ERROR missing documentation for a macro () => () } } pub macro top_level_pub_macro { - //~^ ERROR missing documentation for macro + //~^ ERROR missing documentation for a macro () => () } diff --git a/src/test/ui/lint/missing-doc-private-macro.stderr b/src/test/ui/lint/missing-doc-private-macro.stderr index a5d39faf40562..979b007d0ecd6 100644 --- a/src/test/ui/lint/missing-doc-private-macro.stderr +++ b/src/test/ui/lint/missing-doc-private-macro.stderr @@ -1,4 +1,4 @@ -error: missing documentation for macro +error: missing documentation for a macro --> $DIR/missing-doc-private-macro.rs:31:5 | LL | macro_rules! exported_to_top_level { @@ -10,7 +10,7 @@ note: the lint level is defined here LL | #![deny(missing_docs)] | ^^^^^^^^^^^^ -error: missing documentation for macro +error: missing documentation for a macro --> $DIR/missing-doc-private-macro.rs:37:1 | LL | pub macro top_level_pub_macro { diff --git a/src/test/ui/macros/macro-stability-rpass.rs b/src/test/ui/macros/macro-stability-rpass.rs index a5f538ba6b36a..2d02b95288df4 100644 --- a/src/test/ui/macros/macro-stability-rpass.rs +++ b/src/test/ui/macros/macro-stability-rpass.rs @@ -1,7 +1,8 @@ // run-pass // aux-build:unstable-macros.rs -#![feature(unstable_macros, local_unstable)] +#![unstable(feature = "one_two_three_testing", issue = "none")] +#![feature(staged_api, unstable_macros, local_unstable)] #[macro_use] extern crate unstable_macros; 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(..) diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index 977e6d966e873..37ec743da314b 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -119,6 +119,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { hir::ItemKind::Const(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Mod(..) + | hir::ItemKind::Macro(..) | hir::ItemKind::Static(..) | hir::ItemKind::Struct(..) | hir::ItemKind::TraitAlias(..) diff --git a/src/tools/clippy/clippy_lints/src/utils/inspector.rs b/src/tools/clippy/clippy_lints/src/utils/inspector.rs index 6bf216cec1670..5395967cdae24 100644 --- a/src/tools/clippy/clippy_lints/src/utils/inspector.rs +++ b/src/tools/clippy/clippy_lints/src/utils/inspector.rs @@ -383,6 +383,13 @@ fn print_item(cx: &LateContext<'_>, item: &hir::Item<'_>) { }, hir::ItemKind::Mod(..) => println!("module"), hir::ItemKind::ForeignMod { abi, .. } => println!("foreign module with abi: {}", abi), + hir::ItemKind::Macro(ref macro_def) => { + if macro_def.macro_rules { + println!("macro introduced by `macro_rules!`"); + } else { + println!("macro introduced by `macro`"); + } + } hir::ItemKind::GlobalAsm(asm) => println!("global asm: {:?}", asm), hir::ItemKind::TyAlias(..) => { println!("type alias for {:?}", cx.tcx.type_of(did));