[Function builders] Use one-way constraints for closure parameters.

Introduce one-way constraints for the parameters of closures to which a
function builder is being applied. This was an intended part of the
model when one-way constraints were introduced, but somehow got
missed. This should further break up large constraints systems for
faster solving, and *most likely* won't break much source code in
practice.

Fixes rdar://problem/64231116.
This commit is contained in:
Doug Gregor
2020-06-10 16:58:03 -07:00
parent 9a3d863c71
commit f60d17bf3d
3 changed files with 46 additions and 24 deletions

View File

@@ -7222,6 +7222,24 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar,
auto *closure = castToExpr<ClosureExpr>(closureLocator->getAnchor());
auto *inferredClosureType = getClosureType(closure);
// Determine whether a function builder will be applied.
Type functionBuilderType;
ConstraintLocator *calleeLocator = nullptr;
if (auto last = locator.last()) {
if (auto argToParam = last->getAs<LocatorPathElt::ApplyArgToParam>()) {
calleeLocator = getCalleeLocator(getConstraintLocator(locator));
functionBuilderType = getFunctionBuilderTypeFor(
*this, argToParam->getParamIdx(), calleeLocator);
}
}
// Determine whether to introduce one-way constraints between the parameter's
// type as seen in the body of the closure and the external parameter
// type.
bool oneWayConstraints =
getASTContext().TypeCheckerOpts.EnableOneWayClosureParameters ||
functionBuilderType;
auto *paramList = closure->getParameters();
SmallVector<AnyFunctionType::Param, 4> parameters;
for (unsigned i = 0, n = paramList->size(); i != n; ++i) {
@@ -7235,9 +7253,6 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar,
}
Type internalType;
bool oneWayConstraints =
getASTContext().TypeCheckerOpts.EnableOneWayClosureParameters;
if (paramList->get(i)->getTypeRepr()) {
// Internal type is the type used in the body of the closure,
// so "external" type translates to it as follows:
@@ -7288,17 +7303,12 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar,
inferredClosureType->getExtInfo());
assignFixedType(typeVar, closureType, closureLocator);
if (auto last = locator.last()) {
if (auto argToParam = last->getAs<LocatorPathElt::ApplyArgToParam>()) {
auto *calleeLocator = getCalleeLocator(getConstraintLocator(locator));
if (auto functionBuilderType = getFunctionBuilderTypeFor(
*this, argToParam->getParamIdx(), calleeLocator)) {
if (auto result = matchFunctionBuilder(
closure, functionBuilderType, closureType->getResult(),
ConstraintKind::Conversion, calleeLocator, locator)) {
return result->isSuccess();
}
}
// If there is a function builder to apply, do so now.
if (functionBuilderType) {
if (auto result = matchFunctionBuilder(
closure, functionBuilderType, closureType->getResult(),
ConstraintKind::Conversion, calleeLocator, locator)) {
return result->isSuccess();
}
}