Skip to content

Commit 4d1de7f

Browse files
committed
[Constraint solver] Sink down initialization pattern constraint generation.
Sink the constraint generation for initialization patterns, including all of the logic for property wrappers, from the high-level entry point `typeCheckBinding` down into the lower-level constraint generation for solution application targets.
1 parent a2640b7 commit 4d1de7f

File tree

3 files changed

+88
-74
lines changed

3 files changed

+88
-74
lines changed

lib/Sema/CSApply.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7265,6 +7265,10 @@ Optional<SolutionApplicationTarget> ConstraintSystem::applySolution(
72657265
if (!rewrittenExpr)
72667266
return None;
72677267

7268+
if (target.getExprContextualTypePurpose() == CTP_Initialization) {
7269+
7270+
}
7271+
72687272
result.setExpr(rewrittenExpr);
72697273
} else {
72707274
auto fn = *target.getAsFunction();

lib/Sema/CSGen.cpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3831,6 +3831,68 @@ static Expr *generateConstraintsFor(ConstraintSystem &cs, Expr *expr,
38313831
return result;
38323832
}
38333833

3834+
/// Generate constraints to produce the wrapped value type given the property
3835+
/// that has an attached property wrapper.
3836+
///
3837+
/// \param initializerType The type of the adjusted initializer, which
3838+
/// initializes the underlying storage variable.
3839+
/// \param wrappedVar The property that has a property wrapper.
3840+
/// \returns the type of the property.
3841+
static Type generateWrappedPropertyTypeConstraints(
3842+
ConstraintSystem &cs, Type initializerType,
3843+
VarDecl *wrappedVar, ConstraintLocator *locator) {
3844+
Type valueType = LValueType::get(initializerType);
3845+
auto dc = wrappedVar->getInnermostDeclContext();
3846+
3847+
for (unsigned i : indices(wrappedVar->getAttachedPropertyWrappers())) {
3848+
auto wrapperInfo = wrappedVar->getAttachedPropertyWrapperTypeInfo(i);
3849+
if (!wrapperInfo)
3850+
break;
3851+
3852+
locator = cs.getConstraintLocator(locator, ConstraintLocator::Member);
3853+
Type memberType = cs.createTypeVariable(locator, TVO_CanBindToLValue);
3854+
cs.addValueMemberConstraint(
3855+
valueType, wrapperInfo.valueVar->createNameRef(),
3856+
memberType, dc, FunctionRefKind::Unapplied, { }, locator);
3857+
valueType = memberType;
3858+
}
3859+
3860+
// Set up an equality constraint to drop the lvalue-ness of the value
3861+
// type we produced.
3862+
Type propertyType = cs.createTypeVariable(locator, 0);
3863+
cs.addConstraint(ConstraintKind::Equal, propertyType, valueType, locator);
3864+
return propertyType;
3865+
}
3866+
3867+
/// Generate additional constraints for the pattern of an initialization.
3868+
static bool generateInitPatternConstraints(
3869+
ConstraintSystem &cs, SolutionApplicationTarget target, Expr *initializer) {
3870+
auto pattern = target.getInitializationPattern();
3871+
auto locator =
3872+
cs.getConstraintLocator(initializer, LocatorPathElt::ContextualType());
3873+
Type patternType = cs.generateConstraints(pattern, locator);
3874+
if (!patternType)
3875+
return true;
3876+
3877+
// Record the type of this pattern.
3878+
cs.setType(pattern, patternType);
3879+
3880+
if (auto wrappedVar = target.getInitializationWrappedVar()) {
3881+
// Add an equal constraint between the pattern type and the
3882+
// property wrapper's "value" type.
3883+
Type propertyType = generateWrappedPropertyTypeConstraints(
3884+
cs, cs.getType(target.getAsExpr()), wrappedVar, locator);
3885+
cs.addConstraint(ConstraintKind::Equal, patternType,
3886+
propertyType, locator, /*isFavored*/ true);
3887+
} else if (!patternType->is<OpaqueTypeArchetypeType>()) {
3888+
// Add a conversion constraint between the types.
3889+
cs.addConstraint(ConstraintKind::Conversion, cs.getType(target.getAsExpr()),
3890+
patternType, locator, /*isFavored*/true);
3891+
}
3892+
3893+
return false;
3894+
}
3895+
38343896
bool ConstraintSystem::generateConstraints(
38353897
SolutionApplicationTarget &target,
38363898
FreeTypeVariableBinding allowFreeTypeVariables) {
@@ -3873,6 +3935,12 @@ bool ConstraintSystem::generateConstraints(
38733935
isOpaqueReturnType);
38743936
}
38753937

3938+
// For an initialization target, generate constraints for the pattern.
3939+
if (target.getExprContextualTypePurpose() == CTP_Initialization &&
3940+
generateInitPatternConstraints(*this, target, expr)) {
3941+
return true;
3942+
}
3943+
38763944
return false;
38773945
}
38783946

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 16 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -2423,9 +2423,6 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
24232423
/// The locator we're using.
24242424
ConstraintLocator *Locator;
24252425

2426-
/// The type of the initializer.
2427-
Type initType;
2428-
24292426
/// The variable to that has property wrappers that have been applied to the initializer expression.
24302427
VarDecl *wrappedVar = nullptr;
24312428

@@ -2435,80 +2432,20 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
24352432
wrappedVar = target.getInitializationWrappedVar();
24362433
}
24372434

