Skip to content

Commit 36fbf8c

Browse files
committed
refactor Visitor into ItemLikeVisitor and intravisit::Visitor
There are now three patterns (shallow, deep, and nested visit). These are described in detail on the docs in `itemlikevisit::ItemLikeVisitor`.
1 parent 478c0d1 commit 36fbf8c

File tree

42 files changed

+239
-126
lines changed

Some content is hidden

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

42 files changed

+239
-126
lines changed

src/librustc/dep_graph/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,5 @@ pub use self::dep_node::WorkProductId;
2525
pub use self::graph::DepGraph;
2626
pub use self::graph::WorkProduct;
2727
pub use self::query::DepGraphQuery;
28-
pub use self::visit::visit_all_items_in_krate;
28+
pub use self::visit::visit_all_item_likes_in_krate;
2929
pub use self::raii::DepTask;

src/librustc/dep_graph/visit.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,31 +10,30 @@
1010

1111
use hir;
1212
use hir::def_id::DefId;
13-
use hir::intravisit::Visitor;
13+
use hir::itemlikevisit::ItemLikeVisitor;
1414
use ty::TyCtxt;
1515

1616
use super::dep_node::DepNode;
1717

18-
1918
/// Visit all the items in the krate in some order. When visiting a
2019
/// particular item, first create a dep-node by calling `dep_node_fn`
2120
/// and push that onto the dep-graph stack of tasks, and also create a
2221
/// read edge from the corresponding AST node. This is used in
2322
/// compiler passes to automatically record the item that they are
2423
/// working on.
25-
pub fn visit_all_items_in_krate<'a, 'tcx, V, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
26-
mut dep_node_fn: F,
27-
visitor: &mut V)
28-
where F: FnMut(DefId) -> DepNode<DefId>, V: Visitor<'tcx>
24+
pub fn visit_all_item_likes_in_krate<'a, 'tcx, V, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
25+
mut dep_node_fn: F,
26+
visitor: &mut V)
27+
where F: FnMut(DefId) -> DepNode<DefId>, V: ItemLikeVisitor<'tcx>
2928
{
3029
struct TrackingVisitor<'visit, 'tcx: 'visit, F: 'visit, V: 'visit> {
3130
tcx: TyCtxt<'visit, 'tcx, 'tcx>,
3231
dep_node_fn: &'visit mut F,
3332
visitor: &'visit mut V
3433
}
3534

36-
impl<'visit, 'tcx, F, V> Visitor<'tcx> for TrackingVisitor<'visit, 'tcx, F, V>
37-
where F: FnMut(DefId) -> DepNode<DefId>, V: Visitor<'tcx>
35+
impl<'visit, 'tcx, F, V> ItemLikeVisitor<'tcx> for TrackingVisitor<'visit, 'tcx, F, V>
36+
where F: FnMut(DefId) -> DepNode<DefId>, V: ItemLikeVisitor<'tcx>
3837
{
3938
fn visit_item(&mut self, i: &'tcx hir::Item) {
4039
let item_def_id = self.tcx.map.local_def_id(i.id);
@@ -54,5 +53,5 @@ pub fn visit_all_items_in_krate<'a, 'tcx, V, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
5453
dep_node_fn: &mut dep_node_fn,
5554
visitor: visitor
5655
};
57-
krate.visit_all_items(&mut tracking_visitor)
56+
krate.visit_all_item_likes(&mut tracking_visitor)
5857
}

src/librustc/hir/intravisit.rs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,15 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
//! HIR walker. Each overridden visit method has full control over what
11+
//! HIR walker for walking the contents of nodes.
12+
//!
13+
//! **For an overview of the visitor strategy, see the docs on the
14+
//! `super::itemlikevisit::ItemLikeVisitor` trait.**
15+
//!
16+
//! If you have decided to use this visitor, here are some general
17+
//! notes on how to do it:
18+
//!
19+
//! Each overridden visit method has full control over what
1220
//! happens with its node, it can do its own traversal of the node's children,
1321
//! call `intravisit::walk_*` to apply the default traversal algorithm, or prevent
1422
//! deeper traversal by doing nothing.
@@ -30,6 +38,7 @@ use syntax::ast::{NodeId, CRATE_NODE_ID, Name, Attribute};
3038
use syntax::codemap::Spanned;
3139
use syntax_pos::Span;
3240
use hir::*;
41+
use super::itemlikevisit::DeepVisitor;
3342

3443
use std::cmp;
3544
use std::u32;
@@ -78,10 +87,9 @@ pub trait Visitor<'v> : Sized {
7887

7988
/// Invoked when a nested item is encountered. By default, does
8089
/// nothing. If you want a deep walk, you need to override to
81-
/// fetch the item contents. But most of the time, it is easier
82-
/// (and better) to invoke `Crate::visit_all_items`, which visits
83-
/// all items in the crate in some order (but doesn't respect
84-
/// nesting).
90+
/// fetch the item contents. But most of the time, it is easier to
91+
/// use either the "shallow" or "deep" visit patterns described on
92+
/// `itemlikevisit::ItemLikeVisitor`.
8593
#[allow(unused_variables)]
8694
fn visit_nested_item(&mut self, id: ItemId) {
8795
}
@@ -92,6 +100,16 @@ pub trait Visitor<'v> : Sized {
92100
walk_item(self, i)
93101
}
94102

