From 5f401e3ce6bf4f5b112204e217fdfa47e8a5a65b Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Thu, 19 Jun 2025 01:30:10 +0900 Subject: [PATCH] fix: Closure capturing for let exprs --- crates/hir-ty/src/infer/closure.rs | 6 +++++- crates/hir-ty/src/tests/closure_captures.rs | 19 +++++++++++++++++++ .../src/handlers/moved_out_of_ref.rs | 19 +++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs index d1432cacf8..b756bb859d 100644 --- a/crates/hir-ty/src/infer/closure.rs +++ b/crates/hir-ty/src/infer/closure.rs @@ -1230,11 +1230,15 @@ impl InferenceContext<'_> { self.select_from_expr(*expr); } } + Expr::Let { pat: _, expr } => { + self.walk_expr(*expr); + let place = self.place_of_expr(*expr); + self.ref_expr(*expr, place); + } Expr::UnaryOp { expr, op: _ } | Expr::Array(Array::Repeat { initializer: expr, repeat: _ }) | Expr::Await { expr } | Expr::Loop { body: expr, label: _ } - | Expr::Let { pat: _, expr } | Expr::Box { expr } | Expr::Cast { expr, type_ref: _ } => { self.consume_expr(*expr); diff --git a/crates/hir-ty/src/tests/closure_captures.rs b/crates/hir-ty/src/tests/closure_captures.rs index 88d21be81e..7fb981752d 100644 --- a/crates/hir-ty/src/tests/closure_captures.rs +++ b/crates/hir-ty/src/tests/closure_captures.rs @@ -444,3 +444,22 @@ fn main() { expect!["99..165;49..54;120..121,133..134 ByRef(Mut { kind: Default }) a &'? mut A"], ); } + +#[test] +fn let_binding_is_a_ref_capture() { + check_closure_captures( + r#" +//- minicore:copy +struct S; +fn main() { + let mut s = S; + let s_ref = &mut s; + let closure = || { + if let ref cb = s_ref { + } + }; +} +"#, + expect!["83..135;49..54;112..117 ByRef(Shared) s_ref &'? &'? mut S"], + ); +} 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 7181d708fe..0928262d22 100644 --- a/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs +++ b/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs @@ -220,4 +220,23 @@ fn test() { "#, ) } + + #[test] + fn regression_18201() { + check_diagnostics( + r#" +//- minicore: copy +struct NotCopy; +struct S(NotCopy); +impl S { + fn f(&mut self) { + || { + if let ref mut _cb = self.0 { + } + }; + } +} +"#, + ) + } }