提交 8a19b234 编写于 作者: B bors

Auto merge of #28413 - arielb1:deduplication, r=eddyb

clean a few things discovered during my split_ty work

r? @EddyB 
......@@ -503,7 +503,7 @@ pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T
{
debug!("normalize_associated_type(t={:?})", value);
let value = erase_regions(tcx, value);
let value = tcx.erase_regions(value);
if !value.has_projection_types() {
return value;
......@@ -525,9 +525,7 @@ pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T
fulfill_cx.register_predicate_obligation(&infcx, obligation);
}
let result = drain_fulfillment_cx_or_panic(DUMMY_SP, &infcx, &mut fulfill_cx, &result);
result
drain_fulfillment_cx_or_panic(DUMMY_SP, &infcx, &mut fulfill_cx, &result)
}
pub fn drain_fulfillment_cx_or_panic<'a,'tcx,T>(span: Span,
......@@ -535,7 +533,7 @@ pub fn drain_fulfillment_cx_or_panic<'a,'tcx,T>(span: Span,
fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
result: &T)
-> T
where T : TypeFoldable<'tcx>
where T : TypeFoldable<'tcx> + HasTypeFlags
{
match drain_fulfillment_cx(infcx, fulfill_cx, result) {
Ok(v) => v,
......@@ -559,7 +557,7 @@ pub fn drain_fulfillment_cx<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
result: &T)
-> Result<T,Vec<traits::FulfillmentError<'tcx>>>
where T : TypeFoldable<'tcx>
where T : TypeFoldable<'tcx> + HasTypeFlags
{
debug!("drain_fulfillment_cx(result={:?})",
result);
......@@ -574,71 +572,8 @@ pub fn drain_fulfillment_cx<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
}
}
// Use freshen to simultaneously replace all type variables with
// their bindings and replace all regions with 'static. This is
// sort of overkill because we do not expect there to be any
// unbound type variables, hence no `TyFresh` types should ever be
// inserted.
Ok(result.fold_with(&mut infcx.freshener()))
}
/// Returns an equivalent value with all free regions removed (note
/// that late-bound regions remain, because they are important for
/// subtyping, but they are anonymized and normalized as well). This
/// is a stronger, caching version of `ty::fold::erase_regions`.
pub fn erase_regions<'tcx,T>(cx: &ty::ctxt<'tcx>, value: &T) -> T
where T : TypeFoldable<'tcx>
{
let value1 = value.fold_with(&mut RegionEraser(cx));
debug!("erase_regions({:?}) = {:?}",
value, value1);
return value1;
struct RegionEraser<'a, 'tcx: 'a>(&'a ty::ctxt<'tcx>);
impl<'a, 'tcx> TypeFolder<'tcx> for RegionEraser<'a, 'tcx> {
fn tcx(&self) -> &ty::ctxt<'tcx> { self.0 }
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
match self.tcx().normalized_cache.borrow().get(&ty).cloned() {
None => {}
Some(u) => return u
}
let t_norm = ty::fold::super_fold_ty(self, ty);
self.tcx().normalized_cache.borrow_mut().insert(ty, t_norm);
return t_norm;
}
fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
where T : TypeFoldable<'tcx>
{
let u = self.tcx().anonymize_late_bound_regions(t);
ty::fold::super_fold_binder(self, &u)
}
fn fold_region(&mut self, r: ty::Region) -> ty::Region {
// because late-bound regions affect subtyping, we can't
// erase the bound/free distinction, but we can replace
// all free regions with 'static.
//
// Note that we *CAN* replace early-bound regions -- the
// type system never "sees" those, they get substituted
// away. In trans, they will always be erased to 'static
// whenever a substitution occurs.
match r {
ty::ReLateBound(..) => r,
_ => ty::ReStatic
}
}
fn fold_substs(&mut self,
substs: &subst::Substs<'tcx>)
-> subst::Substs<'tcx> {
subst::Substs { regions: subst::ErasedRegions,
types: substs.types.fold_with(self) }
}
}
let result = infcx.resolve_type_vars_if_possible(result);
Ok(infcx.tcx.erase_regions(&result))
}
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
......
......@@ -150,6 +150,52 @@ fn has_type_flags(&self, flags: TypeFlags) -> bool {
}
}
impl<'tcx, N: HasTypeFlags> HasTypeFlags for traits::VtableImplData<'tcx, N> {
fn has_type_flags(&self, flags: TypeFlags) -> bool {
self.substs.has_type_flags(flags) ||
self.nested.has_type_flags(flags)
}
}
impl<'tcx, N: HasTypeFlags> HasTypeFlags for traits::VtableClosureData<'tcx, N> {
fn has_type_flags(&self, flags: TypeFlags) -> bool {
self.substs.has_type_flags(flags) ||
self.nested.has_type_flags(flags)
}
}
impl<'tcx, N: HasTypeFlags> HasTypeFlags for traits::VtableDefaultImplData<N> {
fn has_type_flags(&self, flags: TypeFlags) -> bool {
self.nested.has_type_flags(flags)
}
}
impl<'tcx, N: HasTypeFlags> HasTypeFlags for traits::VtableBuiltinData<N> {
fn has_type_flags(&self, flags: TypeFlags) -> bool {
self.nested.has_type_flags(flags)
}
}
impl<'tcx> HasTypeFlags for traits::VtableObjectData<'tcx> {
fn has_type_flags(&self, flags: TypeFlags) -> bool {
self.upcast_trait_ref.has_type_flags(flags)
}
}
impl<'tcx, N: HasTypeFlags> HasTypeFlags for traits::Vtable<'tcx, N> {
fn has_type_flags(&self, flags: TypeFlags) -> bool {
match *self {
traits::VtableImpl(ref v) => v.has_type_flags(flags),
traits::VtableDefaultImpl(ref t) => t.has_type_flags(flags),
traits::VtableClosure(ref d) => d.has_type_flags(flags),
traits::VtableFnPointer(ref d) => d.has_type_flags(flags),
traits::VtableParam(ref n) => n.has_type_flags(flags),
traits::VtableBuiltin(ref d) => d.has_type_flags(flags),
traits::VtableObject(ref d) => d.has_type_flags(flags)
}
}
}
impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx, O>
{
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::Obligation<'tcx, O> {
......@@ -198,6 +244,15 @@ fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableBuiltin
}
}
impl<'tcx> TypeFoldable<'tcx> for traits::VtableObjectData<'tcx> {
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableObjectData<'tcx> {
traits::VtableObjectData {
upcast_trait_ref: self.upcast_trait_ref.fold_with(folder),
vtable_base: self.vtable_base
}
}
}
impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N> {
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::Vtable<'tcx, N> {
match *self {
......@@ -216,15 +271,6 @@ fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::Vtable<'tcx,
}
}
impl<'tcx> TypeFoldable<'tcx> for traits::VtableObjectData<'tcx> {
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableObjectData<'tcx> {
traits::VtableObjectData {
upcast_trait_ref: self.upcast_trait_ref.fold_with(folder),
vtable_base: self.vtable_base
}
}
}
impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Normalized<'tcx, T> {
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Normalized<'tcx, T> {
Normalized {
......
......@@ -37,7 +37,7 @@
use middle::region;
use middle::subst;
use middle::ty::adjustment;
use middle::ty::{self, Binder, Ty, HasTypeFlags, RegionEscape};
use middle::ty::{self, Binder, Ty, RegionEscape};
use std::fmt;
use util::nodemap::{FnvHashMap, FnvHashSet};
......@@ -588,39 +588,63 @@ fn fold_region(&mut self, r: ty::Region) -> ty::Region {
///////////////////////////////////////////////////////////////////////////
// Region eraser
//
// Replaces all free regions with 'static. Useful in contexts, such as
// method probing, where precise region relationships are not
// important. Note that in trans you should use
// `common::erase_regions` instead.
pub struct RegionEraser<'a, 'tcx: 'a> {
tcx: &'a ty::ctxt<'tcx>,
}
impl<'tcx> ty::ctxt<'tcx> {
/// Returns an equivalent value with all free regions removed (note
/// that late-bound regions remain, because they are important for
/// subtyping, but they are anonymized and normalized as well)..
pub fn erase_regions<T>(&self, value: &T) -> T
where T : TypeFoldable<'tcx>
{
let value1 = value.fold_with(&mut RegionEraser(self));
debug!("erase_regions({:?}) = {:?}",
value, value1);
return value1;
pub fn erase_regions<'tcx, T: TypeFoldable<'tcx>>(tcx: &ty::ctxt<'tcx>, t: T) -> T {
let mut eraser = RegionEraser { tcx: tcx };
t.fold_with(&mut eraser)
}
struct RegionEraser<'a, 'tcx: 'a>(&'a ty::ctxt<'tcx>);
impl<'a, 'tcx> TypeFolder<'tcx> for RegionEraser<'a, 'tcx> {
fn tcx(&self) -> &ty::ctxt<'tcx> { self.tcx }
impl<'a, 'tcx> TypeFolder<'tcx> for RegionEraser<'a, 'tcx> {
fn tcx(&self) -> &ty::ctxt<'tcx> { self.0 }
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
if !t.has_erasable_regions() {
return t;
}
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
match self.tcx().normalized_cache.borrow().get(&ty).cloned() {
None => {}
Some(u) => return u
}
super_fold_ty(self, t)
}
let t_norm = ty::fold::super_fold_ty(self, ty);
self.tcx().normalized_cache.borrow_mut().insert(ty, t_norm);
return t_norm;
}
fn fold_region(&mut self, r: ty::Region) -> ty::Region {
// because whether or not a region is bound affects subtyping,
// we can't erase the bound/free distinction, but we can
// replace all free regions with 'static
match r {
ty::ReLateBound(..) | ty::ReEarlyBound(..) => r,
_ => ty::ReStatic
fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
where T : TypeFoldable<'tcx>
{
let u = self.tcx().anonymize_late_bound_regions(t);
ty::fold::super_fold_binder(self, &u)
}
fn fold_region(&mut self, r: ty::Region) -> ty::Region {
// because late-bound regions affect subtyping, we can't
// erase the bound/free distinction, but we can replace
// all free regions with 'static.
//
// Note that we *CAN* replace early-bound regions -- the
// type system never "sees" those, they get substituted
// away. In trans, they will always be erased to 'static
// whenever a substitution occurs.
match r {
ty::ReLateBound(..) => r,
_ => ty::ReStatic
}
}
fn fold_substs(&mut self,
substs: &subst::Substs<'tcx>)
-> subst::Substs<'tcx> {
subst::Substs { regions: subst::ErasedRegions,
types: substs.types.fold_with(self) }
}
}
}
}
......
......@@ -979,18 +979,6 @@ pub fn walk_tys(&self) -> IntoIter<Ty<'tcx>> {
vec.into_iter()
}
pub fn has_escaping_regions(&self) -> bool {
match *self {
Predicate::Trait(ref trait_ref) => trait_ref.has_escaping_regions(),
Predicate::Equate(ref p) => p.has_escaping_regions(),
Predicate::RegionOutlives(ref p) => p.has_escaping_regions(),
Predicate::TypeOutlives(ref p) => p.has_escaping_regions(),
Predicate::Projection(ref p) => p.has_escaping_regions(),
Predicate::WellFormed(p) => p.has_escaping_regions(),
Predicate::ObjectSafe(_trait_def_id) => false,
}
}
pub fn to_opt_poly_trait_ref(&self) -> Option<PolyTraitRef<'tcx>> {
match *self {
Predicate::Trait(ref t) => {
......@@ -1037,10 +1025,6 @@ pub fn empty() -> InstantiatedPredicates<'tcx> {
InstantiatedPredicates { predicates: VecPerParamSpace::empty() }
}
pub fn has_escaping_regions(&self) -> bool {
self.predicates.any(|p| p.has_escaping_regions())
}
pub fn is_empty(&self) -> bool {
self.predicates.is_empty()
}
......
......@@ -45,6 +45,12 @@ fn has_regions_escaping_depth(&self, depth: u32) -> bool {
}
}
impl<'tcx> RegionEscape for ty::InstantiatedPredicates<'tcx> {
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
self.predicates.has_regions_escaping_depth(depth)
}
}
impl<'tcx> RegionEscape for subst::Substs<'tcx> {
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
self.types.has_regions_escaping_depth(depth) ||
......@@ -179,6 +185,13 @@ fn has_regions_escaping_depth(&self, depth: u32) -> bool {
self.trait_ref.has_regions_escaping_depth(depth)
}
}
impl HasTypeFlags for () {
fn has_type_flags(&self, _flags: TypeFlags) -> bool {
false
}
}
impl<'tcx,T:HasTypeFlags> HasTypeFlags for Vec<T> {
fn has_type_flags(&self, flags: TypeFlags) -> bool {
self[..].has_type_flags(flags)
......
......@@ -24,6 +24,7 @@
use llvm::{self, ValueRef, get_params};
use middle::def;
use middle::def_id::{DefId, LOCAL_CRATE};
use middle::infer::normalize_associated_type;
use middle::subst;
use middle::subst::{Subst, Substs};
use rustc::front::map as hir_map;
......@@ -260,7 +261,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
let tcx = ccx.tcx();
// Normalize the type for better caching.
let bare_fn_ty = common::erase_regions(tcx, &bare_fn_ty);
let bare_fn_ty = tcx.erase_regions(&bare_fn_ty);
// If this is an impl of `Fn` or `FnMut` trait, the receiver is `&self`.
let is_by_ref = match closure_kind {
......@@ -521,7 +522,7 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
// Type scheme of the function item (may have type params)
let fn_type_scheme = tcx.lookup_item_type(def_id);
let fn_type = monomorphize::normalize_associated_type(tcx, &fn_type_scheme.ty);
let fn_type = normalize_associated_type(tcx, &fn_type_scheme.ty);
// Find the actual function pointer.
let mut val = {
......
......@@ -135,7 +135,7 @@ pub fn get_or_create_closure_declaration<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-> ValueRef {
// Normalize type so differences in regions and typedefs don't cause
// duplicate declarations
let substs = erase_regions(ccx.tcx(), substs);
let substs = ccx.tcx().erase_regions(substs);
let mono_id = MonoId {
def: closure_id,
params: &substs.func_substs.types
......
......@@ -47,7 +47,6 @@
use libc::{c_uint, c_char};
use std::ffi::CString;
use std::cell::{Cell, RefCell};
use std::result::Result as StdResult;
use std::vec::Vec;
use syntax::ast;
use syntax::codemap::{DUMMY_SP, Span};
......@@ -56,65 +55,6 @@
pub use trans::context::CrateContext;
/// Returns an equivalent value with all free regions removed (note
/// that late-bound regions remain, because they are important for
/// subtyping, but they are anonymized and normalized as well). This
/// is a stronger, caching version of `ty::fold::erase_regions`.
pub fn erase_regions<'tcx,T>(cx: &ty::ctxt<'tcx>, value: &T) -> T
where T : TypeFoldable<'tcx>
{
let value1 = value.fold_with(&mut RegionEraser(cx));
debug!("erase_regions({:?}) = {:?}",
value, value1);
return value1;
struct RegionEraser<'a, 'tcx: 'a>(&'a ty::ctxt<'tcx>);
impl<'a, 'tcx> TypeFolder<'tcx> for RegionEraser<'a, 'tcx> {
fn tcx(&self) -> &ty::ctxt<'tcx> { self.0 }
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
match self.tcx().normalized_cache.borrow().get(&ty).cloned() {
None => {}
Some(u) => return u
}
let t_norm = ty::fold::super_fold_ty(self, ty);
self.tcx().normalized_cache.borrow_mut().insert(ty, t_norm);
return t_norm;
}
fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
where T : TypeFoldable<'tcx>
{
let u = self.tcx().anonymize_late_bound_regions(t);
ty::fold::super_fold_binder(self, &u)
}
fn fold_region(&mut self, r: ty::Region) -> ty::Region {
// because late-bound regions affect subtyping, we can't
// erase the bound/free distinction, but we can replace
// all free regions with 'static.
//
// Note that we *CAN* replace early-bound regions -- the
// type system never "sees" those, they get substituted
// away. In trans, they will always be erased to 'static
// whenever a substitution occurs.
match r {
ty::ReLateBound(..) => r,
_ => ty::ReStatic
}
}
fn fold_substs(&mut self,
substs: &subst::Substs<'tcx>)
-> subst::Substs<'tcx> {
subst::Substs { regions: subst::ErasedRegions,
types: substs.types.fold_with(self) }
}
}
}
/// Is the type's representation size known at compile time?
pub fn type_is_sized<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
ty.is_sized(&tcx.empty_parameter_environment(), DUMMY_SP)
......@@ -1043,7 +983,7 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
let tcx = ccx.tcx();
// Remove any references to regions; this helps improve caching.
let trait_ref = erase_regions(tcx, &trait_ref);
let trait_ref = tcx.erase_regions(&trait_ref);
// First check the cache.
match ccx.trait_cache().borrow().get(&trait_ref) {
......@@ -1098,8 +1038,8 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
let vtable = selection.map(|predicate| {
fulfill_cx.register_predicate_obligation(&infcx, predicate);
});
let vtable = erase_regions(tcx,
&drain_fulfillment_cx_or_panic(span, &infcx, &mut fulfill_cx, &vtable)
let vtable = infer::drain_fulfillment_cx_or_panic(
span, &infcx, &mut fulfill_cx, &vtable
);
info!("Cache miss: {:?} => {:?}", trait_ref, vtable);
......@@ -1134,59 +1074,8 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
let obligation = traits::Obligation::new(cause.clone(), predicate);
fulfill_cx.register_predicate_obligation(&infcx, obligation);
}
drain_fulfillment_cx(&infcx, &mut fulfill_cx, &()).is_ok()
}
pub fn drain_fulfillment_cx_or_panic<'a,'tcx,T>(span: Span,
infcx: &infer::InferCtxt<'a,'tcx>,
fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
result: &T)
-> T
where T : TypeFoldable<'tcx>
{
match drain_fulfillment_cx(infcx, fulfill_cx, result) {
Ok(v) => v,
Err(errors) => {
infcx.tcx.sess.span_bug(
span,
&format!("Encountered errors `{:?}` fulfilling during trans",
errors));
}
}
}
/// Finishes processes any obligations that remain in the fulfillment
/// context, and then "freshens" and returns `result`. This is
/// primarily used during normalization and other cases where
/// processing the obligations in `fulfill_cx` may cause type
/// inference variables that appear in `result` to be unified, and
/// hence we need to process those obligations to get the complete
/// picture of the type.
pub fn drain_fulfillment_cx<'a,'tcx,T>(infcx: &infer::InferCtxt<'a,'tcx>,
fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
result: &T)
-> StdResult<T,Vec<traits::FulfillmentError<'tcx>>>
where T : TypeFoldable<'tcx>
{
debug!("drain_fulfillment_cx(result={:?})",
result);
// In principle, we only need to do this so long as `result`
// contains unbound type parameters. It could be a slight
// optimization to stop iterating early.
match fulfill_cx.select_all_or_error(infcx) {
Ok(()) => { }
Err(errors) => {
return Err(errors);
}
}
// Use freshen to simultaneously replace all type variables with
// their bindings and replace all regions with 'static. This is
// sort of overkill because we do not expect there to be any
// unbound type variables, hence no `TyFresh` types should ever be
// inserted.
Ok(result.fold_with(&mut infcx.freshener()))
infer::drain_fulfillment_cx(&infcx, &mut fulfill_cx, &()).is_ok()
}
// Key used to lookup values supplied for type parameters in an expr.
......
......@@ -27,6 +27,7 @@
use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArray,
DIDescriptor, FlagPrototyped};
use middle::def_id::DefId;
use middle::infer::normalize_associated_type;
use middle::subst::{self, Substs};
use rustc_front;
use rustc_front::hir;
......@@ -463,7 +464,7 @@ fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-> DIArray
{
let self_type = param_substs.self_ty();
let self_type = monomorphize::normalize_associated_type(cx.tcx(), &self_type);
let self_type = normalize_associated_type(cx.tcx(), &self_type);
// Only true for static default methods:
let has_self_type = self_type.is_some();
......
......@@ -26,7 +26,6 @@
use trans::attributes;
use trans::base;
use trans::context::CrateContext;
use trans::monomorphize;
use trans::type_::Type;
use trans::type_of;
......@@ -104,7 +103,7 @@ pub fn declare_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
fn_type: ty::Ty<'tcx>) -> ValueRef {
debug!("declare_rust_fn(name={:?}, fn_type={:?})", name,
fn_type);
let fn_type = monomorphize::normalize_associated_type(ccx.tcx(), &fn_type);
let fn_type = infer::normalize_associated_type(ccx.tcx(), &fn_type);
debug!("declare_rust_fn (after normalised associated types) fn_type={:?}",
fn_type);
......
......@@ -13,10 +13,9 @@
use llvm::ValueRef;
use llvm;
use middle::def_id::DefId;
use middle::infer;
use middle::infer::normalize_associated_type;
use middle::subst;
use middle::subst::{Subst, Substs};
use middle::traits;
use middle::ty::fold::{TypeFolder, TypeFoldable};
use trans::attributes;
use trans::base::{trans_enum_variant, push_ctxt, get_item_val};
......@@ -33,7 +32,6 @@
use syntax::abi;
use syntax::ast;
use syntax::codemap::DUMMY_SP;
use std::hash::{Hasher, Hash, SipHasher};
pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
......@@ -300,39 +298,3 @@ pub fn field_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
{
normalize_associated_type(tcx, &f.ty(tcx, param_substs))
}
/// Removes associated types, if any. Since this during
/// monomorphization, we know that only concrete types are involved,
/// and hence we can be sure that all associated types will be
/// completely normalized away.
pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T
where T : TypeFoldable<'tcx> + HasTypeFlags
{
debug!("normalize_associated_type(t={:?})", value);
let value = erase_regions(tcx, value);
if !value.has_projection_types() {
return value;
}
// FIXME(#20304) -- cache
let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables);
let mut selcx = traits::SelectionContext::new(&infcx);
let cause = traits::ObligationCause::dummy();
let traits::Normalized { value: result, obligations } =
traits::normalize(&mut selcx, cause, &value);
debug!("normalize_associated_type: result={:?} obligations={:?}",
result,
obligations);
let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
for obligation in obligations {
fulfill_cx.register_predicate_obligation(&infcx, obligation);
}
let result = drain_fulfillment_cx_or_panic(DUMMY_SP, &infcx, &mut fulfill_cx, &result);
result
}
......@@ -325,7 +325,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
// Rust types are defined as the same LLVM types. If we don't do
// this then, e.g. `Option<{myfield: bool}>` would be a different
// type than `Option<myrec>`.
let t_norm = erase_regions(cx.tcx(), &t);
let t_norm = cx.tcx().erase_regions(&t);
if t != t_norm {
let llty = in_memory_type_of(cx, t_norm);
......
......@@ -17,7 +17,7 @@
use middle::privacy::{AllPublic, DependsOn, LastPrivate, LastMod};
use middle::subst;
use middle::traits;
use middle::ty::{self, ToPredicate, ToPolyTraitRef, TraitRef};
use middle::ty::{self, RegionEscape, ToPredicate, ToPolyTraitRef, TraitRef};
use middle::ty::adjustment::{AdjustDerefRef, AutoDerefRef, AutoPtr};
use middle::infer;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册