Skip to content

Commit 13a6574

Browse files
committed
Disallow most other conversions when we need an lvalue-to-rvalue conversion.
This change is needed by a separate change I have that penalizes conversions to Any. That change exposed a problem where we ended up doing a direct lvalue-to-Any conversion without first loading as part of an lvalue-to-rvalue conversion. We should really only be doing most of these other conversions/fixes on rvalues. Unfortunately I don't know of a way to hit this without the other change, and thus don't have a test case. As a side note, this also helps some (perhaps most, but definitely not all) of the exponential type inference cases involving arrays and dictionaries. Unfortunately again, we don't currently have a testing mechanism in place to ensure we don't regress those cases, and I don't want to add a test that will completely hang every bot if it does regress, so...*sad face*...no test case for that either.
1 parent 37e6267 commit 13a6574

File tree

1 file changed

+32
-14
lines changed

1 file changed

+32
-14
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1624,8 +1624,10 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
16241624
break;
16251625

16261626
case TypeKind::Tuple: {
1627+
assert(!type2->is<LValueType>() && "Unexpected lvalue type!");
16271628
// Try the tuple-to-tuple conversion.
1628-
conversionsOrFixes.push_back(ConversionRestrictionKind::TupleToTuple);
1629+
if (!type1->is<LValueType>())
1630+
conversionsOrFixes.push_back(ConversionRestrictionKind::TupleToTuple);
16291631
break;
16301632
}
16311633

