Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 4aba2c5

Browse files
committed
Modify find_expr from Span to better account for closures
Start pointing to where bindings were 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 ef8b9dc commit 4aba2c5

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
@@ -1964,7 +1964,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
19641964
pub(crate) fn find_expr(&self, span: Span) -> Option<&hir::Expr<'_>> {
19651965
let tcx = self.infcx.tcx;
19661966
let body_id = tcx.hir_node(self.mir_hir_id()).body_id()?;
1967-
let mut expr_finder = FindExprBySpan::new(span);
1967+
let mut expr_finder = FindExprBySpan::new(span, tcx);
19681968
expr_finder.visit_expr(tcx.hir().body(body_id).value);
19691969
expr_finder.result
19701970
}
@@ -1998,14 +1998,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
19981998
};
19991999

20002000
let mut expr_finder =
2001-
FindExprBySpan::new(self.body.local_decls[*index1].source_info.span);
2001+
FindExprBySpan::new(self.body.local_decls[*index1].source_info.span, tcx);
20022002
expr_finder.visit_expr(hir.body(body_id).value);
20032003
let Some(index1) = expr_finder.result else {
20042004
note_default_suggestion();
20052005
return;
20062006
};
20072007

2008-
expr_finder = FindExprBySpan::new(self.body.local_decls[*index2].source_info.span);
2008+
expr_finder = FindExprBySpan::new(self.body.local_decls[*index2].source_info.span, tcx);
20092009
expr_finder.visit_expr(hir.body(body_id).value);
20102010
let Some(index2) = expr_finder.result else {
20112011
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
@@ -901,7 +901,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
901901
// Remove all the desugaring and macro contexts.
902902
span.remove_mark();
903903
}
904-
let mut expr_finder = FindExprBySpan::new(span);
904+
let mut expr_finder = FindExprBySpan::new(span, self.tcx);
905905
let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else {
906906
return;
907907
};
@@ -1367,7 +1367,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
13671367
return false;
13681368
};
13691369
let body = self.tcx.hir().body(body_id);
1370-
let mut expr_finder = FindExprBySpan::new(span);
1370+
let mut expr_finder = FindExprBySpan::new(span, self.tcx);
13711371
expr_finder.visit_expr(body.value);
13721372
let Some(expr) = expr_finder.result else {
13731373
return false;
@@ -1469,7 +1469,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
14691469
// Remove all the hir desugaring contexts while maintaining the macro contexts.
14701470
span.remove_mark();
14711471
}
1472-
let mut expr_finder = super::FindExprBySpan::new(span);
1472+
let mut expr_finder = super::FindExprBySpan::new(span, self.tcx);
14731473
let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else {
14741474
return false;
14751475
};

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
@@ -2457,7 +2457,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
24572457
&& let Some(body_id) =
24582458
self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id)
24592459
{
2460-
let mut expr_finder = FindExprBySpan::new(span);
2460+
let mut expr_finder = FindExprBySpan::new(span, self.tcx);
24612461
expr_finder.visit_expr(self.tcx.hir().body(body_id).value);
24622462

24632463
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 #[coroutine] || 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 | #[coroutine] || {
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:16:18
2020
|
21+
LL | let ref_ = Box::leak(Box::new(Some(cell.borrow_mut())));
22+
| ---- binding `ref_` declared here
23+
...
2124
LL | || {
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)