1111
1212pub mod specialization_graph;
1313
14- use rustc_data_structures:: fx:: FxIndexSet ;
14+ use rustc_data_structures:: fx:: { FxHashSet , FxIndexSet } ;
1515use rustc_errors:: codes:: * ;
1616use rustc_errors:: { Diag , EmissionGuarantee } ;
1717use rustc_hir:: LangItem ;
@@ -23,6 +23,8 @@ use rustc_middle::ty::print::PrintTraitRefExt as _;
2323use rustc_middle:: ty:: { self , GenericArgsRef , ImplSubject , Ty , TyCtxt , TypeVisitableExt } ;
2424use rustc_session:: lint:: builtin:: { COHERENCE_LEAK_CHECK , ORDER_DEPENDENT_TRAIT_OBJECTS } ;
2525use rustc_span:: { DUMMY_SP , ErrorGuaranteed , Span , sym} ;
26+ use rustc_type_ir:: elaborate;
27+ use rustc_type_ir:: fast_reject:: { SimplifiedType , TreatParams , simplify_type} ;
2628use specialization_graph:: GraphExt ;
2729use tracing:: { debug, instrument} ;
2830
@@ -482,20 +484,62 @@ fn report_conflicting_impls<'tcx>(
482484
483485pub ( super ) fn trait_has_impl_which_may_shadow_dyn < ' tcx > (
484486 tcx : TyCtxt < ' tcx > ,
485- trait_def_id : DefId ,
487+ ( target_trait_def_id , principal_def_id ) : ( DefId , Option < DefId > ) ,
486488) -> bool {
487489 // We only care about trait objects which have associated types.
488490 if !tcx
489- . associated_items ( trait_def_id )
491+ . associated_items ( target_trait_def_id )
490492 . in_definition_order ( )
491493 . any ( |item| item. kind == ty:: AssocKind :: Type )
492494 {
493495 return false ;
494496 }
495497
496- let mut has_impl = false ;
497- tcx. for_each_impl ( trait_def_id, |impl_def_id| {
498- if has_impl {
498+ let target_self_ty =
499+ principal_def_id. map_or ( SimplifiedType :: MarkerTraitObject , SimplifiedType :: Trait ) ;
500+
501+ let elaborated_supertraits =
502+ principal_def_id. into_iter ( ) . flat_map ( |def_id| tcx. supertrait_def_ids ( def_id) ) . collect ( ) ;
503+
504+ trait_has_impl_inner (
505+ tcx,
506+ target_trait_def_id,
507+ target_self_ty,
508+ & elaborated_supertraits,
509+ & mut Default :: default ( ) ,
510+ true ,
511+ )
512+ }
513+
514+ fn trait_has_impl_inner < ' tcx > (
515+ tcx : TyCtxt < ' tcx > ,
516+ target_trait_def_id : DefId ,
517+ target_self_ty : SimplifiedType < DefId > ,
518+ elaborated_supertraits : & FxHashSet < DefId > ,
519+ seen_traits : & mut FxHashSet < DefId > ,
520+ first_generation : bool ,
521+ ) -> bool {
522+ if tcx. is_lang_item ( target_trait_def_id, LangItem :: Sized ) {
523+ return false ;
524+ }
525+
526+ // If we've encountered a trait in a cycle, then let's just
527+ // consider it to be implemented defensively.
528+ if !seen_traits. insert ( target_trait_def_id) {
529+ return true ;
530+ }
531+ // Since we don't pass in the set of auto traits, and just the principal,
532+ // consider all auto traits implemented.
533+ if tcx. trait_is_auto ( target_trait_def_id) {
534+ return true ;
535+ }
536+ if !first_generation && elaborated_supertraits. contains ( & target_trait_def_id) {
537+ return true ;
538+ }
539+
540+ let mut has_offending_impl = false ;
541+ tcx. for_each_impl ( target_trait_def_id, |impl_def_id| {
542+ if has_offending_impl {
499543 return ;
500544 }
501545
@@ -504,33 +548,51 @@ pub(super) fn trait_has_impl_which_may_shadow_dyn<'tcx>(
504548 . expect ( "impl must have trait ref" )
505549 . instantiate_identity ( )
506550 . self_ty ( ) ;
507- if self_ty. is_known_rigid ( ) {
508- return ;
509- }
510551
511- let sized_trait = tcx. require_lang_item ( LangItem :: Sized , None ) ;
512- if tcx
513- . param_env ( impl_def_id)
514- . caller_bounds ( )
515- . iter ( )
516- . filter_map ( |clause| clause. as_trait_clause ( ) )
517- . any ( |bound| bound. def_id ( ) == sized_trait && bound. self_ty ( ) . skip_binder ( ) == self_ty)
552+ if simplify_type ( tcx, self_ty, TreatParams :: InstantiateWithInfer )
553+ . is_some_and ( |simp| simp != target_self_ty)
518554 {
519555 return ;
520556 }
521557
522- if let ty:: Alias ( ty:: Projection , alias_ty) = self_ty. kind ( )
523- && tcx
524- . item_super_predicates ( alias_ty. def_id )
525- . iter_identity ( )
526- . filter_map ( |clause| clause. as_trait_clause ( ) )
527- . any ( |bound| bound. def_id ( ) == sized_trait)
558+ for ( pred, _) in
559+ elaborate:: elaborate ( tcx, tcx. predicates_of ( impl_def_id) . instantiate_identity ( tcx) )
528560 {
529- return ;
561+ if let ty:: ClauseKind :: Trait ( trait_pred) = pred. kind ( ) . skip_binder ( )
562+ && trait_pred. self_ty ( ) == self_ty
563+ && !trait_has_impl_inner (
564+ tcx,
565+ trait_pred. def_id ( ) ,
566+ target_self_ty,
567+ elaborated_supertraits,
568+ seen_traits,
569+ false ,
570+ )
571+ {
572+ return ;
573+ }
574+ }
575+
576+ if let ty:: Alias ( ty:: Projection , alias_ty) = self_ty. kind ( ) {
577+ for pred in tcx. item_super_predicates ( alias_ty. def_id ) . iter_identity ( ) {
578+ if let ty:: ClauseKind :: Trait ( trait_pred) = pred. kind ( ) . skip_binder ( )
579+ && trait_pred. self_ty ( ) == self_ty
580+ && !trait_has_impl_inner (
581+ tcx,
582+ trait_pred. def_id ( ) ,
583+ target_self_ty,
584+ elaborated_supertraits,
585+ seen_traits,
586+ false ,
587+ )
588+ {
589+ return ;
590+ }
591+ }
530592 }
531593
532- has_impl = true ;
594+ has_offending_impl = true ;
533595 } ) ;
534596
535- has_impl
597+ has_offending_impl
536598}
0 commit comments