Skip to content

Commit d381eca

Browse files
authored
Rollup merge of rust-lang#107646 - estebank:specific-span, r=compiler-errors
Provide structured suggestion for binding needing type on E0594 Partially address rust-lang#45405.
2 parents 3666fa0 + e6c56cd commit d381eca

9 files changed

+98
-30
lines changed

compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs

+57-6
Original file line numberDiff line numberDiff line change
@@ -606,12 +606,63 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
606606
}
607607
}
608608
Some((false, err_label_span, message)) => {
609-
err.span_label(
610-
err_label_span,
611-
&format!(
612-
"consider changing this binding's type to be: `{message}`"
613-
),
614-
);
609+
struct BindingFinder {
610+
span: Span,
611+
hir_id: Option<hir::HirId>,
612+
}
613+
614+
impl<'tcx> Visitor<'tcx> for BindingFinder {
615+
fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) {
616+
if let hir::StmtKind::Local(local) = s.kind {
617+
if local.pat.span == self.span {
618+
self.hir_id = Some(local.hir_id);
619+
}
620+
}
621+
hir::intravisit::walk_stmt(self, s);
622+
}
623+
}
624+
let hir_map = self.infcx.tcx.hir();
625+
let def_id = self.body.source.def_id();
626+
let hir_id = hir_map.local_def_id_to_hir_id(def_id.expect_local());
627+
let node = hir_map.find(hir_id);
628+
let hir_id = if let Some(hir::Node::Item(item)) = node
629+
&& let hir::ItemKind::Fn(.., body_id) = item.kind
630+
{
631+
let body = hir_map.body(body_id);
632+
let mut v = BindingFinder {
633+
span: err_label_span,
634+
hir_id: None,
635+
};
636+
v.visit_body(body);
637+
v.hir_id
638+
} else {
639+
None
640+
};
641+
if let Some(hir_id) = hir_id
642+
&& let Some(hir::Node::Local(local)) = hir_map.find(hir_id)
643+
{
644+
let (changing, span, sugg) = match local.ty {
645+
Some(ty) => ("changing", ty.span, message),
646+
None => (
647+
"specifying",
648+
local.pat.span.shrink_to_hi(),
649+
format!(": {message}"),
650+
),
651+
};
652+
err.span_suggestion_verbose(
653+
span,
654+
&format!("consider {changing} this binding's type"),
655+
sugg,
656+
Applicability::HasPlaceholders,
657+
);
658+
} else {
659+
err.span_label(
660+
err_label_span,
661+
&format!(
662+
"consider changing this binding's type to be: `{message}`"
663+
),
664+
);
665+
}
615666
}
616667
None => {}
617668
}

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

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
error[E0594]: cannot assign to `**t1`, which is behind a `&` reference
22
--> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:9:5
33
|
4-
LL | let t1 = t0;
5-
| -- consider changing this binding's type to be: `&mut &mut isize`
6-
LL | let p: &isize = &**t0;
74
LL | **t1 = 22;
85
| ^^^^^^^^^ `t1` is a `&` reference, so the data it refers to cannot be written
6+
|
7+
help: consider specifying this binding's type
8+
|
9+
LL | let t1: &mut &mut isize = t0;
10+
| +++++++++++++++++
911

1012
error[E0502]: cannot borrow `**t0` as immutable because it is also borrowed as mutable
1113
--> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:14:21

