Skip to content

Commit 2ffc8cc

Browse files
authored
Merge pull request #70499 from slavapestov/fix-rdar119541554
AST: Fix ExistentialLayout::isObjC() handling of marker protocols
2 parents a7a8ba1 + 79e9b96 commit 2ffc8cc

File tree

7 files changed

+39
-26
lines changed

7 files changed

+39
-26
lines changed

include/swift/AST/ExistentialLayout.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ struct ExistentialLayout {
3131

3232
ExistentialLayout() {
3333
hasExplicitAnyObject = false;
34-
containsNonObjCProtocol = false;
34+
containsObjCProtocol = false;
35+
containsSwiftProtocol = false;
3536
containsParameterized = false;
3637
representsAnyObject = false;
3738
}
@@ -46,8 +47,11 @@ struct ExistentialLayout {
4647
/// Whether the existential contains an explicit '& AnyObject' constraint.
4748
bool hasExplicitAnyObject : 1;
4849

49-
/// Whether any protocol members are non-@objc.
50-
bool containsNonObjCProtocol : 1;
50+
/// Whether any protocol members are @objc.
51+
bool containsObjCProtocol : 1;
52+
53+
/// Whether any protocol members require a witness table.
54+
bool containsSwiftProtocol : 1;
5155

5256
/// Whether any protocol members are parameterized.s
5357
bool containsParameterized : 1;
@@ -74,8 +78,8 @@ struct ExistentialLayout {
7478
// FIXME: Does the superclass have to be @objc?
7579
return ((explicitSuperclass ||
7680
hasExplicitAnyObject ||
77-
!getProtocols().empty()) &&
78-
!containsNonObjCProtocol);
81+
containsObjCProtocol) &&
82+
!containsSwiftProtocol);
7983
}
8084

8185
/// Whether the existential requires a class, either via an explicit
@@ -109,10 +113,6 @@ struct ExistentialLayout {
109113
/// Zero or more primary associated type requirements from a
110114
/// ParameterizedProtocolType
111115
ArrayRef<Type> sameTypeRequirements;
112-
113-
/// Existentials allow a relaxed notion of \c ValueDecl::isObjC
114-
/// that includes `Sendable` protocol.
115-
static bool isObjCProtocol(ProtocolDecl *P);
116116
};
117117

118118
}

lib/AST/ASTVerifier.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1703,7 +1703,7 @@ class Verifier : public ASTWalker {
17031703
auto concreteLayout = concreteTy->getCanonicalType()
17041704
->getExistentialLayout();
17051705
canBeClass = concreteLayout.getKind() == ExistentialLayout::Kind::Class
1706-
&& !concreteLayout.containsNonObjCProtocol;
1706+
&& !concreteLayout.containsSwiftProtocol;
17071707
} else {
17081708
canBeClass = false;
17091709
}

