Skip to content

Commit dbf401e

Browse files
committed
[CSGen] Tweak favoring hacks to avoid favoring overloads that require narrowing conversions (Double -> CGFloat)
1 parent 6fe4ffc commit dbf401e

File tree

2 files changed

+52
-8
lines changed

2 files changed

+52
-8
lines changed

lib/Sema/CSGen.cpp

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -381,9 +381,13 @@ namespace {
381381
if (paramTy->isEqual(argTy))
382382
return true;
383383

384-
// Double and CGFloat types could be used interchangeably
385-
if ((argTy->isCGFloatType() || argTy->isDoubleType()) &&
386-
(paramTy->isDoubleType() || paramTy->isCGFloatType()))
384+
// Don't favor narrowing conversions.
385+
if (argTy->isDoubleType() && paramTy->isCGFloatType())
386+
return false;
387+
388+
// CGFloat could be passed to a Double parameter and that's
389+
// is either equivalent of widening conversion.
390+
if (argTy->isCGFloatType() && paramTy->isDoubleType())
387391
return true;
388392

389393
llvm::SmallSetVector<ProtocolDecl *, 2> literalProtos;
@@ -549,9 +553,9 @@ namespace {
549553
if (contextualTy->isEqual(resultTy))
550554
return true;
551555

552-
// Double and CGFloat could be used interchangeably.
553-
return (resultTy->isDoubleType() || resultTy->isCGFloatType()) &&
554-
(contextualTy->isDoubleType() || contextualTy->isCGFloatType());
556+
// Double and CGFloat could be used interchangeably, so let's
557+
// favor widening conversion going from CGFloat to Double.
558+
return resultTy->isCGFloatType() && contextualTy->isDoubleType();
555559
}
556560

557561
/// Favor unary operator constraints where we have exact matches
@@ -566,8 +570,19 @@ namespace {
566570

567571
Type paramTy = FunctionType::composeInput(CS.getASTContext(),
568572
fnTy->getParams(), false);
569-
return isFavoredParamAndArg(
570-
CS, paramTy, CS.getType(expr->getArg())->getWithoutParens()) &&
573+
574+
auto argTy = CS.getType(expr->getArg())
575+
->getWithoutParens()
576+
->getWithoutSpecifierType();
577+
578+
// There is no CGFloat overloads on some of the unary operators, so
579+
// in order to preserve current behavior let's not favor overloads
580+
// which would result in conversion from CGFloat to Double otherwise
581+
// it would lead to ambiguities.
582+
if (argTy->isCGFloatType() && paramTy->isDoubleType())
583+
return false;
584+
585+
return isFavoredParamAndArg(CS, paramTy, argTy) &&
571586
hasContextuallyFavorableResultType(fnTy,
572587
CS.getContextualType(expr));
573588
};
@@ -724,6 +739,16 @@ namespace {
724739

725740
auto contextualTy = CS.getContextualType(expr);
726741

742+
// Avoid favoring overloads that would require narrowing conversion
743+
// to match the arguments.
744+
{
745+
if (firstArgTy->isDoubleType() && firstParamTy->isCGFloatType())
746+
return false;
747+
748+
if (secondArgTy->isDoubleType() && secondParamTy->isCGFloatType())
749+
return false;
750+
}
751+
727752
return (isFavoredParamAndArg(CS, firstParamTy, firstArgTy, secondArgTy) ||
728753
isFavoredParamAndArg(CS, secondParamTy, secondArgTy,
729754
firstArgTy)) &&

test/Constraints/implicit_double_cgfloat_conversion.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,3 +173,22 @@ func test_narrowing_is_delayed(x: Double, y: CGFloat) {
173173
// CHECK: function_ref @$s12CoreGraphics7CGFloatVyACSdcf
174174
test(overloaded(x, overloaded(x, y)))
175175
}
176+
177+
extension CGFloat {
178+
static func /(_: CGFloat, _: CGFloat) -> CGFloat { fatalError() }
179+
180+
static prefix func -(_: Self) -> Self { fatalError() }
181+
}
182+
183+
// Make sure that solution with no Double/CGFloat conversions is preferred
184+
func test_no_ambiguity_with_unary_operators(width: CGFloat, height: CGFloat) {
185+
struct R {
186+
init(x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat) {}
187+
init(x: Double, y: Double, width: Double, height: Double) {}
188+
init(x: Int, y: Int, width: Int, height: Int) {}
189+
}
190+
191+
// CHECK: function_ref @$s12CoreGraphics7CGFloatV34implicit_double_cgfloat_conversionE1doiyA2C_ACtFZ
192+
// CHECK: function_ref @$s34implicit_double_cgfloat_conversion38test_no_ambiguity_with_unary_operators5width6heighty12CoreGraphics7CGFloatV_AGtF1RL_V1x1yAcdiG_A3GtcfC
193+
_ = R(x: width / 4, y: -height / 2, width: width, height: height)
194+
}

0 commit comments

Comments
 (0)