Skip to content

Commit af8759a

Browse files
Merge pull request #38740 from nate-chandler/rdar80704984
[SILGen] Handle foreign funcs with error and async conventions.
2 parents 1697184 + 1ae317d commit af8759a

File tree

17 files changed

+623
-215
lines changed

17 files changed

+623
-215
lines changed

include/swift/AST/ForeignInfo.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@
2626
namespace swift {
2727

2828
struct ForeignInfo {
29-
ImportAsMemberStatus Self;
30-
Optional<ForeignErrorConvention> Error;
31-
Optional<ForeignAsyncConvention> Async;
29+
ImportAsMemberStatus self;
30+
Optional<ForeignErrorConvention> error;
31+
Optional<ForeignAsyncConvention> async;
3232
};
3333

3434
} // end namespace swift

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 46 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1557,11 +1557,11 @@ class DestructureInputs {
15571557
unsigned numEltTypes = params.size();
15581558

15591559
bool hasSelf =
1560-
(extInfoBuilder.hasSelfParam() || Foreign.Self.isImportAsMember());
1560+
(extInfoBuilder.hasSelfParam() || Foreign.self.isImportAsMember());
15611561
unsigned numNonSelfParams = (hasSelf ? numEltTypes - 1 : numEltTypes);
15621562
TopLevelOrigType = origType;
15631563
// If we have a foreign-self, install handleSelf as the handler.
1564-
if (Foreign.Self.isInstance()) {
1564+
if (Foreign.self.isInstance()) {
15651565
assert(hasSelf && numEltTypes > 0);
15661566
ForeignSelf = ForeignSelfInfo{origType.getFunctionParamType(numNonSelfParams),
15671567
params[numNonSelfParams]};
@@ -1582,7 +1582,7 @@ class DestructureInputs {
15821582

15831583
// Process the self parameter. Note that we implicitly drop self
15841584
// if this is a static foreign-self import.
1585-
if (hasSelf && !Foreign.Self.isImportAsMember()) {
1585+
if (hasSelf && !Foreign.self.isImportAsMember()) {
15861586
auto selfParam = params[numNonSelfParams];
15871587
auto ty = selfParam.getParameterType();
15881588
auto eltPattern = origType.getFunctionParamType(numNonSelfParams);
@@ -1670,12 +1670,13 @@ class DestructureInputs {
16701670
}
16711671

16721672
bool maybeAddForeignAsyncParameter() {
1673-
if (!Foreign.Async
1674-
|| NextOrigParamIndex != Foreign.Async->completionHandlerParamIndex())
1673+
if (!Foreign.async ||
1674+
NextOrigParamIndex != Foreign.async->completionHandlerParamIndex())
16751675
return false;
1676-
1677-
CanType foreignCHTy = TopLevelOrigType
1678-
.getObjCMethodAsyncCompletionHandlerForeignType(Foreign.Async.getValue(), TC);
1676+
1677+
CanType foreignCHTy =
1678+
TopLevelOrigType.getObjCMethodAsyncCompletionHandlerForeignType(
1679+
Foreign.async.getValue(), TC);
16791680
auto completionHandlerOrigTy = TopLevelOrigType.getObjCMethodAsyncCompletionHandlerType(foreignCHTy);
16801681
auto completionHandlerTy = TC.getLoweredType(completionHandlerOrigTy,
16811682
foreignCHTy, expansion)
@@ -1687,17 +1688,12 @@ class DestructureInputs {
16871688
}
16881689

16891690
bool maybeAddForeignErrorParameter() {
1690-
// A foreign async convention absorbs any error parameter, making it into
1691-
// an argument to the callback.
1692-
if (Foreign.Async)
1693-
return false;
1694-
1695-
if (!Foreign.Error ||
1696-
NextOrigParamIndex != Foreign.Error->getErrorParameterIndex())
1691+
if (!Foreign.error ||
1692+
NextOrigParamIndex != Foreign.error->getErrorParameterIndex())
16971693
return false;
16981694

16991695
auto foreignErrorTy = TC.getLoweredRValueType(
1700-
expansion, Foreign.Error->getErrorParameterType());
1696+
expansion, Foreign.error->getErrorParameterType());
17011697

17021698
// Assume the error parameter doesn't have interesting lowering.
17031699
Inputs.push_back(SILParameterInfo(foreignErrorTy,
@@ -1707,8 +1703,8 @@ class DestructureInputs {
17071703
}
17081704

17091705
bool maybeAddForeignSelfParameter() {
1710-
if (!Foreign.Self.isInstance() ||
1711-
NextOrigParamIndex != Foreign.Self.getSelfIndex())
1706+
if (!Foreign.self.isInstance() ||
1707+
NextOrigParamIndex != Foreign.self.getSelfIndex())
17121708
return false;
17131709

17141710
if (ForeignSelf) {
@@ -1759,27 +1755,27 @@ void updateResultTypeForForeignInfo(
17591755
const ForeignInfo &foreignInfo, CanGenericSignature genericSig,
17601756
AbstractionPattern &origResultType, CanType &substFormalResultType) {
17611757
// If there's no error or async convention, the return type is unchanged.
1762-
if (!foreignInfo.Async && !foreignInfo.Error) {
1758+
if (!foreignInfo.async && !foreignInfo.error) {
17631759
return;
17641760
}
1765-
1766-
// A foreign async convention means our lowered return type is Void, since
1767-
// the imported semantic return and/or error type map to the completion
1768-
// callback's argument(s).
1769-
auto &C = substFormalResultType->getASTContext();
1770-
if (auto async = foreignInfo.Async) {
1761+
1762+
// A foreign async convention without an error convention means our lowered
1763+
// return type is Void, since the imported semantic return map to the
1764+
// completion callback's argument(s).
1765+
if (!foreignInfo.error) {
1766+
auto &C = substFormalResultType->getASTContext();
17711767
substFormalResultType = TupleType::getEmpty(C);
17721768
origResultType = AbstractionPattern(genericSig, substFormalResultType);
17731769
return;
17741770
}
1775-
1771+
17761772
// Otherwise, adjust the return type to match the foreign error convention.
1777-
auto convention = *foreignInfo.Error;
1773+
auto convention = *foreignInfo.error;
17781774
switch (convention.getKind()) {
17791775
// These conventions replace the result type.
17801776
case ForeignErrorConvention::ZeroResult:
17811777
case ForeignErrorConvention::NonZeroResult:
1782-
assert(substFormalResultType->isVoid());
1778+
assert(substFormalResultType->isVoid() || foreignInfo.async);
17831779
substFormalResultType = convention.getResultType();
17841780
origResultType = AbstractionPattern(genericSig, substFormalResultType);
17851781
return;
@@ -2086,27 +2082,25 @@ static CanSILFunctionType getSILFunctionType(
20862082

20872083
Optional<SILResultInfo> errorResult;
20882084
assert(
2089-
(!foreignInfo.Error || substFnInterfaceType->getExtInfo().isThrowing())
2090-
&& "foreignError was set but function type does not throw?");
2091-
assert(
2092-
(!foreignInfo.Async || substFnInterfaceType->getExtInfo().isAsync())
2093-
&& "foreignAsync was set but function type is not async?");
2085+
(!foreignInfo.error || substFnInterfaceType->getExtInfo().isThrowing()) &&
2086+
"foreignError was set but function type does not throw?");
2087+
assert((!foreignInfo.async || substFnInterfaceType->getExtInfo().isAsync()) &&
2088+
"foreignAsync was set but function type is not async?");
20942089

20952090
// Map '@Sendable' to the appropriate `@Sendable` modifier.
20962091
bool isSendable = substFnInterfaceType->getExtInfo().isSendable();
20972092

20982093
// Map 'async' to the appropriate `@async` modifier.
20992094
bool isAsync = false;
2100-
if (substFnInterfaceType->getExtInfo().isAsync() && !foreignInfo.Async) {
2095+
if (substFnInterfaceType->getExtInfo().isAsync() && !foreignInfo.async) {
21012096
assert(!origType.isForeign()
21022097
&& "using native Swift async for foreign type!");
21032098
isAsync = true;
21042099
}
2105-
2100+
21062101
// Map 'throws' to the appropriate error convention.
2107-
if (substFnInterfaceType->getExtInfo().isThrowing()
2108-
&& !foreignInfo.Error
2109-
&& !foreignInfo.Async) {
2102+
if (substFnInterfaceType->getExtInfo().isThrowing() && !foreignInfo.error &&
2103+
!foreignInfo.async) {
21102104
assert(!origType.isForeign()
21112105
&& "using native Swift error convention for foreign type!");
21122106
SILType exnType = SILType::getExceptionType(TC.Context);
@@ -2892,20 +2886,21 @@ static CanSILFunctionType getSILFunctionTypeForClangDecl(
28922886
SILExtInfoBuilder extInfoBuilder, const ForeignInfo &foreignInfo,
28932887
Optional<SILDeclRef> constant) {
28942888
if (auto method = dyn_cast<clang::ObjCMethodDecl>(clangDecl)) {
2895-
auto origPattern =
2896-
AbstractionPattern::getObjCMethod(origType, method,
2897-
foreignInfo.Error,
2898-
foreignInfo.Async);
2889+
auto origPattern = AbstractionPattern::getObjCMethod(
2890+
origType, method, foreignInfo.error, foreignInfo.async);
28992891
return getSILFunctionType(
29002892
TC, TypeExpansionContext::minimal(), origPattern, substInterfaceType,
29012893
extInfoBuilder, ObjCMethodConventions(method), foreignInfo, constant,
29022894
constant, None, ProtocolConformanceRef());
29032895
}
29042896

29052897
if (auto method = dyn_cast<clang::CXXMethodDecl>(clangDecl)) {
2906-
AbstractionPattern origPattern = method->isOverloadedOperator() ?
2907-
AbstractionPattern::getCXXOperatorMethod(origType, method, foreignInfo.Self):
2908-
AbstractionPattern::getCXXMethod(origType, method, foreignInfo.Self);
2898+
AbstractionPattern origPattern =
2899+
method->isOverloadedOperator()
2900+
? AbstractionPattern::getCXXOperatorMethod(origType, method,
2901+
foreignInfo.self)
2902+
: AbstractionPattern::getCXXMethod(origType, method,
2903+
foreignInfo.self);
29092904
bool isMutating =
29102905
TC.Context.getClangModuleLoader()->isCXXMethodMutating(method);
29112906
auto conventions = CXXMethodConventions(method, isMutating);
@@ -2918,10 +2913,10 @@ static CanSILFunctionType getSILFunctionTypeForClangDecl(
29182913
if (auto func = dyn_cast<clang::FunctionDecl>(clangDecl)) {
29192914
auto clangType = func->getType().getTypePtr();
29202915
AbstractionPattern origPattern =
2921-
foreignInfo.Self.isImportAsMember()
2922-
? AbstractionPattern::getCFunctionAsMethod(origType, clangType,
2923-
foreignInfo.Self)
2924-
: AbstractionPattern(origType, clangType);
2916+
foreignInfo.self.isImportAsMember()
2917+
? AbstractionPattern::getCFunctionAsMethod(origType, clangType,
2918+
foreignInfo.self)
2919+
: AbstractionPattern(origType, clangType);
29252920
return getSILFunctionType(TC, TypeExpansionContext::minimal(), origPattern,
29262921
substInterfaceType, extInfoBuilder,
29272922
CFunctionConventions(func), foreignInfo, constant,
@@ -3214,10 +3209,10 @@ static CanSILFunctionType getUncachedSILFunctionTypeForConstant(
32143209
// import-as-member but do involve the same gymnastics with the
32153210
// formal type. That's all that SILFunctionType cares about, so
32163211
// pretend that it's import-as-member.
3217-
if (!foreignInfo.Self.isImportAsMember() &&
3212+
if (!foreignInfo.self.isImportAsMember() &&
32183213
isImporterGeneratedAccessor(clangDecl, constant)) {
32193214
unsigned selfIndex = cast<AccessorDecl>(decl)->isSetter() ? 1 : 0;
3220-
foreignInfo.Self.setSelfIndex(selfIndex);
3215+
foreignInfo.self.setSelfIndex(selfIndex);
32213216
}
32223217

32233218
return getSILFunctionTypeForClangDecl(

lib/SILGen/Callee.h

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "swift/AST/ForeignAsyncConvention.h"
1717
#include "swift/AST/ForeignErrorConvention.h"
18+
#include "swift/AST/ForeignInfo.h"
1819
#include "swift/AST/Types.h"
1920
#include "swift/SIL/AbstractionPattern.h"
2021

@@ -27,11 +28,6 @@ class CalleeTypeInfo {
2728
CanSILFunctionType substFnType;
2829
Optional<AbstractionPattern> origResultType;
2930
CanType substResultType;
30-
struct ForeignInfo {
31-
Optional<ForeignErrorConvention> error;
32-
Optional<ForeignAsyncConvention> async;
33-
ImportAsMemberStatus self;
34-
};
3531
ForeignInfo foreign;
3632

3733
private:
@@ -48,8 +44,8 @@ class CalleeTypeInfo {
4844
Optional<SILFunctionTypeRepresentation> overrideRep = None)
4945
: origFormalType(llvm::None), substFnType(substFnType),
5046
origResultType(origResultType),
51-
substResultType(substResultType), foreign{foreignError, foreignAsync,
52-
foreignSelf},
47+
substResultType(substResultType), foreign{foreignSelf, foreignError,
48+
foreignAsync},
5349
overrideRep(overrideRep) {}
5450

5551
CalleeTypeInfo(CanSILFunctionType substFnType,

0 commit comments

Comments
 (0)