lib/AST/Type.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,9 @@ ExistentialLayout::ExistentialLayout(CanProtocolType type) {
372372
auto *protoDecl = type->getDecl();
373373

374374
hasExplicitAnyObject = false;
375-
containsNonObjCProtocol = !isObjCProtocol(protoDecl);
375+
containsObjCProtocol = protoDecl->isObjC();
376+
containsSwiftProtocol = (!protoDecl->isObjC() &&
377+
!protoDecl->isMarkerProtocol());
376378
containsParameterized = false;
377379
representsAnyObject = false;
378380

@@ -384,7 +386,8 @@ ExistentialLayout::ExistentialLayout(CanProtocolType type) {
384386

385387
ExistentialLayout::ExistentialLayout(CanProtocolCompositionType type) {
386388
hasExplicitAnyObject = type->hasExplicitAnyObject();
387-
containsNonObjCProtocol = false;
389+
containsObjCProtocol = false;
390+
containsSwiftProtocol = false;
388391
containsParameterized = false;
389392

390393
auto members = type.getMembers();
@@ -404,7 +407,10 @@ ExistentialLayout::ExistentialLayout(CanProtocolCompositionType type) {
404407
protoDecl = parameterized->getProtocol();
405408
containsParameterized = true;
406409
}
407-
containsNonObjCProtocol |= !isObjCProtocol(protoDecl);
410+
if (protoDecl->isObjC())
411+
containsObjCProtocol = true;
412+
else if (!protoDecl->isMarkerProtocol())
413+
containsSwiftProtocol = true;
408414
protocols.push_back(protoDecl);
409415
}
410416

@@ -421,10 +427,6 @@ ExistentialLayout::ExistentialLayout(CanParameterizedProtocolType type)
421427
containsParameterized = true;
422428
}
423429

424-
bool ExistentialLayout::isObjCProtocol(ProtocolDecl *P) {
425-
return P->isObjC() || P->isSpecificProtocol(KnownProtocolKind::Sendable);
426-
}
427-
428430
ExistentialLayout TypeBase::getExistentialLayout() {
429431
return getCanonicalType().getExistentialLayout();
430432
}

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ static bool isNSObjectOrAnyHashable(ASTContext &ctx, Type type) {
6060
}
6161

6262
static bool isAnyObjectOrAny(Type type) {
63-
return type->isAnyObject() || type->isAny();
63+
return type->isAnyObject() || type->isMarkerExistential();
6464
}
6565

6666
// For a given Decl and Type, if the type is not an optional return
@@ -2377,7 +2377,7 @@ class DeclAndTypePrinter::Implementation
23772377
// Use the type as bridged to Objective-C unless the element type is itself
23782378
// an imported type or a collection.
23792379
const StructDecl *SD = ty->getStructOrBoundGenericStruct();
2380-
if (ty->isAny()) {
2380+
if (ty->isMarkerExistential()) {
23812381
ty = ctx.getAnyObjectType();
23822382
} else if (!ty->isKnownStdlibCollectionType() && !isSwiftNewtype(SD)) {
23832383
ty = ctx.getBridgedToObjC(&owningPrinter.M, ty);

lib/SIL/IR/SILType.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -255,12 +255,8 @@ static bool isSingleSwiftRefcounted(SILModule &M,
255255
if (Ty->isAnyExistentialType()) {
256256
auto layout = Ty->getExistentialLayout();
257257
// Must be no protocol constraints that aren't @objc or @_marker.
258-
if (layout.containsNonObjCProtocol) {
259-
for (auto proto : layout.getProtocols()) {
260-
if (!proto->isObjC() && !proto->isMarkerProtocol()) {
261-
return false;
262-
}
263-
}
258+
if (layout.containsSwiftProtocol) {
259+
return false;
264260
}
265261

266262
// The Error existential has its own special layout.
@@ -592,6 +588,7 @@ SILType::getPreferredExistentialRepresentation(Type containedType) const {
592588
return ExistentialRepresentation::Class;
593589

594590
// Otherwise, we need to use a fixed-sized buffer.
591+
assert(!layout.isObjC());
595592
return ExistentialRepresentation::Opaque;
596593
}
597594

test/Concurrency/emit_objc_header_with_Sendable.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import Foundation
2020
@objc public protocol Q {
2121
// CHECK: - (NSArray<NSDictionary<NSString *, id> *> * _Nonnull)data1 SWIFT_WARN_UNUSED_RESULT;
2222
func data1() -> [[String: any Sendable]]
23-
// CHECK: - (NSArray<id> * _Nullable)data2 SWIFT_WARN_UNUSED_RESULT;
23+
// CHECK: - (NSArray * _Nullable)data2 SWIFT_WARN_UNUSED_RESULT;
2424
func data2() -> [any Sendable]?
2525
// CHECK: - (void)data3:(id _Nonnull)_;
2626
func data3(_: any Sendable)

test/Interpreter/rdar119541554.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// RUN: %target-build-swift %s -o %t/a.out -O -target %target-future-triple
4+
// RUN: %target-codesign %t/a.out
5+
// RUN: %target-run %t/a.out
6+
7+
// REQUIRES: executable_test
8+
// REQUIRES: macos_min_version_13
9+
10+
struct S {
11+
var x = 42
12+
}
13+
14+
_ = [S() as Sendable]

0 commit comments

Comments
 (0)