[Typed throws] Basic SIL lowering and SIL generation for typed throws

Lower the thrown error type into the SIL function type. This requires
very little code because the thrown error type was already modeled as
a SILResultInfo, which carries type information. Note that this
lowering does not yet account for error types that need to passed
indirectly, but we will need to do so for (e.g.) using resilient error
types.

Teach a few places in SIL generation not to assume that thrown types
are always the existential error type, which primarily comes down to
ensuring that rethrow epilogues have the thrown type of the
corresponding function or closure.

Teach throw emission to implicitly box concrete thrown errors in the
error existential when needed to satisfy the throw destination. This
is a temporary solution that helps translate typed throws into untyped
throws, but it should be replaced by a better modeling within the AST
of the points at which thrown errors are converted.
This commit is contained in:
Doug Gregor
2023-09-22 10:22:28 -07:00
parent 31b8811167
commit b6b999abd4
18 changed files with 232 additions and 34 deletions

View File

@@ -1051,7 +1051,7 @@ void SILGenFunction::emitFunction(FuncDecl *fd) {
emitDistributedActorFactory(fd);
} else {
prepareEpilog(fd->getResultInterfaceType(),
fd->hasThrows(), CleanupLocation(fd));
fd->getEffectiveThrownInterfaceType(), CleanupLocation(fd));
if (fd->requiresUnavailableDeclABICompatibilityStubs())
emitApplyOfUnavailableCodeReached();
@@ -1077,7 +1077,8 @@ void SILGenFunction::emitClosure(AbstractClosureExpr *ace) {
emitProlog(captureInfo, ace->getParameters(), /*selfParam=*/nullptr,
ace, resultIfaceTy, ace->isBodyThrowing(), ace->getLoc(),
OrigFnType);
prepareEpilog(resultIfaceTy, ace->isBodyThrowing(), CleanupLocation(ace));
prepareEpilog(resultIfaceTy, ace->getEffectiveThrownType(),
CleanupLocation(ace));
emitProfilerIncrement(ace);
if (auto *ce = dyn_cast<ClosureExpr>(ace)) {
@@ -1559,7 +1560,7 @@ void SILGenFunction::emitGeneratorFunction(SILDeclRef function, Expr *value,
// been recorded for this expression, not the sub-expression.
emitProfilerIncrement(topLevelValue);
}
prepareEpilog(interfaceType, false, CleanupLocation(Loc));
prepareEpilog(interfaceType, llvm::None, CleanupLocation(Loc));
{
llvm::Optional<SILGenFunction::OpaqueValueRAII> opaqueValue;
@@ -1622,7 +1623,7 @@ void SILGenFunction::emitGeneratorFunction(SILDeclRef function, VarDecl *var) {
emitBasicProlog(/*paramList*/ nullptr, /*selfParam*/ nullptr,
interfaceType, dc, /*throws=*/ false,SourceLoc(),
/*ignored parameters*/ 0);
prepareEpilog(interfaceType, false, CleanupLocation(loc));
prepareEpilog(interfaceType, llvm::None, CleanupLocation(loc));
auto pbd = var->getParentPatternBinding();
const auto i = pbd->getPatternEntryIndexForVarDecl(var);
@@ -1678,7 +1679,7 @@ void SILGenFunction::emitGeneratorFunction(
/*selfParam=*/nullptr, dc, resultInterfaceType, /*throws=*/false,
SourceLoc(), pattern);
prepareEpilog(resultInterfaceType, /*hasThrows=*/false, CleanupLocation(loc));
prepareEpilog(resultInterfaceType, llvm::None, CleanupLocation(loc));
emitStmt(body);