Skip to content

Commit 8c230de

Browse files
authored
Merge pull request #73541 from slavapestov/pack-expansion-closures-6.0
[6.0] Support closures that capture opened pack element types
2 parents 2e7e483 + 4c36819 commit 8c230de

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1353
-303
lines changed

include/swift/AST/ASTMangler.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,8 @@ class ASTMangler : public Mangler {
657657
void appendClosureEntity(const AbstractClosureExpr *closure);
658658

659659
void appendClosureComponents(Type Ty, unsigned discriminator, bool isImplicit,
660-
const DeclContext *parentContext);
660+
const DeclContext *parentContext,
661+
ArrayRef<GenericEnvironment *> capturedEnvs);
661662

662663
void appendDefaultArgumentEntity(const DeclContext *ctx, unsigned index);
663664

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();
@@ -189,6 +204,7 @@ class CaptureInfo {
189204
!hasDynamicSelfCapture() && !hasOpaqueValueCapture();
190205
}
191206

207+
/// Returns all captured values and opaque expressions.
192208
ArrayRef<CapturedValue> getCaptures() const {
193209
// FIXME: Ideally, everywhere that synthesizes a function should include
194210
// its capture info.
@@ -206,7 +222,14 @@ class CaptureInfo {
206222
/// \returns true if getLocalCaptures() will return a non-empty list.
207223
bool hasLocalCaptures() const;
208224

209-
/// \returns true if the function captures any generic type parameters.
225+
/// Returns all captured pack element environments.
226+
ArrayRef<GenericEnvironment *> getGenericEnvironments() const {
227+
assert(hasBeenComputed());
228+
return StorageAndFlags.getPointer()->getGenericEnvironments();
229+
}
230+
231+
/// \returns true if the function captures the primary generic environment
232+
/// from its innermost declaration context.
210233
bool hasGenericParamCaptures() const {
211234
// FIXME: Ideally, everywhere that synthesizes a function should include
212235
// its capture info.

include/swift/AST/Decl.h

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6053,10 +6053,6 @@ enum class PropertyWrapperSynthesizedPropertyKind {
60536053
class VarDecl : public AbstractStorageDecl {
60546054
friend class NamingPatternRequest;
60556055
NamedPattern *NamingPattern = nullptr;
6056-
/// When the variable is declared in context of a for-in loop over the elements of
6057-
/// a parameter pack, this is the opened element environment of the pack expansion
6058-
/// to use as the variable's context generic environment.
6059-
GenericEnvironment *OpenedElementEnvironment = nullptr;
60606056

60616057
public:
60626058
enum class Introducer : uint8_t {
@@ -6195,13 +6191,6 @@ class VarDecl : public AbstractStorageDecl {
61956191
NamedPattern *getNamingPattern() const;
61966192
void setNamingPattern(NamedPattern *Pat);
61976193

6198-
GenericEnvironment *getOpenedElementEnvironment() const {
6199-
return OpenedElementEnvironment;
6200-
}
6201-
void setOpenedElementEnvironment(GenericEnvironment *Env) {
6202-
OpenedElementEnvironment = Env;
6203-
}
6204-
62056194
/// If this is a VarDecl that does not belong to a CaseLabelItem's pattern,
62066195
/// return this. Otherwise, this VarDecl must belong to a CaseStmt's
62076196
/// CaseLabelItem. In that case, return the first case label item of the first

include/swift/AST/GenericSignature.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,11 @@ class GenericSignature {
197197
/// array of the generic parameters for the innermost generic type.
198198
ArrayRef<GenericTypeParamType *> getInnermostGenericParams() const;
199199

200+
/// Returns the depth that a generic parameter at the next level of
201+
/// nesting would have. This is zero for the empty signature,
202+
/// and one plus the depth of the final generic parameter otherwise.
203+
unsigned getNextDepth() const;
204+
200205
/// Retrieve the requirements.
201206
ArrayRef<Requirement> getRequirements() const;
202207

@@ -307,6 +312,9 @@ class alignas(1 << TypeAlignInBits) GenericSignatureImpl final
307312
return Mem;
308313
}
309314

315+
/// Returns the depth of the last generic parameter.
316+
unsigned getMaxDepth() const;
317+
310318
/// Transform the requirements into a form where implicit Copyable and
311319
/// Escapable conformances are omitted, and their absence is explicitly
312320
/// noted.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
//===--- LocalArchetypeRequirementCollector.h -------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file has utility code for extending a generic signature with opened
14+
// existentials and shape classes.
15+
//
16+
//===----------------------------------------------------------------------===//
17+
18+
#ifndef SWIFT_AST_LOCAL_ARCHETYPE_REQUIREMENT_COLLECTOR_H
19+
#define SWIFT_AST_LOCAL_ARCHETYPE_REQUIREMENT_COLLECTOR_H
20+
21+
#include "swift/AST/ASTContext.h"
22+
#include "swift/AST/GenericSignature.h"
23+
#include "swift/AST/Requirement.h"
24+
#include "swift/AST/Types.h"
25+
26+
namespace swift {
27+
28+
struct LocalArchetypeRequirementCollector {
29+
const ASTContext &Context;
30+
GenericSignature OuterSig;
31+
unsigned Depth;
32+
33+
/// The lists of new parameters and requirements to add to the signature.
34+
SmallVector<GenericTypeParamType *, 2> Params;
35+
SmallVector<Requirement, 2> Requirements;
36+
37+
LocalArchetypeRequirementCollector(const ASTContext &ctx, GenericSignature sig);
38+
39+
void addOpenedExistential(Type constraint);
40+
void addOpenedElement(CanGenericTypeParamType shapeClass);
41+
42+
GenericTypeParamType *addParameter();
43+
};
44+
45+
struct MapLocalArchetypesOutOfContext {
46+
GenericSignature baseGenericSig;
47+
ArrayRef<GenericEnvironment *> capturedEnvs;
48+
49+
MapLocalArchetypesOutOfContext(GenericSignature baseGenericSig,
50+
ArrayRef<GenericEnvironment *> capturedEnvs)
51+
: baseGenericSig(baseGenericSig), capturedEnvs(capturedEnvs) {}
52+
53+
Type operator()(SubstitutableType *type) const;
54+
};
55+
56+
struct MapIntoLocalArchetypeContext {
57+
GenericEnvironment *baseGenericEnv;
58+
ArrayRef<GenericEnvironment *> capturedEnvs;
59+
60+
MapIntoLocalArchetypeContext(GenericEnvironment *baseGenericEnv,
61+
ArrayRef<GenericEnvironment *> capturedEnvs)
62+
: baseGenericEnv(baseGenericEnv), capturedEnvs(capturedEnvs) {}
63+
64+
Type operator()(SubstitutableType *type) const;
65+
};
66+
67+
GenericSignature buildGenericSignatureWithCapturedEnvironments(
68+
ASTContext &ctx,
69+
GenericSignature sig,
70+
ArrayRef<GenericEnvironment *> capturedEnvs);
71+
72+
SubstitutionMap buildSubstitutionMapWithCapturedEnvironments(
73+
SubstitutionMap baseSubMap,
74+
GenericSignature genericSigWithCaptures,
75+
ArrayRef<GenericEnvironment *> capturedEnvs);
76+
77+
}
78+
79+
#endif // SWIFT_AST_LOCAL_ARCHETYPE_REQUIREMENT_COLLECTOR_H

include/swift/AST/Types.h

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,9 @@ class RecursiveTypeProperties {
128128
/// This type expression contains a TypeVariableType.
129129
HasTypeVariable = 0x01,
130130

131-
/// This type expression contains a context-dependent archetype, either a
132-
/// \c PrimaryArchetypeType, \c OpenedArchetypeType,
133-
/// \c ElementArchetypeType, or \c PackArchetype.
134-
HasArchetype = 0x02,
131+
/// This type expression contains a PrimaryArchetypeType
132+
/// or PackArchetypeType.
133+
HasPrimaryArchetype = 0x02,
135134

136135
/// This type expression contains a GenericTypeParamType.
137136
HasTypeParameter = 0x04,
@@ -171,7 +170,7 @@ class RecursiveTypeProperties {
171170
/// This type contains a parameterized existential type \c any P<T>.
172171
HasParameterizedExistential = 0x2000,
173172

174-
/// This type contains an ElementArchetype.
173+
/// This type contains an ElementArchetypeType.
175174
HasElementArchetype = 0x4000,
176175

177176
/// Whether the type is allocated in the constraint solver arena. This can
@@ -183,7 +182,7 @@ class RecursiveTypeProperties {
183182
/// Contains a PackType.
184183
HasPack = 0x10000,
185184

186-
/// Contains a PackArchetypeType.
185+
/// Contains a PackArchetypeType. Also implies HasPrimaryArchetype.
187186
HasPackArchetype = 0x20000,
188187

189188
Last_Property = HasPackArchetype
@@ -205,9 +204,10 @@ class RecursiveTypeProperties {
205204
/// variable?
206205
bool hasTypeVariable() const { return Bits & HasTypeVariable; }
207206

208-
/// Does a type with these properties structurally contain a
209-
/// context-dependent archetype (that is, a Primary- or OpenedArchetype)?
210-
bool hasArchetype() const { return Bits & HasArchetype; }
207+
/// Does a type with these properties structurally contain a primary
208+
/// or pack archetype? These are the archetypes instantiated from a
209+
/// primary generic environment.
210+
bool hasPrimaryArchetype() const { return Bits & HasPrimaryArchetype; }
211211

212212
/// Does a type with these properties structurally contain an
213213
/// archetype from an opaque type declaration?
@@ -696,9 +696,23 @@ class alignas(1 << TypeAlignInBits) TypeBase
696696
return getRecursiveProperties().hasPlaceholder();
697697
}
698698

699-
/// Determine whether the type involves a context-dependent archetype.
699+
/// Determine whether the type involves a PrimaryArchetypeType *or* a
700+
/// PackArchetypeType. These are the archetypes instantiated from a
701+
/// primary generic environment.
702+
bool hasPrimaryArchetype() const {
703+
return getRecursiveProperties().hasPrimaryArchetype();
704+
}
705+
706+
/// Whether the type contains a PackArchetypeType.
707+
bool hasPackArchetype() const {
708+
return getRecursiveProperties().hasPackArchetype();
709+
}
710+
711+
/// Determine whether the type involves a primary, pack or local archetype.
712+
///
713+
/// FIXME: Replace all remaining callers with a more precise check.
700714
bool hasArchetype() const {
701-
return getRecursiveProperties().hasArchetype();
715+
return hasPrimaryArchetype() || hasLocalArchetype();
702716
}
703717

704718
/// Determine whether the type involves an opened existential archetype.
@@ -727,11 +741,6 @@ class alignas(1 << TypeAlignInBits) TypeBase
727741
return getRecursiveProperties().hasPack();
728742
}
729743

730-
/// Whether the type contains a PackArchetypeType.
731-
bool hasPackArchetype() const {
732-
return getRecursiveProperties().hasPackArchetype();
733-
}
734-
735744
/// Whether the type has any flavor of pack.
736745
bool hasAnyPack() const {
737746
return hasParameterPack() || hasPack() || hasPackArchetype();

include/swift/SIL/SILFunction.h

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,9 @@ class SILFunction
237237
/// The context archetypes of the function.
238238
GenericEnvironment *GenericEnv = nullptr;
239239

240+
/// Captured local generic environments.
241+
ArrayRef<GenericEnvironment *> CapturedEnvs;
242+
240243
/// The information about specialization.
241244
/// Only set if this function is a specialization of another function.
242245
const GenericSpecializationInformation *SpecializationInfo = nullptr;
@@ -1276,8 +1279,22 @@ class SILFunction
12761279
GenericEnvironment *getGenericEnvironment() const {
12771280
return GenericEnv;
12781281
}
1279-
void setGenericEnvironment(GenericEnvironment *env) {
1282+
1283+
/// Return any captured local generic environments, currently used for pack
1284+
/// element environments only. After SILGen, these are rewritten into
1285+
/// primary archetypes.
1286+
ArrayRef<GenericEnvironment *> getCapturedEnvironments() const {
1287+
return CapturedEnvs;
1288+
}
1289+
1290+
void setGenericEnvironment(GenericEnvironment *env);
1291+
1292+
void setGenericEnvironment(GenericEnvironment *env,
1293+
ArrayRef<GenericEnvironment *> capturedEnvs,
1294+
SubstitutionMap forwardingSubs) {
12801295
GenericEnv = env;
1296+
CapturedEnvs = capturedEnvs;
1297+
ForwardingSubMap = forwardingSubs;
12811298
}
12821299

12831300
/// Retrieve the generic signature from the generic environment of this
@@ -1306,9 +1323,30 @@ class SILFunction
13061323
/// responsibility of the caller.
13071324
void eraseAllBlocks();
13081325

1309-
/// Return the identity substitutions necessary to forward this call if it is
1310-
/// generic.
1311-
SubstitutionMap getForwardingSubstitutionMap();
1326+
/// A substitution map that sends the generic parameters of the invocation
1327+
/// generic signature to some combination of primar and local archetypes.
1328+
///
1329+
/// CAUTION: If this is a SILFunction that captures pack element environments,
1330+
/// then at SILGen time, this is not actually the forwarding substitution map
1331+
/// of the SILFunction's generic environment. This is because:
1332+
///
1333+
/// 1) The SILFunction's generic signature includes extra generic parameters,
1334+
/// to model captured pack elements;
1335+
/// 2) The SILFunction's generic environment is the AST generic environment,
1336+
/// so it's based on the original generic signature;
1337+
/// 3) SILGen uses this AST generic environment together with local archetypes
1338+
/// for lowering SIL instructions.
1339+
///
1340+
/// Therefore, the SILFunction's forwarding substitution map takes the extended
1341+
/// generic signature (1). It maps the original generic parameters to the
1342+
/// archetypes of (2), and the extended generic parameters to the local archetypes
1343+
/// of (3).
1344+
///
1345+
/// After SILGen, all archetypes are re-instantiated inside the SIL function,
1346+
/// and the forwarding substitution map and generic environment then align.
1347+
SubstitutionMap getForwardingSubstitutionMap() const {
1348+
return ForwardingSubMap;
1349+
}
13121350

13131351
/// Returns true if this SILFunction must be a defer statement.
13141352
///

include/swift/SIL/SILModule.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,11 @@ class SILModule {
477477
/// This should only be the case during parsing or deserialization.
478478
bool hasUnresolvedLocalArchetypeDefinitions();
479479

480+
/// If we added any instructions that reference unresolved local archetypes
481+
/// and then deleted those instructions without resolving those archetypes,
482+
/// we must reclaim those unresolved local archetypes.
483+
void reclaimUnresolvedLocalArchetypeDefinitions();
484+
480485
/// Get a unique index for a struct or class field in layout order.
481486
///
482487
/// Precondition: \p decl must be a non-resilient struct or class.

0 commit comments

Comments
 (0)