@@ -4426,27 +4426,42 @@ diagnoseSingleCandidateFailures(CalleeCandidateInfo &CCI, Expr *fnExpr,
4426
4426
.diagnose ();
4427
4427
}
4428
4428
4429
- static bool isRawRepresentableMismatch (Type fromType, Type toType,
4430
- KnownProtocolKind kind,
4431
- const ConstraintSystem &CS) {
4429
+ namespace {
4430
+ enum class RawRepresentableMismatch {
4431
+ NotApplicable,
4432
+ Convertible,
4433
+ ExactMatch
4434
+ };
4435
+ }
4436
+
4437
+ static RawRepresentableMismatch
4438
+ checkRawRepresentableMismatch (Type fromType, Type toType,
4439
+ KnownProtocolKind kind,
4440
+ const ConstraintSystem &CS) {
4432
4441
toType = toType->lookThroughAllOptionalTypes ();
4433
4442
fromType = fromType->lookThroughAllOptionalTypes ();
4434
4443
4435
4444
// First check if this is an attempt to convert from something to
4436
4445
// raw representable.
4437
4446
if (conformsToKnownProtocol (fromType, kind, CS)) {
4438
- if (isRawRepresentable (toType, kind, CS))
4439
- return true ;
4447
+ if (auto rawType = isRawRepresentable (toType, kind, CS)) {
4448
+ if (rawType->isEqual (fromType))
4449
+ return RawRepresentableMismatch::ExactMatch;
4450
+ return RawRepresentableMismatch::Convertible;
4451
+ }
4440
4452
}
4441
4453
4442
4454
// Otherwise, it might be an attempt to convert from raw representable
4443
4455
// to its raw value.
4444
- if (isRawRepresentable (fromType, kind, CS)) {
4445
- if (conformsToKnownProtocol (toType, kind, CS))
4446
- return true ;
4456
+ if (auto rawType = isRawRepresentable (fromType, kind, CS)) {
4457
+ if (conformsToKnownProtocol (toType, kind, CS)) {
4458
+ if (rawType->isEqual (toType))
4459
+ return RawRepresentableMismatch::ExactMatch;
4460
+ return RawRepresentableMismatch::Convertible;
4461
+ }
4447
4462
}
4448
4463
4449
- return false ;
4464
+ return RawRepresentableMismatch::NotApplicable ;
4450
4465
}
4451
4466
4452
4467
static bool diagnoseRawRepresentableMismatch (CalleeCandidateInfo &CCI,
@@ -4471,13 +4486,17 @@ static bool diagnoseRawRepresentableMismatch(CalleeCandidateInfo &CCI,
4471
4486
if (!argType || argType->hasTypeVariable () || argType->hasUnresolvedType ())
4472
4487
return false ;
4473
4488
4474
- ArrayRef< KnownProtocolKind> rawRepresentableProtocols = {
4489
+ KnownProtocolKind rawRepresentableProtocols[] = {
4475
4490
KnownProtocolKind::ExpressibleByStringLiteral,
4476
4491
KnownProtocolKind::ExpressibleByIntegerLiteral};
4477
4492
4478
4493
const auto &CS = CCI.CS ;
4479
4494
auto arguments = decomposeArgType (argType, argLabels);
4480
- auto *tupleArgs = dyn_cast<TupleExpr>(argExpr);
4495
+
4496
+ auto bestMatchKind = RawRepresentableMismatch::NotApplicable;
4497
+ const UncurriedCandidate *bestMatchCandidate = nullptr ;
4498
+ KnownProtocolKind bestMatchProtocol;
4499
+ size_t bestMatchIndex;
4481
4500
4482
4501
for (auto &candidate : CCI.candidates ) {
4483
4502
auto *decl = candidate.getDecl ();
@@ -4489,6 +4508,7 @@ static bool diagnoseRawRepresentableMismatch(CalleeCandidateInfo &CCI,
4489
4508
computeDefaultMap (candidate.getArgumentType (), decl,
4490
4509
candidate.level , defaultMap);
4491
4510
4511
+ // FIXME: Default arguments?
4492
4512
if (parameters.size () != arguments.size ())
4493
4513
continue ;
4494
4514
@@ -4499,24 +4519,38 @@ static bool diagnoseRawRepresentableMismatch(CalleeCandidateInfo &CCI,
4499
4519
for (auto kind : rawRepresentableProtocols) {
4500
4520
// If trying to convert from raw type to raw representable,
4501
4521
// or vice versa from raw representable (e.g. enum) to raw type.
4502
- if (!isRawRepresentableMismatch (argType, paramType, kind, CS))
4503
- continue ;
4504
-
4505
- auto *expr = argExpr;
4506
- if (tupleArgs)
4507
- expr = tupleArgs->getElement (i);
4508
-
4509
- auto diag =
4510
- CS.TC .diagnose (expr->getLoc (), diag::cannot_convert_argument_value,
4511
- argType, paramType);
4512
-
4513
- tryRawRepresentableFixIts (diag, CS, argType, paramType, kind, expr);
4514
- return true ;
4522
+ auto matchKind = checkRawRepresentableMismatch (argType, paramType, kind,
4523
+ CS);
4524
+ if (matchKind > bestMatchKind) {
4525
+ bestMatchKind = matchKind;
4526
+ bestMatchProtocol = kind;
4527
+ bestMatchCandidate = &candidate;
4528
+ bestMatchIndex = i;
4529
+ }
4515
4530
}
4516
4531
}
4517
4532
}
4518
4533
4519
- return false ;
4534
+ if (bestMatchKind == RawRepresentableMismatch::NotApplicable)
4535
+ return false ;
4536
+
4537
+ const Expr *expr = argExpr;
4538
+ if (auto *tupleArgs = dyn_cast<TupleExpr>(argExpr))
4539
+ expr = tupleArgs->getElement (bestMatchIndex);
4540
+ expr = expr->getValueProvidingExpr ();
4541
+
4542
+ auto parameters = bestMatchCandidate->getUncurriedFunctionType ()->getParams ();
4543
+ auto paramType = parameters[bestMatchIndex].getType ();
4544
+ auto singleArgType = arguments[bestMatchIndex].getType ();
4545
+
4546
+ auto diag = CS.TC .diagnose (expr->getLoc (),
4547
+ diag::cannot_convert_argument_value,
4548
+ singleArgType, paramType);
4549
+
4550
+ tryRawRepresentableFixIts (diag, CS, singleArgType, paramType,
4551
+ bestMatchProtocol, expr);
4552
+ return true ;
4553
+
4520
4554
}
4521
4555
4522
4556
// Extract expression for failed argument number
0 commit comments