@@ -30,6 +30,7 @@ use super::{VtableImplData, VtableObjectData, VtableBuiltinData,
30
30
VtableClosureData , VtableDefaultImplData , VtableFnPointerData } ;
31
31
use super :: util;
32
32
33
+ use dep_graph:: { DepNodeIndex , DepKind } ;
33
34
use hir:: def_id:: DefId ;
34
35
use infer;
35
36
use infer:: { InferCtxt , InferOk , TypeFreshener } ;
@@ -105,7 +106,7 @@ struct TraitObligationStack<'prev, 'tcx: 'prev> {
105
106
#[ derive( Clone ) ]
106
107
pub struct SelectionCache < ' tcx > {
107
108
hashmap : RefCell < FxHashMap < ty:: TraitRef < ' tcx > ,
108
- SelectionResult < ' tcx , SelectionCandidate < ' tcx > > > > ,
109
+ WithDepNode < SelectionResult < ' tcx , SelectionCandidate < ' tcx > > > > > ,
109
110
}
110
111
111
112
/// The selection process begins by considering all impls, where
@@ -369,7 +370,7 @@ impl EvaluationResult {
369
370
370
371
#[ derive( Clone ) ]
371
372
pub struct EvaluationCache < ' tcx > {
372
- hashmap : RefCell < FxHashMap < ty:: PolyTraitRef < ' tcx > , EvaluationResult > >
373
+ hashmap : RefCell < FxHashMap < ty:: PolyTraitRef < ' tcx > , WithDepNode < EvaluationResult > > >
373
374
}
374
375
375
376
impl < ' cx , ' gcx , ' tcx > SelectionContext < ' cx , ' gcx , ' tcx > {
@@ -466,8 +467,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
466
467
assert ! ( !obligation. predicate. has_escaping_regions( ) ) ;
467
468
468
469
let tcx = self . tcx ( ) ;
469
- let dep_node = obligation. predicate . dep_node ( tcx) ;
470
- let _task = tcx. dep_graph . in_task ( dep_node) ;
471
470
472
471
let stack = self . push_stack ( TraitObligationStackList :: empty ( ) , obligation) ;
473
472
let ret = match self . candidate_from_obligation ( & stack) ? {
@@ -710,12 +709,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
710
709
return result;
711
710
}
712
711
713
- let result = self . evaluate_stack ( & stack) ;
712
+ let ( result, dep_node ) = self . in_task ( |this| this . evaluate_stack ( & stack) ) ;
714
713
715
714
debug ! ( "CACHE MISS: EVAL({:?})={:?}" ,
716
715
fresh_trait_ref,
717
716
result) ;
718
- self . insert_evaluation_cache ( obligation. param_env , fresh_trait_ref, result) ;
717
+ self . insert_evaluation_cache ( obligation. param_env , fresh_trait_ref, dep_node , result) ;
719
718
720
719
result
721
720
}
@@ -870,22 +869,23 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
870
869
trait_ref : ty:: PolyTraitRef < ' tcx > )
871
870
-> Option < EvaluationResult >
872
871
{
872
+ let tcx = self . tcx ( ) ;
873
873
if self . can_use_global_caches ( param_env) {
874
- let cache = self . tcx ( ) . evaluation_cache . hashmap . borrow ( ) ;
874
+ let cache = tcx. evaluation_cache . hashmap . borrow ( ) ;
875
875
if let Some ( cached) = cache. get ( & trait_ref) {
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 ( ) ) ;
876
+ return Some ( cached. get ( tcx) ) ;
881
877
}
882
878
}
883
- self . infcx . evaluation_cache . hashmap . borrow ( ) . get ( & trait_ref) . cloned ( )
879
+ self . infcx . evaluation_cache . hashmap
880
+ . borrow ( )
881
+ . get ( & trait_ref)
882
+ . map ( |v| v. get ( tcx) )
884
883
}
885
884
886
885
fn insert_evaluation_cache ( & mut self ,
887
886
param_env : ty:: ParamEnv < ' tcx > ,
888
887
trait_ref : ty:: PolyTraitRef < ' tcx > ,
888
+ dep_node : DepNodeIndex ,
889
889
result : EvaluationResult )
890
890
{
891
891
// Avoid caching results that depend on more than just the trait-ref:
@@ -902,12 +902,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
902
902
if self . can_use_global_caches ( param_env) {
903
903
let mut cache = self . tcx ( ) . evaluation_cache . hashmap . borrow_mut ( ) ;
904
904
if let Some ( trait_ref) = self . tcx ( ) . lift_to_global ( & trait_ref) {
905
- cache. insert ( trait_ref, result) ;
905
+ cache. insert ( trait_ref, WithDepNode :: new ( dep_node , result) ) ;
906
906
return ;
907
907
}
908
908
}
909
909
910
- self . infcx . evaluation_cache . hashmap . borrow_mut ( ) . insert ( trait_ref, result) ;
910
+ self . infcx . evaluation_cache . hashmap
911
+ . borrow_mut ( )
912
+ . insert ( trait_ref, WithDepNode :: new ( dep_node, result) ) ;
911
913
}
912
914
913
915
///////////////////////////////////////////////////////////////////////////
@@ -949,19 +951,32 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
949
951
}
950
952
951
953
// If no match, compute result and insert into cache.
952
- let candidate = self . candidate_from_obligation_no_cache ( stack) ;
954
+ let ( candidate, dep_node) = self . in_task ( |this| {
955
+ this. candidate_from_obligation_no_cache ( stack)
956
+ } ) ;
953
957
954
958
if self . should_update_candidate_cache ( & cache_fresh_trait_pred, & candidate) {
955
959
debug ! ( "CACHE MISS: SELECT({:?})={:?}" ,
956
960
cache_fresh_trait_pred, candidate) ;
957
961
self . insert_candidate_cache ( stack. obligation . param_env ,
958
962
cache_fresh_trait_pred,
963
+ dep_node,
959
964
candidate. clone ( ) ) ;
960
965
}
961
966
962
967
candidate
963
968
}
964
969
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
+
965
980
// Treat negative impls as unimplemented
966
981
fn filter_negative_impls ( & self , candidate : SelectionCandidate < ' tcx > )
967
982
-> SelectionResult < ' tcx , SelectionCandidate < ' tcx > > {
@@ -1151,33 +1166,41 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
1151
1166
cache_fresh_trait_pred : & ty:: PolyTraitPredicate < ' tcx > )
1152
1167
-> Option < SelectionResult < ' tcx , SelectionCandidate < ' tcx > > >
1153
1168
{
1169
+ let tcx = self . tcx ( ) ;
1154
1170
let trait_ref = & cache_fresh_trait_pred. 0 . trait_ref ;
1155
1171
if self . can_use_global_caches ( param_env) {
1156
- let cache = self . tcx ( ) . selection_cache . hashmap . borrow ( ) ;
1172
+ let cache = tcx. selection_cache . hashmap . borrow ( ) ;
1157
1173
if let Some ( cached) = cache. get ( & trait_ref) {
1158
- return Some ( cached. clone ( ) ) ;
1174
+ return Some ( cached. get ( tcx ) ) ;
1159
1175
}
1160
1176
}
1161
- self . infcx . selection_cache . hashmap . borrow ( ) . get ( trait_ref) . cloned ( )
1177
+ self . infcx . selection_cache . hashmap
1178
+ . borrow ( )
1179
+ . get ( trait_ref)
1180
+ . map ( |v| v. get ( tcx) )
1162
1181
}
1163
1182
1164
1183
fn insert_candidate_cache ( & mut self ,
1165
1184
param_env : ty:: ParamEnv < ' tcx > ,
1166
1185
cache_fresh_trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
1186
+ dep_node : DepNodeIndex ,
1167
1187
candidate : SelectionResult < ' tcx , SelectionCandidate < ' tcx > > )
1168
1188
{
1189
+ let tcx = self . tcx ( ) ;
1169
1190
let trait_ref = cache_fresh_trait_pred. 0 . trait_ref ;
1170
1191
if self . can_use_global_caches ( param_env) {
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) ;
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) ) ;
1175
1196
return ;
1176
1197
}
1177
1198
}
1178
1199
}
1179
1200
1180
- self . infcx . selection_cache . hashmap . borrow_mut ( ) . insert ( trait_ref, candidate) ;
1201
+ self . infcx . selection_cache . hashmap
1202
+ . borrow_mut ( )
1203
+ . insert ( trait_ref, WithDepNode :: new ( dep_node, candidate) ) ;
1181
1204
}
1182
1205
1183
1206
fn should_update_candidate_cache ( & mut self ,
@@ -3138,3 +3161,20 @@ impl<'o,'tcx> fmt::Debug for TraitObligationStack<'o,'tcx> {
3138
3161
write ! ( f, "TraitObligationStack({:?})" , self . obligation)
3139
3162
}
3140
3163
}
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
+ }
0 commit comments