@@ -78,7 +78,7 @@ impl<'tcx, F> NeedsDropTypes<'tcx, F> {
78
78
79
79
impl < ' tcx , F , I > Iterator for NeedsDropTypes < ' tcx , F >
80
80
where
81
- F : Fn ( & ty:: AdtDef , SubstsRef < ' tcx > ) -> NeedsDropResult < I > ,
81
+ F : Fn ( & ty:: AdtDef , SubstsRef < ' tcx > , & FxHashSet < Ty < ' tcx > > ) -> NeedsDropResult < I > ,
82
82
I : Iterator < Item = Ty < ' tcx > > ,
83
83
{
84
84
type Item = NeedsDropResult < Ty < ' tcx > > ;
@@ -142,7 +142,7 @@ where
142
142
// `ManuallyDrop`. If it's a struct or enum without a `Drop`
143
143
// impl then check whether the field types need `Drop`.
144
144
ty:: Adt ( adt_def, substs) => {
145
- let tys = match ( self . adt_components ) ( adt_def, substs) {
145
+ let tys = match ( self . adt_components ) ( adt_def, substs, & self . seen_tys ) {
146
146
Err ( e) => return Some ( Err ( e) ) ,
147
147
Ok ( tys) => tys,
148
148
} ;
@@ -200,62 +200,67 @@ fn drop_tys_helper<'tcx>(
200
200
tcx : TyCtxt < ' tcx > ,
201
201
iter : impl IntoIterator < Item = Ty < ' tcx > > ,
202
202
only_significant : bool ,
203
+ seen_tys : & FxHashSet < Ty < ' tcx > > ,
203
204
) -> NeedsDropResult < Vec < Ty < ' tcx > > > {
204
205
iter. into_iter ( ) . try_fold ( Vec :: new ( ) , |mut vec, subty| {
205
- match subty. kind ( ) {
206
- ty:: Adt ( adt_id, subst) => {
207
- for subty in if only_significant {
208
- tcx. adt_significant_drop_tys ( adt_id. did ) ?
209
- } else {
210
- tcx. adt_drop_tys ( adt_id. did ) ?
211
- } {
212
- vec. push ( subty. subst ( tcx, subst) ) ;
206
+ if !seen_tys. contains ( subty) {
207
+ match subty. kind ( ) {
208
+ ty:: Adt ( adt_id, subst) => {
209
+ for subty in if only_significant {
210
+ tcx. adt_significant_drop_tys ( adt_id. did ) ?
211
+ } else {
212
+ tcx. adt_drop_tys ( adt_id. did ) ?
213
+ } {
214
+ vec. push ( subty. subst ( tcx, subst) ) ;
215
+ }
213
216
}
214
- }
215
- _ => vec . push ( subty ) ,
216
- } ;
217
+ _ => vec . push ( subty ) ,
218
+ } ;
219
+ }
217
220
Ok ( vec)
218
221
} )
219
222
}
220
223
221
- let adt_components = move |adt_def : & ty:: AdtDef , substs : SubstsRef < ' tcx > | {
222
- if adt_def. is_manually_drop ( ) {
223
- debug ! ( "drop_tys_helper: `{:?}` is manually drop" , adt_def) ;
224
- Ok ( Vec :: new ( ) )
225
- } else if let Some ( dtor_info) = adt_has_dtor ( adt_def) {
226
- match dtor_info {
227
- DtorType :: Significant => {
228
- debug ! ( "drop_tys_helper: `{:?}` implements `Drop`" , adt_def) ;
229
- Err ( AlwaysRequiresDrop )
230
- }
231
- DtorType :: Insignificant => {
232
- debug ! ( "drop_tys_helper: `{:?}` drop is insignificant" , adt_def) ;
224
+ let adt_components =
225
+ move |adt_def : & ty:: AdtDef , substs : SubstsRef < ' tcx > , seen_tys : & FxHashSet < Ty < ' tcx > > | {
226
+ if adt_def. is_manually_drop ( ) {
227
+ debug ! ( "drop_tys_helper: `{:?}` is manually drop" , adt_def) ;
228
+ Ok ( Vec :: new ( ) )
229
+ } else if let Some ( dtor_info) = adt_has_dtor ( adt_def) {
230
+ match dtor_info {
231
+ DtorType :: Significant => {
232
+ debug ! ( "drop_tys_helper: `{:?}` implements `Drop`" , adt_def) ;
233
+ Err ( AlwaysRequiresDrop )
234
+ }
235
+ DtorType :: Insignificant => {
236
+ debug ! ( "drop_tys_helper: `{:?}` drop is insignificant" , adt_def) ;
233
237
234
- // Since the destructor is insignificant, we just want to make sure all of
235
- // the passed in type parameters are also insignificant.
236
- // Eg: Vec<T> dtor is insignificant when T=i32 but significant when T=Mutex.
237
- with_query_cache ( tcx, substs. types ( ) , only_significant)
238
+ // Since the destructor is insignificant, we just want to make sure all of
239
+ // the passed in type parameters are also insignificant.
240
+ // Eg: Vec<T> dtor is insignificant when T=i32 but significant when T=Mutex.
241
+ with_query_cache ( tcx, substs. types ( ) , only_significant, seen_tys)
242
+ }
238
243
}
244
+ } else if adt_def. is_union ( ) {
245
+ debug ! ( "drop_tys_helper: `{:?}` is a union" , adt_def) ;
246
+ Ok ( Vec :: new ( ) )
247
+ } else {
248
+ with_query_cache (
249
+ tcx,
250
+ adt_def. all_fields ( ) . map ( |field| {
251
+ let r = tcx. type_of ( field. did ) . subst ( tcx, substs) ;
252
+ debug ! (
253
+ "drop_tys_helper: Subst into {:?} with {:?} gettng {:?}" ,
254
+ field, substs, r
255
+ ) ;
256
+ r
257
+ } ) ,
258
+ only_significant,
259
+ seen_tys,
260
+ )
239
261
}
240
- } else if adt_def. is_union ( ) {
241
- debug ! ( "drop_tys_helper: `{:?}` is a union" , adt_def) ;
242
- Ok ( Vec :: new ( ) )
243
- } else {
244
- with_query_cache (
245
- tcx,
246
- adt_def. all_fields ( ) . map ( |field| {
247
- let r = tcx. type_of ( field. did ) . subst ( tcx, substs) ;
248
- debug ! (
249
- "drop_tys_helper: Subst into {:?} with {:?} gettng {:?}" ,
250
- field, substs, r
251
- ) ;
252
- r
253
- } ) ,
254
- only_significant,
255
- )
256
- }
257
- . map ( |v| v. into_iter ( ) )
258
- } ;
262
+ . map ( |v| v. into_iter ( ) )
263
+ } ;
259
264
260
265
NeedsDropTypes :: new ( tcx, param_env, ty, adt_components)
261
266
}
0 commit comments