@@ -80,22 +80,30 @@ fn dropck_outlives<'tcx>(
8080 let mut fulfill_cx = TraitEngine :: new ( infcx. tcx ) ;
8181
8282 let cause = ObligationCause :: dummy ( ) ;
83+ let mut constraints = DtorckConstraint :: empty ( ) ;
8384 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) ?;
8988
9089 // "outlives" represent types/regions that may be touched
9190 // 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+ }
94102
95103 // dtorck types are "types that will get dropped but which
96104 // do not themselves define a destructor", more or less. We have
97105 // to push them onto the stack to be expanded.
98- for ty in dtorck_types {
106+ for ty in constraints . dtorck_types . drain ( .. ) {
99107 match infcx. at ( & cause, param_env) . normalize ( & ty) {
100108 Ok ( Normalized {
101109 value : ty,
@@ -152,21 +160,23 @@ fn dtorck_constraint_for_ty<'tcx>(
152160 for_ty : Ty < ' tcx > ,
153161 depth : usize ,
154162 ty : Ty < ' tcx > ,
155- ) -> Result < DtorckConstraint < ' tcx > , NoSolution > {
163+ constraints : & mut DtorckConstraint < ' tcx > ,
164+ ) -> Result < ( ) , NoSolution > {
156165 debug ! (
157166 "dtorck_constraint_for_ty({:?}, {:?}, {:?}, {:?})" ,
158167 span, for_ty, depth, ty
159168 ) ;
160169
161170 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 ( ( ) ) ;
167173 }
168174
169- let result = match ty. kind {
175+ if tcx. trivial_dropck_outlives ( ty) {
176+ return Ok ( ( ) ) ;
177+ }
178+
179+ match ty. kind {
170180 ty:: Bool
171181 | ty:: Char
172182 | ty:: Int ( _)
@@ -181,22 +191,20 @@ fn dtorck_constraint_for_ty<'tcx>(
181191 | ty:: FnPtr ( _)
182192 | ty:: GeneratorWitness ( ..) => {
183193 // these types never have a destructor
184- Ok ( DtorckConstraint :: empty ( ) )
185194 }
186195
187196 ty:: Array ( ety, _) | ty:: Slice ( ety) => {
188197 // 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 ) ? ;
190199 }
191200
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+ } ,
195204
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+ }
200208
201209 ty:: Generator ( def_id, substs, _movability) => {
202210 // rust-lang/rust#49918: types can be constructed, stored
@@ -222,17 +230,8 @@ fn dtorck_constraint_for_ty<'tcx>(
222230 // derived from lifetimes attached to the upvars, and we
223231 // *do* incorporate the upvars here.
224232
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 ( ) } ) ) ;
236235 }
237236
238237 ty:: Adt ( def, substs) => {
@@ -241,41 +240,34 @@ fn dtorck_constraint_for_ty<'tcx>(
241240 outlives,
242241 overflows,
243242 } = 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) ) ;
251248 }
252249
253250 // Objects must be alive in order for their destructor
254251 // 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+ } ,
260255
261256 // 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+ } ,
267260
268261 ty:: UnnormalizedProjection ( ..) => bug ! ( "only used with chalk-engine" ) ,
269262
270263 ty:: Placeholder ( ..) | ty:: Bound ( ..) | ty:: Infer ( ..) | ty:: Error => {
271264 // By the time this code runs, all type variables ought to
272265 // be fully resolved.
273- Err ( NoSolution )
266+ return Err ( NoSolution )
274267 }
275- } ;
268+ }
276269
277- debug ! ( "dtorck_constraint_for_ty({:?}) = {:?}" , ty, result) ;
278- result
270+ Ok ( ( ) )
279271}
280272
281273/// Calculates the dtorck constraint for a type.
@@ -301,10 +293,11 @@ crate fn adt_dtorck_constraint(
301293 return Ok ( result) ;
302294 }
303295
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+ }
308301 result. outlives . extend ( tcx. destructor_constraints ( def) ) ;
309302 dedup_dtorck_constraint ( & mut result) ;
310303
0 commit comments