Skip to content

Commit 69bded2

Browse files
committed
Add union justifications to conflicting borrows.
This commit adds justifications to error messages for conflicting borrows of union fields. Where previously an error message would say ``cannot borrow `u.b` as mutable..``, it now says ``cannot borrow `u` (via `u.b`) as mutable..``.
1 parent 79d8a0f commit 69bded2

7 files changed

+141
-127
lines changed

src/librustc_mir/borrow_check/error_reporting.rs

+48-10
Original file line numberDiff line numberDiff line change
@@ -329,10 +329,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
329329
"closure"
330330
};
331331

332-
let desc_place = self.describe_place(place).unwrap_or_else(|| "_".to_owned());
333-
let tcx = self.infcx.tcx;
334-
335-
let first_borrow_desc;
332+
let (desc_place, msg_place, msg_borrow) = if issued_borrow.borrowed_place == *place {
333+
let desc_place = self.describe_place(place).unwrap_or_else(|| "_".to_owned());
334+
(desc_place, "".to_string(), "".to_string())
335+
} else {
336+
let (desc_place, msg_place) = self.describe_place_for_conflicting_borrow(place);
337+
let (_, msg_borrow) = self.describe_place_for_conflicting_borrow(
338+
&issued_borrow.borrowed_place
339+
);
340+
(desc_place, msg_place, msg_borrow)
341+
};
336342

337343
let explanation = self.explain_why_borrow_contains_point(context, issued_borrow, None);
338344
let second_borrow_desc = if explanation.is_explained() {
@@ -342,6 +348,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
342348
};
343349

344350
// FIXME: supply non-"" `opt_via` when appropriate
351+
let tcx = self.infcx.tcx;
352+
let first_borrow_desc;
345353
let mut err = match (
346354
gen_borrow_kind,
347355
"immutable",
@@ -355,12 +363,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
355363
tcx.cannot_reborrow_already_borrowed(
356364
span,
357365
&desc_place,
358-
"",
366+
&msg_place,
359367
lft,
360368
issued_span,
361369
"it",
362370
rgt,
363-
"",
371+
&msg_borrow,
364372
None,
365373
Origin::Mir,
366374
)
@@ -370,12 +378,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
370378
tcx.cannot_reborrow_already_borrowed(
371379
span,
372380
&desc_place,
373-
"",
381+
&msg_place,
374382
lft,
375383
issued_span,
376384
"it",
377385
rgt,
378-
"",
386+
&msg_borrow,
379387
None,
380388
Origin::Mir,
381389
)
@@ -386,9 +394,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
386394
tcx.cannot_mutably_borrow_multiply(
387395
span,
388396
&desc_place,
389-
"",
397+
&msg_place,
390398
issued_span,
391-
"",
399+
&msg_borrow,
392400
None,
393401
Origin::Mir,
394402
)
@@ -518,6 +526,36 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
518526
err.buffer(&mut self.errors_buffer);
519527
}
520528

529+
/// Returns a description of a place and an associated message for the purposes of conflicting
530+
/// borrow diagnostics.
531+
///
532+
/// If the borrow is of the field `b` of a union `u`, then the return value will be
533+
/// `("u", " (via \`u.b\`)")`. Otherwise, for some variable `a`, the return value will be
534+
/// `("a", "")`.
535+
pub(super) fn describe_place_for_conflicting_borrow(
536+
&self,
537+
place: &Place<'tcx>,
538+
) -> (String, String) {
539+
place.base_local()
540+
.filter(|local| {
541+
// Filter out non-unions.
542+
self.mir.local_decls[*local].ty
543+
.ty_adt_def()
544+
.map(|adt| adt.is_union())
545+
.unwrap_or(false)
546+
})
547+
.and_then(|local| {
548+
let desc_base = self.describe_place(&Place::Local(local))
549+
.unwrap_or_else(|| "_".to_owned());
550+
let desc_original = self.describe_place(place)
551+
.unwrap_or_else(|| "_".to_owned());
552+
return Some((desc_base, format!(" (via `{}`)", desc_original)));
553+
})
554+
.unwrap_or_else(|| {
555+
(self.describe_place(place).unwrap_or_else(|| "_".to_owned()), "".to_string())
556+
})
557+
}
558+
521559
/// Reports StorageDeadOrDrop of `place` conflicts with `borrow`.
522560
///
523561
/// This means that some data referenced by `borrow` needs to live

