@@ -2062,13 +2062,19 @@ class TupleMatcher {
2062
2062
TupleType *tuple2;
2063
2063
2064
2064
public:
2065
+ enum class MatchKind : uint8_t {
2066
+ Equality,
2067
+ Subtype,
2068
+ Conversion,
2069
+ };
2070
+
2065
2071
SmallVector<MatchedPair, 4> pairs;
2066
2072
bool hasLabelMismatch = false;
2067
2073
2068
2074
TupleMatcher(TupleType *tuple1, TupleType *tuple2)
2069
- : tuple1(tuple1), tuple2(tuple2) {}
2075
+ : tuple1(tuple1), tuple2(tuple2) {}
2070
2076
2071
- bool matchBind( ) {
2077
+ bool match(MatchKind kind, ConstraintLocatorBuilder locator ) {
2072
2078
// FIXME: TuplePackMatcher should completely replace the non-variadic
2073
2079
// case too eventually.
2074
2080
if (tuple1->containsPackExpansionType() ||
@@ -2084,42 +2090,32 @@ class TupleMatcher {
2084
2090
if (tuple1->getNumElements() != tuple2->getNumElements())
2085
2091
return true;
2086
2092
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) );
2090
2096
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();
2094
2099
2095
- pairs.emplace_back(elt1.getType(), elt2.getType(), i, i);
2100
+ case MatchKind::Conversion:
2101
+ return matchConversion();
2096
2102
}
2097
-
2098
- return false;
2099
2103
}
2100
2104
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) {
2117
2107
for (unsigned i = 0, n = tuple1->getNumElements(); i != n; ++i) {
2118
2108
const auto &elt1 = tuple1->getElement(i);
2119
2109
const auto &elt2 = tuple2->getElement(i);
2120
2110
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
+ }
2123
2119
2124
2120
pairs.emplace_back(elt1.getType(), elt2.getType(), i, i);
2125
2121
}
@@ -2128,21 +2124,6 @@ class TupleMatcher {
2128
2124
}
2129
2125
2130
2126
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
-
2146
2127
for (unsigned i = 0, n = tuple1->getNumElements(); i != n; ++i) {
2147
2128
const auto &elt1 = tuple1->getElement(i);
2148
2129
const auto &elt2 = tuple2->getElement(i);
@@ -2166,18 +2147,6 @@ class TupleMatcher {
2166
2147
}
2167
2148
2168
2149
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
-
2181
2150
SmallVector<unsigned, 4> sources;
2182
2151
if (computeTupleShuffle(tuple1, tuple2, sources))
2183
2152
return true;
@@ -2201,23 +2170,16 @@ ConstraintSystem::TypeMatchResult
2201
2170
ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
2202
2171
ConstraintKind kind, TypeMatchOptions flags,
2203
2172
ConstraintLocatorBuilder locator) {
2204
- TupleMatcher matcher(tuple1, tuple2) ;
2173
+ using TupleMatchKind = TupleMatcher::MatchKind ;
2205
2174
2206
2175
ConstraintKind subkind;
2176
+ TupleMatchKind matchKind;
2207
2177
2208
2178
switch (kind) {
2209
2179
case ConstraintKind::Bind:
2210
2180
case ConstraintKind::Equal: {
2211
2181
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;
2221
2183
break;
2222
2184
}
2223
2185
@@ -2227,29 +2189,15 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
2227
2189
case ConstraintKind::Subtype:
2228
2190
case ConstraintKind::BindToPointerType: {
2229
2191
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;
2241
2193
break;
2242
2194
}
2243
2195
2244
2196
case ConstraintKind::Conversion:
2245
2197
case ConstraintKind::ArgumentConversion:
2246
2198
case ConstraintKind::OperatorArgumentConversion: {
2247
2199
subkind = ConstraintKind::Conversion;
2248
-
2249
- // Compute the element shuffles for conversions.
2250
- if (matcher.matchConversion())
2251
- return getTypeMatchFailure(locator);
2252
-
2200
+ matchKind = TupleMatchKind::Conversion;
2253
2201
break;
2254
2202
}
2255
2203
@@ -2289,6 +2237,19 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
2289
2237
llvm_unreachable("Bad constraint kind in matchTupleTypes()");
2290
2238
}
2291
2239
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
+
2292
2253
TypeMatchOptions subflags = getDefaultDecompositionOptions(flags);
2293
2254
2294
2255
for (auto pair : matcher.pairs) {
0 commit comments