Skip to content

Commit 4debf30

Browse files
committed
[CSStep] Conjunction: Propagate fix and hole scores to outer solution
While producing a combined solution, let's reflect the number of fixes and holes discovered in the conjunction, that way it would be possible to filter solutions and keep track of the fact that there were issues in the conjunction.
1 parent dfadee3 commit 4debf30

File tree

2 files changed

+36
-19
lines changed

2 files changed

+36
-19
lines changed

lib/Sema/CSStep.cpp

+25-14
Original file line numberDiff line numberDiff line change
@@ -942,13 +942,10 @@ StepResult ConjunctionStep::resume(bool prevFailed) {
942942
// and scoring information.
943943
Snapshot.reset();
944944

945-
// Restore original scores of outer context before
946-
// trying to produce a combined solution.
947-
restoreOriginalScores();
948-
949945
// Apply all of the information deduced from the
950946
// conjunction (up to the point of ambiguity)
951947
// back to the outer context and form a joined solution.
948+
unsigned numSolutions = 0;
952949
for (auto &solution : Solutions) {
953950
ConstraintSystem::SolverScope scope(CS);
954951

@@ -958,34 +955,47 @@ StepResult ConjunctionStep::resume(bool prevFailed) {
958955
// of the constraint system, so they have to be
959956
// restored right afterwards because score of the
960957
// element does contribute to the overall score.
961-
restoreOriginalScores();
958+
restoreBestScore();
959+
restoreCurrentScore(solution.getFixedScore());
962960

963961
// Transform all of the unbound outer variables into
964962
// placeholders since we are not going to solve for
965963
// each ambguous solution.
966-
for (auto *typeVar : CS.getTypeVariables()) {
967-
if (!typeVar->getImpl().hasRepresentativeOrFixed()) {
968-
CS.assignFixedType(
969-
typeVar, PlaceholderType::get(CS.getASTContext(), typeVar));
964+
{
965+
unsigned numHoles = 0;
966+
for (auto *typeVar : CS.getTypeVariables()) {
967+
if (!typeVar->getImpl().hasRepresentativeOrFixed()) {
968+
CS.assignFixedType(
969+
typeVar, PlaceholderType::get(CS.getASTContext(), typeVar));
970+
++numHoles;
971+
}
970972
}
973+
CS.increaseScore(SK_Hole, numHoles);
971974
}
972975

976+
if (CS.worseThanBestSolution())
977+
continue;
978+
973979
// Note that `worseThanBestSolution` isn't checked
974980
// here because `Solutions` were pre-filtered, and
975981
// outer score is the same for all of them.
976982
OuterSolutions.push_back(CS.finalize());
983+
++numSolutions;
977984
}
978985

979-
return done(/*isSuccess=*/true);
986+
return done(/*isSuccess=*/numSolutions > 0);
980987
}
981988

989+
auto solution = Solutions.pop_back_val();
990+
auto score = solution.getFixedScore();
991+
982992
// Restore outer type variables and prepare to solve
983993
// constraints associated with outer context together
984994
// with information deduced from the conjunction.
985-
Snapshot->setupOuterContext(Solutions.pop_back_val());
995+
Snapshot->setupOuterContext(std::move(solution));
986996

987997
// Pretend that conjunction never happened.
988-
restoreOuterState();
998+
restoreOuterState(score);
989999

9901000
// Now that all of the information from the conjunction has
9911001
// been applied, let's attempt to solve the outer scope.
@@ -997,10 +1007,11 @@ StepResult ConjunctionStep::resume(bool prevFailed) {
9971007
return take(prevFailed);
9981008
}
9991009

1000-
void ConjunctionStep::restoreOuterState() const {
1010+
void ConjunctionStep::restoreOuterState(const Score &solutionScore) const {
10011011
// Restore best/current score, since upcoming step is going to
10021012
// work with outer scope in relation to the conjunction.
1003-
restoreOriginalScores();
1013+
restoreBestScore();
1014+
restoreCurrentScore(solutionScore);
10041015

10051016
// Active all of the previously out-of-scope constraints
10061017
// because conjunction can propagate type information up

lib/Sema/CSStep.h

+11-5
Original file line numberDiff line numberDiff line change
@@ -962,8 +962,11 @@ class ConjunctionStep : public BindingStep<ConjunctionElementProducer> {
962962

963963
// Restore best score only if conjunction fails because
964964
// successful outcome should keep a score set by `restoreOuterState`.
965-
if (HadFailure)
966-
restoreOriginalScores();
965+
if (HadFailure) {
966+
auto solutionScore = Score();
967+
restoreBestScore();
968+
restoreCurrentScore(solutionScore);
969+
}
967970

968971
if (OuterTimeRemaining) {
969972
auto anchor = OuterTimeRemaining->first;
@@ -1015,16 +1018,19 @@ class ConjunctionStep : public BindingStep<ConjunctionElementProducer> {
10151018

10161019
private:
10171020
/// Restore best and current scores as they were before conjunction.
1018-
void restoreOriginalScores() const {
1019-
CS.solverState->BestScore = BestScore;
1021+
void restoreCurrentScore(const Score &solutionScore) const {
10201022
CS.CurrentScore = CurrentScore;
1023+
CS.increaseScore(SK_Fix, solutionScore.Data[SK_Fix]);
1024+
CS.increaseScore(SK_Hole, solutionScore.Data[SK_Hole]);
10211025
}
10221026

1027+
void restoreBestScore() const { CS.solverState->BestScore = BestScore; }
1028+
10231029
// Restore constraint system state before conjunction.
10241030
//
10251031
// Note that this doesn't include conjunction constraint
10261032
// itself because we don't want to re-solve it.
1027-
void restoreOuterState() const;
1033+
void restoreOuterState(const Score &solutionScore) const;
10281034
};
10291035

10301036
} // end namespace constraints

0 commit comments

Comments
 (0)