src/test/ui/borrowck/borrowck-union-borrow.ast.nll.stderr renamed to src/test/ui/borrowck/borrowck-union-borrow.nll.stderr

+34-45
Original file line numberDiff line numberDiff line change
@@ -1,132 +1,121 @@
11
error[E0502]: cannot borrow `u.a` as mutable because it is also borrowed as immutable
2-
--> $DIR/borrowck-union-borrow.rs:27:23
2+
--> $DIR/borrowck-union-borrow.rs:25:23
33
|
44
LL | let ra = &u.a;
55
| ---- immutable borrow occurs here
6-
LL | let rma = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
6+
LL | let rma = &mut u.a; //~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
77
| ^^^^^^^^ mutable borrow occurs here
8-
LL | //[mir]~^ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
98
LL | drop(ra);
109
| -- immutable borrow later used here
1110

1211
error[E0506]: cannot assign to `u.a` because it is borrowed
13-
--> $DIR/borrowck-union-borrow.rs:33:13
12+
--> $DIR/borrowck-union-borrow.rs:30:13
1413
|
1514
LL | let ra = &u.a;
1615
| ---- borrow of `u.a` occurs here
17-
LL | u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed
16+
LL | u.a = 1; //~ ERROR cannot assign to `u.a` because it is borrowed
1817
| ^^^^^^^ assignment to borrowed `u.a` occurs here
19-
LL | //[mir]~^ ERROR cannot assign to `u.a` because it is borrowed
2018
LL | drop(ra);
2119
| -- borrow later used here
2220

23-
error[E0502]: cannot borrow `u.b` as mutable because it is also borrowed as immutable
24-
--> $DIR/borrowck-union-borrow.rs:50:23
21+
error[E0502]: cannot borrow `u` (via `u.b`) as mutable because it is also borrowed as immutable (via `u.a`)
22+
--> $DIR/borrowck-union-borrow.rs:46:23
2523
|
2624
LL | let ra = &u.a;
27-
| ---- immutable borrow occurs here
28-
LL | let rmb = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
29-
| ^^^^^^^^ mutable borrow occurs here
30-
LL | //[mir]~^ ERROR cannot borrow `u.b` as mutable because it is also borrowed as immutable
25+
| ---- immutable borrow occurs here (via `u.a`)
26+
LL | let rmb = &mut u.b; //~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
27+
| ^^^^^^^^ mutable borrow occurs here (via `u.b`)
3128
LL | drop(ra);
3229
| -- immutable borrow later used here
3330

3431
error[E0506]: cannot assign to `u.b` because it is borrowed
35-
--> $DIR/borrowck-union-borrow.rs:56:13
32+
--> $DIR/borrowck-union-borrow.rs:51:13
3633
|
3734
LL | let ra = &u.a;
3835
| ---- borrow of `u.b` occurs here
39-
LL | u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed
36+
LL | u.b = 1; //~ ERROR cannot assign to `u.b` because it is borrowed
4037
| ^^^^^^^ assignment to borrowed `u.b` occurs here
41-
LL | //[mir]~^ ERROR cannot assign to `u.b` because it is borrowed
4238
LL | drop(ra);
4339
| -- borrow later used here
4440

4541
error[E0502]: cannot borrow `u.a` as immutable because it is also borrowed as mutable
46-
--> $DIR/borrowck-union-borrow.rs:63:22
42+
--> $DIR/borrowck-union-borrow.rs:57:22
4743
|
4844
LL | let rma = &mut u.a;
4945
| -------- mutable borrow occurs here
50-
LL | let ra = &u.a; //[ast]~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
46+
LL | let ra = &u.a; //~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
5147
| ^^^^ immutable borrow occurs here
52-
LL | //[mir]~^ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
5348
LL | drop(rma);
5449
| --- mutable borrow later used here
5550

5651
error[E0503]: cannot use `u.a` because it was mutably borrowed
57-
--> $DIR/borrowck-union-borrow.rs:69:21
52+
--> $DIR/borrowck-union-borrow.rs:62:21
5853
|
5954
LL | let ra = &mut u.a;
6055
| -------- borrow of `u.a` occurs here
61-
LL | let a = u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed
56+
LL | let a = u.a; //~ ERROR cannot use `u.a` because it was mutably borrowed
6257
| ^^^ use of borrowed `u.a`
63-
LL | //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed
6458
LL | drop(ra);
6559
| -- borrow later used here
6660