@@ -1634,7 +1636,9 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
16341636
case TypeKind::Class: {
16351637
auto nominal1 = cast<NominalType>(desugar1);
16361638
auto nominal2 = cast<NominalType>(desugar2);
1637-
if (nominal1->getDecl() == nominal2->getDecl()) {
1639+
assert(!type2->is<LValueType>() && "Unexpected lvalue type!");
1640+
if (!type1->is<LValueType>() &&
1641+
nominal1->getDecl() == nominal2->getDecl()) {
16381642
conversionsOrFixes.push_back(ConversionRestrictionKind::DeepEquality);
16391643
}
16401644

@@ -1645,15 +1649,19 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
16451649
auto class2 = cast<ClassDecl>(nominal2->getDecl());
16461650

16471651
// CF -> Objective-C via toll-free bridging.
1648-
if (class1->getForeignClassKind() == ClassDecl::ForeignKind::CFType &&
1652+
assert(!type2->is<LValueType>() && "Unexpected lvalue type!");
1653+
if (!type1->is<LValueType>() &&
1654+
class1->getForeignClassKind() == ClassDecl::ForeignKind::CFType &&
16491655
class2->getForeignClassKind() != ClassDecl::ForeignKind::CFType &&
16501656
class1->getAttrs().hasAttribute<ObjCBridgedAttr>()) {
16511657
conversionsOrFixes.push_back(
16521658
ConversionRestrictionKind::CFTollFreeBridgeToObjC);
16531659
}
16541660

16551661
// Objective-C -> CF via toll-free bridging.
1656-
if (class2->getForeignClassKind() == ClassDecl::ForeignKind::CFType &&
1662+
assert(!type2->is<LValueType>() && "Unexpected lvalue type!");
1663+
if (!type1->is<LValueType>() &&
1664+
class2->getForeignClassKind() == ClassDecl::ForeignKind::CFType &&
16571665
class1->getForeignClassKind() != ClassDecl::ForeignKind::CFType &&
16581666
class2->getAttrs().hasAttribute<ObjCBridgedAttr>()) {
16591667
conversionsOrFixes.push_back(
@@ -1744,7 +1752,8 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
17441752
auto bound1 = cast<BoundGenericType>(desugar1);
17451753
auto bound2 = cast<BoundGenericType>(desugar2);
17461754

1747-
if (bound1->getDecl() == bound2->getDecl()) {
1755+
assert(!type2->is<LValueType>() && "Unexpected lvalue type!");
1756+
if (!type1->is<LValueType>() && bound1->getDecl() == bound2->getDecl()) {
17481757
conversionsOrFixes.push_back(ConversionRestrictionKind::DeepEquality);
17491758
}
17501759
break;
@@ -1779,12 +1788,13 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
17791788
// there is at most one non-defaulted element.
17801789
// For non-argument tuples, we can do the same conversion but not
17811790
// to a tuple with varargs.
1782-
if ((tuple2->getNumElements() == 1 &&
1783-
!tuple2->getElement(0).isVararg()) ||
1784-
(kind >= ConstraintKind::Conversion &&
1785-
tuple2->getElementForScalarInit() >= 0 &&
1786-
(isArgumentTupleConversion ||
1787-
!tuple2->getVarArgsBaseType()))) {
1791+
if (!type1->is<LValueType>() &&
1792+
((tuple2->getNumElements() == 1 &&
1793+
!tuple2->getElement(0).isVararg()) ||
1794+
(kind >= ConstraintKind::Conversion &&
1795+
tuple2->getElementForScalarInit() >= 0 &&
1796+
(isArgumentTupleConversion ||
1797+
!tuple2->getVarArgsBaseType())))) {
17881798
conversionsOrFixes.push_back(
17891799
ConversionRestrictionKind::ScalarToTuple);
17901800

@@ -1798,6 +1808,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
17981808
type2->getClassOrBoundGenericClass() &&
17991809
type1->getClassOrBoundGenericClass()
18001810
!= type2->getClassOrBoundGenericClass()) {
1811+
assert(!type2->is<LValueType>() && "Unexpected lvalue type!");
18011812
conversionsOrFixes.push_back(ConversionRestrictionKind::Superclass);
18021813
}
18031814

@@ -1806,7 +1817,9 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
18061817
// Don't allow this in operator contexts or we'll end up allowing
18071818
// 'T() == U()' for unrelated T and U that just happen to be Hashable.
18081819
// We can remove this special case when we implement operator hiding.
1809-
if (kind != ConstraintKind::OperatorArgumentConversion) {
1820+
if (!type1->is<LValueType>() &&
1821+
kind != ConstraintKind::OperatorArgumentConversion) {
1822+
assert(!type2->is<LValueType>() && "Unexpected lvalue type!");
18101823
conversionsOrFixes.push_back(
18111824
ConversionRestrictionKind::HashableToAnyHashable);
18121825
}
@@ -1866,16 +1879,20 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
18661879
}
18671880

18681881
// Special implicit nominal conversions.
1869-
if (kind >= ConstraintKind::Conversion) {
1882+
if (!type1->is<LValueType>() &&
1883+
kind >= ConstraintKind::Conversion) {
18701884
// Array -> Array.
18711885
if (isArrayType(desugar1) && isArrayType(desugar2)) {
1886+
assert(!type2->is<LValueType>() && "Unexpected lvalue type!");
18721887
conversionsOrFixes.push_back(ConversionRestrictionKind::ArrayUpcast);
18731888
// Dictionary -> Dictionary.
18741889
} else if (isDictionaryType(desugar1) && isDictionaryType(desugar2)) {
1890+
assert(!type2->is<LValueType>() && "Unexpected lvalue type!");
18751891
conversionsOrFixes.push_back(
18761892
ConversionRestrictionKind::DictionaryUpcast);
18771893
// Set -> Set.
18781894
} else if (isSetType(desugar1) && isSetType(desugar2)) {
1895+
assert(!type2->is<LValueType>() && "Unexpected lvalue type!");
18791896
conversionsOrFixes.push_back(
18801897
ConversionRestrictionKind::SetUpcast);
18811898
}
@@ -2047,6 +2064,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
20472064
// we hit commit_to_conversions below, but we have to add a token restriction
20482065
// to ensure we wrap the metatype value in a metatype erasure.
20492066
if (concrete && type2->isExistentialType() &&
2067+
!type1->is<LValueType>() &&
20502068
kind >= ConstraintKind::Subtype) {
20512069
conversionsOrFixes.push_back(ConversionRestrictionKind::Existential);
20522070
}
@@ -2055,7 +2073,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
20552073
// to U by force-unwrapping the source value.
20562074
// A value of type T, T?, or T! can be converted to type U? or U! if
20572075
// T is convertible to U.
2058-
if (concrete && kind >= ConstraintKind::Subtype) {
2076+
if (concrete && !type1->is<LValueType>() && kind >= ConstraintKind::Subtype) {
20592077
enumerateOptionalConversionRestrictions(
20602078
type1, type2, kind, locator,
20612079
[&](ConversionRestrictionKind restriction) {

0 commit comments

Comments
 (0)