rustc_ast/
mut_visit.rs

1//! A `MutVisitor` represents an AST modification; it accepts an AST piece and
2//! mutates it in place. So, for instance, macro expansion is a `MutVisitor`
3//! that walks over an AST and modifies it.
4//!
5//! Note: using a `MutVisitor` (other than the `MacroExpander` `MutVisitor`) on
6//! an AST before macro expansion is probably a bad idea. For instance,
7//! a `MutVisitor` renaming item names in a module will miss all of those
8//! that are created by the expansion of a macro.
9
10use 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    /// This is for compatibility with the regular `Visitor`.
28    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}