Skip to content

Commit 5e68204

Browse files
authored
Merge pull request #36459 from xedin/rdar-75146811
[ConstraintSystem] Teach `getFunctionArgApplyInfo` about `inout` expr…
2 parents 1dd914a + 4ca67f6 commit 5e68204

File tree

3 files changed

+84
-1
lines changed

3 files changed

+84
-1
lines changed

Diff for: lib/Sema/CSSimplify.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -3474,6 +3474,13 @@ static bool repairOutOfOrderArgumentsInBinaryFunction(
34743474

34753475
bool isOperatorRef = overload->choice.getDecl()->isOperator();
34763476

3477+
// If one of the parameters is `inout`, we can't flip the arguments.
3478+
{
3479+
auto params = fnType->getParams();
3480+
if (params[0].isInOut() != params[1].isInOut())
3481+
return false;
3482+
}
3483+
34773484
auto matchArgToParam = [&](Type argType, Type paramType, ASTNode anchor) {
34783485
auto *loc = cs.getConstraintLocator(anchor);
34793486
// If argument (and/or parameter) is a generic type let's not even try this

Diff for: lib/Sema/ConstraintSystem.cpp

+53-1
Original file line numberDiff line numberDiff line change
@@ -4542,6 +4542,59 @@ Type Solution::resolveInterfaceType(Type type) const {
45424542

45434543
Optional<FunctionArgApplyInfo>
45444544
Solution::getFunctionArgApplyInfo(ConstraintLocator *locator) const {
4545+
auto &cs = getConstraintSystem();
4546+
4547+
// It's only valid to use `&` in argument positions, but we need
4548+
// to figure out exactly where it was used.
4549+
if (auto *argExpr = getAsExpr<InOutExpr>(locator->getAnchor())) {
4550+
auto *argList = cs.getParentExpr(argExpr);
4551+
assert(argList);
4552+
4553+
// `inout` expression might be wrapped in a number of
4554+
// parens e.g. `test(((&x)))`.
4555+
if (isa<ParenExpr>(argList)) {
4556+
for (;;) {
4557+
auto nextParent = cs.getParentExpr(argList);
4558+
assert(nextParent && "Incorrect use of `inout` expression");
4559+
4560+
// e.g. `test((&x), x: ...)`
4561+
if (isa<TupleExpr>(nextParent)) {
4562+
argList = nextParent;
4563+
break;
4564+
}
4565+
4566+
// e.g. `test(((&x)))`
4567+
if (isa<ParenExpr>(nextParent)) {
4568+
argList = nextParent;
4569+
continue;
4570+
}
4571+
4572+
break;
4573+
}
4574+
}
4575+
4576+
unsigned argIdx = 0;
4577+
if (auto *tuple = dyn_cast<TupleExpr>(argList)) {
4578+
auto arguments = tuple->getElements();
4579+
4580+
for (auto idx : indices(arguments)) {
4581+
if (arguments[idx]->getSemanticsProvidingExpr() == argExpr) {
4582+
argIdx = idx;
4583+
break;
4584+
}
4585+
}
4586+
}
4587+
4588+
auto *call = cs.getParentExpr(argList);
4589+
assert(call);
4590+
4591+
ParameterTypeFlags flags;
4592+
locator = cs.getConstraintLocator(
4593+
call, {ConstraintLocator::ApplyArgument,
4594+
LocatorPathElt::ApplyArgToParam(argIdx, argIdx,
4595+
flags.withInOut(true))});
4596+
}
4597+
45454598
auto anchor = locator->getAnchor();
45464599
auto path = locator->getPath();
45474600

@@ -4635,7 +4688,6 @@ Solution::getFunctionArgApplyInfo(ConstraintLocator *locator) const {
46354688
auto argIdx = applyArgElt->getArgIdx();
46364689
auto paramIdx = applyArgElt->getParamIdx();
46374690

4638-
auto &cs = getConstraintSystem();
46394691
return FunctionArgApplyInfo(cs.getParentExpr(argExpr), argExpr, argIdx,
46404692
simplifyType(getType(argExpr)), paramIdx,
46414693
fnInterfaceType, fnType, callee);

Diff for: test/Constraints/optional.swift

+24
Original file line numberDiff line numberDiff line change
@@ -460,3 +460,27 @@ func sr_12309() {
460460
return (((nil))) // Ok
461461
}
462462
}
463+
464+
// rdar://75146811 - crash due to incrrect inout type
465+
func rdar75146811() {
466+
func test(_: UnsafeMutablePointer<Double>) {}
467+
func test_tuple(_: UnsafeMutablePointer<Double>, x: Int) {}
468+
func test_named(x: UnsafeMutablePointer<Double>) {}
469+
470+
var arr: [Double]! = []
471+
472+
test(&arr) // expected-error {{cannot convert value of type '[Double]?' to expected argument type 'Double'}}
473+
test((&arr)) // expected-error {{use of extraneous '&'}}
474+
// expected-error@-1 {{cannot convert value of type '[Double]?' to expected argument type 'Double'}}
475+
test(&(arr)) // expected-error {{cannot convert value of type '[Double]?' to expected argument type 'Double'}}
476+
477+
test_tuple(&arr, x: 0) // expected-error {{cannot convert value of type '[Double]?' to expected argument type 'Double'}}
478+
test_tuple((&arr), x: 0) // expected-error {{use of extraneous '&'}}
479+
// expected-error@-1 {{cannot convert value of type '[Double]?' to expected argument type 'Double'}}
480+
test_tuple(&(arr), x: 0) // expected-error {{cannot convert value of type '[Double]?' to expected argument type 'Double'}}
481+
482+
test_named(x: &arr) // expected-error {{cannot convert value of type '[Double]?' to expected argument type 'Double'}}
483+
test_named(x: (&arr)) // expected-error {{use of extraneous '&'}}
484+
// expected-error@-1 {{cannot convert value of type '[Double]?' to expected argument type 'Double'}}
485+
test_named(x: &(arr)) // expected-error {{cannot convert value of type '[Double]?' to expected argument type 'Double'}}
486+
}

0 commit comments

Comments
 (0)