Skip to content

Commit 6a5907d

Browse files
xedinmeg-gupta
authored andcommitted
[CSBindings] Make it possible to enumerate supertypes of existentials
- Drop `mayHaveSuperclass` because it's too restrictive. - Add logic to get superclass of existential and re-create existential type with all of the protocol requirements.
1 parent 236cd6b commit 6a5907d

File tree

2 files changed

+53
-3
lines changed

2 files changed

+53
-3
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2172,10 +2172,43 @@ static Type getOptionalSuperclass(Type type) {
21722172
type = underlying;
21732173
}
21742174

2175-
if (!type->mayHaveSuperclass())
2176-
return Type();
2175+
Type superclass;
2176+
if (auto *existential = type->getAs<ExistentialType>()) {
2177+
auto constraintTy = existential->getConstraintType();
2178+
if (auto *compositionTy = constraintTy->getAs<ProtocolCompositionType>()) {
2179+
SmallVector<Type, 2> members;
2180+
bool found = false;
2181+
// Preserve all of the protocol requirements of the type i.e.
2182+
// if the type was `any B & P` where `B : A` the supertype is
2183+
// going to be `any A & P`.
2184+
//
2185+
// This is especially important for Sendable key paths because
2186+
// to reserve sendability of the original type.
2187+
for (auto member : compositionTy->getMembers()) {
2188+
if (member->getClassOrBoundGenericClass()) {
2189+
member = member->getSuperclass();
2190+
if (!member)
2191+
return Type();
2192+
found = true;
2193+
}
2194+
members.push_back(member);
2195+
}
2196+
2197+
if (!found)
2198+
return Type();
2199+
2200+
superclass = ExistentialType::get(
2201+
ProtocolCompositionType::get(type->getASTContext(), members,
2202+
compositionTy->hasExplicitAnyObject()));
2203+
} else {
2204+
// Avoid producing superclass for situations like `any P` where `P` is
2205+
// `protocol P : C`.
2206+
return Type();
2207+
}
2208+
} else {
2209+
superclass = type->getSuperclass();
2210+
}
21772211

2178-
auto superclass = type->getSuperclass();
21792212
if (!superclass)
21802213
return Type();
21812214

test/Concurrency/sendable_keypaths.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,3 +200,20 @@ func testReferencesToDifferentGlobalActorIsolatedMembers() {
200200
// expected-warning@-1 {{cannot form key path to main actor-isolated property 'name'; this is an error in Swift 6}}
201201
}
202202
}
203+
204+
do {
205+
struct S {
206+
var a: Int
207+
var b: String?
208+
}
209+
210+
func test<T: Sendable>(_: T) {}
211+
212+
let kp = [\S.a, \S.b]
213+
214+
test(kp) // Ok
215+
test([\S.a, \S.b]) // Ok
216+
217+
let _: [PartialKeyPath<S>] = [\.a, \.b] // Ok
218+
let _: [any PartialKeyPath<S> & Sendable] = [\.a, \.b] // Ok
219+
}

0 commit comments

Comments
 (0)