Skip to content

Commit 20e4413

Browse files
authored
Merge pull request #80812 from jamieQ/invalid-isolated-any-conversion
[Sema]: ban @isolated(any) conversions to synchronous function types
2 parents 6baa3de + 629e208 commit 20e4413

File tree

3 files changed

+44
-2
lines changed

3 files changed

+44
-2
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5045,6 +5045,10 @@ ERROR(capture_across_type_decl,none,
50455045
"scope",
50465046
(const NominalTypeDecl *, const ValueDecl *))
50475047

5048+
ERROR(isolated_any_conversion_to_synchronous_func,none,
5049+
"converting @isolated(any) function of type %0 to synchronous function type %1 is not allowed",
5050+
(Type, Type))
5051+
50485052
ERROR(reference_to_invalid_decl,none,
50495053
"cannot reference invalid declaration %0", (const ValueDecl *))
50505054

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2694,6 +2694,18 @@ namespace {
26942694
}
26952695
}
26962696

2697+
// @isolated(any) functions (async or not) cannot be converted to
2698+
// synchronous, non-@isolated(any) functions.
2699+
if (fromIsolation.isErased() && !toIsolation.isErased() &&
2700+
!toFnType->isAsync()) {
2701+
ctx.Diags
2702+
.diagnose(funcConv->getLoc(),
2703+
diag::isolated_any_conversion_to_synchronous_func,
2704+
fromFnType, toFnType)
2705+
.warnUntilFutureSwiftVersion();
2706+
return;
2707+
}
2708+
26972709
// Conversions from non-Sendable types are handled by
26982710
// region-based isolation.
26992711
// Function conversions are used to inject concurrency attributes

test/Concurrency/isolated_any.swift

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,23 @@ func testEraseFromIsolatedArgument() {
6464
requireIsolatedAnyWithActorArgument(hasIsolatedArgument)
6565
}
6666

67-
func requireSendableNonIsolated(_ fn: @Sendable () -> ()) {}
67+
func requireSendableNonIsolated(_ fn: @Sendable () async -> ()) {}
6868
func testConvertIsolatedAnyToNonIsolated(fn: @Sendable @isolated(any) () -> ()) {
6969
requireSendableNonIsolated(fn)
7070
}
7171

72+
func requireSendableNonIsolated_sync(_ fn: @Sendable () -> ()) {}
73+
func testConvertIsolatedAnyToNonIsolated_sync(fn: @Sendable @isolated(any) () -> ()) {
74+
// expected-warning @+1 {{converting @isolated(any) function of type '@isolated(any) @Sendable () -> ()' to synchronous function type '@Sendable () -> ()' is not allowed; this will be an error in a future Swift language mode}}
75+
requireSendableNonIsolated_sync(fn)
76+
}
77+
78+
func requireNonSendableNonIsolated_sync(_ fn: () -> ()) {}
79+
func testConvertIsolatedAnyToNonSendableNonIsolated_sync(fn: @isolated(any) () -> ()) {
80+
// expected-warning @+1 {{converting @isolated(any) function of type '@isolated(any) () -> ()' to synchronous function type '() -> ()' is not allowed; this will be an error in a future Swift language mode}}
81+
requireNonSendableNonIsolated_sync(fn)
82+
}
83+
7284
func requireSendableGlobalActor(_ fn: @Sendable @MainActor () -> ()) {}
7385
func testConvertIsolatedAnyToMainActor(fn: @Sendable @isolated(any) () -> ()) {
7486
// expected-error @+1 {{cannot convert value of type '@isolated(any) @Sendable () -> ()' to expected argument type '@MainActor @Sendable () -> ()'}}
@@ -125,8 +137,22 @@ func testFunctionIsolationExprTuple(
125137
return (fn1?.isolation, fn2?.isolation)
126138
}
127139

128-
func nonSendableIsolatedAny(
140+
func nonSendableIsolatedAnySyncToSendableSync(
129141
_ fn: @escaping @isolated(any) () -> Void // expected-note {{parameter 'fn' is implicitly non-sendable}}
130142
) {
131143
let _: @Sendable () -> Void = fn // expected-warning {{using non-sendable parameter 'fn' in a context expecting a '@Sendable' closure}}
144+
// expected-warning @-1 {{converting @isolated(any) function of type '@isolated(any) () -> Void' to synchronous function type '@Sendable () -> Void' is not allowed; this will be an error in a future Swift language mode}}
145+
}
146+
147+
func nonSendableIsolatedAnyAsyncToSendableSync(
148+
_ fn: @escaping @isolated(any) () async -> Void // expected-note {{parameter 'fn' is implicitly non-sendable}}
149+
) {
150+
let _: @Sendable () -> Void = fn // expected-warning {{using non-sendable parameter 'fn' in a context expecting a '@Sendable' closure}}
151+
// expected-error @-1 {{invalid conversion from 'async' function of type '@isolated(any) () async -> Void' to synchronous function type '@Sendable () -> Void'}}
152+
}
153+
154+
func nonSendableIsolatedAnyAsyncToSendableAsync(
155+
_ fn: @escaping @isolated(any) () async -> Void // expected-note {{parameter 'fn' is implicitly non-sendable}}
156+
) {
157+
let _: @Sendable () async -> Void = fn // expected-warning {{using non-sendable parameter 'fn' in a context expecting a '@Sendable' closure}}
132158
}

0 commit comments

Comments
 (0)