]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_infer/src/infer/opaque_types/table.rs
Rollup merge of #93830 - camelid:cleanup-section-code, r=GuillaumeGomez
[rust.git] / compiler / rustc_infer / src / infer / opaque_types / table.rs
1 use rustc_data_structures::undo_log::UndoLogs;
2 use rustc_hir::OpaqueTyOrigin;
3 use rustc_middle::ty::{self, OpaqueTypeKey, Ty};
4 use rustc_span::DUMMY_SP;
5
6 use crate::infer::{InferCtxtUndoLogs, UndoLog};
7
8 use super::{OpaqueHiddenType, OpaqueTypeDecl, OpaqueTypeMap};
9
10 #[derive(Default, Debug)]
11 pub struct OpaqueTypeStorage<'tcx> {
12     // Opaque types found in explicit return types and their
13     // associated fresh inference variable. Writeback resolves these
14     // variables to get the concrete type, which can be used to
15     // 'de-opaque' OpaqueTypeDecl, after typeck is done with all functions.
16     pub opaque_types: OpaqueTypeMap<'tcx>,
17 }
18
19 impl<'tcx> OpaqueTypeStorage<'tcx> {
20     #[instrument(level = "debug")]
21     pub(crate) fn remove(&mut self, key: OpaqueTypeKey<'tcx>, idx: Option<OpaqueHiddenType<'tcx>>) {
22         if let Some(idx) = idx {
23             self.opaque_types.get_mut(&key).unwrap().hidden_type = idx;
24         } else {
25             match self.opaque_types.remove(&key) {
26                 None => bug!("reverted opaque type inference that was never registered: {:?}", key),
27                 Some(_) => {}
28             }
29         }
30     }
31
32     pub fn get_decl(&self, key: &OpaqueTypeKey<'tcx>) -> Option<&OpaqueTypeDecl<'tcx>> {
33         self.opaque_types.get(key)
34     }
35
36     pub fn opaque_types(&self) -> OpaqueTypeMap<'tcx> {
37         self.opaque_types.clone()
38     }
39
40     #[instrument(level = "debug")]
41     pub fn take_opaque_types(&mut self) -> OpaqueTypeMap<'tcx> {
42         std::mem::take(&mut self.opaque_types)
43     }
44
45     #[inline]
46     pub(crate) fn with_log<'a>(
47         &'a mut self,
48         undo_log: &'a mut InferCtxtUndoLogs<'tcx>,
49     ) -> OpaqueTypeTable<'a, 'tcx> {
50         OpaqueTypeTable { storage: self, undo_log }
51     }
52 }
53
54 impl<'tcx> Drop for OpaqueTypeStorage<'tcx> {
55     fn drop(&mut self) {
56         if !self.opaque_types.is_empty() {
57             ty::tls::with(|tcx| {
58                 tcx.sess.delay_span_bug(DUMMY_SP, &format!("{:?}", self.opaque_types))
59             });
60         }
61     }
62 }
63
64 pub struct OpaqueTypeTable<'a, 'tcx> {
65     storage: &'a mut OpaqueTypeStorage<'tcx>,
66
67     undo_log: &'a mut InferCtxtUndoLogs<'tcx>,
68 }
69
70 impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> {
71     #[instrument(skip(self), level = "debug")]
72     pub fn register(
73         &mut self,
74         key: OpaqueTypeKey<'tcx>,
75         hidden_type: OpaqueHiddenType<'tcx>,
76         origin: OpaqueTyOrigin,
77     ) -> Option<Ty<'tcx>> {
78         if let Some(decl) = self.storage.opaque_types.get_mut(&key) {
79             let prev = std::mem::replace(&mut decl.hidden_type, hidden_type);
80             self.undo_log.push(UndoLog::OpaqueTypes(key, Some(prev)));
81             return Some(prev.ty);
82         }
83         let decl = OpaqueTypeDecl { hidden_type, origin };
84         self.storage.opaque_types.insert(key, decl);
85         self.undo_log.push(UndoLog::OpaqueTypes(key, None));
86         None
87     }
88 }