@@ -9,7 +9,6 @@ use rustc::mir::{
99 ConstraintCategory , Local , Location ,
1010} ;
1111use rustc:: ty:: { self , subst:: SubstsRef , RegionVid , Ty , TyCtxt , TypeFoldable } ;
12- use rustc:: util:: common:: ErrorReported ;
1312use rustc_errors:: DiagnosticBuilder ;
1413use rustc_data_structures:: binary_search_util;
1514use rustc_index:: bit_set:: BitSet ;
@@ -225,6 +224,15 @@ pub struct TypeTest<'tcx> {
225224 pub verify_bound : VerifyBound < ' tcx > ,
226225}
227226
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+
228236impl < ' tcx > RegionInferenceContext < ' tcx > {
229237 /// Creates a new region inference context with a total of
230238 /// `num_region_variables` valid inference variables; the first N
@@ -1386,7 +1394,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
13861394 body,
13871395 & mut propagated_outlives_requirements,
13881396 ) ;
1389- if ! propagated {
1397+ if propagated == RegionRelationCheckResult :: Error {
13901398 errors_buffer. push ( RegionErrorKind :: RegionError {
13911399 longer_fr : * longer_fr,
13921400 shorter_fr : * shorter_fr,
@@ -1412,7 +1420,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
14121420 }
14131421 }
14141422 }
1415-
14161423 }
14171424
14181425 /// Checks the final value for the free region `fr` to see if it
@@ -1447,86 +1454,89 @@ impl<'tcx> RegionInferenceContext<'tcx> {
14471454 // one in this SCC, so we will always check the representative here.
14481455 let representative = self . scc_representatives [ longer_fr_scc] ;
14491456 if representative != longer_fr {
1450- self . check_universal_region_relation (
1457+ if let RegionRelationCheckResult :: Error = self . check_universal_region_relation (
14511458 longer_fr,
14521459 representative,
14531460 body,
14541461 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+ }
14571469 return ;
14581470 }
14591471
14601472 // Find every region `o` such that `fr: o`
14611473 // (because `fr` includes `end(o)`).
1474+ let mut error_reported = false ;
14621475 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 (
14641477 longer_fr,
14651478 shorter_fr,
14661479 body,
14671480 propagated_outlives_requirements,
1468- errors_buffer,
14691481 ) {
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 ;
14771498 }
14781499 }
14791500 }
14801501
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.
14811505 fn check_universal_region_relation (
14821506 & self ,
14831507 longer_fr : RegionVid ,
14841508 shorter_fr : RegionVid ,
14851509 body : & Body < ' tcx > ,
14861510 propagated_outlives_requirements : & mut Option < & mut Vec < ClosureOutlivesRequirement < ' tcx > > > ,
1487- errors_buffer : & mut RegionErrors < ' tcx > ,
1488- ) -> Option < ErrorReported > {
1511+ ) -> RegionRelationCheckResult {
14891512 // If it is known that `fr: o`, carry on.
14901513 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
15031515 } else {
15041516 // If we are not in a context where we can't propagate errors, or we
15051517 // could not shrink `fr` to something smaller, then just report an
15061518 // error.
15071519 //
15081520 // Note: in this case, we use the unapproximated regions to report the
15091521 // 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+ )
15161528 }
15171529 }
15181530
15191531 /// Attempt to propagate a region error (e.g. `'a: 'b`) that is not met to a closure's
15201532 /// 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.
15231533 fn try_propagate_universal_region_error (
15241534 & self ,
15251535 longer_fr : RegionVid ,
15261536 shorter_fr : RegionVid ,
15271537 body : & Body < ' tcx > ,
15281538 propagated_outlives_requirements : & mut Option < & mut Vec < ClosureOutlivesRequirement < ' tcx > > > ,
1529- ) -> bool {
1539+ ) -> RegionRelationCheckResult {
15301540 if let Some ( propagated_outlives_requirements) = propagated_outlives_requirements {
15311541 // Shrink `longer_fr` until we find a non-local region (if we do).
15321542 // We'll call it `fr-` -- it's ever so slightly smaller than
@@ -1558,11 +1568,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
15581568 category : blame_span_category. 0 ,
15591569 } ) ;
15601570 }
1561- return true ;
1571+ return RegionRelationCheckResult :: Propagated ;
15621572 }
15631573 }
15641574
1565- false
1575+ RegionRelationCheckResult :: Error
15661576 }
15671577
15681578 fn check_bound_universal_region (
0 commit comments