@@ -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,21 +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
- let result = match ty. kind {
175
+ if tcx. trivial_dropck_outlives ( ty) {
176
+ return Ok ( ( ) ) ;
177
+ }
178
+
179
+ match ty. kind {
170
180
ty:: Bool
171
181
| ty:: Char
172
182
| ty:: Int ( _)
@@ -181,22 +191,20 @@ fn dtorck_constraint_for_ty<'tcx>(
181
191
| ty:: FnPtr ( _)
182
192
| ty:: GeneratorWitness ( ..) => {
183
193
// these types never have a destructor
184
- Ok ( DtorckConstraint :: empty ( ) )
185
194
}
186
195
187
196
ty:: Array ( ety, _) | ty:: Slice ( ety) => {
188
197
// single-element containers, behave like their element
189
- dtorck_constraint_for_ty ( tcx, span, for_ty, depth + 1 , ety)
198
+ dtorck_constraint_for_ty ( tcx, span, for_ty, depth + 1 , ety, constraints ) ? ;
190
199
}
191
200
192
- ty:: Tuple ( tys) => tys. iter ( )
193
- . map ( |ty| dtorck_constraint_for_ty ( tcx, span, for_ty, depth + 1 , ty. expect_ty ( ) ) )
194
- . 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
+ } ,
195
204
196
- ty:: Closure ( def_id, substs) => substs. as_closure ( )
197
- . upvar_tys ( def_id, tcx)
198
- . map ( |ty| dtorck_constraint_for_ty ( tcx, span, for_ty, depth + 1 , ty) )
199
- . 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
+ }
200
208
201
209
ty:: Generator ( def_id, substs, _movability) => {
202
210
// rust-lang/rust#49918: types can be constructed, stored
@@ -222,17 +230,8 @@ fn dtorck_constraint_for_ty<'tcx>(
222
230
// derived from lifetimes attached to the upvars, and we
223
231
// *do* incorporate the upvars here.
224
232
225
- let constraint = DtorckConstraint {
226
- outlives : substs. as_generator ( ) . upvar_tys ( def_id, tcx) . map ( |t| t. into ( ) ) . collect ( ) ,
227
- dtorck_types : vec ! [ ] ,
228
- overflows : vec ! [ ] ,
229
- } ;
230
- debug ! (
231
- "dtorck_constraint: generator {:?} => {:?}" ,
232
- def_id, constraint
233
- ) ;
234
-
235
- Ok ( constraint)
233
+ constraints. outlives . extend ( substs. as_generator ( ) . upvar_tys ( def_id, tcx)
234
+ . map ( |t| -> ty:: subst:: GenericArg < ' tcx > { t. into ( ) } ) ) ;
236
235
}
237
236
238
237
ty:: Adt ( def, substs) => {
@@ -241,41 +240,34 @@ fn dtorck_constraint_for_ty<'tcx>(
241
240
outlives,
242
241
overflows,
243
242
} = tcx. at ( span) . adt_dtorck_constraint ( def. did ) ?;
244
- Ok ( DtorckConstraint {
245
- // FIXME: we can try to recursively `dtorck_constraint_on_ty`
246
- // there, but that needs some way to handle cycles.
247
- dtorck_types : dtorck_types. subst ( tcx, substs) ,
248
- outlives : outlives. subst ( tcx, substs) ,
249
- overflows : overflows. subst ( tcx, substs) ,
250
- } )
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) ) ;
251
248
}
252
249
253
250
// Objects must be alive in order for their destructor
254
251
// to be called.
255
- ty:: Dynamic ( ..) => Ok ( DtorckConstraint {
256
- outlives : vec ! [ ty. into( ) ] ,
257
- dtorck_types : vec ! [ ] ,
258
- overflows : vec ! [ ] ,
259
- } ) ,
252
+ ty:: Dynamic ( ..) => {
253
+ constraints. outlives . push ( ty. into ( ) ) ;
254
+ } ,
260
255
261
256
// Types that can't be resolved. Pass them forward.
262
- ty:: Projection ( ..) | ty:: Opaque ( ..) | ty:: Param ( ..) => Ok ( DtorckConstraint {
263
- outlives : vec ! [ ] ,
264
- dtorck_types : vec ! [ ty] ,
265
- overflows : vec ! [ ] ,
266
- } ) ,
257
+ ty:: Projection ( ..) | ty:: Opaque ( ..) | ty:: Param ( ..) => {
258
+ constraints. dtorck_types . push ( ty) ;
259
+ } ,
267
260
268
261
ty:: UnnormalizedProjection ( ..) => bug ! ( "only used with chalk-engine" ) ,
269
262
270
263
ty:: Placeholder ( ..) | ty:: Bound ( ..) | ty:: Infer ( ..) | ty:: Error => {
271
264
// By the time this code runs, all type variables ought to
272
265
// be fully resolved.
273
- Err ( NoSolution )
266
+ return Err ( NoSolution )
274
267
}
275
- } ;
268
+ }
276
269
277
- debug ! ( "dtorck_constraint_for_ty({:?}) = {:?}" , ty, result) ;
278
- result
270
+ Ok ( ( ) )
279
271
}
280
272
281
273
/// Calculates the dtorck constraint for a type.
@@ -301,10 +293,11 @@ crate fn adt_dtorck_constraint(
301
293
return Ok ( result) ;
302
294
}
303
295
304
- let mut result = def. all_fields ( )
305
- . map ( |field| tcx. type_of ( field. did ) )
306
- . map ( |fty| dtorck_constraint_for_ty ( tcx, span, fty, 0 , fty) )
307
- . 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
+ }
308
301
result. outlives . extend ( tcx. destructor_constraints ( def) ) ;
309
302
dedup_dtorck_constraint ( & mut result) ;
310
303
0 commit comments