@@ -716,132 +716,74 @@ matchCallArguments(SmallVectorImpl<AnyFunctionType::Param> &args,
716716 // If any arguments were provided out-of-order, check whether we have
717717 // violated any of the reordering rules.
718718 if (potentiallyOutOfOrder) {
719- // If we've seen label failures and now there is an out-of-order
720- // parameter (or even worse - OoO parameter with label re-naming),
721- // we most likely have no idea what would be the best
722- // diagnostic for this situation, so let's just try to re-label.
723- auto isOutOfOrderArgument = [&](unsigned toParamIdx, unsigned fromArgIdx,
724- unsigned toArgIdx) {
725- if (fromArgIdx <= toArgIdx) {
726- return false ;
727- }
728-
729- auto newLabel = args[fromArgIdx].getLabel ();
730- auto oldLabel = args[toArgIdx].getLabel ();
719+ // Fix all labeling failures.
731720
732- if (newLabel != params[toParamIdx]. getLabel ()) {
733- return false ;
734- }
721+ auto isTrailingClosureArgument = [&]( unsigned argIdx) -> bool {
722+ return unlabeledTrailingClosureArgIndex. hasValue () && argIdx == numArgs - 1 ;
723+ };
735724
736- auto paramIdx = toParamIdx + 1 ;
737- for (; paramIdx < params.size (); ++paramIdx) {
738- // Looks like new position (excluding defaulted parameters),
739- // has a valid label.
740- if (oldLabel == params[paramIdx].getLabel ())
741- break ;
725+ // Pick arguments mapped to some parameter.
726+ // It' used for searching expected destination of label which is out of
727+ // order.
728+ SmallVector<Optional<unsigned >, 4 > argBindings (args.size ());
729+ for (auto paramIdx : indices (params)) {
730+ if (parameterBindings[paramIdx].empty ())
731+ continue ;
732+ const auto argIdx = parameterBindings[paramIdx].front ();
733+ // Skip synthesized argument for missing argument
734+ if (argIdx >= numArgs)
735+ continue ;
742736
743- // If we are moving the the position with a different label
744- // and there is no default value for it, can't diagnose the
745- // problem as a simple re-ordering.
746- if (!paramInfo.hasDefaultArgument (paramIdx))
747- return false ;
748- }
737+ argBindings[argIdx] = paramIdx;
738+ }
749739
750- // label was not found
751- if ( paramIdx == params. size ( )) {
752- return false ;
753- }
740+ // Emit all label errors
741+ for ( const auto paramIdx : indices (params )) {
742+ if (parameterBindings[paramIdx]. empty ())
743+ continue ;
754744
755- return true ;
756- };
745+ // Skip synthesized argument for missing argument
746+ const auto argIdx = parameterBindings[paramIdx].front ();
747+ if (argIdx >= numArgs)
748+ continue ;
757749
758- SmallVector<unsigned , 4 > paramToArgMap;
759- paramToArgMap.reserve (params.size ());
760- {
761- unsigned argIdx = 0 ;
762- for (const auto &binding : parameterBindings) {
763- paramToArgMap.push_back (argIdx);
764- argIdx += binding.size ();
765- }
766- }
750+ // Trailing closure doesn't case label
751+ if (isTrailingClosureArgument (argIdx))
752+ continue ;
767753
768- // Enumerate the parameters and their bindings to see if any arguments are
769- // our of order
770- bool hadLabelMismatch = false ;
771- for (const auto paramIdx : indices (params)) {
772- const auto toArgIdx = paramToArgMap[paramIdx];
773- const auto &binding = parameterBindings[paramIdx];
774- for (const auto paramBindIdx : indices (binding)) {
775- // We've found the parameter that has an out of order
776- // argument, and know the indices of the argument that
777- // needs to move (fromArgIdx) and the argument location
778- // it should move to (toArgIdx).
779- const auto fromArgIdx = binding[paramBindIdx];
780-
781- // Does nothing for variadic tail.
782- if (params[paramIdx].isVariadic () && paramBindIdx > 0 ) {
783- assert (args[fromArgIdx].getLabel ().empty ());
784- continue ;
785- }
754+ const auto argLabel = args[argIdx].getLabel ();
755+ const auto paramLabel = params[paramIdx].getLabel ();
786756
787- // First let's double check if out-of-order argument is nothing
788- // more than a simple label mismatch, because in situation where
789- // one argument requires label and another one doesn't, but caller
790- // doesn't provide either, problem is going to be identified as
791- // out-of-order argument instead of label mismatch.
792- const auto expectedLabel = params[paramIdx].getLabel ();
793- const auto argumentLabel = args[fromArgIdx].getLabel ();
794-
795- if (argumentLabel != expectedLabel) {
796- // - The parameter is unnamed, in which case we try to fix the
797- // problem by removing the name.
798- if (expectedLabel.empty ()) {
799- hadLabelMismatch = true ;
800- if (listener.extraneousLabel (paramIdx))
801- return true ;
802- // - The argument is unnamed, in which case we try to fix the
803- // problem by adding the name.
804- } else if (argumentLabel.empty ()) {
805- hadLabelMismatch = true ;
806- if (listener.missingLabel (paramIdx))
807- return true ;
808- // - The argument label has a typo at the same position.
809- } else if (fromArgIdx == toArgIdx) {
810- hadLabelMismatch = true ;
811- if (listener.incorrectLabel (paramIdx))
812- return true ;
813- }
757+ if (argLabel != paramLabel) {
758+ // emit label wrong/missing/extra
759+ if (argLabel.empty ()) {
760+ if (listener.missingLabel (argIdx, paramIdx))
761+ return true ;
762+ } else if (paramLabel.empty ()) {
763+ if (listener.extraneousLabel (argIdx, paramIdx))
764+ return true ;
765+ } else {
766+ if (listener.incorrectLabel (argIdx, paramIdx))
767+ return true ;
814768 }
769+ }
815770
816- if (fromArgIdx == toArgIdx) {
817- // If the argument is in the right location, just continue
771+ for (unsigned leftArgIdx = 0 ; leftArgIdx < argIdx; leftArgIdx++) {
772+ const auto leftParamIdx = argBindings[leftArgIdx];
773+ if (!leftParamIdx)
818774 continue ;
819- }
820775
821- // This situation looks like out-of-order argument but it's hard
822- // to say exactly without considering other factors, because it
823- // could be invalid labeling too.
824- if (!hadLabelMismatch &&
825- isOutOfOrderArgument (paramIdx, fromArgIdx, toArgIdx))
826- return listener.outOfOrderArgument (fromArgIdx, toArgIdx);
827-
828- SmallVector<Identifier, 8 > expectedLabels;
829- llvm::transform (params, std::back_inserter (expectedLabels),
830- [](const AnyFunctionType::Param ¶m) {
831- return param.getLabel ();
832- });
833- return listener.relabelArguments (expectedLabels);
776+ if (paramIdx <= *leftParamIdx) {
777+ // emit out of order
778+ if (listener.outOfOrderArgument (argIdx, leftArgIdx))
779+ return true ;
780+ break ;
781+ }
834782 }
835783 }
836784 }
837785
838- // If no arguments were renamed, the call arguments match up with the
839- // parameters.
840- if (actualArgNames.empty ())
841- return false ;
842-
843- // The arguments were relabeled; notify the listener.
844- return listener.relabelArguments (actualArgNames);
786+ return false ;
845787}
846788
847789class ArgumentFailureTracker : public MatchCallArgumentListener {
0 commit comments