@@ -526,9 +526,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
526
526
527
527
// If no match, compute result and insert into cache.
528
528
let candidate = self . candidate_from_obligation_no_cache ( stack) ;
529
- debug ! ( "CACHE MISS: cache_fresh_trait_pred={}, candidate={}" ,
530
- cache_fresh_trait_pred. repr( self . tcx( ) ) , candidate. repr( self . tcx( ) ) ) ;
531
- self . insert_candidate_cache ( cache_fresh_trait_pred, candidate. clone ( ) ) ;
529
+
530
+ if self . should_update_candidate_cache ( & cache_fresh_trait_pred, & candidate) {
531
+ debug ! ( "CACHE MISS: cache_fresh_trait_pred={}, candidate={}" ,
532
+ cache_fresh_trait_pred. repr( self . tcx( ) ) , candidate. repr( self . tcx( ) ) ) ;
533
+ self . insert_candidate_cache ( cache_fresh_trait_pred, candidate. clone ( ) ) ;
534
+ }
535
+
532
536
candidate
533
537
}
534
538
@@ -705,6 +709,47 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
705
709
hashmap. insert ( cache_fresh_trait_pred. 0 . trait_ref . clone ( ) , candidate) ;
706
710
}
707
711
712
+ fn should_update_candidate_cache ( & mut self ,
713
+ cache_fresh_trait_pred : & ty:: PolyTraitPredicate < ' tcx > ,
714
+ candidate : & SelectionResult < ' tcx , SelectionCandidate < ' tcx > > )
715
+ -> bool
716
+ {
717
+ // In general, it's a good idea to cache results, even
718
+ // ambigious ones, to save us some trouble later. But we have
719
+ // to be careful not to cache results that could be
720
+ // invalidated later by advances in inference. Normally, this
721
+ // is not an issue, because any inference variables whose
722
+ // types are not yet bound are "freshened" in the cache key,
723
+ // which means that if we later get the same request once that
724
+ // type variable IS bound, we'll have a different cache key.
725
+ // For example, if we have `Vec<_#0t> : Foo`, and `_#0t` is
726
+ // not yet known, we may cache the result as `None`. But if
727
+ // later `_#0t` is bound to `Bar`, then when we freshen we'll
728
+ // have `Vec<Bar> : Foo` as the cache key.
729
+ //
730
+ // HOWEVER, it CAN happen that we get an ambiguity result in
731
+ // one particular case around closures where the cache key
732
+ // would not change. That is when the precise types of the
733
+ // upvars that a closure references have not yet been figured
734
+ // out (i.e., because it is not yet known if they are captured
735
+ // by ref, and if by ref, what kind of ref). In these cases,
736
+ // when matching a builtin bound, we will yield back an
737
+ // ambiguous result. But the *cache key* is just the closure type,
738
+ // it doesn't capture the state of the upvar computation.
739
+ //
740
+ // To avoid this trap, just don't cache ambiguous results if
741
+ // the self-type contains no inference byproducts (that really
742
+ // shouldn't happen in other circumstances anyway, given
743
+ // coherence).
744
+
745
+ match * candidate {
746
+ Ok ( Some ( _) ) | Err ( _) => true ,
747
+ Ok ( None ) => {
748
+ cache_fresh_trait_pred. 0 . input_types ( ) . iter ( ) . any ( |& t| ty:: type_has_ty_infer ( t) )
749
+ }
750
+ }
751
+ }
752
+
708
753
fn assemble_candidates < ' o > ( & mut self ,
709
754
stack : & TraitObligationStack < ' o , ' tcx > )
710
755
-> Result < SelectionCandidateSet < ' tcx > , SelectionError < ' tcx > >
@@ -788,6 +833,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
788
833
// FIXME(#20297) -- being strict about this can cause
789
834
// inference failures with BorrowFrom, which is
790
835
// unfortunate. Can we do better here?
836
+ debug ! ( "assemble_candidates_for_projected_tys: ambiguous self-type" ) ;
791
837
candidates. ambiguous = true ;
792
838
return ;
793
839
}
@@ -962,6 +1008,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
962
1008
let ( closure_def_id, substs) = match self_ty. sty {
963
1009
ty:: ty_unboxed_closure( id, _, ref substs) => ( id, substs. clone ( ) ) ,
964
1010
ty:: ty_infer( ty:: TyVar ( _) ) => {
1011
+ debug ! ( "assemble_unboxed_closure_candidates: ambiguous self-type" ) ;
965
1012
candidates. ambiguous = true ;
966
1013
return Ok ( ( ) ) ;
967
1014
}
@@ -1000,6 +1047,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1000
1047
let self_ty = self . infcx . shallow_resolve ( obligation. self_ty ( ) ) ;
1001
1048
match self_ty. sty {
1002
1049
ty:: ty_infer( ty:: TyVar ( _) ) => {
1050
+ debug ! ( "assemble_fn_pointer_candidates: ambiguous self-type" ) ;
1003
1051
candidates. ambiguous = true ; // could wind up being a fn() type
1004
1052
}
1005
1053
@@ -1270,7 +1318,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1270
1318
Ok ( ( ) )
1271
1319
}
1272
1320
Ok ( ParameterBuiltin ) => { Ok ( ( ) ) }
1273
- Ok ( AmbiguousBuiltin ) => { Ok ( candidates. ambiguous = true ) }
1321
+ Ok ( AmbiguousBuiltin ) => {
1322
+ debug ! ( "assemble_builtin_bound_candidates: ambiguous builtin" ) ;
1323
+ Ok ( candidates. ambiguous = true )
1324
+ }
1274
1325
Err ( e) => { Err ( e) }
1275
1326
}
1276
1327
}
@@ -1476,6 +1527,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1476
1527
Ok ( If ( upvars. iter ( ) . map ( |c| c. ty ) . collect ( ) ) )
1477
1528
}
1478
1529
None => {
1530
+ debug ! ( "assemble_builtin_bound_candidates: no upvar types available yet" ) ;
1479
1531
Ok ( AmbiguousBuiltin )
1480
1532
}
1481
1533
}
@@ -1512,6 +1564,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1512
1564
// Unbound type variable. Might or might not have
1513
1565
// applicable impls and so forth, depending on what
1514
1566
// those type variables wind up being bound to.
1567
+ debug ! ( "assemble_builtin_bound_candidates: ambiguous builtin" ) ;
1515
1568
Ok ( AmbiguousBuiltin )
1516
1569
}
1517
1570
0 commit comments