Skip to content
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
17 changes: 14 additions & 3 deletions compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1410,9 +1410,20 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
(span, " mut".to_owned(), true)
// If there is already a binding, we modify it to be `mut`.
} else if binding_exists {
// Shrink the span to just after the `&` in `&variable`.
let span = span.with_lo(span.lo() + BytePos(1)).shrink_to_lo();
(span, "mut ".to_owned(), true)
// Replace the sigil with the mutable version. We may be dealing
// with parser recovery here and cannot assume the user actually
// typed `&` or `*const`, so we compute the prefix from the snippet.
let Ok(src) = self.infcx.tcx.sess.source_map().span_to_snippet(span) else {
return;
};
let (prefix_len, replacement) = if local_decl.ty.is_ref() {
(src.chars().next().map_or(0, char::len_utf8), "&mut ")
} else {
(src.find("const").map_or(1, |i| i + "const".len()), "*mut ")
};
let ws_len = src[prefix_len..].len() - src[prefix_len..].trim_start().len();
let span = span.with_hi(span.lo() + BytePos((prefix_len + ws_len) as u32));
(span, replacement.to_owned(), true)
} else {
// Otherwise, suggest that the user annotates the binding; We provide the
// type of the local.
Expand Down
2 changes: 0 additions & 2 deletions tests/crashes/139089.rs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ LL | *s.pointer += 1;
|
help: consider changing this to be a mutable reference
|
LL | fn c(s: &mut &mut S) {
LL | fn c(s: &mut &mut S) {
| +++

error: aborting due to 2 previous errors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ LL | let x: &mut isize = &mut **t0;
|
help: consider changing this to be a mutable reference
|
LL | fn foo4(t0: &mut &mut isize) {
LL | fn foo4(t0: &mut &mut isize) {
| +++

error: aborting due to 3 previous errors
Expand Down
20 changes: 12 additions & 8 deletions tests/ui/borrowck/mutability-errors.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,9 @@ LL | *x = (1,);
|
help: consider changing this to be a mutable pointer
|
LL | unsafe fn named_ptr(x: *mut const (i32,)) {
| +++
Comment on lines -77 to -78
Copy link
Copy Markdown
Contributor Author

@lapla-cogito lapla-cogito Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This suggestion was incorrect.

View changes since the review

LL - unsafe fn named_ptr(x: *const (i32,)) {
LL + unsafe fn named_ptr(x: *mut (i32,)) {
|

error[E0594]: cannot assign to `x.0`, which is behind a `*const` pointer
--> $DIR/mutability-errors.rs:24:5
Expand All @@ -85,8 +86,9 @@ LL | (*x).0 = 1;
|
help: consider changing this to be a mutable pointer
|
LL | unsafe fn named_ptr(x: *mut const (i32,)) {
| +++
LL - unsafe fn named_ptr(x: *const (i32,)) {
LL + unsafe fn named_ptr(x: *mut (i32,)) {
|

error[E0596]: cannot borrow `*x` as mutable, as it is behind a `*const` pointer
--> $DIR/mutability-errors.rs:25:5
Expand All @@ -96,8 +98,9 @@ LL | &mut *x;
|
help: consider changing this to be a mutable pointer
|
LL | unsafe fn named_ptr(x: *mut const (i32,)) {
| +++
LL - unsafe fn named_ptr(x: *const (i32,)) {
LL + unsafe fn named_ptr(x: *mut (i32,)) {
|

error[E0596]: cannot borrow `x.0` as mutable, as it is behind a `*const` pointer
--> $DIR/mutability-errors.rs:26:5
Expand All @@ -107,8 +110,9 @@ LL | &mut (*x).0;
|
help: consider changing this to be a mutable pointer
|
LL | unsafe fn named_ptr(x: *mut const (i32,)) {
| +++
LL - unsafe fn named_ptr(x: *const (i32,)) {
LL + unsafe fn named_ptr(x: *mut (i32,)) {
|

error[E0594]: cannot assign to data in a `*const` pointer
--> $DIR/mutability-errors.rs:30:5
Expand Down
9 changes: 9 additions & 0 deletions tests/ui/span/mutability-suggestion-fullwidth-ampersand.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Regression test for https://github.com/rust-lang/rust/issues/139089

fn foo(x: &Vec<u8>) {
//~^ ERROR unknown start of token
x.push(0);
//~^ ERROR cannot borrow `*x` as mutable
}

fn main() {}
27 changes: 27 additions & 0 deletions tests/ui/span/mutability-suggestion-fullwidth-ampersand.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
error: unknown start of token: \u{ff06}
--> $DIR/mutability-suggestion-fullwidth-ampersand.rs:3:11
|
LL | fn foo(x: &Vec<u8>) {
| ^^
|
help: Unicode character '&' (Fullwidth Ampersand) looks like '&' (Ampersand), but it is not
|
LL - fn foo(x: &Vec<u8>) {
LL + fn foo(x: &Vec<u8>) {
|

error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
--> $DIR/mutability-suggestion-fullwidth-ampersand.rs:5:5
|
LL | x.push(0);
| ^ `x` is a `&` reference, so it cannot be borrowed as mutable
|
help: consider changing this to be a mutable reference
|
LL - fn foo(x: &Vec<u8>) {
LL + fn foo(x: &mut Vec<u8>) {
|

Comment thread
lapla-cogito marked this conversation as resolved.
error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0596`.
Loading