@@ -547,16 +547,56 @@ fn virtual_call_violation_for_method<'tcx>(
547
547
548
548
// NOTE: This check happens last, because it results in a lint, and not a
549
549
// 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
+ } ) {
560
600
return Some ( MethodViolationCode :: WhereClauseReferencesSelf ) ;
561
601
}
562
602
0 commit comments