@@ -78,7 +78,7 @@ impl<'tcx, F> NeedsDropTypes<'tcx, F> {
7878
7979impl < ' tcx , F , I > Iterator for NeedsDropTypes < ' tcx , F >
8080where
81- F : Fn ( & ty:: AdtDef , SubstsRef < ' tcx > ) -> NeedsDropResult < I > ,
81+ F : Fn ( & ty:: AdtDef , SubstsRef < ' tcx > , & FxHashSet < Ty < ' tcx > > ) -> NeedsDropResult < I > ,
8282 I : Iterator < Item = Ty < ' tcx > > ,
8383{
8484 type Item = NeedsDropResult < Ty < ' tcx > > ;
@@ -142,7 +142,7 @@ where
142142 // `ManuallyDrop`. If it's a struct or enum without a `Drop`
143143 // impl then check whether the field types need `Drop`.
144144 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 ) {
146146 Err ( e) => return Some ( Err ( e) ) ,
147147 Ok ( tys) => tys,
148148 } ;
@@ -200,62 +200,67 @@ fn drop_tys_helper<'tcx>(
200200 tcx : TyCtxt < ' tcx > ,
201201 iter : impl IntoIterator < Item = Ty < ' tcx > > ,
202202 only_significant : bool ,
203+ seen_tys : & FxHashSet < Ty < ' tcx > > ,
203204 ) -> NeedsDropResult < Vec < Ty < ' tcx > > > {
204205 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+ }
213216 }
214- }
215- _ => vec . push ( subty ) ,
216- } ;
217+ _ => vec . push ( subty ) ,
218+ } ;
219+ }
217220 Ok ( vec)
218221 } )
219222 }
220223
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) ;
233237
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+ }
238243 }
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+ )
239261 }
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+ } ;
259264
260265 NeedsDropTypes :: new ( tcx, param_env, ty, adt_components)
261266}
0 commit comments