Skip to content

Commit 38f8be1

Browse files
committed
[CSBindings] Don't delay solving self-contained of result builder transformed closures
If a result builder transformed closure doesn't rely on any external type information it could be solved right after it's resolved. We determine that based on three criteria: - Builder type doesn't have any unresolved generic parameters; - Closure doesn't have any parameters; - The contextual result type is either concrete or opaque type.
1 parent a815de7 commit 38f8be1

File tree

1 file changed

+55
-0
lines changed

1 file changed

+55
-0
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,6 +1071,61 @@ bool BindingSet::favoredOverConjunction(Constraint *conjunction) const {
10711071
if (forClosureResult() || forGenericParameter())
10721072
return false;
10731073
}
1074+
1075+
auto *locator = conjunction->getLocator();
1076+
if (locator->directlyAt<ClosureExpr>()) {
1077+
auto *closure = castToExpr<ClosureExpr>(locator->getAnchor());
1078+
1079+
if (auto transform = CS.getAppliedResultBuilderTransform(closure)) {
1080+
// Conjunctions that represent closures with result builder transformed
1081+
// bodies could be attempted right after their resolution if they meet
1082+
// all of the following criteria:
1083+
//
1084+
// - Builder type doesn't have any unresolved generic parameters;
1085+
// - Closure doesn't have any parameters;
1086+
// - The contextual result type is either concrete or opaque type.
1087+
auto contextualType = transform->contextualType;
1088+
if (!(contextualType && contextualType->is<FunctionType>()))
1089+
return true;
1090+
1091+
auto *contextualFnType = contextualType->castTo<FunctionType>();
1092+
auto resultType = contextualFnType->getResult();
1093+
if (resultType->hasTypeVariable()) {
1094+
auto *typeVar = resultType->getAs<TypeVariableType>();
1095+
// If contextual result type is represented by an opaque type,
1096+
// it's a strong indication that body is self-contained, otherwise
1097+
// closure might rely on external types flowing into the body for
1098+
// disambiguation of `build{Partial}Block` or `buildFinalResult`
1099+
// calls.
1100+
if (!(typeVar && typeVar->getImpl().isOpaqueType()))
1101+
return true;
1102+
}
1103+
1104+
auto *closureType = CS.getClosureType(closure);
1105+
// If closure has parameters, it has to be delayed to give
1106+
// them a chance to be resolved.
1107+
//
1108+
// Note: Since we have access to a contextual type here it should be
1109+
// possible to transform this check into - if some of the parameters
1110+
// have type variables (that means not-yet-resolved generic parameters).
1111+
if (closureType->getNumParams() != 0)
1112+
return true;
1113+
1114+
// If conjunction references a single type variable (closure itself)
1115+
// it means that the builder is either not generic or has all of its
1116+
// generic parameter specified explicitly, and there are no references
1117+
// to declarations from outer context. Such conjunctions don't have to
1118+
// be delayed.
1119+
if (conjunction->getTypeVariables().size() == 1) {
1120+
assert(
1121+
conjunction->getTypeVariables()[0]->isEqual(CS.getType(closure)));
1122+
return false;
1123+
}
1124+
1125+
return true;
1126+
}
1127+
}
1128+
10741129
return true;
10751130
}
10761131

0 commit comments

Comments
 (0)