2438-
/// Retrieve the type to which the pattern should be coerced.
2439-
Type getPatternInitType(ConstraintSystem *cs) const {
2440-
if (!wrappedVar || initType->hasError() ||
2441-
initType->is<TypeVariableType>())
2442-
return initType;
2443-
2444-
// When we have an active constraint system, form value-member
2445-
// constraints to dig in to the appropriate resulting property.
2446-
if (cs) {
2447-
Type valueType = LValueType::get(initType);
2448-
auto dc = wrappedVar->getInnermostDeclContext();
2449-
auto *loc = cs->getConstraintLocator(target.getAsExpr());
2450-
2451-
for (unsigned i : indices(wrappedVar->getAttachedPropertyWrappers())) {
2452-
auto wrapperInfo = wrappedVar->getAttachedPropertyWrapperTypeInfo(i);
2453-
if (!wrapperInfo)
2454-
break;
2455-
2456-
loc = cs->getConstraintLocator(loc, ConstraintLocator::Member);
2457-
Type memberType = cs->createTypeVariable(loc, TVO_CanBindToLValue);
2458-
cs->addValueMemberConstraint(
2459-
valueType, wrapperInfo.valueVar->createNameRef(),
2460-
memberType, dc, FunctionRefKind::Unapplied, { }, loc);
2461-
valueType = memberType;
2462-
}
2463-
2464-
// Set up an equality constraint to drop the lvalue-ness of the value
2465-
// type we produced.
2466-
Type propertyType = cs->createTypeVariable(loc, 0);
2467-
cs->addConstraint(ConstraintKind::Equal, propertyType, valueType, loc);
2468-
return propertyType;
2469-
}
2470-
2471-
// Otherwise, compute the wrapped value type directly.
2472-
return computeWrappedValueType(wrappedVar, initType);
2473-
}
2474-
24752435
bool builtConstraints(ConstraintSystem &cs, Expr *expr) override {
2476-
assert(!expr->isSemanticallyInOutExpr());
2477-
2478-
// Save the locator we're using for the expression.
2436+
// The expression has been pre-checked; save it in case we fail later.
24792437
Locator = cs.getConstraintLocator(expr, LocatorPathElt::ContextualType());
2438+
return false;
2439+
}
24802440

2481-
// Collect constraints from the pattern.
2482-
Type patternType =
2483-
cs.generateConstraints(target.getInitializationPattern(), Locator);
2484-
if (!patternType)
2485-
return true;
2486-
2441+
Expr *appliedSolution(Solution &solution, Expr *expr) override {
2442+
Type initType;
24872443
if (wrappedVar) {
2488-
// When we have applied a property wrapper, the initializer type
2489-
// is the initialization of the property wrapper instance.
2490-
initType = cs.getType(expr);
2491-
2492-
// Add an equal constraint between the pattern type and the
2493-
// property wrapper's "value" type.
2494-
cs.addConstraint(ConstraintKind::Equal, patternType,
2495-
getPatternInitType(&cs), Locator, /*isFavored*/ true);
2444+
initType = solution.getType(expr);
24962445
} else {
2497-
// The initializer type is the type of the pattern.
2498-
initType = patternType;
2499-
2500-
// Add a conversion constraint between the types.
2501-
if (!initType->is<OpaqueTypeArchetypeType>()) {
2502-
cs.addConstraint(ConstraintKind::Conversion, cs.getType(expr),
2503-
patternType, Locator, /*isFavored*/true);
2504-
}
2446+
initType = solution.getType(target.getInitializationPattern());
25052447
}
25062448

2507-
// The expression has been pre-checked; save it in case we fail later.
2508-
return false;
2509-
}
2510-
2511-
Expr *appliedSolution(Solution &solution, Expr *expr) override {
25122449
{
25132450
// Figure out what type the constraints decided on.
25142451
auto ty = solution.simplifyType(initType);
@@ -2520,8 +2457,6 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
25202457
if (!expr)
25212458
return nullptr;
25222459

2523-
assert(solution.getConstraintSystem().getType(expr)->isEqual(initType));
2524-
25252460
// Record the property wrapper type and note that the initializer has
25262461
// been subsumed by the backing property.
25272462
if (wrappedVar) {
@@ -2542,7 +2477,7 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
25422477
auto target = SolutionApplicationTarget::forInitialization(
25432478
initializer, DC, patternType, pattern);
25442479
initializer = target.getAsExpr();
2545-
2480+
25462481
BindingListener listener(Context, target);
25472482
if (!initializer)
25482483
return true;
@@ -2561,10 +2496,17 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
25612496
: TypeResolverContext::InExpression;
25622497
options |= TypeResolutionFlags::OverrideType;
25632498

2564-
auto initTy = listener.getPatternInitType(nullptr);
2499+
Type initTy = initializer->getType();
2500+
if (auto wrappedVar = target.getInitializationWrappedVar()) {
2501+
if (!initTy->hasError() && !initTy->is<TypeVariableType>())
2502+
initTy = computeWrappedValueType(wrappedVar, initTy);
2503+
}
2504+
25652505
if (initTy->hasDependentMember())
25662506
return true;
25672507

2508+
initTy = initTy->reconstituteSugar(/*recursive =*/false);
2509+
25682510
// Apply the solution to the pattern as well.
25692511
auto contextualPattern =
25702512
ContextualPattern::forRawPattern(pattern, DC);

0 commit comments

Comments
 (0)