Skip to content

misc. ty cleanup #28413

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 15, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 6 additions & 71 deletions src/librustc/middle/infer/mod.rs
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
16 changes: 0 additions & 16 deletions src/librustc/middle/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -979,18 +979,6 @@ impl<'tcx> Predicate<'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) => {
Expand Down Expand Up @@ -1037,10 +1025,6 @@ impl<'tcx> 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()
}
Expand Down
13 changes: 13 additions & 0 deletions src/librustc/middle/ty/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ impl<'tcx> RegionEscape for ty::ExistentialBounds<'tcx> {
}
}

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) ||
Expand Down Expand Up @@ -179,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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Loading