@@ -32,6 +32,7 @@ use rustc_middle::traits::select::OverflowError;
3232use rustc_middle:: ty:: fold:: { TypeFoldable , TypeFolder , TypeSuperFoldable } ;
3333use rustc_middle:: ty:: subst:: Subst ;
3434use rustc_middle:: ty:: visit:: { MaxUniverse , TypeVisitable } ;
35+ use rustc_middle:: ty:: DefIdTree ;
3536use rustc_middle:: ty:: { self , Term , ToPredicate , Ty , TyCtxt } ;
3637use rustc_span:: symbol:: sym;
3738
@@ -70,6 +71,8 @@ enum ProjectionCandidate<'tcx> {
7071
7172 /// From an "impl" (or a "pseudo-impl" returned by select)
7273 Select ( Selection < ' tcx > ) ,
74+
75+ ImplTraitInTrait ( ImplSourceUserDefinedData < ' tcx , PredicateObligation < ' tcx > > ) ,
7376}
7477
7578enum ProjectionCandidateSet < ' tcx > {
@@ -1265,6 +1268,8 @@ fn project<'cx, 'tcx>(
12651268
12661269 let mut candidates = ProjectionCandidateSet :: None ;
12671270
1271+ assemble_candidate_for_impl_trait_in_trait ( selcx, obligation, & mut candidates) ;
1272+
12681273 // Make sure that the following procedures are kept in order. ParamEnv
12691274 // needs to be first because it has highest priority, and Select checks
12701275 // the return value of push_candidate which assumes it's ran at last.
@@ -1303,6 +1308,48 @@ fn project<'cx, 'tcx>(
13031308 }
13041309}
13051310
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+
13061353/// The first thing we have to do is scan through the parameter
13071354/// environment to see whether there are any projection predicates
13081355/// there that can answer this question.
@@ -1745,6 +1792,9 @@ fn confirm_candidate<'cx, 'tcx>(
17451792 ProjectionCandidate :: Select ( impl_source) => {
17461793 confirm_select_candidate ( selcx, obligation, impl_source)
17471794 }
1795+ ProjectionCandidate :: ImplTraitInTrait ( data) => {
1796+ confirm_impl_trait_in_trait_candidate ( selcx, obligation, data)
1797+ }
17481798 } ;
17491799
17501800 // When checking for cycle during evaluation, we compare predicates with
@@ -2107,6 +2157,73 @@ fn confirm_impl_candidate<'cx, 'tcx>(
21072157 }
21082158}
21092159
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+
21102227// Get obligations corresponding to the predicates from the where-clause of the
21112228// associated type itself.
21122229// Note: `feature(generic_associated_types)` is required to write such
0 commit comments