Skip to content

Commit 52c1c8c

Browse files
committed
Sema: Clean up solving BindParam constraint
- Avoid creating an unnecessary type variable - Even if both sides are type variables we can solve them if the LHS cannot bind to an InOut or the RHS cannot bind to an LValue; in this case the two types are identical and we can merge them
1 parent 353b4cc commit 52c1c8c

File tree

1 file changed

+22
-24
lines changed

1 file changed

+22
-24
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1759,46 +1759,44 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
17591759
case ConstraintKind::BindParam: {
17601760
if (typeVar2 && !typeVar1) {
17611761
// Simplify the left-hand type and perform the "occurs" check.
1762-
typeVar2 = getRepresentative(typeVar2);
1762+
auto rep2 = getRepresentative(typeVar2);
17631763
type1 = simplifyType(type1, flags);
17641764
if (!isBindable(typeVar2, type1))
17651765
return formUnsolvedResult();
17661766

17671767
if (auto *iot = type1->getAs<InOutType>()) {
1768-
assignFixedType(typeVar2, LValueType::get(iot->getObjectType()));
1768+
if (!rep2->getImpl().canBindToLValue())
1769+
return getTypeMatchFailure(locator);
1770+
assignFixedType(rep2, LValueType::get(iot->getObjectType()));
17691771
} else {
1770-
assignFixedType(typeVar2, type1);
1772+
assignFixedType(rep2, type1);
17711773
}
17721774
return getTypeMatchSuccess();
17731775
} else if (typeVar1 && !typeVar2) {
17741776
// Simplify the right-hand type and perform the "occurs" check.
1775-
typeVar1 = getRepresentative(typeVar1);
1777+
auto rep1 = getRepresentative(typeVar1);
17761778
type2 = simplifyType(type2, flags);
1777-
if (!isBindable(typeVar1, type2))
1779+
if (!isBindable(rep1, type2))
17781780
return formUnsolvedResult();
17791781

1780-
// If the right-hand side of the BindParam constraint
1781-
// is `lvalue` type, we'll have to make sure that
1782-
// left-hand side is bound to type variable which
1783-
// is wrapped in `inout` type to preserve inout/lvalue pairing.
17841782
if (auto *lvt = type2->getAs<LValueType>()) {
1785-
auto *tv = createTypeVariable(typeVar1->getImpl().getLocator());
1786-
assignFixedType(typeVar1, InOutType::get(tv));
1787-
1788-
typeVar1 = tv;
1789-
type2 = lvt->getObjectType();
1783+
if (!rep1->getImpl().canBindToInOut())
1784+
return getTypeMatchFailure(locator);
1785+
assignFixedType(rep1, InOutType::get(lvt->getObjectType()));
1786+
} else {
1787+
assignFixedType(rep1, type2);
17901788
}
1791-
1792-
// If we have a binding for the right-hand side
1793-
// (argument type used in the body) don't try
1794-
// to bind it to the left-hand side (parameter type)
1795-
// directly, because there could be an implicit
1796-
// conversion between them, and actual binding
1797-
// can only come from the left-hand side.
1798-
addUnsolvedConstraint(
1799-
Constraint::create(*this, ConstraintKind::Equal, typeVar1, type2,
1800-
getConstraintLocator(locator)));
18011789
return getTypeMatchSuccess();
1790+
} if (typeVar1 && typeVar2) {
1791+
auto rep1 = getRepresentative(typeVar1);
1792+
auto rep2 = getRepresentative(typeVar2);
1793+
1794+
if (!rep1->getImpl().canBindToInOut() ||
1795+
!rep2->getImpl().canBindToLValue()) {
1796+
// Merge the equivalence classes corresponding to these two variables.
1797+
mergeEquivalenceClasses(rep1, rep2);
1798+
return getTypeMatchSuccess();
1799+
}
18021800
}
18031801

18041802
return formUnsolvedResult();

0 commit comments

Comments
 (0)