Skip to content

Commit 603cba3

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 (cherry picked from commit 28a66a2)
1 parent ddc8208 commit 603cba3

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
@@ -1969,21 +1969,23 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
19691969
auto meta1 = cast<AnyMetatypeType>(desugar1);
19701970
auto meta2 = cast<AnyMetatypeType>(desugar2);
19711971

1972-
ConstraintKind subKind = ConstraintKind::Equal;
19731972
// A.Type < B.Type if A < B and both A and B are classes.
1974-
if (isa<MetatypeType>(meta1) &&
1975-
meta1->getInstanceType()->mayHaveSuperclass() &&
1976-
meta2->getInstanceType()->getClassOrBoundGenericClass())
1977-
subKind = std::min(kind, ConstraintKind::Subtype);
19781973
// P.Type < Q.Type if P < Q, both P and Q are protocols, and P.Type
1979-
// and Q.Type are both existential metatypes.
1980-
else if (isa<ExistentialMetatypeType>(meta1))
1981-
subKind = std::min(kind, ConstraintKind::Subtype);
1982-
1983-
return matchTypes(meta1->getInstanceType(), meta2->getInstanceType(),
1984-
subKind, subflags,
1985-
locator.withPathElement(
1986-
ConstraintLocator::InstanceType));
1974+
// and Q.Type are both existential metatypes
1975+
auto subKind = std::min(kind, ConstraintKind::Subtype);
1976+
// If instance types can't have a subtype relationship
1977+
// it means that such types can be simply equated.
1978+
auto instanceType1 = meta1->getInstanceType();
1979+
auto instanceType2 = meta2->getInstanceType();
1980+
if (isa<MetatypeType>(meta1) &&
1981+
!(instanceType1->mayHaveSuperclass() &&
1982+
instanceType2->getClassOrBoundGenericClass())) {
1983+
subKind = ConstraintKind::Equal;
1984+
}
1985+
1986+
return matchTypes(
1987+
instanceType1, instanceType2, subKind, subflags,
1988+
locator.withPathElement(ConstraintLocator::InstanceType));
19871989
}
19881990

19891991
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)