Skip to main content

charon_lib/transform/simplify_output/
hide_allocator_param.rs

1use derive_generic_visitor::*;
2use itertools::Itertools;
3use std::collections::HashSet;
4
5use crate::{ast::*, name_matcher::NamePattern};
6
7use crate::transform::{TransformCtx, ctx::TransformPass};
8
9#[derive(Visitor)]
10struct RemoveLastParamVisitor {
11    types: HashSet<TypeId>,
12}
13
14impl VisitAstMut for RemoveLastParamVisitor {
15    fn enter_type_decl_ref(&mut self, x: &mut TypeDeclRef) {
16        if self.types.contains(&x.id) {
17            // Remove the last param.
18            x.generics.types.pop();
19        }
20    }
21}
22
23pub struct Transform;
24impl TransformPass for Transform {
25    fn transform_ctx(&self, ctx: &mut TransformCtx) {
26        if !ctx.options.hide_allocator {
27            return;
28        }
29        let types = &[
30            "alloc::boxed::Box",
31            "alloc::vec::Vec",
32            "alloc::rc::Rc",
33            "alloc::sync::Arc",
34        ];
35
36        let types: Vec<NamePattern> = types
37            .iter()
38            .map(|s| NamePattern::parse(s).unwrap())
39            .collect_vec();
40        let types: HashSet<TypeId> = ctx
41            .translated
42            .item_names
43            .iter()
44            .filter(|(_, name)| types.iter().any(|p| p.matches(&ctx.translated, name)))
45            .filter_map(|(id, _)| id.as_type())
46            .copied()
47            .map(TypeId::Adt)
48            .chain([TypeId::Builtin(BuiltinTy::Box)])
49            .collect();
50
51        for &id in &types {
52            if let Some(&id) = id.as_adt()
53                && let Some(tdecl) = ctx.translated.type_decls.get_mut(id)
54            {
55                if tdecl.generics.types.is_empty() {
56                    // We monomorpohized this type.
57                    let args = tdecl.item_meta.name.mono_args_mut().unwrap();
58                    args.types.pop().unwrap();
59                } else {
60                    struct SubstWithErrorVisitor(TypeVarId);
61                    impl VarsVisitor for SubstWithErrorVisitor {
62                        fn visit_type_var(&mut self, v: TypeDbVar) -> Option<Ty> {
63                            if let DeBruijnVar::Bound(DeBruijnId::ZERO, var_id) = v
64                                && var_id == self.0
65                            {
66                                Some(
67                                    TyKind::Error("removed allocator parameter".to_owned())
68                                        .into_ty(),
69                                )
70                            } else {
71                                None
72                            }
73                        }
74                    }
75                    let tvar = tdecl.generics.types.pop().unwrap();
76                    tdecl.visit_vars(&mut SubstWithErrorVisitor(tvar.index));
77                }
78            }
79        }
80
81        let _ = ctx
82            .translated
83            .drive_mut(&mut RemoveLastParamVisitor { types });
84    }
85}