@@ -1013,15 +1013,39 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
1013
1013
let mut associated_types = BTreeSet :: default ( ) ;
1014
1014
1015
1015
for tr in traits:: elaborate_trait_ref ( tcx, principal) {
1016
+ debug ! ( "conv_object_ty_poly_trait_ref: observing object predicate `{:?}`" , tr) ;
1016
1017
match tr {
1017
1018
ty:: Predicate :: Trait ( pred) => {
1018
1019
associated_types. extend ( tcx. associated_items ( pred. def_id ( ) )
1019
1020
. filter ( |item| item. kind == ty:: AssociatedKind :: Type )
1020
1021
. map ( |item| item. def_id ) ) ;
1021
1022
}
1022
1023
ty:: Predicate :: Projection ( pred) => {
1023
- // Include projections defined on supertraits.
1024
- projection_bounds. push ( ( pred, DUMMY_SP ) )
1024
+ // A `Self` within the original bound will be substituted with a
1025
+ // `TRAIT_OBJECT_DUMMY_SELF`, so check for that.
1026
+ let references_self =
1027
+ pred. skip_binder ( ) . ty . walk ( ) . any ( |t| t == dummy_self) ;
1028
+
1029
+ // If the projection output contains `Self`, force the user to
1030
+ // elaborate it explicitly to avoid a bunch of complexity.
1031
+ //
1032
+ // The "classicaly useful" case is the following:
1033
+ // ```
1034
+ // trait MyTrait: FnMut() -> <Self as MyTrait>::MyOutput {
1035
+ // type MyOutput;
1036
+ // }
1037
+ // ```
1038
+ //
1039
+ // Here, the user could theoretically write `dyn MyTrait<Output=X>`,
1040
+ // but actually supporting that would "expand" to an infinitely-long type
1041
+ // `fix $ τ → dyn MyTrait<MyOutput=X, Output=<τ as MyTrait>::MyOutput`.
1042
+ //
1043
+ // Instead, we force the user to write `dyn MyTrait<MyOutput=X, Output=X>`,
1044
+ // which is uglier but works. See the discussion in #56288 for alternatives.
1045
+ if !references_self {
1046
+ // Include projections defined on supertraits,
1047
+ projection_bounds. push ( ( pred, DUMMY_SP ) )
1048
+ }
1025
1049
}
1026
1050
_ => ( )
1027
1051
}
0 commit comments