Skip to content

Commit 70bdea4

Browse files
authored
Merge pull request swiftlang#18783 from rintaro/parse-stmtcondition-recover-rdar43395202
[Parse] Recover missing initializer in stmt condition
2 parents 47f046e + 6bd888f commit 70bdea4

File tree

2 files changed

+27
-11
lines changed

2 files changed

+27
-11
lines changed

lib/Parse/ParseStmt.cpp

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1474,23 +1474,25 @@ Parser::parseStmtConditionElement(SmallVectorImpl<StmtConditionElement> &result,
14741474
}
14751475

14761476
// Conditional bindings must have an initializer.
1477-
Expr *Init;
1477+
ParserResult<Expr> Init;
14781478
if (Tok.is(tok::equal)) {
14791479
SyntaxParsingContext InitCtxt(SyntaxContext, SyntaxKind::InitializerClause);
14801480
consumeToken();
1481-
ParserResult<Expr> InitExpr =
1482-
parseExprBasic(diag::expected_expr_conditional_var);
1483-
Init = InitExpr.getPtrOrNull();
1484-
if (InitExpr.hasCodeCompletion())
1485-
Status.setHasCodeCompletion();
1481+
Init = parseExprBasic(diag::expected_expr_conditional_var);
14861482
} else {
1487-
// Although we require an initializer, recover by parsing as if it were
1488-
// merely omitted.
14891483
diagnose(Tok, diag::conditional_var_initializer_required);
1490-
Init = new (Context) ErrorExpr(ThePattern.get()->getEndLoc());
14911484
}
1492-
1493-
result.push_back({IntroducerLoc, ThePattern.get(), Init});
1485+
1486+
if (Init.hasCodeCompletion())
1487+
Status.setHasCodeCompletion();
1488+
1489+
if (Init.isNull()) {
1490+
// Recover by creating ErrorExpr.
1491+
Init = makeParserResult(new (Context)
1492+
ErrorExpr(ThePattern.get()->getEndLoc()));
1493+
}
1494+
1495+
result.push_back({IntroducerLoc, ThePattern.get(), Init.get()});
14941496

14951497
// Add variable bindings from the pattern to our current scope and mark
14961498
// them as being having a non-pattern-binding initializer.

test/IDE/complete_stmt_controlling_expr.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,13 @@
110110
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IF_LET_BIND_1 | %FileCheck %s -check-prefix=FOOSTRUCT_DOT_BOOL
111111
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IF_LET_BIND_2 | %FileCheck %s -check-prefix=FOOSTRUCT_DOT_BOOL
112112
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IF_LET_BIND_3 | %FileCheck %s -check-prefix=FOOSTRUCT_DOT
113+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IF_LET_BIND_4 | %FileCheck %s -check-prefix=FOOSTRUCT_NODOT
113114
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GUARD_LET_BIND_1 | %FileCheck %s -check-prefix=FOOSTRUCT_DOT_BOOL
114115
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GUARD_LET_BIND_2 | %FileCheck %s -check-prefix=FOOSTRUCT_DOT_BOOL
115116
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GUARD_LET_BIND_3 | %FileCheck %s -check-prefix=FOOSTRUCT_DOT_BOOL
116117
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GUARD_LET_BIND_4 | %FileCheck %s -check-prefix=FOOSTRUCT_DOT_BOOL
117118
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GUARD_LET_BIND_5 | %FileCheck %s -check-prefix=FOOSTRUCT_DOT
119+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GUARD_LET_BIND_6 | %FileCheck %s -check-prefix=FOOSTRUCT_NODOT
118120

119121

120122
struct FooStruct {
@@ -582,6 +584,9 @@ func testIfLetBinding2(x: FooStruct?) {
582584
func testIfLetBinding3(x: FooStruct?) {
583585
if let y = x, let z = y.#^IF_LET_BIND_3^# {}
584586
}
587+
func testIfLetBinding3(x: FooStruct?) {
588+
if let y = x, let z = y#^IF_LET_BIND_4^# {}
589+
}
585590
func testGuardLetBinding1(x: FooStruct?) {
586591
guard let y = x, y.#^GUARD_LET_BIND_1^# else {}
587592
}
@@ -597,6 +602,9 @@ func testGuardLetBinding4(x: FooStruct?) {
597602
func testGuardLetBinding5(x: FooStruct?) {
598603
guard let y = x, let z = y.#^GUARD_LET_BIND_5^# else {}
599604
}
605+
func testGuardLetBinding5(x: FooStruct?) {
606+
guard let y = x, z = y#^GUARD_LET_BIND_6^# else {}
607+
}
600608

601609
// FOOSTRUCT_DOT: Begin completions
602610
// FOOSTRUCT_DOT-DAG: Decl[InstanceVar]/CurrNominal: instanceVar[#Int#];
@@ -609,3 +617,9 @@ func testGuardLetBinding5(x: FooStruct?) {
609617
// FOOSTRUCT_DOT_BOOL-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Identical]: boolGen()[#Bool#];
610618
// FOOSTRUCT_DOT_BOOL-DAG: Decl[InstanceMethod]/CurrNominal: intGen()[#Int#];
611619
// FOOSTRUCT_DOT_BOOL: End completions
620+
621+
// FOOSTRUCT_NODOT: Begin completions
622+
// FOOSTRUCT_NODOT-DAG: Decl[InstanceVar]/CurrNominal: .instanceVar[#Int#];
623+
// FOOSTRUCT_NODOT-DAG: Decl[InstanceMethod]/CurrNominal: .boolGen()[#Bool#];
624+
// FOOSTRUCT_NODOT-DAG: Decl[InstanceMethod]/CurrNominal: .intGen()[#Int#];
625+
// FOOSTRUCT_NODOT: End completions

0 commit comments

Comments
 (0)