Skip to content

Commit 7bcba14

Browse files
author
Nathan Hawes
committed
[IDE] Fix code completion crash after already-typechecked ApplyExprs
This was due to us unconditionally setting the referenced decl to be the decl referenced by the ApplyExpr's function, when we should only do that for SelfApplyExprs. This caused a crash for calls returning a function type due to a mismatch between the resulting type (the function type the applied function returns) vs the referenced decl signature (the signature of the applied function itself). Resolves rdar://problem/53034130.
1 parent 3ce90df commit 7bcba14

File tree

2 files changed

+29
-2
lines changed

2 files changed

+29
-2
lines changed

lib/IDE/CodeCompletion.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,11 +1279,23 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
12791279
if (CheckKind == CompletionTypeCheckKind::Normal &&
12801280
ParsedExpr->getType() && !ParsedExpr->getType()->is<ErrorType>()) {
12811281
auto refDecl = ParsedExpr->getReferencedDecl();
1282+
auto exprTy = ParsedExpr->getType();
12821283
if (!refDecl) {
1283-
if (auto apply = dyn_cast<ApplyExpr>(ParsedExpr))
1284+
// FIXME: do this in the not-already-type-checked branch too?
1285+
if (auto *apply = dyn_cast<SelfApplyExpr>(ParsedExpr)) {
12841286
refDecl = apply->getFn()->getReferencedDecl();
1287+
} else if (auto *apply = dyn_cast<ApplyExpr>(ParsedExpr)) {
1288+
// If this is an IUO, use the underlying non-optional type instead
1289+
auto fnDecl = apply->getFn()->getReferencedDecl();
1290+
if (auto FD = fnDecl.getDecl()) {
1291+
if (FD->isImplicitlyUnwrappedOptional()) {
1292+
if (auto OT = exprTy->getOptionalObjectType())
1293+
exprTy = OT;
1294+
}
1295+
}
1296+
}
12851297
}
1286-
return std::make_pair(ParsedExpr->getType(), refDecl);
1298+
return std::make_pair(exprTy, refDecl);
12871299
}
12881300

12891301
ConcreteDeclRef ReferencedDecl = nullptr;

test/IDE/complete_value_expr.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@
199199
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_ARRAY_LITERAL_2 | %FileCheck %s -check-prefix=SIMPLE_OBJECT_DOT
200200
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_DICTIONARY_LITERAL_1 | %FileCheck %s -check-prefix=SIMPLE_OBJECT_DOT
201201
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_DICTIONARY_LITERAL_2 | %FileCheck %s -check-prefix=SIMPLE_OBJECT_DOT
202+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COMPLETE_CALL_RESULT | %FileCheck %s -check-prefix=COMPLETE_CALL_RESULT
202203

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

@@ -2173,3 +2174,17 @@ func testInCollectionLiteral(value: SimpleStruct) {
21732174
value.#^IN_DICTIONARY_LITERAL_2^# : "test"
21742175
]
21752176
}
2177+
2178+
// rdar://problem/54047322
2179+
struct Resolver<T> {
2180+
func fulfill(_ value: T) {}
2181+
}
2182+
func wrapSuccess<T>(_ onSuccess: @escaping (T) -> Void) -> (T, Bool) -> Void {
2183+
fatalError()
2184+
}
2185+
func testWrapSuccess(promise: Int, seal: Resolver<Void>) {
2186+
wrapSuccess(seal.fulfill)#^COMPLETE_CALL_RESULT^#
2187+
// COMPLETE_CALL_RESULT: Begin completions
2188+
// COMPLETE_CALL_RESULT: Pattern/CurrModule: ({#Void#}, {#Bool#})[#Void#]; name=(Void, Bool)
2189+
// COMPLETE_CALL_RESULT: End completions
2190+
}

0 commit comments

Comments
 (0)