rustc_infer/infer/opaque_types/
table.rs1use rustc_data_structures::undo_log::UndoLogs;
2use rustc_middle::bug;
3use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty};
4use tracing::instrument;
5
6use super::OpaqueTypeMap;
7use crate::infer::snapshot::undo_log::{InferCtxtUndoLogs, UndoLog};
8
9#[derive(Default, Debug, Clone)]
10pub(crate) struct OpaqueTypeStorage<'tcx> {
11 pub opaque_types: OpaqueTypeMap<'tcx>,
16}
17
18impl<'tcx> OpaqueTypeStorage<'tcx> {
19 #[instrument(level = "debug")]
20 pub(crate) fn remove(
21 &mut self,
22 key: OpaqueTypeKey<'tcx>,
23 prev: Option<OpaqueHiddenType<'tcx>>,
24 ) {
25 if let Some(prev) = prev {
26 *self.opaque_types.get_mut(&key).unwrap() = prev;
27 } else {
28 match self.opaque_types.swap_remove(&key) {
30 None => bug!("reverted opaque type inference that was never registered: {:?}", key),
31 Some(_) => {}
32 }
33 }
34 }
35
36 #[inline]
37 pub(crate) fn with_log<'a>(
38 &'a mut self,
39 undo_log: &'a mut InferCtxtUndoLogs<'tcx>,
40 ) -> OpaqueTypeTable<'a, 'tcx> {
41 OpaqueTypeTable { storage: self, undo_log }
42 }
43}
44
45impl<'tcx> Drop for OpaqueTypeStorage<'tcx> {
46 fn drop(&mut self) {
47 if !self.opaque_types.is_empty() {
48 ty::tls::with(|tcx| tcx.dcx().delayed_bug(format!("{:?}", self.opaque_types)));
49 }
50 }
51}
52
53pub(crate) struct OpaqueTypeTable<'a, 'tcx> {
54 storage: &'a mut OpaqueTypeStorage<'tcx>,
55
56 undo_log: &'a mut InferCtxtUndoLogs<'tcx>,
57}
58
59impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> {
60 #[instrument(skip(self), level = "debug")]
61 pub(crate) fn register(
62 &mut self,
63 key: OpaqueTypeKey<'tcx>,
64 hidden_type: OpaqueHiddenType<'tcx>,
65 ) -> Option<Ty<'tcx>> {
66 if let Some(entry) = self.storage.opaque_types.get_mut(&key) {
67 let prev = std::mem::replace(entry, hidden_type);
68 self.undo_log.push(UndoLog::OpaqueTypes(key, Some(prev)));
69 return Some(prev.ty);
70 }
71 self.storage.opaque_types.insert(key, hidden_type);
72 self.undo_log.push(UndoLog::OpaqueTypes(key, None));
73 None
74 }
75}