@@ -28,6 +28,8 @@ use middle::ty_fold::TypeFoldable;
28
28
use middle:: typeck:: check:: regionmanip;
29
29
use middle:: typeck:: infer;
30
30
use middle:: typeck:: infer:: { InferCtxt , TypeSkolemizer } ;
31
+ use std:: cell:: RefCell ;
32
+ use std:: collections:: hashmap:: HashMap ;
31
33
use std:: rc:: Rc ;
32
34
use syntax:: ast;
33
35
use util:: ppaux:: Repr ;
@@ -46,15 +48,15 @@ struct ObligationStack<'prev> {
46
48
previous : Option < & ' prev ObligationStack < ' prev > >
47
49
}
48
50
49
- // pub struct SelectionCache {
50
- // hashmap: RefCell<HashMap<CacheKey, Candidate>>,
51
- // }
51
+ pub struct SelectionCache {
52
+ hashmap : RefCell < HashMap < CacheKey , SelectionResult < Candidate > > > ,
53
+ }
52
54
53
- // #[deriving(Hash,Eq,PartialEq)]
54
- // struct CacheKey {
55
- // trait_def_id: ast::DefId,
56
- // skol_obligation_self_ty: ty::t,
57
- // }
55
+ #[ deriving( Hash , Eq , PartialEq ) ]
56
+ struct CacheKey {
57
+ trait_def_id : ast:: DefId ,
58
+ skol_obligation_self_ty : ty:: t ,
59
+ }
58
60
59
61
#[ deriving( PartialEq , Eq ) ]
60
62
enum MatchResult < T > {
@@ -309,14 +311,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
309
311
// First, check the cache.
310
312
match self . check_candidate_cache ( stack. obligation , stack. skol_obligation_self_ty ) {
311
313
Some ( c) => {
312
- return Ok ( Some ( c) ) ;
314
+ debug ! ( "check_candidate_cache(obligation={}, skol_obligation_self_ty={}, \
315
+ candidate={})",
316
+ stack. obligation. trait_ref. def_id,
317
+ stack. skol_obligation_self_ty. repr( self . tcx( ) ) ,
318
+ c. repr( self . tcx( ) ) ) ;
319
+ return c;
313
320
}
314
321
None => { }
315
322
}
316
323
317
324
// If no match, compute result and insert into cache.
318
325
let result = self . pick_candidate ( stack) ;
319
- // self.insert_candidate_cache(obligation, skol_obligation_self_ty, result.clone());
326
+ self . insert_candidate_cache ( stack. obligation ,
327
+ stack. skol_obligation_self_ty ,
328
+ result. clone ( ) ) ;
320
329
result
321
330
}
322
331
@@ -330,9 +339,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
330
339
331
340
let mut candidates = try!( self . assemble_candidates ( stack) ) ;
332
341
333
- debug ! ( "candidate_from_obligation: {} candidates for {}" ,
334
- candidates. len( ) ,
335
- stack. repr( self . tcx( ) ) ) ;
342
+ debug ! ( "assembled {} candidates for {}" ,
343
+ candidates. len( ) , stack. repr( self . tcx( ) ) ) ;
336
344
337
345
// Examine candidates to determine outcome. Ideally we will
338
346
// have exactly one candidate that is definitively applicable.
@@ -348,55 +356,63 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
348
356
debug ! ( "0 matches, unimpl" ) ;
349
357
Err ( Unimplemented )
350
358
} else {
351
- debug ! ( "candidate_from_obligation({}) -> 0 matches, ambig" ,
352
- stack. repr( self . tcx( ) ) ) ;
359
+ debug ! ( "0 matches, ambig" ) ;
353
360
Ok ( None )
354
- } ;
355
- }
356
-
357
- if candidates. len ( ) > 1 {
361
+ }
362
+ } else if candidates. len ( ) > 1 {
358
363
// Ambiguity. Possibly we should report back more
359
364
// information on the potential candidates so we can give
360
365
// a better error message.
361
- debug ! ( "candidate_from_obligation({}) -> multiple matches, ambig" ,
362
- stack. repr( self . tcx( ) ) ) ;
363
-
364
- return Ok ( None ) ;
366
+ debug ! ( "multiple matches, ambig" ) ;
367
+ Ok ( None )
368
+ } else {
369
+ let candidate = candidates. pop ( ) . unwrap ( ) ;
370
+ Ok ( Some ( candidate) )
365
371
}
372
+ }
366
373
367
- let candidate = candidates. pop ( ) . unwrap ( ) ;
368
- self . insert_candidate_cache ( stack. obligation ,
369
- stack. skol_obligation_self_ty ,
370
- candidate. clone ( ) ) ;
371
- Ok ( Some ( candidate) )
374
+ fn pick_candidate_cache ( & self ,
375
+ _obligation : & Obligation ,
376
+ skol_obligation_self_ty : ty:: t )
377
+ -> & SelectionCache
378
+ {
379
+ if
380
+ ty:: type_has_self ( skol_obligation_self_ty) ||
381
+ ty:: type_has_params ( skol_obligation_self_ty)
382
+ {
383
+ & self . param_env . selection_cache
384
+ } else {
385
+ & self . tcx ( ) . selection_cache
386
+ }
372
387
}
373
388
374
389
fn check_candidate_cache ( & mut self ,
375
- _obligation : & Obligation ,
376
- _skol_obligation_self_ty : ty:: t )
377
- -> Option < Candidate >
390
+ obligation : & Obligation ,
391
+ skol_obligation_self_ty : ty:: t )
392
+ -> Option < SelectionResult < Candidate > >
378
393
{
379
- // let cache_key = CacheKey::new (obligation.trait_ref.def_id,
380
- // skol_obligation_self_ty);
381
- // let hashmap = self.tcx().selection_cache.hashmap.borrow( );
382
- // hashmap.find(&cache_key).map(|c| (*c).clone())
383
- None
394
+ let cache = self . pick_candidate_cache ( obligation, skol_obligation_self_ty ) ;
395
+ let cache_key = CacheKey :: new ( obligation . trait_ref . def_id ,
396
+ skol_obligation_self_ty ) ;
397
+ let hashmap = cache . hashmap . borrow ( ) ;
398
+ hashmap . find ( & cache_key ) . map ( |c| ( * c ) . clone ( ) )
384
399
}
385
400
386
401
fn insert_candidate_cache ( & mut self ,
387
- _obligation : & Obligation ,
388
- _skol_obligation_self_ty : ty:: t ,
389
- _candidate : Candidate )
402
+ obligation : & Obligation ,
403
+ skol_obligation_self_ty : ty:: t ,
404
+ candidate : SelectionResult < Candidate > )
390
405
{
391
- // FIXME -- Enable caching. I think the right place to put the cache
392
- // is in the ParameterEnvironment, not the tcx, because otherwise
393
- // when there are distinct where clauses in scope the cache can get
394
- // confused.
395
- //
396
- //let cache_key = CacheKey::new(obligation.trait_ref.def_id,
397
- // skol_obligation_self_ty);
398
- //let mut hashmap = self.tcx().selection_cache.hashmap.borrow_mut();
399
- //hashmap.insert(cache_key, candidate);
406
+ debug ! ( "insert_candidate_cache(obligation={}, skol_obligation_self_ty={}, candidate={})" ,
407
+ obligation. trait_ref. def_id,
408
+ skol_obligation_self_ty. repr( self . tcx( ) ) ,
409
+ candidate. repr( self . tcx( ) ) ) ;
410
+
411
+ let cache = self . pick_candidate_cache ( obligation, skol_obligation_self_ty) ;
412
+ let cache_key = CacheKey :: new ( obligation. trait_ref . def_id ,
413
+ skol_obligation_self_ty) ;
414
+ let mut hashmap = cache. hashmap . borrow_mut ( ) ;
415
+ hashmap. insert ( cache_key, candidate) ;
400
416
}
401
417
402
418
fn assemble_candidates ( & mut self ,
@@ -1487,6 +1503,14 @@ impl Repr for ImplCandidate {
1487
1503
}
1488
1504
}
1489
1505
1506
+ impl SelectionCache {
1507
+ pub fn new ( ) -> SelectionCache {
1508
+ SelectionCache {
1509
+ hashmap : RefCell :: new ( HashMap :: new ( ) )
1510
+ }
1511
+ }
1512
+ }
1513
+
1490
1514
impl < ' o > ObligationStack < ' o > {
1491
1515
fn iter ( & self ) -> Option < & ObligationStack > {
1492
1516
Some ( self )
@@ -1515,22 +1539,14 @@ impl<'o> Repr for ObligationStack<'o> {
1515
1539
}
1516
1540
}
1517
1541
1518
- // impl SelectionCache {
1519
- // pub fn new() -> SelectionCache {
1520
- // SelectionCache {
1521
- // hashmap: RefCell::new(HashMap::new())
1522
- // }
1523
- // }
1524
- // }
1525
-
1526
- // impl CacheKey {
1527
- // pub fn new(trait_def_id: ast::DefId,
1528
- // skol_obligation_self_ty: ty::t)
1529
- // -> CacheKey
1530
- // {
1531
- // CacheKey {
1532
- // trait_def_id: trait_def_id,
1533
- // skol_obligation_self_ty: skol_obligation_self_ty
1534
- // }
1535
- // }
1536
- // }
1542
+ impl CacheKey {
1543
+ pub fn new ( trait_def_id : ast:: DefId ,
1544
+ skol_obligation_self_ty : ty:: t )
1545
+ -> CacheKey
1546
+ {
1547
+ CacheKey {
1548
+ trait_def_id : trait_def_id,
1549
+ skol_obligation_self_ty : skol_obligation_self_ty
1550
+ }
1551
+ }
1552
+ }
0 commit comments