Skip to content

Commit 80a0504

Browse files
committed
Revert "Auto merge of #43184 - nikomatsakis:incr-comp-anonymize-trait-selection, r=michaelwoerister"
This reverts commit b4502f7, reversing changes made to 23ecebd.
1 parent 64e40c2 commit 80a0504

File tree

6 files changed

+120
-83
lines changed

6 files changed

+120
-83
lines changed

src/librustc/dep_graph/dep_node.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ define_dep_nodes!( <'tcx>
495495
// imprecision in our dep-graph tracking. The important thing is
496496
// that for any given trait-ref, we always map to the **same**
497497
// trait-select node.
498-
[anon] TraitSelect,
498+
[] TraitSelect { trait_def_id: DefId, input_def_id: DefId },
499499

500500
// For proj. cache, we just keep a list of all def-ids, since it is
501501
// not a hotspot.

src/librustc/dep_graph/dep_tracking_map.rs

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,24 @@ use rustc_data_structures::fx::FxHashMap;
1212
use std::cell::RefCell;
1313
use std::hash::Hash;
1414
use std::marker::PhantomData;
15+
use ty::TyCtxt;
1516
use util::common::MemoizationMap;
1617

17-
use super::{DepKind, DepNodeIndex, DepGraph};
18+
use super::{DepNode, DepGraph};
1819

1920
/// A DepTrackingMap offers a subset of the `Map` API and ensures that
2021
/// we make calls to `read` and `write` as appropriate. We key the
2122
/// maps with a unique type for brevity.
2223
pub struct DepTrackingMap<M: DepTrackingMapConfig> {
2324
phantom: PhantomData<M>,
2425
graph: DepGraph,
25-
map: FxHashMap<M::Key, (M::Value, DepNodeIndex)>,
26+
map: FxHashMap<M::Key, M::Value>,
2627
}
2728

2829
pub trait DepTrackingMapConfig {
2930
type Key: Eq + Hash + Clone;
3031
type Value: Clone;
31-
fn to_dep_kind() -> DepKind;
32+
fn to_dep_node(tcx: TyCtxt, key: &Self::Key) -> DepNode;
3233
}
3334

3435
impl<M: DepTrackingMapConfig> DepTrackingMap<M> {
@@ -39,6 +40,27 @@ impl<M: DepTrackingMapConfig> DepTrackingMap<M> {
3940
map: FxHashMap(),
4041
}
4142
}
43+
44+
/// Registers a (synthetic) read from the key `k`. Usually this
45+
/// is invoked automatically by `get`.
46+
fn read(&self, tcx: TyCtxt, k: &M::Key) {
47+
let dep_node = M::to_dep_node(tcx, k);
48+
self.graph.read(dep_node);
49+
}
50+
51+
pub fn get(&self, tcx: TyCtxt, k: &M::Key) -> Option<&M::Value> {
52+
self.read(tcx, k);
53+
self.map.get(k)
54+
}
55+
56+
pub fn contains_key(&self, tcx: TyCtxt, k: &M::Key) -> bool {
57+
self.read(tcx, k);
58+
self.map.contains_key(k)
59+
}
60+
61+
pub fn keys(&self) -> Vec<M::Key> {
62+
self.map.keys().cloned().collect()
63+
}
4264
}
4365

