diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2023-02-04 20:29:06 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-02-04 20:29:06 +0100 |
| commit | d381eca5dc000efbb90a439de860cc9a796d042d (patch) | |
| tree | 6716e86c2912603afa694e01bf680631a4c9a540 | |
| parent | 3666fa080050594ab3ad26255c069e4d2000a3f4 (diff) | |
| parent | e6c56cda09633c0388ef4c6c9e97d064db829cc3 (diff) | |
| download | rust-d381eca5dc000efbb90a439de860cc9a796d042d.tar.gz rust-d381eca5dc000efbb90a439de860cc9a796d042d.zip | |
Rollup merge of #107646 - estebank:specific-span, r=compiler-errors
Provide structured suggestion for binding needing type on E0594 Partially address #45405.
| -rw-r--r-- | compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs | 63 | ||||
| -rw-r--r-- | tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr | 8 | ||||
| -rw-r--r-- | tests/ui/borrowck/issue-85765.rs | 6 | ||||
| -rw-r--r-- | tests/ui/borrowck/issue-85765.stderr | 24 | ||||
| -rw-r--r-- | tests/ui/borrowck/issue-91206.rs | 2 | ||||
| -rw-r--r-- | tests/ui/borrowck/issue-91206.stderr | 8 | ||||
| -rw-r--r-- | tests/ui/borrowck/issue-92015.stderr | 7 | ||||
| -rw-r--r-- | tests/ui/issues/issue-51515.rs | 1 | ||||
| -rw-r--r-- | tests/ui/issues/issue-51515.stderr | 9 |
9 files changed, 98 insertions, 30 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 40f518b33cf..9f37b915b77 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -606,12 +606,63 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } Some((false, err_label_span, message)) => { - err.span_label( - err_label_span, - &format!( - "consider changing this binding's type to be: `{message}`" - ), - ); + struct BindingFinder { + span: Span, + hir_id: Option<hir::HirId>, + } + + impl<'tcx> Visitor<'tcx> for BindingFinder { + 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 def_id = self.body.source.def_id(); + let hir_id = hir_map.local_def_id_to_hir_id(def_id.expect_local()); + let node = hir_map.find(hir_id); + let hir_id = if let Some(hir::Node::Item(item)) = node + && let hir::ItemKind::Fn(.., body_id) = item.kind + { + let body = hir_map.body(body_id); + let mut v = BindingFinder { + span: err_label_span, + hir_id: None, + }; + v.visit_body(body); + v.hir_id + } else { + None + }; + if let Some(hir_id) = hir_id + && 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 => {} } diff --git a/tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr b/tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr index ce9f7aa050a..dd0817ff233 100644 --- a/tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr +++ b/tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr @@ -1,11 +1,13 @@ 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; - | -- consider changing this binding's type to be: `&mut &mut isize` -LL | let p: &isize = &**t0; LL | **t1 = 22; | ^^^^^^^^^ `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 --> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:14:21 diff --git a/tests/ui/borrowck/issue-85765.rs b/tests/ui/borrowck/issue-85765.rs index 1598cd5d3c8..76e0b517354 100644 --- a/tests/ui/borrowck/issue-85765.rs +++ b/tests/ui/borrowck/issue-85765.rs @@ -1,7 +1,7 @@ fn main() { let mut test = Vec::new(); 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()); //~^ 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 @@ -15,14 +15,14 @@ fn main() { #[rustfmt::skip] let x: &usize = &mut{0}; - //~^ NOTE consider changing this binding's type to be + //~^ HELP consider changing this binding's type *x = 1; //~^ ERROR cannot assign to `*x`, which is behind a `&` reference //~| NOTE `x` is a `&` reference, so the data it refers to cannot be written #[rustfmt::skip] let y: &usize = &mut(0); - //~^ NOTE consider changing this binding's type to be + //~^ HELP consider changing this binding's type *y = 1; //~^ ERROR cannot assign to `*y`, which is behind a `&` reference //~| NOTE `y` is a `&` reference, so the data it refers to cannot be written diff --git a/tests/ui/borrowck/issue-85765.stderr b/tests/ui/borrowck/issue-85765.stderr index 7da7dba68ab..b4bb128cbb4 100644 --- a/tests/ui/borrowck/issue-85765.stderr +++ b/tests/ui/borrowck/issue-85765.stderr @@ -1,11 +1,13 @@ error[E0596]: cannot borrow `*rofl` as mutable, as it is behind a `&` reference --> $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()); | ^^^^^^^^^^^^^^^^^^^^^ `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 --> $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 --> $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; | ^^^^^^ `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 --> $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; | ^^^^^^ `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 diff --git a/tests/ui/borrowck/issue-91206.rs b/tests/ui/borrowck/issue-91206.rs index 67407c1eae3..e062a253767 100644 --- a/tests/ui/borrowck/issue-91206.rs +++ b/tests/ui/borrowck/issue-91206.rs @@ -9,7 +9,7 @@ impl TestClient { fn main() { let client = TestClient; let inner = client.get_inner_ref(); - //~^ NOTE consider changing this binding's type to be + //~^ HELP consider specifying this binding's type inner.clear(); //~^ 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 diff --git a/tests/ui/borrowck/issue-91206.stderr b/tests/ui/borrowck/issue-91206.stderr index 12d8d27c5f0..6653d497873 100644 --- a/tests/ui/borrowck/issue-91206.stderr +++ b/tests/ui/borrowck/issue-91206.stderr @@ -1,11 +1,13 @@ error[E0596]: cannot borrow `*inner` as mutable, as it is behind a `&` reference --> $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(); | ^^^^^^^^^^^^^ `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 diff --git a/tests/ui/borrowck/issue-92015.stderr b/tests/ui/borrowck/issue-92015.stderr index 62b1183e71b..ea4f9abb87d 100644 --- a/tests/ui/borrowck/issue-92015.stderr +++ b/tests/ui/borrowck/issue-92015.stderr @@ -1,10 +1,13 @@ error[E0594]: cannot assign to `*foo`, which is behind a `&` reference --> $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; | ^^^^^^^^ `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 diff --git a/tests/ui/issues/issue-51515.rs b/tests/ui/issues/issue-51515.rs index 797c1085d51..84e09afac0a 100644 --- a/tests/ui/issues/issue-51515.rs +++ b/tests/ui/issues/issue-51515.rs @@ -5,6 +5,7 @@ fn main() { *foo = 32; //~^ ERROR cannot assign to `*foo`, which is behind a `&` reference let bar = foo; + //~^ HELP consider specifying this binding's type *bar = 64; //~^ ERROR cannot assign to `*bar`, which is behind a `&` reference } diff --git a/tests/ui/issues/issue-51515.stderr b/tests/ui/issues/issue-51515.stderr index c4e61e71953..94e5c9f1b83 100644 --- a/tests/ui/issues/issue-51515.stderr +++ b/tests/ui/issues/issue-51515.stderr @@ -10,12 +10,15 @@ LL | let foo = &mut 16; | ~~~~~~~ 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; | ^^^^^^^^^ `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 |
