Skip to content

Commit bf2d01e

Browse files
authored
Merge pull request #80419 from xedin/revert-pr-79397
Revert "Sema: Allow optional-to-optional CGFloat <-> Double conversion"
2 parents 6d425fc + 00f0d3a commit bf2d01e

File tree

5 files changed

+50
-10
lines changed

5 files changed

+50
-10
lines changed

include/swift/AST/DiagnosticsSema.def

+7
Original file line numberDiff line numberDiff line change
@@ -7580,6 +7580,13 @@ ERROR(result_builder_buildpartialblock_accumulated_not_accessible,none,
75807580
"expression shuffles the elements of this tuple; "
75817581
"this behavior is deprecated", ())
75827582

7583+
//------------------------------------------------------------------------------
7584+
// MARK: Implicit conversion diagnostics
7585+
//------------------------------------------------------------------------------
7586+
ERROR(cannot_implicitly_convert_in_optional_context,none,
7587+
"cannot implicitly convert value of type %0 to expected type %1",
7588+
(Type, Type))
7589+
75837590
//------------------------------------------------------------------------------
75847591
// MARK: marker protocol diagnostics
75857592
//------------------------------------------------------------------------------

lib/Sema/CSDiagnostics.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -2852,6 +2852,22 @@ bool ContextualFailure::diagnoseAsError() {
28522852
break;
28532853
}
28542854

2855+
case ConstraintLocator::OptionalInjection: {
2856+
// If this is an attempt at a Double <-> CGFloat conversion
2857+
// through optional chaining, let's produce a tailored diagnostic.
2858+
if (isExpr<OptionalEvaluationExpr>(getAnchor())) {
2859+
if ((fromType->isDouble() || fromType->isCGFloat()) &&
2860+
(toType->isDouble() || toType->isCGFloat())) {
2861+
fromType = OptionalType::get(fromType);
2862+
toType = OptionalType::get(toType);
2863+
diagnostic = diag::cannot_implicitly_convert_in_optional_context;
2864+
break;
2865+
}
2866+
}
2867+
2868+
return false;
2869+
}
2870+
28552871
case ConstraintLocator::EnumPatternImplicitCastMatch: {
28562872
// In this case, the types are reversed, as we are checking whether we
28572873
// can convert the pattern type to the context type.

lib/Sema/CSSimplify.cpp

+16-6
Original file line numberDiff line numberDiff line change
@@ -7489,18 +7489,28 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
74897489
// Look through all value-to-optional promotions to allow
74907490
// conversions like Double -> CGFloat?? and vice versa.
74917491
// T -> Optional<T>
7492-
if (location.endsWith<LocatorPathElt::OptionalInjection>() ||
7493-
location.endsWith<LocatorPathElt::GenericArgument>()) {
7492+
if (location.endsWith<LocatorPathElt::OptionalInjection>()) {
74947493
SmallVector<LocatorPathElt, 4> path;
74957494
auto anchor = location.getLocatorParts(path);
74967495

7497-
// Drop all of the applied `value-to-optional` and
7498-
// `optional-to-optional` conversions.
7496+
// An attempt at Double/CGFloat conversion through
7497+
// optional chaining. This is not supported at the
7498+
// moment because solution application doesn't know
7499+
// how to map Double to/from CGFloat through optionals.
7500+
if (isExpr<OptionalEvaluationExpr>(anchor)) {
7501+
if (!shouldAttemptFixes())
7502+
return getTypeMatchFailure(locator);
7503+
7504+
conversionsOrFixes.push_back(ContextualMismatch::create(
7505+
*this, nominal1, nominal2, getConstraintLocator(locator)));
7506+
break;
7507+
}
7508+
7509+
// Drop all of the applied `value-to-optional` promotions.
74997510
path.erase(llvm::remove_if(
75007511
path,
75017512
[](const LocatorPathElt &elt) {
7502-
return elt.is<LocatorPathElt::OptionalInjection>() ||
7503-
elt.is<LocatorPathElt::GenericArgument>();
7513+
return elt.is<LocatorPathElt::OptionalInjection>();
75047514
}),
75057515
path.end());
75067516

test/Constraints/implicit_double_cgfloat_conversion.swift

+10-3
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,14 @@ func test_init_validation() {
350350
}
351351
}
352352

353-
// Optional-to-optional conversion
354-
func optional_to_optional(x: CGFloat?) -> Double? {
355-
return x
353+
func test_ternary_and_nil_coalescing() {
354+
func test(_: Double?) {}
355+
356+
func ternary(v: CGFloat) {
357+
test(true ? v : nil) // Ok
358+
}
359+
360+
func test_nil_coalescing(v: CGFloat?) {
361+
test(v ?? 0.0) // Ok
362+
}
356363
}

validation-test/Sema/type_checker_crashers_fixed/rdar83666783.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ func compute(_: Double?) -> Double? {
1212
}
1313

1414
func test(s: S?) {
15-
_ = compute(s?.test)
15+
_ = compute(s?.test) // expected-error {{cannot implicitly convert value of type 'CGFloat?' to expected type 'Double?'}}
1616
}

0 commit comments

Comments
 (0)