Skip to content

Commit cdfe336

Browse files
authored
Merge pull request #74509 from hborla/fix-infer-sendable-from-global-actor
[Concurrency] Fix `@Sendable` inference for global-actor-isolated function types.
2 parents b810077 + e1c3781 commit cdfe336

10 files changed

+21
-22
lines changed

lib/AST/Type.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3894,11 +3894,6 @@ Type AnyFunctionType::getThrownError() const {
38943894
}
38953895

38963896
bool AnyFunctionType::isSendable() const {
3897-
auto &ctx = getASTContext();
3898-
if (ctx.LangOpts.hasFeature(Feature::GlobalActorIsolatedTypesUsability)) {
3899-
// Global-actor-isolated function types are implicitly Sendable.
3900-
return getExtInfo().isSendable() || getIsolation().isGlobalActor();
3901-
}
39023897
return getExtInfo().isSendable();
39033898
}
39043899

lib/ClangImporter/ImportType.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1695,8 +1695,7 @@ void swift::getConcurrencyAttrs(ASTContext &SwiftContext,
16951695
findSwiftAttributes(type, [&](const clang::SwiftAttrAttr *attr) {
16961696
if (isMainActorAttr(attr)) {
16971697
isMainActor = true;
1698-
isNonSendable = importKind == ImportTypeKind::Parameter ||
1699-
importKind == ImportTypeKind::CompletionHandlerParameter;
1698+
isSendable = true; // MainActor implies Sendable
17001699
} else if (attr->getAttribute() == "@Sendable")
17011700
isSendable = true;
17021701
else if (attr->getAttribute() == "@_nonSendable")

lib/Sema/CSGen.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2588,6 +2588,10 @@ namespace {
25882588
return FunctionTypeIsolation::forNonIsolated();
25892589
}();
25902590
extInfo = extInfo.withIsolation(isolation);
2591+
if (isolation.isGlobalActor() &&
2592+
CS.getASTContext().LangOpts.hasFeature(Feature::GlobalActorIsolatedTypesUsability)) {
2593+
extInfo = extInfo.withSendable();
2594+
}
25912595

25922596
auto *fnTy = FunctionType::get(closureParams, resultTy, extInfo);
25932597
return CS.replaceInferableTypesWithTypeVars(

lib/Sema/TypeCheckType.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3920,6 +3920,10 @@ NeverNullType TypeResolver::resolveASTFunctionType(
39203920
globalActorAttr->setInvalid();
39213921
} else {
39223922
isolation = FunctionTypeIsolation::forGlobalActor(globalActor);
3923+
3924+
// This inference is currently gated because `@Sendable` impacts mangling.
3925+
if (ctx.LangOpts.hasFeature(Feature::GlobalActorIsolatedTypesUsability))
3926+
sendable = true;
39233927
}
39243928
}
39253929

test/Concurrency/predates_concurrency_swift6.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,29 +25,29 @@ struct X {
2525

2626
func testInAsync(x: X) async {
2727
let _: Int = unsafelySendableClosure // expected-error{{type '@Sendable (@Sendable () -> Void) -> ()'}}
28-
let _: Int = unsafelyMainActorClosure // expected-error{{type '@Sendable (@MainActor () -> Void) -> ()'}}
28+
let _: Int = unsafelyMainActorClosure // expected-error{{type '@Sendable (@MainActor @Sendable () -> Void) -> ()'}}
2929
let _: Int = unsafelyDoEverythingClosure // expected-error{{type '@Sendable (@MainActor @Sendable () -> Void) -> ()'}}
3030
let _: Int = x.unsafelyDoEverythingClosure // expected-error{{type '@Sendable (@MainActor @Sendable () -> Void) -> ()'}}
3131
let _: Int = X.unsafelyDoEverythingClosure // expected-error{{type '@Sendable (X) -> @Sendable (@MainActor @Sendable () -> Void) -> ()'}}
3232
let _: Int = (X.unsafelyDoEverythingClosure)(x) // expected-error{{type '@Sendable (@MainActor @Sendable () -> Void) -> ()'}}
3333

3434
let _: Int = x.sendableVar // expected-error{{type '@Sendable () -> Void'}}
35-
let _: Int = x.mainActorVar // expected-error{{type '@MainActor () -> Void'}}
35+
let _: Int = x.mainActorVar // expected-error{{type '@MainActor @Sendable () -> Void'}}
3636

3737
let _: Int = x[{ onMainActor() }] // expected-error{{type '@Sendable () -> Void'}}
3838
let _: Int = X[statically: { onMainActor() }] // expected-error{{type '@Sendable () -> Void'}}
3939
}
4040

4141
func testElsewhere(x: X) {
4242
let _: Int = unsafelySendableClosure // expected-error{{type '@Sendable (@Sendable () -> Void) -> ()'}}
43-
let _: Int = unsafelyMainActorClosure // expected-error{{type '@Sendable (@MainActor () -> Void) -> ()'}}
43+
let _: Int = unsafelyMainActorClosure // expected-error{{type '@Sendable (@MainActor @Sendable () -> Void) -> ()'}}
4444
let _: Int = unsafelyDoEverythingClosure // expected-error{{type '@Sendable (@MainActor @Sendable () -> Void) -> ()'}}
4545
let _: Int = x.unsafelyDoEverythingClosure // expected-error{{type '@Sendable (@MainActor @Sendable () -> Void) -> ()'}}
4646
let _: Int = X.unsafelyDoEverythingClosure // expected-error{{type '@Sendable (X) -> @Sendable (@MainActor @Sendable () -> Void) -> ()'}}
4747
let _: Int = (X.unsafelyDoEverythingClosure)(x) // expected-error{{type '@Sendable (@MainActor @Sendable () -> Void) -> ()'}}
4848

4949
let _: Int = x.sendableVar // expected-error{{type '@Sendable () -> Void'}}
50-
let _: Int = x.mainActorVar // expected-error{{type '@MainActor () -> Void'}}
50+
let _: Int = x.mainActorVar // expected-error{{type '@MainActor @Sendable () -> Void'}}
5151

5252
let _: Int = x[{ onMainActor() }] // expected-error{{type '@Sendable () -> Void'}}
5353
let _: Int = X[statically: { onMainActor() }] // expected-error{{type '@Sendable () -> Void'}}

test/Concurrency/sendable_objc_attr_in_type_context_swift6.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ class TestConformanceWithStripping : InnerSendableTypes {
125125
}
126126

127127
func test(withCallback name: String, handler: @escaping @MainActor ([String : Any], (any Error)?) -> Void) {
128-
// expected-note@-1 {{candidate has non-matching type '(String, @escaping @MainActor ([String : Any], (any Error)?) -> Void) -> ()'}}
128+
// expected-note@-1 {{candidate has non-matching type '(String, @escaping @MainActor @Sendable ([String : Any], (any Error)?) -> Void) -> ()'}}
129129
}
130130
}
131131

test/Concurrency/transfernonsendable_global_actor_sending.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func useValue<T>(_ t: T) {}
2626
let ns = NonSendableKlass()
2727

2828
// Will be resolved once @MainActor is @Sendable
29-
Task.fakeInit { @MainActor in // expected-error {{main actor-isolated value of type '@MainActor () async -> ()' passed as a strongly transferred parameter}}
29+
Task.fakeInit { @MainActor in // expected-error {{main actor-isolated value of type '@MainActor @Sendable () async -> ()' passed as a strongly transferred parameter}}
3030
print(ns)
3131
}
3232

test/Concurrency/transfernonsendable_sending_params.swift

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -358,20 +358,17 @@ func testTransferOtherParamTuple(_ x: sending Klass, y: (Klass, Klass)) async {
358358
func fakeInitOutside(operation: sending @escaping () async -> ()) {}
359359

360360
func taskIsolatedOutsideError(_ x: @escaping @MainActor () async -> ()) {
361-
fakeInitOutside(operation: x) // expected-warning {{sending 'x' risks causing data races}}
362-
// expected-note @-1 {{task-isolated 'x' is passed as a 'sending' parameter; Uses in callee may race with later task-isolated uses}}
361+
fakeInitOutside(operation: x) // okay; x is @Sendable
363362
}
364363

365364
@MainActor func actorIsolatedOutsideError(_ x: @escaping @MainActor () async -> ()) {
366-
fakeInitOutside(operation: x) // expected-warning {{sending 'x' risks causing data races}}
367-
// expected-note @-1 {{main actor-isolated 'x' is passed as a 'sending' parameter; Uses in callee may race with later main actor-isolated uses}}
365+
fakeInitOutside(operation: x) // okay; x is @Sendable
368366
}
369367

370368
func taskIsolatedInsideError(_ x: @escaping @MainActor () async -> ()) {
371369
func fakeInit(operation: sending @escaping () async -> ()) {}
372370

373-
fakeInit(operation: x) // expected-warning {{sending 'x' risks causing data races}}
374-
// expected-note @-1 {{task-isolated 'x' is passed as a 'sending' parameter; Uses in callee may race with later task-isolated uses}}
371+
fakeInit(operation: x) // okay; x is @Sendable
375372
}
376373

377374
@MainActor func actorIsolatedInsideError(_ x: @escaping @MainActor () async -> ()) {

test/IDE/print_clang_objc_async.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ import _Concurrency
9090
// CHECK: func __leap(_ height: Int) async -> String
9191

9292
// CHECK: @available(*, renamed: "runOnMainThread()")
93-
// CHECK-NEXT: func runOnMainThread(completionHandler completion: (@MainActor (String) -> Void)? = nil)
93+
// CHECK-NEXT: func runOnMainThread(completionHandler completion: (@MainActor @Sendable (String) -> Void)? = nil)
9494
// CHECK-NEXT: @discardableResult
9595
// CHECK-NEXT: func runOnMainThread() async -> String
9696

test/IDE/print_clang_objc_effectful_properties.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@
3333
// CHECK-NEXT: var fromNullableHandler: String { get async }
3434

3535
// CHECK: @available(*, renamed: "getter:mainDogProp()")
36-
// CHECK-NEXT: func getMainDog(_ completion: @escaping @MainActor (String) -> Void)
36+
// CHECK-NEXT: func getMainDog(_ completion: @escaping @MainActor @Sendable (String) -> Void)
3737
// CHECK-NEXT: var mainDogProp: String { get async }
3838

3939
// CHECK: @available(*, renamed: "regularMainDog()")
40-
// CHECK-NEXT: func regularMainDog(_ completion: @escaping @MainActor (String) -> Void)
40+
// CHECK-NEXT: func regularMainDog(_ completion: @escaping @MainActor @Sendable (String) -> Void)
4141
// CHECK-NEXT: @discardableResult
4242
// CHECK-NEXT: func regularMainDog() async -> String
4343
// CHECK: }

0 commit comments

Comments
 (0)