@@ -500,49 +500,47 @@ namespace {
500
500
return false ;
501
501
}
502
502
503
- // / Determine whether the given parameter and argument type should be
503
+ // / Determine whether the given parameter type and argument should be
504
504
// / "favored" because they match exactly.
505
505
bool isFavoredParamAndArg (ConstraintSystem &CS,
506
506
Type paramTy,
507
+ Expr *arg,
507
508
Type argTy,
508
- Type otherArgTy) {
509
- if (argTy->getAs <LValueType>())
510
- argTy = argTy->getLValueOrInOutObjectType ();
511
-
512
- if (!otherArgTy.isNull () &&
513
- otherArgTy->getAs <LValueType>())
514
- otherArgTy = otherArgTy->getLValueOrInOutObjectType ();
515
-
509
+ Expr *otherArg = nullptr ,
510
+ Type otherArgTy = Type()) {
511
+ // Determine the argument type.
512
+ argTy = argTy->getLValueOrInOutObjectType ();
513
+
516
514
// Do the types match exactly?
517
515
if (paramTy->isEqual (argTy))
518
516
return true ;
519
-
520
- // If the argument is a type variable created for a literal that has a
521
- // default type, this is a favored param/arg pair if the parameter is of
522
- // that default type.
523
- // Is the argument a type variable...
524
- if (auto argTypeVar = argTy->getAs <TypeVariableType>()) {
525
- if (auto proto = argTypeVar->getImpl ().literalConformanceProto ) {
526
- // If it's a struct type associated with the literal conformance,
527
- // test against it directly. This helps to avoid 'widening' the
528
- // favored type to the default type for the literal.
529
- if (!otherArgTy.isNull () &&
530
- otherArgTy->getAs <StructType>()) {
531
-
532
- if (CS.TC .conformsToProtocol (otherArgTy,
533
- proto,
534
- CS.DC ,
535
- ConformanceCheckFlags::InExpression)) {
536
- return otherArgTy->isEqual (paramTy);
537
- }
538
- } else if (auto defaultTy = CS.TC .getDefaultType (proto, CS.DC )) {
539
- if (paramTy->isEqual (defaultTy)) {
540
- return true ;
541
- }
542
- }
543
- }
517
+
518
+ // If the argument is a literal, this is a favored param/arg pair if
519
+ // the parameter is of that default type.
520
+ auto &tc = CS.getTypeChecker ();
521
+ auto literalProto = tc.getLiteralProtocol (arg->getSemanticsProvidingExpr ());
522
+ if (!literalProto) return false ;
523
+
524
+ // Dig out the second argument type.
525
+ if (otherArgTy)
526
+ otherArgTy = otherArgTy->getLValueOrInOutObjectType ();
527
+
528
+ // If there is another, concrete argument, check whether it's type
529
+ // conforms to the literal protocol and test against it directly.
530
+ // This helps to avoid 'widening' the favored type to the default type for
531
+ // the literal.
532
+ if (otherArgTy && otherArgTy->getAnyNominal ()) {
533
+ return otherArgTy->isEqual (paramTy) &&
534
+ tc.conformsToProtocol (otherArgTy, literalProto, CS.DC ,
535
+ ConformanceCheckFlags::InExpression);
544
536
}
545
-
537
+
538
+ // If there is a default type for the literal protocol, check whether
539
+ // it is the same as the parameter type.
540
+ // Check whether there is a default type to compare against.
541
+ if (Type defaultType = tc.getDefaultType (literalProto, CS.DC ))
542
+ return paramTy->isEqual (defaultType);
543
+
546
544
return false ;
547
545
}
548
546
@@ -742,9 +740,6 @@ namespace {
742
740
// / for the operand and contextual type.
743
741
void favorMatchingUnaryOperators (ApplyExpr *expr,
744
742
ConstraintSystem &CS) {
745
- // Find the argument type.
746
- auto argTy = expr->getArg ()->getType ()->getWithoutParens ();
747
-
748
743
// Determine whether the given declaration is favored.
749
744
auto isFavoredDecl = [&](ValueDecl *value) -> bool {
750
745
auto valueTy = value->getType ();
@@ -762,7 +757,8 @@ namespace {
762
757
auto resultTy = fnTy->getResult ();
763
758
auto contextualTy = CS.getContextualType (expr);
764
759
765
- return isFavoredParamAndArg (CS, paramTy, argTy, Type ()) &&
760
+ return isFavoredParamAndArg (CS, paramTy, expr->getArg (),
761
+ expr->getArg ()->getType ()->getWithoutParens ()) &&
766
762
(!contextualTy || contextualTy->isEqual (resultTy));
767
763
};
768
764
@@ -881,8 +877,10 @@ namespace {
881
877
if (!fnTy)
882
878
return false ;
883
879
884
- auto firstFavoredTy = CS.getFavoredType (argTupleExpr->getElement (0 ));
885
- auto secondFavoredTy = CS.getFavoredType (argTupleExpr->getElement (1 ));
880
+ Expr *firstArg = argTupleExpr->getElement (0 );
881
+ auto firstFavoredTy = CS.getFavoredType (firstArg);
882
+ Expr *secondArg = argTupleExpr->getElement (1 );
883
+ auto secondFavoredTy = CS.getFavoredType (secondArg);
886
884
887
885
auto favoredExprTy = CS.getFavoredType (expr);
888
886
@@ -926,8 +924,10 @@ namespace {
926
924
auto contextualTy = CS.getContextualType (expr);
927
925
928
926
return
929
- (isFavoredParamAndArg (CS, firstParamTy, firstArgTy, secondArgTy) ||
930
- isFavoredParamAndArg (CS, secondParamTy, secondArgTy, firstArgTy)) &&
927
+ (isFavoredParamAndArg (CS, firstParamTy, firstArg, firstArgTy,
928
+ secondArg, secondArgTy) ||
929
+ isFavoredParamAndArg (CS, secondParamTy, secondArg, secondArgTy,
930
+ firstArg, firstArgTy)) &&
931
931
firstParamTy->isEqual (secondParamTy) &&
932
932
(!contextualTy || contextualTy->isEqual (resultTy));
933
933
};
@@ -1083,7 +1083,7 @@ namespace {
1083
1083
auto keyTy = dictTy->first ;
1084
1084
auto valueTy = dictTy->second ;
1085
1085
1086
- if (isFavoredParamAndArg (CS, keyTy, index->getType (), Type ())) {
1086
+ if (isFavoredParamAndArg (CS, keyTy, index, index ->getType ())) {
1087
1087
outputTy = OptionalType::get (valueTy);
1088
1088
1089
1089
if (isLValueBase)
@@ -1164,10 +1164,7 @@ namespace {
1164
1164
1165
1165
auto tv = CS.createTypeVariable (CS.getConstraintLocator (expr),
1166
1166
TVO_PrefersSubtypeBinding);
1167
-
1168
- tv->getImpl ().literalConformanceProto = protocol;
1169
-
1170
- CS.addConstraint (ConstraintKind::ConformsTo, tv,
1167
+ CS.addConstraint (ConstraintKind::LiteralConformsTo, tv,
1171
1168
protocol->getDeclaredType (),
1172
1169
CS.getConstraintLocator (expr));
1173
1170
return tv;
@@ -1190,8 +1187,7 @@ namespace {
1190
1187
// ExpressibleByStringInterpolation protocol.
1191
1188
auto locator = CS.getConstraintLocator (expr);
1192
1189
auto tv = CS.createTypeVariable (locator, TVO_PrefersSubtypeBinding);
1193
- tv->getImpl ().literalConformanceProto = interpolationProto;
1194
- CS.addConstraint (ConstraintKind::ConformsTo, tv,
1190
+ CS.addConstraint (ConstraintKind::LiteralConformsTo, tv,
1195
1191
interpolationProto->getDeclaredType (),
1196
1192
locator);
1197
1193
@@ -1264,9 +1260,7 @@ namespace {
1264
1260
auto tv = CS.createTypeVariable (CS.getConstraintLocator (expr),
1265
1261
TVO_PrefersSubtypeBinding);
1266
1262
1267
- tv->getImpl ().literalConformanceProto = protocol;
1268
-
1269
- CS.addConstraint (ConstraintKind::ConformsTo, tv,
1263
+ CS.addConstraint (ConstraintKind::LiteralConformsTo, tv,
1270
1264
protocol->getDeclaredType (),
1271
1265
CS.getConstraintLocator (expr));
1272
1266
@@ -1683,7 +1677,7 @@ namespace {
1683
1677
contextualArrayElementType =
1684
1678
CS.getBaseTypeForArrayType (contextualType.getPointer ());
1685
1679
1686
- CS.addConstraint (ConstraintKind::ConformsTo , contextualType,
1680
+ CS.addConstraint (ConstraintKind::LiteralConformsTo , contextualType,
1687
1681
arrayProto->getDeclaredType (),
1688
1682
locator);
1689
1683
@@ -1703,7 +1697,7 @@ namespace {
1703
1697
auto arrayTy = CS.createTypeVariable (locator, TVO_PrefersSubtypeBinding);
1704
1698
1705
1699
// The array must be an array literal type.
1706
- CS.addConstraint (ConstraintKind::ConformsTo , arrayTy,
1700
+ CS.addConstraint (ConstraintKind::LiteralConformsTo , arrayTy,
1707
1701
arrayProto->getDeclaredType (),
1708
1702
locator);
1709
1703
@@ -1769,8 +1763,8 @@ namespace {
1769
1763
auto dictionaryTy = CS.createTypeVariable (locator,
1770
1764
TVO_PrefersSubtypeBinding);
1771
1765
1772
- // The array must be a dictionary literal type.
1773
- CS.addConstraint (ConstraintKind::ConformsTo , dictionaryTy,
1766
+ // The dictionary must be a dictionary literal type.
1767
+ CS.addConstraint (ConstraintKind::LiteralConformsTo , dictionaryTy,
1774
1768
dictionaryProto->getDeclaredType (),
1775
1769
locator);
1776
1770
0 commit comments