Skip to content

Commit 031f5a4

Browse files
authored
Merge pull request #30065 from DougGregor/function-builders-if-case-fixes
[Constraint system] Cleanups for function builders support for if let/if case let
2 parents e70ef60 + c58e0aa commit 031f5a4

File tree

6 files changed

+187
-98
lines changed

6 files changed

+187
-98
lines changed

lib/Sema/BuilderTransform.cpp

Lines changed: 9 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ class BuilderClosureVisitor
331331
addChild(captureExpr(expr, /*oneWay=*/true, node.get<Expr *>()));
332332
}
333333

334-
if (!cs)
334+
if (!cs || hadError)
335335
return nullptr;
336336

337337
// Call Builder.buildBlock(... args ...)
@@ -920,38 +920,9 @@ class BuilderClosureRewriter
920920

921921
Stmt *visitIfStmt(IfStmt *ifStmt, FunctionBuilderTarget target) {
922922
// Rewrite the condition.
923-
auto condition = ifStmt->getCond();
924-
for (auto &condElement : condition) {
925-
switch (condElement.getKind()) {
926-
case StmtConditionElement::CK_Availability:
927-
continue;
928-
929-
case StmtConditionElement::CK_Boolean: {
930-
auto condExpr = condElement.getBoolean();
931-
auto finalCondExpr = rewriteExpr(condExpr);
932-
933-
// Load the condition if needed.
934-
if (finalCondExpr->getType()->hasLValueType()) {
935-
finalCondExpr = TypeChecker::addImplicitLoadExpr(ctx, finalCondExpr);
936-
}
937-
938-
condElement.setBoolean(finalCondExpr);
939-
continue;
940-
}
941-
942-
case StmtConditionElement::CK_PatternBinding: {
943-
ConstraintSystem &cs = solution.getConstraintSystem();
944-
auto target = *cs.getStmtConditionTarget(&condElement);
945-
auto resolvedTarget = rewriteTarget(target);
946-
if (resolvedTarget) {
947-
condElement.setInitializer(resolvedTarget->getAsExpr());
948-
condElement.setPattern(resolvedTarget->getInitializationPattern());
949-
}
950-
continue;
951-
}
952-
}
953-
}
954-
ifStmt->setCond(condition);
923+
if (auto condition = rewriteTarget(
924+
SolutionApplicationTarget(ifStmt->getCond(), dc)))
925+
ifStmt->setCond(*condition->getAsStmtCondition());
955926

956927
assert(target.kind == FunctionBuilderTarget::TemporaryVar);
957928
auto temporaryVar = target.captured.first;
@@ -1383,6 +1354,11 @@ class PreCheckFunctionBuilderApplication : public ASTWalker {
13831354
// Otherwise, recurse into the statement normally.
13841355
return std::make_pair(true, S);
13851356
}
1357+
1358+
/// Ignore patterns.
1359+
std::pair<bool, Pattern*> walkToPatternPre(Pattern *pat) override {
1360+
return { false, pat };
1361+
}
13861362
};
13871363

13881364
}

lib/Sema/CSApply.cpp

Lines changed: 88 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -7093,6 +7093,48 @@ bool swift::exprNeedsParensAfterAddingNilCoalescing(DeclContext *DC,
70937093
}
70947094

