@@ -747,7 +747,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
747747 }
748748
749749 self . assemble_candidates_from_projected_tys ( obligation, & mut candidates) ;
750- try!( self . assemble_candidates_from_caller_bounds ( obligation , & mut candidates) ) ;
750+ try!( self . assemble_candidates_from_caller_bounds ( stack , & mut candidates) ) ;
751751 debug ! ( "candidate list size: {}" , candidates. vec. len( ) ) ;
752752 Ok ( candidates)
753753 }
@@ -884,13 +884,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
884884 /// supplied to find out whether it is listed among them.
885885 ///
886886 /// Never affects inference environment.
887- fn assemble_candidates_from_caller_bounds ( & mut self ,
888- obligation : & TraitObligation < ' tcx > ,
889- candidates : & mut SelectionCandidateSet < ' tcx > )
890- -> Result < ( ) , SelectionError < ' tcx > >
887+ fn assemble_candidates_from_caller_bounds < ' o > ( & mut self ,
888+ stack : & TraitObligationStack < ' o , ' tcx > ,
889+ candidates : & mut SelectionCandidateSet < ' tcx > )
890+ -> Result < ( ) , SelectionError < ' tcx > >
891891 {
892892 debug ! ( "assemble_candidates_from_caller_bounds({})" ,
893- obligation. repr( self . tcx( ) ) ) ;
893+ stack . obligation. repr( self . tcx( ) ) ) ;
894894
895895 let caller_trait_refs: Vec < _ > =
896896 self . param_env ( ) . caller_bounds . predicates . iter ( )
@@ -903,8 +903,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
903903
904904 let matching_bounds =
905905 all_bounds. filter (
906- |bound| self . infcx . probe (
907- |_| self . match_poly_trait_ref ( obligation, bound. clone ( ) ) ) . is_ok ( ) ) ;
906+ |bound| self . evaluate_where_clause ( stack, bound. clone ( ) ) . may_apply ( ) ) ;
908907
909908 let param_candidates =
910909 matching_bounds. map ( |bound| ParamCandidate ( bound) ) ;
@@ -914,6 +913,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
914913 Ok ( ( ) )
915914 }
916915
916+ fn evaluate_where_clause < ' o > ( & mut self ,
917+ stack : & TraitObligationStack < ' o , ' tcx > ,
918+ where_clause_trait_ref : ty:: PolyTraitRef < ' tcx > )
919+ -> EvaluationResult < ' tcx >
920+ {
921+ self . infcx ( ) . probe ( move |_| {
922+ match self . match_where_clause_trait_ref ( stack. obligation , where_clause_trait_ref) {
923+ Ok ( obligations) => {
924+ self . evaluate_predicates_recursively ( Some ( stack) , obligations. iter ( ) )
925+ }
926+ Err ( ( ) ) => {
927+ EvaluatedToErr ( Unimplemented )
928+ }
929+ }
930+ } )
931+ }
932+
917933 /// Check for the artificial impl that the compiler will create for an obligation like `X :
918934 /// FnMut<..>` where `X` is an unboxed closure type.
919935 ///
@@ -1140,6 +1156,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11401156 candidate_j : & SelectionCandidate < ' tcx > )
11411157 -> bool
11421158 {
1159+ if candidate_i == candidate_j {
1160+ return true ;
1161+ }
1162+
11431163 match ( candidate_i, candidate_j) {
11441164 ( & ImplCandidate ( impl_def_id) , & ParamCandidate ( ref bound) ) => {
11451165 debug ! ( "Considering whether to drop param {} in favor of impl {}" ,
@@ -1179,8 +1199,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11791199 // the where clauses are in scope.
11801200 true
11811201 }
1202+ ( & ParamCandidate ( ref bound1) , & ParamCandidate ( ref bound2) ) => {
1203+ self . infcx . probe ( |_| {
1204+ let bound1 =
1205+ project:: normalize_with_depth ( self ,
1206+ stack. obligation . cause . clone ( ) ,
1207+ stack. obligation . recursion_depth +1 ,
1208+ bound1) ;
1209+ let bound2 =
1210+ project:: normalize_with_depth ( self ,
1211+ stack. obligation . cause . clone ( ) ,
1212+ stack. obligation . recursion_depth +1 ,
1213+ bound2) ;
1214+ let origin =
1215+ infer:: RelateOutputImplTypes ( stack. obligation . cause . span ) ;
1216+ self . infcx
1217+ . sub_poly_trait_refs ( false , origin, bound1. value , bound2. value )
1218+ . is_ok ( )
1219+ } )
1220+ }
11821221 _ => {
1183- * candidate_i == * candidate_j
1222+ false
11841223 }
11851224 }
11861225 }
@@ -1548,8 +1587,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15481587 }
15491588
15501589 ParamCandidate ( param) => {
1551- self . confirm_param_candidate ( obligation, param) ;
1552- Ok ( VtableParam )
1590+ let obligations = self . confirm_param_candidate ( obligation, param) ;
1591+ Ok ( VtableParam ( obligations ) )
15531592 }
15541593
15551594 ImplCandidate ( impl_def_id) => {
@@ -1576,7 +1615,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15761615
15771616 ProjectionCandidate => {
15781617 self . confirm_projection_candidate ( obligation) ;
1579- Ok ( VtableParam )
1618+ Ok ( VtableParam ( Vec :: new ( ) ) )
15801619 }
15811620 }
15821621 }
@@ -1597,6 +1636,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15971636 fn confirm_param_candidate ( & mut self ,
15981637 obligation : & TraitObligation < ' tcx > ,
15991638 param : ty:: PolyTraitRef < ' tcx > )
1639+ -> Vec < PredicateObligation < ' tcx > >
16001640 {
16011641 debug ! ( "confirm_param_candidate({},{})" ,
16021642 obligation. repr( self . tcx( ) ) ,
@@ -1606,11 +1646,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
16061646 // where-clause trait-ref could be unified with the obligation
16071647 // trait-ref. Repeat that unification now without any
16081648 // transactional boundary; it should not fail.
1609- match self . confirm_poly_trait_refs ( obligation. cause . clone ( ) ,
1610- obligation. predicate . to_poly_trait_ref ( ) ,
1611- param. clone ( ) ) {
1612- Ok ( ( ) ) => { }
1613- Err ( _) => {
1649+ match self . match_where_clause_trait_ref ( obligation, param. clone ( ) ) {
1650+ Ok ( obligations) => obligations,
1651+ Err ( ( ) ) => {
16141652 self . tcx ( ) . sess . bug (
16151653 format ! ( "Where clause `{}` was applicable to `{}` but now is not" ,
16161654 param. repr( self . tcx( ) ) ,
@@ -2037,19 +2075,43 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
20372075 } )
20382076 }
20392077
2078+ /// Normalize `where_clause_trait_ref` and try to match it against
2079+ /// `obligation`. If successful, return any predicates that
2080+ /// result from the normalization. Normalization is necessary
2081+ /// because where-clauses are stored in the parameter environment
2082+ /// unnormalized.
2083+ fn match_where_clause_trait_ref ( & mut self ,
2084+ obligation : & TraitObligation < ' tcx > ,
2085+ where_clause_trait_ref : ty:: PolyTraitRef < ' tcx > )
2086+ -> Result < Vec < PredicateObligation < ' tcx > > , ( ) >
2087+ {
2088+ let where_clause_trait_ref =
2089+ project:: normalize_with_depth ( self ,
2090+ obligation. cause . clone ( ) ,
2091+ obligation. recursion_depth +1 ,
2092+ & where_clause_trait_ref) ;
2093+
2094+ let ( ) =
2095+ try!( self . match_poly_trait_ref ( obligation, where_clause_trait_ref. value . clone ( ) ) ) ;
2096+
2097+ Ok ( where_clause_trait_ref. obligations )
2098+ }
2099+
2100+ /// Returns `Ok` if `poly_trait_ref` being true implies that the
2101+ /// obligation is satisfied.
20402102 fn match_poly_trait_ref ( & mut self ,
20412103 obligation : & TraitObligation < ' tcx > ,
2042- where_clause_trait_ref : ty:: PolyTraitRef < ' tcx > )
2104+ poly_trait_ref : ty:: PolyTraitRef < ' tcx > )
20432105 -> Result < ( ) , ( ) >
20442106 {
2045- debug ! ( "match_poly_trait_ref: obligation={} where_clause_trait_ref ={}" ,
2107+ debug ! ( "match_poly_trait_ref: obligation={} poly_trait_ref ={}" ,
20462108 obligation. repr( self . tcx( ) ) ,
2047- where_clause_trait_ref . repr( self . tcx( ) ) ) ;
2109+ poly_trait_ref . repr( self . tcx( ) ) ) ;
20482110
20492111 let origin = infer:: RelateOutputImplTypes ( obligation. cause . span ) ;
20502112 match self . infcx . sub_poly_trait_refs ( false ,
20512113 origin,
2052- where_clause_trait_ref ,
2114+ poly_trait_ref ,
20532115 obligation. predicate . to_poly_trait_ref ( ) ) {
20542116 Ok ( ( ) ) => Ok ( ( ) ) ,
20552117 Err ( _) => Err ( ( ) ) ,
0 commit comments