@@ -1782,7 +1782,76 @@ void AttributeChecker::visitUIApplicationMainAttr(UIApplicationMainAttr *attr) {
17821782 C.getIdentifier (" UIApplicationMain" ));
17831783}
17841784
1785- void AttributeChecker::visitMainTypeAttr (MainTypeAttr *attr) {
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+
1846+ FuncDecl *
1847+ SynthesizeMainFunctionRequest::evaluate (Evaluator &evaluator,
1848+ Decl *D) const {
1849+ auto &context = D->getASTContext ();
1850+
1851+ MainTypeAttr *attr = D->getAttrs ().getAttribute <MainTypeAttr>();
1852+ if (attr == nullptr )
1853+ return nullptr ;
1854+
17861855 auto *extension = dyn_cast<ExtensionDecl>(D);
17871856
17881857 IterableDeclContext *iterableDeclContext;
@@ -1802,25 +1871,19 @@ void AttributeChecker::visitMainTypeAttr(MainTypeAttr *attr) {
18021871 braces = nominal->getBraces ();
18031872 }
18041873
1805- if (!nominal) {
1806- assert (false && " Should have already recognized that the MainType decl "
1874+ assert (nominal && " Should have already recognized that the MainType decl "
18071875 " isn't applicable to decls other than NominalTypeDecls" );
1808- return ;
1809- }
18101876 assert (iterableDeclContext);
18111877 assert (declContext);
18121878
18131879 // The type cannot be generic.
18141880 if (nominal->isGenericContext ()) {
1815- diagnose (attr->getLocation (),
1816- diag::attr_generic_ApplicationMain_not_supported, 2 );
1881+ context. Diags . diagnose (attr->getLocation (),
1882+ diag::attr_generic_ApplicationMain_not_supported, 2 );
18171883 attr->setInvalid ();
1818- return ;
1884+ return nullptr ;
18191885 }
18201886
1821- SourceFile *file = cast<SourceFile>(declContext->getModuleScopeContext ());
1822- assert (file);
1823-
18241887 // Create a function
18251888 //
18261889 // func $main() {
@@ -1832,8 +1895,6 @@ void AttributeChecker::visitMainTypeAttr(MainTypeAttr *attr) {
18321895 // usual type-checking. The alternative would be to directly call
18331896 // mainType.main() from the entry point, and that would require fully
18341897 // type-checking the call to mainType.main().
1835- auto &context = D->getASTContext ();
1836- auto location = attr->getLocation ();
18371898
18381899 auto resolution = resolveValueMember (
18391900 *declContext, nominal->getInterfaceType (), context.Id_main );
@@ -1861,107 +1922,52 @@ void AttributeChecker::visitMainTypeAttr(MainTypeAttr *attr) {
18611922 }
18621923
18631924 if (viableCandidates.size () != 1 ) {
1864- diagnose (attr->getLocation (), diag::attr_MainType_without_main,
1865- nominal->getBaseName ());
1925+ context.Diags .diagnose (attr->getLocation (),
1926+ diag::attr_MainType_without_main,
1927+ nominal->getBaseName ());
18661928 attr->setInvalid ();
1867- return ;
1929+ return nullptr ;
18681930 }
18691931 mainFunction = viableCandidates[0 ];
18701932 }
18711933
1872- bool mainFunctionThrows = mainFunction->hasThrows ();
1873-
1874- auto voidToVoidFunctionType =
1875- FunctionType::get ({}, context.TheEmptyTupleType ,
1876- FunctionType::ExtInfo ().withThrows (mainFunctionThrows));
1877- auto nominalToVoidToVoidFunctionType = FunctionType::get ({AnyFunctionType::Param (nominal->getInterfaceType ())}, voidToVoidFunctionType);
18781934 auto *func = FuncDecl::create (
18791935 context, /* StaticLoc*/ SourceLoc (), StaticSpellingKind::KeywordStatic,
18801936 /* FuncLoc*/ SourceLoc (),
18811937 DeclName (context, DeclBaseName (context.Id_MainEntryPoint ),
18821938 ParameterList::createEmpty (context)),
1883- /* NameLoc*/ SourceLoc (), /* Throws=*/ mainFunctionThrows ,
1939+ /* NameLoc*/ SourceLoc (), /* Throws=*/ mainFunction-> hasThrows () ,
18841940 /* ThrowsLoc=*/ SourceLoc (),
18851941 /* GenericParams=*/ nullptr , ParameterList::createEmpty (context),
18861942 /* FnRetType=*/ TypeLoc::withoutLoc (TupleType::getEmpty (context)),
18871943 declContext);
18881944 func->setImplicit (true );
18891945 func->setSynthesized (true );
18901946
1891- auto *typeExpr = TypeExpr::createImplicit (nominal->getDeclaredType (), context);
1892-
1893- SubstitutionMap substitutionMap;
1894- if (auto *environment = mainFunction->getGenericEnvironment ()) {
1895- substitutionMap = SubstitutionMap::get (
1896- environment->getGenericSignature (),
1897- [&](SubstitutableType *type) { return nominal->getDeclaredType (); },
1898- LookUpConformanceInModule (nominal->getModuleContext ()));
1899- } else {
1900- substitutionMap = SubstitutionMap ();
1901- }
1902-
1903- auto funcDeclRef = ConcreteDeclRef (mainFunction, substitutionMap);
1904-
1905- auto *memberRefExpr = new (context) MemberRefExpr (
1906- typeExpr, SourceLoc (), funcDeclRef, DeclNameLoc (location),
1907- /* Implicit*/ true );
1908- memberRefExpr->setImplicit (true );
1909-
1910- auto *callExpr = CallExpr::createImplicit (context, memberRefExpr, {}, {});
1911- callExpr->setImplicit (true );
1912- callExpr->setThrows (mainFunctionThrows);
1913- callExpr->setType (context.TheEmptyTupleType );
1914-
1915- Expr *returnedExpr;
1947+ auto *params = context.Allocate <MainTypeAttrParams>();
1948+ params->mainFunction = mainFunction;
1949+ params->attr = attr;
1950+ func->setBodySynthesizer (synthesizeMainBody, params);
19161951
1917- if (mainFunctionThrows) {
1918- auto *tryExpr = new (context) TryExpr (
1919- SourceLoc (), callExpr, context.TheEmptyTupleType , /* implicit=*/ true );
1920- returnedExpr = tryExpr;
1921- } else {
1922- returnedExpr = callExpr;
1923- }
1952+ iterableDeclContext->addMember (func);
19241953
1925- auto *returnStmt =
1926- new (context) ReturnStmt ( SourceLoc (), callExpr, /* Implicit= */ true );
1954+ return func;
1955+ }
19271956
1928- SmallVector<ASTNode, 1 > stmts;
1929- stmts.push_back (returnStmt);
1930- auto *body = BraceStmt::create (context, SourceLoc (), stmts,
1931- SourceLoc (), /* Implicit*/ true );
1932- func->setBodyParsed (body);
1933- func->setInterfaceType (nominalToVoidToVoidFunctionType);
1957+ void AttributeChecker::visitMainTypeAttr (MainTypeAttr *attr) {
1958+ auto &context = D->getASTContext ();
19341959
1935- iterableDeclContext->addMember (func);
1960+ SourceFile *file = D->getDeclContext ()->getParentSourceFile ();
1961+ assert (file);
19361962
1937- // This function must be type-checked. Why? Consider the following scenario:
1938- //
1939- // protocol AlmostMainable {}
1940- // protocol ReallyMainable {}
1941- // extension AlmostMainable where Self : ReallyMainable {
1942- // static func main() {}
1943- // }
1944- // @main struct Main : AlmostMainable {}
1945- //
1946- // Note in particular that Main does not conform to ReallyMainable.
1947- //
1948- // In this case, resolveValueMember will find the function main in the
1949- // extension, and so, since there is one candidate, the function $main will
1950- // accordingly be formed as usual:
1951- //
1952- // func $main() {
1953- // return Main.main()
1954- // }
1955- //
1956- // Of course, this function's body does not type-check.
1957- file->DelayedFunctions .push_back (func);
1963+ auto *func = evaluateOrDefault (context.evaluator ,
1964+ SynthesizeMainFunctionRequest{D},
1965+ nullptr );
19581966
19591967 // Register the func as the main decl in the module. If there are multiples
19601968 // they will be diagnosed.
1961- if (file->registerMainDecl (func, attr->getLocation ())) {
1969+ if (file->registerMainDecl (func, attr->getLocation ()))
19621970 attr->setInvalid ();
1963- return ;
1964- }
19651971}
19661972
19671973// / Determine whether the given context is an extension to an Objective-C class
0 commit comments