@@ -500,47 +500,49 @@ namespace {
500500 return false ;
501501 }
502502
503- // / Determine whether the given parameter type and argument should be
503+ // / Determine whether the given parameter and argument type should be
504504 // / "favored" because they match exactly.
505505 bool isFavoredParamAndArg (ConstraintSystem &CS,
506506 Type paramTy,
507- Expr *arg,
508507 Type argTy,
509- Expr *otherArg = nullptr ,
510- Type otherArgTy = Type()) {
511- // Determine the argument type.
512- argTy = argTy->getLValueOrInOutObjectType ();
513-
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+
514516 // Do the types match exactly?
515517 if (paramTy->isEqual (argTy))
516518 return true ;
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);
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+ }
536544 }
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-
545+
544546 return false ;
545547 }
546548
@@ -740,6 +742,9 @@ namespace {
740742 // / for the operand and contextual type.
741743 void favorMatchingUnaryOperators (ApplyExpr *expr,
742744 ConstraintSystem &CS) {
745+ // Find the argument type.
746+ auto argTy = expr->getArg ()->getType ()->getWithoutParens ();
747+
743748 // Determine whether the given declaration is favored.
744749 auto isFavoredDecl = [&](ValueDecl *value) -> bool {
745750 auto valueTy = value->getType ();
@@ -757,8 +762,7 @@ namespace {
757762 auto resultTy = fnTy->getResult ();
758763 auto contextualTy = CS.getContextualType (expr);
759764
760- return isFavoredParamAndArg (CS, paramTy, expr->getArg (),
761- expr->getArg ()->getType ()) &&
765+ return isFavoredParamAndArg (CS, paramTy, argTy, Type ()) &&
762766 (!contextualTy || contextualTy->isEqual (resultTy));
763767 };
764768
@@ -877,10 +881,8 @@ namespace {
877881 if (!fnTy)
878882 return false ;
879883
880- Expr *firstArg = argTupleExpr->getElement (0 );
881- auto firstFavoredTy = CS.getFavoredType (firstArg);
882- Expr *secondArg = argTupleExpr->getElement (1 );
883- auto secondFavoredTy = CS.getFavoredType (secondArg);
884+ auto firstFavoredTy = CS.getFavoredType (argTupleExpr->getElement (0 ));
885+ auto secondFavoredTy = CS.getFavoredType (argTupleExpr->getElement (1 ));
884886
885887 auto favoredExprTy = CS.getFavoredType (expr);
886888
@@ -924,10 +926,8 @@ namespace {
924926 auto contextualTy = CS.getContextualType (expr);
925927
926928 return
927- (isFavoredParamAndArg (CS, firstParamTy, firstArg, firstArgTy,
928- secondArg, secondArgTy) ||
929- isFavoredParamAndArg (CS, secondParamTy, secondArg, secondArgTy,
930- firstArg, firstArgTy)) &&
929+ (isFavoredParamAndArg (CS, firstParamTy, firstArgTy, secondArgTy) ||
930+ isFavoredParamAndArg (CS, secondParamTy, secondArgTy, firstArgTy)) &&
931931 firstParamTy->isEqual (secondParamTy) &&
932932 (!contextualTy || contextualTy->isEqual (resultTy));
933933 };
@@ -1083,7 +1083,7 @@ namespace {
10831083 auto keyTy = dictTy->first ;
10841084 auto valueTy = dictTy->second ;
10851085
1086- if (isFavoredParamAndArg (CS, keyTy, index, index ->getType ())) {
1086+ if (isFavoredParamAndArg (CS, keyTy, index->getType (), Type ())) {
10871087 outputTy = OptionalType::get (valueTy);
10881088
10891089 if (isLValueBase)
@@ -1164,7 +1164,10 @@ namespace {
11641164
11651165 auto tv = CS.createTypeVariable (CS.getConstraintLocator (expr),
11661166 TVO_PrefersSubtypeBinding);
1167- CS.addConstraint (ConstraintKind::LiteralConformsTo, tv,
1167+
1168+ tv->getImpl ().literalConformanceProto = protocol;
1169+
1170+ CS.addConstraint (ConstraintKind::ConformsTo, tv,
11681171 protocol->getDeclaredType (),
11691172 CS.getConstraintLocator (expr));
11701173 return tv;
@@ -1187,7 +1190,8 @@ namespace {
11871190 // ExpressibleByStringInterpolation protocol.
11881191 auto locator = CS.getConstraintLocator (expr);
11891192 auto tv = CS.createTypeVariable (locator, TVO_PrefersSubtypeBinding);
1190- CS.addConstraint (ConstraintKind::LiteralConformsTo, tv,
1193+ tv->getImpl ().literalConformanceProto = interpolationProto;
1194+ CS.addConstraint (ConstraintKind::ConformsTo, tv,
11911195 interpolationProto->getDeclaredType (),
11921196 locator);
11931197
@@ -1260,7 +1264,9 @@ namespace {
12601264 auto tv = CS.createTypeVariable (CS.getConstraintLocator (expr),
12611265 TVO_PrefersSubtypeBinding);
12621266
1263- CS.addConstraint (ConstraintKind::LiteralConformsTo, tv,
1267+ tv->getImpl ().literalConformanceProto = protocol;
1268+
1269+ CS.addConstraint (ConstraintKind::ConformsTo, tv,
12641270 protocol->getDeclaredType (),
12651271 CS.getConstraintLocator (expr));
12661272
@@ -1677,7 +1683,7 @@ namespace {
16771683 contextualArrayElementType =
16781684 CS.getBaseTypeForArrayType (contextualType.getPointer ());
16791685
1680- CS.addConstraint (ConstraintKind::LiteralConformsTo , contextualType,
1686+ CS.addConstraint (ConstraintKind::ConformsTo , contextualType,
16811687 arrayProto->getDeclaredType (),
16821688 locator);
16831689
@@ -1697,7 +1703,7 @@ namespace {
16971703 auto arrayTy = CS.createTypeVariable (locator, TVO_PrefersSubtypeBinding);
16981704
16991705 // The array must be an array literal type.
1700- CS.addConstraint (ConstraintKind::LiteralConformsTo , arrayTy,
1706+ CS.addConstraint (ConstraintKind::ConformsTo , arrayTy,
17011707 arrayProto->getDeclaredType (),
17021708 locator);
17031709
@@ -1763,8 +1769,8 @@ namespace {
17631769 auto dictionaryTy = CS.createTypeVariable (locator,
17641770 TVO_PrefersSubtypeBinding);
17651771
1766- // The dictionary must be a dictionary literal type.
1767- CS.addConstraint (ConstraintKind::LiteralConformsTo , dictionaryTy,
1772+ // The array must be a dictionary literal type.
1773+ CS.addConstraint (ConstraintKind::ConformsTo , dictionaryTy,
17681774 dictionaryProto->getDeclaredType (),
17691775 locator);
17701776
0 commit comments