Skip to content

Commit 646c5aa

Browse files
committed
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.
1 parent ffb9d94 commit 646c5aa

File tree

20 files changed

+214
-120
lines changed

20 files changed

+214
-120
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4603,6 +4603,7 @@ dependencies = [
46034603
name = "rustc_span"
46044604
version = "0.0.0"
46054605
dependencies = [
4606+
"bitflags",
46064607
"blake3",
46074608
"derive-where",
46084609
"indexmap",

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -465,14 +465,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
465465
let body = P(self.lower_delim_args(body));
466466
let def_id = self.local_def_id(id);
467467
let def_kind = self.tcx.def_kind(def_id);
468-
let DefKind::Macro(macro_kind) = def_kind else {
468+
let DefKind::Macro(macro_kinds) = def_kind else {
469469
unreachable!(
470470
"expected DefKind::Macro for macro item, found {}",
471471
def_kind.descr(def_id.to_def_id())
472472
);
473473
};
474474
let macro_def = self.arena.alloc(ast::MacroDef { body, macro_rules: *macro_rules });
475-
hir::ItemKind::Macro(ident, macro_def, macro_kind)
475+
hir::ItemKind::Macro(ident, macro_def, macro_kinds)
476476
}
477477
ItemKind::Delegation(box delegation) => {
478478
let delegation_results = self.lower_delegation(delegation, id, false);

compiler/rustc_expand/src/base.rs

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use rustc_session::parse::ParseSess;
2727
use rustc_session::{Limit, Session};
2828
use rustc_span::def_id::{CrateNum, DefId, LocalDefId};
2929
use rustc_span::edition::Edition;
30-
use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId, MacroKind};
30+
use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId, MacroKind, MacroKinds};
3131
use rustc_span::source_map::SourceMap;
3232
use rustc_span::{DUMMY_SP, FileName, Ident, Span, Symbol, kw, sym};
3333
use smallvec::{SmallVec, smallvec};
@@ -719,6 +719,9 @@ impl MacResult for DummyResult {
719719
/// A syntax extension kind.
720720
#[derive(Clone)]
721721
pub enum SyntaxExtensionKind {
722+
/// A `macro_rules!` macro that can work as any `MacroKind`
723+
MacroRules(Arc<crate::MacroRulesMacroExpander>),
724+
722725
/// A token-based function-like macro.
723726
Bang(
724727
/// An expander with signature TokenStream -> TokenStream.
@@ -776,6 +779,34 @@ pub enum SyntaxExtensionKind {
776779
GlobDelegation(Arc<dyn GlobDelegationExpander + sync::DynSync + sync::DynSend>),
777780
}
778781

782+
impl SyntaxExtensionKind {
783+
/// Returns `Some(expander)` for a macro usable as a `LegacyBang`; otherwise returns `None`
784+
///
785+
/// This includes a `MacroRules` with function-like rules.
786+
pub fn as_legacy_bang(&self) -> Option<&(dyn TTMacroExpander + sync::DynSync + sync::DynSend)> {
787+
match self {
788+
SyntaxExtensionKind::LegacyBang(exp) => Some(exp.as_ref()),
789+
SyntaxExtensionKind::MacroRules(exp) if exp.kinds().contains(MacroKinds::BANG) => {
790+
Some(exp.as_ref())
791+
}
792+
_ => None,
793+
}
794+
}
795+
796+
/// Returns `Some(expander)` for a macro usable as an `Attr`; otherwise returns `None`
797+
///
798+
/// This includes a `MacroRules` with `attr` rules.
799+
pub fn as_attr(&self) -> Option<&(dyn AttrProcMacro + sync::DynSync + sync::DynSend)> {
800+
match self {
801+
SyntaxExtensionKind::Attr(exp) => Some(exp.as_ref()),
802+
SyntaxExtensionKind::MacroRules(exp) if exp.kinds().contains(MacroKinds::ATTR) => {
803+
Some(exp.as_ref())
804+
}
805+
_ => None,
806+
}
807+
}
808+
}
809+
779810
/// A struct representing a macro definition in "lowered" form ready for expansion.
780811
pub struct SyntaxExtension {
781812
/// A syntax extension kind.
@@ -805,18 +836,19 @@ pub struct SyntaxExtension {
805836
}
806837

807838
impl SyntaxExtension {
808-
/// Returns which kind of macro calls this syntax extension.
809-
pub fn macro_kind(&self) -> MacroKind {
839+
/// Returns which kinds of macro call this syntax extension.
840+
pub fn macro_kinds(&self) -> MacroKinds {
810841
match self.kind {
811842
SyntaxExtensionKind::Bang(..)
812843
| SyntaxExtensionKind::LegacyBang(..)
813-
| SyntaxExtensionKind::GlobDelegation(..) => MacroKind::Bang,
844+
| SyntaxExtensionKind::GlobDelegation(..) => MacroKinds::BANG,
814845
SyntaxExtensionKind::Attr(..)
815846
| SyntaxExtensionKind::LegacyAttr(..)
816-
| SyntaxExtensionKind::NonMacroAttr => MacroKind::Attr,
847+
| SyntaxExtensionKind::NonMacroAttr => MacroKinds::ATTR,
817848
SyntaxExtensionKind::Derive(..) | SyntaxExtensionKind::LegacyDerive(..) => {
818-
MacroKind::Derive
849+
MacroKinds::DERIVE
819850
}
851+
SyntaxExtensionKind::MacroRules(ref m) => m.kinds(),
820852
}
821853
}
822854

@@ -1025,11 +1057,12 @@ impl SyntaxExtension {
10251057
parent: LocalExpnId,
10261058
call_site: Span,
10271059
descr: Symbol,
1060+
kind: MacroKind,
10281061
macro_def_id: Option<DefId>,
10291062
parent_module: Option<DefId>,
10301063
) -> ExpnData {
10311064
ExpnData::new(
1032-
ExpnKind::Macro(self.macro_kind(), descr),
1065+
ExpnKind::Macro(kind, descr),
10331066
parent.to_expn_id(),
10341067
call_site,
10351068
self.span,

compiler/rustc_expand/src/expand.rs

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -737,8 +737,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
737737

738738
let (fragment_kind, span) = (invoc.fragment_kind, invoc.span());
739739
ExpandResult::Ready(match invoc.kind {
740-
InvocationKind::Bang { mac, span } => match ext {
741-
SyntaxExtensionKind::Bang(expander) => {
740+
InvocationKind::Bang { mac, span } => {
741+
if let SyntaxExtensionKind::Bang(expander) = ext {
742742
match expander.expand(self.cx, span, mac.args.tokens.clone()) {
743743
Ok(tok_result) => {
744744
let fragment =
@@ -756,8 +756,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
756756
}
757757
Err(guar) => return ExpandResult::Ready(fragment_kind.dummy(span, guar)),
758758
}
759-
}
760-
SyntaxExtensionKind::LegacyBang(expander) => {
759+
} else if let Some(expander) = ext.as_legacy_bang() {
761760
let tok_result = match expander.expand(self.cx, span, mac.args.tokens.clone()) {
762761
ExpandResult::Ready(tok_result) => tok_result,
763762
ExpandResult::Retry(_) => {
@@ -777,11 +776,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
777776
let guar = self.error_wrong_fragment_kind(fragment_kind, &mac, span);
778777
fragment_kind.dummy(span, guar)
779778
}
779+
} else {
780+
unreachable!();
780781
}
781-
_ => unreachable!(),
782-
},
783-
InvocationKind::Attr { attr, pos, mut item, derives } => match ext {
784-
SyntaxExtensionKind::Attr(expander) => {
782+
}
783+
InvocationKind::Attr { attr, pos, mut item, derives } => {
784+
if let Some(expander) = ext.as_attr() {
785785
self.gate_proc_macro_input(&item);
786786
self.gate_proc_macro_attr_item(span, &item);
787787
let tokens = match &item {
@@ -836,8 +836,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
836836
}
837837
Err(guar) => return ExpandResult::Ready(fragment_kind.dummy(span, guar)),
838838
}
839-
}
840-
SyntaxExtensionKind::LegacyAttr(expander) => {
839+
} else if let SyntaxExtensionKind::LegacyAttr(expander) = ext {
841840
match validate_attr::parse_meta(&self.cx.sess.psess, &attr) {
842841
Ok(meta) => {
843842
let item_clone = macro_stats.then(|| item.clone());
@@ -879,15 +878,15 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
879878
fragment_kind.expect_from_annotatables(iter::once(item))
880879
}
881880
}
882-
}
883-
SyntaxExtensionKind::NonMacroAttr => {
881+
} else if let SyntaxExtensionKind::NonMacroAttr = ext {
884882
// `-Zmacro-stats` ignores these because they don't do any real expansion.
885883
self.cx.expanded_inert_attrs.mark(&attr);
886884
item.visit_attrs(|attrs| attrs.insert(pos, attr));
887885
fragment_kind.expect_from_annotatables(iter::once(item))
886+
} else {
887+
unreachable!();
888888
}
889-
_ => unreachable!(),
890-
},
889+
}
891890
InvocationKind::Derive { path, item, is_const } => match ext {
892891
SyntaxExtensionKind::Derive(expander)
893892
| SyntaxExtensionKind::LegacyDerive(expander) => {

compiler/rustc_expand/src/mbe/macro_rules.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use rustc_parse::parser::{Parser, Recovery};
2525
use rustc_session::Session;
2626
use rustc_session::parse::{ParseSess, feature_err};
2727
use rustc_span::edition::Edition;
28-
use rustc_span::hygiene::Transparency;
28+
use rustc_span::hygiene::{MacroKinds, Transparency};
2929
use rustc_span::{Ident, Span, kw, sym};
3030
use tracing::{debug, instrument, trace, trace_span};
3131

@@ -144,6 +144,7 @@ pub struct MacroRulesMacroExpander {
144144
name: Ident,
145145
span: Span,
146146
transparency: Transparency,
147+
kinds: MacroKinds,
147148
rules: Vec<MacroRule>,
148149
}
149150

@@ -158,6 +159,10 @@ impl MacroRulesMacroExpander {
158159
};
159160
if has_compile_error_macro(rhs) { None } else { Some((&self.name, span)) }
160161
}
162+
163+
pub fn kinds(&self) -> MacroKinds {
164+
self.kinds
165+
}
161166
}
162167

163168
impl TTMacroExpander for MacroRulesMacroExpander {
@@ -540,13 +545,13 @@ pub fn compile_declarative_macro(
540545
span: Span,
541546
node_id: NodeId,
542547
edition: Edition,
543-
) -> (SyntaxExtension, Option<Arc<SyntaxExtension>>, usize) {
548+
) -> (SyntaxExtension, usize) {
544549
let mk_syn_ext = |kind| {
545550
let is_local = is_defined_in_current_crate(node_id);
546551
SyntaxExtension::new(sess, kind, span, Vec::new(), edition, ident.name, attrs, is_local)
547552
};
548-
let mk_bang_ext = |expander| mk_syn_ext(SyntaxExtensionKind::LegacyBang(expander));
549-
let dummy_syn_ext = |guar| (mk_bang_ext(Arc::new(DummyExpander(guar))), None, 0);
553+
let dummy_syn_ext =
554+
|guar| (mk_syn_ext(SyntaxExtensionKind::LegacyBang(Arc::new(DummyExpander(guar)))), 0);
550555

551556
let macro_rules = macro_def.macro_rules;
552557
let exp_sep = if macro_rules { exp!(Semi) } else { exp!(Comma) };
@@ -559,12 +564,12 @@ pub fn compile_declarative_macro(
559564
let mut guar = None;
560565
let mut check_emission = |ret: Result<(), ErrorGuaranteed>| guar = guar.or(ret.err());
561566

562-
let mut has_attr_rules = false;
567+
let mut kinds = MacroKinds::empty();
563568
let mut rules = Vec::new();
564569

565570
while p.token != token::Eof {
566571
let args = if p.eat_keyword_noexpect(sym::attr) {
567-
has_attr_rules = true;
572+
kinds |= MacroKinds::ATTR;
568573
if !features.macro_attr() {
569574
feature_err(sess, sym::macro_attr, span, "`macro_rules!` attributes are unstable")
570575
.emit();
@@ -581,6 +586,7 @@ pub fn compile_declarative_macro(
581586
}
582587
Some(args)
583588
} else {
589+
kinds |= MacroKinds::BANG;
584590
None
585591
};
586592
let lhs_tt = p.parse_token_tree();
@@ -627,6 +633,7 @@ pub fn compile_declarative_macro(
627633
let guar = sess.dcx().span_err(span, "macros must contain at least one rule");
628634
return dummy_syn_ext(guar);
629635
}
636+
assert!(!kinds.is_empty());
630637

631638
let transparency = find_attr!(attrs, AttributeKind::MacroTransparency(x) => *x)
632639
.unwrap_or(Transparency::fallback(macro_rules));
@@ -640,12 +647,8 @@ pub fn compile_declarative_macro(
640647
// Return the number of rules for unused rule linting, if this is a local macro.
641648
let nrules = if is_defined_in_current_crate(node_id) { rules.len() } else { 0 };
642649

643-
let exp = Arc::new(MacroRulesMacroExpander { name: ident, span, node_id, transparency, rules });
644-
let opt_attr_ext = has_attr_rules.then(|| {
645-
let exp = Arc::clone(&exp);
646-
Arc::new(mk_syn_ext(SyntaxExtensionKind::Attr(exp)))
647-
});
648-
(mk_bang_ext(exp), opt_attr_ext, nrules)
650+
let exp = MacroRulesMacroExpander { name: ident, kinds, span, node_id, transparency, rules };
651+
(mk_syn_ext(SyntaxExtensionKind::MacroRules(Arc::new(exp))), nrules)
649652
}
650653

651654
fn check_no_eof(sess: &Session, p: &Parser<'_>, msg: &'static str) -> Option<ErrorGuaranteed> {

compiler/rustc_hir/src/def.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_data_structures::unord::UnordMap;
88
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
99
use rustc_span::Symbol;
1010
use rustc_span::def_id::{DefId, LocalDefId};
11-
use rustc_span::hygiene::MacroKind;
11+
use rustc_span::hygiene::MacroKinds;
1212

1313
use crate::definitions::DefPathData;
1414
use crate::hir;
@@ -101,7 +101,7 @@ pub enum DefKind {
101101
AssocConst,
102102

103103
// Macro namespace
104-
Macro(MacroKind),
104+
Macro(MacroKinds),
105105

106106
// Not namespaced (or they are, but we don't treat them so)
107107
ExternCrate,
@@ -177,7 +177,7 @@ impl DefKind {
177177
DefKind::AssocConst => "associated constant",
178178
DefKind::TyParam => "type parameter",
179179
DefKind::ConstParam => "const parameter",
180-
DefKind::Macro(macro_kind) => macro_kind.descr(),
180+
DefKind::Macro(kinds) => kinds.descr(),
181181
DefKind::LifetimeParam => "lifetime parameter",
182182
DefKind::Use => "import",
183183
DefKind::ForeignMod => "foreign module",
@@ -208,7 +208,7 @@ impl DefKind {
208208
| DefKind::Use
209209
| DefKind::InlineConst
210210
| DefKind::ExternCrate => "an",
211-
DefKind::Macro(macro_kind) => macro_kind.article(),
211+
DefKind::Macro(kinds) => kinds.article(),
212212
_ => "a",
213213
}
214214
}
@@ -803,10 +803,10 @@ impl<Id> Res<Id> {
803803
)
804804
}
805805

806-
pub fn macro_kind(self) -> Option<MacroKind> {
806+
pub fn macro_kinds(self) -> Option<MacroKinds> {
807807
match self {
808-
Res::Def(DefKind::Macro(kind), _) => Some(kind),
809-
Res::NonMacroAttr(..) => Some(MacroKind::Attr),
808+
Res::Def(DefKind::Macro(kinds), _) => Some(kinds),
809+
Res::NonMacroAttr(..) => Some(MacroKinds::ATTR),
810810
_ => None,
811811
}
812812
}

compiler/rustc_hir/src/hir.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use rustc_data_structures::tagged_ptr::TaggedRef;
2020
use rustc_index::IndexVec;
2121
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
2222
use rustc_span::def_id::LocalDefId;
23-
use rustc_span::hygiene::MacroKind;
23+
use rustc_span::hygiene::MacroKinds;
2424
use rustc_span::source_map::Spanned;
2525
use rustc_span::{BytePos, DUMMY_SP, ErrorGuaranteed, Ident, Span, Symbol, kw, sym};
2626
use rustc_target::asm::InlineAsmRegOrRegClass;
@@ -4156,7 +4156,7 @@ impl<'hir> Item<'hir> {
41564156
expect_fn, (Ident, &FnSig<'hir>, &'hir Generics<'hir>, BodyId),
41574157
ItemKind::Fn { ident, sig, generics, body, .. }, (*ident, sig, generics, *body);
41584158

4159-
expect_macro, (Ident, &ast::MacroDef, MacroKind),
4159+
expect_macro, (Ident, &ast::MacroDef, MacroKinds),
41604160
ItemKind::Macro(ident, def, mk), (*ident, def, *mk);
41614161

41624162
expect_mod, (Ident, &'hir Mod<'hir>), ItemKind::Mod(ident, m), (*ident, m);
@@ -4335,7 +4335,7 @@ pub enum ItemKind<'hir> {
43354335
has_body: bool,
43364336
},
43374337
/// A MBE macro definition (`macro_rules!` or `macro`).
4338-
Macro(Ident, &'hir ast::MacroDef, MacroKind),
4338+
Macro(Ident, &'hir ast::MacroDef, MacroKinds),
43394339
/// A module.
43404340
Mod(Ident, &'hir Mod<'hir>),
43414341
/// An external module, e.g. `extern { .. }`.

compiler/rustc_lint/src/non_local_def.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_hir::{Body, HirId, Item, ItemKind, Node, Path, TyKind};
55
use rustc_middle::ty::TyCtxt;
66
use rustc_session::{declare_lint, impl_lint_pass};
77
use rustc_span::def_id::{DefId, LOCAL_CRATE};
8-
use rustc_span::{ExpnKind, MacroKind, Span, kw, sym};
8+
use rustc_span::{ExpnKind, Span, kw, sym};
99

1010
use crate::lints::{NonLocalDefinitionsCargoUpdateNote, NonLocalDefinitionsDiag};
1111
use crate::{LateContext, LateLintPass, LintContext, fluent_generated as fluent};
@@ -240,7 +240,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
240240
},
241241
)
242242
}
243-
ItemKind::Macro(_, _macro, MacroKind::Bang)
243+
ItemKind::Macro(_, _macro, _kinds)
244244
if cx.tcx.has_attr(item.owner_id.def_id, sym::macro_export) =>
245245
{
246246
cx.emit_span_lint(

compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1981,7 +1981,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
19811981
def_key.disambiguated_data.data = DefPathData::MacroNs(name);
19821982

19831983
let def_id = id.to_def_id();
1984-
self.tables.def_kind.set_some(def_id.index, DefKind::Macro(macro_kind));
1984+
self.tables.def_kind.set_some(def_id.index, DefKind::Macro(macro_kind.into()));
19851985
self.tables.proc_macro.set_some(def_id.index, macro_kind);
19861986
self.encode_attrs(id);
19871987
record!(self.tables.def_keys[def_id] <- def_key);

compiler/rustc_metadata/src/rmeta/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use rustc_serialize::opaque::FileEncoder;
3535
use rustc_session::config::{SymbolManglingVersion, TargetModifier};
3636
use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib};
3737
use rustc_span::edition::Edition;
38-
use rustc_span::hygiene::{ExpnIndex, MacroKind, SyntaxContextKey};
38+
use rustc_span::hygiene::{ExpnIndex, MacroKind, MacroKinds, SyntaxContextKey};
3939
use rustc_span::{self, ExpnData, ExpnHash, ExpnId, Ident, Span, Symbol};
4040
use rustc_target::spec::{PanicStrategy, TargetTuple};
4141
use table::TableBuilder;

0 commit comments

Comments
 (0)