summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_transmute/src/maybe_transmutable/query_context.rs')
-rw-r--r--compiler/rustc_transmute/src/maybe_transmutable/query_context.rs93
1 files changed, 93 insertions, 0 deletions
diff --git a/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs b/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs
new file mode 100644
index 000000000..9c2cf4c9a
--- /dev/null
+++ b/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs
@@ -0,0 +1,93 @@
+use crate::layout;
+
+/// Context necessary to answer the question "Are these types transmutable?".
+pub(crate) trait QueryContext {
+ type Def: layout::Def;
+ type Ref: layout::Ref;
+ type Scope: Copy;
+
+ /// Is `def` accessible from the defining module of `scope`?
+ fn is_accessible_from(&self, def: Self::Def, scope: Self::Scope) -> bool;
+
+ fn min_align(&self, reference: Self::Ref) -> usize;
+}
+
+#[cfg(test)]
+pub(crate) mod test {
+ use super::QueryContext;
+
+ pub(crate) struct UltraMinimal;
+
+ #[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)]
+ pub(crate) enum Def {
+ Visible,
+ Invisible,
+ }
+
+ impl crate::layout::Def for Def {}
+
+ impl QueryContext for UltraMinimal {
+ type Def = Def;
+ type Ref = !;
+ type Scope = ();
+
+ fn is_accessible_from(&self, def: Def, scope: ()) -> bool {
+ matches!(Def::Visible, def)
+ }
+
+ fn min_align(&self, reference: !) -> usize {
+ unimplemented!()
+ }
+ }
+}
+
+#[cfg(feature = "rustc")]
+mod rustc {
+ use super::*;
+ use rustc_middle::ty::{Ty, TyCtxt};
+
+ impl<'tcx> super::QueryContext for TyCtxt<'tcx> {
+ type Def = layout::rustc::Def<'tcx>;
+ type Ref = layout::rustc::Ref<'tcx>;
+
+ type Scope = Ty<'tcx>;
+
+ #[instrument(level = "debug", skip(self))]
+ fn is_accessible_from(&self, def: Self::Def, scope: Self::Scope) -> bool {
+ use layout::rustc::Def;
+ use rustc_middle::ty;
+
+ let parent = if let ty::Adt(adt_def, ..) = scope.kind() {
+ use rustc_middle::ty::DefIdTree;
+ let parent = self.parent(adt_def.did());
+ parent
+ } else {
+ // Is this always how we want to handle a non-ADT scope?
+ return false;
+ };
+
+ let def_id = match def {
+ Def::Adt(adt_def) => adt_def.did(),
+ Def::Variant(variant_def) => variant_def.def_id,
+ Def::Field(field_def) => field_def.did,
+ Def::Primitive => {
+ // primitives do not have a def_id, but they're always accessible
+ return true;
+ }
+ };
+
+ let ret = if self.visibility(def_id).is_accessible_from(parent, *self) {
+ true
+ } else {
+ false
+ };
+
+ tracing::trace!(?ret, "ret");
+ ret
+ }
+
+ fn min_align(&self, reference: Self::Ref) -> usize {
+ unimplemented!()
+ }
+ }
+}