1use super::translate_ctx::*;
2use charon_lib::ast::*;
3use charon_lib::ids::IndexMap;
4use rustc_span::{kw, sym};
5
6impl<'tcx> TranslateCtx<'tcx> {
7 pub fn recognize_builtin_impl(
8 &self,
9 trait_data: &hax::BuiltinTraitData,
10 trait_def: &hax::FullDef,
11 ) -> Option<BuiltinImplData> {
12 Some(match trait_data {
13 hax::BuiltinTraitData::Destruct(x) => {
14 match x {
15 hax::DestructData::Noop => BuiltinImplData::NoopDestruct,
16 hax::DestructData::Implicit => BuiltinImplData::UntrackedDestruct,
17 hax::DestructData::Glue { .. } => return None,
19 }
20 }
21 hax::BuiltinTraitData::Other => match &trait_def.lang_item {
22 _ if self
23 .tcx
24 .trait_is_auto(trait_def.def_id().real_rust_def_id()) =>
25 {
26 BuiltinImplData::Auto
27 }
28 None => return None,
29 Some(litem) => match *litem {
30 sym::sized => BuiltinImplData::Sized,
31 sym::meta_sized => BuiltinImplData::MetaSized,
32 sym::tuple_trait => BuiltinImplData::Tuple,
33 kw::Fn => BuiltinImplData::Fn,
34 sym::fn_mut => BuiltinImplData::FnMut,
35 sym::fn_once => BuiltinImplData::FnOnce,
36 sym::pointee_trait => BuiltinImplData::Pointee,
37 sym::clone => BuiltinImplData::Clone,
38 sym::copy => BuiltinImplData::Copy,
39 sym::discriminant_kind => BuiltinImplData::DiscriminantKind,
40 _ => return None,
41 },
42 },
43 })
44 }
45}
46
47impl<'tcx, 'ctx> ItemTransCtx<'tcx, 'ctx> {
48 pub(crate) fn register_predicates(
54 &mut self,
55 preds: &hax::GenericPredicates,
56 origin: PredicateOrigin,
57 ) -> Result<(), Error> {
58 self.translate_predicates(preds, origin, None)?;
59 Ok(())
60 }
61
62 pub(crate) fn translate_predicates(
65 &mut self,
66 preds: &hax::GenericPredicates,
67 origin: PredicateOrigin,
68 mut trait_clauses: Option<&mut IndexMap<TraitClauseId, TraitParam>>,
70 ) -> Result<(), Error> {
71 if trait_clauses.is_none() {
72 let next_clause_id = self.innermost_generics_mut().trait_clauses.next_id();
77 for (i, pred) in preds
78 .predicates
79 .iter()
80 .filter(|pred| {
81 matches!(
82 pred.clause.kind.hax_skip_binder_ref(),
83 hax::ClauseKind::Trait(_)
84 )
85 })
86 .enumerate()
87 {
88 self.innermost_binder_mut()
89 .trait_preds
90 .insert(pred.id.clone(), next_clause_id + i);
91 }
92 }
93
94 for pred in &preds.predicates {
95 self.translate_predicate(pred, origin.clone(), trait_clauses.as_deref_mut())?;
96 }
97 Ok(())
98 }
99
100 pub(crate) fn translate_poly_trait_ref(
101 &mut self,
102 span: Span,
103 bound_trait_ref: &hax::Binder<hax::TraitRef>,
104 ) -> Result<PolyTraitDeclRef, Error> {
105 self.translate_region_binder(span, bound_trait_ref, move |ctx, trait_ref| {
106 ctx.translate_trait_ref(span, trait_ref)
107 })
108 }
109
110 pub(crate) fn translate_poly_trait_predicate(
111 &mut self,
112 span: Span,
113 bound_trait_ref: &hax::Binder<hax::TraitPredicate>,
114 ) -> Result<PolyTraitDeclRef, Error> {
115 self.translate_region_binder(span, bound_trait_ref, move |ctx, trait_ref| {
116 ctx.translate_trait_predicate(span, trait_ref)
117 })
118 }
119
120 pub(crate) fn translate_trait_predicate(
121 &mut self,
122 span: Span,
123 trait_pred: &hax::TraitPredicate,
124 ) -> Result<TraitDeclRef, Error> {
125 assert!(trait_pred.is_positive);
127 self.translate_trait_ref(span, &trait_pred.trait_ref)
128 }
129
130 pub(crate) fn translate_trait_ref(
131 &mut self,
132 span: Span,
133 trait_ref: &hax::TraitRef,
134 ) -> Result<TraitDeclRef, Error> {
135 self.translate_trait_decl_ref(span, trait_ref)
136 }
137
138 pub(crate) fn translate_predicate(
139 &mut self,
140 pred: &hax::GenericPredicate,
141 origin: PredicateOrigin,
142 mut trait_clauses: Option<&mut IndexMap<TraitClauseId, TraitParam>>,
144 ) -> Result<(), Error> {
145 use hax::ClauseKind;
146 let clause = &pred.clause;
147 trace!("{:?}", clause);
148 let span = self.translate_span(&pred.span);
149 match clause.kind.hax_skip_binder_ref() {
150 ClauseKind::Trait(trait_pred) => {
151 let trait_pred = self.translate_region_binder(span, &clause.kind, |ctx, _| {
152 ctx.translate_trait_predicate(span, trait_pred)
153 })?;
154 let clause_id = trait_clauses
155 .as_deref_mut()
156 .unwrap_or(&mut self.innermost_generics_mut().trait_clauses)
157 .push_with(|clause_id| TraitParam {
158 clause_id,
159 origin,
160 span: Some(span),
161 trait_: trait_pred,
162 });
163
164 if trait_clauses.is_none() {
165 let expected_clause_id = self
167 .innermost_binder_mut()
168 .trait_preds
169 .get(&pred.id)
170 .unwrap();
171 debug_assert_eq!(clause_id, *expected_clause_id);
172 }
173 }
174 ClauseKind::RegionOutlives(p) => {
175 let pred = self.translate_region_binder(span, &clause.kind, |ctx, _| {
176 let r0 = ctx.translate_region(span, &p.lhs)?;
177 let r1 = ctx.translate_region(span, &p.rhs)?;
178 Ok(OutlivesPred(r0, r1))
179 })?;
180 self.innermost_generics_mut().regions_outlive.push(pred);
181 }
182 ClauseKind::TypeOutlives(p) => {
183 let pred = self.translate_region_binder(span, &clause.kind, |ctx, _| {
184 let ty = ctx.translate_ty(span, &p.lhs)?;
185 let r = ctx.translate_region(span, &p.rhs)?;
186 Ok(OutlivesPred(ty, r))
187 })?;
188 self.innermost_generics_mut().types_outlive.push(pred);
189 }
190 ClauseKind::Projection(p) => {
191 let pred = self.translate_region_binder(span, &clause.kind, |ctx, _| {
198 let trait_ref = ctx.translate_trait_impl_expr(span, &p.impl_expr)?;
199 let ty = ctx.translate_ty(span, &p.ty)?;
200 let type_name = ctx.t_ctx.translate_trait_item_name(&p.assoc_item.def_id)?;
201 Ok(TraitTypeConstraint {
202 trait_ref,
203 type_name,
204 ty,
205 })
206 })?;
207 self.innermost_generics_mut()
208 .trait_type_constraints
209 .push(pred);
210 }
211 ClauseKind::ConstArgHasType(..) => {
212 }
215 ClauseKind::HostEffect(..) => {
216 }
219 ClauseKind::WellFormed(..) | ClauseKind::ConstEvaluatable(..) => {
220 }
224 ClauseKind::UnstableFeature(..) => {
225 }
227 #[expect(unreachable_patterns)]
228 kind => raise_error!(self, span, "Unsupported clause: {:?}", kind),
229 }
230 Ok(())
231 }
232
233 pub(crate) fn translate_trait_impl_exprs(
234 &mut self,
235 span: Span,
236 impl_sources: &[hax::ImplExpr],
237 ) -> Result<IndexMap<TraitClauseId, TraitRef>, Error> {
238 impl_sources
239 .iter()
240 .map(|x| self.translate_trait_impl_expr(span, x))
241 .try_collect()
242 }
243
244 #[tracing::instrument(skip(self, span, impl_expr))]
245 pub(crate) fn translate_trait_impl_expr(
246 &mut self,
247 span: Span,
248 impl_expr: &hax::ImplExpr,
249 ) -> Result<TraitRef, Error> {
250 let trait_decl_ref = self.translate_poly_trait_ref(span, &impl_expr.r#trait)?;
251
252 match self.translate_trait_impl_expr_aux(span, impl_expr, trait_decl_ref.clone()) {
253 Ok(res) => Ok(res),
254 Err(err) => {
255 register_error!(self, span, "Error during trait resolution: {}", &err.msg);
256 Ok(TraitRef::new(
257 TraitRefKind::Unknown(err.msg),
258 trait_decl_ref,
259 ))
260 }
261 }
262 }
263
264 pub(crate) fn translate_trait_impl_expr_aux(
265 &mut self,
266 span: Span,
267 impl_source: &hax::ImplExpr,
268 trait_decl_ref: PolyTraitDeclRef,
269 ) -> Result<TraitRef, Error> {
270 trace!("impl_expr: {:#?}", impl_source);
271 use hax::DestructData;
272 use hax::ImplExprAtom;
273
274 let trait_ref = match &impl_source.r#impl {
275 ImplExprAtom::Concrete(item) => {
276 let impl_ref =
277 self.translate_trait_impl_ref(span, item, TraitImplSource::Normal)?;
278 TraitRef::new(TraitRefKind::TraitImpl(impl_ref), trait_decl_ref)
279 }
280 ImplExprAtom::SelfImpl {
281 r#trait: trait_ref,
282 path,
283 }
284 | ImplExprAtom::LocalBound {
285 r#trait: trait_ref,
286 path,
287 ..
288 } => {
289 trace!(
290 "impl source (self or clause): param:\n- trait_ref: {:?}\n- path: {:?}",
291 trait_ref, path,
292 );
293 let mut tref_kind = match &impl_source.r#impl {
295 ImplExprAtom::SelfImpl { .. } => TraitRefKind::SelfId,
296 ImplExprAtom::LocalBound { id, .. } => match self.lookup_clause_var(span, id) {
297 Ok(var) => TraitRefKind::Clause(var),
298 Err(err) => TraitRefKind::Unknown(err.msg),
299 },
300 _ => unreachable!(),
301 };
302
303 let mut current_pred = self.translate_poly_trait_ref(span, trait_ref)?;
304
305 for path_elem in path {
307 use hax::ImplExprPathChunk::*;
308 let trait_ref = Box::new(TraitRef::new(tref_kind, current_pred));
309 match path_elem {
310 AssocItem {
311 item,
312 predicate,
313 index,
314 ..
315 } => {
316 let name = self.t_ctx.translate_trait_item_name(&item.def_id)?;
317 tref_kind = TraitRefKind::ItemClause(
318 trait_ref,
319 name,
320 TraitClauseId::new(*index),
321 );
322 current_pred = self.translate_poly_trait_predicate(span, predicate)?;
323 }
324 Parent {
325 predicate, index, ..
326 } => {
327 tref_kind =
328 TraitRefKind::ParentClause(trait_ref, TraitClauseId::new(*index));
329 current_pred = self.translate_poly_trait_predicate(span, predicate)?;
330 }
331 }
332 }
333
334 TraitRef::new(tref_kind, trait_decl_ref)
335 }
336 ImplExprAtom::Dyn => TraitRef::new(TraitRefKind::Dyn, trait_decl_ref),
337 ImplExprAtom::Builtin {
338 trait_data,
339 impl_exprs,
340 types,
341 ..
342 } => {
343 let tref = &impl_source.r#trait;
344 let trait_def =
345 self.hax_def(&tref.hax_skip_binder_ref().erase(self.hax_state_with_id()))?;
346 let kind = if let hax::FullDefKind::TraitAlias { .. } = trait_def.kind() {
347 let impl_id = self.register_item(
349 span,
350 tref.hax_skip_binder_ref(),
351 TransItemSourceKind::TraitImpl(TraitImplSource::TraitAlias),
352 );
353 let mut generics = self.erase_region_binder(trait_decl_ref.clone()).generics;
354 assert!(
355 generics.trait_refs.is_empty(),
356 "found trait alias with non-empty required predicates"
357 );
358 generics.trait_refs = self.translate_trait_impl_exprs(span, &impl_exprs)?;
359 TraitRefKind::TraitImpl(TraitImplRef {
360 id: impl_id,
361 generics,
362 })
363 } else if let hax::BuiltinTraitData::Destruct(DestructData::Glue { ty, .. }) =
364 trait_data
365 {
366 let (hax::TyKind::Adt(item)
367 | hax::TyKind::Closure(hax::ClosureArgs { item, .. })
368 | hax::TyKind::Array(item)
369 | hax::TyKind::Slice(item)
370 | hax::TyKind::Tuple(item)) = ty.kind()
371 else {
372 raise_error!(self, span, "failed to translate drop glue for type {ty:?}")
373 };
374 TraitRefKind::TraitImpl(self.translate_trait_impl_ref(
375 span,
376 item,
377 TraitImplSource::ImplicitDestruct,
378 )?)
379 } else {
380 let Some(builtin_data) = self.recognize_builtin_impl(trait_data, &trait_def)
381 else {
382 raise_error!(
383 self,
384 span,
385 "found a built-in trait impl we did not recognize: \
386 {:?} (lang_item={:?})",
387 trait_def.def_id(),
388 trait_def.lang_item,
389 )
390 };
391 if let Some(closure_kind) = builtin_data.as_closure_kind()
394 && let Some(hax::GenericArg::Type(closure_ty)) = impl_source
395 .r#trait
396 .hax_skip_binder_ref()
397 .generic_args
398 .first()
399 && let hax::TyKind::Closure(closure_args) = closure_ty.kind()
400 {
401 let binder = self.translate_region_binder(
402 span,
403 &impl_source.r#trait,
404 |ctx, _tref| {
405 ctx.translate_closure_impl_ref(span, closure_args, closure_kind)
406 },
407 )?;
408 TraitRefKind::TraitImpl(self.erase_region_binder(binder))
409 } else {
410 let parent_trait_refs =
411 self.translate_trait_impl_exprs(span, &impl_exprs)?;
412 let types = if self.monomorphize() {
413 vec![]
414 } else {
415 types
416 .iter()
417 .map(|(def_id, ty, impl_exprs)| -> Result<_, Error> {
418 let name = self.t_ctx.translate_trait_item_name(def_id)?;
419 let assoc_ty = TraitAssocTyImpl {
420 value: self.translate_ty(span, ty)?,
421 implied_trait_refs: self
422 .translate_trait_impl_exprs(span, impl_exprs)?,
423 };
424 Ok((name, assoc_ty))
425 })
426 .try_collect()?
427 };
428 TraitRefKind::BuiltinOrAuto {
429 builtin_data,
430 parent_trait_refs,
431 types,
432 }
433 }
434 };
435 TraitRef::new(kind, trait_decl_ref)
436 }
437 ImplExprAtom::Error(msg) => {
438 let trait_ref = TraitRef::new(TraitRefKind::Unknown(msg.clone()), trait_decl_ref);
439 if self.error_on_impl_expr_error {
440 register_error!(self, span, "Error during trait resolution: {}", msg);
441 }
442 trait_ref
443 }
444 };
445 Ok(trait_ref)
446 }
447}