Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit c68b10f

Browse files
mikhail-m1Your Name
authored andcommittedOct 4, 2017
add notes to report_conflicting_borrow MIR borrowck
1 parent f1938cf commit c68b10f

File tree

4 files changed

+150
-136
lines changed

4 files changed

+150
-136
lines changed
 

‎src/librustc_borrowck/borrowck/check_loans.rs

Lines changed: 18 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -470,102 +470,29 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
470470
old_loan.kill_scope.span(self.tcx(), &self.bccx.region_scope_tree).end_point();
471471

472472
let mut err = match (new_loan.kind, old_loan.kind) {
473-
(ty::MutBorrow, ty::MutBorrow) => {
474-
let mut err = self.bccx.cannot_mutably_borrow_multiply(
475-
new_loan.span, &nl, &new_loan_msg, Origin::Ast);
476-
477-
if new_loan.span == old_loan.span {
478-
// Both borrows are happening in the same place
479-
// Meaning the borrow is occurring in a loop
480-
err.span_label(
481-
new_loan.span,
482-
format!("mutable borrow starts here in previous \
483-
iteration of loop{}", new_loan_msg));
484-
err.span_label(
485-
previous_end_span,
486-
"mutable borrow ends here");
487-
err
488-
} else {
489-
err.span_label(
490-
old_loan.span,
491-
format!("first mutable borrow occurs here{}", old_loan_msg));
492-
err.span_label(
493-
new_loan.span,
494-
format!("second mutable borrow occurs here{}", new_loan_msg));
495-
err.span_label(
496-
previous_end_span,
497-
"first borrow ends here");
498-
err
499-
}
500-
}
501-
502-
(ty::UniqueImmBorrow, ty::UniqueImmBorrow) => {
503-
let mut err = self.bccx.cannot_uniquely_borrow_by_two_closures(
504-
new_loan.span, &nl, Origin::Ast);
505-
err.span_label(
506-
old_loan.span,
507-
"first closure is constructed here");
508-
err.span_label(
509-
new_loan.span,
510-
"second closure is constructed here");
511-
err.span_label(
512-
previous_end_span,
513-
"borrow from first closure ends here");
514-
err
515-
}
516-
517-
(ty::UniqueImmBorrow, _) => {
518-
let mut err = self.bccx.cannot_uniquely_borrow_by_one_closure(
519-
new_loan.span, &nl, &ol_pronoun, &old_loan_msg, Origin::Ast);
520-
err.span_label(
521-
new_loan.span,
522-
format!("closure construction occurs here{}", new_loan_msg));
523-
err.span_label(
524-
old_loan.span,
525-
format!("borrow occurs here{}", old_loan_msg));
526-
err.span_label(
527-
previous_end_span,
528-
"borrow ends here");
529-
err
530-
}
531-
473+
(ty::MutBorrow, ty::MutBorrow) =>
474+
self.bccx.cannot_mutably_borrow_multiply(
475+
new_loan.span, &nl, &new_loan_msg, old_loan.span, &old_loan_msg,
476+
previous_end_span, Origin::Ast),
477+
(ty::UniqueImmBorrow, ty::UniqueImmBorrow) =>
478+
self.bccx.cannot_uniquely_borrow_by_two_closures(
479+
new_loan.span, &nl, old_loan.span, previous_end_span, Origin::Ast),
480+
(ty::UniqueImmBorrow, _) =>
481+
self.bccx.cannot_uniquely_borrow_by_one_closure(
482+
new_loan.span, &nl, &new_loan_msg,
483+
old_loan.span, &ol_pronoun, &old_loan_msg, previous_end_span, Origin::Ast),
532484
(_, ty::UniqueImmBorrow) => {
533485
let new_loan_str = &new_loan.kind.to_user_str();
534-
let mut err = self.bccx.cannot_reborrow_already_uniquely_borrowed(
535-
new_loan.span, &nl, &new_loan_msg, new_loan_str, Origin::Ast);
536-
err.span_label(
537-
new_loan.span,
538-
format!("borrow occurs here{}", new_loan_msg));
539-
err.span_label(
540-
old_loan.span,
541-
format!("closure construction occurs here{}", old_loan_msg));
542-
err.span_label(
543-
previous_end_span,
544-
"borrow from closure ends here");
545-
err
486+
self.bccx.cannot_reborrow_already_uniquely_borrowed(
487+
new_loan.span, &nl, &new_loan_msg, new_loan_str,
488+
old_loan.span, &old_loan_msg, previous_end_span, Origin::Ast)
546489
}
547-
548-
(..) => {
549-
let mut err = self.bccx.cannot_reborrow_already_borrowed(
490+
(..) =>
491+
self.bccx.cannot_reborrow_already_borrowed(
550492
new_loan.span,
551493
&nl, &new_loan_msg, &new_loan.kind.to_user_str(),
552-
&ol_pronoun, &old_loan.kind.to_user_str(), &old_loan_msg, Origin::Ast);
553-
err.span_label(
554-
new_loan.span,
555-
format!("{} borrow occurs here{}",
556-
new_loan.kind.to_user_str(),
557-
new_loan_msg));
558-
err.span_label(
559-
old_loan.span,
560-
format!("{} borrow occurs here{}",
561-
old_loan.kind.to_user_str(),
562-
old_loan_msg));
563-
err.span_label(
564-
previous_end_span,
565-
format!("{} borrow ends here",
566-
old_loan.kind.to_user_str()));
567-
err
568-
}
494+
old_loan.span, &ol_pronoun, &old_loan.kind.to_user_str(), &old_loan_msg,
495+
previous_end_span, Origin::Ast)
569496
};
570497

571498
match new_loan.cause {

‎src/librustc_mir/borrow_check.rs

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -396,28 +396,34 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
396396
ReadKind::Copy =>
397397
this.report_use_while_mutably_borrowed(
398398
context, lvalue_span, borrow),
399-
ReadKind::Borrow(bk) =>
399+
ReadKind::Borrow(bk) => {
400+
let end_issued_loan_span =
401+
flow_state.borrows.base_results.operator().region_span(
402+
&borrow.region).end_point();
400403
this.report_conflicting_borrow(
401-
context, lvalue_span,
402-
common_prefix,
403-
(lvalue_span.0, bk), (&borrow.lvalue, borrow.kind)),
404+
context, common_prefix, lvalue_span, bk,
405+
&borrow, end_issued_loan_span)
406+
}
404407
}
405408
Control::Break
406409
}
407410
(Write(kind), _) => {
408411
match kind {
409-
WriteKind::MutableBorrow(bk) =>
412+
WriteKind::MutableBorrow(bk) => {
413+
let end_issued_loan_span =
414+
flow_state.borrows.base_results.operator().region_span(
415+
&borrow.region).end_point();
410416
this.report_conflicting_borrow(
411-
context, lvalue_span,
412-
common_prefix,
413-
(lvalue_span.0, bk), (&borrow.lvalue, borrow.kind)),
417+
context, common_prefix, lvalue_span, bk,
418+
&borrow, end_issued_loan_span)
419+
}
414420
WriteKind::StorageDead |
415421
WriteKind::Mutate =>
416422
this.report_illegal_mutation_of_borrowed(
417423
context, lvalue_span, borrow),
418424
WriteKind::Move =>
419425
this.report_move_out_while_borrowed(
420-
context, lvalue_span, borrow),
426+
context, lvalue_span, &borrow),
421427
}
422428
Control::Break
423429
}
@@ -966,48 +972,49 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
966972

