rustc_infer/infer/opaque_types/
table.rs1use std::ops::Deref;
2
3use rustc_data_structures::fx::FxIndexMap;
4use rustc_data_structures::undo_log::UndoLogs;
5use rustc_middle::bug;
6use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty};
7use tracing::instrument;
8
9use crate::infer::snapshot::undo_log::{InferCtxtUndoLogs, UndoLog};
10
11#[derive(Default, Debug, Clone)]
12pub struct OpaqueTypeStorage<'tcx> {
13 opaque_types: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
14 duplicate_entries: Vec<(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)>,
15}
16
17#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
22pub struct OpaqueTypeStorageEntries {
23 opaque_types: usize,
24 duplicate_entries: usize,
25}
26
27impl<'tcx> OpaqueTypeStorage<'tcx> {
28 #[instrument(level = "debug")]
29 pub(crate) fn remove(
30 &mut self,
31 key: OpaqueTypeKey<'tcx>,
32 prev: Option<OpaqueHiddenType<'tcx>>,
33 ) {
34 if let Some(prev) = prev {
35 *self.opaque_types.get_mut(&key).unwrap() = prev;
36 } else {
37 match self.opaque_types.swap_remove(&key) {
39 None => bug!("reverted opaque type inference that was never registered: {:?}", key),
40 Some(_) => {}
41 }
42 }
43 }
44
45 pub(crate) fn pop_duplicate_entry(&mut self) {
46 let entry = self.duplicate_entries.pop();
47 assert!(entry.is_some());
48 }
49
50 pub(crate) fn is_empty(&self) -> bool {
51 let OpaqueTypeStorage { opaque_types, duplicate_entries } = self;
52 opaque_types.is_empty() && duplicate_entries.is_empty()
53 }
54
55 pub(crate) fn take_opaque_types(
56 &mut self,
57 ) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
58 let OpaqueTypeStorage { opaque_types, duplicate_entries } = self;
59 std::mem::take(opaque_types).into_iter().chain(std::mem::take(duplicate_entries))
60 }
61
62 pub fn num_entries(&self) -> OpaqueTypeStorageEntries {
63 OpaqueTypeStorageEntries {
64 opaque_types: self.opaque_types.len(),
65 duplicate_entries: self.duplicate_entries.len(),
66 }
67 }
68
69 pub fn opaque_types_added_since(
70 &self,
71 prev_entries: OpaqueTypeStorageEntries,
72 ) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
73 self.opaque_types
74 .iter()
75 .skip(prev_entries.opaque_types)
76 .map(|(k, v)| (*k, *v))
77 .chain(self.duplicate_entries.iter().skip(prev_entries.duplicate_entries).copied())
78 }
79
80 pub fn iter_lookup_table(
86 &self,
87 ) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
88 self.opaque_types.iter().map(|(k, v)| (*k, *v))
89 }
90
91 pub fn iter_duplicate_entries(
97 &self,
98 ) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
99 self.duplicate_entries.iter().copied()
100 }
101
102 pub fn iter_opaque_types(
103 &self,
104 ) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
105 let OpaqueTypeStorage { opaque_types, duplicate_entries } = self;
106 opaque_types.iter().map(|(k, v)| (*k, *v)).chain(duplicate_entries.iter().copied())
107 }
108
109 #[inline]
110 pub(crate) fn with_log<'a>(
111 &'a mut self,
112 undo_log: &'a mut InferCtxtUndoLogs<'tcx>,
113 ) -> OpaqueTypeTable<'a, 'tcx> {
114 OpaqueTypeTable { storage: self, undo_log }
115 }
116}
117
118impl<'tcx> Drop for OpaqueTypeStorage<'tcx> {
119 fn drop(&mut self) {
120 if !self.is_empty() {
121 ty::tls::with(|tcx| tcx.dcx().delayed_bug(format!("{:?}", self.opaque_types)));
122 }
123 }
124}
125
126pub struct OpaqueTypeTable<'a, 'tcx> {
127 storage: &'a mut OpaqueTypeStorage<'tcx>,
128
129 undo_log: &'a mut InferCtxtUndoLogs<'tcx>,
130}
131impl<'tcx> Deref for OpaqueTypeTable<'_, 'tcx> {
132 type Target = OpaqueTypeStorage<'tcx>;
133 fn deref(&self) -> &Self::Target {
134 self.storage
135 }
136}
137
138impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> {
139 #[instrument(skip(self), level = "debug")]
140 pub fn register(
141 &mut self,
142 key: OpaqueTypeKey<'tcx>,
143 hidden_type: OpaqueHiddenType<'tcx>,
144 ) -> Option<Ty<'tcx>> {
145 if let Some(entry) = self.storage.opaque_types.get_mut(&key) {
146 let prev = std::mem::replace(entry, hidden_type);
147 self.undo_log.push(UndoLog::OpaqueTypes(key, Some(prev)));
148 return Some(prev.ty);
149 }
150 self.storage.opaque_types.insert(key, hidden_type);
151 self.undo_log.push(UndoLog::OpaqueTypes(key, None));
152 None
153 }
154
155 pub fn add_duplicate(&mut self, key: OpaqueTypeKey<'tcx>, hidden_type: OpaqueHiddenType<'tcx>) {
156 self.storage.duplicate_entries.push((key, hidden_type));
157 self.undo_log.push(UndoLog::DuplicateOpaqueType);
158 }
159}