From 0b855bcdc9b0fafa5a4a4330e10655105daf27cb Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Thu, 7 Aug 2025 19:21:16 -0700 Subject: Switch to a bitflags `MacroKinds` to support macros with more than one kind Review everything that uses `MacroKind`, and switch anything that could refer to more than one kind to use `MacroKinds`. Add a new `SyntaxExtensionKind::MacroRules` for `macro_rules!` macros, using the concrete `MacroRulesMacroExpander` type, and have it track which kinds it can handle. Eliminate the separate optional `attr_ext`, now that a `SyntaxExtension` can handle multiple macro kinds. This also avoids the need to downcast when calling methods on `MacroRulesMacroExpander`, such as `get_unused_rule`. Integrate macro kind checking into name resolution's `sub_namespace_match`, so that we only find a macro if it's the right type, and eliminate the special-case hack for attributes. --- compiler/rustc_hir/src/def.rs | 59 ++++++++++++++++++++++++++++++++++++++----- compiler/rustc_hir/src/hir.rs | 7 +++-- 2 files changed, 56 insertions(+), 10 deletions(-) (limited to 'compiler/rustc_hir/src') diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 339d4e2eab7..79319e24266 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -31,6 +31,53 @@ pub enum CtorKind { Const, } +/// A set of macro kinds, for macros that can have more than one kind +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable, Hash, Debug)] +#[derive(HashStable_Generic)] +pub struct MacroKinds(u8); +bitflags::bitflags! { + impl MacroKinds: u8 { + const BANG = 1 << 0; + const ATTR = 1 << 1; + const DERIVE = 1 << 2; + } +} + +impl From for MacroKinds { + fn from(kind: MacroKind) -> Self { + match kind { + MacroKind::Bang => Self::BANG, + MacroKind::Attr => Self::ATTR, + MacroKind::Derive => Self::DERIVE, + } + } +} + +impl MacroKinds { + /// Convert the MacroKinds to a static string. + /// + /// This hardcodes all the possibilities, in order to return a static string. + pub fn descr(self) -> &'static str { + match self { + // FIXME: change this to "function-like macro" and fix all tests + Self::BANG => "macro", + Self::ATTR => "attribute macro", + Self::DERIVE => "derive macro", + _ if self == (Self::ATTR | Self::BANG) => "attribute/function macro", + _ if self == (Self::DERIVE | Self::BANG) => "derive/function macro", + _ if self == (Self::ATTR | Self::DERIVE) => "attribute/derive macro", + _ if self.is_all() => "attribute/derive/function macro", + _ if self.is_empty() => "useless macro", + _ => unreachable!(), + } + } + + /// Return an indefinite article (a/an) for use with `descr()` + pub fn article(self) -> &'static str { + if self.contains(Self::ATTR) { "an" } else { "a" } + } +} + /// An attribute that is not a macro; e.g., `#[inline]` or `#[rustfmt::skip]`. #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug, HashStable_Generic)] pub enum NonMacroAttrKind { @@ -101,7 +148,7 @@ pub enum DefKind { AssocConst, // Macro namespace - Macro(MacroKind), + Macro(MacroKinds), // Not namespaced (or they are, but we don't treat them so) ExternCrate, @@ -177,7 +224,7 @@ impl DefKind { DefKind::AssocConst => "associated constant", DefKind::TyParam => "type parameter", DefKind::ConstParam => "const parameter", - DefKind::Macro(macro_kind) => macro_kind.descr(), + DefKind::Macro(kinds) => kinds.descr(), DefKind::LifetimeParam => "lifetime parameter", DefKind::Use => "import", DefKind::ForeignMod => "foreign module", @@ -208,7 +255,7 @@ impl DefKind { | DefKind::Use | DefKind::InlineConst | DefKind::ExternCrate => "an", - DefKind::Macro(macro_kind) => macro_kind.article(), + DefKind::Macro(kinds) => kinds.article(), _ => "a", } } @@ -845,10 +892,10 @@ impl Res { ) } - pub fn macro_kind(self) -> Option { + pub fn macro_kinds(self) -> Option { match self { - Res::Def(DefKind::Macro(kind), _) => Some(kind), - Res::NonMacroAttr(..) => Some(MacroKind::Attr), + Res::Def(DefKind::Macro(kinds), _) => Some(kinds), + Res::NonMacroAttr(..) => Some(MacroKinds::ATTR), _ => None, } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 34db6f92d92..8358a11e586 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -20,7 +20,6 @@ use rustc_data_structures::tagged_ptr::TaggedRef; use rustc_index::IndexVec; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::def_id::LocalDefId; -use rustc_span::hygiene::MacroKind; use rustc_span::source_map::Spanned; use rustc_span::{BytePos, DUMMY_SP, ErrorGuaranteed, Ident, Span, Symbol, kw, sym}; use rustc_target::asm::InlineAsmRegOrRegClass; @@ -30,7 +29,7 @@ use tracing::debug; use crate::LangItem; use crate::attrs::AttributeKind; -use crate::def::{CtorKind, DefKind, PerNS, Res}; +use crate::def::{CtorKind, DefKind, MacroKinds, PerNS, Res}; use crate::def_id::{DefId, LocalDefIdMap}; pub(crate) use crate::hir_id::{HirId, ItemLocalId, ItemLocalMap, OwnerId}; use crate::intravisit::{FnKind, VisitorExt}; @@ -4156,7 +4155,7 @@ impl<'hir> Item<'hir> { expect_fn, (Ident, &FnSig<'hir>, &'hir Generics<'hir>, BodyId), ItemKind::Fn { ident, sig, generics, body, .. }, (*ident, sig, generics, *body); - expect_macro, (Ident, &ast::MacroDef, MacroKind), + expect_macro, (Ident, &ast::MacroDef, MacroKinds), ItemKind::Macro(ident, def, mk), (*ident, def, *mk); expect_mod, (Ident, &'hir Mod<'hir>), ItemKind::Mod(ident, m), (*ident, m); @@ -4335,7 +4334,7 @@ pub enum ItemKind<'hir> { has_body: bool, }, /// A MBE macro definition (`macro_rules!` or `macro`). - Macro(Ident, &'hir ast::MacroDef, MacroKind), + Macro(Ident, &'hir ast::MacroDef, MacroKinds), /// A module. Mod(Ident, &'hir Mod<'hir>), /// An external module, e.g. `extern { .. }`. -- cgit 1.4.1-3-g733a5