Skip to content

Commit e5614cd

Browse files
committed
[Concurrency] Skip Sendable checking for nonisolated(nonsending) -> @concurrent conversions
Converting a `nonisolated(nonsending)` function type to a `@concurrent` one is the same as converting it to an actor-isolated function type. `nonisolated(nonsending)` functions run on the caller's actor without crossing an isolation boundary and so no Sendable checking is necessary. Resolves: swiftlang#87235 Resolves: rdar://170380869 (cherry picked from commit 5f9efd2)
1 parent c101b8a commit e5614cd

File tree

2 files changed

+10
-12
lines changed

2 files changed

+10
-12
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2829,7 +2829,6 @@ namespace {
28292829
case FunctionTypeIsolation::Kind::NonIsolated: {
28302830
switch (fromIsolation.getKind()) {
28312831
case FunctionTypeIsolation::Kind::Parameter:
2832-
case FunctionTypeIsolation::Kind::NonIsolatedNonsending:
28332832
case FunctionTypeIsolation::Kind::Erased:
28342833
diagnoseNonSendableParametersAndResult(
28352834
toFnType, version::Version::getFutureMajorLanguageVersion());
@@ -2841,13 +2840,13 @@ namespace {
28412840
break;
28422841
}
28432842

2844-
case FunctionTypeIsolation::Kind::NonIsolated: {
2845-
// nonisolated synchronous <-> @concurrent
2846-
if (fromFnType->isAsync() != toFnType->isAsync()) {
2847-
diagnoseNonSendableParametersAndResult(
2848-
toFnType,
2849-
version::Version::getFutureMajorLanguageVersion());
2850-
}
2843+
case FunctionTypeIsolation::Kind::NonIsolated:
2844+
case FunctionTypeIsolation::Kind::NonIsolatedNonsending: {
2845+
// Converting a `nonisolated(nonsending)` function type to a
2846+
// `@concurrent` one is the same as converting it to an
2847+
// actor-isolated function type. `nonisolated(nonsending)`
2848+
// functions run on the caller's actor without crossing an
2849+
// isolation boundary and so no Sendable checking is necessary.
28512850
break;
28522851
}
28532852
}

test/Concurrency/attr_execution/conversions.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,9 @@ func testNonSendableDiagnostics(
141141
// expected-warning@-1 {{cannot convert '@isolated(any) @Sendable () async -> NonSendable' to '() async -> NonSendable' because crossing of an isolation boundary requires parameter and result types to conform to 'Sendable' protocol}}
142142

143143

144-
let _: @concurrent (NonSendable) async -> Void = caller1 // expected-note {{type 'NonSendable' does not conform to 'Sendable' protocol}}
145-
// expected-warning@-1 {{cannot convert 'nonisolated(nonsending) @Sendable (NonSendable) async -> Void' to '(NonSendable) async -> Void' because crossing of an isolation boundary requires parameter and result types to conform to 'Sendable' protocol}}
146-
let _: @concurrent () async -> NonSendable = caller2 // expected-note {{type 'NonSendable' does not conform to 'Sendable' protocol}}
147-
// expected-warning@-1 {{cannot convert 'nonisolated(nonsending) @Sendable () async -> NonSendable' to '() async -> NonSendable' because crossing of an isolation boundary requires parameter and result types to conform to 'Sendable' protocol}}
144+
// Calling `nonisolated(nonsending)` from `@concurrent` doesn't cross an isolation boundary.
145+
let _: @concurrent (NonSendable) async -> Void = caller1 // Ok
146+
let _: @concurrent () async -> NonSendable = caller2 // Ok
148147

149148
let _: @MainActor (NonSendable) async -> Void = nonIsolated1 // Ok
150149
let _: @MainActor (NonSendable) async -> Void = nonIsolated2 // expected-note {{type 'NonSendable' does not conform to 'Sendable' protocol}}

0 commit comments

Comments
 (0)