Skip to content

Commit 3ddf6f7

Browse files
committed
use maybe_body_owned_by for closure
1 parent 7bd81ee commit 3ddf6f7

11 files changed

+229
-74
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -363,21 +363,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
363363
}
364364
}
365365
let hir = self.infcx.tcx.hir();
366-
if let Some(hir::Node::Item(hir::Item {
367-
kind: hir::ItemKind::Fn(_, _, body_id),
368-
..
369-
})) = hir.find(self.mir_hir_id())
370-
&& let Some(hir::Node::Expr(expr)) = hir.find(body_id.hir_id)
371-
{
366+
if let Some(body_id) = hir.maybe_body_owned_by(self.mir_def_id()) {
367+
let expr = hir.body(body_id).value;
372368
let place = &self.move_data.move_paths[mpi].place;
373-
let span = place.as_local()
374-
.map(|local| self.body.local_decls[local].source_info.span);
375-
let mut finder = ExpressionFinder {
376-
expr_span: move_span,
377-
expr: None,
378-
pat: None,
379-
parent_pat: None,
380-
};
369+
let span = place.as_local().map(|local| self.body.local_decls[local].source_info.span);
370+
let mut finder =
371+
ExpressionFinder { expr_span: move_span, expr: None, pat: None, parent_pat: None };
381372
finder.visit_expr(expr);
382373
if let Some(span) = span && let Some(expr) = finder.expr {
383374
for (_, expr) in hir.parent_iter(expr.hir_id) {

compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs

Lines changed: 41 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed
22
use rustc_hir as hir;
33
use rustc_hir::intravisit::Visitor;
44
use rustc_hir::Node;
5-
use rustc_middle::hir::map::Map;
65
use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem};
76
use rustc_middle::ty::{self, Ty, TyCtxt};
87
use rustc_middle::{
@@ -646,14 +645,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
646645
}
647646
let hir_map = self.infcx.tcx.hir();
648647
let def_id = self.body.source.def_id();
649-
let hir_id = hir_map.local_def_id_to_hir_id(def_id.as_local().unwrap());
650-
let node = hir_map.find(hir_id);
651-
let Some(hir::Node::Item(item)) = node else {
652-
return;
653-
};
654-
let hir::ItemKind::Fn(.., body_id) = item.kind else {
655-
return;
656-
};
648+
let Some(local_def_id) = def_id.as_local() else { return };
649+
let Some(body_id) = hir_map.maybe_body_owned_by(local_def_id) else { return };
657650
let body = self.infcx.tcx.hir().body(body_id);
658651

659652
let mut v = V { assign_span: span, err, ty, suggested: false };
@@ -790,23 +783,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
790783
// In the future, attempt in all path but initially for RHS of for_loop
791784
fn suggest_similar_mut_method_for_for_loop(&self, err: &mut Diagnostic) {
792785
use hir::{
793-
BodyId, Expr,
786+
Expr,
794787
ExprKind::{Block, Call, DropTemps, Match, MethodCall},
795-
HirId, ImplItem, ImplItemKind, Item, ItemKind,
796788
};
797789

798-
fn maybe_body_id_of_fn(hir_map: Map<'_>, id: HirId) -> Option<BodyId> {
799-
match hir_map.find(id) {
800-
Some(Node::Item(Item { kind: ItemKind::Fn(_, _, body_id), .. }))
801-
| Some(Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(_, body_id), .. })) => {
802-
Some(*body_id)
803-
}
804-
_ => None,
805-
}
806-
}
807790
let hir_map = self.infcx.tcx.hir();
808-
let mir_body_hir_id = self.mir_hir_id();
809-
if let Some(fn_body_id) = maybe_body_id_of_fn(hir_map, mir_body_hir_id) {
791+
if let Some(body_id) = hir_map.maybe_body_owned_by(self.mir_def_id()) {
810792
if let Block(
811793
hir::Block {
812794
expr:
@@ -840,7 +822,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
840822
..
841823
},
842824
_,
843-
) = hir_map.body(fn_body_id).value.kind
825+
) = hir_map.body(body_id).value.kind
844826
{
845827
let opt_suggestions = self
846828
.infcx
@@ -1102,46 +1084,45 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
11021084
}
11031085
let hir_map = self.infcx.tcx.hir();
11041086
let def_id = self.body.source.def_id();
1105-
let hir_id = hir_map.local_def_id_to_hir_id(def_id.expect_local());
1106-
let node = hir_map.find(hir_id);
1107-
let hir_id = if let Some(hir::Node::Item(item)) = node
1108-
&& let hir::ItemKind::Fn(.., body_id) = item.kind
1109-
{
1110-
let body = hir_map.body(body_id);
1111-
let mut v = BindingFinder {
1112-
span: err_label_span,
1113-
hir_id: None,
1087+
let hir_id = if let Some(local_def_id) = def_id.as_local() &&
1088+
let Some(body_id) = hir_map.maybe_body_owned_by(local_def_id)
1089+
{
1090+
let body = hir_map.body(body_id);
1091+
let mut v = BindingFinder {
1092+
span: err_label_span,
1093+
hir_id: None,
1094+
};
1095+
v.visit_body(body);
1096+
v.hir_id
1097+
} else {
1098+
None
11141099
};
1115-
v.visit_body(body);
1116-
v.hir_id
1117-
} else {
1118-
None
1119-
};
1100+
11201101
if let Some(hir_id) = hir_id
11211102
&& let Some(hir::Node::Local(local)) = hir_map.find(hir_id)
1122-
{
1123-
let (changing, span, sugg) = match local.ty {
1124-
Some(ty) => ("changing", ty.span, message),
1125-
None => (
1126-
"specifying",
1127-
local.pat.span.shrink_to_hi(),
1128-
format!(": {message}"),
1129-
),
1130-
};
1131-
err.span_suggestion_verbose(
1132-
span,
1133-
format!("consider {changing} this binding's type"),
1134-
sugg,
1135-
Applicability::HasPlaceholders,
1136-
);
1137-
} else {
1138-
err.span_label(
1139-
err_label_span,
1140-
format!(
1141-
"consider changing this binding's type to be: `{message}`"
1142-
),
1143-
);
1144-
}
1103+
{
1104+
let (changing, span, sugg) = match local.ty {
1105+
Some(ty) => ("changing", ty.span, message),
1106+
None => (
1107+
"specifying",
1108+
local.pat.span.shrink_to_hi(),
1109+
format!(": {message}"),
1110+
),
1111+
};
1112+
err.span_suggestion_verbose(
1113+
span,
1114+
format!("consider {changing} this binding's type"),
1115+
sugg,
1116+
Applicability::HasPlaceholders,
1117+
);
1118+
} else {
1119+
err.span_label(
1120+
err_label_span,
1121+
format!(
1122+
"consider changing this binding's type to be: `{message}`"
1123+
),
1124+
);
1125+
}
11451126
}
11461127
None => {}
11471128
}

tests/ui/borrowck/copy-suggestion-region-vid.stderr

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ LL | HelperStruct { helpers, is_empty: helpers[0].is_empty() }
88
| ------- ^^^^^^^^^^ value borrowed here after move
99
| |
1010
| value moved here
11+
|
12+
help: consider cloning the value if the performance cost is acceptable
13+
|
14+
LL | HelperStruct { helpers.clone(), is_empty: helpers[0].is_empty() }
15+
| ++++++++
1116

1217
error: aborting due to previous error
1318

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
fn main() {
2+
let _ = || {
3+
let mut test = Vec::new();
4+
let rofl: &Vec<Vec<i32>> = &mut test;
5+
//~^ HELP consider changing this binding's type
6+
rofl.push(Vec::new());
7+
//~^ ERROR cannot borrow `*rofl` as mutable, as it is behind a `&` reference
8+
//~| NOTE `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable
9+
10+
let mut mutvar = 42;
11+
let r = &mutvar;
12+
//~^ HELP consider changing this to be a mutable reference
13+
*r = 0;
14+
//~^ ERROR cannot assign to `*r`, which is behind a `&` reference
15+
//~| NOTE `r` is a `&` reference, so the data it refers to cannot be written
16+
17+
#[rustfmt::skip]
18+
let x: &usize = &mut{0};
19+
//~^ HELP consider changing this binding's type
20+
*x = 1;
21+
//~^ ERROR cannot assign to `*x`, which is behind a `&` reference
22+
//~| NOTE `x` is a `&` reference, so the data it refers to cannot be written
23+
24+
#[rustfmt::skip]
25+
let y: &usize = &mut(0);
26+
//~^ HELP consider changing this binding's type
27+
*y = 1;
28+
//~^ ERROR cannot assign to `*y`, which is behind a `&` reference
29+
//~| NOTE `y` is a `&` reference, so the data it refers to cannot be written
30+
};
31+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
error[E0596]: cannot borrow `*rofl` as mutable, as it is behind a `&` reference
2+
--> $DIR/issue-85765-closure.rs:6:9
3+
|
4+
LL | rofl.push(Vec::new());
5+
| ^^^^ `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+
| ~~~~~~~~~~~~~~~~~~
11+
12+
error[E0594]: cannot assign to `*r`, which is behind a `&` reference
13+
--> $DIR/issue-85765-closure.rs:13:9
14+
|
15+
LL | *r = 0;
16+
| ^^^^^^ `r` is a `&` reference, so the data it refers to cannot be written
17+
|
18+
help: consider changing this to be a mutable reference
19+
|
20+
LL | let r = &mut mutvar;
21+
| +++
22+
23+
error[E0594]: cannot assign to `*x`, which is behind a `&` reference
24+
--> $DIR/issue-85765-closure.rs:20:9
25+
|
26+
LL | *x = 1;
27+
| ^^^^^^ `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+
| ~~~~~~~~~~
33+
34+
error[E0594]: cannot assign to `*y`, which is behind a `&` reference
35+
--> $DIR/issue-85765-closure.rs:27:9
36+
|
37+
LL | *y = 1;
38+
| ^^^^^^ `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+
| ~~~~~~~~~~
44+
45+
error: aborting due to 4 previous errors
46+
47+
Some errors have detailed explanations: E0594, E0596.
48+
For more information about an error, try `rustc --explain E0594`.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
use std::collections::BTreeMap;
2+
3+
fn main() {
4+
let _ = || {
5+
let mut map = BTreeMap::<u32, u32>::new();
6+
map[&0] = 1; //~ ERROR cannot assign
7+
};
8+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0594]: cannot assign to data in an index of `BTreeMap<u32, u32>`
2+
--> $DIR/btreemap-index-mut-2.rs:6:9
3+
|
4+
LL | map[&0] = 1;
5+
| ^^^^^^^^^^^ cannot assign
6+
|
7+
= help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `BTreeMap<u32, u32>`
8+
help: to modify a `BTreeMap<u32, u32>`, use `.get_mut()`, `.insert()` or the entry API
9+
|
10+
LL | map.insert(&0, 1);
11+
| ~~~~~~~~ ~ +
12+
LL | map.get_mut(&0).map(|val| { *val = 1; });
13+
| ~~~~~~~~~ ~~~~~~~~~~~~~~~~~~ ++++
14+
LL | let val = map.entry(&0).or_insert(1);
15+
| +++++++++ ~~~~~~~ ~~~~~~~~~~~~ +
16+
17+
error: aborting due to previous error
18+
19+
For more information about this error, try `rustc --explain E0594`.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
fn take(_x: Box<isize>) {}
2+
3+
4+
fn main() {
5+
let _ = || {
6+
let x: Box<isize> = Box::new(25);
7+
8+
loop {
9+
take(x); //~ ERROR use of moved value: `x`
10+
}
11+
};
12+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error[E0382]: use of moved value: `x`
2+
--> $DIR/liveness-move-call-arg-2.rs:9:18
3+
|
4+
LL | let x: Box<isize> = Box::new(25);
5+
| - move occurs because `x` has type `Box<isize>`, which does not implement the `Copy` trait
6+
LL |
7+
LL | loop {
8+
| ---- inside of this loop
9+
LL | take(x);
10+
| ^ value moved here, in previous iteration of loop
11+
|
12+
note: consider changing this parameter type in function `take` to borrow instead if owning the value isn't necessary
13+
--> $DIR/liveness-move-call-arg-2.rs:1:13
14+
|
15+
LL | fn take(_x: Box<isize>) {}
16+
| ---- ^^^^^^^^^^ this parameter takes ownership of the value
17+
| |
18+
| in this function
19+
help: consider cloning the value if the performance cost is acceptable
20+
|
21+
LL | take(x.clone());
22+
| ++++++++
23+
24+
error: aborting due to previous error
25+
26+
For more information about this error, try `rustc --explain E0382`.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
use std::collections::HashMap;
2+
struct X(usize);
3+
struct Y {
4+
v: u32,
5+
}
6+
7+
fn main() {
8+
let _ = || {
9+
let mut buzz = HashMap::new();
10+
buzz.insert("a", Y { v: 0 });
11+
12+
for mut t in buzz.values() {
13+
//~^ HELP
14+
//~| SUGGESTION values_mut()
15+
t.v += 1;
16+
//~^ ERROR cannot assign
17+
}
18+
};
19+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0594]: cannot assign to `t.v`, which is behind a `&` reference
2+
--> $DIR/suggest-mut-method-for-loop-closure.rs:15:13
3+
|
4+
LL | for mut t in buzz.values() {
5+
| -------------
6+
| | |
7+
| | help: use mutable method: `values_mut()`
8+
| this iterator yields `&` references
9+
...
10+
LL | t.v += 1;
11+
| ^^^^^^^^ `t` is a `&` reference, so the data it refers to cannot be written
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0594`.

0 commit comments

Comments
 (0)