rustc_infer/infer/snapshot/
undo_log.rs1use std::assert_matches;
2use std::marker::PhantomData;
3
4use rustc_data_structures::undo_log::{Rollback, UndoLogs};
5use rustc_data_structures::{snapshot_vec as sv, unify as ut};
6use rustc_middle::ty::{self, OpaqueTypeKey, ProvisionalHiddenType};
7use tracing::debug;
8
9use crate::infer::unify_key::{ConstVidKey, RegionVidKey};
10use crate::infer::{InferCtxtInner, SolverRegionConstraint, region_constraints, type_variable};
11use crate::traits;
12
13pub struct Snapshot<'tcx> {
14 pub(crate) undo_len: usize,
15 _marker: PhantomData<&'tcx ()>,
16}
17
18#[derive(#[automatically_derived]
impl<'tcx> ::core::clone::Clone for UndoLog<'tcx> {
#[inline]
fn clone(&self) -> UndoLog<'tcx> {
match self {
UndoLog::DuplicateOpaqueType => UndoLog::DuplicateOpaqueType,
UndoLog::OpaqueTypes(__self_0, __self_1) =>
UndoLog::OpaqueTypes(::core::clone::Clone::clone(__self_0),
::core::clone::Clone::clone(__self_1)),
UndoLog::TypeVariables(__self_0) =>
UndoLog::TypeVariables(::core::clone::Clone::clone(__self_0)),
UndoLog::ConstUnificationTable(__self_0) =>
UndoLog::ConstUnificationTable(::core::clone::Clone::clone(__self_0)),
UndoLog::IntUnificationTable(__self_0) =>
UndoLog::IntUnificationTable(::core::clone::Clone::clone(__self_0)),
UndoLog::FloatUnificationTable(__self_0) =>
UndoLog::FloatUnificationTable(::core::clone::Clone::clone(__self_0)),
UndoLog::RegionConstraintCollector(__self_0) =>
UndoLog::RegionConstraintCollector(::core::clone::Clone::clone(__self_0)),
UndoLog::RegionUnificationTable(__self_0) =>
UndoLog::RegionUnificationTable(::core::clone::Clone::clone(__self_0)),
UndoLog::ProjectionCache(__self_0) =>
UndoLog::ProjectionCache(::core::clone::Clone::clone(__self_0)),
UndoLog::PushTypeOutlivesConstraint =>
UndoLog::PushTypeOutlivesConstraint,
UndoLog::PushSolverRegionConstraint { previous_was_and: __self_0 }
=>
UndoLog::PushSolverRegionConstraint {
previous_was_and: ::core::clone::Clone::clone(__self_0),
},
UndoLog::OverwriteSolverRegionConstraint {
old_constraint: __self_0 } =>
UndoLog::OverwriteSolverRegionConstraint {
old_constraint: ::core::clone::Clone::clone(__self_0),
},
UndoLog::PushRegionAssumption => UndoLog::PushRegionAssumption,
UndoLog::PushHirTypeckPotentiallyRegionDependentGoal =>
UndoLog::PushHirTypeckPotentiallyRegionDependentGoal,
}
}
}Clone)]
20pub(crate) enum UndoLog<'tcx> {
21 DuplicateOpaqueType,
22 OpaqueTypes(OpaqueTypeKey<'tcx>, Option<ProvisionalHiddenType<'tcx>>),
23 TypeVariables(type_variable::UndoLog<'tcx>),
24 ConstUnificationTable(sv::UndoLog<ut::Delegate<ConstVidKey<'tcx>>>),
25 IntUnificationTable(sv::UndoLog<ut::Delegate<ty::IntVid>>),
26 FloatUnificationTable(sv::UndoLog<ut::Delegate<ty::FloatVid>>),
27 RegionConstraintCollector(region_constraints::UndoLog<'tcx>),
28 RegionUnificationTable(sv::UndoLog<ut::Delegate<RegionVidKey<'tcx>>>),
29 ProjectionCache(traits::UndoLog<'tcx>),
30 PushTypeOutlivesConstraint,
31 PushSolverRegionConstraint { previous_was_and: bool },
32 OverwriteSolverRegionConstraint { old_constraint: SolverRegionConstraint<'tcx> },
33 PushRegionAssumption,
34 PushHirTypeckPotentiallyRegionDependentGoal,
35}
36
37macro_rules! impl_from {
38 ($($ctor:ident ($ty:ty),)*) => {
39 $(
40 impl<'tcx> From<$ty> for UndoLog<'tcx> {
41 fn from(x: $ty) -> Self {
42 UndoLog::$ctor(x.into())
43 }
44 }
45 )*
46 }
47}
48
49impl<'tcx> From<region_constraints::UndoLog<'tcx>> for UndoLog<'tcx> {
fn from(x: region_constraints::UndoLog<'tcx>) -> Self {
UndoLog::RegionConstraintCollector(x.into())
}
}
impl<'tcx> From<sv::UndoLog<ut::Delegate<type_variable::TyVidEqKey<'tcx>>>>
for UndoLog<'tcx> {
fn from(x: sv::UndoLog<ut::Delegate<type_variable::TyVidEqKey<'tcx>>>)
-> Self {
UndoLog::TypeVariables(x.into())
}
}
impl<'tcx> From<sv::UndoLog<ut::Delegate<type_variable::TyVidSubKey>>> for
UndoLog<'tcx> {
fn from(x: sv::UndoLog<ut::Delegate<type_variable::TyVidSubKey>>)
-> Self {
UndoLog::TypeVariables(x.into())
}
}
impl<'tcx> From<type_variable::UndoLog<'tcx>> for UndoLog<'tcx> {
fn from(x: type_variable::UndoLog<'tcx>) -> Self {
UndoLog::TypeVariables(x.into())
}
}
impl<'tcx> From<sv::UndoLog<ut::Delegate<ty::IntVid>>> for UndoLog<'tcx> {
fn from(x: sv::UndoLog<ut::Delegate<ty::IntVid>>) -> Self {
UndoLog::IntUnificationTable(x.into())
}
}
impl<'tcx> From<sv::UndoLog<ut::Delegate<ty::FloatVid>>> for UndoLog<'tcx> {
fn from(x: sv::UndoLog<ut::Delegate<ty::FloatVid>>) -> Self {
UndoLog::FloatUnificationTable(x.into())
}
}
impl<'tcx> From<sv::UndoLog<ut::Delegate<ConstVidKey<'tcx>>>> for
UndoLog<'tcx> {
fn from(x: sv::UndoLog<ut::Delegate<ConstVidKey<'tcx>>>) -> Self {
UndoLog::ConstUnificationTable(x.into())
}
}
impl<'tcx> From<sv::UndoLog<ut::Delegate<RegionVidKey<'tcx>>>> for
UndoLog<'tcx> {
fn from(x: sv::UndoLog<ut::Delegate<RegionVidKey<'tcx>>>) -> Self {
UndoLog::RegionUnificationTable(x.into())
}
}
impl<'tcx> From<traits::UndoLog<'tcx>> for UndoLog<'tcx> {
fn from(x: traits::UndoLog<'tcx>) -> Self {
UndoLog::ProjectionCache(x.into())
}
}impl_from! {
51 RegionConstraintCollector(region_constraints::UndoLog<'tcx>),
52
53 TypeVariables(sv::UndoLog<ut::Delegate<type_variable::TyVidEqKey<'tcx>>>),
54 TypeVariables(sv::UndoLog<ut::Delegate<type_variable::TyVidSubKey>>),
55 TypeVariables(type_variable::UndoLog<'tcx>),
56 IntUnificationTable(sv::UndoLog<ut::Delegate<ty::IntVid>>),
57 FloatUnificationTable(sv::UndoLog<ut::Delegate<ty::FloatVid>>),
58
59 ConstUnificationTable(sv::UndoLog<ut::Delegate<ConstVidKey<'tcx>>>),
60
61 RegionUnificationTable(sv::UndoLog<ut::Delegate<RegionVidKey<'tcx>>>),
62 ProjectionCache(traits::UndoLog<'tcx>),
63}
64
65impl<'tcx> Rollback<UndoLog<'tcx>> for InferCtxtInner<'tcx> {
67 fn reverse(&mut self, undo: UndoLog<'tcx>) {
68 match undo {
69 UndoLog::DuplicateOpaqueType => self.opaque_type_storage.pop_duplicate_entry(),
70 UndoLog::OpaqueTypes(key, idx) => self.opaque_type_storage.remove(key, idx),
71 UndoLog::TypeVariables(undo) => self.type_variable_storage.reverse(undo),
72 UndoLog::ConstUnificationTable(undo) => self.const_unification_storage.reverse(undo),
73 UndoLog::IntUnificationTable(undo) => self.int_unification_storage.reverse(undo),
74 UndoLog::FloatUnificationTable(undo) => self.float_unification_storage.reverse(undo),
75 UndoLog::RegionConstraintCollector(undo) => {
76 self.region_constraint_storage.as_mut().unwrap().reverse(undo)
77 }
78 UndoLog::RegionUnificationTable(undo) => {
79 self.region_constraint_storage.as_mut().unwrap().unification_table.reverse(undo)
80 }
81 UndoLog::ProjectionCache(undo) => self.projection_cache.reverse(undo),
82 UndoLog::PushSolverRegionConstraint { previous_was_and } => {
83 let popped = self.solver_region_constraint_storage.pop(previous_was_and);
84 {
match popped {
Some(_) => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val, "Some(_)",
::core::option::Option::Some(format_args!("pushed solver region constraint but could not pop it")));
}
}
};assert_matches!(
85 popped,
86 Some(_),
87 "pushed solver region constraint but could not pop it"
88 );
89 }
90 UndoLog::OverwriteSolverRegionConstraint { old_constraint } => {
91 self.solver_region_constraint_storage.overwrite(old_constraint);
92 }
93 UndoLog::PushTypeOutlivesConstraint => {
94 let popped = self.region_obligations.pop();
95 {
match popped {
Some(_) => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val, "Some(_)",
::core::option::Option::Some(format_args!("pushed region constraint but could not pop it")));
}
}
};assert_matches!(popped, Some(_), "pushed region constraint but could not pop it");
96 }
97 UndoLog::PushRegionAssumption => {
98 let popped = self.region_assumptions.pop();
99 {
match popped {
Some(_) => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val, "Some(_)",
::core::option::Option::Some(format_args!("pushed region assumption but could not pop it")));
}
}
};assert_matches!(popped, Some(_), "pushed region assumption but could not pop it");
100 }
101 UndoLog::PushHirTypeckPotentiallyRegionDependentGoal => {
102 let popped = self.hir_typeck_potentially_region_dependent_goals.pop();
103 {
match popped {
Some(_) => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val, "Some(_)",
::core::option::Option::Some(format_args!("pushed goal but could not pop it")));
}
}
};assert_matches!(popped, Some(_), "pushed goal but could not pop it");
104 }
105 }
106 }
107}
108
109#[derive(#[automatically_derived]
impl<'tcx> ::core::clone::Clone for InferCtxtUndoLogs<'tcx> {
#[inline]
fn clone(&self) -> InferCtxtUndoLogs<'tcx> {
InferCtxtUndoLogs {
logs: ::core::clone::Clone::clone(&self.logs),
num_open_snapshots: ::core::clone::Clone::clone(&self.num_open_snapshots),
}
}
}Clone, #[automatically_derived]
impl<'tcx> ::core::default::Default for InferCtxtUndoLogs<'tcx> {
#[inline]
fn default() -> InferCtxtUndoLogs<'tcx> {
InferCtxtUndoLogs {
logs: ::core::default::Default::default(),
num_open_snapshots: ::core::default::Default::default(),
}
}
}Default)]
112pub(crate) struct InferCtxtUndoLogs<'tcx> {
113 logs: Vec<UndoLog<'tcx>>,
114 num_open_snapshots: usize,
115}
116
117impl<'tcx, T> UndoLogs<T> for InferCtxtUndoLogs<'tcx>
120where
121 UndoLog<'tcx>: From<T>,
122{
123 #[inline]
124 fn num_open_snapshots(&self) -> usize {
125 self.num_open_snapshots
126 }
127
128 #[inline]
129 fn push(&mut self, undo: T) {
130 if self.in_snapshot() {
131 self.logs.push(undo.into())
132 }
133 }
134
135 fn clear(&mut self) {
136 self.logs.clear();
137 self.num_open_snapshots = 0;
138 }
139
140 fn extend<J>(&mut self, undos: J)
141 where
142 J: IntoIterator<Item = T>,
143 {
144 if self.in_snapshot() {
145 self.logs.extend(undos.into_iter().map(UndoLog::from))
146 }
147 }
148}
149
150impl<'tcx> InferCtxtInner<'tcx> {
151 pub fn rollback_to(&mut self, snapshot: Snapshot<'tcx>) {
152 {
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/undo_log.rs:152",
"rustc_infer::infer::snapshot::undo_log",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/snapshot/undo_log.rs"),
::tracing_core::__macro_support::Option::Some(152u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::snapshot::undo_log"),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("rollback_to({0})",
snapshot.undo_len) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("rollback_to({})", snapshot.undo_len);
153 self.undo_log.assert_open_snapshot(&snapshot);
154
155 while self.undo_log.logs.len() > snapshot.undo_len {
156 let undo = self.undo_log.logs.pop().unwrap();
157 self.reverse(undo);
158 }
159
160 self.type_variable_storage.finalize_rollback();
161
162 if self.undo_log.num_open_snapshots == 1 {
163 if !(snapshot.undo_len == 0) {
::core::panicking::panic("assertion failed: snapshot.undo_len == 0")
};assert!(snapshot.undo_len == 0);
165 if !self.undo_log.logs.is_empty() {
::core::panicking::panic("assertion failed: self.undo_log.logs.is_empty()")
};assert!(self.undo_log.logs.is_empty());
166 }
167
168 self.undo_log.num_open_snapshots -= 1;
169 }
170
171 pub fn commit(&mut self, snapshot: Snapshot<'tcx>) {
172 {
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/undo_log.rs:172",
"rustc_infer::infer::snapshot::undo_log",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/snapshot/undo_log.rs"),
::tracing_core::__macro_support::Option::Some(172u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::snapshot::undo_log"),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("commit({0})",
snapshot.undo_len) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("commit({})", snapshot.undo_len);
173
174 if self.undo_log.num_open_snapshots == 1 {
175 if !(snapshot.undo_len == 0) {
::core::panicking::panic("assertion failed: snapshot.undo_len == 0")
};assert!(snapshot.undo_len == 0);
179 self.undo_log.logs.clear();
180 }
181
182 self.undo_log.num_open_snapshots -= 1;
183 }
184}
185
186impl<'tcx> InferCtxtUndoLogs<'tcx> {
187 pub(crate) fn start_snapshot(&mut self) -> Snapshot<'tcx> {
188 self.num_open_snapshots += 1;
189 Snapshot { undo_len: self.logs.len(), _marker: PhantomData }
190 }
191
192 pub(crate) fn region_constraints_in_snapshot(
193 &self,
194 s: &Snapshot<'tcx>,
195 ) -> impl Iterator<Item = &'_ region_constraints::UndoLog<'tcx>> + Clone {
196 self.logs[s.undo_len..].iter().filter_map(|log| match log {
197 UndoLog::RegionConstraintCollector(log) => Some(log),
198 _ => None,
199 })
200 }
201
202 pub(crate) fn opaque_types_in_snapshot(&self, s: &Snapshot<'tcx>) -> bool {
203 self.logs[s.undo_len..].iter().any(|log| #[allow(non_exhaustive_omitted_patterns)] match log {
UndoLog::OpaqueTypes(..) => true,
_ => false,
}matches!(log, UndoLog::OpaqueTypes(..)))
204 }
205
206 fn assert_open_snapshot(&self, snapshot: &Snapshot<'tcx>) {
207 if !(self.logs.len() >= snapshot.undo_len) {
::core::panicking::panic("assertion failed: self.logs.len() >= snapshot.undo_len")
};assert!(self.logs.len() >= snapshot.undo_len);
209 if !(self.num_open_snapshots > 0) {
::core::panicking::panic("assertion failed: self.num_open_snapshots > 0")
};assert!(self.num_open_snapshots > 0);
210 }
211}
212
213impl<'tcx> std::ops::Index<usize> for InferCtxtUndoLogs<'tcx> {
214 type Output = UndoLog<'tcx>;
215
216 fn index(&self, key: usize) -> &Self::Output {
217 &self.logs[key]
218 }
219}
220
221impl<'tcx> std::ops::IndexMut<usize> for InferCtxtUndoLogs<'tcx> {
222 fn index_mut(&mut self, key: usize) -> &mut Self::Output {
223 &mut self.logs[key]
224 }
225}