@@ -133,7 +133,7 @@ pub fn compute_dropck_outlives_inner<'tcx>(
133
133
result. overflows. len( ) ,
134
134
ty_stack. len( )
135
135
) ;
136
- dtorck_constraint_for_ty_inner ( tcx, DUMMY_SP , for_ty , depth, ty, & mut constraints) ?;
136
+ dtorck_constraint_for_ty_inner ( tcx, param_env , DUMMY_SP , depth, ty, & mut constraints) ?;
137
137
138
138
// "outlives" represent types/regions that may be touched
139
139
// by a destructor.
@@ -185,16 +185,15 @@ pub fn compute_dropck_outlives_inner<'tcx>(
185
185
186
186
/// Returns a set of constraints that needs to be satisfied in
187
187
/// order for `ty` to be valid for destruction.
188
+ #[ instrument( level = "debug" , skip( tcx, param_env, span, constraints) ) ]
188
189
pub fn dtorck_constraint_for_ty_inner < ' tcx > (
189
190
tcx : TyCtxt < ' tcx > ,
191
+ param_env : ty:: ParamEnv < ' tcx > ,
190
192
span : Span ,
191
- for_ty : Ty < ' tcx > ,
192
193
depth : usize ,
193
194
ty : Ty < ' tcx > ,
194
195
constraints : & mut DropckConstraint < ' tcx > ,
195
196
) -> Result < ( ) , NoSolution > {
196
- debug ! ( "dtorck_constraint_for_ty_inner({:?}, {:?}, {:?}, {:?})" , span, for_ty, depth, ty) ;
197
-
198
197
if !tcx. recursion_limit ( ) . value_within_limit ( depth) {
199
198
constraints. overflows . push ( ty) ;
200
199
return Ok ( ( ) ) ;
@@ -224,13 +223,13 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
224
223
ty:: Array ( ety, _) | ty:: Slice ( ety) => {
225
224
// single-element containers, behave like their element
226
225
rustc_data_structures:: stack:: ensure_sufficient_stack ( || {
227
- dtorck_constraint_for_ty_inner ( tcx, span , for_ty , depth + 1 , * ety, constraints)
226
+ dtorck_constraint_for_ty_inner ( tcx, param_env , span , depth + 1 , * ety, constraints)
228
227
} ) ?;
229
228
}
230
229
231
230
ty:: Tuple ( tys) => rustc_data_structures:: stack:: ensure_sufficient_stack ( || {
232
231
for ty in tys. iter ( ) {
233
- dtorck_constraint_for_ty_inner ( tcx, span , for_ty , depth + 1 , ty, constraints) ?;
232
+ dtorck_constraint_for_ty_inner ( tcx, param_env , span , depth + 1 , ty, constraints) ?;
234
233
}
235
234
Ok :: < _ , NoSolution > ( ( ) )
236
235
} ) ?,
@@ -249,7 +248,14 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
249
248
250
249
rustc_data_structures:: stack:: ensure_sufficient_stack ( || {
251
250
for ty in args. as_closure ( ) . upvar_tys ( ) {
252
- dtorck_constraint_for_ty_inner ( tcx, span, for_ty, depth + 1 , ty, constraints) ?;
251
+ dtorck_constraint_for_ty_inner (
252
+ tcx,
253
+ param_env,
254
+ span,
255
+ depth + 1 ,
256
+ ty,
257
+ constraints,
258
+ ) ?;
253
259
}
254
260
Ok :: < _ , NoSolution > ( ( ) )
255
261
} ) ?
@@ -278,8 +284,8 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
278
284
// only take place through references with lifetimes
279
285
// derived from lifetimes attached to the upvars and resume
280
286
// argument, and we *do* incorporate those here.
281
-
282
- if !args. as_coroutine ( ) . is_valid ( ) {
287
+ let args = args . as_coroutine ( ) ;
288
+ if !args. is_valid ( ) {
283
289
// By the time this code runs, all type variables ought to
284
290
// be fully resolved.
285
291
tcx. sess . delay_span_bug (
@@ -289,10 +295,13 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
289
295
return Err ( NoSolution ) ;
290
296
}
291
297
292
- constraints
293
- . outlives
294
- . extend ( args. as_coroutine ( ) . upvar_tys ( ) . iter ( ) . map ( ty:: GenericArg :: from) ) ;
295
- constraints. outlives . push ( args. as_coroutine ( ) . resume_ty ( ) . into ( ) ) ;
298
+ // While we conservatively assume that all coroutines require drop
299
+ // to avoid query cycles during MIR building, we can check the actual
300
+ // witness during borrowck to avoid unnecessary liveness constraints.
301
+ if args. witness ( ) . needs_drop ( tcx, tcx. erase_regions ( param_env) ) {
302
+ constraints. outlives . extend ( args. upvar_tys ( ) . iter ( ) . map ( ty:: GenericArg :: from) ) ;
303
+ constraints. outlives . push ( args. resume_ty ( ) . into ( ) ) ;
304
+ }
296
305
}
297
306
298
307
ty:: Adt ( def, args) => {
0 commit comments