Skip to content

Commit a237368

Browse files
committed
[CS] Fix DeclContext for multi-statement captures
Make sure we set the correct DeclContext for CSGen of multi-statement captures, since otherwise the DeclContext is set to the closure itself, which is wrong.
1 parent 963889d commit a237368

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

lib/Sema/CSSyntacticElement.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,20 @@ class SyntacticElementConstraintGenerator
818818

819819
if (patternBinding->isInitializerChecked(index))
820820
return;
821-
821+
822+
// Capture list bindings in multi-statement closures get solved as part of
823+
// the closure's conjunction, which has the DeclContext set to the closure.
824+
// This is wrong for captures though, which are semantically bound outside
825+
// of the closure body. So we need to re-adjust their DeclContext here for
826+
// constraint generation. The constraint system's DeclContext will be wrong
827+
// for solving, but CSGen should ensure that constraints carry the correct
828+
// DeclContext.
829+
std::optional<llvm::SaveAndRestore<DeclContext *>> DCScope;
830+
if (auto *var = patternBinding->getSingleVar()) {
831+
if (var->getParentCaptureList())
832+
DCScope.emplace(cs.DC, var->getDeclContext());
833+
}
834+
822835
auto contextualPattern =
823836
ContextualPattern::forPatternBindingDecl(patternBinding, index);
824837
Type patternType = TypeChecker::typeCheckPattern(contextualPattern);

test/Constraints/issue-79444.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
// https://github.com/swiftlang/swift/issues/79444
4+
class C {
5+
func foo() {
6+
_ = { [x = "\(self)"] in } // expected-warning {{capture 'x' was never used}}
7+
_ = { [x = "\(self)"] in x }
8+
_ = { [x = "\(self)"] in
9+
let y = x
10+
return y
11+
}
12+
_ = { [x = "\(self)"] in
13+
let fn = { [y = "\(x)"] in
14+
let z = y
15+
return z
16+
}
17+
return fn()
18+
}
19+
}
20+
}

0 commit comments

Comments
 (0)