Skip to content

Commit 8bedc61

Browse files
authored
Merge pull request #18073 from apple/revert-17855-rdar19748710
2 parents 67cf94f + c0007f8 commit 8bedc61

File tree

7 files changed

+54
-116
lines changed

7 files changed

+54
-116
lines changed

lib/Sema/CSRanking.cpp

Lines changed: 50 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,7 @@ void ConstraintSystem::increaseScore(ScoreKind kind, unsigned value) {
6767
case SK_CollectionUpcastConversion:
6868
log << "collection upcast conversion";
6969
break;
70-
71-
case SK_BindOptionalToArchetype:
72-
log << "bind optional to archetype";
73-
break;
74-
70+
7571
case SK_ValueToOptional:
7672
log << "value to optional";
7773
break;
@@ -638,28 +634,6 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
638634
Type paramType1 = getAdjustedParamType(param1);
639635
Type paramType2 = getAdjustedParamType(param2);
640636

641-
// If we have:
642-
// param1Type = $T0?
643-
// param2Type = $T1
644-
// the subtype constraint check will always return true
645-
// since we'll attempt to bind $T1 as $T0?.
646-
//
647-
// What we're comparing here is foo<T>(_: T?) vs. foo<T>(_: T) and
648-
// we don't want to consider the optional-taking function to be the
649-
// the more specialized one since throughout the type system we
650-
// consider T to be a subtype of T?.
651-
SmallVector<Type, 2> optionals1;
652-
paramType1->lookThroughAllOptionalTypes(optionals1);
653-
auto numOptionals1 = optionals1.size();
654-
655-
SmallVector<Type, 2> optionals2;
656-
Type objType2 = paramType2->lookThroughAllOptionalTypes(optionals2);
657-
auto numOptionals2 = optionals2.size();
658-
659-
if (numOptionals1 > numOptionals2 &&
660-
(objType2->is<TypeVariableType>() || objType2->isAny()))
661-
return false;
662-
663637
// Check whether the first parameter is a subtype of the second.
664638
cs.addConstraint(ConstraintKind::Subtype,
665639
paramType1, paramType2, locator);
@@ -708,7 +682,10 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
708682

709683
if (!knownNonSubtype) {
710684
// Solve the system.
711-
if (cs.solveSingle(FreeTypeVariableBinding::Allow))
685+
auto solution = cs.solveSingle(FreeTypeVariableBinding::Allow);
686+
687+
// Ban value-to-optional conversions.
688+
if (solution && solution->getFixedScore().Data[SK_ValueToOptional] == 0)
712689
return true;
713690
}
714691

@@ -775,6 +752,9 @@ SolutionCompareResult ConstraintSystem::compareSolutions(
775752
auto foundRefinement1 = false;
776753
auto foundRefinement2 = false;
777754

755+
bool isStdlibOptionalMPlusOperator1 = false;
756+
bool isStdlibOptionalMPlusOperator2 = false;
757+
778758
auto getWeight = [&](ConstraintLocator *locator) -> unsigned {
779759
if (auto *anchor = locator->getAnchor()) {
780760
auto weight = weights.find(anchor);
@@ -980,6 +960,40 @@ SolutionCompareResult ConstraintSystem::compareSolutions(
980960
foundRefinement2 = decl2InSubprotocol;
981961
}
982962
}
963+
964+
// FIXME: Lousy hack for ?? to prefer the catamorphism (flattening)
965+
// over the mplus (non-flattening) overload if all else is equal.
966+
if (decl1->getBaseName() == "??") {
967+
assert(decl2->getBaseName() == "??");
968+
969+
auto check = [](const ValueDecl *VD) -> bool {
970+
if (!VD->getModuleContext()->isStdlibModule())
971+
return false;
972+
auto fnTy = VD->getInterfaceType()->castTo<AnyFunctionType>();
973+
if (!fnTy->getResult()->getOptionalObjectType())
974+
return false;
975+
976+
// Check that the standard library hasn't added another overload of
977+
// the ?? operator.
978+
auto params = fnTy->getParams();
979+
assert(params.size() == 2);
980+
981+
auto param1 = params[0].getType();
982+
auto param2 = params[1].getType()->castTo<AnyFunctionType>();
983+
984+
assert(param1->getOptionalObjectType());
985+
assert(param2->isAutoClosure());
986+
assert(param2->getResult()->getOptionalObjectType());
987+
988+
(void) param1;
989+
(void) param2;
990+
991+
return true;
992+
};
993+
994+
isStdlibOptionalMPlusOperator1 = check(decl1);
995+
isStdlibOptionalMPlusOperator2 = check(decl2);
996+
}
983997
}
984998

985999
// Compare the type variable bindings.
@@ -1095,6 +1109,14 @@ SolutionCompareResult ConstraintSystem::compareSolutions(
10951109
}
10961110
}
10971111

1112+
// FIXME: All other things being equal, prefer the catamorphism (flattening)
1113+
// overload of ?? over the mplus (non-flattening) overload.
1114+
if (score1 == score2) {
1115+
// This is correct: we want to /disprefer/ the mplus.
1116+
score2 += isStdlibOptionalMPlusOperator1;
1117+
score1 += isStdlibOptionalMPlusOperator2;
1118+
}
1119+
10981120
// FIXME: There are type variables and overloads not common to both solutions
10991121
// that haven't been considered. They make the systems different, but don't
11001122
// affect ranking. We need to handle this.

lib/Sema/CSSimplify.cpp

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -683,9 +683,6 @@ matchCallArguments(ConstraintSystem &cs, ConstraintKind kind,
683683
}
684684
}
685685

686-
if (!argType->isAny())
687-
cs.increaseScore(ScoreKind::SK_EmptyExistentialConversion);
688-
689686
return cs.getTypeMatchSuccess();
690687
}
691688

