Skip to content

Commit 87940a9

Browse files
authored
Merge pull request #20161 from ShoyuVanilla/closure-capture
fix: Incorrect closure capturing for let exprs
2 parents c0d9c95 + f3eb22e commit 87940a9

File tree

3 files changed

+48
-5
lines changed

3 files changed

+48
-5
lines changed

crates/hir-ty/src/infer/closure.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1229,10 +1229,11 @@ impl InferenceContext<'_> {
12291229
self.select_from_expr(*expr);
12301230
}
12311231
}
1232-
Expr::Let { pat: _, expr } => {
1232+
Expr::Let { pat, expr } => {
12331233
self.walk_expr(*expr);
1234-
let place = self.place_of_expr(*expr);
1235-
self.ref_expr(*expr, place);
1234+
if let Some(place) = self.place_of_expr(*expr) {
1235+
self.consume_with_pat(place, *pat);
1236+
}
12361237
}
12371238
Expr::UnaryOp { expr, op: _ }
12381239
| Expr::Array(Array::Repeat { initializer: expr, repeat: _ })

crates/hir-ty/src/tests/closure_captures.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -446,20 +446,44 @@ fn main() {
446446
}
447447

448448
#[test]
449-
fn let_binding_is_a_ref_capture() {
449+
fn let_binding_is_a_ref_capture_in_ref_binding() {
450450
check_closure_captures(
451451
r#"
452452
//- minicore:copy
453453
struct S;
454454
fn main() {
455455
let mut s = S;
456456
let s_ref = &mut s;
457+
let mut s2 = S;
458+
let s_ref2 = &mut s2;
457459
let closure = || {
458460
if let ref cb = s_ref {
461+
} else if let ref mut cb = s_ref2 {
459462
}
460463
};
461464
}
462465
"#,
463-
expect!["83..135;49..54;112..117 ByRef(Shared) s_ref &'? &'? mut S"],
466+
expect![[r#"
467+
129..225;49..54;149..155 ByRef(Shared) s_ref &'? &'? mut S
468+
129..225;93..99;188..198 ByRef(Mut { kind: Default }) s_ref2 &'? mut &'? mut S"#]],
469+
);
470+
}
471+
472+
#[test]
473+
fn let_binding_is_a_value_capture_in_binding() {
474+
check_closure_captures(
475+
r#"
476+
//- minicore:copy, option
477+
struct Box(i32);
478+
fn main() {
479+
let b = Some(Box(0));
480+
let closure = || {
481+
if let Some(b) = b {
482+
let _move = b;
483+
}
484+
};
485+
}
486+
"#,
487+
expect!["73..149;37..38;103..104 ByValue b Option<Box>"],
464488
);
465489
}

crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,24 @@ impl S {
236236
};
237237
}
238238
}
239+
"#,
240+
)
241+
}
242+
243+
#[test]
244+
fn regression_20155() {
245+
check_diagnostics(
246+
r#"
247+
//- minicore: copy, option
248+
struct Box(i32);
249+
fn test() {
250+
let b = Some(Box(0));
251+
|| {
252+
if let Some(b) = b {
253+
let _move = b;
254+
}
255+
};
256+
}
239257
"#,
240258
)
241259
}

0 commit comments

Comments
 (0)