mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[ConstraintSystem] Allow getPotentialBindings to find supertypes of optionals.
Improve enumerateDirectSupertypes so that for T? it will return U? if U is a supertype of T. This is another form of direct supertype. This is making up for a deficiency in the completeness of our Type join implementation, which should be able to directly compute a join of disparate types that share some common supertype, but sometimes fails to in cases involving protocol compositions. Fixes rdar://problem/45490737
This commit is contained in:
@@ -757,6 +757,29 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Given a possibly-Optional type, return the direct superclass of the
|
||||
// (underlying) type wrapped in the same number of optional levels as
|
||||
// type.
|
||||
static Type getOptionalSuperclass(Type type) {
|
||||
int optionalLevels = 0;
|
||||
while (auto underlying = type->getOptionalObjectType()) {
|
||||
++optionalLevels;
|
||||
type = underlying;
|
||||
}
|
||||
|
||||
if (!type->mayHaveSuperclass())
|
||||
return Type();
|
||||
|
||||
auto superclass = type->getSuperclass();
|
||||
if (!superclass)
|
||||
return Type();
|
||||
|
||||
while (optionalLevels--)
|
||||
superclass = OptionalType::get(superclass);
|
||||
|
||||
return superclass;
|
||||
}
|
||||
|
||||
/// \brief Enumerates all of the 'direct' supertypes of the given type.
|
||||
///
|
||||
/// The direct supertype S of a type T is a supertype of T (e.g., T < S)
|
||||
@@ -764,19 +787,19 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
|
||||
static SmallVector<Type, 4> enumerateDirectSupertypes(Type type) {
|
||||
SmallVector<Type, 4> result;
|
||||
|
||||
if (type->mayHaveSuperclass()) {
|
||||
if (type->is<InOutType>() || type->is<LValueType>()) {
|
||||
type = type->getWithoutSpecifierType();
|
||||
result.push_back(type);
|
||||
}
|
||||
|
||||
if (auto superclass = getOptionalSuperclass(type)) {
|
||||
// FIXME: Can also weaken to the set of protocol constraints, but only
|
||||
// if there are any protocols that the type conforms to but the superclass
|
||||
// does not.
|
||||
|
||||
// If there is a superclass, it is a direct supertype.
|
||||
if (auto superclass = type->getSuperclass())
|
||||
result.push_back(superclass);
|
||||
result.push_back(superclass);
|
||||
}
|
||||
|
||||
if (type->is<InOutType>() || type->is<LValueType>())
|
||||
result.push_back(type->getWithoutSpecifierType());
|
||||
|
||||
// FIXME: lots of other cases to consider!
|
||||
return result;
|
||||
}
|
||||
|
||||
22
test/Constraints/rdar45490737.swift
Normal file
22
test/Constraints/rdar45490737.swift
Normal file
@@ -0,0 +1,22 @@
|
||||
// RUN: %target-typecheck-verify-swift
|
||||
|
||||
protocol X {}
|
||||
class B : Equatable {
|
||||
static func == (lhs: B, rhs: B) -> Bool { fatalError() }
|
||||
}
|
||||
class C : B {}
|
||||
extension C : X {}
|
||||
|
||||
func f<T: Equatable>(_ lhs: T, _ rhs: T) {}
|
||||
|
||||
extension Optional where Wrapped : Equatable {
|
||||
static func f(_ lhs: Wrapped?, _ rhs: Wrapped?) {}
|
||||
}
|
||||
|
||||
// Ensure that we can call both a function that has generic parameters
|
||||
// as well as one that has the generic parameters wrapped in
|
||||
// Optionals.
|
||||
func test(x: (X & B)?, y: C?) {
|
||||
f(x, y)
|
||||
Optional.f(x, y)
|
||||
}
|
||||
Reference in New Issue
Block a user