@@ -17,7 +17,8 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>
17
17
// needs drop.
18
18
let adt_has_dtor =
19
19
|adt_def : & ty:: AdtDef | adt_def. destructor ( tcx) . map ( |_| DtorType :: Significant ) ;
20
- let res = drop_tys_helper ( tcx, query. value , query. param_env , adt_has_dtor) . next ( ) . is_some ( ) ;
20
+ let res =
21
+ drop_tys_helper ( tcx, query. value , query. param_env , adt_has_dtor, false ) . next ( ) . is_some ( ) ;
21
22
22
23
debug ! ( "needs_drop_raw({:?}) = {:?}" , query, res) ;
23
24
res
@@ -27,10 +28,15 @@ fn has_significant_drop_raw<'tcx>(
27
28
tcx : TyCtxt < ' tcx > ,
28
29
query : ty:: ParamEnvAnd < ' tcx , Ty < ' tcx > > ,
29
30
) -> bool {
30
- let res =
31
- drop_tys_helper ( tcx, query. value , query. param_env , adt_consider_insignificant_dtor ( tcx) )
32
- . next ( )
33
- . is_some ( ) ;
31
+ let res = drop_tys_helper (
32
+ tcx,
33
+ query. value ,
34
+ query. param_env ,
35
+ adt_consider_insignificant_dtor ( tcx) ,
36
+ true ,
37
+ )
38
+ . next ( )
39
+ . is_some ( ) ;
34
40
debug ! ( "has_significant_drop_raw({:?}) = {:?}" , query, res) ;
35
41
res
36
42
}
@@ -141,9 +147,9 @@ where
141
147
Ok ( tys) => tys,
142
148
} ;
143
149
for required_ty in tys {
144
- let subst_ty =
150
+ let required =
145
151
tcx. normalize_erasing_regions ( self . param_env , required_ty) ;
146
- queue_type ( self , subst_ty ) ;
152
+ queue_type ( self , required ) ;
147
153
}
148
154
}
149
155
ty:: Array ( ..) | ty:: Opaque ( ..) | ty:: Projection ( ..) | ty:: Param ( _) => {
@@ -186,39 +192,67 @@ fn drop_tys_helper<'tcx>(
186
192
ty : Ty < ' tcx > ,
187
193
param_env : rustc_middle:: ty:: ParamEnv < ' tcx > ,
188
194
adt_has_dtor : impl Fn ( & ty:: AdtDef ) -> Option < DtorType > ,
195
+ only_significant : bool ,
189
196
) -> impl Iterator < Item = NeedsDropResult < Ty < ' tcx > > > {
197
+ fn with_query_cache < ' tcx > (
198
+ tcx : TyCtxt < ' tcx > ,
199
+ iter : impl IntoIterator < Item = Ty < ' tcx > > ,
200
+ only_significant : bool ,
201
+ ) -> NeedsDropResult < Vec < Ty < ' tcx > > > {
202
+ iter. into_iter ( ) . try_fold ( Vec :: new ( ) , |mut vec, subty| {
203
+ match subty. kind ( ) {
204
+ ty:: Adt ( adt_id, subst) => {
205
+ for subty in if only_significant {
206
+ tcx. adt_significant_drop_tys ( adt_id. did ) ?
207
+ } else {
208
+ tcx. adt_drop_tys ( adt_id. did ) ?
209
+ } {
210
+ vec. push ( subty. subst ( tcx, subst) ) ;
211
+ }
212
+ }
213
+ _ => vec. push ( subty) ,
214
+ } ;
215
+ Ok ( vec)
216
+ } )
217
+ }
218
+
190
219
let adt_components = move |adt_def : & ty:: AdtDef , substs : SubstsRef < ' tcx > | {
191
220
if adt_def. is_manually_drop ( ) {
192
221
debug ! ( "drop_tys_helper: `{:?}` is manually drop" , adt_def) ;
193
- return Ok ( Vec :: new ( ) . into_iter ( ) ) ;
222
+ Ok ( Vec :: new ( ) )
194
223
} else if let Some ( dtor_info) = adt_has_dtor ( adt_def) {
195
224
match dtor_info {
196
225
DtorType :: Significant => {
197
226
debug ! ( "drop_tys_helper: `{:?}` implements `Drop`" , adt_def) ;
198
- return Err ( AlwaysRequiresDrop ) ;
227
+ Err ( AlwaysRequiresDrop )
199
228
}
200
229
DtorType :: Insignificant => {
201
230
debug ! ( "drop_tys_helper: `{:?}` drop is insignificant" , adt_def) ;
202
231
203
232
// Since the destructor is insignificant, we just want to make sure all of
204
233
// the passed in type parameters are also insignificant.
205
234
// Eg: Vec<T> dtor is insignificant when T=i32 but significant when T=Mutex.
206
- return Ok ( substs. types ( ) . collect :: < Vec < Ty < ' _ > > > ( ) . into_iter ( ) ) ;
235
+ with_query_cache ( tcx , substs. types ( ) , only_significant )
207
236
}
208
237
}
209
238
} else if adt_def. is_union ( ) {
210
239
debug ! ( "drop_tys_helper: `{:?}` is a union" , adt_def) ;
211
- return Ok ( Vec :: new ( ) . into_iter ( ) ) ;
240
+ Ok ( Vec :: new ( ) )
241
+ } else {
242
+ with_query_cache (
243
+ tcx,
244
+ adt_def. all_fields ( ) . map ( |field| {
245
+ let r = tcx. type_of ( field. did ) . subst ( tcx, substs) ;
246
+ debug ! (
247
+ "drop_tys_helper: Subst into {:?} with {:?} gettng {:?}" ,
248
+ field, substs, r
249
+ ) ;
250
+ r
251
+ } ) ,
252
+ only_significant,
253
+ )
212
254
}
213
- Ok ( adt_def
214
- . all_fields ( )
215
- . map ( |field| {
216
- let r = tcx. type_of ( field. did ) . subst ( tcx, substs) ;
217
- debug ! ( "drop_tys_helper: Subst into {:?} with {:?} gettng {:?}" , field, substs, r) ;
218
- r
219
- } )
220
- . collect :: < Vec < _ > > ( )
221
- . into_iter ( ) )
255
+ . map ( |v| v. into_iter ( ) )
222
256
} ;
223
257
224
258
NeedsDropTypes :: new ( tcx, param_env, ty, adt_components)
@@ -252,20 +286,24 @@ fn adt_drop_tys(tcx: TyCtxt<'_>, def_id: DefId) -> Result<&ty::List<Ty<'_>>, Alw
252
286
// significant.
253
287
let adt_has_dtor =
254
288
|adt_def : & ty:: AdtDef | adt_def. destructor ( tcx) . map ( |_| DtorType :: Significant ) ;
255
- drop_tys_helper ( tcx, tcx. type_of ( def_id) , tcx. param_env ( def_id) , adt_has_dtor)
289
+ // `tcx.type_of(def_id)` identical to `tcx.make_adt(def, identity_substs)`
290
+ drop_tys_helper ( tcx, tcx. type_of ( def_id) , tcx. param_env ( def_id) , adt_has_dtor, false )
256
291
. collect :: < Result < Vec < _ > , _ > > ( )
257
292
. map ( |components| tcx. intern_type_list ( & components) )
258
293
}
259
-
294
+ // If `def_id` refers to a generic ADT, the queries above and below act as if they had been handed
295
+ // a `tcx.make_ty(def, identity_substs)` and as such it is legal to substitue the generic parameters
296
+ // of the ADT into the outputted `ty`s.
260
297
fn adt_significant_drop_tys (
261
298
tcx : TyCtxt < ' _ > ,
262
299
def_id : DefId ,
263
300
) -> Result < & ty:: List < Ty < ' _ > > , AlwaysRequiresDrop > {
264
301
drop_tys_helper (
265
302
tcx,
266
- tcx. type_of ( def_id) ,
303
+ tcx. type_of ( def_id) , // identical to `tcx.make_adt(def, identity_substs)`
267
304
tcx. param_env ( def_id) ,
268
305
adt_consider_insignificant_dtor ( tcx) ,
306
+ true ,
269
307
)
270
308
. collect :: < Result < Vec < _ > , _ > > ( )
271
309
. map ( |components| tcx. intern_type_list ( & components) )
0 commit comments