charon_lib/transform/
remove_unused_self_clause.rs1use derive_generic_visitor::*;
5use std::collections::HashSet;
6
7use crate::ast::*;
8
9use super::{ctx::TransformPass, TransformCtx};
10
11struct FoundClause;
12
13struct UsesClauseVisitor(TraitClauseId);
14impl Visitor for UsesClauseVisitor {
15 type Break = FoundClause;
16}
17
18impl VisitAst for UsesClauseVisitor {
20 fn visit_trait_clause_id(&mut self, x: &TraitClauseId) -> ControlFlow<Self::Break> {
21 if *x == self.0 {
22 Break(FoundClause)
23 } else {
24 Continue(())
25 }
26 }
27 fn visit_trait_clause(&mut self, _: &TraitClause) -> ControlFlow<Self::Break> {
28 Continue(())
31 }
32 fn visit_fun_decl(&mut self, x: &FunDecl) -> ControlFlow<Self::Break> {
33 if let Err(Opaque) = x.body {
34 return Break(FoundClause);
37 }
38 self.visit_inner(x)
39 }
40}
41
42pub struct Transform;
43impl TransformPass for Transform {
44 fn transform_ctx(&self, ctx: &mut TransformCtx) {
45 if !ctx.options.remove_unused_self_clauses {
46 return;
47 }
48 let self_clause_id = TraitClauseId::from_raw(0);
49 let mut doesnt_use_self: HashSet<AnyTransId> = Default::default();
50
51 for tdecl in &ctx.translated.trait_decls {
54 let methods = tdecl.methods().map(|(_, bound_fn)| bound_fn.skip_binder.id);
55 let consts = tdecl
57 .const_defaults
58 .iter()
59 .filter_map(|(_, x)| ctx.translated.global_decls.get(x.id))
60 .map(|gdecl| gdecl.init);
61 let funs = methods
62 .chain(consts)
63 .filter_map(|id: FunDeclId| ctx.translated.fun_decls.get(id));
64 for fun in funs {
65 match fun.drive(&mut UsesClauseVisitor(self_clause_id)) {
66 Continue(()) => {
67 doesnt_use_self.insert(fun.def_id.into());
68 if let Some(gid) = fun.is_global_initializer {
69 doesnt_use_self.insert(gid.into());
70 }
71 }
72 Break(FoundClause) => {}
73 }
74 }
75 }
76
77 for &id in &doesnt_use_self {
79 let Some(mut item) = ctx.translated.get_item_mut(id) else {
80 continue;
81 };
82 item.generic_params()
83 .trait_clauses
84 .remove_and_shift_ids(self_clause_id);
85 item.dyn_visit_mut(|clause_id: &mut TraitClauseId| {
86 *clause_id = TraitClauseId::from_usize(clause_id.index() - 1);
87 });
88 }
89
90 ctx.translated.dyn_visit_mut(|args: &mut GenericArgs| {
92 if let GenericsSource::Item(target_id) = args.target
93 && doesnt_use_self.contains(&target_id)
94 {
95 args.trait_refs.remove_and_shift_ids(self_clause_id);
96 }
97 });
98 }
99}