Skip to content

Commit 185a7d5

Browse files
committed
[CS] Fix locator for if expressions
Currently we don't insert an intermediate `SyntacticElement` locator element for the `if` statement in a SingleValueStmtExpr, which leads to an assertion failure when attempting to simplify a following `TernaryBranch` element. Move the insertion of the `SyntacticElement` locator element for the statement into the SingleValueStmtExpr constraint generation function, and remove it from the statement visitors themselves. For the other cases, the `SyntacticElement` was already being inserted for children of a BraceStmt, so we were actually previously ending up with duplicated elements in a couple of places.
1 parent bc8efec commit 185a7d5

File tree

2 files changed

+29
-13
lines changed

2 files changed

+29
-13
lines changed

lib/Sema/CSSyntacticElement.cpp

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -999,14 +999,11 @@ class SyntacticElementConstraintGenerator
999999
}
10001000

10011001
void visitSwitchStmt(SwitchStmt *switchStmt) {
1002-
auto *switchLoc = cs.getConstraintLocator(
1003-
locator, LocatorPathElt::SyntacticElement(switchStmt));
1004-
10051002
SmallVector<ElementInfo, 4> elements;
10061003
{
10071004
auto *subjectExpr = switchStmt->getSubjectExpr();
10081005
{
1009-
elements.push_back(makeElement(subjectExpr, switchLoc));
1006+
elements.push_back(makeElement(subjectExpr, locator));
10101007

10111008
SyntacticElementTarget target(subjectExpr, context.getAsDeclContext(),
10121009
CTP_Unused, Type(),
@@ -1016,32 +1013,29 @@ class SyntacticElementConstraintGenerator
10161013
}
10171014

10181015
for (auto rawCase : switchStmt->getRawCases())
1019-
elements.push_back(makeElement(rawCase, switchLoc));
1016+
elements.push_back(makeElement(rawCase, locator));
10201017
}
10211018

1022-
createConjunction(elements, switchLoc);
1019+
createConjunction(elements, locator);
10231020
}
10241021

10251022
void visitDoCatchStmt(DoCatchStmt *doStmt) {
1026-
auto *doLoc = cs.getConstraintLocator(
1027-
locator, LocatorPathElt::SyntacticElement(doStmt));
1028-
10291023
SmallVector<ElementInfo, 4> elements;
10301024

10311025
// First, let's record a body of `do` statement. Note we need to add a
10321026
// SyntaticElement locator path element here to avoid treating the inner
10331027
// brace conjunction as being isolated if 'doLoc' is for an isolated
10341028
// conjunction (as is the case with 'do' expressions).
10351029
auto *doBodyLoc = cs.getConstraintLocator(
1036-
doLoc, LocatorPathElt::SyntacticElement(doStmt->getBody()));
1030+
locator, LocatorPathElt::SyntacticElement(doStmt->getBody()));
10371031
elements.push_back(makeElement(doStmt->getBody(), doBodyLoc));
10381032

10391033
// After that has been type-checked, let's switch to
10401034
// individual `catch` statements.
10411035
for (auto *catchStmt : doStmt->getCatches())
1042-
elements.push_back(makeElement(catchStmt, doLoc));
1036+
elements.push_back(makeElement(catchStmt, locator));
10431037

1044-
createConjunction(elements, doLoc);
1038+
createConjunction(elements, locator);
10451039
}
10461040

10471041
void visitCaseStmt(CaseStmt *caseStmt) {
@@ -1556,7 +1550,9 @@ bool ConstraintSystem::generateConstraints(SingleValueStmtExpr *E) {
15561550

15571551
// Generate the conjunction for the branches.
15581552
auto context = SyntacticElementContext::forSingleValueStmtExpr(E, join);
1559-
SyntacticElementConstraintGenerator generator(*this, context, loc);
1553+
auto *stmtLoc =
1554+
getConstraintLocator(loc, LocatorPathElt::SyntacticElement(S));
1555+
SyntacticElementConstraintGenerator generator(*this, context, stmtLoc);
15601556
generator.visit(S);
15611557
return generator.hadError;
15621558
}

test/Constraints/issue-71282.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
// https://github.com/apple/swift/issues/71282
4+
5+
enum E {
6+
case e
7+
}
8+
9+
// Make sure we don't crash.
10+
func foo(_ x: E) {
11+
return if .random() {
12+
()
13+
switch x {
14+
case .e:
15+
()
16+
}
17+
} else { // expected-error {{non-expression branch of 'if' expression may only end with a 'throw'}}
18+
()
19+
}
20+
}

0 commit comments

Comments
 (0)