Skip to content

Commit 0525818

Browse files
committed
[CSOptimizer] Allow matching candidates with optional types against generic paameter types
For example passing `Int?` to `T` should be considered a match if `T` doesn't have any requirements that block it.
1 parent ac24a8e commit 0525818

File tree

4 files changed

+25
-3
lines changed

4 files changed

+25
-3
lines changed

lib/Sema/CSOptimizer.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -926,7 +926,10 @@ static void determineBestChoicesInContext(
926926
paramType = paramType->lookThroughAllOptionalTypes(paramOptionals);
927927

928928
if (!candidateOptionals.empty() || !paramOptionals.empty()) {
929-
if (paramOptionals.size() >= candidateOptionals.size()) {
929+
// Can match i.e. Int? to Int or T to Int?
930+
if ((paramOptionals.empty() &&
931+
paramType->is<GenericTypeParamType>()) ||
932+
paramOptionals.size() >= candidateOptionals.size()) {
930933
auto score = scoreCandidateMatch(genericSig, choice, candidateType,
931934
paramType, options);
932935
// Injection lowers the score slightly to comply with
@@ -1031,6 +1034,11 @@ static void determineBestChoicesInContext(
10311034
}
10321035
}
10331036

1037+
// If there are no requirements associated with the generic
1038+
// parameter or dependent member type it could match any type.
1039+
if (requirements.empty())
1040+
return 0.7;
1041+
10341042
// If some of the requirements cannot be satisfied, because
10351043
// they reference other generic parameters, for example:
10361044
// `<T, U, where T.Element == U.Element>`, let's perform a

test/Constraints/nil-coalescing-favoring.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,17 @@ do {
2828
let _: Super = x
2929
}
3030
}
31+
32+
// Reduced from vapor project. Favoring _only_ an overload of `??` and takes `T?` as a second parameter would result in an invalid solution.
33+
extension Array where Element == UInt8 {
34+
init?(decodingBase32 str: String) {
35+
guard let decoded = str.utf8.withContiguousStorageIfAvailable({ Array(decodingBase32: $0) }) ?? Array(decodingBase32: Array(str.utf8)) else { // Ok
36+
return nil
37+
}
38+
self = decoded
39+
}
40+
41+
init?<C>(decodingBase32 bytes: C) where C: RandomAccessCollection, C.Element == UInt8, C.Index == Int {
42+
fatalError()
43+
}
44+
}

test/SILOptimizer/infinite_recursion.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ public class U {
282282
}
283283

284284
func == (l: S?, r: S?) -> Bool {
285-
if l == nil && r == nil { return true } // expected-warning {{function call causes an infinite recursion}}
285+
if l == nil && r == nil { return true }
286286
guard let l = l, let r = r else { return false }
287287
return l === r
288288
}

validation-test/Sema/type_checker_perf/fast/nil_coalescing_dictionary_values.swift.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ let x: Int?
55

66
let _ = [
77
%for i in range(0, N):
8-
"%{i}" : x ?? 0,
8+
"${i}" : x ?? 0,
99
%end
1010
]

0 commit comments

Comments
 (0)