@@ -206,7 +206,7 @@ enum SelectionCandidate<'tcx> {
206
206
207
207
/// This is a trait matching with a projected type as `Self`, and
208
208
/// we found an applicable bound in the trait definition.
209
- ProjectionCandidate ,
209
+ ProjectionCandidate ( ty :: PolyTraitRef < ' tcx > ) ,
210
210
211
211
/// Implementation of a `Fn`-family trait by one of the anonymous types
212
212
/// generated for a `||` expression. The ty::ClosureKind informs the
@@ -238,7 +238,9 @@ impl<'a, 'tcx> ty::Lift<'tcx> for SelectionCandidate<'a> {
238
238
DefaultImplObjectCandidate ( def_id) => {
239
239
DefaultImplObjectCandidate ( def_id)
240
240
}
241
- ProjectionCandidate => ProjectionCandidate ,
241
+ ProjectionCandidate ( ref bound) => {
242
+ return tcx. lift ( bound) . map ( ProjectionCandidate ) ;
243
+ }
242
244
FnPointerCandidate => FnPointerCandidate ,
243
245
ObjectCandidate => ObjectCandidate ,
244
246
BuiltinObjectCandidate => BuiltinObjectCandidate ,
@@ -1170,22 +1172,20 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
1170
1172
debug ! ( "assemble_candidates_for_projected_tys: trait_def_id={:?}" ,
1171
1173
trait_def_id) ;
1172
1174
1173
- let result = self . probe ( |this, snapshot| {
1175
+ self . in_snapshot ( |this, snapshot| {
1174
1176
this. match_projection_obligation_against_bounds_from_trait ( obligation,
1175
- snapshot)
1177
+ candidates,
1178
+ snapshot) ;
1176
1179
} ) ;
1177
-
1178
- if result {
1179
- candidates. vec . push ( ProjectionCandidate ) ;
1180
- }
1181
1180
}
1182
1181
1183
1182
fn match_projection_obligation_against_bounds_from_trait (
1184
1183
& mut self ,
1185
1184
obligation : & TraitObligation < ' tcx > ,
1185
+ candidates : & mut SelectionCandidateSet < ' tcx > ,
1186
1186
snapshot : & infer:: CombinedSnapshot )
1187
- -> bool
1188
1187
{
1188
+
1189
1189
let poly_trait_predicate =
1190
1190
self . infcx ( ) . resolve_type_vars_if_possible ( & obligation. predicate ) ;
1191
1191
let ( skol_trait_predicate, skol_map) =
@@ -1215,36 +1215,19 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
1215
1215
bounds={:?}",
1216
1216
bounds) ;
1217
1217
1218
- let matching_bound =
1218
+ let matching_bounds =
1219
1219
util:: elaborate_predicates ( self . tcx ( ) , bounds. predicates . into_vec ( ) )
1220
1220
. filter_to_traits ( )
1221
- . find (
1221
+ . filter (
1222
1222
|bound| self . probe (
1223
1223
|this, _| this. match_projection ( obligation,
1224
1224
bound. clone ( ) ,
1225
1225
skol_trait_predicate. trait_ref . clone ( ) ,
1226
1226
& skol_map,
1227
- snapshot) ) ) ;
1228
-
1229
- debug ! ( "match_projection_obligation_against_bounds_from_trait: \
1230
- matching_bound={:?}",
1231
- matching_bound) ;
1232
- match matching_bound {
1233
- None => false ,
1234
- Some ( bound) => {
1235
- // Repeat the successful match, if any, this time outside of a probe.
1236
- let result = self . match_projection ( obligation,
1237
- bound,
1238
- skol_trait_predicate. trait_ref . clone ( ) ,
1239
- & skol_map,
1240
- snapshot) ;
1241
-
1242
- self . infcx . pop_skolemized ( skol_map, snapshot) ;
1227
+ snapshot) ) )
1228
+ . map ( |bound| ProjectionCandidate ( bound) ) ;
1243
1229
1244
- assert ! ( result) ;
1245
- true
1246
- }
1247
- }
1230
+ candidates. vec . extend ( matching_bounds) ;
1248
1231
}
1249
1232
1250
1233
fn match_projection ( & mut self ,
@@ -1684,7 +1667,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
1684
1667
1685
1668
match other. candidate {
1686
1669
ObjectCandidate |
1687
- ParamCandidate ( _) | ProjectionCandidate => match victim. candidate {
1670
+ ParamCandidate ( _) | ProjectionCandidate ( .. ) => match victim. candidate {
1688
1671
DefaultImplCandidate ( ..) => {
1689
1672
bug ! (
1690
1673
"default implementations shouldn't be recorded \
@@ -1701,11 +1684,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
1701
1684
// for impls.
1702
1685
true
1703
1686
}
1704
- ObjectCandidate |
1705
- ProjectionCandidate => {
1706
- // Arbitrarily give param candidates priority
1707
- // over projection and object candidates.
1708
- true
1687
+ // Arbitrarily give param candidates priority
1688
+ // over projection and object candidates.
1689
+ ObjectCandidate => true ,
1690
+ ProjectionCandidate ( ..) => {
1691
+ if let ProjectionCandidate ( ..) = other. candidate {
1692
+ // Not identical, since equality is checked at the start
1693
+ false
1694
+ } else {
1695
+ true
1696
+ }
1709
1697
} ,
1710
1698
ParamCandidate ( ..) => false ,
1711
1699
} ,
@@ -2056,8 +2044,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
2056
2044
Ok ( VtableFnPointer ( data) )
2057
2045
}
2058
2046
2059
- ProjectionCandidate => {
2060
- self . confirm_projection_candidate ( obligation) ;
2047
+ ProjectionCandidate ( bound ) => {
2048
+ self . confirm_projection_candidate ( obligation, bound ) ;
2061
2049
Ok ( VtableParam ( Vec :: new ( ) ) )
2062
2050
}
2063
2051
@@ -2069,14 +2057,27 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
2069
2057
}
2070
2058
2071
2059
fn confirm_projection_candidate ( & mut self ,
2072
- obligation : & TraitObligation < ' tcx > )
2060
+ obligation : & TraitObligation < ' tcx > ,
2061
+ matching_bound : ty:: PolyTraitRef < ' tcx > )
2073
2062
{
2063
+ debug ! ( "confirm_projection_candidate: matching_bound={:?}" , matching_bound) ;
2064
+
2074
2065
self . in_snapshot ( |this, snapshot| {
2075
- let result =
2076
- this. match_projection_obligation_against_bounds_from_trait ( obligation,
2077
- snapshot) ;
2066
+ let poly_trait_predicate =
2067
+ this. infcx ( ) . resolve_type_vars_if_possible ( & obligation. predicate ) ;
2068
+ let ( skol_trait_predicate, skol_map) =
2069
+ this. infcx ( ) . skolemize_late_bound_regions ( & poly_trait_predicate, snapshot) ;
2070
+
2071
+ // Repeat the successful match, if any, this time outside of a probe.
2072
+ let result = this. match_projection ( obligation,
2073
+ matching_bound,
2074
+ skol_trait_predicate. trait_ref . clone ( ) ,
2075
+ & skol_map,
2076
+ snapshot) ;
2077
+ this. infcx . pop_skolemized ( skol_map, snapshot) ;
2078
+
2078
2079
assert ! ( result) ;
2079
- } )
2080
+ } ) ;
2080
2081
}
2081
2082
2082
2083
fn confirm_param_candidate ( & mut self ,
0 commit comments