Skip to content

Commit 5e4704f

Browse files
committed
deduplicate erase_regions
there is no need for 3 versions of the function
1 parent 3dc780e commit 5e4704f

File tree

11 files changed

+133
-269
lines changed

11 files changed

+133
-269
lines changed

src/librustc/middle/infer/mod.rs

+6-71
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T
503503
{
504504
debug!("normalize_associated_type(t={:?})", value);
505505

506-
let value = erase_regions(tcx, value);
506+
let value = tcx.erase_regions(value);
507507

508508
if !value.has_projection_types() {
509509
return value;
@@ -525,17 +525,15 @@ pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T
525525
fulfill_cx.register_predicate_obligation(&infcx, obligation);
526526
}
527527

528-
let result = drain_fulfillment_cx_or_panic(DUMMY_SP, &infcx, &mut fulfill_cx, &result);
529-
530-
result
528+
drain_fulfillment_cx_or_panic(DUMMY_SP, &infcx, &mut fulfill_cx, &result)
531529
}
532530

533531
pub fn drain_fulfillment_cx_or_panic<'a,'tcx,T>(span: Span,
534532
infcx: &InferCtxt<'a,'tcx>,
535533
fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
536534
result: &T)
537535
-> T
538-
where T : TypeFoldable<'tcx>
536+
where T : TypeFoldable<'tcx> + HasTypeFlags
539537
{
540538
match drain_fulfillment_cx(infcx, fulfill_cx, result) {
541539
Ok(v) => v,
@@ -559,7 +557,7 @@ pub fn drain_fulfillment_cx<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
559557
fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
560558
result: &T)
561559
-> Result<T,Vec<traits::FulfillmentError<'tcx>>>
562-
where T : TypeFoldable<'tcx>
560+
where T : TypeFoldable<'tcx> + HasTypeFlags
563561
{
564562
debug!("drain_fulfillment_cx(result={:?})",
565563
result);
@@ -574,71 +572,8 @@ pub fn drain_fulfillment_cx<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
574572
}
575573
}
576574

577-
// Use freshen to simultaneously replace all type variables with
578-
// their bindings and replace all regions with 'static. This is
579-
// sort of overkill because we do not expect there to be any
580-
// unbound type variables, hence no `TyFresh` types should ever be
581-
// inserted.
582-
Ok(result.fold_with(&mut infcx.freshener()))
583-
}
584-
585-
/// Returns an equivalent value with all free regions removed (note
586-
/// that late-bound regions remain, because they are important for
587-
/// subtyping, but they are anonymized and normalized as well). This
588-
/// is a stronger, caching version of `ty::fold::erase_regions`.
589-
pub fn erase_regions<'tcx,T>(cx: &ty::ctxt<'tcx>, value: &T) -> T
590-
where T : TypeFoldable<'tcx>
591-
{
592-
let value1 = value.fold_with(&mut RegionEraser(cx));
593-
debug!("erase_regions({:?}) = {:?}",
594-
value, value1);
595-
return value1;
596-
597-
struct RegionEraser<'a, 'tcx: 'a>(&'a ty::ctxt<'tcx>);
598-
599-
impl<'a, 'tcx> TypeFolder<'tcx> for RegionEraser<'a, 'tcx> {
600-
fn tcx(&self) -> &ty::ctxt<'tcx> { self.0 }
601-
602-
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
603-
match self.tcx().normalized_cache.borrow().get(&ty).cloned() {
604-
None => {}
605-
Some(u) => return u
606-
}
607-
608-
let t_norm = ty::fold::super_fold_ty(self, ty);
609-
self.tcx().normalized_cache.borrow_mut().insert(ty, t_norm);
610-
return t_norm;
611-
}
612-
613-
fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
614-
where T : TypeFoldable<'tcx>
615-
{
616-
let u = self.tcx().anonymize_late_bound_regions(t);
617-
ty::fold::super_fold_binder(self, &u)
618-
}
619-
620-
fn fold_region(&mut self, r: ty::Region) -> ty::Region {
621-
// because late-bound regions affect subtyping, we can't
622-
// erase the bound/free distinction, but we can replace
623-
// all free regions with 'static.
624-
//
625-
// Note that we *CAN* replace early-bound regions -- the
626-
// type system never "sees" those, they get substituted
627-
// away. In trans, they will always be erased to 'static
628-
// whenever a substitution occurs.
629-
match r {
630-
ty::ReLateBound(..) => r,
631-
_ => ty::ReStatic
632-
}
633-
}
634-
635-
fn fold_substs(&mut self,
636-
substs: &subst::Substs<'tcx>)
637-
-> subst::Substs<'tcx> {
638-
subst::Substs { regions: subst::ErasedRegions,
639-
types: substs.types.fold_with(self) }
640-
}
641-
}
575+
let result = infcx.resolve_type_vars_if_possible(result);
576+
Ok(infcx.tcx.erase_regions(&result))
642577
}
643578

