@@ -87,7 +87,7 @@ fn prepare_vtable_segments_inner<'tcx, T>(
8787 let mut visited = PredicateSet :: new ( tcx) ;
8888 let predicate = trait_ref. without_const ( ) . to_predicate ( tcx) ;
8989 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 ) ) ] ;
9191 visited. insert ( predicate) ;
9292
9393 // the main traversal loop:
@@ -138,7 +138,7 @@ fn prepare_vtable_segments_inner<'tcx, T>(
138138 stack. push ( (
139139 next_super_trait,
140140 emit_vptr_on_new_entry,
141- Some ( direct_super_traits_iter) ,
141+ maybe_iter ( Some ( direct_super_traits_iter) ) ,
142142 ) )
143143 }
144144
@@ -152,30 +152,26 @@ fn prepare_vtable_segments_inner<'tcx, T>(
152152
153153 // emit innermost item, move to next sibling and stop there if possible, otherwise jump to outer level.
154154 ' 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 ( ) {
156156 segment_visitor ( VtblSegment :: TraitOwnEntries {
157157 trait_ref : * inner_most_trait_ref,
158158 emit_vptr : * emit_vptr,
159159 } ) ?;
160160
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;
176174 }
177- stack. pop ( ) ;
178- continue ' exiting_out;
179175 }
180176 }
181177 // all done
@@ -184,6 +180,12 @@ fn prepare_vtable_segments_inner<'tcx, T>(
184180 }
185181}
186182
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+
187189fn dump_vtable_entries < ' tcx > (
188190 tcx : TyCtxt < ' tcx > ,
189191 sp : Span ,
0 commit comments