Skip to content

Commit 963889d

Browse files
authored
Merge pull request #79420 from hamishknight/more-context
[CS] Ensure DeclContext is switched for if/switch expressions
2 parents f778170 + fd5346f commit 963889d

File tree

3 files changed

+71
-5
lines changed

3 files changed

+71
-5
lines changed

lib/Sema/CSStep.h

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,27 @@ class DisjunctionStep final : public BindingStep<DisjunctionChoiceProducer> {
802802
}
803803
};
804804

805+
/// Retrieves the DeclContext that a conjunction should be solved within.
806+
static DeclContext *getDeclContextForConjunction(ConstraintLocator *loc) {
807+
// Closures introduce a new DeclContext that needs switching into.
808+
auto anchor = loc->getAnchor();
809+
if (loc->directlyAt<ClosureExpr>())
810+
return castToExpr<ClosureExpr>(anchor);
811+
812+
// SingleValueStmtExprs need to switch to their enclosing context. This
813+
// is unfortunately necessary since they can be present in single-expression
814+
// closures, which don't have their DeclContext established since they're
815+
// solved together with the rest of the system.
816+
if (loc->isForSingleValueStmtConjunction())
817+
return castToExpr<SingleValueStmtExpr>(anchor)->getDeclContext();
818+
819+
// Do the same for TapExprs.
820+
if (loc->directlyAt<TapExpr>())
821+
return castToExpr<TapExpr>(anchor)->getVar()->getDeclContext();
822+
823+
return nullptr;
824+
}
825+
805826
class ConjunctionStep : public BindingStep<ConjunctionElementProducer> {
806827
/// Snapshot of the constraint system before conjunction.
807828
class SolverSnapshot {
@@ -826,11 +847,9 @@ class ConjunctionStep : public BindingStep<ConjunctionElementProducer> {
826847
: CS(cs), Conjunction(conjunction),
827848
TypeVars(std::move(cs.TypeVariables)) {
828849
auto *locator = Conjunction->getLocator();
829-
// If this conjunction represents a closure, we need to
830-
// switch declaration context over to it.
831-
if (locator->directlyAt<ClosureExpr>()) {
832-
DC.emplace(CS.DC, castToExpr<ClosureExpr>(locator->getAnchor()));
833-
}
850+
// If we need to switch into a new DeclContext for the conjunction, do so.
851+
if (auto *newDC = getDeclContextForConjunction(locator))
852+
DC.emplace(CS.DC, newDC);
834853

835854
auto &CG = CS.getConstraintGraph();
836855
// Remove all of the current inactive constraints.

test/Constraints/if_expr.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,3 +706,25 @@ func testInvalidOptionalChainingInIfContext() {
706706
let v63796 = 1
707707
if v63796? {} // expected-error{{cannot use optional chaining on non-optional value of type 'Int'}}
708708
}
709+
710+
// https://github.com/swiftlang/swift/issues/79395
711+
_ = {
712+
if .random() {
713+
struct S: Error {}
714+
throw S()
715+
} else {
716+
1
717+
}
718+
}
719+
_ = {
720+
if .random() {
721+
if .random() {
722+
struct S: Error {}
723+
throw S()
724+
} else {
725+
0
726+
}
727+
} else {
728+
1
729+
}
730+
}

test/Constraints/switch_expr.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -819,3 +819,28 @@ func builderInClosure() {
819819
}
820820
}
821821
}
822+
823+
// https://github.com/swiftlang/swift/issues/79395
824+
_ = {
825+
switch Bool.random() {
826+
case true:
827+
struct S: Error {}
828+
throw S()
829+
case false:
830+
1
831+
}
832+
}
833+
_ = {
834+
switch Bool.random() {
835+
case true:
836+
switch Bool.random() {
837+
case true:
838+
struct S: Error {}
839+
throw S()
840+
case false:
841+
0
842+
}
843+
case false:
844+
1
845+
}
846+
}

0 commit comments

Comments
 (0)