about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Woerister <michaelwoerister@posteo>2017-09-26 19:43:17 +0200
committerMichael Woerister <michaelwoerister@posteo>2017-10-02 15:38:57 +0200
commitf0bbf4e1f25fb9f1882bbf0e4c92395f38474fb5 (patch)
tree82c087a2a5edcb48c56d2bb87e754c21f3b1f0ef
parent6db27d9f90223693e84d230e5654d4c1a5afe700 (diff)
downloadrust-f0bbf4e1f25fb9f1882bbf0e4c92395f38474fb5.tar.gz
rust-f0bbf4e1f25fb9f1882bbf0e4c92395f38474fb5.zip
incr.comp.: Re-execute queries during red/green marking in order to find out their color.
-rw-r--r--src/librustc/dep_graph/dep_node.rs17
-rw-r--r--src/librustc/dep_graph/graph.rs34
-rw-r--r--src/librustc/ty/maps/mod.rs1
-rw-r--r--src/librustc/ty/maps/plumbing.rs409
-rw-r--r--src/librustc_mir/transform/mod.rs15
-rw-r--r--src/librustc_trans/base.rs13
6 files changed, 397 insertions, 92 deletions
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 7a78765365d..987bb5a9a4d 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -66,7 +66,6 @@ use hir::{HirId, ItemLocalId};
 
 use ich::Fingerprint;
 use ty::{TyCtxt, Instance, InstanceDef};
-use ty::fast_reject::SimplifiedType;
 use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
 use ich::StableHashingContext;
 use std::fmt;
