1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
//! `MutVisit` trait for AST types that can be modified.
use syntax::ast::*;
use syntax::mut_visit::*;
use syntax::parse::token::{self, Token};
use syntax::ptr::P;
use syntax::source_map::Span;
use syntax::tokenstream::{TokenStream, TokenTree};
use syntax::util::map_in_place::MapInPlace;

use smallvec::SmallVec;

use crate::util::Lone;
use c2rust_macros::gen_visitor_impls;

/// A trait for AST nodes that can accept a `MutVisitor`.
pub trait MutVisit: Sized {
    fn visit<F: MutVisitor>(&mut self, _: &mut F) {
        unimplemented!("visit is not implemented for {}", stringify!(Self));
    }

    fn flat_map<F: MutVisitor>(mut self, f: &mut F) -> SmallVec<[Self; 1]> {
        self.visit(f);
        smallvec![self]
    }
}

/// Trait for AST node types that can be rewritten with a mutable visit.
pub trait MutVisitNodes: MutVisit + Sized {
    fn visit<T, F>(target: &mut T, callback: F)
    where
        T: MutVisit,
        F: FnMut(&mut Self);
}

/// Trait for AST node types that can be rewritten with a flat_map.
pub trait FlatMapNodes: MutVisit + Sized {
    fn visit<T, F>(target: &mut T, callback: F)
    where
        T: MutVisit,
        F: FnMut(Self) -> SmallVec<[Self; 1]>;

    fn flat_map<T, F>(target: T, callback: F) -> SmallVec<[T; 1]>
    where
        T: MutVisit,
        F: FnMut(Self) -> SmallVec<[Self; 1]>;
}

impl<T> MutVisit for Vec<T>
where
    T: MutVisit,
{
    fn visit<F: MutVisitor>(&mut self, f: &mut F) {
        for elem in self {
            elem.visit(f);
        }
    }
}

impl<T> MutVisit for Option<T>
where
    T: MutVisit,
{
    fn visit<F: MutVisitor>(&mut self, f: &mut F) {
        if let Some(elem) = self {
            elem.visit(f)
        }
    }
}

