Skip to content

Commit 48cc328

Browse files
committed
Sema: Track active pack expansions across closure boundaries
1 parent 38df64a commit 48cc328

File tree

3 files changed

+41
-15
lines changed

3 files changed

+41
-15
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2237,6 +2237,10 @@ class ConstraintSystem {
22372237
/// from declared parameters/result and body.
22382238
llvm::MapVector<const ClosureExpr *, FunctionType *> ClosureTypes;
22392239

2240+
/// Maps closures and local functions to the pack expansion expressions they
2241+
/// capture.
2242+
llvm::MapVector<AnyFunctionRef, SmallVector<PackExpansionExpr *, 1>> CapturedExpansions;
2243+
22402244
/// Maps expressions for implied results (e.g implicit 'then' statements,
22412245
/// implicit 'return' statements in single expression body closures) to their
22422246
/// result kind.
@@ -3172,6 +3176,19 @@ class ConstraintSystem {
31723176
return nullptr;
31733177
}
31743178

3179+
SmallVector<PackExpansionExpr *, 1> getCapturedExpansions(AnyFunctionRef func) const {
3180+
auto result = CapturedExpansions.find(func);
3181+
if (result == CapturedExpansions.end())
3182+
return {};
3183+
3184+
return result->second;
3185+
}
3186+
3187+
void setCapturedExpansions(AnyFunctionRef func, SmallVector<PackExpansionExpr *, 1> exprs) {
3188+
assert(CapturedExpansions.count(func) == 0 && "Cannot reset captured expansions");
3189+
CapturedExpansions.insert({func, exprs});
3190+
}
3191+
31753192
TypeVariableType *getKeyPathValueType(const KeyPathExpr *keyPath) const {
31763193
auto result = getKeyPathValueTypeIfAvailable(keyPath);
31773194
assert(result);

lib/Sema/CSGen.cpp

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -933,7 +933,7 @@ namespace {
933933
llvm::MapVector<UnresolvedMemberExpr *, Type> UnresolvedBaseTypes;
934934

935935
/// A stack of pack expansions that can open pack elements.
936-
llvm::SmallVector<PackExpansionExpr *, 2> PackElementEnvironments;
936+
llvm::SmallVector<PackExpansionExpr *, 1> OuterExpansions;
937937

938938
/// Returns false and emits the specified diagnostic if the member reference
939939
/// base is a nil literal. Returns true otherwise.
@@ -1000,7 +1000,7 @@ namespace {
10001000
}
10011001
unsigned options = (TVO_CanBindToLValue |
10021002
TVO_CanBindToNoEscape);
1003-
if (!PackElementEnvironments.empty())
1003+
if (!OuterExpansions.empty())
10041004
options |= TVO_CanBindToPack;
10051005

10061006
auto tv = CS.createTypeVariable(
@@ -1185,6 +1185,12 @@ namespace {
11851185
// result builders could generate constraints for its body
11861186
// in the middle of the solving.
11871187
CS.setPhase(ConstraintSystemPhase::ConstraintGeneration);
1188+
1189+
// Pick up the saved stack of pack expansions so we can continue
1190+
// to handle pack element references inside the closure body.
1191+
if (auto *ACE = dyn_cast<AbstractClosureExpr>(CurDC)) {
1192+
OuterExpansions = CS.getCapturedExpansions(ACE);
1193+
}
11881194
}
11891195

11901196
virtual ~ConstraintGenerator() {
@@ -1193,8 +1199,8 @@ namespace {
11931199

11941200
ConstraintSystem &getConstraintSystem() const { return CS; }
11951201

1196-
void addPackElementEnvironment(PackExpansionExpr *expr) {
1197-
PackElementEnvironments.push_back(expr);
1202+
void pushPackExpansionExpr(PackExpansionExpr *expr) {
1203+
OuterExpansions.push_back(expr);
11981204

11991205
SmallVector<ASTNode, 2> expandedPacks;
12001206
collectExpandedPacks(expr, expandedPacks);
@@ -1213,6 +1219,7 @@ namespace {
12131219
CS.getConstraintLocator(expr, ConstraintLocator::PackShape);
12141220
auto *shapeTypeVar = CS.createTypeVariable(
12151221
shapeLoc, TVO_CanBindToPack | TVO_CanBindToHole);
1222+
12161223
auto expansionType = PackExpansionType::get(patternType, shapeTypeVar);
12171224
CS.setType(expr, expansionType);
12181225
}
@@ -1585,7 +1592,7 @@ namespace {
15851592

15861593
unsigned options = (TVO_CanBindToLValue |
15871594
TVO_CanBindToNoEscape);
1588-
if (!PackElementEnvironments.empty())
1595+
if (!OuterExpansions.empty())
15891596
options |= TVO_CanBindToPack;
15901597

15911598
// Create an overload choice referencing this declaration and immediately
@@ -1623,9 +1630,9 @@ namespace {
16231630

16241631
// Add a PackElementOf constraint for 'each T' type reprs.
16251632
PackExpansionExpr *elementEnv = nullptr;
1626-
if (!PackElementEnvironments.empty()) {
1633+
if (!OuterExpansions.empty()) {
16271634
options |= TypeResolutionFlags::AllowPackReferences;
1628-
elementEnv = PackElementEnvironments.back();
1635+
elementEnv = OuterExpansions.back();
16291636
}
16301637
const auto packElementOpener = OpenPackElementType(CS, locator, elementEnv);
16311638

@@ -1876,9 +1883,9 @@ namespace {
18761883
TypeResolutionOptions(TypeResolverContext::InExpression);
18771884
for (auto specializationArg : specializationArgs) {
18781885
PackExpansionExpr *elementEnv = nullptr;
1879-
if (!PackElementEnvironments.empty()) {
1886+
if (!OuterExpansions.empty()) {
18801887
options |= TypeResolutionFlags::AllowPackReferences;
1881-
elementEnv = PackElementEnvironments.back();
1888+
elementEnv = OuterExpansions.back();
18821889
}
18831890
const auto result = TypeResolution::resolveContextualType(
18841891
specializationArg, CurDC, options,
@@ -3042,6 +3049,9 @@ namespace {
30423049
Constraint::create(CS, ConstraintKind::FallbackType, closureType,
30433050
inferredType, locator, referencedVars));
30443051

3052+
if (!OuterExpansions.empty())
3053+
CS.setCapturedExpansions(closure, OuterExpansions);
3054+
30453055
CS.setClosureType(closure, inferredType);
30463056
return closureType;
30473057
}
@@ -3147,8 +3157,8 @@ namespace {
31473157
}
31483158

31493159
Type visitPackExpansionExpr(PackExpansionExpr *expr) {
3150-
assert(PackElementEnvironments.back() == expr);
3151-
PackElementEnvironments.pop_back();
3160+
assert(OuterExpansions.back() == expr);
3161+
OuterExpansions.pop_back();
31523162

31533163
auto expansionType = CS.getType(expr)->castTo<PackExpansionType>();
31543164
auto elementResultType = CS.getType(expr->getPatternExpr());
@@ -3169,7 +3179,7 @@ namespace {
31693179
for (auto pack : expandedPacks) {
31703180
Type packType;
31713181
/// Skipping over pack elements because the relationship to its
3172-
/// environment is now established during \c addPackElementEnvironment
3182+
/// environment is now established during \c pushPackExpansionExpr
31733183
/// upon visiting its pack expansion and the Shape constraint added
31743184
/// upon visiting the pack element.
31753185
if (isExpr<PackElementExpr>(pack)) {
@@ -4319,7 +4329,7 @@ namespace {
43194329
}
43204330

43214331
if (auto *expansion = dyn_cast<PackExpansionExpr>(expr)) {
4322-
CG.addPackElementEnvironment(expansion);
4332+
CG.pushPackExpansionExpr(expansion);
43234333
}
43244334

43254335
return Action::Continue(expr);

test/Constraints/pack-expansion-expressions.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -608,9 +608,8 @@ func test_that_expansions_are_bound_early() {
608608
do {
609609
func test<T>(x: T) {}
610610

611-
// rdar://110711746 to make this valid
612611
func caller1<each T>(x: repeat each T) {
613-
_ = (repeat { test(x: each x) }()) // expected-error {{pack reference 'each T' can only appear in pack expansion}}
612+
_ = (repeat { test(x: each x) }())
614613
}
615614

616615
func caller2<each T>(x: repeat each T) {

0 commit comments

Comments
 (0)