Rollup merge of #155311 - cyrgani:expand-clean, r=Kivooeo,petrochenkov

various small `rustc_expand` cleanups

Each commit should be reviewable on its own.
This commit is contained in:
Jonathan Brouwer
2026-04-15 14:39:09 +02:00
committed by GitHub
16 changed files with 102 additions and 120 deletions
+10 -16
View File
@@ -409,17 +409,10 @@ pub trait GlobDelegationExpander {
fn expand(&self, ecx: &mut ExtCtxt<'_>) -> ExpandResult<Vec<(Ident, Option<Ident>)>, ()>;
}
// Use a macro because forwarding to a simple function has type system issues
macro_rules! make_stmts_default {
($me:expr) => {
$me.make_expr().map(|e| {
smallvec![ast::Stmt {
id: ast::DUMMY_NODE_ID,
span: e.span,
kind: ast::StmtKind::Expr(e),
}]
})
};
fn make_stmts_default(expr: Option<Box<ast::Expr>>) -> Option<SmallVec<[ast::Stmt; 1]>> {
expr.map(|e| {
smallvec![ast::Stmt { id: ast::DUMMY_NODE_ID, span: e.span, kind: ast::StmtKind::Expr(e) }]
})
}
/// The result of a macro expansion. The return values of the various
@@ -465,7 +458,7 @@ fn make_pat(self: Box<Self>) -> Option<Box<ast::Pat>> {
/// By default this attempts to create an expression statement,
/// returning None if that fails.
fn make_stmts(self: Box<Self>) -> Option<SmallVec<[ast::Stmt; 1]>> {
make_stmts_default!(self)
make_stmts_default(self.make_expr())
}
fn make_ty(self: Box<Self>) -> Option<Box<ast::Ty>> {
@@ -571,9 +564,10 @@ fn make_expr(self: Box<Self>) -> Option<Box<ast::Expr>> {
}
fn make_stmts(self: Box<Self>) -> Option<SmallVec<[ast::Stmt; 1]>> {
match self.stmts.as_ref().map_or(0, |s| s.len()) {
0 => make_stmts_default!(self),
_ => self.stmts,
if self.stmts.as_ref().is_none_or(|s| s.is_empty()) {
make_stmts_default(self.make_expr())
} else {
self.stmts
}
}
@@ -898,7 +892,7 @@ pub fn default(kind: SyntaxExtensionKind, edition: Edition) -> SyntaxExtension {
fn get_collapse_debuginfo(sess: &Session, attrs: &[hir::Attribute], ext: bool) -> bool {
let flag = sess.opts.cg.collapse_macro_debuginfo;
let attr = if let Some(info) = find_attr!(attrs, CollapseDebugInfo(info) => info) {
info.clone()
*info
} else if find_attr!(attrs, RustcBuiltinMacro { .. }) {
CollapseMacroDebuginfo::Yes
} else {
+13 -22
View File
@@ -106,33 +106,24 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -
// If the enabled feature is unstable, record it.
if UNSTABLE_LANG_FEATURES.iter().find(|f| feature_ident.name == f.name).is_some() {
// When the ICE comes from a standard library crate, there's a chance that the person
// hitting the ICE may be using -Zbuild-std or similar with an untested target.
// The bug is probably in the standard library and not the compiler in that case,
// but that doesn't really matter - we want a bug report.
if features.internal(feature_ident.name)
&& !STDLIB_STABLE_CRATES.contains(&crate_name)
{
sess.using_internal_features.store(true, std::sync::atomic::Ordering::Relaxed);
}
features.set_enabled_lang_feature(EnabledLangFeature {
gate_name: feature_ident.name,
attr_sp: feature_ident.span,
stable_since: None,
});
continue;
} else {
// Otherwise, the feature is unknown. Enable it as a lib feature.
// It will be checked later whether the feature really exists.
features.set_enabled_lib_feature(EnabledLibFeature {
gate_name: feature_ident.name,
attr_sp: feature_ident.span,
});
}
// Otherwise, the feature is unknown. Enable it as a lib feature.
// It will be checked later whether the feature really exists.
features.set_enabled_lib_feature(EnabledLibFeature {
gate_name: feature_ident.name,
attr_sp: feature_ident.span,
});
// Similar to above, detect internal lib features to suppress
// the ICE message that asks for a report.
// When the ICE comes from a standard library crate, there's a chance that the person
// hitting the ICE may be using -Zbuild-std or similar with an untested target.
// The bug is probably in the standard library and not the compiler in that case,
// but that doesn't really matter - we want a bug report.
if features.internal(feature_ident.name) && !STDLIB_STABLE_CRATES.contains(&crate_name)
{
sess.using_internal_features.store(true, std::sync::atomic::Ordering::Relaxed);
@@ -285,7 +276,7 @@ pub(crate) fn expand_cfg_attr(&self, cfg_attr: &Attribute, recursive: bool) -> V
let Some((cfg_predicate, expanded_attrs)) = rustc_attr_parsing::parse_cfg_attr(
cfg_attr,
&self.sess,
self.sess,
self.features,
self.lint_node_id,
) else {
@@ -422,7 +413,7 @@ pub(crate) fn maybe_emit_expr_attr_err(&self, attr: &Attribute) {
&& !attr.span.allows_unstable(sym::stmt_expr_attributes)
{
let mut err = feature_err(
&self.sess,
self.sess,
sym::stmt_expr_attributes,
attr.span,
msg!("attributes on expressions are experimental"),
+4 -4
View File
@@ -1050,7 +1050,7 @@ fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
return;
}
feature_err(
&self.cx.sess,
self.cx.sess,
sym::proc_macro_hygiene,
span,
format!("custom attributes cannot be applied to {kind}"),
@@ -1085,7 +1085,7 @@ fn visit_item(&mut self, item: &'ast ast::Item) {
}
if !self.cx.ecfg.features.proc_macro_hygiene() {
annotatable.visit_with(&mut GateProcMacroInput { sess: &self.cx.sess });
annotatable.visit_with(&mut GateProcMacroInput { sess: self.cx.sess });
}
}
@@ -1474,7 +1474,7 @@ fn collect_use_tree_leaves(ut: &ast::UseTree, idents: &mut Vec<Ident>) {
}
}
let mut idents = Vec::new();
collect_use_tree_leaves(&ut, &mut idents);
collect_use_tree_leaves(ut, &mut idents);
idents
} else {
self.kind.ident().into_iter().collect()
@@ -1482,7 +1482,7 @@ fn collect_use_tree_leaves(ut: &ast::UseTree, idents: &mut Vec<Ident>) {
}
fn as_target(&self) -> Target {
Target::from_ast_item(&*self)
Target::from_ast_item(self)
}
}
+22 -27
View File
@@ -288,27 +288,24 @@ pub(super) fn emit_frag_parse_err(
_ => annotate_err_with_kind(&mut e, kind, site_span),
};
let mut bindings_rules = vec![];
for rule in bindings {
let MacroRule::Func { lhs, .. } = rule else { continue };
for param in lhs {
let MatcherLoc::MetaVarDecl { bind, .. } = param else { continue };
bindings_rules.push(*bind);
}
}
let mut matched_rule_bindings_rules = vec![];
for param in matched_rule_bindings {
let MatcherLoc::MetaVarDecl { bind, .. } = param else { continue };
matched_rule_bindings_rules.push(*bind);
}
let matched_rule_bindings_names: Vec<_> =
matched_rule_bindings_rules.iter().map(|bind| bind.name).collect();
let bindings_name: Vec<_> = bindings_rules.iter().map(|bind| bind.name).collect();
if parser.token.kind == token::Dollar {
parser.bump();
if let token::Ident(name, _) = parser.token.kind {
let mut bindings_names = vec![];
for rule in bindings {
let MacroRule::Func { lhs, .. } = rule else { continue };
for param in lhs {
let MatcherLoc::MetaVarDecl { bind, .. } = param else { continue };
bindings_names.push(bind.name);
}
}
let mut matched_rule_bindings_names = vec![];
for param in matched_rule_bindings {
let MatcherLoc::MetaVarDecl { bind, .. } = param else { continue };
matched_rule_bindings_names.push(bind.name);
}
if let Some(matched_name) = rustc_span::edit_distance::find_best_match_for_name(
&matched_rule_bindings_names[..],
name,
@@ -316,24 +313,22 @@ pub(super) fn emit_frag_parse_err(
) {
e.span_suggestion_verbose(
parser.token.span,
"there is a macro metavariable with similar name",
format!("{matched_name}"),
"there is a macro metavariable with a similar name",
matched_name,
Applicability::MaybeIncorrect,
);
} else if bindings_name.contains(&name) {
} else if bindings_names.contains(&name) {
e.span_label(
parser.token.span,
format!(
"there is an macro metavariable with this name in another macro matcher"
),
"there is an macro metavariable with this name in another macro matcher",
);
} else if let Some(matched_name) =
rustc_span::edit_distance::find_best_match_for_name(&bindings_name[..], name, None)
rustc_span::edit_distance::find_best_match_for_name(&bindings_names[..], name, None)
{
e.span_suggestion_verbose(
parser.token.span,
"there is a macro metavariable with a similar name in another macro matcher",
format!("{matched_name}"),
matched_name,
Applicability::MaybeIncorrect,
);
} else {
@@ -343,7 +338,7 @@ pub(super) fn emit_frag_parse_err(
.collect::<Vec<_>>()
.join(", ");
e.span_label(parser.token.span, format!("macro metavariable not found"));
e.span_label(parser.token.span, "macro metavariable not found");
if !matched_rule_bindings_names.is_empty() {
e.note(format!("available metavariable names are: {msg}"));
}
@@ -199,8 +199,8 @@ fn inner(
let idx_seq = idx_first - 1;
inner(&seq.tts, locs, next_metavar, seq_depth + 1);
if let Some(separator) = &seq.separator {
locs.push(MatcherLoc::SequenceSep { separator: separator.clone() });
if let Some(separator) = seq.separator {
locs.push(MatcherLoc::SequenceSep { separator });
locs.push(MatcherLoc::SequenceKleeneOpAfterSep { idx_first });
} else {
locs.push(MatcherLoc::SequenceKleeneOpNoSep { op, idx_first });
+2 -2
View File
@@ -214,7 +214,7 @@ fn parse_tree<'a>(
// during parsing.
let mut next = outer_iter.next();
let mut iter_storage;
let mut iter: &mut TokenStreamIter<'_> = match next {
let iter: &mut TokenStreamIter<'_> = match next {
Some(tokenstream::TokenTree::Delimited(.., delim, tts)) if delim.skip() => {
iter_storage = tts.iter();
next = iter_storage.next();
@@ -284,7 +284,7 @@ fn parse_tree<'a>(
let sequence = parse(tts, part, sess, node_id, features, edition);
// Get the Kleene operator and optional separator
let (separator, kleene) =
parse_sep_and_kleene_op(&mut iter, delim_span.entire(), sess);
parse_sep_and_kleene_op(iter, delim_span.entire(), sess);
// Count the number of captured "names" (i.e., named metavars)
let num_captures =
if part.is_pattern() { count_metavar_decls(&sequence) } else { 0 };
+3 -3
View File
@@ -396,7 +396,7 @@ fn transcribe_sequence<'tx, 'itp>(
// The first time we encounter the sequence we push it to the stack. It
// then gets reused (see the beginning of the loop) until we are done
// repeating.
tscx.stack.push(Frame::new_sequence(seq_rep, seq.separator.clone(), seq.kleene.op));
tscx.stack.push(Frame::new_sequence(seq_rep, seq.separator, seq.kleene.op));
}
}
}
@@ -629,7 +629,7 @@ fn metavar_expr_concat<'tx>(
) -> PResult<'tx, TokenTree> {
let dcx = tscx.psess.dcx();
let mut concatenated = String::new();
for element in elements.into_iter() {
for element in elements {
let symbol = match element {
MetaVarExprConcatElem::Ident(elem) => elem.name,
MetaVarExprConcatElem::Literal(elem) => *elem,
@@ -747,7 +747,7 @@ fn maybe_use_metavar_location(
TokenTree::Token(Token { kind, span }, spacing) => {
let span = metavar_span.with_ctxt(span.ctxt());
with_metavar_spans(|mspans| mspans.insert(span, metavar_span));
TokenTree::Token(Token { kind: kind.clone(), span }, *spacing)
TokenTree::Token(Token { kind: *kind, span }, *spacing)
}
TokenTree::Delimited(dspan, dspacing, delimiter, tts) => {
let open = metavar_span.with_ctxt(dspan.open.ctxt());
+1 -1
View File
@@ -77,7 +77,7 @@ pub(crate) fn parse_external_mod(
Some(span),
));
let (inner_attrs, items, inner_span) =
parser.parse_mod(exp!(Eof)).map_err(|err| ModError::ParserError(err))?;
parser.parse_mod(exp!(Eof)).map_err(ModError::ParserError)?;
attrs.extend(inner_attrs);
(items, inner_span, mp.file_path)
};
+23 -25
View File
@@ -1,5 +1,6 @@
use rustc_ast as ast;
use rustc_ast::tokenstream::TokenStream;
use rustc_data_structures::profiling::TimingGuard;
use rustc_errors::ErrorGuaranteed;
use rustc_middle::ty::{self, TyCtxt};
use rustc_parse::parser::{AllowConstBlockItems, ForceCollect, Parser};
@@ -19,6 +20,16 @@ fn exec_strategy(sess: &Session) -> impl pm::bridge::server::ExecutionStrategy +
}
}
fn record_expand_proc_macro<'a>(
ecx: &ExtCtxt<'a>,
name: &'static str,
span: Span,
) -> TimingGuard<'a> {
ecx.sess.prof.generic_activity_with_arg_recorder(name, |recorder| {
recorder.record_arg_with_span(ecx.sess.source_map(), ecx.expansion_descr(), span);
})
}
pub struct BangProcMacro {
pub client: pm::bridge::client::Client<pm::TokenStream, pm::TokenStream>,
}
@@ -30,10 +41,7 @@ fn expand(
span: Span,
input: TokenStream,
) -> Result<TokenStream, ErrorGuaranteed> {
let _timer =
ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| {
recorder.record_arg_with_span(ecx.sess.source_map(), ecx.expansion_descr(), span);
});
let _timer = record_expand_proc_macro(ecx, "expand_proc_macro", span);
let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
let strategy = exec_strategy(ecx.sess);
@@ -41,9 +49,7 @@ fn expand(
self.client.run(&strategy, server, input, proc_macro_backtrace).map_err(|e| {
ecx.dcx().emit_err(errors::ProcMacroPanicked {
span,
message: e
.as_str()
.map(|message| errors::ProcMacroPanickedHelp { message: message.into() }),
message: e.into_string().map(|message| errors::ProcMacroPanickedHelp { message }),
})
})
}
@@ -61,10 +67,7 @@ fn expand(
annotation: TokenStream,
annotated: TokenStream,
) -> Result<TokenStream, ErrorGuaranteed> {
let _timer =
ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| {
recorder.record_arg_with_span(ecx.sess.source_map(), ecx.expansion_descr(), span);
});
let _timer = record_expand_proc_macro(ecx, "expand_proc_macro", span);
let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
let strategy = exec_strategy(ecx.sess);
@@ -73,9 +76,9 @@ fn expand(
|e| {
ecx.dcx().emit_err(errors::CustomAttributePanicked {
span,
message: e.as_str().map(|message| errors::CustomAttributePanickedHelp {
message: message.into(),
}),
message: e
.into_string()
.map(|message| errors::CustomAttributePanickedHelp { message }),
})
},
)
@@ -95,12 +98,7 @@ fn expand(
item: Annotatable,
_is_derive_const: bool,
) -> ExpandResult<Vec<Annotatable>, Annotatable> {
let _timer = ecx.sess.prof.generic_activity_with_arg_recorder(
"expand_derive_proc_macro_outer",
|recorder| {
recorder.record_arg_with_span(ecx.sess.source_map(), ecx.expansion_descr(), span);
},
);
let _timer = record_expand_proc_macro(ecx, "expand_derive_proc_macro_outer", span);
// We need special handling for statement items
// (e.g. `fn foo() { #[derive(Debug)] struct Bar; }`)
@@ -191,7 +189,7 @@ fn expand_derive_macro(
let invoc_expn_data = invoc_id.expn_data();
let span = invoc_expn_data.call_site;
let event_arg = invoc_expn_data.kind.descr();
recorder.record_arg_with_span(ecx.sess.source_map(), event_arg.clone(), span);
recorder.record_arg_with_span(ecx.sess.source_map(), event_arg, span);
});
let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
@@ -206,9 +204,9 @@ fn expand_derive_macro(
ecx.dcx().emit_err({
errors::ProcMacroDerivePanicked {
span,
message: e.as_str().map(|message| errors::ProcMacroDerivePanickedHelp {
message: message.into(),
}),
message: e
.into_string()
.map(|message| errors::ProcMacroDerivePanickedHelp { message }),
}
});
Err(())
@@ -232,7 +230,7 @@ fn enter<F, R>(ecx: &mut ExtCtxt<'_>, client: DeriveClient, f: F) -> R
{
// We need erasure to get rid of the lifetime
let ctx = Self { expansion_ctx: ecx as *mut _ as *mut (), client };
DERIVE_EXPAND_CTX.set(&ctx, || f())
DERIVE_EXPAND_CTX.set(&ctx, f)
}
/// Accesses the thread local value of the derive expansion context.
+9 -13
View File
@@ -110,26 +110,22 @@ fn from_internal(stream: TokenStream) -> Self {
// Estimate the capacity as `stream.len()` rounded up to the next power
// of two to limit the number of required reallocations.
let mut trees = Vec::with_capacity(stream.len().next_power_of_two());
let mut iter = stream.iter();
while let Some(tree) = iter.next() {
for tree in stream.iter() {
let (Token { kind, span }, joint) = match tree.clone() {
tokenstream::TokenTree::Delimited(span, _, mut delim, mut stream) => {
// In `mk_delimited` we avoid nesting invisible delimited
// of the same `MetaVarKind`. Here we do the same but
// ignore the `MetaVarKind` because it is discarded when we
// convert it to a `Group`.
while let Delimiter::Invisible(InvisibleOrigin::MetaVar(_)) = delim {
if stream.len() == 1
&& let tree = stream.iter().next().unwrap()
&& let tokenstream::TokenTree::Delimited(_, _, delim2, stream2) = tree
&& let Delimiter::Invisible(InvisibleOrigin::MetaVar(_)) = delim2
{
delim = *delim2;
stream = stream2.clone();
} else {
break;
}
while let Delimiter::Invisible(InvisibleOrigin::MetaVar(_)) = delim
&& stream.len() == 1
&& let tree = stream.get(0).unwrap()
&& let tokenstream::TokenTree::Delimited(_, _, delim2, stream2) = tree
&& let Delimiter::Invisible(InvisibleOrigin::MetaVar(_)) = delim2
{
delim = *delim2;
stream = stream2.clone();
}
trees.push(TokenTree::Group(Group {
+1 -1
View File
@@ -152,7 +152,7 @@ pub(crate) fn update_macro_stats(
}
// The recorded size is the difference between the input and the output.
let entry = ecx.macro_stats.entry((name, macro_kind)).or_insert(MacroStat::default());
let entry = ecx.macro_stats.entry((name, macro_kind)).or_default();
entry.uses += 1;
entry.lines += num_lines;
entry.bytes += num_bytes;
+8
View File
@@ -244,6 +244,14 @@ pub fn as_str(&self) -> Option<&str> {
PanicMessage::Unknown => None,
}
}
pub fn into_string(self) -> Option<String> {
match self {
PanicMessage::StaticStr(s) => Some(s.into()),
PanicMessage::String(s) => Some(s),
PanicMessage::Unknown => None,
}
}
}
impl<S> Encode<S> for PanicMessage {
@@ -7,7 +7,7 @@
impl From<bridge::PanicMessage> for crate::PanicMessage {
fn from(p: bridge::PanicMessage) -> Self {
Self { message: p.as_str().map(|s| s.to_owned()) }
Self { message: p.into_string() }
}
}
+1 -1
View File
@@ -2,7 +2,7 @@
macro_rules! m {
(begin $ard:ident end) => {
[$ard] //~ ERROR: expected expression, found `$`
//~^ HELP: there is a macro metavariable with similar name
//~^ HELP: there is a macro metavariable with a similar name
};
}
+1 -1
View File
@@ -2,7 +2,7 @@
macro_rules! m {
(begin $ard:ident end) => {
[$arg] //~ ERROR: expected expression, found `$`
//~^ HELP: there is a macro metavariable with similar name
//~^ HELP: there is a macro metavariable with a similar name
};
}
+1 -1
View File
@@ -8,7 +8,7 @@ LL | let _ = m![begin x end];
| --------------- in this macro invocation
|
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
help: there is a macro metavariable with similar name
help: there is a macro metavariable with a similar name
|
LL - [$arg]
LL + [$ard]