Skip to content

Commit fd2dd9f

Browse files
committed
Sema: Fix OperatorArgumentConversion with LHS of InOutType
We don't require or allow '&' for the mutable parameters in operator calls, since we want to write 'x += 10' and not '&x += 10'. The constraint sovler accepted '&x += 10' though, and we had a separate pass in MiscDiagnostics for rejecting it. Instead, let's just reject this in the solver. The main difficulty is that we must now be prepared to fail certain OperatorArgumentConversion and ApplicableFunction constraints even when both the LHS and RHS types are equal.
1 parent b6985ac commit fd2dd9f

File tree

2 files changed

+24
-8
lines changed

2 files changed

+24
-8
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2169,7 +2169,8 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
21692169
auto desugar2 = type2->getDesugaredType();
21702170

21712171
// If the types are obviously equivalent, we're done.
2172-
if (desugar1->isEqual(desugar2))
2172+
if (desugar1->isEqual(desugar2) &&
2173+
!isa<InOutType>(desugar2))
21732174
return getTypeMatchSuccess();
21742175

21752176
// Local function that should be used to produce the return value whenever
@@ -2478,11 +2479,15 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
24782479
ConstraintLocator::LValueConversion));
24792480

24802481
case TypeKind::InOut:
2481-
// If the RHS is an inout type, the LHS must be an @lvalue type.
2482-
if (kind == ConstraintKind::BindParam ||
2483-
kind >= ConstraintKind::OperatorArgumentConversion)
2482+
if (kind == ConstraintKind::BindParam)
24842483
return getTypeMatchFailure(locator);
24852484

2485+
if (kind == ConstraintKind::OperatorArgumentConversion) {
2486+
conversionsOrFixes.push_back(
2487+
RemoveAddressOf::create(*this, getConstraintLocator(locator)));
2488+
break;
2489+
}
2490+
24862491
return matchTypes(cast<InOutType>(desugar1)->getObjectType(),
24872492
cast<InOutType>(desugar2)->getObjectType(),
24882493
ConstraintKind::Bind, subflags,
@@ -5606,9 +5611,20 @@ ConstraintSystem::simplifyApplicableFnConstraint(
56065611
isa<PostfixUnaryExpr>(anchor) ||
56075612
isa<BinaryExpr>(anchor));
56085613

5609-
// If the types are obviously equivalent, we're done.
5610-
if (type1.getPointer() == desugar2)
5611-
return SolutionKind::Solved;
5614+
auto hasInOut = [&]() {
5615+
for (auto param : func1->getParams())
5616+
if (param.isInOut())
5617+
return true;
5618+
return false;
5619+
};
5620+
5621+
// If the types are obviously equivalent, we're done. This optimization
5622+
// is not valid for operators though, where an inout parameter does not
5623+
// have an explicit inout argument.
5624+
if (type1.getPointer() == desugar2) {
5625+
if (!isOperator || !hasInOut())
5626+
return SolutionKind::Solved;
5627+
}
56125628

56135629
// Local function to form an unsolved result.
56145630
auto formUnsolved = [&] {

test/expr/expressions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -829,7 +829,7 @@ func inoutTests(_ arr: inout Int) {
829829
inoutTests(&x)
830830

831831
// <rdar://problem/17489894> inout not rejected as operand to assignment operator
832-
&x += y // expected-error {{'&' can only appear immediately in a call argument list}}
832+
&x += y // expected-error {{use of extraneous '&'}}
833833

834834
// <rdar://problem/23249098>
835835
func takeAny(_ x: Any) {}

0 commit comments

Comments
 (0)