Skip to content

Commit d5f2745

Browse files
committed
Auto merge of #47098 - estebank:immutable-field, r=nagisa
Reword trying to operate in immutable fields The previous message ("cannot assign/mutably borrow immutable field") when trying to modify a field of an immutable binding gave the (incorrect) impression that fields can be mutable independently of their ADT's binding. Slightly reword the message to read "cannot assign/mutably borrow field of immutable binding". Re #35937.
2 parents bc1dda4 + 6384568 commit d5f2745

11 files changed

+85
-64
lines changed

src/librustc_borrowck/borrowck/mod.rs

+41-23
Original file line numberDiff line numberDiff line change
@@ -484,54 +484,60 @@ impl<'a, 'tcx> LoanPath<'tcx> {
484484
}
485485
}
486486

487-
pub fn opt_loan_path<'tcx>(cmt: &mc::cmt<'tcx>) -> Option<Rc<LoanPath<'tcx>>> {
488-
//! Computes the `LoanPath` (if any) for a `cmt`.
489-
//! Note that this logic is somewhat duplicated in
490-
//! the method `compute()` found in `gather_loans::restrictions`,
491-
//! which allows it to share common loan path pieces as it
492-
//! traverses the CMT.
493-
487+
// Avoid "cannot borrow immutable field `self.x` as mutable" as that implies that a field *can* be
488+
// mutable independently of the struct it belongs to. (#35937)
489+
pub fn opt_loan_path_is_field<'tcx>(cmt: &mc::cmt<'tcx>) -> (Option<Rc<LoanPath<'tcx>>>, bool) {
494490
let new_lp = |v: LoanPathKind<'tcx>| Rc::new(LoanPath::new(v, cmt.ty));
495491

496492
match cmt.cat {
497493
Categorization::Rvalue(..) |
498494
Categorization::StaticItem => {
499-
None
495+
(None, false)
500496
}
501497

502498
Categorization::Local(id) => {
503-
Some(new_lp(LpVar(id)))
499+
(Some(new_lp(LpVar(id))), false)
504500
}
505501

506502
Categorization::Upvar(mc::Upvar { id, .. }) => {
507-
Some(new_lp(LpUpvar(id)))
503+
(Some(new_lp(LpUpvar(id))), false)
508504
}
509505

510506
Categorization::Deref(ref cmt_base, pk) => {
511-
opt_loan_path(cmt_base).map(|lp| {
507+
let lp = opt_loan_path_is_field(cmt_base);
508+
(lp.0.map(|lp| {
512509
new_lp(LpExtend(lp, cmt.mutbl, LpDeref(pk)))
513-
})
510+
}), lp.1)
514511
}
515512

516513
Categorization::Interior(ref cmt_base, ik) => {
517-
opt_loan_path(cmt_base).map(|lp| {
514+
(opt_loan_path(cmt_base).map(|lp| {
518515
let opt_variant_id = match cmt_base.cat {
519516
Categorization::Downcast(_, did) => Some(did),
520517
_ => None
521518
};
522519
new_lp(LpExtend(lp, cmt.mutbl, LpInterior(opt_variant_id, ik.cleaned())))
523-
})
520+
}), true)
524521
}
525522

526-
Categorization::Downcast(ref cmt_base, variant_def_id) =>
527-
opt_loan_path(cmt_base)
528-
.map(|lp| {
523+
Categorization::Downcast(ref cmt_base, variant_def_id) => {
524+
let lp = opt_loan_path_is_field(cmt_base);
525+
(lp.0.map(|lp| {
529526
new_lp(LpDowncast(lp, variant_def_id))
530-
}),
531-
527+
}), lp.1)
528+
}
532529
}
533530
}
534531

532+
/// Computes the `LoanPath` (if any) for a `cmt`.
533+
/// Note that this logic is somewhat duplicated in
534+
/// the method `compute()` found in `gather_loans::restrictions`,
535+
/// which allows it to share common loan path pieces as it
536+
/// traverses the CMT.
537+
pub fn opt_loan_path<'tcx>(cmt: &mc::cmt<'tcx>) -> Option<Rc<LoanPath<'tcx>>> {
538+
opt_loan_path_is_field(cmt).0
539+
}
540+
535541
///////////////////////////////////////////////////////////////////////////
536542
// Errors
537543