tests/ui/borrowck/issue-85765.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
fn main() {
22
let mut test = Vec::new();
33
let rofl: &Vec<Vec<i32>> = &mut test;
4-
//~^ NOTE consider changing this binding's type to be
4+
//~^ HELP consider changing this binding's type
55
rofl.push(Vec::new());
66
//~^ ERROR cannot borrow `*rofl` as mutable, as it is behind a `&` reference
77
//~| NOTE `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable
@@ -15,14 +15,14 @@ fn main() {
1515

1616
#[rustfmt::skip]
1717
let x: &usize = &mut{0};
18-
//~^ NOTE consider changing this binding's type to be
18+
//~^ HELP consider changing this binding's type
1919
*x = 1;
2020
//~^ ERROR cannot assign to `*x`, which is behind a `&` reference
2121
//~| NOTE `x` is a `&` reference, so the data it refers to cannot be written
2222

2323
#[rustfmt::skip]
2424
let y: &usize = &mut(0);
25-
//~^ NOTE consider changing this binding's type to be
25+
//~^ HELP consider changing this binding's type
2626
*y = 1;
2727
//~^ ERROR cannot assign to `*y`, which is behind a `&` reference
2828
//~| NOTE `y` is a `&` reference, so the data it refers to cannot be written

tests/ui/borrowck/issue-85765.stderr

+15-9
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
error[E0596]: cannot borrow `*rofl` as mutable, as it is behind a `&` reference
22
--> $DIR/issue-85765.rs:5:5
33
|
4-
LL | let rofl: &Vec<Vec<i32>> = &mut test;
5-
| ---- consider changing this binding's type to be: `&mut Vec<Vec<i32>>`
6-
LL |
74
LL | rofl.push(Vec::new());
85
| ^^^^^^^^^^^^^^^^^^^^^ `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable
6+
|
7+
help: consider changing this binding's type
8+
|
9+
LL | let rofl: &mut Vec<Vec<i32>> = &mut test;
10+
| ~~~~~~~~~~~~~~~~~~
911

1012
error[E0594]: cannot assign to `*r`, which is behind a `&` reference
1113
--> $DIR/issue-85765.rs:12:5
@@ -21,20 +23,24 @@ LL | let r = &mut mutvar;
2123
error[E0594]: cannot assign to `*x`, which is behind a `&` reference
2224
--> $DIR/issue-85765.rs:19:5
2325
|
24-
LL | let x: &usize = &mut{0};
25-
| - consider changing this binding's type to be: `&mut usize`
26-
LL |
2726
LL | *x = 1;
2827
| ^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
28+
|
29+
help: consider changing this binding's type
30+
|
31+
LL | let x: &mut usize = &mut{0};
32+
| ~~~~~~~~~~
2933

3034
error[E0594]: cannot assign to `*y`, which is behind a `&` reference
3135
--> $DIR/issue-85765.rs:26:5
3236
|
33-
LL | let y: &usize = &mut(0);
34-
| - consider changing this binding's type to be: `&mut usize`
35-
LL |
3637
LL | *y = 1;
3738
| ^^^^^^ `y` is a `&` reference, so the data it refers to cannot be written
39+
|
40+
help: consider changing this binding's type
41+
|
42+
LL | let y: &mut usize = &mut(0);
43+
| ~~~~~~~~~~
3844

3945
error: aborting due to 4 previous errors
4046

tests/ui/borrowck/issue-91206.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ impl TestClient {
99
fn main() {
1010
let client = TestClient;
1111
let inner = client.get_inner_ref();
12-
//~^ NOTE consider changing this binding's type to be
12+
//~^ HELP consider specifying this binding's type
1313
inner.clear();
1414
//~^ ERROR cannot borrow `*inner` as mutable, as it is behind a `&` reference [E0596]
1515
//~| NOTE `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable

tests/ui/borrowck/issue-91206.stderr

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
error[E0596]: cannot borrow `*inner` as mutable, as it is behind a `&` reference
22
--> $DIR/issue-91206.rs:13:5
33
|
4-
LL | let inner = client.get_inner_ref();
5-
| ----- consider changing this binding's type to be: `&mut Vec<usize>`
6-
LL |
74
LL | inner.clear();
85
| ^^^^^^^^^^^^^ `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable
6+
|
7+
help: consider specifying this binding's type
8+
|
9+
LL | let inner: &mut Vec<usize> = client.get_inner_ref();
10+
| +++++++++++++++++
911

1012
error: aborting due to previous error
1113

tests/ui/borrowck/issue-92015.stderr

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
error[E0594]: cannot assign to `*foo`, which is behind a `&` reference
22
--> $DIR/issue-92015.rs:6:5
33
|
4-
LL | let foo = Some(&0).unwrap();
5-
| --- consider changing this binding's type to be: `&mut i32`
64
LL | *foo = 1;
75
| ^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written
6+
|
7+
help: consider specifying this binding's type
8+
|
9+
LL | let foo: &mut i32 = Some(&0).unwrap();
10+
| ++++++++++
811

912
error: aborting due to previous error
1013

tests/ui/issues/issue-51515.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ fn main() {
55
*foo = 32;
66
//~^ ERROR cannot assign to `*foo`, which is behind a `&` reference
77
let bar = foo;
8+
//~^ HELP consider specifying this binding's type
89
*bar = 64;
910
//~^ ERROR cannot assign to `*bar`, which is behind a `&` reference
1011
}

tests/ui/issues/issue-51515.stderr

+6-3
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@ LL | let foo = &mut 16;
1010
| ~~~~~~~
1111

1212
error[E0594]: cannot assign to `*bar`, which is behind a `&` reference
13-
--> $DIR/issue-51515.rs:8:5
13+
--> $DIR/issue-51515.rs:9:5
1414
|
15-
LL | let bar = foo;
16-
| --- consider changing this binding's type to be: `&mut i32`
1715
LL | *bar = 64;
1816
| ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written
17+
|
18+
help: consider specifying this binding's type
19+
|
20+
LL | let bar: &mut i32 = foo;
21+
| ++++++++++
1922

2023
error: aborting due to 2 previous errors
2124

0 commit comments

Comments
 (0)