Skip to content

Commit 788c9f6

Browse files
authored
Merge pull request #63857 from ahoppen/ahoppen/solution-specific-var-types
[IDE] Set solution-specific variable types as interface types
2 parents 4eb87bd + 614679f commit 788c9f6

File tree

6 files changed

+78
-0
lines changed

6 files changed

+78
-0
lines changed

include/swift/IDE/TypeCheckCompletionCallback.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,43 @@ void getSolutionSpecificVarTypes(
8282
const constraints::Solution &S,
8383
llvm::SmallDenseMap<const VarDecl *, Type> &Result);
8484

85+
/// While this RAII is alive the interface types of the variables defined in
86+
/// \c SolutionSpecificVarTypes are temporarily set to the types in the map.
87+
/// Afterwards, their types are restored.
88+
struct WithSolutionSpecificVarTypesRAII {
89+
llvm::SmallDenseMap<const VarDecl *, Type> RestoreVarTypes;
90+
91+
WithSolutionSpecificVarTypesRAII(
92+
llvm::SmallDenseMap<const VarDecl *, Type> SolutionSpecificVarTypes) {
93+
for (auto SolutionVarType : SolutionSpecificVarTypes) {
94+
if (SolutionVarType.first->hasInterfaceType()) {
95+
RestoreVarTypes[SolutionVarType.first] =
96+
SolutionVarType.first->getInterfaceType();
97+
} else {
98+
RestoreVarTypes[SolutionVarType.first] = Type();
99+
}
100+
if (!SolutionVarType.second->hasArchetype()) {
101+
setInterfaceType(const_cast<VarDecl *>(SolutionVarType.first),
102+
SolutionVarType.second);
103+
} else {
104+
setInterfaceType(const_cast<VarDecl *>(SolutionVarType.first),
105+
ErrorType::get(SolutionVarType.second));
106+
}
107+
}
108+
}
109+
110+
~WithSolutionSpecificVarTypesRAII() {
111+
for (auto Var : RestoreVarTypes) {
112+
setInterfaceType(const_cast<VarDecl *>(Var.first), Var.second);
113+
}
114+
}
115+
116+
private:
117+
/// Sets the interface type of \p VD, similar to \c VD->setInterfaceType
118+
/// but also allows resetting the interface type of \p VD to null.
119+
static void setInterfaceType(VarDecl *VD, Type Ty);
120+
};
121+
85122
/// Whether the given completion expression is the only expression in its
86123
/// containing closure or function body and its value is implicitly returned.
87124
///

lib/IDE/ArgumentCompletion.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,13 @@ void ArgumentTypeCheckCompletionCallback::deliverResults(
350350
}
351351

352352
if (shouldPerformGlobalCompletion) {
353+
llvm::SmallDenseMap<const VarDecl *, Type> SolutionSpecificVarTypes;
354+
if (!Results.empty()) {
355+
SolutionSpecificVarTypes = Results[0].SolutionSpecificVarTypes;
356+
}
357+
358+
WithSolutionSpecificVarTypesRAII VarTypes(SolutionSpecificVarTypes);
359+
353360
for (auto &Result : Results) {
354361
ExpectedTypes.push_back(Result.ExpectedType);
355362
Lookup.setSolutionSpecificVarTypes(Result.SolutionSpecificVarTypes);

lib/IDE/ExprCompletion.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ void ExprTypeCheckCompletionCallback::deliverResults(
105105
Lookup.shouldCheckForDuplicates(Results.size() > 1);
106106

107107
for (auto &Result : Results) {
108+
WithSolutionSpecificVarTypesRAII VarTypes(Result.SolutionSpecificVarTypes);
109+
108110
Lookup.setExpectedTypes(ExpectedTypes,
109111
Result.IsImplicitSingleExpressionReturn);
110112
Lookup.setCanCurrDeclContextHandleAsync(Result.IsInAsyncContext);

lib/IDE/TypeCheckCompletionCallback.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,11 @@ void swift::ide::getSolutionSpecificVarTypes(
136136
}
137137
}
138138

139+
void WithSolutionSpecificVarTypesRAII::setInterfaceType(VarDecl *VD, Type Ty) {
140+
VD->getASTContext().evaluator.cacheOutput(InterfaceTypeRequest{VD},
141+
std::move(Ty));
142+
}
143+
139144
bool swift::ide::isImplicitSingleExpressionReturn(ConstraintSystem &CS,
140145
Expr *CompletionExpr) {
141146
Expr *ParentExpr = CS.getParentExpr(CompletionExpr);

test/IDE/complete_in_closures.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,3 +496,16 @@ func testCompleteInMatchOfAssociatedValueInSwitchCase() {
496496
}
497497

498498
}
499+
500+
func testReferenceToVariableDefinedInClosure() {
501+
func takeClosure(_ x: () -> Void) {}
502+
503+
takeClosure {
504+
let item = "\(1)"
505+
#^VARIABLE_DEFINED_IN_CLOSURE^#
506+
}
507+
// VARIABLE_DEFINED_IN_CLOSURE: Begin completions
508+
// VARIABLE_DEFINED_IN_CLOSURE: Decl[LocalVar]/Local: item[#String#]; name=item
509+
// VARIABLE_DEFINED_IN_CLOSURE: End completions
510+
}
511+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// import SwiftUI
2+
3+
struct ProgressView {
4+
@ViewBuilder var body: Int {
5+
// RUN: %sourcekitd-test -req=typecontextinfo -pos=%(line + 1):35 %s -- %s
6+
grame(width: max(12345678901, 2))
7+
}
8+
}
9+
10+
func grame(width: Int?) -> Int {}
11+
12+
@resultBuilder struct ViewBuilder {
13+
public static func buildBlock(_ content: Int) -> Int
14+
}

0 commit comments

Comments
 (0)