967973
fn report_conflicting_borrow(&mut self,
968974
_context: Context,
969-
(lvalue, span): (&Lvalue, Span),
970975
common_prefix: &Lvalue,
971-
loan1: (&Lvalue, BorrowKind),
972-
loan2: (&Lvalue, BorrowKind)) {
976+
(lvalue, span): (&Lvalue, Span),
977+
gen_borrow_kind: BorrowKind,
978+
issued_borrow: &BorrowData,
979+
end_issued_loan_span: Span) {
973980
use self::prefixes::IsPrefixOf;
974981

975-
let (loan1_lvalue, loan1_kind) = loan1;
976-
let (loan2_lvalue, loan2_kind) = loan2;
982+
assert!(common_prefix.is_prefix_of(lvalue));
983+
assert!(common_prefix.is_prefix_of(&issued_borrow.lvalue));
977984

978-
assert!(common_prefix.is_prefix_of(loan1_lvalue));
979-
assert!(common_prefix.is_prefix_of(loan2_lvalue));
985+
let issued_span = self.retrieve_borrow_span(issued_borrow);
980986

981987
// FIXME: supply non-"" `opt_via` when appropriate
982-
let mut err = match (loan1_kind, "immutable", "mutable",
983-
loan2_kind, "immutable", "mutable") {
988+
let mut err = match (gen_borrow_kind, "immutable", "mutable",
989+
issued_borrow.kind, "immutable", "mutable") {
984990
(BorrowKind::Shared, lft, _, BorrowKind::Mut, _, rgt) |
985991
(BorrowKind::Mut, _, lft, BorrowKind::Shared, rgt, _) =>
986992
self.tcx.cannot_reborrow_already_borrowed(
987-
span, &self.describe_lvalue(lvalue),
988-
"", lft, "it", rgt, "", Origin::Mir),
993+
span, &self.describe_lvalue(lvalue), "", lft, issued_span,
994+
"it", rgt, "", end_issued_loan_span, Origin::Mir),
989995

990996
(BorrowKind::Mut, _, _, BorrowKind::Mut, _, _) =>
991997
self.tcx.cannot_mutably_borrow_multiply(
992-
span, &self.describe_lvalue(lvalue), "", Origin::Mir),
998+
span, &self.describe_lvalue(lvalue), "", issued_span,
999+
"", end_issued_loan_span, Origin::Mir),
9931000

9941001
(BorrowKind::Unique, _, _, BorrowKind::Unique, _, _) =>
9951002
self.tcx.cannot_uniquely_borrow_by_two_closures(
996-
span, &self.describe_lvalue(lvalue), Origin::Mir),
1003+
span, &self.describe_lvalue(lvalue), issued_span,
1004+
end_issued_loan_span, Origin::Mir),
9971005

