11
11
12
12
pub mod specialization_graph;
13
13
14
- use rustc_data_structures:: fx:: FxIndexSet ;
14
+ use rustc_data_structures:: fx:: { FxHashSet , FxIndexSet } ;
15
15
use rustc_errors:: codes:: * ;
16
16
use rustc_errors:: { Diag , EmissionGuarantee } ;
17
+ use rustc_hir:: LangItem ;
17
18
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
18
19
use rustc_infer:: infer:: DefineOpaqueTypes ;
19
20
use rustc_middle:: bug;
@@ -24,6 +25,8 @@ use rustc_middle::ty::{
24
25
} ;
25
26
use rustc_session:: lint:: builtin:: { COHERENCE_LEAK_CHECK , ORDER_DEPENDENT_TRAIT_OBJECTS } ;
26
27
use rustc_span:: { DUMMY_SP , ErrorGuaranteed , Span , sym} ;
28
+ use rustc_type_ir:: elaborate;
29
+ use rustc_type_ir:: fast_reject:: { SimplifiedType , TreatParams , simplify_type} ;
27
30
use specialization_graph:: GraphExt ;
28
31
use tracing:: { debug, instrument} ;
29
32
@@ -480,3 +483,118 @@ fn report_conflicting_impls<'tcx>(
480
483
}
481
484
}
482
485
}
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