From 17b1afdbb234a1cdf5db92ec8639cbd2909ac629 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 11 Dec 2021 19:52:23 +0800 Subject: [PATCH] resolve: Fix incorrect results of `opt_def_kind` query for some built-in macros Previously it always returned `MacroKind::Bang` while some of those macros are actually attributes and derives --- compiler/rustc_ast_lowering/src/item.rs | 4 ++-- compiler/rustc_ast_lowering/src/lib.rs | 4 +++- compiler/rustc_hir/src/hir.rs | 3 ++- compiler/rustc_hir/src/intravisit.rs | 2 +- compiler/rustc_hir_pretty/src/lib.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_middle/src/hir/map/mod.rs | 3 +-- compiler/rustc_passes/src/check_attr.rs | 2 +- compiler/rustc_privacy/src/lib.rs | 4 ++-- compiler/rustc_resolve/src/lib.rs | 8 ++++++++ compiler/rustc_resolve/src/macros.rs | 8 +++++++- compiler/rustc_save_analysis/src/sig.rs | 2 +- compiler/rustc_typeck/src/collect.rs | 2 +- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/doctest.rs | 2 +- src/librustdoc/visit_ast.rs | 2 +- src/tools/clippy/clippy_lints/src/utils/inspector.rs | 2 +- 17 files changed, 35 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index a8633336512..3ddc7fce1b7 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -444,8 +444,8 @@ fn lower_item_kind( ), ItemKind::MacroDef(MacroDef { ref body, macro_rules }) => { let body = P(self.lower_mac_args(body)); - - hir::ItemKind::Macro(ast::MacroDef { body, macro_rules }) + let macro_kind = self.resolver.decl_macro_kind(self.resolver.local_def_id(id)); + hir::ItemKind::Macro(ast::MacroDef { body, macro_rules }, macro_kind) } 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 0a59e3c2e3f..0156c5016ac 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -61,7 +61,7 @@ use rustc_session::parse::feature_err; use rustc_session::utils::{FlattenNonterminals, NtToTokenstream}; use rustc_session::Session; -use rustc_span::hygiene::ExpnId; +use rustc_span::hygiene::{ExpnId, MacroKind}; use rustc_span::source_map::{respan, DesugaringKind}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -210,6 +210,8 @@ fn create_def( expn_id: ExpnId, span: Span, ) -> LocalDefId; + + fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind; } /// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index d48c8e81f54..72c02932945 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -15,6 +15,7 @@ use rustc_data_structures::sorted_map::SortedMap; use rustc_index::vec::IndexVec; use rustc_macros::HashStable_Generic; +use rustc_span::hygiene::MacroKind; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{def_id::LocalDefId, BytePos, MultiSpan, Span, DUMMY_SP}; @@ -2803,7 +2804,7 @@ pub enum ItemKind<'hir> { /// A function declaration. Fn(FnSig<'hir>, Generics<'hir>, BodyId), /// A MBE macro definition (`macro_rules!` or `macro`). - Macro(ast::MacroDef), + Macro(ast::MacroDef, MacroKind), /// A module. Mod(Mod<'hir>), /// An external module, e.g. `extern { .. }`. diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index c55f2a7b039..1b40f3d390e 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -575,7 +575,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) { item.span, item.hir_id(), ), - ItemKind::Macro(_) => { + ItemKind::Macro(..) => { visitor.visit_id(item.hir_id()); } ItemKind::Mod(ref module) => { diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 8e45b636f47..b3042c61002 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -570,7 +570,7 @@ pub fn print_item(&mut self, item: &hir::Item<'_>) { self.end(); // need to close a box self.ann.nested(self, Nested::Body(body)); } - hir::ItemKind::Macro(ref macro_def) => { + hir::ItemKind::Macro(ref macro_def, _) => { self.print_mac_def(macro_def, &item.ident, item.span, |state| { state.print_visibility(&item.vis) }); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index da8995df1ac..85b1b31ba84 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1406,7 +1406,7 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item<'tcx>) { EntryKind::Fn(self.lazy(data)) } - hir::ItemKind::Macro(ref macro_def) => { + hir::ItemKind::Macro(ref macro_def, _) => { EntryKind::MacroDef(self.lazy(macro_def.clone())) } hir::ItemKind::Mod(ref m) => { diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index f36847c7781..ec20e888333 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -14,7 +14,6 @@ use rustc_index::vec::Idx; use rustc_middle::hir::nested_filter; use rustc_span::def_id::StableCrateId; -use rustc_span::hygiene::MacroKind; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; @@ -232,7 +231,7 @@ pub fn opt_def_kind(self, local_def_id: LocalDefId) -> Option { ItemKind::Static(..) => DefKind::Static, ItemKind::Const(..) => DefKind::Const, ItemKind::Fn(..) => DefKind::Fn, - ItemKind::Macro(..) => DefKind::Macro(MacroKind::Bang), + ItemKind::Macro(_, macro_kind) => DefKind::Macro(macro_kind), ItemKind::Mod(..) => DefKind::Mod, ItemKind::OpaqueTy(..) => DefKind::OpaqueTy, ItemKind::TyAlias(..) => DefKind::TyAlias, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 3d69e8ba4e4..b545961245a 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1951,7 +1951,7 @@ 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 { + 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); diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 48594e73f5b..3dd9995fa00 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -564,7 +564,7 @@ fn update_macro_reachable_def( // privacy and mark them reachable. DefKind::Macro(_) => { let item = self.tcx.hir().expect_item(def_id); - if let hir::ItemKind::Macro(MacroDef { macro_rules: false, .. }) = item.kind { + 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); } @@ -686,7 +686,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { } } } - hir::ItemKind::Macro(ref macro_def) => { + hir::ItemKind::Macro(ref macro_def, _) => { self.update_reachability_from_macro(item.def_id, macro_def); } hir::ItemKind::ForeignMod { items, .. } => { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 04b0a18b12b..2fb69e438c4 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -990,6 +990,9 @@ pub struct Resolver<'a> { crate_loader: CrateLoader<'a>, macro_names: FxHashSet, builtin_macros: FxHashMap, + /// A small map keeping true kinds of built-in macros that appear to be fn-like on + /// the surface (`macro` items in libcore), but are actually attributes or derives. + builtin_macro_kinds: FxHashMap, registered_attrs: FxHashSet, registered_tools: RegisteredTools, macro_use_prelude: FxHashMap>, @@ -1261,6 +1264,10 @@ fn create_def( def_id } + + fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind { + self.builtin_macro_kinds.get(&def_id).copied().unwrap_or(MacroKind::Bang) + } } impl<'a> Resolver<'a> { @@ -1381,6 +1388,7 @@ pub fn new( crate_loader: CrateLoader::new(session, metadata_loader, crate_name), macro_names: FxHashSet::default(), builtin_macros: Default::default(), + builtin_macro_kinds: Default::default(), registered_attrs, registered_tools, macro_use_prelude: FxHashMap::default(), diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 89c2a0c74bd..e34d3e605ec 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -1209,7 +1209,13 @@ fn prohibit_imported_non_macro_attrs( // while still taking everything else from the source code. // If we already loaded this builtin macro, give a better error message than 'no such builtin macro'. match mem::replace(builtin_macro, BuiltinMacroState::AlreadySeen(item.span)) { - BuiltinMacroState::NotYetSeen(ext) => result.kind = ext, + BuiltinMacroState::NotYetSeen(ext) => { + result.kind = ext; + if item.id != ast::DUMMY_NODE_ID { + self.builtin_macro_kinds + .insert(self.local_def_id(item.id), result.macro_kind()); + } + } BuiltinMacroState::AlreadySeen(span) => { struct_span_err!( self.session, diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs index 3bb1d2ff357..8f50f445719 100644 --- a/compiler/rustc_save_analysis/src/sig.rs +++ b/compiler/rustc_save_analysis/src/sig.rs @@ -416,7 +416,7 @@ fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext< Ok(sig) } - hir::ItemKind::Macro(_) => { + hir::ItemKind::Macro(..) => { let mut text = "macro".to_owned(); let name = self.ident.to_string(); text.push_str(&name); diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 392144ca763..4a25b49eb2d 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -730,7 +730,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::Macro(..) | hir::ItemKind::Mod(_) | hir::ItemKind::GlobalAsm(_) => {} hir::ItemKind::ForeignMod { items, .. } => { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 76994f2ee17..1e0c1e8f1f3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1855,7 +1855,7 @@ fn clean_maybe_renamed_item( 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) => { + ItemKind::Macro(ref macro_def, _) => { let ty_vis = cx.tcx.visibility(def_id).clean(cx); MacroItem(Macro { source: display_macro_source(cx, name, macro_def, def_id, ty_vis), diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 696397c5f67..5ccc3dabe83 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -1164,7 +1164,7 @@ fn nested_visit_map(&mut self) -> Self::Map { fn visit_item(&mut self, item: &'hir hir::Item<'_>) { let name = match &item.kind { - hir::ItemKind::Macro(ref macro_def) => { + 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(); diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index e8b3a0929db..1693034db0e 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -325,7 +325,7 @@ fn visit_item( om.items.push((item, renamed)) } - hir::ItemKind::Macro(ref macro_def) => { + 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: diff --git a/src/tools/clippy/clippy_lints/src/utils/inspector.rs b/src/tools/clippy/clippy_lints/src/utils/inspector.rs index 86911483137..dc48ea3f4f9 100644 --- a/src/tools/clippy/clippy_lints/src/utils/inspector.rs +++ b/src/tools/clippy/clippy_lints/src/utils/inspector.rs @@ -373,7 +373,7 @@ fn print_item(cx: &LateContext<'_>, item: &hir::Item<'_>) { let item_ty = cx.tcx.type_of(did); println!("function of type {:#?}", item_ty); }, - hir::ItemKind::Macro(ref macro_def) => { + hir::ItemKind::Macro(ref macro_def, _) => { if macro_def.macro_rules { println!("macro introduced by `macro_rules!`"); } else { -- GitLab