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
17
use rustc_hir:: LangItem ;
@@ -23,6 +23,8 @@ use rustc_middle::ty::print::PrintTraitRefExt as _;
23
23
use rustc_middle:: ty:: { self , GenericArgsRef , ImplSubject , Ty , TyCtxt , TypeVisitableExt } ;
24
24
use rustc_session:: lint:: builtin:: { COHERENCE_LEAK_CHECK , ORDER_DEPENDENT_TRAIT_OBJECTS } ;
25
25
use rustc_span:: { DUMMY_SP , ErrorGuaranteed , Span , sym} ;
26
+ use rustc_type_ir:: elaborate;
27
+ use rustc_type_ir:: fast_reject:: { SimplifiedType , TreatParams , simplify_type} ;
26
28
use specialization_graph:: GraphExt ;
27
29
use tracing:: { debug, instrument} ;
28
30
@@ -482,20 +484,62 @@ fn report_conflicting_impls<'tcx>(
482
484
483
485
pub ( super ) fn trait_has_impl_which_may_shadow_dyn < ' tcx > (
484
486
tcx : TyCtxt < ' tcx > ,
485
- trait_def_id : DefId ,
487
+ ( target_trait_def_id , principal_def_id ) : ( DefId , Option < DefId > ) ,
486
488
) -> bool {
487
489
// We only care about trait objects which have associated types.
488
490
if !tcx
489
- . associated_items ( trait_def_id )
491
+ . associated_items ( target_trait_def_id )
490
492
. in_definition_order ( )
491
493
. any ( |item| item. kind == ty:: AssocKind :: Type )
492
494
{
493
495
return false ;
494
496
}
495
497
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 {
499
543
return ;
500
544
}
501
545
@@ -504,33 +548,51 @@ pub(super) fn trait_has_impl_which_may_shadow_dyn<'tcx>(
504
548
. expect ( "impl must have trait ref" )
505
549
. instantiate_identity ( )
506
550
. self_ty ( ) ;
507
- if self_ty. is_known_rigid ( ) {
508
- return ;
509
- }
510
551
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)
518
554
{
519
555
return ;
520
556
}
521
557
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) )
528
560
{
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
+ }
530
592
}
531
593
532
- has_impl = true ;
594
+ has_offending_impl = true ;
533
595
} ) ;
534
596
535
- has_impl
597
+ has_offending_impl
536
598
}
0 commit comments