Skip to content

Commit a1932f1

Browse files
committed
[Constraint solver] Sink remaining logic from typeCheckBinding.
Move the remaining logic of typeCheckBinding, which consists of applying the solution to the pattern, down into the normal solution application path. typeCheckBinding() is now a thin shell over the normal typeCheckExpression() convenience function.
1 parent 364770e commit a1932f1

File tree

3 files changed

+64
-50
lines changed

3 files changed

+64
-50
lines changed

lib/Sema/CSApply.cpp

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "MiscDiagnostics.h"
2323
#include "SolutionResult.h"
2424
#include "TypeCheckProtocol.h"
25+
#include "TypeCheckType.h"
2526
#include "swift/AST/ASTVisitor.h"
2627
#include "swift/AST/ASTWalker.h"
2728
#include "swift/AST/ExistentialLayout.h"
@@ -7230,12 +7231,13 @@ bool ConstraintSystem::applySolutionFixes(const Solution &solution) {
72307231
/// Apply the given solution to the initialization target.
72317232
///
72327233
/// \returns the resulting initialiation expression.
7233-
static Expr *applySolutionToInitialization(
7234-
Solution &solution, SolutionApplicationTarget target, Expr *expr) {
7234+
static Optional<SolutionApplicationTarget> applySolutionToInitialization(
7235+
Solution &solution, SolutionApplicationTarget target,
7236+
Expr *initializer) {
72357237
auto wrappedVar = target.getInitializationWrappedVar();
72367238
Type initType;
72377239
if (wrappedVar) {
7238-
initType = solution.getType(expr);
7240+
initType = solution.getType(initializer);
72397241
} else {
72407242
initType = solution.getType(target.getInitializationPattern());
72417243
}
@@ -7249,10 +7251,13 @@ static Expr *applySolutionToInitialization(
72497251
// Convert the initializer to the type of the pattern.
72507252
auto &cs = solution.getConstraintSystem();
72517253
auto locator =
7252-
cs.getConstraintLocator(expr, LocatorPathElt::ContextualType());
7253-
expr = solution.coerceToType(expr, initType, locator);
7254-
if (!expr)
7255-
return nullptr;
7254+
cs.getConstraintLocator(initializer, LocatorPathElt::ContextualType());
7255+
initializer = solution.coerceToType(initializer, initType, locator);
7256+
if (!initializer)
7257+
return None;
7258+
7259+
SolutionApplicationTarget resultTarget = target;
7260+
resultTarget.setExpr(initializer);
72567261

72577262
// Record the property wrapper type and note that the initializer has
72587263
// been subsumed by the backing property.
@@ -7264,10 +7269,40 @@ static Expr *applySolutionToInitialization(
72647269

72657270
// Record the semantic initializer on the outermost property wrapper.
72667271
wrappedVar->getAttachedPropertyWrappers().front()
7267-
->setSemanticInit(expr);
7272+
->setSemanticInit(initializer);
72687273
}
72697274

7270-
return expr;
7275+
// Coerce the pattern to the type of the initializer.
7276+
TypeResolutionOptions options =
7277+
isa<EditorPlaceholderExpr>(initializer->getSemanticsProvidingExpr())
7278+
? TypeResolverContext::EditorPlaceholderExpr
7279+
: TypeResolverContext::InExpression;
7280+
options |= TypeResolutionFlags::OverrideType;
7281+
7282+
// Determine the type of the pattern.
7283+
Type finalPatternType = initializer->getType();
7284+
if (wrappedVar) {
7285+
if (!finalPatternType->hasError() && !finalPatternType->is<TypeVariableType>())
7286+
finalPatternType = computeWrappedValueType(wrappedVar, finalPatternType);
7287+
}
7288+
7289+
if (finalPatternType->hasDependentMember())
7290+
return None;
7291+
7292+
finalPatternType = finalPatternType->reconstituteSugar(/*recursive =*/false);
7293+
7294+
// Apply the solution to the pattern as well.
7295+
auto contextualPattern =
7296+
ContextualPattern::forRawPattern(target.getInitializationPattern(),
7297+
target.getDeclContext());
7298+
if (auto coercedPattern = TypeChecker::coercePatternToType(
7299+
contextualPattern, finalPatternType, options)) {
7300+
resultTarget.setPattern(coercedPattern);
7301+
} else {
7302+
return None;
7303+
}
7304+
7305+
return resultTarget;
72717306
}
72727307

72737308
/// Apply a given solution to the expression, producing a fully
@@ -7310,13 +7345,15 @@ Optional<SolutionApplicationTarget> ConstraintSystem::applySolution(
73107345

73117346
/// Handle application for initializations.
73127347
if (target.getExprContextualTypePurpose() == CTP_Initialization) {
7313-
rewrittenExpr = applySolutionToInitialization(
7348+
auto initResultTarget = applySolutionToInitialization(
73147349
solution, target, rewrittenExpr);
7315-
if (!rewrittenExpr)
7350+
if (!initResultTarget)
73167351
return None;
7317-
}
73187352

7319-
result.setExpr(rewrittenExpr);
7353+
result = *initResultTarget;
7354+
} else {
7355+
result.setExpr(rewrittenExpr);
7356+
}
73207357
} else {
73217358
auto fn = *target.getAsFunction();
73227359

lib/Sema/ConstraintSystem.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1314,6 +1314,12 @@ class SolutionApplicationTarget {
13141314
expression.expression = expr;
13151315
}
13161316

1317+
void setPattern(Pattern *pattern) {
1318+
assert(kind == Kind::expression);
1319+
assert(expression.contextualPurpose == CTP_Initialization);
1320+
expression.pattern = pattern;
1321+
}
1322+
13171323
Optional<AnyFunctionRef> getAsFunction() const {
13181324
switch (kind) {
13191325
case Kind::expression:

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 8 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2413,57 +2413,29 @@ TypeChecker::getTypeOfCompletionOperator(DeclContext *DC, Expr *LHS,
24132413
bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
24142414
DeclContext *DC,
24152415
Type patternType) {
2416-
auto &Context = DC->getASTContext();
24172416
auto target = SolutionApplicationTarget::forInitialization(
24182417
initializer, DC, patternType, pattern);
2419-
initializer = target.getAsExpr();
24202418

24212419
// Type-check the initializer.
24222420
bool unresolvedTypeExprs = false;
24232421
auto resultTarget = typeCheckExpression(target, unresolvedTypeExprs);
24242422

24252423
if (resultTarget) {
24262424
initializer = resultTarget->getAsExpr();
2427-
2428-
TypeResolutionOptions options =
2429-
isa<EditorPlaceholderExpr>(initializer->getSemanticsProvidingExpr())
2430-
? TypeResolverContext::EditorPlaceholderExpr
2431-
: TypeResolverContext::InExpression;
2432-
options |= TypeResolutionFlags::OverrideType;
2433-
2434-
Type initTy = initializer->getType();
2435-
if (auto wrappedVar = target.getInitializationWrappedVar()) {
2436-
if (!initTy->hasError() && !initTy->is<TypeVariableType>())
2437-
initTy = computeWrappedValueType(wrappedVar, initTy);
2438-
}
2439-
2440-
if (initTy->hasDependentMember())
2441-
return true;
2442-
2443-
initTy = initTy->reconstituteSugar(/*recursive =*/false);
2444-
2445-
// Apply the solution to the pattern as well.
2446-
auto contextualPattern =
2447-
ContextualPattern::forRawPattern(pattern, DC);
2448-
if (auto coercedPattern = TypeChecker::coercePatternToType(
2449-
contextualPattern, initTy, options)) {
2450-
pattern = coercedPattern;
2451-
} else {
2452-
return true;
2453-
}
2454-
} else {
2455-
initializer = target.getAsExpr();
2425+
return false;
24562426
}
24572427

2458-
if (!resultTarget && !initializer->getType())
2428+
auto &Context = DC->getASTContext();
2429+
initializer = target.getAsExpr();
2430+
2431+
if (!initializer->getType())
24592432
initializer->setType(ErrorType::get(Context));
24602433

24612434
// If the type of the pattern is inferred, assign error types to the pattern
24622435
// and its variables, to prevent it from being referenced by the constraint
24632436
// system.
2464-
if (!resultTarget &&
2465-
(patternType->hasUnresolvedType() ||
2466-
patternType->hasUnboundGenericType())) {
2437+
if (patternType->hasUnresolvedType() ||
2438+
patternType->hasUnboundGenericType()) {
24672439
pattern->setType(ErrorType::get(Context));
24682440
pattern->forEachVariable([&](VarDecl *var) {
24692441
// Don't change the type of a variable that we've been able to
@@ -2476,8 +2448,7 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
24762448
var->setInvalid();
24772449
});
24782450
}
2479-
2480-
return !resultTarget;
2451+
return true;
24812452
}
24822453

24832454
bool TypeChecker::typeCheckPatternBinding(PatternBindingDecl *PBD,

0 commit comments

Comments
 (0)