@@ -2069,13 +2069,19 @@ class TupleMatcher {
2069
2069
TupleType *tuple2;
2070
2070
2071
2071
public:
2072
+ enum class MatchKind : uint8_t {
2073
+ Equality,
2074
+ Subtype,
2075
+ Conversion,
2076
+ };
2077
+
2072
2078
SmallVector<MatchedPair, 4> pairs;
2073
2079
bool hasLabelMismatch = false;
2074
2080
2075
2081
TupleMatcher(TupleType *tuple1, TupleType *tuple2)
2076
- : tuple1(tuple1), tuple2(tuple2) {}
2082
+ : tuple1(tuple1), tuple2(tuple2) {}
2077
2083
2078
- bool matchBind( ) {
2084
+ bool match(MatchKind kind, ConstraintLocatorBuilder locator ) {
2079
2085
// FIXME: TuplePackMatcher should completely replace the non-variadic
2080
2086
// case too eventually.
2081
2087
if (tuple1->containsPackExpansionType() ||
@@ -2091,42 +2097,32 @@ class TupleMatcher {
2091
2097
if (tuple1->getNumElements() != tuple2->getNumElements())
2092
2098
return true;
2093
2099
2094
- for (unsigned i = 0, n = tuple1->getNumElements(); i != n; ++i ) {
2095
- const auto &elt1 = tuple1->getElement(i);
2096
- const auto &elt2 = tuple2->getElement(i );
2100
+ switch (kind ) {
2101
+ case MatchKind::Equality:
2102
+ return matchEquality(isInPatternMatchingContext(locator) );
2097
2103
2098
- // If the names don't match, we have a conflict.
2099
- if (elt1.getName() != elt2.getName())
2100
- return true;
2104
+ case MatchKind::Subtype:
2105
+ return matchSubtype();
2101
2106
2102
- pairs.emplace_back(elt1.getType(), elt2.getType(), i, i);
2107
+ case MatchKind::Conversion:
2108
+ return matchConversion();
2103
2109
}
2104
-
2105
- return false;
2106
2110
}
2107
2111
2108
- bool matchInPatternMatchingContext() {
2109
- // FIXME: TuplePackMatcher should completely replace the non-variadic
2110
- // case too eventually.
2111
- if (tuple1->containsPackExpansionType() ||
2112
- tuple2->containsPackExpansionType()) {
2113
- TuplePackMatcher matcher(tuple1, tuple2);
2114
- if (matcher.match())
2115
- return true;
2116
-
2117
- pairs = matcher.pairs;
2118
- return false;
2119
- }
2120
-
2121
- if (tuple1->getNumElements() != tuple2->getNumElements())
2122
- return true;
2123
-
2112
+ private:
2113
+ bool matchEquality(bool inPatternMatchingContext) {
2124
2114
for (unsigned i = 0, n = tuple1->getNumElements(); i != n; ++i) {
2125
2115
const auto &elt1 = tuple1->getElement(i);
2126
2116
const auto &elt2 = tuple2->getElement(i);
2127
2117
2128
- if (elt1.hasName() && elt1.getName() != elt2.getName())
2129
- return true;
2118
+ if (inPatternMatchingContext) {
2119
+ if (elt1.hasName() && elt1.getName() != elt2.getName())
2120
+ return true;
2121
+ } else {
2122
+ // If the names don't match, we have a conflict.
2123
+ if (elt1.getName() != elt2.getName())
2124
+ return true;
2125
+ }
2130
2126
2131
2127
pairs.emplace_back(elt1.getType(), elt2.getType(), i, i);
2132
2128
}
@@ -2135,21 +2131,6 @@ class TupleMatcher {
2135
2131
}
2136
2132
2137
2133
bool matchSubtype() {
2138
- // FIXME: TuplePackMatcher should completely replace the non-variadic
2139
- // case too eventually.
2140
- if (tuple1->containsPackExpansionType() ||
2141
- tuple2->containsPackExpansionType()) {
2142
- TuplePackMatcher matcher(tuple1, tuple2);
2143
- if (matcher.match())
2144
- return true;
2145
-
2146
- pairs = matcher.pairs;
2147
- return false;
2148
- }
2149
-
2150
- if (tuple1->getNumElements() != tuple2->getNumElements())
2151
- return true;
2152
-
2153
2134
for (unsigned i = 0, n = tuple1->getNumElements(); i != n; ++i) {
2154
2135
const auto &elt1 = tuple1->getElement(i);
2155
2136
const auto &elt2 = tuple2->getElement(i);
@@ -2173,18 +2154,6 @@ class TupleMatcher {
2173
2154
}
2174
2155
2175
2156
bool matchConversion() {
2176
- // FIXME: TuplePackMatcher should completely replace the non-variadic
2177
- // case too eventually.
2178
- if (tuple1->containsPackExpansionType() ||
2179
- tuple2->containsPackExpansionType()) {
2180
- TuplePackMatcher matcher(tuple1, tuple2);
2181
- if (matcher.match())
2182
- return true;
2183
-
2184
- pairs = matcher.pairs;
2185
- return false;
2186
- }
2187
-
2188
2157
SmallVector<unsigned, 4> sources;
2189
2158
if (computeTupleShuffle(tuple1, tuple2, sources))
2190
2159
return true;
@@ -2208,23 +2177,16 @@ ConstraintSystem::TypeMatchResult
2208
2177
ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
2209
2178
ConstraintKind kind, TypeMatchOptions flags,
2210
2179
ConstraintLocatorBuilder locator) {
2211
- TupleMatcher matcher(tuple1, tuple2) ;
2180
+ using TupleMatchKind = TupleMatcher::MatchKind ;
2212
2181
2213
2182
ConstraintKind subkind;
2183
+ TupleMatchKind matchKind;
2214
2184
2215
2185
switch (kind) {
2216
2186
case ConstraintKind::Bind:
2217
2187
case ConstraintKind::Equal: {
2218
2188
subkind = kind;
2219
-
2220
- if (isInPatternMatchingContext(locator)) {
2221
- if (matcher.matchInPatternMatchingContext())
2222
- return getTypeMatchFailure(locator);
2223
- } else {
2224
- if (matcher.matchBind())
2225
- return getTypeMatchFailure(locator);
2226
- }
2227
-
2189
+ matchKind = TupleMatchKind::Equality;
2228
2190
break;
2229
2191
}
2230
2192
@@ -2234,29 +2196,15 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
2234
2196
case ConstraintKind::Subtype:
2235
2197
case ConstraintKind::BindToPointerType: {
2236
2198
subkind = kind;
2237
-
2238
- if (matcher.matchSubtype())
2239
- return getTypeMatchFailure(locator);
2240
-
2241
- if (matcher.hasLabelMismatch) {
2242
- // If we had a label mismatch, emit a warning. This is something we
2243
- // shouldn't permit, as it's more permissive than what a conversion would
2244
- // allow. Ideally we'd turn this into an error in Swift 6 mode.
2245
- recordFix(AllowTupleLabelMismatch::create(
2246
- *this, tuple1, tuple2, getConstraintLocator(locator)));
2247
- }
2199
+ matchKind = TupleMatchKind::Subtype;
2248
2200
break;
2249
2201
}
2250
2202
2251
2203
case ConstraintKind::Conversion:
2252
2204
case ConstraintKind::ArgumentConversion:
2253
2205
case ConstraintKind::OperatorArgumentConversion: {
2254
2206
subkind = ConstraintKind::Conversion;
2255
-
2256
- // Compute the element shuffles for conversions.
2257
- if (matcher.matchConversion())
2258
- return getTypeMatchFailure(locator);
2259
-
2207
+ matchKind = TupleMatchKind::Conversion;
2260
2208
break;
2261
2209
}
2262
2210
@@ -2296,6 +2244,19 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
2296
2244
llvm_unreachable("Bad constraint kind in matchTupleTypes()");
2297
2245
}
2298
2246
2247
+ TupleMatcher matcher(tuple1, tuple2);
2248
+
2249
+ if (matcher.match(matchKind, locator))
2250
+ return getTypeMatchFailure(locator);
2251
+
2252
+ if (matcher.hasLabelMismatch) {
2253
+ // If we had a label mismatch, emit a warning. This is something we
2254
+ // shouldn't permit, as it's more permissive than what a conversion would
2255
+ // allow. Ideally we'd turn this into an error in Swift 6 mode.
2256
+ recordFix(AllowTupleLabelMismatch::create(*this, tuple1, tuple2,
2257
+ getConstraintLocator(locator)));
2258
+ }
2259
+
2299
2260
TypeMatchOptions subflags = getDefaultDecompositionOptions(flags);
2300
2261
2301
2262
for (auto pair : matcher.pairs) {
0 commit comments