flux_infer/
evars.rs
1use std::fmt;
2
3use flux_common::index::IndexVec;
4use flux_middle::{
5 pretty::{Pretty, PrettyCx, impl_debug_with_default_cx, w},
6 rty::{EVid, Expr, fold::TypeFoldable},
7};
8
9use crate::refine_tree::Marker;
10
11#[derive(Default, Debug)]
12pub(crate) struct EVarStore {
13 evars: IndexVec<EVid, EVarState>,
14 scopes: Vec<Vec<EVid>>,
15}
16
17pub(crate) enum EVarState {
18 Solved(Expr),
19 Unsolved(Marker),
20}
21
22impl EVarStore {
23 pub(crate) fn fresh(&mut self, marker: Marker) -> EVid {
24 let evid = self.evars.push(EVarState::Unsolved(marker));
25 if let Some(scope) = self.scopes.last_mut() {
26 scope.push(evid);
27 }
28 evid
29 }
30
31 pub(crate) fn push_scope(&mut self) {
32 self.scopes.push(vec![]);
33 }
34
35 pub(crate) fn pop_scope(&mut self) -> Result<(), EVid> {
36 let Some(scope) = self.scopes.pop() else { return Ok(()) };
37 for evid in scope {
38 if let EVarState::Unsolved(..) = self.get(evid) {
39 return Err(evid);
40 }
41 }
42 Ok(())
43 }
44
45 pub(crate) fn replace_evars<T: TypeFoldable>(&self, t: &T) -> Result<T, EVid> {
46 t.replace_evars(&mut |evid| {
47 match self.get(evid) {
48 EVarState::Solved(expr) => Some(expr.clone()),
49 EVarState::Unsolved(..) => None,
50 }
51 })
52 }
53
54 pub(crate) fn solve(&mut self, evid: EVid, expr: Expr) {
55 debug_assert!(matches!(self.evars[evid], EVarState::Unsolved(_)));
56 self.evars[evid] = EVarState::Solved(expr);
57 }
58
59 pub(crate) fn get(&self, evid: EVid) -> &EVarState {
60 &self.evars[evid]
61 }
62}
63
64impl Pretty for EVarState {
65 fn fmt(&self, cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66 match self {
67 EVarState::Solved(expr) => w!(cx, f, "Solved({:?})", expr),
68 EVarState::Unsolved(_) => w!(cx, f, "Unsolved"),
69 }
70 }
71}
72
73impl_debug_with_default_cx!(EVarState);