@@ -67,6 +67,62 @@ impl<'a> FnKind<'a> {
6767 }
6868}
6969
70+ /// Specifies what nested things a visitor wants to visit. The most
71+ /// common choice is `OnlyBodies`, which will cause the visitor to
72+ /// visit fn bodies for fns that it encounters, but skip over nested
73+ /// item-like things.
74+ ///
75+ /// See the comments on `ItemLikeVisitor` for more details on the overall
76+ /// visit strategy.
77+ pub enum NestedVisitorMap < ' this , ' tcx : ' this > {
78+ /// Do not visit any nested things. When you add a new
79+ /// "non-nested" thing, you will want to audit such uses to see if
80+ /// they remain valid.
81+ ///
82+ /// Use this if you are only walking some particular kind of tree
83+ /// (i.e., a type, or fn signature) and you don't want to thread a
84+ /// HIR map around.
85+ None ,
86+
87+ /// Do not visit nested item-like things, but visit nested things
88+ /// that are inside of an item-like.
89+ ///
90+ /// **This is the most common choice.** A very commmon pattern is
91+ /// to use `tcx.visit_all_item_likes_in_krate()` as an outer loop,
92+ /// and to have the visitor that visits the contents of each item
93+ /// using this setting.
94+ OnlyBodies ( & ' this Map < ' tcx > ) ,
95+
96+ /// Visit all nested things, including item-likes.
97+ ///
98+ /// **This is an unusual choice.** It is used when you want to
99+ /// process everything within their lexical context. Typically you
100+ /// kick off the visit by doing `walk_krate()`.
101+ All ( & ' this Map < ' tcx > ) ,
102+ }
103+
104+ impl < ' this , ' tcx > NestedVisitorMap < ' this , ' tcx > {
105+ /// Returns the map to use for an "intra item-like" thing (if any).
106+ /// e.g., function body.
107+ pub fn intra ( self ) -> Option < & ' this Map < ' tcx > > {
108+ match self {
109+ NestedVisitorMap :: None => None ,
110+ NestedVisitorMap :: OnlyBodies ( map) => Some ( map) ,
111+ NestedVisitorMap :: All ( map) => Some ( map) ,
112+ }
113+ }
114+
115+ /// Returns the map to use for an "item-like" thing (if any).
116+ /// e.g., item, impl-item.
117+ pub fn inter ( self ) -> Option < & ' this Map < ' tcx > > {
118+ match self {
119+ NestedVisitorMap :: None => None ,
120+ NestedVisitorMap :: OnlyBodies ( _) => None ,
121+ NestedVisitorMap :: All ( map) => Some ( map) ,
122+ }
123+ }
124+ }
125+
70126/// Each method of the Visitor trait is a hook to be potentially
71127/// overridden. Each method's default implementation recursively visits
72128/// the substructure of the input via the corresponding `walk` method;
@@ -88,23 +144,22 @@ pub trait Visitor<'v> : Sized {
88144 // Nested items.
89145
90146 /// The default versions of the `visit_nested_XXX` routines invoke
91- /// this method to get a map to use; if they get back `None`, they
92- /// just skip nested things. Otherwise, they will lookup the
93- /// nested item-like things in the map and visit it. So the best
94- /// way to implement a nested visitor is to override this method
95- /// to return a `Map`; one advantage of this is that if we add
96- /// more types of nested things in the future, they will
97- /// automatically work.
147+ /// this method to get a map to use. By selecting an enum variant,
148+ /// you control which kinds of nested HIR are visited; see
149+ /// `NestedVisitorMap` for details. By "nested HIR", we are
150+ /// referring to bits of HIR that are not directly embedded within
151+ /// one another but rather indirectly, through a table in the
152+ /// crate. This is done to control dependencies during incremental
153+ /// compilation: the non-inline bits of HIR can be tracked and
154+ /// hashed separately.
98155 ///
99156 /// **If for some reason you want the nested behavior, but don't
100157 /// have a `Map` are your disposal:** then you should override the
101158 /// `visit_nested_XXX` methods, and override this method to
102159 /// `panic!()`. This way, if a new `visit_nested_XXX` variant is
103160 /// added in the future, we will see the panic in your code and
104161 /// fix it appropriately.
105- fn nested_visit_map ( & mut self ) -> Option < & Map < ' v > > {
106- None
107- }
162+ fn nested_visit_map < ' this > ( & ' this mut self ) -> NestedVisitorMap < ' this , ' v > ;
108163
109164 /// Invoked when a nested item is encountered. By default does
110165 /// nothing unless you override `nested_visit_map` to return
@@ -116,8 +171,7 @@ pub trait Visitor<'v> : Sized {
116171 /// but cannot supply a `Map`; see `nested_visit_map` for advice.
117172 #[ allow( unused_variables) ]
118173 fn visit_nested_item ( & mut self , id : ItemId ) {
119- let opt_item = self . nested_visit_map ( )
120- . map ( |map| map. expect_item ( id. id ) ) ;
174+ let opt_item = self . nested_visit_map ( ) . inter ( ) . map ( |map| map. expect_item ( id. id ) ) ;
121175 if let Some ( item) = opt_item {
122176 self . visit_item ( item) ;
123177 }
@@ -128,13 +182,23 @@ pub trait Visitor<'v> : Sized {
128182 /// method.
129183 #[ allow( unused_variables) ]
130184 fn visit_nested_impl_item ( & mut self , id : ImplItemId ) {
131- let opt_item = self . nested_visit_map ( )
132- . map ( |map| map. impl_item ( id) ) ;
185+ let opt_item = self . nested_visit_map ( ) . inter ( ) . map ( |map| map. impl_item ( id) ) ;
133186 if let Some ( item) = opt_item {
134187 self . visit_impl_item ( item) ;
135188 }
136189 }
137190
191+ /// Invoked to visit the body of a function, method or closure. Like
192+ /// visit_nested_item, does nothing by default unless you override
193+ /// `nested_visit_map` to return `Some(_)`, in which case it will walk the
194+ /// body.
195+ fn visit_body ( & mut self , id : ExprId ) {
196+ let opt_expr = self . nested_visit_map ( ) . intra ( ) . map ( |map| map. expr ( id) ) ;
197+ if let Some ( expr) = opt_expr {
198+ self . visit_expr ( expr) ;
199+ }
200+ }
201+
138202 /// Visit the top-level item and (optionally) nested items / impl items. See
139203 /// `visit_nested_item` for details.
140204 fn visit_item ( & mut self , i : & ' v Item ) {
@@ -200,7 +264,7 @@ pub trait Visitor<'v> : Sized {
200264 fn visit_where_predicate ( & mut self , predicate : & ' v WherePredicate ) {
201265 walk_where_predicate ( self , predicate)
202266 }
203- fn visit_fn ( & mut self , fk : FnKind < ' v > , fd : & ' v FnDecl , b : & ' v Expr , s : Span , id : NodeId ) {
267+ fn visit_fn ( & mut self , fk : FnKind < ' v > , fd : & ' v FnDecl , b : ExprId , s : Span , id : NodeId ) {
204268 walk_fn ( self , fk, fd, b, s, id)
205269 }
206270 fn visit_trait_item ( & mut self , ti : & ' v TraitItem ) {
@@ -363,7 +427,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
363427 visitor. visit_ty ( typ) ;
364428 visitor. visit_expr ( expr) ;
365429 }
366- ItemFn ( ref declaration, unsafety, constness, abi, ref generics, ref body ) => {
430+ ItemFn ( ref declaration, unsafety, constness, abi, ref generics, body_id ) => {
367431 visitor. visit_fn ( FnKind :: ItemFn ( item. name ,
368432 generics,
369433 unsafety,
@@ -372,7 +436,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
372436 & item. vis ,
373437 & item. attrs ) ,
374438 declaration,
375- body ,
439+ body_id ,
376440 item. span ,
377441 item. id )
378442 }
@@ -697,13 +761,25 @@ pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'
697761pub fn walk_fn < ' v , V : Visitor < ' v > > ( visitor : & mut V ,
698762 function_kind : FnKind < ' v > ,
699763 function_declaration : & ' v FnDecl ,
700- function_body : & ' v Expr ,
764+ body_id : ExprId ,
701765 _span : Span ,
702766 id : NodeId ) {
703767 visitor. visit_id ( id) ;
704768 walk_fn_decl ( visitor, function_declaration) ;
705769 walk_fn_kind ( visitor, function_kind) ;
706- visitor. visit_expr ( function_body)
770+ visitor. visit_body ( body_id)
771+ }
772+
773+ pub fn walk_fn_with_body < ' v , V : Visitor < ' v > > ( visitor : & mut V ,
774+ function_kind : FnKind < ' v > ,
775+ function_declaration : & ' v FnDecl ,
776+ body : & ' v Expr ,
777+ _span : Span ,
778+ id : NodeId ) {
779+ visitor. visit_id ( id) ;
780+ walk_fn_decl ( visitor, function_declaration) ;
781+ walk_fn_kind ( visitor, function_kind) ;
782+ visitor. visit_expr ( body)
707783}
708784
709785pub fn walk_trait_item < ' v , V : Visitor < ' v > > ( visitor : & mut V , trait_item : & ' v TraitItem ) {
@@ -720,13 +796,13 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
720796 visitor. visit_generics ( & sig. generics ) ;
721797 walk_fn_decl ( visitor, & sig. decl ) ;
722798 }
723- MethodTraitItem ( ref sig, Some ( ref body ) ) => {
799+ MethodTraitItem ( ref sig, Some ( body_id ) ) => {
724800 visitor. visit_fn ( FnKind :: Method ( trait_item. name ,
725801 sig,
726802 None ,
727803 & trait_item. attrs ) ,
728804 & sig. decl ,
729- body ,
805+ body_id ,
730806 trait_item. span ,
731807 trait_item. id ) ;
732808 }
@@ -752,13 +828,13 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
752828 visitor. visit_ty ( ty) ;
753829 visitor. visit_expr ( expr) ;
754830 }
755- ImplItemKind :: Method ( ref sig, ref body ) => {
831+ ImplItemKind :: Method ( ref sig, body_id ) => {
756832 visitor. visit_fn ( FnKind :: Method ( impl_item. name ,
757833 sig,
758834 Some ( & impl_item. vis ) ,
759835 & impl_item. attrs ) ,
760836 & sig. decl ,
761- body ,
837+ body_id ,
762838 impl_item. span ,
763839 impl_item. id ) ;
764840 }
@@ -883,7 +959,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
883959 visitor. visit_expr ( subexpression) ;
884960 walk_list ! ( visitor, visit_arm, arms) ;
885961 }
886- ExprClosure ( _, ref function_declaration, ref body, _fn_decl_span) => {
962+ ExprClosure ( _, ref function_declaration, body, _fn_decl_span) => {
887963 visitor. visit_fn ( FnKind :: Closure ( & expression. attrs ) ,
888964 function_declaration,
889965 body,
@@ -998,34 +1074,40 @@ impl IdRange {
9981074}
9991075
10001076
1001- pub struct IdRangeComputingVisitor {
1002- pub result : IdRange ,
1077+ pub struct IdRangeComputingVisitor < ' a , ' ast : ' a > {
1078+ result : IdRange ,
1079+ map : & ' a map:: Map < ' ast > ,
10031080}
10041081
1005- impl IdRangeComputingVisitor {
1006- pub fn new ( ) -> IdRangeComputingVisitor {
1007- IdRangeComputingVisitor { result : IdRange :: max ( ) }
1082+ impl < ' a , ' ast > IdRangeComputingVisitor < ' a , ' ast > {
1083+ pub fn new ( map : & ' a map :: Map < ' ast > ) -> IdRangeComputingVisitor < ' a , ' ast > {
1084+ IdRangeComputingVisitor { result : IdRange :: max ( ) , map : map }
10081085 }
10091086
10101087 pub fn result ( & self ) -> IdRange {
10111088 self . result
10121089 }
10131090}
10141091
1015- impl < ' v > Visitor < ' v > for IdRangeComputingVisitor {
1092+ impl < ' a , ' ast > Visitor < ' ast > for IdRangeComputingVisitor < ' a , ' ast > {
1093+ fn nested_visit_map < ' this > ( & ' this mut self ) -> NestedVisitorMap < ' this , ' ast > {
1094+ NestedVisitorMap :: OnlyBodies ( & self . map )
1095+ }
1096+
10161097 fn visit_id ( & mut self , id : NodeId ) {
10171098 self . result . add ( id) ;
10181099 }
10191100}
10201101
10211102/// Computes the id range for a single fn body, ignoring nested items.
1022- pub fn compute_id_range_for_fn_body ( fk : FnKind ,
1023- decl : & FnDecl ,
1024- body : & Expr ,
1025- sp : Span ,
1026- id : NodeId )
1027- -> IdRange {
1028- let mut visitor = IdRangeComputingVisitor :: new ( ) ;
1029- visitor. visit_fn ( fk, decl, body, sp, id) ;
1103+ pub fn compute_id_range_for_fn_body < ' v > ( fk : FnKind < ' v > ,
1104+ decl : & ' v FnDecl ,
1105+ body : & ' v Expr ,
1106+ sp : Span ,
1107+ id : NodeId ,
1108+ map : & map:: Map < ' v > )
1109+ -> IdRange {
1110+ let mut visitor = IdRangeComputingVisitor :: new ( map) ;
1111+ walk_fn_with_body ( & mut visitor, fk, decl, body, sp, id) ;
10301112 visitor. result ( )
10311113}
0 commit comments