Skip to content

Commit dfda7ac

Browse files
committed
[Constraint solver] Generalize "target" of solution application.
Chip away at the expression-centric nature of the constraint system by generalizing the "target" of solution application from a single expression to a a "SolutionApplicationTarget", which can be an expression or a function body. The latter will be used for applying function builders to an entire function body.
1 parent 51bbaeb commit dfda7ac

File tree

4 files changed

+140
-49
lines changed

4 files changed

+140
-49
lines changed

lib/Sema/CSApply.cpp

Lines changed: 60 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7206,10 +7206,9 @@ bool ConstraintSystem::applySolutionFixes(const Solution &solution) {
72067206

72077207
/// Apply a given solution to the expression, producing a fully
72087208
/// type-checked expression.
7209-
Expr *ConstraintSystem::applySolution(Solution &solution, Expr *expr,
7210-
Type convertType,
7211-
bool discardedExpr,
7212-
bool performingDiagnostics) {
7209+
llvm::PointerUnion<Expr *, Stmt *> ConstraintSystem::applySolutionImpl(
7210+
Solution &solution, SolutionApplicationTarget target, Type convertType,
7211+
bool discardedExpr, bool performingDiagnostics) {
72137212
// If any fixes needed to be applied to arrive at this solution, resolve
72147213
// them to specific expressions.
72157214
if (!solution.Fixes.empty()) {
@@ -7228,18 +7227,32 @@ Expr *ConstraintSystem::applySolution(Solution &solution, Expr *expr,
72287227

72297228
// If we didn't manage to diagnose anything well, so fall back to
72307229
// diagnosing mining the system to construct a reasonable error message.
7231-
diagnoseFailureForExpr(expr);
7230+
diagnoseFailureFor(target);
72327231
return nullptr;
72337232
}
72347233
}
72357234

72367235
ExprRewriter rewriter(*this, solution, shouldSuppressDiagnostics());
72377236
ExprWalker walker(rewriter);
72387237

7239-
// Apply the solution to the expression.
7240-
auto result = expr->walk(walker);
7241-
if (!result)
7242-
return nullptr;
7238+
// Apply the solution to the target.
7239+
llvm::PointerUnion<Expr *, Stmt *> result;
7240+
if (auto expr = target.getAsExpr()) {
7241+
result = expr->walk(walker);
7242+
} else {
7243+
// FIXME: Implement this!
7244+
llvm_unreachable("Not yet implemented");
7245+
7246+
#if false
7247+
auto fn = *target.getAsFunction();
7248+
auto transform = rewriter.getAppliedBuilderTransform(fn);
7249+
assert(transform && "Not applying builder transform?");
7250+
result = walker.applyFunctionBuilderBodyTransform(fn, transform);
7251+
#endif
7252+
}
7253+
7254+
if (result.isNull())
7255+
return result;
72437256

72447257
// If we're re-typechecking an expression for diagnostics, don't
72457258
// visit closures that have non-single expression bodies.
@@ -7261,28 +7274,36 @@ Expr *ConstraintSystem::applySolution(Solution &solution, Expr *expr,
72617274
return nullptr;
72627275
}
72637276

7264-
// We are supposed to use contextual type only if it is present and
7265-
// this expression doesn't represent the implicit return of the single
7266-
// expression function which got deduced to be `Never`.
7267-
auto shouldCoerceToContextualType = [&]() {
7268-
return convertType && !(getType(result)->isUninhabited() &&
7269-
getContextualTypePurpose() == CTP_ReturnSingleExpr);
7270-
};
7277+
if (auto resultExpr = result.dyn_cast<Expr *>()) {
7278+
Expr *expr = target.getAsExpr();
7279+
assert(expr && "Can't have expression result without expression target");
7280+
// We are supposed to use contextual type only if it is present and
7281+
// this expression doesn't represent the implicit return of the single
7282+
// expression function which got deduced to be `Never`.
7283+
auto shouldCoerceToContextualType = [&]() {
7284+
return convertType &&
7285+
!(getType(resultExpr)->isUninhabited() &&
7286+
getContextualTypePurpose() == CTP_ReturnSingleExpr);
7287+
};
72717288

7272-
// If we're supposed to convert the expression to some particular type,
7273-
// do so now.
7274-
if (shouldCoerceToContextualType()) {
7275-
result = rewriter.coerceToType(result, convertType,
7276-
getConstraintLocator(expr));
7277-
if (!result)
7278-
return nullptr;
7279-
} else if (getType(result)->hasLValueType() && !discardedExpr) {
7280-
// We referenced an lvalue. Load it.
7281-
result = rewriter.coerceToType(result, getType(result)->getRValueType(),
7282-
getConstraintLocator(expr));
7289+
// If we're supposed to convert the expression to some particular type,
7290+
// do so now.
7291+
if (shouldCoerceToContextualType()) {
7292+
result = rewriter.coerceToType(resultExpr, convertType,
7293+
getConstraintLocator(expr));
7294+
if (!result)
7295+
return nullptr;
7296+
} else if (getType(resultExpr)->hasLValueType() && !discardedExpr) {
7297+
// We referenced an lvalue. Load it.
7298+
result = rewriter.coerceToType(resultExpr,
7299+
getType(resultExpr)->getRValueType(),
7300+
getConstraintLocator(expr));
7301+
}
7302+
7303+
if (resultExpr)
7304+
solution.setExprTypes(resultExpr);
72837305
}
72847306

7285-
solution.setExprTypes(result);
72867307
rewriter.finalize();
72877308

72887309
return result;
@@ -7431,3 +7452,14 @@ ArrayRef<Solution> SolutionResult::getAmbiguousSolutions() const {
74317452
assert(getKind() == Ambiguous);
74327453
return makeArrayRef(solutions, numSolutions);
74337454
}
7455+
7456+
llvm::PointerUnion<Expr *, Stmt *> SolutionApplicationTarget::walk(
7457+
ASTWalker &walker) {
7458+
switch (kind) {
7459+
case Kind::expression:
7460+
return getAsExpr()->walk(walker);
7461+
7462+
case Kind::function:
7463+
return getAsFunction()->getBody()->walk(walker);
7464+
}
7465+
}

lib/Sema/CSDiag.cpp

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2430,30 +2430,32 @@ bool FailureDiagnosis::diagnoseExprFailure() {
24302430
///
24312431
/// This is guaranteed to always emit an error message.
24322432
///
2433-
void ConstraintSystem::diagnoseFailureForExpr(Expr *expr) {
2433+
void ConstraintSystem::diagnoseFailureFor(SolutionApplicationTarget target) {
24342434
setPhase(ConstraintSystemPhase::Diagnostics);
24352435

24362436
SWIFT_DEFER { setPhase(ConstraintSystemPhase::Finalization); };
24372437

2438-
// Look through RebindSelfInConstructorExpr to avoid weird Sema issues.
2439-
if (auto *RB = dyn_cast<RebindSelfInConstructorExpr>(expr))
2440-
expr = RB->getSubExpr();
2438+
if (auto expr = target.getAsExpr()) {
2439+
// Look through RebindSelfInConstructorExpr to avoid weird Sema issues.
2440+
if (auto *RB = dyn_cast<RebindSelfInConstructorExpr>(expr))
2441+
expr = RB->getSubExpr();
24412442

2442-
FailureDiagnosis diagnosis(expr, *this);
2443+
FailureDiagnosis diagnosis(expr, *this);
24432444

2444-
// Now, attempt to diagnose the failure from the info we've collected.
2445-
if (diagnosis.diagnoseExprFailure())
2446-
return;
2445+
// Now, attempt to diagnose the failure from the info we've collected.
2446+
if (diagnosis.diagnoseExprFailure())
2447+
return;
24472448

2448-
// If this is a contextual conversion problem, dig out some information.
2449-
if (diagnosis.diagnoseContextualConversionError(expr, getContextualType(),
2450-
getContextualTypePurpose()))
2451-
return;
2449+
// If this is a contextual conversion problem, dig out some information.
2450+
if (diagnosis.diagnoseContextualConversionError(expr, getContextualType(),
2451+
getContextualTypePurpose()))
2452+
return;
24522453

2453-
// If no one could find a problem with this expression or constraint system,
2454-
// then it must be well-formed... but is ambiguous. Handle this by diagnostic
2455-
// various cases that come up.
2456-
diagnosis.diagnoseAmbiguity(expr);
2454+
// If no one could find a problem with this expression or constraint system,
2455+
// then it must be well-formed... but is ambiguous. Handle this by diagnostic
2456+
// various cases that come up.
2457+
diagnosis.diagnoseAmbiguity(expr);
2458+
}
24572459
}
24582460

24592461
std::pair<Type, ContextualTypePurpose>

lib/Sema/CSSolver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1127,7 +1127,7 @@ bool ConstraintSystem::solve(Expr *&expr,
11271127
return true;
11281128

11291129
case SolutionResult::Kind::UndiagnosedError:
1130-
diagnoseFailureForExpr(expr);
1130+
diagnoseFailureFor(expr);
11311131
salvagedResult.markAsDiagnosed();
11321132
return true;
11331133

lib/Sema/ConstraintSystem.h

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,54 @@ struct DynamicCallableMethods {
11001100
}
11011101
};
11021102

1103+
/// Describes the target to which a constraint system's solution can be
1104+
/// applied.
1105+
class SolutionApplicationTarget {
1106+
enum class Kind {
1107+
expression,
1108+
function
1109+
} kind;
1110+
1111+
union {
1112+
Expr *expression;
1113+
AnyFunctionRef function;
1114+
};
1115+
1116+
public:
1117+
SolutionApplicationTarget(Expr *expr) {
1118+
kind = Kind::expression;
1119+
expression = expr;
1120+
}
1121+
1122+
SolutionApplicationTarget(AnyFunctionRef fn) {
1123+
kind = Kind::function;
1124+
function = fn;
1125+
}
1126+
1127+
Expr *getAsExpr() const {
1128+
switch (kind) {
1129+
case Kind::expression:
1130+
return expression;
1131+
1132+
case Kind::function:
1133+
return nullptr;
1134+
}
1135+
}
1136+
1137+
Optional<AnyFunctionRef> getAsFunction() const {
1138+
switch (kind) {
1139+
case Kind::expression:
1140+
return None;
1141+
1142+
case Kind::function:
1143+
return function;
1144+
}
1145+
}
1146+
1147+
/// Walk the contents of the application target.
1148+
llvm::PointerUnion<Expr *, Stmt *> walk(ASTWalker &walker);
1149+
};
1150+
11031151
enum class ConstraintSystemPhase {
11041152
ConstraintGeneration,
11051153
Solving,
@@ -2243,12 +2291,12 @@ class ConstraintSystem {
22432291
/// system to generate a plausible diagnosis of why the system could not be
22442292
/// solved.
22452293
///
2246-
/// \param expr The expression whose constraints we're investigating for a
2247-
/// better diagnostic.
2294+
/// \param target The solution target whose constraints we're investigating
2295+
/// for a better diagnostic.
22482296
///
22492297
/// Assuming that this constraint system is actually erroneous, this *always*
22502298
/// emits an error message.
2251-
void diagnoseFailureForExpr(Expr *expr);
2299+
void diagnoseFailureFor(SolutionApplicationTarget target);
22522300

22532301
bool diagnoseAmbiguity(ArrayRef<Solution> solutions);
22542302
bool diagnoseAmbiguityWithFixes(SmallVectorImpl<Solution> &solutions);
@@ -3922,6 +3970,12 @@ class ConstraintSystem {
39223970
findBestSolution(SmallVectorImpl<Solution> &solutions,
39233971
bool minimize);
39243972

3973+
private:
3974+
llvm::PointerUnion<Expr *, Stmt *> applySolutionImpl(
3975+
Solution &solution, SolutionApplicationTarget target,
3976+
Type convertType, bool discardedExpr, bool performingDiagnostics);
3977+
3978+
public:
39253979
/// Apply a given solution to the expression, producing a fully
39263980
/// type-checked expression.
39273981
///
@@ -3934,7 +3988,10 @@ class ConstraintSystem {
39343988
Expr *applySolution(Solution &solution, Expr *expr,
39353989
Type convertType,
39363990
bool discardedExpr,
3937-
bool performingDiagnostics);
3991+
bool performingDiagnostics) {
3992+
return applySolutionImpl(solution, expr, convertType, discardedExpr,
3993+
performingDiagnostics).get<Expr *>();
3994+
}
39383995

39393996
/// Reorder the disjunctive clauses for a given expression to
39403997
/// increase the likelihood that a favored constraint will be successfully

0 commit comments

Comments
 (0)