4466
impl<M: DepTrackingMapConfig> MemoizationMap for RefCell<DepTrackingMap<M>> {
@@ -76,22 +98,22 @@ impl<M: DepTrackingMapConfig> MemoizationMap for RefCell<DepTrackingMap<M>> {
7698
/// The key is the line marked `(*)`: the closure implicitly
7799
/// accesses the body of the item `item`, so we register a read
78100
/// from `Hir(item_def_id)`.
79-
fn memoize<OP>(&self, key: M::Key, op: OP) -> M::Value
101+
fn memoize<OP>(&self, tcx: TyCtxt, key: M::Key, op: OP) -> M::Value
80102
where OP: FnOnce() -> M::Value
81103
{
82104
let graph;
83105
{
84106
let this = self.borrow();
85-
if let Some(&(ref result, dep_node)) = this.map.get(&key) {
86-
this.graph.read_index(dep_node);
107+
if let Some(result) = this.map.get(&key) {
108+
this.read(tcx, &key);
87109
return result.clone();
88110
}
89111
graph = this.graph.clone();
90112
}
91113

92-
let (result, dep_node) = graph.with_anon_task(M::to_dep_kind(), op);
93-
self.borrow_mut().map.insert(key, (result.clone(), dep_node));
94-
graph.read_index(dep_node);
114+
let _task = graph.in_task(M::to_dep_node(tcx, &key));
115+
let result = op();
116+
self.borrow_mut().map.insert(key, result.clone());
95117
result
96118
}
97119
}

src/librustc/traits/select.rs

Lines changed: 24 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ use super::{VtableImplData, VtableObjectData, VtableBuiltinData,
3030
VtableClosureData, VtableDefaultImplData, VtableFnPointerData};
3131
use super::util;
3232

33-
use dep_graph::{DepNodeIndex, DepKind};
3433
use hir::def_id::DefId;
3534
use infer;
3635
use infer::{InferCtxt, InferOk, TypeFreshener};
@@ -106,7 +105,7 @@ struct TraitObligationStack<'prev, 'tcx: 'prev> {
106105
#[derive(Clone)]
107106
pub struct SelectionCache<'tcx> {
108107
hashmap: RefCell<FxHashMap<ty::TraitRef<'tcx>,
109-
WithDepNode<SelectionResult<'tcx, SelectionCandidate<'tcx>>>>>,
108+
SelectionResult<'tcx, SelectionCandidate<'tcx>>>>,
110109
}
111110

112111
/// The selection process begins by considering all impls, where
@@ -370,7 +369,7 @@ impl EvaluationResult {
370369

371370
#[derive(Clone)]
372371
pub struct EvaluationCache<'tcx> {
373-
hashmap: RefCell<FxHashMap<ty::PolyTraitRef<'tcx>, WithDepNode<EvaluationResult>>>
372+
hashmap: RefCell<FxHashMap<ty::PolyTraitRef<'tcx>, EvaluationResult>>
374373
}
375374

376375
impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
@@ -467,6 +466,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
467466
assert!(!obligation.predicate.has_escaping_regions());
468467

469468
let tcx = self.tcx();
469+
let dep_node = obligation.predicate.dep_node(tcx);
470+
let _task = tcx.dep_graph.in_task(dep_node);
470471

471472
let stack = self.push_stack(TraitObligationStackList::empty(), obligation);
472473
let ret = match self.candidate_from_obligation(&stack)? {
@@ -709,12 +710,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
709710
return result;
710711
}
711712

712-
let (result, dep_node) = self.in_task(|this| this.evaluate_stack(&stack));
713+
let result = self.evaluate_stack(&stack);
713714

714715
debug!("CACHE MISS: EVAL({:?})={:?}",
715716
fresh_trait_ref,
716717
result);
717-
self.insert_evaluation_cache(obligation.param_env, fresh_trait_ref, dep_node, result);
718+
self.insert_evaluation_cache(obligation.param_env, fresh_trait_ref, result);
718719

719720
result
720721
}
@@ -869,23 +870,22 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
869870
trait_ref: ty::PolyTraitRef<'tcx>)
870871
-> Option<EvaluationResult>
871872
{
872-
let tcx = self.tcx();
873873
if self.can_use_global_caches(param_env) {
874-
let cache = tcx.evaluation_cache.hashmap.borrow();
874+
let cache = self.tcx().evaluation_cache.hashmap.borrow();
875875
if let Some(cached) = cache.get(&trait_ref) {
876-
return Some(cached.get(tcx));
876+
let dep_node = trait_ref
877+
.to_poly_trait_predicate()
878+
.dep_node(self.tcx());
879+
self.tcx().hir.dep_graph.read(dep_node);
880+
return Some(cached.clone());
877881
}
878882
}
879-
self.infcx.evaluation_cache.hashmap
880-
.borrow()
881-
.get(&trait_ref)
882-
.map(|v| v.get(tcx))
883+
self.infcx.evaluation_cache.hashmap.borrow().get(&trait_ref).cloned()
883884
}
884885

885886
fn insert_evaluation_cache(&mut self,
886887
param_env: ty::ParamEnv<'tcx>,
887888
trait_ref: ty::PolyTraitRef<'tcx>,
888-
dep_node: DepNodeIndex,
889889
result: EvaluationResult)
890890
{
891891
// Avoid caching results that depend on more than just the trait-ref:
@@ -902,14 +902,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
902902
if self.can_use_global_caches(param_env) {
903903
let mut cache = self.tcx().evaluation_cache.hashmap.borrow_mut();
904904
if let Some(trait_ref) = self.tcx().lift_to_global(&trait_ref) {
905-
cache.insert(trait_ref, WithDepNode::new(dep_node, result));
905+
cache.insert(trait_ref, result);
906906
return;
907907
}
908908
}
909909

910-
self.infcx.evaluation_cache.hashmap
911-
.borrow_mut()
912-
.insert(trait_ref, WithDepNode::new(dep_node, result));
910+
self.infcx.evaluation_cache.hashmap.borrow_mut().insert(trait_ref, result);
913911
}
914912

