Skip to content

Commit 9cf4d61

Browse files
authored
Merge pull request #73685 from slavapestov/pack-expansion-closures-part-5
Pack expansion closures, part 5
2 parents 4debfad + cf27663 commit 9cf4d61

12 files changed

+179
-47
lines changed

include/swift/AST/ASTMangler.h

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

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

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

include/swift/AST/LocalArchetypeRequirementCollector.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,17 @@ struct MapLocalArchetypesOutOfContext {
5353
Type operator()(SubstitutableType *type) const;
5454
};
5555

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+
5667
GenericSignature buildGenericSignatureWithCapturedEnvironments(
5768
ASTContext &ctx,
5869
GenericSignature sig,

include/swift/SIL/SILFunction.h

Lines changed: 40 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;
@@ -1292,9 +1295,21 @@ class SILFunction
12921295
GenericEnvironment *getGenericEnvironment() const {
12931296
return GenericEnv;
12941297
}
1298+
1299+
/// Return any captured local generic environments, currently used for pack
1300+
/// element environments only. After SILGen, these are rewritten into
1301+
/// primary archetypes.
1302+
ArrayRef<GenericEnvironment *> getCapturedEnvironments() const {
1303+
return CapturedEnvs;
1304+
}
1305+
1306+
void setGenericEnvironment(GenericEnvironment *env);
1307+
12951308
void setGenericEnvironment(GenericEnvironment *env,
1296-
SubstitutionMap forwardingSubs=SubstitutionMap()) {
1309+
ArrayRef<GenericEnvironment *> capturedEnvs,
1310+
SubstitutionMap forwardingSubs) {
12971311
GenericEnv = env;
1312+
CapturedEnvs = capturedEnvs;
12981313
ForwardingSubMap = forwardingSubs;
12991314
}
13001315

@@ -1324,9 +1339,30 @@ class SILFunction
13241339
/// responsibility of the caller.
13251340
void eraseAllBlocks();
13261341

1327-
/// Return the identity substitutions necessary to forward this call if it is
1328-
/// generic.
1329-
SubstitutionMap getForwardingSubstitutionMap();
1342+
/// A substitution map that sends the generic parameters of the invocation
1343+
/// generic signature to some combination of primar and local archetypes.
1344+
///
1345+
/// CAUTION: If this is a SILFunction that captures pack element environments,
1346+
/// then at SILGen time, this is not actually the forwarding substitution map
1347+
/// of the SILFunction's generic environment. This is because:
1348+
///
1349+
/// 1) The SILFunction's generic signature includes extra generic parameters,
1350+
/// to model captured pack elements;
1351+
/// 2) The SILFunction's generic environment is the AST generic environment,
1352+
/// so it's based on the original generic signature;
1353+
/// 3) SILGen uses this AST generic environment together with local archetypes
1354+
/// for lowering SIL instructions.
1355+
///
1356+
/// Therefore, the SILFunction's forwarding substitution map takes the extended
1357+
/// generic signature (1). It maps the original generic parameters to the
1358+
/// archetypes of (2), and the extended generic parameters to the local archetypes
1359+
/// of (3).
1360+
///
1361+
/// After SILGen, all archetypes are re-instantiated inside the SIL function,
1362+
/// and the forwarding substitution map and generic environment then align.
1363+
SubstitutionMap getForwardingSubstitutionMap() const {
1364+
return ForwardingSubMap;
1365+
}
13301366

13311367
/// Returns true if this SILFunction must be a defer statement.
13321368
///

include/swift/SIL/TypeLowering.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1080,7 +1080,7 @@ class TypeConverter {
10801080
/// sends the generic parameters of the function's interface type into
10811081
/// archetypes, which will either be primary archetypes from this
10821082
/// environment, or local archetypes captured by this function.
1083-
std::pair<GenericEnvironment *, SubstitutionMap>
1083+
std::tuple<GenericEnvironment *, ArrayRef<GenericEnvironment *>, SubstitutionMap>
10841084
getForwardingSubstitutionsForLowering(SILDeclRef constant);
10851085

10861086
/// Returns the SIL type of a constant reference.

lib/AST/ASTMangler.cpp

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "swift/AST/GenericSignature.h"
2626
#include "swift/AST/Initializer.h"
2727
#include "swift/AST/LazyResolver.h"
28+
#include "swift/AST/LocalArchetypeRequirementCollector.h"
2829
#include "swift/AST/MacroDiscriminatorContext.h"
2930
#include "swift/AST/Module.h"
3031
#include "swift/AST/Ownership.h"
@@ -3733,29 +3734,48 @@ void ASTMangler::appendAssociatedTypeName(DependentMemberType *dmt,
37333734

37343735
void ASTMangler::appendClosureEntity(
37353736
const SerializedAbstractClosureExpr *closure) {
3737+
assert(!closure->getType()->hasLocalArchetype() &&
3738+
"Not enough information here to handle this case");
3739+
37363740
appendClosureComponents(closure->getType(), closure->getDiscriminator(),
3737-
closure->isImplicit(), closure->getParent());
3741+
closure->isImplicit(), closure->getParent(),
3742+
ArrayRef<GenericEnvironment *>());
37383743
}
37393744

37403745
void ASTMangler::appendClosureEntity(const AbstractClosureExpr *closure) {
3741-
appendClosureComponents(closure->getType(), closure->getDiscriminator(),
3742-
isa<AutoClosureExpr>(closure), closure->getParent());
3746+
ArrayRef<GenericEnvironment *> capturedEnvs;
3747+
3748+
auto type = closure->getType();
3749+
3750+
// FIXME: CodeCompletionResultBuilder calls printValueDeclUSR() but the
3751+
// closure hasn't been type checked yet.
3752+
if (!type)
3753+
type = ErrorType::get(closure->getASTContext());
3754+
3755+
if (type->hasLocalArchetype())
3756+
capturedEnvs = closure->getCaptureInfo().getGenericEnvironments();
3757+
3758+
appendClosureComponents(type, closure->getDiscriminator(),
3759+
isa<AutoClosureExpr>(closure), closure->getParent(),
3760+
capturedEnvs);
37433761
}
37443762

37453763
void ASTMangler::appendClosureComponents(Type Ty, unsigned discriminator,
37463764
bool isImplicit,
3747-
const DeclContext *parentContext) {
3765+
const DeclContext *parentContext,
3766+
ArrayRef<GenericEnvironment *> capturedEnvs) {
37483767
assert(discriminator != AbstractClosureExpr::InvalidDiscriminator
37493768
&& "closure must be marked correctly with discriminator");
37503769

37513770
BaseEntitySignature base(parentContext->getInnermostDeclarationDeclContext());
37523771
appendContext(parentContext, base, StringRef());
37533772

3754-
if (!Ty)
3755-
Ty = ErrorType::get(parentContext->getASTContext());
3756-
37573773
auto Sig = parentContext->getGenericSignatureOfContext();
3758-
Ty = Ty->mapTypeOutOfContext();
3774+
3775+
Ty = Ty.subst(MapLocalArchetypesOutOfContext(Sig, capturedEnvs),
3776+
MakeAbstractConformanceForGenericType(),
3777+
SubstFlags::PreservePackExpansionLevel);
3778+
37593779
appendType(Ty->getCanonicalType(), Sig);
37603780
appendOperator(isImplicit ? "fu" : "fU", Index(discriminator));
37613781
}

lib/AST/LocalArchetypeRequirementCollector.cpp

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,28 @@ Type MapLocalArchetypesOutOfContext::operator()(SubstitutableType *type) const {
194194
llvm_unreachable("Fell off the end");
195195
}
196196

197+
static Type mapIntoLocalContext(GenericTypeParamType *param, unsigned baseDepth,
198+
ArrayRef<GenericEnvironment *> capturedEnvs) {
199+
assert(!param->isParameterPack());
200+
unsigned envIndex = param->getDepth() - baseDepth;
201+
assert(envIndex < capturedEnvs.size());
202+
auto *capturedEnv = capturedEnvs[envIndex];
203+
auto localInterfaceType = capturedEnv->getGenericSignature()
204+
.getInnermostGenericParams()[param->getIndex()];
205+
assert(localInterfaceType->getIndex() == param->getIndex());
206+
return capturedEnvs[envIndex]->mapTypeIntoContext(localInterfaceType);
207+
}
208+
209+
Type MapIntoLocalArchetypeContext::operator()(SubstitutableType *type) const {
210+
unsigned baseDepth = baseGenericEnv->getGenericSignature().getNextDepth();
211+
212+
auto param = cast<GenericTypeParamType>(type);
213+
if (param->getDepth() >= baseDepth)
214+
return mapIntoLocalContext(param, baseDepth, capturedEnvs);
215+
216+
return baseGenericEnv->mapTypeIntoContext(param);
217+
}
218+
197219
/// Given a substitution map for a call to a local function or closure, extend
198220
/// it to include all captured element archetypes; they become primary archetypes
199221
/// inside the body of the function.
@@ -215,15 +237,8 @@ swift::buildSubstitutionMapWithCapturedEnvironments(
215237
genericSigWithCaptures,
216238
[&](SubstitutableType *type) -> Type {
217239
auto param = cast<GenericTypeParamType>(type);
218-
if (param->getDepth() >= baseDepth) {
219-
assert(!param->isParameterPack());
220-
unsigned envIndex = param->getDepth() - baseDepth;
221-
assert(envIndex < capturedEnvs.size());
222-
auto *capturedEnv = capturedEnvs[envIndex];
223-
auto localInterfaceType = capturedEnv->getGenericSignature()
224-
.getInnermostGenericParams()[param->getIndex()];
225-
return capturedEnvs[envIndex]->mapTypeIntoContext(localInterfaceType);
226-
}
240+
if (param->getDepth() >= baseDepth)
241+
return mapIntoLocalContext(param, baseDepth, capturedEnvs);
227242
return Type(type).subst(baseSubMap);
228243
},
229244
[&](CanType origType, Type substType,

lib/SIL/IR/SILFunction.cpp

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "swift/AST/Expr.h"
1818
#include "swift/AST/GenericEnvironment.h"
1919
#include "swift/AST/IRGenOptions.h"
20+
#include "swift/AST/LocalArchetypeRequirementCollector.h"
2021
#include "swift/AST/Module.h"
2122
#include "swift/AST/Stmt.h"
2223
#include "swift/Basic/OptimizationMode.h"
@@ -245,7 +246,6 @@ void SILFunction::init(
245246
"function type has open type parameters");
246247

247248
this->LoweredType = LoweredType;
248-
this->GenericEnv = genericEnv;
249249
this->SpecializationInfo = nullptr;
250250
this->EntryCount = entryCount;
251251
this->Availability = AvailabilityContext::alwaysAvailable();
@@ -282,6 +282,7 @@ void SILFunction::init(
282282
assert(!Transparent || !IsDynamicReplaceable);
283283
validateSubclassScope(classSubclassScope, isThunk, nullptr);
284284
setDebugScope(DebugScope);
285+
setGenericEnvironment(genericEnv);
285286
}
286287

287288
SILFunction::~SILFunction() {
@@ -492,24 +493,51 @@ bool SILFunction::shouldOptimize() const {
492493
}
493494

494495
Type SILFunction::mapTypeIntoContext(Type type) const {
495-
return GenericEnvironment::mapTypeIntoContext(
496-
getGenericEnvironment(), type);
496+
assert(!type->hasPrimaryArchetype());
497+
498+
if (GenericEnv) {
499+
// The complication here is that we sometimes call this with an AST interface
500+
// type, which might contain element archetypes, if it was the interface type
501+
// of a closure or local variable.
502+
if (type->hasElementArchetype())
503+
return GenericEnv->mapTypeIntoContext(type);
504+
505+
// Otherwise, assume we have an interface type for the "combined" captured
506+
// environment.
507+
return type.subst(MapIntoLocalArchetypeContext(GenericEnv, CapturedEnvs),
508+
LookUpConformanceInModule(Module.getSwiftModule()),
509+
SubstFlags::AllowLoweredTypes |
510+
SubstFlags::PreservePackExpansionLevel);
511+
}
512+
513+
assert(!type->hasTypeParameter());
514+
return type;
497515
}
498516

499517
SILType SILFunction::mapTypeIntoContext(SILType type) const {
500-
if (auto *genericEnv = getGenericEnvironment())
501-
return genericEnv->mapTypeIntoContext(getModule(), type);
518+
assert(!type.hasPrimaryArchetype());
519+
520+
if (GenericEnv) {
521+
auto genericSig = GenericEnv->getGenericSignature().getCanonicalSignature();
522+
return type.subst(Module,
523+
MapIntoLocalArchetypeContext(GenericEnv, CapturedEnvs),
524+
LookUpConformanceInModule(Module.getSwiftModule()),
525+
genericSig,
526+
SubstFlags::PreservePackExpansionLevel);
527+
}
528+
529+
assert(!type.hasTypeParameter());
502530
return type;
503531
}
504532

505533
SILType GenericEnvironment::mapTypeIntoContext(SILModule &M,
506534
SILType type) const {
507-
assert(!type.hasArchetype());
535+
assert(!type.hasPrimaryArchetype());
508536

509537
auto genericSig = getGenericSignature().getCanonicalSignature();
510538
return type.subst(M,
511539
QueryInterfaceTypeSubstitutions(this),
512-
LookUpConformanceInSignature(genericSig.getPointer()),
540+
LookUpConformanceInModule(M.getSwiftModule()),
513541
genericSig,
514542
SubstFlags::PreservePackExpansionLevel);
515543
}
@@ -1033,14 +1061,10 @@ void SILFunction::eraseAllBlocks() {
10331061
BlockList.clear();
10341062
}
10351063

1036-
SubstitutionMap SILFunction::getForwardingSubstitutionMap() {
1037-
if (ForwardingSubMap)
1038-
return ForwardingSubMap;
1039-
1040-
if (auto *env = getGenericEnvironment())
1041-
ForwardingSubMap = env->getForwardingSubstitutionMap();
1042-
1043-
return ForwardingSubMap;
1064+
void SILFunction::setGenericEnvironment(GenericEnvironment *env) {
1065+
setGenericEnvironment(env, ArrayRef<GenericEnvironment *>(),
1066+
env ? env->getForwardingSubstitutionMap()
1067+
: SubstitutionMap());
10441068
}
10451069

10461070
bool SILFunction::shouldVerifyOwnership() const {

lib/SIL/IR/SILModule.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,23 @@ SILValue SILModule::getRootLocalArchetypeDef(CanLocalArchetypeType archetype,
688688
}
689689

690690
bool SILModule::hasUnresolvedLocalArchetypeDefinitions() {
691+
// Garbage collect dead placeholders first.
692+
llvm::DenseMap<LocalArchetypeKey, SILValue> newLocalArchetypeDefs;
693+
694+
for (auto pair : RootLocalArchetypeDefs) {
695+
if (auto *placeholder = dyn_cast<PlaceholderValue>(pair.second)) {
696+
if (placeholder->use_empty()) {
697+
--numUnresolvedLocalArchetypes;
698+
::delete placeholder;
699+
continue;
700+
}
701+
}
702+
703+
newLocalArchetypeDefs.insert(pair);
704+
}
705+
706+
std::swap(newLocalArchetypeDefs, RootLocalArchetypeDefs);
707+
691708
return numUnresolvedLocalArchetypes != 0;
692709
}
693710

@@ -753,6 +770,8 @@ void SILModule::notifyAddedInstruction(SILInstruction *inst) {
753770
auto *placeholder = cast<PlaceholderValue>(val);
754771
placeholder->replaceAllUsesWith(dependency);
755772
::delete placeholder;
773+
774+
assert(numUnresolvedLocalArchetypes > 0);
756775
numUnresolvedLocalArchetypes--;
757776
}
758777
val = dependency;

lib/SIL/IR/TypeLowering.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4116,17 +4116,15 @@ TypeConverter::getConstantGenericEnvironment(SILDeclRef c) {
41164116
.genericSig.getGenericEnvironment();
41174117
}
41184118

4119-
std::pair<GenericEnvironment *, SubstitutionMap>
4119+
std::tuple<GenericEnvironment *, ArrayRef<GenericEnvironment *>, SubstitutionMap>
41204120
TypeConverter::getForwardingSubstitutionsForLowering(SILDeclRef constant) {
41214121
auto sig = getGenericSignatureWithCapturedEnvironments(constant);
41224122

4123-
GenericEnvironment *genericEnv = nullptr;
4123+
auto *genericEnv = sig.baseGenericSig.getGenericEnvironment();
41244124
SubstitutionMap forwardingSubs;
41254125

4126-
if (sig.baseGenericSig) {
4127-
genericEnv = sig.baseGenericSig.getGenericEnvironment();
4126+
if (sig.baseGenericSig)
41284127
forwardingSubs = genericEnv->getForwardingSubstitutionMap();
4129-
}
41304128

41314129
if (!sig.capturedEnvs.empty()) {
41324130
assert(sig.genericSig && !sig.genericSig->isEqual(sig.baseGenericSig));
@@ -4135,7 +4133,7 @@ TypeConverter::getForwardingSubstitutionsForLowering(SILDeclRef constant) {
41354133
forwardingSubs, sig.genericSig, sig.capturedEnvs);
41364134
}
41374135

4138-
return std::make_pair(genericEnv, forwardingSubs);
4136+
return std::make_tuple(genericEnv, sig.capturedEnvs, forwardingSubs);
41394137
}
41404138

41414139
SILType TypeConverter::getSubstitutedStorageType(TypeExpansionContext context,

lib/SILGen/SILGen.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,8 +1224,9 @@ void SILGenModule::preEmitFunction(SILDeclRef constant, SILFunction *F,
12241224
assert(F->empty() && "already emitted function?!");
12251225

12261226
if (F->getLoweredFunctionType()->isPolymorphic()) {
1227-
auto pair = Types.getForwardingSubstitutionsForLowering(constant);
1228-
F->setGenericEnvironment(pair.first, pair.second);
1227+
auto [genericEnv, capturedEnvs, forwardingSubs]
1228+
= Types.getForwardingSubstitutionsForLowering(constant);
1229+
F->setGenericEnvironment(genericEnv, capturedEnvs, forwardingSubs);
12291230
}
12301231

12311232
// If we have global actor isolation for our constant, put the isolation onto

0 commit comments

Comments
 (0)