@@ -160,6 +160,10 @@ fn object_safety_violations_for_trait(
160
160
if !spans. is_empty ( ) {
161
161
violations. push ( ObjectSafetyViolation :: SupertraitSelf ( spans) ) ;
162
162
}
163
+ let spans = bounds_reference_self ( tcx, trait_def_id) ;
164
+ if !spans. is_empty ( ) {
165
+ violations. push ( ObjectSafetyViolation :: SupertraitSelf ( spans) ) ;
166
+ }
163
167
164
168
violations. extend (
165
169
tcx. associated_items ( trait_def_id)
@@ -239,51 +243,70 @@ fn predicates_reference_self(
239
243
} else {
240
244
tcx. predicates_of ( trait_def_id)
241
245
} ;
242
- let self_ty = tcx. types . self_param ;
243
- let has_self_ty = |arg : & GenericArg < ' _ > | arg. walk ( ) . any ( |arg| arg == self_ty. into ( ) ) ;
244
246
predicates
245
247
. predicates
246
248
. iter ( )
247
- . map ( |( predicate, sp) | ( predicate. subst_supertrait ( tcx, & trait_ref) , sp) )
248
- . filter_map ( |( predicate, & sp) | {
249
- match predicate. skip_binders ( ) {
250
- ty:: PredicateAtom :: Trait ( ref data, _) => {
251
- // In the case of a trait predicate, we can skip the "self" type.
252
- if data. trait_ref . substs [ 1 ..] . iter ( ) . any ( has_self_ty) { Some ( sp) } else { None }
253
- }
254
- ty:: PredicateAtom :: Projection ( ref data) => {
255
- // And similarly for projections. This should be redundant with
256
- // the previous check because any projection should have a
257
- // matching `Trait` predicate with the same inputs, but we do
258
- // the check to be safe.
259
- //
260
- // Note that we *do* allow projection *outputs* to contain
261
- // `self` (i.e., `trait Foo: Bar<Output=Self::Result> { type Result; }`),
262
- // we just require the user to specify *both* outputs
263
- // in the object type (i.e., `dyn Foo<Output=(), Result=()>`).
264
- //
265
- // This is ALT2 in issue #56288, see that for discussion of the
266
- // possible alternatives.
267
- if data. projection_ty . trait_ref ( tcx) . substs [ 1 ..] . iter ( ) . any ( has_self_ty) {
268
- Some ( sp)
269
- } else {
270
- None
271
- }
272
- }
273
- ty:: PredicateAtom :: WellFormed ( ..)
274
- | ty:: PredicateAtom :: ObjectSafe ( ..)
275
- | ty:: PredicateAtom :: TypeOutlives ( ..)
276
- | ty:: PredicateAtom :: RegionOutlives ( ..)
277
- | ty:: PredicateAtom :: ClosureKind ( ..)
278
- | ty:: PredicateAtom :: Subtype ( ..)
279
- | ty:: PredicateAtom :: ConstEvaluatable ( ..)
280
- | ty:: PredicateAtom :: ConstEquate ( ..)
281
- | ty:: PredicateAtom :: TypeWellFormedFromEnv ( ..) => None ,
282
- }
283
- } )
249
+ . map ( |( predicate, sp) | ( predicate. subst_supertrait ( tcx, & trait_ref) , * sp) )
250
+ . filter_map ( |predicate| predicate_references_self ( tcx, predicate) )
251
+ . collect ( )
252
+ }
253
+
254
+ fn bounds_reference_self ( tcx : TyCtxt < ' _ > , trait_def_id : DefId ) -> SmallVec < [ Span ; 1 ] > {
255
+ let trait_ref = ty:: Binder :: dummy ( ty:: TraitRef :: identity ( tcx, trait_def_id) ) ;
256
+ tcx. associated_items ( trait_def_id)
257
+ . in_definition_order ( )
258
+ . filter ( |item| item. kind == ty:: AssocKind :: Type )
259
+ . flat_map ( |item| tcx. explicit_item_bounds ( item. def_id ) )
260
+ . map ( |( predicate, sp) | ( predicate. subst_supertrait ( tcx, & trait_ref) , * sp) )
261
+ . filter_map ( |predicate| predicate_references_self ( tcx, predicate) )
284
262
. collect ( )
285
263
}
286
264
265
+ fn predicate_references_self (
266
+ tcx : TyCtxt < ' tcx > ,
267
+ ( predicate, sp) : ( ty:: Predicate < ' tcx > , Span ) ,
268
+ ) -> Option < Span > {
269
+ let self_ty = tcx. types . self_param ;
270
+ let has_self_ty = |arg : & GenericArg < ' _ > | arg. walk ( ) . any ( |arg| arg == self_ty. into ( ) ) ;
271
+ match predicate. skip_binders ( ) {
272
+ ty:: PredicateAtom :: Trait ( ref data, _) => {
273
+ // In the case of a trait predicate, we can skip the "self" type.
274
+ if data. trait_ref . substs [ 1 ..] . iter ( ) . any ( has_self_ty) { Some ( sp) } else { None }
275
+ }
276
+ ty:: PredicateAtom :: Projection ( ref data) => {
277
+ // And similarly for projections. This should be redundant with
278
+ // the previous check because any projection should have a
279
+ // matching `Trait` predicate with the same inputs, but we do
280
+ // the check to be safe.
281
+ //
282
+ // It's also won't be redundant if we allow type-generic associated
283
+ // types for trait objects.
284
+ //
285
+ // Note that we *do* allow projection *outputs* to contain
286
+ // `self` (i.e., `trait Foo: Bar<Output=Self::Result> { type Result; }`),
287
+ // we just require the user to specify *both* outputs
288
+ // in the object type (i.e., `dyn Foo<Output=(), Result=()>`).
289
+ //
290
+ // This is ALT2 in issue #56288, see that for discussion of the
291
+ // possible alternatives.
292
+ if data. projection_ty . trait_ref ( tcx) . substs [ 1 ..] . iter ( ) . any ( has_self_ty) {
293
+ Some ( sp)
294
+ } else {
295
+ None
296
+ }
297
+ }
298
+ ty:: PredicateAtom :: WellFormed ( ..)
299
+ | ty:: PredicateAtom :: ObjectSafe ( ..)
300
+ | ty:: PredicateAtom :: TypeOutlives ( ..)
301
+ | ty:: PredicateAtom :: RegionOutlives ( ..)
302
+ | ty:: PredicateAtom :: ClosureKind ( ..)
303
+ | ty:: PredicateAtom :: Subtype ( ..)
304
+ | ty:: PredicateAtom :: ConstEvaluatable ( ..)
305
+ | ty:: PredicateAtom :: ConstEquate ( ..)
306
+ | ty:: PredicateAtom :: TypeWellFormedFromEnv ( ..) => None ,
307
+ }
308
+ }
309
+
287
310
fn trait_has_sized_self ( tcx : TyCtxt < ' _ > , trait_def_id : DefId ) -> bool {
288
311
generics_require_sized_self ( tcx, trait_def_id)
289
312
}
0 commit comments