Skip to main content

charon_lib/transform/
utils.rs

1use crate::ast::*;
2use crate::formatter::{AstFormatter, FmtCtx};
3use crate::pretty::FmtWithCtx;
4use derive_generic_visitor::*;
5use macros::EnumIsA;
6use std::fmt::{self, Debug};
7
8/// Each `GenericArgs` is meant for a corresponding `GenericParams`; this describes which one.
9#[derive(Debug, Clone, Eq, PartialEq, Hash, EnumIsA, Drive, DriveMut)]
10pub enum GenericsSource {
11    /// A top-level item.
12    Item(ItemId),
13    /// A trait method.
14    Method(TraitDeclId, TraitMethodId),
15    /// A trait associated type.
16    TraitType(TraitDeclId, AssocTypeId),
17    /// A builtin item like `Box`.
18    Builtin,
19    /// Some other use of generics outside the main Charon ast.
20    Other,
21}
22
23impl GenericsSource {
24    pub fn item<I: Into<ItemId>>(id: I) -> Self {
25        Self::Item(id.into())
26    }
27
28    /// Return a path that represents the target item.
29    pub fn item_name(&self, translated: &TranslatedCrate, fmt_ctx: &FmtCtx) -> String {
30        match self {
31            GenericsSource::Item(id) => translated.item_name(*id).to_string_with_ctx(fmt_ctx),
32            GenericsSource::Method(trait_id, method_name) => format!(
33                "{}::{method_name}",
34                translated.item_name(*trait_id).to_string_with_ctx(fmt_ctx),
35            ),
36            GenericsSource::TraitType(trait_id, type_id) => {
37                let type_name =
38                    fmt::from_fn(|f| fmt_ctx.format_assoc_type_name(f, *trait_id, *type_id));
39                format!(
40                    "{}::{type_name}",
41                    translated.item_name(*trait_id).to_string_with_ctx(fmt_ctx),
42                )
43            }
44            GenericsSource::Builtin => "<built-in>".to_string(),
45            GenericsSource::Other => "<unknown>".to_string(),
46        }
47    }
48}
49
50impl TypeId {
51    pub fn generics_target(&self) -> GenericsSource {
52        match *self {
53            TypeId::Adt(decl_id) => GenericsSource::item(decl_id),
54            TypeId::Tuple | TypeId::Builtin(..) => GenericsSource::Builtin,
55        }
56    }
57}
58impl FunId {
59    pub fn generics_target(&self) -> GenericsSource {
60        match *self {
61            FunId::Regular(fun_id) => GenericsSource::item(fun_id),
62            FunId::Builtin(..) => GenericsSource::Builtin,
63        }
64    }
65}
66impl FnPtrKind {
67    pub fn generics_target(&self) -> GenericsSource {
68        match self {
69            FnPtrKind::Fun(fun_id) => fun_id.generics_target(),
70            FnPtrKind::Trait(trait_ref, name) => {
71                GenericsSource::Method(trait_ref.trait_decl_ref.skip_binder.id, *name)
72            }
73        }
74    }
75}