@@ -109,10 +109,9 @@ pub fn is_vtable_safe_method(tcx: TyCtxt<'_>, trait_def_id: DefId, method: ty::A
109109 return false ;
110110 }
111111
112- match virtual_call_violation_for_method ( tcx, trait_def_id, method) {
113- None | Some ( MethodViolationCode :: WhereClauseReferencesSelf ) => true ,
114- Some ( _) => false ,
115- }
112+ virtual_call_violation_for_method ( tcx, trait_def_id, method)
113+ . iter ( )
114+ . all ( |v| matches ! ( v, MethodViolationCode :: WhereClauseReferencesSelf ) )
116115}
117116
118117fn object_safety_violations_for_trait (
@@ -123,7 +122,7 @@ fn object_safety_violations_for_trait(
123122 let mut violations: Vec < _ > = tcx
124123 . associated_items ( trait_def_id)
125124 . in_definition_order ( )
126- . filter_map ( |& item| object_safety_violation_for_assoc_item ( tcx, trait_def_id, item) )
125+ . flat_map ( |& item| object_safety_violation_for_assoc_item ( tcx, trait_def_id, item) )
127126 . collect ( ) ;
128127
129128 // Check the trait itself.
@@ -365,45 +364,48 @@ fn object_safety_violation_for_assoc_item(
365364 tcx : TyCtxt < ' _ > ,
366365 trait_def_id : DefId ,
367366 item : ty:: AssocItem ,
368- ) -> Option < ObjectSafetyViolation > {
367+ ) -> Vec < ObjectSafetyViolation > {
369368 // Any item that has a `Self : Sized` requisite is otherwise
370369 // exempt from the regulations.
371370 if tcx. generics_require_sized_self ( item. def_id ) {
372- return None ;
371+ return Vec :: new ( ) ;
373372 }
374373
375374 match item. kind {
376375 // Associated consts are never object safe, as they can't have `where` bounds yet at all,
377376 // and associated const bounds in trait objects aren't a thing yet either.
378377 ty:: AssocKind :: Const => {
379- Some ( ObjectSafetyViolation :: AssocConst ( item. name , item. ident ( tcx) . span ) )
378+ vec ! [ ObjectSafetyViolation :: AssocConst ( item. name, item. ident( tcx) . span) ]
380379 }
381- ty:: AssocKind :: Fn => virtual_call_violation_for_method ( tcx, trait_def_id, item) . map ( |v| {
382- let node = tcx. hir ( ) . get_if_local ( item. def_id ) ;
383- // Get an accurate span depending on the violation.
384- let span = match ( & v, node) {
385- ( MethodViolationCode :: ReferencesSelfInput ( Some ( span) ) , _) => * span,
386- ( MethodViolationCode :: UndispatchableReceiver ( Some ( span) ) , _) => * span,
387- ( MethodViolationCode :: ReferencesImplTraitInTrait ( span) , _) => * span,
388- ( MethodViolationCode :: ReferencesSelfOutput , Some ( node) ) => {
389- node. fn_decl ( ) . map_or ( item. ident ( tcx) . span , |decl| decl. output . span ( ) )
390- }
391- _ => item. ident ( tcx) . span ,
392- } ;
380+ ty:: AssocKind :: Fn => virtual_call_violation_for_method ( tcx, trait_def_id, item)
381+ . into_iter ( )
382+ . map ( |v| {
383+ let node = tcx. hir ( ) . get_if_local ( item. def_id ) ;
384+ // Get an accurate span depending on the violation.
385+ let span = match ( & v, node) {
386+ ( MethodViolationCode :: ReferencesSelfInput ( Some ( span) ) , _) => * span,
387+ ( MethodViolationCode :: UndispatchableReceiver ( Some ( span) ) , _) => * span,
388+ ( MethodViolationCode :: ReferencesImplTraitInTrait ( span) , _) => * span,
389+ ( MethodViolationCode :: ReferencesSelfOutput , Some ( node) ) => {
390+ node. fn_decl ( ) . map_or ( item. ident ( tcx) . span , |decl| decl. output . span ( ) )
391+ }
392+ _ => item. ident ( tcx) . span ,
393+ } ;
393394
394- ObjectSafetyViolation :: Method ( item. name , v, span)
395- } ) ,
395+ ObjectSafetyViolation :: Method ( item. name , v, span)
396+ } )
397+ . collect ( ) ,
396398 // Associated types can only be object safe if they have `Self: Sized` bounds.
397399 ty:: AssocKind :: Type => {
398400 if !tcx. features ( ) . generic_associated_types_extended
399401 && !tcx. generics_of ( item. def_id ) . params . is_empty ( )
400402 && !item. is_impl_trait_in_trait ( )
401403 {
402- Some ( ObjectSafetyViolation :: GAT ( item. name , item. ident ( tcx) . span ) )
404+ vec ! [ ObjectSafetyViolation :: GAT ( item. name, item. ident( tcx) . span) ]
403405 } else {
404406 // We will permit associated types if they are explicitly mentioned in the trait object.
405407 // We can't check this here, as here we only check if it is guaranteed to not be possible.
406- None
408+ Vec :: new ( )
407409 }
408410 }
409411 }
@@ -417,7 +419,7 @@ fn virtual_call_violation_for_method<'tcx>(
417419 tcx : TyCtxt < ' tcx > ,
418420 trait_def_id : DefId ,
419421 method : ty:: AssocItem ,
420- ) -> Option < MethodViolationCode > {
422+ ) -> Vec < MethodViolationCode > {
421423 let sig = tcx. fn_sig ( method. def_id ) . instantiate_identity ( ) ;
422424
423425 // The method's first parameter must be named `self`
@@ -442,9 +444,14 @@ fn virtual_call_violation_for_method<'tcx>(
442444 } else {
443445 None
444446 } ;
445- return Some ( MethodViolationCode :: StaticMethod ( sugg) ) ;
447+
448+ // Not having `self` parameter messes up the later checks,
449+ // so we need to return instead of pushing
450+ return vec ! [ MethodViolationCode :: StaticMethod ( sugg) ] ;
446451 }
447452
453+ let mut errors = Vec :: new ( ) ;
454+
448455 for ( i, & input_ty) in sig. skip_binder ( ) . inputs ( ) . iter ( ) . enumerate ( ) . skip ( 1 ) {
449456 if contains_illegal_self_type_reference ( tcx, trait_def_id, sig. rebind ( input_ty) ) {
450457 let span = if let Some ( hir:: Node :: TraitItem ( hir:: TraitItem {
@@ -456,20 +463,20 @@ fn virtual_call_violation_for_method<'tcx>(
456463 } else {
457464 None
458465 } ;
459- return Some ( MethodViolationCode :: ReferencesSelfInput ( span) ) ;
466+ errors . push ( MethodViolationCode :: ReferencesSelfInput ( span) ) ;
460467 }
461468 }
462469 if contains_illegal_self_type_reference ( tcx, trait_def_id, sig. output ( ) ) {
463- return Some ( MethodViolationCode :: ReferencesSelfOutput ) ;
470+ errors . push ( MethodViolationCode :: ReferencesSelfOutput ) ;
464471 }
465472 if let Some ( code) = contains_illegal_impl_trait_in_trait ( tcx, method. def_id , sig. output ( ) ) {
466- return Some ( code) ;
473+ errors . push ( code) ;
467474 }
468475
469476 // We can't monomorphize things like `fn foo<A>(...)`.
470477 let own_counts = tcx. generics_of ( method. def_id ) . own_counts ( ) ;
471478 if own_counts. types > 0 || own_counts. consts > 0 {
472- return Some ( MethodViolationCode :: Generic ) ;
479+ errors . push ( MethodViolationCode :: Generic ) ;
473480 }
474481
475482 let receiver_ty = tcx. liberate_late_bound_regions ( method. def_id , sig. input ( 0 ) ) ;
@@ -489,7 +496,7 @@ fn virtual_call_violation_for_method<'tcx>(
489496 } else {
490497 None
491498 } ;
492- return Some ( MethodViolationCode :: UndispatchableReceiver ( span) ) ;
499+ errors . push ( MethodViolationCode :: UndispatchableReceiver ( span) ) ;
493500 } else {
494501 // Do sanity check to make sure the receiver actually has the layout of a pointer.
495502
@@ -598,10 +605,10 @@ fn virtual_call_violation_for_method<'tcx>(
598605
599606 contains_illegal_self_type_reference ( tcx, trait_def_id, pred)
600607 } ) {
601- return Some ( MethodViolationCode :: WhereClauseReferencesSelf ) ;
608+ errors . push ( MethodViolationCode :: WhereClauseReferencesSelf ) ;
602609 }
603610
604- None
611+ errors
605612}
606613
607614/// Performs a type substitution to produce the version of `receiver_ty` when `Self = self_ty`.
0 commit comments