@@ -651,58 +651,67 @@ matchCallArguments(SmallVectorImpl<AnyFunctionType::Param> &args,
651
651
// parameter (or even worse - OoO parameter with label re-naming),
652
652
// we most likely have no idea what would be the best
653
653
// diagnostic for this situation, so let's just try to re-label.
654
- auto isOutOfOrderArgument = [&](bool hadLabelMismatch , unsigned argIdx ,
655
- unsigned prevArgIdx ) {
656
- if (hadLabelMismatch)
654
+ auto isOutOfOrderArgument = [&](unsigned toParamIdx , unsigned fromArgIdx ,
655
+ unsigned toArgIdx ) {
656
+ if (fromArgIdx <= toArgIdx) {
657
657
return false ;
658
+ }
659
+
660
+ auto newLabel = args[fromArgIdx].getLabel ();
661
+ auto oldLabel = args[toArgIdx].getLabel ();
658
662
659
- auto newLabel = args[argIdx].getLabel ();
660
- auto oldLabel = args[prevArgIdx].getLabel ();
663
+ if (newLabel != params[toParamIdx].getLabel ()) {
664
+ return false ;
665
+ }
661
666
662
- unsigned actualIndex = prevArgIdx ;
663
- for (; actualIndex != argIdx ; ++actualIndex ) {
667
+ auto paramIdx = toParamIdx + 1 ;
668
+ for (; paramIdx < params. size () ; ++paramIdx ) {
664
669
// Looks like new position (excluding defaulted parameters),
665
670
// has a valid label.
666
- if (newLabel == params[actualIndex ].getLabel ())
671
+ if (oldLabel == params[paramIdx ].getLabel ())
667
672
break ;
668
673
669
674
// If we are moving the the position with a different label
670
675
// and there is no default value for it, can't diagnose the
671
676
// problem as a simple re-ordering.
672
- if (!paramInfo.hasDefaultArgument (actualIndex ))
677
+ if (!paramInfo.hasDefaultArgument (paramIdx ))
673
678
return false ;
674
679
}
675
680
676
- for (unsigned i = actualIndex + 1 , n = params.size (); i != n; ++i) {
677
- if (oldLabel == params[i].getLabel ())
678
- break ;
679
-
680
- if (!paramInfo.hasDefaultArgument (i))
681
- return false ;
681
+ // label was not found
682
+ if (paramIdx == params.size ()) {
683
+ return false ;
682
684
}
683
685
684
686
return true ;
685
687
};
686
688
687
- unsigned argIdx = 0 ;
689
+ SmallVector<unsigned , 4 > paramToArgMap;
690
+ paramToArgMap.reserve (params.size ());
691
+ {
692
+ unsigned argIdx = 0 ;
693
+ for (const auto &binding : parameterBindings) {
694
+ paramToArgMap.push_back (argIdx);
695
+ argIdx += binding.size ();
696
+ }
697
+ }
698
+
688
699
// Enumerate the parameters and their bindings to see if any arguments are
689
700
// our of order
690
701
bool hadLabelMismatch = false ;
691
- for (auto binding : parameterBindings) {
692
- for (auto boundArgIdx : binding) {
702
+ for (const auto paramIdx : indices (params)) {
703
+ const auto toArgIdx = paramToArgMap[paramIdx];
704
+ const auto &binding = parameterBindings[paramIdx];
705
+ for (const auto paramBindIdx : indices (binding)) {
693
706
// We've found the parameter that has an out of order
694
707
// argument, and know the indices of the argument that
695
708
// needs to move (fromArgIdx) and the argument location
696
709
// it should move to (toArgIdx).
697
- auto fromArgIdx = boundArgIdx;
698
- auto toArgIdx = argIdx;
710
+ const auto fromArgIdx = binding[paramBindIdx];
699
711
700
- // If there is no re-ordering going on, and index is past
701
- // the number of parameters, it could only mean that this
702
- // is variadic parameter, so let's just move on.
703
- if (fromArgIdx == toArgIdx && toArgIdx >= params.size ()) {
712
+ // Does nothing for variadic tail.
713
+ if (params[paramIdx].isVariadic () && paramBindIdx > 0 ) {
704
714
assert (args[fromArgIdx].getLabel ().empty ());
705
- argIdx++;
706
715
continue ;
707
716
}
708
717
@@ -711,40 +720,40 @@ matchCallArguments(SmallVectorImpl<AnyFunctionType::Param> &args,
711
720
// one argument requires label and another one doesn't, but caller
712
721
// doesn't provide either, problem is going to be identified as
713
722
// out-of-order argument instead of label mismatch.
714
- auto expectedLabel = params[toArgIdx ].getLabel ();
715
- auto argumentLabel = args[fromArgIdx].getLabel ();
723
+ const auto expectedLabel = params[paramIdx ].getLabel ();
724
+ const auto argumentLabel = args[fromArgIdx].getLabel ();
716
725
717
726
if (argumentLabel != expectedLabel) {
718
727
// - The parameter is unnamed, in which case we try to fix the
719
728
// problem by removing the name.
720
729
if (expectedLabel.empty ()) {
721
730
hadLabelMismatch = true ;
722
- if (listener.extraneousLabel (toArgIdx ))
731
+ if (listener.extraneousLabel (paramIdx ))
723
732
return true ;
724
733
// - The argument is unnamed, in which case we try to fix the
725
734
// problem by adding the name.
726
735
} else if (argumentLabel.empty ()) {
727
736
hadLabelMismatch = true ;
728
- if (listener.missingLabel (toArgIdx ))
737
+ if (listener.missingLabel (paramIdx ))
729
738
return true ;
730
739
// - The argument label has a typo at the same position.
731
740
} else if (fromArgIdx == toArgIdx) {
732
741
hadLabelMismatch = true ;
733
- if (listener.incorrectLabel (toArgIdx ))
734
- return true ;
742
+ if (listener.incorrectLabel (paramIdx ))
743
+ return true ;
735
744
}
736
745
}
737
746
738
- if (boundArgIdx == argIdx ) {
747
+ if (fromArgIdx == toArgIdx ) {
739
748
// If the argument is in the right location, just continue
740
- argIdx++;
741
749
continue ;
742
750
}
743
751
744
752
// This situation looks like out-of-order argument but it's hard
745
753
// to say exactly without considering other factors, because it
746
754
// could be invalid labeling too.
747
- if (isOutOfOrderArgument (hadLabelMismatch, fromArgIdx, toArgIdx))
755
+ if (!hadLabelMismatch &&
756
+ isOutOfOrderArgument (paramIdx, fromArgIdx, toArgIdx))
748
757
return listener.outOfOrderArgument (fromArgIdx, toArgIdx);
749
758
750
759
SmallVector<Identifier, 8 > expectedLabels;
0 commit comments