Skip to main content

charon_lib/ast/
names_utils.rs

1//! Defines some utilities for [crate::names]
2//!
3//! For now, we have one function per object kind (type, trait, function,
4//! module): many of them could be factorized (will do).
5use crate::ast::*;
6
7impl PathElem {
8    fn equals_ident(&self, id: &str) -> bool {
9        match self {
10            PathElem::Ident(s, d) => s == id && d.is_zero(),
11            _ => false,
12        }
13    }
14
15    pub fn as_monomorphized(&self) -> Option<&GenericArgs> {
16        let binder = self.as_instantiated()?;
17        binder.params.is_empty().then_some(&binder.skip_binder)
18    }
19    pub fn as_monomorphized_mut(&mut self) -> Option<&mut GenericArgs> {
20        let binder = self.as_instantiated_mut()?;
21        binder.params.is_empty().then_some(&mut binder.skip_binder)
22    }
23    pub fn is_monomorphized(&self) -> bool {
24        self.as_monomorphized().is_some()
25    }
26}
27
28impl Name {
29    /// Convert a path like `["std", "alloc", "Box"]` to a name. Needed on occasion when crafting
30    /// names that were not present in the original code.
31    pub fn from_path(path: &[&str]) -> Name {
32        Name {
33            name: path
34                .iter()
35                .map(|elem| PathElem::Ident(elem.to_string(), Disambiguator::ZERO))
36                .collect(),
37        }
38    }
39
40    #[allow(clippy::len_without_is_empty)]
41    pub fn len(&self) -> usize {
42        self.name.len()
43    }
44
45    /// If this item comes from monomorphization, return the arguments used.
46    pub fn mono_args(&self) -> Option<&GenericArgs> {
47        self.name.last()?.as_monomorphized()
48    }
49    /// If this item comes from monomorphization, return the arguments used.
50    pub fn mono_args_mut(&mut self) -> Option<&mut GenericArgs> {
51        self.name.last_mut()?.as_monomorphized_mut()
52    }
53
54    /// Strip the trailing `PathElem::Target` from a name, if any.
55    pub fn strip_target_suffix(&self) -> Option<(Name, TargetTriple)> {
56        match self.name.last() {
57            Some(PathElem::Target(target)) => {
58                let target = target.clone();
59                let mut base = self.clone();
60                base.name.pop();
61                Some((base, target))
62            }
63            _ => None,
64        }
65    }
66
67    /// Compare the name to a constant array.
68    /// This ignores disambiguators.
69    ///
70    /// `equal`: if `true`, check that the name is equal to the ref. If `false`:
71    /// only check if the ref is a prefix of the name.
72    pub fn compare_with_ref_name(&self, equal: bool, ref_name: &[&str]) -> bool {
73        let name: Vec<&PathElem> = self.name.iter().filter(|e| e.is_ident()).collect();
74
75        if name.len() < ref_name.len() || (equal && name.len() != ref_name.len()) {
76            return false;
77        }
78
79        for i in 0..ref_name.len() {
80            if !name[i].equals_ident(ref_name[i]) {
81                return false;
82            }
83        }
84        true
85    }
86
87    /// Compare the name to a constant array.
88    /// This ignores disambiguators.
89    pub fn equals_ref_name(&self, ref_name: &[&str]) -> bool {
90        self.compare_with_ref_name(true, ref_name)
91    }
92
93    /// Created an instantiated version of this name by putting a `PathElem::Instantiated` last. If
94    /// the item was already instantiated, this merges the two instantiations.
95    pub fn instantiate(mut self, binder: Binder<GenericArgs>) -> Self {
96        if let [.., PathElem::Instantiated(box x)] = self.name.as_mut_slice() {
97            // Put the new args in place; the params are what we want but the args are wrong.
98            let old_args = std::mem::replace(x, binder);
99            // Apply the new args to the old binder to get correct args.
100            x.skip_binder = old_args.apply(&x.skip_binder);
101        } else {
102            self.name.push(PathElem::Instantiated(Box::new(binder)));
103        }
104        self
105    }
106
107    /// Get the last identifier of the name, if any. This is useful for error messages and such.
108    /// Panics if the name is empty or if the last element is not an identifier.
109    pub fn short_str(&self) -> &String {
110        self.name.last().unwrap().as_ident().unwrap().0
111    }
112}