Skip to content

Commit 5dd5454

Browse files
committed
[CSSimplify] Determine if argument is out-of-order while matching labels
Instead of rerouting out-of-order into re-labeling during diagnostics, let's do that as part of the label matching algorithm.
1 parent 48a6de1 commit 5dd5454

File tree

4 files changed

+66
-57
lines changed

4 files changed

+66
-57
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 2 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -3369,8 +3369,6 @@ class ArgumentMatcher : public MatchCallArgumentListener {
33693369
// Stores parameter bindings determined by call to matchCallArguments.
33703370
SmallVector<ParamBinding, 4> Bindings;
33713371

3372-
unsigned NumLabelFailures = 0;
3373-
33743372
public:
33753373
ArgumentMatcher(Expr *fnExpr, Expr *argExpr,
33763374
ArrayRef<AnyFunctionType::Param> &params,
@@ -3547,68 +3545,22 @@ class ArgumentMatcher : public MatchCallArgumentListener {
35473545
}
35483546

35493547
bool missingLabel(unsigned paramIdx) override {
3550-
++NumLabelFailures;
35513548
return false;
35523549
}
35533550

35543551
bool extraneousLabel(unsigned paramIdx) override {
3555-
++NumLabelFailures;
35563552
return false;
35573553
}
35583554

35593555
bool incorrectLabel(unsigned paramIdx) override {
3560-
++NumLabelFailures;
35613556
return false;
35623557
}
35633558

3564-
void outOfOrderArgument(unsigned argIdx, unsigned prevArgIdx) override {
3559+
bool outOfOrderArgument(unsigned argIdx, unsigned prevArgIdx) override {
35653560
auto tuple = cast<TupleExpr>(ArgExpr);
35663561
Identifier first = tuple->getElementName(argIdx);
35673562
Identifier second = tuple->getElementName(prevArgIdx);
35683563

3569-
// If we've seen label failures and now there is an out-of-order
3570-
// parameter (or even worse - OoO parameter with label re-naming),
3571-
// we most likely have no idea what would be the best
3572-
// diagnostic for this situation, so let's just try to re-label.
3573-
auto shouldDiagnoseOoO = [&](Identifier newLabel, Identifier oldLabel) {
3574-
if (NumLabelFailures > 0)
3575-
return false;
3576-
3577-
unsigned actualIndex = prevArgIdx;
3578-
for (; actualIndex != argIdx; ++actualIndex) {
3579-
// Looks like new position (excluding defaulted parameters),
3580-
// has a valid label.
3581-
if (newLabel == Parameters[actualIndex].getLabel())
3582-
break;
3583-
3584-
// If we are moving the the position with a different label
3585-
// and there is no default value for it, can't diagnose the
3586-
// problem as a simple re-ordering.
3587-
if (!DefaultMap.test(actualIndex))
3588-
return false;
3589-
}
3590-
3591-
for (unsigned i = actualIndex + 1, n = Parameters.size(); i != n; ++i) {
3592-
if (oldLabel == Parameters[i].getLabel())
3593-
break;
3594-
3595-
if (!DefaultMap.test(i))
3596-
return false;
3597-
}
3598-
3599-
return true;
3600-
};
3601-
3602-
if (!shouldDiagnoseOoO(first, second)) {
3603-
SmallVector<Identifier, 8> paramLabels;
3604-
llvm::transform(Parameters, std::back_inserter(paramLabels),
3605-
[](const AnyFunctionType::Param &param) {
3606-
return param.getLabel();
3607-
});
3608-
relabelArguments(paramLabels);
3609-
return;
3610-
}
3611-
36123564
// Build a mapping from arguments to parameters.
36133565
SmallVector<unsigned, 4> argBindings(tuple->getNumElements());
36143566
for (unsigned paramIdx = 0; paramIdx != Bindings.size(); ++paramIdx) {
@@ -3671,6 +3623,7 @@ class ArgumentMatcher : public MatchCallArgumentListener {
36713623
}
36723624

36733625
Diagnosed = true;
3626+
return true;
36743627
}
36753628

36763629
bool relabelArguments(ArrayRef<Identifier> newNames) override {

lib/Sema/CSSimplify.cpp

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@ bool MatchCallArgumentListener::incorrectLabel(unsigned paramIdx) {
4444
return true;
4545
}
4646

47-
void MatchCallArgumentListener::outOfOrderArgument(unsigned argIdx,
47+
bool MatchCallArgumentListener::outOfOrderArgument(unsigned argIdx,
4848
unsigned prevArgIdx) {
49+
return true;
4950
}
5051

5152
bool MatchCallArgumentListener::relabelArguments(ArrayRef<Identifier> newNames){
@@ -578,9 +579,47 @@ matchCallArguments(ArrayRef<AnyFunctionType::Param> args,
578579
// If any arguments were provided out-of-order, check whether we have
579580
// violated any of the reordering rules.
580581
if (potentiallyOutOfOrder) {
582+
// If we've seen label failures and now there is an out-of-order
583+
// parameter (or even worse - OoO parameter with label re-naming),
584+
// we most likely have no idea what would be the best
585+
// diagnostic for this situation, so let's just try to re-label.
586+
auto isOutOfOrderArgument = [&](bool hadLabelMismatch, unsigned argIdx,
587+
unsigned prevArgIdx) {
588+
if (hadLabelMismatch)
589+
return false;
590+
591+
auto newLabel = args[argIdx].getLabel();
592+
auto oldLabel = args[prevArgIdx].getLabel();
593+
594+
unsigned actualIndex = prevArgIdx;
595+
for (; actualIndex != argIdx; ++actualIndex) {
596+
// Looks like new position (excluding defaulted parameters),
597+
// has a valid label.
598+
if (newLabel == params[actualIndex].getLabel())
599+
break;
600+
601+
// If we are moving the the position with a different label
602+
// and there is no default value for it, can't diagnose the
603+
// problem as a simple re-ordering.
604+
if (!defaultMap.test(actualIndex))
605+
return false;
606+
}
607+
608+
for (unsigned i = actualIndex + 1, n = params.size(); i != n; ++i) {
609+
if (oldLabel == params[i].getLabel())
610+
break;
611+
612+
if (!defaultMap.test(i))
613+
return false;
614+
}
615+
616+
return true;
617+
};
618+
581619
unsigned argIdx = 0;
582620
// Enumerate the parameters and their bindings to see if any arguments are
583621
// our of order
622+
bool hadLabelMismatch = false;
584623
for (auto binding : parameterBindings) {
585624
for (auto boundArgIdx : binding) {
586625
// We've found the parameter that has an out of order
@@ -611,17 +650,20 @@ matchCallArguments(ArrayRef<AnyFunctionType::Param> args,
611650
// - The parameter is unnamed, in which case we try to fix the
612651
// problem by removing the name.
613652
if (expectedLabel.empty()) {
653+
hadLabelMismatch = true;
614654
if (listener.extraneousLabel(toArgIdx))
615655
return true;
616656
// - The argument is unnamed, in which case we try to fix the
617657
// problem by adding the name.
618658
} else if (argumentLabel.empty()) {
659+
hadLabelMismatch = true;
619660
if (listener.missingLabel(toArgIdx))
620661
return true;
621662
// - The argument label has a typo at the same position.
622-
} else if (fromArgIdx == toArgIdx &&
623-
listener.incorrectLabel(toArgIdx)) {
624-
return true;
663+
} else if (fromArgIdx == toArgIdx) {
664+
hadLabelMismatch = true;
665+
if (listener.incorrectLabel(toArgIdx))
666+
return true;
625667
}
626668
}
627669

@@ -631,8 +673,18 @@ matchCallArguments(ArrayRef<AnyFunctionType::Param> args,
631673
continue;
632674
}
633675

634-
listener.outOfOrderArgument(fromArgIdx, toArgIdx);
635-
return true;
676+
// This situation looks like out-of-order argument but it's hard
677+
// to say exactly without considering other factors, because it
678+
// could be invalid labeling too.
679+
if (isOutOfOrderArgument(hadLabelMismatch, fromArgIdx, toArgIdx))
680+
return listener.outOfOrderArgument(fromArgIdx, toArgIdx);
681+
682+
SmallVector<Identifier, 8> expectedLabels;
683+
llvm::transform(params, std::back_inserter(expectedLabels),
684+
[](const AnyFunctionType::Param &param) {
685+
return param.getLabel();
686+
});
687+
return listener.relabelArguments(expectedLabels);
636688
}
637689
}
638690
}

lib/Sema/CalleeCandidateInfo.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,8 +346,9 @@ CalleeCandidateInfo::ClosenessResultTy CalleeCandidateInfo::evaluateCloseness(
346346
result = CC_ArgumentLabelMismatch;
347347
return true;
348348
}
349-
void outOfOrderArgument(unsigned argIdx, unsigned prevArgIdx) override {
349+
bool outOfOrderArgument(unsigned argIdx, unsigned prevArgIdx) override {
350350
result = CC_ArgumentLabelMismatch;
351+
return true;
351352
}
352353
bool relabelArguments(ArrayRef<Identifier> newNames) override {
353354
result = CC_ArgumentLabelMismatch;

lib/Sema/ConstraintSystem.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3506,7 +3506,10 @@ class MatchCallArgumentListener {
35063506
///
35073507
/// \param argIdx The argument that came too late in the argument list.
35083508
/// \param prevArgIdx The argument that the \c argIdx should have preceded.
3509-
virtual void outOfOrderArgument(unsigned argIdx, unsigned prevArgIdx);
3509+
///
3510+
/// \returns true to indicate that this should cause a failure, false
3511+
/// otherwise.
3512+
virtual bool outOfOrderArgument(unsigned argIdx, unsigned prevArgIdx);
35103513

35113514
/// Indicates that the arguments need to be relabeled to match the parameters.
35123515
///

0 commit comments

Comments
 (0)