Skip to content

Commit cc14548

Browse files
authored
Merge pull request #79759 from jameesbrown/bool-literal-case
[TypeChecker] Simplify ExprPattern from Bool literals in Bool? switch
2 parents 80050bb + 3649dcb commit cc14548

File tree

2 files changed

+61
-13
lines changed

2 files changed

+61
-13
lines changed

lib/Sema/TypeCheckPattern.cpp

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,24 +1011,39 @@ void repairTupleOrAssociatedValuePatternIfApplicable(
10111011
}
10121012
}
10131013

1014+
/// Try to simplify an `ExprPattern` with a Boolean literal sub-expression
1015+
/// to a `BoolPattern`, recursively unwrapping optional types if necessary.
1016+
static NullablePtr<Pattern> simplifyToBoolPattern(ASTContext &Ctx,
1017+
const ExprPattern *EP,
1018+
const BooleanLiteralExpr *BLE,
1019+
Type patternTy) {
1020+
// If the type is Bool, return a BoolPattern.
1021+
if (patternTy->isBool()) {
1022+
auto *BP = new (Ctx) BoolPattern(BLE->getLoc(), BLE->getValue());
1023+
BP->setType(patternTy);
1024+
return BP;
1025+
}
1026+
// If the pattern type is optional, attempt to simplify the wrapped type.
1027+
// `true` and `false` are treated as if they had `?` appended
1028+
// for each level of optionality.
1029+
if (auto wrappedType = patternTy->getOptionalObjectType()) {
1030+
if (auto P =
1031+
simplifyToBoolPattern(Ctx, EP, BLE, wrappedType).getPtrOrNull()) {
1032+
auto OP = OptionalSomePattern::createImplicit(Ctx, P, P->getEndLoc());
1033+
OP->setType(patternTy);
1034+
return OP;
1035+
}
1036+
}
1037+
return nullptr;
1038+
}
1039+
10141040
NullablePtr<Pattern> TypeChecker::trySimplifyExprPattern(ExprPattern *EP,
10151041
Type patternTy) {
10161042
auto *subExpr = EP->getSubExpr();
10171043
auto &ctx = EP->getDeclContext()->getASTContext();
10181044

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-
}
1029-
10301045
// case nil is equivalent to .none when switching on Optionals.
1031-
if (auto *NLE = dyn_cast<NilLiteralExpr>(EP->getSubExpr())) {
1046+
if (auto *NLE = dyn_cast<NilLiteralExpr>(subExpr)) {
10321047
if (patternTy->getOptionalObjectType()) {
10331048
auto *NoneEnumElement = ctx.getOptionalNoneDecl();
10341049
return EnumElementPattern::createImplicit(
@@ -1045,7 +1060,13 @@ NullablePtr<Pattern> TypeChecker::trySimplifyExprPattern(ExprPattern *EP,
10451060
return nullptr;
10461061
}
10471062
}
1048-
return nullptr;
1063+
1064+
const auto *BLE =
1065+
dyn_cast<BooleanLiteralExpr>(subExpr->getSemanticsProvidingExpr());
1066+
if (!BLE)
1067+
return nullptr;
1068+
1069+
return simplifyToBoolPattern(ctx, EP, BLE, patternTy);
10491070
}
10501071

10511072
/// 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)