Skip to content

Commit 56a0b82

Browse files
committed
Sema: Lazily synthesize body of main function
1 parent 1ac9acb commit 56a0b82

File tree

1 file changed

+67
-50
lines changed

1 file changed

+67
-50
lines changed

lib/Sema/TypeCheckAttr.cpp

Lines changed: 67 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1782,6 +1782,67 @@ void AttributeChecker::visitUIApplicationMainAttr(UIApplicationMainAttr *attr) {
17821782
C.getIdentifier("UIApplicationMain"));
17831783
}
17841784

1785+
namespace {
1786+
struct MainTypeAttrParams {
1787+
FuncDecl *mainFunction;
1788+
MainTypeAttr *attr;
1789+
};
1790+
1791+
}
1792+
static std::pair<BraceStmt *, bool>
1793+
synthesizeMainBody(AbstractFunctionDecl *fn, void *arg) {
1794+
ASTContext &context = fn->getASTContext();
1795+
MainTypeAttrParams *params = (MainTypeAttrParams *) arg;
1796+
1797+
FuncDecl *mainFunction = params->mainFunction;
1798+
auto location = params->attr->getLocation();
1799+
NominalTypeDecl *nominal = fn->getDeclContext()->getSelfNominalTypeDecl();
1800+
1801+
auto *typeExpr = TypeExpr::createImplicit(nominal->getDeclaredType(), context);
1802+
1803+
SubstitutionMap substitutionMap;
1804+
if (auto *environment = mainFunction->getGenericEnvironment()) {
1805+
substitutionMap = SubstitutionMap::get(
1806+
environment->getGenericSignature(),
1807+
[&](SubstitutableType *type) { return nominal->getDeclaredType(); },
1808+
LookUpConformanceInModule(nominal->getModuleContext()));
1809+
} else {
1810+
substitutionMap = SubstitutionMap();
1811+
}
1812+
1813+
auto funcDeclRef = ConcreteDeclRef(mainFunction, substitutionMap);
1814+
1815+
auto *memberRefExpr = new (context) MemberRefExpr(
1816+
typeExpr, SourceLoc(), funcDeclRef, DeclNameLoc(location),
1817+
/*Implicit*/ true);
1818+
memberRefExpr->setImplicit(true);
1819+
1820+
auto *callExpr = CallExpr::createImplicit(context, memberRefExpr, {}, {});
1821+
callExpr->setImplicit(true);
1822+
callExpr->setThrows(mainFunction->hasThrows());
1823+
callExpr->setType(context.TheEmptyTupleType);
1824+
1825+
Expr *returnedExpr;
1826+
1827+
if (mainFunction->hasThrows()) {
1828+
auto *tryExpr = new (context) TryExpr(
1829+
SourceLoc(), callExpr, context.TheEmptyTupleType, /*implicit=*/true);
1830+
returnedExpr = tryExpr;
1831+
} else {
1832+
returnedExpr = callExpr;
1833+
}
1834+
1835+
auto *returnStmt =
1836+
new (context) ReturnStmt(SourceLoc(), callExpr, /*Implicit=*/true);
1837+
1838+
SmallVector<ASTNode, 1> stmts;
1839+
stmts.push_back(returnStmt);
1840+
auto *body = BraceStmt::create(context, SourceLoc(), stmts,
1841+
SourceLoc(), /*Implicit*/true);
1842+
1843+
return std::make_pair(body, /*typechecked=*/false);
1844+
}
1845+
17851846
void AttributeChecker::visitMainTypeAttr(MainTypeAttr *attr) {
17861847
auto *extension = dyn_cast<ExtensionDecl>(D);
17871848

@@ -1802,11 +1863,8 @@ void AttributeChecker::visitMainTypeAttr(MainTypeAttr *attr) {
18021863
braces = nominal->getBraces();
18031864
}
18041865

1805-
if (!nominal) {
1806-
assert(false && "Should have already recognized that the MainType decl "
1866+
assert(nominal && "Should have already recognized that the MainType decl "
18071867
"isn't applicable to decls other than NominalTypeDecls");
1808-
return;
1809-
}
18101868
assert(iterableDeclContext);
18111869
assert(declContext);
18121870

@@ -1833,7 +1891,6 @@ void AttributeChecker::visitMainTypeAttr(MainTypeAttr *attr) {
18331891
// mainType.main() from the entry point, and that would require fully
18341892
// type-checking the call to mainType.main().
18351893
auto &context = D->getASTContext();
1836-
auto location = attr->getLocation();
18371894

18381895
auto resolution = resolveValueMember(
18391896
*declContext, nominal->getInterfaceType(), context.Id_main);
@@ -1869,63 +1926,23 @@ void AttributeChecker::visitMainTypeAttr(MainTypeAttr *attr) {
18691926
mainFunction = viableCandidates[0];
18701927
}
18711928

1872-
bool mainFunctionThrows = mainFunction->hasThrows();
1873-
18741929
auto *func = FuncDecl::create(
18751930
context, /*StaticLoc*/ SourceLoc(), StaticSpellingKind::KeywordStatic,
18761931
/*FuncLoc*/ SourceLoc(),
18771932
DeclName(context, DeclBaseName(context.Id_MainEntryPoint),
18781933
ParameterList::createEmpty(context)),
1879-
/*NameLoc*/ SourceLoc(), /*Throws=*/mainFunctionThrows,
1934+
/*NameLoc*/ SourceLoc(), /*Throws=*/mainFunction->hasThrows(),
18801935
/*ThrowsLoc=*/SourceLoc(),
18811936
/*GenericParams=*/nullptr, ParameterList::createEmpty(context),
18821937
/*FnRetType=*/TypeLoc::withoutLoc(TupleType::getEmpty(context)),
18831938
declContext);
18841939
func->setImplicit(true);
18851940
func->setSynthesized(true);
18861941

1887-
auto *typeExpr = TypeExpr::createImplicit(nominal->getDeclaredType(), context);
1888-
1889-
SubstitutionMap substitutionMap;
1890-
if (auto *environment = mainFunction->getGenericEnvironment()) {
1891-
substitutionMap = SubstitutionMap::get(
1892-
environment->getGenericSignature(),
1893-
[&](SubstitutableType *type) { return nominal->getDeclaredType(); },
1894-
LookUpConformanceInModule(nominal->getModuleContext()));
1895-
} else {
1896-
substitutionMap = SubstitutionMap();
1897-
}
1898-
1899-
auto funcDeclRef = ConcreteDeclRef(mainFunction, substitutionMap);
1900-
1901-
auto *memberRefExpr = new (context) MemberRefExpr(
1902-
typeExpr, SourceLoc(), funcDeclRef, DeclNameLoc(location),
1903-
/*Implicit*/ true);
1904-
memberRefExpr->setImplicit(true);
1905-
1906-
auto *callExpr = CallExpr::createImplicit(context, memberRefExpr, {}, {});
1907-
callExpr->setImplicit(true);
1908-
callExpr->setThrows(mainFunctionThrows);
1909-
callExpr->setType(context.TheEmptyTupleType);
1910-
1911-
Expr *returnedExpr;
1912-
1913-
if (mainFunctionThrows) {
1914-
auto *tryExpr = new (context) TryExpr(
1915-
SourceLoc(), callExpr, context.TheEmptyTupleType, /*implicit=*/true);
1916-
returnedExpr = tryExpr;
1917-
} else {
1918-
returnedExpr = callExpr;
1919-
}
1920-
1921-
auto *returnStmt =
1922-
new (context) ReturnStmt(SourceLoc(), callExpr, /*Implicit=*/true);
1923-
1924-
SmallVector<ASTNode, 1> stmts;
1925-
stmts.push_back(returnStmt);
1926-
auto *body = BraceStmt::create(context, SourceLoc(), stmts,
1927-
SourceLoc(), /*Implicit*/true);
1928-
func->setBodyParsed(body);
1942+
auto *params = context.Allocate<MainTypeAttrParams>();
1943+
params->mainFunction = mainFunction;
1944+
params->attr = attr;
1945+
func->setBodySynthesizer(synthesizeMainBody, params);
19291946

19301947
iterableDeclContext->addMember(func);
19311948

0 commit comments

Comments
 (0)