Skip to content

[IDE] Fix code completion crash after already-typechecked ApplyExpr #26723

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
16 changes: 14 additions & 2 deletions lib/IDE/CodeCompletion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1279,11 +1279,23 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
if (CheckKind == CompletionTypeCheckKind::Normal &&
ParsedExpr->getType() && !ParsedExpr->getType()->is<ErrorType>()) {
auto refDecl = ParsedExpr->getReferencedDecl();
auto exprTy = ParsedExpr->getType();
if (!refDecl) {
if (auto apply = dyn_cast<ApplyExpr>(ParsedExpr))
// FIXME: do this in the not-already-type-checked branch too?
if (auto *apply = dyn_cast<SelfApplyExpr>(ParsedExpr)) {
refDecl = apply->getFn()->getReferencedDecl();
} else if (auto *apply = dyn_cast<ApplyExpr>(ParsedExpr)) {
// If this is an IUO, use the underlying non-optional type instead
auto fnDecl = apply->getFn()->getReferencedDecl();
if (auto FD = fnDecl.getDecl()) {
if (FD->isImplicitlyUnwrappedOptional()) {
if (auto OT = exprTy->getOptionalObjectType())
exprTy = OT;
}
}
}
}
return std::make_pair(ParsedExpr->getType(), refDecl);
return std::make_pair(exprTy, refDecl);
}

ConcreteDeclRef ReferencedDecl = nullptr;
Expand Down
15 changes: 15 additions & 0 deletions test/IDE/complete_value_expr.swift
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_ARRAY_LITERAL_2 | %FileCheck %s -check-prefix=SIMPLE_OBJECT_DOT
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_DICTIONARY_LITERAL_1 | %FileCheck %s -check-prefix=SIMPLE_OBJECT_DOT
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_DICTIONARY_LITERAL_2 | %FileCheck %s -check-prefix=SIMPLE_OBJECT_DOT
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COMPLETE_CALL_RESULT | %FileCheck %s -check-prefix=COMPLETE_CALL_RESULT

// Test code completion of expressions that produce a value.

Expand Down Expand Up @@ -2173,3 +2174,17 @@ func testInCollectionLiteral(value: SimpleStruct) {
value.#^IN_DICTIONARY_LITERAL_2^# : "test"
]
}

// rdar://problem/54047322
struct Resolver<T> {
func fulfill(_ value: T) {}
}
func wrapSuccess<T>(_ onSuccess: @escaping (T) -> Void) -> (T, Bool) -> Void {
fatalError()
}
func testWrapSuccess(promise: Int, seal: Resolver<Void>) {
wrapSuccess(seal.fulfill)#^COMPLETE_CALL_RESULT^#
// COMPLETE_CALL_RESULT: Begin completions
// COMPLETE_CALL_RESULT: Pattern/CurrModule: ({#Void#}, {#Bool#})[#Void#]; name=(Void, Bool)
// COMPLETE_CALL_RESULT: End completions
}