Skip to content

Commit d5256ef

Browse files
authored
Merge pull request #16202 from CodaFi/coercive-compliance
[SR-7554][4.2] Re-project cast subpatterns
2 parents afbfae4 + fd2bb47 commit d5256ef

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
@@ -327,6 +327,7 @@ func switcheroo(a: XX, b: XX) -> Int {
327327
enum PatternCasts {
328328
case one(Any)
329329
case two
330+
case three(String)
330331
}
331332

332333
func checkPatternCasts() {
@@ -336,13 +337,22 @@ func checkPatternCasts() {
336337
case .one(let s as String): print(s)
337338
case .one: break
338339
case .two: break
340+
case .three: break
339341
}
340342

341343
// But should warn here.
342344
switch x {
343345
case .one(_): print(s)
344346
case .one: break // expected-warning {{case is already handled by previous patterns; consider removing it}}
345347
case .two: break
348+
case .three: break
349+
}
350+
351+
// And not here
352+
switch x {
353+
case .one: break
354+
case .two: break
355+
case .three(let s as String?): print(s as Any)
346356
}
347357
}
348358

0 commit comments

Comments
 (0)