@@ -73,8 +73,8 @@ enum Inserted {
73
73
/// The impl was inserted as a new child in this group of children.
74
74
BecameNewSibling ( Option < OverlapError > ) ,
75
75
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 ) ,
78
78
79
79
/// The impl is a specialization of an existing child.
80
80
ShouldRecurseOn ( DefId ) ,
@@ -94,12 +94,34 @@ impl<'a, 'gcx, 'tcx> Children {
94
94
impl_def_id : DefId ) {
95
95
let trait_ref = tcx. impl_trait_ref ( impl_def_id) . unwrap ( ) ;
96
96
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) ;
97
98
self . nonblanket_impls . entry ( sty) . or_insert ( vec ! [ ] ) . push ( impl_def_id)
98
99
} else {
100
+ debug ! ( "insert_blindly: impl_def_id={:?} sty=None" , impl_def_id) ;
99
101
self . blanket_impls . push ( impl_def_id)
100
102
}
101
103
}
102
104
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
+
103
125
/// Attempt to insert an impl into this set of children, while comparing for
104
126
/// specialization relationships.
105
127
fn insert ( & mut self ,
@@ -110,11 +132,22 @@ impl<'a, 'gcx, 'tcx> Children {
110
132
{
111
133
let mut last_lint = None ;
112
134
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 ( ) ,
116
144
} {
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
+ ) ;
118
151
119
152
let overlap_error = |overlap : traits:: coherence:: OverlapResult | {
120
153
// overlap, but no specialization; error out
@@ -168,9 +201,7 @@ impl<'a, 'gcx, 'tcx> Children {
168
201
debug ! ( "placing as parent of TraitRef {:?}" ,
169
202
tcx. impl_trait_ref( possible_sibling) . unwrap( ) ) ;
170
203
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) ) ;
174
205
} else {
175
206
if !tcx. impls_are_allowed_to_overlap ( impl_def_id, possible_sibling) {
176
207
traits:: overlapping_impls (
@@ -193,15 +224,14 @@ impl<'a, 'gcx, 'tcx> Children {
193
224
Ok ( Inserted :: BecameNewSibling ( last_lint) )
194
225
}
195
226
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 ( ) )
199
230
}
200
231
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 ( ) )
205
235
}
206
236
}
207
237
@@ -259,11 +289,38 @@ impl<'a, 'gcx, 'tcx> Graph {
259
289
last_lint = opt_lint;
260
290
break ;
261
291
}
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) ;
267
324
break ;
268
325
}
269
326
ShouldRecurseOn ( new_parent) => {
0 commit comments