Skip to content

Commit 84a3db4

Browse files
committed
[CS] Account for type variables when matching metatypes
Previously we could prematurely attempt to perform a bind of class metatypes without checking for subtyping. Tweak the logic to not perform a bind if we can't prove that we're dealing with non-class types.
1 parent 5126775 commit 84a3db4

File tree

1 file changed

+24
-12
lines changed

1 file changed

+24
-12
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4373,22 +4373,34 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
43734373
auto meta1 = cast<AnyMetatypeType>(desugar1);
43744374
auto meta2 = cast<AnyMetatypeType>(desugar2);
43754375

4376-
// A.Type < B.Type if A < B and both A and B are classes.
4377-
// P.Type < Q.Type if P < Q, both P and Q are protocols, and P.Type
4378-
// and Q.Type are both existential metatypes
4379-
auto subKind = std::min(kind, ConstraintKind::Subtype);
4380-
// If instance types can't have a subtype relationship
4381-
// it means that such types can be simply equated.
43824376
auto instanceType1 = meta1->getInstanceType();
43834377
auto instanceType2 = meta2->getInstanceType();
4384-
if (isa<MetatypeType>(meta1) &&
4385-
!(instanceType1->mayHaveSuperclass() &&
4386-
instanceType2->getClassOrBoundGenericClass())) {
4387-
subKind = ConstraintKind::Bind;
4388-
}
4378+
4379+
// A.Type < B.Type if A < B and both A and B are classes.
4380+
// P.Type < Q.Type if P < Q, both P and Q are protocols, and P.Type
4381+
// and Q.Type are both existential metatypes.
4382+
auto getSubKind = [&]() -> ConstraintKind {
4383+
auto subKind = std::min(kind, ConstraintKind::Subtype);
4384+
4385+
// If we have existential metatypes, we need to perform subtyping.
4386+
if (!isa<MetatypeType>(meta1))
4387+
return subKind;
4388+
4389+
// If the LHS cannot be a type with a superclass, we can perform a bind.
4390+
if (!instanceType1->isTypeVariableOrMember() &&
4391+
!instanceType1->mayHaveSuperclass())
4392+
return ConstraintKind::Bind;
4393+
4394+
// If the RHS cannot be a class type, we can perform a bind.
4395+
if (!instanceType2->isTypeVariableOrMember() &&
4396+
!instanceType2->getClassOrBoundGenericClass())
4397+
return ConstraintKind::Bind;
4398+
4399+
return subKind;
4400+
};
43894401

43904402
auto result =
4391-
matchTypes(instanceType1, instanceType2, subKind, subflags,
4403+
matchTypes(instanceType1, instanceType2, getSubKind(), subflags,
43924404
locator.withPathElement(ConstraintLocator::InstanceType));
43934405

43944406
// If matching of the instance types resulted in the failure make sure

0 commit comments

Comments
 (0)