Skip to content

Commit 71fea61

Browse files
committed
suggest adding a local for vector to fix borrowck errors
1 parent dc1f829 commit 71fea61

6 files changed

+109
-9
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+31-9
Original file line numberDiff line numberDiff line change
@@ -785,13 +785,22 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
785785
issued_borrow: &BorrowData<'tcx>,
786786
explanation: BorrowExplanation,
787787
) {
788-
let used_in_call =
789-
matches!(explanation, BorrowExplanation::UsedLater(LaterUseKind::Call, _call_span, _));
788+
let used_in_call = matches!(
789+
explanation,
790+
BorrowExplanation::UsedLater(LaterUseKind::Call | LaterUseKind::Other, _call_span, _)
791+
);
790792
if !used_in_call {
791793
debug!("not later used in call");
792794
return;
793795
}
794796

797+
let use_span =
798+
if let BorrowExplanation::UsedLater(LaterUseKind::Other, use_span, _) = explanation {
799+
Some(use_span)
800+
} else {
801+
None
802+
};
803+
795804
let outer_call_loc =
796805
if let TwoPhaseActivation::ActivatedAt(loc) = issued_borrow.activation_location {
797806
loc
@@ -835,7 +844,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
835844
debug!("===> outer_call_loc = {:?}, inner_call_loc = {:?}", outer_call_loc, inner_call_loc);
836845

837846
let inner_call_span = inner_call_term.source_info.span;
838-
let outer_call_span = outer_call_stmt.either(|s| s.source_info, |t| t.source_info).span;
847+
let outer_call_span = match use_span {
848+
Some(span) => span,
849+
None => outer_call_stmt.either(|s| s.source_info, |t| t.source_info).span,
850+
};
839851
if outer_call_span == inner_call_span || !outer_call_span.contains(inner_call_span) {
840852
// FIXME: This stops the suggestion in some cases where it should be emitted.
841853
// Fix the spans for those cases so it's emitted correctly.
@@ -845,8 +857,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
845857
);
846858
return;
847859
}
848-
err.span_help(inner_call_span, "try adding a local storing this argument...");
849-
err.span_help(outer_call_span, "...and then using that local as the argument to this call");
860+
err.span_help(
861+
inner_call_span,
862+
&format!(
863+
"try adding a local storing this{}...",
864+
if use_span.is_some() { "" } else { " argument" }
865+
),
866+
);
867+
err.span_help(
868+
outer_call_span,
869+
&format!(
870+
"...and then using that local {}",
871+
if use_span.is_some() { "here" } else { "as the argument to this call" }
872+
),
873+
);
850874
}
851875

852876
fn suggest_split_at_mut_if_applicable(
@@ -1912,10 +1936,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
19121936
} else {
19131937
"cannot assign twice to immutable variable"
19141938
};
1915-
if span != assigned_span {
1916-
if !from_arg {
1917-
err.span_label(assigned_span, format!("first assignment to {}", place_description));
1918-
}
1939+
if span != assigned_span && !from_arg {
1940+
err.span_label(assigned_span, format!("first assignment to {}", place_description));
19191941
}
19201942
if let Some(decl) = local_decl
19211943
&& let Some(name) = local_name
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
fn main() {
2+
let mut vec = vec![0u32; 420];
3+
vec[vec.len() - 1] = 123; //~ ERROR cannot borrow `vec` as immutable because it is also borrowed as mutable
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
error[E0502]: cannot borrow `vec` as immutable because it is also borrowed as mutable
2+
--> $DIR/suggest-local-var-for-vector.rs:3:9
3+
|
4+
LL | vec[vec.len() - 1] = 123;
5+
| ----^^^^^^^^^-----
6+
| | |
7+
| | immutable borrow occurs here
8+
| mutable borrow occurs here
9+
| mutable borrow later used here
10+
|
11+
help: try adding a local storing this...
12+
--> $DIR/suggest-local-var-for-vector.rs:3:9
13+
|
14+
LL | vec[vec.len() - 1] = 123;
15+
| ^^^^^^^^^
16+
help: ...and then using that local here
17+
--> $DIR/suggest-local-var-for-vector.rs:3:5
18+
|
19+
LL | vec[vec.len() - 1] = 123;
20+
| ^^^^^^^^^^^^^^^^^^
21+
22+
error: aborting due to previous error
23+
24+
For more information about this error, try `rustc --explain E0502`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
fn main() {
2+
let mut vec = vec![0u32; 420];
3+
vec[vec.len() - 1] = 123; //~ ERROR cannot borrow `vec` as immutable because it is also borrowed as mutable
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
error[E0502]: cannot borrow `vec` as immutable because it is also borrowed as mutable
2+
--> $DIR/suggest-storing-local-var-for-vector.rs:3:9
3+
|
4+
LL | vec[vec.len() - 1] = 123;
5+
| ----^^^^^^^^^-----
6+
| | |
7+
| | immutable borrow occurs here
8+
| mutable borrow occurs here
9+
| mutable borrow later used here
10+
|
11+
help: try adding a local storing this...
12+
--> $DIR/suggest-storing-local-var-for-vector.rs:3:9
13+
|
14+
LL | vec[vec.len() - 1] = 123;
15+
| ^^^^^^^^^
16+
help: ...and then using that local here
17+
--> $DIR/suggest-storing-local-var-for-vector.rs:3:5
18+
|
19+
LL | vec[vec.len() - 1] = 123;
20+
| ^^^^^^^^^^^^^^^^^^
21+
22+
error: aborting due to previous error
23+
24+
For more information about this error, try `rustc --explain E0502`.

src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr

+22
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,17 @@ LL | i[i[3]] = 4;
5454
| | immutable borrow occurs here
5555
| mutable borrow occurs here
5656
| mutable borrow later used here
57+
|
58+
help: try adding a local storing this...
59+
--> $DIR/two-phase-nonrecv-autoref.rs:138:7
60+
|
61+
LL | i[i[3]] = 4;
62+
| ^^^^
63+
help: ...and then using that local here
64+
--> $DIR/two-phase-nonrecv-autoref.rs:138:5
65+
|
66+
LL | i[i[3]] = 4;
67+
| ^^^^^^^
5768

5869
error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable
5970
--> $DIR/two-phase-nonrecv-autoref.rs:143:7
@@ -64,6 +75,17 @@ LL | i[i[3]] = i[4];
6475
| | immutable borrow occurs here
6576
| mutable borrow occurs here
6677
| mutable borrow later used here
78+
|
79+
help: try adding a local storing this...
80+
--> $DIR/two-phase-nonrecv-autoref.rs:143:7
81+
|
82+
LL | i[i[3]] = i[4];
83+
| ^^^^
84+
help: ...and then using that local here
85+
--> $DIR/two-phase-nonrecv-autoref.rs:143:5
86+
|
87+
LL | i[i[3]] = i[4];
88+
| ^^^^^^^
6789

6890
error: aborting due to 7 previous errors
6991

0 commit comments

Comments
 (0)