Skip to content

Commit afd83ba

Browse files
Fix related bug in pattern projection, handling the tuple case correctly.
1 parent 3892c55 commit afd83ba

File tree

2 files changed

+34
-21
lines changed

2 files changed

+34
-21
lines changed

lib/Sema/TypeCheckSwitchStmt.cpp

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,30 @@ namespace {
737737
}
738738
}
739739

740+
/// Use this if you're doing getAs<TupleType> on a Type (and it succeeds)
741+
/// to compute the spaces for it. Handy for disambiguating fields
742+
/// that are tuples from associated values.
743+
///
744+
/// .e((a: X, b: X)) -> ((a: X, b: X))
745+
/// vs .f(a: X, b: X) -> (a: X, b: X)
746+
static void getTupleTypeSpaces(Type &outerType,
747+
TupleType *tty,
748+
SmallVectorImpl<Space> &spaces) {
749+
ArrayRef<TupleTypeElt> ttyElts = tty->getElements();
750+
if (isa<ParenType>(outerType.getPointer())) {
751+
// We had an actual tuple!
752+
SmallVector<Space, 4> innerSpaces;
753+
for (auto &elt: ttyElts)
754+
innerSpaces.push_back(Space::forType(elt.getType(), elt.getName()));
755+
spaces.push_back(
756+
Space::forConstructor(tty, Identifier(), innerSpaces));
757+
} else {
758+
// We're looking at the fields of a constructor here.
759+
for (auto &elt: ttyElts)
760+
spaces.push_back(Space::forType(elt.getType(), elt.getName()));
761+
}
762+
};
763+
740764
// Decompose a type into its component spaces.
741765
static void decompose(TypeChecker &TC, const DeclContext *DC, Type tp,
742766
SmallVectorImpl<Space> &arr) {
@@ -776,20 +800,7 @@ namespace {
776800
SmallVector<Space, 4> constElemSpaces;
777801
if (eedTy) {
778802
if (auto *TTy = eedTy->getAs<TupleType>()) {
779-
if (isa<ParenType>(eedTy.getPointer())) {
780-
// We had an actual tuple!
781-
SmallVector<Space, 4> innerElemSpaces;
782-
for (auto &elt: TTy->getElements())
783-
innerElemSpaces.push_back(
784-
Space::forType(elt.getType(), elt.getName()));
785-
constElemSpaces.push_back(
786-
Space::forConstructor(TTy, Identifier(), innerElemSpaces));
787-
} else {
788-
// We're just looking at fields of a constructor here.
789-
for (auto &elt: TTy->getElements())
790-
constElemSpaces.push_back(
791-
Space::forType(elt.getType(), elt.getName()));
792-
}
803+
Space::getTupleTypeSpaces(eedTy, TTy, constElemSpaces);
793804
} else if (auto *TTy = dyn_cast<ParenType>(eedTy.getPointer())) {
794805
constElemSpaces.push_back(
795806
Space::forType(TTy->getUnderlyingType(), Identifier()));
@@ -1452,14 +1463,11 @@ namespace {
14521463
// FIXME: SE-0155 makes this case unreachable.
14531464
if (SP->getKind() == PatternKind::Named
14541465
|| SP->getKind() == PatternKind::Any) {
1455-
if (auto *TTy = SP->getType()->getAs<TupleType>()) {
1456-
for (auto ty : TTy->getElements()) {
1457-
conArgSpace.push_back(Space::forType(ty.getType(),
1458-
ty.getName()));
1459-
}
1460-
} else {
1466+
Type outerType = SP->getType();
1467+
if (auto *TTy = outerType->getAs<TupleType>())
1468+
Space::getTupleTypeSpaces(outerType, TTy, conArgSpace);
1469+
else
14611470
conArgSpace.push_back(projectPattern(TC, SP));
1462-
}
14631471
} else if (SP->getKind() == PatternKind::Tuple) {
14641472
Space argTupleSpace = projectPattern(TC, SP);
14651473
// Tuples are modeled as if they are enums with a single, nameless

test/Sema/exhaustive_switch.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1177,6 +1177,11 @@ func sr10301_as(_ foo: SR10301<String,(Int,Error)>) {
11771177
}
11781178

11791179
func sr11160() {
1180+
switch Optional<(Int, Int)>((5, 6)) {
1181+
case .some((let a, let b)): print(a, b)
1182+
case nil: print(0)
1183+
}
1184+
11801185
switch Optional<(Int, Int)>((5, 6)) {
11811186
case let b?: print(b)
11821187
case nil: print(0)

0 commit comments

Comments
 (0)