6761
error[E0499]: cannot borrow `u.a` as mutable more than once at a time
68-
--> $DIR/borrowck-union-borrow.rs:75:24
62+
--> $DIR/borrowck-union-borrow.rs:67:24
6963
|
7064
LL | let rma = &mut u.a;
7165
| -------- first mutable borrow occurs here
72-
LL | let rma2 = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable more than once at a time
66+
LL | let rma2 = &mut u.a; //~ ERROR cannot borrow `u.a` as mutable more than once at a time
7367
| ^^^^^^^^ second mutable borrow occurs here
74-
LL | //[mir]~^ ERROR cannot borrow `u.a` as mutable more than once at a time
7568
LL | drop(rma);
7669
| --- first borrow later used here
7770

7871
error[E0506]: cannot assign to `u.a` because it is borrowed
79-
--> $DIR/borrowck-union-borrow.rs:81:13
72+
--> $DIR/borrowck-union-borrow.rs:72:13
8073
|
8174
LL | let rma = &mut u.a;
8275
| -------- borrow of `u.a` occurs here
83-
LL | u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed
76+
LL | u.a = 1; //~ ERROR cannot assign to `u.a` because it is borrowed
8477
| ^^^^^^^ assignment to borrowed `u.a` occurs here
85-
LL | //[mir]~^ ERROR cannot assign to `u.a` because it is borrowed
8678
LL | drop(rma);
8779
| --- borrow later used here
8880

89-
error[E0502]: cannot borrow `u.b` as immutable because it is also borrowed as mutable
90-
--> $DIR/borrowck-union-borrow.rs:88:22
81+
error[E0502]: cannot borrow `u` (via `u.b`) as immutable because it is also borrowed as mutable (via `u.a`)
82+
--> $DIR/borrowck-union-borrow.rs:78:22
9183
|
9284
LL | let rma = &mut u.a;
93-
| -------- mutable borrow occurs here
94-
LL | let rb = &u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
95-
| ^^^^ immutable borrow occurs here
96-
LL | //[mir]~^ ERROR cannot borrow `u.b` as immutable because it is also borrowed as mutable
85+
| -------- mutable borrow occurs here (via `u.a`)
86+
LL | let rb = &u.b; //~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
87+
| ^^^^ immutable borrow occurs here (via `u.b`)
9788
LL | drop(rma);
9889
| --- mutable borrow later used here
9990

10091
error[E0503]: cannot use `u.b` because it was mutably borrowed
101-
--> $DIR/borrowck-union-borrow.rs:94:21
92+
--> $DIR/borrowck-union-borrow.rs:83:21
10293
|
10394
LL | let ra = &mut u.a;
10495
| -------- borrow of `u.a` occurs here
105-
LL | let b = u.b; //[ast]~ ERROR cannot use `u.b` because it was mutably borrowed
96+
LL | let b = u.b; //~ ERROR cannot use `u.b` because it was mutably borrowed
10697
| ^^^ use of borrowed `u.a`
107-
...
98+
LL |
10899
LL | drop(ra);
109100
| -- borrow later used here
110101

111-
error[E0499]: cannot borrow `u.b` as mutable more than once at a time
112-
--> $DIR/borrowck-union-borrow.rs:101:24
102+
error[E0499]: cannot borrow `u` (via `u.b`) as mutable more than once at a time
103+
--> $DIR/borrowck-union-borrow.rs:89:24
113104
|
114105
LL | let rma = &mut u.a;
115-
| -------- first mutable borrow occurs here
116-
LL | let rmb2 = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time
117-
| ^^^^^^^^ second mutable borrow occurs here
118-
LL | //[mir]~^ ERROR cannot borrow `u.b` as mutable more than once at a time
106+
| -------- first mutable borrow occurs here (via `u.a`)
107+
LL | let rmb2 = &mut u.b; //~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time
108+
| ^^^^^^^^ second mutable borrow occurs here (via `u.b`)
119109
LL | drop(rma);
120110
| --- first borrow later used here
121111

