mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge pull request #70499 from slavapestov/fix-rdar119541554
AST: Fix ExistentialLayout::isObjC() handling of marker protocols
This commit is contained in:
@@ -31,7 +31,8 @@ struct ExistentialLayout {
|
||||
|
||||
ExistentialLayout() {
|
||||
hasExplicitAnyObject = false;
|
||||
containsNonObjCProtocol = false;
|
||||
containsObjCProtocol = false;
|
||||
containsSwiftProtocol = false;
|
||||
containsParameterized = false;
|
||||
representsAnyObject = false;
|
||||
}
|
||||
@@ -46,8 +47,11 @@ struct ExistentialLayout {
|
||||
/// Whether the existential contains an explicit '& AnyObject' constraint.
|
||||
bool hasExplicitAnyObject : 1;
|
||||
|
||||
/// Whether any protocol members are non-@objc.
|
||||
bool containsNonObjCProtocol : 1;
|
||||
/// Whether any protocol members are @objc.
|
||||
bool containsObjCProtocol : 1;
|
||||
|
||||
/// Whether any protocol members require a witness table.
|
||||
bool containsSwiftProtocol : 1;
|
||||
|
||||
/// Whether any protocol members are parameterized.s
|
||||
bool containsParameterized : 1;
|
||||
@@ -74,8 +78,8 @@ struct ExistentialLayout {
|
||||
// FIXME: Does the superclass have to be @objc?
|
||||
return ((explicitSuperclass ||
|
||||
hasExplicitAnyObject ||
|
||||
!getProtocols().empty()) &&
|
||||
!containsNonObjCProtocol);
|
||||
containsObjCProtocol) &&
|
||||
!containsSwiftProtocol);
|
||||
}
|
||||
|
||||
/// Whether the existential requires a class, either via an explicit
|
||||
@@ -109,10 +113,6 @@ private:
|
||||
/// Zero or more primary associated type requirements from a
|
||||
/// ParameterizedProtocolType
|
||||
ArrayRef<Type> sameTypeRequirements;
|
||||
|
||||
/// Existentials allow a relaxed notion of \c ValueDecl::isObjC
|
||||
/// that includes `Sendable` protocol.
|
||||
static bool isObjCProtocol(ProtocolDecl *P);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1703,7 +1703,7 @@ public:
|
||||
auto concreteLayout = concreteTy->getCanonicalType()
|
||||
->getExistentialLayout();
|
||||
canBeClass = concreteLayout.getKind() == ExistentialLayout::Kind::Class
|
||||
&& !concreteLayout.containsNonObjCProtocol;
|
||||
&& !concreteLayout.containsSwiftProtocol;
|
||||
} else {
|
||||
canBeClass = false;
|
||||
}
|
||||
|
||||
@@ -372,7 +372,9 @@ ExistentialLayout::ExistentialLayout(CanProtocolType type) {
|
||||
auto *protoDecl = type->getDecl();
|
||||
|
||||
hasExplicitAnyObject = false;
|
||||
containsNonObjCProtocol = !isObjCProtocol(protoDecl);
|
||||
containsObjCProtocol = protoDecl->isObjC();
|
||||
containsSwiftProtocol = (!protoDecl->isObjC() &&
|
||||
!protoDecl->isMarkerProtocol());
|
||||
containsParameterized = false;
|
||||
representsAnyObject = false;
|
||||
|
||||
@@ -384,7 +386,8 @@ ExistentialLayout::ExistentialLayout(CanProtocolType type) {
|
||||
|
||||
ExistentialLayout::ExistentialLayout(CanProtocolCompositionType type) {
|
||||
hasExplicitAnyObject = type->hasExplicitAnyObject();
|
||||
containsNonObjCProtocol = false;
|
||||
containsObjCProtocol = false;
|
||||
containsSwiftProtocol = false;
|
||||
containsParameterized = false;
|
||||
|
||||
auto members = type.getMembers();
|
||||
@@ -404,7 +407,10 @@ ExistentialLayout::ExistentialLayout(CanProtocolCompositionType type) {
|
||||
protoDecl = parameterized->getProtocol();
|
||||
containsParameterized = true;
|
||||
}
|
||||
containsNonObjCProtocol |= !isObjCProtocol(protoDecl);
|
||||
if (protoDecl->isObjC())
|
||||
containsObjCProtocol = true;
|
||||
else if (!protoDecl->isMarkerProtocol())
|
||||
containsSwiftProtocol = true;
|
||||
protocols.push_back(protoDecl);
|
||||
}
|
||||
|
||||
@@ -421,10 +427,6 @@ ExistentialLayout::ExistentialLayout(CanParameterizedProtocolType type)
|
||||
containsParameterized = true;
|
||||
}
|
||||
|
||||
bool ExistentialLayout::isObjCProtocol(ProtocolDecl *P) {
|
||||
return P->isObjC() || P->isSpecificProtocol(KnownProtocolKind::Sendable);
|
||||
}
|
||||
|
||||
ExistentialLayout TypeBase::getExistentialLayout() {
|
||||
return getCanonicalType().getExistentialLayout();
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ static bool isNSObjectOrAnyHashable(ASTContext &ctx, Type type) {
|
||||
}
|
||||
|
||||
static bool isAnyObjectOrAny(Type type) {
|
||||
return type->isAnyObject() || type->isAny();
|
||||
return type->isAnyObject() || type->isMarkerExistential();
|
||||
}
|
||||
|
||||
// For a given Decl and Type, if the type is not an optional return
|
||||
@@ -2377,7 +2377,7 @@ private:
|
||||
// Use the type as bridged to Objective-C unless the element type is itself
|
||||
// an imported type or a collection.
|
||||
const StructDecl *SD = ty->getStructOrBoundGenericStruct();
|
||||
if (ty->isAny()) {
|
||||
if (ty->isMarkerExistential()) {
|
||||
ty = ctx.getAnyObjectType();
|
||||
} else if (!ty->isKnownStdlibCollectionType() && !isSwiftNewtype(SD)) {
|
||||
ty = ctx.getBridgedToObjC(&owningPrinter.M, ty);
|
||||
|
||||
@@ -255,12 +255,8 @@ static bool isSingleSwiftRefcounted(SILModule &M,
|
||||
if (Ty->isAnyExistentialType()) {
|
||||
auto layout = Ty->getExistentialLayout();
|
||||
// Must be no protocol constraints that aren't @objc or @_marker.
|
||||
if (layout.containsNonObjCProtocol) {
|
||||
for (auto proto : layout.getProtocols()) {
|
||||
if (!proto->isObjC() && !proto->isMarkerProtocol()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (layout.containsSwiftProtocol) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The Error existential has its own special layout.
|
||||
@@ -592,6 +588,7 @@ SILType::getPreferredExistentialRepresentation(Type containedType) const {
|
||||
return ExistentialRepresentation::Class;
|
||||
|
||||
// Otherwise, we need to use a fixed-sized buffer.
|
||||
assert(!layout.isObjC());
|
||||
return ExistentialRepresentation::Opaque;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import Foundation
|
||||
@objc public protocol Q {
|
||||
// CHECK: - (NSArray<NSDictionary<NSString *, id> *> * _Nonnull)data1 SWIFT_WARN_UNUSED_RESULT;
|
||||
func data1() -> [[String: any Sendable]]
|
||||
// CHECK: - (NSArray<id> * _Nullable)data2 SWIFT_WARN_UNUSED_RESULT;
|
||||
// CHECK: - (NSArray * _Nullable)data2 SWIFT_WARN_UNUSED_RESULT;
|
||||
func data2() -> [any Sendable]?
|
||||
// CHECK: - (void)data3:(id _Nonnull)_;
|
||||
func data3(_: any Sendable)
|
||||
|
||||
14
test/Interpreter/rdar119541554.swift
Normal file
14
test/Interpreter/rdar119541554.swift
Normal file
@@ -0,0 +1,14 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
|
||||
// RUN: %target-build-swift %s -o %t/a.out -O -target %target-future-triple
|
||||
// RUN: %target-codesign %t/a.out
|
||||
// RUN: %target-run %t/a.out
|
||||
|
||||
// REQUIRES: executable_test
|
||||
// REQUIRES: macos_min_version_13
|
||||
|
||||
struct S {
|
||||
var x = 42
|
||||
}
|
||||
|
||||
_ = [S() as Sendable]
|
||||
Reference in New Issue
Block a user