@@ -1782,7 +1782,76 @@ void AttributeChecker::visitUIApplicationMainAttr(UIApplicationMainAttr *attr) {
1782
1782
C.getIdentifier (" UIApplicationMain" ));
1783
1783
}
1784
1784
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
+
1786
1855
auto *extension = dyn_cast<ExtensionDecl>(D);
1787
1856
1788
1857
IterableDeclContext *iterableDeclContext;
@@ -1802,25 +1871,19 @@ void AttributeChecker::visitMainTypeAttr(MainTypeAttr *attr) {
1802
1871
braces = nominal->getBraces ();
1803
1872
}
1804
1873
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 "
1807
1875
" isn't applicable to decls other than NominalTypeDecls" );
1808
- return ;
1809
- }
1810
1876
assert (iterableDeclContext);
1811
1877
assert (declContext);
1812
1878
1813
1879
// The type cannot be generic.
1814
1880
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 );
1817
1883
attr->setInvalid ();
1818
- return ;
1884
+ return nullptr ;
1819
1885
}
1820
1886
1821
- SourceFile *file = cast<SourceFile>(declContext->getModuleScopeContext ());
1822
- assert (file);
1823
-
1824
1887
// Create a function
1825
1888
//
1826
1889
// func $main() {
@@ -1832,8 +1895,6 @@ void AttributeChecker::visitMainTypeAttr(MainTypeAttr *attr) {
1832
1895
// usual type-checking. The alternative would be to directly call
1833
1896
// mainType.main() from the entry point, and that would require fully
1834
1897
// type-checking the call to mainType.main().
1835
- auto &context = D->getASTContext ();
1836
- auto location = attr->getLocation ();
1837
1898
1838
1899
auto resolution = resolveValueMember (
1839
1900
*declContext, nominal->getInterfaceType (), context.Id_main );
@@ -1861,107 +1922,52 @@ void AttributeChecker::visitMainTypeAttr(MainTypeAttr *attr) {
1861
1922
}
1862
1923
1863
1924
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 ());
1866
1928
attr->setInvalid ();
1867
- return ;
1929
+ return nullptr ;
1868
1930
}
1869
1931
mainFunction = viableCandidates[0 ];
1870
1932
}
1871
1933
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);
1878
1934
auto *func = FuncDecl::create (
1879
1935
context, /* StaticLoc*/ SourceLoc (), StaticSpellingKind::KeywordStatic,
1880
1936
/* FuncLoc*/ SourceLoc (),
1881
1937
DeclName (context, DeclBaseName (context.Id_MainEntryPoint ),
1882
1938
ParameterList::createEmpty (context)),
1883
- /* NameLoc*/ SourceLoc (), /* Throws=*/ mainFunctionThrows ,
1939
+ /* NameLoc*/ SourceLoc (), /* Throws=*/ mainFunction-> hasThrows () ,
1884
1940
/* ThrowsLoc=*/ SourceLoc (),
1885
1941
/* GenericParams=*/ nullptr , ParameterList::createEmpty (context),
1886
1942
/* FnRetType=*/ TypeLoc::withoutLoc (TupleType::getEmpty (context)),
1887
1943
declContext);
1888
1944
func->setImplicit (true );
1889
1945
func->setSynthesized (true );
1890
1946
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);
1916
1951
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);
1924
1953
1925
- auto *returnStmt =
1926
- new (context) ReturnStmt ( SourceLoc (), callExpr, /* Implicit= */ true );
1954
+ return func;
1955
+ }
1927
1956
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 ();
1934
1959
1935
- iterableDeclContext->addMember (func);
1960
+ SourceFile *file = D->getDeclContext ()->getParentSourceFile ();
1961
+ assert (file);
1936
1962
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 );
1958
1966
1959
1967
// Register the func as the main decl in the module. If there are multiples
1960
1968
// they will be diagnosed.
1961
- if (file->registerMainDecl (func, attr->getLocation ())) {
1969
+ if (file->registerMainDecl (func, attr->getLocation ()))
1962
1970
attr->setInvalid ();
1963
- return ;
1964
- }
1965
1971
}
1966
1972
1967
1973
// / Determine whether the given context is an extension to an Objective-C class
0 commit comments