1use std::ops::DerefMut;
11use std::panic;
12
13use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
14use rustc_span::source_map::Spanned;
15use rustc_span::{Ident, Span, Symbol};
16use smallvec::{SmallVec, smallvec};
17use thin_vec::ThinVec;
18
19use crate::ast::*;
20use crate::ptr::P;
21use crate::tokenstream::*;
22use crate::visit::{AssocCtxt, BoundKind, FnCtxt, LifetimeCtxt, VisitorResult, try_visit};
23
24mod sealed {
25 use rustc_ast_ir::visit::VisitorResult;
26
27 pub trait MutVisitorResult {
29 type Result: VisitorResult;
30 }
31
32 impl<T> MutVisitorResult for T {
33 type Result = ();
34 }
35}
36
37use sealed::MutVisitorResult;
38
39pub(crate) trait MutVisitable<V: MutVisitor> {
40 type Extra: Copy;
41 fn visit_mut(&mut self, visitor: &mut V, extra: Self::Extra);
42}
43
44impl<V: MutVisitor, T: ?Sized> MutVisitable<V> for P<T>
45where
46 T: MutVisitable<V>,
47{
48 type Extra = T::Extra;
49 fn visit_mut(&mut self, visitor: &mut V, extra: Self::Extra) {
50 (**self).visit_mut(visitor, extra)
51 }
52}
53
54impl<V: MutVisitor, T> MutVisitable<V> for Option<T>
55where
56 T: MutVisitable<V>,
57{
58 type Extra = T::Extra;
59 fn visit_mut(&mut self, visitor: &mut V, extra: Self::Extra) {
60 if let Some(this) = self {
61 this.visit_mut(visitor, extra)
62 }
63 }
64}
65
66impl<V: MutVisitor, T> MutVisitable<V> for Spanned<T>
67where
68 T: MutVisitable<V>,
69{
70 type Extra = T::Extra;
71 fn visit_mut(&mut self, visitor: &mut V, extra: Self::Extra) {
72 let Spanned { span, node } = self;
73 span.visit_mut(visitor, ());
74 node.visit_mut(visitor, extra);
75 }
76}
77
78impl<V: MutVisitor, T> MutVisitable<V> for [T]
79where
80 T: MutVisitable<V>,
81{
82 type Extra = T::Extra;
83 fn visit_mut(&mut self, visitor: &mut V, extra: Self::Extra) {
84 for item in self {
85 item.visit_mut(visitor, extra);
86 }
87 }
88}
89
90impl<V: MutVisitor, T> MutVisitable<V> for Vec<T>
91where
92 T: MutVisitable<V>,
93{
94 type Extra = T::Extra;
95 fn visit_mut(&mut self, visitor: &mut V, extra: Self::Extra) {
96 for item in self {
97 item.visit_mut(visitor, extra);
98 }
99 }
100}
101
102impl<V: MutVisitor, T> MutVisitable<V> for (T,)
103where
104 T: MutVisitable<V>,
105{
106 type Extra = T::Extra;
107 fn visit_mut(&mut self, visitor: &mut V, extra: Self::Extra) {
108 self.0.visit_mut(visitor, extra);
109 }
110}
111
112impl<V: MutVisitor, T1, T2> MutVisitable<V> for (T1, T2)
113where
114 T1: MutVisitable<V, Extra = ()>,
115 T2: MutVisitable<V, Extra = ()>,
116{
117 type Extra = ();
118 fn visit_mut(&mut self, visitor: &mut V, extra: Self::Extra) {
119 self.0.visit_mut(visitor, extra);
120 self.1.visit_mut(visitor, extra);
121 }
122}
123
124impl<V: MutVisitor, T1, T2, T3> MutVisitable<V> for (T1, T2, T3)
125where
126 T1: MutVisitable<V, Extra = ()>,
127 T2: MutVisitable<V, Extra = ()>,
128 T3: MutVisitable<V, Extra = ()>,
129{
130 type Extra = ();
131 fn visit_mut(&mut self, visitor: &mut V, extra: Self::Extra) {
132 self.0.visit_mut(visitor, extra);
133 self.1.visit_mut(visitor, extra);
134 self.2.visit_mut(visitor, extra);
135 }
136}
137
138impl<V: MutVisitor, T1, T2, T3, T4> MutVisitable<V> for (T1, T2, T3, T4)
139where
140 T1: MutVisitable<V, Extra = ()>,
141 T2: MutVisitable<V, Extra = ()>,
142 T3: MutVisitable<V, Extra = ()>,
143 T4: MutVisitable<V, Extra = ()>,
144{
145 type Extra = ();
146 fn visit_mut(&mut self, visitor: &mut V, extra: Self::Extra) {
147 self.0.visit_mut(visitor, extra);
148 self.1.visit_mut(visitor, extra);
149 self.2.visit_mut(visitor, extra);
150 self.3.visit_mut(visitor, extra);
151 }
152}
153
154pub trait MutWalkable<V: MutVisitor> {
155 fn walk_mut(&mut self, visitor: &mut V);
156}
157
158macro_rules! visit_visitable {
159 (mut $visitor:expr, $($expr:expr),* $(,)?) => {{
160 $(MutVisitable::visit_mut($expr, $visitor, ());)*
161 }};
162}
163
164macro_rules! visit_visitable_with {
165 (mut $visitor:expr, $expr:expr, $extra:expr $(,)?) => {
166 MutVisitable::visit_mut($expr, $visitor, $extra)
167 };
168}
169
170macro_rules! walk_walkable {
171 ($visitor:expr, $expr:expr, mut) => {
172 MutWalkable::walk_mut($expr, $visitor)
173 };
174}
175
176macro_rules! impl_visitable {
177 (|&mut $self:ident: $self_ty:ty,
178 $vis:ident: &mut $vis_ty:ident,
179 $extra:ident: $extra_ty:ty| $block:block) => {
180 #[allow(unused_parens, non_local_definitions)]
181 impl<$vis_ty: MutVisitor> MutVisitable<$vis_ty> for $self_ty {
182 type Extra = $extra_ty;
183 fn visit_mut(&mut $self, $vis: &mut $vis_ty, $extra: Self::Extra) -> V::Result {
184 $block
185 }
186 }
187 };
188}
189
190macro_rules! impl_walkable {
191 ($(<$K:ident: $Kb:ident>)? |&mut $self:ident: $self_ty:ty,
192 $vis:ident: &mut $vis_ty:ident| $block:block) => {
193 #[allow(unused_parens, non_local_definitions)]
194 impl<$($K: $Kb,)? $vis_ty: MutVisitor> MutWalkable<$vis_ty> for $self_ty {
195 fn walk_mut(&mut $self, $vis: &mut $vis_ty) -> V::Result {
196 $block
197 }
198 }
199 };
200}
201
202macro_rules! impl_visitable_noop {
203 (<mut> $($ty:ty,)*) => {
204 $(
205 impl_visitable!(|&mut self: $ty, _vis: &mut V, _extra: ()| {});
206 )*
207 };
208}
209
210macro_rules! impl_visitable_list {
211 (<mut> $($ty:ty,)*) => {
212 $(impl<V: MutVisitor, T> MutVisitable<V> for $ty
213 where
214 for<'a> &'a mut $ty: IntoIterator<Item = &'a mut T>,
215 T: MutVisitable<V>,
216 {
217 type Extra = <T as MutVisitable<V>>::Extra;
218
219 #[inline]
220 fn visit_mut(&mut self, visitor: &mut V, extra: Self::Extra) {
221 for i in self {
222 i.visit_mut(visitor, extra);
223 }
224 }
225 })*
226 }
227}
228
229macro_rules! impl_visitable_direct {
230 (<mut> $($ty:ty,)*) => {
231 $(impl_visitable!(
232 |&mut self: $ty, visitor: &mut V, _extra: ()| {
233 MutWalkable::walk_mut(self, visitor)
234 }
235 );)*
236 }
237}
238
239macro_rules! impl_visitable_calling_walkable {
240 (<mut>
241 $( fn $method:ident($ty:ty $(, $extra_name:ident: $extra_ty:ty)?); )*
242 ) => {
243 $(fn $method(&mut self, node: &mut $ty $(, $extra_name:$extra_ty)?) {
244 impl_visitable!(|&mut self: $ty, visitor: &mut V, extra: ($($extra_ty)?)| {
245 let ($($extra_name)?) = extra;
246 visitor.$method(self $(, $extra_name)?);
247 });
248 walk_walkable!(self, node, mut)
249 })*
250 }
251}
252
253macro_rules! define_named_walk {
254 ((mut) $Visitor:ident
255 $( pub fn $method:ident($ty:ty); )*
256 ) => {
257 $(pub fn $method<V: $Visitor>(visitor: &mut V, node: &mut $ty) {
258 walk_walkable!(visitor, node, mut)
259 })*
260 };
261}
262
263super::common_visitor_and_walkers!((mut) MutVisitor);
264
265macro_rules! generate_flat_map_visitor_fns {
266 ($($name:ident, $Ty:ty, $flat_map_fn:ident$(, $param:ident: $ParamTy:ty)*;)+) => {
267 $(
268 #[allow(unused_parens)]
269 impl<V: MutVisitor> MutVisitable<V> for ThinVec<$Ty> {
270 type Extra = ($($ParamTy),*);
271
272 #[inline]
273 fn visit_mut(
274 &mut self,
275 visitor: &mut V,
276 ($($param),*): Self::Extra,
277 ) -> V::Result {
278 $name(visitor, self $(, $param)*)
279 }
280 }
281
282 fn $name<V: MutVisitor>(
283 vis: &mut V,
284 values: &mut ThinVec<$Ty>,
285 $(
286 $param: $ParamTy,
287 )*
288 ) {
289 values.flat_map_in_place(|value| vis.$flat_map_fn(value$(,$param)*));
290 }
291 )+
292 }
293}
294
295generate_flat_map_visitor_fns! {
296 visit_items, P<Item>, flat_map_item;
297 visit_foreign_items, P<ForeignItem>, flat_map_foreign_item;
298 visit_generic_params, GenericParam, flat_map_generic_param;
299 visit_stmts, Stmt, flat_map_stmt;
300 visit_exprs, P<Expr>, filter_map_expr;
301 visit_expr_fields, ExprField, flat_map_expr_field;
302 visit_pat_fields, PatField, flat_map_pat_field;
303 visit_variants, Variant, flat_map_variant;
304 visit_assoc_items, P<AssocItem>, flat_map_assoc_item, ctxt: AssocCtxt;
305 visit_where_predicates, WherePredicate, flat_map_where_predicate;
306 visit_params, Param, flat_map_param;
307 visit_field_defs, FieldDef, flat_map_field_def;
308 visit_arms, Arm, flat_map_arm;
309}
310
311pub fn walk_flat_map_pat_field<T: MutVisitor>(
312 vis: &mut T,
313 mut fp: PatField,
314) -> SmallVec<[PatField; 1]> {
315 vis.visit_pat_field(&mut fp);
316 smallvec![fp]
317}
318
319macro_rules! generate_walk_flat_map_fns {
320 ($($fn_name:ident($Ty:ty$(,$extra_name:ident: $ExtraTy:ty)*) => $visit_fn_name:ident;)+) => {$(
321 pub fn $fn_name<V: MutVisitor>(vis: &mut V, mut value: $Ty$(,$extra_name: $ExtraTy)*) -> SmallVec<[$Ty; 1]> {
322 vis.$visit_fn_name(&mut value$(,$extra_name)*);
323 smallvec![value]
324 }
325 )+};
326}
327
328generate_walk_flat_map_fns! {
329 walk_flat_map_arm(Arm) => visit_arm;
330 walk_flat_map_variant(Variant) => visit_variant;
331 walk_flat_map_param(Param) => visit_param;
332 walk_flat_map_generic_param(GenericParam) => visit_generic_param;
333 walk_flat_map_where_predicate(WherePredicate) => visit_where_predicate;
334 walk_flat_map_field_def(FieldDef) => visit_field_def;
335 walk_flat_map_expr_field(ExprField) => visit_expr_field;
336 walk_flat_map_item(P<Item>) => visit_item;
337 walk_flat_map_foreign_item(P<ForeignItem>) => visit_foreign_item;
338 walk_flat_map_assoc_item(P<AssocItem>, ctxt: AssocCtxt) => visit_assoc_item;
339}
340
341pub fn walk_filter_map_expr<T: MutVisitor>(vis: &mut T, mut e: P<Expr>) -> Option<P<Expr>> {
342 vis.visit_expr(&mut e);
343 Some(e)
344}
345
346pub fn walk_flat_map_stmt<T: MutVisitor>(
347 vis: &mut T,
348 Stmt { kind, span, mut id }: Stmt,
349) -> SmallVec<[Stmt; 1]> {
350 vis.visit_id(&mut id);
351 let mut stmts: SmallVec<[Stmt; 1]> = walk_flat_map_stmt_kind(vis, kind)
352 .into_iter()
353 .map(|kind| Stmt { id, kind, span })
354 .collect();
355 match &mut stmts[..] {
356 [] => {}
357 [stmt] => vis.visit_span(&mut stmt.span),
358 _ => panic!(
359 "cloning statement `NodeId`s is prohibited by default, \
360 the visitor should implement custom statement visiting"
361 ),
362 }
363 stmts
364}
365
366fn walk_flat_map_stmt_kind<T: MutVisitor>(vis: &mut T, kind: StmtKind) -> SmallVec<[StmtKind; 1]> {
367 match kind {
368 StmtKind::Let(mut local) => smallvec![StmtKind::Let({
369 vis.visit_local(&mut local);
370 local
371 })],
372 StmtKind::Item(item) => vis.flat_map_item(item).into_iter().map(StmtKind::Item).collect(),
373 StmtKind::Expr(expr) => vis.filter_map_expr(expr).into_iter().map(StmtKind::Expr).collect(),
374 StmtKind::Semi(expr) => vis.filter_map_expr(expr).into_iter().map(StmtKind::Semi).collect(),
375 StmtKind::Empty => smallvec![StmtKind::Empty],
376 StmtKind::MacCall(mut mac) => {
377 let MacCallStmt { mac: mac_, style: _, attrs, tokens: _ } = mac.deref_mut();
378 for attr in attrs {
379 vis.visit_attribute(attr);
380 }
381 vis.visit_mac_call(mac_);
382 smallvec![StmtKind::MacCall(mac)]
383 }
384 }
385}