@@ -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,25 +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
169175 if tcx. trivial_dropck_outlives ( ty) {
170- return Ok ( DtorckConstraint :: empty ( ) ) ;
176+ return Ok ( ( ) ) ;
171177 }
172178
173- let result = match ty. kind {
179+ match ty. kind {
174180 ty:: Bool
175181 | ty:: Char
176182 | ty:: Int ( _)
@@ -185,22 +191,20 @@ fn dtorck_constraint_for_ty<'tcx>(
185191 | ty:: FnPtr ( _)
186192 | ty:: GeneratorWitness ( ..) => {
187193 // these types never have a destructor
188- Ok ( DtorckConstraint :: empty ( ) )
189194 }
190195
191196 ty:: Array ( ety, _) | ty:: Slice ( ety) => {
192197 // 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 ) ? ;
194199 }
195200
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+ } ,
199204
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+ }
204208
205209 ty:: Generator ( def_id, substs, _movability) => {
206210 // rust-lang/rust#49918: types can be constructed, stored
@@ -226,17 +230,8 @@ fn dtorck_constraint_for_ty<'tcx>(
226230 // derived from lifetimes attached to the upvars, and we
227231 // *do* incorporate the upvars here.
228232
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 ( ) } ) ) ;
240235 }
241236
242237 ty:: Adt ( def, substs) => {
@@ -245,41 +240,34 @@ fn dtorck_constraint_for_ty<'tcx>(
245240 outlives,
246241 overflows,
247242 } = 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) ) ;
255248 }
256249
257250 // Objects must be alive in order for their destructor
258251 // 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+ } ,
264255
265256 // 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+ } ,
271260
272261 ty:: UnnormalizedProjection ( ..) => bug ! ( "only used with chalk-engine" ) ,
273262
274263 ty:: Placeholder ( ..) | ty:: Bound ( ..) | ty:: Infer ( ..) | ty:: Error => {
275264 // By the time this code runs, all type variables ought to
276265 // be fully resolved.
277- Err ( NoSolution )
266+ return Err ( NoSolution )
278267 }
279- } ;
268+ }
280269
281- debug ! ( "dtorck_constraint_for_ty({:?}) = {:?}" , ty, result) ;
282- result
270+ Ok ( ( ) )
283271}
284272
285273/// Calculates the dtorck constraint for a type.
@@ -305,10 +293,11 @@ crate fn adt_dtorck_constraint(
305293 return Ok ( result) ;
306294 }
307295
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+ }
312301 result. outlives . extend ( tcx. destructor_constraints ( def) ) ;
313302 dedup_dtorck_constraint ( & mut result) ;
314303
0 commit comments