Skip to content

Commit 4c2c3d3

Browse files
authored
Merge pull request swiftlang#69540 from xedin/rdar-102728938-5.10
[5.10][AST/TypeChecker] Allow existential values of Sendable be used from Objective-C
2 parents 5071d59 + e6b7686 commit 4c2c3d3

File tree

7 files changed

+52
-9
lines changed

7 files changed

+52
-9
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5906,8 +5906,9 @@ ERROR(invalid_objc_decl_context,none,
59065906
"@objc can only be used with members of classes, @objc protocols, and "
59075907
"concrete extensions of classes", ())
59085908
ERROR(invalid_objc_decl,none,
5909-
"only classes (and their extensions), protocols, methods, initializers, "
5910-
"properties, and subscript declarations can be declared @objc", ())
5909+
"only classes (and their extensions), non-marker protocols, methods, "
5910+
"initializers, properties, and subscript declarations can be declared"
5911+
" @objc", ())
59115912
ERROR(invalid_objc_swift_rooted_class,none,
59125913
"only classes that inherit from NSObject can be declared @objc", ())
59135914
NOTE(invalid_objc_swift_root_class_insert_nsobject,none,

include/swift/AST/ExistentialLayout.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ struct ExistentialLayout {
105105
/// Zero or more primary associated type requirements from a
106106
/// ParameterizedProtocolType
107107
ArrayRef<Type> sameTypeRequirements;
108+
109+
/// Existentials allow a relaxed notion of \c ValueDecl::isObjC
110+
/// that includes `Sendable` protocol.
111+
static bool isObjCProtocol(ProtocolDecl *P);
108112
};
109113

110114
}

lib/AST/Type.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ ExistentialLayout::ExistentialLayout(CanProtocolType type) {
299299
auto *protoDecl = type->getDecl();
300300

301301
hasExplicitAnyObject = false;
302-
containsNonObjCProtocol = !protoDecl->isObjC();
302+
containsNonObjCProtocol = !isObjCProtocol(protoDecl);
303303
containsParameterized = false;
304304

305305
protocols.push_back(protoDecl);
@@ -327,9 +327,7 @@ ExistentialLayout::ExistentialLayout(CanProtocolCompositionType type) {
327327
protoDecl = parameterized->getProtocol();
328328
containsParameterized = true;
329329
}
330-
containsNonObjCProtocol |=
331-
!protoDecl->isObjC() &&
332-
!protoDecl->isSpecificProtocol(KnownProtocolKind::Sendable);
330+
containsNonObjCProtocol |= !isObjCProtocol(protoDecl);
333331
protocols.push_back(protoDecl);
334332
}
335333
}
@@ -340,6 +338,10 @@ ExistentialLayout::ExistentialLayout(CanParameterizedProtocolType type)
340338
containsParameterized = true;
341339
}
342340

341+
bool ExistentialLayout::isObjCProtocol(ProtocolDecl *P) {
342+
return P->isObjC() || P->isSpecificProtocol(KnownProtocolKind::Sendable);
343+
}
344+
343345
ExistentialLayout TypeBase::getExistentialLayout() {
344346
return getCanonicalType().getExistentialLayout();
345347
}

lib/PrintAsClang/ModuleContentsWriter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,8 @@ class ModuleWriter {
326326
(void)addImport(CD);
327327
}
328328
} else if (auto PD = dyn_cast<ProtocolDecl>(TD)) {
329-
forwardDeclare(PD);
329+
if (!PD->isMarkerProtocol())
330+
forwardDeclare(PD);
330331
} else if (auto TAD = dyn_cast<TypeAliasDecl>(TD)) {
331332
bool imported = false;
332333
if (TAD->hasClangNode())

lib/Sema/TypeCheckAttr.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1303,9 +1303,12 @@ void AttributeChecker::visitObjCAttr(ObjCAttr *attr) {
13031303

13041304
// Only certain decls can be ObjC.
13051305
llvm::Optional<Diag<>> error;
1306-
if (isa<ClassDecl>(D) ||
1307-
isa<ProtocolDecl>(D)) {
1306+
if (isa<ClassDecl>(D)) {
13081307
/* ok */
1308+
} else if (auto *P = dyn_cast<ProtocolDecl>(D)) {
1309+
if (P->isMarkerProtocol())
1310+
error = diag::invalid_objc_decl;
1311+
/* ok on non-marker protocols */
13091312
} else if (auto Ext = dyn_cast<ExtensionDecl>(D)) {
13101313
if (!Ext->getSelfClassDecl())
13111314
error = diag::objc_extension_not_class;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck %s -parse-as-library -emit-objc-header-path %t/swift.h
3+
// RUN: %FileCheck %s < %t/swift.h
4+
5+
// REQUIRES: concurrency
6+
// REQUIRES: asserts
7+
// REQUIRES: objc_interop
8+
9+
import Foundation
10+
11+
@objc public protocol P {}
12+
13+
@objc public class Klass : NSObject {
14+
// CHECK: - (void)test1:(NSDictionary<NSString *, id> * _Nonnull)_;
15+
@objc public func test1(_: [String: any Sendable]) {}
16+
// CHECK: - (void)test2:(NSDictionary<NSString *, id <P>> * _Nonnull)_;
17+
@objc public func test2(_: [String: any P & Sendable]) {}
18+
}
19+
20+
@objc public protocol Q {
21+
// CHECK: - (NSArray<NSDictionary<NSString *, id> *> * _Nonnull)data1 SWIFT_WARN_UNUSED_RESULT;
22+
func data1() -> [[String: any Sendable]]
23+
// CHECK: - (NSArray<id> * _Nullable)data2 SWIFT_WARN_UNUSED_RESULT;
24+
func data2() -> [any Sendable]?
25+
// CHECK: - (void)data3:(id _Nonnull)_;
26+
func data3(_: any Sendable)
27+
// CHECK: - (void)data4:(id _Nullable)_;
28+
func data4(_: (any Sendable)?)
29+
}

test/attr/attr_marker_protocol.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,6 @@ protocol P10 { }
6767

6868
extension Array: P10 where Element: P10, Element: P8 { }
6969
// expected-error@-1{{conditional conformance to non-marker protocol 'P10' cannot depend on conformance of 'Element' to marker protocol 'P8'}}
70+
71+
@objc @_marker protocol P11 {}
72+
// expected-error@-1 {{only classes (and their extensions), non-marker protocols, methods, initializers, properties, and subscript declarations can be declared @objc}}

0 commit comments

Comments
 (0)