diff options
Diffstat (limited to 'compiler/rustc_expand/src')
| -rw-r--r-- | compiler/rustc_expand/src/base.rs | 20 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/mbe/macro_rules.rs | 65 |
2 files changed, 58 insertions, 27 deletions
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index d6d89808839..757a7e1c8e7 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -34,6 +34,7 @@ use thin_vec::ThinVec; use crate::base::ast::MetaItemInner; use crate::errors; use crate::expand::{self, AstFragment, Invocation}; +use crate::mbe::macro_rules::ParserAnyMacro; use crate::module::DirOwnership; use crate::stats::MacroStat; @@ -262,6 +263,25 @@ impl<T, U> ExpandResult<T, U> { } } +impl<'cx> MacroExpanderResult<'cx> { + /// Creates a [`MacroExpanderResult::Ready`] from a [`TokenStream`]. + /// + /// The `TokenStream` is forwarded without any expansion. + pub fn from_tts( + cx: &'cx mut ExtCtxt<'_>, + tts: TokenStream, + site_span: Span, + arm_span: Span, + macro_ident: Ident, + ) -> Self { + // Emit the SEMICOLON_IN_EXPRESSIONS_FROM_MACROS deprecation lint. + let is_local = true; + + let parser = ParserAnyMacro::from_tts(cx, tts, site_span, arm_span, is_local, macro_ident); + ExpandResult::Ready(Box::new(parser)) + } +} + pub trait MultiItemModifier { /// `meta_item` is the attribute, and `item` is the item being modified. fn expand( diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 89547088f50..2d792355b27 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -96,6 +96,30 @@ impl<'a> ParserAnyMacro<'a> { ensure_complete_parse(parser, &path, kind.name(), site_span); fragment } + + #[instrument(skip(cx, tts))] + pub(crate) fn from_tts<'cx>( + cx: &'cx mut ExtCtxt<'a>, + tts: TokenStream, + site_span: Span, + arm_span: Span, + is_local: bool, + macro_ident: Ident, + ) -> Self { + Self { + parser: Parser::new(&cx.sess.psess, tts, None), + + // Pass along the original expansion site and the name of the macro + // so we can print a useful error message if the parse of the expanded + // macro leaves unparsed tokens. + site_span, + macro_ident, + lint_node_id: cx.current_expansion.lint_node_id, + is_trailing_mac: cx.current_expansion.is_trailing_mac, + arm_span, + is_local, + } + } } pub(super) struct MacroRule { @@ -207,9 +231,6 @@ fn expand_macro<'cx>( rules: &[MacroRule], ) -> Box<dyn MacResult + 'cx> { let psess = &cx.sess.psess; - // Macros defined in the current crate have a real node id, - // whereas macros from an external crate have a dummy id. - let is_local = node_id != DUMMY_NODE_ID; if cx.trace_macros() { let msg = format!("expanding `{}! {{ {} }}`", name, pprust::tts_to_string(&arg)); @@ -220,7 +241,7 @@ fn expand_macro<'cx>( let try_success_result = try_match_macro(psess, name, &arg, rules, &mut NoopTracker); match try_success_result { - Ok((i, rule, named_matches)) => { + Ok((rule_index, rule, named_matches)) => { let mbe::TokenTree::Delimited(rhs_span, _, ref rhs) = rule.rhs else { cx.dcx().span_bug(sp, "malformed macro rhs"); }; @@ -241,27 +262,13 @@ fn expand_macro<'cx>( trace_macros_note(&mut cx.expansions, sp, msg); } - let p = Parser::new(psess, tts, None); - + let is_local = is_defined_in_current_crate(node_id); if is_local { - cx.resolver.record_macro_rule_usage(node_id, i); + cx.resolver.record_macro_rule_usage(node_id, rule_index); } - // Let the context choose how to interpret the result. - // Weird, but useful for X-macros. - Box::new(ParserAnyMacro { - parser: p, - - // Pass along the original expansion site and the name of the macro - // so we can print a useful error message if the parse of the expanded - // macro leaves unparsed tokens. - site_span: sp, - macro_ident: name, - lint_node_id: cx.current_expansion.lint_node_id, - is_trailing_mac: cx.current_expansion.is_trailing_mac, - arm_span, - is_local, - }) + // Let the context choose how to interpret the result. Weird, but useful for X-macros. + Box::new(ParserAnyMacro::from_tts(cx, tts, sp, arm_span, is_local, name)) } Err(CanRetry::No(guar)) => { debug!("Will not retry matching as an error was emitted already"); @@ -373,9 +380,9 @@ pub fn compile_declarative_macro( node_id: NodeId, edition: Edition, ) -> (SyntaxExtension, usize) { - let is_local = node_id != DUMMY_NODE_ID; let mk_syn_ext = |expander| { let kind = SyntaxExtensionKind::LegacyBang(expander); + let is_local = is_defined_in_current_crate(node_id); SyntaxExtension::new(sess, kind, span, Vec::new(), edition, ident.name, attrs, is_local) }; let dummy_syn_ext = |guar| (mk_syn_ext(Arc::new(DummyExpander(guar))), 0); @@ -439,7 +446,7 @@ pub fn compile_declarative_macro( } // Return the number of rules for unused rule linting, if this is a local macro. - let nrules = if is_local { rules.len() } else { 0 }; + let nrules = if is_defined_in_current_crate(node_id) { rules.len() } else { 0 }; let expander = Arc::new(MacroRulesMacroExpander { name: ident, span, node_id, transparency, rules }); @@ -1034,9 +1041,7 @@ fn check_matcher_core<'tt>( // definition of this macro_rules, not while (re)parsing // the macro when compiling another crate that is using the // macro. (See #86567.) - // Macros defined in the current crate have a real node id, - // whereas macros from an external crate have a dummy id. - if node_id != DUMMY_NODE_ID + if is_defined_in_current_crate(node_id) && matches!(kind, NonterminalKind::Pat(PatParam { inferred: true })) && matches!( next_token, @@ -1296,6 +1301,12 @@ fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String { } } +fn is_defined_in_current_crate(node_id: NodeId) -> bool { + // Macros defined in the current crate have a real node id, + // whereas macros from an external crate have a dummy id. + node_id != DUMMY_NODE_ID +} + pub(super) fn parser_from_cx( psess: &ParseSess, mut tts: TokenStream, |
