Skip to content

Commit d903ca9

Browse files
authored
Merge pull request swiftlang#29026 from DougGregor/generalize-solution-apply
Generalize solution application
2 parents b6e0ffd + fffe129 commit d903ca9

File tree

6 files changed

+170
-72
lines changed

6 files changed

+170
-72
lines changed

include/swift/AST/AnyFunctionRef.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,14 @@ class AnyFunctionRef {
208208
llvm_unreachable("unexpected AnyFunctionRef representation");
209209
}
210210

211+
friend bool operator==(AnyFunctionRef lhs, AnyFunctionRef rhs) {
212+
return lhs.TheFunction == rhs.TheFunction;
213+
}
214+
215+
friend bool operator!=(AnyFunctionRef lhs, AnyFunctionRef rhs) {
216+
return lhs.TheFunction != rhs.TheFunction;
217+
}
218+
211219
private:
212220
ArrayRef<AnyFunctionType::Yield>
213221
getYieldResultsImpl(SmallVectorImpl<AnyFunctionType::Yield> &buffer,

lib/Sema/BuilderTransform.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -604,13 +604,13 @@ ConstraintSystem::TypeMatchResult ConstraintSystem::applyFunctionBuilder(
604604

605605
// Record the transformation.
606606
assert(std::find_if(
607-
builderTransformedClosures.begin(),
608-
builderTransformedClosures.end(),
609-
[&](const std::pair<ClosureExpr *, AppliedBuilderTransform> &elt) {
607+
functionBuilderTransformed.begin(),
608+
functionBuilderTransformed.end(),
609+
[&](const std::pair<AnyFunctionRef, AppliedBuilderTransform> &elt) {
610610
return elt.first == closure;
611-
}) == builderTransformedClosures.end() &&
611+
}) == functionBuilderTransformed.end() &&
612612
"already transformed this closure along this path!?!");
613-
builderTransformedClosures.push_back(
613+
functionBuilderTransformed.push_back(
614614
std::make_pair(closure,
615615
AppliedBuilderTransform{builderType, singleExpr}));
616616

lib/Sema/CSApply.cpp

Lines changed: 62 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7041,9 +7041,8 @@ namespace {
70417041
// If this closure had a function builder applied, rewrite it to a
70427042
// closure with a single expression body containing the builder
70437043
// invocations.
7044-
auto builder =
7045-
Rewriter.solution.builderTransformedClosures.find(closure);
7046-
if (builder != Rewriter.solution.builderTransformedClosures.end()) {
7044+
auto builder = Rewriter.solution.functionBuilderTransformed.find(closure);
7045+
if (builder != Rewriter.solution.functionBuilderTransformed.end()) {
70477046
auto singleExpr = builder->second.singleExpr;
70487047
auto returnStmt = new (ctx) ReturnStmt(
70497048
singleExpr->getStartLoc(), singleExpr, /*implicit=*/true);
@@ -7206,10 +7205,9 @@ bool ConstraintSystem::applySolutionFixes(const Solution &solution) {
72067205

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

72297227
// If we didn't manage to diagnose anything well, so fall back to
72307228
// diagnosing mining the system to construct a reasonable error message.
7231-
diagnoseFailureForExpr(expr);
7229+
diagnoseFailureFor(target);
72327230
return nullptr;
72337231
}
72347232
}
72357233

72367234
ExprRewriter rewriter(*this, solution, shouldSuppressDiagnostics());
72377235
ExprWalker walker(rewriter);
72387236

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

72447256
// If we're re-typechecking an expression for diagnostics, don't
72457257
// visit closures that have non-single expression bodies.
@@ -7261,28 +7273,36 @@ Expr *ConstraintSystem::applySolution(Solution &solution, Expr *expr,
72617273
return nullptr;
72627274
}
72637275

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

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));
7288+
// If we're supposed to convert the expression to some particular type,
7289+
// do so now.
7290+
if (shouldCoerceToContextualType()) {
7291+
result = rewriter.coerceToType(resultExpr, convertType,
7292+
getConstraintLocator(expr));
7293+
if (!result)
7294+
return nullptr;
7295+
} else if (getType(resultExpr)->hasLValueType() && !discardedExpr) {
7296+
// We referenced an lvalue. Load it.
7297+
result = rewriter.coerceToType(resultExpr,
7298+
getType(resultExpr)->getRValueType(),
7299+
getConstraintLocator(expr));
7300+
}
7301+
7302+
if (resultExpr)
7303+
solution.setExprTypes(resultExpr);
72837304
}
72847305

7285-
solution.setExprTypes(result);
72867306
rewriter.finalize();
72877307

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

lib/Sema/CSDiag.cpp

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2420,30 +2420,32 @@ bool FailureDiagnosis::diagnoseExprFailure() {
24202420
///
24212421
/// This is guaranteed to always emit an error message.
24222422
///
2423-
void ConstraintSystem::diagnoseFailureForExpr(Expr *expr) {
2423+
void ConstraintSystem::diagnoseFailureFor(SolutionApplicationTarget target) {
24242424
setPhase(ConstraintSystemPhase::Diagnostics);
24252425

24262426
SWIFT_DEFER { setPhase(ConstraintSystemPhase::Finalization); };
24272427

2428-
// Look through RebindSelfInConstructorExpr to avoid weird Sema issues.
2429-
if (auto *RB = dyn_cast<RebindSelfInConstructorExpr>(expr))
2430-
expr = RB->getSubExpr();
2428+
if (auto expr = target.getAsExpr()) {
2429+
// Look through RebindSelfInConstructorExpr to avoid weird Sema issues.
2430+
if (auto *RB = dyn_cast<RebindSelfInConstructorExpr>(expr))
2431+
expr = RB->getSubExpr();
24312432

2432-
FailureDiagnosis diagnosis(expr, *this);
2433+
FailureDiagnosis diagnosis(expr, *this);
24332434

2434-
// Now, attempt to diagnose the failure from the info we've collected.
2435-
if (diagnosis.diagnoseExprFailure())
2436-
return;
2435+
// Now, attempt to diagnose the failure from the info we've collected.
2436+
if (diagnosis.diagnoseExprFailure())
2437+
return;
24372438

2438-
// If this is a contextual conversion problem, dig out some information.
2439-
if (diagnosis.diagnoseContextualConversionError(expr, getContextualType(),
2440-
getContextualTypePurpose()))
2441-
return;
2439+
// If this is a contextual conversion problem, dig out some information.
2440+
if (diagnosis.diagnoseContextualConversionError(expr, getContextualType(),
2441+
getContextualTypePurpose()))
2442+
return;
24422443

2443-
// If no one could find a problem with this expression or constraint system,
2444-
// then it must be well-formed... but is ambiguous. Handle this by diagnostic
2445-
// various cases that come up.
2446-
diagnosis.diagnoseAmbiguity(expr);
2444+
// If no one could find a problem with this expression or constraint system,
2445+
// then it must be well-formed... but is ambiguous. Handle this by diagnostic
2446+
// various cases that come up.
2447+
diagnosis.diagnoseAmbiguity(expr);
2448+
}
24472449
}
24482450

24492451
std::pair<Type, ContextualTypePurpose>

lib/Sema/CSSolver.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -171,13 +171,13 @@ Solution ConstraintSystem::finalize() {
171171
for (auto &e : CheckedConformances)
172172
solution.Conformances.push_back({e.first, e.second});
173173

174-
for (const auto &transformed : builderTransformedClosures) {
174+
for (const auto &transformed : functionBuilderTransformed) {
175175
auto known =
176-
solution.builderTransformedClosures.find(transformed.first);
177-
if (known != solution.builderTransformedClosures.end()) {
176+
solution.functionBuilderTransformed.find(transformed.first);
177+
if (known != solution.functionBuilderTransformed.end()) {
178178
assert(known->second.singleExpr == transformed.second.singleExpr);
179179
}
180-
solution.builderTransformedClosures.insert(transformed);
180+
solution.functionBuilderTransformed.insert(transformed);
181181
}
182182

183183
return solution;
@@ -241,8 +241,8 @@ void ConstraintSystem::applySolution(const Solution &solution) {
241241
for (auto &conformance : solution.Conformances)
242242
CheckedConformances.push_back(conformance);
243243

244-
for (const auto &transformed : solution.builderTransformedClosures) {
245-
builderTransformedClosures.push_back(transformed);
244+
for (const auto &transformed : solution.functionBuilderTransformed) {
245+
functionBuilderTransformed.push_back(transformed);
246246
}
247247

248248
// Register any fixes produced along this path.
@@ -436,7 +436,7 @@ ConstraintSystem::SolverScope::SolverScope(ConstraintSystem &cs)
436436
numCheckedConformances = cs.CheckedConformances.size();
437437
numDisabledConstraints = cs.solverState->getNumDisabledConstraints();
438438
numFavoredConstraints = cs.solverState->getNumFavoredConstraints();
439-
numBuilderTransformedClosures = cs.builderTransformedClosures.size();
439+
numFunctionBuilderTransformed = cs.functionBuilderTransformed.size();
440440
numResolvedOverloads = cs.ResolvedOverloads.size();
441441

442442
PreviousScore = cs.CurrentScore;
@@ -503,7 +503,7 @@ ConstraintSystem::SolverScope::~SolverScope() {
503503
truncate(cs.CheckedConformances, numCheckedConformances);
504504

505505
/// Remove any builder transformed closures.
506-
truncate(cs.builderTransformedClosures, numBuilderTransformedClosures);
506+
truncate(cs.functionBuilderTransformed, numFunctionBuilderTransformed);
507507

508508
// Reset the previous score.
509509
cs.CurrentScore = PreviousScore;
@@ -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

0 commit comments

Comments
 (0)