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!
This commit is contained in:
parent
faf477a8c2
commit
27c4ff6967
@ -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 {
|
||||
|
@ -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
|
||||
};
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -808,8 +808,6 @@ pub struct GlobalCtxt<'tcx> {
|
||||
|
||||
pub sess: &'tcx Session,
|
||||
|
||||
pub specializes_cache: RefCell<traits::SpecializesCache>,
|
||||
|
||||
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(),
|
||||
|
@ -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<Option<ExternCrate>>,
|
||||
|
||||
[] lint_levels: lint_levels(CrateNum) -> Rc<lint::LintLevelMap>,
|
||||
|
||||
[] 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 }
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user