Skip to content

Commit 31b356f

Browse files
committed
[ConstraintSystem] Add a dedicated method to pre-check solver targets
Since `SolutionApplicationTarget` could represent whole statement or pattern with multiple expressions, it makes sense to add a dedicated method to pre-check everything together.
1 parent 9c4ff93 commit 31b356f

File tree

4 files changed

+57
-37
lines changed

4 files changed

+57
-37
lines changed

include/swift/Sema/ConstraintSystem.h

+9
Original file line numberDiff line numberDiff line change
@@ -5122,6 +5122,15 @@ class ConstraintSystem {
51225122
= FreeTypeVariableBinding::Disallow);
51235123

51245124
public:
5125+
/// Pre-check the target, validating any types that occur in it
5126+
/// and folding sequence expressions.
5127+
///
5128+
/// \param replaceInvalidRefsWithErrors Indicates whether it's allowed
5129+
/// to replace any discovered invalid member references with `ErrorExpr`.
5130+
static bool preCheckTarget(SolutionApplicationTarget &target,
5131+
bool replaceInvalidRefsWithErrors,
5132+
bool leaveClosureBodiesUnchecked);
5133+
51255134
/// Pre-check the expression, validating any types that occur in the
51265135
/// expression and folding sequence expressions.
51275136
///

lib/Sema/PreCheckExpr.cpp

+34
Original file line numberDiff line numberDiff line change
@@ -2110,6 +2110,40 @@ Expr *PreCheckExpression::simplifyTypeConstructionWithLiteralArg(Expr *E) {
21102110
: nullptr;
21112111
}
21122112

2113+
bool ConstraintSystem::preCheckTarget(SolutionApplicationTarget &target,
2114+
bool replaceInvalidRefsWithErrors,
2115+
bool leaveClosureBodiesUnchecked) {
2116+
auto *DC = target.getDeclContext();
2117+
2118+
bool hadErrors = false;
2119+
2120+
if (auto *expr = target.getAsExpr()) {
2121+
hadErrors |= preCheckExpression(expr, DC, replaceInvalidRefsWithErrors,
2122+
leaveClosureBodiesUnchecked);
2123+
// Even if the pre-check fails, expression still has to be re-set.
2124+
target.setExpr(expr);
2125+
}
2126+
2127+
if (target.isForEachStmt()) {
2128+
auto &info = target.getForEachStmtInfo();
2129+
2130+
if (info.whereExpr)
2131+
hadErrors |= preCheckExpression(info.whereExpr, DC,
2132+
/*replaceInvalidRefsWithErrors=*/true,
2133+
/*leaveClosureBodiesUnchecked=*/false);
2134+
2135+
// Update sequence and where expressions to pre-checked versions.
2136+
if (!hadErrors) {
2137+
info.stmt->setSequence(target.getAsExpr());
2138+
2139+
if (info.whereExpr)
2140+
info.stmt->setWhere(info.whereExpr);
2141+
}
2142+
}
2143+
2144+
return hadErrors;
2145+
}
2146+
21132147
/// Pre-check the expression, validating any types that occur in the
21142148
/// expression and folding sequence expressions.
21152149
bool ConstraintSystem::preCheckExpression(Expr *&expr, DeclContext *dc,

lib/Sema/TypeCheckCodeCompletion.cpp

+4-6
Original file line numberDiff line numberDiff line change
@@ -793,12 +793,10 @@ bool TypeChecker::typeCheckForCodeCompletion(
793793
if (needsPrecheck) {
794794
// First, pre-check the expression, validating any types that occur in the
795795
// expression and folding sequence expressions.
796-
auto failedPreCheck = ConstraintSystem::preCheckExpression(
797-
expr, DC,
798-
/*replaceInvalidRefsWithErrors=*/true,
799-
/*leaveClosureBodiesUnchecked=*/true);
800-
801-
target.setExpr(expr);
796+
auto failedPreCheck =
797+
ConstraintSystem::preCheckTarget(target,
798+
/*replaceInvalidRefsWithErrors=*/true,
799+
/*leaveClosureBodiesUnchecked=*/true);
802800

803801
if (failedPreCheck)
804802
return false;

lib/Sema/TypeCheckConstraints.cpp

+10-31
Original file line numberDiff line numberDiff line change
@@ -337,25 +337,23 @@ Type TypeChecker::typeCheckExpression(Expr *&expr, DeclContext *dc,
337337
}
338338

339339
Optional<SolutionApplicationTarget>
340-
TypeChecker::typeCheckExpression(
341-
SolutionApplicationTarget &target,
342-
TypeCheckExprOptions options) {
343-
Expr *expr = target.getAsExpr();
340+
TypeChecker::typeCheckExpression(SolutionApplicationTarget &target,
341+
TypeCheckExprOptions options) {
344342
DeclContext *dc = target.getDeclContext();
345343
auto &Context = dc->getASTContext();
346-
FrontendStatsTracer StatsTracer(Context.Stats,
347-
"typecheck-expr", expr);
348-
PrettyStackTraceExpr stackTrace(Context, "type-checking", expr);
344+
FrontendStatsTracer StatsTracer(Context.Stats, "typecheck-expr",
345+
target.getAsExpr());
346+
PrettyStackTraceExpr stackTrace(Context, "type-checking", target.getAsExpr());
349347

350348
// First, pre-check the expression, validating any types that occur in the
351349
// expression and folding sequence expressions.
352-
if (ConstraintSystem::preCheckExpression(
353-
expr, dc, /*replaceInvalidRefsWithErrors=*/true,
354-
options.contains(TypeCheckExprFlags::LeaveClosureBodyUnchecked))) {
355-
target.setExpr(expr);
350+
if (ConstraintSystem::preCheckTarget(
351+
target, /*replaceInvalidRefsWithErrors=*/true,
352+
options.contains(TypeCheckExprFlags::LeaveClosureBodyUnchecked))) {
356353
return None;
357354
}
358-
target.setExpr(expr);
355+
356+
auto *expr = target.getAsExpr();
359357

360358
// Check whether given expression has a code completion token which requires
361359
// special handling.
@@ -569,25 +567,6 @@ bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) {
569567
if (!sequenceProto)
570568
return failed();
571569

572-
// Precheck the sequence.
573-
Expr *sequence = stmt->getSequence();
574-
if (ConstraintSystem::preCheckExpression(
575-
sequence, dc, /*replaceInvalidRefsWithErrors=*/true,
576-
/*leaveClosureBodiesUnchecked=*/false))
577-
return failed();
578-
stmt->setSequence(sequence);
579-
580-
// Precheck the filtering condition.
581-
if (Expr *whereExpr = stmt->getWhere()) {
582-
if (ConstraintSystem::preCheckExpression(
583-
whereExpr, dc,
584-
/*replaceInvalidRefsWithErrors=*/true,
585-
/*leaveClosureBodiesUnchecked=*/false))
586-
return failed();
587-
588-
stmt->setWhere(whereExpr);
589-
}
590-
591570
auto target = SolutionApplicationTarget::forForEachStmt(
592571
stmt, sequenceProto, dc, /*bindPatternVarsOneWay=*/false);
593572
if (!typeCheckExpression(target))

0 commit comments

Comments
 (0)