9981006
(BorrowKind::Unique, _, _, _, _, _) =>
9991007
self.tcx.cannot_uniquely_borrow_by_one_closure(
1000-
span, &self.describe_lvalue(lvalue), "it", "", Origin::Mir),
1008+
span, &self.describe_lvalue(lvalue), "",
1009+
issued_span, "it", "", end_issued_loan_span, Origin::Mir),
10011010

10021011
(_, _, _, BorrowKind::Unique, _, _) =>
10031012
self.tcx.cannot_reborrow_already_uniquely_borrowed(
1004-
span, &self.describe_lvalue(lvalue), "it", "", Origin::Mir),
1013+
span, &self.describe_lvalue(lvalue), "it", "",
1014+
issued_span, "", end_issued_loan_span, Origin::Mir),
10051015

10061016
(BorrowKind::Shared, _, _, BorrowKind::Shared, _, _) =>
10071017
unreachable!(),
1008-
1009-
// FIXME: add span labels for first and second mutable borrows, as well as
1010-
// end point for first.
10111018
};
10121019
err.emit();
10131020
}

‎src/librustc_mir/dataflow/impls/borrows.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use rustc::mir::{self, Location, Mir};
1212
use rustc::mir::visit::Visitor;
1313
use rustc::ty::{Region, TyCtxt};
14+
use rustc::ty::RegionKind;
1415
use rustc::ty::RegionKind::ReScope;
1516
use rustc::util::nodemap::{FxHashMap, FxHashSet};
1617

@@ -21,6 +22,8 @@ use rustc_data_structures::indexed_vec::{IndexVec};
2122
use dataflow::{BitDenotation, BlockSets, DataflowOperator};
2223
pub use dataflow::indexes::BorrowIndex;
2324

25+
use syntax_pos::Span;
26+
2427
use std::fmt;
2528

2629
// `Borrows` maps each dataflow bit to an `Rvalue::Ref`, which can be
@@ -32,6 +35,7 @@ pub struct Borrows<'a, 'tcx: 'a> {
3235
borrows: IndexVec<BorrowIndex, BorrowData<'tcx>>,
3336
location_map: FxHashMap<Location, BorrowIndex>,
3437
region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
38+
region_span_map: FxHashMap<RegionKind, Span>,
3539
}
3640

