Skip to content

Commit 7fe6cd8

Browse files
committed
[SE-0338] Perform Sendable checking when exiting an actor via conformance.
When a requirement is actor-isolated and asynchronous but its witness is non-isolated, perform Sendable checking on the requirement's type. (cherry picked from commit 717da76)
1 parent 87b43e6 commit 7fe6cd8

File tree

2 files changed

+13
-6
lines changed

2 files changed

+13
-6
lines changed

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2954,6 +2954,10 @@ bool ConformanceChecker::checkActorIsolation(
29542954
requirementIsolation = requirementIsolation.subst(subs);
29552955
}
29562956

2957+
SourceLoc loc = witness->getLoc();
2958+
if (loc.isInvalid())
2959+
loc = Conformance->getLoc();
2960+
29572961
auto refResult = ActorReferenceResult::forReference(
29582962
getConcreteWitness(), witness->getLoc(), DC, None, None,
29592963
None, requirementIsolation);
@@ -2971,7 +2975,8 @@ bool ConformanceChecker::checkActorIsolation(
29712975
return false;
29722976

29732977
case ActorReferenceResult::ExitsActorToNonisolated:
2974-
// FIXME: SE-0338 would diagnose this.
2978+
diagnoseNonSendableTypesInReference(
2979+
getConcreteWitness(), DC, loc, SendableCheckReason::Conformance);
29752980
return false;
29762981

29772982
case ActorReferenceResult::EntersActor:
@@ -3015,10 +3020,6 @@ bool ConformanceChecker::checkActorIsolation(
30153020

30163021
// If we aren't missing anything, do a Sendable check and move on.
30173022
if (!missingOptions) {
3018-
SourceLoc loc = witness->getLoc();
3019-
if (loc.isInvalid())
3020-
loc = Conformance->getLoc();
3021-
30223023
// FIXME: Disable Sendable checking when the witness is an initializer
30233024
// that is explicitly marked nonisolated.
30243025
if (isa<ConstructorDecl>(witness) &&

test/Concurrency/sendable_conformance_checking.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// REQUIRES: concurrency
33

44
@available(SwiftStdlib 5.1, *)
5-
class NotSendable { // expected-note 8{{class 'NotSendable' does not conform to the 'Sendable' protocol}}
5+
class NotSendable { // expected-note 9{{class 'NotSendable' does not conform to the 'Sendable' protocol}}
66
}
77

88
@available(SwiftStdlib 5.1, *)
@@ -13,13 +13,16 @@ extension NotSendable: Sendable { }
1313
protocol IsolatedWithNotSendableRequirements: Actor {
1414
func f() -> NotSendable
1515
var prop: NotSendable { get }
16+
17+
func fAsync() async -> NotSendable
1618
}
1719

1820
// Okay, everything is isolated the same way
1921
@available(SwiftStdlib 5.1, *)
2022
actor A1: IsolatedWithNotSendableRequirements {
2123
func f() -> NotSendable { NotSendable() }
2224
var prop: NotSendable { NotSendable() }
25+
func fAsync() async -> NotSendable { NotSendable() }
2326
}
2427

2528
// Okay, sendable checking occurs when calling through the protocol
@@ -28,6 +31,9 @@ actor A1: IsolatedWithNotSendableRequirements {
2831
actor A2: IsolatedWithNotSendableRequirements {
2932
nonisolated func f() -> NotSendable { NotSendable() }
3033
nonisolated var prop: NotSendable { NotSendable() }
34+
35+
nonisolated func fAsync() async -> NotSendable { NotSendable() }
36+
// expected-warning@-1{{non-sendable type 'NotSendable' returned by nonisolated instance method 'fAsync()' satisfying protocol requirement cannot cross actor boundary}}
3137
}
3238

3339
@available(SwiftStdlib 5.1, *)

0 commit comments

Comments
 (0)