@@ -18,6 +18,8 @@ use rustc_target::spec::abi;
18
18
use hir as ast;
19
19
use traits;
20
20
21
+ use rustc_data_structures:: fx:: FxHashSet ;
22
+
21
23
pub type RelateResult < ' tcx , T > = Result < T , TypeError < ' tcx > > ;
22
24
23
25
#[ derive( Clone , Debug ) ]
@@ -601,40 +603,37 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
601
603
use ty:: ExistentialPredicate :: * ;
602
604
603
605
let tcx = relation. tcx ( ) ;
604
- let ( a_buf, b_buf) ;
605
- let ( a_norm, b_norm) : ( & [ _ ] , & [ _ ] ) = match relation. trait_object_mode ( ) {
606
- TraitObjectMode :: NoSquash => {
607
- ( a, b)
608
- }
609
- TraitObjectMode :: SquashAutoTraitsIssue33140 => {
610
- // Treat auto-trait "principal" components as equal
611
- // to the non-principal components, to make
612
- // `dyn Send+Sync = dyn Sync+Send`.
613
- let normalize = |d : & [ ty:: ExistentialPredicate < ' tcx > ] | {
614
- let mut result: Vec < _ > = d. iter ( ) . map ( |pi| match pi {
615
- Trait ( ref a) if tcx. trait_is_auto ( a. def_id ) => {
616
- AutoTrait ( a. def_id )
617
- } ,
618
- other => * other
619
- } ) . collect ( ) ;
620
-
621
- result. sort_by ( |a, b| a. stable_cmp ( tcx, b) ) ;
622
- result. dedup ( ) ;
623
- result
624
- } ;
625
-
626
- a_buf = normalize ( a) ;
627
- b_buf = normalize ( b) ;
628
-
629
- ( & a_buf, & b_buf)
606
+ if let TraitObjectMode :: SquashAutoTraitsIssue33140 = relation. trait_object_mode ( ) {
607
+ // Treat auto-trait "principal" components as equal
608
+ // to the non-principal components, to make
609
+ // `dyn Send+Sync = dyn Sync+Send`.
610
+ //
611
+ // In that case,both types will be "fully resolved" (because
612
+ // auto-traits can't have type parameters or lifetimes), and we
613
+ // can just return either of them - we don't perform a full
614
+ // relation because that would "spread" the unnormalized types.
615
+
616
+ let auto_traits = |d : & [ ty:: ExistentialPredicate < ' tcx > ] | {
617
+ d. iter ( ) . map ( |pi| match pi {
618
+ Trait ( ref a) if tcx. trait_is_auto ( a. def_id ) => {
619
+ Ok ( a. def_id )
620
+ } ,
621
+ AutoTrait ( def_id) => Ok ( * def_id) ,
622
+ _ => Err ( ( ) ) ,
623
+ } ) . collect :: < Result < FxHashSet < _ > , ( ) > > ( )
624
+ } ;
625
+
626
+ match ( & auto_traits ( a) , & auto_traits ( b) ) {
627
+ ( Ok ( a_dids) , Ok ( b_dids) ) if a_dids == b_dids => return Ok ( a) ,
628
+ _ => { }
630
629
}
631
630
} ;
632
631
633
- if a_norm . len ( ) != b_norm . len ( ) {
632
+ if a . len ( ) != b . len ( ) {
634
633
return Err ( TypeError :: ExistentialMismatch ( expected_found ( relation, a, b) ) ) ;
635
634
}
636
635
637
- let v = a_norm . iter ( ) . zip ( b_norm . iter ( ) ) . map ( |( ep_a, ep_b) | {
636
+ let v = a . iter ( ) . zip ( b . iter ( ) ) . map ( |( ep_a, ep_b) | {
638
637
use ty:: ExistentialPredicate :: * ;
639
638
match ( * ep_a, * ep_b) {
640
639
( Trait ( ref a) , Trait ( ref b) ) => Ok ( Trait ( relation. relate ( a, b) ?) ) ,
0 commit comments