103+
/// When invoking `visit_all_item_likes()`, you need to supply an
104+
/// item-like visitor. This method converts a "intra-visit"
105+
/// visitor into an item-like visitor that walks the entire tree.
106+
/// If you use this, you probably don't want to process the
107+
/// contents of nested item-like things, since the outer loop will
108+
/// visit them as well.
109+
fn as_deep_visitor<'s>(&'s mut self) -> DeepVisitor<'s, Self> {
110+
DeepVisitor::new(self)
111+
}
112+
95113
///////////////////////////////////////////////////////////////////////////
96114

97115
fn visit_id(&mut self, _node_id: NodeId) {

src/librustc/hir/itemlikevisit.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use super::Item;
12+
use super::intravisit::Visitor;
13+
14+
/// The "item-like visitor" visitor defines only the top-level methods
15+
/// that can be invoked by `Crate::visit_all_item_likes()`. Whether
16+
/// this trait is the right one to implement will depend on the
17+
/// overall pattern you need. Here are the three available patterns,
18+
/// in roughly the order of desirability:
19+
///
20+
/// 1. **Shallow visit**: Get a simple callback for every item (or item-like thing) in the HIR.
21+
/// - Example: find all items with a `#[foo]` attribute on them.
22+
/// - How: Implement `ItemLikeVisitor` and call `tcx.visit_all_item_likes_in_krate()`.
23+
/// - Pro: Efficient; just walks the lists of item-like things, not the nodes themselves.
24+
/// - Pro: Integrates well into dependency tracking.
25+
/// - Con: Don't get information about nesting
26+
/// - Con: Don't have methods for specific bits of HIR, like "on
27+
/// every expr, do this".
28+
/// 2. **Deep visit**: Want to scan for specific kinds of HIR nodes within
29+
/// an item, but don't care about how item-like things are nested
30+
/// within one another.
31+
/// - Example: Examine each expression to look for its type and do some check or other.
32+
/// - How: Implement `intravisit::Visitor` and use
33+
/// `tcx.visit_all_item_likes_in_krate(visitor.as_deep_visitor())`. Within
34+
/// your `intravisit::Visitor` impl, implement methods like
35+
/// `visit_expr()`; don't forget to invoke
36+
/// `intravisit::walk_visit_expr()` to keep walking the subparts.
37+
/// - Pro: Visitor methods for any kind of HIR node, not just item-like things.
38+
/// - Pro: Integrates well into dependency tracking.
39+
/// - Con: Don't get information about nesting between items
40+
/// 3. **Nested visit**: Want to visit the whole HIR and you care about the nesting between
41+
/// item-like things.
42+
/// - Example: Lifetime resolution, which wants to bring lifetimes declared on the
43+
/// impl into scope while visiting the impl-items, and then back out again.
44+
/// - How: Implement `intravisit::Visitor` and override the `visit_nested_foo()` foo methods
45+
/// as needed. Walk your crate with `intravisit::walk_crate()` invoked on `tcx.map.krate()`.
46+
/// - Pro: Visitor methods for any kind of HIR node, not just item-like things.
47+
/// - Pro: Preserves nesting information
48+
/// - Con: Does not integrate well into dependency tracking.
49+
///
50+
/// Note: the methods of `ItemLikeVisitor` intentionally have no
51+
/// defaults, so that as we expand the list of item-like things, we
52+
/// revisit the various visitors to see if they need to change. This
53+
/// is harder to do with `intravisit::Visitor`, so when you add a new
54+
/// `visit_nested_foo()` method, it is recommended that you search for
55+
/// existing `fn visit_nested` methods to see where changes are
56+
/// needed.
57+
pub trait ItemLikeVisitor<'hir> {
58+
fn visit_item(&mut self, item: &'hir Item);
59+
}
60+
61+
pub struct DeepVisitor<'v, V: 'v> {
62+
visitor: &'v mut V,
63+
}
64+
65+
impl<'v, 'hir, V> DeepVisitor<'v, V>
66+
where V: Visitor<'hir> + 'v
67+
{
68+
pub fn new(base: &'v mut V) -> Self {
69+
DeepVisitor { visitor: base }
70+
}
71+
}
72+
73+
impl<'v, 'hir, V> ItemLikeVisitor<'hir> for DeepVisitor<'v, V>
74+
where V: Visitor<'hir>
75+
{
76+
fn visit_item(&mut self, item: &'hir Item) {
77+
self.visitor.visit_item(item);
78+
}
79+
}

src/librustc/hir/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ pub mod check_attr;
6868
pub mod def;
6969
pub mod def_id;
7070
pub mod intravisit;
71+
pub mod itemlikevisit;
7172
pub mod lowering;
7273
pub mod map;
7374
pub mod pat_util;
@@ -438,8 +439,8 @@ impl Crate {
438439
/// follows lexical scoping rules -- then you want a different
439440
/// approach. You should override `visit_nested_item` in your
440441
/// visitor and then call `intravisit::walk_crate` instead.
441-
pub fn visit_all_items<'hir, V>(&'hir self, visitor: &mut V)
442-
where V: intravisit::Visitor<'hir>
442+
pub fn visit_all_item_likes<'hir, V>(&'hir self, visitor: &mut V)
443+
where V: itemlikevisit::ItemLikeVisitor<'hir>
443444
{
444445
for (_, item) in &self.items {
445446
visitor.visit_item(item);

src/librustc/middle/dead.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use dep_graph::DepNode;
1616
use hir::map as ast_map;
1717
use hir::{self, pat_util, PatKind};
1818
use hir::intravisit::{self, Visitor};
19+
use hir::itemlikevisit::ItemLikeVisitor;
1920

2021
use middle::privacy;
2122
use ty::{self, TyCtxt};
@@ -333,7 +334,7 @@ struct LifeSeeder {
333334
worklist: Vec<ast::NodeId>
334335
}
335336

336-
impl<'v> Visitor<'v> for LifeSeeder {
337+
impl<'v> ItemLikeVisitor<'v> for LifeSeeder {
337338
fn visit_item(&mut self, item: &hir::Item) {
338339
let allow_dead_code = has_allow_dead_code_or_lang_attr(&item.attrs);
339340
if allow_dead_code {
@@ -388,7 +389,7 @@ fn create_and_seed_worklist<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
388389
let mut life_seeder = LifeSeeder {
389390
worklist: worklist
390391
};
391-
krate.visit_all_items(&mut life_seeder);
392+
krate.visit_all_item_likes(&mut life_seeder);
392393

393394
return life_seeder.worklist;
394395
}

src/librustc/middle/effect.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,5 +235,5 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
235235
unsafe_context: UnsafeContext::new(SafeContext),
236236
};
237237

238-
tcx.map.krate().visit_all_items(&mut visitor);
238+
tcx.map.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
239239
}

src/librustc/middle/entry.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use syntax::attr;
1818
use syntax::entry::EntryPointType;
1919
use syntax_pos::Span;
2020
use hir::{Item, ItemFn};
21-
use hir::intravisit::Visitor;
21+
use hir::itemlikevisit::ItemLikeVisitor;
2222

2323
struct EntryContext<'a, 'tcx: 'a> {
2424
session: &'a Session,
@@ -39,7 +39,7 @@ struct EntryContext<'a, 'tcx: 'a> {
3939
non_main_fns: Vec<(NodeId, Span)> ,
4040
}
4141

42-
impl<'a, 'tcx> Visitor<'tcx> for EntryContext<'a, 'tcx> {
42+
impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> {
4343
fn visit_item(&mut self, item: &'tcx Item) {
4444
let def_id = self.map.local_def_id(item.id);
4545
let def_key = self.map.def_key(def_id);
@@ -74,7 +74,7 @@ pub fn find_entry_point(session: &Session, ast_map: &ast_map::Map) {
7474
non_main_fns: Vec::new(),
7575
};
7676

77-
ast_map.krate().visit_all_items(&mut ctxt);
77+
ast_map.krate().visit_all_item_likes(&mut ctxt);
7878

7979
configure_main(&mut ctxt);
8080
}

src/librustc/middle/intrinsicck.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
2626
let mut visitor = ItemVisitor {
2727
tcx: tcx
2828
};
29-
tcx.visit_all_items_in_krate(DepNode::IntrinsicCheck, &mut visitor);
29+
tcx.visit_all_item_likes_in_krate(DepNode::IntrinsicCheck, &mut visitor.as_deep_visitor());
3030
}
3131

3232
struct ItemVisitor<'a, 'tcx: 'a> {

src/librustc/middle/lang_items.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use util::nodemap::FxHashMap;
3131

3232
use syntax::ast;
3333
use syntax::parse::token::InternedString;
34-
use hir::intravisit::Visitor;
34+
use hir::itemlikevisit::ItemLikeVisitor;
3535
use hir;
3636

3737
// The actual lang items defined come at the end of this file in one handy table.
@@ -149,7 +149,7 @@ struct LanguageItemCollector<'a, 'tcx: 'a> {
149149
item_refs: FxHashMap<&'static str, usize>,
150150
}
151151

152-
impl<'a, 'v, 'tcx> Visitor<'v> for LanguageItemCollector<'a, 'tcx> {
152+
impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'a, 'tcx> {
153153
fn visit_item(&mut self, item: &hir::Item) {
154154
if let Some(value) = extract(&item.attrs) {
155155
let item_index = self.item_refs.get(&value[..]).cloned();
@@ -219,7 +219,7 @@ impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> {
219219
}
220220

221221
pub fn collect_local_language_items(&mut self, krate: &hir::Crate) {
222-
krate.visit_all_items(self);
222+
krate.visit_all_item_likes(self);
223223
}
224224

225225
pub fn collect_external_language_items(&mut self) {

0 commit comments

Comments
 (0)