644579
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {

src/librustc/middle/traits/structural_impls.rs

+55-9
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,52 @@ impl<'tcx, T: HasTypeFlags> HasTypeFlags for Normalized<'tcx, T> {
150150
}
151151
}
152152

153+
impl<'tcx, N: HasTypeFlags> HasTypeFlags for traits::VtableImplData<'tcx, N> {
154+
fn has_type_flags(&self, flags: TypeFlags) -> bool {
155+
self.substs.has_type_flags(flags) ||
156+
self.nested.has_type_flags(flags)
157+
}
158+
}
159+
160+
impl<'tcx, N: HasTypeFlags> HasTypeFlags for traits::VtableClosureData<'tcx, N> {
161+
fn has_type_flags(&self, flags: TypeFlags) -> bool {
162+
self.substs.has_type_flags(flags) ||
163+
self.nested.has_type_flags(flags)
164+
}
165+
}
166+
167+
impl<'tcx, N: HasTypeFlags> HasTypeFlags for traits::VtableDefaultImplData<N> {
168+
fn has_type_flags(&self, flags: TypeFlags) -> bool {
169+
self.nested.has_type_flags(flags)
170+
}
171+
}
172+
173+
impl<'tcx, N: HasTypeFlags> HasTypeFlags for traits::VtableBuiltinData<N> {
174+
fn has_type_flags(&self, flags: TypeFlags) -> bool {
175+
self.nested.has_type_flags(flags)
176+
}
177+
}
178+
179+
impl<'tcx> HasTypeFlags for traits::VtableObjectData<'tcx> {
180+
fn has_type_flags(&self, flags: TypeFlags) -> bool {
181+
self.upcast_trait_ref.has_type_flags(flags)
182+
}
183+
}
184+
185+
impl<'tcx, N: HasTypeFlags> HasTypeFlags for traits::Vtable<'tcx, N> {
186+
fn has_type_flags(&self, flags: TypeFlags) -> bool {
187+
match *self {
188+
traits::VtableImpl(ref v) => v.has_type_flags(flags),
189+
traits::VtableDefaultImpl(ref t) => t.has_type_flags(flags),
190+
traits::VtableClosure(ref d) => d.has_type_flags(flags),
191+
traits::VtableFnPointer(ref d) => d.has_type_flags(flags),
192+
traits::VtableParam(ref n) => n.has_type_flags(flags),
193+
traits::VtableBuiltin(ref d) => d.has_type_flags(flags),
194+
traits::VtableObject(ref d) => d.has_type_flags(flags)
195+
}
196+
}
197+
}
198+
153199
impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx, O>
154200
{
155201
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::Obligation<'tcx, O> {
@@ -198,6 +244,15 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableBuiltinDa
198244
}
199245
}
200246

