-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[ConstraintSystem] adjust matching position of unlabeled parameter #32037
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -289,6 +289,7 @@ matchCallArguments(SmallVectorImpl<AnyFunctionType::Param> &args, | |
// Local function that retrieves the next unclaimed argument with the given | ||
// name (which may be empty). This routine claims the argument. | ||
auto claimNextNamed = [&](unsigned &nextArgIdx, Identifier paramLabel, | ||
Optional<unsigned> paramIdx, | ||
bool ignoreNameMismatch, | ||
bool forVariadic = false) -> Optional<unsigned> { | ||
// Skip over any claimed arguments. | ||
|
@@ -298,6 +299,47 @@ matchCallArguments(SmallVectorImpl<AnyFunctionType::Param> &args, | |
if (numClaimedArgs == numArgs) | ||
return None; | ||
|
||
/// When we determine which argument is bound to unlabeled parameter, | ||
/// consider still unbounded parameter which is prior to current parameter. | ||
/// In order not to intersect binding position that remaining parameter will | ||
/// bind later, skip a unlabeled argument as much as it can. | ||
/// | ||
/// For example: | ||
/// @code | ||
/// func f(aa: Int, _ bb: Int) {} | ||
/// f(0, 1) | ||
/// @endcode | ||
/// Choice argument[1] for parameter[1] so that parameter[0] will be bounded | ||
/// to argument[0] later. | ||
/// | ||
/// Because variadics parameter can be bounded with more than one arguments, | ||
/// they don't this. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's re-phrase - There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks! |
||
if (paramLabel.empty() && paramIdx && !forVariadic && | ||
!params[*paramIdx].isVariadic()) { | ||
unsigned unboundedParamCount = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about |
||
for (unsigned pi = 0; pi < *paramIdx; pi++) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you please re-name |
||
if (parameterBindings[pi].empty()) { | ||
if (params[pi].isVariadic() || paramInfo.hasDefaultArgument(pi)) | ||
continue; | ||
|
||
unboundedParamCount++; | ||
} | ||
} | ||
|
||
unsigned keepedArgCount = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be |
||
for (unsigned ai = nextArgIdx; ai < numArgs; ai++) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you please re-name |
||
if (claimedArgs[ai]) | ||
continue; | ||
|
||
nextArgIdx = std::max(nextArgIdx, ai); | ||
|
||
if (keepedArgCount >= unboundedParamCount) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why this is relationship between unclaimed arguments and parameters important that way? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is exactly important.
I explain with two examples. example1func f(aa: Int, _ bb: Int) {}
f(0, 1) I use following definitions for explanation:
With example1, current behavior is following.
I want to shift binding target for With example1, patched behavior is following:
Labeling errors are same. example2func f(aa: Int, bb: Int, _ cc: Int, dd: Int = 0) {}
f(0, 1, 2) With example1, current behavior is following.
I want to shift binding target for With example1, patched behavior is following:
In this case, labeling errors are same. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I understand the intent here but the problem is that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @xedin |
||
break; | ||
} | ||
keepedArgCount++; | ||
} | ||
} | ||
|
||
// Go hunting for an unclaimed argument whose name does match. | ||
Optional<unsigned> claimedWithSameName; | ||
for (unsigned i = nextArgIdx; i != numArgs; ++i) { | ||
|
@@ -390,8 +432,8 @@ matchCallArguments(SmallVectorImpl<AnyFunctionType::Param> &args, | |
// Handle variadic parameters. | ||
if (param.isVariadic()) { | ||
// Claim the next argument with the name of this parameter. | ||
auto claimed = | ||
claimNextNamed(nextArgIdx, param.getLabel(), ignoreNameMismatch); | ||
auto claimed = claimNextNamed(nextArgIdx, param.getLabel(), paramIdx, | ||
ignoreNameMismatch); | ||
|
||
// If there was no such argument, leave the parameter unfulfilled. | ||
if (!claimed) { | ||
|
@@ -412,8 +454,10 @@ matchCallArguments(SmallVectorImpl<AnyFunctionType::Param> &args, | |
{ | ||
nextArgIdx = *claimed; | ||
// Claim any additional unnamed arguments. | ||
while ( | ||
(claimed = claimNextNamed(nextArgIdx, Identifier(), false, true))) { | ||
while ((claimed = claimNextNamed( | ||
nextArgIdx, /*paramLabel=*/Identifier(), /*paramIdx=*/None, | ||
/*ignoreNameMismatch=*/false, | ||
/*forVariadic=*/true))) { | ||
parameterBindings[paramIdx].push_back(*claimed); | ||
} | ||
} | ||
|
@@ -423,8 +467,8 @@ matchCallArguments(SmallVectorImpl<AnyFunctionType::Param> &args, | |
} | ||
|
||
// Try to claim an argument for this parameter. | ||
if (auto claimed = | ||
claimNextNamed(nextArgIdx, param.getLabel(), ignoreNameMismatch)) { | ||
if (auto claimed = claimNextNamed(nextArgIdx, param.getLabel(), paramIdx, | ||
ignoreNameMismatch)) { | ||
parameterBindings[paramIdx].push_back(*claimed); | ||
return; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -705,12 +705,10 @@ func testUnlabeledParameterBindingPosition() { | |
// expected-error@-1:6 {{missing argument label 'aa:' in call}} | ||
|
||
f(0, xx: 1) | ||
// expected-error@-1:7 {{missing argument for parameter 'aa' in call}} | ||
// expected-error@-2:14 {{extra argument 'xx' in call}} | ||
// expected-error@-1:6 {{incorrect argument labels in call (have '_:xx:', expected 'aa:_:')}} | ||
|
||
f(xx: 0, 1) | ||
// expected-error@-1:7 {{missing argument for parameter 'aa' in call}} | ||
// expected-error@-2:14 {{extra argument in call}} | ||
// expected-error@-1:6 {{incorrect argument label in call (have 'xx:_:', expected 'aa:_:')}} | ||
|
||
f(0, 1, 9) | ||
// expected-error@-1:13 {{extra argument in call}} | ||
|
@@ -719,15 +717,15 @@ func testUnlabeledParameterBindingPosition() { | |
// expected-error@-1:17 {{extra argument 'xx' in call}} | ||
|
||
f(xx: 91, 1, 92) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be diagnosed as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm... Yes.
|
||
// expected-error@-1 {{extra arguments at positions #2, #3 in call}} | ||
// expected-error@-1 {{extra arguments at positions #1, #3 in call}} | ||
// expected-error@-2 {{missing argument for parameter 'aa' in call}} | ||
} | ||
|
||
do { | ||
func f(_ aa: Int, bb: Int, _ cc: Int) { } | ||
|
||
f(bb: 1, 0, 2) | ||
// expected-error@-1 {{unnamed argument #3 must precede argument 'bb'}} | ||
// expected-error@-1 {{unnamed argument #2 must precede argument 'bb'}} | ||
} | ||
|
||
do { | ||
|
@@ -755,15 +753,17 @@ func testUnlabeledParameterBindingPosition() { | |
func f(aa: Int, _ bb: Int, _ cc: Int) {} | ||
|
||
f(0, 1) | ||
// expected-error@-1:7 {{missing argument for parameter 'aa' in call}} | ||
// expected-error@-1:6 {{missing argument label 'aa:' in call}} | ||
// expected-error@-2:11 {{missing argument for parameter #3 in call}} | ||
} | ||
|
||
do { | ||
// expected-note@+1 *{{'f(aa:_:_:)' declared here}} | ||
func f(aa: Int, _ bb: Int = 81, _ cc: Int) {} | ||
|
||
f(0, 1) | ||
// expected-error@-1:7 {{missing argument for parameter 'aa' in call}} | ||
// expected-error@-1:6 {{missing argument label 'aa:' in call}} | ||
// expected-error@-2:11 {{missing argument for parameter #3 in call}} | ||
} | ||
|
||
do { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit:
bounded
->bound
.