@@ -251,24 +251,88 @@ impl<'tcx> RegionInferenceContext<'tcx> {
251
251
mir_def_id : DefId ,
252
252
) -> Option < ClosureRegionRequirements > {
253
253
assert ! ( self . inferred_values. is_none( ) , "values already inferred" ) ;
254
- let tcx = infcx. tcx ;
255
254
256
- // Find the minimal regions that can solve the constraints. This is infallible.
257
255
self . propagate_constraints ( mir) ;
258
256
259
- // Now, see whether any of the constraints were too strong. In
260
- // particular, we want to check for a case where a universally
261
- // quantified region exceeded its bounds. Consider:
262
- //
263
- // fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
264
- //
265
- // In this case, returning `x` requires `&'a u32 <: &'b u32`
266
- // and hence we establish (transitively) a constraint that
267
- // `'a: 'b`. The `propagate_constraints` code above will
268
- // therefore add `end('a)` into the region for `'b` -- but we
269
- // have no evidence that `'a` outlives `'b`, so we want to report
270
- // an error.
257
+ let outlives_requirements = self . check_universal_regions ( infcx , mir_def_id ) ;
258
+
259
+ if outlives_requirements . is_empty ( ) {
260
+ None
261
+ } else {
262
+ let num_external_vids = self . universal_regions . num_global_and_external_regions ( ) ;
263
+ Some ( ClosureRegionRequirements {
264
+ num_external_vids ,
265
+ outlives_requirements ,
266
+ } )
267
+ }
268
+ }
271
269
270
+ /// Propagate the region constraints: this will grow the values
271
+ /// for each region variable until all the constraints are
272
+ /// satisfied. Note that some values may grow **too** large to be
273
+ /// feasible, but we check this later.
274
+ fn propagate_constraints ( & mut self , mir : & Mir < ' tcx > ) {
275
+ let mut changed = true ;
276
+
277
+ debug ! ( "propagate_constraints()" ) ;
278
+ debug ! ( "propagate_constraints: constraints={:#?}" , {
279
+ let mut constraints: Vec <_> = self . constraints. iter( ) . collect( ) ;
280
+ constraints. sort( ) ;
281
+ constraints
282
+ } ) ;
283
+
284
+ // The initial values for each region are derived from the liveness
285
+ // constraints we have accumulated.
286
+ let mut inferred_values = self . liveness_constraints . clone ( ) ;
287
+
288
+ while changed {
289
+ changed = false ;
290
+ debug ! ( "propagate_constraints: --------------------" ) ;
291
+ for constraint in & self . constraints {
292
+ debug ! ( "propagate_constraints: constraint={:?}" , constraint) ;
293
+
294
+ // Grow the value as needed to accommodate the
295
+ // outlives constraint.
296
+ let Ok ( made_changes) = self . dfs (
297
+ mir,
298
+ CopyFromSourceToTarget {
299
+ source_region : constraint. sub ,
300
+ target_region : constraint. sup ,
301
+ inferred_values : & mut inferred_values,
302
+ constraint_point : constraint. point ,
303
+ } ,
304
+ ) ;
305
+
306
+ if made_changes {
307
+ debug ! ( "propagate_constraints: sub={:?}" , constraint. sub) ;
308
+ debug ! ( "propagate_constraints: sup={:?}" , constraint. sup) ;
309
+ changed = true ;
310
+ }
311
+ }
312
+ debug ! ( "\n " ) ;
313
+ }
314
+
315
+ self . inferred_values = Some ( inferred_values) ;
316
+ }
317
+
318
+ /// Once regions have been propagated, this method is used to see
319
+ /// whether any of the constraints were too strong. In particular,
320
+ /// we want to check for a case where a universally quantified
321
+ /// region exceeded its bounds. Consider:
322
+ ///
323
+ /// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
324
+ ///
325
+ /// In this case, returning `x` requires `&'a u32 <: &'b u32`
326
+ /// and hence we establish (transitively) a constraint that
327
+ /// `'a: 'b`. The `propagate_constraints` code above will
328
+ /// therefore add `end('a)` into the region for `'b` -- but we
329
+ /// have no evidence that `'b` outlives `'a`, so we want to report
330
+ /// an error.
331
+ fn check_universal_regions (
332
+ & self ,
333
+ infcx : & InferCtxt < ' _ , ' _ , ' tcx > ,
334
+ mir_def_id : DefId ,
335
+ ) -> Vec < ClosureOutlivesRequirement > {
272
336
// The universal regions are always found in a prefix of the
273
337
// full list.
274
338
let universal_definitions = self . definitions
@@ -283,27 +347,23 @@ impl<'tcx> RegionInferenceContext<'tcx> {
283
347
self . check_universal_region ( infcx, fr, & mut outlives_requirements) ;
284
348
}
285
349
286
- // If this is not a closure, then there is no caller to which we can
287
- // "pass the buck". So if there are any outlives-requirements that were
288
- // not satisfied, we just have to report a hard error here.
289
- if !tcx. is_closure ( mir_def_id) {
290
- for outlives_requirement in outlives_requirements {
291
- self . report_error (
292
- infcx,
293
- outlives_requirement. free_region ,
294
- outlives_requirement. outlived_free_region ,
295
- outlives_requirement. blame_span ,
296
- ) ;
297
- }
298
- return None ;
350
+ // If this is a closure, we can propagate unsatisfied
351
+ // `outlives_requirements` to our creator. Otherwise, we have
352
+ // to report a hard error here.
353
+ if infcx. tcx . is_closure ( mir_def_id) {
354
+ return outlives_requirements;
299
355
}
300
356
301
- let num_external_vids = self . universal_regions . num_global_and_external_regions ( ) ;
357
+ for outlives_requirement in outlives_requirements {
358
+ self . report_error (
359
+ infcx,
360
+ outlives_requirement. free_region ,
361
+ outlives_requirement. outlived_free_region ,
362
+ outlives_requirement. blame_span ,
363
+ ) ;
364
+ }
302
365
303
- Some ( ClosureRegionRequirements {
304
- num_external_vids,
305
- outlives_requirements,
306
- } )
366
+ vec ! [ ]
307
367
}
308
368
309
369
/// Check the final value for the free region `fr` to see if it
@@ -396,54 +456,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
396
456
) ;
397
457
}
398
458
399
- /// Propagate the region constraints: this will grow the values
400
- /// for each region variable until all the constraints are
401
- /// satisfied. Note that some values may grow **too** large to be
402
- /// feasible, but we check this later.
403
- fn propagate_constraints ( & mut self , mir : & Mir < ' tcx > ) {
404
- let mut changed = true ;
405
-
406
- debug ! ( "propagate_constraints()" ) ;
407
- debug ! ( "propagate_constraints: constraints={:#?}" , {
408
- let mut constraints: Vec <_> = self . constraints. iter( ) . collect( ) ;
409
- constraints. sort( ) ;
410
- constraints
411
- } ) ;
412
-
413
- // The initial values for each region are derived from the liveness
414
- // constraints we have accumulated.
415
- let mut inferred_values = self . liveness_constraints . clone ( ) ;
416
-
417
- while changed {
418
- changed = false ;
419
- debug ! ( "propagate_constraints: --------------------" ) ;
420
- for constraint in & self . constraints {
421
- debug ! ( "propagate_constraints: constraint={:?}" , constraint) ;
422
-
423
- // Grow the value as needed to accommodate the
424
- // outlives constraint.
425
- let Ok ( made_changes) = self . dfs (
426
- mir,
427
- CopyFromSourceToTarget {
428
- source_region : constraint. sub ,
429
- target_region : constraint. sup ,
430
- inferred_values : & mut inferred_values,
431
- constraint_point : constraint. point ,
432
- } ,
433
- ) ;
434
-
435
- if made_changes {
436
- debug ! ( "propagate_constraints: sub={:?}" , constraint. sub) ;
437
- debug ! ( "propagate_constraints: sup={:?}" , constraint. sup) ;
438
- changed = true ;
439
- }
440
- }
441
- debug ! ( "\n " ) ;
442
- }
443
-
444
- self . inferred_values = Some ( inferred_values) ;
445
- }
446
-
447
459
/// Tries to finds a good span to blame for the fact that `fr1`
448
460
/// contains `fr2`.
449
461
fn blame_span ( & self , fr1 : RegionVid , fr2 : RegionVid ) -> Span {
@@ -589,4 +601,3 @@ impl ClosureRegionRequirementsExt for ClosureRegionRequirements {
589
601
}
590
602
}
591
603
}
592
-
0 commit comments