247+
impl<'tcx> TypeFoldable<'tcx> for traits::VtableObjectData<'tcx> {
248+
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableObjectData<'tcx> {
249+
traits::VtableObjectData {
250+
upcast_trait_ref: self.upcast_trait_ref.fold_with(folder),
251+
vtable_base: self.vtable_base
252+
}
253+
}
254+
}
255+
201256
impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N> {
202257
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::Vtable<'tcx, N> {
203258
match *self {
@@ -216,15 +271,6 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N>
216271
}
217272
}
218273

219-
impl<'tcx> TypeFoldable<'tcx> for traits::VtableObjectData<'tcx> {
220-
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableObjectData<'tcx> {
221-
traits::VtableObjectData {
222-
upcast_trait_ref: self.upcast_trait_ref.fold_with(folder),
223-
vtable_base: self.vtable_base
224-
}
225-
}
226-
}
227-
228274
impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Normalized<'tcx, T> {
229275
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Normalized<'tcx, T> {
230276
Normalized {

src/librustc/middle/ty/fold.rs

+52-28
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
use middle::region;
3838
use middle::subst;
3939
use middle::ty::adjustment;
40-
use middle::ty::{self, Binder, Ty, HasTypeFlags, RegionEscape};
40+
use middle::ty::{self, Binder, Ty, RegionEscape};
4141

4242
use std::fmt;
4343
use util::nodemap::{FnvHashMap, FnvHashSet};
@@ -588,39 +588,63 @@ impl<'a, 'tcx> TypeFolder<'tcx> for RegionReplacer<'a, 'tcx>
588588

589589
///////////////////////////////////////////////////////////////////////////
590590
// Region eraser
591-
//
592-
// Replaces all free regions with 'static. Useful in contexts, such as
593-
// method probing, where precise region relationships are not
594-
// important. Note that in trans you should use
595-
// `common::erase_regions` instead.
596591

597-
pub struct RegionEraser<'a, 'tcx: 'a> {
598-
tcx: &'a ty::ctxt<'tcx>,
599-
}
592+
impl<'tcx> ty::ctxt<'tcx> {
593+
/// Returns an equivalent value with all free regions removed (note
594+
/// that late-bound regions remain, because they are important for
595+
/// subtyping, but they are anonymized and normalized as well)..
596+
pub fn erase_regions<T>(&self, value: &T) -> T
597+
where T : TypeFoldable<'tcx>
598+
{
599+
let value1 = value.fold_with(&mut RegionEraser(self));
600+
debug!("erase_regions({:?}) = {:?}",
601+
value, value1);
602+
return value1;
600603

601-
pub fn erase_regions<'tcx, T: TypeFoldable<'tcx>>(tcx: &ty::ctxt<'tcx>, t: T) -> T {
602-
let mut eraser = RegionEraser { tcx: tcx };
603-
t.fold_with(&mut eraser)
604-
}
604+
struct RegionEraser<'a, 'tcx: 'a>(&'a ty::ctxt<'tcx>);
605605

606-
impl<'a, 'tcx> TypeFolder<'tcx> for RegionEraser<'a, 'tcx> {
607-
fn tcx(&self) -> &ty::ctxt<'tcx> { self.tcx }
606+
impl<'a, 'tcx> TypeFolder<'tcx> for RegionEraser<'a, 'tcx> {
607+
fn tcx(&self) -> &ty::ctxt<'tcx> { self.0 }
608608

609-
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
610-
if !t.has_erasable_regions() {
611-
return t;
612-
}
609+
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
610+
match self.tcx().normalized_cache.borrow().get(&ty).cloned() {
611+
None => {}
612+
Some(u) => return u
613+
}
613614

614-
super_fold_ty(self, t)
615-
}
615+
let t_norm = ty::fold::super_fold_ty(self, ty);
616+
self.tcx().normalized_cache.borrow_mut().insert(ty, t_norm);
617+
return t_norm;
618+
}
616619

