@@ -752,7 +752,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
752
752
}
753
753
754
754
self . assemble_candidates_from_projected_tys ( obligation, & mut candidates) ;
755
- try!( self . assemble_candidates_from_caller_bounds ( obligation , & mut candidates) ) ;
755
+ try!( self . assemble_candidates_from_caller_bounds ( stack , & mut candidates) ) ;
756
756
debug ! ( "candidate list size: {}" , candidates. vec. len( ) ) ;
757
757
Ok ( candidates)
758
758
}
@@ -889,13 +889,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
889
889
/// supplied to find out whether it is listed among them.
890
890
///
891
891
/// Never affects inference environment.
892
- fn assemble_candidates_from_caller_bounds ( & mut self ,
893
- obligation : & TraitObligation < ' tcx > ,
894
- candidates : & mut SelectionCandidateSet < ' tcx > )
895
- -> Result < ( ) , SelectionError < ' tcx > >
892
+ fn assemble_candidates_from_caller_bounds < ' o > ( & mut self ,
893
+ stack : & TraitObligationStack < ' o , ' tcx > ,
894
+ candidates : & mut SelectionCandidateSet < ' tcx > )
895
+ -> Result < ( ) , SelectionError < ' tcx > >
896
896
{
897
897
debug ! ( "assemble_candidates_from_caller_bounds({})" ,
898
- obligation. repr( self . tcx( ) ) ) ;
898
+ stack . obligation. repr( self . tcx( ) ) ) ;
899
899
900
900
let caller_trait_refs: Vec < _ > =
901
901
self . param_env ( ) . caller_bounds . predicates . iter ( )
@@ -908,8 +908,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
908
908
909
909
let matching_bounds =
910
910
all_bounds. filter (
911
- |bound| self . infcx . probe (
912
- |_| self . match_poly_trait_ref ( obligation, bound. clone ( ) ) ) . is_ok ( ) ) ;
911
+ |bound| self . evaluate_where_clause ( stack, bound. clone ( ) ) . may_apply ( ) ) ;
913
912
914
913
let param_candidates =
915
914
matching_bounds. map ( |bound| ParamCandidate ( bound) ) ;
@@ -919,6 +918,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
919
918
Ok ( ( ) )
920
919
}
921
920
921
+ fn evaluate_where_clause < ' o > ( & mut self ,
922
+ stack : & TraitObligationStack < ' o , ' tcx > ,
923
+ where_clause_trait_ref : ty:: PolyTraitRef < ' tcx > )
924
+ -> EvaluationResult < ' tcx >
925
+ {
926
+ self . infcx ( ) . probe ( move |_| {
927
+ match self . match_where_clause_trait_ref ( stack. obligation , where_clause_trait_ref) {
928
+ Ok ( obligations) => {
929
+ self . evaluate_predicates_recursively ( Some ( stack) , obligations. iter ( ) )
930
+ }
931
+ Err ( ( ) ) => {
932
+ EvaluatedToErr ( Unimplemented )
933
+ }
934
+ }
935
+ } )
936
+ }
937
+
922
938
/// Check for the artificial impl that the compiler will create for an obligation like `X :
923
939
/// FnMut<..>` where `X` is an unboxed closure type.
924
940
///
@@ -1145,6 +1161,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1145
1161
candidate_j : & SelectionCandidate < ' tcx > )
1146
1162
-> bool
1147
1163
{
1164
+ if candidate_i == candidate_j {
1165
+ return true ;
1166
+ }
1167
+
1148
1168
match ( candidate_i, candidate_j) {
1149
1169
( & ImplCandidate ( impl_def_id) , & ParamCandidate ( ref bound) ) => {
1150
1170
debug ! ( "Considering whether to drop param {} in favor of impl {}" ,
@@ -1184,8 +1204,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1184
1204
// the where clauses are in scope.
1185
1205
true
1186
1206
}
1207
+ ( & ParamCandidate ( ref bound1) , & ParamCandidate ( ref bound2) ) => {
1208
+ self . infcx . probe ( |_| {
1209
+ let bound1 =
1210
+ project:: normalize_with_depth ( self ,
1211
+ stack. obligation . cause . clone ( ) ,
1212
+ stack. obligation . recursion_depth +1 ,
1213
+ bound1) ;
1214
+ let bound2 =
1215
+ project:: normalize_with_depth ( self ,
1216
+ stack. obligation . cause . clone ( ) ,
1217
+ stack. obligation . recursion_depth +1 ,
1218
+ bound2) ;
1219
+ let origin =
1220
+ infer:: RelateOutputImplTypes ( stack. obligation . cause . span ) ;
1221
+ self . infcx
1222
+ . sub_poly_trait_refs ( false , origin, bound1. value , bound2. value )
1223
+ . is_ok ( )
1224
+ } )
1225
+ }
1187
1226
_ => {
1188
- * candidate_i == * candidate_j
1227
+ false
1189
1228
}
1190
1229
}
1191
1230
}
@@ -1567,8 +1606,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1567
1606
}
1568
1607
1569
1608
ParamCandidate ( param) => {
1570
- self . confirm_param_candidate ( obligation, param) ;
1571
- Ok ( VtableParam )
1609
+ let obligations = self . confirm_param_candidate ( obligation, param) ;
1610
+ Ok ( VtableParam ( obligations ) )
1572
1611
}
1573
1612
1574
1613
ImplCandidate ( impl_def_id) => {
@@ -1595,7 +1634,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1595
1634
1596
1635
ProjectionCandidate => {
1597
1636
self . confirm_projection_candidate ( obligation) ;
1598
- Ok ( VtableParam )
1637
+ Ok ( VtableParam ( Vec :: new ( ) ) )
1599
1638
}
1600
1639
}
1601
1640
}
@@ -1616,6 +1655,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1616
1655
fn confirm_param_candidate ( & mut self ,
1617
1656
obligation : & TraitObligation < ' tcx > ,
1618
1657
param : ty:: PolyTraitRef < ' tcx > )
1658
+ -> Vec < PredicateObligation < ' tcx > >
1619
1659
{
1620
1660
debug ! ( "confirm_param_candidate({},{})" ,
1621
1661
obligation. repr( self . tcx( ) ) ,
@@ -1625,11 +1665,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1625
1665
// where-clause trait-ref could be unified with the obligation
1626
1666
// trait-ref. Repeat that unification now without any
1627
1667
// transactional boundary; it should not fail.
1628
- match self . confirm_poly_trait_refs ( obligation. cause . clone ( ) ,
1629
- obligation. predicate . to_poly_trait_ref ( ) ,
1630
- param. clone ( ) ) {
1631
- Ok ( ( ) ) => { }
1632
- Err ( _) => {
1668
+ match self . match_where_clause_trait_ref ( obligation, param. clone ( ) ) {
1669
+ Ok ( obligations) => obligations,
1670
+ Err ( ( ) ) => {
1633
1671
self . tcx ( ) . sess . bug (
1634
1672
format ! ( "Where clause `{}` was applicable to `{}` but now is not" ,
1635
1673
param. repr( self . tcx( ) ) ,
@@ -2056,19 +2094,43 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
2056
2094
} )
2057
2095
}
2058
2096
2097
+ /// Normalize `where_clause_trait_ref` and try to match it against
2098
+ /// `obligation`. If successful, return any predicates that
2099
+ /// result from the normalization. Normalization is necessary
2100
+ /// because where-clauses are stored in the parameter environment
2101
+ /// unnormalized.
2102
+ fn match_where_clause_trait_ref ( & mut self ,
2103
+ obligation : & TraitObligation < ' tcx > ,
2104
+ where_clause_trait_ref : ty:: PolyTraitRef < ' tcx > )
2105
+ -> Result < Vec < PredicateObligation < ' tcx > > , ( ) >
2106
+ {
2107
+ let where_clause_trait_ref =
2108
+ project:: normalize_with_depth ( self ,
2109
+ obligation. cause . clone ( ) ,
2110
+ obligation. recursion_depth +1 ,
2111
+ & where_clause_trait_ref) ;
2112
+
2113
+ let ( ) =
2114
+ try!( self . match_poly_trait_ref ( obligation, where_clause_trait_ref. value . clone ( ) ) ) ;
2115
+
2116
+ Ok ( where_clause_trait_ref. obligations )
2117
+ }
2118
+
2119
+ /// Returns `Ok` if `poly_trait_ref` being true implies that the
2120
+ /// obligation is satisfied.
2059
2121
fn match_poly_trait_ref ( & mut self ,
2060
2122
obligation : & TraitObligation < ' tcx > ,
2061
- where_clause_trait_ref : ty:: PolyTraitRef < ' tcx > )
2123
+ poly_trait_ref : ty:: PolyTraitRef < ' tcx > )
2062
2124
-> Result < ( ) , ( ) >
2063
2125
{
2064
- debug ! ( "match_poly_trait_ref: obligation={} where_clause_trait_ref ={}" ,
2126
+ debug ! ( "match_poly_trait_ref: obligation={} poly_trait_ref ={}" ,
2065
2127
obligation. repr( self . tcx( ) ) ,
2066
- where_clause_trait_ref . repr( self . tcx( ) ) ) ;
2128
+ poly_trait_ref . repr( self . tcx( ) ) ) ;
2067
2129
2068
2130
let origin = infer:: RelateOutputImplTypes ( obligation. cause . span ) ;
2069
2131
match self . infcx . sub_poly_trait_refs ( false ,
2070
2132
origin,
2071
- where_clause_trait_ref ,
2133
+ poly_trait_ref ,
2072
2134
obligation. predicate . to_poly_trait_ref ( ) ) {
2073
2135
Ok ( ( ) ) => Ok ( ( ) ) ,
2074
2136
Err ( _) => Err ( ( ) ) ,
0 commit comments