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