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 ;
@@ -25,6 +25,8 @@ use rustc_middle::ty::{
25
25
} ;
26
26
use rustc_session:: lint:: builtin:: { COHERENCE_LEAK_CHECK , ORDER_DEPENDENT_TRAIT_OBJECTS } ;
27
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} ;
28
30
use specialization_graph:: GraphExt ;
29
31
use tracing:: { debug, instrument} ;
30
32
@@ -484,20 +486,62 @@ fn report_conflicting_impls<'tcx>(
484
486
485
487
pub ( super ) fn trait_has_impl_which_may_shadow_dyn < ' tcx > (
486
488
tcx : TyCtxt < ' tcx > ,
487
- trait_def_id : DefId ,
489
+ ( target_trait_def_id , principal_def_id ) : ( DefId , Option < DefId > ) ,
488
490
) -> bool {
489
491
// We only care about trait objects which have associated types.
490
492
if !tcx
491
- . associated_items ( trait_def_id )
493
+ . associated_items ( target_trait_def_id )
492
494
. in_definition_order ( )
493
495
. any ( |item| item. kind == ty:: AssocKind :: Type )
494
496
{
495
497
return false ;
496
498
}
497
499
498
- let mut has_impl = false ;
499
- tcx. for_each_impl ( trait_def_id, |impl_def_id| {
500
- if has_impl {
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 {
501
545
return ;
502
546
}
503
547
@@ -506,33 +550,51 @@ pub(super) fn trait_has_impl_which_may_shadow_dyn<'tcx>(
506
550
. expect ( "impl must have trait ref" )
507
551
. instantiate_identity ( )
508
552
. self_ty ( ) ;
509
- if self_ty. is_known_rigid ( ) {
510
- return ;
511
- }
512
553
513
- let sized_trait = tcx. require_lang_item ( LangItem :: Sized , None ) ;
514
- if tcx
515
- . param_env ( impl_def_id)
516
- . caller_bounds ( )
517
- . iter ( )
518
- . filter_map ( |clause| clause. as_trait_clause ( ) )
519
- . any ( |bound| bound. def_id ( ) == sized_trait && bound. self_ty ( ) . skip_binder ( ) == self_ty)
554
+ if simplify_type ( tcx, self_ty, TreatParams :: InstantiateWithInfer )
555
+ . is_some_and ( |simp| simp != target_self_ty)
520
556
{
521
557
return ;
522
558
}
523
559
524
- if let ty:: Alias ( ty:: Projection , alias_ty) = self_ty. kind ( )
525
- && tcx
526
- . item_super_predicates ( alias_ty. def_id )
527
- . iter_identity ( )
528
- . filter_map ( |clause| clause. as_trait_clause ( ) )
529
- . any ( |bound| bound. def_id ( ) == sized_trait)
560
+ for ( pred, _) in
561
+ elaborate:: elaborate ( tcx, tcx. predicates_of ( impl_def_id) . instantiate_identity ( tcx) )
530
562
{
531
- return ;
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
+ }
532
594
}
533
595
534
- has_impl = true ;
596
+ has_offending_impl = true ;
535
597
} ) ;
536
598
537
- has_impl
599
+ has_offending_impl
538
600
}
0 commit comments