Skip to content

Commit 02ba725

Browse files
committed
Use constraint solver results for main resolution
This is effectively reverting #40577. The mechanism that I tried to use didn't respect `where` clauses on extensions and, as a result, could select a totally unrelated and incorrect main function. This results in beautiful explosions in the rest of the typesystem.
1 parent e35261f commit 02ba725

File tree

1 file changed

+14
-56
lines changed

1 file changed

+14
-56
lines changed

lib/Sema/TypeCheckAttr.cpp

Lines changed: 14 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -2018,65 +2018,23 @@ synthesizeMainBody(AbstractFunctionDecl *fn, void *arg) {
20182018
static FuncDecl *resolveMainFunctionDecl(DeclContext *declContext,
20192019
ResolvedMemberResult &resolution,
20202020
ASTContext &ctx) {
2021-
// The normal resolution mechanism won't choose the asynchronous main function
2022-
// unless no other options are available because extensions and generic types
2023-
// (structs/classes) are not considered asynchronous contexts.
2024-
// We want them to be promoted to a viable entrypoint if the deployment target
2025-
// is high enough.
2026-
SmallVector<FuncDecl *, 4> viableCandidates;
2027-
for (ValueDecl *candidate : resolution.getMemberDecls(Viable)) {
2028-
if (FuncDecl *function = dyn_cast<FuncDecl>(candidate)) {
2029-
if (function->isMainTypeMainMethod())
2030-
viableCandidates.push_back(function);
2021+
// Choose the best overload if it's a main function
2022+
if (resolution.hasBestOverload()) {
2023+
ValueDecl *best = resolution.getBestOverload();
2024+
if (FuncDecl *func = dyn_cast<FuncDecl>(best)) {
2025+
if (func->isMainTypeMainMethod()) {
2026+
return func;
2027+
}
20312028
}
20322029
}
2033-
if (viableCandidates.empty()) {
2034-
return nullptr;
2035-
}
2036-
2037-
AvailabilityContext contextAvailability =
2038-
AvailabilityContext::forDeploymentTarget(ctx);
2039-
const bool hasAsyncSupport = contextAvailability.isContainedIn(
2040-
ctx.getBackDeployedConcurrencyAvailability());
2041-
2042-
FuncDecl *best = nullptr;
2043-
for (FuncDecl *candidate : viableCandidates) {
2044-
// The candidate will work if it's synchronous, or if we support concurrency
2045-
// and it is async, or if we are in YOLO mode
2046-
const bool candidateWorks = !candidate->hasAsync() ||
2047-
(hasAsyncSupport && candidate->hasAsync()) ||
2048-
ctx.LangOpts.DisableAvailabilityChecking;
2049-
2050-
// Skip it if it won't work
2051-
if (!candidateWorks)
2052-
continue;
2053-
2054-
// If we don't have a best, the candidate is the best so far
2055-
if (!best) {
2056-
best = candidate;
2057-
continue;
2030+
// Look for the most highly-ranked main-function candidate
2031+
for (ValueDecl *candidate : resolution.getMemberDecls(Viable)) {
2032+
if (FuncDecl *func = dyn_cast<FuncDecl>(candidate)) {
2033+
if (func->isMainTypeMainMethod())
2034+
return func;
20582035
}
2059-
2060-
// If the candidate is better and it's synchronous, just swap it right in.
2061-
// If the candidate is better and it's async, make sure we support async
2062-
// before selecting it.
2063-
//
2064-
// If it's unordered (equally bestest), use the async version if we support
2065-
// it or use the sync version if we don't.
2066-
const Comparison rank =
2067-
TypeChecker::compareDeclarations(declContext, candidate, best);
2068-
const bool isBetter = rank == Comparison::Better;
2069-
const bool isUnordered = rank == Comparison::Unordered;
2070-
const bool swapForAsync =
2071-
hasAsyncSupport && candidate->hasAsync() && !best->hasAsync();
2072-
const bool swapForSync =
2073-
!hasAsyncSupport && !candidate->hasAsync() && best->hasAsync();
2074-
const bool selectCandidate =
2075-
isBetter || (isUnordered && (swapForAsync || swapForSync));
2076-
if (selectCandidate)
2077-
best = candidate;
2078-
}
2079-
return best;
2036+
}
2037+
return nullptr;
20802038
}
20812039

20822040
FuncDecl *

0 commit comments

Comments
 (0)