Skip to content

Commit 1b42e55

Browse files
committed
[CSSimplify] NFC: Refactor TupleMatcher to consolidate pack expansion matching
1 parent be6b05b commit 1b42e55

File tree

1 file changed

+43
-82
lines changed

1 file changed

+43
-82
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 43 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -2062,13 +2062,19 @@ class TupleMatcher {
20622062
TupleType *tuple2;
20632063

20642064
public:
2065+
enum class MatchKind : uint8_t {
2066+
Equality,
2067+
Subtype,
2068+
Conversion,
2069+
};
2070+
20652071
SmallVector<MatchedPair, 4> pairs;
20662072
bool hasLabelMismatch = false;
20672073

20682074
TupleMatcher(TupleType *tuple1, TupleType *tuple2)
2069-
: tuple1(tuple1), tuple2(tuple2) {}
2075+
: tuple1(tuple1), tuple2(tuple2) {}
20702076

2071-
bool matchBind() {
2077+
bool match(MatchKind kind, ConstraintLocatorBuilder locator) {
20722078
// FIXME: TuplePackMatcher should completely replace the non-variadic
20732079
// case too eventually.
20742080
if (tuple1->containsPackExpansionType() ||
@@ -2084,42 +2090,32 @@ class TupleMatcher {
20842090
if (tuple1->getNumElements() != tuple2->getNumElements())
20852091
return true;
20862092

2087-
for (unsigned i = 0, n = tuple1->getNumElements(); i != n; ++i) {
2088-
const auto &elt1 = tuple1->getElement(i);
2089-
const auto &elt2 = tuple2->getElement(i);
2093+
switch (kind) {
2094+
case MatchKind::Equality:
2095+
return matchEquality(isInPatternMatchingContext(locator));
20902096

2091-
// If the names don't match, we have a conflict.
2092-
if (elt1.getName() != elt2.getName())
2093-
return true;
2097+
case MatchKind::Subtype:
2098+
return matchSubtype();
20942099

2095-
pairs.emplace_back(elt1.getType(), elt2.getType(), i, i);
2100+
case MatchKind::Conversion:
2101+
return matchConversion();
20962102
}
2097-
2098-
return false;
20992103
}
21002104

2101-
bool matchInPatternMatchingContext() {
2102-
// FIXME: TuplePackMatcher should completely replace the non-variadic
2103-
// case too eventually.
2104-
if (tuple1->containsPackExpansionType() ||
2105-
tuple2->containsPackExpansionType()) {
2106-
TuplePackMatcher matcher(tuple1, tuple2);
2107-
if (matcher.match())
2108-
return true;
2109-
2110-
pairs = matcher.pairs;
2111-
return false;
2112-
}
2113-
2114-
if (tuple1->getNumElements() != tuple2->getNumElements())
2115-
return true;
2116-
2105+
private:
2106+
bool matchEquality(bool inPatternMatchingContext) {
21172107
for (unsigned i = 0, n = tuple1->getNumElements(); i != n; ++i) {
21182108
const auto &elt1 = tuple1->getElement(i);
21192109
const auto &elt2 = tuple2->getElement(i);
21202110

2121-
if (elt1.hasName() && elt1.getName() != elt2.getName())
2122-
return true;
2111+
if (inPatternMatchingContext) {
2112+
if (elt1.hasName() && elt1.getName() != elt2.getName())
2113+
return true;
2114+
} else {
2115+
// If the names don't match, we have a conflict.
2116+
if (elt1.getName() != elt2.getName())
2117+
return true;
2118+
}
21232119

21242120
pairs.emplace_back(elt1.getType(), elt2.getType(), i, i);
21252121
}
@@ -2128,21 +2124,6 @@ class TupleMatcher {
21282124
}
21292125

21302126
bool matchSubtype() {
2131-
// FIXME: TuplePackMatcher should completely replace the non-variadic
2132-
// case too eventually.
2133-
if (tuple1->containsPackExpansionType() ||
2134-
tuple2->containsPackExpansionType()) {
2135-
TuplePackMatcher matcher(tuple1, tuple2);
2136-
if (matcher.match())
2137-
return true;
2138-
2139-
pairs = matcher.pairs;
2140-
return false;
2141-
}
2142-
2143-
if (tuple1->getNumElements() != tuple2->getNumElements())
2144-
return true;
2145-
21462127
for (unsigned i = 0, n = tuple1->getNumElements(); i != n; ++i) {
21472128
const auto &elt1 = tuple1->getElement(i);
21482129
const auto &elt2 = tuple2->getElement(i);
@@ -2166,18 +2147,6 @@ class TupleMatcher {
21662147
}
21672148

21682149
bool matchConversion() {
2169-
// FIXME: TuplePackMatcher should completely replace the non-variadic
2170-
// case too eventually.
2171-
if (tuple1->containsPackExpansionType() ||
2172-
tuple2->containsPackExpansionType()) {
2173-
TuplePackMatcher matcher(tuple1, tuple2);
2174-
if (matcher.match())
2175-
return true;
2176-
2177-
pairs = matcher.pairs;
2178-
return false;
2179-
}
2180-
21812150
SmallVector<unsigned, 4> sources;
21822151
if (computeTupleShuffle(tuple1, tuple2, sources))
21832152
return true;
@@ -2201,23 +2170,16 @@ ConstraintSystem::TypeMatchResult
22012170
ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
22022171
ConstraintKind kind, TypeMatchOptions flags,
22032172
ConstraintLocatorBuilder locator) {
2204-
TupleMatcher matcher(tuple1, tuple2);
2173+
using TupleMatchKind = TupleMatcher::MatchKind;
22052174

22062175
ConstraintKind subkind;
2176+
TupleMatchKind matchKind;
22072177

22082178
switch (kind) {
22092179
case ConstraintKind::Bind:
22102180
case ConstraintKind::Equal: {
22112181
subkind = kind;
2212-
2213-
if (isInPatternMatchingContext(locator)) {
2214-
if (matcher.matchInPatternMatchingContext())
2215-
return getTypeMatchFailure(locator);
2216-
} else {
2217-
if (matcher.matchBind())
2218-
return getTypeMatchFailure(locator);
2219-
}
2220-
2182+
matchKind = TupleMatchKind::Equality;
22212183
break;
22222184
}
22232185

@@ -2227,29 +2189,15 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
22272189
case ConstraintKind::Subtype:
22282190
case ConstraintKind::BindToPointerType: {
22292191
subkind = kind;
2230-
2231-
if (matcher.matchSubtype())
2232-
return getTypeMatchFailure(locator);
2233-
2234-
if (matcher.hasLabelMismatch) {
2235-
// If we had a label mismatch, emit a warning. This is something we
2236-
// shouldn't permit, as it's more permissive than what a conversion would
2237-
// allow. Ideally we'd turn this into an error in Swift 6 mode.
2238-
recordFix(AllowTupleLabelMismatch::create(
2239-
*this, tuple1, tuple2, getConstraintLocator(locator)));
2240-
}
2192+
matchKind = TupleMatchKind::Subtype;
22412193
break;
22422194
}
22432195

22442196
case ConstraintKind::Conversion:
22452197
case ConstraintKind::ArgumentConversion:
22462198
case ConstraintKind::OperatorArgumentConversion: {
22472199
subkind = ConstraintKind::Conversion;
2248-
2249-
// Compute the element shuffles for conversions.
2250-
if (matcher.matchConversion())
2251-
return getTypeMatchFailure(locator);
2252-
2200+
matchKind = TupleMatchKind::Conversion;
22532201
break;
22542202
}
22552203

@@ -2289,6 +2237,19 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
22892237
llvm_unreachable("Bad constraint kind in matchTupleTypes()");
22902238
}
22912239

2240+
TupleMatcher matcher(tuple1, tuple2);
2241+
2242+
if (matcher.match(matchKind, locator))
2243+
return getTypeMatchFailure(locator);
2244+
2245+
if (matcher.hasLabelMismatch) {
2246+
// If we had a label mismatch, emit a warning. This is something we
2247+
// shouldn't permit, as it's more permissive than what a conversion would
2248+
// allow. Ideally we'd turn this into an error in Swift 6 mode.
2249+
recordFix(AllowTupleLabelMismatch::create(*this, tuple1, tuple2,
2250+
getConstraintLocator(locator)));
2251+
}
2252+
22922253
TypeMatchOptions subflags = getDefaultDecompositionOptions(flags);
22932254

22942255
for (auto pair : matcher.pairs) {

0 commit comments

Comments
 (0)