@@ -87,7 +87,7 @@ fn prepare_vtable_segments_inner<'tcx, T>(
87
87
let mut visited = PredicateSet :: new ( tcx) ;
88
88
let predicate = trait_ref. without_const ( ) . to_predicate ( tcx) ;
89
89
let mut stack: SmallVec < [ ( ty:: PolyTraitRef < ' tcx > , _ , _ ) ; 5 ] > =
90
- smallvec ! [ ( trait_ref, emit_vptr_on_new_entry, None ) ] ;
90
+ smallvec ! [ ( trait_ref, emit_vptr_on_new_entry, maybe_iter ( None ) ) ] ;
91
91
visited. insert ( predicate) ;
92
92
93
93
// the main traversal loop:
@@ -138,7 +138,7 @@ fn prepare_vtable_segments_inner<'tcx, T>(
138
138
stack. push ( (
139
139
next_super_trait,
140
140
emit_vptr_on_new_entry,
141
- Some ( direct_super_traits_iter) ,
141
+ maybe_iter ( Some ( direct_super_traits_iter) ) ,
142
142
) )
143
143
}
144
144
@@ -152,30 +152,26 @@ fn prepare_vtable_segments_inner<'tcx, T>(
152
152
153
153
// emit innermost item, move to next sibling and stop there if possible, otherwise jump to outer level.
154
154
' exiting_out: loop {
155
- if let Some ( ( inner_most_trait_ref, emit_vptr, siblings_opt ) ) = stack. last_mut ( ) {
155
+ if let Some ( ( inner_most_trait_ref, emit_vptr, siblings ) ) = stack. last_mut ( ) {
156
156
segment_visitor ( VtblSegment :: TraitOwnEntries {
157
157
trait_ref : * inner_most_trait_ref,
158
158
emit_vptr : * emit_vptr,
159
159
} ) ?;
160
160
161
- ' exiting_out_skip_visited_traits: loop {
162
- if let Some ( siblings) = siblings_opt {
163
- if let Some ( next_inner_most_trait_ref) = siblings. next ( ) {
164
- if visited. insert ( next_inner_most_trait_ref. to_predicate ( tcx) ) {
165
- // We're throwing away potential constness of super traits here.
166
- // FIXME: handle ~const super traits
167
- let next_inner_most_trait_ref =
168
- next_inner_most_trait_ref. map_bound ( |t| t. trait_ref ) ;
169
- * inner_most_trait_ref = next_inner_most_trait_ref;
170
- * emit_vptr = emit_vptr_on_new_entry;
171
- break ' exiting_out;
172
- } else {
173
- continue ' exiting_out_skip_visited_traits;
174
- }
175
- }
161
+ match siblings. find ( |& sibling| visited. insert ( sibling. to_predicate ( tcx) ) ) {
162
+ Some ( next_inner_most_trait_ref) => {
163
+ // We're throwing away potential constness of super traits here.
164
+ // FIXME: handle ~const super traits
165
+ let next_inner_most_trait_ref =
166
+ next_inner_most_trait_ref. map_bound ( |t| t. trait_ref ) ;
167
+ * inner_most_trait_ref = next_inner_most_trait_ref;
168
+ * emit_vptr = emit_vptr_on_new_entry;
169
+ break ' exiting_out;
170
+ }
171
+ None => {
172
+ stack. pop ( ) ;
173
+ continue ' exiting_out;
176
174
}
177
- stack. pop ( ) ;
178
- continue ' exiting_out;
179
175
}
180
176
}
181
177
// all done
@@ -184,6 +180,12 @@ fn prepare_vtable_segments_inner<'tcx, T>(
184
180
}
185
181
}
186
182
183
+ /// Turns option of iterator into an iterator (this is just flatten)
184
+ fn maybe_iter < I : Iterator > ( i : Option < I > ) -> impl Iterator < Item = I :: Item > {
185
+ // Flatten is bad perf-vise, we could probably implement a special case here that is better
186
+ i. into_iter ( ) . flatten ( )
187
+ }
188
+
187
189
fn dump_vtable_entries < ' tcx > (
188
190
tcx : TyCtxt < ' tcx > ,
189
191
sp : Span ,
0 commit comments