diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 6993ef3768a79..53a6b688a0faa 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -90,6 +90,11 @@ macro_rules! is_input_attr { ($attr:ident) => (false); } +macro_rules! is_eval_always_attr { + (eval_always) => (true); + ($attr:ident) => (false); +} + macro_rules! contains_anon_attr { ($($attr:ident),*) => ({$(is_anon_attr!($attr) | )* false}); } @@ -98,6 +103,10 @@ macro_rules! contains_input_attr { ($($attr:ident),*) => ({$(is_input_attr!($attr) | )* false}); } +macro_rules! contains_eval_always_attr { + ($($attr:ident),*) => ({$(is_eval_always_attr!($attr) | )* false}); +} + macro_rules! define_dep_nodes { (<$tcx:tt> $( @@ -160,6 +169,15 @@ macro_rules! define_dep_nodes { } } + #[inline] + pub fn is_eval_always(&self) -> bool { + match *self { + $( + DepKind :: $variant => { contains_eval_always_attr!($($attr), *) } + )* + } + } + #[allow(unreachable_code)] #[inline] pub fn has_params(&self) -> bool { @@ -447,10 +465,10 @@ define_dep_nodes!( <'tcx> // Represents different phases in the compiler. [] RegionScopeTree(DefId), - [] Coherence, - [] CoherenceInherentImplOverlapCheck, + [eval_always] Coherence, + [eval_always] CoherenceInherentImplOverlapCheck, [] CoherenceCheckTrait(DefId), - [] PrivacyAccessLevels(CrateNum), + [eval_always] PrivacyAccessLevels(CrateNum), // Represents the MIR for a fn; also used as the task node for // things read/modify that MIR. @@ -467,7 +485,7 @@ define_dep_nodes!( <'tcx> [] Reachability, [] MirKeys, - [] CrateVariances, + [eval_always] CrateVariances, // Nodes representing bits of computed IR in the tcx. Each shared // table in the tcx (or elsewhere) maps to one of these @@ -497,7 +515,7 @@ define_dep_nodes!( <'tcx> [] DtorckConstraint(DefId), [] AdtDestructor(DefId), [] AssociatedItemDefIds(DefId), - [] InherentImpls(DefId), + [eval_always] InherentImpls(DefId), [] TypeckBodiesKrate, [] TypeckTables(DefId), [] HasTypeckTables(DefId), @@ -566,7 +584,7 @@ define_dep_nodes!( <'tcx> [] IsCompilerBuiltins(CrateNum), [] HasGlobalAllocator(CrateNum), [] ExternCrate(DefId), - [] LintLevels, + [eval_always] LintLevels, [] Specializes { impl1: DefId, impl2: DefId }, [input] InScopeTraits(DefIndex), [] ModuleExports(DefId), @@ -625,7 +643,7 @@ define_dep_nodes!( <'tcx> [] StabilityIndex, [] AllCrateNums, [] ExportedSymbols(CrateNum), - [] CollectAndPartitionTranslationItems, + [eval_always] CollectAndPartitionTranslationItems, [] ExportName(DefId), [] ContainsExternIndicator(DefId), [] IsTranslatedFunction(DefId), diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 0fdb6dc068dd9..ec709b301eb73 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -199,11 +199,27 @@ impl DepGraph { -> (R, DepNodeIndex) where C: DepGraphSafe + StableHashingContextProvider<ContextType=HCX>, R: HashStable<HCX>, + { + self.with_task_impl(key, cx, arg, task, + |data, key| data.borrow_mut().push_task(key), + |data, key| data.borrow_mut().pop_task(key)) + } + + fn with_task_impl<C, A, R, HCX>(&self, + key: DepNode, + cx: C, + arg: A, + task: fn(C, A) -> R, + push: fn(&RefCell<CurrentDepGraph>, DepNode), + pop: fn(&RefCell<CurrentDepGraph>, DepNode) -> DepNodeIndex) + -> (R, DepNodeIndex) + where C: DepGraphSafe + StableHashingContextProvider<ContextType=HCX>, + R: HashStable<HCX>, { if let Some(ref data) = self.data { debug_assert!(!data.colors.borrow().contains_key(&key)); - data.current.borrow_mut().push_task(key); + push(&data.current, key); if cfg!(debug_assertions) { profq_msg(ProfileQueriesMsg::TaskBegin(key.clone())) }; @@ -220,7 +236,7 @@ impl DepGraph { profq_msg(ProfileQueriesMsg::TaskEnd) }; - let dep_node_index = data.current.borrow_mut().pop_task(key); + let dep_node_index = pop(&data.current, key); let mut stable_hasher = StableHasher::new(); result.hash_stable(&mut hcx, &mut stable_hasher); @@ -290,6 +306,22 @@ impl DepGraph { } } + /// Execute something within an "eval-always" task which is a task + // that runs whenever anything changes. + pub fn with_eval_always_task<C, A, R, HCX>(&self, + key: DepNode, + cx: C, + arg: A, + task: fn(C, A) -> R) + -> (R, DepNodeIndex) + where C: DepGraphSafe + StableHashingContextProvider<ContextType=HCX>, + R: HashStable<HCX>, + { + self.with_task_impl(key, cx, arg, task, + |data, key| data.borrow_mut().push_eval_always_task(key), + |data, key| data.borrow_mut().pop_eval_always_task(key)) + } + #[inline] pub fn read(&self, v: DepNode) { if let Some(ref data) = self.data { @@ -788,6 +820,24 @@ impl CurrentDepGraph { } } + fn push_eval_always_task(&mut self, key: DepNode) { + self.task_stack.push(OpenTask::EvalAlways { node: key }); + } + + fn pop_eval_always_task(&mut self, key: DepNode) -> DepNodeIndex { + let popped_node = self.task_stack.pop().unwrap(); + + if let OpenTask::EvalAlways { + node, + } = popped_node { + debug_assert_eq!(node, key); + let krate_idx = self.node_to_node_index[&DepNode::new_no_params(DepKind::Krate)]; + self.alloc_node(node, vec![krate_idx]) + } else { + bug!("pop_eval_always_task() - Expected eval always task to be popped"); + } + } + fn read_index(&mut self, source: DepNodeIndex) { match self.task_stack.last_mut() { Some(&mut OpenTask::Regular { @@ -818,7 +868,8 @@ impl CurrentDepGraph { reads.push(source); } } - Some(&mut OpenTask::Ignore) | None => { + Some(&mut OpenTask::Ignore) | + Some(&mut OpenTask::EvalAlways { .. }) | None => { // ignore } } @@ -851,4 +902,7 @@ enum OpenTask { read_set: FxHashSet<DepNodeIndex>, }, Ignore, + EvalAlways { + node: DepNode, + }, } diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 5f93c3de336cc..e8f1ee10d6dbf 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -433,10 +433,17 @@ macro_rules! define_maps { 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) + if dep_node.kind.is_eval_always() { + tcx.dep_graph.with_eval_always_task(dep_node, + tcx, + key, + Self::compute_result) + } else { + tcx.dep_graph.with_task(dep_node, + tcx, + key, + Self::compute_result) + } }) })?; profq_msg!(tcx, ProfileQueriesMsg::ProviderEnd); diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index e7a1dd6b043b1..8abf7d3d09cd8 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -1563,9 +1563,7 @@ pub fn provide(providers: &mut Providers) { } pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Rc<AccessLevels> { - tcx.dep_graph.with_ignore(|| { // FIXME - tcx.privacy_access_levels(LOCAL_CRATE) - }) + tcx.privacy_access_levels(LOCAL_CRATE) } fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,