122112
error[E0506]: cannot assign to `u.b` because it is borrowed
123-
--> $DIR/borrowck-union-borrow.rs:107:13
113+
--> $DIR/borrowck-union-borrow.rs:94:13
124114
|
125115
LL | let rma = &mut u.a;
126116
| -------- borrow of `u.b` occurs here
127-
LL | u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed
117+
LL | u.b = 1; //~ ERROR cannot assign to `u.b` because it is borrowed
128118
| ^^^^^^^ assignment to borrowed `u.b` occurs here
129-
LL | //[mir]~^ ERROR cannot assign to `u.b` because it is borrowed
130119
LL | drop(rma);
131120
| --- borrow later used here
132121

src/test/ui/borrowck/borrowck-union-borrow.rs

+12-26
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
// ignore-tidy-linelength
2-
// revisions: ast mir
3-
//[mir]compile-flags: -Z borrowck=mir
42

53
#[derive(Clone, Copy)]
64
union U {
@@ -24,14 +22,12 @@ fn main() {
2422
}
2523
{
2624
let ra = &u.a;
27-
let rma = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
28-
//[mir]~^ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
25+
let rma = &mut u.a; //~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
2926
drop(ra);
3027
}
3128
{
3229
let ra = &u.a;
33-
u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed
34-
//[mir]~^ ERROR cannot assign to `u.a` because it is borrowed
30+
u.a = 1; //~ ERROR cannot assign to `u.a` because it is borrowed
3531
drop(ra);
3632
}
3733
// Imm borrow, other field
@@ -47,65 +43,55 @@ fn main() {
4743
}
4844
{
4945
let ra = &u.a;
50-
let rmb = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
51-
//[mir]~^ ERROR cannot borrow `u.b` as mutable because it is also borrowed as immutable
46+
let rmb = &mut u.b; //~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
5247
drop(ra);
5348
}
5449
{
5550
let ra = &u.a;
56-
u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed
57-
//[mir]~^ ERROR cannot assign to `u.b` because it is borrowed
51+
u.b = 1; //~ ERROR cannot assign to `u.b` because it is borrowed
5852
drop(ra);
5953
}
6054
// Mut borrow, same field
6155
{
6256
let rma = &mut u.a;
63-
let ra = &u.a; //[ast]~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
64-
//[mir]~^ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
57+
let ra = &u.a; //~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
6558
drop(rma);
6659
}
6760
{
6861
let ra = &mut u.a;
69-
let a = u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed
70-
//[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed
62+
let a = u.a; //~ ERROR cannot use `u.a` because it was mutably borrowed
7163
drop(ra);
7264
}
7365
{
7466
let rma = &mut u.a;
75-
let rma2 = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable more than once at a time
76-
//[mir]~^ ERROR cannot borrow `u.a` as mutable more than once at a time
67+
let rma2 = &mut u.a; //~ ERROR cannot borrow `u.a` as mutable more than once at a time
7768
drop(rma);
7869
}
7970
{
8071
let rma = &mut u.a;
81-
u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed
82-
//[mir]~^ ERROR cannot assign to `u.a` because it is borrowed
72+
u.a = 1; //~ ERROR cannot assign to `u.a` because it is borrowed
8373
drop(rma);
8474
}
8575
// Mut borrow, other field
8676
{
8777
let rma = &mut u.a;
88-
let rb = &u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
89-
//[mir]~^ ERROR cannot borrow `u.b` as immutable because it is also borrowed as mutable
78+
let rb = &u.b; //~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
9079
drop(rma);
9180
}
9281
{
9382
let ra = &mut u.a;
94-
let b = u.b; //[ast]~ ERROR cannot use `u.b` because it was mutably borrowed
95-
//[mir]~^ ERROR cannot use `u.b` because it was mutably borrowed
83+
let b = u.b; //~ ERROR cannot use `u.b` because it was mutably borrowed
9684

9785
drop(ra);
9886
}
9987
{
10088
let rma = &mut u.a;
101-
let rmb2 = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time
102-
//[mir]~^ ERROR cannot borrow `u.b` as mutable more than once at a time
89+
let rmb2 = &mut u.b; //~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time
10390
drop(rma);
10491
}
10592
{
10693
let rma = &mut u.a;
107-
u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed
108-
//[mir]~^ ERROR cannot assign to `u.b` because it is borrowed
94+
u.b = 1; //~ ERROR cannot assign to `u.b` because it is borrowed
10995
drop(rma);
11096
}
11197
}

0 commit comments

Comments
 (0)