Skip to content

Commit ee5d8d3

Browse files
committed
Auto merge of #90986 - camsteffen:nested-filter, r=cjgillot
Replace `NestedVisitorMap` with generic `NestedFilter` This is an attempt to make the `intravisit::Visitor` API simpler and "more const" with regard to nested visiting. With this change, `intravisit::Visitor` does not visit nested things by default, unless you specify `type NestedFilter = nested_filter::OnlyBodies` (or `All`). `nested_visit_map` returns `Self::Map` instead of `NestedVisitorMap<Self::Map>`. It panics by default (unreachable if `type NestedFilter` is omitted). One somewhat trixty thing here is that `nested_filter::{OnlyBodies, All}` live in `rustc_middle` so that they may have `type Map = map::Map` and so that `impl Visitor`s never need to specify `type Map` - it has a default of `Self::NestedFilter::Map`.
2 parents a34c079 + be6d693 commit ee5d8d3

File tree

110 files changed

+387
-946
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

110 files changed

+387
-946
lines changed

compiler/rustc_ast_lowering/src/index.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use rustc_data_structures::sorted_map::SortedMap;
33
use rustc_hir as hir;
44
use rustc_hir::def_id::LocalDefId;
55
use rustc_hir::definitions;
6-
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
6+
use rustc_hir::intravisit::{self, Visitor};
77
use rustc_hir::*;
88
use rustc_index::vec::{Idx, IndexVec};
99
use rustc_session::Session;
@@ -101,16 +101,10 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
101101
}
102102

