[CSSimplify] Delay binding metatype instance types if one side is type variable

While matching two metatypes where one side is a class (which could have
supertypes) and another is a type variable use `subtype` constraint to
delay binding types together because there is a real possibility that
there exists a superclass associated with yet free type variable which
would be a better match when attempted.

Resolves: rdar://problem/44816848
This commit is contained in:
Pavel Yaskevich
2018-11-27 10:47:21 -08:00
parent ae9f1b1cad
commit 28a66a23eb
2 changed files with 31 additions and 13 deletions

View File

@@ -1962,21 +1962,23 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
auto meta1 = cast<AnyMetatypeType>(desugar1);
auto meta2 = cast<AnyMetatypeType>(desugar2);
ConstraintKind subKind = ConstraintKind::Equal;
// A.Type < B.Type if A < B and both A and B are classes.
if (isa<MetatypeType>(meta1) &&
meta1->getInstanceType()->mayHaveSuperclass() &&
meta2->getInstanceType()->getClassOrBoundGenericClass())
subKind = std::min(kind, ConstraintKind::Subtype);
// P.Type < Q.Type if P < Q, both P and Q are protocols, and P.Type
// and Q.Type are both existential metatypes.
else if (isa<ExistentialMetatypeType>(meta1))
subKind = std::min(kind, ConstraintKind::Subtype);
return matchTypes(meta1->getInstanceType(), meta2->getInstanceType(),
subKind, subflags,
locator.withPathElement(
ConstraintLocator::InstanceType));
// and Q.Type are both existential metatypes
auto subKind = std::min(kind, ConstraintKind::Subtype);
// If instance types can't have a subtype relationship
// it means that such types can be simply equated.
auto instanceType1 = meta1->getInstanceType();
auto instanceType2 = meta2->getInstanceType();
if (isa<MetatypeType>(meta1) &&
!(instanceType1->mayHaveSuperclass() &&
instanceType2->getClassOrBoundGenericClass())) {
subKind = ConstraintKind::Equal;
}
return matchTypes(
instanceType1, instanceType2, subKind, subflags,
locator.withPathElement(ConstraintLocator::InstanceType));
}
case TypeKind::Function: {