@@ -2112,42 +2112,67 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
2112
2112
self_ty : Ty < ' tcx > ,
2113
2113
probes : & [ ( & Candidate < ' tcx > , ProbeResult ) ] ,
2114
2114
) -> Option < Pick < ' tcx > > {
2115
- let mut child_pick = probes[ 0 ] . 0 ;
2116
- let mut supertraits: SsoHashSet < _ > =
2117
- supertrait_def_ids ( self . tcx , child_pick. item . trait_container ( self . tcx ) ?) . collect ( ) ;
2115
+ let mut child_candidate = probes[ 0 ] . 0 ;
2116
+ let mut child_trait = child_candidate. item . trait_container ( self . tcx ) ?;
2117
+ let mut supertraits: SsoHashSet < _ > = supertrait_def_ids ( self . tcx , child_trait) . collect ( ) ;
2118
+
2119
+ let mut remaining_candidates: Vec < _ > = probes[ 1 ..] . iter ( ) . map ( |& ( p, _) | p) . collect ( ) ;
2120
+ while !remaining_candidates. is_empty ( ) {
2121
+ let mut made_progress = false ;
2122
+ let mut next_round = vec ! [ ] ;
2123
+
2124
+ for remaining_candidate in remaining_candidates {
2125
+ let remaining_trait = remaining_candidate. item . trait_container ( self . tcx ) ?;
2126
+ if supertraits. contains ( & remaining_trait) {
2127
+ made_progress = true ;
2128
+ continue ;
2129
+ }
2118
2130
2119
- // All other picks should be a supertrait of the `child_pick`.
2120
- // If it's not, then we update the `child_pick` and the `supertraits`
2121
- // list.
2122
- for ( p, _) in & probes[ 1 ..] {
2123
- let p_container = p. item . trait_container ( self . tcx ) ?;
2124
- if !supertraits. contains ( & p_container) {
2125
2131
// This pick is not a supertrait of the `child_pick`.
2126
- // Check if it's a subtrait of the `child_pick`, which
2127
- // is sufficient to imply that all of the previous picks
2128
- // are also supertraits of this pick.
2129
- supertraits = supertrait_def_ids ( self . tcx , p_container) . collect ( ) ;
2130
- if supertraits. contains ( & child_pick. item . trait_container ( self . tcx ) . unwrap ( ) ) {
2131
- child_pick = * p;
2132
- } else {
2133
- // `child_pick` is not a supertrait of this pick. Bail.
2134
- return None ;
2132
+ // Check if it's a subtrait of the `child_pick`, instead.
2133
+ // If it is, then it must have been a subtrait of every
2134
+ // other pick we've eliminated at this point. It will
2135
+ // take over at this point.
2136
+ let remaining_trait_supertraits: SsoHashSet < _ > =
2137
+ supertrait_def_ids ( self . tcx , remaining_trait) . collect ( ) ;
2138
+ if remaining_trait_supertraits. contains ( & child_trait) {
2139
+ child_candidate = remaining_candidate;
2140
+ child_trait = remaining_trait;
2141
+ supertraits = remaining_trait_supertraits;
2142
+ made_progress = true ;
2143
+ continue ;
2135
2144
}
2145
+
2146
+ // `child_pick` is not a supertrait of this pick.
2147
+ // Don't bail here, since we may be comparing two supertraits
2148
+ // of a common subtrait. These two supertraits won't be related
2149
+ // at all, but we will pick them up next round when we find their
2150
+ // child as we continue iterating in this round.
2151
+ next_round. push ( remaining_candidate) ;
2152
+ }
2153
+
2154
+ if made_progress {
2155
+ // If we've made progress, iterate again.
2156
+ remaining_candidates = next_round;
2157
+ } else {
2158
+ // Otherwise, we must have at least two candidates which
2159
+ // are not related to each other at all.
2160
+ return None ;
2136
2161
}
2137
2162
}
2138
2163
2139
2164
Some ( Pick {
2140
- item : child_pick . item ,
2165
+ item : child_candidate . item ,
2141
2166
kind : TraitPick ,
2142
- import_ids : child_pick . import_ids . clone ( ) ,
2167
+ import_ids : child_candidate . import_ids . clone ( ) ,
2143
2168
autoderefs : 0 ,
2144
2169
autoref_or_ptr_adjustment : None ,
2145
2170
self_ty,
2146
2171
unstable_candidates : vec ! [ ] ,
2147
2172
shadowed_candidates : probes
2148
2173
. iter ( )
2149
2174
. map ( |( c, _) | c. item )
2150
- . filter ( |item| item. def_id != child_pick . item . def_id )
2175
+ . filter ( |item| item. def_id != child_candidate . item . def_id )
2151
2176
. collect ( ) ,
2152
2177
receiver_steps : None ,
2153
2178
} )
0 commit comments