@@ -787,14 +793,26 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
787793
mc::NoteClosureEnv(_) | mc::NoteUpvarRef(_) => {
788794
self.cmt_to_string(&err.cmt)
789795
}
790-
_ => match opt_loan_path(&err.cmt) {
791-
None => {
796+
_ => match opt_loan_path_is_field(&err.cmt) {
797+
(None, true) => {
798+
format!("{} of {} binding",
799+
self.cmt_to_string(&err.cmt),
800+
err.cmt.mutbl.to_user_str())
801+
802+
}
803+
(None, false) => {
792804
format!("{} {}",
793805
err.cmt.mutbl.to_user_str(),
794806
self.cmt_to_string(&err.cmt))
795807

796808
}
797-
Some(lp) => {
809+
(Some(lp), true) => {
810+
format!("{} `{}` of {} binding",
811+
self.cmt_to_string(&err.cmt),
812+
self.loan_path_to_string(&lp),
813+
err.cmt.mutbl.to_user_str())
814+
}
815+
(Some(lp), false) => {
798816
format!("{} {} `{}`",
799817
err.cmt.mutbl.to_user_str(),
800818
self.cmt_to_string(&err.cmt),
@@ -1326,7 +1344,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
13261344
} else if let Categorization::Interior(ref cmt, _) = err.cmt.cat {
13271345
if let mc::MutabilityCategory::McImmutable = cmt.mutbl {
13281346
db.span_label(*error_span,
1329-
"cannot mutably borrow immutable field");
1347+
"cannot mutably borrow field of immutable binding");
13301348
}
13311349
}
13321350
}

src/test/compile-fail/issue-5500-1.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ struct TrieMapIterator<'a> {
1818
fn main() {
1919
let a = 5;
2020
let _iter = TrieMapIterator{node: &a};
21-
_iter.node = & //[ast]~ ERROR cannot assign to immutable field `_iter.node`
22-
//[mir]~^ ERROR cannot assign to immutable field `_iter.node` (Ast)
21+
_iter.node = & //[ast]~ ERROR cannot assign to field `_iter.node` of immutable binding
22+
//[mir]~^ ERROR cannot assign to field `_iter.node` of immutable binding (Ast)
2323
// MIR doesn't generate an error because the code isn't reachable. This is OK
2424
// because the test is here to check that the compiler doesn't ICE (cf. #5500).
2525
panic!()
+6-6
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
1-
error[E0596]: cannot borrow immutable field `f.v` as mutable
1+
error[E0596]: cannot borrow field `f.v` of immutable binding as mutable
22
--> $DIR/issue-35937.rs:17:5
33
|
44
16 | let f = Foo { v: Vec::new() };
55
| - consider changing this to `mut f`
66
17 | f.v.push("cat".to_string()); //~ ERROR cannot borrow
7-
| ^^^ cannot mutably borrow immutable field
7+
| ^^^ cannot mutably borrow field of immutable binding
88

9-
error[E0594]: cannot assign to immutable field `s.x`
9+
error[E0594]: cannot assign to field `s.x` of immutable binding
1010
--> $DIR/issue-35937.rs:26:5
1111
|
1212
25 | let s = S { x: 42 };
1313
| - consider changing this to `mut s`
1414
26 | s.x += 1; //~ ERROR cannot assign
15-
| ^^^^^^^^ cannot mutably borrow immutable field
15+
| ^^^^^^^^ cannot mutably borrow field of immutable binding
1616

17-
error[E0594]: cannot assign to immutable field `s.x`
17+
error[E0594]: cannot assign to field `s.x` of immutable binding
1818
--> $DIR/issue-35937.rs:30:5
1919
|
2020
29 | fn bar(s: S) {
2121
| - consider changing this to `mut s`
2222
30 | s.x += 1; //~ ERROR cannot assign
23-
| ^^^^^^^^ cannot mutably borrow immutable field
23+
| ^^^^^^^^ cannot mutably borrow field of immutable binding
2424

2525
error: aborting due to 3 previous errors
2626

src/test/ui/did_you_mean/issue-38147-2.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ struct Bar<'a> {
1414

1515
impl<'a> Bar<'a> {
1616
fn f(&mut self) {
17-
self.s.push('x'); //~ ERROR cannot borrow immutable borrowed
17+
self.s.push('x');
18+
//~^ ERROR cannot borrow borrowed content `*self.s` of immutable binding as mutable
1819
}
1920
}
2021

src/test/ui/did_you_mean/issue-38147-2.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error[E0596]: cannot borrow immutable borrowed content `*self.s` as mutable
1+
error[E0596]: cannot borrow borrowed content `*self.s` of immutable binding as mutable
22
--> $DIR/issue-38147-2.rs:17:9
33
|
44
12 | s: &'a String
55
| ---------- use `&'a mut String` here to make mutable
66
...
7-
17 | self.s.push('x'); //~ ERROR cannot borrow immutable borrowed
7+
17 | self.s.push('x');
88
| ^^^^^^ cannot borrow as mutable
99

1010
error: aborting due to previous error

src/test/ui/did_you_mean/issue-38147-3.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ struct Qux<'a> {
1414

1515
impl<'a> Qux<'a> {
1616
fn f(&self) {
17-
self.s.push('x'); //~ ERROR cannot borrow immutable borrowed
17+
self.s.push('x');
18+
//~^ ERROR cannot borrow borrowed content `*self.s` of immutable binding as mutable
1819
}
1920
}
2021

src/test/ui/did_you_mean/issue-38147-3.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error[E0596]: cannot borrow immutable borrowed content `*self.s` as mutable
1+
error[E0596]: cannot borrow borrowed content `*self.s` of immutable binding as mutable
22
--> $DIR/issue-38147-3.rs:17:9
33
|
44
12 | s: &'a String
55
| ---------- use `&'a mut String` here to make mutable
66
...
7-
17 | self.s.push('x'); //~ ERROR cannot borrow immutable borrowed
7+
17 | self.s.push('x');
88
| ^^^^^^ cannot borrow as mutable
99

1010
error: aborting due to previous error

src/test/ui/did_you_mean/issue-39544.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,6 @@ pub fn with_arg(z: Z, w: &Z) {
5555
pub fn with_tuple() {
5656
let mut y = 0;
5757
let x = (&y,);
58-
*x.0 = 1; //~ ERROR cannot assign to immutable borrowed content
58+
*x.0 = 1;
59+
//~^ ERROR cannot assign to borrowed content `*x.0` of immutable binding
5960
}

src/test/ui/did_you_mean/issue-39544.stderr

+24-24
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,99 @@
1-
error[E0596]: cannot borrow immutable field `z.x` as mutable
1+
error[E0596]: cannot borrow field `z.x` of immutable binding as mutable
22
--> $DIR/issue-39544.rs:21:18
33
|
44
20 | let z = Z { x: X::Y };
55
| - consider changing this to `mut z`
66
21 | let _ = &mut z.x; //~ ERROR cannot borrow
7-
| ^^^ cannot mutably borrow immutable field
7+
| ^^^ cannot mutably borrow field of immutable binding
88

9-
error[E0596]: cannot borrow immutable field `self.x` as mutable
9+
error[E0596]: cannot borrow field `self.x` of immutable binding as mutable
1010
--> $DIR/issue-39544.rs:26:22
1111
|
1212
25 | fn foo<'z>(&'z self) {
1313
| -------- use `&'z mut self` here to make mutable
1414
26 | let _ = &mut self.x; //~ ERROR cannot borrow
15-
| ^^^^^^ cannot mutably borrow immutable field
15+
| ^^^^^^ cannot mutably borrow field of immutable binding
1616

17-
error[E0596]: cannot borrow immutable field `self.x` as mutable
17+
error[E0596]: cannot borrow field `self.x` of immutable binding as mutable
1818
--> $DIR/issue-39544.rs:30:22
1919
|
2020
29 | fn foo1(&self, other: &Z) {
2121
| ----- use `&mut self` here to make mutable
2222
30 | let _ = &mut self.x; //~ ERROR cannot borrow
23-
| ^^^^^^ cannot mutably borrow immutable field
23+
| ^^^^^^ cannot mutably borrow field of immutable binding
2424

25-
error[E0596]: cannot borrow immutable field `other.x` as mutable
25+
error[E0596]: cannot borrow field `other.x` of immutable binding as mutable
2626
--> $DIR/issue-39544.rs:31:22
2727
|
2828
29 | fn foo1(&self, other: &Z) {
2929
| -- use `&mut Z` here to make mutable
3030
30 | let _ = &mut self.x; //~ ERROR cannot borrow
3131
31 | let _ = &mut other.x; //~ ERROR cannot borrow
32-
| ^^^^^^^ cannot mutably borrow immutable field
32+
| ^^^^^^^ cannot mutably borrow field of immutable binding
3333

34-
error[E0596]: cannot borrow immutable field `self.x` as mutable
34+
error[E0596]: cannot borrow field `self.x` of immutable binding as mutable
3535
--> $DIR/issue-39544.rs:35:22
3636
|
3737
34 | fn foo2<'a>(&'a self, other: &Z) {
3838
| -------- use `&'a mut self` here to make mutable
3939
35 | let _ = &mut self.x; //~ ERROR cannot borrow
40-
| ^^^^^^ cannot mutably borrow immutable field
40+
| ^^^^^^ cannot mutably borrow field of immutable binding
4141

42-
error[E0596]: cannot borrow immutable field `other.x` as mutable
42+
error[E0596]: cannot borrow field `other.x` of immutable binding as mutable
4343
--> $DIR/issue-39544.rs:36:22
4444
|
4545
34 | fn foo2<'a>(&'a self, other: &Z) {
4646
| -- use `&mut Z` here to make mutable
4747
35 | let _ = &mut self.x; //~ ERROR cannot borrow
4848
36 | let _ = &mut other.x; //~ ERROR cannot borrow
49-
| ^^^^^^^ cannot mutably borrow immutable field
49+
| ^^^^^^^ cannot mutably borrow field of immutable binding
5050

51-
error[E0596]: cannot borrow immutable field `self.x` as mutable
51+
error[E0596]: cannot borrow field `self.x` of immutable binding as mutable
5252
--> $DIR/issue-39544.rs:40:22
5353
|
5454
39 | fn foo3<'a>(self: &'a Self, other: &Z) {
5555
| -------- use `&'a mut Self` here to make mutable
5656
40 | let _ = &mut self.x; //~ ERROR cannot borrow
57-
| ^^^^^^ cannot mutably borrow immutable field
57+
| ^^^^^^ cannot mutably borrow field of immutable binding
5858

59-
error[E0596]: cannot borrow immutable field `other.x` as mutable
59+
error[E0596]: cannot borrow field `other.x` of immutable binding as mutable
6060
--> $DIR/issue-39544.rs:41:22
6161
|
6262
39 | fn foo3<'a>(self: &'a Self, other: &Z) {
6363
| -- use `&mut Z` here to make mutable
6464
40 | let _ = &mut self.x; //~ ERROR cannot borrow
6565
41 | let _ = &mut other.x; //~ ERROR cannot borrow
66-
| ^^^^^^^ cannot mutably borrow immutable field
66+
| ^^^^^^^ cannot mutably borrow field of immutable binding
6767

68-
error[E0596]: cannot borrow immutable field `other.x` as mutable
68+
error[E0596]: cannot borrow field `other.x` of immutable binding as mutable
6969
--> $DIR/issue-39544.rs:45:22
7070
|
7171
44 | fn foo4(other: &Z) {
7272
| -- use `&mut Z` here to make mutable
7373
45 | let _ = &mut other.x; //~ ERROR cannot borrow
74-
| ^^^^^^^ cannot mutably borrow immutable field
74+
| ^^^^^^^ cannot mutably borrow field of immutable binding
7575

76-
error[E0596]: cannot borrow immutable field `z.x` as mutable
76+
error[E0596]: cannot borrow field `z.x` of immutable binding as mutable
7777
--> $DIR/issue-39544.rs:51:18
7878
|
7979
50 | pub fn with_arg(z: Z, w: &Z) {
8080
| - consider changing this to `mut z`
8181
51 | let _ = &mut z.x; //~ ERROR cannot borrow
82-
| ^^^ cannot mutably borrow immutable field
82+
| ^^^ cannot mutably borrow field of immutable binding
8383

84-
error[E0596]: cannot borrow immutable field `w.x` as mutable
84+
error[E0596]: cannot borrow field `w.x` of immutable binding as mutable
8585
--> $DIR/issue-39544.rs:52:18
8686
|
8787
50 | pub fn with_arg(z: Z, w: &Z) {
8888
| -- use `&mut Z` here to make mutable
8989
51 | let _ = &mut z.x; //~ ERROR cannot borrow
9090
52 | let _ = &mut w.x; //~ ERROR cannot borrow
91-
| ^^^ cannot mutably borrow immutable field
91+
| ^^^ cannot mutably borrow field of immutable binding
9292

93-
error[E0594]: cannot assign to immutable borrowed content `*x.0`
93+
error[E0594]: cannot assign to borrowed content `*x.0` of immutable binding
9494
--> $DIR/issue-39544.rs:58:5
9595
|
96-
58 | *x.0 = 1; //~ ERROR cannot assign to immutable borrowed content
96+
58 | *x.0 = 1;
9797
| ^^^^^^^^ cannot borrow as mutable
9898

9999
error: aborting due to 12 previous errors

src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ fn test3<F>(f: &mut F) where F: FnMut() {
4242

4343
fn test4(f: &Test) {
4444
f.f.call_mut(())
45-
//~^ ERROR: cannot borrow immutable `Box` content `*f.f` as mutable
45+
//~^ ERROR: cannot borrow `Box` content `*f.f` of immutable binding as mutable
4646
}
4747

4848
fn test5(f: &mut Test) {

src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ error[E0596]: cannot borrow immutable borrowed content `*f` as mutable
1919
35 | (*f)();
2020
| ^^^^ cannot borrow as mutable
2121

22-
error[E0596]: cannot borrow immutable `Box` content `*f.f` as mutable
22+
error[E0596]: cannot borrow `Box` content `*f.f` of immutable binding as mutable
2323
--> $DIR/borrowck-call-is-borrow-issue-12224.rs:44:5
2424
|
2525
43 | fn test4(f: &Test) {

0 commit comments

Comments
 (0)