Skip to content

Commit 28a66a2

Browse files
committed
[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
1 parent ae9f1b1 commit 28a66a2

File tree

2 files changed

+31
-13
lines changed

2 files changed

+31
-13
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1962,21 +1962,23 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
19621962
auto meta1 = cast<AnyMetatypeType>(desugar1);
19631963
auto meta2 = cast<AnyMetatypeType>(desugar2);
19641964

1965-
ConstraintKind subKind = ConstraintKind::Equal;
19661965
// A.Type < B.Type if A < B and both A and B are classes.
1967-
if (isa<MetatypeType>(meta1) &&
1968-
meta1->getInstanceType()->mayHaveSuperclass() &&
1969-
meta2->getInstanceType()->getClassOrBoundGenericClass())
1970-
subKind = std::min(kind, ConstraintKind::Subtype);
19711966
// P.Type < Q.Type if P < Q, both P and Q are protocols, and P.Type
1972-
// and Q.Type are both existential metatypes.
1973-
else if (isa<ExistentialMetatypeType>(meta1))
1974-
subKind = std::min(kind, ConstraintKind::Subtype);
1975-
1976-
return matchTypes(meta1->getInstanceType(), meta2->getInstanceType(),
1977-
subKind, subflags,
1978-
locator.withPathElement(
1979-
ConstraintLocator::InstanceType));
1967+
// and Q.Type are both existential metatypes
1968+
auto subKind = std::min(kind, ConstraintKind::Subtype);
1969+
// If instance types can't have a subtype relationship
1970+
// it means that such types can be simply equated.
1971+
auto instanceType1 = meta1->getInstanceType();
1972+
auto instanceType2 = meta2->getInstanceType();
1973+
if (isa<MetatypeType>(meta1) &&
1974+
!(instanceType1->mayHaveSuperclass() &&
1975+
instanceType2->getClassOrBoundGenericClass())) {
1976+
subKind = ConstraintKind::Equal;
1977+
}
1978+
1979+
return matchTypes(
1980+
instanceType1, instanceType2, subKind, subflags,
1981+
locator.withPathElement(ConstraintLocator::InstanceType));
19801982
}
19811983

19821984
case TypeKind::Function: {

test/Constraints/rdar44816848.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
class A {}
4+
class B: A {}
5+
class C: A {}
6+
7+
struct S {
8+
func foo<T: A>(types: [T.Type]) {}
9+
}
10+
11+
func bar(_ s: S, _ forced_s: S!) {
12+
s.foo(types: [A.self, B.self]) // ok
13+
s.foo(types: [B.self, A.self]) // ok
14+
forced_s.foo(types: [A.self, B.self]) // ok
15+
forced_s.foo(types: [B.self, A.self]) // ok
16+
}

0 commit comments

Comments
 (0)