about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2018-06-06 22:13:52 +0200
committerJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2019-01-11 03:53:29 +0100
commit69d18a398656f41ff713b26cc8a0149635a8eea2 (patch)
tree8731c660d4e1662fcbc24f0fb18598592adf4f45
parentc2d381d39d282c0586d50ea7d7a431ffd5ddb3fb (diff)
downloadrust-69d18a398656f41ff713b26cc8a0149635a8eea2.tar.gz
rust-69d18a398656f41ff713b26cc8a0149635a8eea2.zip
Make more passes incremental
-rw-r--r--src/librustc/dep_graph/dep_node.rs6
-rw-r--r--src/librustc/hir/check_attr.rs26
-rw-r--r--src/librustc/hir/def_id.rs9
-rw-r--r--src/librustc/hir/lowering.rs40
-rw-r--r--src/librustc/hir/map/collector.rs1
-rw-r--r--src/librustc/hir/map/mod.rs30
-rw-r--r--src/librustc/hir/mod.rs16
-rw-r--r--src/librustc/middle/stability.rs20
-rw-r--r--src/librustc/ty/query/config.rs47
-rw-r--r--src/librustc/ty/query/mod.rs12
-rw-r--r--src/librustc/ty/query/plumbing.rs5
-rw-r--r--src/librustc_driver/driver.rs7
-rw-r--r--src/librustc_passes/lib.rs1
-rw-r--r--src/librustc_passes/loops.rs34
-rw-r--r--src/librustc_typeck/check/mod.rs10
-rw-r--r--src/librustc_typeck/collect.rs16
16 files changed, 246 insertions, 34 deletions
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 3156f17e0c4..427fe51e6ff 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -472,6 +472,12 @@ define_dep_nodes!( <'tcx>
     [] UnsafetyCheckResult(DefId),
     [] UnsafeDeriveOnReprPacked(DefId),
 
+    [] CheckModAttrs(DefId),
+    [] CheckModLoops(DefId),
+    [] CheckModUnstableApiUsage(DefId),
+    [] CheckModItemTypes(DefId),
+    [] CollectModItemTypes(DefId),
+
     [] Reachability,
     [] MirKeys,
     [eval_always] CrateVariances,
diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs
index 2e0e9672758..2cce8e0f9c9 100644
--- a/src/librustc/hir/check_attr.rs
+++ b/src/librustc/hir/check_attr.rs
@@ -4,9 +4,14 @@
 //! conflicts between multiple such attributes attached to the same
 //! item.
 
+
+use ty::TyCtxt;
+use ty::query::Providers;
+use ty::query::queries;
+
 use hir;
+use hir::def_id::DefId;
 use hir::intravisit::{self, Visitor, NestedVisitorMap};
-use ty::TyCtxt;
 use std::fmt::{self, Display};
 use syntax_pos::Span;
 
@@ -364,8 +369,9 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckAttrVisitor<'a, 'tcx> {
 }
 
 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    let mut checker = CheckAttrVisitor { tcx };
-    tcx.hir().krate().visit_all_item_likes(&mut checker.as_deep_visitor());
+    for &module in tcx.hir().krate().modules.keys() {
+        queries::check_mod_attrs::ensure(tcx, tcx.hir().local_def_id(module));
+    }
 }
 
 fn is_c_like_enum(item: &hir::Item) -> bool {
@@ -381,3 +387,17 @@ fn is_c_like_enum(item: &hir::Item) -> bool {
         false
     }
 }
+
+pub fn check_mod_attrs<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
+    tcx.hir().visit_module_item_likes(
+        module_def_id,
+        &mut CheckAttrVisitor { tcx }.as_deep_visitor()
+    );
+}
+
+pub(crate) fn provide(providers: &mut Providers<'_>) {
+    *providers = Providers {
+        check_mod_attrs,
+        ..*providers
+    };
+}
diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs
index fb2c873d740..868072b2fa7 100644
--- a/src/librustc/hir/def_id.rs
+++ b/src/librustc/hir/def_id.rs
@@ -1,4 +1,5 @@
 use ty;
