Skip to content

Commit 3720bad

Browse files
committed
Sema: Fix matchTypes() for existential to superclass conversions
Now that mayHaveSuperclass() is back to its old meaning, we can't piggy-back off of it anymore and must add a new bit of logic for class-constrained existential to superclass conversions. Also re-organize the code a bit.
1 parent e2d81a1 commit 3720bad

File tree

1 file changed

+38
-42
lines changed

1 file changed

+38
-42
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 38 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1709,15 +1709,13 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
17091709

17101710
ConstraintKind subKind = ConstraintKind::Equal;
17111711
// A.Type < B.Type if A < B and both A and B are classes.
1712-
if (isa<MetatypeType>(desugar1) &&
1713-
kind != ConstraintKind::Equal &&
1712+
if (isa<MetatypeType>(meta1) &&
17141713
meta1->getInstanceType()->mayHaveSuperclass() &&
17151714
meta2->getInstanceType()->getClassOrBoundGenericClass())
17161715
subKind = std::min(kind, ConstraintKind::Subtype);
17171716
// P.Type < Q.Type if P < Q, both P and Q are protocols, and P.Type
17181717
// and Q.Type are both existential metatypes.
1719-
else if (isa<ExistentialMetatypeType>(meta1)
1720-
&& isa<ExistentialMetatypeType>(meta2))
1718+
else if (isa<ExistentialMetatypeType>(meta1))
17211719
subKind = std::min(kind, ConstraintKind::Subtype);
17221720

17231721
return matchTypes(meta1->getInstanceType(), meta2->getInstanceType(),
@@ -1827,13 +1825,48 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
18271825

18281826
// Subclass-to-superclass conversion.
18291827
if (type1->mayHaveSuperclass() &&
1830-
type2->mayHaveSuperclass() &&
18311828
type2->getClassOrBoundGenericClass() &&
18321829
type1->getClassOrBoundGenericClass()
18331830
!= type2->getClassOrBoundGenericClass()) {
18341831
conversionsOrFixes.push_back(ConversionRestrictionKind::Superclass);
18351832
}
18361833

1834+
// Existential-to-superclass conversion.
1835+
if (type1->isClassExistentialType() &&
1836+
type2->getClassOrBoundGenericClass()) {
1837+
conversionsOrFixes.push_back(ConversionRestrictionKind::Superclass);
1838+
}
1839+
1840+
// Metatype-to-existential-metatype conversion.
1841+
//
1842+
// Equivalent to a conformance relation on the instance types.
1843+
if (type1->is<MetatypeType>() &&
1844+
type2->is<ExistentialMetatypeType>()) {
1845+
conversionsOrFixes.push_back(
1846+
ConversionRestrictionKind::MetatypeToExistentialMetatype);
1847+
}
1848+
1849+
// Existential-metatype-to-superclass-metatype conversion.
1850+
if (type2->is<MetatypeType>()) {
1851+
if (auto *meta1 = type1->getAs<ExistentialMetatypeType>()) {
1852+
if (meta1->getInstanceType()->isClassExistentialType()) {
1853+
conversionsOrFixes.push_back(
1854+
ConversionRestrictionKind::ExistentialMetatypeToMetatype);
1855+
}
1856+
}
1857+
}
1858+
1859+
// Concrete value to existential conversion.
1860+
if (!type1->is<LValueType>() &&
1861+
type2->isExistentialType()) {
1862+
1863+
// Penalize conversions to Any.
1864+
if (kind >= ConstraintKind::Conversion && type2->isAny())
1865+
increaseScore(ScoreKind::SK_EmptyExistentialConversion);
1866+
1867+
conversionsOrFixes.push_back(ConversionRestrictionKind::Existential);
1868+
}
1869+
18371870
// T -> AnyHashable.
18381871
if (isAnyHashableType(desugar2)) {
18391872
// Don't allow this in operator contexts or we'll end up allowing
@@ -2072,43 +2105,6 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
20722105
}
20732106
}
20742107

2075-
// Conformance of a metatype to an existential metatype is actually
2076-
// equivalent to a conformance relationship on the instance types.
2077-
// This applies to nested metatype levels, so if A : P then
2078-
// A.Type : P.Type.
2079-
if (concrete &&
2080-
kind >= ConstraintKind::Subtype &&
2081-
type1->is<MetatypeType>() &&
2082-
type2->is<ExistentialMetatypeType>()) {
2083-
conversionsOrFixes.push_back(
2084-
ConversionRestrictionKind::MetatypeToExistentialMetatype);
2085-
}
2086-
2087-
// An existential metatype can be upcast to a class metatype if the
2088-
// existential contains a superclass constraint.
2089-
if (concrete &&
2090-
kind >= ConstraintKind::Subtype &&
2091-
type1->is<ExistentialMetatypeType>() &&
2092-
type2->is<MetatypeType>()) {
2093-
conversionsOrFixes.push_back(
2094-
ConversionRestrictionKind::ExistentialMetatypeToMetatype);
2095-
}
2096-
2097-
// Instance type check for the above. We are going to check conformance once
2098-
// we hit commit_to_conversions below, but we have to add a token restriction
2099-
// to ensure we wrap the metatype value in a metatype erasure.
2100-
if (concrete &&
2101-
kind >= ConstraintKind::Subtype &&
2102-
!type1->is<LValueType>() &&
2103-
type2->isExistentialType()) {
2104-
2105-
// Penalize conversions to Any.
2106-
if (kind >= ConstraintKind::Conversion && type2->isAny())
2107-
increaseScore(ScoreKind::SK_EmptyExistentialConversion);
2108-
2109-
conversionsOrFixes.push_back(ConversionRestrictionKind::Existential);
2110-
}
2111-
21122108
// A value of type T! can be converted to type U if T is convertible
21132109
// to U by force-unwrapping the source value.
21142110
// A value of type T, T?, or T! can be converted to type U? or U! if

0 commit comments

Comments
 (0)