Skip to content

Commit 818979f

Browse files
authored
Merge pull request #83034 from hamishknight/origami
[Sema] Avoid folding sequences multiple times
2 parents a5f1d3d + 95f1b07 commit 818979f

File tree

3 files changed

+31
-25
lines changed

3 files changed

+31
-25
lines changed

lib/Sema/TypeCheckExpr.cpp

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -288,51 +288,31 @@ static Expr *makeBinOp(ASTContext &Ctx, Expr *Op, Expr *LHS, Expr *RHS,
288288

289289
if (auto *ternary = dyn_cast<TernaryExpr>(Op)) {
290290
// Resolve the ternary expression.
291-
if (!Ctx.CompletionCallback) {
292-
// In code completion we might call preCheckTarget twice - once for
293-
// the first pass and once for the second pass. This is fine since
294-
// preCheckTarget is idempotent.
295-
assert(!ternary->isFolded() && "already folded if expr in sequence?!");
296-
}
291+
ASSERT(!ternary->isFolded() && "already folded if expr in sequence?!");
297292
ternary->setCondExpr(LHS);
298293
ternary->setElseExpr(RHS);
299294
return ternary;
300295
}
301296

302297
if (auto *assign = dyn_cast<AssignExpr>(Op)) {
303298
// Resolve the assignment expression.
304-
if (!Ctx.CompletionCallback) {
305-
// In code completion we might call preCheckTarget twice - once for
306-
// the first pass and once for the second pass. This is fine since
307-
// preCheckTarget is idempotent.
308-
assert(!assign->isFolded() && "already folded assign expr in sequence?!");
309-
}
299+
ASSERT(!assign->isFolded() && "already folded assign expr in sequence?!");
310300
assign->setDest(LHS);
311301
assign->setSrc(RHS);
312302
return assign;
313303
}
314304

315305
if (auto *as = dyn_cast<ExplicitCastExpr>(Op)) {
316306
// Resolve the 'as' or 'is' expression.
317-
if (!Ctx.CompletionCallback) {
318-
// In code completion we might call preCheckTarget twice - once for
319-
// the first pass and once for the second pass. This is fine since
320-
// preCheckTarget is idempotent.
321-
assert(!as->isFolded() && "already folded 'as' expr in sequence?!");
322-
}
307+
ASSERT(!as->isFolded() && "already folded 'as' expr in sequence?!");
323308
assert(RHS == as && "'as' with non-type RHS?!");
324309
as->setSubExpr(LHS);
325310
return as;
326311
}
327312

328313
if (auto *arrow = dyn_cast<ArrowExpr>(Op)) {
329314
// Resolve the '->' expression.
330-
if (!Ctx.CompletionCallback) {
331-
// In code completion we might call preCheckTarget twice - once for
332-
// the first pass and once for the second pass. This is fine since
333-
// preCheckTarget is idempotent.
334-
assert(!arrow->isFolded() && "already folded '->' expr in sequence?!");
335-
}
315+
ASSERT(!arrow->isFolded() && "already folded '->' expr in sequence?!");
336316
arrow->setArgsExpr(LHS);
337317
arrow->setResultExpr(RHS);
338318
return arrow;
@@ -633,6 +613,15 @@ swift::DefaultTypeRequest::evaluate(Evaluator &evaluator,
633613
}
634614

635615
Expr *TypeChecker::foldSequence(SequenceExpr *expr, DeclContext *dc) {
616+
// We may end up running pre-checking multiple times for completion and
617+
// pattern type-checking, just use the folded expression if we've already
618+
// folded the sequence.
619+
// FIXME: We ought to fix these cases to not pre-check multiple times,
620+
// strictly speaking it isn't idempotent (e.g for things like
621+
// `markDirectCallee`).
622+
if (auto *folded = expr->getFoldedExpr())
623+
return folded;
624+
636625
// First resolve any unresolved decl references in operator positions.
637626
for (auto i : indices(expr->getElements())) {
638627
if (i % 2 == 0)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %batch-code-completion
2+
3+
// https://github.com/apple/swift/issues/75845
4+
// Make sure we don't crash.
5+
6+
struct Foo {
7+
init() {
8+
do {
9+
} catch {
10+
#^A^#self#^B^# = #^C^#error#^D^#
11+
}
12+
}
13+
}
14+
// A: Decl[LocalVar]/Local: error[#any Error#]; name=error
15+
// B: Begin completions
16+
// C: Decl[LocalVar]/Local: error[#any Error#]; name=error
17+
// D: Begin completions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
// {"signature":"makeBinOp(swift::ASTContext&, swift::Expr*, swift::Expr*, swift::Expr*, swift::PrecedenceGroupDecl*, bool)"}
2-
// RUN: not --crash %target-swift-frontend -typecheck %s
2+
// RUN: not %target-swift-frontend -typecheck %s
33
let a= switch a { case &b as? b

0 commit comments

Comments
 (0)