Skip to content

Commit b714e62

Browse files
author
Nathan Hawes
committed
[CodeCompletion][Sema] Don't guess whether a solution will be applied to the AST based on solutions formed for code completion.
When solving for code completion, we ignore missing arguments after the one containing the code completion location, don't favor overloads with a number of params matching the number of arguments in a call and so on. Because of this, we can't assume multiple solutions being formed when solving for code completion means there won't be a single best solution formed when solving for regular type-checking. Resolves rdar://problem/72362275
1 parent 367586d commit b714e62

File tree

2 files changed

+21
-23
lines changed

2 files changed

+21
-23
lines changed

lib/Sema/TypeCheckCodeCompletion.cpp

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -821,20 +821,6 @@ static void filterSolutions(SolutionApplicationTarget &target,
821821
});
822822
}
823823

824-
/// When solving for code completion we still consider solutions with holes as
825-
/// valid. Regular type-checking does not. This is intended to return true only
826-
/// if regular type-checking would consider this solution viable.
827-
static bool isViableForReTypeCheck(const Solution &S) {
828-
if (llvm::any_of(S.Fixes, [&](const ConstraintFix *CF) {
829-
return !CF->isWarning();
830-
}))
831-
return false;
832-
using Binding = std::pair<swift::TypeVariableType *, swift::Type>;
833-
return llvm::none_of(S.typeBindings, [&](const Binding& binding) {
834-
return binding.second->hasHole();
835-
});
836-
}
837-
838824
bool TypeChecker::typeCheckForCodeCompletion(
839825
SolutionApplicationTarget &target, bool needsPrecheck,
840826
llvm::function_ref<void(const Solution &)> callback) {
@@ -931,15 +917,14 @@ bool TypeChecker::typeCheckForCodeCompletion(
931917
}
932918

933919
// At this point we know the code completion expression wasn't checked
934-
// with the closure's surrounding context. If a single valid solution
935-
// was formed we can wait until the body of the closure is type-checked
936-
// and gather completions then.
937-
if (solutions.size() == 1 && isViableForReTypeCheck(solution))
938-
return CompletionResult::NotApplicable;
939-
940-
// Otherwise, it's unlikely the body will ever be type-checked, so fall
941-
// back to manually checking a sub-expression within the closure body.
942-
return CompletionResult::Fallback;
920+
// with the closure's surrounding context, so can defer to regular type-
921+
// checking for the current call to typeCheckExpression. If that succeeds
922+
// we will get a second call to typeCheckExpression for the body of the
923+
// closure later and can gather completions then. If it doesn't we rely
924+
// on the fallback typechecking in the subclasses of
925+
// TypeCheckCompletionCallback that considers in isolation a
926+
// sub-expression of the closure that contains the completion location.
927+
return CompletionResult::NotApplicable;
943928
}
944929

945930
llvm::for_each(solutions, callback);

test/IDE/complete_ambiguous.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=MULTICLOSURE_FUNCBUILDER | %FileCheck %s --check-prefix=POINT_MEMBER
4646
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=MULTICLOSURE_FUNCBUILDER_ERROR | %FileCheck %s --check-prefix=POINT_MEMBER
4747
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=MULTICLOSURE_FUNCBUILDER_FIXME | %FileCheck %s --check-prefix=NORESULTS
48+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=REGULAR_MULTICLOSURE_APPLIED | %FileCheck %s --check-prefix=POINT_MEMBER
49+
4850

4951
struct A {
5052
func doAThings() -> A { return self }
@@ -425,3 +427,14 @@ CreateThings {
425427
}
426428
Thing. // ErrorExpr
427429
}
430+
431+
432+
func takesClosureOfPoint(_: (Point)->()) {}
433+
func overloadedWithDefaulted(_: ()->()) {}
434+
func overloadedWithDefaulted(_: ()->(), _ defaulted: Int = 10) {}
435+
436+
takesClosureOfPoint { p in
437+
overloadedWithDefaulted {
438+
if p.#^REGULAR_MULTICLOSURE_APPLIED^# {}
439+
}
440+
}

0 commit comments

Comments
 (0)