[Typed throws] Location based lookup for the thrown error type

Introduce a new API to find the AST node that catches or rethrows an
error thrown from the given source location. Use it to determine the
thrown error type to use for type checking a `throw` statement, which
begins as `any Error` within a `do..catch` and is later refined.
This commit is contained in:
Doug Gregor
2023-10-15 14:33:04 -07:00
parent 7e9013dd52
commit 3dd4df2351
9 changed files with 226 additions and 9 deletions

View File

@@ -712,3 +712,30 @@ void ASTScopeImpl::lookupEnclosingMacroScope(
} while ((scope = scope->getParent().getPtrOrNull()));
}
CatchNode ASTScopeImpl::lookupCatchNode(ModuleDecl *module, SourceLoc loc) {
auto sourceFile = module->getSourceFileContainingLocation(loc);
if (!sourceFile)
return nullptr;
auto *fileScope = sourceFile->getScope().impl;
const auto *innermost = fileScope->findInnermostEnclosingScope(
module, loc, nullptr);
ASTScopeAssert(innermost->getWasExpanded(),
"If looking in a scope, it must have been expanded.");
// Look for a body scope that's the
const BraceStmtScope *innerBodyScope = nullptr;
for (auto scope = innermost; scope; scope = scope->getParent().getPtrOrNull()) {
// If we are at a catch node and in the body of the region from which that
// node catches thrown errors, we have our result.
auto caught = scope->getCatchNodeBody();
if (caught.first && caught.second == innerBodyScope) {
return caught.first;
}
innerBodyScope = scope->getAsBraceStmtScope().getPtrOrNull();
}
return nullptr;
}