Skip to content

Commit

Permalink
deduplicate erase_regions
Browse files Browse the repository at this point in the history
there is no need for 3 versions of the function
  • Loading branch information
arielb1 committed Sep 14, 2015
1 parent 3dc780e commit 5e4704f
Show file tree
Hide file tree
Showing 11 changed files with 133 additions and 269 deletions.
77 changes: 6 additions & 71 deletions src/librustc/middle/infer/mod.rs
Expand Up @@ -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;
Expand All @@ -525,17 +525,15 @@ 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,
infcx: &InferCtxt<'a,'tcx>,
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,
Expand All @@ -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);
Expand All @@ -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> {
Expand Down
64 changes: 55 additions & 9 deletions src/librustc/middle/traits/structural_impls.rs
Expand Up @@ -150,6 +150,52 @@ impl<'tcx, T: HasTypeFlags> HasTypeFlags for Normalized<'tcx, T> {
}
}

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> {
Expand Down Expand Up @@ -198,6 +244,15 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableBuiltinDa
}
}

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 {
Expand All @@ -216,15 +271,6 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N>
}
}

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 {
Expand Down
80 changes: 52 additions & 28 deletions src/librustc/middle/ty/fold.rs
Expand Up @@ -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};
Expand Down Expand Up @@ -588,39 +588,63 @@ impl<'a, 'tcx> TypeFolder<'tcx> for RegionReplacer<'a, 'tcx>

///////////////////////////////////////////////////////////////////////////
// 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) }
}
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/librustc/middle/ty/structural_impls.rs
Expand Up @@ -185,6 +185,13 @@ impl<'tcx> RegionEscape for ty::ProjectionTy<'tcx> {
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)
Expand Down
5 changes: 3 additions & 2 deletions src/librustc_trans/trans/callee.rs
Expand Up @@ -24,6 +24,7 @@ use session;
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;
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 = {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/trans/closure.rs
Expand Up @@ -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
Expand Down

0 comments on commit 5e4704f

Please sign in to comment.