Skip to content

Commit 494f6d7

Browse files
committed
Modify find_expr from Span to better account for closures
Start pointing to where bindings where declared when they are captured in closures: ``` error[E0597]: `x` does not live long enough --> $DIR/suggest-return-closure.rs:23:9 | LL | let x = String::new(); | - binding `x` declared here ... LL | |c| { | --- value captured here LL | x.push(c); | ^ borrowed value does not live long enough ... LL | } | -- borrow later used here | | | `x` dropped here while still borrowed ``` Suggest cloning in more cases involving closures: ``` error[E0507]: cannot move out of `foo` in pattern guard --> $DIR/issue-27282-move-ref-mut-into-guard.rs:11:19 | LL | if { (|| { let mut bar = foo; bar.take() })(); false } => {}, | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait | | | `foo` is moved here | = note: variables bound in patterns cannot be moved from until after the end of the pattern guard help: consider cloning the value if the performance cost is acceptable | LL | if { (|| { let mut bar = foo.clone(); bar.take() })(); false } => {}, | ++++++++ ```
1 parent c8d9753 commit 494f6d7

31 files changed

+202
-31
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2017,7 +2017,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
20172017
pub(crate) fn find_expr(&self, span: Span) -> Option<&hir::Expr<'_>> {
20182018
let tcx = self.infcx.tcx;
20192019
let body_id = tcx.hir_node(self.mir_hir_id()).body_id()?;
2020-
let mut expr_finder = FindExprBySpan::new(span);
2020+
let mut expr_finder = FindExprBySpan::new(span, tcx);
20212021
expr_finder.visit_expr(tcx.hir().body(body_id).value);
20222022
expr_finder.result
20232023
}
@@ -2051,14 +2051,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
20512051
};
20522052

20532053
let mut expr_finder =
2054-
FindExprBySpan::new(self.body.local_decls[*index1].source_info.span);
2054+
FindExprBySpan::new(self.body.local_decls[*index1].source_info.span, tcx);
20552055
expr_finder.visit_expr(hir.body(body_id).value);
20562056
let Some(index1) = expr_finder.result else {
20572057
note_default_suggestion();
20582058
return;
20592059
};
20602060

