Skip to content

Commit 6ea82b2

Browse files
authored
Merge pull request swiftlang#63196 from xedin/connect-captures-to-closure
[CSGen] Captures should always be connected to their closure
2 parents 8d0b187 + 60720f4 commit 6ea82b2

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

lib/Sema/CSGen.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2970,6 +2970,15 @@ namespace {
29702970
SmallVector<TypeVariableType *, 4> referencedVars{
29712971
collectVarRefs.varRefs.begin(), collectVarRefs.varRefs.end()};
29722972

2973+
if (auto *captureList =
2974+
getAsExpr<CaptureListExpr>(CS.getParentExpr(closure))) {
2975+
for (const auto &capture : captureList->getCaptureList()) {
2976+
if (auto *typeVar =
2977+
CS.getType(capture.getVar())->getAs<TypeVariableType>())
2978+
referencedVars.push_back(typeVar);
2979+
}
2980+
}
2981+
29732982
CS.addUnsolvedConstraint(Constraint::create(
29742983
CS, ConstraintKind::DefaultClosureType, closureType, inferredType,
29752984
locator, referencedVars));

unittests/Sema/ConstraintGenerationTests.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,64 @@ TEST_F(SemaTest, TestImplicitConditionalCastConstraintGeneration) {
115115
ASSERT_TRUE(getTypeOfCoercedExpr(cast<ConditionalCheckedCastExpr>(resultExpr))
116116
->isEqual(getStdlibType("Int")));
117117
}
118+
119+
TEST_F(SemaTest, TestCaptureListIsConnectedToTheClosure) {
120+
ConstraintSystem cs(DC, ConstraintSystemOptions());
121+
122+
DeclAttributes attrs;
123+
auto *closure = new (Context) ClosureExpr(attrs,
124+
/*bracetRange=*/SourceRange(),
125+
/*capturedSelfDecl=*/nullptr,
126+
ParameterList::createEmpty(Context),
127+
/*asyncLoc=*/SourceLoc(),
128+
/*throwsLoc=*/SourceLoc(),
129+
/*arrowLoc=*/SourceLoc(),
130+
/*inLoc=*/SourceLoc(),
131+
/*explicitResultType=*/nullptr, DC);
132+
closure->setImplicit();
133+
closure->setBody(BraceStmt::createImplicit(Context, /*elements=*/{}),
134+
/*isSingleExpression=*/true);
135+
136+
SmallVector<CaptureListEntry> captures;
137+
{
138+
// The capture variable.
139+
auto *xVar = new (Context)
140+
VarDecl(/*isStatic=*/false, VarDecl::Introducer::Var,
141+
/*loc=*/SourceLoc(), Context.getIdentifier("x"), DC);
142+
xVar->setImplicit();
143+
144+
auto *PBD = PatternBindingDecl::createImplicit(
145+
Context, StaticSpellingKind::None,
146+
/*pattern=*/NamedPattern::createImplicit(Context, xVar),
147+
IntegerLiteralExpr::createFromUnsigned(Context, 42, SourceLoc()), DC);
148+
149+
captures.push_back(CaptureListEntry(PBD));
150+
}
151+
152+
auto *captureList = CaptureListExpr::create(Context, captures, closure);
153+
154+
// _ = { [x = 42] in }
155+
Expr *assign = new (Context)
156+
AssignExpr(new (Context) DiscardAssignmentExpr(/*loc=*/SourceLoc(),
157+
/*Implicit=*/true),
158+
/*EqualLoc=*/SourceLoc(), captureList, /*Implicit=*/true);
159+
160+
auto *processed = cs.generateConstraints(assign, DC);
161+
ASSERT_NE(processed, nullptr);
162+
163+
auto *closureType = cs.getType(closure)->castTo<TypeVariableType>();
164+
auto &CG = cs.getConstraintGraph();
165+
166+
for (auto *constraint : CG[closureType].getConstraints()) {
167+
if (constraint->getKind() != ConstraintKind::DefaultClosureType)
168+
continue;
169+
170+
for (const auto &capture : captureList->getCaptureList()) {
171+
auto *capturedVar =
172+
cs.getType(capture.getVar())->castTo<TypeVariableType>();
173+
174+
ASSERT_TRUE(
175+
llvm::is_contained(constraint->getTypeVariables(), capturedVar));
176+
}
177+
}
178+
}

0 commit comments

Comments
 (0)