@@ -747,7 +747,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
747
747
}
748
748
749
749
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) ) ;
751
751
debug ! ( "candidate list size: {}" , candidates. vec. len( ) ) ;
752
752
Ok ( candidates)
753
753
}
@@ -884,13 +884,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
884
884
/// supplied to find out whether it is listed among them.
885
885
///
886
886
/// 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 > >
891
891
{
892
892
debug ! ( "assemble_candidates_from_caller_bounds({})" ,
893
- obligation. repr( self . tcx( ) ) ) ;
893
+ stack . obligation. repr( self . tcx( ) ) ) ;
894
894
895
895
let caller_trait_refs: Vec < _ > =
896
896
self . param_env ( ) . caller_bounds . predicates . iter ( )
@@ -903,8 +903,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
903
903
904
904
let matching_bounds =
905
905
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 ( ) ) ;
908
907
909
908
let param_candidates =
910
909
matching_bounds. map ( |bound| ParamCandidate ( bound) ) ;
@@ -914,6 +913,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
914
913
Ok ( ( ) )
915
914
}
916
915
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
+
917
933
/// Check for the artificial impl that the compiler will create for an obligation like `X :
918
934
/// FnMut<..>` where `X` is an unboxed closure type.
919
935
///
@@ -1140,6 +1156,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1140
1156
candidate_j : & SelectionCandidate < ' tcx > )
1141
1157
-> bool
1142
1158
{
1159
+ if candidate_i == candidate_j {
1160
+ return true ;
1161
+ }
1162
+
1143
1163
match ( candidate_i, candidate_j) {
1144
1164
( & ImplCandidate ( impl_def_id) , & ParamCandidate ( ref bound) ) => {
1145
1165
debug ! ( "Considering whether to drop param {} in favor of impl {}" ,
@@ -1179,8 +1199,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1179
1199
// the where clauses are in scope.
1180
1200
true
1181
1201
}
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
+ }
1182
1221
_ => {
1183
- * candidate_i == * candidate_j
1222
+ false
1184
1223
}
1185
1224
}
1186
1225
}
@@ -1548,8 +1587,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1548
1587
}
1549
1588
1550
1589
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 ) )
1553
1592
}
1554
1593
1555
1594
ImplCandidate ( impl_def_id) => {
@@ -1576,7 +1615,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1576
1615
1577
1616
ProjectionCandidate => {
1578
1617
self . confirm_projection_candidate ( obligation) ;
1579
- Ok ( VtableParam )
1618
+ Ok ( VtableParam ( Vec :: new ( ) ) )
1580
1619
}
1581
1620
}
1582
1621
}
@@ -1597,6 +1636,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1597
1636
fn confirm_param_candidate ( & mut self ,
1598
1637
obligation : & TraitObligation < ' tcx > ,
1599
1638
param : ty:: PolyTraitRef < ' tcx > )
1639
+ -> Vec < PredicateObligation < ' tcx > >
1600
1640
{
1601
1641
debug ! ( "confirm_param_candidate({},{})" ,
1602
1642
obligation. repr( self . tcx( ) ) ,
@@ -1606,11 +1646,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1606
1646
// where-clause trait-ref could be unified with the obligation
1607
1647
// trait-ref. Repeat that unification now without any
1608
1648
// 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 ( ( ) ) => {
1614
1652
self . tcx ( ) . sess . bug (
1615
1653
format ! ( "Where clause `{}` was applicable to `{}` but now is not" ,
1616
1654
param. repr( self . tcx( ) ) ,
@@ -2037,19 +2075,43 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
2037
2075
} )
2038
2076
}
2039
2077
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.
2040
2102
fn match_poly_trait_ref ( & mut self ,
2041
2103
obligation : & TraitObligation < ' tcx > ,
2042
- where_clause_trait_ref : ty:: PolyTraitRef < ' tcx > )
2104
+ poly_trait_ref : ty:: PolyTraitRef < ' tcx > )
2043
2105
-> Result < ( ) , ( ) >
2044
2106
{
2045
- debug ! ( "match_poly_trait_ref: obligation={} where_clause_trait_ref ={}" ,
2107
+ debug ! ( "match_poly_trait_ref: obligation={} poly_trait_ref ={}" ,
2046
2108
obligation. repr( self . tcx( ) ) ,
2047
- where_clause_trait_ref . repr( self . tcx( ) ) ) ;
2109
+ poly_trait_ref . repr( self . tcx( ) ) ) ;
2048
2110
2049
2111
let origin = infer:: RelateOutputImplTypes ( obligation. cause . span ) ;
2050
2112
match self . infcx . sub_poly_trait_refs ( false ,
2051
2113
origin,
2052
- where_clause_trait_ref ,
2114
+ poly_trait_ref ,
2053
2115
obligation. predicate . to_poly_trait_ref ( ) ) {
2054
2116
Ok ( ( ) ) => Ok ( ( ) ) ,
2055
2117
Err ( _) => Err ( ( ) ) ,
0 commit comments