Skip to content

Commit 056f4e6

Browse files
committed
fix: Cleanup delayed_check with sort variables
1 parent 1d11a86 commit 056f4e6

File tree

2 files changed

+36
-17
lines changed

2 files changed

+36
-17
lines changed

engine/uState.ml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -158,18 +158,18 @@ let set q qv m =
158158
let q, rigid = match q with ReprVar (q, rigid) -> q, rigid | ReprConstant _ -> assert false in
159159
let qv = match qv with QVar qv -> repr_node qv m | QConstant qc -> ReprConstant qc in
160160
let enforce_eq q1 q2 g = QGraph.enforce_eliminates_to q1 q2 (QGraph.enforce_eliminates_to q2 q1 g) in
161-
match q, qv with
162-
| q, ReprVar (qv, _qvrigd) ->
161+
match qv with
162+
| ReprVar (qv, _qvrigd) ->
163163
if QVar.equal q qv then Some m
164164
else if rigid then None
165165
else
166166
let above_prop =
167167
if is_above_prop m q
168168
then QSet.add qv (QSet.remove q m.above_prop)
169169
else m.above_prop in
170-
Some { qmap = QMap.add q (Equiv (QVar qv)) m.qmap; above_prop;
171-
elims = enforce_eq (QVar qv) (QVar q) m.elims; initial_elims = m.initial_elims }
172-
| q, ReprConstant qc ->
170+
Some { m with qmap = QMap.add q (Equiv (QVar qv)) m.qmap; above_prop;
171+
elims = enforce_eq (QVar qv) (QVar q) m.elims; }
172+
| ReprConstant qc ->
173173
if qc == QSProp && (is_above_prop m q || eliminates_to_prop m q) then None
174174
else if rigid then None
175175
else

kernel/qGraph.ml

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -154,11 +154,31 @@ let rec update_dominance g q qv =
154154
| Some q' -> update_dominant_if_related g qv q' q in
155155
match QMap.find_opt qv g.delayed_check with
156156
| None -> g'
157-
| Some qs ->
158-
let g' = QSet.fold (fun v g -> Option.bind g (fun g -> update_dominance g q v)) qs g' in
159-
match g' with
160-
| Some graph -> Some { graph with delayed_check = QMap.set qv QSet.empty g.delayed_check }
161-
| None -> None
157+
| Some delayed_qs ->
158+
(* When two sort variables are `set` to each other, e.g. uState, (q1 <-> q2), without being
159+
dominated, then both delay the domination check of each other:
160+
delayed_check[q1] = {q2}
161+
delayed_check[q2] = {q1}
162+
163+
When one of them becomes dominated, e.g. q1 dominated by Type, then we need to clear up
164+
any occurrence of it in the delayed check of the other, e.g. remove q1 from delayed_check[q2].
165+
Otherwise, we end up in a loop. *)
166+
let remove_qv_from_delayed delayed_q delayed_check =
167+
match QMap.find_opt delayed_q delayed_check with
168+
| None -> delayed_check
169+
| Some dqs ->
170+
QMap.set delayed_q (QSet.remove qv dqs) delayed_check
171+
in
172+
let clearup_cyclic_delay graph =
173+
QSet.fold (fun delayed_q acc_graph ->
174+
{ acc_graph with delayed_check = remove_qv_from_delayed delayed_q acc_graph.delayed_check })
175+
delayed_qs graph
176+
in
177+
let g' = Option.map clearup_cyclic_delay g' in
178+
let g' = QSet.fold (fun v g -> Option.bind g (fun g -> update_dominance g q v)) delayed_qs g' in
179+
match g' with
180+
| Some graph -> Some { graph with delayed_check = QMap.set qv QSet.empty g.delayed_check }
181+
| None -> None
162182

163183
let update_dominance_if_valid g (q1,k,q2) =
164184
match k with
@@ -229,9 +249,8 @@ let enforce_constraint (q1, k, q2) g =
229249
let e = lazy (G.get_explanation (q1,to_graph_cstr k,q2) g.graph) in
230250
raise @@ EliminationError (QualityInconsistency (None, (k, q1, q2, Some (Path e))))
231251
| Some graph ->
232-
let g = { g with graph } in
233-
if Quality.equal q1 q2 then g
234-
else dominance_check g (q1, k, q2)
252+
if Quality.equal q1 q2 then graph
253+
else dominance_check graph (q1, k, q2)
235254

236255
let merge_constraints csts g = ElimConstraints.fold enforce_constraint csts g
237256

@@ -296,10 +315,10 @@ let merge g g' =
296315
(fun q acc -> try add_quality q acc with _ -> acc) qs g in
297316
Quality.Set.fold
298317
(fun q -> Quality.Set.fold
299-
(fun q' acc -> if Quality.equal q q' then acc
300-
else if eliminates_to g' q q'
301-
then enforce_eliminates_to q q' acc
302-
else acc) qs) qs g
318+
(fun q' acc -> if Quality.equal q q' then acc
319+
else if eliminates_to g' q q'
320+
then enforce_eliminates_to q q' acc
321+
else acc) qs) qs g
303322

304323
let is_empty g = QVar.Set.is_empty (qvar_domain g)
305324

0 commit comments

Comments
 (0)