Skip to content

Commit 4c098df

Browse files
authored
Merge pull request #41573 from etcwilde/ewilde/revert-async-main-resolution
Revert async-main lookup resolution
2 parents a08bfb9 + 7b676e0 commit 4c098df

File tree

4 files changed

+63
-56
lines changed

4 files changed

+63
-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 *

test/Concurrency/async_main_resolution.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
// sync main is nested deeper in protocols than async, use async
77
// async and sync are same level, use async
88

9+
// REQUIRES: rdar89500797
10+
911
// REQUIRES: concurrency
1012
// UNSUPPORTED: VENDOR=apple
1113

test/Concurrency/async_main_resolution_macos.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// sync main is nested deeper in protocols than async, use async if supported
33
// async and sync are same level, use async if supported
44

5+
// REQUIRES: rdar89500797
6+
57
// async main is nested in the protocol chain from `MyMain`
68
// Always choose Sync overload
79
// RUN: %target-swift-frontend -target x86_64-apple-macosx10.9 -DASYNC_NESTED -DINHERIT_SYNC -typecheck -dump-ast -parse-as-library %s | %FileCheck %s --check-prefix=CHECK-IS-SYNC
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// RUN: %target-swift-frontend -disable-availability-checking -D CONFIG1 -dump-ast -parse-as-library %s | %FileCheck %s --check-prefix=CHECK-CONFIG1
2+
// RUN: %target-swift-frontend -disable-availability-checking -D CONFIG2 -dump-ast -parse-as-library %s | %FileCheck %s --check-prefix=CHECK-CONFIG2
3+
// RUN: %target-swift-frontend -disable-availability-checking -D CONFIG3 -dump-ast -parse-as-library %s | %FileCheck %s --check-prefix=CHECK-CONFIG3
4+
5+
// REQUIRES: concurrency
6+
7+
protocol AppConfiguration { }
8+
9+
struct Config1: AppConfiguration {}
10+
struct Config2: AppConfiguration {}
11+
struct Config3: AppConfiguration {}
12+
13+
protocol App {
14+
associatedtype Configuration: AppConfiguration
15+
}
16+
17+
extension App where Configuration == Config1 {
18+
// CHECK-CONFIG1: (func_decl implicit "$main()" interface type='(MainType.Type) -> () -> ()'
19+
// CHECK-CONFIG1: where_clause_main_resolution.swift:[[# @LINE+1 ]]
20+
static func main() { }
21+
}
22+
23+
extension App where Configuration == Config2 {
24+
// CHECK-CONFIG2: (func_decl implicit "$main()" interface type='(MainType.Type) -> () async -> ()'
25+
// CHECK-CONFIG2: where_clause_main_resolution.swift:[[# @LINE+1 ]]
26+
static func main() async { }
27+
}
28+
29+
extension App {
30+
// CHECK-CONFIG3: (func_decl implicit "$main()" interface type='(MainType.Type) -> () async -> ()'
31+
// CHECK-CONFIG3: where_clause_main_resolution.swift:[[# @LINE+1 ]]
32+
static func main() async { }
33+
}
34+
35+
@main
36+
struct MainType : App {
37+
38+
#if CONFIG1
39+
typealias Configuration = Config1
40+
#elseif CONFIG2
41+
typealias Configuration = Config2
42+
#elseif CONFIG3
43+
typealias Configuration = Config3
44+
#endif
45+
}

0 commit comments

Comments
 (0)