@@ -1725,42 +1725,67 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1725
1725
self_ty : Ty < ' tcx > ,
1726
1726
probes : & [ ( & Candidate < ' tcx > , ProbeResult ) ] ,
1727
1727
) -> Option < Pick < ' tcx > > {
1728
- let mut child_pick = probes[ 0 ] . 0 ;
1729
- let mut supertraits: SsoHashSet < _ > =
1730
- supertrait_def_ids ( self . tcx , child_pick. item . trait_container ( self . tcx ) ?) . collect ( ) ;
1728
+ let mut child_candidate = probes[ 0 ] . 0 ;
1729
+ let mut child_trait = child_candidate. item . trait_container ( self . tcx ) ?;
1730
+ let mut supertraits: SsoHashSet < _ > = supertrait_def_ids ( self . tcx , child_trait) . collect ( ) ;
1731
+
1732
+ let mut remaining_candidates: Vec < _ > = probes[ 1 ..] . iter ( ) . map ( |& ( p, _) | p) . collect ( ) ;
1733
+ while !remaining_candidates. is_empty ( ) {
1734
+ let mut made_progress = false ;
1735
+ let mut next_round = vec ! [ ] ;
1736
+
1737
+ for remaining_candidate in remaining_candidates {
1738
+ let remaining_trait = remaining_candidate. item . trait_container ( self . tcx ) ?;
1739
+ if supertraits. contains ( & remaining_trait) {
1740
+ made_progress = true ;
1741
+ continue ;
1742
+ }
1731
1743
1732
- // All other picks should be a supertrait of the `child_pick`.
1733
- // If it's not, then we update the `child_pick` and the `supertraits`
1734
- // list.
1735
- for ( p, _) in & probes[ 1 ..] {
1736
- let p_container = p. item . trait_container ( self . tcx ) ?;
1737
- if !supertraits. contains ( & p_container) {
1738
1744
// This pick is not a supertrait of the `child_pick`.
1739
- // Check if it's a subtrait of the `child_pick`, which
1740
- // is sufficient to imply that all of the previous picks
1741
- // are also supertraits of this pick.
1742
- supertraits = supertrait_def_ids ( self . tcx , p_container) . collect ( ) ;
1743
- if supertraits. contains ( & child_pick. item . trait_container ( self . tcx ) . unwrap ( ) ) {
1744
- child_pick = * p;
1745
- } else {
1746
- // `child_pick` is not a supertrait of this pick. Bail.
1747
- return None ;
1745
+ // Check if it's a subtrait of the `child_pick`, instead.
1746
+ // If it is, then it must have been a subtrait of every
1747
+ // other pick we've eliminated at this point. It will
1748
+ // take over at this point.
1749
+ let remaining_trait_supertraits: SsoHashSet < _ > =
1750
+ supertrait_def_ids ( self . tcx , remaining_trait) . collect ( ) ;
1751
+ if remaining_trait_supertraits. contains ( & child_trait) {
1752
+ child_candidate = remaining_candidate;
1753
+ child_trait = remaining_trait;
1754
+ supertraits = remaining_trait_supertraits;
1755
+ made_progress = true ;
1756
+ continue ;
1748
1757
}
1758
+
1759
+ // `child_pick` is not a supertrait of this pick.
1760
+ // Don't bail here, since we may be comparing two supertraits
1761
+ // of a common subtrait. These two supertraits won't be related
1762
+ // at all, but we will pick them up next round when we find their
1763
+ // child as we continue iterating in this round.
1764
+ next_round. push ( remaining_candidate) ;
1765
+ }
1766
+
1767
+ if made_progress {
1768
+ // If we've made progress, iterate again.
1769
+ remaining_candidates = next_round;
1770
+ } else {
1771
+ // Otherwise, we must have at least two candidates which
1772
+ // are not related to each other at all.
1773
+ return None ;
1749
1774
}
1750
1775
}
1751
1776
1752
1777
Some ( Pick {
1753
- item : child_pick . item ,
1778
+ item : child_candidate . item ,
1754
1779
kind : TraitPick ,
1755
- import_ids : child_pick . import_ids . clone ( ) ,
1780
+ import_ids : child_candidate . import_ids . clone ( ) ,
1756
1781
autoderefs : 0 ,
1757
1782
autoref_or_ptr_adjustment : None ,
1758
1783
self_ty,
1759
1784
unstable_candidates : vec ! [ ] ,
1760
1785
shadowed_candidates : probes
1761
1786
. iter ( )
1762
1787
. map ( |( c, _) | c. item )
1763
- . filter ( |item| item. def_id != child_pick . item . def_id )
1788
+ . filter ( |item| item. def_id != child_candidate . item . def_id )
1764
1789
. collect ( ) ,
1765
1790
} )
1766
1791
}
0 commit comments