diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 08acc22114b2..ae3157e81a0a 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -609,6 +609,7 @@ define_dep_nodes!( <'tcx> [] PostorderCnums, [] HasCloneClosures(CrateNum), [] HasCopyClosures(CrateNum), + [] EraseRegionsTy { ty: Ty<'tcx> }, [] Freevars(DefId), [] MaybeUnusedTraitImport(DefId), diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 3ba7dc68f9b0..3d5e8ea583cc 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -892,9 +892,6 @@ pub struct GlobalCtxt<'tcx> { // Internal cache for metadata decoding. No need to track deps on this. pub rcache: RefCell>>, - // FIXME dep tracking -- should be harmless enough - pub normalized_cache: RefCell, Ty<'tcx>>>, - /// Caches the results of trait selection. This cache is used /// for things that do not have to do with the parameters in scope. pub selection_cache: traits::SelectionCache<'tcx>, @@ -1172,7 +1169,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { maps: maps::Maps::new(providers), mir_passes, rcache: RefCell::new(FxHashMap()), - normalized_cache: RefCell::new(FxHashMap()), selection_cache: traits::SelectionCache::new(), evaluation_cache: traits::EvaluationCache::new(), crate_name: Symbol::intern(crate_name), diff --git a/src/librustc/ty/erase_regions.rs b/src/librustc/ty/erase_regions.rs new file mode 100644 index 000000000000..4f8fca67949b --- /dev/null +++ b/src/librustc/ty/erase_regions.rs @@ -0,0 +1,79 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use ty::{self, Ty, TyCtxt}; +use ty::fold::{TypeFolder, TypeFoldable}; + +pub(super) fn provide(providers: &mut ty::maps::Providers) { + *providers = ty::maps::Providers { + erase_regions_ty, + ..*providers + }; +} + +fn erase_regions_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + // NB: use `super_fold_with` here. If we used `fold_with`, it + // could invoke the `erase_regions_ty` query recursively. + ty.super_fold_with(&mut RegionEraserVisitor { tcx }) +} + +impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, '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(self, value: &T) -> T + where T : TypeFoldable<'tcx> + { + let value1 = value.fold_with(&mut RegionEraserVisitor { tcx: self }); + debug!("erase_regions({:?}) = {:?}", value, value1); + value1 + } +} + +struct RegionEraserVisitor<'a, 'gcx: 'tcx, 'tcx: 'a> { + tcx: TyCtxt<'a, 'gcx, 'tcx>, +} + +impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionEraserVisitor<'a, 'gcx, 'tcx> { + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { + self.tcx + } + + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + if let Some(ty_lifted) = self.tcx.lift_to_global(&ty) { + self.tcx.erase_regions_ty(ty_lifted) + } else { + ty.super_fold_with(self) + } + } + + fn fold_binder(&mut self, t: &ty::Binder) -> ty::Binder + where T : TypeFoldable<'tcx> + { + let u = self.tcx.anonymize_late_bound_regions(t); + u.super_fold_with(self) + } + + fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + // because late-bound regions affect subtyping, we can't + // erase the bound/free distinction, but we can replace + // all free regions with 'erased. + // + // 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 'erased + // whenever a substitution occurs. + match *r { + ty::ReLateBound(..) => r, + _ => self.tcx.types.re_erased + } + } +} + diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 543e8f3e2f04..edd4329fa419 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -444,67 +444,6 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionReplacer<'a, 'gcx, 'tcx> { } } -/////////////////////////////////////////////////////////////////////////// -// Region eraser - -impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, '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(self, value: &T) -> T - where T : TypeFoldable<'tcx> - { - let value1 = value.fold_with(&mut RegionEraser(self)); - debug!("erase_regions({:?}) = {:?}", - value, value1); - return value1; - - struct RegionEraser<'a, 'gcx: 'a+'tcx, 'tcx: 'a>(TyCtxt<'a, 'gcx, 'tcx>); - - impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionEraser<'a, 'gcx, 'tcx> { - fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.0 } - - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if let Some(u) = self.tcx().normalized_cache.borrow().get(&ty).cloned() { - return u; - } - - // FIXME(eddyb) should local contexts have a cache too? - if let Some(ty_lifted) = self.tcx().lift_to_global(&ty) { - let tcx = self.tcx().global_tcx(); - let t_norm = ty_lifted.super_fold_with(&mut RegionEraser(tcx)); - tcx.normalized_cache.borrow_mut().insert(ty_lifted, t_norm); - t_norm - } else { - ty.super_fold_with(self) - } - } - - fn fold_binder(&mut self, t: &ty::Binder) -> ty::Binder - where T : TypeFoldable<'tcx> - { - let u = self.tcx().anonymize_late_bound_regions(t); - u.super_fold_with(self) - } - - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - // because late-bound regions affect subtyping, we can't - // erase the bound/free distinction, but we can replace - // all free regions with 'erased. - // - // 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 'erased - // whenever a substitution occurs. - match *r { - ty::ReLateBound(..) => r, - _ => self.tcx().types.re_erased - } - } - } - } -} - /////////////////////////////////////////////////////////////////////////// // Region shifter // diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index 2279dff1335f..8f8cda0e0f1d 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -75,6 +75,12 @@ impl<'tcx> QueryDescription for queries::super_predicates_of<'tcx> { } } +impl<'tcx> QueryDescription for queries::erase_regions_ty<'tcx> { + fn describe(_tcx: TyCtxt, ty: Ty<'tcx>) -> String { + format!("erasing regions from `{:?}`", ty) + } +} + impl<'tcx> QueryDescription for queries::type_param_predicates<'tcx> { fn describe(tcx: TyCtxt, (_, def_id): (DefId, DefId)) -> String { let id = tcx.hir.as_local_node_id(def_id).unwrap(); diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 07807429bfb3..95192dc5baea 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -341,12 +341,21 @@ define_maps! { <'tcx> [] fn has_copy_closures: HasCopyClosures(CrateNum) -> bool, [] fn has_clone_closures: HasCloneClosures(CrateNum) -> bool, + + // Erases regions from `ty` to yield a new type. + // Normally you would just use `tcx.erase_regions(&value)`, + // however, which uses this query as a kind of cache. + [] fn erase_regions_ty: erase_regions_ty(Ty<'tcx>) -> Ty<'tcx>, } ////////////////////////////////////////////////////////////////////// // These functions are little shims used to find the dep-node for a // given query when there is not a *direct* mapping: +fn erase_regions_ty<'tcx>(ty: Ty<'tcx>) -> DepConstructor<'tcx> { + DepConstructor::EraseRegionsTy { ty } +} + fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> { DepConstructor::TypeParamPredicates { item_id, diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index d6eaf6d1bc48..3fc9d854f295 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -701,6 +701,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::CompileCodegenUnit | DepKind::FulfillObligation | DepKind::VtableMethods | + DepKind::EraseRegionsTy | // These are just odd DepKind::Null | @@ -773,6 +774,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::ConstIsRvaluePromotableToStatic => { force!(const_is_rvalue_promotable_to_static, def_id!()); } + DepKind::RvaluePromotableMap => { force!(rvalue_promotable_map, def_id!()); } DepKind::ImplParent => { force!(impl_parent, def_id!()); } DepKind::TraitOfItem => { force!(trait_of_item, def_id!()); } DepKind::IsExportedSymbol => { force!(is_exported_symbol, def_id!()); } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 35969361544e..129c81c5cd61 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -90,6 +90,7 @@ pub mod adjustment; pub mod binding; pub mod cast; pub mod error; +mod erase_regions; pub mod fast_reject; pub mod fold; pub mod inhabitedness; @@ -2575,6 +2576,7 @@ fn original_crate_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub fn provide(providers: &mut ty::maps::Providers) { util::provide(providers); context::provide(providers); + erase_regions::provide(providers); *providers = ty::maps::Providers { associated_item, associated_item_def_ids,