Skip to content

Commit b500054

Browse files
author
Nathan Hawes
committed
[CodeCompletion] Avoid prechecking twice when typeCheckForCodeCompletion is given a non-applicable expression (NFC)
For code completion within a multi-statement closure, typeCheckExpression will be called on the expression containing the closure, and potentially again on the expression within the closure body that contains the completion location. In the first call, the typeCheckForCodeCompletion pre-checks the expression as part of determining whether a second call is going to be made (in which case the first is not applicable for completion purposes) or not. In the case where it's not applicable control is returned to the regular typeCheckExpression code path, which would then precheck the expression again. This just moves the precheck before the call out to typeCheckForCodeCompletion so we avoid prechecking twice unecessarily.
1 parent 9269c5c commit b500054

File tree

3 files changed

+16
-24
lines changed

3 files changed

+16
-24
lines changed

lib/Sema/TypeCheckCodeCompletion.cpp

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -825,7 +825,7 @@ static bool isViableForReTypeCheck(const Solution &S) {
825825
}
826826

827827
bool TypeChecker::typeCheckForCodeCompletion(
828-
SolutionApplicationTarget &target,
828+
SolutionApplicationTarget &target, bool needsPrecheck,
829829
llvm::function_ref<void(const Solution &)> callback) {
830830
auto *DC = target.getDeclContext();
831831
auto &Context = DC->getASTContext();
@@ -867,7 +867,7 @@ bool TypeChecker::typeCheckForCodeCompletion(
867867
// (that are type-checked together with enclosing context)
868868
// and regular closures which are type-checked separately.
869869

870-
{
870+
if (needsPrecheck) {
871871
// First, pre-check the expression, validating any types that occur in the
872872
// expression and folding sequence expressions.
873873
auto failedPreCheck = ConstraintSystem::preCheckExpression(
@@ -953,18 +953,8 @@ bool TypeChecker::typeCheckForCodeCompletion(
953953
fallback->DC, CTP_Unused,
954954
/*contextualType=*/Type(),
955955
/*isDiscarded=*/true);
956-
if (fallback->SeparatePrecheck) {
957-
typeCheckForCodeCompletion(completionTarget, callback);
958-
return true;
959-
}
960-
961-
switch (solveForCodeCompletion(completionTarget)) {
962-
case CompletionResult::Ok:
963-
case CompletionResult::Fallback:
964-
break;
965-
case CompletionResult::NotApplicable:
966-
llvm_unreachable("fallback expr not applicable?");
967-
}
956+
typeCheckForCodeCompletion(completionTarget, fallback->SeparatePrecheck,
957+
callback);
968958
}
969959
return true;
970960
}
@@ -1084,7 +1074,8 @@ void DotExprTypeCheckCompletionCallback::fallbackTypeCheck() {
10841074
/*isDiscared=*/true);
10851075

10861076
TypeChecker::typeCheckForCodeCompletion(
1087-
completionTarget, [&](const Solution &S) { sawSolution(S); });
1077+
completionTarget, /*needsPrecheck*/true,
1078+
[&](const Solution &S) { sawSolution(S); });
10881079
}
10891080

10901081
void DotExprTypeCheckCompletionCallback::

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -326,14 +326,6 @@ TypeChecker::typeCheckExpression(
326326
"typecheck-expr", expr);
327327
PrettyStackTraceExpr stackTrace(Context, "type-checking", expr);
328328

329-
// First let's check whether given expression has a code completion
330-
// token which requires special handling.
331-
if (Context.CompletionCallback &&
332-
typeCheckForCodeCompletion(target, [&](const constraints::Solution &S) {
333-
Context.CompletionCallback->sawSolution(S);
334-
}))
335-
return None;
336-
337329
// First, pre-check the expression, validating any types that occur in the
338330
// expression and folding sequence expressions.
339331
if (ConstraintSystem::preCheckExpression(
@@ -343,6 +335,15 @@ TypeChecker::typeCheckExpression(
343335
}
344336
target.setExpr(expr);
345337

338+
// Check whether given expression has a code completion token which requires
339+
// special handling.
340+
if (Context.CompletionCallback &&
341+
typeCheckForCodeCompletion(target, /*needsPrecheck*/false,
342+
[&](const constraints::Solution &S) {
343+
Context.CompletionCallback->sawSolution(S);
344+
}))
345+
return None;
346+
346347
// Construct a constraint system from this expression.
347348
ConstraintSystemOptions csOptions = ConstraintSystemFlags::AllowFixes;
348349

lib/Sema/TypeChecker.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@ FunctionType *getTypeOfCompletionOperator(DeclContext *DC, Expr *LHS,
591591
/// \returns `true` if target was applicable and it was possible to infer
592592
/// types for code completion, `false` othrewise.
593593
bool typeCheckForCodeCompletion(
594-
constraints::SolutionApplicationTarget &target,
594+
constraints::SolutionApplicationTarget &target, bool needsPrecheck,
595595
llvm::function_ref<void(const constraints::Solution &)> callback);
596596

597597
/// Check the key-path expression.

0 commit comments

Comments
 (0)