Skip to content

Commit 5cac7db

Browse files
authored
Merge pull request #78357 from xedin/too-complex-with-count
[CSOptimizer] Few tweaks to make unapplied disjunction and literal array arguments faster
2 parents f6bf596 + cfd34e5 commit 5cac7db

File tree

3 files changed

+74
-2
lines changed

3 files changed

+74
-2
lines changed

lib/Sema/CSOptimizer.cpp

Lines changed: 43 additions & 2 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"
@@ -61,6 +62,12 @@ static bool isFloatType(Type type) {
6162
return type->isFloat() || type->isDouble() || type->isFloat80();
6263
}
6364

65+
static bool isUnboundArrayType(Type type) {
66+
if (auto *UGT = type->getAs<UnboundGenericType>())
67+
return UGT->getDecl() == type->getASTContext().getArrayDecl();
68+
return false;
69+
}
70+
6471
static bool isSupportedOperator(Constraint *disjunction) {
6572
if (!isOperatorDisjunction(disjunction))
6673
return false;
@@ -298,9 +305,19 @@ static void determineBestChoicesInContext(
298305
case ExprKind::Binary:
299306
case ExprKind::PrefixUnary:
300307
case ExprKind::PostfixUnary:
301-
case ExprKind::UnresolvedDot:
302-
recordResult(disjunction, {/*score=*/1.0});
308+
case ExprKind::UnresolvedDot: {
309+
llvm::SmallVector<Constraint *, 2> favoredChoices;
310+
// Favor choices that don't require application.
311+
llvm::copy_if(
312+
disjunction->getNestedConstraints(),
313+
std::back_inserter(favoredChoices), [](Constraint *choice) {
314+
auto *decl = getOverloadChoiceDecl(choice);
315+
return decl &&
316+
!decl->getInterfaceType()->is<AnyFunctionType>();
317+
});
318+
recordResult(disjunction, {/*score=*/1.0, favoredChoices});
303319
continue;
320+
}
304321

305322
default:
306323
break;
@@ -538,6 +555,30 @@ static void determineBestChoicesInContext(
538555
}
539556
}
540557

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+
541582
if (options.contains(MatchFlag::ExactOnly))
542583
return areEqual(candidateType, paramType) ? 1 : 0;
543584

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %target-typecheck-verify-swift -solver-scope-threshold=11000
2+
// REQUIRES: tools-release,no_asan
3+
// REQUIRES: OS=macosx
4+
5+
func f(n: Int, a: [Int]) {
6+
let _ = [(0 ..< n + a.count).map { Int8($0) }] +
7+
[(0 ..< n + a.count).map { Int8($0) }.reversed()] // Ok
8+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %scale-test --begin 1 --end 15 --step 1 --select NumLeafScopes %s --expected-exit-code 0
2+
// REQUIRES: asserts,no_asan
3+
4+
enum E {
5+
case a
6+
case b
7+
case c(Int32)
8+
}
9+
10+
struct Tester {
11+
mutating func test(arr: [E], cond: Bool = false) {}
12+
mutating func test(arr: E..., cond: Bool = false) {}
13+
}
14+
15+
func test() {
16+
var tester = Tester()
17+
tester.test(arr: [
18+
.c(1), .a,
19+
%for i in range(N):
20+
.c(1 << 4 | 8), .c(0),
21+
%end
22+
.c(1), .b])
23+
}

0 commit comments

Comments
 (0)