Skip to content

Commit 0dab1b7

Browse files
committed
Ensure that lookup of Sendable always considers superclass Sendable.
Fixes rdar://90617628.
1 parent c4e6e6d commit 0dab1b7

File tree

3 files changed

+40
-17
lines changed

3 files changed

+40
-17
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4516,27 +4516,27 @@ ProtocolConformance *GetImplicitSendableRequest::evaluate(
45164516
return conformance;
45174517
};
45184518

4519-
// A non-protocol type with a global actor is implicitly Sendable.
4520-
if (nominal->getGlobalActorAttr()) {
4521-
// If this is a class, check the superclass. If it's already Sendable,
4522-
// form an inherited conformance.
4523-
if (classDecl) {
4524-
if (Type superclass = classDecl->getSuperclass()) {
4525-
auto classModule = classDecl->getParentModule();
4526-
if (auto inheritedConformance = TypeChecker::conformsToProtocol(
4527-
classDecl->mapTypeIntoContext(superclass),
4528-
proto, classModule, /*allowMissing=*/false)) {
4529-
inheritedConformance = inheritedConformance
4530-
.mapConformanceOutOfContext();
4531-
if (inheritedConformance.isConcrete()) {
4532-
return ctx.getInheritedConformance(
4533-
nominal->getDeclaredInterfaceType(),
4534-
inheritedConformance.getConcrete());
4535-
}
4519+
// If this is a class, check the superclass. If it's already Sendable,
4520+
// form an inherited conformance.
4521+
if (classDecl) {
4522+
if (Type superclass = classDecl->getSuperclass()) {
4523+
auto classModule = classDecl->getParentModule();
4524+
if (auto inheritedConformance = TypeChecker::conformsToProtocol(
4525+
classDecl->mapTypeIntoContext(superclass),
4526+
proto, classModule, /*allowMissing=*/false)) {
4527+
inheritedConformance = inheritedConformance
4528+
.mapConformanceOutOfContext();
4529+
if (inheritedConformance.isConcrete()) {
4530+
return ctx.getInheritedConformance(
4531+
nominal->getDeclaredInterfaceType(),
4532+
inheritedConformance.getConcrete());
45364533
}
45374534
}
45384535
}
4536+
}
45394537

4538+
// A non-protocol type with a global actor is implicitly Sendable.
4539+
if (nominal->getGlobalActorAttr()) {
45404540
// Form the implicit conformance to Sendable.
45414541
return formConformance(nullptr);
45424542
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -I %S/Inputs/custom-modules %s -verify -parse-as-library -require-explicit-sendable
2+
3+
// REQUIRES: objc_interop
4+
// REQUIRES: concurrency
5+
import Foundation
6+
import ObjCConcurrency
7+
8+
open class X: NXView { }
9+
open class Y: X { }
10+
11+
12+
open class Z: NSObject { } // expected-warning{{public class 'Z' does not specify whether it is 'Sendable' or not}}
13+
// expected-note@-1{{add '@unchecked Sendable' conformance to class 'Z' if this type manually implements concurrency safety}}
14+
// expected-note@-2{{make class 'Z' explicitly non-Sendable to suppress this warning}}

test/Concurrency/require-explicit-sendable.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,12 @@ struct S11: Sendable {
9999
}
100100

101101
@_nonSendable public struct S12 { }
102+
103+
// Don't complain about global-actor-qualified classes or their subclasses.
104+
@MainActor
105+
open class TestThing {}
106+
open class TestSubThing : TestThing {}
107+
108+
@MainActor(unsafe)
109+
open class TestThing2 {}
110+
open class TestSubThing2 : TestThing2 {}

0 commit comments

Comments
 (0)