charon_lib/transform/lift_associated_item_clauses.rs
1//! Move clauses on associated types to be parent clauses. The distinction is not semantically
2//! meaningful. We should ideally to this directly when translating but this is currently
3//! difficult; instead we do this as a post-processing pass.
4use std::collections::HashMap;
5use std::mem;
6
7use crate::{ast::*, ids::Vector};
8
9use super::{ctx::TransformPass, TransformCtx};
10
11pub struct Transform;
12impl TransformPass for Transform {
13 fn transform_ctx(&self, ctx: &mut TransformCtx) {
14 // For each trait, we move the item-local clauses to be top-level parent clauses, and
15 // record the mapping from the old to the new ids.
16 let trait_item_clause_ids: Vector<
17 TraitDeclId,
18 HashMap<TraitItemName, Vector<TraitClauseId, TraitClauseId>>,
19 > = ctx.translated.trait_decls.map_ref_mut(|decl| {
20 mem::take(&mut decl.type_clauses)
21 .into_iter()
22 .map(|(name, clauses)| {
23 let id_map = clauses.map(|mut clause| {
24 decl.parent_clauses.push_with(|id| {
25 clause.clause_id = id;
26 clause
27 })
28 });
29 (name, id_map)
30 })
31 .collect()
32 });
33
34 // Move the item-local trait refs to match what we did in the trait declarations.
35 for timpl in ctx.translated.trait_impls.iter_mut() {
36 for (_, refs) in mem::take(&mut timpl.type_clauses) {
37 for trait_ref in refs {
38 // Note: this assumes that we listed the types in the same order as in the trait
39 // decl, which we do.
40 timpl.parent_trait_refs.push(trait_ref);
41 }
42 }
43 }
44
45 // Update trait refs.
46 ctx.translated.dyn_visit_mut(|trkind: &mut TraitRefKind| {
47 use TraitRefKind::*;
48 match trkind {
49 ItemClause(..) => take_mut::take(trkind, |trkind| {
50 let ItemClause(trait_ref, trait_decl, item_name, item_clause_id) = trkind
51 else {
52 unreachable!()
53 };
54 let new_id = (|| {
55 let new_id = *trait_item_clause_ids
56 .get(trait_decl)?
57 .get(&item_name)?
58 .get(item_clause_id)?;
59 Some(new_id)
60 })();
61 match new_id {
62 Some(new_id) => ParentClause(trait_ref, trait_decl, new_id),
63 None => ItemClause(trait_ref, trait_decl, item_name, item_clause_id),
64 }
65 }),
66 BuiltinOrAuto {
67 parent_trait_refs,
68 types,
69 ..
70 } => {
71 for (_, _, ty_trait_refs) in types {
72 for tref in std::mem::take(ty_trait_refs) {
73 // Note: this assumes that we listed the types in the same order as in
74 // the trait decl, which we do.
75 parent_trait_refs.push(tref);
76 }
77 }
78 }
79 _ => {}
80 }
81 });
82 }
83}