@@ -92,122 +92,141 @@ impl<'tcx> ChildrenExt<'tcx> for Children {
92
92
simplified_self : Option < SimplifiedType > ,
93
93
overlap_mode : OverlapMode ,
94
94
) -> Result < OverlapResult < ' tcx > , OverlapError < ' tcx > > {
95
- let mut last_lint = None ;
96
- let mut replace_children = Vec :: new ( ) ;
97
-
98
95
let possible_siblings = match simplified_self {
99
96
Some ( st) => PotentialSiblings :: Filtered ( filtered_children ( self , st) ) ,
100
97
None => PotentialSiblings :: Unfiltered ( iter_children ( self ) ) ,
101
98
} ;
102
99
103
- for possible_sibling in possible_siblings {
104
- debug ! ( ?possible_sibling) ;
105
-
106
- let create_overlap_error = |overlap : traits:: coherence:: OverlapResult < ' tcx > | {
107
- let trait_ref = overlap. impl_header . trait_ref . unwrap ( ) ;
108
- let self_ty = trait_ref. self_ty ( ) ;
109
-
110
- OverlapError {
111
- with_impl : possible_sibling,
112
- trait_ref,
113
- // Only report the `Self` type if it has at least
114
- // some outer concrete shell; otherwise, it's
115
- // not adding much information.
116
- self_ty : self_ty. has_concrete_skeleton ( ) . then_some ( self_ty) ,
117
- intercrate_ambiguity_causes : overlap. intercrate_ambiguity_causes ,
118
- involves_placeholder : overlap. involves_placeholder ,
119
- }
120
- } ;
121
-
122
- let report_overlap_error = |overlap : traits:: coherence:: OverlapResult < ' tcx > ,
123
- last_lint : & mut _ | {
124
- // Found overlap, but no specialization; error out or report future-compat warning.
125
-
126
- // Do we *still* get overlap if we disable the future-incompatible modes?
127
- let should_err = traits:: overlapping_impls (
128
- tcx,
129
- possible_sibling,
130
- impl_def_id,
131
- traits:: SkipLeakCheck :: default ( ) ,
132
- overlap_mode,
133
- )
134
- . is_some ( ) ;
135
-
136
- let error = create_overlap_error ( overlap) ;
137
-
138
- if should_err {
139
- Err ( error)
140
- } else {
141
- * last_lint = Some ( FutureCompatOverlapError {
142
- error,
143
- kind : FutureCompatOverlapErrorKind :: LeakCheck ,
144
- } ) ;
145
-
146
- Ok ( ( false , false ) )
147
- }
148
- } ;
100
+ let result = overlap_check_considering_specialization (
101
+ tcx,
102
+ impl_def_id,
103
+ possible_siblings,
104
+ overlap_mode,
105
+ ) ;
106
+
107
+ if let Ok ( OverlapResult :: NoOverlap ( _) ) = result {
108
+ // No overlap with any potential siblings, so add as a new sibling.
109
+ debug ! ( "placing as new sibling" ) ;
110
+ self . insert_blindly ( tcx, impl_def_id) ;
111
+ }
112
+
113
+ result
114
+ }
115
+ }
116
+
117
+ fn overlap_check_considering_specialization < ' tcx > (
118
+ tcx : TyCtxt < ' tcx > ,
119
+ impl_def_id : DefId ,
120
+ possible_siblings : PotentialSiblings < impl Iterator < Item = DefId > , impl Iterator < Item = DefId > > ,
121
+ overlap_mode : OverlapMode ,
122
+ ) -> Result < OverlapResult < ' tcx > , OverlapError < ' tcx > > {
123
+ let mut last_lint = None ;
124
+ let mut replace_children = Vec :: new ( ) ;
125
+
126
+ for possible_sibling in possible_siblings {
127
+ debug ! ( ?possible_sibling) ;
128
+
129
+ let create_overlap_error = |overlap : traits:: coherence:: OverlapResult < ' tcx > | {
130
+ let trait_ref = overlap. impl_header . trait_ref . unwrap ( ) ;
131
+ let self_ty = trait_ref. self_ty ( ) ;
132
+
133
+ OverlapError {
134
+ with_impl : possible_sibling,
135
+ trait_ref,
136
+ // Only report the `Self` type if it has at least
137
+ // some outer concrete shell; otherwise, it's
138
+ // not adding much information.
139
+ self_ty : self_ty. has_concrete_skeleton ( ) . then_some ( self_ty) ,
140
+ intercrate_ambiguity_causes : overlap. intercrate_ambiguity_causes ,
141
+ involves_placeholder : overlap. involves_placeholder ,
142
+ }
143
+ } ;
149
144
150
- let last_lint_mut = & mut last_lint;
151
- let ( le, ge) = traits:: overlapping_impls (
145
+ let report_overlap_error = |overlap : traits:: coherence:: OverlapResult < ' tcx > ,
146
+ last_lint : & mut _ | {
147
+ // Found overlap, but no specialization; error out or report future-compat warning.
148
+
149
+ // Do we *still* get overlap if we disable the future-incompatible modes?
150
+ let should_err = traits:: overlapping_impls (
152
151
tcx,
153
152
possible_sibling,
154
153
impl_def_id,
155
- traits:: SkipLeakCheck :: Yes ,
154
+ traits:: SkipLeakCheck :: default ( ) ,
156
155
overlap_mode,
157
156
)
158
- . map_or ( Ok ( ( false , false ) ) , |overlap| {
159
- if let Some ( overlap_kind) =
160
- tcx. impls_are_allowed_to_overlap ( impl_def_id, possible_sibling)
161
- {
162
- match overlap_kind {
163
- ty:: ImplOverlapKind :: Permitted { marker : _ } => { }
164
- ty:: ImplOverlapKind :: Issue33140 => {
165
- * last_lint_mut = Some ( FutureCompatOverlapError {
166
- error : create_overlap_error ( overlap) ,
167
- kind : FutureCompatOverlapErrorKind :: Issue33140 ,
168
- } ) ;
169
- }
170
- }
157
+ . is_some ( ) ;
158
+
159
+ let error = create_overlap_error ( overlap) ;
171
160
172
- return Ok ( ( false , false ) ) ;
161
+ if should_err {
162
+ Err ( error)
163
+ } else {
164
+ * last_lint = Some ( FutureCompatOverlapError {
165
+ error,
166
+ kind : FutureCompatOverlapErrorKind :: LeakCheck ,
167
+ } ) ;
168
+
169
+ Ok ( ( false , false ) )
170
+ }
171
+ } ;
172
+
173
+ let last_lint_mut = & mut last_lint;
174
+ let ( le, ge) = traits:: overlapping_impls (
175
+ tcx,
176
+ possible_sibling,
177
+ impl_def_id,
178
+ traits:: SkipLeakCheck :: Yes ,
179
+ overlap_mode,
180
+ )
181
+ . map_or ( Ok ( ( false , false ) ) , |overlap| {
182
+ if let Some ( overlap_kind) =
183
+ tcx. impls_are_allowed_to_overlap ( impl_def_id, possible_sibling)
184
+ {
185
+ match overlap_kind {
186
+ ty:: ImplOverlapKind :: Permitted { marker : _ } => { }
187
+ ty:: ImplOverlapKind :: Issue33140 => {
188
+ * last_lint_mut = Some ( FutureCompatOverlapError {
189
+ error : create_overlap_error ( overlap) ,
190
+ kind : FutureCompatOverlapErrorKind :: Issue33140 ,
191
+ } ) ;
192
+ }
173
193
}
174
194
175
- let le = tcx . specializes ( ( impl_def_id , possible_sibling ) ) ;
176
- let ge = tcx . specializes ( ( possible_sibling , impl_def_id ) ) ;
195
+ return Ok ( ( false , false ) ) ;
196
+ }
177
197
178
- if le == ge { report_overlap_error ( overlap , last_lint_mut ) } else { Ok ( ( le , ge ) ) }
179
- } ) ? ;
198
+ let le = tcx . specializes ( ( impl_def_id , possible_sibling ) ) ;
199
+ let ge = tcx . specializes ( ( possible_sibling , impl_def_id ) ) ;
180
200
181
- if le && !ge {
182
- debug ! (
183
- "descending as child of TraitRef {:?}" ,
184
- tcx. impl_trait_ref( possible_sibling) . unwrap( ) . subst_identity( )
185
- ) ;
201
+ if le == ge { report_overlap_error ( overlap, last_lint_mut) } else { Ok ( ( le, ge) ) }
202
+ } ) ?;
186
203
187
- // The impl specializes `possible_sibling`.
188
- return Ok ( OverlapResult :: SpecializeOne ( possible_sibling) ) ;
189
- } else if ge && !le {
190
- debug ! (
191
- "placing as parent of TraitRef {:?}" ,
192
- tcx. impl_trait_ref( possible_sibling) . unwrap( ) . subst_identity( )
193
- ) ;
204
+ if le && !ge {
205
+ debug ! (
206
+ "descending as child of TraitRef {:?}" ,
207
+ tcx. impl_trait_ref( possible_sibling) . unwrap( ) . subst_identity( )
208
+ ) ;
194
209
195
- replace_children. push ( possible_sibling) ;
196
- } else {
197
- // Either there's no overlap, or the overlap was already reported by
198
- // `overlap_error`.
199
- }
200
- }
210
+ // The impl specializes `possible_sibling`.
211
+ return Ok ( OverlapResult :: SpecializeOne ( possible_sibling) ) ;
212
+ } else if ge && !le {
213
+ debug ! (
214
+ "placing as parent of TraitRef {:?}" ,
215
+ tcx. impl_trait_ref( possible_sibling) . unwrap( ) . subst_identity( )
216
+ ) ;
201
217
202
- if !replace_children. is_empty ( ) {
203
- return Ok ( OverlapResult :: SpecializeAll ( replace_children) ) ;
218
+ replace_children. push ( possible_sibling) ;
219
+ } else {
220
+ // Either there's no overlap, or the overlap was already reported by
221
+ // `overlap_error`.
204
222
}
223
+ }
205
224
206
- // No overlap with any potential siblings, so add as a new sibling.
207
- debug ! ( "placing as new sibling" ) ;
208
- self . insert_blindly ( tcx, impl_def_id) ;
209
- Ok ( OverlapResult :: NoOverlap ( last_lint) )
225
+ if !replace_children. is_empty ( ) {
226
+ return Ok ( OverlapResult :: SpecializeAll ( replace_children) ) ;
210
227
}
228
+
229
+ Ok ( OverlapResult :: NoOverlap ( last_lint) )
211
230
}
212
231
213
232
fn iter_children ( children : & mut Children ) -> impl Iterator < Item = DefId > + ' _ {
0 commit comments