[AST] Make function body synthesizers less stateful.

Instead of requiring that function body synthesizers will always call
setBody(), which is annoyingly stateful, have function body synthesizers
always return the synthesized brace statement along with a bit that
indicates whether the body was already type-checked. This takes us a
step closer to centralizing the mutation of the body of a function.
This commit is contained in:
Doug Gregor
2019-07-11 14:35:53 -07:00
parent 015b7c5266
commit 8117849d46
11 changed files with 238 additions and 220 deletions

View File

@@ -29,7 +29,8 @@ using namespace swift;
/// Sets the body of the given function to `return nil`.
///
/// \param funcDecl The function whose body to set.
static void deriveNilReturn(AbstractFunctionDecl *funcDecl, void *) {
static std::pair<BraceStmt *, bool>
deriveNilReturn(AbstractFunctionDecl *funcDecl, void *) {
auto *parentDC = funcDecl->getDeclContext();
auto &C = parentDC->getASTContext();
@@ -37,13 +38,14 @@ static void deriveNilReturn(AbstractFunctionDecl *funcDecl, void *) {
auto *returnStmt = new (C) ReturnStmt(SourceLoc(), nilExpr);
auto *body = BraceStmt::create(C, SourceLoc(), ASTNode(returnStmt),
SourceLoc());
funcDecl->setBody(body);
return { body, /*isTypeChecked=*/false };
}
/// Sets the body of the given function to `return self.rawValue`.
///
/// \param funcDecl The function whose body to set.
static void deriveRawValueReturn(AbstractFunctionDecl *funcDecl, void *) {
static std::pair<BraceStmt *, bool>
deriveRawValueReturn(AbstractFunctionDecl *funcDecl, void *) {
auto *parentDC = funcDecl->getDeclContext();
auto &C = parentDC->getASTContext();
@@ -55,14 +57,15 @@ static void deriveRawValueReturn(AbstractFunctionDecl *funcDecl, void *) {
auto *returnStmt = new (C) ReturnStmt(SourceLoc(), memberRef);
auto *body = BraceStmt::create(C, SourceLoc(), ASTNode(returnStmt),
SourceLoc());
funcDecl->setBody(body);
return { body, /*isTypeChecked=*/false };
}
/// Sets the body of the given function to `self.init(rawValue:)`, passing along
/// the parameter of the given constructor.
///
/// \param initDecl The constructor whose body to set.
static void deriveRawValueInit(AbstractFunctionDecl *initDecl, void *) {
static std::pair<BraceStmt *, bool>
deriveRawValueInit(AbstractFunctionDecl *initDecl, void *) {
auto *parentDC = initDecl->getDeclContext();
auto &C = parentDC->getASTContext();
@@ -96,7 +99,7 @@ static void deriveRawValueInit(AbstractFunctionDecl *initDecl, void *) {
auto *body = BraceStmt::create(C, SourceLoc(), ASTNode(callExpr),
SourceLoc());
initDecl->setBody(body);
return { body, /*isTypeChecked=*/false };
}
/// Synthesizes a constructor declaration with the given parameter name and
@@ -189,7 +192,7 @@ static ValueDecl *deriveProperty(DerivedConformance &derived, Type type,
/// switching on `self`.
///
/// \param strValDecl The function whose body to set.
static void
static std::pair<BraceStmt *, bool>
deriveBodyCodingKey_enum_stringValue(AbstractFunctionDecl *strValDecl, void *) {
// enum SomeEnum {
// case A, B, C
@@ -247,14 +250,14 @@ deriveBodyCodingKey_enum_stringValue(AbstractFunctionDecl *strValDecl, void *) {
body = BraceStmt::create(C, SourceLoc(), ASTNode(switchStmt), SourceLoc());
}
strValDecl->setBody(body);
return { body, /*isTypeChecked=*/false };
}
/// Sets the body of the given constructor to initialize `self` based on the
/// value of the given string param.
///
/// \param initDecl The function whose body to set.
static void
static std::pair<BraceStmt *, bool>
deriveBodyCodingKey_init_stringValue(AbstractFunctionDecl *initDecl, void *) {
// enum SomeEnum {
// case A, B, C
@@ -279,8 +282,7 @@ deriveBodyCodingKey_init_stringValue(AbstractFunctionDecl *initDecl, void *) {
auto elements = enumDecl->getAllElements();
if (elements.empty() /* empty enum */) {
deriveNilReturn(initDecl, nullptr);
return;
return deriveNilReturn(initDecl, nullptr);
}
auto *selfRef = DerivedConformance::createSelfDeclRef(initDecl);
@@ -327,7 +329,7 @@ deriveBodyCodingKey_init_stringValue(AbstractFunctionDecl *initDecl, void *) {
SourceLoc(), C);
auto *body = BraceStmt::create(C, SourceLoc(), ASTNode(switchStmt),
SourceLoc());
initDecl->setBody(body);
return { body, /*isTypeChecked=*/false };
}
/// Returns whether the given enum is eligible for CodingKey synthesis.