Skip to content

Commit 98a6a84

Browse files
committed
[CSStep] Conjunction: integrate isolation scope into snapshot
It helps to simply handling of outer constrants because they have to be added to the constraint system before scope is created but constraint graph have to get updated after to make sure that incremental binding inference already knows about types inferred from conjunction.
1 parent cedb345 commit 98a6a84

File tree

2 files changed

+52
-29
lines changed

2 files changed

+52
-29
lines changed

Diff for: lib/Sema/CSStep.cpp

+10-21
Original file line numberDiff line numberDiff line change
@@ -821,9 +821,7 @@ StepResult ConjunctionStep::resume(bool prevFailed) {
821821
// Return from the follow-up splitter step that
822822
// attempted to apply information gained from the
823823
// isolated constraint to the outer context.
824-
if (bool(IsolationScope)) {
825-
IsolationScope.reset();
826-
824+
if (Snapshot && Snapshot->isScoped()) {
827825
if (CS.isDebugMode())
828826
getDebugLogger() << ")\n";
829827

@@ -870,18 +868,6 @@ StepResult ConjunctionStep::resume(bool prevFailed) {
870868
// solving along the current path until complete
871869
// solution is reached.
872870
if (Producer.isExhausted()) {
873-
// Restore constraint system state before conjunction.
874-
//
875-
// Note that this doesn't include conjunction constraint
876-
// itself because we don't want to re-solve it at this
877-
// point.
878-
if (Conjunction->isIsolated()) {
879-
assert(
880-
Snapshot &&
881-
"Isolated conjunction requires a snapshot of the constraint system");
882-
Snapshot.reset();
883-
}
884-
885871
// If one of the elements failed, that means while
886872
// conjunction failed with it.
887873
if (HadFailure)
@@ -901,12 +887,15 @@ StepResult ConjunctionStep::resume(bool prevFailed) {
901887
log << "(applying conjunction result to outer context\n";
902888
}
903889

904-
// Establish isolation scope so that conjunction solution
905-
// and follow-up steps could be rolled back.
906-
IsolationScope = std::make_unique<Scope>(CS);
907-
908-
// Apply solution inferred for the conjunction.
909-
CS.applySolution(Solutions.pop_back_val());
890+
// Restore constraint system state before conjunction.
891+
//
892+
// Note that this doesn't include conjunction constraint
893+
// itself because we don't want to re-solve it at this
894+
// point.
895+
assert(
896+
Snapshot &&
897+
"Isolated conjunction requires a snapshot of the constraint system");
898+
Snapshot->setupOuterContext(Solutions.pop_back_val());
910899

911900
// Restore best score, since upcoming step is going to
912901
// work with outer scope in relation to the conjunction.

Diff for: lib/Sema/CSStep.h

+42-8
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,12 @@ class ConjunctionStep : public BindingStep<ConjunctionElementProducer> {
775775
llvm::SetVector<TypeVariableType *> TypeVars;
776776
ConstraintList Constraints;
777777

778+
/// If this conjunction has to be solved in isolation,
779+
/// this scope would be initialized once all of the
780+
/// elements are successfully solved to continue solving
781+
/// along the current path as-if there was no conjunction.
782+
std::unique_ptr<Scope> IsolationScope = nullptr;
783+
778784
public:
779785
SolverSnapshot(ConstraintSystem &cs)
780786
: CS(cs), TypeVars(std::move(cs.TypeVariables)) {
@@ -786,12 +792,47 @@ class ConjunctionStep : public BindingStep<ConjunctionElementProducer> {
786792
CG.removeConstraint(&constraint);
787793
}
788794

795+
void setupOuterContext(Solution solution) {
796+
// Re-add type variables and constraints back
797+
// to the constraint system.
798+
restore();
799+
800+
// Establish isolation scope so that conjunction solution
801+
// and follow-up steps could be rolled back.
802+
IsolationScope = std::make_unique<Scope>(CS);
803+
804+
// Apply solution inferred for the conjunction.
805+
CS.applySolution(solution);
806+
807+
// Add constraints to the graph after solution
808+
// has been applied to make sure that all type
809+
// information is available to incremental inference.
810+
for (auto &constraint : CS.InactiveConstraints)
811+
CS.CG.addConstraint(&constraint);
812+
}
813+
814+
bool isScoped() const { return bool(IsolationScope); }
815+
789816
~SolverSnapshot() {
790-
auto &CG = CS.getConstraintGraph();
817+
if (!IsolationScope)
818+
restore();
819+
820+
IsolationScope.reset();
821+
// Re-add all of the constraint to the constraint
822+
// graph after scope has been rolled back, to make
823+
// make sure the original (before conjunction)
824+
// state is completely restored.
825+
updateConstraintGraph();
826+
}
791827

828+
private:
829+
void restore() {
792830
CS.TypeVariables = std::move(TypeVars);
793831
CS.InactiveConstraints.splice(CS.InactiveConstraints.end(), Constraints);
832+
}
794833

834+
void updateConstraintGraph() {
835+
auto &CG = CS.getConstraintGraph();
795836
for (auto &constraint : CS.InactiveConstraints)
796837
CG.addConstraint(&constraint);
797838
}
@@ -812,12 +853,6 @@ class ConjunctionStep : public BindingStep<ConjunctionElementProducer> {
812853
/// Indicates that one of the elements failed inference.
813854
bool HadFailure = false;
814855

815-
/// If this conjunction has to be solved in isolation,
816-
/// this scope would be initialized once all of the
817-
/// elements are successfully solved to continue solving
818-
/// along the current path as-if there was no conjunction.
819-
std::unique_ptr<Scope> IsolationScope = nullptr;
820-
821856
/// If conjunction has to be solved in isolation, this
822857
/// variable would capture the snapshot of the constraint
823858
/// system step before conjunction step.
@@ -838,7 +873,6 @@ class ConjunctionStep : public BindingStep<ConjunctionElementProducer> {
838873

839874
~ConjunctionStep() override {
840875
assert(!bool(ActiveChoice));
841-
assert(!bool(IsolationScope));
842876

843877
// Return all of the type variables and constraints back.
844878
Snapshot.reset();

0 commit comments

Comments
 (0)