Rollup merge of #141430 - fee1-dead-contrib:push-nmzoprvtsvww, r=petrochenkov

remove `visit_clobber` and move `DummyAstNode` to `rustc_expand`

`visit_clobber` is not really useful except for one niche purpose
involving generic code. We should just use the replace logic where we
can.
This commit is contained in:
Matthias Krüger
2025-05-30 07:01:29 +02:00
committed by GitHub
6 changed files with 95 additions and 146 deletions

View File

@@ -3,15 +3,14 @@ use std::rc::Rc;
use std::sync::Arc;
use std::{iter, mem};
use rustc_ast as ast;
use rustc_ast::mut_visit::*;
use rustc_ast::ptr::P;
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::visit::{self, AssocCtxt, Visitor, VisitorResult, try_visit, walk_list};
use rustc_ast::{
AssocItemKind, AstNodeWrapper, AttrArgs, AttrStyle, AttrVec, ExprKind, ForeignItemKind,
HasAttrs, HasNodeId, Inline, ItemKind, MacStmtStyle, MetaItemInner, MetaItemKind, ModKind,
NodeId, PatKind, StmtKind, TyKind, token,
self as ast, AssocItemKind, AstNodeWrapper, AttrArgs, AttrStyle, AttrVec, DUMMY_NODE_ID,
ExprKind, ForeignItemKind, HasAttrs, HasNodeId, Inline, ItemKind, MacStmtStyle, MetaItemInner,
MetaItemKind, ModKind, NodeId, PatKind, StmtKind, TyKind, token,
};
use rustc_ast_pretty::pprust;
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
@@ -131,13 +130,9 @@ macro_rules! ast_fragments {
pub(crate) fn mut_visit_with<F: MutVisitor>(&mut self, vis: &mut F) {
match self {
AstFragment::OptExpr(opt_expr) => {
visit_clobber(opt_expr, |opt_expr| {
if let Some(expr) = opt_expr {
vis.filter_map_expr(expr)
} else {
None
}
});
if let Some(expr) = opt_expr.take() {
*opt_expr = vis.filter_map_expr(expr)
}
}
AstFragment::MethodReceiverExpr(expr) => vis.visit_method_receiver_expr(expr),
$($(AstFragment::$Kind(ast) => vis.$mut_visit_ast(ast),)?)*
@@ -1782,11 +1777,7 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, OptExprTag> {
/// This struct is a hack to workaround unstable of `stmt_expr_attributes`.
/// It can be removed once that feature is stabilized.
struct MethodReceiverTag;
impl DummyAstNode for MethodReceiverTag {
fn dummy() -> MethodReceiverTag {
MethodReceiverTag
}
}
impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, MethodReceiverTag> {
type OutputTy = Self;
const KIND: AstFragmentKind = AstFragmentKind::MethodReceiverExpr;
@@ -1852,6 +1843,57 @@ fn build_single_delegations<'a, Node: InvocationCollectorNode>(
})
}
/// Required for `visit_node` obtained an owned `Node` from `&mut Node`.
trait DummyAstNode {
fn dummy() -> Self;
}
impl DummyAstNode for ast::Crate {
fn dummy() -> Self {
ast::Crate {
attrs: Default::default(),
items: Default::default(),
spans: Default::default(),
id: DUMMY_NODE_ID,
is_placeholder: Default::default(),
}
}
}
impl DummyAstNode for P<ast::Ty> {
fn dummy() -> Self {
P(ast::Ty {
id: DUMMY_NODE_ID,
kind: TyKind::Dummy,
span: Default::default(),
tokens: Default::default(),
})
}
}
impl DummyAstNode for P<ast::Pat> {
fn dummy() -> Self {
P(ast::Pat {
id: DUMMY_NODE_ID,
kind: PatKind::Wild,
span: Default::default(),
tokens: Default::default(),
})
}
}
impl DummyAstNode for P<ast::Expr> {
fn dummy() -> Self {
ast::Expr::dummy()
}
}
impl DummyAstNode for AstNodeWrapper<P<ast::Expr>, MethodReceiverTag> {
fn dummy() -> Self {
AstNodeWrapper::new(ast::Expr::dummy(), MethodReceiverTag)
}
}
struct InvocationCollector<'a, 'b> {
cx: &'a mut ExtCtxt<'b>,
invocations: Vec<(Invocation, Option<Arc<SyntaxExtension>>)>,
@@ -2155,18 +2197,19 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
self.expand_cfg_attr(node, &attr, pos);
continue;
}
_ => visit_clobber(node, |node| {
self.collect_attr((attr, pos, derives), node.to_annotatable(), Node::KIND)
_ => {
let n = mem::replace(node, Node::dummy());
*node = self
.collect_attr((attr, pos, derives), n.to_annotatable(), Node::KIND)
.make_ast::<Node>()
}),
}
},
None if node.is_mac_call() => {
visit_clobber(node, |node| {
// Do not clobber unless it's actually a macro (uncommon case).
let (mac, attrs, _) = node.take_mac_call();
self.check_attributes(&attrs, &mac);
self.collect_bang(mac, Node::KIND).make_ast::<Node>()
})
let n = mem::replace(node, Node::dummy());
let (mac, attrs, _) = n.take_mac_call();
self.check_attributes(&attrs, &mac);
*node = self.collect_bang(mac, Node::KIND).make_ast::<Node>()
}
None if node.delegation().is_some() => unreachable!(),
None => {
@@ -2293,11 +2336,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
}
fn visit_method_receiver_expr(&mut self, node: &mut P<ast::Expr>) {
visit_clobber(node, |node| {
let mut wrapper = AstNodeWrapper::new(node, MethodReceiverTag);
self.visit_node(&mut wrapper);
wrapper.wrapped
})
self.visit_node(AstNodeWrapper::from_mut(node, MethodReceiverTag))
}
fn filter_map_expr(&mut self, node: P<ast::Expr>) -> Option<P<ast::Expr>> {