Skip to content

Commit 5d9e74e

Browse files
committed
some more refactoring + maintain diagnostic status quo
1 parent e5a1f48 commit 5d9e74e

File tree

1 file changed

+50
-40
lines changed
  • src/librustc_mir/borrow_check/region_infer

1 file changed

+50
-40
lines changed

src/librustc_mir/borrow_check/region_infer/mod.rs

Lines changed: 50 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use rustc::mir::{
99
ConstraintCategory, Local, Location,
1010
};
1111
use rustc::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable};
12-
use rustc::util::common::ErrorReported;
1312
use rustc_errors::DiagnosticBuilder;
1413
use rustc_data_structures::binary_search_util;
1514
use 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+
228236
impl<'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

Comments
 (0)