[ConstraintSystem] Fix out-of-order arguments

Detect and fix out-of-order arguments by moving them into correct
positions.
This commit is contained in:
Pavel Yaskevich
2019-03-04 18:02:23 -08:00
parent 5dd5454a75
commit 1d2c3633fb
3 changed files with 60 additions and 3 deletions

View File

@@ -371,3 +371,14 @@ AddMissingArguments::create(ConstraintSystem &cs, FunctionType *funcType,
void *mem = cs.getAllocator().Allocate(size, alignof(AddMissingArguments));
return new (mem) AddMissingArguments(cs, funcType, synthesizedArgs, locator);
}
bool MoveOutOfOrderArgument::diagnose(Expr *root, bool asNote) const {
return false;
}
MoveOutOfOrderArgument *MoveOutOfOrderArgument::create(
ConstraintSystem &cs, unsigned argIdx, unsigned prevArgIdx,
ArrayRef<ParamBinding> bindings, ConstraintLocator *locator) {
return new (cs.getAllocator())
MoveOutOfOrderArgument(cs, argIdx, prevArgIdx, bindings, locator);
}

View File

@@ -129,6 +129,9 @@ enum class FixKind : uint8_t {
/// Allow single tuple closure parameter destructuring into N arguments.
AllowClosureParameterDestructuring,
/// If there is out-of-order argument, let's fix that by re-ordering.
MoveOutOfOrderArgument,
};
class ConstraintFix {
@@ -681,6 +684,35 @@ private:
}
};
class MoveOutOfOrderArgument final : public ConstraintFix {
using ParamBinding = SmallVector<unsigned, 1>;
unsigned ArgIdx;
unsigned PrevArgIdx;
SmallVector<ParamBinding, 4> Bindings;
MoveOutOfOrderArgument(ConstraintSystem &cs, unsigned argIdx,
unsigned prevArgIdx, ArrayRef<ParamBinding> bindings,
ConstraintLocator *locator)
: ConstraintFix(cs, FixKind::MoveOutOfOrderArgument, locator),
ArgIdx(argIdx), PrevArgIdx(prevArgIdx),
Bindings(bindings.begin(), bindings.end()) {}
public:
std::string getName() const override {
return "move out-of-order argument to correct position";
}
bool diagnose(Expr *root, bool asNote = false) const override;
static MoveOutOfOrderArgument *create(ConstraintSystem &cs,
unsigned argIdx,
unsigned prevArgIdx,
ArrayRef<ParamBinding> bindings,
ConstraintLocator *locator);
};
} // end namespace constraints
} // end namespace swift

View File

@@ -855,11 +855,14 @@ getCalleeDeclAndArgs(ConstraintSystem &cs,
class ArgumentFailureTracker : public MatchCallArgumentListener {
ConstraintSystem &CS;
SmallVectorImpl<ParamBinding> &Bindings;
ConstraintLocatorBuilder Locator;
public:
ArgumentFailureTracker(ConstraintSystem &cs, ConstraintLocatorBuilder locator)
: CS(cs), Locator(locator) {}
ArgumentFailureTracker(ConstraintSystem &cs,
SmallVectorImpl<ParamBinding> &bindings,
ConstraintLocatorBuilder locator)
: CS(cs), Bindings(bindings), Locator(locator) {}
bool missingLabel(unsigned paramIndex) override {
return !CS.shouldAttemptFixes();
@@ -873,6 +876,16 @@ public:
return !CS.shouldAttemptFixes();
}
bool outOfOrderArgument(unsigned argIdx, unsigned prevArgIdx) override {
if (CS.shouldAttemptFixes()) {
auto *fix = MoveOutOfOrderArgument::create(
CS, argIdx, prevArgIdx, Bindings, CS.getConstraintLocator(Locator));
return CS.recordFix(fix);
}
return true;
}
bool relabelArguments(ArrayRef<Identifier> newLabels) override {
if (!CS.shouldAttemptFixes())
return true;
@@ -940,8 +953,8 @@ ConstraintSystem::TypeMatchResult constraints::matchCallArguments(
}
// Match up the call arguments to the parameters.
ArgumentFailureTracker listener(cs, locator);
SmallVector<ParamBinding, 4> parameterBindings;
ArgumentFailureTracker listener(cs, parameterBindings, locator);
if (constraints::matchCallArguments(argsWithLabels, params,
defaultMap,
hasTrailingClosure,
@@ -6022,6 +6035,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
case FixKind::AllowInvalidPartialApplication:
case FixKind::AllowInvalidInitRef:
case FixKind::AllowClosureParameterDestructuring:
case FixKind::MoveOutOfOrderArgument:
llvm_unreachable("handled elsewhere");
}