Provide structured suggestion for binding needing type on E0594
Partially address #45405.
This commit is contained in:
parent
97872b792c
commit
da1360d981
9 changed files with 95 additions and 30 deletions
|
@ -606,12 +606,60 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some((false, err_label_span, message)) => {
|
Some((false, err_label_span, message)) => {
|
||||||
err.span_label(
|
struct V {
|
||||||
err_label_span,
|
span: Span,
|
||||||
&format!(
|
hir_id: Option<hir::HirId>,
|
||||||
"consider changing this binding's type to be: `{message}`"
|
}
|
||||||
),
|
|
||||||
);
|
impl<'tcx> Visitor<'tcx> for V {
|
||||||
|
fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) {
|
||||||
|
if let hir::StmtKind::Local(local) = s.kind {
|
||||||
|
if local.pat.span == self.span {
|
||||||
|
self.hir_id = Some(local.hir_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hir::intravisit::walk_stmt(self, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let hir_map = self.infcx.tcx.hir();
|
||||||
|
let pat = loop {
|
||||||
|
// Poor man's try block
|
||||||
|
let def_id = self.body.source.def_id();
|
||||||
|
let hir_id =
|
||||||
|
hir_map.local_def_id_to_hir_id(def_id.as_local().unwrap());
|
||||||
|
let node = hir_map.find(hir_id);
|
||||||
|
let Some(hir::Node::Item(item)) = node else { break None; };
|
||||||
|
let hir::ItemKind::Fn(.., body_id) = item.kind else { break None; };
|
||||||
|
let body = self.infcx.tcx.hir().body(body_id);
|
||||||
|
let mut v = V { span: err_label_span, hir_id: None };
|
||||||
|
v.visit_body(body);
|
||||||
|
break v.hir_id;
|
||||||
|
};
|
||||||
|
if let Some(hir_id) = pat
|
||||||
|
&& let Some(hir::Node::Local(local)) = hir_map.find(hir_id)
|
||||||
|
{
|
||||||
|
let (changing, span, sugg) = match local.ty {
|
||||||
|
Some(ty) => ("changing", ty.span, message),
|
||||||
|
None => (
|
||||||
|
"specifying",
|
||||||
|
local.pat.span.shrink_to_hi(),
|
||||||
|
format!(": {message}"),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
span,
|
||||||
|
&format!("consider {changing} this binding's type"),
|
||||||
|
sugg,
|
||||||
|
Applicability::HasPlaceholders,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
err.span_label(
|
||||||
|
err_label_span,
|
||||||
|
&format!(
|
||||||
|
"consider changing this binding's type to be: `{message}`"
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
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
|
--> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:9:5
|
||||||
|
|
|
|
||||||
LL | let t1 = t0;
|
|
||||||
| -- consider changing this binding's type to be: `&mut &mut isize`
|
|
||||||
LL | let p: &isize = &**t0;
|
|
||||||
LL | **t1 = 22;
|
LL | **t1 = 22;
|
||||||
| ^^^^^^^^^ `t1` is a `&` reference, so the data it refers to cannot be written
|
| ^^^^^^^^^ `t1` is a `&` reference, so the data it refers to cannot be written
|
||||||
|
|
|
||||||
|
help: consider specifying this binding's type
|
||||||
|
|
|
||||||
|
LL | let t1: &mut &mut isize = t0;
|
||||||
|
| +++++++++++++++++
|
||||||
|
|
||||||
error[E0502]: cannot borrow `**t0` as immutable because it is also borrowed as mutable
|
error[E0502]: cannot borrow `**t0` as immutable because it is also borrowed as mutable
|
||||||
--> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:14:21
|
--> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:14:21
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut test = Vec::new();
|
let mut test = Vec::new();
|
||||||
let rofl: &Vec<Vec<i32>> = &mut test;
|
let rofl: &Vec<Vec<i32>> = &mut test;
|
||||||
//~^ NOTE consider changing this binding's type to be
|
//~^ HELP consider changing this binding's type
|
||||||
rofl.push(Vec::new());
|
rofl.push(Vec::new());
|
||||||
//~^ ERROR cannot borrow `*rofl` as mutable, as it is behind a `&` reference
|
//~^ 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
|
//~| NOTE `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
||||||
|
@ -15,14 +15,14 @@ fn main() {
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
let x: &usize = &mut{0};
|
let x: &usize = &mut{0};
|
||||||
//~^ NOTE consider changing this binding's type to be
|
//~^ HELP consider changing this binding's type
|
||||||
*x = 1;
|
*x = 1;
|
||||||
//~^ ERROR cannot assign to `*x`, which is behind a `&` reference
|
//~^ ERROR cannot assign to `*x`, which is behind a `&` reference
|
||||||
//~| NOTE `x` is a `&` reference, so the data it refers to cannot be written
|
//~| NOTE `x` is a `&` reference, so the data it refers to cannot be written
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
let y: &usize = &mut(0);
|
let y: &usize = &mut(0);
|
||||||
//~^ NOTE consider changing this binding's type to be
|
//~^ HELP consider changing this binding's type
|
||||||
*y = 1;
|
*y = 1;
|
||||||
//~^ ERROR cannot assign to `*y`, which is behind a `&` reference
|
//~^ ERROR cannot assign to `*y`, which is behind a `&` reference
|
||||||
//~| NOTE `y` is a `&` reference, so the data it refers to cannot be written
|
//~| NOTE `y` is a `&` reference, so the data it refers to cannot be written
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
error[E0596]: cannot borrow `*rofl` as mutable, as it is behind a `&` reference
|
error[E0596]: cannot borrow `*rofl` as mutable, as it is behind a `&` reference
|
||||||
--> $DIR/issue-85765.rs:5:5
|
--> $DIR/issue-85765.rs:5:5
|
||||||
|
|
|
|
||||||
LL | let rofl: &Vec<Vec<i32>> = &mut test;
|
|
||||||
| ---- consider changing this binding's type to be: `&mut Vec<Vec<i32>>`
|
|
||||||
LL |
|
|
||||||
LL | rofl.push(Vec::new());
|
LL | rofl.push(Vec::new());
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^ `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
| ^^^^^^^^^^^^^^^^^^^^^ `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
||||||
|
|
|
||||||
|
help: consider changing this binding's type
|
||||||
|
|
|
||||||
|
LL | let rofl: &mut Vec<Vec<i32>> = &mut test;
|
||||||
|
| ~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
error[E0594]: cannot assign to `*r`, which is behind a `&` reference
|
error[E0594]: cannot assign to `*r`, which is behind a `&` reference
|
||||||
--> $DIR/issue-85765.rs:12:5
|
--> $DIR/issue-85765.rs:12:5
|
||||||
|
@ -21,20 +23,24 @@ LL | let r = &mut mutvar;
|
||||||
error[E0594]: cannot assign to `*x`, which is behind a `&` reference
|
error[E0594]: cannot assign to `*x`, which is behind a `&` reference
|
||||||
--> $DIR/issue-85765.rs:19:5
|
--> $DIR/issue-85765.rs:19:5
|
||||||
|
|
|
|
||||||
LL | let x: &usize = &mut{0};
|
|
||||||
| - consider changing this binding's type to be: `&mut usize`
|
|
||||||
LL |
|
|
||||||
LL | *x = 1;
|
LL | *x = 1;
|
||||||
| ^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
|
| ^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
|
||||||
|
|
|
||||||
|
help: consider changing this binding's type
|
||||||
|
|
|
||||||
|
LL | let x: &mut usize = &mut{0};
|
||||||
|
| ~~~~~~~~~~
|
||||||
|
|
||||||
error[E0594]: cannot assign to `*y`, which is behind a `&` reference
|
error[E0594]: cannot assign to `*y`, which is behind a `&` reference
|
||||||
--> $DIR/issue-85765.rs:26:5
|
--> $DIR/issue-85765.rs:26:5
|
||||||
|
|
|
|
||||||
LL | let y: &usize = &mut(0);
|
|
||||||
| - consider changing this binding's type to be: `&mut usize`
|
|
||||||
LL |
|
|
||||||
LL | *y = 1;
|
LL | *y = 1;
|
||||||
| ^^^^^^ `y` is a `&` reference, so the data it refers to cannot be written
|
| ^^^^^^ `y` is a `&` reference, so the data it refers to cannot be written
|
||||||
|
|
|
||||||
|
help: consider changing this binding's type
|
||||||
|
|
|
||||||
|
LL | let y: &mut usize = &mut(0);
|
||||||
|
| ~~~~~~~~~~
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ impl TestClient {
|
||||||
fn main() {
|
fn main() {
|
||||||
let client = TestClient;
|
let client = TestClient;
|
||||||
let inner = client.get_inner_ref();
|
let inner = client.get_inner_ref();
|
||||||
//~^ NOTE consider changing this binding's type to be
|
//~^ HELP consider specifying this binding's type
|
||||||
inner.clear();
|
inner.clear();
|
||||||
//~^ ERROR cannot borrow `*inner` as mutable, as it is behind a `&` reference [E0596]
|
//~^ ERROR cannot borrow `*inner` as mutable, as it is behind a `&` reference [E0596]
|
||||||
//~| NOTE `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
//~| NOTE `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
error[E0596]: cannot borrow `*inner` as mutable, as it is behind a `&` reference
|
error[E0596]: cannot borrow `*inner` as mutable, as it is behind a `&` reference
|
||||||
--> $DIR/issue-91206.rs:13:5
|
--> $DIR/issue-91206.rs:13:5
|
||||||
|
|
|
|
||||||
LL | let inner = client.get_inner_ref();
|
|
||||||
| ----- consider changing this binding's type to be: `&mut Vec<usize>`
|
|
||||||
LL |
|
|
||||||
LL | inner.clear();
|
LL | inner.clear();
|
||||||
| ^^^^^^^^^^^^^ `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
| ^^^^^^^^^^^^^ `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
||||||
|
|
|
||||||
|
help: consider specifying this binding's type
|
||||||
|
|
|
||||||
|
LL | let inner: &mut Vec<usize> = client.get_inner_ref();
|
||||||
|
| +++++++++++++++++
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
error[E0594]: cannot assign to `*foo`, which is behind a `&` reference
|
error[E0594]: cannot assign to `*foo`, which is behind a `&` reference
|
||||||
--> $DIR/issue-92015.rs:6:5
|
--> $DIR/issue-92015.rs:6:5
|
||||||
|
|
|
|
||||||
LL | let foo = Some(&0).unwrap();
|
|
||||||
| --- consider changing this binding's type to be: `&mut i32`
|
|
||||||
LL | *foo = 1;
|
LL | *foo = 1;
|
||||||
| ^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written
|
| ^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written
|
||||||
|
|
|
||||||
|
help: consider specifying this binding's type
|
||||||
|
|
|
||||||
|
LL | let foo: &mut i32 = Some(&0).unwrap();
|
||||||
|
| ++++++++++
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ fn main() {
|
||||||
*foo = 32;
|
*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;
|
let bar = foo;
|
||||||
|
//~^ HELP consider specifying this binding's type
|
||||||
*bar = 64;
|
*bar = 64;
|
||||||
//~^ ERROR cannot assign to `*bar`, which is behind a `&` reference
|
//~^ ERROR cannot assign to `*bar`, which is behind a `&` reference
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,12 +10,15 @@ LL | let foo = &mut 16;
|
||||||
| ~~~~~~~
|
| ~~~~~~~
|
||||||
|
|
||||||
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:8:5
|
--> $DIR/issue-51515.rs:9:5
|
||||||
|
|
|
|
||||||
LL | let bar = foo;
|
|
||||||
| --- consider changing this binding's type to be: `&mut i32`
|
|
||||||
LL | *bar = 64;
|
LL | *bar = 64;
|
||||||
| ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written
|
| ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written
|
||||||
|
|
|
||||||
|
help: consider specifying this binding's type
|
||||||
|
|
|
||||||
|
LL | let bar: &mut i32 = foo;
|
||||||
|
| ++++++++++
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue