Skip to content

Commit 8e6e963

Browse files
committed
[ConstraintSystem] implement new logic of reporting label ...
issues in `matchCallArguments`. It finds all of out of order label matchings. It reports label issues individually.
1 parent 92a0580 commit 8e6e963

File tree

1 file changed

+52
-110
lines changed

1 file changed

+52
-110
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 52 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -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 &param) {
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

847789
class ArgumentFailureTracker : public MatchCallArgumentListener {

0 commit comments

Comments
 (0)