Skip to content

Commit fd42745

Browse files
authored
Merge pull request #73849 from xedin/collect-closures-to-pack-expansion-they-appear-in
[ConstraintSystem] Fix type-checking of closures in pack expansion contexts
2 parents 653372a + bc3b274 commit fd42745

File tree

4 files changed

+51
-0
lines changed

4 files changed

+51
-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

lib/Sema/CSSyntacticElement.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,17 @@ class TypeVariableRefFinder : public ASTWalker {
153153
}
154154
}
155155

156+
// If closure appears inside of a pack expansion, the elements
157+
// that reference pack elements have to bring expansion's shape
158+
// type in scope to make sure that the shapes match.
159+
if (auto *packElement = getAsExpr<PackElementExpr>(expr)) {
160+
if (auto *outerEnvironment = CS.getPackEnvironment(packElement)) {
161+
auto *expansionTy = CS.simplifyType(CS.getType(outerEnvironment))
162+
->castTo<PackExpansionType>();
163+
expansionTy->getCountType()->getTypeVariables(ReferencedVars);
164+
}
165+
}
166+
156167
return Action::Continue(expr);
157168
}
158169

test/Constraints/pack-expansion-expressions.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -739,3 +739,25 @@ 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+
func testMultiStmtClosure<each T>(_ t: repeat each T) -> (repeat each T) {
752+
(repeat takesClosure {
753+
let v = each t
754+
return v
755+
}) // Ok
756+
}
757+
758+
func takesAutoclosure<T>(_ fn: @autoclosure () -> T) -> T { return fn() }
759+
760+
func f2<each T>(_ t: repeat each T) -> (repeat each T) {
761+
(repeat takesAutoclosure(each t)) // Ok
762+
}
763+
}

0 commit comments

Comments
 (0)