70957095
namespace {
7096+
class SetExprTypes : public ASTWalker {
7097+
const Solution &solution;
7098+
7099+
public:
7100+
explicit SetExprTypes(const Solution &solution)
7101+
: solution(solution) {}
7102+
7103+
Expr *walkToExprPost(Expr *expr) override {
7104+
auto &cs = solution.getConstraintSystem();
7105+
auto exprType = cs.getType(expr);
7106+
exprType = solution.simplifyType(exprType);
7107+
// assert((!expr->getType() || expr->getType()->isEqual(exprType)) &&
7108+
// "Mismatched types!");
7109+
assert(!exprType->hasTypeVariable() &&
7110+
"Should not write type variable into expression!");
7111+
expr->setType(exprType);
7112+
7113+
if (auto kp = dyn_cast<KeyPathExpr>(expr)) {
7114+
for (auto i : indices(kp->getComponents())) {
7115+
Type componentType;
7116+
if (cs.hasType(kp, i)) {
7117+
componentType = solution.simplifyType(cs.getType(kp, i));
7118+
assert(!componentType->hasTypeVariable() &&
7119+
"Should not write type variable into key-path component");
7120+
}
7121+
7122+
kp->getMutableComponents()[i].setComponentType(componentType);
7123+
}
7124+
}
7125+
7126+
return expr;
7127+
}
7128+
7129+
/// Ignore statements.
7130+
std::pair<bool, Stmt *> walkToStmtPre(Stmt *stmt) override {
7131+
return { false, stmt };
7132+
}
7133+
7134+
/// Ignore declarations.
7135+
bool walkToDeclPre(Decl *decl) override { return false; }
7136+
};
7137+
70967138
class ExprWalker : public ASTWalker {
70977139
ExprRewriter &Rewriter;
70987140
SmallVector<ClosureExpr *, 4> ClosuresToTypeCheck;
@@ -7395,6 +7437,45 @@ ExprWalker::rewriteTarget(SolutionApplicationTarget target) {
73957437
} else {
73967438
result.setExpr(rewrittenExpr);
73977439
}
7440+
} else if (auto stmtCondition = target.getAsStmtCondition()) {
7441+
for (auto &condElement : *stmtCondition) {
7442+
switch (condElement.getKind()) {
7443+
case StmtConditionElement::CK_Availability:
7444+
continue;
7445+
7446+
case StmtConditionElement::CK_Boolean: {
7447+
auto condExpr = condElement.getBoolean();
7448+
auto finalCondExpr = condExpr->walk(*this);
7449+
if (!finalCondExpr)
7450+
return None;
7451+
7452+
// Load the condition if needed.
7453+
solution.setExprTypes(finalCondExpr);
7454+
if (finalCondExpr->getType()->hasLValueType()) {
7455+
ASTContext &ctx = solution.getConstraintSystem().getASTContext();
7456+
finalCondExpr = TypeChecker::addImplicitLoadExpr(ctx, finalCondExpr);
7457+
}
7458+
7459+
condElement.setBoolean(finalCondExpr);
7460+
continue;
7461+
}
7462+
7463+
case StmtConditionElement::CK_PatternBinding: {
7464+
ConstraintSystem &cs = solution.getConstraintSystem();
7465+
auto target = *cs.getStmtConditionTarget(&condElement);
7466+
auto resolvedTarget = rewriteTarget(target);
7467+
if (!resolvedTarget)
7468+
return None;
7469+
7470+
solution.setExprTypes(resolvedTarget->getAsExpr());
7471+
condElement.setInitializer(resolvedTarget->getAsExpr());
7472+
condElement.setPattern(resolvedTarget->getInitializationPattern());
7473+
continue;
7474+
}
7475+
}
7476+
}
7477+
7478+
return target;
73987479
} else {
73997480
auto fn = *target.getAsFunction();
74007481

@@ -7408,7 +7489,7 @@ ExprWalker::rewriteTarget(SolutionApplicationTarget target) {
74087489
auto resultTarget = rewriteTarget(target);
74097490
if (resultTarget) {
74107491
if (auto expr = resultTarget->getAsExpr())
7411-
Rewriter.solution.setExprTypes(expr);
7492+
solution.setExprTypes(expr);
74127493
}
74137494

74147495
return resultTarget;
@@ -7547,50 +7628,6 @@ Expr *Solution::coerceToType(Expr *expr, Type toType,
75477628
return result;
75487629
}
75497630

7550-
namespace {
7551-
class SetExprTypes : public ASTWalker {
7552-
const Solution &solution;
7553-
7554-
public:
7555-
explicit SetExprTypes(const Solution &solution)
7556-
: solution(solution) {}
7557-
7558-
Expr *walkToExprPost(Expr *expr) override {
7559-
auto &cs = solution.getConstraintSystem();
7560-
auto exprType = cs.getType(expr);
7561-
exprType = solution.simplifyType(exprType);
7562-
// assert((!expr->getType() || expr->getType()->isEqual(exprType)) &&
7563-
// "Mismatched types!");
7564-
assert(!exprType->hasTypeVariable() &&
7565-
"Should not write type variable into expression!");
7566-
expr->setType(exprType);
7567-
7568-
if (auto kp = dyn_cast<KeyPathExpr>(expr)) {
7569-
for (auto i : indices(kp->getComponents())) {
7570-
Type componentType;
7571-
if (cs.hasType(kp, i)) {
7572-
componentType = solution.simplifyType(cs.getType(kp, i));
7573-
assert(!componentType->hasTypeVariable() &&
7574-
"Should not write type variable into key-path component");
7575-
}
7576-
7577-
kp->getMutableComponents()[i].setComponentType(componentType);
7578-
}
7579-
}
7580-
7581-
return expr;
7582-
}
7583-
7584-
/// Ignore statements.
7585-
std::pair<bool, Stmt *> walkToStmtPre(Stmt *stmt) override {
7586-
return { false, stmt };
7587-
}
7588-
7589-
/// Ignore declarations.
7590-
bool walkToDeclPre(Decl *decl) override { return false; }
7591-
};
7592-
}
7593-
75947631
ProtocolConformanceRef Solution::resolveConformance(
75957632
ConstraintLocator *locator, ProtocolDecl *proto) {
75967633
for (const auto &conformance : Conformances) {
@@ -7705,5 +7742,11 @@ SolutionApplicationTarget SolutionApplicationTarget::walk(ASTWalker &walker) {
77057742
return SolutionApplicationTarget(
77067743
*getAsFunction(),
77077744
cast_or_null<BraceStmt>(getFunctionBody()->walk(walker)));
7745+
7746+
case Kind::stmtCondition:
7747+
for (auto &condElement : stmtCondition.stmtCondition) {
7748+
condElement = *condElement.walk(walker);
7749+
}
7750+
return *this;
77087751
}
77097752
}

lib/Sema/CSGen.cpp

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2197,6 +2197,18 @@ namespace {
21972197
/// type information with fresh type variables.
21982198
///
21992199
/// \param pattern The pattern.
2200+
///
2201+
/// \param locator The locator to use for generated constraints and
2202+
/// type variables.
2203+
///
2204+
/// \param externalPatternType The type imposed by the enclosing pattern,
2205+
/// if any. This will be non-null in cases where there is, e.g., a
2206+
/// pattern such as "is SubClass".
2207+
///
2208+
/// \param bindPatternVarsOneWay When true, generate fresh type variables
2209+
/// for the types of each variable declared within the pattern, along
2210+
/// with a one-way constraint binding that to the type to which the
2211+
/// variable will be ascribed or inferred.
22002212
Type getTypeForPattern(Pattern *pattern, ConstraintLocatorBuilder locator,
22012213
Type externalPatternType,
22022214
bool bindPatternVarsOneWay) {
@@ -2257,14 +2269,9 @@ namespace {
22572269
if (bindPatternVarsOneWay) {
22582270
oneWayVarType = CS.createTypeVariable(
22592271
CS.getConstraintLocator(locator), TVO_CanBindToNoEscape);
2260-
if (externalPatternType) {
2261-
CS.addConstraint(
2262-
ConstraintKind::OneWayEqual, oneWayVarType,
2263-
externalPatternType, locator);
2264-
} else {
2265-
CS.addConstraint(
2266-
ConstraintKind::OneWayEqual, oneWayVarType, varType, locator);
2267-
}
2272+
CS.addConstraint(
2273+
ConstraintKind::OneWayEqual, oneWayVarType,
2274+
externalPatternType ? externalPatternType : varType, locator);
22682275
}
22692276

22702277
// If there is an externally-imposed type.
@@ -2357,16 +2364,13 @@ namespace {
23572364
case PatternKind::OptionalSome: {
23582365
// Remove an optional from the object type.
23592366
if (externalPatternType) {
2360-
if (Type objType = externalPatternType->getOptionalObjectType()) {
2361-
externalPatternType = objType;
2362-
} else {
2363-
Type objVar = CS.createTypeVariable(
2364-
CS.getConstraintLocator(locator), TVO_CanBindToNoEscape);
2365-
CS.addConstraint(
2366-
ConstraintKind::Equal, OptionalType::get(objVar),
2367-
externalPatternType, locator);
2368-
externalPatternType = objVar;
2369-
}
2367+
Type objVar = CS.createTypeVariable(
2368+
CS.getConstraintLocator(locator), TVO_CanBindToNoEscape);
2369+
CS.addConstraint(
2370+
ConstraintKind::OptionalObject, externalPatternType,
2371+
objVar, locator);
2372+
2373+
externalPatternType = objVar;
23702374
}
23712375

23722376
// The subpattern must have optional type.

0 commit comments

Comments
 (0)