1use super::translate_ctx::*;
2use charon_lib::ast::*;
3use charon_lib::formatter::IntoFormatter;
4use charon_lib::meta::ItemMeta;
5use charon_lib::pretty::FmtWithCtx;
6use charon_lib::ullbc_ast as ast;
7use hax_frontend_exporter as hax;
8use indexmap::IndexMap;
9use itertools::Itertools;
10use std::mem;
11use std::sync::Arc;
12
13pub(crate) enum PredicateLocation {
16 Parent,
18 Item(TraitItemName),
20 Base,
22}
23
24impl<'tcx, 'ctx> TranslateCtx<'tcx> {
25 pub(crate) fn translate_trait_item_name(
27 &mut self,
28 def_id: &hax::DefId,
29 ) -> Result<TraitItemName, Error> {
30 let name = self.hax_def_id_to_name(def_id)?;
32 let (name, id) = name.name.last().unwrap().as_ident().unwrap();
33 assert!(id.is_zero());
34 Ok(TraitItemName(name.to_string()))
35 }
36}
37
38impl ItemTransCtx<'_, '_> {
39 #[tracing::instrument(skip(self, item_meta))]
40 pub fn translate_trait_decl(
41 mut self,
42 def_id: TraitDeclId,
43 item_meta: ItemMeta,
44 def: &hax::FullDef,
45 ) -> Result<TraitDecl, Error> {
46 trace!("About to translate trait decl:\n{:?}", def.def_id);
47 trace!("Trait decl id:\n{:?}", def_id);
48
49 let span = item_meta.span;
50
51 if let hax::FullDefKind::TraitAlias { .. } = def.kind() {
52 raise_error!(self, span, "Trait aliases are not supported");
53 }
54
55 let hax::FullDefKind::Trait { items, .. } = &def.kind else {
56 raise_error!(self, span, "Unexpected definition: {def:?}");
57 };
58 let items: Vec<(TraitItemName, &hax::AssocItem, Arc<hax::FullDef>)> = items
59 .iter()
60 .map(|(item, def)| {
61 let name = TraitItemName(item.name.clone());
62 (name, item, def.clone())
63 })
64 .collect_vec();
65
66 self.translate_def_generics(span, def)?;
71
72 let mut consts = Vec::new();
75 let mut const_defaults = IndexMap::new();
76 let mut types = Vec::new();
77 let mut type_clauses = Vec::new();
78 let mut type_defaults = IndexMap::new();
79 let mut methods = Vec::new();
80 for (item_name, hax_item, hax_def) in &items {
81 let item_def_id = &hax_item.def_id;
82 let item_span = self.def_span(item_def_id);
83 match &hax_def.kind {
84 hax::FullDefKind::AssocFn { .. } => {
85 let fun_def = self.t_ctx.hax_def(item_def_id)?;
86 let binder_kind = BinderKind::TraitMethod(def_id, item_name.clone());
87 let fn_ref = self.translate_binder_for_def(
88 item_span,
89 binder_kind,
90 &fun_def,
91 |bt_ctx| {
92 let fun_id = if bt_ctx.t_ctx.options.translate_all_methods
100 || item_meta.opacity.is_transparent()
101 || !hax_item.has_value
102 {
103 bt_ctx.register_fun_decl_id(item_span, item_def_id)
104 } else {
105 bt_ctx.register_fun_decl_id_no_enqueue(item_span, item_def_id)
106 };
107
108 assert_eq!(bt_ctx.binding_levels.len(), 2);
110 let fun_generics = bt_ctx
111 .outermost_binder()
112 .params
113 .identity_args_at_depth(
114 GenericsSource::item(def_id),
115 DeBruijnId::one(),
116 )
117 .concat(
118 GenericsSource::item(fun_id),
119 &bt_ctx.innermost_binder().params.identity_args_at_depth(
120 GenericsSource::Method(def_id.into(), item_name.clone()),
121 DeBruijnId::zero(),
122 ),
123 );
124 Ok(FunDeclRef {
125 id: fun_id,
126 generics: fun_generics,
127 })
128 },
129 )?;
130 methods.push((item_name.clone(), fn_ref));
131 }
132 hax::FullDefKind::AssocConst { ty, .. } => {
133 if hax_item.has_value {
135 let id = self.register_global_decl_id(item_span, item_def_id);
138 let generics_target = GenericsSource::item(id);
139 let gref = GlobalDeclRef {
140 id,
141 generics: self.the_only_binder().params.identity_args(generics_target),
142 };
143 const_defaults.insert(item_name.clone(), gref);
144 };
145 let ty = self.translate_ty(item_span, ty)?;
146 consts.push((item_name.clone(), ty));
147 }
148 hax::FullDefKind::AssocTy { param_env, .. }
149 if !param_env.generics.params.is_empty() =>
150 {
151 raise_error!(
152 self,
153 item_span,
154 "Generic associated types are not supported"
155 );
156 }
157 hax::FullDefKind::AssocTy { value, .. } => {
158 if let Some(clauses) = self.item_trait_clauses.get(item_name) {
160 type_clauses.push((item_name.clone(), clauses.clone()));
161 }
162 if let Some(ty) = value {
163 let ty = self.translate_ty(item_span, &ty)?;
164 type_defaults.insert(item_name.clone(), ty);
165 };
166 types.push(item_name.clone());
167 }
168 _ => panic!("Unexpected definition for trait item: {hax_def:?}"),
169 }
170 }
171
172 Ok(ast::TraitDecl {
176 def_id,
177 item_meta,
178 parent_clauses: mem::take(&mut self.parent_trait_clauses),
179 generics: self.into_generics(),
180 type_clauses,
181 consts,
182 const_defaults,
183 types,
184 type_defaults,
185 methods,
186 })
187 }
188
189 #[tracing::instrument(skip(self, item_meta))]
190 pub fn translate_trait_impl(
191 mut self,
192 def_id: TraitImplId,
193 item_meta: ItemMeta,
194 def: &hax::FullDef,
195 ) -> Result<TraitImpl, Error> {
196 trace!("About to translate trait impl:\n{:?}", def.def_id);
197 trace!("Trait impl id:\n{:?}", def_id);
198
199 let span = item_meta.span;
200
201 self.translate_def_generics(span, def)?;
202
203 let hax::FullDefKind::TraitImpl {
204 trait_pred,
205 implied_impl_exprs,
206 items: impl_items,
207 ..
208 } = &def.kind
209 else {
210 unreachable!()
211 };
212
213 let implemented_trait_id = &trait_pred.trait_ref.def_id;
215 let trait_id = self.register_trait_decl_id(span, implemented_trait_id);
216 let implemented_trait = {
217 let implemented_trait = &trait_pred.trait_ref;
218 let generics = self.translate_generic_args(
219 span,
220 &implemented_trait.generic_args,
221 &[],
222 None,
223 GenericsSource::item(trait_id),
224 )?;
225 TraitDeclRef { trait_id, generics }
226 };
227
228 let parent_trait_refs = self.translate_trait_impl_exprs(span, &implied_impl_exprs)?;
230
231 {
232 let ctx = self.into_fmt();
234 let refs = parent_trait_refs
235 .iter()
236 .map(|c| c.fmt_with_ctx(&ctx))
237 .collect::<Vec<String>>()
238 .join("\n");
239 trace!(
240 "Trait impl: {:?}\n- parent_trait_refs:\n{}",
241 def.def_id,
242 refs
243 );
244 }
245
246 let mut consts = Vec::new();
248 let mut types: Vec<(TraitItemName, Ty)> = Vec::new();
249 let mut methods = Vec::new();
250 let mut type_clauses = Vec::new();
251
252 for impl_item in impl_items {
253 use hax::ImplAssocItemValue::*;
254 let name = TraitItemName(impl_item.name.clone());
255 let item_def = impl_item.def(); let item_span = self.def_span(&item_def.def_id);
257 let item_def_id = &item_def.def_id;
258 match item_def.kind() {
259 hax::FullDefKind::AssocFn { .. } => {
260 match &impl_item.value {
261 Provided { is_override, .. } => {
262 let fun_def = self.t_ctx.hax_def(item_def_id)?;
263 let binder_kind = BinderKind::TraitMethod(trait_id, name.clone());
264 let fn_ref = self.translate_binder_for_def(
265 item_span,
266 binder_kind,
267 &fun_def,
268 |bt_ctx| {
269 let fun_id = if bt_ctx.t_ctx.options.translate_all_methods
276 || item_meta.opacity.is_transparent()
277 || !*is_override
278 {
279 bt_ctx.register_fun_decl_id(item_span, item_def_id)
280 } else {
281 bt_ctx
282 .register_fun_decl_id_no_enqueue(item_span, item_def_id)
283 };
284
285 assert_eq!(bt_ctx.binding_levels.len(), 2);
287 let fun_generics = bt_ctx
288 .outermost_binder()
289 .params
290 .identity_args_at_depth(
291 GenericsSource::item(def_id),
292 DeBruijnId::one(),
293 )
294 .concat(
295 GenericsSource::item(fun_id),
296 &bt_ctx
297 .innermost_binder()
298 .params
299 .identity_args_at_depth(
300 GenericsSource::Method(
301 trait_id.into(),
302 name.clone(),
303 ),
304 DeBruijnId::zero(),
305 ),
306 );
307 Ok(FunDeclRef {
308 id: fun_id,
309 generics: fun_generics,
310 })
311 },
312 )?;
313 methods.push((name, fn_ref));
314 }
315 DefaultedFn { .. } => {
316 }
318 _ => unreachable!(),
319 }
320 }
321 hax::FullDefKind::AssocConst { .. } => {
322 let id = self.register_global_decl_id(item_span, item_def_id);
323 let generics_target = GenericsSource::item(id);
324 let generics = match &impl_item.value {
327 Provided { .. } => {
328 self.the_only_binder().params.identity_args(generics_target)
329 }
330 _ => implemented_trait
331 .generics
332 .clone()
333 .with_target(generics_target),
334 };
335 let gref = GlobalDeclRef { id, generics };
336 consts.push((name, gref));
337 }
338 hax::FullDefKind::AssocTy { param_env, .. }
339 if !param_env.generics.params.is_empty() =>
340 {
341 }
343 hax::FullDefKind::AssocTy { value, .. } => {
344 let ty = match &impl_item.value {
345 Provided { .. } => value.as_ref().unwrap(),
346 DefaultedTy { ty, .. } => ty,
347 _ => unreachable!(),
348 };
349 let ty = self.translate_ty(item_span, &ty)?;
350 types.push((name.clone(), ty));
351
352 let trait_refs =
353 self.translate_trait_impl_exprs(item_span, &impl_item.required_impl_exprs)?;
354 type_clauses.push((name, trait_refs));
355 }
356 _ => panic!("Unexpected definition for trait item: {item_def:?}"),
357 }
358 }
359
360 Ok(ast::TraitImpl {
361 def_id,
362 item_meta,
363 impl_trait: implemented_trait,
364 generics: self.into_generics(),
365 parent_trait_refs,
366 type_clauses,
367 consts,
368 types,
369 methods,
370 })
371 }
372}