Skip to content

Commit 0e67d17

Browse files
committed
make erase_regions use a query instead of an ad-hoc cache
1 parent 0ae18a1 commit 0e67d17

File tree

8 files changed

+99
-65
lines changed

8 files changed

+99
-65
lines changed

src/librustc/dep_graph/dep_node.rs

+1
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,7 @@ define_dep_nodes!( <'tcx>
609609
[] PostorderCnums,
610610
[] HasCloneClosures(CrateNum),
611611
[] HasCopyClosures(CrateNum),
612+
[] EraseRegionsTy { ty: Ty<'tcx> },
612613

613614
[] Freevars(DefId),
614615
[] MaybeUnusedTraitImport(DefId),

src/librustc/ty/context.rs

-4
Original file line numberDiff line numberDiff line change
@@ -892,9 +892,6 @@ pub struct GlobalCtxt<'tcx> {
892892
// Internal cache for metadata decoding. No need to track deps on this.
893893
pub rcache: RefCell<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
894894

895-
// FIXME dep tracking -- should be harmless enough
896-
pub normalized_cache: RefCell<FxHashMap<Ty<'tcx>, Ty<'tcx>>>,
897-
898895
/// Caches the results of trait selection. This cache is used
899896
/// for things that do not have to do with the parameters in scope.
900897
pub selection_cache: traits::SelectionCache<'tcx>,
@@ -1172,7 +1169,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
11721169
maps: maps::Maps::new(providers),
11731170
mir_passes,
11741171
rcache: RefCell::new(FxHashMap()),
1175-
normalized_cache: RefCell::new(FxHashMap()),
11761172
selection_cache: traits::SelectionCache::new(),
11771173
evaluation_cache: traits::EvaluationCache::new(),
11781174
crate_name: Symbol::intern(crate_name),

src/librustc/ty/erase_regions.rs

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use ty::{self, Ty, TyCtxt};
12+
use ty::fold::{TypeFolder, TypeFoldable};
13+
14+
pub(super) fn provide(providers: &mut ty::maps::Providers) {
15+
*providers = ty::maps::Providers {
16+
erase_regions_ty,
17+
..*providers
18+
};
19+
}
20+
21+
fn erase_regions_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
22+
// NB: use `super_fold_with` here. If we used `fold_with`, it
23+
// could invoke the `erase_regions_ty` query recursively.
24+
ty.super_fold_with(&mut RegionEraserVisitor { tcx })
25+
}
26+
27+
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
28+
/// Returns an equivalent value with all free regions removed (note
29+
/// that late-bound regions remain, because they are important for
30+
/// subtyping, but they are anonymized and normalized as well)..
31+
pub fn erase_regions<T>(self, value: &T) -> T
32+
where T : TypeFoldable<'tcx>
33+
{
34+
let value1 = value.fold_with(&mut RegionEraserVisitor { tcx: self });
35+
debug!("erase_regions({:?}) = {:?}", value, value1);
36+
value1
37+
}
38+
}
39+
40+
struct RegionEraserVisitor<'a, 'gcx: 'tcx, 'tcx: 'a> {
41+
tcx: TyCtxt<'a, 'gcx, 'tcx>,
42+
}
43+
44+
impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionEraserVisitor<'a, 'gcx, 'tcx> {
45+
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
46+
self.tcx
47+
}
48+
49+
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
50+
if let Some(ty_lifted) = self.tcx.lift_to_global(&ty) {
51+
self.tcx.erase_regions_ty(ty_lifted)
52+
} else {
53+
ty.super_fold_with(self)
54+
}
55+
}
56+
57+
fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
58+
where T : TypeFoldable<'tcx>
59+
{
60+
let u = self.tcx.anonymize_late_bound_regions(t);
61+
u.super_fold_with(self)
62+
}
63+
64+
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
65+
// because late-bound regions affect subtyping, we can't
66+
// erase the bound/free distinction, but we can replace
67+
// all free regions with 'erased.
68+
//
69+
// Note that we *CAN* replace early-bound regions -- the
70+
// type system never "sees" those, they get substituted
71+
// away. In trans, they will always be erased to 'erased
72+
// whenever a substitution occurs.
73+
match *r {
74+
ty::ReLateBound(..) => r,
75+
_ => self.tcx.types.re_erased
76+
}
77+
}
78+
}
79+

src/librustc/ty/fold.rs

-61
Original file line numberDiff line numberDiff line change
@@ -444,67 +444,6 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionReplacer<'a, 'gcx, 'tcx> {
444444
}
445445
}
446446

