[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.
This commit is contained in:
Hamish Knight
2023-02-17 20:58:46 +00:00
parent eac3fb4506
commit f7191b35b6
4 changed files with 38 additions and 16 deletions

View File

@@ -9224,20 +9224,13 @@ ExprWalker::rewriteTarget(SolutionApplicationTarget target) {
}
// If there is a guard expression, coerce that.
if (auto guardExpr = info.guardExpr) {
guardExpr = guardExpr->walk(*this);
if (!guardExpr)
if (auto *guardExpr = info.guardExpr) {
auto target = *cs.getSolutionApplicationTarget(guardExpr);
auto resultTarget = rewriteTarget(target);
if (!resultTarget)
return None;
// FIXME: Feels like we could leverage existing code more.
Type boolType = cs.getASTContext().getBoolType();
guardExpr = solution.coerceToType(
guardExpr, boolType, cs.getConstraintLocator(info.guardExpr));
if (!guardExpr)
return None;
(*caseLabelItem)->setGuardExpr(guardExpr);
solution.setExprTypes(guardExpr);
(*caseLabelItem)->setGuardExpr(resultTarget->getAsExpr());
}
return target;

View File

@@ -4768,9 +4768,15 @@ bool ConstraintSystem::generateConstraints(
// Generate constraints for the guard expression, if there is one.
Expr *guardExpr = caseLabelItem.getGuardExpr();
if (guardExpr) {
guardExpr = generateConstraints(guardExpr, dc);
if (!guardExpr)
auto &ctx = dc->getASTContext();
SolutionApplicationTarget guardTarget(
guardExpr, dc, CTP_Condition, ctx.getBoolType(), /*discarded*/ false);
if (generateConstraints(guardTarget))
return true;
guardExpr = guardTarget.getAsExpr();
setSolutionApplicationTarget(guardExpr, guardTarget);
}
// Save this info.

View File

@@ -529,6 +529,9 @@ public:
void visitCaseItem(CaseLabelItem *caseItem, ContextualTypeInfo contextInfo) {
assert(contextInfo.purpose == CTP_CaseStmt);
auto *DC = context.getAsDeclContext();
auto &ctx = DC->getASTContext();
// Resolve the pattern.
auto *pattern = caseItem->getPattern();
if (!caseItem->isPatternResolved()) {
@@ -554,11 +557,15 @@ public:
// Generate constraints for `where` clause (if any).
if (guardExpr) {
guardExpr = cs.generateConstraints(guardExpr, context.getAsDeclContext());
if (!guardExpr) {
SolutionApplicationTarget guardTarget(
guardExpr, DC, CTP_Condition, ctx.getBoolType(), /*discarded*/ false);
if (cs.generateConstraints(guardTarget)) {
hadError = true;
return;
}
guardExpr = guardTarget.getAsExpr();
cs.setSolutionApplicationTarget(guardExpr, guardTarget);
}
// Save information about case item so it could be referenced during

View File

@@ -1531,6 +1531,22 @@ func testUnwrapFixIts(x: Int?) throws {
let _: Int = try! .optionalThrowsMember ?? 0
}
// https://github.com/apple/swift/issues/63746
func issue63746() {
let fn1 = {
switch 0 {
case 1 where 0: // expected-error {{type 'Int' cannot be used as a boolean; test for '!= 0' instead}}
()
}
}
let fn2 = {
switch 0 {
case 1 where 0: // expected-error {{type 'Int' cannot be used as a boolean; test for '!= 0' instead}}
break
}
}
}
func rdar86611718(list: [Int]) {
String(list.count())
// expected-error@-1 {{cannot call value of non-function type 'Int'}}