Skip to content

Commit 9280536

Browse files
committed
Merge pull request #2767 from slavapestov/generic-local-captures
Finish up SILGen support for nested generic functions
2 parents cbd6573 + 4bfc784 commit 9280536

17 files changed

+267
-145
lines changed

include/swift/AST/Decl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2415,7 +2415,7 @@ class GenericTypeDecl : public TypeDecl, public DeclContext {
24152415
ValidatingGenericSignature = ivgs;
24162416
}
24172417

2418-
bool IsValidatingGenericSignature() {
2418+
bool isValidatingGenericSignature() const {
24192419
return ValidatingGenericSignature;
24202420
}
24212421

lib/AST/ASTVerifier.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2196,6 +2196,15 @@ struct ASTNodeBase {};
21962196
abort();
21972197
}
21982198

2199+
// If the function has a generic interface type, it should also have a
2200+
// generic signature.
2201+
if (AFD->getInterfaceType()->is<GenericFunctionType>() !=
2202+
(AFD->getGenericSignature() != nullptr)) {
2203+
Out << "Missing generic signature for generic function\n";
2204+
AFD->dump(Out);
2205+
abort();
2206+
}
2207+
21992208
// If there is an interface type, it shouldn't have any unresolved
22002209
// dependent member types.
22012210
// FIXME: This is a general property of the type system.

