Skip to content

Commit a95d081

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 1e9232a commit a95d081

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
@@ -2157,7 +2157,9 @@ class TupleMatcher {
21572157
const auto &elt2 = tuple2->getElement(i);
21582158

21592159
if (inPatternMatchingContext) {
2160-
if (elt1.hasName() && elt1.getName() != elt2.getName())
2160+
// FIXME: The fact that this isn't symmetric is wrong since this logic
2161+
// is called for bind and equal constraints...
2162+
if (elt2.hasName() && elt1.getName() != elt2.getName())
21612163
return true;
21622164
} else {
21632165
// If the names don't match, we have a conflict.
@@ -3515,21 +3517,12 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
35153517
// FIXME: We should check value ownership too, but it's not completely
35163518
// trivial because of inout-to-pointer conversions.
35173519

3518-
// For equality contravariance doesn't matter, but let's make sure
3519-
// that types are matched in original order because that is important
3520-
// when function types are equated as part of pattern matching.
3521-
auto paramType1 = kind == ConstraintKind::Equal ? func1Param.getOldType()
3522-
: func2Param.getOldType();
3523-
3524-
auto paramType2 = kind == ConstraintKind::Equal ? func2Param.getOldType()
3525-
: func1Param.getOldType();
3526-
3527-
// Compare the parameter types.
3528-
auto result = matchTypes(paramType1, paramType2, subKind, subflags,
3529-
(func1Params.size() == 1
3530-
? argumentLocator
3531-
: argumentLocator.withPathElement(
3532-
LocatorPathElt::TupleElement(i))));
3520+
// Compare the parameter types, taking contravariance into account.
3521+
auto result = matchTypes(
3522+
func2Param.getOldType(), func1Param.getOldType(), subKind, subflags,
3523+
(func1Params.size() == 1 ? argumentLocator
3524+
: argumentLocator.withPathElement(
3525+
LocatorPathElt::TupleElement(i))));
35333526
if (result.isFailure())
35343527
return result;
35353528
}
@@ -6394,7 +6387,7 @@ bool ConstraintSystem::repairFailures(
63946387
if (auto *OA = var->getAttrs().getAttribute<ReferenceOwnershipAttr>())
63956388
ROK = OA->get();
63966389

6397-
if (!rhs->getOptionalObjectType() &&
6390+
if (!lhs->getOptionalObjectType() &&
63986391
optionalityOf(ROK) == ReferenceOwnershipOptionality::Required) {
63996392
conversionsOrFixes.push_back(
64006393
AllowNonOptionalWeak::create(*this, getConstraintLocator(NP)));
@@ -14786,7 +14779,10 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
1478614779
if (recordFix(fix))
1478714780
return SolutionKind::Error;
1478814781

14789-
(void)matchTypes(type1, OptionalType::get(type2), ConstraintKind::Equal,
14782+
// NOTE: The order here is important! Pattern matching equality is
14783+
// not symmetric (we need to fix that either by using a different
14784+
// constraint, or actually making it symmetric).
14785+
(void)matchTypes(OptionalType::get(type1), type2, ConstraintKind::Equal,
1479014786
TypeMatchFlags::TMF_ApplyingFix, locator);
1479114787

1479214788
return SolutionKind::Solved;

0 commit comments

Comments
 (0)