@@ -97,6 +97,10 @@ fn check_is_object_safe(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
9797/// object. Note that object-safe traits can have some
9898/// non-vtable-safe methods, so long as they require `Self: Sized` or
9999/// otherwise ensure that they cannot be used when `Self = Trait`.
100+ ///
101+ /// [`MethodViolationCode::WhereClauseReferencesSelf`] is considered object safe due to backwards
102+ /// compatibility, see <https://github.com/rust-lang/rust/issues/51443> and
103+ /// [`WHERE_CLAUSES_OBJECT_SAFETY`].
100104pub fn is_vtable_safe_method ( tcx : TyCtxt < ' _ > , trait_def_id : DefId , method : ty:: AssocItem ) -> bool {
101105 debug_assert ! ( tcx. generics_of( trait_def_id) . has_self) ;
102106 debug ! ( "is_vtable_safe_method({:?}, {:?})" , trait_def_id, method) ;
@@ -105,10 +109,9 @@ pub fn is_vtable_safe_method(tcx: TyCtxt<'_>, trait_def_id: DefId, method: ty::A
105109 return false ;
106110 }
107111
108- match virtual_call_violation_for_method ( tcx, trait_def_id, method) {
109- None | Some ( MethodViolationCode :: WhereClauseReferencesSelf ) => true ,
110- Some ( _) => false ,
111- }
112+ virtual_call_violations_for_method ( tcx, trait_def_id, method)
113+ . iter ( )
114+ . all ( |v| matches ! ( v, MethodViolationCode :: WhereClauseReferencesSelf ) )
112115}
113116
114117fn object_safety_violations_for_trait (
@@ -119,7 +122,7 @@ fn object_safety_violations_for_trait(
119122 let mut violations: Vec < _ > = tcx
120123 . associated_items ( trait_def_id)
121124 . in_definition_order ( )
122- . filter_map ( |& item| object_safety_violation_for_assoc_item ( tcx, trait_def_id, item) )
125+ . flat_map ( |& item| object_safety_violations_for_assoc_item ( tcx, trait_def_id, item) )
123126 . collect ( ) ;
124127
125128 // Check the trait itself.
@@ -357,49 +360,52 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
357360
358361/// Returns `Some(_)` if this item makes the containing trait not object safe.
359362#[ instrument( level = "debug" , skip( tcx) , ret) ]
360- fn object_safety_violation_for_assoc_item (
363+ fn object_safety_violations_for_assoc_item (
361364 tcx : TyCtxt < ' _ > ,
362365 trait_def_id : DefId ,
363366 item : ty:: AssocItem ,
364- ) -> Option < ObjectSafetyViolation > {
367+ ) -> Vec < ObjectSafetyViolation > {
365368 // Any item that has a `Self : Sized` requisite is otherwise
366369 // exempt from the regulations.
367370 if tcx. generics_require_sized_self ( item. def_id ) {
368- return None ;
371+ return Vec :: new ( ) ;
369372 }
370373
371374 match item. kind {
372375 // Associated consts are never object safe, as they can't have `where` bounds yet at all,
373376 // and associated const bounds in trait objects aren't a thing yet either.
374377 ty:: AssocKind :: Const => {
375- Some ( ObjectSafetyViolation :: AssocConst ( item. name , item. ident ( tcx) . span ) )
378+ vec ! [ ObjectSafetyViolation :: AssocConst ( item. name, item. ident( tcx) . span) ]
376379 }
377- ty:: AssocKind :: Fn => virtual_call_violation_for_method ( tcx, trait_def_id, item) . map ( |v| {
378- let node = tcx. hir ( ) . get_if_local ( item. def_id ) ;
379- // Get an accurate span depending on the violation.
380- let span = match ( & v, node) {
381- ( MethodViolationCode :: ReferencesSelfInput ( Some ( span) ) , _) => * span,
382- ( MethodViolationCode :: UndispatchableReceiver ( Some ( span) ) , _) => * span,
383- ( MethodViolationCode :: ReferencesImplTraitInTrait ( span) , _) => * span,
384- ( MethodViolationCode :: ReferencesSelfOutput , Some ( node) ) => {
385- node. fn_decl ( ) . map_or ( item. ident ( tcx) . span , |decl| decl. output . span ( ) )
386- }
387- _ => item. ident ( tcx) . span ,
388- } ;
380+ ty:: AssocKind :: Fn => virtual_call_violations_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+ } ;
389394
390- ObjectSafetyViolation :: Method ( item. name , v, span)
391- } ) ,
395+ ObjectSafetyViolation :: Method ( item. name , v, span)
396+ } )
397+ . collect ( ) ,
392398 // Associated types can only be object safe if they have `Self: Sized` bounds.
393399 ty:: AssocKind :: Type => {
394400 if !tcx. features ( ) . generic_associated_types_extended
395401 && !tcx. generics_of ( item. def_id ) . params . is_empty ( )
396402 && !item. is_impl_trait_in_trait ( )
397403 {
398- Some ( ObjectSafetyViolation :: GAT ( item. name , item. ident ( tcx) . span ) )
404+ vec ! [ ObjectSafetyViolation :: GAT ( item. name, item. ident( tcx) . span) ]
399405 } else {
400406 // We will permit associated types if they are explicitly mentioned in the trait object.
401407 // We can't check this here, as here we only check if it is guaranteed to not be possible.
402- None
408+ Vec :: new ( )
403409 }
404410 }
405411 }
@@ -409,11 +415,11 @@ fn object_safety_violation_for_assoc_item(
409415/// object; this does not necessarily imply that the enclosing trait
410416/// is not object safe, because the method might have a where clause
411417/// `Self:Sized`.
412- fn virtual_call_violation_for_method < ' tcx > (
418+ fn virtual_call_violations_for_method < ' tcx > (
413419 tcx : TyCtxt < ' tcx > ,
414420 trait_def_id : DefId ,
415421 method : ty:: AssocItem ,
416- ) -> Option < MethodViolationCode > {
422+ ) -> Vec < MethodViolationCode > {
417423 let sig = tcx. fn_sig ( method. def_id ) . instantiate_identity ( ) ;
418424
419425 // The method's first parameter must be named `self`
@@ -438,9 +444,14 @@ fn virtual_call_violation_for_method<'tcx>(
438444 } else {
439445 None
440446 } ;
441- 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) ] ;
442451 }
443452
453+ let mut errors = Vec :: new ( ) ;
454+
444455 for ( i, & input_ty) in sig. skip_binder ( ) . inputs ( ) . iter ( ) . enumerate ( ) . skip ( 1 ) {
445456 if contains_illegal_self_type_reference ( tcx, trait_def_id, sig. rebind ( input_ty) ) {
446457 let span = if let Some ( hir:: Node :: TraitItem ( hir:: TraitItem {
@@ -452,20 +463,20 @@ fn virtual_call_violation_for_method<'tcx>(
452463 } else {
453464 None
454465 } ;
455- return Some ( MethodViolationCode :: ReferencesSelfInput ( span) ) ;
466+ errors . push ( MethodViolationCode :: ReferencesSelfInput ( span) ) ;
456467 }
457468 }
458469 if contains_illegal_self_type_reference ( tcx, trait_def_id, sig. output ( ) ) {
459- return Some ( MethodViolationCode :: ReferencesSelfOutput ) ;
470+ errors . push ( MethodViolationCode :: ReferencesSelfOutput ) ;
460471 }
461472 if let Some ( code) = contains_illegal_impl_trait_in_trait ( tcx, method. def_id , sig. output ( ) ) {
462- return Some ( code) ;
473+ errors . push ( code) ;
463474 }
464475
465476 // We can't monomorphize things like `fn foo<A>(...)`.
466477 let own_counts = tcx. generics_of ( method. def_id ) . own_counts ( ) ;
467- if own_counts. types + own_counts. consts != 0 {
468- return Some ( MethodViolationCode :: Generic ) ;
478+ if own_counts. types > 0 || own_counts. consts > 0 {
479+ errors . push ( MethodViolationCode :: Generic ) ;
469480 }
470481
471482 let receiver_ty = tcx. liberate_late_bound_regions ( method. def_id , sig. input ( 0 ) ) ;
@@ -485,7 +496,7 @@ fn virtual_call_violation_for_method<'tcx>(
485496 } else {
486497 None
487498 } ;
488- return Some ( MethodViolationCode :: UndispatchableReceiver ( span) ) ;
499+ errors . push ( MethodViolationCode :: UndispatchableReceiver ( span) ) ;
489500 } else {
490501 // Do sanity check to make sure the receiver actually has the layout of a pointer.
491502
@@ -593,10 +604,10 @@ fn virtual_call_violation_for_method<'tcx>(
593604
594605 contains_illegal_self_type_reference ( tcx, trait_def_id, pred)
595606 } ) {
596- return Some ( MethodViolationCode :: WhereClauseReferencesSelf ) ;
607+ errors . push ( MethodViolationCode :: WhereClauseReferencesSelf ) ;
597608 }
598609
599- None
610+ errors
600611}
601612
602613/// Performs a type substitution to produce the version of `receiver_ty` when `Self = self_ty`.
@@ -709,7 +720,6 @@ fn object_ty_for_trait<'tcx>(
709720// FIXME(mikeyhew) when unsized receivers are implemented as part of unsized rvalues, add this
710721// fallback query: `Receiver: Unsize<Receiver[Self => U]>` to support receivers like
711722// `self: Wrapper<Self>`.
712- #[ allow( dead_code) ]
713723fn receiver_is_dispatchable < ' tcx > (
714724 tcx : TyCtxt < ' tcx > ,
715725 method : ty:: AssocItem ,
0 commit comments