@@ -115,15 +115,11 @@ fn object_safety_violations_for_trait(
115115 tcx : TyCtxt < ' _ > ,
116116 trait_def_id : DefId ,
117117) -> Vec < ObjectSafetyViolation > {
118- // Check methods for violations.
118+ // Check assoc items for violations.
119119 let mut violations: Vec < _ > = tcx
120120 . associated_items ( trait_def_id)
121121 . 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) )
127123 . collect ( ) ;
128124
129125 // Check the trait itself.
@@ -145,30 +141,6 @@ fn object_safety_violations_for_trait(
145141 violations. push ( ObjectSafetyViolation :: SupertraitNonLifetimeBinder ( spans) ) ;
146142 }
147143
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| tcx. opt_rpitit_info ( item. def_id ) . is_none ( ) )
165- . map ( |item| {
166- let ident = item. ident ( tcx) ;
167- ObjectSafetyViolation :: GAT ( ident. name , ident. span )
168- } ) ,
169- ) ;
170- }
171-
172144 debug ! (
173145 "object_safety_violations_for_trait(trait_def_id={:?}) = {:?}" ,
174146 trait_def_id, violations
@@ -401,34 +373,54 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
401373 } )
402374}
403375
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 (
406379 tcx : TyCtxt < ' _ > ,
407380 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
412384 // exempt from the regulations.
413- if generics_require_sized_self ( tcx, method . def_id ) {
385+ if generics_require_sized_self ( tcx, item . def_id ) {
414386 return None ;
415387 }
416388
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
427421 }
428- _ => method. ident ( tcx) . span ,
429- } ;
430- ( v, span)
431- } )
422+ }
423+ }
432424}
433425
434426/// Returns `Some(_)` if this method cannot be called on a trait
0 commit comments