@@ -161,6 +161,10 @@ matchCallArguments(ArrayRef<AnyFunctionType::Param> args,
161161 // requiring further checking at the end.
162162 bool potentiallyOutOfOrder = false ;
163163
164+ auto hasDefault = [&defaultMap, &numParams](unsigned idx) -> bool {
165+ return idx < numParams ? defaultMap.test (idx) : false ;
166+ };
167+
164168 // Local function that claims the argument at \c argNumber, returning the
165169 // index of the claimed argument. This is primarily a helper for
166170 // \c claimNextNamed.
@@ -206,7 +210,7 @@ matchCallArguments(ArrayRef<AnyFunctionType::Param> args,
206210 // Local function that retrieves the next unclaimed argument with the given
207211 // name (which may be empty). This routine claims the argument.
208212 auto claimNextNamed
209- = [&](Identifier name , bool ignoreNameMismatch,
213+ = [&](Identifier paramLabel , bool ignoreNameMismatch,
210214 bool forVariadic = false ) -> Optional<unsigned > {
211215 // Skip over any claimed arguments.
212216 skipClaimedArgs ();
@@ -218,8 +222,9 @@ matchCallArguments(ArrayRef<AnyFunctionType::Param> args,
218222 // Go hunting for an unclaimed argument whose name does match.
219223 Optional<unsigned > claimedWithSameName;
220224 for (unsigned i = nextArgIdx; i != numArgs; ++i) {
221- // Skip arguments where the name doesn't match.
222- if (args[i].getLabel () != name) {
225+ auto argLabel = args[i].getLabel ();
226+
227+ if (argLabel != paramLabel) {
223228 // If this is an attempt to claim additional unlabeled arguments
224229 // for variadic parameter, we have to stop at first labeled argument.
225230 if (forVariadic)
@@ -240,11 +245,23 @@ matchCallArguments(ArrayRef<AnyFunctionType::Param> args,
240245
241246 // We found a match. If the match wasn't the next one, we have
242247 // potentially out of order arguments.
243- if (i != nextArgIdx)
248+ if (i != nextArgIdx) {
249+ // Avoid claiming un-labeled defaulted parameters
250+ // by out-of-order un-labeled arguments or parts
251+ // of variadic argument sequence, because that might
252+ // be incorrect:
253+ // ```swift
254+ // func foo(_ a: Int, _ b: Int = 0, c: Int = 0, _ d: Int) {}
255+ // foo(1, c: 2, 3) // -> `3` will be claimed as '_ b:'.
256+ // ```
257+ if (argLabel.empty () && (hasDefault (i) || !forVariadic))
258+ continue ;
259+
244260 potentiallyOutOfOrder = true ;
261+ }
245262
246263 // Claim it.
247- return claim (name , i);
264+ return claim (paramLabel , i);
248265 }
249266
250267 // If we're not supposed to attempt any fixes, we're done.
@@ -268,8 +285,8 @@ matchCallArguments(ArrayRef<AnyFunctionType::Param> args,
268285 // Claim this argument if we are asked to ignore labeling failure,
269286 // only if argument doesn't have a label when parameter expected
270287 // it to, or vice versa.
271- if (name .empty () || argLabel.empty ())
272- return claim (name , nextArgIdx);
288+ if (paramLabel .empty () || argLabel.empty ())
289+ return claim (paramLabel , nextArgIdx);
273290 }
274291
275292 // Redundant keyword arguments.
@@ -478,7 +495,7 @@ matchCallArguments(ArrayRef<AnyFunctionType::Param> args,
478495 continue ;
479496
480497 // Parameters with defaults can be unfulfilled.
481- if (defaultMap. test (paramIdx))
498+ if (hasDefault (paramIdx))
482499 continue ;
483500
484501 listener.missingArgument (paramIdx);
0 commit comments