Skip to content

Commit 1e18a68

Browse files
committed
[TypeChecker] Bool literals in switch
Bool literals are regarded as expr patterns when switching over Optional<Bool>. Simplify the expr by converting to their optional counterparts.
1 parent 56144a0 commit 1e18a68

File tree

2 files changed

+54
-14
lines changed

2 files changed

+54
-14
lines changed

lib/Sema/TypeCheckPattern.cpp

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,21 +1015,11 @@ NullablePtr<Pattern> TypeChecker::trySimplifyExprPattern(ExprPattern *EP,
10151015
Type patternTy) {
10161016
auto *subExpr = EP->getSubExpr();
10171017
auto &ctx = EP->getDeclContext()->getASTContext();
1018-
1019-
if (patternTy->isBool()) {
1020-
// The type is Bool.
1021-
// Check if the pattern is a Bool literal
1022-
auto *semanticSubExpr = subExpr->getSemanticsProvidingExpr();
1023-
if (auto *BLE = dyn_cast<BooleanLiteralExpr>(semanticSubExpr)) {
1024-
auto *BP = new (ctx) BoolPattern(BLE->getLoc(), BLE->getValue());
1025-
BP->setType(patternTy);
1026-
return BP;
1027-
}
1028-
}
1018+
const auto wrappedType = patternTy->getOptionalObjectType();
10291019

10301020
// case nil is equivalent to .none when switching on Optionals.
1031-
if (auto *NLE = dyn_cast<NilLiteralExpr>(EP->getSubExpr())) {
1032-
if (patternTy->getOptionalObjectType()) {
1021+
if (auto *NLE = dyn_cast<NilLiteralExpr>(subExpr)) {
1022+
if (wrappedType) {
10331023
auto *NoneEnumElement = ctx.getOptionalNoneDecl();
10341024
return EnumElementPattern::createImplicit(
10351025
patternTy, NLE->getLoc(), DeclNameLoc(NLE->getLoc()), NoneEnumElement,
@@ -1045,7 +1035,30 @@ NullablePtr<Pattern> TypeChecker::trySimplifyExprPattern(ExprPattern *EP,
10451035
return nullptr;
10461036
}
10471037
}
1048-
return nullptr;
1038+
// Try to simplify a Boolean literal expression to a BoolPattern,
1039+
// recursively handling multiple levels of optionality if necessary.
1040+
const auto *BLE = dyn_cast_or_null<BooleanLiteralExpr>(
1041+
subExpr->getSemanticsProvidingExpr());
1042+
if (!BLE)
1043+
return nullptr;
1044+
// If the type is Bool, return a BoolPattern.
1045+
if (patternTy->isBool()) {
1046+
auto *BP = new (ctx) BoolPattern(BLE->getLoc(), BLE->getValue());
1047+
BP->setType(patternTy);
1048+
return BP;
1049+
}
1050+
// If the pattern type is optional, attempt to simplify the wrapped type.
1051+
// `true` and `false` are treated as if they had "?" appended
1052+
// for each level of optionality.
1053+
if (wrappedType) {
1054+
auto simplified = trySimplifyExprPattern(EP, wrappedType);
1055+
if (auto P = simplified.getPtrOrNull()) {
1056+
auto OP = OptionalSomePattern::createImplicit(ctx, P, P->getEndLoc());
1057+
OP->setType(patternTy);
1058+
return OP;
1059+
}
1060+
}
1061+
return nullptr;
10491062
}
10501063

10511064
/// Perform top-down type coercion on the given pattern.

test/Sema/exhaustive_switch.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,3 +1489,30 @@ do {
14891489
case (e: .y, b: true)?: break
14901490
}
14911491
}
1492+
1493+
// https://github.com/swiftlang/swift/issues/61817
1494+
do {
1495+
let a: Bool? = true
1496+
switch a {
1497+
case true: break
1498+
case false: break
1499+
case nil: break
1500+
}
1501+
1502+
let result = {
1503+
switch a {
1504+
case true: true
1505+
case false: true
1506+
case nil: true
1507+
}
1508+
}
1509+
_ = result()
1510+
1511+
let b: Bool?? = true
1512+
switch b {
1513+
case true: break
1514+
case false: break
1515+
case nil: break
1516+
case nil?: break
1517+
}
1518+
}

0 commit comments

Comments
 (0)