gen_visitor_impls! {
    pub trait MutVisitor: Sized {
        // Methods in this trait have one of three forms:
        //
        //   fn visit_t(&mut self, t: &mut T);                      // common
        //   fn flat_map_t(&mut self, t: T) -> SmallVec<[T; 1]>;    // rare
        //   fn filter_map_t(&mut self, t: T) -> Option<T>;         // rarest
        //
        // Any additions to this trait should happen in form of a call to a public
        // `noop_*` function that only calls out to the visitor again, not other
        // `noop_*` functions. This is a necessary API workaround to the problem of
        // not being able to call out to the super default method in an overridden
        // default method.
        //
        // When writing these methods, it is better to use destructuring like this:
        //
        //   fn visit_abc(&mut self, ABC { a, b, c: _ }: &mut ABC) {
        //       visit_a(a);
        //       visit_b(b);
        //   }
        //
        // than to use field access like this:
        //
        //   fn visit_abc(&mut self, abc: &mut ABC) {
        //       visit_a(&mut abc.a);
        //       visit_b(&mut abc.b);
        //       // ignore abc.c
        //   }
        //
        // As well as being more concise, the former is explicit about which fields
        // are skipped. Furthermore, if a new field is added, the destructuring
        // version will cause a compile error, which is good. In comparison, the
        // field access version will continue working and it would be easy to
        // forget to add handling for it.

        fn visit_crate(&mut self, c: &mut Crate) {
            noop_visit_crate(c, self)
        }

        fn visit_meta_list_item(&mut self, list_item: &mut NestedMetaItem) {
            noop_visit_meta_list_item(list_item, self);
        }

        fn visit_meta_item(&mut self, meta_item: &mut MetaItem) {
            noop_visit_meta_item(meta_item, self);
        }

        fn visit_use_tree(&mut self, use_tree: &mut UseTree) {
            noop_visit_use_tree(use_tree, self);
        }

        fn flat_map_foreign_item(&mut self, ni: ForeignItem) -> SmallVec<[ForeignItem; 1]> {
            noop_flat_map_foreign_item(ni, self)
        }

        fn flat_map_item(&mut self, i: P<Item>) -> SmallVec<[P<Item>; 1]> {
            noop_flat_map_item(i, self)
        }

        fn visit_fn_header(&mut self, header: &mut FnHeader) {
            noop_visit_fn_header(header, self);
        }

        fn visit_struct_field(&mut self, sf: &mut StructField) {
            noop_visit_struct_field(sf, self);
        }

        fn visit_item_kind(&mut self, i: &mut ItemKind) {
            noop_visit_item_kind(i, self);
        }

        fn flat_map_trait_item(&mut self, i: TraitItem) -> SmallVec<[TraitItem; 1]> {
            noop_flat_map_trait_item(i, self)
        }

        fn flat_map_impl_item(&mut self, i: ImplItem) -> SmallVec<[ImplItem; 1]> {
            noop_flat_map_impl_item(i, self)
        }

        fn visit_fn_decl(&mut self, d: &mut P<FnDecl>) {
            noop_visit_fn_decl(d, self);
        }

        fn visit_asyncness(&mut self, a: &mut IsAsync) {
            noop_visit_asyncness(a, self);
        }

        fn visit_block(&mut self, b: &mut P<Block>) {
            noop_visit_block(b, self);
        }

        fn flat_map_stmt(&mut self, s: Stmt) -> SmallVec<[Stmt; 1]> {
            noop_flat_map_stmt(s, self)
        }

        fn visit_arm(&mut self, a: &mut Arm) {
            noop_visit_arm(a, self);
        }

        fn visit_guard(&mut self, g: &mut Guard) {
            noop_visit_guard(g, self);
        }

        fn visit_pat(&mut self, p: &mut P<Pat>) {
            noop_visit_pat(p, self);
        }

        fn visit_anon_const(&mut self, c: &mut AnonConst) {
            noop_visit_anon_const(c, self);
        }

        fn visit_expr(&mut self, e: &mut P<Expr>) {
            noop_visit_expr(e, self);
        }

        // fn filter_map_expr(&mut self, e: P<Expr>) -> Option<P<Expr>> {
        //     noop_filter_map_expr(e, self)
        // }

        fn visit_generic_arg(&mut self, arg: &mut GenericArg) {
            noop_visit_generic_arg(arg, self);
        }

        fn visit_ty(&mut self, t: &mut P<Ty>) {
            noop_visit_ty(t, self);
        }

        // noop_visit_lifetime is private, so we can't walk lifetimes
        // fn visit_lifetime(&mut self, l: &mut Lifetime) {
        //     noop_visit_lifetime(l, self);
        // }

        fn visit_ty_binding(&mut self, t: &mut TypeBinding) {
            noop_visit_ty_binding(t, self);
        }

        fn visit_mod(&mut self, m: &mut Mod) {
            noop_visit_mod(m, self);
        }

        fn visit_foreign_mod(&mut self, nm: &mut ForeignMod) {
            noop_visit_foreign_mod(nm, self);
        }

        fn visit_variant(&mut self, v: &mut Variant) {
            noop_visit_variant(v, self);
        }

        fn visit_ident(&mut self, i: &mut Ident) {
            noop_visit_ident(i, self);
        }

        fn visit_path(&mut self, p: &mut Path) {
            noop_visit_path(p, self);
        }

        fn visit_qself(&mut self, qs: &mut Option<QSelf>) {
            noop_visit_qself(qs, self);
        }

        fn visit_generic_args(&mut self, p: &mut GenericArgs) {
            noop_visit_generic_args(p, self);
        }

        fn visit_angle_bracketed_parameter_data(&mut self, p: &mut AngleBracketedArgs) {
            noop_visit_angle_bracketed_parameter_data(p, self);
        }

        fn visit_parenthesized_parameter_data(&mut self, p: &mut ParenthesizedArgs) {
            noop_visit_parenthesized_parameter_data(p, self);
        }

        fn visit_local(&mut self, l: &mut P<Local>) {
            noop_visit_local(l, self);
        }

        // fn visit_mac(&mut self, _mac: &mut Mac) {
        //     panic!("visit_mac disabled by default");
        //     // N.B., see note about macros above. If you really want a visitor that
        //     // works on macros, use this definition in your trait impl:
        //     //   mut_visit::noop_visit_mac(_mac, self);
        // }

        fn visit_macro_def(&mut self, def: &mut MacroDef) {
            noop_visit_macro_def(def, self);
        }

        fn visit_label(&mut self, label: &mut Label) {
            noop_visit_label(label, self);
        }

        fn visit_attribute(&mut self, at: &mut Attribute) {
            noop_visit_attribute(at, self);
        }

        fn visit_arg(&mut self, a: &mut Arg) {
            noop_visit_arg(a, self);
        }

        fn visit_generics(&mut self, generics: &mut Generics) {
            noop_visit_generics(generics, self);
        }

        fn visit_trait_ref(&mut self, tr: &mut TraitRef) {
            noop_visit_trait_ref(tr, self);
        }

        fn visit_poly_trait_ref(&mut self, p: &mut PolyTraitRef) {
            noop_visit_poly_trait_ref(p, self);
        }

        fn visit_variant_data(&mut self, vdata: &mut VariantData) {
            noop_visit_variant_data(vdata, self);
        }

        fn visit_generic_param(&mut self, param: &mut GenericParam) {
            noop_visit_generic_param(param, self);
        }

        // fn visit_generic_params(&mut self, params: &mut Vec<GenericParam>) {
        //     noop_visit_generic_params(params, self);
        // }

        fn visit_tt(&mut self, tt: &mut TokenTree) {
            noop_visit_tt(tt, self);
        }

        fn visit_tts(&mut self, tts: &mut TokenStream) {
            noop_visit_tts(tts, self);
        }

        fn visit_token(&mut self, t: &mut Token) {
            noop_visit_token(t, self);
        }

        fn visit_interpolated(&mut self, nt: &mut token::Nonterminal) {
            noop_visit_interpolated(nt, self);
        }

        fn visit_param_bound(&mut self, tpb: &mut GenericBound) {
            noop_visit_param_bound(tpb, self);
        }

        fn visit_mt(&mut self, mt: &mut MutTy) {
            noop_visit_mt(mt, self);
        }

        fn visit_field(&mut self, field: &mut Field) {
            noop_visit_field(field, self);
        }

        fn visit_where_clause(&mut self, where_clause: &mut WhereClause) {
            noop_visit_where_clause(where_clause, self);
        }

        fn visit_where_predicate(&mut self, where_predicate: &mut WherePredicate) {
            noop_visit_where_predicate(where_predicate, self);
        }

        fn visit_vis(&mut self, vis: &mut Visibility) {
            noop_visit_vis(vis, self);
        }

        fn visit_id(&mut self, _id: &mut NodeId) {
            // Do nothing.
        }

        fn visit_span(&mut self, _sp: &mut Span) {
            // Do nothing.
        }
    }
}