Skip to content

Commit 35d26a8

Browse files
committed
[Concurrency] @isolated(any) does not imply @Sendable.
1 parent 7ded57b commit 35d26a8

File tree

4 files changed

+26
-23
lines changed

4 files changed

+26
-23
lines changed

lib/Sema/TypeCheckType.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3941,9 +3941,6 @@ NeverNullType TypeResolver::resolveASTFunctionType(
39413941
conventionAttr->getConventionName());
39423942
} else {
39433943
isolation = FunctionTypeIsolation::forErased();
3944-
3945-
// @isolated(any) implies @Sendable, unconditionally for now.
3946-
sendable = true;
39473944
}
39483945
break;
39493946
}

test/Concurrency/isolated_any.swift

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func testConvertIsolatedAnyToMainActor(fn: @Sendable @isolated(any) () -> ()) {
7575
requireSendableGlobalActor(fn)
7676
}
7777

78-
func extractFunctionIsolation(_ fn: @isolated(any) @escaping () async -> Void) {
78+
func extractFunctionIsolation(_ fn: @isolated(any) @Sendable @escaping () async -> Void) {
7979
let _: (any Actor)? = extractIsolation(fn)
8080

8181
let myActor = A()
@@ -85,8 +85,8 @@ func extractFunctionIsolation(_ fn: @isolated(any) @escaping () async -> Void) {
8585
}
8686

8787
func extractFunctionIsolationExpr(
88-
_ fn1: @isolated(any) @escaping () async -> Void,
89-
_ fn2: @isolated(any) @escaping (Int, String) -> Bool
88+
_ fn1: @isolated(any) @Sendable @escaping () async -> Void,
89+
_ fn2: @isolated(any) @Sendable @escaping (Int, String) -> Bool
9090
) {
9191
let _: (any Actor)? = fn1.isolation
9292
let _: (any Actor)? = fn2.isolation
@@ -118,9 +118,15 @@ func testFunctionIsolationExpr2(_ fn: Optional<(@isolated(any) () -> Void)>) ->
118118
}
119119

120120
func testFunctionIsolationExprTuple(
121-
_ fn1: (@isolated(any) () -> Void)?,
122-
_ fn2: (@isolated(any) () -> Void)?
121+
_ fn1: (@isolated(any) @Sendable () -> Void)?,
122+
_ fn2: (@isolated(any) @Sendable () -> Void)?
123123
) -> ((any Actor)?, (any Actor)?)
124124
{
125125
return (fn1?.isolation, fn2?.isolation)
126126
}
127+
128+
func nonSendableIsolatedAny(
129+
_ fn: @escaping @isolated(any) () -> Void // expected-note {{parameter 'fn' is implicitly non-sendable}}
130+
) {
131+
let _: @Sendable () -> Void = fn // expected-warning {{using non-sendable parameter 'fn' in a context expecting a @Sendable closure}}
132+
}

test/SILGen/isolated_any.swift

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
// CHECK-NEXT: end_borrow [[FN_BORROW2]]
1515
// CHECK-NEXT: end_borrow [[FN_BORROW1]]
1616
// CHECK-NEXT: hop_to_executor [[NIL_EXECUTOR]]
17-
func callSync(fn: @isolated(any) () -> ()) async {
17+
func callSync(fn: @isolated(any) @Sendable () -> ()) async {
1818
await fn()
1919
}
2020

@@ -26,7 +26,7 @@ func callSync(fn: @isolated(any) () -> ()) async {
2626
// CHECK-NEXT: apply [[FN_BORROW2]]()
2727
// CHECK-NEXT: end_borrow [[FN_BORROW2]]
2828
// CHECK-NEXT: hop_to_executor [[NIL_EXECUTOR]]
29-
func callAsync(fn: @isolated(any) () async -> ()) async {
29+
func callAsync(fn: @isolated(any) @Sendable () async -> ()) async {
3030
await fn()
3131
}
3232

@@ -40,7 +40,7 @@ func callAsync(fn: @isolated(any) () async -> ()) async {
4040
// CHECK-NEXT: [[THUNKED_FN:%.*]] = partial_apply [callee_guaranteed] [isolated_any] [[THUNK]]([[ISOLATION]], [[FN_COPY]])
4141
// CHECK-NEXT: return [[THUNKED_FN]] : $@isolated(any) @Sendable @async @callee_guaranteed () -> ()
4242
func convertFromNonIsolated(fn: @escaping @Sendable () async -> ())
43-
-> @isolated(any) () async -> () {
43+
-> @isolated(any) @Sendable () async -> () {
4444
return fn
4545
}
4646

@@ -71,7 +71,7 @@ func convertFromNonIsolated(fn: @escaping @Sendable () async -> ())
7171
// CHECK-NEXT: [[THUNKED_FN:%.*]] = partial_apply [callee_guaranteed] [isolated_any] [[THUNK]]([[ISOLATION]], [[FN_COPY]])
7272
// CHECK-NEXT: return [[THUNKED_FN]] : $@isolated(any) @Sendable @async @callee_guaranteed () -> ()
7373
func convertFromMainActor(fn: @escaping @Sendable @MainActor () async -> ())
74-
-> @isolated(any) () async -> () {
74+
-> @isolated(any) @Sendable () async -> () {
7575
return fn
7676
}
7777

@@ -90,7 +90,7 @@ func convertFromMainActor(fn: @escaping @Sendable @MainActor () async -> ())
9090
// CHECK-NEXT: [[THUNKED_FN:%.*]] = partial_apply [callee_guaranteed] [isolated_any] [[THUNK]]([[ISOLATION]], [[FN_COPY]])
9191
// CHECK-NEXT: return [[THUNKED_FN]] : $@isolated(any) @Sendable @async @callee_guaranteed () -> Optional<Int>
9292
func convertFromMainActorWithOtherChanges(fn: @escaping @Sendable @MainActor () async -> Int)
93-
-> @isolated(any) () async -> Int? {
93+
-> @isolated(any) @Sendable () async -> Int? {
9494
return fn
9595
}
9696

@@ -107,7 +107,7 @@ func convertFromMainActorWithOtherChanges(fn: @escaping @Sendable @MainActor ()
107107
// CHECK-NEXT: [[FN_COPY:%.*]] = copy_value %0 :
108108
// CHECK-NEXT: [[FN_CONVERTED:%.*]] = convert_function [[FN_COPY]] : $@isolated(any) @Sendable @async @callee_guaranteed () -> () to $@Sendable @async @callee_guaranteed () -> ()
109109
// CHECK-NEXT: return [[FN_CONVERTED]] :
110-
func convertToNonIsolated(fn: @escaping @isolated(any) () async -> ())
110+
func convertToNonIsolated(fn: @escaping @isolated(any) @Sendable () async -> ())
111111
-> @Sendable () async -> () {
112112
return fn
113113
}
@@ -129,16 +129,16 @@ func convertToNonIsolated(fn: @escaping @isolated(any) () async -> ())
129129
// CHECK-NEXT: [[SOME_INT:%.*]] = enum $Optional<Int>, #Optional.some!enumelt, [[INT]] : $Int
130130
// CHECK-NEXT: return [[SOME_INT]] : $Optional<Int>
131131

132-
func convertToNonIsolatedWithOtherChanges(fn: @escaping @isolated(any) () async -> Int) -> @Sendable () async -> Int? {
132+
func convertToNonIsolatedWithOtherChanges(fn: @escaping @isolated(any) @Sendable () async -> Int) -> @Sendable () async -> Int? {
133133
return fn
134134
}
135135

136136
/*-- Sync closures --*/
137137

138138
func syncAction() {}
139139

140-
func takeSyncIsolatedAny(fn: @escaping @isolated(any) () -> ()) {}
141-
func takeInheritingSyncIsolatedAny(@_inheritActorContext fn: @escaping @isolated(any) () -> ()) {}
140+
func takeSyncIsolatedAny(fn: @escaping @isolated(any) @Sendable () -> ()) {}
141+
func takeInheritingSyncIsolatedAny(@_inheritActorContext fn: @escaping @isolated(any) @Sendable () -> ()) {}
142142

143143
// CHECK-LABEL: sil hidden [ossa] @$s4test0A27EraseSyncNonIsolatedClosureyyF
144144
// CHECK: // function_ref closure #1
@@ -246,8 +246,8 @@ actor MyActor {
246246

247247
func asyncAction() async {}
248248

249-
func takeAsyncIsolatedAny(fn: @escaping @isolated(any) () async -> ()) {}
250-
func takeInheritingAsyncIsolatedAny(@_inheritActorContext fn: @escaping @isolated(any) () async -> ()) {}
249+
func takeAsyncIsolatedAny(fn: @escaping @isolated(any) @Sendable () async -> ()) {}
250+
func takeInheritingAsyncIsolatedAny(@_inheritActorContext fn: @escaping @isolated(any) @Sendable () async -> ()) {}
251251

252252
// CHECK-LABEL: sil hidden [ossa] @$s4test0A28EraseAsyncNonIsolatedClosureyyF
253253
// CHECK: // function_ref closure #1
@@ -383,7 +383,7 @@ extension MyActor {
383383
func asyncAction() async {}
384384
}
385385

386-
func takeInheritingOptionalAsyncIsolatedAny(@_inheritActorContext fn: Optional<@isolated(any) () async -> ()>) {}
386+
func takeInheritingOptionalAsyncIsolatedAny(@_inheritActorContext fn: Optional<@isolated(any) @Sendable () async -> ()>) {}
387387

388388
// CHECK-LABEL: sil hidden [ossa] @$s4test7MyActorC0a20EraseInheritingAsyncC19ClosureIntoOptionalyyF
389389
// CHECK: // function_ref closure #1
@@ -406,7 +406,7 @@ extension MyActor {
406406
}
407407
}
408408

409-
func takeInheritingAsyncIsolatedAny_optionalResult(@_inheritActorContext fn: @escaping @isolated(any) () async -> Int?) {}
409+
func takeInheritingAsyncIsolatedAny_optionalResult(@_inheritActorContext fn: @escaping @isolated(any) @Sendable () async -> Int?) {}
410410

411411
// Test that we correctly handle isolation erasure from closures even when
412412
// we can't completely apply the conversion as a peephole.
@@ -526,6 +526,6 @@ func testEraseAsyncActorIsolatedPartialApplication(a: MyActor) {
526526
// CHECK-NEXT: end_borrow [[FN_BORROW]] : $@isolated(any) @Sendable @callee_guaranteed () -> ()
527527
// CHECK-NEXT: destroy_value [[FN]] : $@isolated(any) @Sendable @callee_guaranteed () -> ()
528528
// CHECK-NEXT: return [[RESULT]] : $Optional<any Actor>
529-
func extractIsolation(fn: @escaping @isolated(any) () -> Void) -> (any Actor)? {
529+
func extractIsolation(fn: @escaping @isolated(any) @Sendable () -> Void) -> (any Actor)? {
530530
fn.isolation
531531
}

test/SILGen/isolated_any_conformance.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// introduced a protocol for different task group types.
88

99
struct A<T> {
10-
func enqueue(operation: @escaping @isolated(any) () async -> T) {}
10+
func enqueue(operation: @escaping @isolated(any) @Sendable () async -> T) {}
1111
}
1212

1313
protocol Enqueuer {

0 commit comments

Comments
 (0)