Skip to content

Commit 4c0892f

Browse files
committed
[CodeComplete] Strip out try and optional eval expr in operator compilation
foldSequence() may hoist these expression up by mutating their sub expression. When completing operators, this behavior ruins reusability of operand. Since these expression doesn't affect completion, we can strip them out. rdar://problem/42452085
1 parent f2d5f97 commit 4c0892f

File tree

2 files changed

+36
-6
lines changed

2 files changed

+36
-6
lines changed

lib/IDE/CodeCompletion.cpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3440,24 +3440,38 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
34403440
flattenBinaryExpr(assignExpr->getSrc(), sequence);
34413441
assignExpr->setDest(nullptr);
34423442
assignExpr->setSrc(nullptr);
3443+
} else if (auto tryExpr = dyn_cast<AnyTryExpr>(expr)) {
3444+
// Strip out try expression. It doesn't affect completion.
3445+
flattenBinaryExpr(tryExpr->getSubExpr(), sequence);
3446+
} else if (auto optEval = dyn_cast<OptionalEvaluationExpr>(expr)){
3447+
// Strip out optional evaluation expression. It doesn't affect completion.
3448+
flattenBinaryExpr(optEval->getSubExpr(), sequence);
34433449
} else {
34443450
sequence.push_back(expr);
34453451
}
34463452
}
34473453

34483454
void typeCheckLeadingSequence(SmallVectorImpl<Expr *> &sequence) {
3455+
3456+
// Strip out try and optional evaluation expr because foldSequence() mutates
3457+
// hierarchy of these expressions. They don't affect completion anyway.
3458+
for (auto &element : sequence) {
3459+
if (auto *tryExpr = dyn_cast<AnyTryExpr>(element))
3460+
element = tryExpr->getSubExpr();
3461+
if (auto *optEval = dyn_cast<OptionalEvaluationExpr>(element))
3462+
element = optEval->getSubExpr();
3463+
}
3464+
34493465
Expr *expr =
34503466
SequenceExpr::create(CurrDeclContext->getASTContext(), sequence);
34513467
prepareForRetypechecking(expr);
34523468
// Take advantage of the fact the type-checker leaves the types on the AST.
34533469
if (!typeCheckExpression(const_cast<DeclContext *>(CurrDeclContext),
34543470
expr)) {
3455-
if (isa<BinaryExpr>(expr) || isa<AssignExpr>(expr)) {
3456-
// Rebuild the sequence from the type-checked version.
3457-
sequence.clear();
3458-
flattenBinaryExpr(expr, sequence);
3459-
return;
3460-
}
3471+
// Rebuild the sequence from the type-checked version.
3472+
sequence.clear();
3473+
flattenBinaryExpr(expr, sequence);
3474+
return;
34613475
}
34623476

34633477
// Fall back to just using the immediate LHS.

test/IDE/complete_crashes.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,3 +313,19 @@ func test_40956846(
313313
// RDAR_40956846-DAG: Decl[LocalVar]/Local: arg_40956846_3[#(() -> Int)!#]; name=arg_40956846_3
314314
// RDAR_40956846-DAG: Decl[LocalVar]/Local: arg_40956846_4[#inout ((Int) -> Int)!#]; name=arg_40956846_4
315315
// RDAR_40956846: End completions
316+
317+
// rdar://problem/42452085
318+
// RUN: %target-swift-ide-test -code-completion -code-completion-token=RDAR_42452085_1 -source-filename=%s | %FileCheck %s -check-prefix=RDAR_42452085
319+
// RUN: %target-swift-ide-test -code-completion -code-completion-token=RDAR_42452085_2 -source-filename=%s | %FileCheck %s -check-prefix=RDAR_42452085
320+
// RUN: %target-swift-ide-test -code-completion -code-completion-token=RDAR_42452085_3 -source-filename=%s | %FileCheck %s -check-prefix=RDAR_42452085
321+
class cls_42452085 {
322+
var value: Any
323+
func canThrow() throws -> Int { return 1 }
324+
}
325+
func test_42452085(any: Any, obj: cls_42452085?) throws {
326+
var object: Any? = nil
327+
object = (any as? String) #^RDAR_42452085_1^#
328+
obj?.value = any #^RDAR_42452085_2^#
329+
_ = try obj?.canThrow() #^RDAR_42452085_3^#
330+
}
331+
// RDAR_42452085: Begin completions

0 commit comments

Comments
 (0)