mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge pull request #24615 from xedin/fix-autoclj-returning-fn-type
[ConstraintSystem] Allow arguments to be passed by value to `@autoclo…
This commit is contained in:
@@ -973,30 +973,6 @@ ConstraintSystem::TypeMatchResult constraints::matchCallArguments(
|
||||
auto *anchor = locator.getAnchor();
|
||||
assert(anchor && "locator without anchor expression?");
|
||||
|
||||
// Check whether argument of the call at given position refers to
|
||||
// parameter marked as `@autoclosure`. This function is used to
|
||||
// maintain source compatibility with Swift versions < 5,
|
||||
// previously examples like following used to type-check:
|
||||
//
|
||||
// func foo(_ x: @autoclosure () -> Int) {}
|
||||
// func bar(_ y: @autoclosure () -> Int) {
|
||||
// foo(y)
|
||||
// }
|
||||
auto isAutoClosureArg = [&](Expr *anchor, unsigned argIdx) -> bool {
|
||||
assert(anchor);
|
||||
|
||||
auto *argExpr = getArgumentExpr(anchor, argIdx);
|
||||
if (!argExpr)
|
||||
return false;
|
||||
|
||||
if (auto *DRE = dyn_cast<DeclRefExpr>(argExpr)) {
|
||||
if (auto *param = dyn_cast<ParamDecl>(DRE->getDecl()))
|
||||
return param->isAutoClosure();
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
for (unsigned paramIdx = 0, numParams = parameterBindings.size();
|
||||
paramIdx != numParams; ++paramIdx){
|
||||
// Skip unfulfilled parameters. There's nothing to do for them.
|
||||
@@ -1007,9 +983,6 @@ ConstraintSystem::TypeMatchResult constraints::matchCallArguments(
|
||||
const auto ¶m = params[paramIdx];
|
||||
auto paramTy = param.getOldType();
|
||||
|
||||
if (param.isAutoClosure())
|
||||
paramTy = paramTy->castTo<FunctionType>()->getResult();
|
||||
|
||||
// Compare each of the bound arguments for this parameter.
|
||||
for (auto argIdx : parameterBindings[paramIdx]) {
|
||||
auto loc = locator.withPathElement(LocatorPathElt::
|
||||
@@ -1017,19 +990,26 @@ ConstraintSystem::TypeMatchResult constraints::matchCallArguments(
|
||||
paramIdx));
|
||||
auto argTy = argsWithLabels[argIdx].getOldType();
|
||||
|
||||
// If parameter was marked as `@autoclosure` and argument
|
||||
// is itself `@autoclosure` function type in Swift < 5,
|
||||
// let's fix that up by making it look like argument is
|
||||
// called implicitly.
|
||||
if (param.isAutoClosure() &&
|
||||
isAutoClosureArg(locator.getAnchor(), argIdx)) {
|
||||
argTy = argTy->castTo<FunctionType>()->getResult();
|
||||
cs.increaseScore(SK_FunctionConversion);
|
||||
bool matchingAutoClosureResult = param.isAutoClosure();
|
||||
if (param.isAutoClosure()) {
|
||||
auto &ctx = cs.getASTContext();
|
||||
auto *fnType = paramTy->castTo<FunctionType>();
|
||||
auto *argExpr = getArgumentExpr(locator.getAnchor(), argIdx);
|
||||
|
||||
if (cs.getASTContext().isSwiftVersionAtLeast(5)) {
|
||||
auto *fixLoc = cs.getConstraintLocator(loc);
|
||||
if (cs.recordFix(AutoClosureForwarding::create(cs, fixLoc)))
|
||||
return cs.getTypeMatchFailure(loc);
|
||||
// If the argument is not marked as @autoclosure or
|
||||
// this is Swift version >= 5 where forwarding is not allowed,
|
||||
// argument would always be wrapped into an implicit closure
|
||||
// at the end, so we can safely match against result type.
|
||||
if (ctx.isSwiftVersionAtLeast(5) || !isAutoClosureArgument(argExpr)) {
|
||||
// In Swift >= 5 mode there is no @autoclosure forwarding,
|
||||
// so let's match result types.
|
||||
paramTy = fnType->getResult();
|
||||
} else {
|
||||
// Matching @autoclosure argument to @autoclosure parameter
|
||||
// directly would mean introducting a function conversion
|
||||
// in Swift <= 4 mode.
|
||||
cs.increaseScore(SK_FunctionConversion);
|
||||
matchingAutoClosureResult = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1040,7 +1020,7 @@ ConstraintSystem::TypeMatchResult constraints::matchCallArguments(
|
||||
|
||||
cs.addConstraint(
|
||||
subKind, argTy, paramTy,
|
||||
param.isAutoClosure()
|
||||
matchingAutoClosureResult
|
||||
? loc.withPathElement(ConstraintLocator::AutoclosureResult)
|
||||
: loc,
|
||||
/*isFavored=*/false);
|
||||
@@ -2187,6 +2167,18 @@ bool ConstraintSystem::repairFailures(
|
||||
break;
|
||||
}
|
||||
|
||||
case ConstraintLocator::FunctionResult: {
|
||||
// `apply argument` -> `arg/param compare` ->
|
||||
// `@autoclosure result` -> `function result`
|
||||
if (path.size() > 3) {
|
||||
const auto &elt = path[path.size() - 2];
|
||||
if (elt.getKind() == ConstraintLocator::AutoclosureResult &&
|
||||
repairByInsertingExplicitCall(lhs, rhs))
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ConstraintLocator::AutoclosureResult: {
|
||||
if (repairByInsertingExplicitCall(lhs, rhs))
|
||||
return true;
|
||||
@@ -6576,6 +6568,12 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
|
||||
return result;
|
||||
}
|
||||
|
||||
case FixKind::AutoClosureForwarding: {
|
||||
if (recordFix(fix))
|
||||
return SolutionKind::Error;
|
||||
return matchTypes(type1, type2, matchKind, subflags, locator);
|
||||
}
|
||||
|
||||
case FixKind::InsertCall:
|
||||
case FixKind::RemoveReturn:
|
||||
case FixKind::RemoveAddressOf:
|
||||
@@ -6591,7 +6589,6 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
|
||||
case FixKind::CoerceToCheckedCast:
|
||||
case FixKind::RelabelArguments:
|
||||
case FixKind::AddConformance:
|
||||
case FixKind::AutoClosureForwarding:
|
||||
case FixKind::RemoveUnwrap:
|
||||
case FixKind::DefineMemberBasedOnUse:
|
||||
case FixKind::AllowTypeOrInstanceMember:
|
||||
|
||||
Reference in New Issue
Block a user