@@ -645,6 +645,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
645
645
}
646
646
647
647
let mut candidates = candidate_set. vec ;
648
+ let candidate;
648
649
649
650
debug ! ( "assembled {} candidates for {}: {}" ,
650
651
candidates. len( ) ,
@@ -678,39 +679,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
678
679
candidates. retain ( |c| self . winnow_candidate ( stack, c) . may_apply ( ) )
679
680
}
680
681
681
- // If the predicate is fully known, there should be only one
682
- // matching candidate by coherence. However, there may also be
683
- // other candidates from impls (see the doc-comment for
684
- // Candidate). Pick one candidate to use. This is somewhat
685
- // wrong around regions.
686
- if candidates. len ( ) > 1 && !stack. obligation . predicate . has_ty_infer ( ) {
687
- let mut i = 0 ;
688
- while i < candidates. len ( ) {
689
- let is_dup =
690
- ( 0 ..candidates. len ( ) )
691
- . filter ( |& j| i != j)
692
- . any ( |j| self . candidate_should_be_dropped_in_favor_of ( & candidates[ i] ,
693
- & candidates[ j] ) ) ;
694
- if is_dup {
695
- debug ! ( "Dropping candidate #{}/{}: {}" ,
696
- i, candidates. len( ) , candidates[ i] . repr( self . tcx( ) ) ) ;
697
- candidates. swap_remove ( i) ;
698
- } else {
699
- debug ! ( "Retaining candidate #{}/{}: {}" ,
700
- i, candidates. len( ) , candidates[ i] . repr( self . tcx( ) ) ) ;
701
- i += 1 ;
702
- }
703
- }
704
- }
705
-
706
- // If there are *STILL* multiple candidates, give up and
707
- // report ambiguity.
708
- if candidates. len ( ) > 1 {
709
- debug ! ( "multiple matches, ambig" ) ;
710
- return Ok ( None ) ;
711
- }
712
-
713
-
714
682
// If there are *NO* candidates, that there are no impls --
715
683
// that we know of, anyway. Note that in the case where there
716
684
// are unbound type variables within the obligation, it might
@@ -724,22 +692,65 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
724
692
return Err ( Unimplemented ) ;
725
693
}
726
694
727
- // Just one candidate left.
728
- let candidate = candidates. pop ( ) . unwrap ( ) ;
729
-
730
- match candidate {
731
- ImplCandidate ( def_id) => {
732
- match ty:: trait_impl_polarity ( self . tcx ( ) , def_id) {
733
- Some ( ast:: ImplPolarity :: Negative ) => return Err ( Unimplemented ) ,
734
- _ => { }
695
+ let candidate;
696
+ if let Some ( c) = self . find_sure_clause ( & stack. obligation , & candidates) {
697
+ // If we have a projection/where-clause candidate that
698
+ // surely matches, go ahead and pick it. There can be other
699
+ // candidates that match, but the clause will transform into
700
+ // the right one at monomorphization-time.
701
+ candidate = candidates. swap_remove ( c)
702
+ } else {
703
+ candidate = candidates. pop ( ) . unwrap ( ) ;
704
+
705
+ // If there are *still* multiple distinct candidates,
706
+ // report ambiguity.
707
+ for c in candidates {
708
+ if c != candidate {
709
+ debug ! ( "multiple matches, ambig" ) ;
710
+ return Ok ( None ) ;
735
711
}
736
712
}
737
- _ => { }
713
+ }
714
+
715
+ if let ImplCandidate ( def_id) = candidate {
716
+ let polarity = ty:: trait_impl_polarity ( self . tcx ( ) , def_id) ;
717
+ if polarity == Some ( ast:: ImplPolarity :: Negative ) {
718
+ return Err ( Unimplemented ) ;
719
+ }
738
720
}
739
721
740
722
Ok ( Some ( candidate) )
741
723
}
742
724
725
+ /// Return the index of a where clause/projection that surely matches out
726
+ /// of cs, if any exists.
727
+ ///
728
+ /// This is somewhat wrong as it does not take regions into account.
729
+ fn find_sure_candidate( & self ,
730
+ obligation : & TraitObligation < ' tcx > ,
731
+ cs : & [ SelectionCandidate < ' tcx > ] )
732
+ -> Option < usize >
733
+ {
734
+ let sure_projection = None ;
735
+ let sure_impl = None ;
736
+ for ( i, candidate) in cs. iter ( ) . enumerate ( ) {
737
+ match candidate {
738
+ & ErrorCandidate => return None ,
739
+ & ProjectionCandidate => {
740
+ // if let Ok(_) = self.match_where_
741
+ } ,
742
+ & ImplCandidate ( iid) => {
743
+ if let Ok ( ..) = self . infcx . can_equate (
744
+ & obligation. predicate . trait_ref . 0 ,
745
+ &
746
+ } ,
747
+ _ => { }
748
+ }
749
+ }
750
+
751
+ sure_projection. or ( sure_impl)
752
+ }
753
+
743
754
fn pick_candidate_cache ( & self ) -> & SelectionCache <' tcx> {
744
755
// If there are any where-clauses in scope, then we always use
745
756
// a cache local to this particular scope. Otherwise, we
0 commit comments