@@ -69,6 +69,12 @@ static bool isUnboundArrayType(Type type) {
69
69
return false ;
70
70
}
71
71
72
+ static bool isUnboundDictionaryType (Type type) {
73
+ if (auto *UGT = type->getAs <UnboundGenericType>())
74
+ return UGT->getDecl () == type->getASTContext ().getDictionaryDecl ();
75
+ return false ;
76
+ }
77
+
72
78
static bool isSupportedOperator (Constraint *disjunction) {
73
79
if (!isOperatorDisjunction (disjunction))
74
80
return false ;
@@ -749,31 +755,17 @@ static void determineBestChoicesInContext(
749
755
}
750
756
}
751
757
752
- // Match `[...]` to Array<...> and/or `ExpressibleByArrayLiteral`
753
- // conforming types.
754
- if (options.contains (MatchFlag::OnParam) &&
755
- options.contains (MatchFlag::Literal) &&
756
- isUnboundArrayType (candidateType)) {
758
+ if (options.contains (MatchFlag::ExactOnly)) {
757
759
// If an exact match is requested favor only `[...]` to `Array<...>`
758
760
// since everything else is going to increase to score.
759
- if (options.contains (MatchFlag::ExactOnly))
760
- return paramType->isArray () ? 1 : 0 ;
761
-
762
- // Otherwise, check if the other side conforms to
763
- // `ExpressibleByArrayLiteral` protocol (in some way).
764
- // We want an overly optimistic result here to avoid
765
- // under-favoring.
766
- auto &ctx = cs.getASTContext ();
767
- return checkConformanceWithoutContext (
768
- paramType,
769
- ctx.getProtocol (
770
- KnownProtocolKind::ExpressibleByArrayLiteral),
771
- /* allowMissing=*/ true )
772
- ? 0.3
773
- : 0 ;
774
- }
761
+ if (options.contains (MatchFlag::Literal)) {
762
+ if (isUnboundArrayType (candidateType))
763
+ return paramType->isArrayType () ? 0.3 : 0 ;
764
+
765
+ if (isUnboundDictionaryType (candidateType))
766
+ return cs.isDictionaryType (paramType) ? 0.3 : 0 ;
767
+ }
775
768
776
- if (options.contains (MatchFlag::ExactOnly)) {
777
769
if (!areEqual (candidateType, paramType))
778
770
return 0 ;
779
771
return options.contains (MatchFlag::Literal) ? 0.3 : 1 ;
@@ -785,39 +777,73 @@ static void determineBestChoicesInContext(
785
777
}
786
778
787
779
if (options.contains (MatchFlag::Literal)) {
788
- if (candidateType->isInt () || candidateType->isDouble ()) {
789
- if (paramType->hasTypeParameter () ||
790
- paramType->isAnyExistentialType ()) {
791
- // Attempt to match literal default to generic parameter.
792
- // This helps to determine whether there are any generic
793
- // overloads that are a possible match.
794
- auto score =
795
- scoreCandidateMatch (genericSig, choice, candidateType,
796
- paramType, options - MatchFlag::Literal);
797
- if (score == 0 )
798
- return 0 ;
799
-
800
- // Optional injection lowers the score for operators to match
801
- // pre-optimizer behavior.
802
- return choice->isOperator () && paramType->getOptionalObjectType ()
803
- ? 0.2
804
- : 0.3 ;
805
- } else {
806
- // Integer and floating-point literals can match any parameter
807
- // type that conforms to `ExpressibleBy{Integer, Float}Literal`
808
- // protocol. Since this assessment is done in isolation we don't
809
- // lower the score even though this would be a non-default binding
810
- // for a literal.
811
- if (candidateType->isInt () &&
812
- TypeChecker::conformsToKnownProtocol (
813
- paramType, KnownProtocolKind::ExpressibleByIntegerLiteral))
814
- return 0.3 ;
815
-
816
- if (candidateType->isDouble () &&
817
- TypeChecker::conformsToKnownProtocol (
818
- paramType, KnownProtocolKind::ExpressibleByFloatLiteral))
819
- return 0.3 ;
820
- }
780
+ if (paramType->hasTypeParameter () ||
781
+ paramType->isAnyExistentialType ()) {
782
+ // Attempt to match literal default to generic parameter.
783
+ // This helps to determine whether there are any generic
784
+ // overloads that are a possible match.
785
+ auto score =
786
+ scoreCandidateMatch (genericSig, choice, candidateType,
787
+ paramType, options - MatchFlag::Literal);
788
+ if (score == 0 )
789
+ return 0 ;
790
+
791
+ // Optional injection lowers the score for operators to match
792
+ // pre-optimizer behavior.
793
+ return choice->isOperator () && paramType->getOptionalObjectType ()
794
+ ? 0.2
795
+ : 0.3 ;
796
+ } else {
797
+ // Integer and floating-point literals can match any parameter
798
+ // type that conforms to `ExpressibleBy{Integer, Float}Literal`
799
+ // protocol. Since this assessment is done in isolation we don't
800
+ // lower the score even though this would be a non-default binding
801
+ // for a literal.
802
+ if (candidateType->isInt () &&
803
+ TypeChecker::conformsToKnownProtocol (
804
+ paramType, KnownProtocolKind::ExpressibleByIntegerLiteral))
805
+ return 0.3 ;
806
+
807
+ if (candidateType->isDouble () &&
808
+ TypeChecker::conformsToKnownProtocol (
809
+ paramType, KnownProtocolKind::ExpressibleByFloatLiteral))
810
+ return 0.3 ;
811
+
812
+ if (candidateType->isBool () &&
813
+ TypeChecker::conformsToKnownProtocol (
814
+ paramType, KnownProtocolKind::ExpressibleByBooleanLiteral))
815
+ return 0.3 ;
816
+
817
+ if (candidateType->isString () &&
818
+ (TypeChecker::conformsToKnownProtocol (
819
+ paramType, KnownProtocolKind::ExpressibleByStringLiteral) ||
820
+ TypeChecker::conformsToKnownProtocol (
821
+ paramType,
822
+ KnownProtocolKind::ExpressibleByStringInterpolation)))
823
+ return 0.3 ;
824
+
825
+ auto &ctx = cs.getASTContext ();
826
+
827
+ // Check if the other side conforms to `ExpressibleByArrayLiteral`
828
+ // protocol (in some way). We want an overly optimistic result
829
+ // here to avoid under-favoring.
830
+ if (candidateType->isArray () &&
831
+ checkConformanceWithoutContext (
832
+ paramType,
833
+ ctx.getProtocol (KnownProtocolKind::ExpressibleByArrayLiteral),
834
+ /* allowMissing=*/ true ))
835
+ return 0.3 ;
836
+
837
+ // Check if the other side conforms to
838
+ // `ExpressibleByDictionaryLiteral` protocol (in some way).
839
+ // We want an overly optimistic result here to avoid under-favoring.
840
+ if (candidateType->isDictionary () &&
841
+ checkConformanceWithoutContext (
842
+ paramType,
843
+ ctx.getProtocol (
844
+ KnownProtocolKind::ExpressibleByDictionaryLiteral),
845
+ /* allowMissing=*/ true ))
846
+ return 0.3 ;
821
847
}
822
848
823
849
return 0 ;
@@ -896,6 +922,7 @@ static void determineBestChoicesInContext(
896
922
// dependent member type (i.e. `Self.T`), let's check conformances
897
923
// only and lower the score.
898
924
if (candidateType->hasTypeVariable () ||
925
+ candidateType->hasUnboundGenericType () ||
899
926
paramType->is <DependentMemberType>()) {
900
927
return checkProtocolRequirementsOnly ();
901
928
}
0 commit comments