Skip to content

Commit c10f04d

Browse files
committed
[TypeChecker] Allow Double<->CGFloat conversion with optional promotions
There are APIs that expect a `Double?` or `CGFloat?` argument and it should be possible to pass `CGFloat` and `Double` respectively.
1 parent 4de232e commit c10f04d

File tree

3 files changed

+47
-2
lines changed

3 files changed

+47
-2
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5131,14 +5131,36 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
51315131
nominal1->getDecl() != nominal2->getDecl() &&
51325132
((nominal1->isCGFloatType() || nominal2->isCGFloatType()) &&
51335133
(nominal1->isDoubleType() || nominal2->isDoubleType()))) {
5134+
ConstraintLocatorBuilder location{locator};
5135+
// Look through all value-to-optional promotions to allow
5136+
// conversions like Double -> CGFloat?? and vice versa.
5137+
if (auto last = location.last()) {
5138+
// T -> Optional<T>
5139+
if (last->is<LocatorPathElt::OptionalPayload>()) {
5140+
SmallVector<LocatorPathElt, 4> path;
5141+
auto anchor = location.getLocatorParts(path);
5142+
5143+
// Drop all of the applied `value-to-optional` promotions.
5144+
path.erase(llvm::remove_if(
5145+
path,
5146+
[](const LocatorPathElt &elt) {
5147+
return elt.is<LocatorPathElt::OptionalPayload>();
5148+
}),
5149+
path.end());
5150+
5151+
location = getConstraintLocator(anchor, path);
5152+
}
5153+
}
5154+
51345155
// Support implicit Double<->CGFloat conversions only for
51355156
// something which could be directly represented in the AST
51365157
// e.g. argument-to-parameter, contextual conversions etc.
5137-
if (!locator.trySimplifyToExpr())
5158+
if (!location.trySimplifyToExpr()) {
51385159
return getTypeMatchFailure(locator);
5160+
}
51395161

51405162
SmallVector<LocatorPathElt, 4> path;
5141-
auto anchor = locator.getLocatorParts(path);
5163+
auto anchor = location.getLocatorParts(path);
51425164

51435165
// Try implicit CGFloat conversion only if:
51445166
// - This is not:

test/Constraints/implicit_double_cgfloat_conversion.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,3 +192,20 @@ func test_no_ambiguity_with_unary_operators(width: CGFloat, height: CGFloat) {
192192
// CHECK: function_ref @$s34implicit_double_cgfloat_conversion38test_no_ambiguity_with_unary_operators5width6heighty12CoreGraphics7CGFloatV_AGtF1RL_V1x1yAcdiG_A3GtcfC
193193
_ = R(x: width / 4, y: -height / 2, width: width, height: height)
194194
}
195+
196+
func test_conversions_with_optional_promotion(d: Double, cgf: CGFloat) {
197+
func test_double(_: Double??) {}
198+
func test_cgfloat(_: CGFloat??) {}
199+
200+
// CHECK: function_ref @$sSd12CoreGraphicsEySdAA7CGFloatVcfC
201+
// CHECK-NEXT: apply
202+
// CHECK-NEXT: enum $Optional<Double>, #Optional.some!enumelt
203+
// CHECK-NEXT: enum $Optional<Optional<Double>>, #Optional.some!enumelt
204+
test_double(cgf)
205+
206+
// CHECK: function_ref @$s12CoreGraphics7CGFloatVyACSdcfC
207+
// CHECK-NEXT: apply
208+
// CHECK-NEXT: enum $Optional<CGFloat>, #Optional.some!enumelt
209+
// CHECK-NEXT: enum $Optional<Optional<CGFloat>>, #Optional.some!enumelt
210+
test_cgfloat(d)
211+
}

test/Misc/misc_diagnostics.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,4 +228,10 @@ func test_implicit_cgfloat_conversion() {
228228
}
229229
_ = S(x: 0.0, y: values.0) // Ok
230230
}
231+
232+
func allow_optional_promotion_double(_: Double??) {}
233+
func allow_optional_promotion_cgfloat(_: CGFloat??) {}
234+
235+
allow_optional_promotion_double(cgf) // Ok -> CGFloat -> Double -> Double??
236+
allow_optional_promotion_cgfloat(d) // Ok -> Double -> CGFloat -> CFloat??
231237
}

0 commit comments

Comments
 (0)