@@ -540,7 +540,6 @@ namespace {
540
540
// / "favored" because they match exactly.
541
541
bool isFavoredParamAndArg (ConstraintSystem &CS,
542
542
Type paramTy,
543
- Expr *arg,
544
543
Type argTy,
545
544
Type otherArgTy = Type()) {
546
545
// Determine the argument type.
@@ -550,32 +549,45 @@ namespace {
550
549
if (paramTy->isEqual (argTy))
551
550
return true ;
552
551
553
- // If the argument is a literal, this is a favored param/arg pair if
554
- // the parameter is of that default type.
555
- auto &tc = CS.getTypeChecker ();
556
- auto literalProto = tc.getLiteralProtocol (arg->getSemanticsProvidingExpr ());
557
- if (!literalProto) return false ;
552
+ llvm::SmallSetVector<ProtocolDecl *, 2 > literalProtos;
553
+ if (auto argTypeVar = argTy->getAs <TypeVariableType>()) {
554
+ llvm::SetVector<Constraint *> constraints;
555
+ CS.getConstraintGraph ().gatherConstraints (
556
+ argTypeVar, constraints,
557
+ ConstraintGraph::GatheringKind::EquivalenceClass,
558
+ [](Constraint *constraint) {
559
+ return constraint->getKind () == ConstraintKind::LiteralConformsTo;
560
+ });
561
+
562
+ for (auto constraint : constraints) {
563
+ literalProtos.insert (constraint->getProtocol ());
564
+ }
565
+ }
558
566
559
567
// Dig out the second argument type.
560
568
if (otherArgTy)
561
569
otherArgTy = otherArgTy->getWithoutSpecifierType ();
562
570
563
- // If there is another, concrete argument, check whether it's type
564
- // conforms to the literal protocol and test against it directly.
565
- // This helps to avoid 'widening' the favored type to the default type for
566
- // the literal.
567
- if (otherArgTy && otherArgTy->getAnyNominal ()) {
568
- return otherArgTy->isEqual (paramTy) &&
569
- tc.conformsToProtocol (otherArgTy, literalProto, CS.DC ,
570
- ConformanceCheckFlags::InExpression);
571
+ auto &tc = CS.getTypeChecker ();
572
+ for (auto literalProto : literalProtos) {
573
+ // If there is another, concrete argument, check whether it's type
574
+ // conforms to the literal protocol and test against it directly.
575
+ // This helps to avoid 'widening' the favored type to the default type for
576
+ // the literal.
577
+ if (otherArgTy && otherArgTy->getAnyNominal ()) {
578
+ if (otherArgTy->isEqual (paramTy) &&
579
+ tc.conformsToProtocol (otherArgTy, literalProto, CS.DC ,
580
+ ConformanceCheckFlags::InExpression))
581
+ return true ;
582
+ } else if (Type defaultType = tc.getDefaultType (literalProto, CS.DC )) {
583
+ // If there is a default type for the literal protocol, check whether
584
+ // it is the same as the parameter type.
585
+ // Check whether there is a default type to compare against.
586
+ if (paramTy->isEqual (defaultType))
587
+ return true ;
588
+ }
571
589
}
572
590
573
- // If there is a default type for the literal protocol, check whether
574
- // it is the same as the parameter type.
575
- // Check whether there is a default type to compare against.
576
- if (Type defaultType = tc.getDefaultType (literalProto, CS.DC ))
577
- return paramTy->isEqual (defaultType);
578
-
579
591
return false ;
580
592
}
581
593
@@ -744,7 +756,7 @@ namespace {
744
756
auto contextualTy = CS.getContextualType (expr);
745
757
746
758
return isFavoredParamAndArg (
747
- CS, paramTy, expr-> getArg (),
759
+ CS, paramTy,
748
760
CS.getType (expr->getArg ())->getWithoutParens ()) &&
749
761
(!contextualTy || contextualTy->isEqual (resultTy));
750
762
};
@@ -899,14 +911,6 @@ namespace {
899
911
CS.setFavoredType (argTupleExpr->getElement (1 ), favoredExprTy);
900
912
secondFavoredTy = favoredExprTy;
901
913
}
902
-
903
- if (firstFavoredTy && firstArgTy->is <TypeVariableType>()) {
904
- firstArgTy = firstFavoredTy;
905
- }
906
-
907
- if (secondFavoredTy && secondArgTy->is <TypeVariableType>()) {
908
- secondArgTy = secondFavoredTy;
909
- }
910
914
}
911
915
912
916
// Figure out the parameter type.
@@ -924,9 +928,8 @@ namespace {
924
928
auto resultTy = fnTy->getResult ();
925
929
auto contextualTy = CS.getContextualType (expr);
926
930
927
- return (isFavoredParamAndArg (CS, firstParamTy, firstArg, firstArgTy,
928
- secondArgTy) ||
929
- isFavoredParamAndArg (CS, secondParamTy, secondArg, secondArgTy,
931
+ return (isFavoredParamAndArg (CS, firstParamTy, firstArgTy, secondArgTy) ||
932
+ isFavoredParamAndArg (CS, secondParamTy, secondArgTy,
930
933
firstArgTy)) &&
931
934
firstParamTy->isEqual (secondParamTy) &&
932
935
!isPotentialForcingOpportunity (firstArgTy, secondArgTy) &&
@@ -1109,7 +1112,7 @@ namespace {
1109
1112
auto keyTy = dictTy->first ;
1110
1113
auto valueTy = dictTy->second ;
1111
1114
1112
- if (isFavoredParamAndArg (CS, keyTy, index, CS.getType (index))) {
1115
+ if (isFavoredParamAndArg (CS, keyTy, CS.getType (index))) {
1113
1116
outputTy = OptionalType::get (valueTy);
1114
1117
1115
1118
if (isLValueBase)
@@ -2523,10 +2526,8 @@ namespace {
2523
2526
return resultOfTypeOperation (typeOperation, expr->getArg ());
2524
2527
}
2525
2528
2526
- if (isa<DeclRefExpr>(fnExpr)) {
2527
- if (auto fnType = CS.getType (fnExpr)->getAs <AnyFunctionType>()) {
2528
- outputTy = fnType->getResult ();
2529
- }
2529
+ if (auto fnType = CS.getType (fnExpr)->getAs <AnyFunctionType>()) {
2530
+ outputTy = fnType->getResult ();
2530
2531
} else if (auto OSR = dyn_cast<OverloadedDeclRefExpr>(fnExpr)) {
2531
2532
// Determine if the overloads are all functions that share a common
2532
2533
// return type.
0 commit comments