Skip to content

[ConstraintSystem] Allow getPotentialBindings to find supertypes of o… #20017

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 30 additions & 7 deletions lib/Sema/CSBindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -757,26 +757,49 @@ 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)
/// such that there is no type U where T < U and U < S.
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;
}
Expand Down
22 changes: 22 additions & 0 deletions test/Constraints/rdar45490737.swift
Original file line number Diff line number Diff line change
@@ -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)
}