[CSClosure] Declarations prefixed with $ can act as inferrable placeholders

If the type for such declaration could be completely inferred it
would be used during solution application. This is used to infer
types for result builder components.
This commit is contained in:
Pavel Yaskevich
2022-05-02 11:30:06 -07:00
parent 65aeb4ad89
commit a6421fc94e
3 changed files with 63 additions and 4 deletions

View File

@@ -9045,12 +9045,23 @@ ExprWalker::rewriteTarget(SolutionApplicationTarget target) {
return target;
} else if (auto *pattern = target.getAsUninitializedVar()) {
TypeResolutionOptions options(TypeResolverContext::PatternBindingDecl);
auto contextualPattern = target.getContextualPattern();
auto patternType = target.getTypeOfUninitializedVar();
auto *PB = target.getPatternBindingOfUninitializedVar();
// If this is a placeholder variable, let's override its type with
// inferred one.
if (auto *var = PB->getSingleVar()) {
if (var->getName().hasDollarPrefix() && patternType->hasPlaceholder()) {
patternType = solution.getResolvedType(var);
options |= TypeResolutionFlags::OverrideType;
}
}
if (auto coercedPattern = TypeChecker::coercePatternToType(
contextualPattern, patternType,
TypeResolverContext::PatternBindingDecl)) {
contextualPattern, patternType, options)) {
auto resultTarget = target;
resultTarget.setPattern(coercedPattern);
return resultTarget;

View File

@@ -85,6 +85,30 @@ public:
}
inferVariables(type);
return {true, expr};
}
auto var = dyn_cast<VarDecl>(decl);
if (!var)
return {true, expr};
// If there is no type recorded yet, let's check whether
// it is a placeholder variable implicitly generated by the
// compiler.
if (var->getName().hasDollarPrefix()) {
if (auto *PB = var->getParentPatternBinding()) {
auto patternTarget = CS.getSolutionApplicationTarget({PB, 0});
if (!patternTarget)
return {true, expr};
auto patternType = patternTarget->getTypeOfUninitializedVar();
if (patternType->hasPlaceholder()) {
auto openedTy = CS.replaceInferableTypesWithTypeVars(
patternType, CS.getConstraintLocator(expr));
inferVariables(openedTy);
CS.setType(var, openedTy);
}
}
}
}
@@ -521,14 +545,26 @@ private:
}
auto target = getTargetForPattern(patternBinding, index, patternType);
if (!target ||
cs.generateConstraints(*target, FreeTypeVariableBinding::Disallow)) {
if (!target) {
hadError = true;
return;
}
// Keep track of this binding entry.
cs.setSolutionApplicationTarget({patternBinding, index}, *target);
if (patternType->hasPlaceholder()) {
if (auto *var = patternBinding->getSingleVar()) {
if (var->getName().hasDollarPrefix() &&
!patternBinding->isExplicitlyInitialized(index))
return;
}
}
if (cs.generateConstraints(*target, FreeTypeVariableBinding::Disallow)) {
hadError = true;
return;
}
}
void visitDecl(Decl *decl) {

View File

@@ -894,6 +894,18 @@ Type ConstraintSystem::replaceInferableTypesWithTypeVars(
TVO_CanBindToNoEscape | TVO_PrefersSubtypeBinding |
TVO_CanBindToHole);
}
if (auto *var = placeholderTy->getOriginator().dyn_cast<VarDecl *>()) {
if (var->getName().hasDollarPrefix()) {
auto *repr =
new (type->getASTContext()) PlaceholderTypeRepr(var->getLoc());
return createTypeVariable(
getConstraintLocator(locator,
LocatorPathElt::PlaceholderType(repr)),
TVO_CanBindToNoEscape | TVO_PrefersSubtypeBinding |
TVO_CanBindToHole);
}
}
}
return type;