Skip to content

Commit 8a304f8

Browse files
committed
[CSOptimizer] Extend candidate/parameter matching to support array literals
Match `[...]` to Array<...> and/or `ExpressibleByArrayLiteral` conforming types. This is very helpful for expressions like: `[...] + [...]`.
1 parent 0737542 commit 8a304f8

File tree

2 files changed

+27
-1
lines changed

2 files changed

+27
-1
lines changed

lib/Sema/CSOptimizer.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
//===----------------------------------------------------------------------===//
1616

1717
#include "TypeChecker.h"
18+
#include "swift/AST/ConformanceLookup.h"
1819
#include "swift/AST/ExistentialLayout.h"
1920
#include "swift/AST/GenericSignature.h"
2021
#include "swift/Basic/OptionSet.h"
@@ -554,6 +555,30 @@ static void determineBestChoicesInContext(
554555
}
555556
}
556557

558+
// Match `[...]` to Array<...> and/or `ExpressibleByArrayLiteral`
559+
// conforming types.
560+
if (options.contains(MatchFlag::OnParam) &&
561+
options.contains(MatchFlag::Literal) &&
562+
isUnboundArrayType(candidateType)) {
563+
// If an exact match is requested favor only `[...]` to `Array<...>`
564+
// since everything else is going to increase to score.
565+
if (options.contains(MatchFlag::ExactOnly))
566+
return paramType->isArrayType() ? 1 : 0;
567+
568+
// Otherwise, check if the other side conforms to
569+
// `ExpressibleByArrayLiteral` protocol (in some way).
570+
// We want an overly optimistic result here to avoid
571+
// under-favoring.
572+
auto &ctx = cs.getASTContext();
573+
return checkConformanceWithoutContext(
574+
paramType,
575+
ctx.getProtocol(
576+
KnownProtocolKind::ExpressibleByArrayLiteral),
577+
/*allowMissing=*/true)
578+
? 0.3
579+
: 0;
580+
}
581+
557582
if (options.contains(MatchFlag::ExactOnly))
558583
return areEqual(candidateType, paramType) ? 1 : 0;
559584

validation-test/Sema/type_checker_perf/fast/array_count_property_vs_method.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
// RUN: %target-typecheck-verify-swift -solver-expression-time-threshold=5
1+
// RUN: %target-typecheck-verify-swift -solver-scope-threshold=11000
22
// REQUIRES: tools-release,no_asan
3+
// REQUIRES: OS=macosx
34

45
func f(n: Int, a: [Int]) {
56
let _ = [(0 ..< n + a.count).map { Int8($0) }] +

0 commit comments

Comments
 (0)