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