From 27c4ff69675ad216bbf492d6c9d9bf4c41dcd0de Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 29 Aug 2017 09:25:25 -0700 Subject: [PATCH] rustc: Remove `specailization_cache` in favor of a query This commit removes the `specialization_cache` field of `TyCtxt` by moving it to a dedicated query, which it turned out was already quite easily structured to do so! --- src/librustc/dep_graph/dep_node.rs | 1 + src/librustc/traits/mod.rs | 4 +++- src/librustc/traits/select.rs | 3 +-- src/librustc/traits/specialize/mod.rs | 18 ++++++------------ .../traits/specialize/specialization_graph.rs | 6 +++--- src/librustc/ty/context.rs | 3 --- src/librustc/ty/maps.rs | 12 ++++++++++++ 7 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 9a80db472db..5114b94571d 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -527,6 +527,7 @@ define_dep_nodes!( <'tcx> [] HasGlobalAllocator(DefId), [] ExternCrate(DefId), [] LintLevels, + [] Specializes { impl1: DefId, impl2: DefId }, ); trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug { diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 228c9761756..019f0a70911 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -38,7 +38,7 @@ pub use self::project::{ProjectionCache, ProjectionCacheSnapshot, Reveal}; pub use self::object_safety::ObjectSafetyViolation; pub use self::object_safety::MethodViolationCode; pub use self::select::{EvaluationCache, SelectionContext, SelectionCache}; -pub use self::specialize::{OverlapError, specialization_graph, specializes, translate_substs}; +pub use self::specialize::{OverlapError, specialization_graph, translate_substs}; pub use self::specialize::{SpecializesCache, find_associated_item}; pub use self::util::elaborate_predicates; pub use self::util::supertraits; @@ -831,6 +831,7 @@ pub fn provide(providers: &mut ty::maps::Providers) { *providers = ty::maps::Providers { is_object_safe: object_safety::is_object_safe_provider, specialization_graph_of: specialize::specialization_graph_provider, + specializes: specialize::specializes, ..*providers }; } @@ -839,6 +840,7 @@ pub fn provide_extern(providers: &mut ty::maps::Providers) { *providers = ty::maps::Providers { is_object_safe: object_safety::is_object_safe_provider, specialization_graph_of: specialize::specialization_graph_provider, + specializes: specialize::specializes, ..*providers }; } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 44b8af3c1df..8856176dcb0 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -36,7 +36,6 @@ use infer; use infer::{InferCtxt, InferOk, TypeFreshener}; use ty::subst::{Kind, Subst, Substs}; use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; -use traits; use ty::fast_reject; use ty::relate::TypeRelation; use middle::lang_items; @@ -1927,7 +1926,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { if other.evaluation == EvaluatedToOk { if let ImplCandidate(victim_def) = victim.candidate { let tcx = self.tcx().global_tcx(); - return traits::specializes(tcx, other_def, victim_def) || + return tcx.specializes((other_def, victim_def)) || tcx.impls_are_allowed_to_overlap(other_def, victim_def); } } diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 7c916e162a4..2dd6ca4b5a9 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -150,15 +150,12 @@ pub fn find_associated_item<'a, 'tcx>( /// Specialization is determined by the sets of types to which the impls apply; /// impl1 specializes impl2 if it applies to a subset of the types impl2 applies /// to. -pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - impl1_def_id: DefId, - impl2_def_id: DefId) -> bool { +pub(super) fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + (impl1_def_id, impl2_def_id): (DefId, DefId)) + -> bool +{ debug!("specializes({:?}, {:?})", impl1_def_id, impl2_def_id); - if let Some(r) = tcx.specializes_cache.borrow().check(impl1_def_id, impl2_def_id) { - return r; - } - // The feature gate should prevent introducing new specializations, but not // taking advantage of upstream ones. if !tcx.sess.features.borrow().specialization && @@ -188,7 +185,7 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap(); // Create a infcx, taking the predicates of impl1 as assumptions: - let result = tcx.infer_ctxt().enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { // Normalize the trait reference. The WF rules ought to ensure // that this always succeeds. let impl1_trait_ref = @@ -204,10 +201,7 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Attempt to prove that impl2 applies, given all of the above. fulfill_implication(&infcx, penv, impl1_trait_ref, impl2_def_id).is_ok() - }); - - tcx.specializes_cache.borrow_mut().insert(impl1_def_id, impl2_def_id, result); - result + }) } /// Attempt to fulfill all obligations of `target_impl` after unification with diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index 8b31cb599e4..5242accceab 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::{OverlapError, specializes}; +use super::OverlapError; use hir::def_id::DefId; use traits; @@ -118,8 +118,8 @@ impl<'a, 'gcx, 'tcx> Children { return Ok((false, false)); } - let le = specializes(tcx, impl_def_id, possible_sibling); - let ge = specializes(tcx, possible_sibling, impl_def_id); + let le = tcx.specializes((impl_def_id, possible_sibling)); + let ge = tcx.specializes((possible_sibling, impl_def_id)); if le == ge { // overlap, but no specialization; error out diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 1fe53882c70..1255a9c1f1e 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -808,8 +808,6 @@ pub struct GlobalCtxt<'tcx> { pub sess: &'tcx Session, - pub specializes_cache: RefCell, - pub trans_trait_caches: traits::trans::TransTraitCaches<'tcx>, pub dep_graph: DepGraph, @@ -1072,7 +1070,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { tls::enter_global(GlobalCtxt { sess: s, trans_trait_caches: traits::trans::TransTraitCaches::new(dep_graph.clone()), - specializes_cache: RefCell::new(traits::SpecializesCache::new()), global_arenas: arenas, global_interners: interners, dep_graph: dep_graph.clone(), diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 03e093c5a50..c7303c749a4 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -540,6 +540,12 @@ impl<'tcx> QueryDescription for queries::lint_levels<'tcx> { } } +impl<'tcx> QueryDescription for queries::specializes<'tcx> { + fn describe(_tcx: TyCtxt, _: (DefId, DefId)) -> String { + format!("computing whether impls specialize one another") + } +} + // If enabled, send a message to the profile-queries thread macro_rules! profq_msg { ($tcx:expr, $msg:expr) => { @@ -1108,6 +1114,8 @@ define_maps! { <'tcx> [] extern_crate: ExternCrate(DefId) -> Rc>, [] lint_levels: lint_levels(CrateNum) -> Rc, + + [] specializes: specializes_node((DefId, DefId)) -> bool, } fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> { @@ -1183,3 +1191,7 @@ fn layout_dep_node<'tcx>(_: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor<' fn lint_levels<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { DepConstructor::LintLevels } + +fn specializes_node<'tcx>((a, b): (DefId, DefId)) -> DepConstructor<'tcx> { + DepConstructor::Specializes { impl1: a, impl2: b } +}