Skip to content

Commit 5552a4b

Browse files
authored
Merge pull request #36247 from DougGregor/async-sync-overloading-like-reasync
[Concurrency] Tune overloading to to allow sync overloads in async contexts
2 parents f81aba7 + 9ccf206 commit 5552a4b

File tree

6 files changed

+40
-8
lines changed

6 files changed

+40
-8
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -775,9 +775,11 @@ enum ScoreKind {
775775
SK_Hole,
776776
/// A reference to an @unavailable declaration.
777777
SK_Unavailable,
778-
/// A reference to an async function in a synchronous context, or
779-
/// vice versa.
780-
SK_AsyncSyncMismatch,
778+
/// A reference to an async function in a synchronous context.
779+
SK_AsyncInSyncMismatch,
780+
/// Synchronous function in an asynchronous context or a conversion of
781+
/// a synchronous function to an asynchronous one.
782+
SK_SyncInAsync,
781783
/// A use of the "forward" scan for trailing closures.
782784
SK_ForwardTrailingClosure,
783785
/// A use of a disfavored overload.

lib/Sema/CSRanking.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,11 @@ static StringRef getScoreKindName(ScoreKind kind) {
4040
case SK_Unavailable:
4141
return "use of an unavailable declaration";
4242

43-
case SK_AsyncSyncMismatch:
44-
return "async/synchronous mismatch";
43+
case SK_AsyncInSyncMismatch:
44+
return "async-in-synchronous mismatch";
45+
46+
case SK_SyncInAsync:
47+
return "sync-in-asynchronous";
4548

4649
case SK_ForwardTrailingClosure:
4750
return "forward scan when matching a trailing closure";

lib/Sema/CSSimplify.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1983,6 +1983,8 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
19831983
if (recordFix(fix))
19841984
return getTypeMatchFailure(locator);
19851985
}
1986+
1987+
increaseScore(SK_SyncInAsync);
19861988
}
19871989

19881990
// A @concurrent function can be a subtype of a non-@concurrent function.

lib/Sema/CSStep.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,7 @@ bool DisjunctionStep::shouldStopAt(const DisjunctionChoice &choice) const {
711711
auto delta = LastSolvedChoice->second - getCurrentScore();
712712
bool hasUnavailableOverloads = delta.Data[SK_Unavailable] > 0;
713713
bool hasFixes = delta.Data[SK_Fix] > 0;
714-
bool hasAsyncMismatch = delta.Data[SK_AsyncSyncMismatch] > 0;
714+
bool hasAsyncMismatch = delta.Data[SK_AsyncInSyncMismatch] > 0;
715715
auto isBeginningOfPartition = choice.isBeginningOfPartition();
716716

717717
// Attempt to short-circuit evaluation of this disjunction only

lib/Sema/ConstraintSystem.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2820,8 +2820,10 @@ void ConstraintSystem::resolveOverload(ConstraintLocator *locator,
28202820
// If we're choosing an asynchronous declaration within a synchronous
28212821
// context, or vice-versa, increase the async/async mismatch score.
28222822
if (auto func = dyn_cast<AbstractFunctionDecl>(decl)) {
2823-
if (func->isAsyncContext() != isAsynchronousContext(useDC))
2824-
increaseScore(SK_AsyncSyncMismatch);
2823+
if (func->isAsyncContext() != isAsynchronousContext(useDC)) {
2824+
increaseScore(
2825+
func->isAsyncContext() ? SK_AsyncInSyncMismatch : SK_SyncInAsync);
2826+
}
28252827
}
28262828

28272829
// If we're binding to an init member, the 'throws' need to line up

test/Constraints/async.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,26 @@ struct FunctionTypes {
115115
asyncNonThrowing = syncThrowing // expected-error{{invalid conversion}}
116116
}
117117
}
118+
119+
// Overloading when there is conversion from sync to async.
120+
func bar(_ f: (Int) -> Int) -> Int {
121+
return f(2)
122+
}
123+
124+
func bar(_ f: (Int) async -> Int) async -> Int {
125+
return await f(2)
126+
}
127+
128+
func incrementSync(_ x: Int) -> Int {
129+
return x + 1
130+
}
131+
132+
func incrementAsync(_ x: Int) async -> Int {
133+
return x + 1
134+
}
135+
136+
func testAsyncWithConversions() async {
137+
_ = bar(incrementSync)
138+
_ = bar { -$0 }
139+
_ = bar(incrementAsync) // expected-error{{call is 'async' but is not marked with 'await'}}
140+
}

0 commit comments

Comments
 (0)