Skip to content

Commit 531dd3a

Browse files
authored
Merge pull request #64420 from rjmccall/silgen-variadic-abstraction-changes
Improve how we work with pack-expansion abstraction patterns in SILGen
2 parents 8ddbc68 + f3e7daf commit 531dd3a

12 files changed

+635
-422
lines changed

include/swift/AST/GenericEnvironment.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,12 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
129129
/// generic signature.
130130
ArrayRef<Type> getContextTypes() const;
131131

132+
/// Retrieve the array of opened pack parameters for this opened-element
133+
/// environment. This is parallel to the array of element parameters,
134+
/// i.e. the innermost generic context.
135+
MutableArrayRef<Type> getOpenedPackParams();
136+
ArrayRef<Type> getOpenedPackParams() const;
137+
132138
/// Get the nested type storage, allocating it if required.
133139
NestedTypeStorage &getOrCreateNestedTypeStorage();
134140

@@ -201,6 +207,9 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
201207
/// Retrieve the UUID for an opened element environment.
202208
UUID getOpenedElementUUID() const;
203209

210+
/// Return the number of opened pack parameters.
211+
unsigned getNumOpenedPackParams() const;
212+
204213
void forEachPackElementArchetype(
205214
llvm::function_ref<void(ElementArchetypeType*)> function) const;
206215

@@ -285,10 +294,26 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
285294

286295
/// Map a contextual type containing parameter packs to a contextual
287296
/// type in the opened element generic context.
297+
///
298+
/// This operation only makes sense if the generic environment that the
299+
/// pack archetypes are contextual in matches the generic signature
300+
/// of this environment. That will be true for opened element
301+
/// environments coming straight out of the type checker, such as
302+
/// the one in a PackExpansionExpr, or opened element environments
303+
/// created directly from the current environment. It is not
304+
/// reliable for opened element environments in arbitrary SIL functions.
288305
Type mapContextualPackTypeIntoElementContext(Type type) const;
289306

290307
/// Map a contextual type containing parameter packs to a contextual
291308
/// type in the opened element generic context.
309+
///
310+
/// This operation only makes sense if the generic environment that the
311+
/// pack archetypes are contextual in matches the generic signature
312+
/// of this environment. That will be true for opened element
313+
/// environments coming straight out of the type checker, such as
314+
/// the one in a PackExpansionExpr, or opened element environments
315+
/// created directly from the current environment. It is not
316+
/// reliable for opened element environments in arbitrary SIL functions.
292317
CanType mapContextualPackTypeIntoElementContext(CanType type) const;
293318

294319
/// Map a type containing pack element type parameters to a contextual

include/swift/SIL/AbstractionPattern.h

