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 } ;
17+ use rustc_hir:: LangItem ;
1718use rustc_hir:: def_id:: { DefId , LocalDefId } ;
1819use rustc_infer:: infer:: DefineOpaqueTypes ;
1920use rustc_middle:: bug;
@@ -24,6 +25,8 @@ use rustc_middle::ty::{
2425} ;
2526use rustc_session:: lint:: builtin:: { COHERENCE_LEAK_CHECK , ORDER_DEPENDENT_TRAIT_OBJECTS } ;
2627use rustc_span:: { DUMMY_SP , ErrorGuaranteed , Span , sym} ;
28+ use rustc_type_ir:: elaborate;
29+ use rustc_type_ir:: fast_reject:: { SimplifiedType , TreatParams , simplify_type} ;
2730use specialization_graph:: GraphExt ;
2831use tracing:: { debug, instrument} ;
2932
@@ -480,3 +483,118 @@ fn report_conflicting_impls<'tcx>(
480483 }
481484 }
482485}
486+
487+ pub ( super ) fn trait_has_impl_which_may_shadow_dyn < ' tcx > (
488+ tcx : TyCtxt < ' tcx > ,
489+ ( target_trait_def_id, principal_def_id) : ( DefId , Option < DefId > ) ,
490+ ) -> bool {
491+ // We only care about trait objects which have associated types.
492+ if !tcx
493+ . associated_items ( target_trait_def_id)
494+ . in_definition_order ( )
495+ . any ( |item| item. kind == ty:: AssocKind :: Type )
496+ {
497+ return false ;
498+ }
499+
500+ let target_self_ty =
501+ principal_def_id. map_or ( SimplifiedType :: MarkerTraitObject , SimplifiedType :: Trait ) ;
502+
503+ let elaborated_supertraits =
504+ principal_def_id. into_iter ( ) . flat_map ( |def_id| tcx. supertrait_def_ids ( def_id) ) . collect ( ) ;
505+
506+ trait_has_impl_inner (
507+ tcx,
508+ target_trait_def_id,
509+ target_self_ty,
510+ & elaborated_supertraits,
511+ & mut Default :: default ( ) ,
512+ true ,
513+ )
514+ }
515+
516+ fn trait_has_impl_inner < ' tcx > (
517+ tcx : TyCtxt < ' tcx > ,
518+ target_trait_def_id : DefId ,
519+ target_self_ty : SimplifiedType < DefId > ,
520+ elaborated_supertraits : & FxHashSet < DefId > ,
521+ seen_traits : & mut FxHashSet < DefId > ,
522+ first_generation : bool ,
523+ ) -> bool {
524+ if tcx. is_lang_item ( target_trait_def_id, LangItem :: Sized ) {
525+ return false ;
526+ }
527+
528+ // If we've encountered a trait in a cycle, then let's just
529+ // consider it to be implemented defensively.
530+ if !seen_traits. insert ( target_trait_def_id) {
531+ return true ;
532+ }
533+ // Since we don't pass in the set of auto traits, and just the principal,
534+ // consider all auto traits implemented.
535+ if tcx. trait_is_auto ( target_trait_def_id) {
536+ return true ;
537+ }
538+ if !first_generation && elaborated_supertraits. contains ( & target_trait_def_id) {
539+ return true ;
540+ }
541+
542+ let mut has_offending_impl = false ;
543+ tcx. for_each_impl ( target_trait_def_id, |impl_def_id| {
544+ if has_offending_impl {
545+ return ;
546+ }
547+
548+ let self_ty = tcx
549+ . impl_trait_ref ( impl_def_id)
550+ . expect ( "impl must have trait ref" )
551+ . instantiate_identity ( )
552+ . self_ty ( ) ;
553+
554+ if simplify_type ( tcx, self_ty, TreatParams :: InstantiateWithInfer )
555+ . is_some_and ( |simp| simp != target_self_ty)
556+ {
557+ return ;
558+ }
559+
560+ for ( pred, _) in
561+ elaborate:: elaborate ( tcx, tcx. predicates_of ( impl_def_id) . instantiate_identity ( tcx) )
562+ {
563+ if let ty:: ClauseKind :: Trait ( trait_pred) = pred. kind ( ) . skip_binder ( )
564+ && trait_pred. self_ty ( ) == self_ty
565+ && !trait_has_impl_inner (
566+ tcx,
567+ trait_pred. def_id ( ) ,
568+ target_self_ty,
569+ elaborated_supertraits,
570+ seen_traits,
571+ false ,
572+ )
573+ {
574+ return ;
575+ }
576+ }
577+
578+ if let ty:: Alias ( ty:: Projection , alias_ty) = self_ty. kind ( ) {
579+ for pred in tcx. item_super_predicates ( alias_ty. def_id ) . iter_identity ( ) {
580+ if let ty:: ClauseKind :: Trait ( trait_pred) = pred. kind ( ) . skip_binder ( )
581+ && trait_pred. self_ty ( ) == self_ty
582+ && !trait_has_impl_inner (
583+ tcx,
584+ trait_pred. def_id ( ) ,
585+ target_self_ty,
586+ elaborated_supertraits,
587+ seen_traits,
588+ false ,
589+ )
590+ {
591+ return ;
592+ }
593+ }
594+ }
595+
596+ has_offending_impl = true ;
597+ } ) ;
598+
599+ has_offending_impl
600+ }
0 commit comments