Skip to content

Commit c853611

Browse files
committed
[CS] Reverse the type order in a couple of pattern equality constraints
Order them such that if they were changed to conversions, they would be sound. This shouldn't make a difference, but unfortunately it turns out pattern equality is not symmetric. As such, tweak the pattern equality logic to account for the reversed types. This allows us to remove a special case from function matching.
1 parent a35a43f commit c853611

File tree

2 files changed

+29
-21
lines changed

2 files changed

+29
-21
lines changed

lib/Sema/CSGen.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2713,8 +2713,11 @@ namespace {
27132713
if (!subPatternType)
27142714
return Type();
27152715

2716+
// NOTE: The order here is important! Pattern matching equality is
2717+
// not symmetric (we need to fix that either by using a different
2718+
// constraint, or actually making it symmetric).
27162719
CS.addConstraint(
2717-
ConstraintKind::Equal, subPatternType, openedType,
2720+
ConstraintKind::Equal, openedType, subPatternType,
27182721
locator.withPathElement(LocatorPathElt::PatternMatch(pattern)));
27192722

27202723
// FIXME [OPAQUE SUPPORT]: the distinction between where we want opaque
@@ -2826,8 +2829,11 @@ namespace {
28262829
locator.withPathElement(LocatorPathElt::PatternMatch(subPattern)),
28272830
castType, bindPatternVarsOneWay);
28282831

2832+
// NOTE: The order here is important! Pattern matching equality is
2833+
// not symmetric (we need to fix that either by using a different
2834+
// constraint, or actually making it symmetric).
28292835
CS.addConstraint(
2830-
ConstraintKind::Equal, subPatternType, castType,
2836+
ConstraintKind::Equal, castType, subPatternType,
28312837
locator.withPathElement(LocatorPathElt::PatternMatch(pattern)));
28322838
}
28332839
return setType(isType);
@@ -2956,7 +2962,13 @@ namespace {
29562962
// FIXME: Verify ExtInfo state is correct, not working by accident.
29572963
FunctionType::ExtInfo info;
29582964
Type functionType = FunctionType::get(params, outputType, info);
2959-
// TODO: Convert to FunctionInput/FunctionResult constraints.
2965+
2966+
// TODO: Convert to own constraint? Note that ApplicableFn isn't quite
2967+
// right, as pattern matching has data flowing *into* the apply result
2968+
// and call arguments, not the other way around.
2969+
// NOTE: The order here is important! Pattern matching equality is
2970+
// not symmetric (we need to fix that either by using a different
2971+
// constraint, or actually making it symmetric).
29602972
CS.addConstraint(
29612973
ConstraintKind::Equal, functionType, memberType,
29622974
locator.withPathElement(LocatorPathElt::PatternMatch(pattern)));

lib/Sema/CSSimplify.cpp

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2165,7 +2165,9 @@ class TupleMatcher {
21652165
const auto &elt2 = tuple2->getElement(i);
21662166

21672167
if (inPatternMatchingContext) {
2168-
if (elt1.hasName() && elt1.getName() != elt2.getName())
2168+
// FIXME: The fact that this isn't symmetric is wrong since this logic
2169+
// is called for bind and equal constraints...
2170+
if (elt2.hasName() && elt1.getName() != elt2.getName())
21692171
return true;
21702172
} else {
21712173
// If the names don't match, we have a conflict.
@@ -3523,21 +3525,12 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
35233525
// FIXME: We should check value ownership too, but it's not completely
35243526
// trivial because of inout-to-pointer conversions.
35253527

3526-
// For equality contravariance doesn't matter, but let's make sure
3527-
// that types are matched in original order because that is important
3528-
// when function types are equated as part of pattern matching.
3529-
auto paramType1 = kind == ConstraintKind::Equal ? func1Param.getOldType()
3530-
: func2Param.getOldType();
3531-
3532-
auto paramType2 = kind == ConstraintKind::Equal ? func2Param.getOldType()
3533-
: func1Param.getOldType();
3534-
3535-
// Compare the parameter types.
3536-
auto result = matchTypes(paramType1, paramType2, subKind, subflags,
3537-
(func1Params.size() == 1
3538-
? argumentLocator
3539-
: argumentLocator.withPathElement(
3540-
LocatorPathElt::TupleElement(i))));
3528+
// Compare the parameter types, taking contravariance into account.
3529+
auto result = matchTypes(
3530+
func2Param.getOldType(), func1Param.getOldType(), subKind, subflags,
3531+
(func1Params.size() == 1 ? argumentLocator
3532+
: argumentLocator.withPathElement(
3533+
LocatorPathElt::TupleElement(i))));
35413534
if (result.isFailure())
35423535
return result;
35433536
}
@@ -6405,7 +6398,7 @@ bool ConstraintSystem::repairFailures(
64056398
if (auto *OA = var->getAttrs().getAttribute<ReferenceOwnershipAttr>())
64066399
ROK = OA->get();
64076400

6408-
if (!rhs->getOptionalObjectType() &&
6401+
if (!lhs->getOptionalObjectType() &&
64096402
optionalityOf(ROK) == ReferenceOwnershipOptionality::Required) {
64106403
conversionsOrFixes.push_back(
64116404
AllowNonOptionalWeak::create(*this, getConstraintLocator(NP)));
@@ -14821,7 +14814,10 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
1482114814
if (recordFix(fix))
1482214815
return SolutionKind::Error;
1482314816

14824-
(void)matchTypes(type1, OptionalType::get(type2), ConstraintKind::Equal,
14817+
// NOTE: The order here is important! Pattern matching equality is
14818+
// not symmetric (we need to fix that either by using a different
14819+
// constraint, or actually making it symmetric).
14820+
(void)matchTypes(OptionalType::get(type1), type2, ConstraintKind::Equal,
1482514821
TypeMatchFlags::TMF_ApplyingFix, locator);
1482614822

1482714823
return SolutionKind::Solved;

0 commit comments

Comments
 (0)