3741
// temporarily allow some dead fields: `kind` and `region` will be
@@ -63,18 +67,21 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
6367
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
6468
let mut visitor = GatherBorrows { idx_vec: IndexVec::new(),
6569
location_map: FxHashMap(),
66-
region_map: FxHashMap(), };
70+
region_map: FxHashMap(),
71+
region_span_map: FxHashMap()};
6772
visitor.visit_mir(mir);
6873
return Borrows { tcx: tcx,
6974
mir: mir,
7075
borrows: visitor.idx_vec,
7176
location_map: visitor.location_map,
72-
region_map: visitor.region_map, };
77+
region_map: visitor.region_map,
78+
region_span_map: visitor.region_span_map};
7379

7480
struct GatherBorrows<'tcx> {
7581
idx_vec: IndexVec<BorrowIndex, BorrowData<'tcx>>,
7682
location_map: FxHashMap<Location, BorrowIndex>,
7783
region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
84+
region_span_map: FxHashMap<RegionKind, Span>,
7885
}
7986
impl<'tcx> Visitor<'tcx> for GatherBorrows<'tcx> {
8087
fn visit_rvalue(&mut self,
@@ -90,6 +97,16 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
9097
borrows.insert(idx);
9198
}
9299
}
100+
101+
fn visit_statement(&mut self,
102+
block: mir::BasicBlock,
103+
statement: &mir::Statement<'tcx>,
104+
location: Location) {
105+
if let mir::StatementKind::EndRegion(region_scope) = statement.kind {
106+
self.region_span_map.insert(ReScope(region_scope), statement.source_info.span);
107+
}
108+
self.super_statement(block, statement, location);
109+
}
93110
}
94111
}
95112

@@ -98,6 +115,12 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
98115
pub fn location(&self, idx: BorrowIndex) -> &Location {
99116
&self.borrows[idx].location
100117
}
118+
119+
pub fn region_span(&self, region: &Region) -> Span {
120+
let opt_span = self.region_span_map.get(region);
121+
assert!(opt_span.is_some(), "end region not found for {:?}", region);
122+
*opt_span.unwrap()
123+
}
101124
}
102125

