From f3eb22edd01bb4d3e446702e6844c684449d9734 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Thu, 3 Jul 2025 22:51:16 +0900 Subject: [PATCH] fix: Closure capturing for let exprs, again --- crates/hir-ty/src/infer/closure.rs | 7 +++-- crates/hir-ty/src/tests/closure_captures.rs | 28 +++++++++++++++++-- .../src/handlers/moved_out_of_ref.rs | 18 ++++++++++++ 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs index 65a273cdf8..c3029bf2b5 100644 --- a/crates/hir-ty/src/infer/closure.rs +++ b/crates/hir-ty/src/infer/closure.rs @@ -1229,10 +1229,11 @@ impl InferenceContext<'_> { self.select_from_expr(*expr); } } - Expr::Let { pat: _, expr } => { + Expr::Let { pat, expr } => { self.walk_expr(*expr); - let place = self.place_of_expr(*expr); - self.ref_expr(*expr, place); + if let Some(place) = self.place_of_expr(*expr) { + self.consume_with_pat(place, *pat); + } } Expr::UnaryOp { expr, op: _ } | Expr::Array(Array::Repeat { initializer: expr, repeat: _ }) diff --git a/crates/hir-ty/src/tests/closure_captures.rs b/crates/hir-ty/src/tests/closure_captures.rs index 7fb981752d..dbc68eeba1 100644 --- a/crates/hir-ty/src/tests/closure_captures.rs +++ b/crates/hir-ty/src/tests/closure_captures.rs @@ -446,7 +446,7 @@ fn main() { } #[test] -fn let_binding_is_a_ref_capture() { +fn let_binding_is_a_ref_capture_in_ref_binding() { check_closure_captures( r#" //- minicore:copy @@ -454,12 +454,36 @@ struct S; fn main() { let mut s = S; let s_ref = &mut s; + let mut s2 = S; + let s_ref2 = &mut s2; let closure = || { if let ref cb = s_ref { + } else if let ref mut cb = s_ref2 { } }; } "#, - expect!["83..135;49..54;112..117 ByRef(Shared) s_ref &'? &'? mut S"], + expect![[r#" + 129..225;49..54;149..155 ByRef(Shared) s_ref &'? &'? mut S + 129..225;93..99;188..198 ByRef(Mut { kind: Default }) s_ref2 &'? mut &'? mut S"#]], + ); +} + +#[test] +fn let_binding_is_a_value_capture_in_binding() { + check_closure_captures( + r#" +//- minicore:copy, option +struct Box(i32); +fn main() { + let b = Some(Box(0)); + let closure = || { + if let Some(b) = b { + let _move = b; + } + }; +} +"#, + expect!["73..149;37..38;103..104 ByValue b Option"], ); } diff --git a/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs b/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs index 0928262d22..1e80d02926 100644 --- a/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs +++ b/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs @@ -236,6 +236,24 @@ impl S { }; } } +"#, + ) + } + + #[test] + fn regression_20155() { + check_diagnostics( + r#" +//- minicore: copy, option +struct Box(i32); +fn test() { + let b = Some(Box(0)); + || { + if let Some(b) = b { + let _move = b; + } + }; +} "#, ) }