Skip to content

Commit efd4152

Browse files
committed
[Constraint solver] Factor constraint generation logic for solution targets
Move more constraint generation logic for an expression target into a new generateConstraints() on a solution target, so we can further generalize the main “solve” logic.
1 parent bbc0a95 commit efd4152

File tree

3 files changed

+59
-37
lines changed

3 files changed

+59
-37
lines changed

lib/Sema/CSGen.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3782,6 +3782,54 @@ static Expr *generateConstraintsFor(ConstraintSystem &cs, Expr *expr,
37823782
return result;
37833783
}
37843784

3785+
bool ConstraintSystem::generateConstraints(
3786+
SolutionApplicationTarget &target,
3787+
FreeTypeVariableBinding allowFreeTypeVariables) {
3788+
if (Expr *expr = target.getAsExpr()) {
3789+
// Try to shrink the system by reducing disjunction domains. This
3790+
// goes through every sub-expression and generate its own sub-system, to
3791+
// try to reduce the domains of those subexpressions.
3792+
shrink(expr);
3793+
target.setExpr(expr);
3794+
3795+
// Generate constraints for the main system.
3796+
expr = generateConstraints(expr, target.getDeclContext());
3797+
if (!expr)
3798+
return true;
3799+
target.setExpr(expr);
3800+
3801+
// If there is a type that we're expected to convert to, add the conversion
3802+
// constraint.
3803+
if (Type convertType = target.getExprConversionType()) {
3804+
// Determine whether we know more about the contextual type.
3805+
ContextualTypePurpose ctp = target.getExprContextualTypePurpose();
3806+
bool isOpaqueReturnType = target.infersOpaqueReturnType();
3807+
3808+
// Substitute type variables in for unresolved types.
3809+
if (allowFreeTypeVariables == FreeTypeVariableBinding::UnresolvedType) {
3810+
bool isForSingleExprFunction = (ctp == CTP_ReturnSingleExpr);
3811+
auto *convertTypeLocator = getConstraintLocator(
3812+
expr, LocatorPathElt::ContextualType(isForSingleExprFunction));
3813+
3814+
convertType = convertType.transform([&](Type type) -> Type {
3815+
if (type->is<UnresolvedType>()) {
3816+
return createTypeVariable(
3817+
convertTypeLocator, TVO_CanBindToNoEscape);
3818+
}
3819+
return type;
3820+
});
3821+
}
3822+
3823+
addContextualConversionConstraint(expr, convertType, ctp,
3824+
isOpaqueReturnType);
3825+
}
3826+
3827+
return false;
3828+
}
3829+
3830+
llvm_unreachable("BOOM");
3831+
}
3832+
37853833
Expr *ConstraintSystem::generateConstraints(ClosureExpr *closure) {
37863834
assert(closure->hasSingleExpressionBody());
37873835
return generateConstraintsFor(*this, closure->getSingleExpressionBody(),

lib/Sema/CSSolver.cpp

Lines changed: 5 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1239,46 +1239,14 @@ ConstraintSystem::solveImpl(SolutionApplicationTarget &target,
12391239
assert(!solverState && "cannot be used directly");
12401240

12411241
// Set up the expression type checker timer.
1242-
Expr *expr = target.getAsExpr();
1243-
Timer.emplace(expr, *this);
1244-
1245-
// Try to shrink the system by reducing disjunction domains. This
1246-
// goes through every sub-expression and generate its own sub-system, to
1247-
// try to reduce the domains of those subexpressions.
1248-
shrink(expr);
1249-
1250-
// Generate constraints for the main system.
1251-
if (auto generatedExpr = generateConstraints(expr, DC))
1252-
expr = generatedExpr;
1253-
else {
1254-
return SolutionResult::forError();
1255-
}
1242+
if (Expr *expr = target.getAsExpr())
1243+
Timer.emplace(expr, *this);
12561244

1257-
// If there is a type that we're expected to convert to, add the conversion
1258-
// constraint.
1259-
if (Type convertType = target.getExprConversionType()) {
1260-
// Determine whether we know more about the contextual type.
1261-
ContextualTypePurpose ctp = target.getExprContextualTypePurpose();
1262-
bool isOpaqueReturnType = target.infersOpaqueReturnType();
1263-
1264-
// Substitute type variables in for unresolved types.
1265-
if (allowFreeTypeVariables == FreeTypeVariableBinding::UnresolvedType) {
1266-
bool isForSingleExprFunction = (ctp == CTP_ReturnSingleExpr);
1267-
auto *convertTypeLocator = getConstraintLocator(
1268-
expr, LocatorPathElt::ContextualType(isForSingleExprFunction));
1269-
1270-
convertType = convertType.transform([&](Type type) -> Type {
1271-
if (type->is<UnresolvedType>())
1272-
return createTypeVariable(convertTypeLocator, TVO_CanBindToNoEscape);
1273-
return type;
1274-
});
1275-
}
1276-
1277-
addContextualConversionConstraint(expr, convertType, ctp,
1278-
isOpaqueReturnType);
1279-
}
1245+
if (generateConstraints(target, allowFreeTypeVariables))
1246+
return SolutionResult::forError();;
12801247

12811248
// Notify the listener that we've built the constraint system.
1249+
Expr *expr = target.getAsExpr();
12821250
if (listener && listener->builtConstraints(*this, expr)) {
12831251
return SolutionResult::forError();
12841252
}

lib/Sema/ConstraintSystem.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3231,6 +3231,12 @@ class ConstraintSystem {
32313231
return allocateCopy(vec.begin(), vec.end());
32323232
}
32333233

3234+
/// Generate constraints for the given solution target.
3235+
///
3236+
/// \returns true if an error occurred, false otherwise.
3237+
bool generateConstraints(SolutionApplicationTarget &target,
3238+
FreeTypeVariableBinding allowFreeTypeVariables);
3239+
32343240
/// Generate constraints for the body of the given single-statement closure.
32353241
///
32363242
/// \returns a possibly-sanitized expression, or null if an error occurred.

0 commit comments

Comments
 (0)