@@ -71,7 +71,15 @@ enum ProjectionCandidate<'tcx> {
71
71
/// From an "impl" (or a "pseudo-impl" returned by select)
72
72
Select ( Selection < ' tcx > ) ,
73
73
74
- ImplTraitInTrait ( ImplSourceUserDefinedData < ' tcx , PredicateObligation < ' tcx > > ) ,
74
+ ImplTraitInTrait ( ImplTraitInTraitCandidate < ' tcx > ) ,
75
+ }
76
+
77
+ #[ derive( PartialEq , Eq , Debug ) ]
78
+ enum ImplTraitInTraitCandidate < ' tcx > {
79
+ // The `impl Trait` from a trait function's default body
80
+ Trait ,
81
+ // A concrete type provided from a trait's `impl Trait` from an impl
82
+ Impl ( ImplSourceUserDefinedData < ' tcx , PredicateObligation < ' tcx > > ) ,
75
83
}
76
84
77
85
enum ProjectionCandidateSet < ' tcx > {
@@ -1317,6 +1325,17 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
1317
1325
) {
1318
1326
let tcx = selcx. tcx ( ) ;
1319
1327
if tcx. def_kind ( obligation. predicate . item_def_id ) == DefKind :: ImplTraitPlaceholder {
1328
+ // If we are trying to project an RPITIT with the _identity_ substs,
1329
+ // then we must be within a default trait body.
1330
+ if obligation. predicate . substs
1331
+ == ty:: InternalSubsts :: identity_for_item ( tcx, obligation. predicate . item_def_id )
1332
+ {
1333
+ candidate_set. push_candidate ( ProjectionCandidate :: ImplTraitInTrait (
1334
+ ImplTraitInTraitCandidate :: Trait ,
1335
+ ) ) ;
1336
+ return ;
1337
+ }
1338
+
1320
1339
let trait_fn_def_id = tcx. impl_trait_in_trait_parent ( obligation. predicate . item_def_id ) ;
1321
1340
let trait_def_id = tcx. parent ( trait_fn_def_id) ;
1322
1341
let trait_substs =
@@ -1329,7 +1348,9 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
1329
1348
let _ =
1330
1349
selcx. infcx ( ) . commit_if_ok ( |_| match selcx. select ( & obligation. with ( trait_predicate) ) {
1331
1350
Ok ( Some ( super :: ImplSource :: UserDefined ( data) ) ) => {
1332
- candidate_set. push_candidate ( ProjectionCandidate :: ImplTraitInTrait ( data) ) ;
1351
+ candidate_set. push_candidate ( ProjectionCandidate :: ImplTraitInTrait (
1352
+ ImplTraitInTraitCandidate :: Impl ( data) ,
1353
+ ) ) ;
1333
1354
Ok ( ( ) )
1334
1355
}
1335
1356
Ok ( None ) => {
@@ -1792,9 +1813,18 @@ fn confirm_candidate<'cx, 'tcx>(
1792
1813
ProjectionCandidate :: Select ( impl_source) => {
1793
1814
confirm_select_candidate ( selcx, obligation, impl_source)
1794
1815
}
1795
- ProjectionCandidate :: ImplTraitInTrait ( data) => {
1816
+ ProjectionCandidate :: ImplTraitInTrait ( ImplTraitInTraitCandidate :: Impl ( data) ) => {
1796
1817
confirm_impl_trait_in_trait_candidate ( selcx, obligation, data)
1797
1818
}
1819
+ // If we're projecting an RPITIT for a default trait body, that's just
1820
+ // the same def-id, but as an opaque type (with regular RPIT semantics).
1821
+ ProjectionCandidate :: ImplTraitInTrait ( ImplTraitInTraitCandidate :: Trait ) => Progress {
1822
+ term : selcx
1823
+ . tcx ( )
1824
+ . mk_opaque ( obligation. predicate . item_def_id , obligation. predicate . substs )
1825
+ . into ( ) ,
1826
+ obligations : vec ! [ ] ,
1827
+ } ,
1798
1828
} ;
1799
1829
1800
1830
// When checking for cycle during evaluation, we compare predicates with
@@ -2212,6 +2242,16 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
2212
2242
return Progress { term : tcx. ty_error ( ) . into ( ) , obligations } ;
2213
2243
}
2214
2244
2245
+ // Use the default `impl Trait` for the trait, e.g., for a default trait body
2246
+ if leaf_def. item . container == ty:: AssocItemContainer :: TraitContainer {
2247
+ return Progress {
2248
+ term : tcx
2249
+ . mk_opaque ( obligation. predicate . item_def_id , obligation. predicate . substs )
2250
+ . into ( ) ,
2251
+ obligations,
2252
+ } ;
2253
+ }
2254
+
2215
2255
let impl_fn_def_id = leaf_def. item . def_id ;
2216
2256
let impl_fn_substs = obligation. predicate . substs . rebase_onto ( tcx, trait_fn_def_id, data. substs ) ;
2217
2257
0 commit comments