@@ -115,15 +115,11 @@ fn object_safety_violations_for_trait(
115
115
tcx : TyCtxt < ' _ > ,
116
116
trait_def_id : DefId ,
117
117
) -> Vec < ObjectSafetyViolation > {
118
- // Check methods for violations.
118
+ // Check assoc items for violations.
119
119
let mut violations: Vec < _ > = tcx
120
120
. associated_items ( trait_def_id)
121
121
. in_definition_order ( )
122
- . filter ( |item| item. kind == ty:: AssocKind :: Fn )
123
- . filter_map ( |& item| {
124
- object_safety_violation_for_method ( tcx, trait_def_id, item)
125
- . map ( |( code, span) | ObjectSafetyViolation :: Method ( item. name , code, span) )
126
- } )
122
+ . filter_map ( |& item| object_safety_violation_for_assoc_item ( tcx, trait_def_id, item) )
127
123
. collect ( ) ;
128
124
129
125
// Check the trait itself.
@@ -145,30 +141,6 @@ fn object_safety_violations_for_trait(
145
141
violations. push ( ObjectSafetyViolation :: SupertraitNonLifetimeBinder ( spans) ) ;
146
142
}
147
143
148
- violations. extend (
149
- tcx. associated_items ( trait_def_id)
150
- . in_definition_order ( )
151
- . filter ( |item| item. kind == ty:: AssocKind :: Const )
152
- . map ( |item| {
153
- let ident = item. ident ( tcx) ;
154
- ObjectSafetyViolation :: AssocConst ( ident. name , ident. span )
155
- } ) ,
156
- ) ;
157
-
158
- if !tcx. features ( ) . generic_associated_types_extended {
159
- violations. extend (
160
- tcx. associated_items ( trait_def_id)
161
- . in_definition_order ( )
162
- . filter ( |item| item. kind == ty:: AssocKind :: Type )
163
- . filter ( |item| !tcx. generics_of ( item. def_id ) . params . is_empty ( ) )
164
- . filter ( |item| item. opt_rpitit_info . is_none ( ) )
165
- . map ( |item| {
166
- let ident = item. ident ( tcx) ;
167
- ObjectSafetyViolation :: GAT ( ident. name , ident. span )
168
- } ) ,
169
- ) ;
170
- }
171
-
172
144
debug ! (
173
145
"object_safety_violations_for_trait(trait_def_id={:?}) = {:?}" ,
174
146
trait_def_id, violations
@@ -401,34 +373,54 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
401
373
} )
402
374
}
403
375
404
- /// Returns `Some(_)` if this method makes the containing trait not object safe.
405
- fn object_safety_violation_for_method (
376
+ /// Returns `Some(_)` if this item makes the containing trait not object safe.
377
+ #[ instrument( level = "debug" , skip( tcx) , ret) ]
378
+ fn object_safety_violation_for_assoc_item (
406
379
tcx : TyCtxt < ' _ > ,
407
380
trait_def_id : DefId ,
408
- method : ty:: AssocItem ,
409
- ) -> Option < ( MethodViolationCode , Span ) > {
410
- debug ! ( "object_safety_violation_for_method({:?}, {:?})" , trait_def_id, method) ;
411
- // Any method that has a `Self : Sized` requisite is otherwise
381
+ item : ty:: AssocItem ,
382
+ ) -> Option < ObjectSafetyViolation > {
383
+ // Any item that has a `Self : Sized` requisite is otherwise
412
384
// exempt from the regulations.
413
- if generics_require_sized_self ( tcx, method . def_id ) {
385
+ if generics_require_sized_self ( tcx, item . def_id ) {
414
386
return None ;
415
387
}
416
388
417
- let violation = virtual_call_violation_for_method ( tcx, trait_def_id, method) ;
418
- // Get an accurate span depending on the violation.
419
- violation. map ( |v| {
420
- let node = tcx. hir ( ) . get_if_local ( method. def_id ) ;
421
- let span = match ( & v, node) {
422
- ( MethodViolationCode :: ReferencesSelfInput ( Some ( span) ) , _) => * span,
423
- ( MethodViolationCode :: UndispatchableReceiver ( Some ( span) ) , _) => * span,
424
- ( MethodViolationCode :: ReferencesImplTraitInTrait ( span) , _) => * span,
425
- ( MethodViolationCode :: ReferencesSelfOutput , Some ( node) ) => {
426
- node. fn_decl ( ) . map_or ( method. ident ( tcx) . span , |decl| decl. output . span ( ) )
389
+ match item. kind {
390
+ // Associated consts are never object safe, as they can't have `where` bounds yet at all,
391
+ // and associated const bounds in trait objects aren't a thing yet either.
392
+ ty:: AssocKind :: Const => {
393
+ Some ( ObjectSafetyViolation :: AssocConst ( item. name , item. ident ( tcx) . span ) )
394
+ }
395
+ ty:: AssocKind :: Fn => virtual_call_violation_for_method ( tcx, trait_def_id, item) . map ( |v| {
396
+ let node = tcx. hir ( ) . get_if_local ( item. def_id ) ;
397
+ // Get an accurate span depending on the violation.
398
+ let span = match ( & v, node) {
399
+ ( MethodViolationCode :: ReferencesSelfInput ( Some ( span) ) , _) => * span,
400
+ ( MethodViolationCode :: UndispatchableReceiver ( Some ( span) ) , _) => * span,
401
+ ( MethodViolationCode :: ReferencesImplTraitInTrait ( span) , _) => * span,
402
+ ( MethodViolationCode :: ReferencesSelfOutput , Some ( node) ) => {
403
+ node. fn_decl ( ) . map_or ( item. ident ( tcx) . span , |decl| decl. output . span ( ) )
404
+ }
405
+ _ => item. ident ( tcx) . span ,
406
+ } ;
407
+
408
+ ObjectSafetyViolation :: Method ( item. name , v, span)
409
+ } ) ,
410
+ // Associated types can only be object safe if they have `Self: Sized` bounds.
411
+ ty:: AssocKind :: Type => {
412
+ if !tcx. features ( ) . generic_associated_types_extended
413
+ && !tcx. generics_of ( item. def_id ) . params . is_empty ( )
414
+ && item. opt_rpitit_info . is_none ( )
415
+ {
416
+ Some ( ObjectSafetyViolation :: GAT ( item. name , item. ident ( tcx) . span ) )
417
+ } else {
418
+ // We will permit associated types if they are explicitly mentioned in the trait object.
419
+ // We can't check this here, as here we only check if it is guaranteed to not be possible.
420
+ None
427
421
}
428
- _ => method. ident ( tcx) . span ,
429
- } ;
430
- ( v, span)
431
- } )
422
+ }
423
+ }
432
424
}
433
425
434
426
/// Returns `Some(_)` if this method cannot be called on a trait
0 commit comments