Lines changed: 82 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -913,6 +913,9 @@ class AbstractionPattern {
913913
bool hasCachingKey() const {
914914
// Only the simplest Kind::Type pattern has a caching key; we
915915
// don't want to try to unique by Clang node.
916+
//
917+
// Even if we support Clang nodes someday, we *cannot* cache
918+
// by the open-coded patterns like Tuple and PackExpansion.
916919
return getKind() == Kind::Type || getKind() == Kind::Opaque
917920
|| getKind() == Kind::Discard;
918921
}
@@ -1216,9 +1219,7 @@ class AbstractionPattern {
12161219
case Kind::Invalid:
12171220
llvm_unreachable("querying invalid abstraction pattern!");
12181221
case Kind::Opaque:
1219-
return typename CanTypeWrapperTraits<TYPE>::type();
12201222
case Kind::Tuple:
1221-
return typename CanTypeWrapperTraits<TYPE>::type();
12221223
case Kind::OpaqueFunction:
12231224
case Kind::OpaqueDerivativeFunction:
12241225
return typename CanTypeWrapperTraits<TYPE>::type();
@@ -1275,7 +1276,7 @@ class AbstractionPattern {
12751276

12761277
/// Is the given tuple type a valid substitution of this abstraction
12771278
/// pattern?
1278-
bool matchesTuple(CanTupleType substType);
1279+
bool matchesTuple(CanTupleType substType) const;
12791280

12801281
bool isTuple() const {
12811282
switch (getKind()) {
@@ -1346,6 +1347,40 @@ class AbstractionPattern {
13461347
return { { this, 0 }, { this, getNumTupleElements() } };
13471348
}
13481349

1350+
/// Perform a parallel visitation of the elements of a tuple type,
1351+
/// preserving structure about where pack expansions appear in the
1352+
/// original type and how many elements of the substituted type they
1353+
/// expand to.
1354+
///
1355+
/// This pattern must be a tuple pattern.
1356+
///
1357+
/// Calls handleScalar or handleExpansion as appropriate for each
1358+
/// element of the original tuple, in order.
1359+
void forEachTupleElement(CanTupleType substType,
1360+
llvm::function_ref<void(unsigned origEltIndex,
1361+
unsigned substEltIndex,
1362+
AbstractionPattern origEltType,
1363+
CanType substEltType)>
1364+
handleScalar,
1365+
llvm::function_ref<void(unsigned origEltIndex,
1366+
unsigned substEltIndex,
1367+
AbstractionPattern origExpansionType,
1368+
CanTupleEltTypeArrayRef substEltTypes)>
1369+
handleExpansion) const;
1370+
1371+
/// Perform a parallel visitation of the elements of a tuple type,
1372+
/// expanding the elements of the type. This preserves the structure
1373+
/// of the *substituted* tuple type: it will be called once per element
1374+
/// of the substituted type, in order. The original element trappings
1375+
/// are also provided for convenience.
1376+
///
1377+
/// This pattern must match the substituted type, but it may be an
1378+
/// opaque pattern.
1379+
void forEachExpandedTupleElement(CanTupleType substType,
1380+
llvm::function_ref<void(AbstractionPattern origEltType,
1381+
CanType substEltType,
1382+
const TupleTypeElt &elt)> handleElement) const;
1383+
13491384
/// Is the given pack type a valid substitution of this abstraction
13501385
/// pattern?
13511386
bool matchesPack(CanPackType substType);
@@ -1420,13 +1455,20 @@ class AbstractionPattern {
14201455
/// the abstraction pattern for an element type.
14211456
AbstractionPattern getPackElementType(unsigned index) const;
14221457

1423-
/// Give that the value being abstracted is a pack expansion type, return the
1424-
/// underlying pattern type.
1458+
/// Given that the value being abstracted is a pack expansion type,
1459+
/// return the underlying pattern type.
1460+
///
1461+
/// If you're looking for getPackExpansionCountType(), it deliberately
1462+
/// does not exist. Count types are not lowered types, and the original
1463+
/// count types are not relevant to lowering. Only the substituted
1464+
/// components and expansion counts are significant.
14251465
AbstractionPattern getPackExpansionPatternType() const;
14261466

1427-
/// Give that the value being abstracted is a pack expansion type, return the
1428-
/// underlying count type.
1429-
AbstractionPattern getPackExpansionCountType() const;
1467+
/// Given that the value being abstracted is a pack expansion type,
1468+
/// return the appropriate pattern type for the given expansion
1469+
/// component.
1470+
AbstractionPattern getPackExpansionComponentType(CanType substType) const;
1471+
AbstractionPattern getPackExpansionComponentType(bool isExpansion) const;
14301472

14311473
/// Given that the value being abstracted is a function, return the
14321474
/// abstraction pattern for its result type.
@@ -1446,6 +1488,30 @@ class AbstractionPattern {
14461488
/// parameters in the pattern.
14471489
unsigned getNumFunctionParams() const;
14481490

1491+
/// Perform a parallel visitation of the parameters of a function.
1492+
///
1493+
/// If this is a function pattern, calls handleScalar or
1494+
/// handleExpansion as appropriate for each parameter of the
1495+
/// original function, in order.
1496+
///
1497+
/// If this is not a function pattern, calls handleScalar for each
1498+
/// parameter of the substituted function type. Functions with
1499+
/// pack expansions cannot be abstracted legally this way.
1500+
void forEachFunctionParam(AnyFunctionType::CanParamArrayRef substParams,
1501+
bool ignoreFinalParam,
1502+
llvm::function_ref<void(unsigned origParamIndex,
1503+
unsigned substParamIndex,
1504+
ParameterTypeFlags origFlags,
1505+
AbstractionPattern origParamType,
1506+
AnyFunctionType::CanParam substParam)>
1507+
handleScalar,
1508+
llvm::function_ref<void(unsigned origParamIndex,
1509+
unsigned substParamIndex,
1510+
ParameterTypeFlags origFlags,
1511+
AbstractionPattern origExpansionType,
1512+
AnyFunctionType::CanParamArrayRef substParams)>
1513+
handleExpansion) const;
1514+
14491515
/// Given that the value being abstracted is optional, return the
14501516
/// abstraction pattern for its object type.
14511517
AbstractionPattern getOptionalObjectType() const;
@@ -1477,16 +1543,14 @@ class AbstractionPattern {
14771543
AbstractionPattern getObjCMethodAsyncCompletionHandlerType(
14781544
CanType swiftCompletionHandlerType) const;
14791545

1480-
/// Given that this is a pack expansion, invoke the given callback for
1481-
/// each component of the substituted expansion of this pattern. The
1482-
/// pattern will be for a pack expansion type over a contextual type if
1483-
/// the substituted component is still a pack expansion. If there aren't
1484-
/// substitutions available, this will just invoke the callback with the
1485-
/// component.
1486-
void forEachPackExpandedComponent(
1487-
llvm::function_ref<void(AbstractionPattern pattern)> fn) const;
1488-
1489-
SmallVector<AbstractionPattern, 4> getPackExpandedComponents() const;
1546+
/// Given that this is a pack expansion, return the number of components
1547+
/// that it should expand to. This, and the general correctness of
1548+
/// traversing variadically generic tuple and function types under
1549+
/// substitution, relies on substitutions having been set properly
1550+
/// on the abstraction pattern; without that, AbstractionPattern assumes
1551+
/// that every component expands to a single pack expansion component,
1552+
/// which will generally only work in specific situations.
1553+
size_t getNumPackExpandedComponents() const;
14901554

14911555
/// If this pattern refers to a foreign ObjC method that was imported as
14921556
/// async, return the bridged-back-to-ObjC completion handler type.

lib/AST/ASTContext.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5164,10 +5164,12 @@ GenericEnvironment::forOpenedElement(GenericSignature signature,
51645164

51655165
// Allocate and construct the new environment.
51665166
unsigned numGenericParams = signature.getGenericParams().size();
5167+
unsigned numOpenedParams = signature.getInnermostGenericParams().size();
51675168
size_t bytes = totalSizeToAlloc<OpaqueEnvironmentData,
51685169
OpenedExistentialEnvironmentData,
5169-
OpenedElementEnvironmentData, Type>(
5170-
0, 0, 1, numGenericParams);
5170+
OpenedElementEnvironmentData,
5171+
Type>(
5172+
0, 0, 1, numGenericParams + numOpenedParams);
51715173
void *mem = ctx.Allocate(bytes, alignof(GenericEnvironment));
51725174
auto *genericEnv = new (mem) GenericEnvironment(signature,
51735175
uuid, shapeClass,

0 commit comments

Comments
 (0)