@@ -67,6 +67,62 @@ impl<'a> FnKind<'a> {
67
67
}
68
68
}
69
69
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
+
70
126
/// Each method of the Visitor trait is a hook to be potentially
71
127
/// overridden. Each method's default implementation recursively visits
72
128
/// the substructure of the input via the corresponding `walk` method;
@@ -88,23 +144,22 @@ pub trait Visitor<'v> : Sized {
88
144
// Nested items.
89
145
90
146
/// 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.
98
155
///
99
156
/// **If for some reason you want the nested behavior, but don't
100
157
/// have a `Map` are your disposal:** then you should override the
101
158
/// `visit_nested_XXX` methods, and override this method to
102
159
/// `panic!()`. This way, if a new `visit_nested_XXX` variant is
103
160
/// added in the future, we will see the panic in your code and
104
161
/// 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 > ;
108
163
109
164
/// Invoked when a nested item is encountered. By default does
110
165
/// nothing unless you override `nested_visit_map` to return
@@ -116,8 +171,7 @@ pub trait Visitor<'v> : Sized {
116
171
/// but cannot supply a `Map`; see `nested_visit_map` for advice.
117
172
#[ allow( unused_variables) ]
118
173
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 ) ) ;
121
175
if let Some ( item) = opt_item {
122
176
self . visit_item ( item) ;
123
177
}
@@ -128,13 +182,23 @@ pub trait Visitor<'v> : Sized {
128
182
/// method.
129
183
#[ allow( unused_variables) ]
130
184
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) ) ;
133
186
if let Some ( item) = opt_item {
134
187
self . visit_impl_item ( item) ;
135
188
}
136
189
}
137
190
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
+
138
202
/// Visit the top-level item and (optionally) nested items / impl items. See
139
203
/// `visit_nested_item` for details.
140
204
fn visit_item ( & mut self , i : & ' v Item ) {
@@ -200,7 +264,7 @@ pub trait Visitor<'v> : Sized {
200
264
fn visit_where_predicate ( & mut self , predicate : & ' v WherePredicate ) {
201
265
walk_where_predicate ( self , predicate)
202
266
}
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 ) {
204
268
walk_fn ( self , fk, fd, b, s, id)
205
269
}
206
270
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) {
363
427
visitor. visit_ty ( typ) ;
364
428
visitor. visit_expr ( expr) ;
365
429
}
366
- ItemFn ( ref declaration, unsafety, constness, abi, ref generics, ref body ) => {
430
+ ItemFn ( ref declaration, unsafety, constness, abi, ref generics, body_id ) => {
367
431
visitor. visit_fn ( FnKind :: ItemFn ( item. name ,
368
432
generics,
369
433
unsafety,
@@ -372,7 +436,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
372
436
& item. vis ,
373
437
& item. attrs ) ,
374
438
declaration,
375
- body ,
439
+ body_id ,
376
440
item. span ,
377
441
item. id )
378
442
}
@@ -697,13 +761,25 @@ pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'
697
761
pub fn walk_fn < ' v , V : Visitor < ' v > > ( visitor : & mut V ,
698
762
function_kind : FnKind < ' v > ,
699
763
function_declaration : & ' v FnDecl ,
700
- function_body : & ' v Expr ,
764
+ body_id : ExprId ,
701
765
_span : Span ,
702
766
id : NodeId ) {
703
767
visitor. visit_id ( id) ;
704
768
walk_fn_decl ( visitor, function_declaration) ;
705
769
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)
707
783
}
708
784
709
785
pub 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
720
796
visitor. visit_generics ( & sig. generics ) ;
721
797
walk_fn_decl ( visitor, & sig. decl ) ;
722
798
}
723
- MethodTraitItem ( ref sig, Some ( ref body ) ) => {
799
+ MethodTraitItem ( ref sig, Some ( body_id ) ) => {
724
800
visitor. visit_fn ( FnKind :: Method ( trait_item. name ,
725
801
sig,
726
802
None ,
727
803
& trait_item. attrs ) ,
728
804
& sig. decl ,
729
- body ,
805
+ body_id ,
730
806
trait_item. span ,
731
807
trait_item. id ) ;
732
808
}
@@ -752,13 +828,13 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
752
828
visitor. visit_ty ( ty) ;
753
829
visitor. visit_expr ( expr) ;
754
830
}
755
- ImplItemKind :: Method ( ref sig, ref body ) => {
831
+ ImplItemKind :: Method ( ref sig, body_id ) => {
756
832
visitor. visit_fn ( FnKind :: Method ( impl_item. name ,
757
833
sig,
758
834
Some ( & impl_item. vis ) ,
759
835
& impl_item. attrs ) ,
760
836
& sig. decl ,
761
- body ,
837
+ body_id ,
762
838
impl_item. span ,
763
839
impl_item. id ) ;
764
840
}
@@ -883,7 +959,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
883
959
visitor. visit_expr ( subexpression) ;
884
960
walk_list ! ( visitor, visit_arm, arms) ;
885
961
}
886
- ExprClosure ( _, ref function_declaration, ref body, _fn_decl_span) => {
962
+ ExprClosure ( _, ref function_declaration, body, _fn_decl_span) => {
887
963
visitor. visit_fn ( FnKind :: Closure ( & expression. attrs ) ,
888
964
function_declaration,
889
965
body,
@@ -998,34 +1074,40 @@ impl IdRange {
998
1074
}
999
1075
1000
1076
1001
- pub struct IdRangeComputingVisitor {
1002
- pub result : IdRange ,
1077
+ pub struct IdRangeComputingVisitor < ' a , ' ast : ' a > {
1078
+ result : IdRange ,
1079
+ map : & ' a map:: Map < ' ast > ,
1003
1080
}
1004
1081
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 }
1008
1085
}
1009
1086
1010
1087
pub fn result ( & self ) -> IdRange {
1011
1088
self . result
1012
1089
}
1013
1090
}
1014
1091
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
+
1016
1097
fn visit_id ( & mut self , id : NodeId ) {
1017
1098
self . result . add ( id) ;
1018
1099
}
1019
1100
}
1020
1101
1021
1102
/// 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) ;
1030
1112
visitor. result ( )
1031
1113
}
0 commit comments