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