103126
impl<'a, 'tcx> BitDenotation for Borrows<'a, 'tcx> {

‎src/librustc_mir/util/borrowck_errors.rs

Lines changed: 73 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -88,66 +88,123 @@ pub trait BorrowckErrors {
8888
}
8989

9090
fn cannot_mutably_borrow_multiply(&self,
91-
span: Span,
91+
new_loan_span: Span,
9292
desc: &str,
9393
opt_via: &str,
94+
old_loan_span: Span,
95+
old_opt_via: &str,
96+
old_load_end_span:Span,
9497
o: Origin)
9598
-> DiagnosticBuilder
9699
{
97-
struct_span_err!(self, span, E0499,
100+
let mut err = struct_span_err!(self, new_loan_span, E0499,
98101
"cannot borrow `{}`{} as mutable more than once at a time{OGN}",
99-
desc, opt_via, OGN=o)
102+
desc, opt_via, OGN=o);
103+
if old_loan_span == new_loan_span {
104+
// Both borrows are happening in the same place
105+
// Meaning the borrow is occurring in a loop
106+
err.span_label(new_loan_span,
107+
format!("mutable borrow starts here in previous \
108+
iteration of loop{}", opt_via));
109+
err.span_label(old_load_end_span, "mutable borrow ends here");
110+
} else {
111+
err.span_label(old_loan_span,
112+
format!("first mutable borrow occurs here{}", old_opt_via));
113+
err.span_label(new_loan_span,
114+
format!("second mutable borrow occurs here{}", opt_via));
115+
err.span_label(old_load_end_span, "first borrow ends here");
116+
}
117+
err
100118
}
101119

102-
fn cannot_uniquely_borrow_by_two_closures(&self, span: Span, desc: &str, o: Origin)
120+
fn cannot_uniquely_borrow_by_two_closures(&self,
121+
new_loan_span: Span,
122+
desc: &str,
123+
old_loan_span: Span,
124+
old_load_end_span: Span,
125+
o: Origin)
103126
-> DiagnosticBuilder
104127
{
105-
struct_span_err!(self, span, E0524,
128+
let mut err = struct_span_err!(self, new_loan_span, E0524,
106129
"two closures require unique access to `{}` at the same time{OGN}",
107-
desc, OGN=o)
130+
desc, OGN=o);
131+
err.span_label(
132+
old_loan_span,
133+
"first closure is constructed here");
134+
err.span_label(
135+
new_loan_span,
136+
"second closure is constructed here");
137+
err.span_label(
138+
old_load_end_span,
139+
"borrow from first closure ends here");
140+
err
108141
}
109142

110143
fn cannot_uniquely_borrow_by_one_closure(&self,
111-
span: Span,
144+
new_loan_span: Span,
112145
desc_new: &str,
146+
opt_via: &str,
147+
old_loan_span: Span,
113148
noun_old: &str,
114-
msg_old: &str,
149+
old_opt_via: &str,
150+
previous_end_span: Span,
115151
o: Origin)
116152
-> DiagnosticBuilder
117153
{
118-
struct_span_err!(self, span, E0500,
154+
let mut err = struct_span_err!(self, new_loan_span, E0500,
119155
"closure requires unique access to `{}` but {} is already borrowed{}{OGN}",
120-
desc_new, noun_old, msg_old, OGN=o)
156+
desc_new, noun_old, old_opt_via, OGN=o);
157+
err.span_label(new_loan_span,
158+
format!("closure construction occurs here{}", opt_via));
159+
err.span_label(old_loan_span,
160+
format!("borrow occurs here{}", old_opt_via));
161+
err.span_label(previous_end_span, "borrow ends here");
162+
err
121163
}
122164

123165
fn cannot_reborrow_already_uniquely_borrowed(&self,
124-
span: Span,
166+
new_loan_span: Span,
125167
desc_new: &str,
126-
msg_new: &str,
168+
opt_via: &str,
127169
kind_new: &str,
170+
old_loan_span: Span,
171+
old_opt_via: &str,
172+
previous_end_span: Span,
128173
o: Origin)
129174
-> DiagnosticBuilder
130175
{
131-
struct_span_err!(self, span, E0501,
176+
let mut err = struct_span_err!(self, new_loan_span, E0501,
132177
"cannot borrow `{}`{} as {} because previous closure \
133178
requires unique access{OGN}",
134-
desc_new, msg_new, kind_new, OGN=o)
179+
desc_new, opt_via, kind_new, OGN=o);
180+
err.span_label(new_loan_span,
181+
format!("borrow occurs here{}", opt_via));
182+
err.span_label(old_loan_span,
183+
format!("closure construction occurs here{}", old_opt_via));
184+
err.span_label(previous_end_span, "borrow from closure ends here");
185+
err
135186
}
136187

137188
fn cannot_reborrow_already_borrowed(&self,
138189
span: Span,
139190
desc_new: &str,
140191
msg_new: &str,
141192
kind_new: &str,
193+
old_span: Span,
142194
noun_old: &str,
143195
kind_old: &str,
144196
msg_old: &str,
197+
old_load_end_span: Span,
145198
o: Origin)
146199
-> DiagnosticBuilder
147200
{
148-
struct_span_err!(self, span, E0502,
201+
let mut err = struct_span_err!(self, span, E0502,
149202
"cannot borrow `{}`{} as {} because {} is also borrowed as {}{}{OGN}",
150-
desc_new, msg_new, kind_new, noun_old, kind_old, msg_old, OGN=o)
203+
desc_new, msg_new, kind_new, noun_old, kind_old, msg_old, OGN=o);
204+
err.span_label(span, format!("{} borrow occurs here{}", kind_new, msg_new));
205+
err.span_label(old_span, format!("{} borrow occurs here{}", kind_old, msg_old));
206+
err.span_label(old_load_end_span, format!("{} borrow ends here", kind_old));
207+
err
151208
}
152209

153210
fn cannot_assign_to_borrowed(&self, span: Span, borrow_span: Span, desc: &str, o: Origin)

0 commit comments

Comments
 (0)
Please sign in to comment.