Skip to main content

charon_lib/ast/items/
global_decl.rs

1use derive_generic_visitor::{Drive, DriveMut, DriveTwo};
2use serde_state::{DeserializeState, SerializeState};
3
4use crate::ast::*;
5use macros::EnumIsA;
6
7/// A global variable definition (constant or static).
8#[derive(Debug, Clone)]
9#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
10pub struct GlobalDecl {
11    pub def_id: GlobalDeclId,
12    /// The meta data associated with the declaration.
13    pub item_meta: ItemMeta,
14    /// Remark: constants can actually have generic parameters.
15    /// ```text
16    /// struct V<const N: usize, T> {
17    ///     x: [T; N],
18    /// }
19    ///
20    /// impl<const N: usize, T> V<N, T> {
21    ///     const LEN: usize = N; // This has generics <N, T>
22    /// }
23    ///
24    /// fn use_v<const N: usize, T>(v: V<N, T>) {
25    ///     let l = V::<N, T>::LEN; // We need to provided a substitution here
26    /// }
27    /// ```
28    pub generics: GenericParams,
29    pub ty: Ty,
30    /// The size in bytes of the global's allocation.
31    pub size: Size,
32    /// The alignment in bytes of the global's allocation.
33    pub align: Size,
34    /// The pointer metadata for references to this global (needed for unsized globals).
35    pub ptr_metadata: ConstantExpr,
36    /// The context of the global: distinguishes normal items from trait-associated items and
37    /// vtable instances.
38    pub src: GlobalSource,
39    /// The kind of global (static or const).
40    pub global_kind: GlobalKind,
41    /// The value of this constant/static. By default this is a [`ConstantExprKind::Call`] to the
42    /// initializer function that computes the value (the function uses the same generic parameters
43    /// as the global).
44    pub value: ConstantExpr,
45}
46
47#[derive(Debug, Clone, PartialEq, Eq)]
48#[derive(EnumIsA)]
49#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
50pub enum GlobalKind {
51    /// A static or thread-local static.
52    Static {
53        is_mut: bool,
54        /// `false` for statics declared in an `extern` block without the `safe` qualifier.
55        is_safe: bool,
56        /// `true` for thread-local statics (through `thread_local!` or `#[thread_local]`).
57        is_thread_local: bool,
58    },
59    /// A const with a name (either top-level or an associated const in a trait).
60    NamedConst,
61    /// A const without a name:
62    /// - An inline const expression (`const { 1 + 1 }`);
63    /// - A const expression in a type (`[u8; sizeof::<T>()]`);
64    /// - A promoted constant, automatically lifted from a body (`&0`).
65    AnonConst,
66    /// The VTable of a trait implementation. Such globals can only be accessed by the generated
67    /// code -- it is UB to access them from user code.
68    #[cfg_attr(feature = "charon_on_charon", charon::rename("VTableGlobal"))]
69    VTable,
70}
71
72/// Where a given global came from.
73#[derive(Debug, Clone)]
74#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
75#[cfg_attr(feature = "charon_on_charon", charon::variants_suffix("Global"))]
76pub enum GlobalSource {
77    /// A normal global.
78    Normal,
79    /// A default assoc const in a trait declaration.
80    TraitDefault {
81        /// The trait declaration the const belongs to.
82        trait_ref: TraitDeclRef,
83        /// The associated const this corresponds to.
84        item_id: AssocConstId,
85    },
86    /// An associated const in a trait implementation.
87    TraitImpl {
88        /// The trait implementation the const belongs to.
89        impl_ref: TraitImplRef,
90        /// The trait declaration that the impl block implements.
91        trait_ref: TraitDeclRef,
92        /// The associated const this corresponds to.
93        item_id: AssocConstId,
94        /// True if the trait decl had a default value for this const and this item is a copy of
95        /// the default item.
96        reuses_default: bool,
97    },
98    /// Defines the vtable for a trait impl.
99    VTableInstance {
100        /// The concrete type this vtable is for.
101        self_ty: Ty,
102        /// The originating impl. This is `None` in monomorphized mode: the vtable global itself
103        /// identifies the concrete instantiation, so we don't translate an impl reference solely
104        /// to record its provenance.
105        impl_ref: Option<TraitImplRef>,
106    },
107}
108
109impl GlobalDecl {
110    /// If this global's value is a call to its initializer function, returns the initializer's id.
111    pub fn init_fun_id(&self) -> Option<FunDeclId> {
112        match self.value.kind() {
113            ConstantExprKind::Call(fn_ptr, _) => match &*fn_ptr.kind {
114                FnPtrKind::Fun(id) => Some(*id),
115                _ => None,
116            },
117            _ => None,
118        }
119    }
120
121    /// Whether this global is unsafe to access, because it is a mutable or unsafe external static (safety.unsafe-static).
122    pub fn is_unsafe_to_access(&self, _krate: &TranslatedCrate) -> bool {
123        match self.global_kind {
124            GlobalKind::Static {
125                is_mut,
126                is_safe,
127                is_thread_local: _,
128            } => is_mut || !is_safe,
129            GlobalKind::NamedConst | GlobalKind::AnonConst | GlobalKind::VTable => false,
130        }
131    }
132
133    /// Whether this global is unsafe to declare.
134    pub fn is_unsafe_to_declare(&self, _krate: &TranslatedCrate) -> bool {
135        self.item_meta.is_unsafe_to_declare()
136    }
137}