@@ -1779,42 +1779,67 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1779
1779
self_ty : Ty < ' tcx > ,
1780
1780
probes : & [ ( & Candidate < ' tcx > , ProbeResult ) ] ,
1781
1781
) -> Option < Pick < ' tcx > > {
1782
- let mut child_pick = probes[ 0 ] . 0 ;
1783
- let mut supertraits: SsoHashSet < _ > =
1784
- supertrait_def_ids ( self . tcx , child_pick. item . trait_container ( self . tcx ) ?) . collect ( ) ;
1782
+ let mut child_candidate = probes[ 0 ] . 0 ;
1783
+ let mut child_trait = child_candidate. item . trait_container ( self . tcx ) ?;
1784
+ let mut supertraits: SsoHashSet < _ > = supertrait_def_ids ( self . tcx , child_trait) . collect ( ) ;
1785
+
1786
+ let mut remaining_candidates: Vec < _ > = probes[ 1 ..] . iter ( ) . map ( |& ( p, _) | p) . collect ( ) ;
1787
+ while !remaining_candidates. is_empty ( ) {
1788
+ let mut made_progress = false ;
1789
+ let mut next_round = vec ! [ ] ;
1790
+
1791
+ for remaining_candidate in remaining_candidates {
1792
+ let remaining_trait = remaining_candidate. item . trait_container ( self . tcx ) ?;
1793
+ if supertraits. contains ( & remaining_trait) {
1794
+ made_progress = true ;
1795
+ continue ;
1796
+ }
1785
1797
1786
- // All other picks should be a supertrait of the `child_pick`.
1787
- // If it's not, then we update the `child_pick` and the `supertraits`
1788
- // list.
1789
- for ( p, _) in & probes[ 1 ..] {
1790
- let p_container = p. item . trait_container ( self . tcx ) ?;
1791
- if !supertraits. contains ( & p_container) {
1792
1798
// This pick is not a supertrait of the `child_pick`.
1793
- // Check if it's a subtrait of the `child_pick`, which
1794
- // is sufficient to imply that all of the previous picks
1795
- // are also supertraits of this pick.
1796
- supertraits = supertrait_def_ids ( self . tcx , p_container) . collect ( ) ;
1797
- if supertraits. contains ( & child_pick. item . trait_container ( self . tcx ) . unwrap ( ) ) {
1798
- child_pick = * p;
1799
- } else {
1800
- // `child_pick` is not a supertrait of this pick. Bail.
1801
- return None ;
1799
+ // Check if it's a subtrait of the `child_pick`, instead.
1800
+ // If it is, then it must have been a subtrait of every
1801
+ // other pick we've eliminated at this point. It will
1802
+ // take over at this point.
1803
+ let remaining_trait_supertraits: SsoHashSet < _ > =
1804
+ supertrait_def_ids ( self . tcx , remaining_trait) . collect ( ) ;
1805
+ if remaining_trait_supertraits. contains ( & child_trait) {
1806
+ child_candidate = remaining_candidate;
1807
+ child_trait = remaining_trait;
1808
+ supertraits = remaining_trait_supertraits;
1809
+ made_progress = true ;
1810
+ continue ;
1802
1811
}
1812
+
1813
+ // `child_pick` is not a supertrait of this pick.
1814
+ // Don't bail here, since we may be comparing two supertraits
1815
+ // of a common subtrait. These two supertraits won't be related
1816
+ // at all, but we will pick them up next round when we find their
1817
+ // child as we continue iterating in this round.
1818
+ next_round. push ( remaining_candidate) ;
1819
+ }
1820
+
1821
+ if made_progress {
1822
+ // If we've made progress, iterate again.
1823
+ remaining_candidates = next_round;
1824
+ } else {
1825
+ // Otherwise, we must have at least two candidates which
1826
+ // are not related to each other at all.
1827
+ return None ;
1803
1828
}
1804
1829
}
1805
1830
1806
1831
Some ( Pick {
1807
- item : child_pick . item ,
1832
+ item : child_candidate . item ,
1808
1833
kind : TraitPick ,
1809
- import_ids : child_pick . import_ids . clone ( ) ,
1834
+ import_ids : child_candidate . import_ids . clone ( ) ,
1810
1835
autoderefs : 0 ,
1811
1836
autoref_or_ptr_adjustment : None ,
1812
1837
self_ty,
1813
1838
unstable_candidates : vec ! [ ] ,
1814
1839
shadowed_candidates : probes
1815
1840
. iter ( )
1816
1841
. map ( |( c, _) | c. item )
1817
- . filter ( |item| item. def_id != child_pick . item . def_id )
1842
+ . filter ( |item| item. def_id != child_candidate . item . def_id )
1818
1843
. collect ( ) ,
1819
1844
} )
1820
1845
}
0 commit comments