charon_lib/ast/meta.rs
1//! Meta-information about programs (spans, etc.).
2
3use super::from_rustc::{self, LangItem};
4pub use super::meta_utils::*;
5use crate::ast::{FunDeclId, ItemId};
6use crate::names::Name;
7use derive_generic_visitor::{Drive, DriveMut, DriveTwo};
8use macros::{EnumAsGetters, EnumIsA, EnumToGetters};
9use serde::{Deserialize, Serialize};
10use serde_state::{DeserializeState, SerializeState};
11use std::path::PathBuf;
12
13generate_index_type!(FileId);
14
15#[derive(
16 Debug,
17 Copy,
18 Clone,
19 PartialEq,
20 Eq,
21 PartialOrd,
22 Ord,
23 Hash,
24 Serialize,
25 Deserialize,
26 Drive,
27 DriveMut,
28 DriveTwo,
29)]
30#[drive(skip)]
31pub struct Loc {
32 /// The (1-based) line number.
33 pub line: usize,
34 /// The (0-based) column offset.
35 pub col: usize,
36}
37
38/// Span information
39#[derive(
40 Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Drive, DriveMut, DriveTwo,
41)]
42pub struct SpanData {
43 #[cfg_attr(feature = "charon_on_charon", charon::rename("file"))]
44 pub file_id: FileId,
45 #[cfg_attr(feature = "charon_on_charon", charon::rename("beg_loc"))]
46 pub beg: Loc,
47 #[cfg_attr(feature = "charon_on_charon", charon::rename("end_loc"))]
48 pub end: Loc,
49}
50
51/// Meta information about a piece of code (block, statement, etc.)
52#[derive(
53 Debug,
54 Copy,
55 Clone,
56 PartialEq,
57 Eq,
58 PartialOrd,
59 Ord,
60 Hash,
61 Serialize,
62 Deserialize,
63 SerializeState,
64 DeserializeState,
65 Drive,
66 DriveMut,
67 DriveTwo,
68)]
69#[serde_state(stateless)]
70pub struct Span {
71 /// The source code span.
72 ///
73 /// If this meta information is for a statement/terminator coming from a macro
74 /// expansion/inlining/etc., this span is (in case of macros) for the macro
75 /// before expansion (i.e., the location the code where the user wrote the call
76 /// to the macro).
77 ///
78 /// Ex:
79 /// ```text
80 /// // Below, we consider the spans for the statements inside `test`
81 ///
82 /// // the statement we consider, which gets inlined in `test`
83 /// VV
84 /// macro_rules! macro { ... st ... } // `generated_from_span` refers to this location
85 ///
86 /// fn test() {
87 /// macro!(); // <-- `span` refers to this location
88 /// }
89 /// ```
90 pub data: SpanData,
91 /// Where the code actually comes from, in case of macro expansion/inlining/etc.
92 pub generated_from_span: Option<SpanData>,
93}
94
95/// `#[inline]` built-in attribute.
96#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Drive, DriveMut, DriveTwo)]
97pub enum InlineAttr {
98 /// `#[inline]`
99 Hint,
100 /// `#[inline(never)]`
101 Never,
102 /// `#[inline(always)]`
103 Always,
104}
105
106/// Attributes (`#[...]`).
107#[derive(
108 Debug,
109 Clone,
110 PartialEq,
111 Eq,
112 EnumIsA,
113 EnumAsGetters,
114 EnumToGetters,
115 Serialize,
116 Deserialize,
117 Drive,
118 DriveMut,
119 DriveTwo,
120)]
121#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("Attr"))]
122pub enum Attribute {
123 /// Do not translate the body of this item.
124 /// Written `#[charon::opaque]`
125 Opaque,
126 /// Do not translate this item at all.
127 /// Written `#[charon::exclude]`
128 Exclude,
129 /// Provide a new name that consumers of the llbc can use.
130 /// Written `#[charon::rename("new_name")]`
131 Rename(String),
132 /// For enums only: rename the variants by pre-pending their names with the given prefix.
133 /// Written `#[charon::variants_prefix("prefix_")]`.
134 VariantsPrefix(String),
135 /// Same as `VariantsPrefix`, but appends to the name instead of pre-pending.
136 VariantsSuffix(String),
137 /// The structure is treated as a transparent wrapper around its sole field.
138 /// Written `#[charon::transparent]`.
139 Transparent,
140 /// An item annotated with `#[charon::precondition]`. This makes it a precondition for its
141 /// parent item.
142 IsPrecondition(ItemId),
143 /// An item annotated with `#[charon::postcondition]`. This makes it a postcondition for its
144 /// parent item.
145 IsPostcondition(ItemId),
146 /// An item that has a precondition that applies to it. The referenced item is a function the
147 /// specifies the condition.
148 HasPrecondition(FunDeclId),
149 /// An item that has a postcondition that applies to it. The referenced item is a function the
150 /// specifies the condition.
151 HasPostcondition(FunDeclId),
152 /// A doc-comment such as `/// ...`.
153 DocComment(String),
154 /// A built-in attribute.
155 Builtin(#[drive(skip)] from_rustc::AttributeKind),
156 /// None of the above.
157 Unknown(RawAttribute),
158}
159
160/// A general attribute.
161#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Drive, DriveMut, DriveTwo)]
162pub struct RawAttribute {
163 pub path: String,
164 /// The arguments passed to the attribute, if any. We don't distinguish different delimiters or
165 /// the `path = lit` case.
166 pub args: Option<String>,
167}
168
169/// Information about the attributes and visibility of an item, field or variant..
170#[derive(
171 Debug, PartialEq, Eq, Default, Clone, Serialize, Deserialize, Drive, DriveMut, DriveTwo,
172)]
173pub struct AttrInfo {
174 /// Attributes (`#[...]`).
175 pub attributes: Vec<Attribute>,
176 /// Inline hints (on functions only).
177 pub inline: Option<InlineAttr>,
178 /// The name computed from `charon::rename` and `charon::variants_prefix` attributes, if any.
179 /// This provides a custom name that can be used by consumers of llbc. E.g. Aeneas uses this to
180 /// rename definitions in the extracted code.
181 pub rename: Option<String>,
182 /// Whether this item is declared public. Impl blocks and closures don't have visibility
183 /// modifiers; we arbitrarily set this to `false` for them.
184 ///
185 /// Note that this is different from being part of the crate's public API: to be part of the
186 /// public API, an item has to also be reachable from public items in the crate root. For
187 /// example:
188 /// ```rust,ignore
189 /// mod foo {
190 /// pub struct X;
191 /// }
192 /// mod bar {
193 /// pub fn something(_x: super::foo::X) {}
194 /// }
195 /// pub use bar::something; // exposes `X`
196 /// ```
197 /// Without the `pub use ...`, neither `X` nor `something` would be part of the crate's public
198 /// API (this is called "pub-in-priv" items). With or without the `pub use`, we set `public =
199 /// true`; computing item reachability is harder.
200 pub public: bool,
201}
202
203#[derive(
204 Debug,
205 Copy,
206 Clone,
207 PartialEq,
208 Eq,
209 PartialOrd,
210 Ord,
211 Serialize,
212 Deserialize,
213 Drive,
214 DriveMut,
215 DriveTwo,
216 EnumIsA,
217)]
218pub enum ItemOpacity {
219 /// Translate the item fully.
220 Transparent,
221 /// Translate the item depending on the normal rust visibility of its contents: for types, we
222 /// translate fully if it is a struct with public fields or an enum; for other items this is
223 /// equivalent to `Opaque`.
224 Foreign,
225 /// Translate the item name and signature, but not its contents. For function and globals, this
226 /// means we don't translate the body (the code); for ADTs, this means we don't translate the
227 /// fields/variants. For traits and trait impls, this doesn't change anything. For modules,
228 /// this means we don't explore its contents (we still translate any of its items mentioned
229 /// from somewhere else).
230 ///
231 /// This can happen either if the item was annotated with `#[charon::opaque]` or if it was
232 /// declared opaque via a command-line argument.
233 #[cfg_attr(feature = "charon_on_charon", charon::rename("ItemOpaque"))]
234 Opaque,
235 /// Translate nothing of this item. The corresponding map will not have an entry for the
236 /// `ItemId`. Useful when even the signature of the item causes errors.
237 Invisible,
238}
239
240/// Meta information about an item (function, trait decl, trait impl, type decl, global).
241#[derive(
242 Debug, PartialEq, Eq, Clone, SerializeState, DeserializeState, Drive, DriveMut, DriveTwo,
243)]
244#[serde_state(stateless)]
245pub struct ItemMeta {
246 #[serde_state(stateful)]
247 pub name: Name,
248 pub span: Span,
249 /// The source code that corresponds to this item.
250 #[drive(skip)]
251 pub source_text: Option<String>,
252 /// Attributes and visibility.
253 pub attr_info: AttrInfo,
254 /// `true` if the type decl is a local type decl, `false` if it comes from an external crate.
255 #[drive(skip)]
256 pub is_local: bool,
257 /// Whether this item is considered opaque. For function and globals, this means we don't
258 /// translate the body (the code); for ADTs, this means we don't translate the fields/variants.
259 /// For traits and trait impls, this doesn't change anything. For modules, this means we don't
260 /// explore its contents (we still translate any of its items mentioned from somewhere else).
261 ///
262 /// This can happen either if the item was annotated with `#[charon::opaque]` or if it was
263 /// declared opaque via a command-line argument.
264 #[drive(skip)]
265 pub opacity: ItemOpacity,
266 /// If the item is a rustc lang item, record which one it is.
267 #[drive(skip)]
268 pub lang_item: Option<LangItem>,
269 /// If the item is a rustc diagnostic item, record its internal identifier.
270 #[drive(skip)]
271 pub diagnostic_item: Option<String>,
272}
273
274/// A filename.
275#[derive(
276 Debug,
277 PartialEq,
278 Eq,
279 Clone,
280 Hash,
281 PartialOrd,
282 Ord,
283 Serialize,
284 Deserialize,
285 Drive,
286 DriveMut,
287 DriveTwo,
288)]
289pub enum FileName {
290 /// A remapped path (namely paths into stdlib)
291 #[drive(skip)] // drive is not implemented for `PathBuf`
292 Virtual(PathBuf),
293 /// A local path (a file coming from the current crate for instance)
294 #[drive(skip)] // drive is not implemented for `PathBuf`
295 Local(PathBuf),
296 /// A "not real" file name (macro, query, etc.)
297 NotReal(String),
298}
299
300#[derive(
301 Debug,
302 PartialEq,
303 Eq,
304 Clone,
305 Hash,
306 PartialOrd,
307 Ord,
308 Serialize,
309 Deserialize,
310 Drive,
311 DriveMut,
312 DriveTwo,
313)]
314pub struct File {
315 /// The file identifier.
316 #[cfg_attr(feature = "charon_on_charon", charon::opaque)]
317 pub id: FileId,
318 /// The path to the file.
319 #[drive(skip)]
320 pub name: FileName,
321 /// Name of the crate this file comes from.
322 pub crate_name: String,
323 /// The contents of the source file, as seen by rustc at the time of translation.
324 /// Some files don't have contents.
325 pub contents: Option<String>,
326}