+use ty::TyCtxt;
 use hir::map::definitions::FIRST_FREE_HIGH_DEF_INDEX;
 use rustc_data_structures::indexed_vec::Idx;
 use serialize;
@@ -247,6 +248,14 @@ impl DefId {
     pub fn to_local(self) -> LocalDefId {
         LocalDefId::from_def_id(self)
     }
+
+    pub fn describe_as_module(&self, tcx: TyCtxt<'_, '_, '_>) -> String {
+        if self.is_local() && self.index == CRATE_DEF_INDEX {
+            format!("top-level module")
+        } else {
+            format!("module `{}`", tcx.item_path_str(*self))
+        }
+    }
 }
 
 impl serialize::UseSpecializedEncodable for DefId {}
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 359bd374882..6957c97931b 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -48,7 +48,7 @@ use session::config::nightly_options;
 use util::common::FN_OUTPUT_NAME;
 use util::nodemap::{DefIdMap, NodeMap};
 
-use std::collections::BTreeMap;
+use std::collections::{BTreeSet, BTreeMap};
 use std::fmt::Debug;
 use std::mem;
 use smallvec::SmallVec;
@@ -90,6 +90,8 @@ pub struct LoweringContext<'a> {
     trait_impls: BTreeMap<DefId, Vec<NodeId>>,
     trait_auto_impl: BTreeMap<DefId, NodeId>,
 
+    modules: BTreeMap<NodeId, hir::ModuleItems>,
+
     is_generator: bool,
 
     catch_scopes: Vec<NodeId>,
@@ -124,6 +126,8 @@ pub struct LoweringContext<'a> {
     // needs to be created for it.
     in_scope_lifetimes: Vec<Ident>,
 
+    current_module: NodeId,
+
     type_def_lifetime_params: DefIdMap<usize>,
 
     current_hir_id_owner: Vec<(DefIndex, u32)>,
