@@ -2096,28 +2096,6 @@ synthesizeMainBody(AbstractFunctionDecl *fn, void *arg) {
20962096 return std::make_pair (body, /* typechecked=*/ false );
20972097}
20982098
2099- static FuncDecl *resolveMainFunctionDecl (DeclContext *declContext,
2100- ResolvedMemberResult &resolution,
2101- ASTContext &ctx) {
2102- // Choose the best overload if it's a main function
2103- if (resolution.hasBestOverload ()) {
2104- ValueDecl *best = resolution.getBestOverload ();
2105- if (FuncDecl *func = dyn_cast<FuncDecl>(best)) {
2106- if (func->isMainTypeMainMethod ()) {
2107- return func;
2108- }
2109- }
2110- }
2111- // Look for the most highly-ranked main-function candidate
2112- for (ValueDecl *candidate : resolution.getMemberDecls (Viable)) {
2113- if (FuncDecl *func = dyn_cast<FuncDecl>(candidate)) {
2114- if (func->isMainTypeMainMethod ())
2115- return func;
2116- }
2117- }
2118- return nullptr ;
2119- }
2120-
21212099FuncDecl *
21222100SynthesizeMainFunctionRequest::evaluate (Evaluator &evaluator,
21232101 Decl *D) const {
@@ -2170,17 +2148,91 @@ SynthesizeMainFunctionRequest::evaluate(Evaluator &evaluator,
21702148 // usual type-checking. The alternative would be to directly call
21712149 // mainType.main() from the entry point, and that would require fully
21722150 // type-checking the call to mainType.main().
2151+ using namespace constraints ;
2152+ ConstraintSystem CS (declContext,
2153+ ConstraintSystemFlags::IgnoreAsyncSyncMismatch);
2154+ ConstraintLocator *locator =
2155+ CS.getConstraintLocator ({}, ConstraintLocator::Member);
2156+ // Allowed main function types
2157+ // `() -> Void`
2158+ // `() async -> Void`
2159+ // `() throws -> Void`
2160+ // `() async throws -> Void`
2161+ // `@MainActor () -> Void`
2162+ // `@MainActor () async -> Void`
2163+ // `@MainActor () throws -> Void`
2164+ // `@MainActor () async throws -> Void`
2165+ {
2166+ llvm::SmallVector<Type, 8 > mainTypes = {
2167+
2168+ FunctionType::get (/* params*/ {}, context.TheEmptyTupleType ,
2169+ ASTExtInfo ()),
2170+ FunctionType::get (
2171+ /* params*/ {}, context.TheEmptyTupleType ,
2172+ ASTExtInfoBuilder ().withAsync ().build ()),
2173+
2174+ FunctionType::get (/* params*/ {}, context.TheEmptyTupleType ,
2175+ ASTExtInfoBuilder ().withThrows ().build ()),
2176+
2177+ FunctionType::get (
2178+ /* params*/ {}, context.TheEmptyTupleType ,
2179+ ASTExtInfoBuilder ().withAsync ().withThrows ().build ())};
2180+
2181+ Type mainActor = context.getMainActorType ();
2182+ if (mainActor) {
2183+ mainTypes.push_back (FunctionType::get (
2184+ /* params*/ {}, context.TheEmptyTupleType ,
2185+ ASTExtInfoBuilder ().withGlobalActor (mainActor).build ()));
2186+ mainTypes.push_back (FunctionType::get (
2187+ /* params*/ {}, context.TheEmptyTupleType ,
2188+ ASTExtInfoBuilder ().withAsync ().withGlobalActor (mainActor).build ()));
2189+ mainTypes.push_back (FunctionType::get (
2190+ /* params*/ {}, context.TheEmptyTupleType ,
2191+ ASTExtInfoBuilder ().withThrows ().withGlobalActor (mainActor).build ()));
2192+ mainTypes.push_back (FunctionType::get (/* params*/ {},
2193+ context.TheEmptyTupleType ,
2194+ ASTExtInfoBuilder ()
2195+ .withAsync ()
2196+ .withThrows ()
2197+ .withGlobalActor (mainActor)
2198+ .build ()));
2199+ }
2200+ TypeVariableType *mainType =
2201+ CS.createTypeVariable (locator, /* options=*/ 0 );
2202+ llvm::SmallVector<Constraint *, 4 > typeEqualityConstraints;
2203+ typeEqualityConstraints.reserve (mainTypes.size ());
2204+ for (const Type &candidateMainType : mainTypes) {
2205+ typeEqualityConstraints.push_back (
2206+ Constraint::create (CS, ConstraintKind::Equal, Type (mainType),
2207+ candidateMainType, locator));
2208+ }
2209+
2210+ CS.addDisjunctionConstraint (typeEqualityConstraints, locator);
2211+ CS.addValueMemberConstraint (
2212+ nominal->getInterfaceType (), DeclNameRef (context.Id_main ),
2213+ Type (mainType), declContext, FunctionRefKind::SingleApply, {}, locator);
2214+ }
2215+
2216+ FuncDecl *mainFunction = nullptr ;
2217+ llvm::SmallVector<Solution, 4 > candidates;
2218+
2219+ if (!CS.solve (candidates, FreeTypeVariableBinding::Disallow)) {
2220+ // We can't use CS.diagnoseAmbiguity directly since the locator is empty
2221+ // Sticking the main type decl `D` in results in an assert due to a
2222+ // unsimplifiable locator anchor since it appears to be looking for an
2223+ // expression, which we don't have.
2224+ // (locator could not be simplified to anchor)
2225+ // TODO: emit notes for each of the ambiguous candidates
2226+ if (candidates.size () != 1 ) {
2227+ context.Diags .diagnose (nominal->getLoc (), diag::ambiguous_decl_ref,
2228+ DeclNameRef (context.Id_main ));
2229+ attr->setInvalid ();
2230+ return nullptr ;
2231+ }
2232+ mainFunction = dyn_cast<FuncDecl>(
2233+ candidates[0 ].overloadChoices [locator].choice .getDecl ());
2234+ }
21732235
2174- constraints::ConstraintSystemOptions lookupOptions;
2175- if (context.LangOpts .EnableAsyncMainResolution )
2176- lookupOptions |=
2177- constraints::ConstraintSystemFlags::ConsiderNominalTypeContextsAsync;
2178-
2179- auto resolution = resolveValueMember (
2180- *declContext, nominal->getInterfaceType (), context.Id_main ,
2181- lookupOptions);
2182- FuncDecl *mainFunction =
2183- resolveMainFunctionDecl (declContext, resolution, context);
21842236 if (!mainFunction) {
21852237 const bool hasAsyncSupport =
21862238 AvailabilityContext::forDeploymentTarget (context).isContainedIn (
0 commit comments