Skip to content

Commit 9116f95

Browse files
authored
Merge pull request #17714 from jrose-apple/raw-deal
Prefer RawRepresentable fix-its that don't require an extra conversion https://bugs.swift.org/browse/SR-8150
2 parents 542d442 + b318ab1 commit 9116f95

File tree

2 files changed

+84
-27
lines changed

2 files changed

+84
-27
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 59 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4501,27 +4501,42 @@ diagnoseSingleCandidateFailures(CalleeCandidateInfo &CCI, Expr *fnExpr,
45014501
.diagnose();
45024502
}
45034503

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) {
45074516
toType = toType->lookThroughAllOptionalTypes();
45084517
fromType = fromType->lookThroughAllOptionalTypes();
45094518

45104519
// First check if this is an attempt to convert from something to
45114520
// raw representable.
45124521
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+
}
45154527
}
45164528

45174529
// Otherwise, it might be an attempt to convert from raw representable
45184530
// 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+
}
45224537
}
45234538

4524-
return false;
4539+
return RawRepresentableMismatch::NotApplicable;
45254540
}
45264541

45274542
static bool diagnoseRawRepresentableMismatch(CalleeCandidateInfo &CCI,
@@ -4546,13 +4561,17 @@ static bool diagnoseRawRepresentableMismatch(CalleeCandidateInfo &CCI,
45464561
if (!argType || argType->hasTypeVariable() || argType->hasUnresolvedType())
45474562
return false;
45484563

4549-
ArrayRef<KnownProtocolKind> rawRepresentableProtocols = {
4564+
KnownProtocolKind rawRepresentableProtocols[] = {
45504565
KnownProtocolKind::ExpressibleByStringLiteral,
45514566
KnownProtocolKind::ExpressibleByIntegerLiteral};
45524567

45534568
const auto &CS = CCI.CS;
45544569
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;
45564575

45574576
for (auto &candidate : CCI.candidates) {
45584577
auto *decl = candidate.getDecl();
@@ -4563,6 +4582,7 @@ static bool diagnoseRawRepresentableMismatch(CalleeCandidateInfo &CCI,
45634582
continue;
45644583

45654584
auto parameters = candidate.getParameters();
4585+
// FIXME: Default arguments?
45664586
if (parameters.size() != arguments.size())
45674587
continue;
45684588

@@ -4573,24 +4593,38 @@ static bool diagnoseRawRepresentableMismatch(CalleeCandidateInfo &CCI,
45734593
for (auto kind : rawRepresentableProtocols) {
45744594
// If trying to convert from raw type to raw representable,
45754595
// 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+
}
45894604
}
45904605
}
45914606
}
45924607

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+
45944628
}
45954629

45964630
// Extract expression for failed argument number

test/Sema/enum_raw_representable.swift

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ rdar32431165_1(.baz)
120120
// expected-error@-1 {{reference to member 'baz' cannot be resolved without a contextual type}}
121121

122122
rdar32431165_1("")
123-
// expected-error@-1 {{cannot convert value of type 'String' to expected argument type 'E_32431165'}} {{15-15=E_32431165(rawValue: }} {{19-19=)}}
123+
// expected-error@-1 {{cannot convert value of type 'String' to expected argument type 'E_32431165'}} {{16-16=E_32431165(rawValue: }} {{18-18=)}}
124124
rdar32431165_1(42, "")
125125
// expected-error@-1 {{cannot convert value of type 'String' to expected argument type 'E_32431165'}} {{20-20=E_32431165(rawValue: }} {{22-22=)}}
126126

@@ -129,7 +129,7 @@ func rdar32431165_2(_: Int) {}
129129
func rdar32431165_2(_: Int, _: String) {}
130130

131131
rdar32431165_2(E_32431165.bar)
132-
// expected-error@-1 {{cannot convert value of type 'E_32431165' to expected argument type 'String'}} {{15-15=}} {{31-31=.rawValue}}
132+
// expected-error@-1 {{cannot convert value of type 'E_32431165' to expected argument type 'String'}} {{16-16=}} {{30-30=.rawValue}}
133133
rdar32431165_2(42, E_32431165.bar)
134134
// expected-error@-1 {{cannot convert value of type 'E_32431165' to expected argument type 'String'}} {{20-20=}} {{34-34=.rawValue}}
135135

@@ -145,6 +145,29 @@ func rdar32432253(_ condition: Bool = false) {
145145
// expected-error@-1 {{cannot convert value of type 'E_32431165' to expected argument type 'String'}} {{11-11=}} {{17-17=.rawValue}}
146146
}
147147

148+
func sr8150_helper1(_: Int) {}
149+
func sr8150_helper1(_: Double) {}
150+
151+
func sr8150_helper2(_: Double) {}
152+
func sr8150_helper2(_: Int) {}
153+
154+
func sr8150_helper3(_: Foo) {}
155+
func sr8150_helper3(_: Bar) {}
156+
157+
func sr8150_helper4(_: Bar) {}
158+
func sr8150_helper4(_: Foo) {}
159+
160+
func sr8150(bar: Bar) {
161+
sr8150_helper1(bar)
162+
// expected-error@-1 {{cannot convert value of type 'Bar' to expected argument type 'Double'}} {{18-18=}} {{21-21=.rawValue}}
163+
sr8150_helper2(bar)
164+
// expected-error@-1 {{cannot convert value of type 'Bar' to expected argument type 'Double'}} {{18-18=}} {{21-21=.rawValue}}
165+
sr8150_helper3(0.0)
166+
// expected-error@-1 {{cannot convert value of type 'Double' to expected argument type 'Bar'}} {{18-18=Bar(rawValue: }} {{21-21=)}}
167+
sr8150_helper4(0.0)
168+
// expected-error@-1 {{cannot convert value of type 'Double' to expected argument type 'Bar'}} {{18-18=Bar(rawValue: }} {{21-21=)}}
169+
}
170+
148171

149172
struct NotEquatable { }
150173

0 commit comments

Comments
 (0)