Skip to main content

rustc_infer/infer/snapshot/
mod.rs

1use rustc_data_structures::undo_log::UndoLogs;
2use rustc_middle::ty;
3use tracing::{debug, instrument};
4
5use super::InferCtxt;
6use super::region_constraints::RegionSnapshot;
7
8pub(crate) mod fudge;
9pub(crate) mod undo_log;
10
11use undo_log::{Snapshot, UndoLog};
12
13#[must_use = "once you start a snapshot, you should always consume it"]
14pub struct CombinedSnapshot<'tcx> {
15    pub(super) undo_snapshot: Snapshot<'tcx>,
16    region_constraints_snapshot: RegionSnapshot,
17    universe: ty::UniverseIndex,
18}
19
20struct VariableLengths {
21    region_constraints_len: usize,
22    type_var_len: usize,
23    int_var_len: usize,
24    float_var_len: usize,
25    const_var_len: usize,
26}
27
28impl<'tcx> InferCtxt<'tcx> {
29    fn variable_lengths(&self) -> VariableLengths {
30        let mut inner = self.inner.borrow_mut();
31        VariableLengths {
32            region_constraints_len: inner.unwrap_region_constraints().num_region_vars(),
33            type_var_len: inner.type_variables().num_vars(),
34            int_var_len: inner.int_unification_table().len(),
35            float_var_len: inner.float_unification_table().len(),
36            const_var_len: inner.const_unification_table().len(),
37        }
38    }
39
40    pub fn in_snapshot(&self) -> bool {
41        UndoLogs::<UndoLog<'tcx>>::in_snapshot(&self.inner.borrow_mut().undo_log)
42    }
43
44    pub fn num_open_snapshots(&self) -> usize {
45        UndoLogs::<UndoLog<'tcx>>::num_open_snapshots(&self.inner.borrow_mut().undo_log)
46    }
47
48    fn start_snapshot(&self) -> CombinedSnapshot<'tcx> {
49        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_infer/src/infer/snapshot/mod.rs:49",
                        "rustc_infer::infer::snapshot", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/snapshot/mod.rs"),
                        ::tracing_core::__macro_support::Option::Some(49u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_infer::infer::snapshot"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("start_snapshot()")
                                            as &dyn Value))])
            });
    } else { ; }
};debug!("start_snapshot()");
50
51        let mut inner = self.inner.borrow_mut();
52
53        CombinedSnapshot {
54            undo_snapshot: inner.undo_log.start_snapshot(),
55            region_constraints_snapshot: inner.unwrap_region_constraints().start_snapshot(),
56            universe: self.universe(),
57        }
58    }
59
60    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("rollback_to",
                                    "rustc_infer::infer::snapshot", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/snapshot/mod.rs"),
                                    ::tracing_core::__macro_support::Option::Some(60u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_infer::infer::snapshot"),
                                    ::tracing_core::field::FieldSet::new(&[],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{ meta.fields().value_set(&[]) })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: () = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let CombinedSnapshot {
                    undo_snapshot, region_constraints_snapshot, universe } =
                snapshot;
            self.universe.set(universe);
            let mut inner = self.inner.borrow_mut();
            inner.rollback_to(undo_snapshot);
            inner.unwrap_region_constraints().rollback_to(region_constraints_snapshot);
        }
    }
}#[instrument(skip(self, snapshot), level = "debug")]
61    fn rollback_to(&self, snapshot: CombinedSnapshot<'tcx>) {
62        let CombinedSnapshot { undo_snapshot, region_constraints_snapshot, universe } = snapshot;
63
64        self.universe.set(universe);
65
66        let mut inner = self.inner.borrow_mut();
67        inner.rollback_to(undo_snapshot);
68        inner.unwrap_region_constraints().rollback_to(region_constraints_snapshot);
69    }
70
71    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("commit_from",
                                    "rustc_infer::infer::snapshot", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/snapshot/mod.rs"),
                                    ::tracing_core::__macro_support::Option::Some(71u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_infer::infer::snapshot"),
                                    ::tracing_core::field::FieldSet::new(&[],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{ meta.fields().value_set(&[]) })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: () = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let CombinedSnapshot {
                    undo_snapshot, region_constraints_snapshot: _, universe: _
                    } = snapshot;
            self.inner.borrow_mut().commit(undo_snapshot);
        }
    }
}#[instrument(skip(self, snapshot), level = "debug")]
72    fn commit_from(&self, snapshot: CombinedSnapshot<'tcx>) {
73        let CombinedSnapshot { undo_snapshot, region_constraints_snapshot: _, universe: _ } =
74            snapshot;
75
76        self.inner.borrow_mut().commit(undo_snapshot);
77    }
78
79    /// Execute `f` and commit the bindings if closure `f` returns `Ok(_)`.
80    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("commit_if_ok",
                                    "rustc_infer::infer::snapshot", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/snapshot/mod.rs"),
                                    ::tracing_core::__macro_support::Option::Some(80u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_infer::infer::snapshot"),
                                    ::tracing_core::field::FieldSet::new(&[],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{ meta.fields().value_set(&[]) })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: Result<T, E> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let snapshot = self.start_snapshot();
            let r = f(&snapshot);
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_infer/src/infer/snapshot/mod.rs:87",
                                    "rustc_infer::infer::snapshot", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/snapshot/mod.rs"),
                                    ::tracing_core::__macro_support::Option::Some(87u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_infer::infer::snapshot"),
                                    ::tracing_core::field::FieldSet::new(&["message"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::EVENT)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let enabled =
                    ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        {
                            let interest = __CALLSITE.interest();
                            !interest.is_never() &&
                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                    interest)
                        };
                if enabled {
                    (|value_set: ::tracing::field::ValueSet|
                                {
                                    let meta = __CALLSITE.metadata();
                                    ::tracing::Event::dispatch(meta, &value_set);
                                    ;
                                })({
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            let mut iter = __CALLSITE.metadata().fields().iter();
                            __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&format_args!("commit_if_ok() -- r.is_ok() = {0}",
                                                                r.is_ok()) as &dyn Value))])
                        });
                } else { ; }
            };
            match r {
                Ok(_) => { self.commit_from(snapshot); }
                Err(_) => { self.rollback_to(snapshot); }
            }
            r
        }
    }
}#[instrument(skip(self, f), level = "debug")]
81    pub fn commit_if_ok<T, E, F>(&self, f: F) -> Result<T, E>
82    where
83        F: FnOnce(&CombinedSnapshot<'tcx>) -> Result<T, E>,
84    {
85        let snapshot = self.start_snapshot();
86        let r = f(&snapshot);
87        debug!("commit_if_ok() -- r.is_ok() = {}", r.is_ok());
88        match r {
89            Ok(_) => {
90                self.commit_from(snapshot);
91            }
92            Err(_) => {
93                self.rollback_to(snapshot);
94            }
95        }
96        r
97    }
98
99    /// Execute `f` then unroll any bindings it creates.
100    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("probe",
                                    "rustc_infer::infer::snapshot", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/snapshot/mod.rs"),
                                    ::tracing_core::__macro_support::Option::Some(100u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_infer::infer::snapshot"),
                                    ::tracing_core::field::FieldSet::new(&[],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{ meta.fields().value_set(&[]) })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: R = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let snapshot = self.start_snapshot();
            let r = f(&snapshot);
            self.rollback_to(snapshot);
            r
        }
    }
}#[instrument(skip(self, f), level = "debug")]
101    pub fn probe<R, F>(&self, f: F) -> R
102    where
103        F: FnOnce(&CombinedSnapshot<'tcx>) -> R,
104    {
105        let snapshot = self.start_snapshot();
106        let r = f(&snapshot);
107        self.rollback_to(snapshot);
108        r
109    }
110
111    /// Scan the constraints produced since `snapshot` and check whether
112    /// we added any region constraints.
113    pub fn region_constraints_added_in_snapshot(&self, snapshot: &CombinedSnapshot<'tcx>) -> bool {
114        self.inner
115            .borrow_mut()
116            .unwrap_region_constraints()
117            .region_constraints_added_in_snapshot(&snapshot.undo_snapshot)
118    }
119
120    pub fn opaque_types_added_in_snapshot(&self, snapshot: &CombinedSnapshot<'tcx>) -> bool {
121        self.inner.borrow().undo_log.opaque_types_in_snapshot(&snapshot.undo_snapshot)
122    }
123}