lib/ClangImporter/ImportDecl.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2943,6 +2943,7 @@ namespace {
29432943
getProtocolMethodType(proto, fnType->castTo<AnyFunctionType>());
29442944
result->setType(fnType);
29452945
result->setInterfaceType(interfaceType);
2946+
result->setGenericSignature(proto->getGenericSignature());
29462947
} else {
29472948
result->setType(fnType);
29482949
}
@@ -3740,6 +3741,7 @@ namespace {
37403741
result->setBodyResultType(resultTy);
37413742
result->setType(type);
37423743
result->setInterfaceType(interfaceType);
3744+
result->setGenericSignature(dc->getGenericSignatureOfContext());
37433745

37443746
// Optional methods in protocols.
37453747
if (decl->getImplementationControl() == clang::ObjCMethodDecl::Optional &&
@@ -4215,6 +4217,7 @@ namespace {
42154217

42164218
result->setInitializerInterfaceType(interfaceInitType);
42174219
result->setInterfaceType(interfaceAllocType);
4220+
result->setGenericSignature(dc->getGenericSignatureOfContext());
42184221
} else if (dc->isGenericContext()) {
42194222
Type interfaceAllocType;
42204223
Type interfaceInitType;
@@ -4225,6 +4228,7 @@ namespace {
42254228

42264229
result->setInitializerInterfaceType(interfaceInitType);
42274230
result->setInterfaceType(interfaceAllocType);
4231+
result->setGenericSignature(dc->getGenericSignatureOfContext());
42284232
selfVar->overwriteType(initType->castTo<AnyFunctionType>()->getInput());
42294233
}
42304234

@@ -4407,6 +4411,7 @@ namespace {
44074411
getter->getClangNode());
44084412
thunk->setBodyResultType(elementTy);
44094413
thunk->setInterfaceType(interfaceType);
4414+
thunk->setGenericSignature(dc->getGenericSignatureOfContext());
44104415
thunk->setAccessibility(Accessibility::Public);
44114416

44124417
auto objcAttr = getter->getAttrs().getAttribute<ObjCAttr>();
@@ -4482,6 +4487,7 @@ namespace {
44824487
setter->getClangNode());
44834488
thunk->setBodyResultType(TupleType::getEmpty(C));
44844489
thunk->setInterfaceType(interfaceType);
4490+
thunk->setGenericSignature(dc->getGenericSignatureOfContext());
44854491
thunk->setAccessibility(Accessibility::Public);
44864492

44874493
auto objcAttr = setter->getAttrs().getAttribute<ObjCAttr>();

lib/SIL/TypeLowering.cpp

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1773,33 +1773,41 @@ TypeConverter::getFunctionInterfaceTypeWithCaptures(CanAnyFunctionType funcType,
17731773
CanGenericSignature genericSig = getEffectiveGenericSignature(theClosure,
17741774
captureInfo);
17751775

1776+
auto innerExtInfo = AnyFunctionType::ExtInfo(FunctionType::Representation::Thin,
1777+
funcType->isNoReturn(),
1778+
funcType->throws());
1779+
17761780
// If we don't have any local captures (including function captures),
17771781
// there's no context to apply.
17781782
if (!theClosure.getCaptureInfo().hasLocalCaptures()) {
17791783
if (!genericSig)
1780-
return adjustFunctionType(funcType,
1781-
FunctionType::Representation::Thin);
1784+
return CanFunctionType::get(funcType.getInput(),
1785+
funcType.getResult(),
1786+
innerExtInfo);
17821787

1783-
auto extInfo = AnyFunctionType::ExtInfo(FunctionType::Representation::Thin,
1784-
funcType->isNoReturn(),
1785-
funcType->throws());
1786-
17871788
return CanGenericFunctionType::get(genericSig,
17881789
funcType.getInput(),
17891790
funcType.getResult(),
1790-
extInfo);
1791+
innerExtInfo);
17911792
}
17921793

1794+
// Strip the generic signature off the inner type; we will add it to the
1795+
// outer type with captures.
1796+
funcType = CanFunctionType::get(funcType.getInput(),
1797+
funcType.getResult(),
1798+
innerExtInfo);
1799+
17931800
// Add an extra empty tuple level to represent the captures. We'll append the
17941801
// lowered capture types here.
17951802
auto extInfo = AnyFunctionType::ExtInfo(FunctionType::Representation::Thin,
17961803
/*noreturn*/ false,
1797-
funcType->throws());
1804+
/*throws*/ false);
17981805

1799-
if (genericSig)
1806+
if (genericSig) {
18001807
return CanGenericFunctionType::get(genericSig,
18011808
Context.TheEmptyTupleType, funcType,
18021809
extInfo);
1810+
}
18031811

18041812
return CanFunctionType::get(Context.TheEmptyTupleType, funcType, extInfo);
18051813
}

lib/SILGen/SILGenApply.cpp

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,30 +1157,22 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
11571157

11581158
// Otherwise, we have a statically-dispatched call.
11591159
CanFunctionType substFnType = getSubstFnType();
1160-
ArrayRef<Substitution> subs;
1161-
1160+
11621161
auto afd = dyn_cast<AbstractFunctionDecl>(e->getDecl());
11631162
if (afd) {
1164-
auto constantInfo = SGF.getConstantInfo(constant);
1165-
1166-
// Forward local substitutions to a non-generic local function.
1167-
if (afd->getParent()->isLocalContext() && !afd->getGenericParams())
1168-
subs = constantInfo.getForwardingSubstitutions(SGF.getASTContext());
1169-
11701163
// If there are captures, put the placeholder curry level in the formal
11711164
// type.
11721165
// TODO: Eliminate the need for this.
11731166
if (afd->getCaptureInfo().hasLocalCaptures())
11741167
substFnType = CanFunctionType::get(
11751168
SGF.getASTContext().TheEmptyTupleType, substFnType);
11761169
}
1177-
1170+
1171+
ArrayRef<Substitution> subs;
11781172
if (e->getDeclRef().isSpecialized()) {
1179-
assert(subs.empty() && "nested local generics not yet supported");
11801173
subs = e->getDeclRef().getSubstitutions();
11811174
}
1182-
1183-
1175+
11841176
// Enum case constructor references are open-coded.
11851177
if (isa<EnumElementDecl>(e->getDecl()))
11861178
setCallee(Callee::forEnumElement(SGF, constant, substFnType, e));
@@ -1189,21 +1181,20 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
11891181

11901182
// If the decl ref requires captures, emit the capture params.
11911183
if (afd) {
1184+
// FIXME: We should be checking hasLocalCaptures() on the lowered
1185+
// captures in the constant info too, to generate more efficient
1186+
// code for mutually recursive local functions which otherwise
1187+
// capture no state.
11921188
if (afd->getCaptureInfo().hasLocalCaptures()) {
1193-
assert(!e->getDeclRef().isSpecialized()
1194-
&& "generic local fns not implemented");
1195-
11961189
SmallVector<ManagedValue, 4> captures;
11971190
SGF.emitCaptures(e, afd, CaptureEmission::ImmediateApplication,
11981191
captures);
11991192
ApplyCallee->setCaptures(std::move(captures));
12001193
}
1201-
1202-
// FIXME: We should be checking hasLocalCaptures() on the lowered
1203-
// captures in the constant info too, to generate more efficient
1204-
// code for mutually recursive local functions which otherwise
1205-
// capture no state.
1206-
1194+
1195+
if (subs.empty() && afd->getCaptureInfo().hasGenericParamCaptures()) {
1196+
subs = SGF.getForwardingSubstitutions();
1197+
}
12071198
}
12081199

12091200
// If there are substitutions, add them, always at depth 0.
@@ -1227,14 +1218,15 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
12271218
SILDeclRef constant(e);
12281219

12291220
ArrayRef<Substitution> subs;
1221+
if (e->getCaptureInfo().hasGenericParamCaptures())
1222+
subs = SGF.getForwardingSubstitutions();
1223+
12301224
CanFunctionType substFnType = getSubstFnType();
12311225

12321226
// FIXME: We should be checking hasLocalCaptures() on the lowered
12331227
// captures in the constant info above, to generate more efficient
12341228
// code for mutually recursive local functions which otherwise
12351229
// capture no state.
1236-
auto constantInfo = SGF.getConstantInfo(constant);
1237-
subs = constantInfo.getForwardingSubstitutions(SGF.getASTContext());
12381230

12391231
// If there are captures, put the placeholder curry level in the formal
12401232
// type.

lib/SILGen/SILGenExpr.cpp

Lines changed: 11 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -445,57 +445,9 @@ emitRValueForDecl(SILLocation loc, ConcreteDeclRef declRef, Type ncRefType,
445445
}
446446

447447
auto silDeclRef = SILDeclRef(decl, ResilienceExpansion::Minimal, uncurryLevel);
448-
auto constantInfo = getConstantInfo(silDeclRef);
449-
450-
ManagedValue result = emitFunctionRef(loc, silDeclRef, constantInfo);
451-
452-
// Get the lowered AST types:
453-
// - the original type
454-
auto origLoweredFormalType =
455-
AbstractionPattern(constantInfo.LoweredInterfaceType);
456-
if (hasLocalCaptures) {
457-
// Get the unlowered formal type of the constant, stripping off
458-
// the first level of function application, which applies captures.
459-
origLoweredFormalType =
460-
AbstractionPattern(constantInfo.FormalInterfaceType)
461-
.getFunctionResultType();
462-
463-
// Lower it, being careful to use the right generic signature.
464-
origLoweredFormalType =
465-
AbstractionPattern(
466-
origLoweredFormalType.getGenericSignature(),
467-
SGM.Types.getLoweredASTFunctionType(
468-
cast<FunctionType>(origLoweredFormalType.getType()),
469-
0, silDeclRef));
470-
}
471-
472-
// - the substituted type
473-
auto substFormalType = cast<AnyFunctionType>(refType);
474-
auto substLoweredFormalType =
475-
SGM.Types.getLoweredASTFunctionType(substFormalType, 0, silDeclRef);
476-
477-
// If the declaration reference is specialized, create the partial
478-
// application.
479-
if (declRef.isSpecialized()) {
480-
// Substitute the function type.
481-
auto origFnType = result.getType().castTo<SILFunctionType>();
482-
auto substFnType = origFnType->substGenericArgs(
483-
SGM.M, SGM.SwiftModule,
484-
declRef.getSubstitutions());
485-
auto closureType = adjustFunctionType(substFnType,
486-
SILFunctionType::Representation::Thick);
487-
488-
SILValue spec = B.createPartialApply(loc, result.forward(*this),
489-
SILType::getPrimitiveObjectType(substFnType),
490-
declRef.getSubstitutions(),
491-
{ },
492-
SILType::getPrimitiveObjectType(closureType));
493-
result = emitManagedRValueWithCleanup(spec);
494-
}
495-
496-
// Generalize if necessary.
497-
result = emitOrigToSubstValue(loc, result, origLoweredFormalType,
498-
substLoweredFormalType);
448+
449+
ManagedValue result = emitClosureValue(loc, silDeclRef, refType,
450+
declRef.getSubstitutions());
499451
return RValue(*this, loc, refType, result);
500452
}
501453

@@ -1965,9 +1917,16 @@ RValue RValueEmitter::visitAbstractClosureExpr(AbstractClosureExpr *e,
19651917
// Emit the closure body.
19661918
SGF.SGM.emitClosure(e);
19671919

1920+
ArrayRef<Substitution> subs;
1921+
if (e->getCaptureInfo().hasGenericParamCaptures())
1922+
subs = SGF.getForwardingSubstitutions();
1923+
19681924
// Generate the closure value (if any) for the closure expr's function
19691925
// reference.
1970-
return RValue(SGF, e, SGF.emitClosureValue(e, SILDeclRef(e), e));
1926+
auto refType = e->getType()->getCanonicalType();
1927+
ManagedValue result = SGF.emitClosureValue(e, SILDeclRef(e),
1928+
refType, subs);
1929+
return RValue(SGF, e, refType, result);
19711930
}
19721931

19731932
RValue RValueEmitter::

0 commit comments

Comments
 (0)