Skip to content

Commit c8100bd

Browse files
authored
Merge pull request #62414 from slavapestov/variadic-metatypes
Allow forming PackExpansionTypes in expression context
2 parents 571671f + 78bddc6 commit c8100bd

File tree

9 files changed

+384
-304
lines changed

9 files changed

+384
-304
lines changed

include/swift/SIL/AbstractionPattern.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,20 @@ class AbstractionPattern {
933933
return false;
934934
}
935935
}
936+
937+
bool isTypeParameterPack() const {
938+
switch (getKind()) {
939+
case Kind::Opaque:
940+
return false;
941+
case Kind::Type:
942+
case Kind::ClangType:
943+
case Kind::Discard: {
944+
return getType()->isParameterPack();
945+
}
946+
default:
947+
return false;
948+
}
949+
}
936950

937951
/// Is this an interface type that is subject to a concrete
938952
/// same-type constraint?

lib/IRGen/GenProto.cpp

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2920,14 +2920,6 @@ void NecessaryBindings::save(IRGenFunction &IGF, Address buffer) const {
29202920
void NecessaryBindings::addTypeMetadata(CanType type) {
29212921
assert(!isa<InOutType>(type));
29222922

2923-
// If the bindings are for an async function, we will always need the type
2924-
// metadata. The opportunities to reconstruct it available in the context of
2925-
// partial apply forwarders are not available here.
2926-
if (forAsyncFunction()) {
2927-
addRequirement({type, nullptr});
2928-
return;
2929-
}
2930-
29312923
// Bindings are only necessary at all if the type is dependent.
29322924
if (!type->hasArchetype())
29332925
return;
@@ -2995,21 +2987,12 @@ void NecessaryBindings::addProtocolConformance(CanType type,
29952987
dyn_cast<SpecializedProtocolConformance>(concreteConformance);
29962988
// The partial apply forwarder does not have the context to reconstruct
29972989
// abstract conditional conformance requirements.
2998-
if (forPartialApply() && specializedConf) {
2990+
if (specializedConf) {
29992991
addAbstractConditionalRequirements(specializedConf);
3000-
} else if (forAsyncFunction()) {
3001-
ProtocolDecl *protocol = conf.getRequirement();
3002-
GenericRequirement requirement;
3003-
requirement.TypeParameter = type;
3004-
requirement.Protocol = protocol;
3005-
std::pair<GenericRequirement, ProtocolConformanceRef> pair{requirement,
3006-
conf};
3007-
Conformances.insert(pair);
3008-
addRequirement({type, concreteConformance->getProtocol()});
30092992
}
30102993
return;
30112994
}
3012-
assert(isa<ArchetypeType>(type) || forAsyncFunction());
2995+
assert(isa<ArchetypeType>(type));
30132996

30142997
// TODO: pass something about the root conformance necessary to
30152998
// reconstruct this.
@@ -3204,29 +3187,20 @@ void EmitPolymorphicArguments::emit(SubstitutionMap subs,
32043187
}
32053188
}
32063189

3207-
NecessaryBindings NecessaryBindings::forAsyncFunctionInvocation(
3208-
IRGenModule &IGM, CanSILFunctionType origType, SubstitutionMap subs) {
3209-
return computeBindings(IGM, origType, subs,
3210-
false /*forPartialApplyForwarder*/);
3211-
}
3212-
32133190
NecessaryBindings
32143191
NecessaryBindings::forPartialApplyForwarder(IRGenModule &IGM,
32153192
CanSILFunctionType origType,
32163193
SubstitutionMap subs,
32173194
bool considerParameterSources) {
32183195
return computeBindings(IGM, origType, subs,
3219-
true /*forPartialApplyForwarder*/,
32203196
considerParameterSources);
32213197
}
32223198

32233199
NecessaryBindings NecessaryBindings::computeBindings(
32243200
IRGenModule &IGM, CanSILFunctionType origType, SubstitutionMap subs,
3225-
bool forPartialApplyForwarder, bool considerParameterSources) {
3201+
bool considerParameterSources) {
32263202

32273203
NecessaryBindings bindings;
3228-
bindings.kind =
3229-
forPartialApplyForwarder ? Kind::PartialApply : Kind::AsyncFunction;
32303204

32313205
// Bail out early if we don't have polymorphic parameters.
32323206
if (!hasPolymorphicParameters(origType))
@@ -3249,9 +3223,7 @@ NecessaryBindings NecessaryBindings::computeBindings(
32493223
case MetadataSource::Kind::SelfMetadata:
32503224
// Async functions pass the SelfMetadata and SelfWitnessTable parameters
32513225
// along explicitly.
3252-
if (forPartialApplyForwarder) {
3253-
bindings.addTypeMetadata(getSubstSelfType(IGM, origType, subs));
3254-
}
3226+
bindings.addTypeMetadata(getSubstSelfType(IGM, origType, subs));
32553227
continue;
32563228

32573229
case MetadataSource::Kind::SelfWitnessTable:

lib/IRGen/NecessaryBindings.h

Lines changed: 3 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -42,28 +42,11 @@ namespace swift {
4242
/// NecessaryBindings - The set of metadata that must be saved in
4343
/// order to perform some set of operations on a type.
4444
class NecessaryBindings {
45-
enum class Kind {
46-
/// Are the bindings to be computed for a partial apply forwarder.
47-
/// In the case this is true we need to store/restore the conformance of a
48-
/// specialized type with conditional conformance because the conditional
49-
/// requirements are not available in the partial apply forwarder.
50-
PartialApply,
51-
AsyncFunction,
52-
};
53-
Kind kind;
5445
llvm::SetVector<GenericRequirement> RequirementsSet;
55-
llvm::SmallVector<GenericRequirement, 2> RequirementsVector;
5646
llvm::DenseMap<GenericRequirement, ProtocolConformanceRef> Conformances;
5747

5848
void addRequirement(GenericRequirement requirement) {
59-
switch (kind) {
60-
case Kind::PartialApply:
61-
RequirementsSet.insert(requirement);
62-
break;
63-
case Kind::AsyncFunction:
64-
RequirementsVector.push_back(requirement);
65-
break;
66-
}
49+
RequirementsSet.insert(requirement);
6750
}
6851

6952
void addAbstractConditionalRequirements(
@@ -74,9 +57,6 @@ class NecessaryBindings {
7457

7558
/// Collect the necessary bindings to invoke a function with the given
7659
/// signature.
77-
static NecessaryBindings
78-
forAsyncFunctionInvocation(IRGenModule &IGM, CanSILFunctionType origType,
79-
SubstitutionMap subs);
8060
static NecessaryBindings forPartialApplyForwarder(IRGenModule &IGM,
8161
CanSILFunctionType origType,
8262
SubstitutionMap subs,
@@ -88,13 +68,7 @@ class NecessaryBindings {
8868

8969
/// Get the requirement from the bindings at index i.
9070
const GenericRequirement &operator[](size_t i) const {
91-
switch (kind) {
92-
case Kind::PartialApply:
93-
return RequirementsSet[i];
94-
case Kind::AsyncFunction:
95-
return RequirementsVector[i];
96-
}
97-
llvm_unreachable("covered switch");
71+
return RequirementsSet[i];
9872
}
9973

10074
ProtocolConformanceRef
@@ -124,23 +98,13 @@ class NecessaryBindings {
12498
void restore(IRGenFunction &IGF, Address buffer, MetadataState state) const;
12599

126100
const llvm::ArrayRef<GenericRequirement> getRequirements() const {
127-
switch (kind) {
128-
case Kind::PartialApply:
129-
return RequirementsSet.getArrayRef();
130-
case Kind::AsyncFunction:
131-
return RequirementsVector;
132-
}
133-
llvm_unreachable("unhandled case");
101+
return RequirementsSet.getArrayRef();
134102
}
135103

136-
bool forPartialApply() const { return kind == Kind::PartialApply; }
137-
bool forAsyncFunction() const { return kind == Kind::AsyncFunction; }
138-
139104
private:
140105
static NecessaryBindings computeBindings(IRGenModule &IGM,
141106
CanSILFunctionType origType,
142107
SubstitutionMap subs,
143-
bool forPartialApplyForwarder,
144108
bool considerParameterSources = true);
145109
};
146110

lib/Parse/ParseExpr.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,12 +1227,9 @@ Parser::parseExprPostfixSuffix(ParserResult<Expr> Result, bool isExprBasic,
12271227
if (argStat.isErrorOrHasCompletion())
12281228
diagnose(LAngleLoc, diag::while_parsing_as_left_angle_bracket);
12291229

1230-
// The result can be empty in error cases.
1231-
if (!args.empty()) {
1232-
Result = makeParserResult(
1233-
Result, UnresolvedSpecializeExpr::create(
1234-
Context, Result.get(), LAngleLoc, args, RAngleLoc));
1235-
}
1230+
Result = makeParserResult(
1231+
Result, UnresolvedSpecializeExpr::create(
1232+
Context, Result.get(), LAngleLoc, args, RAngleLoc));
12361233
}
12371234

12381235
continue;
@@ -2241,8 +2238,7 @@ ParserResult<Expr> Parser::parseExprIdentifier() {
22412238
if (argStatus.isErrorOrHasCompletion())
22422239
diagnose(LAngleLoc, diag::while_parsing_as_left_angle_bracket);
22432240

2244-
// The result can be empty in error cases.
2245-
hasGenericArgumentList = !args.empty();
2241+
hasGenericArgumentList = true;
22462242
}
22472243

22482244
if (name.getBaseName().isEditorPlaceholder()) {

lib/Parse/ParseType.cpp

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,13 +1365,18 @@ bool Parser::canParseGenericArguments() {
13651365
if (!startsWithLess(Tok))
13661366
return false;
13671367
consumeStartingLess();
1368-
1368+
1369+
if (startsWithGreater(Tok)) {
1370+
consumeStartingGreater();
1371+
return true;
1372+
}
1373+
13691374
do {
13701375
if (!canParseType())
13711376
return false;
13721377
// Parse the comma, if the list continues.
13731378
} while (consumeIf(tok::comma));
1374-
1379+
13751380
if (!startsWithGreater(Tok)) {
13761381
return false;
13771382
} else {
@@ -1454,19 +1459,20 @@ bool Parser::canParseType() {
14541459
break;
14551460
}
14561461

1457-
if (!isAtFunctionTypeArrow())
1458-
return true;
1459-
1460-
// Handle type-function if we have an '->' with optional
1461-
// 'async' and/or 'throws'.
1462-
while (isEffectsSpecifier(Tok))
1463-
consumeToken();
1462+
if (isAtFunctionTypeArrow()) {
1463+
// Handle type-function if we have an '->' with optional
1464+
// 'async' and/or 'throws'.
1465+
while (isEffectsSpecifier(Tok))
1466+
consumeToken();
14641467

1465-
if (!consumeIf(tok::arrow))
1466-
return false;
1467-
1468-
if (!canParseType())
1469-
return false;
1468+
if (!consumeIf(tok::arrow))
1469+
return false;
1470+
1471+
if (!canParseType())
1472+
return false;
1473+
1474+
return true;
1475+
}
14701476

14711477
// Parse pack expansion 'T...'.
14721478
if (Tok.isEllipsis()) {

lib/SIL/IR/AbstractionPattern.cpp

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,7 +1584,15 @@ class SubstFunctionTypePatternVisitor
15841584
// If so, let's put a fresh generic parameter in the substituted signature
15851585
// here.
15861586
unsigned paramIndex = substGenericParams.size();
1587-
auto gp = GenericTypeParamType::get(false, 0, paramIndex, TC.Context);
1587+
1588+
bool isParameterPack = false;
1589+
if (substTy->isParameterPack() || substTy->is<PackArchetypeType>())
1590+
isParameterPack = true;
1591+
else if (pattern.isTypeParameterPack())
1592+
isParameterPack = true;
1593+
1594+
auto gp = GenericTypeParamType::get(isParameterPack, 0, paramIndex,
1595+
TC.Context);
15881596
substGenericParams.push_back(gp);
15891597
substReplacementTypes.push_back(substTy);
15901598

@@ -1881,11 +1889,30 @@ class SubstFunctionTypePatternVisitor
18811889
}
18821890

18831891
CanType visitPackType(PackType *pack, AbstractionPattern pattern) {
1884-
llvm_unreachable("Unimplemented!");
1892+
if (auto gp = handleTypeParameterInAbstractionPattern(pattern, pack))
1893+
return gp;
1894+
1895+
// Break down the pack.
1896+
SmallVector<Type, 4> packElts;
1897+
for (unsigned i = 0; i < pack->getNumElements(); ++i) {
1898+
packElts.push_back(visit(pack->getElementType(i),
1899+
pattern.getPackElementType(i)));
1900+
}
1901+
1902+
return CanType(PackType::get(TC.Context, packElts));
18851903
}
18861904

1887-
CanType visitPackExpansionType(PackExpansionType *pack, AbstractionPattern pattern) {
1888-
llvm_unreachable("Unimplemented!");
1905+
CanType visitPackExpansionType(PackExpansionType *pack,
1906+
AbstractionPattern pattern) {
1907+
// Avoid walking into the pattern and count type if we can help it.
1908+
if (!pack->hasTypeParameter() && !pack->hasArchetype() &&
1909+
!pack->hasOpaqueArchetype()) {
1910+
return CanType(pack);
1911+
}
1912+
1913+
return CanType(PackExpansionType::get(
1914+
visit(pack->getPatternType(), pattern.getPackExpansionPatternType()),
1915+
visit(pack->getCountType(), pattern.getPackExpansionCountType())));
18891916
}
18901917

18911918
CanType visitExistentialType(ExistentialType *exist,

0 commit comments

Comments
 (0)