Skip to content

[IDE] A few minor changes to set LeaveClosureBodiesUnchecked to false in more places #63856

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lib/IDE/CursorInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ namespace {
// MARK: - Utilities

void typeCheckDeclAndParentClosures(ValueDecl *VD) {
if (!VD) {
return;
}
// We need to type check any parent closures because their types are
// encoded in the USR of ParentContexts in the cursor info response.
auto DC = VD->getDeclContext();
Expand Down
17 changes: 0 additions & 17 deletions lib/Sema/TypeCheckCodeCompletion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -633,23 +633,6 @@ bool TypeChecker::typeCheckForCodeCompletion(
if (solutions.empty())
return CompletionResult::Fallback;

// If code completion expression resides inside of multi-statement
// closure body it could either be type-checked together with the context
// or not, it's impossible to say without checking.
if (contextAnalyzer.locatedInMultiStmtClosure()) {
if (!hasTypeForCompletion(solutions.front(), contextAnalyzer)) {
// At this point we know the code completion node wasn't checked with
// the closure's surrounding context, so can defer to regular
// type-checking for the current call to typeCheckExpression. If that
// succeeds we will get a second call to typeCheckExpression for the
// body of the closure later and can gather completions then. If it
// doesn't we rely on the fallback typechecking in the subclasses of
// TypeCheckCompletionCallback that considers in isolation a
// sub-expression of the closure that contains the completion location.
return CompletionResult::NotApplicable;
}
}

// FIXME: instead of filtering, expose the score and viability to clients.
// Remove solutions that skipped over/ignored the code completion point
// or that require fixes and have a score that is worse than the best.
Expand Down
16 changes: 5 additions & 11 deletions lib/Sema/TypeCheckStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2171,7 +2171,7 @@ bool TypeCheckASTNodeAtLocRequest::evaluate(
if (auto Init = PBD->getInit(i)) {
if (!PBD->isInitializerChecked(i)) {
typeCheckPatternBinding(PBD, i,
/*LeaveClosureBodyUnchecked=*/true);
/*LeaveClosureBodyUnchecked=*/false);
// Retrieve the accessor's body to trigger RecontextualizeClosures
// This is important to get the correct USR of variables defined
// in closures initializing lazy variables.
Expand Down Expand Up @@ -2393,8 +2393,6 @@ bool TypeCheckASTNodeAtLocRequest::evaluate(
}
}

bool LeaveBodyUnchecked = !ctx.CompletionCallback;

// The enclosing closure might be a single expression closure or a function
// builder closure. In such cases, the body elements are type checked with
// the closure itself. So we need to try type checking the enclosing closure
Expand All @@ -2418,17 +2416,13 @@ bool TypeCheckASTNodeAtLocRequest::evaluate(
auto ActorIsolation = determineClosureActorIsolation(
CE, __Expr_getType, __AbstractClosureExpr_getActorIsolation);
CE->setActorIsolation(ActorIsolation);
if (!LeaveBodyUnchecked) {
// Type checking the parent closure also type checked this node.
// Nothing to do anymore.
return false;
}
if (CE->getBodyState() != ClosureExpr::BodyState::ReadyForTypeChecking)
return false;
// Type checking the parent closure also type checked this node.
// Nothing to do anymore.
return false;
}
}

TypeChecker::typeCheckASTNode(finder.getRef(), DC, LeaveBodyUnchecked);
TypeChecker::typeCheckASTNode(finder.getRef(), DC, /*LeaveBodyUnchecked=*/false);
return false;
}

Expand Down
2 changes: 1 addition & 1 deletion test/IDE/complete_call_arg.swift
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ func curry<T1, T2, R>(_ f: @escaping (T1, T2) -> R) -> (T1) -> (T2) -> R {
// NESTED_CLOSURE: Begin completions
// FIXME: Should be '/TypeRelation[Invalid]: t2[#T2#]'
// NESTED_CLOSURE: Decl[LocalVar]/Local: t2; name=t2
// NESTED_CLOSURE: Decl[LocalVar]/Local: t1[#T1#]; name=t1
// NESTED_CLOSURE: Decl[LocalVar]/Local: t1; name=t1
}

func trailingClosureLocal(x: Int, fn: (Int) -> Void) {
Expand Down
13 changes: 13 additions & 0 deletions test/SourceKit/CursorInfo/cursor_in_closure.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
struct MyStruct {
var identifier: String
}

func takeClosure(_ x: () -> Void) {}

func test() {
takeClosure {
let foo = MyStruct()
// RUN: %sourcekitd-test -req=cursor -pos=%(line + 1):5 %s -- %s
foo.identifier = "\(item.category)#\(item.name)"
}
}