@@ -69,6 +69,22 @@ static bool isArithmeticOperatorDecl(ValueDecl *vd) {
69
69
vd->getName ().str () == " %" );
70
70
}
71
71
72
+ static bool mergeRepresentativeEquivalenceClasses (ConstraintSystem &CS,
73
+ TypeVariableType* tyvar1,
74
+ TypeVariableType* tyvar2) {
75
+ if (tyvar1 && tyvar2) {
76
+ auto rep1 = CS.getRepresentative (tyvar1);
77
+ auto rep2 = CS.getRepresentative (tyvar2);
78
+
79
+ if (rep1 != rep2) {
80
+ CS.mergeEquivalenceClasses (rep1, rep2, /* updateWorkList*/ false );
81
+ return true ;
82
+ }
83
+ }
84
+
85
+ return false ;
86
+ }
87
+
72
88
namespace {
73
89
74
90
// / Internal struct for tracking information about types within a series
@@ -327,14 +343,7 @@ namespace {
327
343
auto tyvar1 = acp1->getType ()->getAs <TypeVariableType>();
328
344
auto tyvar2 = acp2->getType ()->getAs <TypeVariableType>();
329
345
330
- if (tyvar1 && tyvar2) {
331
- auto rep1 = CS.getRepresentative (tyvar1);
332
- auto rep2 = CS.getRepresentative (tyvar2);
333
-
334
- if (rep1 != rep2) {
335
- CS.mergeEquivalenceClasses (rep1, rep2, /* updateWorkList*/ false );
336
- }
337
- }
346
+ mergeRepresentativeEquivalenceClasses (CS, tyvar1, tyvar2);
338
347
}
339
348
}
340
349
}
@@ -1859,6 +1868,12 @@ namespace {
1859
1868
return arrayTy;
1860
1869
}
1861
1870
1871
+ static bool isMergeableValueKind (Expr *expr) {
1872
+ return isa<CollectionExpr>(expr) ||
1873
+ isa<StringLiteralExpr>(expr) || isa<IntegerLiteralExpr>(expr) ||
1874
+ isa<FloatLiteralExpr>(expr);
1875
+ }
1876
+
1862
1877
Type visitDictionaryExpr (DictionaryExpr *expr) {
1863
1878
ASTContext &C = CS.getASTContext ();
1864
1879
// A dictionary expression can be of a type T that conforms to the
@@ -1908,16 +1923,67 @@ namespace {
1908
1923
TupleTypeElt (dictionaryValueTy) };
1909
1924
Type elementTy = TupleType::get (tupleElts, C);
1910
1925
1926
+ // Keep track of which elements have been "merged". This way, we won't create
1927
+ // needless conversion constraints for elements whose equivalence classes have
1928
+ // been merged.
1929
+ llvm::DenseSet<Expr *> mergedElements;
1930
+
1931
+ // If no contextual type is present, Merge equivalence classes of key
1932
+ // and value types as necessary.
1933
+ if (!CS.getContextualType (expr)) {
1934
+ for (auto element1 : expr->getElements ()) {
1935
+ for (auto element2 : expr->getElements ()) {
1936
+ if (element1 == element2)
1937
+ continue ;
1938
+
1939
+ auto tty1 = element1->getType ()->getAs <TupleType>();
1940
+ auto tty2 = element2->getType ()->getAs <TupleType>();
1941
+
1942
+ if (tty1 && tty2) {
1943
+ auto mergedKey = false ;
1944
+ auto mergedValue = false ;
1945
+
1946
+ auto keyTyvar1 = tty1->getElementTypes ()[0 ]->
1947
+ getAs<TypeVariableType>();
1948
+ auto keyTyvar2 = tty2->getElementTypes ()[0 ]->
1949
+ getAs<TypeVariableType>();
1950
+
1951
+ mergedKey = mergeRepresentativeEquivalenceClasses (CS,
1952
+ keyTyvar1, keyTyvar2);
1953
+
1954
+ auto valueTyvar1 = tty1->getElementTypes ()[1 ]->
1955
+ getAs<TypeVariableType>();
1956
+ auto valueTyvar2 = tty2->getElementTypes ()[1 ]->
1957
+ getAs<TypeVariableType>();
1958
+
1959
+ auto elemExpr1 = dyn_cast<TupleExpr>(element1)->getElements ()[1 ];
1960
+ auto elemExpr2 = dyn_cast<TupleExpr>(element2)->getElements ()[1 ];
1961
+
1962
+ if (elemExpr1->getKind () == elemExpr2->getKind () &&
1963
+ isMergeableValueKind (elemExpr1)) {
1964
+ mergedValue = mergeRepresentativeEquivalenceClasses (CS,
1965
+ valueTyvar1, valueTyvar2);
1966
+ }
1967
+
1968
+ if (mergedKey && mergedValue)
1969
+ mergedElements.insert (element2);
1970
+ }
1971
+ }
1972
+ }
1973
+ }
1974
+
1911
1975
// Introduce conversions from each element to the element type of the
1912
- // dictionary.
1976
+ // dictionary. (If the equivalence class of an element has already been
1977
+ // merged with a previous one, skip it.)
1913
1978
unsigned index = 0 ;
1914
1979
for (auto element : expr->getElements ()) {
1915
- CS.addConstraint (ConstraintKind::Conversion,
1916
- element->getType (),
1917
- elementTy,
1918
- CS.getConstraintLocator (
1919
- expr,
1920
- LocatorPathElt::getTupleElement (index++)));
1980
+ if (!mergedElements.count (element))
1981
+ CS.addConstraint (ConstraintKind::Conversion,
1982
+ element->getType (),
1983
+ elementTy,
1984
+ CS.getConstraintLocator (
1985
+ expr,
1986
+ LocatorPathElt::getTupleElement (index++)));
1921
1987
}
1922
1988
1923
1989
return dictionaryTy;
0 commit comments