Skip to content

Commit 1bf954c

Browse files
committed
[CS] Better diagnose inout argument in tuple construction
Previously we relied on `TupleTypeElt::getType` returning an `InOutType` to fail the tuple type matching logic. Instead, add logic to reject any inout arguments up-front with a more specific diagnostic. Also, while we're here, strip the `_const` parameter flag, as it's not something that needs to be considered for tuple construction.
1 parent 227f0de commit 1bf954c

File tree

3 files changed

+42
-3
lines changed

3 files changed

+42
-3
lines changed

Diff for: lib/Sema/CSSimplify.cpp

+25-2
Original file line numberDiff line numberDiff line change
@@ -6983,10 +6983,33 @@ ConstraintSystem::simplifyConstructionConstraint(
69836983
fnType = contextualType;
69846984
}
69856985
}
6986+
SmallVector<AnyFunctionType::Param, 4> args;
6987+
for (auto idx : indices(fnType->getParams())) {
6988+
auto &arg = fnType->getParams()[idx];
6989+
6990+
// We can disregard '_const', it's not applicable for tuple construction.
6991+
auto flags = arg.getParameterFlags().withCompileTimeConst(false);
6992+
6993+
// We cannot handle inout for tuple construction.
6994+
if (flags.isInOut()) {
6995+
if (!shouldAttemptFixes())
6996+
return SolutionKind::Error;
6997+
6998+
auto *argLoc = getConstraintLocator(locator, {
6999+
LocatorPathElt::ApplyArgument(),
7000+
LocatorPathElt::ApplyArgToParam(idx, idx, ParameterTypeFlags())
7001+
});
7002+
auto argTy = arg.getParameterType();
7003+
if (recordFix(RemoveAddressOf::create(*this, argTy, argTy, argLoc)))
7004+
return SolutionKind::Error;
7005+
7006+
flags = flags.withInOut(false);
7007+
}
7008+
args.push_back(arg.withFlags(flags));
7009+
}
69867010

69877011
// Tuple construction is simply tuple conversion.
6988-
Type argType = AnyFunctionType::composeTuple(getASTContext(),
6989-
fnType->getParams());
7012+
Type argType = AnyFunctionType::composeTuple(getASTContext(), args);
69907013
Type resultType = fnType->getResult();
69917014

69927015
ConstraintLocatorBuilder builder(locator);

Diff for: lib/Sema/ConstraintSystem.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -5608,6 +5608,13 @@ Solution::getFunctionArgApplyInfo(ConstraintLocator *locator) const {
56085608
if (simplifyType(rawFnType)->is<UnresolvedType>())
56095609
return None;
56105610

5611+
// A tuple construction is spelled in the AST as a function call, but
5612+
// is really more like a tuple conversion.
5613+
if (auto metaTy = simplifyType(rawFnType)->getAs<MetatypeType>()) {
5614+
if (metaTy->getInstanceType()->is<TupleType>())
5615+
return None;
5616+
}
5617+
56115618
assert(!shouldHaveDirectCalleeOverload(call) &&
56125619
"Should we have resolved a callee for this?");
56135620
}

Diff for: test/Constraints/diagnostics.swift

+10-1
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,16 @@ func r22263468(_ a : String?) {
573573
// TODO(diagnostics): This is a regression from diagnosing missing optional unwrap for `a`, we have to
574574
// re-think the way errors in tuple elements are detected because it's currently impossible to detect
575575
// exactly what went wrong here and aggregate fixes for different elements at the same time.
576-
_ = MyTuple(42, a) // expected-error {{tuple type '(_const Int, String?)' is not convertible to tuple type 'MyTuple' (aka '(Int, String)')}}
576+
_ = MyTuple(42, a) // expected-error {{tuple type '(Int, String?)' is not convertible to tuple type 'MyTuple' (aka '(Int, String)')}}
577+
}
578+
579+
func testTupleConstructionInOutArg() {
580+
typealias II = (Int, Int)
581+
582+
var i = 0
583+
_ = (Int, Int)(&i, 0) // expected-error {{'&' may only be used to pass an argument to inout parameter}}
584+
_ = II(&i, 0) // expected-error {{'&' may only be used to pass an argument to inout parameter}}
585+
_ = II(&i, &i) // expected-error 2{{'&' may only be used to pass an argument to inout parameter}}
577586
}
578587

579588
// rdar://71829040 - "ambiguous without more context" error for tuple type mismatch.

0 commit comments

Comments
 (0)