|
| 1 | +// Regression test for the `suggest_ampmut` usertype ascription code path in borrowck. |
| 2 | +// |
| 3 | +// When a binding has a user type annotation like `let x: &T = &expr`, MIR creates |
| 4 | +// two statements: an inner borrow `_tmp = &expr` and an outer re-borrow `_x = &(*_tmp)`. |
| 5 | +// The `suggest_ampmut` function must pierce through the re-borrow to find the inner |
| 6 | +// assignment and use its span/snippet to produce a correct `&mut` suggestion. |
| 7 | +// |
| 8 | +// Previously there was a copy-paste bug where `span_to_snippet` was called with the |
| 9 | +// outer span (`rhs_span`) instead of the inner span (`rhs_span_new`). This is a latent |
| 10 | +// bug: current MIR lowering always assigns both statements the same source span, so the |
| 11 | +// diagnostic output is identical either way. However, the fix is semantically correct |
| 12 | +// and would prevent incorrect suggestions if MIR lowering ever produces different spans. |
| 13 | +// |
| 14 | +// This test covers the various patterns that exercise the usertype ascription path |
| 15 | +// to guard against regressions. |
| 16 | + |
| 17 | +fn main() { |
| 18 | + // Basic usertype ascription: `let x: &T = &y` |
| 19 | + // Exercises the inner-assignment pierce-through and suggests `&mut` on the expression. |
| 20 | + let y = 0i32; |
| 21 | + let x: &i32 = &y; |
| 22 | + //~^ HELP consider changing this to be a mutable reference |
| 23 | + *x = 1; |
| 24 | + //~^ ERROR cannot assign to `*x`, which is behind a `&` reference |
| 25 | + //~| NOTE `x` is a `&` reference, so it cannot be written to |
| 26 | + |
| 27 | + // Usertype ascription with `&mut` on the RHS: the inner rvalue is a mutable borrow, |
| 28 | + // so `suggest_ampmut` returns `ChangeBinding` and the caller suggests changing the type. |
| 29 | + let mut v = Vec::new(); |
| 30 | + let w: &Vec<i32> = &mut v; |
| 31 | + //~^ HELP consider changing this binding's type |
| 32 | + w.push(1); |
| 33 | + //~^ ERROR cannot borrow `*w` as mutable, as it is behind a `&` reference |
| 34 | + //~| NOTE `w` is a `&` reference, so it cannot be borrowed as mutable |
| 35 | + |
| 36 | + // Usertype ascription with parenthesized expression. |
| 37 | + let a = 0i32; |
| 38 | + let b: &i32 = &(a); |
| 39 | + //~^ HELP consider changing this to be a mutable reference |
| 40 | + *b = 2; |
| 41 | + //~^ ERROR cannot assign to `*b`, which is behind a `&` reference |
| 42 | + //~| NOTE `b` is a `&` reference, so it cannot be written to |
| 43 | + |
| 44 | + // Usertype ascription inside a block expression. |
| 45 | + let c = 0i32; |
| 46 | + let d: &i32 = { &c }; |
| 47 | + //~^ HELP consider changing this to be a mutable reference |
| 48 | + *d = 3; |
| 49 | + //~^ ERROR cannot assign to `*d`, which is behind a `&` reference |
| 50 | + //~| NOTE `d` is a `&` reference, so it cannot be written to |
| 51 | +} |
0 commit comments