103103
impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
104-
type Map = !;
105-
106104
/// Because we want to track parent items and so forth, enable
107105
/// deep walking so that we walk nested items in the context of
108106
/// their outer items.
109107
110-
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
111-
panic!("`visit_nested_xxx` must be manually implemented in this visitor");
112-
}
113-
114108
fn visit_nested_item(&mut self, item: ItemId) {
115109
debug!("visit_nested_item: {:?}", item);
116110
self.insert_nested(item.def_id);

compiler/rustc_ast_lowering/src/lib.rs

-6
Original file line numberDiff line numberDiff line change
@@ -2436,12 +2436,6 @@ fn lifetimes_from_impl_trait_bounds(
24362436
}
24372437

24382438
impl<'r, 'v> intravisit::Visitor<'v> for ImplTraitLifetimeCollector<'r> {
2439-
type Map = intravisit::ErasedMap<'v>;
2440-
2441-
fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
2442-
intravisit::NestedVisitorMap::None
2443-
}
2444-
24452439
fn visit_generic_args(&mut self, span: Span, parameters: &'v hir::GenericArgs<'v>) {
24462440
// Don't collect elided lifetimes used inside of `Fn()` syntax.
24472441
if parameters.parenthesized {

compiler/rustc_hir/src/intravisit.rs

+54-80
Original file line numberDiff line numberDiff line change
@@ -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.)
260217
pub 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>) {

compiler/rustc_hir/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
//!
33
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
44
5+
#![feature(associated_type_defaults)]
56
#![feature(const_btree_new)]
67
#![feature(crate_visibility_modifier)]
78
#![feature(once_cell)]

compiler/rustc_incremental/src/assert_dep_graph.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,11 @@ use rustc_data_structures::graph::implementation::{Direction, NodeIndex, INCOMIN
3939
use rustc_graphviz as dot;
4040
use rustc_hir as hir;
4141
use rustc_hir::def_id::DefId;
42-
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
42+
use rustc_hir::intravisit::{self, Visitor};
4343
use rustc_middle::dep_graph::{
4444
DepGraphQuery, DepKind, DepNode, DepNodeExt, DepNodeFilter, EdgeFilter,
4545
};
46-
use rustc_middle::hir::map::Map;
46+
use rustc_middle::hir::nested_filter;
4747
use rustc_middle::ty::TyCtxt;
4848
use rustc_span::symbol::{sym, Symbol};
4949
use rustc_span::Span;
@@ -173,10 +173,10 @@ impl<'tcx> IfThisChanged<'tcx> {
173173
}
174174

175175
impl<'tcx> Visitor<'tcx> for IfThisChanged<'tcx> {
176-
type Map = Map<'tcx>;
176+
type NestedFilter = nested_filter::OnlyBodies;
177177

178-
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
179-
NestedVisitorMap::OnlyBodies(self.tcx.hir())
178+
fn nested_visit_map(&mut self) -> Self::Map {
179+
self.tcx.hir()
180180
}
181181

182182
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {

compiler/rustc_incremental/src/persist/dirty_clean.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use rustc_hir::itemlikevisit::ItemLikeVisitor;
2828
use rustc_hir::Node as HirNode;
2929
use rustc_hir::{ImplItemKind, ItemKind as HirItem, TraitItemKind};
3030
use rustc_middle::dep_graph::{label_strs, DepNode, DepNodeExt};
31-
use rustc_middle::hir::map::Map;
31+
use rustc_middle::hir::nested_filter;
3232
use rustc_middle::ty::TyCtxt;
3333
use rustc_span::symbol::{sym, Symbol};
3434
use rustc_span::Span;
@@ -472,10 +472,10 @@ impl<'tcx> FindAllAttrs<'tcx> {
472472
}
473473

474474
impl<'tcx> intravisit::Visitor<'tcx> for FindAllAttrs<'tcx> {
475-
type Map = Map<'tcx>;
475+
type NestedFilter = nested_filter::All;
476476

477-
fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
478-
intravisit::NestedVisitorMap::All(self.tcx.hir())
477+
fn nested_visit_map(&mut self) -> Self::Map {
478+
self.tcx.hir()
479479
}
480480

481481
fn visit_attribute(&mut self, _: hir::HirId, attr: &'tcx Attribute) {

compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}
44
use rustc_hir as hir;
55
use rustc_hir::def::{DefKind, Namespace};
66
use rustc_hir::def_id::DefId;
7-
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
7+
use rustc_hir::intravisit::{self, Visitor};
88
use rustc_hir::{Body, Expr, ExprKind, FnRetTy, HirId, Local, MatchSource, Pat};
9-
use rustc_middle::hir::map::Map;
9+
use rustc_middle::hir::nested_filter;
1010
use rustc_middle::infer::unify_key::ConstVariableOriginKind;
1111
use rustc_middle::ty::print::Print;
1212
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
@@ -83,10 +83,10 @@ impl<'a, 'tcx> FindHirNodeVisitor<'a, 'tcx> {
8383
}
8484

8585
impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> {
86-
type Map = Map<'tcx>;
86+
type NestedFilter = nested_filter::OnlyBodies;
8787

88-
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
89-
NestedVisitorMap::OnlyBodies(self.infcx.tcx.hir())
88+
fn nested_visit_map(&mut self) -> Self::Map {
89+
self.infcx.tcx.hir()
9090
}
9191

9292
fn visit_local(&mut self, local: &'tcx Local<'tcx>) {

compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use rustc_hir as hir;
2-
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
2+
use rustc_hir::intravisit::{self, Visitor};
33
use rustc_hir::Node;
44
use rustc_middle::hir::map::Map;
5+
use rustc_middle::hir::nested_filter;
56
use rustc_middle::middle::resolve_lifetime as rl;
67
use rustc_middle::ty::{self, Region, TyCtxt};
78

@@ -84,10 +85,10 @@ struct FindNestedTypeVisitor<'tcx> {
8485
}
8586

8687
impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
87-
type Map = Map<'tcx>;
88+
type NestedFilter = nested_filter::OnlyBodies;
8889

89-
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
90-
NestedVisitorMap::OnlyBodies(self.tcx.hir())
90+
fn nested_visit_map(&mut self) -> Self::Map {
91+
self.tcx.hir()
9192
}
9293

9394
fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) {
@@ -208,10 +209,10 @@ struct TyPathVisitor<'tcx> {
208209
}
209210

210211
impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
211-
type Map = Map<'tcx>;
212+
type NestedFilter = nested_filter::OnlyBodies;
212213

213-
fn nested_visit_map(&mut self) -> NestedVisitorMap<Map<'tcx>> {
214-
NestedVisitorMap::OnlyBodies(self.tcx.hir())
214+
fn nested_visit_map(&mut self) -> Map<'tcx> {
215+
self.tcx.hir()
215216
}
216217

217218
fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {

compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::traits::{ObligationCauseCode, UnifyReceiverContext};
77
use rustc_data_structures::stable_set::FxHashSet;
88
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
99
use rustc_hir::def_id::DefId;
10-
use rustc_hir::intravisit::{walk_ty, ErasedMap, NestedVisitorMap, Visitor};
10+
use rustc_hir::intravisit::{walk_ty, Visitor};
1111
use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind};
1212
use rustc_middle::ty::{
1313
self, AssocItemContainer, RegionKind, StaticLifetimeVisitor, Ty, TyCtxt, TypeFoldable,
@@ -575,12 +575,6 @@ impl<'tcx> TypeVisitor<'tcx> for TraitObjectVisitor {
575575
pub(super) struct HirTraitObjectVisitor<'a>(pub(super) &'a mut Vec<Span>, pub(super) DefId);
576576

577577
impl<'a, 'tcx> Visitor<'tcx> for HirTraitObjectVisitor<'a> {
578-
type Map = ErasedMap<'tcx>;
579-
580-
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
581-
NestedVisitorMap::None
582-
}
583-
584578
fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) {
585579
if let TyKind::TraitObject(
586580
poly_trait_refs,

0 commit comments

Comments
 (0)