]>
Commit | Line | Data |
---|---|---|
e9174d1e SL |
1 | // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | //! HIR walker. Each overridden visit method has full control over what | |
12 | //! happens with its node, it can do its own traversal of the node's children, | |
9cc50fc6 | 13 | //! call `intravisit::walk_*` to apply the default traversal algorithm, or prevent |
e9174d1e SL |
14 | //! deeper traversal by doing nothing. |
15 | //! | |
92a42be0 SL |
16 | //! When visiting the HIR, the contents of nested items are NOT visited |
17 | //! by default. This is different from the AST visitor, which does a deep walk. | |
18 | //! Hence this module is called `intravisit`; see the method `visit_nested_item` | |
19 | //! for more details. | |
e9174d1e | 20 | //! |
92a42be0 SL |
21 | //! Note: it is an important invariant that the default visitor walks |
22 | //! the body of a function in "execution order" (more concretely, | |
23 | //! reverse post-order with respect to the CFG implied by the AST), | |
24 | //! meaning that if AST node A may execute before AST node B, then A | |
25 | //! is visited first. The borrow checker in particular relies on this | |
26 | //! property. | |
e9174d1e SL |
27 | |
28 | use syntax::abi::Abi; | |
92a42be0 | 29 | use syntax::ast::{NodeId, CRATE_NODE_ID, Name, Attribute}; |
3157f602 XL |
30 | use syntax::codemap::Spanned; |
31 | use syntax_pos::Span; | |
b039eaaf | 32 | use hir::*; |
e9174d1e | 33 | |
54a0048b SL |
34 | use std::cmp; |
35 | use std::u32; | |
36 | ||
e9174d1e SL |
37 | #[derive(Copy, Clone, PartialEq, Eq)] |
38 | pub enum FnKind<'a> { | |
39 | /// fn foo() or extern "Abi" fn foo() | |
54a0048b | 40 | ItemFn(Name, &'a Generics, Unsafety, Constness, Abi, &'a Visibility, &'a [Attribute]), |
e9174d1e SL |
41 | |
42 | /// fn foo(&self) | |
54a0048b | 43 | Method(Name, &'a MethodSig, Option<&'a Visibility>, &'a [Attribute]), |
e9174d1e | 44 | |
b039eaaf | 45 | /// |x, y| {} |
54a0048b SL |
46 | Closure(&'a [Attribute]), |
47 | } | |
48 | ||
49 | impl<'a> FnKind<'a> { | |
50 | pub fn attrs(&self) -> &'a [Attribute] { | |
51 | match *self { | |
52 | FnKind::ItemFn(_, _, _, _, _, _, attrs) => attrs, | |
53 | FnKind::Method(_, _, _, attrs) => attrs, | |
54 | FnKind::Closure(attrs) => attrs, | |
55 | } | |
56 | } | |
e9174d1e SL |
57 | } |
58 | ||
59 | /// Each method of the Visitor trait is a hook to be potentially | |
60 | /// overridden. Each method's default implementation recursively visits | |
61 | /// the substructure of the input via the corresponding `walk` method; | |
9cc50fc6 | 62 | /// e.g. the `visit_mod` method by default calls `intravisit::walk_mod`. |
e9174d1e | 63 | /// |
92a42be0 SL |
64 | /// Note that this visitor does NOT visit nested items by default |
65 | /// (this is why the module is called `intravisit`, to distinguish it | |
66 | /// from the AST's `visit` module, which acts differently). If you | |
67 | /// simply want to visit all items in the crate in some order, you | |
68 | /// should call `Crate::visit_all_items`. Otherwise, see the comment | |
69 | /// on `visit_nested_item` for details on how to visit nested items. | |
70 | /// | |
e9174d1e SL |
71 | /// If you want to ensure that your code handles every variant |
72 | /// explicitly, you need to override each method. (And you also need | |
73 | /// to monitor future changes to `Visitor` in case a new method with a | |
74 | /// new default implementation gets introduced.) | |
75 | pub trait Visitor<'v> : Sized { | |
92a42be0 SL |
76 | /////////////////////////////////////////////////////////////////////////// |
77 | // Nested items. | |
78 | ||
79 | /// Invoked when a nested item is encountered. By default, does | |
80 | /// nothing. If you want a deep walk, you need to override to | |
81 | /// fetch the item contents. But most of the time, it is easier | |
82 | /// (and better) to invoke `Crate::visit_all_items`, which visits | |
83 | /// all items in the crate in some order (but doesn't respect | |
84 | /// nesting). | |
85 | #[allow(unused_variables)] | |
86 | fn visit_nested_item(&mut self, id: ItemId) { | |
87 | } | |
88 | ||
89 | /// Visit the top-level item and (optionally) nested items. See | |
90 | /// `visit_nested_item` for details. | |
91 | fn visit_item(&mut self, i: &'v Item) { | |
92 | walk_item(self, i) | |
93 | } | |
94 | ||
95 | /////////////////////////////////////////////////////////////////////////// | |
96 | ||
5bcae85e SL |
97 | fn visit_id(&mut self, _node_id: NodeId) { |
98 | // Nothing to do. | |
99 | } | |
e9174d1e SL |
100 | fn visit_name(&mut self, _span: Span, _name: Name) { |
101 | // Nothing to do. | |
102 | } | |
5bcae85e SL |
103 | fn visit_mod(&mut self, m: &'v Mod, _s: Span, n: NodeId) { |
104 | walk_mod(self, m, n) | |
b039eaaf SL |
105 | } |
106 | fn visit_foreign_item(&mut self, i: &'v ForeignItem) { | |
107 | walk_foreign_item(self, i) | |
108 | } | |
b039eaaf SL |
109 | fn visit_local(&mut self, l: &'v Local) { |
110 | walk_local(self, l) | |
111 | } | |
112 | fn visit_block(&mut self, b: &'v Block) { | |
113 | walk_block(self, b) | |
114 | } | |
115 | fn visit_stmt(&mut self, s: &'v Stmt) { | |
116 | walk_stmt(self, s) | |
117 | } | |
118 | fn visit_arm(&mut self, a: &'v Arm) { | |
119 | walk_arm(self, a) | |
120 | } | |
121 | fn visit_pat(&mut self, p: &'v Pat) { | |
122 | walk_pat(self, p) | |
123 | } | |
124 | fn visit_decl(&mut self, d: &'v Decl) { | |
125 | walk_decl(self, d) | |
126 | } | |
127 | fn visit_expr(&mut self, ex: &'v Expr) { | |
128 | walk_expr(self, ex) | |
129 | } | |
130 | fn visit_expr_post(&mut self, _ex: &'v Expr) { | |
131 | } | |
132 | fn visit_ty(&mut self, t: &'v Ty) { | |
133 | walk_ty(self, t) | |
134 | } | |
135 | fn visit_generics(&mut self, g: &'v Generics) { | |
136 | walk_generics(self, g) | |
137 | } | |
3157f602 XL |
138 | fn visit_where_predicate(&mut self, predicate: &'v WherePredicate) { |
139 | walk_where_predicate(self, predicate) | |
140 | } | |
5bcae85e SL |
141 | fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Block, s: Span, id: NodeId) { |
142 | walk_fn(self, fk, fd, b, s, id) | |
e9174d1e | 143 | } |
b039eaaf SL |
144 | fn visit_trait_item(&mut self, ti: &'v TraitItem) { |
145 | walk_trait_item(self, ti) | |
146 | } | |
147 | fn visit_impl_item(&mut self, ii: &'v ImplItem) { | |
148 | walk_impl_item(self, ii) | |
149 | } | |
150 | fn visit_trait_ref(&mut self, t: &'v TraitRef) { | |
151 | walk_trait_ref(self, t) | |
152 | } | |
e9174d1e SL |
153 | fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) { |
154 | walk_ty_param_bound(self, bounds) | |
155 | } | |
156 | fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: &'v TraitBoundModifier) { | |
157 | walk_poly_trait_ref(self, t, m) | |
158 | } | |
92a42be0 SL |
159 | fn visit_variant_data(&mut self, |
160 | s: &'v VariantData, | |
161 | _: Name, | |
162 | _: &'v Generics, | |
5bcae85e | 163 | _parent_id: NodeId, |
92a42be0 | 164 | _: Span) { |
e9174d1e SL |
165 | walk_struct_def(self, s) |
166 | } | |
b039eaaf SL |
167 | fn visit_struct_field(&mut self, s: &'v StructField) { |
168 | walk_struct_field(self, s) | |
e9174d1e | 169 | } |
92a42be0 SL |
170 | fn visit_enum_def(&mut self, |
171 | enum_definition: &'v EnumDef, | |
172 | generics: &'v Generics, | |
173 | item_id: NodeId, | |
174 | _: Span) { | |
b039eaaf | 175 | walk_enum_def(self, enum_definition, generics, item_id) |
e9174d1e | 176 | } |
b039eaaf SL |
177 | fn visit_variant(&mut self, v: &'v Variant, g: &'v Generics, item_id: NodeId) { |
178 | walk_variant(self, v, g, item_id) | |
e9174d1e | 179 | } |
b039eaaf SL |
180 | fn visit_lifetime(&mut self, lifetime: &'v Lifetime) { |
181 | walk_lifetime(self, lifetime) | |
e9174d1e SL |
182 | } |
183 | fn visit_lifetime_def(&mut self, lifetime: &'v LifetimeDef) { | |
184 | walk_lifetime_def(self, lifetime) | |
185 | } | |
e9174d1e SL |
186 | fn visit_path(&mut self, path: &'v Path, _id: NodeId) { |
187 | walk_path(self, path) | |
188 | } | |
b039eaaf SL |
189 | fn visit_path_list_item(&mut self, prefix: &'v Path, item: &'v PathListItem) { |
190 | walk_path_list_item(self, prefix, item) | |
191 | } | |
e9174d1e SL |
192 | fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) { |
193 | walk_path_segment(self, path_span, path_segment) | |
194 | } | |
195 | fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &'v PathParameters) { | |
196 | walk_path_parameters(self, path_span, path_parameters) | |
197 | } | |
198 | fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding) { | |
199 | walk_assoc_type_binding(self, type_binding) | |
200 | } | |
b039eaaf SL |
201 | fn visit_attribute(&mut self, _attr: &'v Attribute) { |
202 | } | |
203 | fn visit_macro_def(&mut self, macro_def: &'v MacroDef) { | |
204 | walk_macro_def(self, macro_def) | |
205 | } | |
a7813a04 XL |
206 | fn visit_vis(&mut self, vis: &'v Visibility) { |
207 | walk_vis(self, vis) | |
208 | } | |
e9174d1e SL |
209 | } |
210 | ||
b039eaaf | 211 | pub fn walk_opt_name<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_name: Option<Name>) { |
3157f602 | 212 | if let Some(name) = opt_name { |
b039eaaf | 213 | visitor.visit_name(span, name); |
e9174d1e SL |
214 | } |
215 | } | |
216 | ||
3157f602 XL |
217 | pub fn walk_opt_sp_name<'v, V: Visitor<'v>>(visitor: &mut V, opt_sp_name: &Option<Spanned<Name>>) { |
218 | if let Some(ref sp_name) = *opt_sp_name { | |
219 | visitor.visit_name(sp_name.span, sp_name.node); | |
220 | } | |
221 | } | |
222 | ||
92a42be0 | 223 | /// Walks the contents of a crate. See also `Crate::visit_all_items`. |
b039eaaf SL |
224 | pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) { |
225 | visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID); | |
226 | walk_list!(visitor, visit_attribute, &krate.attrs); | |
227 | walk_list!(visitor, visit_macro_def, &krate.exported_macros); | |
228 | } | |
229 | ||
230 | pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef) { | |
5bcae85e | 231 | visitor.visit_id(macro_def.id); |
b039eaaf SL |
232 | visitor.visit_name(macro_def.span, macro_def.name); |
233 | walk_opt_name(visitor, macro_def.span, macro_def.imported_from); | |
234 | walk_list!(visitor, visit_attribute, ¯o_def.attrs); | |
235 | } | |
236 | ||
5bcae85e SL |
237 | pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod, mod_node_id: NodeId) { |
238 | visitor.visit_id(mod_node_id); | |
92a42be0 SL |
239 | for &item_id in &module.item_ids { |
240 | visitor.visit_nested_item(item_id); | |
241 | } | |
e9174d1e SL |
242 | } |
243 | ||
b039eaaf | 244 | pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) { |
5bcae85e | 245 | visitor.visit_id(local.id); |
b039eaaf SL |
246 | visitor.visit_pat(&local.pat); |
247 | walk_list!(visitor, visit_ty, &local.ty); | |
248 | walk_list!(visitor, visit_expr, &local.init); | |
249 | } | |
250 | ||
251 | pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) { | |
5bcae85e | 252 | visitor.visit_id(lifetime.id); |
b039eaaf | 253 | visitor.visit_name(lifetime.span, lifetime.name); |
e9174d1e SL |
254 | } |
255 | ||
b039eaaf SL |
256 | pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V, lifetime_def: &'v LifetimeDef) { |
257 | visitor.visit_lifetime(&lifetime_def.lifetime); | |
258 | walk_list!(visitor, visit_lifetime, &lifetime_def.bounds); | |
e9174d1e SL |
259 | } |
260 | ||
e9174d1e SL |
261 | pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V, |
262 | trait_ref: &'v PolyTraitRef, | |
263 | _modifier: &'v TraitBoundModifier) | |
264 | where V: Visitor<'v> | |
265 | { | |
92a42be0 | 266 | walk_list!(visitor, visit_lifetime_def, &trait_ref.bound_lifetimes); |
e9174d1e SL |
267 | visitor.visit_trait_ref(&trait_ref.trait_ref); |
268 | } | |
269 | ||
b039eaaf | 270 | pub fn walk_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v TraitRef) |
e9174d1e SL |
271 | where V: Visitor<'v> |
272 | { | |
5bcae85e | 273 | visitor.visit_id(trait_ref.ref_id); |
e9174d1e SL |
274 | visitor.visit_path(&trait_ref.path, trait_ref.ref_id) |
275 | } | |
276 | ||
277 | pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { | |
a7813a04 | 278 | visitor.visit_vis(&item.vis); |
b039eaaf | 279 | visitor.visit_name(item.span, item.name); |
e9174d1e | 280 | match item.node { |
b039eaaf | 281 | ItemExternCrate(opt_name) => { |
5bcae85e | 282 | visitor.visit_id(item.id); |
b039eaaf SL |
283 | walk_opt_name(visitor, item.span, opt_name) |
284 | } | |
e9174d1e | 285 | ItemUse(ref vp) => { |
5bcae85e | 286 | visitor.visit_id(item.id); |
e9174d1e | 287 | match vp.node { |
b039eaaf SL |
288 | ViewPathSimple(name, ref path) => { |
289 | visitor.visit_name(vp.span, name); | |
e9174d1e SL |
290 | visitor.visit_path(path, item.id); |
291 | } | |
292 | ViewPathGlob(ref path) => { | |
293 | visitor.visit_path(path, item.id); | |
294 | } | |
295 | ViewPathList(ref prefix, ref list) => { | |
3157f602 XL |
296 | visitor.visit_path(prefix, item.id); |
297 | for item in list { | |
298 | visitor.visit_path_list_item(prefix, item) | |
e9174d1e | 299 | } |
e9174d1e SL |
300 | } |
301 | } | |
302 | } | |
303 | ItemStatic(ref typ, _, ref expr) | | |
304 | ItemConst(ref typ, ref expr) => { | |
5bcae85e | 305 | visitor.visit_id(item.id); |
b039eaaf SL |
306 | visitor.visit_ty(typ); |
307 | visitor.visit_expr(expr); | |
e9174d1e SL |
308 | } |
309 | ItemFn(ref declaration, unsafety, constness, abi, ref generics, ref body) => { | |
b039eaaf SL |
310 | visitor.visit_fn(FnKind::ItemFn(item.name, |
311 | generics, | |
312 | unsafety, | |
313 | constness, | |
314 | abi, | |
54a0048b SL |
315 | &item.vis, |
316 | &item.attrs), | |
b039eaaf SL |
317 | declaration, |
318 | body, | |
e9174d1e SL |
319 | item.span, |
320 | item.id) | |
321 | } | |
322 | ItemMod(ref module) => { | |
5bcae85e | 323 | // visit_mod() takes care of visiting the Item's NodeId |
e9174d1e SL |
324 | visitor.visit_mod(module, item.span, item.id) |
325 | } | |
326 | ItemForeignMod(ref foreign_module) => { | |
5bcae85e | 327 | visitor.visit_id(item.id); |
b039eaaf | 328 | walk_list!(visitor, visit_foreign_item, &foreign_module.items); |
e9174d1e SL |
329 | } |
330 | ItemTy(ref typ, ref type_parameters) => { | |
5bcae85e | 331 | visitor.visit_id(item.id); |
b039eaaf | 332 | visitor.visit_ty(typ); |
e9174d1e SL |
333 | visitor.visit_generics(type_parameters) |
334 | } | |
335 | ItemEnum(ref enum_definition, ref type_parameters) => { | |
336 | visitor.visit_generics(type_parameters); | |
5bcae85e | 337 | // visit_enum_def() takes care of visiting the Item's NodeId |
b039eaaf | 338 | visitor.visit_enum_def(enum_definition, type_parameters, item.id, item.span) |
e9174d1e SL |
339 | } |
340 | ItemDefaultImpl(_, ref trait_ref) => { | |
5bcae85e | 341 | visitor.visit_id(item.id); |
e9174d1e SL |
342 | visitor.visit_trait_ref(trait_ref) |
343 | } | |
92a42be0 | 344 | ItemImpl(_, _, ref type_parameters, ref opt_trait_reference, ref typ, ref impl_items) => { |
5bcae85e | 345 | visitor.visit_id(item.id); |
e9174d1e | 346 | visitor.visit_generics(type_parameters); |
b039eaaf SL |
347 | walk_list!(visitor, visit_trait_ref, opt_trait_reference); |
348 | visitor.visit_ty(typ); | |
349 | walk_list!(visitor, visit_impl_item, impl_items); | |
e9174d1e SL |
350 | } |
351 | ItemStruct(ref struct_definition, ref generics) => { | |
352 | visitor.visit_generics(generics); | |
5bcae85e | 353 | visitor.visit_id(item.id); |
92a42be0 | 354 | visitor.visit_variant_data(struct_definition, item.name, generics, item.id, item.span); |
e9174d1e SL |
355 | } |
356 | ItemTrait(_, ref generics, ref bounds, ref methods) => { | |
5bcae85e | 357 | visitor.visit_id(item.id); |
e9174d1e | 358 | visitor.visit_generics(generics); |
b039eaaf SL |
359 | walk_list!(visitor, visit_ty_param_bound, bounds); |
360 | walk_list!(visitor, visit_trait_item, methods); | |
e9174d1e SL |
361 | } |
362 | } | |
b039eaaf | 363 | walk_list!(visitor, visit_attribute, &item.attrs); |
e9174d1e SL |
364 | } |
365 | ||
366 | pub fn walk_enum_def<'v, V: Visitor<'v>>(visitor: &mut V, | |
367 | enum_definition: &'v EnumDef, | |
b039eaaf SL |
368 | generics: &'v Generics, |
369 | item_id: NodeId) { | |
5bcae85e | 370 | visitor.visit_id(item_id); |
92a42be0 SL |
371 | walk_list!(visitor, |
372 | visit_variant, | |
373 | &enum_definition.variants, | |
374 | generics, | |
375 | item_id); | |
e9174d1e SL |
376 | } |
377 | ||
378 | pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V, | |
379 | variant: &'v Variant, | |
b039eaaf | 380 | generics: &'v Generics, |
5bcae85e | 381 | parent_item_id: NodeId) { |
b039eaaf | 382 | visitor.visit_name(variant.span, variant.node.name); |
92a42be0 SL |
383 | visitor.visit_variant_data(&variant.node.data, |
384 | variant.node.name, | |
385 | generics, | |
5bcae85e | 386 | parent_item_id, |
92a42be0 | 387 | variant.span); |
b039eaaf SL |
388 | walk_list!(visitor, visit_expr, &variant.node.disr_expr); |
389 | walk_list!(visitor, visit_attribute, &variant.node.attrs); | |
e9174d1e SL |
390 | } |
391 | ||
392 | pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { | |
5bcae85e SL |
393 | visitor.visit_id(typ.id); |
394 | ||
e9174d1e | 395 | match typ.node { |
92a42be0 | 396 | TyVec(ref ty) => { |
b039eaaf | 397 | visitor.visit_ty(ty) |
e9174d1e SL |
398 | } |
399 | TyPtr(ref mutable_type) => { | |
b039eaaf | 400 | visitor.visit_ty(&mutable_type.ty) |
e9174d1e | 401 | } |
b039eaaf SL |
402 | TyRptr(ref opt_lifetime, ref mutable_type) => { |
403 | walk_list!(visitor, visit_lifetime, opt_lifetime); | |
404 | visitor.visit_ty(&mutable_type.ty) | |
e9174d1e | 405 | } |
5bcae85e | 406 | TyNever => {}, |
e9174d1e | 407 | TyTup(ref tuple_element_types) => { |
b039eaaf | 408 | walk_list!(visitor, visit_ty, tuple_element_types); |
e9174d1e SL |
409 | } |
410 | TyBareFn(ref function_declaration) => { | |
b039eaaf | 411 | walk_fn_decl(visitor, &function_declaration.decl); |
92a42be0 | 412 | walk_list!(visitor, visit_lifetime_def, &function_declaration.lifetimes); |
e9174d1e SL |
413 | } |
414 | TyPath(ref maybe_qself, ref path) => { | |
415 | if let Some(ref qself) = *maybe_qself { | |
416 | visitor.visit_ty(&qself.ty); | |
417 | } | |
418 | visitor.visit_path(path, typ.id); | |
419 | } | |
420 | TyObjectSum(ref ty, ref bounds) => { | |
b039eaaf SL |
421 | visitor.visit_ty(ty); |
422 | walk_list!(visitor, visit_ty_param_bound, bounds); | |
e9174d1e SL |
423 | } |
424 | TyFixedLengthVec(ref ty, ref expression) => { | |
b039eaaf SL |
425 | visitor.visit_ty(ty); |
426 | visitor.visit_expr(expression) | |
e9174d1e SL |
427 | } |
428 | TyPolyTraitRef(ref bounds) => { | |
b039eaaf | 429 | walk_list!(visitor, visit_ty_param_bound, bounds); |
e9174d1e | 430 | } |
5bcae85e SL |
431 | TyImplTrait(ref bounds) => { |
432 | walk_list!(visitor, visit_ty_param_bound, bounds); | |
433 | } | |
e9174d1e | 434 | TyTypeof(ref expression) => { |
b039eaaf | 435 | visitor.visit_expr(expression) |
e9174d1e SL |
436 | } |
437 | TyInfer => {} | |
438 | } | |
439 | } | |
440 | ||
e9174d1e SL |
441 | pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) { |
442 | for segment in &path.segments { | |
443 | visitor.visit_path_segment(path.span, segment); | |
444 | } | |
445 | } | |
446 | ||
b039eaaf | 447 | pub fn walk_path_list_item<'v, V: Visitor<'v>>(visitor: &mut V, |
3157f602 | 448 | _prefix: &'v Path, |
b039eaaf | 449 | item: &'v PathListItem) { |
5bcae85e | 450 | visitor.visit_id(item.node.id()); |
b039eaaf SL |
451 | walk_opt_name(visitor, item.span, item.node.name()); |
452 | walk_opt_name(visitor, item.span, item.node.rename()); | |
453 | } | |
454 | ||
e9174d1e SL |
455 | pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V, |
456 | path_span: Span, | |
457 | segment: &'v PathSegment) { | |
a7813a04 | 458 | visitor.visit_name(path_span, segment.name); |
e9174d1e SL |
459 | visitor.visit_path_parameters(path_span, &segment.parameters); |
460 | } | |
461 | ||
462 | pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V, | |
463 | _path_span: Span, | |
464 | path_parameters: &'v PathParameters) { | |
465 | match *path_parameters { | |
b039eaaf SL |
466 | AngleBracketedParameters(ref data) => { |
467 | walk_list!(visitor, visit_ty, &data.types); | |
468 | walk_list!(visitor, visit_lifetime, &data.lifetimes); | |
469 | walk_list!(visitor, visit_assoc_type_binding, &data.bindings); | |
e9174d1e | 470 | } |
b039eaaf SL |
471 | ParenthesizedParameters(ref data) => { |
472 | walk_list!(visitor, visit_ty, &data.inputs); | |
473 | walk_list!(visitor, visit_ty, &data.output); | |
e9174d1e SL |
474 | } |
475 | } | |
476 | } | |
477 | ||
478 | pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V, | |
479 | type_binding: &'v TypeBinding) { | |
5bcae85e | 480 | visitor.visit_id(type_binding.id); |
b039eaaf SL |
481 | visitor.visit_name(type_binding.span, type_binding.name); |
482 | visitor.visit_ty(&type_binding.ty); | |
e9174d1e SL |
483 | } |
484 | ||
485 | pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) { | |
5bcae85e | 486 | visitor.visit_id(pattern.id); |
e9174d1e | 487 | match pattern.node { |
3157f602 | 488 | PatKind::TupleStruct(ref path, ref children, _) => { |
e9174d1e | 489 | visitor.visit_path(path, pattern.id); |
3157f602 | 490 | walk_list!(visitor, visit_pat, children); |
e9174d1e | 491 | } |
5bcae85e SL |
492 | PatKind::Path(ref opt_qself, ref path) => { |
493 | if let Some(ref qself) = *opt_qself { | |
494 | visitor.visit_ty(&qself.ty); | |
495 | } | |
e9174d1e SL |
496 | visitor.visit_path(path, pattern.id) |
497 | } | |
7453a54e | 498 | PatKind::Struct(ref path, ref fields, _) => { |
e9174d1e SL |
499 | visitor.visit_path(path, pattern.id); |
500 | for field in fields { | |
b039eaaf SL |
501 | visitor.visit_name(field.span, field.node.name); |
502 | visitor.visit_pat(&field.node.pat) | |
e9174d1e SL |
503 | } |
504 | } | |
3157f602 | 505 | PatKind::Tuple(ref tuple_elements, _) => { |
b039eaaf | 506 | walk_list!(visitor, visit_pat, tuple_elements); |
e9174d1e | 507 | } |
7453a54e SL |
508 | PatKind::Box(ref subpattern) | |
509 | PatKind::Ref(ref subpattern, _) => { | |
b039eaaf | 510 | visitor.visit_pat(subpattern) |
e9174d1e | 511 | } |
3157f602 | 512 | PatKind::Binding(_, ref pth1, ref optional_subpattern) => { |
a7813a04 | 513 | visitor.visit_name(pth1.span, pth1.node); |
b039eaaf | 514 | walk_list!(visitor, visit_pat, optional_subpattern); |
e9174d1e | 515 | } |
7453a54e SL |
516 | PatKind::Lit(ref expression) => visitor.visit_expr(expression), |
517 | PatKind::Range(ref lower_bound, ref upper_bound) => { | |
b039eaaf SL |
518 | visitor.visit_expr(lower_bound); |
519 | visitor.visit_expr(upper_bound) | |
e9174d1e | 520 | } |
7453a54e SL |
521 | PatKind::Wild => (), |
522 | PatKind::Vec(ref prepatterns, ref slice_pattern, ref postpatterns) => { | |
b039eaaf SL |
523 | walk_list!(visitor, visit_pat, prepatterns); |
524 | walk_list!(visitor, visit_pat, slice_pattern); | |
525 | walk_list!(visitor, visit_pat, postpatterns); | |
e9174d1e SL |
526 | } |
527 | } | |
528 | } | |
529 | ||
b039eaaf | 530 | pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem) { |
5bcae85e | 531 | visitor.visit_id(foreign_item.id); |
a7813a04 | 532 | visitor.visit_vis(&foreign_item.vis); |
b039eaaf | 533 | visitor.visit_name(foreign_item.span, foreign_item.name); |
e9174d1e SL |
534 | |
535 | match foreign_item.node { | |
536 | ForeignItemFn(ref function_declaration, ref generics) => { | |
b039eaaf | 537 | walk_fn_decl(visitor, function_declaration); |
e9174d1e SL |
538 | visitor.visit_generics(generics) |
539 | } | |
b039eaaf | 540 | ForeignItemStatic(ref typ, _) => visitor.visit_ty(typ), |
e9174d1e SL |
541 | } |
542 | ||
b039eaaf | 543 | walk_list!(visitor, visit_attribute, &foreign_item.attrs); |
e9174d1e SL |
544 | } |
545 | ||
b039eaaf | 546 | pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v TyParamBound) { |
e9174d1e SL |
547 | match *bound { |
548 | TraitTyParamBound(ref typ, ref modifier) => { | |
549 | visitor.visit_poly_trait_ref(typ, modifier); | |
550 | } | |
551 | RegionTyParamBound(ref lifetime) => { | |
b039eaaf | 552 | visitor.visit_lifetime(lifetime); |
e9174d1e SL |
553 | } |
554 | } | |
555 | } | |
556 | ||
557 | pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) { | |
b039eaaf | 558 | for param in &generics.ty_params { |
5bcae85e | 559 | visitor.visit_id(param.id); |
b039eaaf SL |
560 | visitor.visit_name(param.span, param.name); |
561 | walk_list!(visitor, visit_ty_param_bound, ¶m.bounds); | |
562 | walk_list!(visitor, visit_ty, ¶m.default); | |
e9174d1e | 563 | } |
b039eaaf | 564 | walk_list!(visitor, visit_lifetime_def, &generics.lifetimes); |
5bcae85e | 565 | visitor.visit_id(generics.where_clause.id); |
3157f602 XL |
566 | walk_list!(visitor, visit_where_predicate, &generics.where_clause.predicates); |
567 | } | |
568 | ||
569 | pub fn walk_where_predicate<'v, V: Visitor<'v>>( | |
570 | visitor: &mut V, | |
571 | predicate: &'v WherePredicate) | |
572 | { | |
573 | match predicate { | |
574 | &WherePredicate::BoundPredicate(WhereBoundPredicate{ref bounded_ty, | |
575 | ref bounds, | |
576 | ref bound_lifetimes, | |
577 | ..}) => { | |
578 | visitor.visit_ty(bounded_ty); | |
579 | walk_list!(visitor, visit_ty_param_bound, bounds); | |
580 | walk_list!(visitor, visit_lifetime_def, bound_lifetimes); | |
581 | } | |
582 | &WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime, | |
583 | ref bounds, | |
584 | ..}) => { | |
585 | visitor.visit_lifetime(lifetime); | |
586 | walk_list!(visitor, visit_lifetime, bounds); | |
587 | } | |
588 | &WherePredicate::EqPredicate(WhereEqPredicate{id, | |
589 | ref path, | |
590 | ref ty, | |
591 | ..}) => { | |
5bcae85e | 592 | visitor.visit_id(id); |
3157f602 XL |
593 | visitor.visit_path(path, id); |
594 | visitor.visit_ty(ty); | |
e9174d1e SL |
595 | } |
596 | } | |
597 | } | |
598 | ||
599 | pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FunctionRetTy) { | |
600 | if let Return(ref output_ty) = *ret_ty { | |
b039eaaf | 601 | visitor.visit_ty(output_ty) |
e9174d1e SL |
602 | } |
603 | } | |
604 | ||
605 | pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) { | |
606 | for argument in &function_declaration.inputs { | |
5bcae85e | 607 | visitor.visit_id(argument.id); |
b039eaaf SL |
608 | visitor.visit_pat(&argument.pat); |
609 | visitor.visit_ty(&argument.ty) | |
e9174d1e SL |
610 | } |
611 | walk_fn_ret_ty(visitor, &function_declaration.output) | |
612 | } | |
613 | ||
b039eaaf SL |
614 | pub fn walk_fn_decl_nopat<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) { |
615 | for argument in &function_declaration.inputs { | |
5bcae85e | 616 | visitor.visit_id(argument.id); |
b039eaaf SL |
617 | visitor.visit_ty(&argument.ty) |
618 | } | |
619 | walk_fn_ret_ty(visitor, &function_declaration.output) | |
620 | } | |
621 | ||
622 | pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'v>) { | |
e9174d1e | 623 | match function_kind { |
54a0048b | 624 | FnKind::ItemFn(_, generics, _, _, _, _, _) => { |
e9174d1e SL |
625 | visitor.visit_generics(generics); |
626 | } | |
54a0048b | 627 | FnKind::Method(_, sig, _, _) => { |
e9174d1e | 628 | visitor.visit_generics(&sig.generics); |
e9174d1e | 629 | } |
54a0048b | 630 | FnKind::Closure(_) => {} |
e9174d1e SL |
631 | } |
632 | } | |
633 | ||
634 | pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V, | |
635 | function_kind: FnKind<'v>, | |
636 | function_declaration: &'v FnDecl, | |
637 | function_body: &'v Block, | |
5bcae85e SL |
638 | _span: Span, |
639 | id: NodeId) { | |
640 | visitor.visit_id(id); | |
e9174d1e SL |
641 | walk_fn_decl(visitor, function_declaration); |
642 | walk_fn_kind(visitor, function_kind); | |
643 | visitor.visit_block(function_body) | |
644 | } | |
645 | ||
646 | pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem) { | |
b039eaaf SL |
647 | visitor.visit_name(trait_item.span, trait_item.name); |
648 | walk_list!(visitor, visit_attribute, &trait_item.attrs); | |
e9174d1e SL |
649 | match trait_item.node { |
650 | ConstTraitItem(ref ty, ref default) => { | |
5bcae85e | 651 | visitor.visit_id(trait_item.id); |
e9174d1e | 652 | visitor.visit_ty(ty); |
b039eaaf | 653 | walk_list!(visitor, visit_expr, default); |
e9174d1e SL |
654 | } |
655 | MethodTraitItem(ref sig, None) => { | |
5bcae85e | 656 | visitor.visit_id(trait_item.id); |
e9174d1e SL |
657 | visitor.visit_generics(&sig.generics); |
658 | walk_fn_decl(visitor, &sig.decl); | |
659 | } | |
660 | MethodTraitItem(ref sig, Some(ref body)) => { | |
54a0048b SL |
661 | visitor.visit_fn(FnKind::Method(trait_item.name, |
662 | sig, | |
663 | None, | |
664 | &trait_item.attrs), | |
b039eaaf SL |
665 | &sig.decl, |
666 | body, | |
667 | trait_item.span, | |
668 | trait_item.id); | |
e9174d1e SL |
669 | } |
670 | TypeTraitItem(ref bounds, ref default) => { | |
5bcae85e | 671 | visitor.visit_id(trait_item.id); |
b039eaaf SL |
672 | walk_list!(visitor, visit_ty_param_bound, bounds); |
673 | walk_list!(visitor, visit_ty, default); | |
e9174d1e SL |
674 | } |
675 | } | |
676 | } | |
677 | ||
678 | pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) { | |
a7813a04 | 679 | visitor.visit_vis(&impl_item.vis); |
b039eaaf SL |
680 | visitor.visit_name(impl_item.span, impl_item.name); |
681 | walk_list!(visitor, visit_attribute, &impl_item.attrs); | |
e9174d1e | 682 | match impl_item.node { |
92a42be0 | 683 | ImplItemKind::Const(ref ty, ref expr) => { |
5bcae85e | 684 | visitor.visit_id(impl_item.id); |
e9174d1e SL |
685 | visitor.visit_ty(ty); |
686 | visitor.visit_expr(expr); | |
687 | } | |
92a42be0 | 688 | ImplItemKind::Method(ref sig, ref body) => { |
54a0048b SL |
689 | visitor.visit_fn(FnKind::Method(impl_item.name, |
690 | sig, | |
691 | Some(&impl_item.vis), | |
692 | &impl_item.attrs), | |
b039eaaf SL |
693 | &sig.decl, |
694 | body, | |
695 | impl_item.span, | |
696 | impl_item.id); | |
e9174d1e | 697 | } |
92a42be0 | 698 | ImplItemKind::Type(ref ty) => { |
5bcae85e | 699 | visitor.visit_id(impl_item.id); |
e9174d1e SL |
700 | visitor.visit_ty(ty); |
701 | } | |
702 | } | |
703 | } | |
704 | ||
b039eaaf | 705 | pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V, struct_definition: &'v VariantData) { |
5bcae85e | 706 | visitor.visit_id(struct_definition.id()); |
b039eaaf | 707 | walk_list!(visitor, visit_struct_field, struct_definition.fields()); |
e9174d1e SL |
708 | } |
709 | ||
b039eaaf | 710 | pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V, struct_field: &'v StructField) { |
5bcae85e | 711 | visitor.visit_id(struct_field.id); |
a7813a04 | 712 | visitor.visit_vis(&struct_field.vis); |
54a0048b SL |
713 | visitor.visit_name(struct_field.span, struct_field.name); |
714 | visitor.visit_ty(&struct_field.ty); | |
715 | walk_list!(visitor, visit_attribute, &struct_field.attrs); | |
e9174d1e SL |
716 | } |
717 | ||
718 | pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block) { | |
5bcae85e | 719 | visitor.visit_id(block.id); |
b039eaaf SL |
720 | walk_list!(visitor, visit_stmt, &block.stmts); |
721 | walk_list!(visitor, visit_expr, &block.expr); | |
e9174d1e SL |
722 | } |
723 | ||
724 | pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt) { | |
725 | match statement.node { | |
5bcae85e SL |
726 | StmtDecl(ref declaration, id) => { |
727 | visitor.visit_id(id); | |
728 | visitor.visit_decl(declaration) | |
729 | } | |
730 | StmtExpr(ref expression, id) | | |
731 | StmtSemi(ref expression, id) => { | |
732 | visitor.visit_id(id); | |
b039eaaf | 733 | visitor.visit_expr(expression) |
e9174d1e SL |
734 | } |
735 | } | |
736 | } | |
737 | ||
738 | pub fn walk_decl<'v, V: Visitor<'v>>(visitor: &mut V, declaration: &'v Decl) { | |
739 | match declaration.node { | |
b039eaaf | 740 | DeclLocal(ref local) => visitor.visit_local(local), |
92a42be0 | 741 | DeclItem(item) => visitor.visit_nested_item(item), |
e9174d1e SL |
742 | } |
743 | } | |
744 | ||
745 | pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { | |
5bcae85e | 746 | visitor.visit_id(expression.id); |
e9174d1e | 747 | match expression.node { |
b039eaaf SL |
748 | ExprBox(ref subexpression) => { |
749 | visitor.visit_expr(subexpression) | |
e9174d1e SL |
750 | } |
751 | ExprVec(ref subexpressions) => { | |
b039eaaf | 752 | walk_list!(visitor, visit_expr, subexpressions); |
e9174d1e SL |
753 | } |
754 | ExprRepeat(ref element, ref count) => { | |
b039eaaf SL |
755 | visitor.visit_expr(element); |
756 | visitor.visit_expr(count) | |
e9174d1e SL |
757 | } |
758 | ExprStruct(ref path, ref fields, ref optional_base) => { | |
759 | visitor.visit_path(path, expression.id); | |
760 | for field in fields { | |
b039eaaf SL |
761 | visitor.visit_name(field.name.span, field.name.node); |
762 | visitor.visit_expr(&field.expr) | |
e9174d1e | 763 | } |
b039eaaf | 764 | walk_list!(visitor, visit_expr, optional_base); |
e9174d1e SL |
765 | } |
766 | ExprTup(ref subexpressions) => { | |
b039eaaf | 767 | walk_list!(visitor, visit_expr, subexpressions); |
e9174d1e SL |
768 | } |
769 | ExprCall(ref callee_expression, ref arguments) => { | |
b039eaaf SL |
770 | walk_list!(visitor, visit_expr, arguments); |
771 | visitor.visit_expr(callee_expression) | |
e9174d1e | 772 | } |
b039eaaf SL |
773 | ExprMethodCall(ref name, ref types, ref arguments) => { |
774 | visitor.visit_name(name.span, name.node); | |
775 | walk_list!(visitor, visit_expr, arguments); | |
776 | walk_list!(visitor, visit_ty, types); | |
e9174d1e SL |
777 | } |
778 | ExprBinary(_, ref left_expression, ref right_expression) => { | |
b039eaaf SL |
779 | visitor.visit_expr(left_expression); |
780 | visitor.visit_expr(right_expression) | |
e9174d1e SL |
781 | } |
782 | ExprAddrOf(_, ref subexpression) | ExprUnary(_, ref subexpression) => { | |
b039eaaf | 783 | visitor.visit_expr(subexpression) |
e9174d1e SL |
784 | } |
785 | ExprLit(_) => {} | |
9cc50fc6 | 786 | ExprCast(ref subexpression, ref typ) | ExprType(ref subexpression, ref typ) => { |
b039eaaf SL |
787 | visitor.visit_expr(subexpression); |
788 | visitor.visit_ty(typ) | |
e9174d1e SL |
789 | } |
790 | ExprIf(ref head_expression, ref if_block, ref optional_else) => { | |
b039eaaf SL |
791 | visitor.visit_expr(head_expression); |
792 | visitor.visit_block(if_block); | |
793 | walk_list!(visitor, visit_expr, optional_else); | |
e9174d1e | 794 | } |
3157f602 | 795 | ExprWhile(ref subexpression, ref block, ref opt_sp_name) => { |
b039eaaf SL |
796 | visitor.visit_expr(subexpression); |
797 | visitor.visit_block(block); | |
3157f602 | 798 | walk_opt_sp_name(visitor, opt_sp_name); |
b039eaaf | 799 | } |
3157f602 | 800 | ExprLoop(ref block, ref opt_sp_name) => { |
b039eaaf | 801 | visitor.visit_block(block); |
3157f602 | 802 | walk_opt_sp_name(visitor, opt_sp_name); |
e9174d1e | 803 | } |
e9174d1e | 804 | ExprMatch(ref subexpression, ref arms, _) => { |
b039eaaf SL |
805 | visitor.visit_expr(subexpression); |
806 | walk_list!(visitor, visit_arm, arms); | |
e9174d1e | 807 | } |
a7813a04 | 808 | ExprClosure(_, ref function_declaration, ref body, _fn_decl_span) => { |
3157f602 | 809 | visitor.visit_fn(FnKind::Closure(&expression.attrs), |
b039eaaf SL |
810 | function_declaration, |
811 | body, | |
e9174d1e SL |
812 | expression.span, |
813 | expression.id) | |
814 | } | |
b039eaaf | 815 | ExprBlock(ref block) => visitor.visit_block(block), |
e9174d1e | 816 | ExprAssign(ref left_hand_expression, ref right_hand_expression) => { |
b039eaaf SL |
817 | visitor.visit_expr(right_hand_expression); |
818 | visitor.visit_expr(left_hand_expression) | |
e9174d1e SL |
819 | } |
820 | ExprAssignOp(_, ref left_expression, ref right_expression) => { | |
b039eaaf SL |
821 | visitor.visit_expr(right_expression); |
822 | visitor.visit_expr(left_expression) | |
e9174d1e | 823 | } |
b039eaaf SL |
824 | ExprField(ref subexpression, ref name) => { |
825 | visitor.visit_expr(subexpression); | |
826 | visitor.visit_name(name.span, name.node); | |
e9174d1e SL |
827 | } |
828 | ExprTupField(ref subexpression, _) => { | |
b039eaaf | 829 | visitor.visit_expr(subexpression); |
e9174d1e SL |
830 | } |
831 | ExprIndex(ref main_expression, ref index_expression) => { | |
b039eaaf SL |
832 | visitor.visit_expr(main_expression); |
833 | visitor.visit_expr(index_expression) | |
e9174d1e | 834 | } |
e9174d1e SL |
835 | ExprPath(ref maybe_qself, ref path) => { |
836 | if let Some(ref qself) = *maybe_qself { | |
837 | visitor.visit_ty(&qself.ty); | |
838 | } | |
839 | visitor.visit_path(path, expression.id) | |
840 | } | |
a7813a04 | 841 | ExprBreak(ref opt_sp_name) | ExprAgain(ref opt_sp_name) => { |
3157f602 | 842 | walk_opt_sp_name(visitor, opt_sp_name); |
e9174d1e | 843 | } |
b039eaaf SL |
844 | ExprRet(ref optional_expression) => { |
845 | walk_list!(visitor, visit_expr, optional_expression); | |
e9174d1e | 846 | } |
54a0048b SL |
847 | ExprInlineAsm(_, ref outputs, ref inputs) => { |
848 | for output in outputs { | |
849 | visitor.visit_expr(output) | |
e9174d1e | 850 | } |
54a0048b SL |
851 | for input in inputs { |
852 | visitor.visit_expr(input) | |
e9174d1e SL |
853 | } |
854 | } | |
855 | } | |
856 | ||
857 | visitor.visit_expr_post(expression) | |
858 | } | |
859 | ||
860 | pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) { | |
b039eaaf SL |
861 | walk_list!(visitor, visit_pat, &arm.pats); |
862 | walk_list!(visitor, visit_expr, &arm.guard); | |
863 | visitor.visit_expr(&arm.body); | |
864 | walk_list!(visitor, visit_attribute, &arm.attrs); | |
e9174d1e | 865 | } |
54a0048b | 866 | |
a7813a04 XL |
867 | pub fn walk_vis<'v, V: Visitor<'v>>(visitor: &mut V, vis: &'v Visibility) { |
868 | if let Visibility::Restricted { ref path, id } = *vis { | |
5bcae85e | 869 | visitor.visit_id(id); |
a7813a04 XL |
870 | visitor.visit_path(path, id) |
871 | } | |
872 | } | |
873 | ||
5bcae85e | 874 | #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq)] |
54a0048b SL |
875 | pub struct IdRange { |
876 | pub min: NodeId, | |
877 | pub max: NodeId, | |
878 | } | |
879 | ||
880 | impl IdRange { | |
881 | pub fn max() -> IdRange { | |
882 | IdRange { | |
883 | min: u32::MAX, | |
884 | max: u32::MIN, | |
885 | } | |
886 | } | |
887 | ||
888 | pub fn empty(&self) -> bool { | |
889 | self.min >= self.max | |
890 | } | |
891 | ||
5bcae85e SL |
892 | pub fn contains(&self, id: NodeId) -> bool { |
893 | id >= self.min && id < self.max | |
894 | } | |
895 | ||
54a0048b SL |
896 | pub fn add(&mut self, id: NodeId) { |
897 | self.min = cmp::min(self.min, id); | |
898 | self.max = cmp::max(self.max, id + 1); | |
899 | } | |
54a0048b | 900 | |
54a0048b SL |
901 | } |
902 | ||
5bcae85e | 903 | |
54a0048b SL |
904 | pub struct IdRangeComputingVisitor { |
905 | pub result: IdRange, | |
906 | } | |
907 | ||
908 | impl IdRangeComputingVisitor { | |
909 | pub fn new() -> IdRangeComputingVisitor { | |
910 | IdRangeComputingVisitor { result: IdRange::max() } | |
911 | } | |
912 | ||
913 | pub fn result(&self) -> IdRange { | |
914 | self.result | |
915 | } | |
916 | } | |
917 | ||
5bcae85e | 918 | impl<'v> Visitor<'v> for IdRangeComputingVisitor { |
54a0048b SL |
919 | fn visit_id(&mut self, id: NodeId) { |
920 | self.result.add(id); | |
921 | } | |
922 | } | |
923 | ||
54a0048b SL |
924 | /// Computes the id range for a single fn body, ignoring nested items. |
925 | pub fn compute_id_range_for_fn_body(fk: FnKind, | |
926 | decl: &FnDecl, | |
927 | body: &Block, | |
928 | sp: Span, | |
929 | id: NodeId) | |
930 | -> IdRange { | |
5bcae85e SL |
931 | let mut visitor = IdRangeComputingVisitor::new(); |
932 | visitor.visit_fn(fk, decl, body, sp, id); | |
933 | visitor.result() | |
54a0048b | 934 | } |