Skip to content

Commit ebad04f

Browse files
committed
[CS] Avoid increasing score for unbound outer type vars for completion
When doing code completion it's entirely expected we'll end up with ambiguities in the body of a closure if we're completing e.g `someOverloadedFn(#^CC^#)`. As such we don't want to penalize the solution for unbound type variables outside of the body since that will prevent us from being able to eagerly prune e.g disfavored overloads in the outer scope. This gives up to a 7% perf win in the stress tester.
1 parent 57ae9de commit ebad04f

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

lib/Sema/CSStep.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -981,7 +981,15 @@ StepResult ConjunctionStep::resume(bool prevFailed) {
981981
++numHoles;
982982
}
983983
}
984-
CS.increaseScore(SK_Hole, Conjunction->getLocator(), numHoles);
984+
// Increase the score for each hole we bind. Avoid doing this for
985+
// completion since it's entirely expected we'll end up with
986+
// ambiguities in the body of a closure if we're completing e.g
987+
// `someOverloadedFn(#^CC^#)`. As such we don't want to penalize the
988+
// solution for unbound type variables outside of the body since
989+
// that will prevent us from being able to eagerly prune e.g
990+
// disfavored overloads in the outer scope.
991+
if (!CS.isForCodeCompletion())
992+
CS.increaseScore(SK_Hole, Conjunction->getLocator(), numHoles);
985993
}
986994

987995
if (CS.worseThanBestSolution())
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %batch-code-completion -debug-constraints 2> %t/constraints.log
3+
// RUN: %FileCheck %s -check-prefix CONSTRAINTS < %t/constraints.log
4+
// RUN: %FileCheck %s -check-prefix CONSTRAINTS-NOT < %t/constraints.log
5+
6+
protocol P1 {}
7+
protocol P2 {}
8+
9+
func foo<T: P1>(_ fn: () -> T) {}
10+
11+
@_disfavoredOverload
12+
func foo<T: P2>(_ fn: () -> T) {}
13+
14+
func bar(_ x: Int) -> Int {}
15+
func bar(_ x: String) -> String {}
16+
17+
// Make sure we eagerly prune the disfavored overload of 'foo', despite the
18+
// ambiguity in the closure body.
19+
foo {
20+
let x = bar(#^COMPLETE^#)
21+
// COMPLETE: Decl[FreeFunction]/CurrModule/Flair[ArgLabels]: ['(']{#(x): Int#}[')'][#Int#]; name=:
22+
// COMPLETE: Decl[FreeFunction]/CurrModule/Flair[ArgLabels]: ['(']{#(x): String#}[')'][#String#]; name=:
23+
24+
return x
25+
}
26+
27+
// CONSTRAINTS: attempting disjunction choice {{.*}}:12:6
28+
// CONSTRAINTS: increasing 'disfavored overload' score
29+
// CONSTRAINTS: solution is worse than the best solution
30+
31+
// CONSTRAINTS-NOT-NOT: increasing 'hole'

0 commit comments

Comments
 (0)