Skip to main content

charon_lib/ast/
names.rs

1//! Defines some utilities for the variables
2use crate::ast::*;
3use derive_generic_visitor::{Drive, DriveMut};
4use macros::{EnumAsGetters, EnumIsA};
5use serde_state::{DeserializeState, SerializeState};
6
7generate_index_type!(Disambiguator);
8
9/// See the comments for [Name]
10#[derive(
11    Debug,
12    Clone,
13    PartialEq,
14    Eq,
15    Hash,
16    SerializeState,
17    DeserializeState,
18    Drive,
19    DriveMut,
20    EnumIsA,
21    EnumAsGetters,
22)]
23#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("Pe"))]
24pub enum PathElem {
25    #[serde_state(stateless)]
26    Ident(#[drive(skip)] String, Disambiguator),
27    Impl(ImplElem),
28    /// This item was obtained by instantiating its parent with the given args. The binder binds
29    /// the parameters of the new items. If the binder binds nothing then this is a
30    /// monomorphization.
31    Instantiated(Box<Binder<GenericArgs>>),
32    /// This item is only available on the given target. Only appears in multi-target mode.
33    #[serde_state(stateless)]
34    Target(#[drive(skip)] TargetTriple),
35}
36
37/// There are two kinds of `impl` blocks:
38/// - impl blocks linked to a type ("inherent" impl blocks following Rust terminology):
39///   ```text
40///   impl<T> List<T> { ...}
41///   ```
42/// - trait impl blocks:
43///   ```text
44///   impl<T> PartialEq for List<T> { ...}
45///   ```
46/// We distinguish the two.
47#[derive(
48    Debug,
49    Clone,
50    PartialEq,
51    Eq,
52    Hash,
53    SerializeState,
54    DeserializeState,
55    Drive,
56    DriveMut,
57    EnumIsA,
58    EnumAsGetters,
59)]
60#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("ImplElem"))]
61pub enum ImplElem {
62    Ty(Box<Binder<Ty>>),
63    Trait(TraitImplId),
64}
65
66/// An item name/path
67///
68/// A name really is a list of strings. However, we sometimes need to
69/// introduce unique indices to disambiguate. This mostly happens because
70/// of "impl" blocks:
71///   ```text
72///   impl<T> List<T> {
73///     ...
74///   }
75///   ```
76///
77/// A type in Rust can have several "impl" blocks, and  those blocks can
78/// contain items with similar names. For this reason, we need to disambiguate
79/// them with unique indices. Rustc calls those "disambiguators". In rustc, this
80/// gives names like this:
81/// - `betree_main::betree::NodeIdCounter{impl#0}::new`
82/// - note that impl blocks can be nested, and macros sometimes generate
83///   weird names (which require disambiguation):
84///   `betree_main::betree_utils::_#1::{impl#0}::deserialize::{impl#0}`
85///
86/// Finally, the paths used by rustc are a lot more precise and explicit than
87/// those we expose in LLBC: for instance, every identifier belongs to a specific
88/// namespace (value namespace, type namespace, etc.), and is coupled with a
89/// disambiguator.
90///
91/// On our side, we want to stay high-level and simple: we use string identifiers
92/// as much as possible, insert disambiguators only when necessary (for instance
93/// when we find an "impl" block or when two loaded crates have the same name)
94/// and check that the disambiguator is useless in the other situations (i.e.,
95/// the disambiguator is always equal to 0).
96///
97/// Moreover, the items are uniquely disambiguated by their (integer) ids
98/// (`TypeDeclId`, etc.), and when extracting the code we have to deal with
99/// name clashes anyway. Still, we might want to be more precise in the future.
100///
101/// Also note that the first path element in the name is always the crate name.
102#[derive(
103    Debug, Default, Clone, PartialEq, Eq, Hash, SerializeState, DeserializeState, Drive, DriveMut,
104)]
105#[serde(transparent)]
106#[cfg_attr(feature = "charon_on_charon", charon::transparent)]
107pub struct Name {
108    pub name: Vec<PathElem>,
109}