@@ -80,22 +80,30 @@ fn dropck_outlives<'tcx>(
80
80
let mut fulfill_cx = TraitEngine :: new ( infcx. tcx ) ;
81
81
82
82
let cause = ObligationCause :: dummy ( ) ;
83
+ let mut constraints = DtorckConstraint :: empty ( ) ;
83
84
while let Some ( ( ty, depth) ) = ty_stack. pop ( ) {
84
- let DtorckConstraint {
85
- dtorck_types,
86
- outlives,
87
- overflows,
88
- } = dtorck_constraint_for_ty ( tcx, DUMMY_SP , for_ty, depth, ty) ?;
85
+ info ! ( "{} kinds, {} overflows, {} ty_stack" ,
86
+ result. kinds. len( ) , result. overflows. len( ) , ty_stack. len( ) ) ;
87
+ dtorck_constraint_for_ty ( tcx, DUMMY_SP , for_ty, depth, ty, & mut constraints) ?;
89
88
90
89
// "outlives" represent types/regions that may be touched
91
90
// by a destructor.
92
- result. kinds . extend ( outlives) ;
93
- result. overflows . extend ( overflows) ;
91
+ result. kinds . extend ( constraints. outlives . drain ( ..) ) ;
92
+ result. overflows . extend ( constraints. overflows . drain ( ..) ) ;
93
+
94
+ // If we have even one overflow, we should stop trying to evaluate further --
95
+ // chances are, the subsequent overflows for this evaluation won't provide useful
96
+ // information and will just decrease the speed at which we can emit these errors
97
+ // (since we'll be printing for just that much longer for the often enormous types
98
+ // that result here).
99
+ if result. overflows . len ( ) >= 1 {
100
+ break ;
101
+ }
94
102
95
103
// dtorck types are "types that will get dropped but which
96
104
// do not themselves define a destructor", more or less. We have
97
105
// to push them onto the stack to be expanded.
98
- for ty in dtorck_types {
106
+ for ty in constraints . dtorck_types . drain ( .. ) {
99
107
match infcx. at ( & cause, param_env) . normalize ( & ty) {
100
108
Ok ( Normalized {
101
109
value : ty,
@@ -152,25 +160,23 @@ fn dtorck_constraint_for_ty<'tcx>(
152
160
for_ty : Ty < ' tcx > ,
153
161
depth : usize ,
154
162
ty : Ty < ' tcx > ,
155
- ) -> Result < DtorckConstraint < ' tcx > , NoSolution > {
163
+ constraints : & mut DtorckConstraint < ' tcx > ,
164
+ ) -> Result < ( ) , NoSolution > {
156
165
debug ! (
157
166
"dtorck_constraint_for_ty({:?}, {:?}, {:?}, {:?})" ,
158
167
span, for_ty, depth, ty
159
168
) ;
160
169
161
170
if depth >= * tcx. sess . recursion_limit . get ( ) {
162
- return Ok ( DtorckConstraint {
163
- outlives : vec ! [ ] ,
164
- dtorck_types : vec ! [ ] ,
165
- overflows : vec ! [ ty] ,
166
- } ) ;
171
+ constraints. overflows . push ( ty) ;
172
+ return Ok ( ( ) ) ;
167
173
}
168
174
169
175
if tcx. trivial_dropck_outlives ( ty) {
170
- return Ok ( DtorckConstraint :: empty ( ) ) ;
176
+ return Ok ( ( ) ) ;
171
177
}
172
178
173
- let result = match ty. kind {
179
+ match ty. kind {
174
180
ty:: Bool
175
181
| ty:: Char
176
182
| ty:: Int ( _)
@@ -185,22 +191,20 @@ fn dtorck_constraint_for_ty<'tcx>(
185
191
| ty:: FnPtr ( _)
186
192
| ty:: GeneratorWitness ( ..) => {
187
193
// these types never have a destructor
188
- Ok ( DtorckConstraint :: empty ( ) )
189
194
}
190
195
191
196
ty:: Array ( ety, _) | ty:: Slice ( ety) => {
192
197
// single-element containers, behave like their element
193
- dtorck_constraint_for_ty ( tcx, span, for_ty, depth + 1 , ety)
198
+ dtorck_constraint_for_ty ( tcx, span, for_ty, depth + 1 , ety, constraints ) ? ;
194
199
}
195
200
196
- ty:: Tuple ( tys) => tys. iter ( )
197
- . map ( |ty| dtorck_constraint_for_ty ( tcx, span, for_ty, depth + 1 , ty. expect_ty ( ) ) )
198
- . collect ( ) ,
201
+ ty:: Tuple ( tys) => for ty in tys. iter ( ) {
202
+ dtorck_constraint_for_ty ( tcx, span, for_ty, depth + 1 , ty. expect_ty ( ) , constraints ) ? ;
203
+ } ,
199
204
200
- ty:: Closure ( def_id, substs) => substs. as_closure ( )
201
- . upvar_tys ( def_id, tcx)
202
- . map ( |ty| dtorck_constraint_for_ty ( tcx, span, for_ty, depth + 1 , ty) )
203
- . collect ( ) ,
205
+ ty:: Closure ( def_id, substs) => for ty in substs. as_closure ( ) . upvar_tys ( def_id, tcx) {
206
+ dtorck_constraint_for_ty ( tcx, span, for_ty, depth + 1 , ty, constraints) ?;
207
+ }
204
208
205
209
ty:: Generator ( def_id, substs, _movability) => {
206
210
// rust-lang/rust#49918: types can be constructed, stored
@@ -226,17 +230,8 @@ fn dtorck_constraint_for_ty<'tcx>(
226
230
// derived from lifetimes attached to the upvars, and we
227
231
// *do* incorporate the upvars here.
228
232
229
- let constraint = DtorckConstraint {
230
- outlives : substs. as_generator ( ) . upvar_tys ( def_id, tcx) . map ( |t| t. into ( ) ) . collect ( ) ,
231
- dtorck_types : vec ! [ ] ,
232
- overflows : vec ! [ ] ,
233
- } ;
234
- debug ! (
235
- "dtorck_constraint: generator {:?} => {:?}" ,
236
- def_id, constraint
237
- ) ;
238
-
239
- Ok ( constraint)
233
+ constraints. outlives . extend ( substs. as_generator ( ) . upvar_tys ( def_id, tcx)
234
+ . map ( |t| -> ty:: subst:: GenericArg < ' tcx > { t. into ( ) } ) ) ;
240
235
}
241
236
242
237
ty:: Adt ( def, substs) => {
@@ -245,41 +240,34 @@ fn dtorck_constraint_for_ty<'tcx>(
245
240
outlives,
246
241
overflows,
247
242
} = tcx. at ( span) . adt_dtorck_constraint ( def. did ) ?;
248
- Ok ( DtorckConstraint {
249
- // FIXME: we can try to recursively `dtorck_constraint_on_ty`
250
- // there, but that needs some way to handle cycles.
251
- dtorck_types : dtorck_types. subst ( tcx, substs) ,
252
- outlives : outlives. subst ( tcx, substs) ,
253
- overflows : overflows. subst ( tcx, substs) ,
254
- } )
243
+ // FIXME: we can try to recursively `dtorck_constraint_on_ty`
244
+ // there, but that needs some way to handle cycles.
245
+ constraints. dtorck_types . extend ( dtorck_types. subst ( tcx, substs) ) ;
246
+ constraints. outlives . extend ( outlives. subst ( tcx, substs) ) ;
247
+ constraints. overflows . extend ( overflows. subst ( tcx, substs) ) ;
255
248
}
256
249
257
250
// Objects must be alive in order for their destructor
258
251
// to be called.
259
- ty:: Dynamic ( ..) => Ok ( DtorckConstraint {
260
- outlives : vec ! [ ty. into( ) ] ,
261
- dtorck_types : vec ! [ ] ,
262
- overflows : vec ! [ ] ,
263
- } ) ,
252
+ ty:: Dynamic ( ..) => {
253
+ constraints. outlives . push ( ty. into ( ) ) ;
254
+ } ,
264
255
265
256
// Types that can't be resolved. Pass them forward.
266
- ty:: Projection ( ..) | ty:: Opaque ( ..) | ty:: Param ( ..) => Ok ( DtorckConstraint {
267
- outlives : vec ! [ ] ,
268
- dtorck_types : vec ! [ ty] ,
269
- overflows : vec ! [ ] ,
270
- } ) ,
257
+ ty:: Projection ( ..) | ty:: Opaque ( ..) | ty:: Param ( ..) => {
258
+ constraints. dtorck_types . push ( ty) ;
259
+ } ,
271
260
272
261
ty:: UnnormalizedProjection ( ..) => bug ! ( "only used with chalk-engine" ) ,
273
262
274
263
ty:: Placeholder ( ..) | ty:: Bound ( ..) | ty:: Infer ( ..) | ty:: Error => {
275
264
// By the time this code runs, all type variables ought to
276
265
// be fully resolved.
277
- Err ( NoSolution )
266
+ return Err ( NoSolution )
278
267
}
279
- } ;
268
+ }
280
269
281
- debug ! ( "dtorck_constraint_for_ty({:?}) = {:?}" , ty, result) ;
282
- result
270
+ Ok ( ( ) )
283
271
}
284
272
285
273
/// Calculates the dtorck constraint for a type.
@@ -305,10 +293,11 @@ crate fn adt_dtorck_constraint(
305
293
return Ok ( result) ;
306
294
}
307
295
308
- let mut result = def. all_fields ( )
309
- . map ( |field| tcx. type_of ( field. did ) )
310
- . map ( |fty| dtorck_constraint_for_ty ( tcx, span, fty, 0 , fty) )
311
- . collect :: < Result < DtorckConstraint < ' _ > , NoSolution > > ( ) ?;
296
+ let mut result = DtorckConstraint :: empty ( ) ;
297
+ for field in def. all_fields ( ) {
298
+ let fty = tcx. type_of ( field. did ) ;
299
+ dtorck_constraint_for_ty ( tcx, span, fty, 0 , fty, & mut result) ?;
300
+ }
312
301
result. outlives . extend ( tcx. destructor_constraints ( def) ) ;
313
302
dedup_dtorck_constraint ( & mut result) ;
314
303
0 commit comments