@@ -1660,16 +1657,6 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
16601657
auto *typeVar = typeVar1 ? typeVar1 : typeVar2;
16611658
auto type = typeVar1 ? type2 : type1;
16621659

1663-
if (type->getOptionalObjectType()) {
1664-
if (auto *typeVarLocator = typeVar->getImpl().getLocator()) {
1665-
auto path = typeVarLocator->getPath();
1666-
if (!path.empty() &&
1667-
path.back().getKind() == ConstraintLocator::Archetype) {
1668-
increaseScore(SK_BindOptionalToArchetype);
1669-
}
1670-
}
1671-
}
1672-
16731660
return matchTypesBindTypeVar(typeVar, type, kind, flags, locator,
16741661
formUnsolvedResult);
16751662
}

lib/Sema/ConstraintSystem.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -456,8 +456,6 @@ enum ScoreKind {
456456
SK_CollectionUpcastConversion,
457457
/// A value-to-optional conversion.
458458
SK_ValueToOptional,
459-
/// Instantiating a function with archetype T as an Optional value.
460-
SK_BindOptionalToArchetype,
461459
/// A conversion to an empty existential type ('Any' or '{}').
462460
SK_EmptyExistentialConversion,
463461
/// A key path application subscript.

test/Constraints/diag_ambiguities.swift

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,11 @@ C(g) // expected-error{{ambiguous use of 'g'}}
2929
func h<T>(_ x: T) -> () {}
3030
C(h) // expected-error{{ambiguous use of 'init'}}
3131

32-
func rdar29691909_callee(_ o: AnyObject?) -> Any? { return o }
33-
func rdar29691909_callee(_ o: AnyObject) -> Any { return o }
32+
func rdar29691909_callee(_ o: AnyObject?) -> Any? { return o } // expected-note {{found this candidate}}
33+
func rdar29691909_callee(_ o: AnyObject) -> Any { return o } // expected-note {{found this candidate}}
3434

3535
func rdar29691909(o: AnyObject) -> Any? {
36-
return rdar29691909_callee(o)
37-
}
38-
39-
func rdar29691909_callee_alt(_ o: AnyObject?) -> Int? { fatalError() }
40-
func rdar29691909_callee_alt(_ o: AnyObject) -> Int { fatalError() }
41-
42-
func rdar29691909_1(o: AnyObject) -> Int {
43-
let r = rdar29691909_callee_alt(o)
44-
return r
36+
return rdar29691909_callee(o) // expected-error{{ambiguous use of 'rdar29691909_callee'}}
4537
}
4638

4739
func rdar29907555(_ value: Any!) -> String {

test/Constraints/overload.swift

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -236,53 +236,3 @@ func autoclosure1<T>(_: [T], _: X) { }
236236
func test_autoclosure1(ia: [Int]) {
237237
autoclosure1(ia, X()) // okay: resolves to the second function
238238
}
239-
240-
// Ensure that we select the (T?, T) -> T overload of '??' in coalesce() below.
241-
func apply<T>(_ fn: () -> T) -> T { return fn() }
242-
func opt(x: String) -> String { return x }
243-
func opt() -> String? { return "hi" }
244-
245-
func coalesce() {
246-
let _ = apply{
247-
_ = opt()
248-
return opt()
249-
} ?? ""
250-
}
251-
252-
// Ensure that we do not select the (T?, T) -> T version of ??, which
253-
// would result in a warning about RHS never being selected.
254-
func rdar19748710_0(_ value: Int?) -> Int? {
255-
return value ?? value
256-
}
257-
258-
// Again, ensure we do not select (T?, T) -> T, despite forcing the result.
259-
func rdar19748710_1(_ value: Int?) -> Int? {
260-
return (value ?? value)!
261-
}
262-
263-
// FIXME: We choose to inject the LHS, which really doesn't seem like
264-
// the reasonable choice here. It seems more predictable and safe to
265-
// either inject the result of ??, or treat this as an error since the
266-
// current behavior will result in .some(nil) being force-unwrapped
267-
// rather than the RHS value. The diagnostic is problematic, too,
268-
// since it claims 'Int?' is a non-optional type.
269-
func rdar19748710_2(_ value: Int?) -> Int? {
270-
return (value ?? value)!! // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'Int?', so the right side is never used}}
271-
}
272-
273-
// Ensure that we select the more closely matching function between
274-
// the two _g overloads.
275-
func giveAny() -> Any { fatalError() }
276-
func giveAnyOptional() -> Any? { fatalError() }
277-
func takeAny(_ a: Any?) -> Any? { fatalError() }
278-
func takeAny(_ a: Any) -> Any { fatalError() }
279-
280-
func testAnyOptional() {
281-
let r = takeAny(giveAnyOptional())
282-
let _ = r!
283-
}
284-
285-
func testAny() {
286-
let r = takeAny(giveAny())
287-
let _ = r! // expected-error {{cannot force unwrap value of non-optional type 'Any'}}
288-
}

test/Constraints/overload_silgen.swift

Lines changed: 0 additions & 10 deletions
This file was deleted.

validation-test/Sema/OverridesAndOverloads.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,8 +328,7 @@ Overloads.test("generic methods are worse than non-generic") {
328328
}
329329

330330
Base().foo(C1()); expectEqual("foo(C1)", which)
331-
Base().foo(Token1()); expectEqual("foo(T)", which)
332-
Base().foo(Token1() as Any); expectEqual("foo(Any)", which)
331+
Base().foo(Token1()); expectEqual("foo(Any)", which)
333332

334333
Base().bar(C1()); expectEqual("bar(C1)", which)
335334
Base().bar(Token1()); expectEqual("bar(T)", which)

0 commit comments

Comments
 (0)