Skip to content

Commit cfca329

Browse files
authored
Merge pull request #14584 from rudkx/rdar37073401
Fix an issue with the constraint favoring code in the constraint opti…
2 parents a46aa98 + dc8c880 commit cfca329

File tree

2 files changed

+36
-10
lines changed

2 files changed

+36
-10
lines changed

lib/Sema/CSGen.cpp

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -828,7 +828,20 @@ namespace {
828828

829829
Type firstArgTy = argTupleTy->getElement(0).getType()->getWithoutParens();
830830
Type secondArgTy = argTupleTy->getElement(1).getType()->getWithoutParens();
831-
831+
832+
auto isOptionalWithMatchingObjectType = [](Type optional,
833+
Type object) -> bool {
834+
if (auto objTy = optional->getRValueType()->getOptionalObjectType())
835+
return objTy->getRValueType()->isEqual(object->getRValueType());
836+
837+
return false;
838+
};
839+
840+
auto isPotentialForcingOpportunity = [&](Type first, Type second) -> bool {
841+
return isOptionalWithMatchingObjectType(first, second) ||
842+
isOptionalWithMatchingObjectType(second, first);
843+
};
844+
832845
// Determine whether the given declaration is favored.
833846
auto isFavoredDecl = [&](ValueDecl *value) -> bool {
834847
auto valueTy = value->getInterfaceType();
@@ -882,14 +895,14 @@ namespace {
882895

883896
auto resultTy = fnTy->getResult();
884897
auto contextualTy = CS.getContextualType(expr);
885-
886-
return
887-
(isFavoredParamAndArg(CS, firstParamTy, firstArg, firstArgTy,
888-
secondArgTy) ||
889-
isFavoredParamAndArg(CS, secondParamTy, secondArg, secondArgTy,
890-
firstArgTy)) &&
891-
firstParamTy->isEqual(secondParamTy) &&
892-
(!contextualTy || contextualTy->isEqual(resultTy));
898+
899+
return (isFavoredParamAndArg(CS, firstParamTy, firstArg, firstArgTy,
900+
secondArgTy) ||
901+
isFavoredParamAndArg(CS, secondParamTy, secondArg, secondArgTy,
902+
firstArgTy)) &&
903+
firstParamTy->isEqual(secondParamTy) &&
904+
!isPotentialForcingOpportunity(firstArgTy, secondArgTy) &&
905+
(!contextualTy || contextualTy->isEqual(resultTy));
893906
};
894907

895908
favorCallOverloads(expr, CS, isFavoredDecl);

test/stdlib/ImplicitlyUnwrappedOptional.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,18 @@ ImplicitlyUnwrappedOptionalTests.test("flatMap") {
5757
// expectNil((3 as Int!).flatMap(half))
5858
}
5959

60-
runAllTests()
60+
infix operator *^* : ComparisonPrecedence
61+
62+
func *^*(lhs: Int?, rhs: Int?) -> Bool { return true }
63+
func *^*(lhs: Int, rhs: Int) -> Bool { return true }
64+
65+
ImplicitlyUnwrappedOptionalTests.test("preferOptional") {
66+
let i: Int! = nil
67+
let j: Int = 1
68+
if i != j {} // we should choose != for Optionals rather than forcing i
69+
if i == j {} // we should choose == for Optionals rather than forcing i
70+
// FIXME: https://bugs.swift.org/browse/SR-6988
71+
// if i *^* j {} // we should choose *^* for Optionals rather than forcing i
72+
}
6173

74+
runAllTests()

0 commit comments

Comments
 (0)