Treat macros as HIR items

This commit is contained in:
inquisitivecrystal 2021-07-30 23:50:57 -07:00
parent ac50a53359
commit 8c62fa0575
31 changed files with 162 additions and 256 deletions

View file

@ -4146,6 +4146,7 @@ dependencies = [
name = "rustc_privacy"
version = "0.0.0"
dependencies = [
"rustc_ast",
"rustc_attr",
"rustc_data_structures",
"rustc_errors",

View file

@ -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<hir::Item<'hir>> {
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")
}
}

View file

@ -103,7 +103,6 @@ struct LoweringContext<'a, 'hir: 'a> {
/// The items being lowered are collected here.
owners: IndexVec<LocalDefId, Option<hir::OwnerNode<'hir>>>,
bodies: BTreeMap<hir::BodyId, hir::Body<'hir>>,
non_exported_macro_attrs: Vec<ast::Attribute>,
trait_impls: BTreeMap<DefId, Vec<LocalDefId>>,
@ -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);

View file

@ -578,6 +578,33 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + 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(),
&macro_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(),
&macro_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))

View file

@ -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>,

View file

@ -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<LocalDefId, Option<OwnerNode<'hir>>>,
pub bodies: BTreeMap<BodyId, Body<'hir>>,
pub trait_impls: BTreeMap<DefId, Vec<LocalDefId>>,
@ -768,32 +765,6 @@ impl Crate<'_> {
_ => None,
})
}
pub fn exported_macros<'hir>(&'hir self) -> impl Iterator<Item = &'hir MacroDef<'hir>> + '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<VisibilityKind<'hir>>;
#[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",

View file

@ -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())

View file

@ -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<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Item<'_> {
});
}
}
impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> 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);
});
}
}

View file

@ -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,

View file

@ -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);

View file

@ -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(..)

View file

@ -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);
})

View file

@ -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);

View file

@ -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 {

View file

@ -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(..)

View file

@ -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| {

View file

@ -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<V>(&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",

View file

@ -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(..)

View file

@ -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(), &macro_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, &param.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);
}
}

View file

@ -107,10 +107,6 @@ fn diagnostic_items<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> FxHashMap<Symbol
// Collect diagnostic items in this crate.
tcx.hir().krate().visit_all_item_likes(&mut collector);
for m in tcx.hir().krate().exported_macros() {
collector.observe_item(m.def_id);
}
collector.items
}

View file

@ -244,11 +244,6 @@ impl<'v> 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> {

View file

@ -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
}

View file

@ -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 { .. }

View file

@ -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).

View file

@ -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" }

View file

@ -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::<AccessLevel>::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(..)

View file

@ -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(..) => {

View file

@ -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();

View file

@ -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, .. } => {

View file

@ -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(..)

View file

@ -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(..)