Skip to content

Commit 7c7e914

Browse files
committed
[Completion] Skip tryOptimizeGenericDisjunction if there's a completion child
Attempting to favor a disjunction choice here can lead to unhelpful results if there's e.g a code completion token argument, since it acts as a placeholder. rdar://127844278
1 parent 09a1f0b commit 7c7e914

File tree

2 files changed

+50
-4
lines changed

2 files changed

+50
-4
lines changed

lib/Sema/CSSolver.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2064,9 +2064,20 @@ Constraint *ConstraintSystem::getUnboundBindOverloadDisjunction(
20642064

20652065
// Performance hack: if there are two generic overloads, and one is
20662066
// more specialized than the other, prefer the more-specialized one.
2067-
static Constraint *tryOptimizeGenericDisjunction(
2068-
DeclContext *dc,
2069-
ArrayRef<Constraint *> constraints) {
2067+
static Constraint *
2068+
tryOptimizeGenericDisjunction(ConstraintSystem &cs, Constraint *disjunction,
2069+
ArrayRef<Constraint *> constraints) {
2070+
auto *dc = cs.DC;
2071+
2072+
// If we're solving for code completion, and have a child completion token,
2073+
// skip this optimization since the completion token being a placeholder can
2074+
// allow us to prefer an unhelpful disjunction choice.
2075+
if (cs.isForCodeCompletion()) {
2076+
auto anchor = disjunction->getLocator()->getAnchor();
2077+
if (cs.containsIDEInspectionTarget(cs.includingParentApply(anchor)))
2078+
return nullptr;
2079+
}
2080+
20702081
llvm::SmallVector<Constraint *, 4> choices;
20712082
for (auto *choice : constraints) {
20722083
if (choices.size() > 2)
@@ -2311,7 +2322,7 @@ void DisjunctionChoiceProducer::partitionDisjunction(
23112322
SmallVectorImpl<unsigned> &PartitionBeginning) {
23122323
// Apply a special-case rule for favoring one generic function over
23132324
// another.
2314-
if (auto favored = tryOptimizeGenericDisjunction(CS.DC, Choices)) {
2325+
if (auto favored = tryOptimizeGenericDisjunction(CS, Disjunction, Choices)) {
23152326
CS.favorConstraint(favored);
23162327
}
23172328

test/IDE/complete_rdar127844278.swift

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// RUN: %batch-code-completion
2+
3+
// rdar://127844278 - Make sure we don't attempt to favor one buildExpression
4+
// call over the other when there's a child code completion.
5+
6+
protocol P {}
7+
protocol Q: P {}
8+
9+
struct S<T>: P {
10+
private init() {}
11+
}
12+
13+
extension S where T == () {
14+
init(a: Void) {}
15+
}
16+
extension S: Q where T == String {
17+
init(b: String) {}
18+
}
19+
20+
@resultBuilder struct Builder {
21+
static func buildExpression<T: P>(_ x: T) -> T { x }
22+
static func buildExpression<T: Q>(_ x: T) -> T { x }
23+
24+
static func buildBlock<T: P>(_ x: T) -> some P { x }
25+
static func buildBlock<T: Q>(_ x: T) -> some P { x }
26+
}
27+
28+
func foo<T>(@Builder _: () -> T) where T: P {}
29+
func foo<T>(@Builder _: () -> T) where T: Q {}
30+
31+
foo {
32+
S(#^COMPLETE^#)
33+
}
34+
// COMPLETE-DAG: Decl[Constructor]/CurrNominal/Flair[ArgLabels]: ['(']{#a: Void#}[')'][#S<()>#]; name=a:
35+
// COMPLETE-DAG: Decl[Constructor]/CurrNominal/Flair[ArgLabels]: ['(']{#b: String#}[')'][#S<String>#]; name=b:

0 commit comments

Comments
 (0)