Skip to content

Commit 8d3409b

Browse files
committed
[ConstraintSystem] Allow argument matcher to continue in presence of missing/extra arguments
This makes it possible to find all of the problems related to a given set of arguments and fix/score each overload candidate correctly.
1 parent b214b8a commit 8d3409b

File tree

3 files changed

+42
-30
lines changed

3 files changed

+42
-30
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,9 @@ bool constraints::doesMemberRefApplyCurriedSelf(Type baseTy,
123123
return true;
124124
}
125125

126-
static bool
127-
areConservativelyCompatibleArgumentLabels(OverloadChoice choice,
128-
ArrayRef<FunctionType::Param> args,
129-
bool hasTrailingClosure) {
126+
static bool areConservativelyCompatibleArgumentLabels(
127+
OverloadChoice choice, SmallVectorImpl<FunctionType::Param> &args,
128+
bool hasTrailingClosure) {
130129
ValueDecl *decl = nullptr;
131130
switch (choice.getKind()) {
132131
case OverloadChoiceKind::Decl:
@@ -217,7 +216,7 @@ static bool acceptsTrailingClosure(const AnyFunctionType::Param &param) {
217216
// FIXME: This should return ConstraintSystem::TypeMatchResult instead
218217
// to give more information to the solver about the failure.
219218
bool constraints::
220-
matchCallArguments(ArrayRef<AnyFunctionType::Param> args,
219+
matchCallArguments(SmallVectorImpl<AnyFunctionType::Param> &args,
221220
ArrayRef<AnyFunctionType::Param> params,
222221
const ParameterListInfo &paramInfo,
223222
bool hasTrailingClosure,
@@ -571,8 +570,6 @@ matchCallArguments(ArrayRef<AnyFunctionType::Param> args,
571570
if (listener.extraArgument(index))
572571
return true;
573572
}
574-
575-
return false;
576573
}
577574

578575
// FIXME: If we had the actual parameters and knew the body names, those
@@ -582,7 +579,6 @@ matchCallArguments(ArrayRef<AnyFunctionType::Param> args,
582579

583580
// If we have any unfulfilled parameters, check them now.
584581
if (haveUnfulfilledParams) {
585-
bool hasSynthesizedArgs = false;
586582
for (paramIdx = 0; paramIdx != numParams; ++paramIdx) {
587583
// If we have a binding for this parameter, we're done.
588584
if (!parameterBindings[paramIdx].empty())
@@ -600,17 +596,11 @@ matchCallArguments(ArrayRef<AnyFunctionType::Param> args,
600596

601597
if (auto newArgIdx = listener.missingArgument(paramIdx)) {
602598
parameterBindings[paramIdx].push_back(*newArgIdx);
603-
hasSynthesizedArgs = true;
604599
continue;
605600
}
606601

607602
return true;
608603
}
609-
610-
// If all of the missing arguments have been synthesized,
611-
// let's stop since we have found the problem.
612-
if (hasSynthesizedArgs)
613-
return false;
614604
}
615605

616606
// If any arguments were provided out-of-order, check whether we have
@@ -873,6 +863,15 @@ class ArgumentFailureTracker : public MatchCallArgumentListener {
873863

874864
bool outOfOrderArgument(unsigned argIdx, unsigned prevArgIdx) override {
875865
if (CS.shouldAttemptFixes()) {
866+
// If some of the arguments are missing/extraneous, no reason to
867+
// record a fix for this, increase the score so there is a way
868+
// to identify that there is something going on besides just missing
869+
// arguments.
870+
if (NumSynthesizedArgs || !ExtraArguments.empty()) {
871+
CS.increaseScore(SK_Fix);
872+
return false;
873+
}
874+
876875
auto *fix = MoveOutOfOrderArgument::create(
877876
CS, argIdx, prevArgIdx, Bindings, CS.getConstraintLocator(Locator));
878877
return CS.recordFix(fix);
@@ -885,31 +884,42 @@ class ArgumentFailureTracker : public MatchCallArgumentListener {
885884
if (!CS.shouldAttemptFixes())
886885
return true;
887886

887+
// TODO(diagnostics): If re-labeling is mixed with extra arguments,
888+
// let's produce a fix only for extraneous arguments for now,
889+
// because they'd share a locator path which (currently) means
890+
// one fix would overwrite another.
891+
if (!ExtraArguments.empty()) {
892+
CS.increaseScore(SK_Fix);
893+
return false;
894+
}
895+
888896
auto *anchor = Locator.getBaseLocator()->getAnchor();
889-
if (!anchor)
897+
if (!anchor || Arguments.size() != newLabels.size())
890898
return true;
891899

892900
unsigned numExtraneous = 0;
893-
for (unsigned paramIdx = 0, n = Bindings.size(); paramIdx != n;
894-
++paramIdx) {
895-
if (Bindings[paramIdx].empty())
901+
unsigned numRenames = 0;
902+
for (unsigned i : indices(newLabels)) {
903+
auto argLabel = Arguments[i].getLabel();
904+
auto paramLabel = newLabels[i];
905+
906+
if (argLabel == paramLabel)
896907
continue;
897908

898-
const auto paramLabel = Parameters[paramIdx].getLabel();
899-
for (auto argIdx : Bindings[paramIdx]) {
900-
auto argLabel = Arguments[argIdx].getLabel();
901-
if (paramLabel.empty() && !argLabel.empty())
909+
if (!argLabel.empty()) {
910+
if (paramLabel.empty())
902911
++numExtraneous;
912+
else
913+
++numRenames;
903914
}
904915
}
905916

906917
auto *locator = CS.getConstraintLocator(Locator);
907918
auto *fix = RelabelArguments::create(CS, newLabels, locator);
908-
CS.recordFix(fix);
909-
// Re-labeling fixes with extraneous labels should take
910-
// lower priority vs. other fixes on same/different
911-
// overload(s) where labels did line up correctly.
912-
CS.increaseScore(ScoreKind::SK_Fix, numExtraneous);
919+
// Re-labeling fixes with extraneous/incorrect labels should be
920+
// lower priority vs. other fixes on same/different overload(s)
921+
// where labels did line up correctly.
922+
CS.recordFix(fix, /*impact=*/1 + numExtraneous * 2 + numRenames * 3);
913923
return false;
914924
}
915925

lib/Sema/CalleeCandidateInfo.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,12 +314,14 @@ CalleeCandidateInfo::ClosenessResultTy CalleeCandidateInfo::evaluateCloseness(
314314
return true;
315315
}
316316
} listener;
317-
317+
318318
// Use matchCallArguments to determine how close the argument list is (in
319319
// shape) to the specified candidates parameters. This ignores the concrete
320320
// types of the arguments, looking only at the argument labels etc.
321+
SmallVector<AnyFunctionType::Param, 4> arguments(actualArgs.begin(),
322+
actualArgs.end());
321323
SmallVector<ParamBinding, 4> paramBindings;
322-
if (matchCallArguments(actualArgs, candArgs,
324+
if (matchCallArguments(arguments, candArgs,
323325
candParamInfo,
324326
hasTrailingClosure,
325327
/*allowFixes:*/ true,

lib/Sema/ConstraintSystem.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3953,7 +3953,7 @@ class MatchCallArgumentListener {
39533953
/// \param parameterBindings Will be populated with the arguments that are
39543954
/// bound to each of the parameters.
39553955
/// \returns true if the call arguments could not be matched to the parameters.
3956-
bool matchCallArguments(ArrayRef<AnyFunctionType::Param> args,
3956+
bool matchCallArguments(SmallVectorImpl<AnyFunctionType::Param> &args,
39573957
ArrayRef<AnyFunctionType::Param> params,
39583958
const ParameterListInfo &paramInfo,
39593959
bool hasTrailingClosure,

0 commit comments

Comments
 (0)