Skip to content

Commit d2eca7e

Browse files
authored
Merge pull request #32650 from rintaro/5.3-ide-completion-forceapply-rdar64079439
[5.3][CodeCompletion] Force apply a viable solution even if ambiguous
2 parents f6ccefe + e6a3215 commit d2eca7e

File tree

4 files changed

+63
-8
lines changed

4 files changed

+63
-8
lines changed

lib/Sema/CSGen.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,18 +1180,24 @@ namespace {
11801180
TVO_CanBindToLValue |
11811181
TVO_CanBindToNoEscape);
11821182

1183-
// Defaults to the type of the base expression if we have a base
1184-
// expression.
1185-
// FIXME: This is just to keep the old behavior where `foo(base.<HERE>)`
1186-
// the argument is type checked to the type of the 'base'. Ideally, code
1187-
// completion expression should be defauled to 'UnresolvedType'
1188-
// regardless of the existence of the base expression. But the constraint
1189-
// system is simply not ready for that.
11901183
if (auto base = E->getBase()) {
1184+
// Defaults to the type of the base expression if we have a base
1185+
// expression.
1186+
// FIXME: This is just to keep the old behavior where `foo(base.<HERE>)`
1187+
// the argument is type checked to the type of the 'base'. Ideally, code
1188+
// completion expression should be defauled to 'UnresolvedType'
1189+
// regardless of the existence of the base expression. But the
1190+
// constraint system is simply not ready for that.
11911191
CS.addConstraint(ConstraintKind::Defaultable, ty, CS.getType(base),
11921192
locator);
1193+
1194+
// Apply a viable solution even if it's ambiguous.
1195+
// FIXME: Remove this. This is a hack for code completion which only
1196+
// see solution applied AST. In future, code completion collects all
1197+
// viable solutions so we need to apply any solution at all.
1198+
CS.Options |= ConstraintSystemFlags::ForceApplyViableSolution;
11931199
}
1194-
1200+
11951201
return ty;
11961202
}
11971203

lib/Sema/CSRanking.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,6 +1335,12 @@ ConstraintSystem::findBestSolution(SmallVectorImpl<Solution> &viable,
13351335
return bestIdx;
13361336
}
13371337

1338+
// FIXME: Terrible hack for code completion. But applying a solution is better
1339+
// than just failing.
1340+
if (Options.contains(ConstraintSystemFlags::ForceApplyViableSolution)) {
1341+
return bestIdx;
1342+
}
1343+
13381344
// If there is not a single "better" than others
13391345
// solution, which probably means that solutions
13401346
// were incomparable, let's just keep the original

lib/Sema/ConstraintSystem.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,6 +1074,11 @@ enum class ConstraintSystemFlags {
10741074
/// If set, constraint system always reuses type of pre-typechecked
10751075
/// expression, and doesn't dig into its subexpressions.
10761076
ReusePrecheckedType = 0x08,
1077+
1078+
/// FIME: Temporary hack.
1079+
/// Force apply a viable solution even if they are ambiguous, so that the
1080+
/// client get a solution.
1081+
ForceApplyViableSolution = 0x10,
10771082
};
10781083

10791084
/// Options that affect the constraint system as a whole.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token COMPLETE1 | %FileCheck %s --check-prefix=CHECK
2+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token COMPLETE1 | %FileCheck %s --check-prefix=CHECK
3+
4+
@_functionBuilder
5+
struct Builder {
6+
static func buildBlock<T1>(_ v1: T1) -> T1 { v1 }
7+
static func buildBlock<T1, T2>(_ v1: T1, _ v2: T2) -> (T1, T2) { v1 }
8+
}
9+
10+
struct MyValue {
11+
var title: String
12+
var id: Int
13+
var value: Float
14+
}
15+
16+
func build<T>(@Builder fn: (MyValue) -> T) {}
17+
18+
struct Container {
19+
init(x: Float) {}
20+
init(x: Int) {}
21+
}
22+
23+
func test(foo: Foo) {
24+
build { val in
25+
Container(x: val.#^COMPLETE1^#)
26+
}
27+
build { val in
28+
1 + 2
29+
Container(x: val.#^COMPLETE2^#)
30+
}
31+
}
32+
33+
// CHECK: Begin completions, 4 items
34+
// CHECK: Keyword[self]/CurrNominal: self[#MyValue#]; name=self
35+
// CHECK: Decl[InstanceVar]/CurrNominal: title[#String#]; name=title
36+
// CHECK: Decl[InstanceVar]/CurrNominal/TypeRelation[Identical]: id[#Int#]; name=id
37+
// CHECK: Decl[InstanceVar]/CurrNominal/TypeRelation[Identical]: value[#Float#]; name=value
38+
// CHECK: End completions

0 commit comments

Comments
 (0)