Skip to content

Commit 4494db9

Browse files
authored
Merge pull request swiftlang#42142 from etcwilde/ewilde/async-main-resolution
Fixing async main resolution
2 parents e790680 + 2eb8011 commit 4494db9

File tree

12 files changed

+92
-128
lines changed

12 files changed

+92
-128
lines changed

include/swift/Basic/LangOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,9 @@ namespace swift {
209209
/// Emit a remark after loading a module.
210210
bool EnableModuleLoadingRemarks = false;
211211

212+
/// Resolve main function as though it were called from an async context
213+
bool EnableAsyncMainResolution = false;
214+
212215
///
213216
/// Support for alternate usage modes
214217
///

include/swift/Option/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,10 @@ def pch_output_dir: Separate<["-"], "pch-output-dir">,
270270
Flags<[FrontendOption, HelpHidden, ArgumentIsPath]>,
271271
HelpText<"Directory to persist automatically created precompiled bridging headers">;
272272

273+
def async_main: Flag<["-"], "async-main">,
274+
Flags<[FrontendOption]>,
275+
HelpText<"Resolve main function as if it were called from an asynchronous context">;
276+
273277
// FIXME: Unhide this once it doesn't depend on an output file map.
274278
def incremental : Flag<["-"], "incremental">,
275279
Flags<[NoInteractiveOption, HelpHidden, DoesNotAffectIncrementalBuild]>,

include/swift/Sema/ConstraintSystem.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,6 +1515,10 @@ enum class ConstraintSystemFlags {
15151515
/// calling conventions, say due to Clang attributes such as
15161516
/// `__attribute__((ns_consumed))`.
15171517
UseClangFunctionTypes = 0x80,
1518+
1519+
/// When set, nominal typedecl contexts are asynchronous contexts.
1520+
/// This is set while searching for the main function
1521+
ConsiderNominalTypeContextsAsync = 0x100,
15181522
};
15191523

15201524
/// Options that affect the constraint system as a whole.

include/swift/Sema/IDETypeChecking.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "swift/AST/Identifier.h"
2323
#include "swift/Basic/SourceLoc.h"
24+
#include "swift/Basic/OptionSet.h"
2425
#include <memory>
2526
#include <tuple>
2627

@@ -50,6 +51,8 @@ namespace swift {
5051
class ConstraintSystem;
5152
class Solution;
5253
class SolutionApplicationTarget;
54+
enum class ConstraintSystemFlags;
55+
using ConstraintSystemOptions = OptionSet<ConstraintSystemFlags>;
5356
}
5457

5558
/// Typecheck binding initializer at \p bindingIndex.
@@ -93,8 +96,9 @@ namespace swift {
9396
/// Unlike other member lookup functions, \c swift::resolveValueMember()
9497
/// should be used when you want to look up declarations with the same name as
9598
/// one you already have.
96-
ResolvedMemberResult resolveValueMember(DeclContext &DC, Type BaseTy,
97-
DeclName Name);
99+
ResolvedMemberResult
100+
resolveValueMember(DeclContext &DC, Type BaseTy, DeclName Name,
101+
constraints::ConstraintSystemOptions Options = {});
98102

99103
/// Given a type and an extension to the original type decl of that type,
100104
/// decide if the extension has been applied, i.e. if the requirements of the

lib/Driver/ToolChains.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI,
299299
inputArgs.AddLastArg(arguments, options::OPT_access_notes_path);
300300
inputArgs.AddLastArg(arguments, options::OPT_library_level);
301301
inputArgs.AddLastArg(arguments, options::OPT_enable_regex_literals);
302+
inputArgs.AddLastArg(arguments, options::OPT_async_main);
302303

303304
// Pass on any build config options
304305
inputArgs.AddAllArgs(arguments, options::OPT_D);

lib/Frontend/CompilerInvocation.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,8 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
489489
Diags.diagnose(SourceLoc(), diag::warn_flag_deprecated,
490490
"-enable-experimental-async-top-level");
491491

492+
Opts.EnableAsyncMainResolution = Args.hasArg(OPT_async_main);
493+
492494
Opts.DiagnoseInvalidEphemeralnessAsError |=
493495
Args.hasArg(OPT_enable_invalid_ephemeralness_as_error);
494496

lib/Sema/CSGen.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4421,9 +4421,10 @@ getMemberDecls(InterestedMemberKind Kind) {
44214421
}
44224422

44234423
ResolvedMemberResult
4424-
swift::resolveValueMember(DeclContext &DC, Type BaseTy, DeclName Name) {
4424+
swift::resolveValueMember(DeclContext &DC, Type BaseTy, DeclName Name,
4425+
ConstraintSystemOptions Options) {
44254426
ResolvedMemberResult Result;
4426-
ConstraintSystem CS(&DC, None);
4427+
ConstraintSystem CS(&DC, Options);
44274428

44284429
// Look up all members of BaseTy with the given Name.
44294430
MemberLookupResult LookupResult = CS.performMemberLookup(

lib/Sema/ConstraintSystem.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2894,6 +2894,11 @@ bool ConstraintSystem::isAsynchronousContext(DeclContext *dc) {
28942894
FunctionType::ExtInfo()).isAsync();
28952895
}
28962896

2897+
if (Options.contains(
2898+
ConstraintSystemFlags::ConsiderNominalTypeContextsAsync) &&
2899+
isa<NominalTypeDecl>(dc))
2900+
return true;
2901+
28972902
return false;
28982903
}
28992904

lib/Sema/TypeCheckAttr.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2171,8 +2171,14 @@ SynthesizeMainFunctionRequest::evaluate(Evaluator &evaluator,
21712171
// mainType.main() from the entry point, and that would require fully
21722172
// type-checking the call to mainType.main().
21732173

2174+
constraints::ConstraintSystemOptions lookupOptions;
2175+
if (context.LangOpts.EnableAsyncMainResolution)
2176+
lookupOptions |=
2177+
constraints::ConstraintSystemFlags::ConsiderNominalTypeContextsAsync;
2178+
21742179
auto resolution = resolveValueMember(
2175-
*declContext, nominal->getInterfaceType(), context.Id_main);
2180+
*declContext, nominal->getInterfaceType(), context.Id_main,
2181+
lookupOptions);
21762182
FuncDecl *mainFunction =
21772183
resolveMainFunctionDecl(declContext, resolution, context);
21782184
if (!mainFunction) {

test/Concurrency/async_main_resolution.swift

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,32 @@
1-
// Non-apple platforms don't need to worry about the version number as much
2-
// because they can pull in the concurrency libraries with the swift
3-
// installation.
4-
51
// async main is nested deeper in protocols than sync, use sync
62
// sync main is nested deeper in protocols than async, use async
73
// async and sync are same level, use async
84

9-
// REQUIRES: rdar89500797
10-
115
// REQUIRES: concurrency
12-
// UNSUPPORTED: VENDOR=apple
13-
14-
// Async is deeper in the protocol chain from `MyMain`, use sync
15-
// RUN: %target-swift-frontend -DASYNC_NESTED -DINHERIT_SYNC -typecheck -dump-ast -parse-as-library %s | %FileCheck %s --check-prefix=CHECK-IS-SYNC
16-
17-
// Sync is deeper in the protocol chain from `MyMain`, use async
18-
// RUN: %target-swift-frontend -typecheck -dump-ast -parse-as-library %s | %FileCheck %s --check-prefix=CHECK-IS-ASYNC
196

20-
// Async and sync are the same level, use async
21-
// RUN: %target-swift-frontend -DBOTH -DINHERIT_SYNC -typecheck -dump-ast -parse-as-library %s | %FileCheck %s --check-prefix=CHECK-IS-ASYNC
7+
// ASYNC_NESTED: async is nested more deeply than sync main in protocol chain
8+
// NO_ASYNC: no async main function
9+
// NO_SYNC: no sync main function
10+
// BOTH: MainProtocol has both sync and async main
11+
// INHERIT_SYNC: main type directly conforms to synchronous main protocol
12+
13+
// | async flag | has async main | has sync main | both | inherits sync | nested async | Result | Run |
14+
// | | | | | | | Error | RUN: not %target-swift-frontend -disable-availability-checking -DNO_ASYNC -DNO_SYNC -parse-as-library -typecheck -dump-ast %s 2>&1 | %FileCheck %s --check-prefix=CHECK-IS-ERROR
15+
// | | x | | | | | Async Main | RUN: %target-swift-frontend -disable-availability-checking -DNO_SYNC -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-ASYNC
16+
// | x | | x | | | | Sync Main | RUN: %target-swift-frontend -disable-availability-checking -DNO_ASYNC -async-main -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-SYNC
17+
// | x | x | x | | | | Async Main | RUN: %target-swift-frontend -disable-availability-checking -async-main -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-ASYNC
18+
// | | x | x | | | | Sync Main | RUN: %target-swift-frontend -disable-availability-checking -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-SYNC
19+
// | | x | x | | | x | Async Main | RUN: %target-swift-frontend -disable-availability-checking -DASYNC_NESTED -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-ASYNC
20+
// | | x | x | | x | x | Sync Main | RUN: %target-swift-frontend -disable-availability-checking -DINHERIT_SYNC -DASYNC_NESTED -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-SYNC
21+
// | x | x | x | | x | x | Async Main | RUN: %target-swift-frontend -disable-availability-checking -DINHERIT_SYNC -DASYNC_NESTED -async-main -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-ASYNC
22+
// | x | | x | | x | x | Sync Main | RUN: %target-swift-frontend -disable-availability-checking -DNO_ASYNC -DINHERIT_SYNC -DASYNC_NESTED -async-main -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-SYNC
23+
// | | | x | x | | | Sync Main | RUN: %target-swift-frontend -disable-availability-checking -DBOTH -DNO_ASYNC -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-SYNC
24+
// | x | | x | x | | | Async Main | RUN: %target-swift-frontend -disable-availability-checking -DBOTH -DNO_ASYNC -async-main -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-ASYNC
25+
26+
// tldr;
27+
// If async flag is set, will pick an asynchronous main function if one is available and related. If none exist, will fall back on synchronous main.
28+
// If async flag is not set, will pick a asynchronous main function if one is available and related. If none exist, will fall back on an asynchronous main
29+
// If neither are available; error
2230

2331
#if ASYNC_NESTED
2432
protocol AsyncMainProtocol { }
@@ -55,8 +63,6 @@ extension MainProtocol {
5563
@main struct MyMain : AsyncMainProtocol {}
5664
#endif
5765

58-
59-
6066
// CHECK-IS-SYNC-LABEL: "MyMain" interface type='MyMain.Type'
6167
// CHECK-IS-SYNC: (func_decl implicit "$main()" interface type='(MyMain.Type) -> () -> ()'
6268
// CHECK-IS-SYNC: (declref_expr implicit type='(MyMain.Type) -> () -> ()'
@@ -65,6 +71,4 @@ extension MainProtocol {
6571
// CHECK-IS-ASYNC: (func_decl implicit "$main()" interface type='(MyMain.Type) -> () async -> ()'
6672
// CHECK-IS-ASYNC: (declref_expr implicit type='(MyMain.Type) -> () async -> ()'
6773

68-
// CHECK-IS-ERROR: error: 'MyMain' is annotated with @main and must provide a main static function of type () -> Void or () throws -> Void
69-
70-
// CHECK-IS-ERROR-ASYNC: error: 'MyMain' is annotated with @main and must provide a main static function of type () -> Void, () throws -> Void, () async -> Void, or () async throws -> Void
74+
// CHECK-IS-ERROR: error: 'MyMain' is annotated with @main and must provide a main static function of type {{\(\) -> Void or \(\) throws -> Void|\(\) -> Void, \(\) throws -> Void, \(\) async -> Void, or \(\) async throws -> Void}}

test/Concurrency/async_main_resolution_macos.swift

Lines changed: 0 additions & 95 deletions
This file was deleted.

0 commit comments

Comments
 (0)