Skip to content

Commit b72ca1e

Browse files
committed
Use a more lightweight cache for erase_regions
1 parent 237bf32 commit b72ca1e

File tree

5 files changed

+75
-30
lines changed

5 files changed

+75
-30
lines changed

src/librustc/dep_graph/graph.rs

+51
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,43 @@ impl DepGraph {
136136
DepGraphQuery::new(&nodes[..], &edges[..])
137137
}
138138

139+
pub fn debug_assert_no_deps<OP, R>(op: OP) -> R
140+
where OP: FnOnce() -> R
141+
{
142+
if cfg!(debug_assertions) {
143+
ty::tls::with_context(|icx| {
144+
let task_deps = Lock::new(TaskDeps {
145+
#[cfg(debug_assertions)]
146+
node: None,
147+
#[cfg(debug_assertions)]
148+
no_deps: true,
149+
reads: SmallVec::new(),
150+
read_set: Default::default(),
151+
});
152+
let icx = ty::tls::ImplicitCtxt {
153+
task_deps: Some(&task_deps),
154+
..icx.clone()
155+
};
156+
157+
let r = ty::tls::enter_context(&icx, |_| {
158+
op()
159+
});
160+
161+
for read in &task_deps.lock().reads {
162+
icx.tcx.dep_graph.data.as_ref().map(|graph| {
163+
eprintln!("read: {:?}", graph.current.lock().data[*read].node);
164+
});
165+
}
166+
// Ensure no dependencies were recorded
167+
assert_eq!(task_deps.into_inner().reads, SmallVec::<[DepNodeIndex; 8]>::new());
168+
169+
r
170+
})
171+
} else {
172+
op()
173+
}
174+
}
175+
139176
pub fn assert_ignored(&self)
140177
{
141178
if let Some(..) = self.data {
@@ -203,6 +240,8 @@ impl DepGraph {
203240
|_key| Some(TaskDeps {
204241
#[cfg(debug_assertions)]
205242
node: Some(_key),
243+
#[cfg(debug_assertions)]
244+
no_deps: false,
206245
reads: SmallVec::new(),
207246
read_set: Default::default(),
208247
}),
@@ -345,6 +384,8 @@ impl DepGraph {
345384
let task_deps = Lock::new(TaskDeps {
346385
#[cfg(debug_assertions)]
347386
node: None,
387+
#[cfg(debug_assertions)]
388+
no_deps: false,
348389
reads: SmallVec::new(),
349390
read_set: Default::default(),
350391
});
@@ -1109,6 +1150,14 @@ impl DepGraphData {
11091150
let icx = if let Some(icx) = icx { icx } else { return };
11101151
if let Some(task_deps) = icx.task_deps {
11111152
let mut task_deps = task_deps.lock();
1153+
1154+
#[cfg(debug_assertions)]
1155+
{
1156+
if task_deps.no_deps {
1157+
panic!("tried to add dependency, but no dependencies are allowed");
1158+
}
1159+
}
1160+
11121161
if cfg!(debug_assertions) {
11131162
self.current.lock().total_read_count += 1;
11141163
}
@@ -1140,6 +1189,8 @@ impl DepGraphData {
11401189
pub struct TaskDeps {
11411190
#[cfg(debug_assertions)]
11421191
node: Option<DepNode>,
1192+
#[cfg(debug_assertions)]
1193+
no_deps: bool,
11431194
reads: SmallVec<[DepNodeIndex; 8]>,
11441195
read_set: FxHashSet<DepNodeIndex>,
11451196
}

src/librustc/query/mod.rs

+1-16
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::ty::query::QueryDescription;
22
use crate::ty::query::queries;
3-
use crate::ty::{self, Ty, TyCtxt};
3+
use crate::ty::{self, TyCtxt};
44
use crate::hir::def_id::{DefId, CrateNum};
55
use crate::dep_graph::SerializedDepNodeIndex;
66
use crate::traits;
@@ -113,21 +113,6 @@ rustc_queries! {
113113
}
114114

115115
TypeChecking {
116-
// Erases regions from `ty` to yield a new type.
117-
// Normally you would just use `tcx.erase_regions(&value)`,
118-
// however, which uses this query as a kind of cache.
119-
query erase_regions_ty(ty: Ty<'tcx>) -> Ty<'tcx> {
120-
// This query is not expected to have input -- as a result, it
121-
// is not a good candidates for "replay" because it is essentially a
122-
// pure function of its input (and hence the expectation is that
123-
// no caller would be green **apart** from just these
124-
// queries). Making it anonymous avoids hashing the result, which
125-
// may save a bit of time.
126-
anon
127-
no_force
128-
desc { "erasing regions from `{:?}`", ty }
129-
}
130-
131116
query program_clauses_for(_: DefId) -> Clauses<'tcx> {
132117
desc { "generating chalk-style clauses" }
133118
}

src/librustc/ty/context.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,8 @@ pub struct GlobalCtxt<'tcx> {
999999
/// Common types, pre-interned for your convenience.
10001000
pub types: CommonTypes<'tcx>,
10011001

1002+
pub(in crate::ty) erased_region_cache: Lock<FxHashMap<Ty<'tcx>, Ty<'tcx>>>,
1003+
10021004
/// Map indicating what traits are in scope for places where this
10031005
/// is relevant; generated by resolve.
10041006
trait_map: FxHashMap<DefIndex,
@@ -1250,6 +1252,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
12501252
global_interners: interners,
12511253
dep_graph,
12521254
types: common_types,
1255+
erased_region_cache: Default::default(),
12531256
trait_map,
12541257
export_map: resolutions.export_map.into_iter().map(|(k, v)| {
12551258
(k, Lrc::new(v))
@@ -2727,8 +2730,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
27272730

27282731
pub fn intern_existential_predicates(self, eps: &[ExistentialPredicate<'tcx>])
27292732
-> &'tcx List<ExistentialPredicate<'tcx>> {
2730-
assert!(!eps.is_empty());
2731-
assert!(eps.windows(2).all(|w| w[0].stable_cmp(self, &w[1]) != Ordering::Greater));
2733+
if cfg!(debug_assertions) {
2734+
assert!(!eps.is_empty());
2735+
self.dep_graph.with_ignore(|| {
2736+
assert!(eps.windows(2).all(|w| {
2737+
w[0].stable_cmp(self, &w[1]) != Ordering::Greater
2738+
}));
2739+
});
2740+
}
27322741
self._intern_existential_predicates(eps)
27332742
}
27342743

src/librustc/ty/erase_regions.rs

+12-11
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
use crate::ty::{self, Ty, TyCtxt, TypeFlags};
22
use crate::ty::fold::{TypeFolder, TypeFoldable};
3-
4-
pub(super) fn provide(providers: &mut ty::query::Providers<'_>) {
5-
*providers = ty::query::Providers {
6-
erase_regions_ty,
7-
..*providers
8-
};
9-
}
3+
use crate::dep_graph::DepGraph;
104

115
fn erase_regions_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
12-
// N.B., use `super_fold_with` here. If we used `fold_with`, it
13-
// could invoke the `erase_regions_ty` query recursively.
14-
ty.super_fold_with(&mut RegionEraserVisitor { tcx })
6+
if let Some(ty) = tcx.erased_region_cache.lock().get(ty) {
7+
return ty;
8+
}
9+
let result = DepGraph::debug_assert_no_deps(|| {
10+
// N.B., use `super_fold_with` here. If we used `fold_with`, it
11+
// could invoke the `erase_regions_ty` function recursively.
12+
ty.super_fold_with(&mut RegionEraserVisitor { tcx })
13+
});
14+
tcx.erased_region_cache.lock().insert(ty, result);
15+
result
1516
}
1617

1718
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
@@ -43,7 +44,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionEraserVisitor<'a, 'gcx, 't
4344

4445
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
4546
if let Some(ty_lifted) = self.tcx.lift_to_global(&ty) {
46-
self.tcx.erase_regions_ty(ty_lifted)
47+
erase_regions_ty(self.tcx.global_tcx(), ty_lifted)
4748
} else {
4849
ty.super_fold_with(self)
4950
}

src/librustc/ty/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -3345,7 +3345,6 @@ fn issue33140_self_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
33453345

33463346
pub fn provide(providers: &mut ty::query::Providers<'_>) {
33473347
context::provide(providers);
3348-
erase_regions::provide(providers);
33493348
layout::provide(providers);
33503349
util::provide(providers);
33513350
constness::provide(providers);

0 commit comments

Comments
 (0)