From b84df92b702ccdfc27bbc2ffdab4f79d79e1f337 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 26 Oct 2023 22:46:39 -0400 Subject: [PATCH] SIL: Type lowering support for indirect error results --- lib/SIL/IR/AbstractionPattern.cpp | 18 ++++++++-- lib/SIL/IR/SILFunctionType.cpp | 56 +++++++++++++++++-------------- 2 files changed, 46 insertions(+), 28 deletions(-) diff --git a/lib/SIL/IR/AbstractionPattern.cpp b/lib/SIL/IR/AbstractionPattern.cpp index 7a1c7ec4b49..aee5dbc08c1 100644 --- a/lib/SIL/IR/AbstractionPattern.cpp +++ b/lib/SIL/IR/AbstractionPattern.cpp @@ -2627,14 +2627,28 @@ public: if (yieldType) { substYieldType = visit(yieldType, yieldPattern); } - + + CanType newErrorType; + + if (auto optPair = pattern.getFunctionThrownErrorType(func)) { + auto errorPattern = optPair->first; + auto errorType = optPair->second; + newErrorType = visit(errorType, errorPattern); + } + auto newResultTy = visit(func.getResult(), pattern.getFunctionResultType()); llvm::Optional extInfo; if (func->hasExtInfo()) extInfo = func->getExtInfo(); - + + if (newErrorType) { + if (!extInfo) + extInfo = FunctionType::ExtInfo(); + extInfo = extInfo->withThrows(true, newErrorType); + } + return CanFunctionType::get(FunctionType::CanParamArrayRef(newParams), newResultTy, extInfo); } diff --git a/lib/SIL/IR/SILFunctionType.cpp b/lib/SIL/IR/SILFunctionType.cpp index ca784bace84..7fe91d0f66f 100644 --- a/lib/SIL/IR/SILFunctionType.cpp +++ b/lib/SIL/IR/SILFunctionType.cpp @@ -2190,32 +2190,6 @@ static CanSILFunctionType getSILFunctionType( isAsync = true; } - // Map 'throws' to the appropriate error convention. - // Give the type an error argument whether the substituted type semantically - // `throws` or if the abstraction pattern specifies a Swift function type - // that also throws. This prevents the need for a second possibly-thunking - // conversion when using a non-throwing function in more abstract throwing - // context. - bool isThrowing = substFnInterfaceType->getExtInfo().isThrowing(); - if (auto origFnType = origType.getAs()) { - isThrowing |= origFnType->getExtInfo().isThrowing(); - } - if (isThrowing && !foreignInfo.error && - !foreignInfo.async) { - assert(!origType.isForeign() - && "using native Swift error convention for foreign type!"); - SILType exnType; - if (CanType thrownError = substFnInterfaceType.getThrownError()) { - exnType = TC.getLoweredType(thrownError, expansionContext); - } else { - // Untyped error throws the exception type. - exnType = SILType::getExceptionType(TC.Context); - } - assert(exnType.isObject()); - errorResult = SILResultInfo(exnType.getASTType(), - ResultConvention::Owned); - } - // Get the yield type for an accessor coroutine. SILCoroutineKind coroutineKind = SILCoroutineKind::None; AbstractionPattern coroutineOrigYieldType = AbstractionPattern::getInvalid(); @@ -2308,6 +2282,36 @@ static CanSILFunctionType getSILFunctionType( } } + // Map 'throws' to the appropriate error convention. + // Give the type an error argument whether the substituted type semantically + // `throws` or if the abstraction pattern specifies a Swift function type + // that also throws. This prevents the need for a second possibly-thunking + // conversion when using a non-throwing function in more abstract throwing + // context. + bool isThrowing = substFnInterfaceType->getExtInfo().isThrowing(); + if (auto origFnType = origType.getAs()) { + isThrowing |= origFnType->getExtInfo().isThrowing(); + } + + if (isThrowing && !foreignInfo.error && + !foreignInfo.async) { + assert(!origType.isForeign() + && "using native Swift error convention for foreign type!"); + auto optPair = origType.getFunctionThrownErrorType(substFnInterfaceType); + assert(optPair && + "Lowering a throwing function type against non-throwing pattern"); + + auto origErrorType = optPair->first; + auto errorType = optPair->second; + auto &errorTLConv = TC.getTypeLowering(origErrorType, errorType, + TypeExpansionContext::minimal()); + + errorResult = SILResultInfo(errorTLConv.getLoweredType().getASTType(), + errorTLConv.isAddressOnly() + ? ResultConvention::Indirect + : ResultConvention::Owned); + } + // Lower the result type. AbstractionPattern origResultType = origType.getFunctionResultType(); CanType substFormalResultType = substFnInterfaceType.getResult();