2061-
expr_finder = FindExprBySpan::new(self.body.local_decls[*index2].source_info.span);
2061+
expr_finder = FindExprBySpan::new(self.body.local_decls[*index2].source_info.span, tcx);
20622062
expr_finder.visit_expr(hir.body(body_id).value);
20632063
let Some(index2) = expr_finder.result else {
20642064
note_default_suggestion();

compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
7676
&& let Some(body_id) = node.body_id()
7777
{
7878
let body = tcx.hir().body(body_id);
79-
let mut expr_finder = FindExprBySpan::new(span);
79+
let mut expr_finder = FindExprBySpan::new(span, tcx);
8080
expr_finder.visit_expr(body.value);
8181
if let Some(mut expr) = expr_finder.result {
8282
while let hir::ExprKind::AddrOf(_, _, inner)

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,22 @@ pub struct FindExprBySpan<'hir> {
5050
pub span: Span,
5151
pub result: Option<&'hir hir::Expr<'hir>>,
5252
pub ty_result: Option<&'hir hir::Ty<'hir>>,
53+
pub tcx: TyCtxt<'hir>,
5354
}
5455

5556
impl<'hir> FindExprBySpan<'hir> {
56-
pub fn new(span: Span) -> Self {
57-
Self { span, result: None, ty_result: None }
57+
pub fn new(span: Span, tcx: TyCtxt<'hir>) -> Self {
58+
Self { span, result: None, ty_result: None, tcx }
5859
}
5960
}
6061

6162
impl<'v> Visitor<'v> for FindExprBySpan<'v> {
63+
type NestedFilter = rustc_middle::hir::nested_filter::OnlyBodies;
64+
65+
fn nested_visit_map(&mut self) -> Self::Map {
66+
self.tcx.hir()
67+
}
68+
6269
fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
6370
if self.span == ex.span {
6471
self.result = Some(ex);

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -903,7 +903,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
903903
// Remove all the desugaring and macro contexts.
904904
span.remove_mark();
905905
}
906-
let mut expr_finder = FindExprBySpan::new(span);
906+
let mut expr_finder = FindExprBySpan::new(span, self.tcx);
907907
let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else {
908908
return;
909909
};
@@ -1369,7 +1369,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
13691369
return false;
13701370
};
13711371
let body = self.tcx.hir().body(body_id);
1372-
let mut expr_finder = FindExprBySpan::new(span);
1372+
let mut expr_finder = FindExprBySpan::new(span, self.tcx);
13731373
expr_finder.visit_expr(body.value);
13741374
let Some(expr) = expr_finder.result else {
13751375
return false;
@@ -1471,7 +1471,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
14711471
// Remove all the hir desugaring contexts while maintaining the macro contexts.
14721472
span.remove_mark();
14731473
}
1474-
let mut expr_finder = super::FindExprBySpan::new(span);
1474+
let mut expr_finder = super::FindExprBySpan::new(span, self.tcx);
14751475
let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else {
14761476
return false;
14771477
};

compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2451,7 +2451,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
24512451
&& let Some(body_id) =
24522452
self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id)
24532453
{
2454-
let mut expr_finder = FindExprBySpan::new(span);
2454+
let mut expr_finder = FindExprBySpan::new(span, self.tcx);
24552455
expr_finder.visit_expr(self.tcx.hir().body(body_id).value);
24562456

24572457
if let Some(hir::Expr {

tests/ui/coroutine/borrowing.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ error[E0597]: `a` does not live long enough
44
LL | let _b = {
55
| -- borrow later stored here
66
LL | let a = 3;
7+
| - binding `a` declared here
78
LL | Pin::new(&mut || yield &a).resume(())
89
| -- ^ borrowed value does not live long enough
910
| |
@@ -18,6 +19,7 @@ error[E0597]: `a` does not live long enough
1819
LL | let _b = {
1920
| -- borrow later stored here
2021
LL | let a = 3;
22+
| - binding `a` declared here
2123
LL | || {
2224
| -- value captured here by coroutine
2325
LL | yield &a

tests/ui/coroutine/dropck.stderr

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ LL | }
1818
error[E0597]: `ref_` does not live long enough
1919
--> $DIR/dropck.rs:15:18
2020
|
21+
LL | let ref_ = Box::leak(Box::new(Some(cell.borrow_mut())));
22+
| ---- binding `ref_` declared here
23+
...
2124
LL | gen = || {
2225
| -- value captured here by coroutine
2326
LL | // but the coroutine can use it to drop a `Ref<'a, i32>`.

tests/ui/fn/suggest-return-closure.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ fn fn_mut() -> _ {
1818
//~| NOTE for more information on `Fn` traits and closure types
1919
let x = String::new();
2020
//~^ HELP: consider changing this to be mutable
21+
//~| NOTE binding `x` declared here
2122
|c| { //~ NOTE: value captured here
2223
x.push(c);
2324
//~^ ERROR: does not live long enough

tests/ui/fn/suggest-return-closure.stderr

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ LL | fn fn_mut() -> _ {
2121
= note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html
2222

2323
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
24-
--> $DIR/suggest-return-closure.rs:31:13
24+
--> $DIR/suggest-return-closure.rs:32:13
2525
|
2626
LL | fn fun() -> _ {
2727
| ^
@@ -32,7 +32,7 @@ LL | fn fun() -> _ {
3232
= note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html
3333

3434
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
35-
--> $DIR/suggest-return-closure.rs:22:9
35+
--> $DIR/suggest-return-closure.rs:23:9
3636
|
3737
LL | let x = String::new();
3838
| - help: consider changing this to be mutable: `mut x`
@@ -41,8 +41,11 @@ LL | x.push(c);
4141
| ^ cannot borrow as mutable
4242

4343
error[E0597]: `x` does not live long enough
44-
--> $DIR/suggest-return-closure.rs:22:9
44+
--> $DIR/suggest-return-closure.rs:23:9
4545
|
46+
LL | let x = String::new();
47+
| - binding `x` declared here
48+
...
4649
LL | |c| {
4750
| --- value captured here
4851
LL | x.push(c);

tests/ui/nll/closure-borrow-spans.stderr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ LL | f.use_ref();
2525
error[E0597]: `x` does not live long enough
2626
--> $DIR/closure-borrow-spans.rs:19:16
2727
|
28+
LL | let x = 1;
29+
| - binding `x` declared here
2830
LL | f = || x;
2931
| -- ^ borrowed value does not live long enough
3032
| |
@@ -85,6 +87,8 @@ LL | f.use_ref();
8587
error[E0597]: `x` does not live long enough
8688
--> $DIR/closure-borrow-spans.rs:52:16
8789
|
90+
LL | let mut x = 1;
91+
| ----- binding `x` declared here
8892
LL | f = || x = 0;
8993
| -- ^ borrowed value does not live long enough
9094
| |
@@ -145,6 +149,8 @@ LL | f.use_ref();
145149
error[E0597]: `x` does not live long enough
146150
--> $DIR/closure-borrow-spans.rs:86:16
147151
|
152+
LL | let x = &mut z;
153+
| - binding `x` declared here
148154
LL | f = || *x = 0;
149155
| -- ^^ borrowed value does not live long enough
150156
| |

0 commit comments

Comments
 (0)