@@ -4500,27 +4500,42 @@ diagnoseSingleCandidateFailures(CalleeCandidateInfo &CCI, Expr *fnExpr,
4500
4500
.diagnose ();
4501
4501
}
4502
4502
4503
- static bool isRawRepresentableMismatch (Type fromType, Type toType,
4504
- KnownProtocolKind kind,
4505
- const ConstraintSystem &CS) {
4503
+ namespace {
4504
+ enum class RawRepresentableMismatch {
4505
+ NotApplicable,
4506
+ Convertible,
4507
+ ExactMatch
4508
+ };
4509
+ }
4510
+
4511
+ static RawRepresentableMismatch
4512
+ checkRawRepresentableMismatch (Type fromType, Type toType,
4513
+ KnownProtocolKind kind,
4514
+ const ConstraintSystem &CS) {
4506
4515
toType = toType->lookThroughAllOptionalTypes ();
4507
4516
fromType = fromType->lookThroughAllOptionalTypes ();
4508
4517
4509
4518
// First check if this is an attempt to convert from something to
4510
4519
// raw representable.
4511
4520
if (conformsToKnownProtocol (fromType, kind, CS)) {
4512
- if (isRawRepresentable (toType, kind, CS))
4513
- return true ;
4521
+ if (auto rawType = isRawRepresentable (toType, kind, CS)) {
4522
+ if (rawType->isEqual (fromType))
4523
+ return RawRepresentableMismatch::ExactMatch;
4524
+ return RawRepresentableMismatch::Convertible;
4525
+ }
4514
4526
}
4515
4527
4516
4528
// Otherwise, it might be an attempt to convert from raw representable
4517
4529
// to its raw value.
4518
- if (isRawRepresentable (fromType, kind, CS)) {
4519
- if (conformsToKnownProtocol (toType, kind, CS))
4520
- return true ;
4530
+ if (auto rawType = isRawRepresentable (fromType, kind, CS)) {
4531
+ if (conformsToKnownProtocol (toType, kind, CS)) {
4532
+ if (rawType->isEqual (toType))
4533
+ return RawRepresentableMismatch::ExactMatch;
4534
+ return RawRepresentableMismatch::Convertible;
4535
+ }
4521
4536
}
4522
4537
4523
- return false ;
4538
+ return RawRepresentableMismatch::NotApplicable ;
4524
4539
}
4525
4540
4526
4541
static bool diagnoseRawRepresentableMismatch (CalleeCandidateInfo &CCI,
@@ -4545,13 +4560,17 @@ static bool diagnoseRawRepresentableMismatch(CalleeCandidateInfo &CCI,
4545
4560
if (!argType || argType->hasTypeVariable () || argType->hasUnresolvedType ())
4546
4561
return false ;
4547
4562
4548
- ArrayRef< KnownProtocolKind> rawRepresentableProtocols = {
4563
+ KnownProtocolKind rawRepresentableProtocols[] = {
4549
4564
KnownProtocolKind::ExpressibleByStringLiteral,
4550
4565
KnownProtocolKind::ExpressibleByIntegerLiteral};
4551
4566
4552
4567
const auto &CS = CCI.CS ;
4553
4568
auto arguments = decomposeArgType (argType, argLabels);
4554
- auto *tupleArgs = dyn_cast<TupleExpr>(argExpr);
4569
+
4570
+ auto bestMatchKind = RawRepresentableMismatch::NotApplicable;
4571
+ const UncurriedCandidate *bestMatchCandidate = nullptr ;
4572
+ KnownProtocolKind bestMatchProtocol;
4573
+ size_t bestMatchIndex;
4555
4574
4556
4575
for (auto &candidate : CCI.candidates ) {
4557
4576
auto *decl = candidate.getDecl ();
@@ -4562,6 +4581,7 @@ static bool diagnoseRawRepresentableMismatch(CalleeCandidateInfo &CCI,
4562
4581
continue ;
4563
4582
4564
4583
auto parameters = candidate.getParameters ();
4584
+ // FIXME: Default arguments?
4565
4585
if (parameters.size () != arguments.size ())
4566
4586
continue ;
4567
4587
@@ -4572,25 +4592,38 @@ static bool diagnoseRawRepresentableMismatch(CalleeCandidateInfo &CCI,
4572
4592
for (auto kind : rawRepresentableProtocols) {
4573
4593
// If trying to convert from raw type to raw representable,
4574
4594
// or vice versa from raw representable (e.g. enum) to raw type.
4575
- if (!isRawRepresentableMismatch (argType, paramType, kind, CS))
4576
- continue ;
4577
-
4578
- const Expr *expr = argExpr;
4579
- if (tupleArgs)
4580
- expr = tupleArgs->getElement (i);
4581
- expr = expr->getValueProvidingExpr ();
4582
-
4583
- auto diag =
4584
- CS.TC .diagnose (expr->getLoc (), diag::cannot_convert_argument_value,
4585
- argType, paramType);
4586
-
4587
- tryRawRepresentableFixIts (diag, CS, argType, paramType, kind, expr);
4588
- return true ;
4595
+ auto matchKind = checkRawRepresentableMismatch (argType, paramType, kind,
4596
+ CS);
4597
+ if (matchKind > bestMatchKind) {
4598
+ bestMatchKind = matchKind;
4599
+ bestMatchProtocol = kind;
4600
+ bestMatchCandidate = &candidate;
4601
+ bestMatchIndex = i;
4602
+ }
4589
4603
}
4590
4604
}
4591
4605
}
4592
4606
4593
- return false ;
4607
+ if (bestMatchKind == RawRepresentableMismatch::NotApplicable)
4608
+ return false ;
4609
+
4610
+ const Expr *expr = argExpr;
4611
+ if (auto *tupleArgs = dyn_cast<TupleExpr>(argExpr))
4612
+ expr = tupleArgs->getElement (bestMatchIndex);
4613
+ expr = expr->getValueProvidingExpr ();
4614
+
4615
+ auto parameters = bestMatchCandidate->getParameters ();
4616
+ auto paramType = parameters[bestMatchIndex].getType ();
4617
+ auto singleArgType = arguments[bestMatchIndex].getType ();
4618
+
4619
+ auto diag = CS.TC .diagnose (expr->getLoc (),
4620
+ diag::cannot_convert_argument_value,
4621
+ singleArgType, paramType);
4622
+
4623
+ tryRawRepresentableFixIts (diag, CS, singleArgType, paramType,
4624
+ bestMatchProtocol, expr);
4625
+ return true ;
4626
+
4594
4627
}
4595
4628
4596
4629
// Extract expression for failed argument number
0 commit comments