Skip to content

Commit ea6fe08

Browse files
committed
Split explain_why_borrow_contains_point into two functions
Allows callers to change other parts of their message based on the explanation
1 parent df6ba0c commit ea6fe08

File tree

1 file changed

+86
-22
lines changed
  • src/librustc_mir/borrow_check/nll/explain_borrow

1 file changed

+86
-22
lines changed

src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs

+86-22
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,28 @@
1111
use borrow_check::borrow_set::BorrowData;
1212
use borrow_check::nll::region_infer::Cause;
1313
use borrow_check::{Context, MirBorrowckCtxt, WriteKind};
14-
use rustc::mir::{Location, Place, TerminatorKind};
14+
use rustc::mir::{Local, Location, Place, TerminatorKind};
1515
use rustc_errors::DiagnosticBuilder;
16+
use rustc::ty::Region;
1617

1718
mod find_use;
1819

20+
#[derive(Copy, Clone, Debug)]
21+
pub enum BorrowContainsPointReason<'tcx> {
22+
Liveness {
23+
local: Local,
24+
location: Location,
25+
in_loop: bool,
26+
},
27+
DropLiveness {
28+
local: Local,
29+
location: Location,
30+
},
31+
OutlivesFreeRegion {
32+
outlived_region: Option<Region<'tcx>>,
33+
},
34+
}
35+
1936
impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
2037
/// Adds annotations to `err` explaining *why* the borrow contains the
2138
/// point from `context`. This is key for the "3-point errors"
@@ -32,15 +49,30 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
3249
///
3350
/// [d]: https://rust-lang.github.io/rfcs/2094-nll.html#leveraging-intuition-framing-errors-in-terms-of-points
3451
pub(in borrow_check) fn explain_why_borrow_contains_point(
35-
&mut self,
52+
&self,
3653
context: Context,
3754
borrow: &BorrowData<'tcx>,
3855
kind_place: Option<(WriteKind, &Place<'tcx>)>,
3956
err: &mut DiagnosticBuilder<'_>,
4057
) {
58+
let reason = self.find_why_borrow_contains_point(context, borrow);
59+
self.report_why_borrow_contains_point(err, reason, kind_place);
60+
}
61+
62+
/// Finds the reason that [explain_why_borrow_contains_point] will report
63+
/// but doesn't add it to any message. This is a separate function in case
64+
/// the caller wants to change the error they report based on the reason
65+
/// that will be reported.
66+
pub(in borrow_check) fn find_why_borrow_contains_point(
67+
&self,
68+
context: Context,
69+
borrow: &BorrowData<'tcx>
70+
) -> BorrowContainsPointReason<'tcx> {
71+
use self::BorrowContainsPointReason::*;
72+
4173
debug!(
42-
"explain_why_borrow_contains_point(context={:?}, borrow={:?}, kind_place={:?})",
43-
context, borrow, kind_place,
74+
"find_why_borrow_contains_point(context={:?}, borrow={:?})",
75+
context, borrow,
4476
);
4577

4678
let regioncx = &self.nonlexical_regioncx;
@@ -62,11 +94,45 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
6294
);
6395

6496
match find_use::find(mir, regioncx, tcx, region_sub, context.loc) {
65-
Some(Cause::LiveVar(local, location)) => {
97+
Some(Cause::LiveVar(local, location)) => Liveness {
98+
local,
99+
location,
100+
in_loop: self.is_borrow_location_in_loop(context.loc),
101+
},
102+
Some(Cause::DropVar(local, location)) => DropLiveness {
103+
local,
104+
location,
105+
},
106+
None => OutlivesFreeRegion {
107+
outlived_region: regioncx.to_error_region(region_sub),
108+
},
109+
}
110+
}
111+
112+
/// Adds annotations to `err` for the explanation `reason`. This is a
113+
/// separate method so that the caller can change their error message based
114+
/// on the reason that is going to be reported.
115+
pub (in borrow_check) fn report_why_borrow_contains_point(
116+
&self,
117+
err: &mut DiagnosticBuilder,
118+
reason: BorrowContainsPointReason<'tcx>,
119+
kind_place: Option<(WriteKind, &Place<'tcx>)>,
120+
) {
121+
use self::BorrowContainsPointReason::*;
122+
123+
debug!(
124+
"find_why_borrow_contains_point(reason={:?}, kind_place={:?})",
125+
reason, kind_place,
126+
);
127+
128+
let mir = self.mir;
129+
130+
match reason {
131+
Liveness { local, location, in_loop } => {
66132
let span = mir.source_info(location).span;
67133
let spans = self.move_spans(&Place::Local(local), location)
68134
.or_else(|| self.borrow_spans(span, location));
69-
let message = if self.is_borrow_location_in_loop(context.loc) {
135+
let message = if in_loop {
70136
if spans.for_closure() {
71137
"borrow captured here by closure in later iteration of loop"
72138
} else {
@@ -81,8 +147,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
81147
};
82148
err.span_label(spans.var_or_use(), message);
83149
}
84-
85-
Some(Cause::DropVar(local, location)) => match &mir.local_decls[local].name {
150+
DropLiveness { local, location } => match &mir.local_decls[local].name {
86151
Some(local_name) => {
87152
err.span_label(
88153
mir.source_info(location).span,
@@ -93,31 +158,29 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
93158
if let Place::Local(borrowed_local) = place {
94159
let dropped_local_scope = mir.local_decls[local].visibility_scope;
95160
let borrowed_local_scope =
96-
mir.local_decls[*borrowed_local].visibility_scope;
161+
mir.local_decls[*borrowed_local].visibility_scope;
97162

98163
if mir.is_sub_scope(borrowed_local_scope, dropped_local_scope) {
99164
err.note(
100-
"values in a scope are dropped \
101-
in the opposite order they are defined",
165+
"values in a scope are dropped \
166+
in the opposite order they are defined",
102167
);
103168
}
104169
}
105170
}
106171
}
107172

108173
None => {}
109-
},
110-
111-
None => {
112-
if let Some(region) = regioncx.to_error_region(region_sub) {
113-
self.tcx.note_and_explain_free_region(
114-
err,
115-
"borrowed value must be valid for ",
116-
region,
117-
"...",
118-
);
119-
}
120174
}
175+
OutlivesFreeRegion { outlived_region: Some(region) } => {
176+
self.tcx.note_and_explain_free_region(
177+
err,
178+
"borrowed value must be valid for ",
179+
region,
180+
"...",
181+
);
182+
}
183+
OutlivesFreeRegion { outlived_region: None } => (),
121184
}
122185
}
123186

@@ -193,3 +256,4 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
193256
false
194257
}
195258
}
259+

0 commit comments

Comments
 (0)