Skip to content

Commit e2fbdb0

Browse files
authored
Merge pull request #20017 from rudkx/rdar45490737-5.0
[ConstraintSystem] Allow getPotentialBindings to find supertypes of o…
2 parents 99253b5 + ce6879a commit e2fbdb0

File tree

2 files changed

+52
-7
lines changed

2 files changed

+52
-7
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -757,26 +757,49 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
757757
return result;
758758
}
759759

760+
// Given a possibly-Optional type, return the direct superclass of the
761+
// (underlying) type wrapped in the same number of optional levels as
762+
// type.
763+
static Type getOptionalSuperclass(Type type) {
764+
int optionalLevels = 0;
765+
while (auto underlying = type->getOptionalObjectType()) {
766+
++optionalLevels;
767+
type = underlying;
768+
}
769+
770+
if (!type->mayHaveSuperclass())
771+
return Type();
772+
773+
auto superclass = type->getSuperclass();
774+
if (!superclass)
775+
return Type();
776+
777+
while (optionalLevels--)
778+
superclass = OptionalType::get(superclass);
779+
780+
return superclass;
781+
}
782+
760783
/// \brief Enumerates all of the 'direct' supertypes of the given type.
761784
///
762785
/// The direct supertype S of a type T is a supertype of T (e.g., T < S)
763786
/// such that there is no type U where T < U and U < S.
764787
static SmallVector<Type, 4> enumerateDirectSupertypes(Type type) {
765788
SmallVector<Type, 4> result;
766789

767-
if (type->mayHaveSuperclass()) {
790+
if (type->is<InOutType>() || type->is<LValueType>()) {
791+
type = type->getWithoutSpecifierType();
792+
result.push_back(type);
793+
}
794+
795+
if (auto superclass = getOptionalSuperclass(type)) {
768796
// FIXME: Can also weaken to the set of protocol constraints, but only
769797
// if there are any protocols that the type conforms to but the superclass
770798
// does not.
771799

772-
// If there is a superclass, it is a direct supertype.
773-
if (auto superclass = type->getSuperclass())
774-
result.push_back(superclass);
800+
result.push_back(superclass);
775801
}
776802

777-
if (type->is<InOutType>() || type->is<LValueType>())
778-
result.push_back(type->getWithoutSpecifierType());
779-
780803
// FIXME: lots of other cases to consider!
781804
return result;
782805
}

test/Constraints/rdar45490737.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
protocol X {}
4+
class B : Equatable {
5+
static func == (lhs: B, rhs: B) -> Bool { fatalError() }
6+
}
7+
class C : B {}
8+
extension C : X {}
9+
10+
func f<T: Equatable>(_ lhs: T, _ rhs: T) {}
11+
12+
extension Optional where Wrapped : Equatable {
13+
static func f(_ lhs: Wrapped?, _ rhs: Wrapped?) {}
14+
}
15+
16+
// Ensure that we can call both a function that has generic parameters
17+
// as well as one that has the generic parameters wrapped in
18+
// Optionals.
19+
func test(x: (X & B)?, y: C?) {
20+
f(x, y)
21+
Optional.f(x, y)
22+
}

0 commit comments

Comments
 (0)