Skip to content

Commit cee2aee

Browse files
committed
AST: Fix ExistentialLayout::isObjC() handling of marker protocols
Fixes rdar://problem/119541554.
1 parent ca7dbed commit cee2aee

File tree

5 files changed

+36
-23
lines changed

5 files changed

+36
-23
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
}
3738

@@ -45,8 +46,11 @@ struct ExistentialLayout {
4546
/// Whether the existential contains an explicit '& AnyObject' constraint.
4647
bool hasExplicitAnyObject : 1;
4748

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

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

7781
/// Whether the existential requires a class, either via an explicit
@@ -105,10 +109,6 @@ struct ExistentialLayout {
105109
/// Zero or more primary associated type requirements from a
106110
/// ParameterizedProtocolType
107111
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);
112112
};
113113

114114
}

lib/AST/ASTVerifier.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1659,7 +1659,7 @@ class Verifier : public ASTWalker {
16591659
auto concreteLayout = concreteTy->getCanonicalType()
16601660
->getExistentialLayout();
16611661
canBeClass = concreteLayout.getKind() == ExistentialLayout::Kind::Class
1662-
&& !concreteLayout.containsNonObjCProtocol;
1662+
&& !concreteLayout.containsSwiftProtocol;
16631663
} else {
16641664
canBeClass = false;
16651665
}

lib/AST/Type.cpp

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

301301
hasExplicitAnyObject = false;
302-
containsNonObjCProtocol = !isObjCProtocol(protoDecl);
302+
containsObjCProtocol = protoDecl->isObjC();
303+
containsSwiftProtocol = (!protoDecl->isObjC() &&
304+
!protoDecl->isMarkerProtocol());
303305
containsParameterized = false;
304306

305307
protocols.push_back(protoDecl);
306308
}
307309

308310
ExistentialLayout::ExistentialLayout(CanProtocolCompositionType type) {
309311
hasExplicitAnyObject = type->hasExplicitAnyObject();
310-
containsNonObjCProtocol = false;
312+
containsObjCProtocol = false;
313+
containsSwiftProtocol = false;
311314
containsParameterized = false;
312315

313316
auto members = type.getMembers();
@@ -327,7 +330,10 @@ ExistentialLayout::ExistentialLayout(CanProtocolCompositionType type) {
327330
protoDecl = parameterized->getProtocol();
328331
containsParameterized = true;
329332
}
330-
containsNonObjCProtocol |= !isObjCProtocol(protoDecl);
333+
if (protoDecl->isObjC())
334+
containsObjCProtocol = true;
335+
else if (!protoDecl->isMarkerProtocol())
336+
containsSwiftProtocol = true;
331337
protocols.push_back(protoDecl);
332338
}
333339
}
@@ -338,10 +344,6 @@ ExistentialLayout::ExistentialLayout(CanParameterizedProtocolType type)
338344
containsParameterized = true;
339345
}
340346

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

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/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)