Skip to content

Commit c452cfa

Browse files
authored
Merge pull request #7222 from rudkx/fix-rdar29960575
[Sema] Penalize conversions to Any.
2 parents 0549822 + 00cc260 commit c452cfa

File tree

6 files changed

+62
-22
lines changed

6 files changed

+62
-22
lines changed

lib/Sema/CSRanking.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ void ConstraintSystem::increaseScore(ScoreKind kind, unsigned value) {
7474
case SK_ScalarPointerConversion:
7575
log << "scalar-to-pointer conversion";
7676
break;
77+
case SK_EmptyExistentialConversion:
78+
log << "empty-existential conversion";
79+
break;
7780
}
7881
log << ")\n";
7982
}

lib/Sema/CSSimplify.cpp

Lines changed: 37 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,15 +2064,21 @@ 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) {
2069+
2070+
// Penalize conversions to Any.
2071+
if (kind >= ConstraintKind::Conversion && type2->isAny())
2072+
increaseScore(ScoreKind::SK_EmptyExistentialConversion);
2073+
20512074
conversionsOrFixes.push_back(ConversionRestrictionKind::Existential);
20522075
}
20532076

20542077
// A value of type T! can be converted to type U if T is convertible
20552078
// to U by force-unwrapping the source value.
20562079
// A value of type T, T?, or T! can be converted to type U? or U! if
20572080
// T is convertible to U.
2058-
if (concrete && kind >= ConstraintKind::Subtype) {
2081+
if (concrete && !type1->is<LValueType>() && kind >= ConstraintKind::Subtype) {
20592082
enumerateOptionalConversionRestrictions(
20602083
type1, type2, kind, locator,
20612084
[&](ConversionRestrictionKind restriction) {

lib/Sema/ConstraintSystem.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,8 +407,10 @@ enum ScoreKind {
407407
SK_ScalarPointerConversion,
408408
/// A conversion from an array to a pointer of matching element type.
409409
SK_ArrayPointerConversion,
410+
/// A conversion to an empty existential type ('Any' or '{}').
411+
SK_EmptyExistentialConversion,
410412

411-
SK_LastScoreKind = SK_ArrayPointerConversion,
413+
SK_LastScoreKind = SK_EmptyExistentialConversion,
412414
};
413415

414416
/// The number of score kinds.

test/Constraints/array_literal.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,10 @@ let router = Company(
227227
}
228228
]
229229
)
230+
231+
// Infer [[Int]] for SR3786aa.
232+
// FIXME: As noted in SR-3786, this was the behavior in Swift 3, but
233+
// it seems like the wrong choice and is less by design than by
234+
// accident.
235+
let SR3786a: [Int] = [1, 2, 3]
236+
let SR3786aa = [SR3786a.reversed(), SR3786a]

test/Constraints/diag_ambiguities.swift

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,9 @@ func rdar29691909(o: AnyObject) -> Any? {
3636
return rdar29691909_callee(o) // expected-error{{ambiguous use of 'rdar29691909_callee'}}
3737
}
3838

39-
// FIXME: The fix for this broke other things. We want to get this
40-
// test case running again, though.
41-
// Ensure that we decay Any! to Any? rather than allowing Any!-to-Any
42-
// conversion directly and ending up with an ambiguity here.
43-
//func rdar29907555(_ value: Any!) -> String {
44-
// return "\(value)" // no error
45-
//}
39+
func rdar29907555(_ value: Any!) -> String {
40+
return "\(value)" // no error
41+
}
4642

4743
struct SR3715 {
4844
var overloaded: Int!

test/Constraints/overload.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,12 @@ func overloadedMethod<T>() {}
186186

187187
overloadedMethod()
188188
// expected-error@-1 {{missing argument for parameter 'n' in call}}
189+
190+
// Ensure we select the overload of '??' returning T? rather than T.
191+
func SR3817(_ d: [String : Any], _ s: String, _ t: String) -> Any {
192+
if let r = d[s] ?? d[t] {
193+
return r
194+
} else {
195+
return 0
196+
}
197+
}

0 commit comments

Comments
 (0)