@@ -67,7 +67,11 @@ void ConstraintSystem::increaseScore(ScoreKind kind, unsigned value) {
67
67
case SK_CollectionUpcastConversion:
68
68
log << " collection upcast conversion" ;
69
69
break ;
70
-
70
+
71
+ case SK_BindOptionalToArchetype:
72
+ log << " bind optional to archetype" ;
73
+ break ;
74
+
71
75
case SK_ValueToOptional:
72
76
log << " value to optional" ;
73
77
break ;
@@ -634,6 +638,27 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
634
638
Type paramType1 = getAdjustedParamType (param1);
635
639
Type paramType2 = getAdjustedParamType (param2);
636
640
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 && objType2->is <TypeVariableType>())
660
+ return false ;
661
+
637
662
// Check whether the first parameter is a subtype of the second.
638
663
cs.addConstraint (ConstraintKind::Subtype,
639
664
paramType1, paramType2, locator);
@@ -682,10 +707,7 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
682
707
683
708
if (!knownNonSubtype) {
684
709
// Solve the system.
685
- auto solution = cs.solveSingle (FreeTypeVariableBinding::Allow);
686
-
687
- // Ban value-to-optional conversions.
688
- if (solution && solution->getFixedScore ().Data [SK_ValueToOptional] == 0 )
710
+ if (cs.solveSingle (FreeTypeVariableBinding::Allow))
689
711
return true ;
690
712
}
691
713
@@ -752,9 +774,6 @@ SolutionCompareResult ConstraintSystem::compareSolutions(
752
774
auto foundRefinement1 = false ;
753
775
auto foundRefinement2 = false ;
754
776
755
- bool isStdlibOptionalMPlusOperator1 = false ;
756
- bool isStdlibOptionalMPlusOperator2 = false ;
757
-
758
777
auto getWeight = [&](ConstraintLocator *locator) -> unsigned {
759
778
if (auto *anchor = locator->getAnchor ()) {
760
779
auto weight = weights.find (anchor);
@@ -960,40 +979,6 @@ SolutionCompareResult ConstraintSystem::compareSolutions(
960
979
foundRefinement2 = decl2InSubprotocol;
961
980
}
962
981
}
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
- }
997
982
}
998
983
999
984
// Compare the type variable bindings.
@@ -1109,14 +1094,6 @@ SolutionCompareResult ConstraintSystem::compareSolutions(
1109
1094
}
1110
1095
}
1111
1096
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
-
1120
1097
// FIXME: There are type variables and overloads not common to both solutions
1121
1098
// that haven't been considered. They make the systems different, but don't
1122
1099
// affect ranking. We need to handle this.
0 commit comments