[CSSimplify] NFC: Refactor TupleMatcher to consolidate pack expansion matching

This commit is contained in:
Pavel Yaskevich
2023-03-23 13:36:13 -07:00
parent be6b05b305
commit 1b42e55039

View File

@@ -2062,13 +2062,19 @@ class TupleMatcher {
TupleType *tuple2;
public:
enum class MatchKind : uint8_t {
Equality,
Subtype,
Conversion,
};
SmallVector<MatchedPair, 4> pairs;
bool hasLabelMismatch = false;
TupleMatcher(TupleType *tuple1, TupleType *tuple2)
: tuple1(tuple1), tuple2(tuple2) {}
: tuple1(tuple1), tuple2(tuple2) {}
bool matchBind() {
bool match(MatchKind kind, ConstraintLocatorBuilder locator) {
// FIXME: TuplePackMatcher should completely replace the non-variadic
// case too eventually.
if (tuple1->containsPackExpansionType() ||
@@ -2084,42 +2090,32 @@ public:
if (tuple1->getNumElements() != tuple2->getNumElements())
return true;
for (unsigned i = 0, n = tuple1->getNumElements(); i != n; ++i) {
const auto &elt1 = tuple1->getElement(i);
const auto &elt2 = tuple2->getElement(i);
switch (kind) {
case MatchKind::Equality:
return matchEquality(isInPatternMatchingContext(locator));
// If the names don't match, we have a conflict.
if (elt1.getName() != elt2.getName())
return true;
case MatchKind::Subtype:
return matchSubtype();
pairs.emplace_back(elt1.getType(), elt2.getType(), i, i);
case MatchKind::Conversion:
return matchConversion();
}
return false;
}
bool matchInPatternMatchingContext() {
// FIXME: TuplePackMatcher should completely replace the non-variadic
// case too eventually.
if (tuple1->containsPackExpansionType() ||
tuple2->containsPackExpansionType()) {
TuplePackMatcher matcher(tuple1, tuple2);
if (matcher.match())
return true;
pairs = matcher.pairs;
return false;
}
if (tuple1->getNumElements() != tuple2->getNumElements())
return true;
private:
bool matchEquality(bool inPatternMatchingContext) {
for (unsigned i = 0, n = tuple1->getNumElements(); i != n; ++i) {
const auto &elt1 = tuple1->getElement(i);
const auto &elt2 = tuple2->getElement(i);
if (elt1.hasName() && elt1.getName() != elt2.getName())
return true;
if (inPatternMatchingContext) {
if (elt1.hasName() && elt1.getName() != elt2.getName())
return true;
} else {
// If the names don't match, we have a conflict.
if (elt1.getName() != elt2.getName())
return true;
}
pairs.emplace_back(elt1.getType(), elt2.getType(), i, i);
}
@@ -2128,21 +2124,6 @@ public:
}
bool matchSubtype() {
// FIXME: TuplePackMatcher should completely replace the non-variadic
// case too eventually.
if (tuple1->containsPackExpansionType() ||
tuple2->containsPackExpansionType()) {
TuplePackMatcher matcher(tuple1, tuple2);
if (matcher.match())
return true;
pairs = matcher.pairs;
return false;
}
if (tuple1->getNumElements() != tuple2->getNumElements())
return true;
for (unsigned i = 0, n = tuple1->getNumElements(); i != n; ++i) {
const auto &elt1 = tuple1->getElement(i);
const auto &elt2 = tuple2->getElement(i);
@@ -2166,18 +2147,6 @@ public:
}
bool matchConversion() {
// FIXME: TuplePackMatcher should completely replace the non-variadic
// case too eventually.
if (tuple1->containsPackExpansionType() ||
tuple2->containsPackExpansionType()) {
TuplePackMatcher matcher(tuple1, tuple2);
if (matcher.match())
return true;
pairs = matcher.pairs;
return false;
}
SmallVector<unsigned, 4> sources;
if (computeTupleShuffle(tuple1, tuple2, sources))
return true;
@@ -2201,23 +2170,16 @@ ConstraintSystem::TypeMatchResult
ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
ConstraintKind kind, TypeMatchOptions flags,
ConstraintLocatorBuilder locator) {
TupleMatcher matcher(tuple1, tuple2);
using TupleMatchKind = TupleMatcher::MatchKind;
ConstraintKind subkind;
TupleMatchKind matchKind;
switch (kind) {
case ConstraintKind::Bind:
case ConstraintKind::Equal: {
subkind = kind;
if (isInPatternMatchingContext(locator)) {
if (matcher.matchInPatternMatchingContext())
return getTypeMatchFailure(locator);
} else {
if (matcher.matchBind())
return getTypeMatchFailure(locator);
}
matchKind = TupleMatchKind::Equality;
break;
}
@@ -2227,17 +2189,7 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
case ConstraintKind::Subtype:
case ConstraintKind::BindToPointerType: {
subkind = kind;
if (matcher.matchSubtype())
return getTypeMatchFailure(locator);
if (matcher.hasLabelMismatch) {
// If we had a label mismatch, emit a warning. This is something we
// shouldn't permit, as it's more permissive than what a conversion would
// allow. Ideally we'd turn this into an error in Swift 6 mode.
recordFix(AllowTupleLabelMismatch::create(
*this, tuple1, tuple2, getConstraintLocator(locator)));
}
matchKind = TupleMatchKind::Subtype;
break;
}
@@ -2245,11 +2197,7 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
case ConstraintKind::ArgumentConversion:
case ConstraintKind::OperatorArgumentConversion: {
subkind = ConstraintKind::Conversion;
// Compute the element shuffles for conversions.
if (matcher.matchConversion())
return getTypeMatchFailure(locator);
matchKind = TupleMatchKind::Conversion;
break;
}
@@ -2289,6 +2237,19 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
llvm_unreachable("Bad constraint kind in matchTupleTypes()");
}
TupleMatcher matcher(tuple1, tuple2);
if (matcher.match(matchKind, locator))
return getTypeMatchFailure(locator);
if (matcher.hasLabelMismatch) {
// If we had a label mismatch, emit a warning. This is something we
// shouldn't permit, as it's more permissive than what a conversion would
// allow. Ideally we'd turn this into an error in Swift 6 mode.
recordFix(AllowTupleLabelMismatch::create(*this, tuple1, tuple2,
getConstraintLocator(locator)));
}
TypeMatchOptions subflags = getDefaultDecompositionOptions(flags);
for (auto pair : matcher.pairs) {