Skip to content

Commit cb3f9e6

Browse files
authored
Merge pull request #26754 from AndrewLitteken/SR-11159-SpaceEngine
Sr 11159 space engine
2 parents a0f04ad + d7e977b commit cb3f9e6

File tree

3 files changed

+64
-41
lines changed

3 files changed

+64
-41
lines changed

lib/Sema/TypeCheckSwitchStmt.cpp

Lines changed: 51 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@
2323
#include "swift/Basic/APIntMap.h"
2424
#include <llvm/ADT/APFloat.h>
2525

26-
#include <numeric>
2726
#include <forward_list>
27+
#include <iterator>
28+
#include <numeric>
29+
#include <utility>
2830

2931
using namespace swift;
3032

@@ -115,7 +117,7 @@ namespace {
115117

116118
// In type space, we reuse HEAD to help us print meaningful name, e.g.,
117119
// tuple element name in fixits.
118-
Identifier Head;
120+
DeclName Head;
119121
std::forward_list<Space> Spaces;
120122

121123
size_t computeSize(TypeChecker &TC, const DeclContext *DC,
@@ -170,19 +172,18 @@ namespace {
170172
llvm_unreachable("unhandled kind");
171173
}
172174

173-
explicit Space(Type T, Identifier NameForPrinting)
174-
: Kind(SpaceKind::Type), TypeAndVal(T),
175-
Head(NameForPrinting), Spaces({}){}
175+
explicit Space(Type T, DeclName NameForPrinting)
176+
: Kind(SpaceKind::Type), TypeAndVal(T), Head(NameForPrinting),
177+
Spaces({}) {}
176178
explicit Space(UnknownCase_t, bool allowedButNotRequired)
177179
: Kind(SpaceKind::UnknownCase),
178180
TypeAndVal(Type(), allowedButNotRequired), Head(Identifier()),
179181
Spaces({}) {}
180-
explicit Space(Type T, Identifier H, ArrayRef<Space> SP)
181-
: Kind(SpaceKind::Constructor), TypeAndVal(T), Head(H),
182-
Spaces(SP.begin(), SP.end()) {}
183-
explicit Space(Type T, Identifier H, std::forward_list<Space> SP)
184-
: Kind(SpaceKind::Constructor), TypeAndVal(T), Head(H),
185-
Spaces(SP) {}
182+
explicit Space(Type T, DeclName H, ArrayRef<Space> SP)
183+
: Kind(SpaceKind::Constructor), TypeAndVal(T), Head(H),
184+
Spaces(SP.begin(), SP.end()) {}
185+
explicit Space(Type T, DeclName H, std::forward_list<Space> SP)
186+
: Kind(SpaceKind::Constructor), TypeAndVal(T), Head(H), Spaces(SP) {}
186187
explicit Space(ArrayRef<Space> SP)
187188
: Kind(SpaceKind::Disjunct), TypeAndVal(Type()),
188189
Head(Identifier()), Spaces(SP.begin(), SP.end()) {}
@@ -194,23 +195,23 @@ namespace {
194195
: Kind(SpaceKind::Empty), TypeAndVal(Type()), Head(Identifier()),
195196
Spaces({}) {}
196197

197-
static Space forType(Type T, Identifier NameForPrinting) {
198+
static Space forType(Type T, DeclName NameForPrinting) {
198199
if (T->isStructurallyUninhabited())
199200
return Space();
200201
return Space(T, NameForPrinting);
201202
}
202203
static Space forUnknown(bool allowedButNotRequired) {
203204
return Space(UnknownCase, allowedButNotRequired);
204205
}
205-
static Space forConstructor(Type T, Identifier H, ArrayRef<Space> SP) {
206+
static Space forConstructor(Type T, DeclName H, ArrayRef<Space> SP) {
206207
if (llvm::any_of(SP, std::mem_fn(&Space::isEmpty))) {
207208
// A constructor with an unconstructible parameter can never actually
208209
// be used.
209210
return Space();
210211
}
211212
return Space(T, H, SP);
212213
}
213-
static Space forConstructor(Type T, Identifier H,
214+
static Space forConstructor(Type T, DeclName H,
214215
std::forward_list<Space> SP) {
215216
// No need to filter SP here; this is only used to copy other
216217
// Constructor spaces.
@@ -263,7 +264,7 @@ namespace {
263264
return TypeAndVal.getPointer();
264265
}
265266

266-
Identifier getHead() const {
267+
DeclName getHead() const {
267268
assert(getKind() == SpaceKind::Constructor
268269
&& "Wrong kind of space tried to access head");
269270
return Head;
@@ -272,7 +273,7 @@ namespace {
272273
Identifier getPrintingName() const {
273274
assert(getKind() == SpaceKind::Type
274275
&& "Wrong kind of space tried to access printing name");
275-
return Head;
276+
return Head.getBaseIdentifier();
276277
}
277278

278279
const std::forward_list<Space> &getSpaces() const {
@@ -333,7 +334,7 @@ namespace {
333334
return this->isSubspace(or2Space, TC, DC);
334335
}
335336

336-
return true;
337+
return false;
337338
}
338339
PAIRCASE (SpaceKind::Type, SpaceKind::Disjunct): {
339340
// (_ : Ty1) <= (S1 | ... | Sn) iff (S1 <= S) || ... || (Sn <= S)
@@ -372,10 +373,11 @@ namespace {
372373
PAIRCASE (SpaceKind::Constructor, SpaceKind::Constructor): {
373374
// Optimization: If the constructor heads don't match, subspace is
374375
// impossible.
376+
375377
if (this->Head != other.Head) {
376378
return false;
377379
}
378-
380+
379381
// Special Case: Short-circuit comparisons with payload-less
380382
// constructors.
381383
if (other.getSpaces().empty()) {
@@ -557,7 +559,8 @@ namespace {
557559
PAIRCASE (SpaceKind::Constructor, SpaceKind::Constructor): {
558560
// Optimization: If the heads of the constructors don't match then
559561
// the two are disjoint and their difference is the first space.
560-
if (this->Head != other.Head) {
562+
if (this->Head.getBaseIdentifier() !=
563+
other.Head.getBaseIdentifier()) {
561564
return *this;
562565
}
563566

@@ -696,19 +699,40 @@ namespace {
696699
buffer << (getBoolValue() ? "true" : "false");
697700
break;
698701
case SpaceKind::Constructor: {
699-
if (!Head.empty()) {
702+
if (!Head.getBaseIdentifier().empty()) {
700703
buffer << ".";
701-
buffer << Head.str();
704+
buffer << Head.getBaseIdentifier().str();
702705
}
703706

704707
if (Spaces.empty()) {
705708
return;
706709
}
707710

711+
auto args = Head.getArgumentNames().begin();
712+
auto argEnd = Head.getArgumentNames().end();
713+
714+
// FIXME: Clean up code for performance
708715
buffer << "(";
709-
interleave(Spaces, [&](const Space &param) {
710-
param.show(buffer, forDisplay);
711-
}, [&buffer]() { buffer << ", "; });
716+
llvm::SmallVector<std::pair<Identifier, Space>, 4> labelSpaces;
717+
for (auto param : Spaces) {
718+
if (args != argEnd) {
719+
labelSpaces.push_back(
720+
std::pair<Identifier, Space>(*args, param));
721+
args++;
722+
} else
723+
labelSpaces.push_back(
724+
std::pair<Identifier, Space>(Identifier(), param));
725+
}
726+
interleave(
727+
labelSpaces,
728+
[&](const std::pair<Identifier, Space> &param) {
729+
if (!param.first.empty()) {
730+
buffer << param.first;
731+
buffer << ": ";
732+
}
733+
param.second.show(buffer, forDisplay);
734+
},
735+
[&buffer]() { buffer << ", "; });
712736
buffer << ")";
713737
}
714738
break;
@@ -800,7 +824,7 @@ namespace {
800824
Space::forType(TTy->getUnderlyingType(), Identifier()));
801825
}
802826
}
803-
return Space::forConstructor(tp, eed->getName(),
827+
return Space::forConstructor(tp, eed->getFullName(),
804828
constElemSpaces);
805829
});
806830

@@ -961,7 +985,6 @@ namespace {
961985
return;
962986

963987
Space projection = projectPattern(TC, caseItem.getPattern());
964-
965988
bool isRedundant = !projection.isEmpty() &&
966989
llvm::any_of(spaces, [&](const Space &handled) {
967990
return projection.isSubspace(handled, TC, DC);
@@ -1414,8 +1437,8 @@ namespace {
14141437
auto subSpace = projectPattern(TC, OSP->getSubPattern());
14151438
// To match patterns like (_, _, ...)?, we must rewrite the underlying
14161439
// tuple pattern to .some(_, _, ...) first.
1417-
if (subSpace.getKind() == SpaceKind::Constructor
1418-
&& subSpace.getHead().empty()) {
1440+
if (subSpace.getKind() == SpaceKind::Constructor &&
1441+
subSpace.getHead().getBaseIdentifier().empty()) {
14191442
return Space::forConstructor(item->getType(), name,
14201443
std::move(subSpace.getSpaces()));
14211444
}

test/FixCode/fixits-switch.swift.result

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,19 +55,19 @@ func foo4(_ e : E2) -> Int {
5555
switch e {
5656
case .e2:
5757
return 1
58-
case .e1(let a, let s):
58+
case .e1(a: let a, s: let s):
5959
<#code#>
60-
case .e3(let a):
60+
case .e3(a: let a):
6161
<#code#>
6262
case .e4(_):
6363
<#code#>
6464
case .e5(_, _):
6565
<#code#>
66-
case .e6(let a, _):
66+
case .e6(a: let a, _):
6767
<#code#>
6868
case .e7:
6969
<#code#>
70-
case .e8(let a, _, _):
70+
case .e8(a: let a, _, _):
7171
<#code#>
7272
case .e9(_, _, _):
7373
<#code#>
@@ -93,19 +93,19 @@ func foo6(_ e : E2) -> Int {
9393
switch e {
9494
case let .e1(x, y):
9595
return x + y
96-
case .e2(let a):
96+
case .e2(a: let a):
9797
<#code#>
98-
case .e3(let a):
98+
case .e3(a: let a):
9999
<#code#>
100100
case .e4(_):
101101
<#code#>
102102
case .e5(_, _):
103103
<#code#>
104-
case .e6(let a, _):
104+
case .e6(a: let a, _):
105105
<#code#>
106106
case .e7:
107107
<#code#>
108-
case .e8(let a, _, _):
108+
case .e8(a: let a, _, _):
109109
<#code#>
110110
case .e9(_, _, _):
111111
<#code#>
@@ -117,17 +117,17 @@ func foo7(_ e : E2) -> Int {
117117
case .e2(1): return 0
118118
case .e1: return 0
119119
case .e3: return 0
120-
case .e2(let a):
120+
case .e2(a: let a):
121121
<#code#>
122122
case .e4(_):
123123
<#code#>
124124
case .e5(_, _):
125125
<#code#>
126-
case .e6(let a, _):
126+
case .e6(a: let a, _):
127127
<#code#>
128128
case .e7:
129129
<#code#>
130-
case .e8(let a, _, _):
130+
case .e8(a: let a, _, _):
131131
<#code#>
132132
case .e9(_, _, _):
133133
<#code#>

test/Sema/exhaustive_switch.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,13 +1196,13 @@ enum Z {
11961196

11971197
func sr11160_extra() {
11981198
switch Z.z1(a: 1) { // expected-error {{switch must be exhaustive}}
1199-
// expected-note@-1 {{add missing case: '.z1(let a)'}}
1199+
// expected-note@-1 {{add missing case: '.z1(a: let a)'}}
12001200
case .z2(_, _): ()
12011201
case .z3(_): ()
12021202
}
12031203

12041204
switch Z.z1(a: 1) { // expected-error {{switch must be exhaustive}}
1205-
// expected-note@-1 {{add missing case: '.z2(let a, let b)'}}
1205+
// expected-note@-1 {{add missing case: '.z2(a: let a, b: let b)'}}
12061206
case .z1(_): ()
12071207
case .z3(_): ()
12081208
}

0 commit comments

Comments
 (0)