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 rustc_type_ir::inherent::OpaqueTypeStorageEntries for OpaqueTypeStorageEntries {
28 fn needs_reevaluation(self, canonicalized: usize) -> bool {
29 self.opaque_types != canonicalized
30 }
31}
32
33impl<'tcx> OpaqueTypeStorage<'tcx> {
34 #[instrument(level = "debug")]
35 pub(crate) fn remove(
36 &mut self,
37 key: OpaqueTypeKey<'tcx>,
38 prev: Option<OpaqueHiddenType<'tcx>>,
39 ) {
40 if let Some(prev) = prev {
41 *self.opaque_types.get_mut(&key).unwrap() = prev;
42 } else {
43 match self.opaque_types.swap_remove(&key) {
45 None => bug!("reverted opaque type inference that was never registered: {:?}", key),
46 Some(_) => {}
47 }
48 }
49 }
50
51 pub(crate) fn pop_duplicate_entry(&mut self) {
52 let entry = self.duplicate_entries.pop();
53 assert!(entry.is_some());
54 }
55
56 pub fn is_empty(&self) -> bool {
57 let OpaqueTypeStorage { opaque_types, duplicate_entries } = self;
58 opaque_types.is_empty() && duplicate_entries.is_empty()
59 }
60
61 pub(crate) fn take_opaque_types(
62 &mut self,
63 ) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
64 let OpaqueTypeStorage { opaque_types, duplicate_entries } = self;
65 std::mem::take(opaque_types).into_iter().chain(std::mem::take(duplicate_entries))
66 }
67
68 pub fn num_entries(&self) -> OpaqueTypeStorageEntries {
69 OpaqueTypeStorageEntries {
70 opaque_types: self.opaque_types.len(),
71 duplicate_entries: self.duplicate_entries.len(),
72 }
73 }
74
75 pub fn opaque_types_added_since(
76 &self,
77 prev_entries: OpaqueTypeStorageEntries,
78 ) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
79 self.opaque_types
80 .iter()
81 .skip(prev_entries.opaque_types)
82 .map(|(k, v)| (*k, *v))
83 .chain(self.duplicate_entries.iter().skip(prev_entries.duplicate_entries).copied())
84 }
85
86 pub fn iter_lookup_table(
92 &self,
93 ) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
94 self.opaque_types.iter().map(|(k, v)| (*k, *v))
95 }
96
97 pub fn iter_duplicate_entries(
103 &self,
104 ) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
105 self.duplicate_entries.iter().copied()
106 }
107
108 pub fn iter_opaque_types(
109 &self,
110 ) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
111 let OpaqueTypeStorage { opaque_types, duplicate_entries } = self;
112 opaque_types.iter().map(|(k, v)| (*k, *v)).chain(duplicate_entries.iter().copied())
113 }
114
115 #[inline]
116 pub(crate) fn with_log<'a>(
117 &'a mut self,
118 undo_log: &'a mut InferCtxtUndoLogs<'tcx>,
119 ) -> OpaqueTypeTable<'a, 'tcx> {
120 OpaqueTypeTable { storage: self, undo_log }
121 }
122}
123
124impl<'tcx> Drop for OpaqueTypeStorage<'tcx> {
125 fn drop(&mut self) {
126 if !self.is_empty() {
127 ty::tls::with(|tcx| tcx.dcx().delayed_bug(format!("{:?}", self.opaque_types)));
128 }
129 }
130}
131
132pub struct OpaqueTypeTable<'a, 'tcx> {
133 storage: &'a mut OpaqueTypeStorage<'tcx>,
134
135 undo_log: &'a mut InferCtxtUndoLogs<'tcx>,
136}
137impl<'tcx> Deref for OpaqueTypeTable<'_, 'tcx> {
138 type Target = OpaqueTypeStorage<'tcx>;
139 fn deref(&self) -> &Self::Target {
140 self.storage
141 }
142}
143
144impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> {
145 #[instrument(skip(self), level = "debug")]
146 pub fn register(
147 &mut self,
148 key: OpaqueTypeKey<'tcx>,
149 hidden_type: OpaqueHiddenType<'tcx>,
150 ) -> Option<Ty<'tcx>> {
151 if let Some(entry) = self.storage.opaque_types.get_mut(&key) {
152 let prev = std::mem::replace(entry, hidden_type);
153 self.undo_log.push(UndoLog::OpaqueTypes(key, Some(prev)));
154 return Some(prev.ty);
155 }
156 self.storage.opaque_types.insert(key, hidden_type);
157 self.undo_log.push(UndoLog::OpaqueTypes(key, None));
158 None
159 }
160
161 pub fn add_duplicate(&mut self, key: OpaqueTypeKey<'tcx>, hidden_type: OpaqueHiddenType<'tcx>) {
162 self.storage.duplicate_entries.push((key, hidden_type));
163 self.undo_log.push(UndoLog::DuplicateOpaqueType);
164 }
165}