Skip to content

Improve error reporting for modifications behind & references #86815

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if let Some(desc) = access_place_desc {
item_msg = format!("`{}`", desc);
reason = match error_access {
AccessKind::Mutate => format!(" which is behind {}", pointer_type),
AccessKind::Mutate => format!(", which is behind {}", pointer_type),
AccessKind::MutableBorrow => {
format!(", as it is behind {}", pointer_type)
}
Expand Down Expand Up @@ -897,16 +897,32 @@ fn suggest_ampmut<'tcx>(
) -> (Span, String) {
if let Some(assignment_rhs_span) = opt_assignment_rhs_span {
if let Ok(src) = tcx.sess.source_map().span_to_snippet(assignment_rhs_span) {
let is_mutbl = |ty: &str| -> bool {
if ty.starts_with("mut") {
let rest = &ty[3..];
match rest.chars().next() {
// e.g. `&mut x`
Some(c) if c.is_whitespace() => true,
// e.g. `&mut(x)`
Some('(') => true,
// e.g. `&mutablevar`
_ => false,
}
} else {
false
}
};
if let (true, Some(ws_pos)) =
(src.starts_with("&'"), src.find(|c: char| -> bool { c.is_whitespace() }))
{
let lt_name = &src[1..ws_pos];
let ty = &src[ws_pos..];
if !ty.trim_start().starts_with("mut") {
let ty = src[ws_pos..].trim_start();
if !is_mutbl(ty) {
return (assignment_rhs_span, format!("&{} mut {}", lt_name, ty));
}
} else if let Some(stripped) = src.strip_prefix('&') {
if !stripped.trim_start().starts_with("mut") {
let stripped = stripped.trim_start();
if !is_mutbl(stripped) {
return (assignment_rhs_span, format!("&mut {}", stripped));
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
error[E0594]: cannot assign to `*s.pointer` which is behind a `&` reference
error[E0594]: cannot assign to `*s.pointer`, which is behind a `&` reference
--> $DIR/borrowck-assign-to-andmut-in-aliasable-loc.rs:9:5
|
LL | fn a(s: &S) {
| -- help: consider changing this to be a mutable reference: `&mut S<'_>`
LL | *s.pointer += 1;
| ^^^^^^^^^^^^^^^ `s` is a `&` reference, so the data it refers to cannot be written

error[E0594]: cannot assign to `*s.pointer` which is behind a `&` reference
error[E0594]: cannot assign to `*s.pointer`, which is behind a `&` reference
--> $DIR/borrowck-assign-to-andmut-in-aliasable-loc.rs:17:5
|
LL | fn c(s: & &mut S) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0594]: cannot assign to `**t1` which is behind a `&` reference
error[E0594]: cannot assign to `**t1`, which is behind a `&` reference
--> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:9:5
|
LL | let t1 = t0;
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/borrowck/borrowck-issue-14498.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0594]: cannot assign to `***p` which is behind a `&` reference
error[E0594]: cannot assign to `***p`, which is behind a `&` reference
--> $DIR/borrowck-issue-14498.rs:16:5
|
LL | let p = &y;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0594]: cannot assign to `*item` which is behind a `&` reference
error[E0594]: cannot assign to `*item`, which is behind a `&` reference
--> $DIR/issue-69789-iterator-mut-suggestion.rs:7:9
|
LL | for item in &mut std::iter::empty::<&'static ()>() {
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/borrowck/issue-83309-ice-immut-in-for-loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ fn main() {
for v in Query.iter_mut() {
//~^ NOTE this iterator yields `&` references
*v -= 1;
//~^ ERROR cannot assign to `*v` which is behind a `&` reference
//~^ ERROR cannot assign to `*v`, which is behind a `&` reference
//~| NOTE `v` is a `&` reference, so the data it refers to cannot be written
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0594]: cannot assign to `*v` which is behind a `&` reference
error[E0594]: cannot assign to `*v`, which is behind a `&` reference
--> $DIR/issue-83309-ice-immut-in-for-loop.rs:11:9
|
LL | for v in Query.iter_mut() {
Expand Down
7 changes: 7 additions & 0 deletions src/test/ui/borrowck/issue-85765.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,11 @@ fn main() {
rofl.push(Vec::new());
//~^ ERROR cannot borrow `*rofl` as mutable, as it is behind a `&` reference
//~| NOTE `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable

let mut mutvar = 42;
let r = &mutvar;
//~^ HELP consider changing this to be a mutable reference
*r = 0;
//~^ ERROR cannot assign to `*r`, which is behind a `&` reference
//~| NOTE `r` is a `&` reference, so the data it refers to cannot be written
}
14 changes: 12 additions & 2 deletions src/test/ui/borrowck/issue-85765.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ LL |
LL | rofl.push(Vec::new());
| ^^^^ `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable

error: aborting due to previous error
error[E0594]: cannot assign to `*r`, which is behind a `&` reference
--> $DIR/issue-85765.rs:12:5
|
LL | let r = &mutvar;
| ------- help: consider changing this to be a mutable reference: `&mut mutvar`
LL |
LL | *r = 0;
| ^^^^^^ `r` is a `&` reference, so the data it refers to cannot be written

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0596`.
Some errors have detailed explanations: E0594, E0596.
For more information about an error, try `rustc --explain E0594`.
8 changes: 4 additions & 4 deletions src/test/ui/borrowck/mutability-errors.stderr
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
error[E0594]: cannot assign to `*x` which is behind a `&` reference
error[E0594]: cannot assign to `*x`, which is behind a `&` reference
--> $DIR/mutability-errors.rs:9:5
|
LL | fn named_ref(x: &(i32,)) {
| ------- help: consider changing this to be a mutable reference: `&mut (i32,)`
LL | *x = (1,);
| ^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written

error[E0594]: cannot assign to `x.0` which is behind a `&` reference
error[E0594]: cannot assign to `x.0`, which is behind a `&` reference
--> $DIR/mutability-errors.rs:10:5
|
LL | fn named_ref(x: &(i32,)) {
Expand Down Expand Up @@ -57,15 +57,15 @@ error[E0596]: cannot borrow data in a `&` reference as mutable
LL | &mut f().0;
| ^^^^^^^^^^ cannot borrow as mutable

error[E0594]: cannot assign to `*x` which is behind a `*const` pointer
error[E0594]: cannot assign to `*x`, which is behind a `*const` pointer
--> $DIR/mutability-errors.rs:23:5
|
LL | unsafe fn named_ptr(x: *const (i32,)) {
| ------------- help: consider changing this to be a mutable pointer: `*mut (i32,)`
LL | *x = (1,);
| ^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be written

error[E0594]: cannot assign to `x.0` which is behind a `*const` pointer
error[E0594]: cannot assign to `x.0`, which is behind a `*const` pointer
--> $DIR/mutability-errors.rs:24:5
|
LL | unsafe fn named_ptr(x: *const (i32,)) {
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/did_you_mean/issue-39544.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,5 @@ pub fn with_tuple() {
let mut y = 0;
let x = (&y,);
*x.0 = 1;
//~^ ERROR cannot assign to `*x.0` which is behind a `&` reference
//~^ ERROR cannot assign to `*x.0`, which is behind a `&` reference
}
2 changes: 1 addition & 1 deletion src/test/ui/did_you_mean/issue-39544.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ LL | let _ = &mut z.x;
LL | let _ = &mut w.x;
| ^^^^^^^^ `w` is a `&` reference, so the data it refers to cannot be borrowed as mutable

error[E0594]: cannot assign to `*x.0` which is behind a `&` reference
error[E0594]: cannot assign to `*x.0`, which is behind a `&` reference
--> $DIR/issue-39544.rs:48:5
|
LL | *x.0 = 1;
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/error-codes/E0389.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ struct FancyNum {
fn main() {
let mut fancy = FancyNum{ num: 5 };
let fancy_ref = &(&mut fancy);
fancy_ref.num = 6; //~ ERROR cannot assign to `fancy_ref.num` which is behind a `&` reference
fancy_ref.num = 6; //~ ERROR cannot assign to `fancy_ref.num`, which is behind a `&` reference
println!("{}", fancy_ref.num);
}
2 changes: 1 addition & 1 deletion src/test/ui/error-codes/E0389.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0594]: cannot assign to `fancy_ref.num` which is behind a `&` reference
error[E0594]: cannot assign to `fancy_ref.num`, which is behind a `&` reference
--> $DIR/E0389.rs:8:5
|
LL | let fancy_ref = &(&mut fancy);
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-51244.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
fn main() {
let ref my_ref @ _ = 0;
*my_ref = 0; //~ ERROR cannot assign to `*my_ref` which is behind a `&` reference [E0594]
*my_ref = 0; //~ ERROR cannot assign to `*my_ref`, which is behind a `&` reference [E0594]
}
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-51244.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0594]: cannot assign to `*my_ref` which is behind a `&` reference
error[E0594]: cannot assign to `*my_ref`, which is behind a `&` reference
--> $DIR/issue-51244.rs:3:5
|
LL | let ref my_ref @ _ = 0;
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/issues/issue-51515.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ fn main() {
//~^ HELP consider changing this to be a mutable reference
//~| SUGGESTION &mut 16
*foo = 32;
//~^ ERROR cannot assign to `*foo` which is behind a `&` reference
//~^ ERROR cannot assign to `*foo`, which is behind a `&` reference
let bar = foo;
//~^ HELP consider changing this to be a mutable reference
//~| SUGGESTION &mut i32
*bar = 64;
//~^ ERROR cannot assign to `*bar` which is behind a `&` reference
//~^ ERROR cannot assign to `*bar`, which is behind a `&` reference
}
4 changes: 2 additions & 2 deletions src/test/ui/issues/issue-51515.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0594]: cannot assign to `*foo` which is behind a `&` reference
error[E0594]: cannot assign to `*foo`, which is behind a `&` reference
--> $DIR/issue-51515.rs:5:5
|
LL | let foo = &16;
Expand All @@ -7,7 +7,7 @@ LL | let foo = &16;
LL | *foo = 32;
| ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written

error[E0594]: cannot assign to `*bar` which is behind a `&` reference
error[E0594]: cannot assign to `*bar`, which is behind a `&` reference
--> $DIR/issue-51515.rs:10:5
|
LL | let bar = foo;
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/mut/mutable-class-fields-2.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0594]: cannot assign to `self.how_hungry` which is behind a `&` reference
error[E0594]: cannot assign to `self.how_hungry`, which is behind a `&` reference
--> $DIR/mutable-class-fields-2.rs:9:5
|
LL | pub fn eat(&self) {
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/nll/issue-47388.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0594]: cannot assign to `fancy_ref.num` which is behind a `&` reference
error[E0594]: cannot assign to `fancy_ref.num`, which is behind a `&` reference
--> $DIR/issue-47388.rs:8:5
|
LL | let fancy_ref = &(&mut fancy);
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/nll/issue-51244.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
fn main() {
let ref my_ref @ _ = 0;
*my_ref = 0;
//~^ ERROR cannot assign to `*my_ref` which is behind a `&` reference [E0594]
//~^ ERROR cannot assign to `*my_ref`, which is behind a `&` reference [E0594]
}
2 changes: 1 addition & 1 deletion src/test/ui/nll/issue-51244.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0594]: cannot assign to `*my_ref` which is behind a `&` reference
error[E0594]: cannot assign to `*my_ref`, which is behind a `&` reference
--> $DIR/issue-51244.rs:3:5
|
LL | let ref my_ref @ _ = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/nll/issue-57989.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

fn f(x: &i32) {
let g = &x;
*x = 0; //~ ERROR cannot assign to `*x` which is behind a `&` reference
*x = 0; //~ ERROR cannot assign to `*x`, which is behind a `&` reference
//~| ERROR cannot assign to `*x` because it is borrowed
g;
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/nll/issue-57989.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0594]: cannot assign to `*x` which is behind a `&` reference
error[E0594]: cannot assign to `*x`, which is behind a `&` reference
--> $DIR/issue-57989.rs:5:5
|
LL | fn f(x: &i32) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ fn tuple() {
_x1 = U; //~ ERROR cannot assign twice to immutable variable
let _x0_hold = &mut tup.0; //~ ERROR cannot borrow `tup.0` as mutable because it is also
let (ref mut _x0_hold, ..) = tup; //~ ERROR cannot borrow `tup.0` as mutable because it is also
*_x0 = U; //~ ERROR cannot assign to `*_x0` which is behind a `&` reference
*_x2 = U; //~ ERROR cannot assign to `*_x2` which is behind a `&` reference
*_x0 = U; //~ ERROR cannot assign to `*_x0`, which is behind a `&` reference
*_x2 = U; //~ ERROR cannot assign to `*_x2`, which is behind a `&` reference
drop(tup.1); //~ ERROR use of moved value: `tup.1`
let _x1_hold = &tup.1; //~ ERROR borrow of moved value: `tup.1`
let (.., ref mut _x3) = tup;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ LL | let (ref mut _x0_hold, ..) = tup;
LL | *_x0 = U;
| -------- immutable borrow later used here

error[E0594]: cannot assign to `*_x0` which is behind a `&` reference
error[E0594]: cannot assign to `*_x0`, which is behind a `&` reference
--> $DIR/borrowck-move-ref-pattern.rs:26:5
|
LL | let (ref _x0, _x1, ref _x2, ..) = tup;
Expand All @@ -110,7 +110,7 @@ LL | let (ref _x0, _x1, ref _x2, ..) = tup;
LL | *_x0 = U;
| ^^^^^^^^ `_x0` is a `&` reference, so the data it refers to cannot be written

error[E0594]: cannot assign to `*_x2` which is behind a `&` reference
error[E0594]: cannot assign to `*_x2`, which is behind a `&` reference
--> $DIR/borrowck-move-ref-pattern.rs:27:5
|
LL | let (ref _x0, _x1, ref _x2, ..) = tup;
Expand Down
6 changes: 3 additions & 3 deletions src/test/ui/rfc-2005-default-binding-mode/enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ use Wrapper::Wrap;

pub fn main() {
let Wrap(x) = &Wrap(3);
*x += 1; //~ ERROR cannot assign to `*x` which is behind a `&` reference
*x += 1; //~ ERROR cannot assign to `*x`, which is behind a `&` reference


if let Some(x) = &Some(3) {
*x += 1; //~ ERROR cannot assign to `*x` which is behind a `&` reference
*x += 1; //~ ERROR cannot assign to `*x`, which is behind a `&` reference
} else {
panic!();
}

while let Some(x) = &Some(3) {
*x += 1; //~ ERROR cannot assign to `*x` which is behind a `&` reference
*x += 1; //~ ERROR cannot assign to `*x`, which is behind a `&` reference
break;
}
}
6 changes: 3 additions & 3 deletions src/test/ui/rfc-2005-default-binding-mode/enum.stderr
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
error[E0594]: cannot assign to `*x` which is behind a `&` reference
error[E0594]: cannot assign to `*x`, which is behind a `&` reference
--> $DIR/enum.rs:9:5
|
LL | *x += 1;
| ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written

error[E0594]: cannot assign to `*x` which is behind a `&` reference
error[E0594]: cannot assign to `*x`, which is behind a `&` reference
--> $DIR/enum.rs:13:9
|
LL | *x += 1;
| ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written

error[E0594]: cannot assign to `*x` which is behind a `&` reference
error[E0594]: cannot assign to `*x`, which is behind a `&` reference
--> $DIR/enum.rs:19:9
|
LL | *x += 1;
Expand Down
6 changes: 3 additions & 3 deletions src/test/ui/rfc-2005-default-binding-mode/explicit-mut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@
fn main() {
match &&Some(5i32) {
Some(n) => {
*n += 1; //~ ERROR cannot assign to `*n` which is behind a `&` reference
*n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference
let _ = n;
}
None => {},
};

match &mut &Some(5i32) {
Some(n) => {
*n += 1; //~ ERROR cannot assign to `*n` which is behind a `&` reference
*n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference
let _ = n;
}
None => {},
};

match &&mut Some(5i32) {
Some(n) => {
*n += 1; //~ ERROR cannot assign to `*n` which is behind a `&` reference
*n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference
let _ = n;
}
None => {},
Expand Down
6 changes: 3 additions & 3 deletions src/test/ui/rfc-2005-default-binding-mode/explicit-mut.stderr
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
error[E0594]: cannot assign to `*n` which is behind a `&` reference
error[E0594]: cannot assign to `*n`, which is behind a `&` reference
--> $DIR/explicit-mut.rs:7:13
|
LL | *n += 1;
| ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written

error[E0594]: cannot assign to `*n` which is behind a `&` reference
error[E0594]: cannot assign to `*n`, which is behind a `&` reference
--> $DIR/explicit-mut.rs:15:13
|
LL | *n += 1;
| ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written

error[E0594]: cannot assign to `*n` which is behind a `&` reference
error[E0594]: cannot assign to `*n`, which is behind a `&` reference
--> $DIR/explicit-mut.rs:23:13
|
LL | *n += 1;
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/suggestions/issue-68049-1.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0594]: cannot assign to `self.0` which is behind a `&` reference
error[E0594]: cannot assign to `self.0`, which is behind a `&` reference
--> $DIR/issue-68049-1.rs:7:9
|
LL | self.0 += 1;
Expand Down
Loading