parent
f5e036a290
commit
31f4b57002
10 changed files with 226 additions and 82 deletions
|
@ -65,7 +65,7 @@ use hir::map::DefPathHash;
|
||||||
use hir::{HirId, ItemLocalId};
|
use hir::{HirId, ItemLocalId};
|
||||||
|
|
||||||
use ich::Fingerprint;
|
use ich::Fingerprint;
|
||||||
use ty::{TyCtxt, Instance, InstanceDef, ParamEnvAnd, Ty};
|
use ty::{TyCtxt, Instance, InstanceDef, ParamEnv, ParamEnvAnd, PolyTraitRef, Ty};
|
||||||
use ty::subst::Substs;
|
use ty::subst::Substs;
|
||||||
use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
|
use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
|
||||||
use ich::StableHashingContext;
|
use ich::StableHashingContext;
|
||||||
|
@ -486,6 +486,7 @@ define_dep_nodes!( <'tcx>
|
||||||
[] InstanceSymbolName { instance: Instance<'tcx> },
|
[] InstanceSymbolName { instance: Instance<'tcx> },
|
||||||
[] SpecializationGraph(DefId),
|
[] SpecializationGraph(DefId),
|
||||||
[] ObjectSafety(DefId),
|
[] ObjectSafety(DefId),
|
||||||
|
[] FulfillObligation { param_env: ParamEnv<'tcx>, trait_ref: PolyTraitRef<'tcx> },
|
||||||
|
|
||||||
[] IsCopy { param_env: ParamEnvAnd<'tcx, Ty<'tcx>> },
|
[] IsCopy { param_env: ParamEnvAnd<'tcx, Ty<'tcx>> },
|
||||||
[] IsSized { param_env: ParamEnvAnd<'tcx, Ty<'tcx>> },
|
[] IsSized { param_env: ParamEnvAnd<'tcx, Ty<'tcx>> },
|
||||||
|
|
|
@ -841,3 +841,129 @@ impl_stable_hash_for!(struct ::util::common::ErrorReported {});
|
||||||
impl_stable_hash_for!(tuple_struct ::middle::reachable::ReachableSet {
|
impl_stable_hash_for!(tuple_struct ::middle::reachable::ReachableSet {
|
||||||
reachable_set
|
reachable_set
|
||||||
});
|
});
|
||||||
|
|
||||||
|
impl<'gcx, N> HashStable<StableHashingContext<'gcx>>
|
||||||
|
for traits::Vtable<'gcx, N> where N: HashStable<StableHashingContext<'gcx>> {
|
||||||
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
|
hcx: &mut StableHashingContext<'gcx>,
|
||||||
|
hasher: &mut StableHasher<W>) {
|
||||||
|
use traits::Vtable::*;
|
||||||
|
|
||||||
|
mem::discriminant(self).hash_stable(hcx, hasher);
|
||||||
|
|
||||||
|
match self {
|
||||||
|
&VtableImpl(ref table_impl) => table_impl.hash_stable(hcx, hasher),
|
||||||
|
&VtableDefaultImpl(ref table_def_impl) => table_def_impl.hash_stable(hcx, hasher),
|
||||||
|
&VtableParam(ref table_param) => table_param.hash_stable(hcx, hasher),
|
||||||
|
&VtableObject(ref table_obj) => table_obj.hash_stable(hcx, hasher),
|
||||||
|
&VtableBuiltin(ref table_builtin) => table_builtin.hash_stable(hcx, hasher),
|
||||||
|
&VtableClosure(ref table_closure) => table_closure.hash_stable(hcx, hasher),
|
||||||
|
&VtableFnPointer(ref table_fn_pointer) => table_fn_pointer.hash_stable(hcx, hasher),
|
||||||
|
&VtableGenerator(ref table_generator) => table_generator.hash_stable(hcx, hasher),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'gcx, N> HashStable<StableHashingContext<'gcx>>
|
||||||
|
for traits::VtableImplData<'gcx, N> where N: HashStable<StableHashingContext<'gcx>> {
|
||||||
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
|
hcx: &mut StableHashingContext<'gcx>,
|
||||||
|
hasher: &mut StableHasher<W>) {
|
||||||
|
let traits::VtableImplData {
|
||||||
|
impl_def_id,
|
||||||
|
substs,
|
||||||
|
ref nested,
|
||||||
|
} = *self;
|
||||||
|
impl_def_id.hash_stable(hcx, hasher);
|
||||||
|
substs.hash_stable(hcx, hasher);
|
||||||
|
nested.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'gcx, N> HashStable<StableHashingContext<'gcx>>
|
||||||
|
for traits::VtableDefaultImplData<N> where N: HashStable<StableHashingContext<'gcx>> {
|
||||||
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
|
hcx: &mut StableHashingContext<'gcx>,
|
||||||
|
hasher: &mut StableHasher<W>) {
|
||||||
|
let traits::VtableDefaultImplData {
|
||||||
|
trait_def_id,
|
||||||
|
ref nested,
|
||||||
|
} = *self;
|
||||||
|
trait_def_id.hash_stable(hcx, hasher);
|
||||||
|
nested.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'gcx, N> HashStable<StableHashingContext<'gcx>>
|
||||||
|
for traits::VtableObjectData<'gcx, N> where N: HashStable<StableHashingContext<'gcx>> {
|
||||||
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
|
hcx: &mut StableHashingContext<'gcx>,
|
||||||
|
hasher: &mut StableHasher<W>) {
|
||||||
|
let traits::VtableObjectData {
|
||||||
|
upcast_trait_ref,
|
||||||
|
vtable_base,
|
||||||
|
ref nested,
|
||||||
|
} = *self;
|
||||||
|
upcast_trait_ref.hash_stable(hcx, hasher);
|
||||||
|
vtable_base.hash_stable(hcx, hasher);
|
||||||
|
nested.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'gcx, N> HashStable<StableHashingContext<'gcx>>
|
||||||
|
for traits::VtableBuiltinData<N> where N: HashStable<StableHashingContext<'gcx>> {
|
||||||
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
|
hcx: &mut StableHashingContext<'gcx>,
|
||||||
|
hasher: &mut StableHasher<W>) {
|
||||||
|
let traits::VtableBuiltinData {
|
||||||
|
ref nested,
|
||||||
|
} = *self;
|
||||||
|
nested.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'gcx, N> HashStable<StableHashingContext<'gcx>>
|
||||||
|
for traits::VtableClosureData<'gcx, N> where N: HashStable<StableHashingContext<'gcx>> {
|
||||||
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
|
hcx: &mut StableHashingContext<'gcx>,
|
||||||
|
hasher: &mut StableHasher<W>) {
|
||||||
|
let traits::VtableClosureData {
|
||||||
|
closure_def_id,
|
||||||
|
substs,
|
||||||
|
ref nested,
|
||||||
|
} = *self;
|
||||||
|
closure_def_id.hash_stable(hcx, hasher);
|
||||||
|
substs.hash_stable(hcx, hasher);
|
||||||
|
nested.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'gcx, N> HashStable<StableHashingContext<'gcx>>
|
||||||
|
for traits::VtableFnPointerData<'gcx, N> where N: HashStable<StableHashingContext<'gcx>> {
|
||||||
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
|
hcx: &mut StableHashingContext<'gcx>,
|
||||||
|
hasher: &mut StableHasher<W>) {
|
||||||
|
let traits::VtableFnPointerData {
|
||||||
|
fn_ty,
|
||||||
|
ref nested,
|
||||||
|
} = *self;
|
||||||
|
fn_ty.hash_stable(hcx, hasher);
|
||||||
|
nested.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'gcx, N> HashStable<StableHashingContext<'gcx>>
|
||||||
|
for traits::VtableGeneratorData<'gcx, N> where N: HashStable<StableHashingContext<'gcx>> {
|
||||||
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
|
hcx: &mut StableHashingContext<'gcx>,
|
||||||
|
hasher: &mut StableHasher<W>) {
|
||||||
|
let traits::VtableGeneratorData {
|
||||||
|
closure_def_id,
|
||||||
|
substs,
|
||||||
|
ref nested,
|
||||||
|
} = *self;
|
||||||
|
closure_def_id.hash_stable(hcx, hasher);
|
||||||
|
substs.hash_stable(hcx, hasher);
|
||||||
|
nested.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -835,6 +835,7 @@ pub fn provide(providers: &mut ty::maps::Providers) {
|
||||||
is_object_safe: object_safety::is_object_safe_provider,
|
is_object_safe: object_safety::is_object_safe_provider,
|
||||||
specialization_graph_of: specialize::specialization_graph_provider,
|
specialization_graph_of: specialize::specialization_graph_provider,
|
||||||
specializes: specialize::specializes,
|
specializes: specialize::specializes,
|
||||||
|
trans_fulfill_obligation: trans::trans_fulfill_obligation,
|
||||||
..*providers
|
..*providers
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -844,6 +845,7 @@ pub fn provide_extern(providers: &mut ty::maps::Providers) {
|
||||||
is_object_safe: object_safety::is_object_safe_provider,
|
is_object_safe: object_safety::is_object_safe_provider,
|
||||||
specialization_graph_of: specialize::specialization_graph_provider,
|
specialization_graph_of: specialize::specialization_graph_provider,
|
||||||
specializes: specialize::specializes,
|
specializes: specialize::specializes,
|
||||||
|
trans_fulfill_obligation: trans::trans_fulfill_obligation,
|
||||||
..*providers
|
..*providers
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,85 +17,77 @@ use dep_graph::{DepGraph, DepKind, DepTrackingMap, DepTrackingMapConfig};
|
||||||
use infer::TransNormalize;
|
use infer::TransNormalize;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use syntax::ast;
|
use syntax_pos::DUMMY_SP;
|
||||||
use syntax_pos::Span;
|
|
||||||
use traits::{FulfillmentContext, Obligation, ObligationCause, SelectionContext, Vtable};
|
use traits::{FulfillmentContext, Obligation, ObligationCause, SelectionContext, Vtable};
|
||||||
use ty::{self, Ty, TyCtxt};
|
use ty::{self, Ty, TyCtxt};
|
||||||
use ty::subst::{Subst, Substs};
|
use ty::subst::{Subst, Substs};
|
||||||
use ty::fold::{TypeFoldable, TypeFolder};
|
use ty::fold::{TypeFoldable, TypeFolder};
|
||||||
use util::common::MemoizationMap;
|
use util::common::MemoizationMap;
|
||||||
|
|
||||||
|
/// Attempts to resolve an obligation to a vtable.. The result is
|
||||||
|
/// a shallow vtable resolution -- meaning that we do not
|
||||||
|
/// (necessarily) resolve all nested obligations on the impl. Note
|
||||||
|
/// that type check should guarantee to us that all nested
|
||||||
|
/// obligations *could be* resolved if we wanted to.
|
||||||
|
/// Assumes that this is run after the entire crate has been successfully type-checked.
|
||||||
|
pub fn trans_fulfill_obligation<'a, 'tcx>(ty: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
(param_env, trait_ref):
|
||||||
|
(ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>))
|
||||||
|
-> Vtable<'tcx, ()>
|
||||||
|
{
|
||||||
|
// Remove any references to regions; this helps improve caching.
|
||||||
|
let trait_ref = ty.erase_regions(&trait_ref);
|
||||||
|
|
||||||
|
debug!("trans::fulfill_obligation(trait_ref={:?}, def_id={:?})",
|
||||||
|
(param_env, trait_ref), trait_ref.def_id());
|
||||||
|
|
||||||
|
// Do the initial selection for the obligation. This yields the
|
||||||
|
// shallow result we are looking for -- that is, what specific impl.
|
||||||
|
ty.infer_ctxt().enter(|infcx| {
|
||||||
|
let mut selcx = SelectionContext::new(&infcx);
|
||||||
|
|
||||||
|
let obligation_cause = ObligationCause::dummy();
|
||||||
|
let obligation = Obligation::new(obligation_cause,
|
||||||
|
param_env,
|
||||||
|
trait_ref.to_poly_trait_predicate());
|
||||||
|
|
||||||
|
let selection = match selcx.select(&obligation) {
|
||||||
|
Ok(Some(selection)) => selection,
|
||||||
|
Ok(None) => {
|
||||||
|
// Ambiguity can happen when monomorphizing during trans
|
||||||
|
// expands to some humongo type that never occurred
|
||||||
|
// statically -- this humongo type can then overflow,
|
||||||
|
// leading to an ambiguous result. So report this as an
|
||||||
|
// overflow bug, since I believe this is the only case
|
||||||
|
// where ambiguity can result.
|
||||||
|
bug!("Encountered ambiguity selecting `{:?}` during trans, \
|
||||||
|
presuming due to overflow",
|
||||||
|
trait_ref)
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
bug!("Encountered error `{:?}` selecting `{:?}` during trans",
|
||||||
|
e, trait_ref)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
debug!("fulfill_obligation: selection={:?}", selection);
|
||||||
|
|
||||||
|
// Currently, we use a fulfillment context to completely resolve
|
||||||
|
// all nested obligations. This is because they can inform the
|
||||||
|
// inference of the impl's type parameters.
|
||||||
|
let mut fulfill_cx = FulfillmentContext::new();
|
||||||
|
let vtable = selection.map(|predicate| {
|
||||||
|
debug!("fulfill_obligation: register_predicate_obligation {:?}", predicate);
|
||||||
|
fulfill_cx.register_predicate_obligation(&infcx, predicate);
|
||||||
|
});
|
||||||
|
let vtable = infcx.drain_fulfillment_cx_or_panic(DUMMY_SP, &mut fulfill_cx, &vtable);
|
||||||
|
|
||||||
|
info!("Cache miss: {:?} => {:?}", trait_ref, vtable);
|
||||||
|
vtable
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
||||||
/// Attempts to resolve an obligation to a vtable.. The result is
|
|
||||||
/// a shallow vtable resolution -- meaning that we do not
|
|
||||||
/// (necessarily) resolve all nested obligations on the impl. Note
|
|
||||||
/// that type check should guarantee to us that all nested
|
|
||||||
/// obligations *could be* resolved if we wanted to.
|
|
||||||
/// Assumes that this is run after the entire crate has been successfully type-checked.
|
|
||||||
pub fn trans_fulfill_obligation(self,
|
|
||||||
span: Span,
|
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
|
||||||
trait_ref: ty::PolyTraitRef<'tcx>)
|
|
||||||
-> Vtable<'tcx, ()>
|
|
||||||
{
|
|
||||||
// Remove any references to regions; this helps improve caching.
|
|
||||||
let trait_ref = self.erase_regions(&trait_ref);
|
|
||||||
|
|
||||||
self.trans_trait_caches.trait_cache.memoize((param_env, trait_ref), || {
|
|
||||||
debug!("trans::fulfill_obligation(trait_ref={:?}, def_id={:?})",
|
|
||||||
(param_env, trait_ref), trait_ref.def_id());
|
|
||||||
|
|
||||||
// Do the initial selection for the obligation. This yields the
|
|
||||||
// shallow result we are looking for -- that is, what specific impl.
|
|
||||||
self.infer_ctxt().enter(|infcx| {
|
|
||||||
let mut selcx = SelectionContext::new(&infcx);
|
|
||||||
|
|
||||||
let obligation_cause = ObligationCause::misc(span,
|
|
||||||
ast::DUMMY_NODE_ID);
|
|
||||||
let obligation = Obligation::new(obligation_cause,
|
|
||||||
param_env,
|
|
||||||
trait_ref.to_poly_trait_predicate());
|
|
||||||
|
|
||||||
let selection = match selcx.select(&obligation) {
|
|
||||||
Ok(Some(selection)) => selection,
|
|
||||||
Ok(None) => {
|
|
||||||
// Ambiguity can happen when monomorphizing during trans
|
|
||||||
// expands to some humongo type that never occurred
|
|
||||||
// statically -- this humongo type can then overflow,
|
|
||||||
// leading to an ambiguous result. So report this as an
|
|
||||||
// overflow bug, since I believe this is the only case
|
|
||||||
// where ambiguity can result.
|
|
||||||
debug!("Encountered ambiguity selecting `{:?}` during trans, \
|
|
||||||
presuming due to overflow",
|
|
||||||
trait_ref);
|
|
||||||
self.sess.span_fatal(span,
|
|
||||||
"reached the recursion limit during monomorphization \
|
|
||||||
(selection ambiguity)");
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
span_bug!(span, "Encountered error `{:?}` selecting `{:?}` during trans",
|
|
||||||
e, trait_ref)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
debug!("fulfill_obligation: selection={:?}", selection);
|
|
||||||
|
|
||||||
// Currently, we use a fulfillment context to completely resolve
|
|
||||||
// all nested obligations. This is because they can inform the
|
|
||||||
// inference of the impl's type parameters.
|
|
||||||
let mut fulfill_cx = FulfillmentContext::new();
|
|
||||||
let vtable = selection.map(|predicate| {
|
|
||||||
debug!("fulfill_obligation: register_predicate_obligation {:?}", predicate);
|
|
||||||
fulfill_cx.register_predicate_obligation(&infcx, predicate);
|
|
||||||
});
|
|
||||||
let vtable = infcx.drain_fulfillment_cx_or_panic(span, &mut fulfill_cx, &vtable);
|
|
||||||
|
|
||||||
info!("Cache miss: {:?} => {:?}", trait_ref, vtable);
|
|
||||||
vtable
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Monomorphizes a type from the AST by first applying the in-scope
|
/// Monomorphizes a type from the AST by first applying the in-scope
|
||||||
/// substitutions and then normalizing any associated types.
|
/// substitutions and then normalizing any associated types.
|
||||||
pub fn trans_apply_param_substs<T>(self,
|
pub fn trans_apply_param_substs<T>(self,
|
||||||
|
@ -149,14 +141,12 @@ impl<'a, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizer<'a, 'gcx> {
|
||||||
/// Specializes caches used in trans -- in particular, they assume all
|
/// Specializes caches used in trans -- in particular, they assume all
|
||||||
/// types are fully monomorphized and that free regions can be erased.
|
/// types are fully monomorphized and that free regions can be erased.
|
||||||
pub struct TransTraitCaches<'tcx> {
|
pub struct TransTraitCaches<'tcx> {
|
||||||
trait_cache: RefCell<DepTrackingMap<TraitSelectionCache<'tcx>>>,
|
|
||||||
project_cache: RefCell<DepTrackingMap<ProjectionCache<'tcx>>>,
|
project_cache: RefCell<DepTrackingMap<ProjectionCache<'tcx>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TransTraitCaches<'tcx> {
|
impl<'tcx> TransTraitCaches<'tcx> {
|
||||||
pub fn new(graph: DepGraph) -> Self {
|
pub fn new(graph: DepGraph) -> Self {
|
||||||
TransTraitCaches {
|
TransTraitCaches {
|
||||||
trait_cache: RefCell::new(DepTrackingMap::new(graph.clone())),
|
|
||||||
project_cache: RefCell::new(DepTrackingMap::new(graph)),
|
project_cache: RefCell::new(DepTrackingMap::new(graph)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ use ty::{self, Ty, TypeFoldable, Substs, TyCtxt};
|
||||||
use ty::subst::{Kind, Subst};
|
use ty::subst::{Kind, Subst};
|
||||||
use traits;
|
use traits;
|
||||||
use syntax::abi::Abi;
|
use syntax::abi::Abi;
|
||||||
use syntax::codemap::DUMMY_SP;
|
|
||||||
use util::ppaux;
|
use util::ppaux;
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -212,7 +211,7 @@ fn resolve_associated_item<'a, 'tcx>(
|
||||||
def_id, trait_id, rcvr_substs);
|
def_id, trait_id, rcvr_substs);
|
||||||
|
|
||||||
let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
|
let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
|
||||||
let vtbl = tcx.trans_fulfill_obligation(DUMMY_SP, param_env, ty::Binder(trait_ref));
|
let vtbl = tcx.trans_fulfill_obligation((param_env, ty::Binder(trait_ref)));
|
||||||
|
|
||||||
// Now that we know which impl is being used, we can dispatch to
|
// Now that we know which impl is being used, we can dispatch to
|
||||||
// the actual function:
|
// the actual function:
|
||||||
|
|
|
@ -221,6 +221,12 @@ impl<'tcx> QueryDescription for queries::is_mir_available<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> QueryDescription for queries::trans_fulfill_obligation<'tcx> {
|
||||||
|
fn describe(tcx: TyCtxt, key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)) -> String {
|
||||||
|
format!("checking if `{}` fulfills its obligations", tcx.item_path_str(key.1.def_id()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> QueryDescription for queries::trait_impls_of<'tcx> {
|
impl<'tcx> QueryDescription for queries::trait_impls_of<'tcx> {
|
||||||
fn describe(tcx: TyCtxt, def_id: DefId) -> String {
|
fn describe(tcx: TyCtxt, def_id: DefId) -> String {
|
||||||
format!("trait impls of `{}`", tcx.item_path_str(def_id))
|
format!("trait impls of `{}`", tcx.item_path_str(def_id))
|
||||||
|
|
|
@ -134,6 +134,15 @@ impl Key for (MirSuite, MirPassIndex, DefId) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) {
|
||||||
|
fn map_crate(&self) -> CrateNum {
|
||||||
|
self.1.def_id().krate
|
||||||
|
}
|
||||||
|
fn default_span(&self, tcx: TyCtxt) -> Span {
|
||||||
|
tcx.def_span(self.1.def_id())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> Key for Ty<'tcx> {
|
impl<'tcx> Key for Ty<'tcx> {
|
||||||
fn map_crate(&self) -> CrateNum {
|
fn map_crate(&self) -> CrateNum {
|
||||||
LOCAL_CRATE
|
LOCAL_CRATE
|
||||||
|
|
|
@ -30,6 +30,7 @@ use middle::trans::{CodegenUnit, Stats};
|
||||||
use mir;
|
use mir;
|
||||||
use session::CompileResult;
|
use session::CompileResult;
|
||||||
use session::config::OutputFilenames;
|
use session::config::OutputFilenames;
|
||||||
|
use traits::Vtable;
|
||||||
use traits::specialization_graph;
|
use traits::specialization_graph;
|
||||||
use ty::{self, CrateInherentImpls, Ty, TyCtxt};
|
use ty::{self, CrateInherentImpls, Ty, TyCtxt};
|
||||||
use ty::layout::{Layout, LayoutError};
|
use ty::layout::{Layout, LayoutError};
|
||||||
|
@ -228,6 +229,8 @@ define_maps! { <'tcx>
|
||||||
[] fn const_is_rvalue_promotable_to_static: ConstIsRvaluePromotableToStatic(DefId) -> bool,
|
[] fn const_is_rvalue_promotable_to_static: ConstIsRvaluePromotableToStatic(DefId) -> bool,
|
||||||
[] fn is_mir_available: IsMirAvailable(DefId) -> bool,
|
[] fn is_mir_available: IsMirAvailable(DefId) -> bool,
|
||||||
|
|
||||||
|
[] fn trans_fulfill_obligation: fulfill_obligation_dep_node(
|
||||||
|
(ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)) -> Vtable<'tcx, ()>,
|
||||||
[] fn trait_impls_of: TraitImpls(DefId) -> Rc<ty::trait_def::TraitImpls>,
|
[] fn trait_impls_of: TraitImpls(DefId) -> Rc<ty::trait_def::TraitImpls>,
|
||||||
[] fn specialization_graph_of: SpecializationGraph(DefId) -> Rc<specialization_graph::Graph>,
|
[] fn specialization_graph_of: SpecializationGraph(DefId) -> Rc<specialization_graph::Graph>,
|
||||||
[] fn is_object_safe: ObjectSafety(DefId) -> bool,
|
[] fn is_object_safe: ObjectSafety(DefId) -> bool,
|
||||||
|
@ -347,6 +350,14 @@ fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fulfill_obligation_dep_node<'tcx>((param_env, trait_ref):
|
||||||
|
(ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)) -> DepConstructor<'tcx> {
|
||||||
|
DepConstructor::FulfillObligation {
|
||||||
|
param_env,
|
||||||
|
trait_ref
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn coherent_trait_dep_node<'tcx>((_, def_id): (CrateNum, DefId)) -> DepConstructor<'tcx> {
|
fn coherent_trait_dep_node<'tcx>((_, def_id): (CrateNum, DefId)) -> DepConstructor<'tcx> {
|
||||||
DepConstructor::CoherenceCheckTrait(def_id)
|
DepConstructor::CoherenceCheckTrait(def_id)
|
||||||
}
|
}
|
||||||
|
|
|
@ -705,6 +705,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
|
||||||
DepKind::TypeParamPredicates |
|
DepKind::TypeParamPredicates |
|
||||||
DepKind::CodegenUnit |
|
DepKind::CodegenUnit |
|
||||||
DepKind::CompileCodegenUnit |
|
DepKind::CompileCodegenUnit |
|
||||||
|
DepKind::FulfillObligation |
|
||||||
|
|
||||||
// These are just odd
|
// These are just odd
|
||||||
DepKind::Null |
|
DepKind::Null |
|
||||||
|
|
|
@ -15,8 +15,6 @@ use rustc::ty::adjustment::CustomCoerceUnsized;
|
||||||
use rustc::ty::subst::{Kind, Subst, Substs};
|
use rustc::ty::subst::{Kind, Subst, Substs};
|
||||||
use rustc::ty::{self, Ty, TyCtxt};
|
use rustc::ty::{self, Ty, TyCtxt};
|
||||||
|
|
||||||
use syntax::codemap::DUMMY_SP;
|
|
||||||
|
|
||||||
pub use rustc::ty::Instance;
|
pub use rustc::ty::Instance;
|
||||||
|
|
||||||
fn fn_once_adapter_instance<'a, 'tcx>(
|
fn fn_once_adapter_instance<'a, 'tcx>(
|
||||||
|
@ -110,13 +108,14 @@ pub fn custom_coerce_unsize_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
source_ty: Ty<'tcx>,
|
source_ty: Ty<'tcx>,
|
||||||
target_ty: Ty<'tcx>)
|
target_ty: Ty<'tcx>)
|
||||||
-> CustomCoerceUnsized {
|
-> CustomCoerceUnsized {
|
||||||
|
let def_id = tcx.lang_items().coerce_unsized_trait().unwrap();
|
||||||
|
|
||||||
let trait_ref = ty::Binder(ty::TraitRef {
|
let trait_ref = ty::Binder(ty::TraitRef {
|
||||||
def_id: tcx.lang_items().coerce_unsized_trait().unwrap(),
|
def_id: def_id,
|
||||||
substs: tcx.mk_substs_trait(source_ty, &[target_ty])
|
substs: tcx.mk_substs_trait(source_ty, &[target_ty])
|
||||||
});
|
});
|
||||||
|
|
||||||
match tcx.trans_fulfill_obligation(
|
match tcx.trans_fulfill_obligation( (ty::ParamEnv::empty(traits::Reveal::All), trait_ref)) {
|
||||||
DUMMY_SP, ty::ParamEnv::empty(traits::Reveal::All), trait_ref) {
|
|
||||||
traits::VtableImpl(traits::VtableImplData { impl_def_id, .. }) => {
|
traits::VtableImpl(traits::VtableImplData { impl_def_id, .. }) => {
|
||||||
tcx.coerce_unsized_info(impl_def_id).custom_kind.unwrap()
|
tcx.coerce_unsized_info(impl_def_id).custom_kind.unwrap()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue