Skip to content

Commit d0fdffc

Browse files
committed
Fix ICE in borrowck mutability suggestion with multi-byte ref sigil
1 parent 12f35ad commit d0fdffc

7 files changed

Lines changed: 62 additions & 15 deletions

compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1410,9 +1410,18 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
14101410
(span, " mut".to_owned(), true)
14111411
// If there is already a binding, we modify it to be `mut`.
14121412
} else if binding_exists {
1413-
// Shrink the span to just after the `&` in `&variable`.
1414-
let span = span.with_lo(span.lo() + BytePos(1)).shrink_to_lo();
1415-
(span, "mut ".to_owned(), true)
1413+
// Replace the sigil with the mutable version.
1414+
let Ok(src) = self.infcx.tcx.sess.source_map().span_to_snippet(span) else {
1415+
return;
1416+
};
1417+
let (prefix_len, replacement) = if local_decl.ty.is_ref() {
1418+
(src.chars().next().map_or(0, char::len_utf8), "&mut ")
1419+
} else {
1420+
(src.find("const").map_or(1, |i| i + "const".len()), "*mut ")
1421+
};
1422+
let ws_len = src[prefix_len..].len() - src[prefix_len..].trim_start().len();
1423+
let span = span.with_hi(span.lo() + BytePos((prefix_len + ws_len) as u32));
1424+
(span, replacement.to_owned(), true)
14161425
} else {
14171426
// Otherwise, suggest that the user annotates the binding; We provide the
14181427
// type of the local.

tests/crashes/139089.rs

Lines changed: 0 additions & 2 deletions
This file was deleted.

tests/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ LL | *s.pointer += 1;
1717
|
1818
help: consider changing this to be a mutable reference
1919
|
20-
LL | fn c(s: &mut &mut S) {
20+
LL | fn c(s: &mut &mut S) {
2121
| +++
2222

2323
error: aborting due to 2 previous errors

tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ LL | let x: &mut isize = &mut **t0;
2727
|
2828
help: consider changing this to be a mutable reference
2929
|
30-
LL | fn foo4(t0: &mut &mut isize) {
30+
LL | fn foo4(t0: &mut &mut isize) {
3131
| +++
3232

3333
error: aborting due to 3 previous errors

tests/ui/borrowck/mutability-errors.stderr

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,9 @@ LL | *x = (1,);
7474
|
7575
help: consider changing this to be a mutable pointer
7676
|
77-
LL | unsafe fn named_ptr(x: *mut const (i32,)) {
78-
| +++
77+
LL - unsafe fn named_ptr(x: *const (i32,)) {
78+
LL + unsafe fn named_ptr(x: *mut (i32,)) {
79+
|
7980

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

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

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

113117
error[E0594]: cannot assign to data in a `*const` pointer
114118
--> $DIR/mutability-errors.rs:30:5
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Regression test for https://github.com/rust-lang/rust/issues/139089
2+
3+
fn foo(x:Vec<u8>) {
4+
//~^ ERROR unknown start of token
5+
x.push(0);
6+
//~^ ERROR cannot borrow `*x` as mutable
7+
}
8+
9+
fn main() {}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error: unknown start of token: \u{ff06}
2+
--> $DIR/mutability-suggestion-fullwidth-ampersand.rs:3:11
3+
|
4+
LL | fn foo(x: &Vec<u8>) {
5+
| ^^
6+
|
7+
help: Unicode character '&' (Fullwidth Ampersand) looks like '&' (Ampersand), but it is not
8+
|
9+
LL - fn foo(x: &Vec<u8>) {
10+
LL + fn foo(x: &Vec<u8>) {
11+
|
12+
13+
error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
14+
--> $DIR/mutability-suggestion-fullwidth-ampersand.rs:5:5
15+
|
16+
LL | x.push(0);
17+
| ^ `x` is a `&` reference, so it cannot be borrowed as mutable
18+
|
19+
help: consider changing this to be a mutable reference
20+
|
21+
LL - fn foo(x: &Vec<u8>) {
22+
LL + fn foo(x: &mut Vec<u8>) {
23+
|
24+
25+
error: aborting due to 2 previous errors
26+
27+
For more information about this error, try `rustc --explain E0596`.

0 commit comments

Comments
 (0)