@@ -228,12 +232,14 @@ pub fn lower_crate(
         bodies: BTreeMap::new(),
         trait_impls: BTreeMap::new(),
         trait_auto_impl: BTreeMap::new(),
+        modules: BTreeMap::new(),
         exported_macros: Vec::new(),
         catch_scopes: Vec::new(),
         loop_scopes: Vec::new(),
         is_in_loop_condition: false,
         anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough,
         type_def_lifetime_params: Default::default(),
+        current_module: CRATE_NODE_ID,
         current_hir_id_owner: vec![(CRATE_DEF_INDEX, 0)],
         item_local_id_counters: Default::default(),
         node_id_to_hir_id: IndexVec::new(),
@@ -356,6 +362,15 @@ impl<'a> LoweringContext<'a> {
         }
 
         impl<'lcx, 'interner> Visitor<'lcx> for MiscCollector<'lcx, 'interner> {
+            fn visit_mod(&mut self, m: &'lcx Mod, _s: Span, _attrs: &[Attribute], n: NodeId) {
+                self.lctx.modules.insert(n, hir::ModuleItems {
+                    items: BTreeSet::new(),
+                    trait_items: BTreeSet::new(),
+                    impl_items: BTreeSet::new(),
+                });
+                visit::walk_mod(self, m);
+            }
+
             fn visit_item(&mut self, item: &'lcx Item) {
                 self.lctx.allocate_hir_id_counter(item.id, item);
 
@@ -414,11 +429,18 @@ impl<'a> LoweringContext<'a> {
         }
 
         impl<'lcx, 'interner> Visitor<'lcx> for ItemLowerer<'lcx, 'interner> {
+            fn visit_mod(&mut self, m: &'lcx Mod, _s: Span, _attrs: &[Attribute], n: NodeId) {
+                let old = self.lctx.current_module;
+                self.lctx.current_module = n;
+                visit::walk_mod(self, m);
+                self.lctx.current_module = old;
+            }
+
             fn visit_item(&mut self, item: &'lcx Item) {
                 let mut item_lowered = true;
                 self.lctx.with_hir_id_owner(item.id, |lctx| {
                     if let Some(hir_item) = lctx.lower_item(item) {
-                        lctx.items.insert(item.id, hir_item);
+                        lctx.insert_item(item.id, hir_item);
                     } else {
                         item_lowered = false;
                     }
@@ -451,6 +473,7 @@ impl<'a> LoweringContext<'a> {
                     let id = hir::TraitItemId { node_id: item.id };
                     let hir_item = lctx.lower_trait_item(item);
                     lctx.trait_items.insert(id, hir_item);
+                    lctx.modules.get_mut(&lctx.current_module).unwrap().trait_items.insert(id);
                 });
 
                 visit::walk_trait_item(self, item);
@@ -461,6 +484,7 @@ impl<'a> LoweringContext<'a> {
                     let id = hir::ImplItemId { node_id: item.id };
                     let hir_item = lctx.lower_impl_item(item);
                     lctx.impl_items.insert(id, hir_item);
+                    lctx.modules.get_mut(&lctx.current_module).unwrap().impl_items.insert(id);
                 });
                 visit::walk_impl_item(self, item);
             }
@@ -492,9 +516,15 @@ impl<'a> LoweringContext<'a> {
             body_ids,
             trait_impls: self.trait_impls,
             trait_auto_impl: self.trait_auto_impl,
+            modules: self.modules,
         }
     }
 
+    fn insert_item(&mut self, id: NodeId, item: hir::Item) {
+        self.items.insert(id, item);
+        self.modules.get_mut(&self.current_module).unwrap().items.insert(id);
+    }
+
     fn allocate_hir_id_counter<T: Debug>(&mut self, owner: NodeId, debug: &T) -> LoweredNodeId {
         if self.item_local_id_counters.insert(owner, 0).is_some() {
             bug!(
@@ -1370,7 +1400,7 @@ impl<'a> LoweringContext<'a> {
             // Insert the item into the global list. This usually happens
             // automatically for all AST items. But this existential type item
             // does not actually exist in the AST.
-            lctx.items.insert(exist_ty_id.node_id, exist_ty_item);
+            lctx.insert_item(exist_ty_id.node_id, exist_ty_item);
 
             // `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
             hir::TyKind::Def(hir::ItemId { id: exist_ty_id.node_id }, lifetimes)
@@ -3026,7 +3056,7 @@ impl<'a> LoweringContext<'a> {
                         };
                         let vis = respan(vis.span, vis_kind);
 
-                        this.items.insert(
+                        this.insert_item(
                             new_id.node_id,
                             hir::Item {
                                 id: new_id.node_id,
@@ -3133,7 +3163,7 @@ impl<'a> LoweringContext<'a> {
                         };
                         let vis = respan(vis.span, vis_kind);
 
-                        this.items.insert(
+                        this.insert_item(
                             new_id,
                             hir::Item {
                                 id: new_id,
diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index 78acea9f588..925a5fb85b8 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -119,6 +119,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
                 trait_impls: _,
                 trait_auto_impl: _,
                 body_ids: _,
+                modules: _,
             } = *krate;
 
             alloc_hir_dep_nodes(
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 5bcbeeefa50..0d55b4fdb74 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -17,6 +17,7 @@ use syntax::ext::base::MacroKind;
 use syntax_pos::{Span, DUMMY_SP};
 
 use hir::*;
+use hir::itemlikevisit::ItemLikeVisitor;
 use hir::print::Nested;
 use util::nodemap::FxHashMap;
 
@@ -506,6 +507,35 @@ impl<'hir> Map<'hir> {
         &self.forest.krate.attrs
     }
 
+    pub fn visit_module_item_likes<V>(&self, module: DefId, visitor: &mut V)
+        where V: ItemLikeVisitor<'hir>
+    {
+        let node_id = self.as_local_node_id(module).unwrap();
+
+        // Read the module so we'll be re-executed if new items
+        // appear immediately under in the module. If some new item appears
+        // in some nested item in the module, we'll be re-executed due to the reads
+        // in the loops below
+        self.read(node_id);
+
+        let module = &self.forest.krate.modules[&node_id];
+
+        for id in &module.items {
+            self.read(*id);
+            visitor.visit_item(&self.forest.krate.items[id]);
+        }
+
+        for id in &module.trait_items {
+            self.read(id.node_id);
+            visitor.visit_trait_item(&self.forest.krate.trait_items[id]);
+        }
+
+        for id in &module.impl_items {
+            self.read(id.node_id);
+            visitor.visit_impl_item(&self.forest.krate.impl_items[id]);
+        }
+    }
+
     /// Retrieve the Node corresponding to `id`, panicking if it cannot
     /// be found.
     pub fn get(&self, id: NodeId) -> Node<'hir> {
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 7e87171a5ed..fc4bd05476f 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -33,7 +33,7 @@ use rustc_data_structures::sync::{ParallelIterator, par_iter, Send, Sync, scope}
 use rustc_data_structures::thin_vec::ThinVec;
 
 use serialize::{self, Encoder, Encodable, Decoder, Decodable};
-use std::collections::BTreeMap;
+use std::collections::{BTreeSet, BTreeMap};
 use std::fmt;
 
 /// HIR doesn't commit to a concrete storage type and has its own alias for a vector.
@@ -676,6 +676,15 @@ pub struct WhereEqPredicate {
     pub rhs_ty: P<Ty>,
 }
 
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+pub struct ModuleItems {
+    // Use BTreeSets here so items are in the same order as in the
+    // list of all items in Crate
+    pub items: BTreeSet<NodeId>,
+    pub trait_items: BTreeSet<TraitItemId>,
+    pub impl_items: BTreeSet<ImplItemId>,
+}
+
 /// The top-level data structure that stores the entire contents of
 /// the crate currently being compiled.
 ///
@@ -708,6 +717,10 @@ pub struct Crate {
     /// in the crate, you should iterate over this list rather than the keys
     /// of bodies.
     pub body_ids: Vec<BodyId>,
+
+    /// A list of modules written out in the order in which they
+    /// appear in the crate. This includes the main crate module.
+    pub modules: BTreeMap<NodeId, ModuleItems>,
 }
 
 impl Crate {
@@ -2408,6 +2421,7 @@ pub type GlobMap = NodeMap<FxHashSet<Name>>;
 
 
 pub fn provide(providers: &mut Providers<'_>) {
+    check_attr::provide(providers);
     providers.describe_def = map::describe_def;
 }
 
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index 43cb89ccf6c..ad275ff2faa 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -8,6 +8,8 @@ use hir::{self, Item, Generics, StructField, Variant, HirId};
 use hir::def::Def;
 use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
 use hir::intravisit::{self, Visitor, NestedVisitorMap};
+use ty::query::Providers;
+use ty::query::queries;
 use middle::privacy::AccessLevels;
 use session::{DiagnosticMessageId, Session};
 use syntax::symbol::Symbol;
@@ -454,11 +456,23 @@ impl<'a, 'tcx> Index<'tcx> {
     }
 }
 
+pub fn check_unstable_api_usage<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+    for &module in tcx.hir().krate().modules.keys() {
+        queries::check_mod_unstable_api_usage::ensure(tcx, tcx.hir().local_def_id(module));
+    }
+}
+
 /// Cross-references the feature names of unstable APIs with enabled
 /// features and possibly prints errors.
-pub fn check_unstable_api_usage<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    let mut checker = Checker { tcx };
-    tcx.hir().krate().visit_all_item_likes(&mut checker.as_deep_visitor());
+pub fn check_mod_unstable_api_usage<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
+    tcx.hir().visit_module_item_likes(module_def_id, &mut Checker { tcx }.as_deep_visitor());
+}
+
+pub fn provide(providers: &mut Providers<'_>) {
+    *providers = Providers {
+        check_mod_unstable_api_usage,
+        ..*providers
+    };
 }
 
 /// Check whether an item marked with `deprecated(since="X")` is currently
diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs
index 3464464aa22..ca5d1f6bd32 100644
--- a/src/librustc/ty/query/config.rs
+++ b/src/librustc/ty/query/config.rs
@@ -68,11 +68,56 @@ impl<'tcx, M: QueryAccessors<'tcx, Key=DefId>> QueryDescription<'tcx> for M {
             format!("processing `{}`", tcx.item_path_str(def_id)).into()
         } else {
             let name = unsafe { ::std::intrinsics::type_name::<M>() };
-            format!("processing `{}` applied to `{:?}`", name, def_id).into()
+            format!("processing {:?} with query `{}`", def_id, name).into()
         }
     }
 }
 
+impl<'tcx> QueryDescription<'tcx> for queries::check_mod_attrs<'tcx> {
+    fn describe(
+        tcx: TyCtxt<'_, '_, '_>,
+        key: DefId,
+    ) -> Cow<'static, str> {
+        format!("checking attributes in {}", key.describe_as_module(tcx)).into()
+    }
+}
+
+impl<'tcx> QueryDescription<'tcx> for queries::check_mod_unstable_api_usage<'tcx> {
+    fn describe(
+        tcx: TyCtxt<'_, '_, '_>,
+        key: DefId,
+    ) -> Cow<'static, str> {
+        format!("checking for unstable API usage in {}", key.describe_as_module(tcx)).into()
+    }
+}
+
+impl<'tcx> QueryDescription<'tcx> for queries::check_mod_loops<'tcx> {
+    fn describe(
+        tcx: TyCtxt<'_, '_, '_>,
+        key: DefId,
+    ) -> Cow<'static, str> {
+        format!("checking loops in {}", key.describe_as_module(tcx)).into()
+    }
+}
+
+impl<'tcx> QueryDescription<'tcx> for queries::check_mod_item_types<'tcx> {
+    fn describe(
+        tcx: TyCtxt<'_, '_, '_>,
+        key: DefId,
+    ) -> Cow<'static, str> {
+        format!("checking item types in {}", key.describe_as_module(tcx)).into()
+    }
+}
+
+impl<'tcx> QueryDescription<'tcx> for queries::collect_mod_item_types<'tcx> {
+    fn describe(
+        tcx: TyCtxt<'_, '_, '_>,
+        key: DefId,
+    ) -> Cow<'static, str> {
+        format!("collecting item types in {}", key.describe_as_module(tcx)).into()
+    }
+}
+
 impl<'tcx> QueryDescription<'tcx> for queries::normalize_projection_ty<'tcx> {
     fn describe(
         _tcx: TyCtxt<'_, '_, '_>,
diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs
index d9cabb39574..39d76ceed95 100644
--- a/src/librustc/ty/query/mod.rs
+++ b/src/librustc/ty/query/mod.rs
@@ -254,6 +254,18 @@ define_queries! { <'tcx>
     },
 
     Other {
+        /// Checks the attributes in the module
+        [] fn check_mod_attrs: CheckModAttrs(DefId) -> (),
+
+        [] fn check_mod_unstable_api_usage: CheckModUnstableApiUsage(DefId) -> (),
+
+        /// Checks the loops in the module
+        [] fn check_mod_loops: CheckModLoops(DefId) -> (),
+
+        [] fn check_mod_item_types: CheckModItemTypes(DefId) -> (),
+
+        [] fn collect_mod_item_types: CollectModItemTypes(DefId) -> (),
+
         /// Caches CoerceUnsized kinds for impls on custom types.
         [] fn coerce_unsized_info: CoerceUnsizedInfo(DefId)
             -> ty::adjustment::CoerceUnsizedInfo,
diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs
index 2d619d19b42..af23bf3c590 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -1262,6 +1262,11 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
         DepKind::MirBorrowCheck => { force!(mir_borrowck, def_id!()); }
         DepKind::UnsafetyCheckResult => { force!(unsafety_check_result, def_id!()); }
         DepKind::UnsafeDeriveOnReprPacked => { force!(unsafe_derive_on_repr_packed, def_id!()); }
+        DepKind::CheckModAttrs => { force!(check_mod_attrs, def_id!()); }
+        DepKind::CheckModLoops => { force!(check_mod_loops, def_id!()); }
+        DepKind::CheckModUnstableApiUsage => { force!(check_mod_unstable_api_usage, def_id!()); }
+        DepKind::CheckModItemTypes => { force!(check_mod_item_types, def_id!()); }
+        DepKind::CollectModItemTypes => { force!(collect_mod_item_types, def_id!()); }
         DepKind::Reachability => { force!(reachable_set, LOCAL_CRATE); }
         DepKind::MirKeys => { force!(mir_keys, LOCAL_CRATE); }
         DepKind::CrateVariances => { force!(crate_variances, LOCAL_CRATE); }
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index bfff592a5dd..380f9afd68d 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -1167,6 +1167,7 @@ pub fn default_provide(providers: &mut ty::query::Providers) {
     typeck::provide(providers);
     ty::provide(providers);
     traits::provide(providers);
+    stability::provide(providers);
     reachable::provide(providers);
     rustc_passes::provide(providers);
     rustc_traits::provide(providers);
@@ -1218,8 +1219,6 @@ where
     sess.proc_macro_decls_static
         .set(proc_macro_decls::find(&hir_map));
 
-    time(sess, "loop checking", || loops::check_crate(sess, &hir_map));
-
     let mut local_providers = ty::query::Providers::default();
     default_provide(&mut local_providers);
     codegen_backend.provide(&mut local_providers);
@@ -1247,7 +1246,9 @@ where
         |tcx| {
             // Do some initialization of the DepGraph that can only be done with the
             // tcx available.
-            rustc_incremental::dep_graph_tcx_init(tcx);
+            time(sess, "dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx));
+
+            time(sess, "loop checking", || loops::check_crate(tcx));
 
             time(sess, "attribute checking", || {
                 hir::check_attr::check_crate(tcx)
diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs
index 0b394d800ea..829d4b34cf7 100644
--- a/src/librustc_passes/lib.rs
+++ b/src/librustc_passes/lib.rs
@@ -38,4 +38,5 @@ __build_diagnostic_array! { librustc_passes, DIAGNOSTICS }
 
 pub fn provide(providers: &mut Providers) {
     rvalue_promotion::provide(providers);
+    loops::provide(providers);
 }
diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs
index 7a37a35abbc..712fa84ccd9 100644
--- a/src/librustc_passes/loops.rs
+++ b/src/librustc_passes/loops.rs
@@ -2,6 +2,10 @@ use self::Context::*;
 
 use rustc::session::Session;
 
+use rustc::ty::query::Providers;
+use rustc::ty::query::queries;
+use rustc::ty::TyCtxt;
+use rustc::hir::def_id::DefId;
 use rustc::hir::map::Map;
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir::{self, Node, Destination};
@@ -42,28 +46,32 @@ struct CheckLoopVisitor<'a, 'hir: 'a> {
     cx: Context,
 }
 
-pub fn check_crate(sess: &Session, map: &Map) {
-    let krate = map.krate();
-    krate.visit_all_item_likes(&mut CheckLoopVisitor {
-        sess,
-        hir_map: map,
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+    for &module in tcx.hir().krate().modules.keys() {
+        queries::check_mod_loops::ensure(tcx, tcx.hir().local_def_id(module));
+    }
+}
+
+pub fn check_mod_loops<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
+    tcx.hir().visit_module_item_likes(module_def_id, &mut CheckLoopVisitor {
+        sess: &tcx.sess,
+        hir_map: &tcx.hir(),
         cx: Normal,
     }.as_deep_visitor());
 }
 
+pub(crate) fn provide(providers: &mut Providers) {
+    *providers = Providers {
+        check_mod_loops,
+        ..*providers
+    };
+}
+
 impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> {
         NestedVisitorMap::OnlyBodies(&self.hir_map)
     }
 
-    fn visit_item(&mut self, i: &'hir hir::Item) {
-        self.with_context(Normal, |v| intravisit::walk_item(v, i));
-    }
-
-    fn visit_impl_item(&mut self, i: &'hir hir::ImplItem) {
-        self.with_context(Normal, |v| intravisit::walk_impl_item(v, i));
-    }
-
     fn visit_anon_const(&mut self, c: &'hir hir::AnonConst) {
         self.with_context(AnonConst, |v| intravisit::walk_anon_const(v, c));
     }
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 1a5d164873d..d008c80267c 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -109,6 +109,7 @@ use rustc::ty::{
 use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::query::Providers;
+use rustc::ty::query::queries;
 use rustc::ty::subst::{UnpackedKind, Subst, Substs, UserSelfTy, UserSubsts};
 use rustc::ty::util::{Representability, IntTypeExt, Discr};
 use rustc::ty::layout::VariantIdx;
@@ -700,10 +701,16 @@ pub fn check_wf_new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorRe
 
 pub fn check_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorReported> {
     tcx.sess.track_errors(|| {
-        tcx.hir().krate().visit_all_item_likes(&mut CheckItemTypesVisitor { tcx });
+        for &module in tcx.hir().krate().modules.keys() {
+            queries::check_mod_item_types::ensure(tcx, tcx.hir().local_def_id(module));
+        }
     })
 }
 
+fn check_mod_item_types<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
+    tcx.hir().visit_module_item_likes(module_def_id, &mut CheckItemTypesVisitor { tcx });
+}
+
 pub fn check_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), CompileIncomplete> {
     tcx.typeck_item_bodies(LOCAL_CRATE)
 }
@@ -742,6 +749,7 @@ pub fn provide(providers: &mut Providers) {
         check_item_well_formed,
         check_trait_item_well_formed,
         check_impl_item_well_formed,
+        check_mod_item_types,
         ..*providers
     };
 }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index e0e173901ef..9bdc0bdc2e9 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -22,6 +22,7 @@ use middle::resolve_lifetime as rl;
 use middle::weak_lang_items;
 use rustc::mir::mono::Linkage;
 use rustc::ty::query::Providers;
+use rustc::ty::query::queries;
 use rustc::ty::subst::Substs;
 use rustc::ty::util::Discr;
 use rustc::ty::util::IntTypeExt;
@@ -55,10 +56,16 @@ struct OnlySelfBounds(bool);
 // Main entry point
 
 pub fn collect_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    let mut visitor = CollectItemTypesVisitor { tcx };
-    tcx.hir()
-       .krate()
-       .visit_all_item_likes(&mut visitor.as_deep_visitor());
+    for &module in tcx.hir().krate().modules.keys() {
+        queries::collect_mod_item_types::ensure(tcx, tcx.hir().local_def_id(module));
+    }
+}
+
+fn collect_mod_item_types<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
+    tcx.hir().visit_module_item_likes(
+        module_def_id,
+        &mut CollectItemTypesVisitor { tcx }.as_deep_visitor()
+    );
 }
 
 pub fn provide(providers: &mut Providers) {
@@ -77,6 +84,7 @@ pub fn provide(providers: &mut Providers) {
         impl_polarity,
         is_foreign_item,
         codegen_fn_attrs,
+        collect_mod_item_types,
         ..*providers
     };
 }