Skip to content

Commit 786db73

Browse files
committed
Move report_region_errors to region_errors.rs
1 parent 736348a commit 786db73

File tree

2 files changed

+125
-124
lines changed

2 files changed

+125
-124
lines changed

src/librustc_mir/borrow_check/diagnostics/region_errors.rs

+123-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! Error reporting machinery for lifetime errors.
22
3-
use rustc::infer::{error_reporting::nice_region_error::NiceRegionError, NLLRegionVariableOrigin};
3+
use rustc::infer::{
4+
error_reporting::nice_region_error::NiceRegionError, opaque_types, NLLRegionVariableOrigin,
5+
};
46
use rustc::mir::ConstraintCategory;
57
use rustc::ty::{self, RegionVid, Ty};
68
use rustc_errors::{Applicability, DiagnosticBuilder};
@@ -109,8 +111,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
109111
/// existentially bound, then we check its inferred value and try
110112
/// to find a good name from that. Returns `None` if we can't find
111113
/// one (e.g., this is just some random part of the CFG).
112-
// TODO(mark-i-m): make this private when we move report_region_errors here...
113-
crate fn to_error_region(&self, r: RegionVid) -> Option<ty::Region<'tcx>> {
114+
pub(super) fn to_error_region(&self, r: RegionVid) -> Option<ty::Region<'tcx>> {
114115
self.to_error_region_vid(r)
115116
.and_then(|r| self.nonlexical_regioncx.definitions[r].external_name)
116117
}
@@ -147,6 +148,125 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
147148
false
148149
}
149150

151+
/// Produces nice borrowck error diagnostics for all the errors collected in `nll_errors`.
152+
pub(in crate::borrow_check) fn report_region_errors(&mut self, nll_errors: RegionErrors<'tcx>) {
153+
// Iterate through all the errors, producing a diagnostic for each one. The diagnostics are
154+
// buffered in the `MirBorrowckCtxt`.
155+
156+
// TODO(mark-i-m): Would be great to get rid of the naming context.
157+
let mut region_naming = RegionErrorNamingCtx::new();
158+
let mut outlives_suggestion = OutlivesSuggestionBuilder::default();
159+
160+
for nll_error in nll_errors.into_iter() {
161+
match nll_error {
162+
RegionErrorKind::TypeTestError { type_test } => {
163+
// Try to convert the lower-bound region into something named we can print for the user.
164+
let lower_bound_region = self.to_error_region(type_test.lower_bound);
165+
166+
// Skip duplicate-ish errors.
167+
let type_test_span = type_test.locations.span(&self.body);
168+
169+
if let Some(lower_bound_region) = lower_bound_region {
170+
let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id);
171+
self.infcx
172+
.construct_generic_bound_failure(
173+
region_scope_tree,
174+
type_test_span,
175+
None,
176+
type_test.generic_kind,
177+
lower_bound_region,
178+
)
179+
.buffer(&mut self.errors_buffer);
180+
} else {
181+
// FIXME. We should handle this case better. It
182+
// indicates that we have e.g., some region variable
183+
// whose value is like `'a+'b` where `'a` and `'b` are
184+
// distinct unrelated univesal regions that are not
185+
// known to outlive one another. It'd be nice to have
186+
// some examples where this arises to decide how best
187+
// to report it; we could probably handle it by
188+
// iterating over the universal regions and reporting
189+
// an error that multiple bounds are required.
190+
self.infcx
191+
.tcx
192+
.sess
193+
.struct_span_err(
194+
type_test_span,
195+
&format!("`{}` does not live long enough", type_test.generic_kind),
196+
)
197+
.buffer(&mut self.errors_buffer);
198+
}
199+
}
200+
201+
RegionErrorKind::UnexpectedHiddenRegion {
202+
opaque_type_def_id,
203+
hidden_ty,
204+
member_region,
205+
} => {
206+
let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id);
207+
opaque_types::unexpected_hidden_region_diagnostic(
208+
self.infcx.tcx,
209+
Some(region_scope_tree),
210+
opaque_type_def_id,
211+
hidden_ty,
212+
member_region,
213+
)
214+
.buffer(&mut self.errors_buffer);
215+
}
216+
217+
RegionErrorKind::BoundUniversalRegionError {
218+
longer_fr,
219+
fr_origin,
220+
error_element,
221+
} => {
222+
let error_region =
223+
self.nonlexical_regioncx.region_from_element(longer_fr, error_element);
224+
225+
// Find the code to blame for the fact that `longer_fr` outlives `error_fr`.
226+
let (_, span) = self.nonlexical_regioncx.find_outlives_blame_span(
227+
&self.body,
228+
longer_fr,
229+
fr_origin,
230+
error_region,
231+
);
232+
233+
// FIXME: improve this error message
234+
self.infcx
235+
.tcx
236+
.sess
237+
.struct_span_err(span, "higher-ranked subtype error")
238+
.buffer(&mut self.errors_buffer);
239+
}
240+
241+
RegionErrorKind::RegionError { fr_origin, longer_fr, shorter_fr, is_reported } => {
242+
if is_reported {
243+
self.report_error(
244+
longer_fr,
245+
fr_origin,
246+
shorter_fr,
247+
&mut outlives_suggestion,
248+
&mut region_naming,
249+
);
250+
} else {
251+
// We only report the first error, so as not to overwhelm the user. See
252+
// `RegRegionErrorKind` docs.
253+
//
254+
// FIXME: currently we do nothing with these, but perhaps we can do better?
255+
// FIXME: try collecting these constraints on the outlives suggestion
256+
// builder. Does it make the suggestions any better?
257+
debug!(
258+
"Unreported region error: can't prove that {:?}: {:?}",
259+
longer_fr, shorter_fr
260+
);
261+
}
262+
}
263+
}
264+
}
265+
266+
// Emit one outlives suggestions for each MIR def we borrowck
267+
outlives_suggestion.add_suggestion(self, &mut region_naming);
268+
}
269+
150270
/// Report an error because the universal region `fr` was required to outlive
151271
/// `outlived_fr` but it is not known to do so. For example:
152272
///

