Skip to content

Commit

Permalink
Rollup merge of rust-lang#86815 - FabianWolff:issue-84210, r=varkor
Browse files Browse the repository at this point in the history
Improve error reporting for modifications behind `&` references

I had a look at rust-lang#84210 and noticed that rust-lang#85823 has effectively already fixed rust-lang#84210.

However, the string matching in rust-lang#85823 is _very_ crude and already breaks down when a variable name starts with `mut`. I have made this a bit more robust; further improvements could definitely be made but are complicated by the lack of information provided by an earlier pass:
https://github.com/rust-lang/rust/blob/ce331ee6ee010438d1a58c7da8ced4f26d69a20e/compiler/rustc_mir_build/src/build/matches/mod.rs#L2103-L2107

I have also fixed a missing comma in the error message.
  • Loading branch information
Dylan-DPC committed Jul 11, 2021
2 parents b05d19a + 5eb83f4 commit 7186a21
Show file tree
Hide file tree
Showing 34 changed files with 90 additions and 57 deletions.
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

0 comments on commit 7186a21

Please sign in to comment.