Skip to content

Commit d3eabb0

Browse files
committed
[Type checker] Don't merge dictionary key type variables with different expression kinds.
The constraint generator's optimization to eagerly merge type variables for different keys in a dictionary literal was too eager, merging the type variables for (e.g.) a string literal and an integer literal. This prevented us from properly inferring AnyHashable key types in dictionary literals. Fixes the rest of rdar://problem/27661580. (cherry picked from commit 4a569f3)
1 parent 2583e2c commit d3eabb0

File tree

2 files changed

+16
-5
lines changed

2 files changed

+16
-5
lines changed

lib/Sema/CSGen.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1739,8 +1739,7 @@ namespace {
17391739
}
17401740

17411741
static bool isMergeableValueKind(Expr *expr) {
1742-
return isa<CollectionExpr>(expr) ||
1743-
isa<StringLiteralExpr>(expr) || isa<IntegerLiteralExpr>(expr) ||
1742+
return isa<StringLiteralExpr>(expr) || isa<IntegerLiteralExpr>(expr) ||
17441743
isa<FloatLiteralExpr>(expr);
17451744
}
17461745

@@ -1818,16 +1817,22 @@ namespace {
18181817
auto keyTyvar2 = tty2->getElementTypes()[0]->
18191818
getAs<TypeVariableType>();
18201819

1821-
mergedKey = mergeRepresentativeEquivalenceClasses(CS,
1820+
auto keyExpr1 = cast<TupleExpr>(element1)->getElements()[0];
1821+
auto keyExpr2 = cast<TupleExpr>(element2)->getElements()[0];
1822+
1823+
if (keyExpr1->getKind() == keyExpr2->getKind() &&
1824+
isMergeableValueKind(keyExpr1)) {
1825+
mergedKey = mergeRepresentativeEquivalenceClasses(CS,
18221826
keyTyvar1, keyTyvar2);
1827+
}
18231828

18241829
auto valueTyvar1 = tty1->getElementTypes()[1]->
18251830
getAs<TypeVariableType>();
18261831
auto valueTyvar2 = tty2->getElementTypes()[1]->
18271832
getAs<TypeVariableType>();
18281833

1829-
auto elemExpr1 = dyn_cast<TupleExpr>(element1)->getElements()[1];
1830-
auto elemExpr2 = dyn_cast<TupleExpr>(element2)->getElements()[1];
1834+
auto elemExpr1 = cast<TupleExpr>(element1)->getElements()[1];
1835+
auto elemExpr2 = cast<TupleExpr>(element2)->getElements()[1];
18311836

18321837
if (elemExpr1->getKind() == elemExpr2->getKind() &&
18331838
isMergeableValueKind(elemExpr1)) {

test/Constraints/dictionary_literal.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,10 @@ func testDefaultExistentials() {
8585

8686
let d3 = ["b" : B(), "c" : C()]
8787
let _: Int = d3 // expected-error{{value of type 'Dictionary<String, A>'}}
88+
89+
let _ = ["a" : B(), 17 : "seventeen", 3.14159 : "Pi"]
90+
// expected-error@-1{{heterogenous collection literal could only be inferred to 'Dictionary<AnyHashable, Any>'}}
91+
92+
let _ = ["a" : "hello", 17 : "string"]
93+
// expected-error@-1{{heterogenous collection literal could only be inferred to 'Dictionary<AnyHashable, String>'}}
8894
}

0 commit comments

Comments
 (0)