@@ -9,7 +9,6 @@ use rustc::mir::{
9
9
ConstraintCategory , Local , Location ,
10
10
} ;
11
11
use rustc:: ty:: { self , subst:: SubstsRef , RegionVid , Ty , TyCtxt , TypeFoldable } ;
12
- use rustc:: util:: common:: ErrorReported ;
13
12
use rustc_errors:: DiagnosticBuilder ;
14
13
use rustc_data_structures:: binary_search_util;
15
14
use rustc_index:: bit_set:: BitSet ;
@@ -225,6 +224,15 @@ pub struct TypeTest<'tcx> {
225
224
pub verify_bound : VerifyBound < ' tcx > ,
226
225
}
227
226
227
+ /// When we have an unmet lifetime constraint, we try to propagate it outward (e.g. to a closure
228
+ /// environment). If we can't, it is an error.
229
+ #[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
230
+ enum RegionRelationCheckResult {
231
+ Ok ,
232
+ Propagated ,
233
+ Error ,
234
+ }
235
+
228
236
impl < ' tcx > RegionInferenceContext < ' tcx > {
229
237
/// Creates a new region inference context with a total of
230
238
/// `num_region_variables` valid inference variables; the first N
@@ -1386,7 +1394,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1386
1394
body,
1387
1395
& mut propagated_outlives_requirements,
1388
1396
) ;
1389
- if ! propagated {
1397
+ if propagated == RegionRelationCheckResult :: Error {
1390
1398
errors_buffer. push ( RegionErrorKind :: RegionError {
1391
1399
longer_fr : * longer_fr,
1392
1400
shorter_fr : * shorter_fr,
@@ -1412,7 +1420,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1412
1420
}
1413
1421
}
1414
1422
}
1415
-
1416
1423
}
1417
1424
1418
1425
/// Checks the final value for the free region `fr` to see if it
@@ -1447,86 +1454,89 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1447
1454
// one in this SCC, so we will always check the representative here.
1448
1455
let representative = self . scc_representatives [ longer_fr_scc] ;
1449
1456
if representative != longer_fr {
1450
- self . check_universal_region_relation (
1457
+ if let RegionRelationCheckResult :: Error = self . check_universal_region_relation (
1451
1458
longer_fr,
1452
1459
representative,
1453
1460
body,
1454
1461
propagated_outlives_requirements,
1455
- errors_buffer,
1456
- ) ;
1462
+ ) {
1463
+ errors_buffer. push ( RegionErrorKind :: RegionError {
1464
+ longer_fr,
1465
+ shorter_fr : representative,
1466
+ fr_origin : NLLRegionVariableOrigin :: FreeRegion ,
1467
+ } ) ;
1468
+ }
1457
1469
return ;
1458
1470
}
1459
1471
1460
1472
// Find every region `o` such that `fr: o`
1461
1473
// (because `fr` includes `end(o)`).
1474
+ let mut error_reported = false ;
1462
1475
for shorter_fr in self . scc_values . universal_regions_outlived_by ( longer_fr_scc) {
1463
- if let Some ( ErrorReported ) = self . check_universal_region_relation (
1476
+ if let RegionRelationCheckResult :: Error = self . check_universal_region_relation (
1464
1477
longer_fr,
1465
1478
shorter_fr,
1466
1479
body,
1467
1480
propagated_outlives_requirements,
1468
- errors_buffer,
1469
1481
) {
1470
- // We only report the first region error. Subsequent errors are hidden so as not to
1471
- // overwhelm the user, but we do record them so as to potentially print better
1472
- // diagnostics elsewhere...
1473
- errors_buffer. push ( RegionErrorKind :: UnreportedError {
1474
- longer_fr, shorter_fr,
1475
- fr_origin : NLLRegionVariableOrigin :: FreeRegion ,
1476
- } ) ;
1482
+ // We only report the first region error. Subsequent errors are hidden so as
1483
+ // not to overwhelm the user, but we do record them so as to potentially print
1484
+ // better diagnostics elsewhere...
1485
+ if error_reported {
1486
+ errors_buffer. push ( RegionErrorKind :: UnreportedError {
1487
+ longer_fr, shorter_fr,
1488
+ fr_origin : NLLRegionVariableOrigin :: FreeRegion ,
1489
+ } ) ;
1490
+ } else {
1491
+ errors_buffer. push ( RegionErrorKind :: RegionError {
1492
+ longer_fr, shorter_fr,
1493
+ fr_origin : NLLRegionVariableOrigin :: FreeRegion ,
1494
+ } ) ;
1495
+ }
1496
+
1497
+ error_reported = true ;
1477
1498
}
1478
1499
}
1479
1500
}
1480
1501
1502
+ /// Checks that we can prove that `longer_fr: shorter_fr`. If we can't we attempt to propagate
1503
+ /// the constraint outward (e.g. to a closure environment), but if that fails, there is an
1504
+ /// error.
1481
1505
fn check_universal_region_relation (
1482
1506
& self ,
1483
1507
longer_fr : RegionVid ,
1484
1508
shorter_fr : RegionVid ,
1485
1509
body : & Body < ' tcx > ,
1486
1510
propagated_outlives_requirements : & mut Option < & mut Vec < ClosureOutlivesRequirement < ' tcx > > > ,
1487
- errors_buffer : & mut RegionErrors < ' tcx > ,
1488
- ) -> Option < ErrorReported > {
1511
+ ) -> RegionRelationCheckResult {
1489
1512
// If it is known that `fr: o`, carry on.
1490
1513
if self . universal_region_relations . outlives ( longer_fr, shorter_fr) {
1491
- return None ;
1492
- }
1493
-
1494
- let propagated = self . try_propagate_universal_region_error (
1495
- longer_fr,
1496
- shorter_fr,
1497
- body,
1498
- propagated_outlives_requirements,
1499
- ) ;
1500
-
1501
- if propagated {
1502
- None
1514
+ RegionRelationCheckResult :: Ok
1503
1515
} else {
1504
1516
// If we are not in a context where we can't propagate errors, or we
1505
1517
// could not shrink `fr` to something smaller, then just report an
1506
1518
// error.
1507
1519
//
1508
1520
// Note: in this case, we use the unapproximated regions to report the
1509
1521
// error. This gives better error messages in some cases.
1510
- errors_buffer . push ( RegionErrorKind :: RegionError {
1511
- longer_fr, shorter_fr ,
1512
- fr_origin : NLLRegionVariableOrigin :: FreeRegion ,
1513
- } ) ;
1514
-
1515
- Some ( ErrorReported )
1522
+ self . try_propagate_universal_region_error (
1523
+ longer_fr,
1524
+ shorter_fr ,
1525
+ body ,
1526
+ propagated_outlives_requirements ,
1527
+ )
1516
1528
}
1517
1529
}
1518
1530
1519
1531
/// Attempt to propagate a region error (e.g. `'a: 'b`) that is not met to a closure's
1520
1532
/// creator. If we cannot, then the caller should report an error to the user.
1521
- ///
1522
- /// Returns `true` if the error was propagated, and `false` otherwise.
1523
1533
fn try_propagate_universal_region_error (
1524
1534
& self ,
1525
1535
longer_fr : RegionVid ,
1526
1536
shorter_fr : RegionVid ,
1527
1537
body : & Body < ' tcx > ,
1528
1538
propagated_outlives_requirements : & mut Option < & mut Vec < ClosureOutlivesRequirement < ' tcx > > > ,
1529
- ) -> bool {
1539
+ ) -> RegionRelationCheckResult {
1530
1540
if let Some ( propagated_outlives_requirements) = propagated_outlives_requirements {
1531
1541
// Shrink `longer_fr` until we find a non-local region (if we do).
1532
1542
// We'll call it `fr-` -- it's ever so slightly smaller than
@@ -1558,11 +1568,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1558
1568
category : blame_span_category. 0 ,
1559
1569
} ) ;
1560
1570
}
1561
- return true ;
1571
+ return RegionRelationCheckResult :: Propagated ;
1562
1572
}
1563
1573
}
1564
1574
1565
- false
1575
+ RegionRelationCheckResult :: Error
1566
1576
}
1567
1577
1568
1578
fn check_bound_universal_region (
0 commit comments