Skip to content

Commit f9d61a0

Browse files
committed
Sema: New way to type check an expression without applying the solution
This introduces a new TypeCheckExprFlags::SkipApplyingSolution flag, and a ExprTypeCheckListener::foundSolution() that is invoked before the solution is applied. While the existing getTypeOfExpressionWithoutApplying() method is similar, it's tailored for diagnostics and has some hacks in it. It should be refactored to use the new mechanism I added.
1 parent 451600c commit f9d61a0

File tree

2 files changed

+29
-5
lines changed

2 files changed

+29
-5
lines changed

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1631,6 +1631,10 @@ bool ExprTypeCheckListener::builtConstraints(ConstraintSystem &cs, Expr *expr) {
16311631
return false;
16321632
}
16331633

1634+
Expr *ExprTypeCheckListener::foundSolution(Solution &solution, Expr *expr) {
1635+
return expr;
1636+
}
1637+
16341638
Expr *ExprTypeCheckListener::appliedSolution(Solution &solution, Expr *expr) {
16351639
return expr;
16361640
}
@@ -1864,14 +1868,24 @@ bool TypeChecker::typeCheckExpression(Expr *&expr, DeclContext *dc,
18641868
expr->setType(ErrorType::get(Context));
18651869
return false;
18661870
}
1867-
1868-
// Apply the solution to the expression.
1871+
1872+
auto result = expr;
18691873
auto &solution = viable[0];
1874+
if (listener) {
1875+
result = listener->foundSolution(solution, result);
1876+
if (!result)
1877+
return true;
1878+
}
1879+
1880+
if (options.contains(TypeCheckExprFlags::SkipApplyingSolution))
1881+
return false;
1882+
1883+
// Apply the solution to the expression.
18701884
bool isDiscarded = options.contains(TypeCheckExprFlags::IsDiscarded);
18711885
bool skipClosures = options.contains(TypeCheckExprFlags::SkipMultiStmtClosures);
1872-
auto result = cs.applySolution(solution, expr, convertType.getType(),
1873-
isDiscarded, suppressDiagnostics,
1874-
skipClosures);
1886+
result = cs.applySolution(solution, result, convertType.getType(),
1887+
isDiscarded, suppressDiagnostics,
1888+
skipClosures);
18751889
if (!result) {
18761890
// Failure already diagnosed, above, as part of applying the solution.
18771891
return true;

lib/Sema/TypeChecker.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,9 @@ enum class TypeCheckExprFlags {
224224
/// Set if the client prefers fixits to be in the form of force unwrapping
225225
/// or optional chaining to return an optional.
226226
PreferForceUnwrapToOptional = 0x80,
227+
228+
/// If set, don't apply a solution.
229+
SkipApplyingSolution = 0x100,
227230
};
228231

229232
typedef OptionSet<TypeCheckExprFlags> TypeCheckExprOptions;
@@ -325,6 +328,13 @@ class ExprTypeCheckListener {
325328
/// constraint system, or false otherwise.
326329
virtual bool builtConstraints(constraints::ConstraintSystem &cs, Expr *expr);
327330

331+
/// Callback invoked once a solution has been found.
332+
///
333+
/// The callback may further alter the expression, returning either a
334+
/// new expression (to replace the result) or a null pointer to indicate
335+
/// failure.
336+
virtual Expr *foundSolution(constraints::Solution &solution, Expr *expr);
337+
328338
/// Callback invokes once the chosen solution has been applied to the
329339
/// expression.
330340
///

0 commit comments

Comments
 (0)