]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_transmute/src/maybe_transmutable/query_context.rs
Auto merge of #103590 - compiler-errors:ocx-more, r=lcnr
[rust.git] / compiler / rustc_transmute / src / maybe_transmutable / query_context.rs
1 use crate::layout;
2
3 /// Context necessary to answer the question "Are these types transmutable?".
4 pub(crate) trait QueryContext {
5     type Def: layout::Def;
6     type Ref: layout::Ref;
7     type Scope: Copy;
8
9     /// Is `def` accessible from the defining module of `scope`?
10     fn is_accessible_from(&self, def: Self::Def, scope: Self::Scope) -> bool;
11
12     fn min_align(&self, reference: Self::Ref) -> usize;
13 }
14
15 #[cfg(test)]
16 pub(crate) mod test {
17     use super::QueryContext;
18
19     pub(crate) struct UltraMinimal;
20
21     #[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)]
22     pub(crate) enum Def {
23         Visible,
24         Invisible,
25     }
26
27     impl crate::layout::Def for Def {}
28
29     impl QueryContext for UltraMinimal {
30         type Def = Def;
31         type Ref = !;
32         type Scope = ();
33
34         fn is_accessible_from(&self, def: Def, scope: ()) -> bool {
35             matches!(Def::Visible, def)
36         }
37
38         fn min_align(&self, reference: !) -> usize {
39             unimplemented!()
40         }
41     }
42 }
43
44 #[cfg(feature = "rustc")]
45 mod rustc {
46     use super::*;
47     use rustc_middle::ty::{Ty, TyCtxt};
48
49     impl<'tcx> super::QueryContext for TyCtxt<'tcx> {
50         type Def = layout::rustc::Def<'tcx>;
51         type Ref = layout::rustc::Ref<'tcx>;
52
53         type Scope = Ty<'tcx>;
54
55         #[instrument(level = "debug", skip(self))]
56         fn is_accessible_from(&self, def: Self::Def, scope: Self::Scope) -> bool {
57             use layout::rustc::Def;
58             use rustc_middle::ty;
59
60             let parent = if let ty::Adt(adt_def, ..) = scope.kind() {
61                 use rustc_middle::ty::DefIdTree;
62                 let parent = self.parent(adt_def.did());
63                 parent
64             } else {
65                 // Is this always how we want to handle a non-ADT scope?
66                 return false;
67             };
68
69             let def_id = match def {
70                 Def::Adt(adt_def) => adt_def.did(),
71                 Def::Variant(variant_def) => variant_def.def_id,
72                 Def::Field(field_def) => field_def.did,
73                 Def::Primitive => {
74                     // primitives do not have a def_id, but they're always accessible
75                     return true;
76                 }
77             };
78
79             let ret = if self.visibility(def_id).is_accessible_from(parent, *self) {
80                 true
81             } else {
82                 false
83             };
84
85             trace!(?ret, "ret");
86             ret
87         }
88
89         fn min_align(&self, reference: Self::Ref) -> usize {
90             unimplemented!()
91         }
92     }
93 }