Skip to content

Commit 400bfc6

Browse files
authored
Merge pull request #65405 from slavapestov/bridging-id-any-sendable
SIL: Bridge 'any Sendable' via the id-as-Any path
2 parents fe90d44 + 385a7be commit 400bfc6

File tree

5 files changed

+46
-4
lines changed

5 files changed

+46
-4
lines changed

include/swift/AST/Types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,9 @@ class alignas(1 << TypeAlignInBits) TypeBase
601601
/// Is this the 'Any' type?
602602
bool isAny();
603603

604+
/// Is this an existential containing only marker protocols?
605+
bool isMarkerExistential();
606+
604607
bool isPlaceholder();
605608

606609
/// Returns true if this is a move-only type.

lib/AST/Type.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,28 @@ bool TypeBase::isAny() {
166166
return constraint->isEqual(getASTContext().TheAnyType);
167167
}
168168

169+
bool TypeBase::isMarkerExistential() {
170+
Type constraint = this;
171+
if (auto existential = constraint->getAs<ExistentialType>())
172+
constraint = existential->getConstraintType();
173+
174+
if (!constraint->isConstraintType())
175+
return false;
176+
177+
auto layout = constraint->getExistentialLayout();
178+
if (layout.hasExplicitAnyObject ||
179+
layout.explicitSuperclass) {
180+
return false;
181+
}
182+
183+
for (auto *proto : layout.getProtocols()) {
184+
if (!proto->isMarkerProtocol())
185+
return false;
186+
}
187+
188+
return true;
189+
}
190+
169191
bool TypeBase::isPureMoveOnly() {
170192
if (auto *nom = getNominalOrBoundGenericNominal())
171193
return nom->isMoveOnly();
@@ -2914,8 +2936,8 @@ getObjCObjectRepresentable(Type type, const DeclContext *dc) {
29142936
return ForeignRepresentableKind::Object;
29152937
}
29162938

2917-
// Any can be bridged to id.
2918-
if (type->isAny()) {
2939+
// Existentials consisting of only marker protocols can be bridged to id.
2940+
if (type->isMarkerExistential()) {
29192941
return ForeignRepresentableKind::Bridged;
29202942
}
29212943

lib/SIL/IR/Bridging.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,9 @@ Type TypeConverter::getLoweredCBridgedType(AbstractionPattern pattern,
172172
}
173173
}
174174

175-
// `Any` can bridge to `AnyObject` (`id` in ObjC).
176-
if (t->isAny())
175+
// Existentials consisting of only marker protocols can bridge to
176+
// `AnyObject` (`id` in ObjC).
177+
if (t->isMarkerExistential())
177178
return Context.getAnyObjectType();
178179

179180
if (auto funTy = t->getAs<FunctionType>()) {
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@import Foundation;
2+
3+
@interface NSBlah: NSObject
4+
- (void) takeSendable: (id __attribute__((swift_attr("@Sendable")))) x;
5+
@end
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %target-swift-emit-silgen(mock-sdk: %clang-importer-sdk) -import-objc-header %S/Inputs/objc_bridging_sendable.h %s | %FileCheck %s
2+
3+
// REQUIRES: objc_interop
4+
5+
// CHECK-LABEL: sil [ossa] @$s22objc_bridging_sendable18passSendableToObjCyys0E0_pF : $@convention(thin) (@in_guaranteed any Sendable) -> () {
6+
// CHECK: function_ref @$ss27_bridgeAnythingToObjectiveCyyXlxlF : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @owned AnyObject
7+
// CHECK: objc_method {{%.*}} : $NSBlah, #NSBlah.takeSendable!foreign : (NSBlah) -> ((any Sendable)?) -> (), $@convention(objc_method) (Optional<AnyObject>, NSBlah) -> ()
8+
// CHECK: return
9+
public func passSendableToObjC(_ s: Sendable) {
10+
NSBlah().takeSendable(s)
11+
}

0 commit comments

Comments
 (0)