@@ -4879,12 +4879,13 @@ static bool repairOutOfOrderArgumentsInBinaryFunction(
4879
4879
if (!argument)
4880
4880
return false;
4881
4881
4882
- auto currArgIdx =
4883
- locator->castLastElementTo<LocatorPathElt::ApplyArgToParam>().getArgIdx();
4882
+ auto argLoc = locator->castLastElementTo<LocatorPathElt::ApplyArgToParam>();
4883
+ auto currArgIdx = argLoc.getArgIdx();
4884
+ auto currParamIdx = argLoc.getParamIdx();
4884
4885
4885
4886
// Argument is extraneous and has been re-ordered to match one
4886
4887
// of two parameter types.
4887
- if (currArgIdx >= 2)
4888
+ if (currArgIdx >= 2 || currArgIdx != currParamIdx )
4888
4889
return false;
4889
4890
4890
4891
auto otherArgIdx = currArgIdx == 0 ? 1 : 0;
@@ -4901,29 +4902,54 @@ static bool repairOutOfOrderArgumentsInBinaryFunction(
4901
4902
return false;
4902
4903
}
4903
4904
4904
- auto matchArgToParam = [&](Type argType, Type paramType, ASTNode anchor) {
4905
- auto *loc = cs.getConstraintLocator(anchor);
4905
+ auto getReorderedArgumentLocator = [&](unsigned argIdx) {
4906
+ auto paramIdx = argIdx == 0 ? 1 : 0;
4907
+ return cs.getConstraintLocator(
4908
+ parentLoc, LocatorPathElt::ApplyArgToParam(
4909
+ argIdx, paramIdx,
4910
+ fnType->getParams()[paramIdx].getParameterFlags()));
4911
+ };
4912
+
4913
+ auto matchArgToParam = [&](Type argType, Type paramType, unsigned argIdx) {
4914
+ auto *loc = getReorderedArgumentLocator(argIdx);
4906
4915
// If argument (and/or parameter) is a generic type let's not even try this
4907
4916
// fix because it would be impossible to match given types without delaying
4908
4917
// until more context becomes available.
4909
4918
if (argType->hasTypeVariable() || paramType->hasTypeVariable())
4910
4919
return cs.getTypeMatchFailure(loc);
4911
4920
4921
+ // FIXME: There is currently no easy way to avoid attempting
4922
+ // fixes, matchTypes do not propagate `TMF_ApplyingFix` flag.
4923
+ llvm::SaveAndRestore<ConstraintSystemOptions> options(
4924
+ cs.Options, cs.Options - ConstraintSystemFlags::AllowFixes);
4925
+
4926
+ // Check optionality, if argument is more optional than parameter
4927
+ // they are not going to match. This saves us one disjunction because
4928
+ // optionals are matched as deep-equality and optional-to-optional.
4929
+ {
4930
+ unsigned numArgUnwraps;
4931
+ unsigned numParamUnwraps;
4932
+
4933
+ std::tie(argType, numArgUnwraps) = getObjectTypeAndNumUnwraps(argType);
4934
+ std::tie(paramType, numParamUnwraps) =
4935
+ getObjectTypeAndNumUnwraps(paramType);
4936
+
4937
+ if (numArgUnwraps > numParamUnwraps)
4938
+ return cs.getTypeMatchFailure(loc);
4939
+ }
4940
+
4912
4941
return cs.matchTypes(
4913
- argType->lookThroughAllOptionalTypes(),
4914
- paramType->lookThroughAllOptionalTypes(),
4942
+ argType, paramType,
4915
4943
isOperatorRef ? ConstraintKind::OperatorArgumentConversion
4916
4944
: ConstraintKind::ArgumentConversion,
4917
4945
ConstraintSystem::TypeMatchFlags::TMF_ApplyingFix, loc);
4918
4946
};
4919
4947
4920
- auto result = matchArgToParam(argType, paramType, argument );
4948
+ auto result = matchArgToParam(argType, paramType, currArgIdx );
4921
4949
if (result.isSuccess()) {
4922
4950
// Let's check whether other argument matches current parameter type,
4923
4951
// if it does - it's definitely out-of-order arguments issue.
4924
- auto *otherArgLoc = cs.getConstraintLocator(
4925
- parentLoc, LocatorPathElt::ApplyArgToParam(otherArgIdx, otherArgIdx,
4926
- ParameterTypeFlags()));
4952
+ auto *otherArgLoc = getReorderedArgumentLocator(otherArgIdx);
4927
4953
auto otherArg = simplifyLocatorToAnchor(otherArgLoc);
4928
4954
// Argument could be synthesized.
4929
4955
if (!otherArg)
@@ -4932,7 +4958,7 @@ static bool repairOutOfOrderArgumentsInBinaryFunction(
4932
4958
argType = cs.getType(otherArg);
4933
4959
paramType = fnType->getParams()[currArgIdx].getOldType();
4934
4960
4935
- result = matchArgToParam(argType, paramType, otherArg );
4961
+ result = matchArgToParam(argType, paramType, otherArgIdx );
4936
4962
if (result.isSuccess()) {
4937
4963
conversionsOrFixes.push_back(MoveOutOfOrderArgument::create(
4938
4964
cs, otherArgIdx, currArgIdx, {{0}, {1}}, parentLoc));
0 commit comments