-
Notifications
You must be signed in to change notification settings - Fork 13k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of #37660 - nikomatsakis:incremental-36349, r=eddyb
Separate impl items from the parent impl This change separates impl item bodies out of the impl itself. This gives incremental more resolution. In so doing, it refactors how the visitors work, and cleans up a bit of the collect/check logic (mostly by moving things out of collect that didn't really belong there, because they were just checking conditions). However, this is not as effective as I expected, for a kind of frustrating reason. In particular, when invoking `foo.bar()` you still wind up with dependencies on private items. The problem is that the method resolution code scans that list for methods with the name `bar` -- and this winds up touching *all* the methods, even private ones. I can imagine two obvious ways to fix this: - separating fn bodies from fn sigs (#35078, currently being pursued by @flodiebold) - a more aggressive model of incremental that @michaelwoerister has been advocating, in which we hash the intermediate results (e.g., the outputs of collect) so that we can see that the intermediate result hasn't changed, even if a particular impl item has changed. So all in all I'm not quite sure whether to land this or not. =) It still seems like it has to be a win in some cases, but not with the test cases we have just now. I can try to gin up some test cases, but I'm not sure if they will be totally realistic. On the other hand, some of the early refactorings to the visitor trait seem worthwhile to me regardless. cc #36349 -- well, this is basically a fix for that issue, I guess r? @michaelwoerister NB: Based atop of @eddyb's PR #37402; don't land until that lands.
- Loading branch information
Showing
73 changed files
with
1,765 additions
and
630 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT | ||
// file at the top-level directory of this distribution and at | ||
// http://rust-lang.org/COPYRIGHT. | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
use super::{Item, ImplItem}; | ||
use super::intravisit::Visitor; | ||
|
||
/// The "item-like visitor" visitor defines only the top-level methods | ||
/// that can be invoked by `Crate::visit_all_item_likes()`. Whether | ||
/// this trait is the right one to implement will depend on the | ||
/// overall pattern you need. Here are the three available patterns, | ||
/// in roughly the order of desirability: | ||
/// | ||
/// 1. **Shallow visit**: Get a simple callback for every item (or item-like thing) in the HIR. | ||
/// - Example: find all items with a `#[foo]` attribute on them. | ||
/// - How: Implement `ItemLikeVisitor` and call `tcx.visit_all_item_likes_in_krate()`. | ||
/// - Pro: Efficient; just walks the lists of item-like things, not the nodes themselves. | ||
/// - Pro: Integrates well into dependency tracking. | ||
/// - Con: Don't get information about nesting | ||
/// - Con: Don't have methods for specific bits of HIR, like "on | ||
/// every expr, do this". | ||
/// 2. **Deep visit**: Want to scan for specific kinds of HIR nodes within | ||
/// an item, but don't care about how item-like things are nested | ||
/// within one another. | ||
/// - Example: Examine each expression to look for its type and do some check or other. | ||
/// - How: Implement `intravisit::Visitor` and use | ||
/// `tcx.visit_all_item_likes_in_krate(visitor.as_deep_visitor())`. Within | ||
/// your `intravisit::Visitor` impl, implement methods like | ||
/// `visit_expr()`; don't forget to invoke | ||
/// `intravisit::walk_visit_expr()` to keep walking the subparts. | ||
/// - Pro: Visitor methods for any kind of HIR node, not just item-like things. | ||
/// - Pro: Integrates well into dependency tracking. | ||
/// - Con: Don't get information about nesting between items | ||
/// 3. **Nested visit**: Want to visit the whole HIR and you care about the nesting between | ||
/// item-like things. | ||
/// - Example: Lifetime resolution, which wants to bring lifetimes declared on the | ||
/// impl into scope while visiting the impl-items, and then back out again. | ||
/// - How: Implement `intravisit::Visitor` and override the `visit_nested_foo()` foo methods | ||
/// as needed. Walk your crate with `intravisit::walk_crate()` invoked on `tcx.map.krate()`. | ||
/// - Pro: Visitor methods for any kind of HIR node, not just item-like things. | ||
/// - Pro: Preserves nesting information | ||
/// - Con: Does not integrate well into dependency tracking. | ||
/// | ||
/// Note: the methods of `ItemLikeVisitor` intentionally have no | ||
/// defaults, so that as we expand the list of item-like things, we | ||
/// revisit the various visitors to see if they need to change. This | ||
/// is harder to do with `intravisit::Visitor`, so when you add a new | ||
/// `visit_nested_foo()` method, it is recommended that you search for | ||
/// existing `fn visit_nested` methods to see where changes are | ||
/// needed. | ||
pub trait ItemLikeVisitor<'hir> { | ||
fn visit_item(&mut self, item: &'hir Item); | ||
fn visit_impl_item(&mut self, impl_item: &'hir ImplItem); | ||
} | ||
|
||
pub struct DeepVisitor<'v, V: 'v> { | ||
visitor: &'v mut V, | ||
} | ||
|
||
impl<'v, 'hir, V> DeepVisitor<'v, V> | ||
where V: Visitor<'hir> + 'v | ||
{ | ||
pub fn new(base: &'v mut V) -> Self { | ||
DeepVisitor { visitor: base } | ||
} | ||
} | ||
|
||
impl<'v, 'hir, V> ItemLikeVisitor<'hir> for DeepVisitor<'v, V> | ||
where V: Visitor<'hir> | ||
{ | ||
fn visit_item(&mut self, item: &'hir Item) { | ||
self.visitor.visit_item(item); | ||
} | ||
|
||
fn visit_impl_item(&mut self, impl_item: &'hir ImplItem) { | ||
self.visitor.visit_impl_item(impl_item); | ||
} | ||
} |
Oops, something went wrong.