Skip to content

Commit 3d9b7f3

Browse files
committed
[Completion] Avoid type-checking parent closure for unattached node
We should have already type-checked a parent closure, and we wouldn't be able to correctly locate the node anyway since it's not actually part of the AST. While here, also walk up to the parent-most closure instead of recursing to avoid unnecessary stack frames for nested closures.
1 parent a5a8cf4 commit 3d9b7f3

File tree

3 files changed

+24
-14
lines changed

3 files changed

+24
-14
lines changed

lib/Sema/TypeCheckStmt.cpp

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2671,18 +2671,28 @@ bool TypeCheckASTNodeAtLocRequest::evaluate(
26712671
// function, we unfortunately need to type-check everything since we need to
26722672
// apply the solution.
26732673
// FIXME: We ought to see if we can do better in that case.
2674-
if (auto *CE = DC->getInnermostClosureForCaptures()) {
2675-
if (CE->getBodyState() == ClosureExpr::BodyState::Parsed) {
2676-
swift::typeCheckASTNodeAtLoc(
2677-
TypeCheckASTNodeAtLocContext::declContext(CE->getParent()),
2678-
CE->getLoc());
2679-
2680-
// If the context itself is a ClosureExpr, we should have type-checked
2681-
// the completion expression now. If it's a nested local declaration,
2682-
// fall through to type-check the AST node now that we've type-checked
2683-
// the surrounding closure.
2684-
if (isa<ClosureExpr>(DC))
2685-
return false;
2674+
//
2675+
// We don't need to do this for unattached nodes since we already would have
2676+
// type-checked the surrounding context, and unattached nodes cannot be
2677+
// typechecked via DeclContext since they aren't actually part of the AST.
2678+
if (!typeCheckCtx.isForUnattachedNode()) {
2679+
if (auto *CE = DC->getInnermostClosureForCaptures()) {
2680+
// Walk up to the parent-most closure.
2681+
while (auto *parent = dyn_cast_or_null<ClosureExpr>(CE->getParent()))
2682+
CE = parent;
2683+
2684+
if (CE->getBodyState() == ClosureExpr::BodyState::Parsed) {
2685+
swift::typeCheckASTNodeAtLoc(
2686+
TypeCheckASTNodeAtLocContext::declContext(CE->getParent()),
2687+
CE->getLoc());
2688+
2689+
// If the context itself is a ClosureExpr, we should have type-checked
2690+
// the completion expression now. If it's a nested local declaration,
2691+
// fall through to type-check the AST node now that we've type-checked
2692+
// the surrounding closure.
2693+
if (isa<ClosureExpr>(DC))
2694+
return false;
2695+
}
26862696
}
26872697
}
26882698

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
// {"kind":"complete","signature":"swift::SourceManager::findBufferContainingLocInternal(swift::SourceLoc) const","signatureAssert":"Assertion failed: (Loc.isValid()), function findBufferContainingLocInternal"}
2-
// RUN: not --crash %target-swift-ide-test -code-completion -batch-code-completion -skip-filecheck -code-completion-diagnostics -source-filename %s
2+
// RUN: %target-swift-ide-test -code-completion -batch-code-completion -skip-filecheck -code-completion-diagnostics -source-filename %s
33
class a { lazy b: () = { answer {}#^^#
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// {"kind":"complete","original":"7bbb1dc5","signature":"swift::TypeRepr::print(swift::ASTPrinter&, swift::PrintOptions const&, swift::optionset::OptionSet<swift::NonRecursivePrintOption, unsigned int>) const","signatureAssert":"Assertion failed: (false && \"Expression wasn't type checked?\"), function getTypeForCompletion"}
2-
// RUN: not --crash %target-swift-ide-test -code-completion -batch-code-completion -skip-filecheck -code-completion-diagnostics -source-filename %s
2+
// RUN: %target-swift-ide-test -code-completion -batch-code-completion -skip-filecheck -code-completion-diagnostics -source-filename %s
33
a ? {
44
init { b { extension
55
}#^^#

0 commit comments

Comments
 (0)