@@ -73,8 +73,8 @@ enum Inserted {
7373 /// The impl was inserted as a new child in this group of children.
7474 BecameNewSibling ( Option < OverlapError > ) ,
7575
76- /// The impl replaced an existing impl that specializes it .
77- Replaced ( DefId ) ,
76+ /// The impl should replace an existing impl X, because the impl specializes X .
77+ ReplaceChild ( DefId ) ,
7878
7979 /// The impl is a specialization of an existing child.
8080 ShouldRecurseOn ( DefId ) ,
@@ -94,12 +94,34 @@ impl<'a, 'gcx, 'tcx> Children {
9494 impl_def_id : DefId ) {
9595 let trait_ref = tcx. impl_trait_ref ( impl_def_id) . unwrap ( ) ;
9696 if let Some ( sty) = fast_reject:: simplify_type ( tcx, trait_ref. self_ty ( ) , false ) {
97+ debug ! ( "insert_blindly: impl_def_id={:?} sty={:?}" , impl_def_id, sty) ;
9798 self . nonblanket_impls . entry ( sty) . or_insert ( vec ! [ ] ) . push ( impl_def_id)
9899 } else {
100+ debug ! ( "insert_blindly: impl_def_id={:?} sty=None" , impl_def_id) ;
99101 self . blanket_impls . push ( impl_def_id)
100102 }
101103 }
102104
105+ /// Remove an impl from this set of children. Used when replacing
106+ /// an impl with a parent. The impl must be present in the list of
107+ /// children already.
108+ fn remove_existing ( & mut self ,
109+ tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
110+ impl_def_id : DefId ) {
111+ let trait_ref = tcx. impl_trait_ref ( impl_def_id) . unwrap ( ) ;
112+ let vec: & mut Vec < DefId > ;
113+ if let Some ( sty) = fast_reject:: simplify_type ( tcx, trait_ref. self_ty ( ) , false ) {
114+ debug ! ( "remove_existing: impl_def_id={:?} sty={:?}" , impl_def_id, sty) ;
115+ vec = self . nonblanket_impls . get_mut ( & sty) . unwrap ( ) ;
116+ } else {
117+ debug ! ( "remove_existing: impl_def_id={:?} sty=None" , impl_def_id) ;
118+ vec = & mut self . blanket_impls ;
119+ }
120+
121+ let index = vec. iter ( ) . position ( |d| * d == impl_def_id) . unwrap ( ) ;
122+ vec. remove ( index) ;
123+ }
124+
103125 /// Attempt to insert an impl into this set of children, while comparing for
104126 /// specialization relationships.
105127 fn insert ( & mut self ,
@@ -110,11 +132,22 @@ impl<'a, 'gcx, 'tcx> Children {
110132 {
111133 let mut last_lint = None ;
112134
113- for slot in match simplified_self {
114- Some ( sty) => self . filtered_mut ( sty) ,
115- None => self . iter_mut ( ) ,
135+ debug ! (
136+ "insert(impl_def_id={:?}, simplified_self={:?})" ,
137+ impl_def_id,
138+ simplified_self,
139+ ) ;
140+
141+ for possible_sibling in match simplified_self {
142+ Some ( sty) => self . filtered ( sty) ,
143+ None => self . iter ( ) ,
116144 } {
117- let possible_sibling = * slot;
145+ debug ! (
146+ "insert: impl_def_id={:?}, simplified_self={:?}, possible_sibling={:?}" ,
147+ impl_def_id,
148+ simplified_self,
149+ possible_sibling,
150+ ) ;
118151
119152 let overlap_error = |overlap : traits:: coherence:: OverlapResult | {
120153 // overlap, but no specialization; error out
@@ -168,9 +201,7 @@ impl<'a, 'gcx, 'tcx> Children {
168201 debug ! ( "placing as parent of TraitRef {:?}" ,
169202 tcx. impl_trait_ref( possible_sibling) . unwrap( ) ) ;
170203
171- // possible_sibling specializes the impl
172- * slot = impl_def_id;
173- return Ok ( Inserted :: Replaced ( possible_sibling) ) ;
204+ return Ok ( Inserted :: ReplaceChild ( possible_sibling) ) ;
174205 } else {
175206 if !tcx. impls_are_allowed_to_overlap ( impl_def_id, possible_sibling) {
176207 traits:: overlapping_impls (
@@ -193,15 +224,14 @@ impl<'a, 'gcx, 'tcx> Children {
193224 Ok ( Inserted :: BecameNewSibling ( last_lint) )
194225 }
195226
196- fn iter_mut ( & ' a mut self ) -> Box < dyn Iterator < Item = & ' a mut DefId > + ' a > {
197- let nonblanket = self . nonblanket_impls . iter_mut ( ) . flat_map ( |( _, v) | v. iter_mut ( ) ) ;
198- Box :: new ( self . blanket_impls . iter_mut ( ) . chain ( nonblanket) )
227+ fn iter ( & mut self ) -> Box < dyn Iterator < Item = DefId > + ' _ > {
228+ let nonblanket = self . nonblanket_impls . iter_mut ( ) . flat_map ( |( _, v) | v. iter ( ) ) ;
229+ Box :: new ( self . blanket_impls . iter ( ) . chain ( nonblanket) . cloned ( ) )
199230 }
200231
201- fn filtered_mut ( & ' a mut self , sty : SimplifiedType )
202- -> Box < dyn Iterator < Item = & ' a mut DefId > + ' a > {
203- let nonblanket = self . nonblanket_impls . entry ( sty) . or_insert ( vec ! [ ] ) . iter_mut ( ) ;
204- Box :: new ( self . blanket_impls . iter_mut ( ) . chain ( nonblanket) )
232+ fn filtered ( & mut self , sty : SimplifiedType ) -> Box < dyn Iterator < Item = DefId > + ' _ > {
233+ let nonblanket = self . nonblanket_impls . entry ( sty) . or_insert ( vec ! [ ] ) . iter ( ) ;
234+ Box :: new ( self . blanket_impls . iter ( ) . chain ( nonblanket) . cloned ( ) )
205235 }
206236}
207237
@@ -259,11 +289,38 @@ impl<'a, 'gcx, 'tcx> Graph {
259289 last_lint = opt_lint;
260290 break ;
261291 }
262- Replaced ( new_child) => {
263- self . parent . insert ( new_child, impl_def_id) ;
264- let mut new_children = Children :: new ( ) ;
265- new_children. insert_blindly ( tcx, new_child) ;
266- self . children . insert ( impl_def_id, new_children) ;
292+ ReplaceChild ( grand_child_to_be) => {
293+ // We currently have
294+ //
295+ // P
296+ // |
297+ // G
298+ //
299+ // and we are inserting the impl N. We want to make it:
300+ //
301+ // P
302+ // |
303+ // N
304+ // |
305+ // G
306+
307+ // Adjust P's list of children: remove G and then add N.
308+ {
309+ let siblings = self . children
310+ . get_mut ( & parent)
311+ . unwrap ( ) ;
312+ siblings. remove_existing ( tcx, grand_child_to_be) ;
313+ siblings. insert_blindly ( tcx, impl_def_id) ;
314+ }
315+
316+ // Set G's parent to N and N's parent to P
317+ self . parent . insert ( grand_child_to_be, impl_def_id) ;
318+ self . parent . insert ( impl_def_id, parent) ;
319+
320+ // Add G as N's child.
321+ let mut grand_children = Children :: new ( ) ;
322+ grand_children. insert_blindly ( tcx, grand_child_to_be) ;
323+ self . children . insert ( impl_def_id, grand_children) ;
267324 break ;
268325 }
269326 ShouldRecurseOn ( new_parent) => {
0 commit comments