447-
///////////////////////////////////////////////////////////////////////////
448-
// Region eraser
449-
450-
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
451-
/// Returns an equivalent value with all free regions removed (note
452-
/// that late-bound regions remain, because they are important for
453-
/// subtyping, but they are anonymized and normalized as well)..
454-
pub fn erase_regions<T>(self, value: &T) -> T
455-
where T : TypeFoldable<'tcx>
456-
{
457-
let value1 = value.fold_with(&mut RegionEraser(self));
458-
debug!("erase_regions({:?}) = {:?}",
459-
value, value1);
460-
return value1;
461-
462-
struct RegionEraser<'a, 'gcx: 'a+'tcx, 'tcx: 'a>(TyCtxt<'a, 'gcx, 'tcx>);
463-
464-
impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionEraser<'a, 'gcx, 'tcx> {
465-
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.0 }
466-
467-
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
468-
if let Some(u) = self.tcx().normalized_cache.borrow().get(&ty).cloned() {
469-
return u;
470-
}
471-
472-
// FIXME(eddyb) should local contexts have a cache too?
473-
if let Some(ty_lifted) = self.tcx().lift_to_global(&ty) {
474-
let tcx = self.tcx().global_tcx();
475-
let t_norm = ty_lifted.super_fold_with(&mut RegionEraser(tcx));
476-
tcx.normalized_cache.borrow_mut().insert(ty_lifted, t_norm);
477-
t_norm
478-
} else {
479-
ty.super_fold_with(self)
480-
}
481-
}
482-
483-
fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
484-
where T : TypeFoldable<'tcx>
485-
{
486-
let u = self.tcx().anonymize_late_bound_regions(t);
487-
u.super_fold_with(self)
488-
}
489-
490-
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
491-
// because late-bound regions affect subtyping, we can't
492-
// erase the bound/free distinction, but we can replace
493-
// all free regions with 'erased.
494-
//
495-
// Note that we *CAN* replace early-bound regions -- the
496-
// type system never "sees" those, they get substituted
497-
// away. In trans, they will always be erased to 'erased
498-
// whenever a substitution occurs.
499-
match *r {
500-
ty::ReLateBound(..) => r,
501-
_ => self.tcx().types.re_erased
502-
}
503-
}
504-
}
505-
}
506-
}
507-
508447
///////////////////////////////////////////////////////////////////////////
509448
// Region shifter
510449
//

src/librustc/ty/maps/config.rs

+6
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@ impl<'tcx> QueryDescription for queries::super_predicates_of<'tcx> {
7575
}
7676
}
7777

78+
impl<'tcx> QueryDescription for queries::erase_regions_ty<'tcx> {
79+
fn describe(_tcx: TyCtxt, ty: Ty<'tcx>) -> String {
80+
format!("erasing regions from `{:?}`", ty)
81+
}
82+
}
83+
7884
impl<'tcx> QueryDescription for queries::type_param_predicates<'tcx> {
7985
fn describe(tcx: TyCtxt, (_, def_id): (DefId, DefId)) -> String {
8086
let id = tcx.hir.as_local_node_id(def_id).unwrap();

src/librustc/ty/maps/mod.rs

+9
Original file line numberDiff line numberDiff line change
@@ -341,12 +341,21 @@ define_maps! { <'tcx>
341341

342342
[] fn has_copy_closures: HasCopyClosures(CrateNum) -> bool,
343343
[] fn has_clone_closures: HasCloneClosures(CrateNum) -> bool,
344+
345+
// Erases regions from `ty` to yield a new type.
346+
// Normally you would just use `tcx.erase_regions(&value)`,
347+
// however, which uses this query as a kind of cache.
348+
[] fn erase_regions_ty: erase_regions_ty(Ty<'tcx>) -> Ty<'tcx>,
344349
}
345350

346351
//////////////////////////////////////////////////////////////////////
347352
// These functions are little shims used to find the dep-node for a
348353
// given query when there is not a *direct* mapping:
349354

355+
fn erase_regions_ty<'tcx>(ty: Ty<'tcx>) -> DepConstructor<'tcx> {
356+
DepConstructor::EraseRegionsTy { ty }
357+
}
358+
350359
fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> {
351360
DepConstructor::TypeParamPredicates {
352361
item_id,

src/librustc/ty/maps/plumbing.rs

+2
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
701701
DepKind::CompileCodegenUnit |
702702
DepKind::FulfillObligation |
703703
DepKind::VtableMethods |
704+
DepKind::EraseRegionsTy |
704705

705706
// These are just odd
706707
DepKind::Null |
@@ -773,6 +774,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
773774
DepKind::ConstIsRvaluePromotableToStatic => {
774775
force!(const_is_rvalue_promotable_to_static, def_id!());
775776
}
777+
DepKind::RvaluePromotableMap => { force!(rvalue_promotable_map, def_id!()); }
776778
DepKind::ImplParent => { force!(impl_parent, def_id!()); }
777779
DepKind::TraitOfItem => { force!(trait_of_item, def_id!()); }
778780
DepKind::IsExportedSymbol => { force!(is_exported_symbol, def_id!()); }

src/librustc/ty/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ pub mod adjustment;
9090
pub mod binding;
9191
pub mod cast;
9292
pub mod error;
93+
mod erase_regions;
9394
pub mod fast_reject;
9495
pub mod fold;
9596
pub mod inhabitedness;
@@ -2575,6 +2576,7 @@ fn original_crate_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
25752576
pub fn provide(providers: &mut ty::maps::Providers) {
25762577
util::provide(providers);
25772578
context::provide(providers);
2579+
erase_regions::provide(providers);
25782580
*providers = ty::maps::Providers {
25792581
associated_item,
25802582
associated_item_def_ids,

0 commit comments

Comments
 (0)