Skip to content

Commit 237376b

Browse files
committed
[CodeCompletion] Call into simplifyTypeImpl when simplifying a type for code completion
This makes sure we e.g. resolve dependent member types after we perform type variable to generic parameter substitutions for code completion
1 parent db13ca8 commit 237376b

File tree

5 files changed

+63
-42
lines changed

5 files changed

+63
-42
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1288,6 +1288,24 @@ class Solution {
12881288
/// type variables for their fixed types.
12891289
Type simplifyType(Type type) const;
12901290

1291+
// To aid code completion, we need to attempt to convert type placeholders
1292+
// back into underlying generic parameters if possible, since type
1293+
// of the code completion expression is used as "expected" (or contextual)
1294+
// type so it's helpful to know what requirements it has to filter
1295+
// the list of possible member candidates e.g.
1296+
//
1297+
// \code
1298+
// func test<T: P>(_: [T]) {}
1299+
//
1300+
// test(42.#^MEMBERS^#)
1301+
// \code
1302+
//
1303+
// It's impossible to resolve `T` in this case but code completion
1304+
// expression should still have a type of `[T]` instead of `[<<hole>>]`
1305+
// because it helps to produce correct contextual member list based on
1306+
// a conformance requirement associated with generic parameter `T`.
1307+
Type simplifyTypeForCodeCompletion(Type type) const;
1308+
12911309
/// Coerce the given expression to the given type.
12921310
///
12931311
/// This operation cannot fail.

lib/IDE/ArgumentCompletion.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ void ArgumentTypeCheckCompletionCallback::sawSolutionImpl(const Solution &S) {
115115
}
116116

117117
ValueDecl *FuncD = SelectedOverload->choice.getDeclOrNull();
118-
Type FuncTy = S.simplifyType(SelectedOverload->openedType)->getRValueType();
118+
Type FuncTy = S.simplifyTypeForCodeCompletion(SelectedOverload->openedType);
119119

120120
// For completion as the arg in a call to the implicit [keypath: _] subscript
121121
// the solver can't know what kind of keypath is expected without an actual

lib/IDE/TypeCheckCompletionCallback.cpp

Lines changed: 1 addition & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -51,47 +51,8 @@ Type swift::ide::getTypeForCompletion(const constraints::Solution &S,
5151

5252
Type Result;
5353

54-
// To aid code completion, we need to attempt to convert type placeholders
55-
// back into underlying generic parameters if possible, since type
56-
// of the code completion expression is used as "expected" (or contextual)
57-
// type so it's helpful to know what requirements it has to filter
58-
// the list of possible member candidates e.g.
59-
//
60-
// \code
61-
// func test<T: P>(_: [T]) {}
62-
//
63-
// test(42.#^MEMBERS^#)
64-
// \code
65-
//
66-
// It's impossible to resolve `T` in this case but code completion
67-
// expression should still have a type of `[T]` instead of `[<<hole>>]`
68-
// because it helps to produce correct contextual member list based on
69-
// a conformance requirement associated with generic parameter `T`.
7054
if (isExpr<CodeCompletionExpr>(Node)) {
71-
auto completionTy = S.getType(Node).transform([&](Type type) -> Type {
72-
if (auto *typeVar = type->getAs<TypeVariableType>())
73-
return S.getFixedType(typeVar);
74-
return type;
75-
});
76-
77-
Result = S.simplifyType(completionTy.transform([&](Type type) {
78-
if (auto *placeholder = type->getAs<PlaceholderType>()) {
79-
if (auto *typeVar =
80-
placeholder->getOriginator().dyn_cast<TypeVariableType *>()) {
81-
if (auto *GP = typeVar->getImpl().getGenericParameter()) {
82-
// Code completion depends on generic parameter type being
83-
// represented in terms of `ArchetypeType` since it's easy
84-
// to extract protocol requirements from it.
85-
if (auto *GPD = GP->getDecl())
86-
return GPD->getInnermostDeclContext()->mapTypeIntoContext(GP);
87-
}
88-
}
89-
90-
return Type(CS.getASTContext().TheUnresolvedType);
91-
}
92-
93-
return type;
94-
}));
55+
Result = S.simplifyTypeForCodeCompletion(S.getType(Node));
9556
} else {
9657
Result = S.getResolvedType(Node);
9758
}

lib/Sema/ConstraintSystem.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3496,6 +3496,48 @@ Type Solution::simplifyType(Type type) const {
34963496
return resolvedType;
34973497
}
34983498

3499+
Type Solution::simplifyTypeForCodeCompletion(Type Ty) const {
3500+
auto &CS = getConstraintSystem();
3501+
3502+
// First, instantiate all type variables that we know, but don't replace
3503+
// placeholders by unresolved types.
3504+
Ty = CS.simplifyTypeImpl(Ty, [this](TypeVariableType *typeVar) -> Type {
3505+
return getFixedType(typeVar);
3506+
});
3507+
3508+
// Next, replace all placeholders by type variables. We know that all type
3509+
// variables now in the type originate from placeholders.
3510+
Ty = Ty.transform([](Type type) -> Type {
3511+
if (auto *placeholder = type->getAs<PlaceholderType>()) {
3512+
if (auto *typeVar =
3513+
placeholder->getOriginator().dyn_cast<TypeVariableType *>()) {
3514+
return typeVar;
3515+
}
3516+
}
3517+
3518+
return type;
3519+
});
3520+
3521+
// Replace all type variables (which must come from placeholders) by their
3522+
// generic parameters. Because we call into simplifyTypeImpl
3523+
Ty = CS.simplifyTypeImpl(Ty, [](TypeVariableType *typeVar) -> Type {
3524+
if (auto *GP = typeVar->getImpl().getGenericParameter()) {
3525+
// Code completion depends on generic parameter type being
3526+
// represented in terms of `ArchetypeType` since it's easy
3527+
// to extract protocol requirements from it.
3528+
if (auto *GPD = GP->getDecl()) {
3529+
return GPD->getInnermostDeclContext()->mapTypeIntoContext(GP);
3530+
}
3531+
}
3532+
return typeVar;
3533+
});
3534+
3535+
// Remove any remaining type variables and placeholders
3536+
Ty = simplifyType(Ty);
3537+
3538+
return Ty->getRValueType();
3539+
}
3540+
34993541
size_t Solution::getTotalMemory() const {
35003542
return sizeof(*this) + typeBindings.getMemorySize() +
35013543
overloadChoices.getMemorySize() +

test/IDE/complete_call_arg.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1317,7 +1317,7 @@ func testPlaceholderNoBetterThanArchetype() {
13171317
}
13181318
// PLACEHOLDER_NO_BETTER_THAN_ARCHETYPE_1: Begin completions, 2 items
13191319
// PLACEHOLDER_NO_BETTER_THAN_ARCHETYPE_1-DAG: Pattern/Local/Flair[ArgLabels]: {#footer: String#}[#String#];
1320-
// PLACEHOLDER_NO_BETTER_THAN_ARCHETYPE_1-DAG: Pattern/Local/Flair[ArgLabels]: {#content: () -> _##() -> _#}[#() -> _#];
1320+
// PLACEHOLDER_NO_BETTER_THAN_ARCHETYPE_1-DAG: Pattern/Local/Flair[ArgLabels]: {#content: () -> Content##() -> Content#}[#() -> Content#];
13211321
// PLACEHOLDER_NO_BETTER_THAN_ARCHETYPE_1: End completions
13221322

13231323
Section(header: TectionHeaderView(text: "abc"), #^PLACEHOLDER_NO_BETTER_THAN_ARCHETYPE_2?check=PLACEHOLDER_NO_BETTER_THAN_ARCHETYPE_1^#)

0 commit comments

Comments
 (0)