Skip to content

Commit 888ab81

Browse files
committed
[ConstraintSystem] Connect closure to outer pack expansions it appears in
Type variable reference collector needs to be augmented to collect type variables associated with pack expansions that a closure references elements of, otherwise it would get disconnected from the context.
1 parent c18d2b1 commit 888ab81

File tree

3 files changed

+42
-0
lines changed

3 files changed

+42
-0
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6453,6 +6453,7 @@ class ConjunctionElementProducer : public BindingProducer<ConjunctionElement> {
64536453
///
64546454
/// This includes:
64556455
/// - Not yet resolved outer VarDecls (including closure parameters)
6456+
/// - Outer pack expansions that are not yet fully resolved
64566457
/// - Return statements with a contextual type that has not yet been resolved
64576458
///
64586459
/// This is required because isolated conjunctions, just like single-expression
@@ -6474,6 +6475,7 @@ class TypeVarRefCollector : public ASTWalker {
64746475

64756476
/// Infer the referenced type variables from a given decl.
64766477
void inferTypeVars(Decl *D);
6478+
void inferTypeVars(PackExpansionExpr *);
64776479

64786480
MacroWalking getMacroWalkingBehavior() const override {
64796481
return MacroWalking::Arguments;

lib/Sema/CSGen.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,14 @@ void TypeVarRefCollector::inferTypeVars(Decl *D) {
870870
TypeVars.insert(typeVars.begin(), typeVars.end());
871871
}
872872

873+
void TypeVarRefCollector::inferTypeVars(PackExpansionExpr *E) {
874+
auto expansionType = CS.getType(E)->castTo<PackExpansionType>();
875+
876+
SmallPtrSet<TypeVariableType *, 4> referencedVars;
877+
expansionType->getTypeVariables(referencedVars);
878+
TypeVars.insert(referencedVars.begin(), referencedVars.end());
879+
}
880+
873881
ASTWalker::PreWalkResult<Expr *>
874882
TypeVarRefCollector::walkToExprPre(Expr *expr) {
875883
if (isa<ClosureExpr>(expr))
@@ -891,6 +899,14 @@ TypeVarRefCollector::walkToExprPre(Expr *expr) {
891899
inferTypeVars(D);
892900
}
893901
}
902+
903+
if (auto *packElement = getAsExpr<PackElementExpr>(expr)) {
904+
// If environment hasn't been established yet, it means that pack expansion
905+
// appears inside of this closure.
906+
if (auto *outerEnvironment = CS.getPackEnvironment(packElement))
907+
inferTypeVars(outerEnvironment);
908+
}
909+
894910
return Action::Continue(expr);
895911
}
896912

test/Constraints/pack-expansion-expressions.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -739,3 +739,27 @@ do {
739739
// expected-warning@-2 {{immutable value 'y' was never used; consider replacing with '_' or removing it}}
740740
}
741741
}
742+
743+
// Closures wrapped in a pack expansion
744+
do {
745+
func takesClosure<T>(_ fn: () -> T) -> T { return fn() }
746+
747+
func testClosure<each T>(_ t: repeat each T) -> (repeat each T) {
748+
(repeat takesClosure { each t }) // Ok
749+
}
750+
751+
// FIXME: multi-statement closures should type-check.
752+
func testMultiStmtClosure<each T>(_ t: repeat each T) -> (repeat each T) {
753+
(repeat takesClosure {
754+
// expected-error@-1 {{pack expansion requires that '_' and 'each T' have the same shape}}
755+
let v = each t
756+
return v
757+
})
758+
}
759+
760+
func takesAutoclosure<T>(_ fn: @autoclosure () -> T) -> T { return fn() }
761+
762+
func f2<each T>(_ t: repeat each T) -> (repeat each T) {
763+
(repeat takesAutoclosure(each t)) // Ok
764+
}
765+
}

0 commit comments

Comments
 (0)