Skip to content

Commit e98c72b

Browse files
committed
[ConstraintSystem] adjust matching position of unlabeled parameter ...
by considering unbounded parameter which is at left of current parameter in `matchCallArgument`. It avoids matching which has unwanted crossing pairs between argument and parameter. It provides natural relabeling diagnostics without reconstructing aligned matching pairs when out of ordered mapping happens like old implementation.
1 parent 37cc05f commit e98c72b

File tree

1 file changed

+50
-6
lines changed

1 file changed

+50
-6
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ matchCallArguments(SmallVectorImpl<AnyFunctionType::Param> &args,
267267
// Local function that retrieves the next unclaimed argument with the given
268268
// name (which may be empty). This routine claims the argument.
269269
auto claimNextNamed = [&](unsigned &nextArgIdx, Identifier paramLabel,
270+
Optional<unsigned> paramIdx,
270271
bool ignoreNameMismatch,
271272
bool forVariadic = false) -> Optional<unsigned> {
272273
// Skip over any claimed arguments.
@@ -276,6 +277,47 @@ matchCallArguments(SmallVectorImpl<AnyFunctionType::Param> &args,
276277
if (numClaimedArgs == numArgs)
277278
return None;
278279

280+
/// When we determine which argument is bound to unlabeled parameter,
281+
/// consider still unbounded parameter which is prior to current parameter.
282+
/// In order not to intersect binding position that remaining parameter will
283+
/// bind later, skip a unlabeled argument as much as it can.
284+
///
285+
/// For example:
286+
/// @code
287+
/// func f(aa: Int, _ bb: Int) {}
288+
/// f(0, 1)
289+
/// @endcode
290+
/// Choice argument[1] for parameter[1] so that parameter[0] will be bounded
291+
/// to argument[0] later.
292+
///
293+
/// Because variadics parameter can be bounded with more than one arguments,
294+
/// they don't this.
295+
if (paramLabel.empty() && paramIdx && !forVariadic &&
296+
!params[*paramIdx].isVariadic()) {
297+
unsigned unboundedParamCount = 0;
298+
for (unsigned pi = 0; pi < *paramIdx; pi++) {
299+
if (parameterBindings[pi].empty()) {
300+
if (params[pi].isVariadic() || paramInfo.hasDefaultArgument(pi))
301+
continue;
302+
303+
unboundedParamCount++;
304+
}
305+
}
306+
307+
unsigned keepedArgCount = 0;
308+
for (unsigned ai = nextArgIdx; ai < numArgs; ai++) {
309+
if (claimedArgs[ai])
310+
continue;
311+
312+
nextArgIdx = std::max(nextArgIdx, ai);
313+
314+
if (keepedArgCount >= unboundedParamCount) {
315+
break;
316+
}
317+
keepedArgCount++;
318+
}
319+
}
320+
279321
// Go hunting for an unclaimed argument whose name does match.
280322
Optional<unsigned> claimedWithSameName;
281323
for (unsigned i = nextArgIdx; i != numArgs; ++i) {
@@ -368,8 +410,8 @@ matchCallArguments(SmallVectorImpl<AnyFunctionType::Param> &args,
368410
// Handle variadic parameters.
369411
if (param.isVariadic()) {
370412
// Claim the next argument with the name of this parameter.
371-
auto claimed =
372-
claimNextNamed(nextArgIdx, param.getLabel(), ignoreNameMismatch);
413+
auto claimed = claimNextNamed(nextArgIdx, param.getLabel(), paramIdx,
414+
ignoreNameMismatch);
373415

374416
// If there was no such argument, leave the parameter unfulfilled.
375417
if (!claimed) {
@@ -390,8 +432,10 @@ matchCallArguments(SmallVectorImpl<AnyFunctionType::Param> &args,
390432
{
391433
nextArgIdx = *claimed;
392434
// Claim any additional unnamed arguments.
393-
while (
394-
(claimed = claimNextNamed(nextArgIdx, Identifier(), false, true))) {
435+
while ((claimed = claimNextNamed(
436+
nextArgIdx, /*paramLabel=*/Identifier(), /*paramIdx=*/None,
437+
/*ignoreNameMismatch=*/false,
438+
/*forVariadic=*/true))) {
395439
parameterBindings[paramIdx].push_back(*claimed);
396440
}
397441
}
@@ -401,8 +445,8 @@ matchCallArguments(SmallVectorImpl<AnyFunctionType::Param> &args,
401445
}
402446

403447
// Try to claim an argument for this parameter.
404-
if (auto claimed =
405-
claimNextNamed(nextArgIdx, param.getLabel(), ignoreNameMismatch)) {
448+
if (auto claimed = claimNextNamed(nextArgIdx, param.getLabel(), paramIdx,
449+
ignoreNameMismatch)) {
406450
parameterBindings[paramIdx].push_back(*claimed);
407451
return;
408452
}

0 commit comments

Comments
 (0)