1use std::{
2 cell::RefCell,
3 ops::ControlFlow,
4 rc::{Rc, Weak},
5};
6
7use flux_common::{index::IndexVec, iter::IterExt, tracked_span_bug};
8use flux_config::OverflowMode;
9use flux_macros::DebugAsJson;
10use flux_middle::{
11 global_env::GlobalEnv,
12 pretty::{PrettyCx, PrettyNested, format_cx},
13 queries::QueryResult,
14 rty::{
15 BaseTy, EVid, Expr, ExprKind, KVid, Name, NameProvenance, PrettyVar, Sort, Ty, TyKind, Var,
16 fold::{TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor},
17 },
18};
19use itertools::Itertools;
20use rustc_data_structures::{
21 snapshot_map::SnapshotMap,
22 unord::{UnordMap, UnordSet},
23};
24use rustc_hash::FxHashSet;
25use rustc_index::newtype_index;
26use serde::Serialize;
27
28use crate::{
29 evars::EVarStore,
30 fixpoint_encoding::{FixpointCtxt, fixpoint},
31 infer::{Tag, TypeTrace},
32};
33
34pub struct RefineTree {
52 root: NodePtr,
53}
54
55impl RefineTree {
56 pub(crate) fn new(params: Vec<(Var, Sort)>, assumptions: Vec<Expr>) -> RefineTree {
57 let root = Node {
58 kind: NodeKind::Root(params, assumptions),
59 nbindings: 0,
60 parent: None,
61 children: vec![],
62 };
63 let root = NodePtr(Rc::new(RefCell::new(root)));
64 RefineTree { root }
65 }
66
67 pub(crate) fn simplify(&mut self, genv: GlobalEnv) {
68 self.root
69 .borrow_mut()
70 .simplify(SimplifyPhase::Full(genv), &mut SnapshotMap::default());
71 self.root.borrow_mut().simplify_bot();
72 self.root.borrow_mut().simplify_top();
73 }
74
75 pub(crate) fn to_fixpoint(
76 &self,
77 cx: &mut FixpointCtxt<Tag>,
78 ) -> QueryResult<fixpoint::Constraint> {
79 Ok(self
80 .root
81 .borrow()
82 .to_fixpoint(cx)?
83 .unwrap_or(fixpoint::Constraint::TRUE))
84 }
85
86 pub(crate) fn cursor_at_root(&mut self) -> Cursor<'_> {
87 Cursor { ptr: NodePtr(Rc::clone(&self.root)), tree: self }
88 }
89
90 pub(crate) fn replace_evars(&mut self, evars: &EVarStore) -> Result<(), EVid> {
91 self.root.borrow_mut().replace_evars(evars)
92 }
93}
94
95pub struct Cursor<'a> {
100 tree: &'a mut RefineTree,
101 ptr: NodePtr,
102}
103
104impl Cursor<'_> {
105 pub(crate) fn move_to(&mut self, marker: &Marker, clear_children: bool) -> Option<Cursor<'_>> {
111 let ptr = marker.ptr.upgrade()?;
112 if clear_children {
113 ptr.borrow_mut().children.clear();
114 }
115 Some(Cursor { ptr, tree: self.tree })
116 }
117
118 #[must_use]
120 pub(crate) fn marker(&self) -> Marker {
121 Marker { ptr: NodePtr::downgrade(&self.ptr) }
122 }
123
124 #[must_use]
125 pub(crate) fn branch(&mut self) -> Cursor<'_> {
126 Cursor { tree: self.tree, ptr: NodePtr::clone(&self.ptr) }
127 }
128
129 pub(crate) fn vars(&self) -> impl Iterator<Item = (Var, Sort)> {
130 self.ptr.scope().into_iter()
132 }
133
134 #[expect(dead_code, reason = "used for debugging")]
135 pub(crate) fn push_trace(&mut self, trace: TypeTrace) {
136 self.ptr = self.ptr.push_node(NodeKind::Trace(trace));
137 }
138
139 pub(crate) fn define_var(&mut self, sort: &Sort, provenance: NameProvenance) -> Name {
142 let fresh = Name::from_usize(self.ptr.next_name_idx());
143 self.ptr = self
144 .ptr
145 .push_node(NodeKind::ForAll(fresh, sort.clone(), provenance));
146 fresh
147 }
148
149 pub(crate) fn assume_pred(&mut self, pred: impl Into<Expr>) {
153 let pred = pred.into();
154 if !pred.is_trivially_true() {
155 self.ptr = self.ptr.push_node(NodeKind::Assumption(pred));
156 }
157 }
158
159 pub(crate) fn check_pred(&mut self, pred: impl Into<Expr>, tag: Tag) {
162 let pred = pred.into();
163 if !pred.is_trivially_true() {
164 self.ptr.push_node(NodeKind::Head(pred, tag));
165 }
166 }
167
168 pub(crate) fn check_impl(&mut self, pred1: impl Into<Expr>, pred2: impl Into<Expr>, tag: Tag) {
171 self.ptr
172 .push_node(NodeKind::Assumption(pred1.into()))
173 .push_node(NodeKind::Head(pred2.into(), tag));
174 }
175
176 pub(crate) fn assume_invariants(
177 &mut self,
178 genv: GlobalEnv,
179 ty: &Ty,
180 overflow_checking: OverflowMode,
181 ) {
182 struct Visitor<'cursor, 'tree, 'genv, 'tcx> {
183 genv: GlobalEnv<'genv, 'tcx>,
184 cursor: &'cursor mut Cursor<'tree>,
185 overflow_mode: OverflowMode,
186 }
187 impl TypeVisitor for Visitor<'_, '_, '_, '_> {
188 fn visit_bty(&mut self, bty: &BaseTy) -> ControlFlow<!> {
189 match bty {
190 BaseTy::Adt(adt_def, substs) if adt_def.is_box() => substs.visit_with(self),
191 BaseTy::Ref(_, ty, _) => ty.visit_with(self),
192 BaseTy::Tuple(tys) => tys.visit_with(self),
193 _ => ControlFlow::Continue(()),
194 }
195 }
196
197 fn visit_ty(&mut self, ty: &Ty) -> ControlFlow<!> {
198 if let TyKind::Indexed(bty, idx) = ty.kind()
199 && !idx.has_escaping_bvars()
200 {
201 for invariant in bty.invariants(self.genv, self.overflow_mode) {
202 let invariant = invariant.apply(idx);
203 self.cursor.assume_pred(&invariant);
204 }
205 }
206 ty.super_visit_with(self)
207 }
208 }
209 let _ =
210 ty.visit_with(&mut Visitor { genv, cursor: self, overflow_mode: overflow_checking });
211 }
212}
213
214pub struct Marker {
221 ptr: WeakNodePtr,
222}
223
224impl Marker {
225 pub fn scope(&self) -> Option<Scope> {
229 Some(self.ptr.upgrade()?.scope())
230 }
231
232 pub fn has_free_vars<T: TypeVisitable>(&self, t: &T) -> bool {
233 let ptr = self
234 .ptr
235 .upgrade()
236 .unwrap_or_else(|| tracked_span_bug!("`has_free_vars` called on invalid `Marker`"));
237
238 let nbindings = ptr.next_name_idx();
239
240 !t.fvars().into_iter().all(|name| name.index() < nbindings)
241 }
242}
243
244#[derive(PartialEq, Eq)]
246pub struct Scope {
247 params: Vec<(Var, Sort)>,
248 bindings: IndexVec<Name, Sort>,
249}
250
251impl Scope {
252 pub(crate) fn iter(&self) -> impl Iterator<Item = (Var, Sort)> + '_ {
253 itertools::chain(
254 self.params.iter().cloned(),
255 self.bindings
256 .iter_enumerated()
257 .map(|(name, sort)| (Var::Free(name), sort.clone())),
258 )
259 }
260
261 fn into_iter(self) -> impl Iterator<Item = (Var, Sort)> {
262 itertools::chain(
263 self.params,
264 self.bindings
265 .into_iter_enumerated()
266 .map(|(name, sort)| (Var::Free(name), sort.clone())),
267 )
268 }
269
270 pub fn has_free_vars<T: TypeFoldable>(&self, t: &T) -> bool {
272 !self.contains_all(t.fvars())
273 }
274
275 fn contains_all(&self, iter: impl IntoIterator<Item = Name>) -> bool {
276 iter.into_iter().all(|name| self.contains(name))
277 }
278
279 fn contains(&self, name: Name) -> bool {
280 name.index() < self.bindings.len()
281 }
282}
283
284struct Node {
285 kind: NodeKind,
286 nbindings: usize,
290 parent: Option<WeakNodePtr>,
291 children: Vec<NodePtr>,
292}
293
294#[derive(Clone)]
295struct NodePtr(Rc<RefCell<Node>>);
296
297impl NodePtr {
298 fn downgrade(this: &Self) -> WeakNodePtr {
299 WeakNodePtr(Rc::downgrade(&this.0))
300 }
301
302 fn push_node(&mut self, kind: NodeKind) -> NodePtr {
303 debug_assert!(!matches!(self.borrow().kind, NodeKind::Head(..)));
304 let node = Node {
305 kind,
306 nbindings: self.next_name_idx(),
307 parent: Some(NodePtr::downgrade(self)),
308 children: vec![],
309 };
310 let node = NodePtr(Rc::new(RefCell::new(node)));
311 self.borrow_mut().children.push(NodePtr::clone(&node));
312 node
313 }
314
315 fn next_name_idx(&self) -> usize {
316 self.borrow().nbindings + usize::from(self.borrow().is_forall())
317 }
318
319 fn scope(&self) -> Scope {
320 let mut params = None;
321 let parents = ParentsIter::new(self.clone());
322 let bindings = parents
323 .filter_map(|node| {
324 let node = node.borrow();
325 match &node.kind {
326 NodeKind::Root(p, _) => {
327 params = Some(p.clone());
328 None
329 }
330 NodeKind::ForAll(_, sort, _) => Some(sort.clone()),
331 _ => None,
332 }
333 })
334 .collect_vec()
335 .into_iter()
336 .rev()
337 .collect();
338 Scope { bindings, params: params.unwrap_or_default() }
339 }
340}
341
342struct WeakNodePtr(Weak<RefCell<Node>>);
343
344impl WeakNodePtr {
345 fn upgrade(&self) -> Option<NodePtr> {
346 Some(NodePtr(self.0.upgrade()?))
347 }
348}
349
350enum NodeKind {
351 Root(Vec<(Var, Sort)>, Vec<Expr>),
354 ForAll(Name, Sort, NameProvenance),
355 Assumption(Expr),
356 Head(Expr, Tag),
357 True,
358 Trace(TypeTrace),
360}
361
362impl std::ops::Index<Name> for Scope {
363 type Output = Sort;
364
365 fn index(&self, name: Name) -> &Self::Output {
366 &self.bindings[name]
367 }
368}
369
370impl std::ops::Deref for NodePtr {
371 type Target = Rc<RefCell<Node>>;
372
373 fn deref(&self) -> &Self::Target {
374 &self.0
375 }
376}
377
378#[derive(Clone, Copy)]
379enum SimplifyPhase<'genv, 'tcx> {
380 Full(GlobalEnv<'genv, 'tcx>),
382 Partial,
384}
385
386impl Node {
387 fn simplify(&mut self, phase: SimplifyPhase, assumed_preds: &mut SnapshotMap<Expr, ()>) {
388 match &mut self.kind {
390 NodeKind::Head(pred, tag) => {
391 let pred = match phase {
392 SimplifyPhase::Full(genv) => pred.reduce(genv).simplify(assumed_preds),
393 SimplifyPhase::Partial => pred.clone(),
394 };
395 if pred.is_trivially_true() {
396 self.kind = NodeKind::True;
397 } else {
398 self.kind = NodeKind::Head(pred, *tag);
399 }
400 }
401 NodeKind::Assumption(pred) => {
402 if let SimplifyPhase::Full(genv) = phase {
403 *pred = pred.reduce(genv).simplify(assumed_preds);
404 }
405 pred.visit_conj(|conjunct| {
406 assumed_preds.insert(conjunct.erase_spans(), ());
407 });
408 }
409 NodeKind::Root(_, assumptions) => {
410 for pred in assumptions {
411 pred.visit_conj(|conjunct| {
412 assumed_preds.insert(conjunct.erase_spans(), ());
413 });
414 }
415 }
416 _ => {}
417 }
418 let is_false_asm =
419 matches!(&self.kind, NodeKind::Assumption(pred) if pred.is_trivially_false());
420
421 for child in &self.children {
424 let current_version = assumed_preds.snapshot();
425 child.borrow_mut().simplify(phase, assumed_preds);
426 assumed_preds.rollback_to(current_version);
427 }
428
429 match &mut self.kind {
431 NodeKind::Head(..) | NodeKind::True => {}
432 NodeKind::Assumption(_)
433 | NodeKind::Trace(_)
434 | NodeKind::Root(..)
435 | NodeKind::ForAll(..) => {
436 self.children
437 .extract_if(.., |child| {
438 is_false_asm || matches!(&child.borrow().kind, NodeKind::True)
439 })
440 .for_each(drop);
441 }
442 }
443 if !self.is_leaf() && self.children.is_empty() {
444 self.kind = NodeKind::True;
445 }
446 }
447
448 fn is_leaf(&self) -> bool {
449 matches!(self.kind, NodeKind::Head(..) | NodeKind::True)
450 }
451
452 fn replace_evars(&mut self, evars: &EVarStore) -> Result<(), EVid> {
453 for child in &self.children {
454 child.borrow_mut().replace_evars(evars)?;
455 }
456 match &mut self.kind {
457 NodeKind::Assumption(pred) => *pred = evars.replace_evars(pred)?,
458 NodeKind::Head(pred, _) => {
459 *pred = evars.replace_evars(pred)?;
460 }
461 NodeKind::Trace(trace) => {
462 evars.replace_evars(trace)?;
463 }
464 NodeKind::Root(_, assumptions) => {
465 for pred in assumptions {
466 *pred = evars.replace_evars(pred)?;
467 }
468 }
469 NodeKind::ForAll(..) | NodeKind::True => {}
470 }
471 Ok(())
472 }
473
474 fn to_fixpoint(&self, cx: &mut FixpointCtxt<Tag>) -> QueryResult<Option<fixpoint::Constraint>> {
475 let cstr = match &self.kind {
476 NodeKind::Trace(_) | NodeKind::ForAll(_, Sort::Loc, _) => {
477 children_to_fixpoint(cx, &self.children)?
478 }
479
480 NodeKind::Root(params, assumptions) => {
481 for (var, sort) in params {
483 if let Var::EarlyParam(param) = var
484 && !sort.is_loc()
485 {
486 cx.with_early_param(param);
487 }
488 }
489
490 let Some(children) = children_to_fixpoint(cx, &self.children)? else {
491 return Ok(None);
492 };
493 let mut constr = children;
494 if !assumptions.is_empty() {
495 let preds = cx.assumptions_to_fixpoint(assumptions)?;
496 constr = fixpoint::Constraint::ForAll(
497 fixpoint::Bind {
498 name: fixpoint::Var::Underscore,
499 sort: fixpoint::Sort::Int,
500 preds,
501 },
502 Box::new(constr),
503 );
504 }
505 for (var, sort) in params.iter().rev() {
506 if sort.is_loc() {
507 continue;
508 }
509 constr = fixpoint::Constraint::ForAll(
510 fixpoint::Bind {
511 name: cx.var_to_fixpoint(var),
512 sort: cx.sort_to_fixpoint(sort),
513 preds: vec![],
514 },
515 Box::new(constr),
516 );
517 }
518 Some(constr)
519 }
520 NodeKind::ForAll(name, sort, provenance) => {
521 cx.with_name_map(*name, *provenance, |cx, fresh| -> QueryResult<_> {
522 let Some(children) = children_to_fixpoint(cx, &self.children)? else {
523 return Ok(None);
524 };
525 Ok(Some(fixpoint::Constraint::ForAll(
526 fixpoint::Bind {
527 name: fixpoint::Var::Local(fresh),
528 sort: cx.sort_to_fixpoint(sort),
529 preds: vec![],
530 },
531 Box::new(children),
532 )))
533 })?
534 }
535 NodeKind::Assumption(pred) => {
536 let preds = cx.assumptions_to_fixpoint([pred])?;
537 let Some(cstr) = children_to_fixpoint(cx, &self.children)? else {
538 return Ok(None);
539 };
540 Some(fixpoint::Constraint::ForAll(
541 fixpoint::Bind {
542 name: fixpoint::Var::Underscore,
543 sort: fixpoint::Sort::Int,
544 preds,
545 },
546 Box::new(cstr),
547 ))
548 }
549 NodeKind::Head(pred, tag) => {
550 Some(cx.head_to_fixpoint(pred, |span| tag.with_dst(span))?)
551 }
552 NodeKind::True => None,
553 };
554 Ok(cstr)
555 }
556
557 fn is_forall(&self) -> bool {
561 matches!(self.kind, NodeKind::ForAll(..))
562 }
563
564 fn is_head(&self) -> bool {
568 matches!(self.kind, NodeKind::Head(..))
569 }
570}
571
572fn children_to_fixpoint(
573 cx: &mut FixpointCtxt<Tag>,
574 children: &[NodePtr],
575) -> QueryResult<Option<fixpoint::Constraint>> {
576 let mut children = children
577 .iter()
578 .filter_map(|node| node.borrow().to_fixpoint(cx).transpose())
579 .try_collect_vec()?;
580 let cstr = match children.len() {
581 0 => None,
582 1 => children.pop(),
583 _ => Some(fixpoint::Constraint::conj(children)),
584 };
585 Ok(cstr)
586}
587
588struct ParentsIter {
589 ptr: Option<NodePtr>,
590}
591
592impl ParentsIter {
593 fn new(ptr: NodePtr) -> Self {
594 Self { ptr: Some(ptr) }
595 }
596}
597
598impl Iterator for ParentsIter {
599 type Item = NodePtr;
600
601 fn next(&mut self) -> Option<Self::Item> {
602 if let Some(ptr) = self.ptr.take() {
603 self.ptr = ptr.borrow().parent.as_ref().and_then(WeakNodePtr::upgrade);
604 Some(ptr)
605 } else {
606 None
607 }
608 }
609}
610
611mod pretty {
612 use std::fmt::{self, Write};
613
614 use flux_middle::pretty::*;
615 use pad_adapter::PadAdapter;
616
617 use super::*;
618
619 fn bindings_chain(ptr: &NodePtr) -> (Vec<(Name, Sort)>, Vec<NodePtr>) {
620 fn go(ptr: &NodePtr, mut bindings: Vec<(Name, Sort)>) -> (Vec<(Name, Sort)>, Vec<NodePtr>) {
621 let node = ptr.borrow();
622 if let NodeKind::ForAll(name, sort, _) = &node.kind {
623 bindings.push((*name, sort.clone()));
624 if let [child] = &node.children[..] {
625 go(child, bindings)
626 } else {
627 (bindings, node.children.clone())
628 }
629 } else {
630 (bindings, vec![NodePtr::clone(ptr)])
631 }
632 }
633 go(ptr, vec![])
634 }
635
636 fn preds_chain(ptr: &NodePtr) -> (Vec<Expr>, Vec<NodePtr>) {
637 fn go(ptr: &NodePtr, mut preds: Vec<Expr>) -> (Vec<Expr>, Vec<NodePtr>) {
638 let node = ptr.borrow();
639 if let NodeKind::Assumption(pred) = &node.kind {
640 preds.push(pred.clone());
641 if let [child] = &node.children[..] {
642 go(child, preds)
643 } else {
644 (preds, node.children.clone())
645 }
646 } else {
647 (preds, vec![NodePtr::clone(ptr)])
648 }
649 }
650 go(ptr, vec![])
651 }
652
653 impl Pretty for RefineTree {
654 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
655 w!(cx, f, "{:?}", &self.root)
656 }
657 }
658
659 impl Pretty for NodePtr {
660 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
661 let node = self.borrow();
662 match &node.kind {
663 NodeKind::Trace(trace) => {
664 w!(cx, f, "@ {:?}", ^trace)?;
665 w!(cx, with_padding(f), "\n{:?}", join!("\n", &node.children))
666 }
667 NodeKind::Root(bindings, assumptions) => {
668 w!(cx, f,
669 "∀ {}.",
670 ^bindings
671 .iter()
672 .format_with(", ", |(name, sort), f| {
673 f(&format_args_cx!(cx, "{:?}: {:?}", ^name, sort))
674 })
675 )?;
676 if !assumptions.is_empty() {
677 w!(cx, f, " {:?} =>", join!(" ∧ ", assumptions))?;
678 }
679 fmt_children(&node.children, cx, f)
680 }
681 NodeKind::ForAll(name, sort, _) => {
682 let (bindings, children) = if cx.bindings_chain {
683 bindings_chain(self)
684 } else {
685 (vec![(*name, sort.clone())], node.children.clone())
686 };
687
688 w!(cx, f,
689 "∀ {}.",
690 ^bindings
691 .into_iter()
692 .format_with(", ", |(name, sort), f| {
693 f(&format_args_cx!(cx, "{:?}: {:?}", ^name, sort))
694 })
695 )?;
696 fmt_children(&children, cx, f)
697 }
698 NodeKind::Assumption(pred) => {
699 let (preds, children) = if cx.preds_chain {
700 preds_chain(self)
701 } else {
702 (vec![pred.clone()], node.children.clone())
703 };
704 let guard = Expr::and_from_iter(preds).simplify(&SnapshotMap::default());
705 w!(cx, f, "{:?} =>", parens!(guard, !guard.is_atom()))?;
706 fmt_children(&children, cx, f)
707 }
708 NodeKind::Head(pred, tag) => {
709 let pred = if cx.simplify_exprs {
710 pred.simplify(&SnapshotMap::default())
711 } else {
712 pred.clone()
713 };
714 w!(cx, f, "{:?}", parens!(pred, !pred.is_atom()))?;
715 if cx.tags {
716 w!(cx, f, " ~ {:?}", tag)?;
717 }
718 Ok(())
719 }
720 NodeKind::True => {
721 w!(cx, f, "true")
722 }
723 }
724 }
725 }
726
727 fn fmt_children(
728 children: &[NodePtr],
729 cx: &PrettyCx,
730 f: &mut fmt::Formatter<'_>,
731 ) -> fmt::Result {
732 match children {
733 [] => w!(cx, f, " true"),
734 [n] => {
735 if n.borrow().is_head() {
736 w!(cx, f, " {:?}", n)
737 } else {
738 w!(cx, with_padding(f), "\n{:?}", n)
739 }
740 }
741 _ => w!(cx, with_padding(f), "\n{:?}", join!("\n", children)),
742 }
743 }
744
745 impl Pretty for Cursor<'_> {
746 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
747 let mut elements = vec![];
748 for node in ParentsIter::new(NodePtr::clone(&self.ptr)) {
749 let n = node.borrow();
750 match &n.kind {
751 NodeKind::Root(bindings, assumptions) => {
752 for pred in assumptions.iter().rev() {
754 elements.push(format_cx!(cx, "{:?}", pred));
755 }
756 for (name, sort) in bindings.iter().rev() {
757 elements.push(format_cx!(cx, "{:?}: {:?}", ^name, sort));
758 }
759 }
760 NodeKind::ForAll(name, sort, _) => {
761 elements.push(format_cx!(cx, "{:?}: {:?}", ^name, sort));
762 }
763 NodeKind::Assumption(pred) => {
764 elements.push(format_cx!(cx, "{:?}", pred));
765 }
766 _ => {}
767 }
768 }
769 write!(f, "{{{}}}", elements.into_iter().rev().format(", "))
770 }
771 }
772
773 impl Pretty for Scope {
774 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
775 write!(
776 f,
777 "[bindings = {}, reftgenerics = {}]",
778 self.bindings
779 .iter_enumerated()
780 .format_with(", ", |(name, sort), f| {
781 f(&format_args_cx!(cx, "{:?}: {:?}", ^name, sort))
782 }),
783 self.params
784 .iter()
785 .format_with(", ", |(param_const, sort), f| {
786 f(&format_args_cx!(cx, "{:?}: {:?}", ^param_const, sort))
787 }),
788 )
789 }
790 }
791
792 fn with_padding<'a, 'b>(f: &'a mut fmt::Formatter<'b>) -> PadAdapter<'a, 'b, 'static> {
793 PadAdapter::with_padding(f, " ")
794 }
795
796 impl_debug_with_default_cx!(
797 RefineTree => "refine_tree",
798 Cursor<'_> => "cursor",
799 Scope,
800 );
801}
802
803#[derive(Serialize, DebugAsJson)]
805pub struct RefineCtxtTrace {
806 bindings: Vec<RcxBind>,
807 exprs: Vec<String>,
808}
809
810#[derive(Serialize)]
811struct RcxBind {
812 name: String,
813 sort: String,
814}
815
816impl RefineCtxtTrace {
817 pub fn new(cx: &mut PrettyCx, cursor: &Cursor) -> Self {
818 let parents = ParentsIter::new(NodePtr::clone(&cursor.ptr)).collect_vec();
819 let mut bindings = vec![];
820 let mut exprs = vec![];
821
822 parents.into_iter().rev().for_each(|ptr| {
823 let node = ptr.borrow();
824 match &node.kind {
825 NodeKind::ForAll(name, sort, provenance) => {
826 let name = cx
827 .pretty_var_env
828 .set(PrettyVar::Local(*name), provenance.opt_symbol());
829 let sort = format_cx!(cx, "{:?}", sort);
830 let bind = RcxBind { name, sort };
831 bindings.push(bind);
832 }
833 NodeKind::Assumption(e)
834 if !e.simplify(&SnapshotMap::default()).is_trivially_true() =>
835 {
836 e.visit_conj(|e| {
837 exprs.push(e.nested_string(cx));
838 });
839 }
840 NodeKind::Root(binds, assumptions) => {
841 for (name, sort) in binds {
842 let name = if let Var::EarlyParam(param) = name {
843 cx.pretty_var_env
844 .set(PrettyVar::Param(*param), Some(param.name))
845 } else {
846 format_cx!(cx, "{:?}", name)
847 };
848 let sort = format_cx!(cx, "{:?}", sort);
849 let bind = RcxBind { name, sort };
850 bindings.push(bind);
851 }
852 for e in assumptions {
853 e.visit_conj(|e| {
854 exprs.push(e.nested_string(cx));
855 });
856 }
857 }
858 _ => (),
859 }
860 });
861 Self { bindings, exprs }
862 }
863}
864
865impl Node {
866 fn simplify_bot(&mut self) {
868 let graph = ConstraintDeps::new(self);
869 let bots = graph.bot_kvars();
870 self.simplify_with_assignment(&bots);
871 self.simplify(SimplifyPhase::Partial, &mut SnapshotMap::default());
872 }
873
874 fn simplify_top(&mut self) {
876 let graph = ConstraintDeps::new(self);
877 let tops = graph.top_kvars();
878 self.simplify_with_assignment(&tops);
879 self.simplify(SimplifyPhase::Partial, &mut SnapshotMap::default());
880 }
881
882 fn simplify_with_assignment(&mut self, assignment: &Assignment) {
885 match &mut self.kind {
886 NodeKind::Head(pred, tag) => {
887 let pred = assignment.simplify(pred);
888 self.kind = NodeKind::Head(pred, *tag);
889 }
890 NodeKind::Assumption(pred) => {
891 let pred = assignment.simplify(pred);
892 self.kind = NodeKind::Assumption(pred);
893 }
894 _ => {}
895 }
896 for child in &self.children {
897 child.borrow_mut().simplify_with_assignment(assignment);
898 }
899 }
900}
901
902#[derive(Debug)]
903struct ConstraintDeps {
904 assumptions: IndexVec<ClauseId, FxHashSet<KVid>>,
906 heads: IndexVec<ClauseId, Head>,
908}
909
910impl ConstraintDeps {
911 fn new(node: &Node) -> Self {
912 let mut graph = Self { assumptions: IndexVec::default(), heads: IndexVec::default() };
913 graph.build(node, &mut vec![]);
914 graph
915 }
916
917 fn insert_clause(&mut self, assumptions: &[KVid], head: Head) {
918 self.assumptions.push(assumptions.iter().copied().collect());
919 self.heads.push(head);
920 }
921
922 fn build(&mut self, node: &Node, assumptions: &mut Vec<KVid>) {
923 let n = assumptions.len();
924 match &node.kind {
925 NodeKind::Head(expr, _) => {
926 expr.visit_conj(|e| {
927 if let ExprKind::KVar(kvar) = e.kind() {
928 self.insert_clause(assumptions, Head::KVar(kvar.kvid));
929 } else {
930 self.insert_clause(assumptions, Head::Conc);
931 }
932 });
933 }
934 NodeKind::Assumption(expr) => {
935 expr.visit_conj(|e| {
936 if let ExprKind::KVar(kvar) = e.kind() {
937 assumptions.push(kvar.kvid);
938 }
939 });
940 }
941 _ => {}
942 };
943
944 for child in &node.children {
945 self.build(&child.borrow(), assumptions);
946 }
947
948 assumptions.truncate(n); }
950
951 fn kv_lhs(&self) -> UnordMap<KVid, Vec<ClauseId>> {
953 let mut res: UnordMap<KVid, Vec<ClauseId>> = UnordMap::default();
954 for (clause_id, kvids) in self.assumptions.iter_enumerated() {
955 for kvid in kvids {
956 res.entry(*kvid).or_default().push(clause_id);
957 }
958 }
959 res
960 }
961
962 fn kv_rhs(&self) -> UnordMap<KVid, Vec<ClauseId>> {
964 let mut res: UnordMap<KVid, Vec<ClauseId>> = UnordMap::default();
965 for (clause_id, head) in self.heads.iter_enumerated() {
966 if let Head::KVar(kvid) = head {
967 res.entry(*kvid).or_default().push(clause_id);
968 }
969 }
970 res
971 }
972
973 fn bot_kvars(self) -> Assignment {
976 let mut assignment = Assignment::new(Label::Bot);
978
979 let kv_lhs = self.kv_lhs();
980
981 let mut bot_assms: IndexVec<ClauseId, FxHashSet<KVid>> = self.assumptions;
983
984 let mut candidates: Vec<ClauseId> = bot_assms
986 .iter_enumerated()
987 .filter_map(|(cid, lhs)| if lhs.is_empty() { Some(cid) } else { None })
988 .collect();
989
990 while let Some(cid) = candidates.pop() {
992 if let Head::KVar(kvid) = self.heads[cid] {
993 assignment.remove(kvid);
995 for cid in kv_lhs.get(&kvid).unwrap_or(&vec![]) {
997 if let Head::KVar(rhs_kvid) = self.heads[*cid] {
999 let assms = &mut bot_assms[*cid];
1000 assms.remove(&kvid);
1001 if assignment.has_label(rhs_kvid) && assms.is_empty() {
1002 candidates.push(*cid);
1003 }
1004 };
1005 }
1006 }
1007 }
1008
1009 assignment
1010 }
1011
1012 fn top_kvars(self) -> Assignment {
1015 let mut assignment = Assignment::new(Label::Top);
1017
1018 let kv_rhs = self.kv_rhs();
1019
1020 let mut candidates = vec![];
1022 for (cid, head) in self.heads.iter_enumerated() {
1023 if matches!(head, Head::Conc) {
1024 for kvid in &self.assumptions[cid] {
1025 candidates.push(*kvid);
1026 }
1027 }
1028 }
1029
1030 while let Some(kvid) = candidates.pop() {
1032 assignment.remove(kvid);
1034
1035 for cid in kv_rhs.get(&kvid).unwrap_or(&vec![]) {
1037 for lhs_kvid in &self.assumptions[*cid] {
1039 if assignment.has_label(*lhs_kvid) {
1040 candidates.push(*lhs_kvid);
1041 }
1042 }
1043 }
1044 }
1045
1046 assignment
1047 }
1048}
1049
1050newtype_index! {
1051 struct ClauseId {}
1052}
1053
1054#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1055enum Head {
1056 KVar(KVid),
1058 Conc,
1061}
1062
1063#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1064enum Label {
1065 Bot,
1067 Top,
1069}
1070
1071struct Assignment {
1072 vars: UnordSet<KVid>,
1075 label: Label,
1076}
1077
1078impl Assignment {
1079 fn new(label: Label) -> Self {
1080 let vars = UnordSet::new();
1081 Self { vars, label }
1082 }
1083
1084 fn has_label(&self, kvid: KVid) -> bool {
1085 !self.vars.contains(&kvid)
1086 }
1087
1088 fn remove(&mut self, kvid: KVid) {
1089 self.vars.insert(kvid);
1090 }
1091
1092 fn simplify(&self, pred: &Expr) -> Expr {
1095 let mut preds = vec![];
1096 for p in pred.flatten_conjs() {
1097 if let ExprKind::KVar(kvar) = p.kind()
1098 && self.has_label(kvar.kvid)
1099 {
1100 if self.label == Label::Bot {
1101 return Expr::ff();
1102 } } else {
1104 preds.push(p.clone());
1105 }
1106 }
1107 Expr::and_from_iter(preds)
1108 }
1109}