915913
///////////////////////////////////////////////////////////////////////////
@@ -951,32 +949,19 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
951949
}
952950

953951
// If no match, compute result and insert into cache.
954-
let (candidate, dep_node) = self.in_task(|this| {
955-
this.candidate_from_obligation_no_cache(stack)
956-
});
952+
let candidate = self.candidate_from_obligation_no_cache(stack);
957953

958954
if self.should_update_candidate_cache(&cache_fresh_trait_pred, &candidate) {
959955
debug!("CACHE MISS: SELECT({:?})={:?}",
960956
cache_fresh_trait_pred, candidate);
961957
self.insert_candidate_cache(stack.obligation.param_env,
962958
cache_fresh_trait_pred,
963-
dep_node,
964959
candidate.clone());
965960
}
966961

967962
candidate
968963
}
969964

970-
fn in_task<OP, R>(&mut self, op: OP) -> (R, DepNodeIndex)
971-
where OP: FnOnce(&mut Self) -> R
972-
{
973-
let (result, dep_node) = self.tcx().dep_graph.with_anon_task(DepKind::TraitSelect, || {
974-
op(self)
975-
});
976-
self.tcx().dep_graph.read_index(dep_node);
977-
(result, dep_node)
978-
}
979-
980965
// Treat negative impls as unimplemented
981966
fn filter_negative_impls(&self, candidate: SelectionCandidate<'tcx>)
982967
-> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
@@ -1166,41 +1151,33 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
11661151
cache_fresh_trait_pred: &ty::PolyTraitPredicate<'tcx>)
11671152
-> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>>
11681153
{
1169-
let tcx = self.tcx();
11701154
let trait_ref = &cache_fresh_trait_pred.0.trait_ref;
11711155
if self.can_use_global_caches(param_env) {
1172-
let cache = tcx.selection_cache.hashmap.borrow();
1156+
let cache = self.tcx().selection_cache.hashmap.borrow();
11731157
if let Some(cached) = cache.get(&trait_ref) {
1174-
return Some(cached.get(tcx));
1158+
return Some(cached.clone());
11751159
}
11761160
}
1177-
self.infcx.selection_cache.hashmap
1178-
.borrow()
1179-
.get(trait_ref)
1180-
.map(|v| v.get(tcx))
1161+
self.infcx.selection_cache.hashmap.borrow().get(trait_ref).cloned()
11811162
}
11821163

11831164
fn insert_candidate_cache(&mut self,
11841165
param_env: ty::ParamEnv<'tcx>,
11851166
cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
1186-
dep_node: DepNodeIndex,
11871167
candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>)
11881168
{
1189-
let tcx = self.tcx();
11901169
let trait_ref = cache_fresh_trait_pred.0.trait_ref;
11911170
if self.can_use_global_caches(param_env) {
1192-
let mut cache = tcx.selection_cache.hashmap.borrow_mut();
1193-
if let Some(trait_ref) = tcx.lift_to_global(&trait_ref) {
1194-
if let Some(candidate) = tcx.lift_to_global(&candidate) {
1195-
cache.insert(trait_ref, WithDepNode::new(dep_node, candidate));
1171+
let mut cache = self.tcx().selection_cache.hashmap.borrow_mut();
1172+
if let Some(trait_ref) = self.tcx().lift_to_global(&trait_ref) {
1173+
if let Some(candidate) = self.tcx().lift_to_global(&candidate) {
1174+
cache.insert(trait_ref, candidate);
11961175
return;
11971176
}
11981177
}
11991178
}
12001179

1201-
self.infcx.selection_cache.hashmap
1202-
.borrow_mut()
1203-
.insert(trait_ref, WithDepNode::new(dep_node, candidate));
1180+
self.infcx.selection_cache.hashmap.borrow_mut().insert(trait_ref, candidate);
12041181
}
12051182

12061183
fn should_update_candidate_cache(&mut self,
@@ -3161,20 +3138,3 @@ impl<'o,'tcx> fmt::Debug for TraitObligationStack<'o,'tcx> {
31613138
write!(f, "TraitObligationStack({:?})", self.obligation)
31623139
}
31633140
}
3164-
3165-
#[derive(Clone)]
3166-
pub struct WithDepNode<T> {
3167-
dep_node: DepNodeIndex,
3168-
cached_value: T
3169-
}
3170-
3171-
impl<T: Clone> WithDepNode<T> {
3172-
pub fn new(dep_node: DepNodeIndex, cached_value: T) -> Self {
3173-
WithDepNode { dep_node, cached_value }
3174-
}
3175-
3176-
pub fn get(&self, tcx: TyCtxt) -> T {
3177-
tcx.dep_graph.read_index(self.dep_node);
3178-
self.cached_value.clone()
3179-
}
3180-
}

src/librustc/traits/trans/mod.rs

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
// seems likely that they should eventually be merged into more
1414
// general routines.
1515

16-
use dep_graph::{DepGraph, DepKind, DepTrackingMap, DepTrackingMapConfig};
16+
use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig,
17+
DepConstructor};
18+
use hir::def_id::DefId;
1719
use infer::TransNormalize;
1820
use std::cell::RefCell;
1921
use std::marker::PhantomData;
@@ -39,7 +41,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
3941
// Remove any references to regions; this helps improve caching.
4042
let trait_ref = self.erase_regions(&trait_ref);
4143

42-
self.trans_trait_caches.trait_cache.memoize(trait_ref, || {
44+
self.trans_trait_caches.trait_cache.memoize(self, trait_ref, || {
4345
debug!("trans::fulfill_obligation(trait_ref={:?}, def_id={:?})",
4446
trait_ref, trait_ref.def_id());
4547

@@ -137,7 +139,7 @@ impl<'a, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizer<'a, 'gcx> {
137139
if !ty.has_projection_types() {
138140
ty
139141
} else {
140-
self.tcx.trans_trait_caches.project_cache.memoize(ty, || {
142+
self.tcx.trans_trait_caches.project_cache.memoize(self.tcx, ty, || {
141143
debug!("AssociatedTypeNormalizer: ty={:?}", ty);
142144
self.tcx.normalize_associated_type(&ty)
143145
})
@@ -169,8 +171,8 @@ pub struct TraitSelectionCache<'tcx> {
169171
impl<'tcx> DepTrackingMapConfig for TraitSelectionCache<'tcx> {
170172
type Key = ty::PolyTraitRef<'tcx>;
171173
type Value = Vtable<'tcx, ()>;
172-
fn to_dep_kind() -> DepKind {
173-
DepKind::TraitSelect
174+
fn to_dep_node(tcx: TyCtxt, key: &ty::PolyTraitRef<'tcx>) -> DepNode {
175+
key.to_poly_trait_predicate().dep_node(tcx)
174176
}
175177
}
176178

@@ -183,8 +185,31 @@ pub struct ProjectionCache<'gcx> {
183185
impl<'gcx> DepTrackingMapConfig for ProjectionCache<'gcx> {
184186
type Key = Ty<'gcx>;
185187
type Value = Ty<'gcx>;
186-
fn to_dep_kind() -> DepKind {
187-
DepKind::TraitSelect
188+
fn to_dep_node(tcx: TyCtxt, key: &Self::Key) -> DepNode {
189+
// Ideally, we'd just put `key` into the dep-node, but we
190+
// can't put full types in there. So just collect up all the
191+
// def-ids of structs/enums as well as any traits that we
192+
// project out of. It doesn't matter so much what we do here,
193+
// except that if we are too coarse, we'll create overly
194+
// coarse edges between impls and the trans. For example, if
195+
// we just used the def-id of things we are projecting out of,
196+
// then the key for `<Foo as SomeTrait>::T` and `<Bar as
197+
// SomeTrait>::T` would both share a dep-node
198+
// (`TraitSelect(SomeTrait)`), and hence the impls for both
199+
// `Foo` and `Bar` would be considered inputs. So a change to
200+
// `Bar` would affect things that just normalized `Foo`.
201+
// Anyway, this heuristic is not ideal, but better than
202+
// nothing.
203+
let def_ids: Vec<DefId> =
204+
key.walk()
205+
.filter_map(|t| match t.sty {
206+
ty::TyAdt(adt_def, _) => Some(adt_def.did),
207+
ty::TyProjection(ref proj) => Some(proj.item_def_id),
208+
_ => None,
209+
})
210+
.collect();
211+
212+
DepNode::new(tcx, DepConstructor::ProjectionCache { def_ids: def_ids })
188213
}
189214
}
190215

0 commit comments

Comments
 (0)