@@ -26,6 +26,23 @@ struct NodeData {
2626 size : usize ,
2727}
2828
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.
2946struct StatCollector < ' k > {
3047 krate : Option < Map < ' k > > ,
3148 data : FxHashMap < & ' static str , NodeData > ,
@@ -44,9 +61,11 @@ pub fn print_hir_stats(tcx: TyCtxt<'_>) {
4461}
4562
4663pub fn print_ast_stats ( krate : & ast:: Crate , title : & str ) {
64+ use rustc_ast:: visit:: Visitor ;
65+
4766 let mut collector =
4867 StatCollector { krate : None , data : FxHashMap :: default ( ) , seen : FxHashSet :: default ( ) } ;
49- ast_visit :: walk_crate ( & mut collector, krate) ;
68+ collector. visit_crate ( krate) ;
5069 collector. print ( title) ;
5170}
5271
@@ -228,6 +247,10 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
228247 hir_visit:: walk_path ( self , path)
229248 }
230249
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.
231254 fn visit_path_segment ( & mut self , path_span : Span , path_segment : & ' v hir:: PathSegment < ' v > ) {
232255 self . record ( "PathSegment" , Id :: None , path_segment) ;
233256 hir_visit:: walk_path_segment ( self , path_span, path_segment)
@@ -269,6 +292,11 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
269292 ast_visit:: walk_stmt ( self , s)
270293 }
271294
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+
272300 fn visit_arm ( & mut self , a : & ' v ast:: Arm ) {
273301 self . record ( "Arm" , Id :: None , a) ;
274302 ast_visit:: walk_arm ( self , a)
@@ -289,6 +317,16 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
289317 ast_visit:: walk_ty ( self , t)
290318 }
291319
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+
292330 fn visit_fn ( & mut self , fk : ast_visit:: FnKind < ' v > , s : Span , _: NodeId ) {
293331 self . record ( "FnDecl" , Id :: None , fk. decl ( ) ) ;
294332 ast_visit:: walk_fn ( self , fk, s)
@@ -318,27 +356,42 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
318356 ast_visit:: walk_variant ( self , v)
319357 }
320358
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.
330363
331364 fn visit_path_segment ( & mut self , path_span : Span , path_segment : & ' v ast:: PathSegment ) {
332365 self . record ( "PathSegment" , Id :: None , path_segment) ;
333366 ast_visit:: walk_path_segment ( self , path_span, path_segment)
334367 }
335368
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)
339376 }
340377
341378 fn visit_attribute ( & mut self , attr : & ' v ast:: Attribute ) {
342379 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)
343396 }
344397}
0 commit comments