Skip to content

Commit 7757c34

Browse files
authored
Merge pull request #73348 from slavapestov/pack-expansion-closures-part-1
Preliminary steps towards support for closures that capture pack element environments
2 parents 7da91bd + 865b155 commit 7757c34

17 files changed

+270
-150
lines changed

include/swift/AST/AnyFunctionRef.h

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,6 @@ class AnyFunctionRef {
7575
return TheFunction.get<AbstractClosureExpr *>()->getCaptureInfo();
7676
}
7777

78-
79-
bool hasType() const {
80-
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>())
81-
return AFD->hasInterfaceType();
82-
return !TheFunction.get<AbstractClosureExpr *>()->getType().isNull();
83-
}
84-
8578
ParameterList *getParameters() const {
8679
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>())
8780
return AFD->getParameters();
@@ -174,20 +167,8 @@ class AnyFunctionRef {
174167
return TheFunction.dyn_cast<AbstractClosureExpr*>();
175168
}
176169

177-
/// Return true if this closure is passed as an argument to a function and is
178-
/// known not to escape from that function. In this case, captures can be
179-
/// more efficient.
180-
bool isKnownNoEscape() const {
181-
if (hasType() && !getType()->hasError())
182-
return getType()->castTo<AnyFunctionType>()->isNoEscape();
183-
return false;
184-
}
185-
186170
/// Whether this function is @Sendable.
187171
bool isSendable() const {
188-
if (!hasType())
189-
return false;
190-
191172
if (auto *fnType = getType()->getAs<AnyFunctionType>())
192173
return fnType->isSendable();
193174

include/swift/AST/CaptureInfo.h

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class ValueDecl;
4343
class FuncDecl;
4444
class OpaqueValueExpr;
4545
class VarDecl;
46+
class GenericEnvironment;
4647

4748
/// CapturedValue includes both the declaration being captured, along with flags
4849
/// that indicate how it is captured.
@@ -140,19 +141,27 @@ class DynamicSelfType;
140141
/// Stores information about captured variables.
141142
class CaptureInfo {
142143
class CaptureInfoStorage final
143-
: public llvm::TrailingObjects<CaptureInfoStorage, CapturedValue> {
144+
: public llvm::TrailingObjects<CaptureInfoStorage,
145+
CapturedValue,
146+
GenericEnvironment *> {
144147

145148
DynamicSelfType *DynamicSelf;
146149
OpaqueValueExpr *OpaqueValue;
147-
unsigned Count;
150+
unsigned NumCapturedValues;
151+
unsigned NumGenericEnvironments;
152+
148153
public:
149-
explicit CaptureInfoStorage(unsigned count, DynamicSelfType *dynamicSelf,
150-
OpaqueValueExpr *opaqueValue)
151-
: DynamicSelf(dynamicSelf), OpaqueValue(opaqueValue), Count(count) { }
154+
explicit CaptureInfoStorage(DynamicSelfType *dynamicSelf,
155+
OpaqueValueExpr *opaqueValue,
156+
unsigned numCapturedValues,
157+
unsigned numGenericEnvironments)
158+
: DynamicSelf(dynamicSelf), OpaqueValue(opaqueValue),
159+
NumCapturedValues(numCapturedValues),
160+
NumGenericEnvironments(numGenericEnvironments) { }
152161

153-
ArrayRef<CapturedValue> getCaptures() const {
154-
return llvm::ArrayRef(this->getTrailingObjects<CapturedValue>(), Count);
155-
}
162+
ArrayRef<CapturedValue> getCaptures() const;
163+
164+
ArrayRef<GenericEnvironment *> getGenericEnvironments() const;
156165

157166
DynamicSelfType *getDynamicSelfType() const {
158167
return DynamicSelf;
@@ -161,6 +170,10 @@ class CaptureInfo {
161170
OpaqueValueExpr *getOpaqueValue() const {
162171
return OpaqueValue;
163172
}
173+
174+
unsigned numTrailingObjects(OverloadToken<CapturedValue>) const {
175+
return NumCapturedValues;
176+
}
164177
};
165178

166179
enum class Flags : unsigned {
@@ -173,9 +186,11 @@ class CaptureInfo {
173186
public:
174187
/// The default-constructed CaptureInfo is "not yet computed".
175188
CaptureInfo() = default;
176-
CaptureInfo(ASTContext &ctx, ArrayRef<CapturedValue> captures,
189+
CaptureInfo(ASTContext &ctx,
190+
ArrayRef<CapturedValue> captures,
177191
DynamicSelfType *dynamicSelf, OpaqueValueExpr *opaqueValue,
178-
bool genericParamCaptures);
192+
bool genericParamCaptures,
193+
ArrayRef<GenericEnvironment *> genericEnv=ArrayRef<GenericEnvironment*>());
179194

180195
/// A CaptureInfo representing no captures at all.
181196
static CaptureInfo empty();
@@ -190,12 +205,20 @@ class CaptureInfo {
190205
!hasDynamicSelfCapture() && !hasOpaqueValueCapture();
191206
}
192207

208+
/// Returns all captured values and opaque expressions.
193209
ArrayRef<CapturedValue> getCaptures() const {
194210
assert(hasBeenComputed());
195211
return StorageAndFlags.getPointer()->getCaptures();
196212
}
197213

198-
/// \returns true if the function captures any generic type parameters.
214+
/// Returns all captured pack element environments.
215+
ArrayRef<GenericEnvironment *> getGenericEnvironments() const {
216+
assert(hasBeenComputed());
217+
return StorageAndFlags.getPointer()->getGenericEnvironments();
218+
}
219+
220+
/// \returns true if the function captures the primary generic environment
221+
/// from its innermost declaration context.
199222
bool hasGenericParamCaptures() const {
200223
assert(hasBeenComputed());
201224
return StorageAndFlags.getInt().contains(Flags::HasGenericParamCaptures);

include/swift/Sema/ConstraintSystem.h

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

2232+
/// Maps closures and local functions to the pack expansion expressions they
2233+
/// capture.
2234+
llvm::MapVector<AnyFunctionRef, SmallVector<PackExpansionExpr *, 1>> CapturedExpansions;
2235+
22322236
/// Maps expressions for implied results (e.g implicit 'then' statements,
22332237
/// implicit 'return' statements in single expression body closures) to their
22342238
/// result kind.
@@ -3164,6 +3168,19 @@ class ConstraintSystem {
31643168
return nullptr;
31653169
}
31663170

3171+
SmallVector<PackExpansionExpr *, 1> getCapturedExpansions(AnyFunctionRef func) const {
3172+
auto result = CapturedExpansions.find(func);
3173+
if (result == CapturedExpansions.end())
3174+
return {};
3175+
3176+
return result->second;
3177+
}
3178+
3179+
void setCapturedExpansions(AnyFunctionRef func, SmallVector<PackExpansionExpr *, 1> exprs) {
3180+
assert(CapturedExpansions.count(func) == 0 && "Cannot reset captured expansions");
3181+
CapturedExpansions.insert({func, exprs});
3182+
}
3183+
31673184
TypeVariableType *getKeyPathValueType(const KeyPathExpr *keyPath) const {
31683185
auto result = getKeyPathValueTypeIfAvailable(keyPath);
31693186
assert(result);

lib/AST/ASTVerifier.cpp

Lines changed: 53 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -198,20 +198,24 @@ class Verifier : public ASTWalker {
198198
using ScopeLike = llvm::PointerUnion<DeclContext *, BraceStmt *>;
199199
SmallVector<ScopeLike, 4> Scopes;
200200

201-
/// The stack of generic contexts.
202-
using GenericLike = llvm::PointerUnion<DeclContext *, GenericEnvironment *>;
203-
SmallVector<GenericLike, 2> Generics;
201+
/// The stack of declaration contexts we're visiting. The primary
202+
/// archetypes from the innermost generic environment are in scope.
203+
SmallVector<DeclContext *, 2> Generics;
204+
205+
/// The set of all opened existential and opened pack element generic
206+
/// environments that are currently in scope.
207+
llvm::DenseSet<GenericEnvironment *> LocalGenerics;
208+
209+
/// We track the pack expansion expressions in ForEachStmts, because
210+
/// their local generics remain in scope until the end of the statement.
211+
llvm::DenseSet<PackExpansionExpr *> ForEachPatternSequences;
204212

205213
/// The stack of optional evaluations active at this point.
206214
SmallVector<OptionalEvaluationExpr *, 4> OptionalEvaluations;
207215

208216
/// The set of opaque value expressions active at this point.
209217
llvm::DenseMap<OpaqueValueExpr *, unsigned> OpaqueValues;
210218

211-
/// The set of opened existential archetypes that are currently
212-
/// active.
213-
llvm::DenseSet<OpenedArchetypeType *> OpenedExistentialArchetypes;
214-
215219
/// The set of inout to pointer expr that match the following pattern:
216220
///
217221
/// (call-expr
@@ -632,11 +636,10 @@ class Verifier : public ASTWalker {
632636

633637
bool foundError = type->getCanonicalType().findIf([&](Type type) -> bool {
634638
if (auto archetype = type->getAs<ArchetypeType>()) {
635-
auto root = archetype->getRoot();
636639

637640
// Opaque archetypes are globally available. We don't need to check
638641
// them here.
639-
if (isa<OpaqueTypeArchetypeType>(root))
642+
if (isa<OpaqueTypeArchetypeType>(archetype))
640643
return false;
641644

642645
// Only visit each archetype once.
@@ -645,11 +648,10 @@ class Verifier : public ASTWalker {
645648

646649
// We should know about archetypes corresponding to opened
647650
// existential archetypes.
648-
if (auto opened = dyn_cast<OpenedArchetypeType>(root)) {
649-
if (OpenedExistentialArchetypes.count(opened) == 0) {
650-
Out << "Found opened existential archetype "
651-
<< root->getString()
652-
<< " outside enclosing OpenExistentialExpr\n";
651+
if (isa<LocalArchetypeType>(archetype)) {
652+
if (LocalGenerics.count(archetype->getGenericEnvironment()) == 0) {
653+
Out << "Found local archetype " << archetype
654+
<< " outside its defining scope\n";
653655
return true;
654656
}
655657

@@ -659,34 +661,19 @@ class Verifier : public ASTWalker {
659661
// Otherwise, the archetype needs to be from this scope.
660662
if (Generics.empty() || !Generics.back()) {
661663
Out << "AST verification error: archetype outside of generic "
662-
"context: " << root->getString() << "\n";
664+
"context: " << archetype << "\n";
663665
return true;
664666
}
665667

666668
// Get the archetype's generic signature.
667-
GenericEnvironment *archetypeEnv = root->getGenericEnvironment();
669+
GenericEnvironment *archetypeEnv = archetype->getGenericEnvironment();
668670
auto archetypeSig = archetypeEnv->getGenericSignature();
669671

670672
auto genericCtx = Generics.back();
671-
GenericSignature genericSig;
672-
if (auto *genericDC = genericCtx.dyn_cast<DeclContext *>()) {
673-
genericSig = genericDC->getGenericSignatureOfContext();
674-
} else {
675-
auto *genericEnv = genericCtx.get<GenericEnvironment *>();
676-
genericSig = genericEnv->getGenericSignature();
677-
678-
// Check whether this archetype is a substitution from the
679-
// outer generic context of an opened element environment.
680-
if (genericEnv->getKind() == GenericEnvironment::Kind::OpenedElement) {
681-
auto contextSubs = genericEnv->getPackElementContextSubstitutions();
682-
QuerySubstitutionMap isInContext{contextSubs};
683-
if (isInContext(root->getInterfaceType()->castTo<GenericTypeParamType>()))
684-
return false;
685-
}
686-
}
673+
GenericSignature genericSig = genericCtx->getGenericSignatureOfContext();
687674

688675
if (genericSig.getPointer() != archetypeSig.getPointer()) {
689-
Out << "Archetype " << root->getString() << " not allowed "
676+
Out << "Archetype " << archetype->getString() << " not allowed "
690677
<< "in this context\n";
691678
Out << "Archetype generic signature: "
692679
<< archetypeSig->getAsString() << "\n";
@@ -735,7 +722,7 @@ class Verifier : public ASTWalker {
735722
}
736723
void popScope(DeclContext *scope) {
737724
assert(Scopes.back().get<DeclContext*>() == scope);
738-
assert(Generics.back().get<DeclContext*>() == scope);
725+
assert(Generics.back() == scope);
739726
Scopes.pop_back();
740727
Generics.pop_back();
741728
}
@@ -808,6 +795,9 @@ class Verifier : public ASTWalker {
808795
if (!shouldVerify(expansion)) {
809796
return false;
810797
}
798+
799+
assert(ForEachPatternSequences.count(expansion) == 0);
800+
ForEachPatternSequences.insert(expansion);
811801
}
812802

813803
if (!S->getElementExpr())
@@ -821,6 +811,10 @@ class Verifier : public ASTWalker {
821811
void cleanup(ForEachStmt *S) {
822812
if (auto *expansion =
823813
dyn_cast<PackExpansionExpr>(S->getParsedSequence())) {
814+
assert(ForEachPatternSequences.count(expansion) != 0);
815+
ForEachPatternSequences.erase(expansion);
816+
817+
// Clean up for real.
824818
cleanup(expansion);
825819
}
826820

@@ -851,6 +845,16 @@ class Verifier : public ASTWalker {
851845
OpaqueValues.erase(expr->getInterpolationExpr());
852846
}
853847

848+
void pushLocalGenerics(GenericEnvironment *env) {
849+
assert(LocalGenerics.count(env)==0);
850+
LocalGenerics.insert(env);
851+
}
852+
853+
void popLocalGenerics(GenericEnvironment *env) {
854+
assert(LocalGenerics.count(env)==1);
855+
LocalGenerics.erase(env);
856+
}
857+
854858
bool shouldVerify(OpenExistentialExpr *expr) {
855859
if (!shouldVerify(cast<Expr>(expr)))
856860
return false;
@@ -862,8 +866,8 @@ class Verifier : public ASTWalker {
862866

863867
assert(!OpaqueValues.count(expr->getOpaqueValue()));
864868
OpaqueValues[expr->getOpaqueValue()] = 0;
865-
assert(OpenedExistentialArchetypes.count(expr->getOpenedArchetype())==0);
866-
OpenedExistentialArchetypes.insert(expr->getOpenedArchetype());
869+
870+
pushLocalGenerics(expr->getOpenedArchetype()->getGenericEnvironment());
867871
return true;
868872
}
869873

@@ -875,22 +879,28 @@ class Verifier : public ASTWalker {
875879

876880
assert(OpaqueValues.count(expr->getOpaqueValue()));
877881
OpaqueValues.erase(expr->getOpaqueValue());
878-
assert(OpenedExistentialArchetypes.count(expr->getOpenedArchetype())==1);
879-
OpenedExistentialArchetypes.erase(expr->getOpenedArchetype());
882+
883+
popLocalGenerics(expr->getOpenedArchetype()->getGenericEnvironment());
880884
}
881885

882886
bool shouldVerify(PackExpansionExpr *expr) {
883887
if (!shouldVerify(cast<Expr>(expr)))
884888
return false;
885889

886-
Generics.push_back(expr->getGenericEnvironment());
890+
// Don't push local generics again when we visit the expr inside
891+
// the ForEachStmt.
892+
if (auto *genericEnv = expr->getGenericEnvironment())
893+
if (ForEachPatternSequences.count(expr) == 0)
894+
pushLocalGenerics(genericEnv);
887895
return true;
888896
}
889897

890-
void cleanup(PackExpansionExpr *E) {
891-
assert(Generics.back().get<GenericEnvironment *>() ==
892-
E->getGenericEnvironment());
893-
Generics.pop_back();
898+
void cleanup(PackExpansionExpr *expr) {
899+
// If this is a pack iteration pattern, don't pop local generics
900+
// until we exit the ForEachStmt.
901+
if (auto *genericEnv = expr->getGenericEnvironment())
902+
if (ForEachPatternSequences.count(expr) == 0)
903+
popLocalGenerics(genericEnv);
894904
}
895905

896906
bool shouldVerify(MakeTemporarilyEscapableExpr *expr) {

0 commit comments

Comments
 (0)