src/librustc_mir/borrow_check/mod.rs

+2-121
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! This query borrow-checks the MIR to (further) ensure it is not broken.
22
3-
use rustc::infer::{opaque_types, InferCtxt};
3+
use rustc::infer::InferCtxt;
44
use rustc::lint::builtin::MUTABLE_BORROW_RESERVATION_CONFLICT;
55
use rustc::lint::builtin::UNUSED_MUT;
66
use rustc::mir::{
@@ -39,9 +39,7 @@ use crate::dataflow::{do_dataflow, DebugFormatted};
3939
use crate::dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
4040
use crate::transform::MirSource;
4141

42-
use self::diagnostics::{
43-
AccessKind, OutlivesSuggestionBuilder, RegionErrorKind, RegionErrorNamingCtx, RegionErrors,
44-
};
42+
use self::diagnostics::AccessKind;
4543
use self::flows::Flows;
4644
use self::location::LocationTable;
4745
use self::prefixes::PrefixSet;
@@ -1465,123 +1463,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
14651463
// initial reservation.
14661464
}
14671465
}
1468-
1469-
/// Produces nice borrowck error diagnostics for all the errors collected in `nll_errors`.
1470-
fn report_region_errors(&mut self, nll_errors: RegionErrors<'tcx>) {
1471-
// Iterate through all the errors, producing a diagnostic for each one. The diagnostics are
1472-
// buffered in the `MirBorrowckCtxt`.
1473-
1474-
// TODO(mark-i-m): Would be great to get rid of the naming context.
1475-
let mut region_naming = RegionErrorNamingCtx::new();
1476-
let mut outlives_suggestion = OutlivesSuggestionBuilder::default();
1477-
1478-
for nll_error in nll_errors.into_iter() {
1479-
match nll_error {
1480-
RegionErrorKind::TypeTestError { type_test } => {
1481-
// Try to convert the lower-bound region into something named we can print for the user.
1482-
let lower_bound_region = self.to_error_region(type_test.lower_bound);
1483-
1484-
// Skip duplicate-ish errors.
1485-
let type_test_span = type_test.locations.span(&self.body);
1486-
1487-
if let Some(lower_bound_region) = lower_bound_region {
1488-
let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id);
1489-
self.infcx
1490-
.construct_generic_bound_failure(
1491-
region_scope_tree,
1492-
type_test_span,
1493-
None,
1494-
type_test.generic_kind,
1495-
lower_bound_region,
1496-
)
1497-
.buffer(&mut self.errors_buffer);
1498-
} else {
1499-
// FIXME. We should handle this case better. It indicates that we have
1500-
// e.g., some region variable whose value is like `'a+'b` where `'a` and
1501-
// `'b` are distinct unrelated univesal regions that are not known to
1502-
// outlive one another. It'd be nice to have some examples where this
1503-
// arises to decide how best to report it; we could probably handle it by
1504-
// iterating over the universal regions and reporting an error that
1505-
// multiple bounds are required.
1506-
self.infcx
1507-
.tcx
1508-
.sess
1509-
.struct_span_err(
1510-
type_test_span,
1511-
&format!("`{}` does not live long enough", type_test.generic_kind),
1512-
)
1513-
.buffer(&mut self.errors_buffer);
1514-
}
1515-
}
1516-
1517-
RegionErrorKind::UnexpectedHiddenRegion {
1518-
opaque_type_def_id,
1519-
hidden_ty,
1520-
member_region,
1521-
} => {
1522-
let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id);
1523-
opaque_types::unexpected_hidden_region_diagnostic(
1524-
self.infcx.tcx,
1525-
Some(region_scope_tree),
1526-
opaque_type_def_id,
1527-
hidden_ty,
1528-
member_region,
1529-
)
1530-
.buffer(&mut self.errors_buffer);
1531-
}
1532-
1533-
RegionErrorKind::BoundUniversalRegionError {
1534-
longer_fr,
1535-
fr_origin,
1536-
error_element,
1537-
} => {
1538-
let error_region =
1539-
self.nonlexical_regioncx.region_from_element(longer_fr, error_element);
1540-
1541-
// Find the code to blame for the fact that `longer_fr` outlives `error_fr`.
1542-
let (_, span) = self.nonlexical_regioncx.find_outlives_blame_span(
1543-
&self.body,
1544-
longer_fr,
1545-
fr_origin,
1546-
error_region,
1547-
);
1548-
1549-
// FIXME: improve this error message
1550-
self.infcx
1551-
.tcx
1552-
.sess
1553-
.struct_span_err(span, "higher-ranked subtype error")
1554-
.buffer(&mut self.errors_buffer);
1555-
}
1556-
1557-
RegionErrorKind::RegionError { fr_origin, longer_fr, shorter_fr, is_reported } => {
1558-
if is_reported {
1559-
self.report_error(
1560-
longer_fr,
1561-
fr_origin,
1562-
shorter_fr,
1563-
&mut outlives_suggestion,
1564-
&mut region_naming,
1565-
);
1566-
} else {
1567-
// We only report the first error, so as not to overwhelm the user. See
1568-
// `RegRegionErrorKind` docs.
1569-
//
1570-
// FIXME: currently we do nothing with these, but perhaps we can do better?
1571-
// FIXME: try collecting these constraints on the outlives suggestion
1572-
// builder. Does it make the suggestions any better?
1573-
debug!(
1574-
"Unreported region error: can't prove that {:?}: {:?}",
1575-
longer_fr, shorter_fr
1576-
);
1577-
}
1578-
}
1579-
}
1580-
}
1581-
1582-
// Emit one outlives suggestions for each MIR def we borrowck
1583-
outlives_suggestion.add_suggestion(self, &mut region_naming);
1584-
}
15851466
}
15861467

15871468
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {

0 commit comments

Comments
 (0)