617-
fn fold_region(&mut self, r: ty::Region) -> ty::Region {
618-
// because whether or not a region is bound affects subtyping,
619-
// we can't erase the bound/free distinction, but we can
620-
// replace all free regions with 'static
621-
match r {
622-
ty::ReLateBound(..) | ty::ReEarlyBound(..) => r,
623-
_ => ty::ReStatic
620+
fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
621+
where T : TypeFoldable<'tcx>
622+
{
623+
let u = self.tcx().anonymize_late_bound_regions(t);
624+
ty::fold::super_fold_binder(self, &u)
625+
}
626+
627+
fn fold_region(&mut self, r: ty::Region) -> ty::Region {
628+
// because late-bound regions affect subtyping, we can't
629+
// erase the bound/free distinction, but we can replace
630+
// all free regions with 'static.
631+
//
632+
// Note that we *CAN* replace early-bound regions -- the
633+
// type system never "sees" those, they get substituted
634+
// away. In trans, they will always be erased to 'static
635+
// whenever a substitution occurs.
636+
match r {
637+
ty::ReLateBound(..) => r,
638+
_ => ty::ReStatic
639+
}
640+
}
641+
642+
fn fold_substs(&mut self,
643+
substs: &subst::Substs<'tcx>)
644+
-> subst::Substs<'tcx> {
645+
subst::Substs { regions: subst::ErasedRegions,
646+
types: substs.types.fold_with(self) }
647+
}
624648
}
625649
}
626650
}

src/librustc/middle/ty/structural_impls.rs

+7
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,13 @@ impl<'tcx> RegionEscape for ty::ProjectionTy<'tcx> {
185185
self.trait_ref.has_regions_escaping_depth(depth)
186186
}
187187
}
188+
189+
impl HasTypeFlags for () {
190+
fn has_type_flags(&self, _flags: TypeFlags) -> bool {
191+
false
192+
}
193+
}
194+
188195
impl<'tcx,T:HasTypeFlags> HasTypeFlags for Vec<T> {
189196
fn has_type_flags(&self, flags: TypeFlags) -> bool {
190197
self[..].has_type_flags(flags)

src/librustc_trans/trans/callee.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use session;
2424
use llvm::{self, ValueRef, get_params};
2525
use middle::def;
2626
use middle::def_id::{DefId, LOCAL_CRATE};
27+
use middle::infer::normalize_associated_type;
2728
use middle::subst;
2829
use middle::subst::{Subst, Substs};
2930
use rustc::front::map as hir_map;
@@ -260,7 +261,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
260261
let tcx = ccx.tcx();
261262

262263
// Normalize the type for better caching.
263-
let bare_fn_ty = common::erase_regions(tcx, &bare_fn_ty);
264+
let bare_fn_ty = tcx.erase_regions(&bare_fn_ty);
264265

265266
// If this is an impl of `Fn` or `FnMut` trait, the receiver is `&self`.
266267
let is_by_ref = match closure_kind {
@@ -521,7 +522,7 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
521522

522523
// Type scheme of the function item (may have type params)
523524
let fn_type_scheme = tcx.lookup_item_type(def_id);
524-
let fn_type = monomorphize::normalize_associated_type(tcx, &fn_type_scheme.ty);
525+
let fn_type = normalize_associated_type(tcx, &fn_type_scheme.ty);
525526

526527
// Find the actual function pointer.
527528
let mut val = {

src/librustc_trans/trans/closure.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ pub fn get_or_create_closure_declaration<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
135135
-> ValueRef {
136136
// Normalize type so differences in regions and typedefs don't cause
137137
// duplicate declarations
138-
let substs = erase_regions(ccx.tcx(), substs);
138+
let substs = ccx.tcx().erase_regions(substs);
139139
let mono_id = MonoId {
140140
def: closure_id,
141141
params: &substs.func_substs.types

0 commit comments

Comments
 (0)