@@ -32,6 +32,7 @@ use rustc_middle::traits::select::OverflowError;
32
32
use rustc_middle:: ty:: fold:: { TypeFoldable , TypeFolder , TypeSuperFoldable } ;
33
33
use rustc_middle:: ty:: subst:: Subst ;
34
34
use rustc_middle:: ty:: visit:: { MaxUniverse , TypeVisitable } ;
35
+ use rustc_middle:: ty:: DefIdTree ;
35
36
use rustc_middle:: ty:: { self , Term , ToPredicate , Ty , TyCtxt } ;
36
37
use rustc_span:: symbol:: sym;
37
38
@@ -70,6 +71,8 @@ enum ProjectionCandidate<'tcx> {
70
71
71
72
/// From an "impl" (or a "pseudo-impl" returned by select)
72
73
Select ( Selection < ' tcx > ) ,
74
+
75
+ ImplTraitInTrait ( ImplSourceUserDefinedData < ' tcx , PredicateObligation < ' tcx > > ) ,
73
76
}
74
77
75
78
enum ProjectionCandidateSet < ' tcx > {
@@ -1265,6 +1268,8 @@ fn project<'cx, 'tcx>(
1265
1268
1266
1269
let mut candidates = ProjectionCandidateSet :: None ;
1267
1270
1271
+ assemble_candidate_for_impl_trait_in_trait ( selcx, obligation, & mut candidates) ;
1272
+
1268
1273
// Make sure that the following procedures are kept in order. ParamEnv
1269
1274
// needs to be first because it has highest priority, and Select checks
1270
1275
// the return value of push_candidate which assumes it's ran at last.
@@ -1303,6 +1308,48 @@ fn project<'cx, 'tcx>(
1303
1308
}
1304
1309
}
1305
1310
1311
+ /// The first thing we have to do is scan through the parameter
1312
+ /// environment to see whether there are any projection predicates
1313
+ /// there that can answer this question.
1314
+ fn assemble_candidate_for_impl_trait_in_trait < ' cx , ' tcx > (
1315
+ selcx : & mut SelectionContext < ' cx , ' tcx > ,
1316
+ obligation : & ProjectionTyObligation < ' tcx > ,
1317
+ candidate_set : & mut ProjectionCandidateSet < ' tcx > ,
1318
+ ) {
1319
+ let tcx = selcx. tcx ( ) ;
1320
+ if tcx. def_kind ( obligation. predicate . item_def_id ) == DefKind :: ImplTraitPlaceholder {
1321
+ let trait_fn_def_id = tcx. parent ( obligation. predicate . item_def_id ) ;
1322
+ let trait_def_id = tcx. parent ( trait_fn_def_id) ;
1323
+ let trait_substs =
1324
+ obligation. predicate . substs . truncate_to ( tcx, tcx. generics_of ( trait_def_id) ) ;
1325
+ // FIXME(named-returns): Binders
1326
+ let trait_predicate =
1327
+ ty:: Binder :: dummy ( ty:: TraitRef { def_id : trait_def_id, substs : trait_substs } )
1328
+ . to_poly_trait_predicate ( ) ;
1329
+
1330
+ let _ =
1331
+ selcx. infcx ( ) . commit_if_ok ( |_| match selcx. select ( & obligation. with ( trait_predicate) ) {
1332
+ Ok ( Some ( super :: ImplSource :: UserDefined ( data) ) ) => {
1333
+ candidate_set. push_candidate ( ProjectionCandidate :: ImplTraitInTrait ( data) ) ;
1334
+ Ok ( ( ) )
1335
+ }
1336
+ Ok ( None ) => {
1337
+ candidate_set. mark_ambiguous ( ) ;
1338
+ return Err ( ( ) ) ;
1339
+ }
1340
+ Ok ( Some ( _) ) => {
1341
+ // Don't know enough about the impl to provide a useful signature
1342
+ return Err ( ( ) ) ;
1343
+ }
1344
+ Err ( e) => {
1345
+ debug ! ( error = ?e, "selection error" ) ;
1346
+ candidate_set. mark_error ( e) ;
1347
+ return Err ( ( ) ) ;
1348
+ }
1349
+ } ) ;
1350
+ }
1351
+ }
1352
+
1306
1353
/// The first thing we have to do is scan through the parameter
1307
1354
/// environment to see whether there are any projection predicates
1308
1355
/// there that can answer this question.
@@ -1745,6 +1792,9 @@ fn confirm_candidate<'cx, 'tcx>(
1745
1792
ProjectionCandidate :: Select ( impl_source) => {
1746
1793
confirm_select_candidate ( selcx, obligation, impl_source)
1747
1794
}
1795
+ ProjectionCandidate :: ImplTraitInTrait ( data) => {
1796
+ confirm_impl_trait_in_trait_candidate ( selcx, obligation, data)
1797
+ }
1748
1798
} ;
1749
1799
1750
1800
// When checking for cycle during evaluation, we compare predicates with
@@ -2107,6 +2157,73 @@ fn confirm_impl_candidate<'cx, 'tcx>(
2107
2157
}
2108
2158
}
2109
2159
2160
+ fn confirm_impl_trait_in_trait_candidate < ' tcx > (
2161
+ selcx : & mut SelectionContext < ' _ , ' tcx > ,
2162
+ obligation : & ProjectionTyObligation < ' tcx > ,
2163
+ data : ImplSourceUserDefinedData < ' tcx , PredicateObligation < ' tcx > > ,
2164
+ ) -> Progress < ' tcx > {
2165
+ let tcx = selcx. tcx ( ) ;
2166
+ let mut obligations = data. nested ;
2167
+
2168
+ let trait_fn_def_id = tcx. parent ( obligation. predicate . item_def_id ) ;
2169
+ let Ok ( leaf_def) = assoc_def ( selcx, data. impl_def_id , trait_fn_def_id) else {
2170
+ return Progress { term : tcx. ty_error ( ) . into ( ) , obligations } ;
2171
+ } ;
2172
+ if !leaf_def. item . defaultness ( tcx) . has_value ( ) {
2173
+ return Progress { term : tcx. ty_error ( ) . into ( ) , obligations } ;
2174
+ }
2175
+
2176
+ let impl_fn_def_id = leaf_def. item . def_id ;
2177
+ let impl_fn_substs = obligation. predicate . substs . rebase_onto ( tcx, trait_fn_def_id, data. substs ) ;
2178
+
2179
+ let sig = tcx
2180
+ . bound_fn_sig ( impl_fn_def_id)
2181
+ . map_bound ( |fn_sig| tcx. liberate_late_bound_regions ( impl_fn_def_id, fn_sig) )
2182
+ . subst ( tcx, impl_fn_substs) ;
2183
+
2184
+ let cause = ObligationCause :: new (
2185
+ obligation. cause . span ,
2186
+ obligation. cause . body_id ,
2187
+ super :: ItemObligation ( impl_fn_def_id) ,
2188
+ ) ;
2189
+ let predicates = normalize_with_depth_to (
2190
+ selcx,
2191
+ obligation. param_env ,
2192
+ cause. clone ( ) ,
2193
+ obligation. recursion_depth + 1 ,
2194
+ tcx. predicates_of ( impl_fn_def_id) . instantiate ( tcx, impl_fn_substs) ,
2195
+ & mut obligations,
2196
+ ) ;
2197
+ obligations. extend ( std:: iter:: zip ( predicates. predicates , predicates. spans ) . map (
2198
+ |( pred, span) | {
2199
+ Obligation :: with_depth (
2200
+ ObligationCause :: new (
2201
+ obligation. cause . span ,
2202
+ obligation. cause . body_id ,
2203
+ if span. is_dummy ( ) {
2204
+ super :: ItemObligation ( impl_fn_def_id)
2205
+ } else {
2206
+ super :: BindingObligation ( impl_fn_def_id, span)
2207
+ } ,
2208
+ ) ,
2209
+ obligation. recursion_depth + 1 ,
2210
+ obligation. param_env ,
2211
+ pred,
2212
+ )
2213
+ } ,
2214
+ ) ) ;
2215
+
2216
+ let ty = super :: normalize_to (
2217
+ selcx,
2218
+ obligation. param_env ,
2219
+ cause. clone ( ) ,
2220
+ sig. output ( ) ,
2221
+ & mut obligations,
2222
+ ) ;
2223
+
2224
+ Progress { term : ty. into ( ) , obligations }
2225
+ }
2226
+
2110
2227
// Get obligations corresponding to the predicates from the where-clause of the
2111
2228
// associated type itself.
2112
2229
// Note: `feature(generic_associated_types)` is required to write such
0 commit comments