20
20
use super :: { SelectionContext , FulfillmentContext } ;
21
21
use super :: util:: { fresh_type_vars_for_impl, impl_trait_ref_and_oblig} ;
22
22
23
+ use rustc_data_structures:: fnv:: FnvHashMap ;
23
24
use hir:: def_id:: DefId ;
24
25
use infer:: { InferCtxt , TypeOrigin } ;
25
26
use middle:: region;
@@ -111,6 +112,10 @@ pub fn translate_substs<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
111
112
pub fn specializes < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
112
113
impl1_def_id : DefId ,
113
114
impl2_def_id : DefId ) -> bool {
115
+ if let Some ( r) = tcx. specializes_cache . borrow ( ) . check ( impl1_def_id, impl2_def_id) {
116
+ return r;
117
+ }
118
+
114
119
// The feature gate should prevent introducing new specializations, but not
115
120
// taking advantage of upstream ones.
116
121
if !tcx. sess . features . borrow ( ) . specialization &&
@@ -146,7 +151,7 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
146
151
. unwrap ( )
147
152
. subst ( tcx, & penv. free_substs ) ;
148
153
149
- tcx. normalizing_infer_ctxt ( ProjectionMode :: Topmost ) . enter ( |mut infcx| {
154
+ let result = tcx. normalizing_infer_ctxt ( ProjectionMode :: Topmost ) . enter ( |mut infcx| {
150
155
// Normalize the trait reference, adding any obligations
151
156
// that arise into the impl1 assumptions.
152
157
let Normalized { value : impl1_trait_ref, obligations : normalization_obligations } = {
@@ -167,7 +172,10 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
167
172
168
173
// Attempt to prove that impl2 applies, given all of the above.
169
174
fulfill_implication ( & infcx, impl1_trait_ref, impl2_def_id) . is_ok ( )
170
- } )
175
+ } ) ;
176
+
177
+ tcx. specializes_cache . borrow_mut ( ) . insert ( impl1_def_id, impl2_def_id, result) ;
178
+ result
171
179
}
172
180
173
181
/// Attempt to fulfill all obligations of `target_impl` after unification with
@@ -225,3 +233,23 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
225
233
}
226
234
} )
227
235
}
236
+
237
+ pub struct SpecializesCache {
238
+ map : FnvHashMap < ( DefId , DefId ) , bool >
239
+ }
240
+
241
+ impl SpecializesCache {
242
+ pub fn new ( ) -> Self {
243
+ SpecializesCache {
244
+ map : FnvHashMap ( )
245
+ }
246
+ }
247
+
248
+ pub fn check ( & self , a : DefId , b : DefId ) -> Option < bool > {
249
+ self . map . get ( & ( a, b) ) . cloned ( )
250
+ }
251
+
252
+ pub fn insert ( & mut self , a : DefId , b : DefId , result : bool ) {
253
+ self . map . insert ( ( a, b) , result) ;
254
+ }
255
+ }
0 commit comments