Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #15625 - jDomantas:domantas/fix-15623, r=HKalbasi
fix: Don't skip closure captures after let-else
As I understand that `return` was left there by accident. It caused capture analysis to skip the rest of the block after a let-else, and then missed captures caused incorrect results in borrowck, closure hints, layout calculation, etc.
Fixes #15623
I didn't understand why I using the example from #15623 as-is doesn't work - I don't get the warnings unless I remove the `call_me()` call, even on the same commit as my own RA version which does show those warnings.
| -rw-r--r-- | crates/hir-ty/src/infer/closure.rs | 10 | ||||
| -rw-r--r-- | crates/hir-ty/src/layout/tests/closure.rs | 14 | ||||
| -rw-r--r-- | crates/ide-diagnostics/src/handlers/mutability_errors.rs | 23 |
3 files changed, 42 insertions, 5 deletions
diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs index 1f040393f1..13d6b5643a 100644 --- a/crates/hir-ty/src/infer/closure.rs +++ b/crates/hir-ty/src/infer/closure.rs @@ -469,13 +469,13 @@ impl InferenceContext<'_> { Statement::Let { pat, type_ref: _, initializer, else_branch } => { if let Some(else_branch) = else_branch { self.consume_expr(*else_branch); - if let Some(initializer) = initializer { - self.consume_expr(*initializer); - } - return; } if let Some(initializer) = initializer { - self.walk_expr(*initializer); + if else_branch.is_some() { + self.consume_expr(*initializer); + } else { + self.walk_expr(*initializer); + } if let Some(place) = self.place_of_expr(*initializer) { self.consume_with_pat(place, *pat); } diff --git a/crates/hir-ty/src/layout/tests/closure.rs b/crates/hir-ty/src/layout/tests/closure.rs index 576e7f3fc6..bbe855a14d 100644 --- a/crates/hir-ty/src/layout/tests/closure.rs +++ b/crates/hir-ty/src/layout/tests/closure.rs @@ -255,3 +255,17 @@ fn ellipsis_pattern() { } } } + +#[test] +fn regression_15623() { + size_and_align_expr! { + let a = 2; + let b = 3; + let c = 5; + move || { + let 0 = a else { return b; }; + let y = c; + y + } + } +} diff --git a/crates/ide-diagnostics/src/handlers/mutability_errors.rs b/crates/ide-diagnostics/src/handlers/mutability_errors.rs index 8976a3de67..d056e5c85c 100644 --- a/crates/ide-diagnostics/src/handlers/mutability_errors.rs +++ b/crates/ide-diagnostics/src/handlers/mutability_errors.rs @@ -1173,4 +1173,27 @@ fn f() { "#, ); } + + #[test] + fn regression_15623() { + check_diagnostics( + r#" +//- minicore: fn + +struct Foo; + +impl Foo { + fn needs_mut(&mut self) {} +} + +fn foo(mut foo: Foo) { + let mut call_me = || { + let 0 = 1 else { return }; + foo.needs_mut(); + }; + call_me(); +} +"#, + ); + } } |