hir_ty/next_solver/infer/snapshot/
mod.rs

1//! Snapshotting in the infer ctxt of the next-trait-solver.
2
3use ena::undo_log::UndoLogs;
4use rustc_type_ir::UniverseIndex;
5use tracing::{debug, instrument};
6
7use super::InferCtxt;
8use super::region_constraints::RegionSnapshot;
9
10mod fudge;
11pub(crate) mod undo_log;
12
13use undo_log::{Snapshot, UndoLog};
14
15#[must_use = "once you start a snapshot, you should always consume it"]
16pub struct CombinedSnapshot {
17    pub(super) undo_snapshot: Snapshot,
18    region_constraints_snapshot: RegionSnapshot,
19    universe: UniverseIndex,
20}
21
22struct VariableLengths {
23    region_constraints_len: usize,
24    type_var_len: usize,
25    int_var_len: usize,
26    float_var_len: usize,
27    const_var_len: usize,
28}
29
30impl<'db> InferCtxt<'db> {
31    fn variable_lengths(&self) -> VariableLengths {
32        let mut inner = self.inner.borrow_mut();
33        VariableLengths {
34            region_constraints_len: inner.unwrap_region_constraints().num_region_vars(),
35            type_var_len: inner.type_variables().num_vars(),
36            int_var_len: inner.int_unification_table().len(),
37            float_var_len: inner.float_unification_table().len(),
38            const_var_len: inner.const_unification_table().len(),
39        }
40    }
41
42    pub fn in_snapshot(&self) -> bool {
43        UndoLogs::<UndoLog<'db>>::in_snapshot(&self.inner.borrow_mut().undo_log)
44    }
45
46    pub fn num_open_snapshots(&self) -> usize {
47        UndoLogs::<UndoLog<'db>>::num_open_snapshots(&self.inner.borrow_mut().undo_log)
48    }
49
50    pub(crate) fn start_snapshot(&self) -> CombinedSnapshot {
51        debug!("start_snapshot()");
52
53        let mut inner = self.inner.borrow_mut();
54
55        CombinedSnapshot {
56            undo_snapshot: inner.undo_log.start_snapshot(),
57            region_constraints_snapshot: inner.unwrap_region_constraints().start_snapshot(),
58            universe: self.universe(),
59        }
60    }
61
62    #[instrument(skip(self, snapshot), level = "debug")]
63    pub(crate) fn rollback_to(&self, snapshot: CombinedSnapshot) {
64        let CombinedSnapshot { undo_snapshot, region_constraints_snapshot, universe } = snapshot;
65
66        self.universe.set(universe);
67
68        let mut inner = self.inner.borrow_mut();
69        inner.rollback_to(undo_snapshot);
70        inner.unwrap_region_constraints().rollback_to(region_constraints_snapshot);
71    }
72
73    #[instrument(skip(self, snapshot), level = "debug")]
74    fn commit_from(&self, snapshot: CombinedSnapshot) {
75        let CombinedSnapshot { undo_snapshot, region_constraints_snapshot: _, universe: _ } =
76            snapshot;
77
78        self.inner.borrow_mut().commit(undo_snapshot);
79    }
80
81    /// Execute `f` and commit the bindings if closure `f` returns `Ok(_)`.
82    #[instrument(skip(self, f), level = "debug")]
83    pub fn commit_if_ok<T, E, F>(&self, f: F) -> Result<T, E>
84    where
85        F: FnOnce(&CombinedSnapshot) -> Result<T, E>,
86    {
87        let snapshot = self.start_snapshot();
88        let r = f(&snapshot);
89        debug!("commit_if_ok() -- r.is_ok() = {}", r.is_ok());
90        match r {
91            Ok(_) => {
92                self.commit_from(snapshot);
93            }
94            Err(_) => {
95                self.rollback_to(snapshot);
96            }
97        }
98        r
99    }
100
101    /// Execute `f` then unroll any bindings it creates.
102    #[instrument(skip(self, f), level = "debug")]
103    pub fn probe<R, F>(&self, f: F) -> R
104    where
105        F: FnOnce(&CombinedSnapshot) -> R,
106    {
107        let snapshot = self.start_snapshot();
108        let r = f(&snapshot);
109        self.rollback_to(snapshot);
110        r
111    }
112
113    /// Scan the constraints produced since `snapshot` and check whether
114    /// we added any region constraints.
115    pub fn region_constraints_added_in_snapshot(&self, snapshot: &CombinedSnapshot) -> bool {
116        self.inner
117            .borrow_mut()
118            .unwrap_region_constraints()
119            .region_constraints_added_in_snapshot(&snapshot.undo_snapshot)
120    }
121
122    pub fn opaque_types_added_in_snapshot(&self, snapshot: &CombinedSnapshot) -> bool {
123        self.inner.borrow().undo_log.opaque_types_in_snapshot(&snapshot.undo_snapshot)
124    }
125}