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