@@ -430,7 +429,6 @@ define_dep_nodes!( <'tcx>
     [] RegionScopeTree(DefId),
     [] Coherence,
     [] CoherenceInherentImplOverlapCheck,
-    [] Resolve,
     [] CoherenceCheckTrait(DefId),
     [] PrivacyAccessLevels(CrateNum),
 
@@ -447,10 +445,8 @@ define_dep_nodes!( <'tcx>
     [] MirBorrowCheck(DefId),
     [] UnsafetyViolations(DefId),
 
-    [] RvalueCheck(DefId),
     [] Reachability,
     [] MirKeys,
-    [] TransWriteMetadata,
     [] CrateVariances,
 
     // Nodes representing bits of computed IR in the tcx. Each shared
@@ -498,18 +494,9 @@ define_dep_nodes!( <'tcx>
 
     // The set of impls for a given trait.
     [] TraitImpls(DefId),
-    [] RelevantTraitImpls(DefId, SimplifiedType),
 
     [] AllLocalTraitImpls,
 
-    // Nodes representing caches. To properly handle a true cache, we
-    // don't use a DepTrackingMap, but rather we push a task node.
-    // Otherwise the write into the map would be incorrectly
-    // attributed to the first task that happened to fill the cache,
-    // which would yield an overly conservative dep-graph.
-    [] TraitItems(DefId),
-    [] ReprHints(DefId),
-
     // Trait selection cache is a little funny. Given a trait
     // reference like `Foo: SomeTrait<Bar>`, there could be
     // arbitrarily many def-ids to map on in there (e.g., `Foo`,
@@ -598,7 +585,6 @@ define_dep_nodes!( <'tcx>
     [] MissingLangItems(CrateNum),
     [] ExternConstBody(DefId),
     [] VisibleParentMap,
-    [] IsDirectExternCrate(CrateNum),
     [] MissingExternCrateItem(CrateNum),
     [] UsedCrateSource(CrateNum),
     [] PostorderCnums,
@@ -618,6 +604,9 @@ define_dep_nodes!( <'tcx>
     [] CodegenUnit(InternedString),
     [] CompileCodegenUnit(InternedString),
     [] OutputFilenames,
+
+    // We use this for most things when incr. comp. is turned off.
+    [] Null,
 );
 
 trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index 071f233b188..80b408f67bb 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -460,8 +460,9 @@ impl DepGraph {
 
         let mut current_deps = Vec::new();
 
-        for &dep_dep_node in prev_deps {
-            let dep_dep_node = &data.previous.index_to_node(dep_dep_node);
+        for &dep_dep_node_index in prev_deps {
+            let dep_dep_node = &data.previous.index_to_node(dep_dep_node_index);
+
             let dep_dep_node_color = data.colors.borrow().get(dep_dep_node).cloned();
             match dep_dep_node_color {
                 Some(DepNodeColor::Green(node_index)) => {
@@ -478,19 +479,42 @@ impl DepGraph {
                     return None
                 }
                 None => {
+                    if dep_dep_node.kind.is_input() {
+                        // This input does not exist anymore.
+                        debug_assert!(dep_dep_node.extract_def_id(tcx).is_none());
+                        return None;
+                    }
+
                     // We don't know the state of this dependency. Let's try to
                     // mark it green.
                     if let Some(node_index) = self.try_mark_green(tcx, dep_dep_node) {
                         current_deps.push(node_index);
                     } else {
-                        // We failed to mark it green. This can have various
-                        // reasons.
-                        return None
+                        // We failed to mark it green, so we try to force the query.
+                        if ::ty::maps::force_from_dep_node(tcx, dep_dep_node) {
+                            let dep_dep_node_color = data.colors.borrow().get(dep_dep_node).cloned();
+                            match dep_dep_node_color {
+                                Some(DepNodeColor::Green(node_index)) => {
+                                    current_deps.push(node_index);
+                                }
+                                Some(DepNodeColor::Red) => {
+                                    return None
+                                }
+                                None => {
+                                    bug!("try_mark_green() - Forcing the DepNode \
+                                          should have set its color")
+                                }
+                            }
+                        } else {
+                            // The DepNode could not be forced.
+                            return None
+                        }
                     }
                 }
             }
         }
 
+
         // If we got here without hitting a `return` that means that all
         // dependencies of this DepNode could be marked as green. Therefore we
         // can also mark this DepNode as green. We do so by...
diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs
index db66c279961..f6c587a9310 100644
--- a/src/librustc/ty/maps/mod.rs
+++ b/src/librustc/ty/maps/mod.rs
@@ -56,6 +56,7 @@ use syntax::symbol::Symbol;
 #[macro_use]
 mod plumbing;
 use self::plumbing::*;
+pub use self::plumbing::force_from_dep_node;
 
 mod keys;
 pub use self::keys::Key;
diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs
index c7c81e3cf89..6b1fa8f685d 100644
--- a/src/librustc/ty/maps/plumbing.rs
+++ b/src/librustc/ty/maps/plumbing.rs
@@ -12,7 +12,7 @@
 //! that generate the actual methods on tcx which find and execute the
 //! provider, manage the caches, and so forth.
 
-use dep_graph::{DepNodeIndex};
+use dep_graph::{DepNodeIndex, DepNode, DepKind};
 use errors::{Diagnostic, DiagnosticBuilder};
 use ty::{TyCtxt};
 use ty::maps::Query; // NB: actually generated by the macros in this file
@@ -232,12 +232,10 @@ macro_rules! define_maps {
                 DepNode::new(tcx, $node(*key))
             }
 
-            fn try_get_with<F, R>(tcx: TyCtxt<'a, $tcx, 'lcx>,
-                                  mut span: Span,
-                                  key: $K,
-                                  f: F)
-                                  -> Result<R, CycleError<'a, $tcx>>
-                where F: FnOnce(&$V) -> R
+            fn try_get_with(tcx: TyCtxt<'a, $tcx, 'lcx>,
+                            mut span: Span,
+                            key: $K)
+                            -> Result<$V, CycleError<'a, $tcx>>
             {
                 debug!("ty::queries::{}::try_get_with(key={:?}, span={:?})",
                        stringify!($name),
@@ -264,8 +262,9 @@ macro_rules! define_maps {
                     }
                     profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
                     tcx.dep_graph.read_index(value.index);
-                    return Ok(f(&value.value));
+                    return Ok((&value.value).clone());
                 }
+
                 // FIXME(eddyb) Get more valid Span's on queries.
                 // def_span guard is necessary to prevent a recursive loop,
                 // default_span calls def_span query internally.
@@ -273,9 +272,43 @@ macro_rules! define_maps {
                     span = key.default_span(tcx)
                 }
 
+                // Fast path for when incr. comp. is off. `to_dep_node` is
+                // expensive for some DepKinds.
+                if !tcx.dep_graph.is_fully_enabled() {
+                    let null_dep_node = DepNode::new_no_params(::dep_graph::DepKind::Null);
+                    return Self::force(tcx, key, span, null_dep_node)
+                                .map(|(v, _)| v);
+                }
+
                 let dep_node = Self::to_dep_node(tcx, &key);
 
-                if !dep_node.kind.is_input() && tcx.sess.opts.build_dep_graph() {
+                if dep_node.kind.is_anon() {
+                    profq_msg!(tcx, ProfileQueriesMsg::ProviderBegin);
+
+                    let res = tcx.cycle_check(span, Query::$name(key), || {
+                        tcx.sess.diagnostic().track_diagnostics(|| {
+                            tcx.dep_graph.with_anon_task(dep_node.kind, || {
+                                Self::compute_result(tcx.global_tcx(), key)
+                            })
+                        })
+                    })?;
+
+                    profq_msg!(tcx, ProfileQueriesMsg::ProviderEnd);
+                    let ((result, dep_node_index), diagnostics) = res;
+
+                    tcx.dep_graph.read_index(dep_node_index);
+                    let value = QueryValue::new(result, dep_node_index, diagnostics);
+
+                    return Ok((&tcx.maps
+                                    .$name
+                                    .borrow_mut()
+                                    .map
+                                    .entry(key)
+                                    .or_insert(value)
+                                    .value).clone());
+                }
+
+                if !dep_node.kind.is_input() {
                     use dep_graph::DepNodeColor;
                     if let Some(DepNodeColor::Green(dep_node_index)) = tcx.dep_graph
                                                                           .node_color(&dep_node) {
@@ -284,8 +317,7 @@ macro_rules! define_maps {
                         return Self::load_from_disk_and_cache_in_memory(tcx,
                                                                         key,
                                                                         span,
-                                                                        dep_node_index,
-                                                                        f)
+                                                                        dep_node_index)
                     }
 
                     if let Some(dep_node_index) = tcx.dep_graph.try_mark_green(tcx, &dep_node) {
@@ -295,43 +327,17 @@ macro_rules! define_maps {
                         return Self::load_from_disk_and_cache_in_memory(tcx,
                                                                         key,
                                                                         span,
-                                                                        dep_node_index,
-                                                                        f)
+                                                                        dep_node_index)
                     }
                 }
 
-                // else, we are going to run the provider:
-                profq_msg!(tcx, ProfileQueriesMsg::ProviderBegin);
-
-                let res = tcx.cycle_check(span, Query::$name(key), || {
-                    tcx.sess.diagnostic().track_diagnostics(|| {
-                        if dep_node.kind.is_anon() {
-                            tcx.dep_graph.with_anon_task(dep_node.kind, || {
-                                Self::compute_result(tcx.global_tcx(), key)
-                            })
-                        } else {
-                            tcx.dep_graph.with_task(dep_node,
-                                                    tcx,
-                                                    key,
-                                                    Self::compute_result)
-                        }
-                    })
-                })?;
-
-                profq_msg!(tcx, ProfileQueriesMsg::ProviderEnd);
-                let ((result, dep_node_index), diagnostics) = res;
-
-                tcx.dep_graph.read_index(dep_node_index);
-
-                let value = QueryValue::new(result, dep_node_index, diagnostics);
-
-                Ok(f(&tcx.maps
-                         .$name
-                         .borrow_mut()
-                         .map
-                         .entry(key)
-                         .or_insert(value)
-                         .value))
+                match Self::force(tcx, key, span, dep_node) {
+                    Ok((result, dep_node_index)) => {
+                        tcx.dep_graph.read_index(dep_node_index);
+                        Ok(result)
+                    }
+                    Err(e) => Err(e)
+                }
             }
 
             fn compute_result(tcx: TyCtxt<'a, $tcx, 'lcx>, key: $K) -> $V {
@@ -339,13 +345,11 @@ macro_rules! define_maps {
                 provider(tcx.global_tcx(), key)
             }
 
-            fn load_from_disk_and_cache_in_memory<F, R>(tcx: TyCtxt<'a, $tcx, 'lcx>,
-                                                        key: $K,
-                                                        span: Span,
-                                                        dep_node_index: DepNodeIndex,
-                                                        f: F)
-                                                        -> Result<R, CycleError<'a, $tcx>>
-                where F: FnOnce(&$V) -> R
+            fn load_from_disk_and_cache_in_memory(tcx: TyCtxt<'a, $tcx, 'lcx>,
+                                                  key: $K,
+                                                  span: Span,
+                                                  dep_node_index: DepNodeIndex)
+                                                  -> Result<$V, CycleError<'a, $tcx>>
             {
                 debug_assert!(tcx.dep_graph.is_green(dep_node_index));
 
@@ -361,32 +365,56 @@ macro_rules! define_maps {
 
                 let value = QueryValue::new(result, dep_node_index, diagnostics);
 
-                Ok(f(&tcx.maps
+                Ok((&tcx.maps
+                         .$name
+                         .borrow_mut()
+                         .map
+                         .entry(key)
+                         .or_insert(value)
+                         .value).clone())
+            }
+
+            fn force(tcx: TyCtxt<'a, $tcx, 'lcx>,
+                     key: $K,
+                     span: Span,
+                     dep_node: DepNode)
+                     -> Result<($V, DepNodeIndex), CycleError<'a, $tcx>> {
+                debug_assert!(tcx.dep_graph.node_color(&dep_node).is_none());
+
+                profq_msg!(tcx, ProfileQueriesMsg::ProviderBegin);
+                let res = tcx.cycle_check(span, Query::$name(key), || {
+                    tcx.sess.diagnostic().track_diagnostics(|| {
+                        tcx.dep_graph.with_task(dep_node,
+                                                tcx,
+                                                key,
+                                                Self::compute_result)
+                    })
+                })?;
+                profq_msg!(tcx, ProfileQueriesMsg::ProviderEnd);
+
+                let ((result, dep_node_index), diagnostics) = res;
+
+                let value = QueryValue::new(result, dep_node_index, diagnostics);
+
+                Ok(((&tcx.maps
                          .$name
                          .borrow_mut()
                          .map
                          .entry(key)
                          .or_insert(value)
-                         .value))
+                         .value).clone(),
+                   dep_node_index))
             }
 
+
+
             pub fn try_get(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K)
                            -> Result<$V, DiagnosticBuilder<'a>> {
-                match Self::try_get_with(tcx, span, key, Clone::clone) {
+                match Self::try_get_with(tcx, span, key) {
                     Ok(e) => Ok(e),
                     Err(e) => Err(tcx.report_cycle(e)),
                 }
             }
-
-            pub fn force(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K) {
-                // Ignore dependencies, since we not reading the computed value
-                let _task = tcx.dep_graph.in_ignore();
-
-                match Self::try_get_with(tcx, span, key, |_| ()) {
-                    Ok(()) => {}
-                    Err(e) => tcx.report_cycle(e).emit(),
-                }
-            }
         })*
 
         #[derive(Copy, Clone)]
@@ -564,3 +592,254 @@ macro_rules! define_provider_struct {
         }
     };
 }
+
+pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
+                                           dep_node: &DepNode)
+                                           -> bool {
+    use ty::maps::keys::Key;
+    use hir::def_id::LOCAL_CRATE;
+
+    // We should never get into the situation of having to force this from the DepNode.
+    // Since we cannot reconstruct the query key, we would always end up having to evaluate
+    // the first caller of this query that *is* reconstructible. This might very well be
+    // compile_codegen_unit() in which case we'd lose all re-use.
+    debug_assert!(dep_node.kind != DepKind::CodegenUnit,
+                  "calling force_from_dep_node() on DepKind::CodegenUnit");
+
+    if !dep_node.kind.can_reconstruct_query_key() {
+        return false
+    }
+
+    macro_rules! def_id {
+        () => {
+            if let Some(def_id) = dep_node.extract_def_id(tcx) {
+                def_id
+            } else {
+                // return from the whole function
+                return false
+            }
+        }
+    };
+
+    macro_rules! krate {
+        () => { (def_id!()).krate }
+    };
+
+    macro_rules! force {
+        ($query:ident, $key:expr) => {
+            {
+                use $crate::util::common::{ProfileQueriesMsg, profq_msg};
+
+                // FIXME(eddyb) Get more valid Span's on queries.
+                // def_span guard is necessary to prevent a recursive loop,
+                // default_span calls def_span query internally.
+                let span = if stringify!($query) != "def_span" {
+                    $key.default_span(tcx)
+                } else {
+                    ::syntax_pos::DUMMY_SP
+                };
+
+                profq_msg!(tcx,
+                    ProfileQueriesMsg::QueryBegin(
+                        span.clone(),
+                        ::ty::maps::QueryMsg::$query(profq_key!(tcx, $key))
+                    )
+                );
+
+                match ::ty::maps::queries::$query::force(tcx, $key, span, *dep_node) {
+                    Ok(_) => {},
+                    Err(e) => {
+                        tcx.report_cycle(e).emit();
+                    }
+                }
+            }
+        }
+    };
+
+    match dep_node.kind {
+        // These are inputs that are expected to be pre-allocated and that
+        // should therefore always be red or green already
+        DepKind::AllLocalTraitImpls |
+        DepKind::Krate |
+        DepKind::CrateMetadata |
+        DepKind::HirBody |
+        DepKind::Hir |
+
+        // This are anonymous nodes
+        DepKind::IsCopy |
+        DepKind::IsSized |
+        DepKind::IsFreeze |
+        DepKind::NeedsDrop |
+        DepKind::Layout |
+        DepKind::TraitSelect |
+        DepKind::ProjectionCache |
+        DepKind::ConstEval |
+
+        // We don't have enough information to reconstruct the query key of
+        // these
+        DepKind::InstanceSymbolName |
+        DepKind::MirShim |
+        DepKind::BorrowCheckKrate |
+        DepKind::Specializes |
+        DepKind::ImplementationsOfTrait |
+        DepKind::TypeParamPredicates |
+        DepKind::CodegenUnit |
+        DepKind::CompileCodegenUnit |
+
+        // This one is just odd
+        DepKind::Null |
+        DepKind::WorkProduct => {
+            bug!("force_from_dep_node() - Encountered {:?}", dep_node.kind)
+        }
+
+        // These is not a queries
+        DepKind::CoherenceCheckTrait |
+        DepKind::ItemVarianceConstraints => {
+            return false
+        }
+
+        DepKind::RegionScopeTree => { force!(region_scope_tree, def_id!()); }
+
+        DepKind::Coherence => { force!(crate_inherent_impls, LOCAL_CRATE); }
+        DepKind::CoherenceInherentImplOverlapCheck => {
+            force!(crate_inherent_impls_overlap_check, LOCAL_CRATE)
+        },
+        DepKind::PrivacyAccessLevels => { force!(privacy_access_levels, LOCAL_CRATE); }
+        DepKind::MirConstQualif => { force!(mir_const_qualif, def_id!()); }
+        DepKind::MirConst => { force!(mir_const, def_id!()); }
+        DepKind::MirValidated => { force!(mir_validated, def_id!()); }
+        DepKind::MirOptimized => { force!(optimized_mir, def_id!()); }
+
+        DepKind::BorrowCheck => { force!(borrowck, def_id!()); }
+        DepKind::MirBorrowCheck => { force!(mir_borrowck, def_id!()); }
+        DepKind::UnsafetyViolations => { force!(unsafety_violations, def_id!()); }
+        DepKind::Reachability => { force!(reachable_set, LOCAL_CRATE); }
+        DepKind::MirKeys => { force!(mir_keys, LOCAL_CRATE); }
+        DepKind::CrateVariances => { force!(crate_variances, LOCAL_CRATE); }
+        DepKind::AssociatedItems => { force!(associated_item, def_id!()); }
+        DepKind::TypeOfItem => { force!(type_of, def_id!()); }
+        DepKind::GenericsOfItem => { force!(generics_of, def_id!()); }
+        DepKind::PredicatesOfItem => { force!(predicates_of, def_id!()); }
+        DepKind::SuperPredicatesOfItem => { force!(super_predicates_of, def_id!()); }
+        DepKind::TraitDefOfItem => { force!(trait_def, def_id!()); }
+        DepKind::AdtDefOfItem => { force!(adt_def, def_id!()); }
+        DepKind::IsDefaultImpl => { force!(is_default_impl, def_id!()); }
+        DepKind::ImplTraitRef => { force!(impl_trait_ref, def_id!()); }
+        DepKind::ImplPolarity => { force!(impl_polarity, def_id!()); }
+        DepKind::ClosureKind => { force!(closure_kind, def_id!()); }
+        DepKind::FnSignature => { force!(fn_sig, def_id!()); }
+        DepKind::GenSignature => { force!(generator_sig, def_id!()); }
+        DepKind::CoerceUnsizedInfo => { force!(coerce_unsized_info, def_id!()); }
+        DepKind::ItemVariances => { force!(variances_of, def_id!()); }
+        DepKind::IsConstFn => { force!(is_const_fn, def_id!()); }
+        DepKind::IsForeignItem => { force!(is_foreign_item, def_id!()); }
+        DepKind::SizedConstraint => { force!(adt_sized_constraint, def_id!()); }
+        DepKind::DtorckConstraint => { force!(adt_dtorck_constraint, def_id!()); }
+        DepKind::AdtDestructor => { force!(adt_destructor, def_id!()); }
+        DepKind::AssociatedItemDefIds => { force!(associated_item_def_ids, def_id!()); }
+        DepKind::InherentImpls => { force!(inherent_impls, def_id!()); }
+        DepKind::TypeckBodiesKrate => { force!(typeck_item_bodies, LOCAL_CRATE); }
+        DepKind::TypeckTables => { force!(typeck_tables_of, def_id!()); }
+        DepKind::HasTypeckTables => { force!(has_typeck_tables, def_id!()); }
+        DepKind::SymbolName => { force!(def_symbol_name, def_id!()); }
+        DepKind::SpecializationGraph => { force!(specialization_graph_of, def_id!()); }
+        DepKind::ObjectSafety => { force!(is_object_safe, def_id!()); }
+        DepKind::TraitImpls => { force!(trait_impls_of, def_id!()); }
+
+        DepKind::ParamEnv => { force!(param_env, def_id!()); }
+        DepKind::DescribeDef => { force!(describe_def, def_id!()); }
+        DepKind::DefSpan => { force!(def_span, def_id!()); }
+        DepKind::LookupStability => { force!(lookup_stability, def_id!()); }
+        DepKind::LookupDeprecationEntry => {
+            force!(lookup_deprecation_entry, def_id!());
+        }
+        DepKind::ItemBodyNestedBodies => { force!(item_body_nested_bodies, def_id!()); }
+        DepKind::ConstIsRvaluePromotableToStatic => {
+            force!(const_is_rvalue_promotable_to_static, def_id!());
+        }
+        DepKind::ImplParent => { force!(impl_parent, def_id!()); }
+        DepKind::TraitOfItem => { force!(trait_of_item, def_id!()); }
+        DepKind::IsExportedSymbol => { force!(is_exported_symbol, def_id!()); }
+        DepKind::IsMirAvailable => { force!(is_mir_available, def_id!()); }
+        DepKind::ItemAttrs => { force!(item_attrs, def_id!()); }
+        DepKind::FnArgNames => { force!(fn_arg_names, def_id!()); }
+        DepKind::DylibDepFormats => { force!(dylib_dependency_formats, krate!()); }
+        DepKind::IsPanicRuntime => { force!(is_panic_runtime, krate!()); }
+        DepKind::IsCompilerBuiltins => { force!(is_compiler_builtins, krate!()); }
+        DepKind::HasGlobalAllocator => { force!(has_global_allocator, krate!()); }
+        DepKind::ExternCrate => { force!(extern_crate, def_id!()); }
+        DepKind::LintLevels => { force!(lint_levels, LOCAL_CRATE); }
+        DepKind::InScopeTraits => { force!(in_scope_traits_map, def_id!().index); }
+        DepKind::ModuleExports => { force!(module_exports, def_id!()); }
+        DepKind::IsSanitizerRuntime => { force!(is_sanitizer_runtime, krate!()); }
+        DepKind::IsProfilerRuntime => { force!(is_profiler_runtime, krate!()); }
+        DepKind::GetPanicStrategy => { force!(panic_strategy, krate!()); }
+        DepKind::IsNoBuiltins => { force!(is_no_builtins, krate!()); }
+        DepKind::ImplDefaultness => { force!(impl_defaultness, def_id!()); }
+        DepKind::ExportedSymbolIds => { force!(exported_symbol_ids, krate!()); }
+        DepKind::NativeLibraries => { force!(native_libraries, krate!()); }
+        DepKind::PluginRegistrarFn => { force!(plugin_registrar_fn, krate!()); }
+        DepKind::DeriveRegistrarFn => { force!(derive_registrar_fn, krate!()); }
+        DepKind::CrateDisambiguator => { force!(crate_disambiguator, krate!()); }
+        DepKind::CrateHash => { force!(crate_hash, krate!()); }
+        DepKind::OriginalCrateName => { force!(original_crate_name, krate!()); }
+
+        DepKind::AllTraitImplementations => {
+            force!(all_trait_implementations, krate!());
+        }
+
+        DepKind::IsDllimportForeignItem => {
+            force!(is_dllimport_foreign_item, def_id!());
+        }
+        DepKind::IsStaticallyIncludedForeignItem => {
+            force!(is_statically_included_foreign_item, def_id!());
+        }
+        DepKind::NativeLibraryKind => { force!(native_library_kind, def_id!()); }
+        DepKind::LinkArgs => { force!(link_args, LOCAL_CRATE); }
+
+        DepKind::NamedRegion => { force!(named_region_map, def_id!().index); }
+        DepKind::IsLateBound => { force!(is_late_bound_map, def_id!().index); }
+        DepKind::ObjectLifetimeDefaults => {
+            force!(object_lifetime_defaults_map, def_id!().index);
+        }
+
+        DepKind::Visibility => { force!(visibility, def_id!()); }
+        DepKind::DepKind => { force!(dep_kind, krate!()); }
+        DepKind::CrateName => { force!(crate_name, krate!()); }
+        DepKind::ItemChildren => { force!(item_children, def_id!()); }
+        DepKind::ExternModStmtCnum => { force!(extern_mod_stmt_cnum, def_id!()); }
+        DepKind::GetLangItems => { force!(get_lang_items, LOCAL_CRATE); }
+        DepKind::DefinedLangItems => { force!(defined_lang_items, krate!()); }
+        DepKind::MissingLangItems => { force!(missing_lang_items, krate!()); }
+        DepKind::ExternConstBody => { force!(extern_const_body, def_id!()); }
+        DepKind::VisibleParentMap => { force!(visible_parent_map, LOCAL_CRATE); }
+        DepKind::MissingExternCrateItem => {
+            force!(missing_extern_crate_item, krate!());
+        }
+        DepKind::UsedCrateSource => { force!(used_crate_source, krate!()); }
+        DepKind::PostorderCnums => { force!(postorder_cnums, LOCAL_CRATE); }
+        DepKind::HasCloneClosures => { force!(has_clone_closures, krate!()); }
+        DepKind::HasCopyClosures => { force!(has_copy_closures, krate!()); }
+
+        DepKind::Freevars => { force!(freevars, def_id!()); }
+        DepKind::MaybeUnusedTraitImport => {
+            force!(maybe_unused_trait_import, def_id!());
+        }
+        DepKind::MaybeUnusedExternCrates => { force!(maybe_unused_extern_crates, LOCAL_CRATE); }
+        DepKind::StabilityIndex => { force!(stability_index, LOCAL_CRATE); }
+        DepKind::AllCrateNums => { force!(all_crate_nums, LOCAL_CRATE); }
+        DepKind::ExportedSymbols => { force!(exported_symbols, krate!()); }
+        DepKind::CollectAndPartitionTranslationItems => {
+            force!(collect_and_partition_translation_items, LOCAL_CRATE);
+        }
+        DepKind::ExportName => { force!(export_name, def_id!()); }
+        DepKind::ContainsExternIndicator => {
+            force!(contains_extern_indicator, def_id!());
+        }
+        DepKind::IsTranslatedFunction => { force!(is_translated_function, def_id!()); }
+        DepKind::OutputFilenames => { force!(output_filenames, LOCAL_CRATE); }
+    }
+
+    true
+}
+
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index 7245b2daa12..322f46cf02b 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -13,7 +13,7 @@ use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc::mir::Mir;
 use rustc::mir::transform::{MirPassIndex, MirSuite, MirSource,
                             MIR_CONST, MIR_VALIDATED, MIR_OPTIMIZED};
-use rustc::ty::{self, TyCtxt};
+use rustc::ty::TyCtxt;
 use rustc::ty::maps::Providers;
 use rustc::ty::steal::Steal;
 use rustc::hir;
@@ -21,7 +21,7 @@ use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::util::nodemap::DefIdSet;
 use std::rc::Rc;
 use syntax::ast;
-use syntax_pos::{DUMMY_SP, Span};
+use syntax_pos::Span;
 use transform;
 
 pub mod add_validation;
@@ -114,11 +114,10 @@ fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
     let source = MirSource::from_local_def_id(tcx, def_id);
     if let MirSource::Const(_) = source {
         // Ensure that we compute the `mir_const_qualif` for constants at
-        // this point, before we steal the mir-const result. We don't
-        // directly need the result or `mir_const_qualif`, so we can just force it.
-        ty::queries::mir_const_qualif::force(tcx, DUMMY_SP, def_id);
+        // this point, before we steal the mir-const result.
+        let _ = tcx.mir_const_qualif(def_id);
     }
-    ty::queries::unsafety_violations::force(tcx, DUMMY_SP, def_id);
+    let _ = tcx.unsafety_violations(def_id);
 
     let mut mir = tcx.mir_const(def_id).steal();
     transform::run_suite(tcx, source, MIR_VALIDATED, &mut mir);
@@ -128,8 +127,8 @@ fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
 fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Mir<'tcx> {
     // (Mir-)Borrowck uses `mir_validated`, so we have to force it to
     // execute before we can steal.
-    ty::queries::mir_borrowck::force(tcx, DUMMY_SP, def_id);
-    ty::queries::borrowck::force(tcx, DUMMY_SP, def_id);
+    let _ = tcx.mir_borrowck(def_id);
+    let _ = tcx.borrowck(def_id);
 
     let mut mir = tcx.mir_validated(def_id).steal();
     let source = MirSource::from_local_def_id(tcx, def_id);
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index 0568bd2f3ca..56b20047808 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -947,6 +947,19 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         shared_ccx.tcx().collect_and_partition_translation_items(LOCAL_CRATE).1;
     let codegen_units = (*codegen_units).clone();
 
+    // Force all codegen_unit queries so they are already either red or green
+    // when compile_codegen_unit accesses them. We are not able to re-execute
+    // the codegen_unit query from just the DepNode, so an unknown color would
+    // lead to having to re-execute compile_codegen_unit, possibly
+    // unnecessarily.
+    if tcx.dep_graph.is_fully_enabled() {
+        for cgu in &codegen_units {
+            tcx.codegen_unit(cgu.name().clone());
+        }
+    }
+
+    assert!(codegen_units.len() <= 1 || !tcx.sess.lto());
+
     let ongoing_translation = write::start_async_translation(
         tcx,
         time_graph.clone(),