charon_lib/transform/add_missing_info/
add_missing_alias_clauses.rs1use derive_generic_visitor::*;
5
6use crate::ast::*;
7use crate::transform::{TransformCtx, ctx::TransformPass};
8
9#[derive(Visitor)]
10struct ClauseExtractor<'a> {
11 params: &'a mut GenericParams,
12 span: Span,
13 binder_stack: BindingStack<GenericParams>,
14}
15
16impl<'a> ClauseExtractor<'a> {
17 fn new(params: &'a mut GenericParams, span: Span) -> Self {
18 Self {
19 binder_stack: BindingStack::new(params.clone()),
20 params,
21 span,
22 }
23 }
24
25 fn extract_trait_clause(&self, mut trait_: PolyTraitDeclRef) -> Option<PolyTraitDeclRef> {
28 let mut scope_regions = Vec::new();
31 for (dbid, params) in self.binder_stack.iter_enumerated().rev().skip(1) {
32 for (old_id, region) in params.regions.iter_enumerated() {
33 let new_id = trait_.regions.push_with(|index| {
34 let mut region = region.clone();
35 region.index = index;
36 region
37 });
38 scope_regions.push((dbid, old_id, new_id));
39 }
40 }
41
42 if !scope_regions.is_empty() {
43 #[derive(Visitor)]
45 struct MoveRegionsToHrtb {
46 binder_depth: DeBruijnId,
47 scope_regions: Vec<(DeBruijnId, RegionId, RegionId)>,
48 }
49
50 impl VisitorWithBinderDepth for MoveRegionsToHrtb {
51 fn binder_depth_mut(&mut self) -> &mut DeBruijnId {
52 &mut self.binder_depth
53 }
54 }
55
56 impl VisitAstMut for MoveRegionsToHrtb {
57 fn visit<T: AstVisitable>(&mut self, x: &mut T) -> ControlFlow<Self::Break> {
58 VisitWithBinderDepth::new(self).visit(x)
59 }
60
61 fn enter_region(&mut self, region: &mut Region) {
62 let Region::Var(var) = region else {
63 return;
64 };
65 let DeBruijnVar::Bound(dbid, old_id) = *var else {
66 return;
67 };
68 let Some(outer_depth) = dbid.sub(self.binder_depth.incr()) else {
69 return;
70 };
71 let Some((_, _, new_id)) = self
72 .scope_regions
73 .iter()
74 .find(|(dbid, id, _)| *dbid == outer_depth && *id == old_id)
75 else {
76 return;
77 };
78 *var = DeBruijnVar::bound(self.binder_depth, *new_id);
79 }
80 }
81
82 MoveRegionsToHrtb {
83 binder_depth: DeBruijnId::zero(),
84 scope_regions,
85 }
86 .visit(&mut trait_.skip_binder);
87 }
88
89 trait_.move_from_under_binders(self.binder_stack.depth())
90 }
91}
92
93impl VisitorWithBinderStack for ClauseExtractor<'_> {
94 fn binder_stack_mut(&mut self) -> &mut BindingStack<GenericParams> {
95 &mut self.binder_stack
96 }
97}
98
99impl VisitAstMut for ClauseExtractor<'_> {
100 fn visit<T: AstVisitable>(&mut self, x: &mut T) -> ControlFlow<Self::Break> {
101 VisitWithBinderStack::new(self).visit(x)
102 }
103
104 fn exit_trait_ref_contents(&mut self, tref: &mut TraitRefContents) {
105 if matches!(tref.kind, TraitRefKind::Unknown(_))
106 && let Some(trait_) = self.extract_trait_clause(tref.trait_decl_ref.clone())
107 {
108 let clause_id = self.params.trait_clauses.push_with(|clause_id| TraitParam {
109 clause_id,
110 span: Some(self.span),
111 origin: PredicateOrigin::WhereClauseOnType,
112 trait_,
113 });
114 tref.kind =
115 TraitRefKind::Clause(DeBruijnVar::bound(self.binder_stack.depth(), clause_id));
116 }
117 }
118}
119
120pub struct Transform;
121impl TransformPass for Transform {
122 fn transform_ctx(&self, ctx: &mut TransformCtx) {
123 for tdecl in &mut ctx.translated.type_decls {
124 if let TypeDeclKind::Alias(ty) = &mut tdecl.kind {
125 ClauseExtractor::new(&mut tdecl.generics, tdecl.item_meta.span).visit(ty);
126 }
127 }
128 }
129}