Skip to content

Commit 0392f37

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.
1 parent 0cb61bd commit 0392f37

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
@@ -2955,6 +2955,10 @@ bool ConformanceChecker::checkActorIsolation(
29552955
requirementIsolation = requirementIsolation.subst(subs);
29562956
}
29572957

2958+
SourceLoc loc = witness->getLoc();
2959+
if (loc.isInvalid())
2960+
loc = Conformance->getLoc();
2961+
29582962
auto refResult = ActorReferenceResult::forReference(
29592963
getConcreteWitness(), witness->getLoc(), DC, None, None,
29602964
None, requirementIsolation);
@@ -2972,7 +2976,8 @@ bool ConformanceChecker::checkActorIsolation(
29722976
return false;
29732977

29742978
case ActorReferenceResult::ExitsActorToNonisolated:
2975-
// FIXME: SE-0338 would diagnose this.
2979+
diagnoseNonSendableTypesInReference(
2980+
getConcreteWitness(), DC, loc, SendableCheckReason::Conformance);
29762981
return false;
29772982

29782983
case ActorReferenceResult::EntersActor:
@@ -3016,10 +3021,6 @@ bool ConformanceChecker::checkActorIsolation(
30163021

30173022
// If we aren't missing anything, do a Sendable check and move on.
30183023
if (!missingOptions) {
3019-
SourceLoc loc = witness->getLoc();
3020-
if (loc.isInvalid())
3021-
loc = Conformance->getLoc();
3022-
30233024
// FIXME: Disable Sendable checking when the witness is an initializer
30243025
// that is explicitly marked nonisolated.
30253026
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)