@@ -160,87 +160,44 @@ impl<'hir> Map<'hir> for ! {
160160 }
161161}
162162
163- /// An erased version of `Map<'hir>`, using dynamic dispatch.
164- /// NOTE: This type is effectively only usable with `NestedVisitorMap::None`.
165- pub struct ErasedMap < ' hir > ( & ' hir dyn Map < ' hir > ) ;
163+ pub mod nested_filter {
164+ use super :: Map ;
166165
167- impl < ' hir > Map < ' hir > for ErasedMap < ' hir > {
168- fn find ( & self , _: HirId ) -> Option < Node < ' hir > > {
169- None
170- }
171- fn body ( & self , id : BodyId ) -> & ' hir Body < ' hir > {
172- self . 0 . body ( id)
173- }
174- fn item ( & self , id : ItemId ) -> & ' hir Item < ' hir > {
175- self . 0 . item ( id)
176- }
177- fn trait_item ( & self , id : TraitItemId ) -> & ' hir TraitItem < ' hir > {
178- self . 0 . trait_item ( id)
179- }
180- fn impl_item ( & self , id : ImplItemId ) -> & ' hir ImplItem < ' hir > {
181- self . 0 . impl_item ( id)
182- }
183- fn foreign_item ( & self , id : ForeignItemId ) -> & ' hir ForeignItem < ' hir > {
184- self . 0 . foreign_item ( id)
166+ /// Specifies what nested things a visitor wants to visit. The most
167+ /// common choice is `OnlyBodies`, which will cause the visitor to
168+ /// visit fn bodies for fns that it encounters, but skip over nested
169+ /// item-like things.
170+ ///
171+ /// See the comments on `ItemLikeVisitor` for more details on the overall
172+ /// visit strategy.
173+ pub trait NestedFilter < ' hir > {
174+ type Map : Map < ' hir > ;
175+
176+ /// Whether the visitor visits nested "item-like" things.
177+ /// E.g., item, impl-item.
178+ const INTER : bool ;
179+ /// Whether the visitor visits "intra item-like" things.
180+ /// E.g., function body, closure, `AnonConst`
181+ const INTRA : bool ;
185182 }
186- }
187183
188- /// Specifies what nested things a visitor wants to visit. The most
189- /// common choice is `OnlyBodies`, which will cause the visitor to
190- /// visit fn bodies for fns that it encounters, but skip over nested
191- /// item-like things.
192- ///
193- /// See the comments on `ItemLikeVisitor` for more details on the overall
194- /// visit strategy.
195- pub enum NestedVisitorMap < M > {
196184 /// Do not visit any nested things. When you add a new
197185 /// "non-nested" thing, you will want to audit such uses to see if
198186 /// they remain valid.
199187 ///
200188 /// Use this if you are only walking some particular kind of tree
201189 /// (i.e., a type, or fn signature) and you don't want to thread a
202190 /// HIR map around.
203- None ,
204-
205- /// Do not visit nested item-like things, but visit nested things
206- /// that are inside of an item-like.
207- ///
208- /// **This is the most common choice.** A very common pattern is
209- /// to use `visit_all_item_likes()` as an outer loop,
210- /// and to have the visitor that visits the contents of each item
211- /// using this setting.
212- OnlyBodies ( M ) ,
213-
214- /// Visits all nested things, including item-likes.
215- ///
216- /// **This is an unusual choice.** It is used when you want to
217- /// process everything within their lexical context. Typically you
218- /// kick off the visit by doing `walk_krate()`.
219- All ( M ) ,
220- }
221-
222- impl < M > NestedVisitorMap < M > {
223- /// Returns the map to use for an "intra item-like" thing (if any).
224- /// E.g., function body.
225- fn intra ( self ) -> Option < M > {
226- match self {
227- NestedVisitorMap :: None => None ,
228- NestedVisitorMap :: OnlyBodies ( map) => Some ( map) ,
229- NestedVisitorMap :: All ( map) => Some ( map) ,
230- }
231- }
232-
233- /// Returns the map to use for an "item-like" thing (if any).
234- /// E.g., item, impl-item.
235- fn inter ( self ) -> Option < M > {
236- match self {
237- NestedVisitorMap :: None => None ,
238- NestedVisitorMap :: OnlyBodies ( _) => None ,
239- NestedVisitorMap :: All ( map) => Some ( map) ,
240- }
191+ pub struct None ( ( ) ) ;
192+ impl NestedFilter < ' _ > for None {
193+ type Map = !;
194+ const INTER : bool = false ;
195+ const INTRA : bool = false ;
241196 }
242197}
243198
199+ use nested_filter:: NestedFilter ;
200+
244201/// Each method of the Visitor trait is a hook to be potentially
245202/// overridden. Each method's default implementation recursively visits
246203/// the substructure of the input via the corresponding `walk` method;
@@ -258,7 +215,9 @@ impl<M> NestedVisitorMap<M> {
258215/// to monitor future changes to `Visitor` in case a new method with a
259216/// new default implementation gets introduced.)
260217pub trait Visitor < ' v > : Sized {
261- type Map : Map < ' v > ;
218+ // this type should not be overridden, it exists for convenient usage as `Self::Map`
219+ type Map : Map < ' v > = <Self :: NestedFilter as NestedFilter < ' v > >:: Map ;
220+ type NestedFilter : NestedFilter < ' v > = nested_filter:: None ;
262221
263222 ///////////////////////////////////////////////////////////////////////////
264223 // Nested items.
@@ -279,7 +238,12 @@ pub trait Visitor<'v>: Sized {
279238 /// `panic!()`. This way, if a new `visit_nested_XXX` variant is
280239 /// added in the future, we will see the panic in your code and
281240 /// fix it appropriately.
282- fn nested_visit_map ( & mut self ) -> NestedVisitorMap < Self :: Map > ;
241+ fn nested_visit_map ( & mut self ) -> Self :: Map {
242+ panic ! (
243+ "nested_visit_map must be implemented or consider using \
244+ `type NestedFilter = nested_filter::None` (the default)"
245+ ) ;
246+ }
283247
284248 /// Invoked when a nested item is encountered. By default does
285249 /// nothing unless you override `nested_visit_map` to return other than
@@ -290,41 +254,51 @@ pub trait Visitor<'v>: Sized {
290254 /// reason to override this method is if you want a nested pattern
291255 /// but cannot supply a `Map`; see `nested_visit_map` for advice.
292256 fn visit_nested_item ( & mut self , id : ItemId ) {
293- let opt_item = self . nested_visit_map ( ) . inter ( ) . map ( |map| map. item ( id) ) ;
294- walk_list ! ( self , visit_item, opt_item) ;
257+ if Self :: NestedFilter :: INTER {
258+ let item = self . nested_visit_map ( ) . item ( id) ;
259+ self . visit_item ( item) ;
260+ }
295261 }
296262
297263 /// Like `visit_nested_item()`, but for trait items. See
298264 /// `visit_nested_item()` for advice on when to override this
299265 /// method.
300266 fn visit_nested_trait_item ( & mut self , id : TraitItemId ) {
301- let opt_item = self . nested_visit_map ( ) . inter ( ) . map ( |map| map. trait_item ( id) ) ;
302- walk_list ! ( self , visit_trait_item, opt_item) ;
267+ if Self :: NestedFilter :: INTER {
268+ let item = self . nested_visit_map ( ) . trait_item ( id) ;
269+ self . visit_trait_item ( item) ;
270+ }
303271 }
304272
305273 /// Like `visit_nested_item()`, but for impl items. See
306274 /// `visit_nested_item()` for advice on when to override this
307275 /// method.
308276 fn visit_nested_impl_item ( & mut self , id : ImplItemId ) {
309- let opt_item = self . nested_visit_map ( ) . inter ( ) . map ( |map| map. impl_item ( id) ) ;
310- walk_list ! ( self , visit_impl_item, opt_item) ;
277+ if Self :: NestedFilter :: INTER {
278+ let item = self . nested_visit_map ( ) . impl_item ( id) ;
279+ self . visit_impl_item ( item) ;
280+ }
311281 }
312282
313283 /// Like `visit_nested_item()`, but for foreign items. See
314284 /// `visit_nested_item()` for advice on when to override this
315285 /// method.
316286 fn visit_nested_foreign_item ( & mut self , id : ForeignItemId ) {
317- let opt_item = self . nested_visit_map ( ) . inter ( ) . map ( |map| map. foreign_item ( id) ) ;
318- walk_list ! ( self , visit_foreign_item, opt_item) ;
287+ if Self :: NestedFilter :: INTER {
288+ let item = self . nested_visit_map ( ) . foreign_item ( id) ;
289+ self . visit_foreign_item ( item) ;
290+ }
319291 }
320292
321293 /// Invoked to visit the body of a function, method or closure. Like
322294 /// visit_nested_item, does nothing by default unless you override
323295 /// `nested_visit_map` to return other than `None`, in which case it will walk
324296 /// the body.
325297 fn visit_nested_body ( & mut self , id : BodyId ) {
326- let opt_body = self . nested_visit_map ( ) . intra ( ) . map ( |map| map. body ( id) ) ;
327- walk_list ! ( self , visit_body, opt_body) ;
298+ if Self :: NestedFilter :: INTRA {
299+ let body = self . nested_visit_map ( ) . body ( id) ;
300+ self . visit_body ( body) ;
301+ }
328302 }
329303
330304 fn visit_param ( & mut self , param : & ' v Param < ' v > ) {
0 commit comments