Skip to content

Commit fd2bb47

Browse files
committed
[SR-7554] Re-project cast subpatterns
A corner-case left over from an earlier fix that made exhaustiveness checker aware of irrefutable coercions. If the coercion occured as part of a sub-pattern, that pattern would be projected with the wrong type and would fail the intersection test. Project the pattern with the type of the scrutinee instead.
1 parent 47af334 commit fd2bb47

File tree

2 files changed

+27
-6
lines changed

2 files changed

+27
-6
lines changed

lib/Sema/TypeCheckSwitchStmt.cpp

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1650,13 +1650,24 @@ namespace {
16501650
switch (IP->getCastKind()) {
16511651
case CheckedCastKind::Coercion:
16521652
case CheckedCastKind::BridgingCoercion: {
1653-
auto *subPattern = IP->getSubPattern();
1654-
if (subPattern)
1655-
return projectPattern(TC, subPattern, sawDowngradablePattern);
1653+
if (auto *subPattern = IP->getSubPattern()) {
1654+
// Project the cast target's subpattern.
1655+
Space castSubSpace = projectPattern(TC, subPattern,
1656+
sawDowngradablePattern);
1657+
// If we recieved a type space from a named pattern or a wildcard
1658+
// we have to re-project with the cast's target type to maintain
1659+
// consistency with the scrutinee's type.
1660+
if (castSubSpace.getKind() == SpaceKind::Type) {
1661+
1662+
return Space::forType(IP->getType(),
1663+
castSubSpace.getPrintingName());
1664+
}
1665+
return castSubSpace;
1666+
}
16561667

1657-
// With no subpattern coercions are irrefutable. Project with the original
1658-
// type instead of the cast's target type to maintain consistency with the
1659-
// scrutinee's type.
1668+
// With no subpattern coercions are irrefutable. Project with the
1669+
// original type instead of the cast's target type to maintain
1670+
// consistency with the scrutinee's type.
16601671
return Space::forType(IP->getType(), Identifier());
16611672
}
16621673
case CheckedCastKind::Unresolved:

test/Sema/exhaustive_switch.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ func switcheroo(a: XX, b: XX) -> Int {
314314
enum PatternCasts {
315315
case one(Any)
316316
case two
317+
case three(String)
317318
}
318319

319320
func checkPatternCasts() {
@@ -323,13 +324,22 @@ func checkPatternCasts() {
323324
case .one(let s as String): print(s)
324325
case .one: break
325326
case .two: break
327+
case .three: break
326328
}
327329

328330
// But should warn here.
329331
switch x {
330332
case .one(_): print(s)
331333
case .one: break // expected-warning {{case is already handled by previous patterns; consider removing it}}
332334
case .two: break
335+
case .three: break
336+
}
337+
338+
// And not here
339+
switch x {
340+
case .one: break
341+
case .two: break
342+
case .three(let s as String?): print(s as Any)
333343
}
334344
}
335345

0 commit comments

Comments
 (0)