@@ -547,16 +547,56 @@ fn virtual_call_violation_for_method<'tcx>(
547547
548548 // NOTE: This check happens last, because it results in a lint, and not a
549549 // hard error.
550- if tcx
551- . predicates_of ( method. def_id )
552- . predicates
553- . iter ( )
554- // A trait object can't claim to live more than the concrete type,
555- // so outlives predicates will always hold.
556- . cloned ( )
557- . filter ( |( p, _) | p. to_opt_type_outlives ( ) . is_none ( ) )
558- . any ( |pred| contains_illegal_self_type_reference ( tcx, trait_def_id, pred) )
559- {
550+ if tcx. predicates_of ( method. def_id ) . predicates . iter ( ) . any ( |& ( pred, span) | {
551+ // dyn Trait is okay:
552+ //
553+ // trait Trait {
554+ // fn f(&self) where Self: 'static;
555+ // }
556+ //
557+ // because a trait object can't claim to live longer than the concrete
558+ // type. If the lifetime bound holds on dyn Trait then it's guaranteed
559+ // to hold as well on the concrete type.
560+ if pred. to_opt_type_outlives ( ) . is_some ( ) {
561+ return false ;
562+ }
563+
564+ // dyn Trait is okay:
565+ //
566+ // auto trait AutoTrait {}
567+ //
568+ // trait Trait {
569+ // fn f(&self) where Self: AutoTrait;
570+ // }
571+ //
572+ // because `impl AutoTrait for dyn Trait` is disallowed by coherence.
573+ // Traits with a default impl are implemented for a trait object if and
574+ // only if the autotrait is one of the trait object's trait bounds, like
575+ // in `dyn Trait + AutoTrait`. This guarantees that trait objects only
576+ // implement auto traits if the underlying type does as well.
577+ if let ty:: PredicateKind :: Clause ( ty:: Clause :: Trait ( ty:: TraitPredicate {
578+ trait_ref : pred_trait_ref,
579+ constness : ty:: BoundConstness :: NotConst ,
580+ polarity : ty:: ImplPolarity :: Positive ,
581+ } ) ) = pred. kind ( ) . skip_binder ( )
582+ && pred_trait_ref. self_ty ( ) == tcx. types . self_param
583+ && tcx. trait_is_auto ( pred_trait_ref. def_id )
584+ {
585+ // Consider bounds like `Self: Bound<Self>`. Auto traits are not
586+ // allowed to have generic parameters so `auto trait Bound<T> {}`
587+ // would already have reported an error at the definition of the
588+ // auto trait.
589+ if pred_trait_ref. substs . len ( ) != 1 {
590+ tcx. sess . diagnostic ( ) . delay_span_bug (
591+ span,
592+ "auto traits cannot have generic parameters" ,
593+ ) ;
594+ }
595+ return false ;
596+ }
597+
598+ contains_illegal_self_type_reference ( tcx, trait_def_id, pred. clone ( ) )
599+ } ) {
560600 return Some ( MethodViolationCode :: WhereClauseReferencesSelf ) ;
561601 }
562602
0 commit comments