Skip to content

Commit f091f16

Browse files
committed
Sema: Track active pack expansions across closure boundaries
1 parent 53d8ba8 commit f091f16

File tree

2 files changed

+24
-15
lines changed

2 files changed

+24
-15
lines changed

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
@@ -1636,9 +1643,9 @@ namespace {
16361643

16371644
// Add a PackElementOf constraint for 'each T' type reprs.
16381645
PackExpansionExpr *elementEnv = nullptr;
1639-
if (!PackElementEnvironments.empty()) {
1646+
if (!OuterExpansions.empty()) {
16401647
options |= TypeResolutionFlags::AllowPackReferences;
1641-
elementEnv = PackElementEnvironments.back();
1648+
elementEnv = OuterExpansions.back();
16421649
}
16431650
const auto packElementOpener = OpenPackElementType(CS, locator, elementEnv);
16441651

@@ -1889,9 +1896,9 @@ namespace {
18891896
TypeResolutionOptions(TypeResolverContext::InExpression);
18901897
for (auto specializationArg : specializationArgs) {
18911898
PackExpansionExpr *elementEnv = nullptr;
1892-
if (!PackElementEnvironments.empty()) {
1899+
if (!OuterExpansions.empty()) {
18931900
options |= TypeResolutionFlags::AllowPackReferences;
1894-
elementEnv = PackElementEnvironments.back();
1901+
elementEnv = OuterExpansions.back();
18951902
}
18961903
const auto result = TypeResolution::resolveContextualType(
18971904
specializationArg, CurDC, options,
@@ -3055,6 +3062,9 @@ namespace {
30553062
Constraint::create(CS, ConstraintKind::FallbackType, closureType,
30563063
inferredType, locator, referencedVars));
30573064

3065+
if (!OuterExpansions.empty())
3066+
CS.setCapturedExpansions(closure, OuterExpansions);
3067+
30583068
CS.setClosureType(closure, inferredType);
30593069
return closureType;
30603070
}
@@ -3160,8 +3170,8 @@ namespace {
31603170
}
31613171

31623172
Type visitPackExpansionExpr(PackExpansionExpr *expr) {
3163-
assert(PackElementEnvironments.back() == expr);
3164-
PackElementEnvironments.pop_back();
3173+
assert(OuterExpansions.back() == expr);
3174+
OuterExpansions.pop_back();
31653175

31663176
auto expansionType = CS.getType(expr)->castTo<PackExpansionType>();
31673177
auto elementResultType = CS.getType(expr->getPatternExpr());
@@ -3182,7 +3192,7 @@ namespace {
31823192
for (auto pack : expandedPacks) {
31833193
Type packType;
31843194
/// Skipping over pack elements because the relationship to its
3185-
/// environment is now established during \c addPackElementEnvironment
3195+
/// environment is now established during \c pushPackExpansionExpr
31863196
/// upon visiting its pack expansion and the Shape constraint added
31873197
/// upon visiting the pack element.
31883198
if (isExpr<PackElementExpr>(pack)) {
@@ -4301,7 +4311,7 @@ namespace {
43014311
}
43024312

43034313
if (auto *expansion = dyn_cast<PackExpansionExpr>(expr)) {
4304-
CG.addPackElementEnvironment(expansion);
4314+
CG.pushPackExpansionExpr(expansion);
43054315
}
43064316

43074317
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)