Skip to content

Commit 5c00c9e

Browse files
committed
[CodeComplete] Fix a crash when completing in the signature of a function annotated with result builder
When we are completing inside a function signature, the function doesn’t have a body. We were still running `PreCheckResultBuilderApplication`, which crashed if the body was `nullptr`. rdar://111489024
1 parent c95d3e2 commit 5c00c9e

File tree

2 files changed

+29
-15
lines changed

2 files changed

+29
-15
lines changed

lib/Sema/TypeCheckStmt.cpp

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2560,22 +2560,25 @@ bool TypeCheckASTNodeAtLocRequest::evaluate(
25602560
// Function builder function doesn't support partial type checking.
25612561
if (auto *func = dyn_cast<FuncDecl>(DC)) {
25622562
if (Type builderType = getResultBuilderType(func)) {
2563-
auto optBody = TypeChecker::applyResultBuilderBodyTransform(
2564-
func, builderType,
2565-
/*ClosuresInResultBuilderDontParticipateInInference=*/
2566-
ctx.CompletionCallback == nullptr && ctx.SolutionCallback == nullptr);
2567-
if (optBody && *optBody) {
2568-
// Wire up the function body now.
2569-
func->setBody(*optBody, AbstractFunctionDecl::BodyKind::TypeChecked);
2570-
return false;
2563+
if (func->getBody()) {
2564+
auto optBody = TypeChecker::applyResultBuilderBodyTransform(
2565+
func, builderType,
2566+
/*ClosuresInResultBuilderDontParticipateInInference=*/
2567+
ctx.CompletionCallback == nullptr &&
2568+
ctx.SolutionCallback == nullptr);
2569+
if (optBody && *optBody) {
2570+
// Wire up the function body now.
2571+
func->setBody(*optBody, AbstractFunctionDecl::BodyKind::TypeChecked);
2572+
return false;
2573+
}
2574+
// FIXME: We failed to apply the result builder transform. Fall back to
2575+
// just type checking the node that contains the code completion token.
2576+
// This may be missing some context from the result builder but in
2577+
// practice it often contains sufficient information to provide a decent
2578+
// level of code completion that's better than providing nothing at all.
2579+
// The proper solution would be to only partially type check the result
2580+
// builder so that this fall back would not be necessary.
25712581
}
2572-
// FIXME: We failed to apply the result builder transform. Fall back to
2573-
// just type checking the node that contains the code completion token.
2574-
// This may be missing some context from the result builder but in
2575-
// practice it often contains sufficient information to provide a decent
2576-
// level of code completion that's better than providing nothing at all.
2577-
// The proper solution would be to only partially type check the result
2578-
// builder so that this fall back would not be necessary.
25792582
} else if (func->hasSingleExpressionBody() &&
25802583
func->getResultInterfaceType()->isVoid()) {
25812584
// The function returns void. We don't need an explicit return, no matter
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-ide-test -batch-code-completion -source-filename %s -filecheck %raw-FileCheck -completion-output-dir %t
3+
4+
@resultBuilder struct MyBuilder {
5+
static func buildBlock() -> Int
6+
static func buildBlock<Content>(_ content: Content) -> Content
7+
}
8+
9+
@MyBuilder func test(action: () -> #^COMPLETE^#Void) {}
10+
11+
// COMPLETE: Decl[TypeAlias]/OtherModule[Swift]/IsSystem: Void[#Void#]; name=Void

0 commit comments

Comments
 (0)