@@ -986,8 +986,35 @@ constraints::matchCallArguments(
986986 };
987987}
988988
989- static Optional<unsigned >
990- getCompletionArgIndex (ASTNode anchor, ConstraintSystem &CS) {
989+ struct CompletionArgInfo {
990+ unsigned completionIdx;
991+ Optional<unsigned > firstTrailingIdx;
992+
993+ bool isAllowableMissingArg (unsigned argInsertIdx,
994+ AnyFunctionType::Param param) {
995+ // If the argument is before or at the index of the argument containing the
996+ // completion, the user would likely have already written it if they
997+ // intended this overload.
998+ if (completionIdx >= argInsertIdx)
999+ return false ;
1000+
1001+ // If the argument is after the first trailing closure, the user can only
1002+ // continue on to write more trailing arguments, so only allow this overload
1003+ // if the missing argument is of function type.
1004+ if (firstTrailingIdx && argInsertIdx > *firstTrailingIdx) {
1005+ if (param.isInOut ())
1006+ return false ;
1007+
1008+ Type expectedTy = param.getPlainType ()->lookThroughAllOptionalTypes ();
1009+ return expectedTy->is <FunctionType>() || expectedTy->isAny () ||
1010+ expectedTy->isTypeVariableOrMember ();
1011+ }
1012+ return true ;
1013+ }
1014+ };
1015+
1016+ static Optional<CompletionArgInfo>
1017+ getCompletionArgInfo (ASTNode anchor, ConstraintSystem &CS) {
9911018 Expr *arg = nullptr ;
9921019 if (auto *CE = getAsExpr<CallExpr>(anchor))
9931020 arg = CE->getArg ();
@@ -999,16 +1026,15 @@ getCompletionArgIndex(ASTNode anchor, ConstraintSystem &CS) {
9991026 if (!arg)
10001027 return None;
10011028
1002- if (auto *TE = dyn_cast<TupleExpr>(arg)) {
1003- auto elems = TE->getElements ();
1004- auto idx = llvm::find_if (elems, [&](Expr *elem) {
1005- return CS.containsCodeCompletionLoc (elem);
1006- });
1007- if (idx != elems.end ())
1008- return std::distance (elems.begin (), idx);
1009- } else if (auto *PE = dyn_cast<ParenExpr>(arg)) {
1029+ auto trailingIdx = arg->getUnlabeledTrailingClosureIndexOfPackedArgument ();
1030+ if (auto *PE = dyn_cast<ParenExpr>(arg)) {
10101031 if (CS.containsCodeCompletionLoc (PE->getSubExpr ()))
1011- return 0 ;
1032+ return CompletionArgInfo{ 0 , trailingIdx };
1033+ } else if (auto *TE = dyn_cast<TupleExpr>(arg)) {
1034+ for (unsigned i: indices (TE->getElements ())) {
1035+ if (CS.containsCodeCompletionLoc (TE->getElement (i)))
1036+ return CompletionArgInfo{ i, trailingIdx };
1037+ }
10121038 }
10131039 return None;
10141040}
@@ -1021,7 +1047,7 @@ class ArgumentFailureTracker : public MatchCallArgumentListener {
10211047
10221048 SmallVector<SynthesizedArg, 4 > MissingArguments;
10231049 SmallVector<std::pair<unsigned , AnyFunctionType::Param>, 4 > ExtraArguments;
1024- Optional<unsigned > CompletionArgIdx ;
1050+ Optional<CompletionArgInfo> CompletionArgInfo ;
10251051
10261052public:
10271053 ArgumentFailureTracker (ConstraintSystem &cs,
@@ -1048,10 +1074,19 @@ class ArgumentFailureTracker : public MatchCallArgumentListener {
10481074 const auto ¶m = Parameters[paramIdx];
10491075
10501076 unsigned newArgIdx = Arguments.size ();
1077+
1078+ bool isAfterCodeCompletionLoc = false ;
1079+ if (CS.isForCodeCompletion ()) {
1080+ if (!CompletionArgInfo)
1081+ CompletionArgInfo = getCompletionArgInfo (Locator.getAnchor (), CS);
1082+ isAfterCodeCompletionLoc = CompletionArgInfo &&
1083+ CompletionArgInfo->isAllowableMissingArg (argInsertIdx, param);
1084+ }
1085+
10511086 auto *argLoc = CS.getConstraintLocator (
10521087 Locator, {LocatorPathElt::ApplyArgToParam (newArgIdx, paramIdx,
10531088 param.getParameterFlags ()),
1054- LocatorPathElt::SynthesizedArgument (newArgIdx)});
1089+ LocatorPathElt::SynthesizedArgument (newArgIdx, isAfterCodeCompletionLoc )});
10551090
10561091 auto *argType =
10571092 CS.createTypeVariable (argLoc, TVO_CanBindToInOut | TVO_CanBindToLValue |
@@ -1060,16 +1095,12 @@ class ArgumentFailureTracker : public MatchCallArgumentListener {
10601095 auto synthesizedArg = param.withType (argType);
10611096 Arguments.push_back (synthesizedArg);
10621097
1063- if (CS.isForCodeCompletion ()) {
1064- // When solving for code completion, if any argument contains the
1065- // completion location, later arguments shouldn't be considered missing
1066- // (causing the solution to have a worse score) as the user just hasn't
1067- // written them yet. Early exit to avoid recording them in this case.
1068- if (!CompletionArgIdx)
1069- CompletionArgIdx = getCompletionArgIndex (Locator.getAnchor (), CS);
1070- if (CompletionArgIdx && *CompletionArgIdx < argInsertIdx)
1071- return newArgIdx;
1072- }
1098+ // When solving for code completion, if any argument contains the
1099+ // completion location, later arguments shouldn't be considered missing
1100+ // (causing the solution to have a worse score) as the user just hasn't
1101+ // written them yet. Early exit to avoid recording them in this case.
1102+ if (isAfterCodeCompletionLoc)
1103+ return newArgIdx;
10731104
10741105 MissingArguments.push_back (SynthesizedArg{paramIdx, synthesizedArg});
10751106
0 commit comments