@@ -26,6 +26,23 @@ struct NodeData {
26
26
size : usize ,
27
27
}
28
28
29
+ /// This type measures the size of AST and HIR nodes, by implementing the AST
30
+ /// and HIR `Visitor` traits. But we don't measure every visited type because
31
+ /// that could cause double counting.
32
+ ///
33
+ /// For example, `ast::Visitor` has `visit_ident`, but `Ident`s are always
34
+ /// stored inline within other AST nodes, so we don't implement `visit_ident`
35
+ /// here. In constrast, we do implement `visit_expr` because `ast::Expr` is
36
+ /// always stored as `P<ast::Expr>`, and every such expression should be
37
+ /// measured separately.
38
+ ///
39
+ /// In general, a `visit_foo` method should be implemented here if the
40
+ /// corresponding `Foo` type is always stored on its own, e.g.: `P<Foo>`,
41
+ /// `Box<Foo>`, `Vec<Foo>`, `Box<[Foo]>`.
42
+ ///
43
+ /// There are some types in the AST and HIR tree that the visitors do not have
44
+ /// a `visit_*` method for, and so we cannot measure these, which is
45
+ /// unfortunate.
29
46
struct StatCollector < ' k > {
30
47
krate : Option < Map < ' k > > ,
31
48
data : FxHashMap < & ' static str , NodeData > ,
@@ -44,9 +61,11 @@ pub fn print_hir_stats(tcx: TyCtxt<'_>) {
44
61
}
45
62
46
63
pub fn print_ast_stats ( krate : & ast:: Crate , title : & str ) {
64
+ use rustc_ast:: visit:: Visitor ;
65
+
47
66
let mut collector =
48
67
StatCollector { krate : None , data : FxHashMap :: default ( ) , seen : FxHashSet :: default ( ) } ;
49
- ast_visit :: walk_crate ( & mut collector, krate) ;
68
+ collector. visit_crate ( krate) ;
50
69
collector. print ( title) ;
51
70
}
52
71
@@ -228,6 +247,10 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
228
247
hir_visit:: walk_path ( self , path)
229
248
}
230
249
250
+ // `PathSegment` has one inline use (in `ast::ExprKind::MethodCall`) and
251
+ // one non-inline use (in `Path::segments`). The latter case is more common
252
+ // than the former case, so we implement this visitor and tolerate the
253
+ // double counting in the former case.
231
254
fn visit_path_segment ( & mut self , path_span : Span , path_segment : & ' v hir:: PathSegment < ' v > ) {
232
255
self . record ( "PathSegment" , Id :: None , path_segment) ;
233
256
hir_visit:: walk_path_segment ( self , path_span, path_segment)
@@ -269,6 +292,11 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
269
292
ast_visit:: walk_stmt ( self , s)
270
293
}
271
294
295
+ fn visit_param ( & mut self , p : & ' v ast:: Param ) {
296
+ self . record ( "Param" , Id :: None , p) ;
297
+ ast_visit:: walk_param ( self , p)
298
+ }
299
+
272
300
fn visit_arm ( & mut self , a : & ' v ast:: Arm ) {
273
301
self . record ( "Arm" , Id :: None , a) ;
274
302
ast_visit:: walk_arm ( self , a)
@@ -289,6 +317,16 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
289
317
ast_visit:: walk_ty ( self , t)
290
318
}
291
319
320
+ fn visit_generic_param ( & mut self , g : & ' v ast:: GenericParam ) {
321
+ self . record ( "GenericParam" , Id :: None , g) ;
322
+ ast_visit:: walk_generic_param ( self , g)
323
+ }
324
+
325
+ fn visit_where_predicate ( & mut self , p : & ' v ast:: WherePredicate ) {
326
+ self . record ( "WherePredicate" , Id :: None , p) ;
327
+ ast_visit:: walk_where_predicate ( self , p)
328
+ }
329
+
292
330
fn visit_fn ( & mut self , fk : ast_visit:: FnKind < ' v > , s : Span , _: NodeId ) {
293
331
self . record ( "FnDecl" , Id :: None , fk. decl ( ) ) ;
294
332
ast_visit:: walk_fn ( self , fk, s)
@@ -318,27 +356,42 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
318
356
ast_visit:: walk_variant ( self , v)
319
357
}
320
358
321
- fn visit_lifetime ( & mut self , lifetime : & ' v ast:: Lifetime , _: ast_visit:: LifetimeCtxt ) {
322
- self . record ( "Lifetime" , Id :: None , lifetime) ;
323
- ast_visit:: walk_lifetime ( self , lifetime)
324
- }
325
-
326
- fn visit_mac_call ( & mut self , mac : & ' v ast:: MacCall ) {
327
- self . record ( "MacCall" , Id :: None , mac) ;
328
- ast_visit:: walk_mac ( self , mac)
329
- }
359
+ // `UseTree` has one inline use (in `ast::ItemKind::Use`) and one
360
+ // non-inline use (in `ast::UseTreeKind::Nested). The former case is more
361
+ // common, so we don't implement `visit_use_tree` and tolerate the missed
362
+ // coverage in the latter case.
330
363
331
364
fn visit_path_segment ( & mut self , path_span : Span , path_segment : & ' v ast:: PathSegment ) {
332
365
self . record ( "PathSegment" , Id :: None , path_segment) ;
333
366
ast_visit:: walk_path_segment ( self , path_span, path_segment)
334
367
}
335
368
336
- fn visit_assoc_constraint ( & mut self , constraint : & ' v ast:: AssocConstraint ) {
337
- self . record ( "AssocConstraint" , Id :: None , constraint) ;
338
- ast_visit:: walk_assoc_constraint ( self , constraint)
369
+ // `GenericArgs` has one inline use (in `ast::AssocConstraint::gen_args`) and one
370
+ // non-inline use (in `ast::PathSegment::args`). The latter case is more
371
+ // common, so we implement `visit_generic_args` and tolerate the double
372
+ // counting in the former case.
373
+ fn visit_generic_args ( & mut self , sp : Span , g : & ' v ast:: GenericArgs ) {
374
+ self . record ( "GenericArgs" , Id :: None , g) ;
375
+ ast_visit:: walk_generic_args ( self , sp, g)
339
376
}
340
377
341
378
fn visit_attribute ( & mut self , attr : & ' v ast:: Attribute ) {
342
379
self . record ( "Attribute" , Id :: None , attr) ;
380
+ ast_visit:: walk_attribute ( self , attr)
381
+ }
382
+
383
+ fn visit_expr_field ( & mut self , f : & ' v ast:: ExprField ) {
384
+ self . record ( "ExprField" , Id :: None , f) ;
385
+ ast_visit:: walk_expr_field ( self , f)
386
+ }
387
+
388
+ fn visit_crate ( & mut self , krate : & ' v ast:: Crate ) {
389
+ self . record ( "Crate" , Id :: None , krate) ;
390
+ ast_visit:: walk_crate ( self , krate)
391
+ }
392
+
393
+ fn visit_inline_asm ( & mut self , asm : & ' v ast:: InlineAsm ) {
394
+ self . record ( "InlineAsm" , Id :: None , asm) ;
395
+ ast_visit:: walk_inline_asm ( self , asm)
343
396
}
344
397
}
0 commit comments