Skip to content

Commit f7191b3

Browse files
committed
[CS] Add contextual Bool type to switch-case where clause
Seems this was accidentally omitted, which would crash in CSApply for any non-Bool-convertible type.
1 parent eac3fb4 commit f7191b3

File tree

4 files changed

+38
-16
lines changed

4 files changed

+38
-16
lines changed

lib/Sema/CSApply.cpp

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9224,20 +9224,13 @@ ExprWalker::rewriteTarget(SolutionApplicationTarget target) {
92249224
}
92259225

92269226
// If there is a guard expression, coerce that.
9227-
if (auto guardExpr = info.guardExpr) {
9228-
guardExpr = guardExpr->walk(*this);
9229-
if (!guardExpr)
9230-
return None;
9231-
9232-
// FIXME: Feels like we could leverage existing code more.
9233-
Type boolType = cs.getASTContext().getBoolType();
9234-
guardExpr = solution.coerceToType(
9235-
guardExpr, boolType, cs.getConstraintLocator(info.guardExpr));
9236-
if (!guardExpr)
9227+
if (auto *guardExpr = info.guardExpr) {
9228+
auto target = *cs.getSolutionApplicationTarget(guardExpr);
9229+
auto resultTarget = rewriteTarget(target);
9230+
if (!resultTarget)
92379231
return None;
92389232

9239-
(*caseLabelItem)->setGuardExpr(guardExpr);
9240-
solution.setExprTypes(guardExpr);
9233+
(*caseLabelItem)->setGuardExpr(resultTarget->getAsExpr());
92419234
}
92429235

92439236
return target;

lib/Sema/CSGen.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4768,9 +4768,15 @@ bool ConstraintSystem::generateConstraints(
47684768
// Generate constraints for the guard expression, if there is one.
47694769
Expr *guardExpr = caseLabelItem.getGuardExpr();
47704770
if (guardExpr) {
4771-
guardExpr = generateConstraints(guardExpr, dc);
4772-
if (!guardExpr)
4771+
auto &ctx = dc->getASTContext();
4772+
SolutionApplicationTarget guardTarget(
4773+
guardExpr, dc, CTP_Condition, ctx.getBoolType(), /*discarded*/ false);
4774+
4775+
if (generateConstraints(guardTarget))
47734776
return true;
4777+
4778+
guardExpr = guardTarget.getAsExpr();
4779+
setSolutionApplicationTarget(guardExpr, guardTarget);
47744780
}
47754781

47764782
// Save this info.

lib/Sema/CSSyntacticElement.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,9 @@ class SyntacticElementConstraintGenerator
529529
void visitCaseItem(CaseLabelItem *caseItem, ContextualTypeInfo contextInfo) {
530530
assert(contextInfo.purpose == CTP_CaseStmt);
531531

532+
auto *DC = context.getAsDeclContext();
533+
auto &ctx = DC->getASTContext();
534+
532535
// Resolve the pattern.
533536
auto *pattern = caseItem->getPattern();
534537
if (!caseItem->isPatternResolved()) {
@@ -554,11 +557,15 @@ class SyntacticElementConstraintGenerator
554557

555558
// Generate constraints for `where` clause (if any).
556559
if (guardExpr) {
557-
guardExpr = cs.generateConstraints(guardExpr, context.getAsDeclContext());
558-
if (!guardExpr) {
560+
SolutionApplicationTarget guardTarget(
561+
guardExpr, DC, CTP_Condition, ctx.getBoolType(), /*discarded*/ false);
562+
563+
if (cs.generateConstraints(guardTarget)) {
559564
hadError = true;
560565
return;
561566
}
567+
guardExpr = guardTarget.getAsExpr();
568+
cs.setSolutionApplicationTarget(guardExpr, guardTarget);
562569
}
563570

564571
// Save information about case item so it could be referenced during

test/Constraints/diagnostics.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,6 +1531,22 @@ func testUnwrapFixIts(x: Int?) throws {
15311531
let _: Int = try! .optionalThrowsMember ?? 0
15321532
}
15331533

1534+
// https://github.com/apple/swift/issues/63746
1535+
func issue63746() {
1536+
let fn1 = {
1537+
switch 0 {
1538+
case 1 where 0: // expected-error {{type 'Int' cannot be used as a boolean; test for '!= 0' instead}}
1539+
()
1540+
}
1541+
}
1542+
let fn2 = {
1543+
switch 0 {
1544+
case 1 where 0: // expected-error {{type 'Int' cannot be used as a boolean; test for '!= 0' instead}}
1545+
break
1546+
}
1547+
}
1548+
}
1549+
15341550
func rdar86611718(list: [Int]) {
15351551
String(list.count())
15361552
// expected-error@-1 {{cannot call value of non-function type 'Int'}}

0 commit comments

Comments
 (0)