1use super::translate_ctx::*;
2use crate::hax;
3use charon_lib::{ast::*, ids::IndexVec};
4
5impl<'tcx> TranslateCtx<'tcx> {
6 pub fn recognize_builtin_impl(
7 &self,
8 trait_data: &hax::BuiltinTraitData,
9 ) -> Option<BuiltinImplData> {
10 Some(match trait_data {
11 hax::BuiltinTraitData::Destruct(x) => {
12 match x {
13 hax::DestructData::Noop => BuiltinImplData::NoopDestruct,
14 hax::DestructData::Implicit => BuiltinImplData::UntrackedDestruct,
15 hax::DestructData::Glue { .. } => unreachable!(),
17 }
18 }
19 hax::BuiltinTraitData::Alias => unreachable!(),
20 hax::BuiltinTraitData::Auto => BuiltinImplData::Auto,
21 hax::BuiltinTraitData::Other(item) => {
22 use hax::SolverTraitLangItem;
23 match item {
26 SolverTraitLangItem::AsyncFn => BuiltinImplData::AsyncFn,
27 SolverTraitLangItem::AsyncFnKindHelper => return None,
28 SolverTraitLangItem::AsyncFnMut => BuiltinImplData::AsyncFnMut,
29 SolverTraitLangItem::AsyncFnOnce => BuiltinImplData::AsyncFnOnce,
30 SolverTraitLangItem::AsyncIterator => return None,
31 SolverTraitLangItem::BikeshedGuaranteedNoDrop => return None,
32 SolverTraitLangItem::Clone => BuiltinImplData::Clone,
33 SolverTraitLangItem::Copy => BuiltinImplData::Copy,
34 SolverTraitLangItem::Coroutine => BuiltinImplData::Coroutine,
35 SolverTraitLangItem::Destruct => BuiltinImplData::UntrackedDestruct,
36 SolverTraitLangItem::DiscriminantKind => BuiltinImplData::DiscriminantKind,
37 SolverTraitLangItem::Drop => return None,
38 SolverTraitLangItem::Field => return None,
39 SolverTraitLangItem::Fn => BuiltinImplData::Fn,
40 SolverTraitLangItem::FnMut => BuiltinImplData::FnMut,
41 SolverTraitLangItem::FnOnce => BuiltinImplData::FnOnce,
42 SolverTraitLangItem::FnPtrTrait => BuiltinImplData::FnPtr,
43 SolverTraitLangItem::FusedIterator => return None,
44 SolverTraitLangItem::Future => BuiltinImplData::Future,
45 SolverTraitLangItem::Iterator => return None,
46 SolverTraitLangItem::MetaSized => BuiltinImplData::MetaSized,
47 SolverTraitLangItem::PointeeSized => BuiltinImplData::PointeeSized,
48 SolverTraitLangItem::PointeeTrait => BuiltinImplData::Pointee,
49 SolverTraitLangItem::Sized => BuiltinImplData::Sized,
50 SolverTraitLangItem::TransmuteTrait => BuiltinImplData::Transmute,
51 SolverTraitLangItem::TrivialClone => BuiltinImplData::Auto,
52 SolverTraitLangItem::TryAsDyn => BuiltinImplData::TryAsDynCompatible,
53 SolverTraitLangItem::Tuple => BuiltinImplData::Tuple,
54 SolverTraitLangItem::Unpin => BuiltinImplData::Auto,
55 SolverTraitLangItem::Unsize => BuiltinImplData::Unsize,
56 }
57 }
58 })
59 }
60}
61
62impl<'tcx, 'ctx> ItemTransCtx<'tcx, 'ctx> {
63 pub(crate) fn register_predicates(
69 &mut self,
70 preds: &hax::GenericPredicates,
71 origin: PredicateOrigin,
72 ) -> Result<(), Error> {
73 self.translate_predicates(preds, origin, None)?;
74 Ok(())
75 }
76
77 pub(crate) fn translate_predicates(
80 &mut self,
81 preds: &hax::GenericPredicates,
82 origin: PredicateOrigin,
83 mut trait_clauses: Option<&mut IndexVec<TraitClauseId, TraitParam>>,
85 ) -> Result<(), Error> {
86 if trait_clauses.is_none() {
87 let next_clause_id = self.innermost_generics_mut().trait_clauses.next_idx();
92 for (i, pred) in preds
93 .predicates
94 .iter()
95 .filter(|pred| {
96 matches!(
97 pred.clause.kind.hax_skip_binder_ref(),
98 hax::ClauseKind::Trait(_)
99 )
100 })
101 .enumerate()
102 {
103 self.innermost_binder_mut()
104 .trait_preds
105 .insert(pred.id.clone(), next_clause_id + i);
106 }
107 }
108
109 for pred in &preds.predicates {
110 self.translate_predicate(pred, origin.clone(), trait_clauses.as_deref_mut())?;
111 }
112 Ok(())
113 }
114
115 pub(crate) fn translate_poly_trait_ref(
116 &mut self,
117 span: Span,
118 bound_trait_ref: &hax::Binder<hax::TraitRef>,
119 ) -> Result<PolyTraitDeclRef, Error> {
120 self.translate_region_binder(span, bound_trait_ref, move |ctx, trait_ref| {
121 ctx.translate_trait_ref(span, trait_ref)
122 })
123 }
124
125 pub(crate) fn translate_trait_predicate(
126 &mut self,
127 span: Span,
128 trait_pred: &hax::TraitPredicate,
129 ) -> Result<TraitDeclRef, Error> {
130 assert!(trait_pred.is_positive);
132 self.translate_trait_ref(span, &trait_pred.trait_ref)
133 }
134
135 pub(crate) fn translate_trait_ref(
136 &mut self,
137 span: Span,
138 trait_ref: &hax::TraitRef,
139 ) -> Result<TraitDeclRef, Error> {
140 self.translate_trait_decl_ref(span, trait_ref)
141 }
142
143 pub(crate) fn translate_predicate(
144 &mut self,
145 pred: &hax::GenericPredicate,
146 mut origin: PredicateOrigin,
147 mut trait_clauses: Option<&mut IndexVec<TraitClauseId, TraitParam>>,
149 ) -> Result<(), Error> {
150 use crate::hax::ClauseKind;
151 let clause = &pred.clause;
152 trace!("{:?}", clause);
153 let span = self.translate_span(&pred.span);
154 match clause.kind.hax_skip_binder_ref() {
155 ClauseKind::Trait(trait_pred) => {
156 if matches!(pred.id, hax::GenericPredicateId::TraitSelf) {
157 origin = PredicateOrigin::TraitSelf;
158 }
159 let trait_pred = self.translate_region_binder(span, &clause.kind, |ctx, _| {
160 ctx.translate_trait_predicate(span, trait_pred)
161 })?;
162 let clause_id = trait_clauses
163 .as_deref_mut()
164 .unwrap_or(&mut self.innermost_generics_mut().trait_clauses)
165 .push_with(|clause_id| TraitParam {
166 clause_id,
167 origin,
168 span: Some(span),
169 trait_: trait_pred,
170 });
171
172 if trait_clauses.is_none() {
173 let expected_clause_id = self
175 .innermost_binder_mut()
176 .trait_preds
177 .get(&pred.id)
178 .unwrap();
179 debug_assert_eq!(clause_id, *expected_clause_id);
180 }
181 }
182 ClauseKind::RegionOutlives(p) => {
183 let pred = self.translate_region_binder(span, &clause.kind, |ctx, _| {
184 let r0 = ctx.translate_region(span, &p.lhs)?;
185 let r1 = ctx.translate_region(span, &p.rhs)?;
186 Ok(OutlivesPred(r0, r1))
187 })?;
188 self.innermost_generics_mut().regions_outlive.push(pred);
189 }
190 ClauseKind::TypeOutlives(p) => {
191 let pred = self.translate_region_binder(span, &clause.kind, |ctx, _| {
192 let ty = ctx.translate_ty(span, &p.lhs)?;
193 let r = ctx.translate_region(span, &p.rhs)?;
194 Ok(OutlivesPred(ty, r))
195 })?;
196 self.innermost_generics_mut().types_outlive.push(pred);
197 }
198 ClauseKind::Projection(p) => {
199 let pred = self.translate_region_binder(span, &clause.kind, |ctx, _| {
206 let trait_ref = ctx.translate_trait_proof(span, &p.trait_proof)?;
207 let ty = ctx.translate_ty(span, &p.ty)?;
208 let type_id =
209 ctx.translate_assoc_type_id(trait_ref.trait_id(), &p.assoc_item.def_id)?;
210 Ok(TraitTypeConstraint {
211 trait_ref,
212 type_id,
213 ty,
214 })
215 })?;
216 self.innermost_generics_mut()
217 .trait_type_constraints
218 .push(pred);
219 }
220 ClauseKind::ConstArgHasType(..) => {
221 }
224 ClauseKind::HostEffect(..) => {
225 }
228 ClauseKind::WellFormed(..) | ClauseKind::ConstEvaluatable(..) => {
229 }
233 ClauseKind::UnstableFeature(..) => {
234 }
236 #[expect(unreachable_patterns)]
237 kind => raise_error!(self, span, "Unsupported clause: {:?}", kind),
238 }
239 Ok(())
240 }
241
242 pub(crate) fn translate_trait_proofs(
243 &mut self,
244 span: Span,
245 impl_sources: &[hax::TraitProof],
246 ) -> Result<IndexVec<TraitClauseId, TraitRef>, Error> {
247 impl_sources
248 .iter()
249 .map(|x| self.translate_trait_proof(span, x))
250 .try_collect()
251 }
252
253 #[tracing::instrument(skip(self, span, trait_proof))]
254 pub(crate) fn translate_trait_proof(
255 &mut self,
256 span: Span,
257 trait_proof: &hax::TraitProof,
258 ) -> Result<TraitRef, Error> {
259 let trait_decl_ref = self.translate_poly_trait_ref(span, &trait_proof.pred)?;
260
261 match self.translate_trait_proof_aux(span, trait_proof, trait_decl_ref.clone()) {
262 Ok(res) => Ok(res),
263 Err(err) => {
264 register_error!(self, span, "Error during trait resolution: {}", &err.msg);
265 Ok(TraitRef::new(
266 TraitRefKind::Unknown(err.msg),
267 trait_decl_ref,
268 ))
269 }
270 }
271 }
272
273 pub(crate) fn translate_trait_proof_aux(
274 &mut self,
275 span: Span,
276 impl_source: &hax::TraitProof,
277 trait_decl_ref: PolyTraitDeclRef,
278 ) -> Result<TraitRef, Error> {
279 trace!("trait_proof: {:#?}", impl_source);
280 use crate::hax::DestructData;
281 use crate::hax::TraitProofKind;
282
283 let kind = match &impl_source.kind {
284 TraitProofKind::Concrete(item) => {
285 let impl_ref =
286 self.translate_trait_impl_ref(span, item, TransImplSource::Normal)?;
287 TraitRefKind::TraitImpl(impl_ref)
288 }
289 TraitProofKind::SelfProof => TraitRefKind::SelfId,
290 TraitProofKind::LocalBound(id) => match self.lookup_clause_var(span, id) {
291 Ok(var) => TraitRefKind::Clause(var),
292 Err(err) => TraitRefKind::Unknown(err.msg),
293 },
294 TraitProofKind::Derived {
295 base,
296 path: path_elem,
297 } => {
298 let trait_ref = self.translate_trait_proof(span, base)?;
299 let trait_ref = Box::new(trait_ref);
300 match path_elem {
301 hax::TraitProofImpliedPredicate::AssocItem { item, index, .. } => {
302 let assoc_type_id =
303 self.translate_assoc_type_id(trait_ref.trait_id(), &item.def_id)?;
304 TraitRefKind::ItemClause(
305 trait_ref,
306 assoc_type_id,
307 TraitClauseId::new(*index),
308 )
309 }
310 hax::TraitProofImpliedPredicate::Parent { index, .. } => {
311 TraitRefKind::ParentClause(trait_ref, TraitClauseId::new(*index))
312 }
313 }
314 }
315 TraitProofKind::Dyn(proof) => {
316 let bound_proof = self.translate_dyn_binder(span, proof, |ctx, _, proof| {
318 ctx.translate_trait_proof(span, proof)
319 })?;
320
321 let args = {
325 let dyn_ty = trait_decl_ref.clone().erase().generics.types[0].clone();
326 assert!(dyn_ty.is_dyn_trait());
327 let mut args = GenericArgs::new_types([dyn_ty].into());
328 args.trait_refs = bound_proof
329 .params
330 .trait_clauses
331 .clone()
332 .substitute(&args)
333 .map(|clause| TraitRef::new(TraitRefKind::Dyn, clause.trait_));
334 args
335 };
336 let trait_ref = bound_proof.apply(&args);
337 assert_eq!(trait_ref.trait_id(), trait_decl_ref.skip_binder.id);
338 trait_ref.kind.clone()
339 }
340 TraitProofKind::Builtin {
341 trait_data,
342 proofs: trait_proofs,
343 types,
344 ..
345 } => {
346 let tref = &impl_source.pred;
347 let trait_def = self.poly_hax_def(&tref.hax_skip_binder_ref().def_id)?;
348 match trait_data {
349 hax::BuiltinTraitData::Alias => {
350 let mut impl_ref: TraitImplRef = self.translate_item(
352 span,
353 &tref.hax_skip_binder_ref().erase(self.hax_state_with_id()),
354 TransItemSourceKind::TraitImpl(TransImplSource::TraitAlias),
355 )?;
356 assert!(
357 impl_ref.generics.trait_refs.is_empty(),
358 "found trait alias with non-empty required predicates"
359 );
360 impl_ref.generics.trait_refs =
361 self.translate_trait_proofs(span, trait_proofs)?;
362 TraitRefKind::TraitImpl(impl_ref)
363 }
364 hax::BuiltinTraitData::Destruct(DestructData::Glue { ty, .. }) => {
365 let (hax::TyKind::Adt(item)
366 | hax::TyKind::Closure(hax::ClosureArgs { item, .. })
367 | hax::TyKind::Array(item)
368 | hax::TyKind::Slice(item)
369 | hax::TyKind::Tuple(item)) = ty.kind()
370 else {
371 raise_error!(
372 self,
373 span,
374 "failed to translate drop glue for type {ty:?}"
375 )
376 };
377 TraitRefKind::TraitImpl(self.translate_trait_impl_ref(
378 span,
379 item,
380 TransImplSource::ImplicitDestruct,
381 )?)
382 }
383 hax::BuiltinTraitData::Other(
384 li @ (hax::SolverTraitLangItem::FnOnce
385 | hax::SolverTraitLangItem::FnMut
386 | hax::SolverTraitLangItem::Fn),
387 ) if let Some(hax::GenericArg::Type(callable_ty)) =
388 impl_source.pred.hax_skip_binder_ref().generic_args.first()
389 && let Some(item) = match callable_ty.kind() {
390 hax::TyKind::Closure(closure_args) => Some(&closure_args.item),
391 hax::TyKind::FnDef { item, .. } => Some(item),
392 _ => None,
393 } =>
394 {
395 let closure_kind = match li {
396 hax::SolverTraitLangItem::FnOnce => ClosureKind::FnOnce,
397 hax::SolverTraitLangItem::FnMut => ClosureKind::FnMut,
398 hax::SolverTraitLangItem::Fn => ClosureKind::Fn,
399 _ => unreachable!(),
400 };
401 let binder =
402 self.translate_region_binder(span, &impl_source.pred, |ctx, _tref| {
403 ctx.translate_callable_impl_ref(span, item, closure_kind)
404 })?;
405 TraitRefKind::TraitImpl(self.erase_region_binder(binder))
406 }
407 _ if let Some(builtin_data) = self.recognize_builtin_impl(trait_data) => {
408 let parent_trait_refs = self.translate_trait_proofs(span, trait_proofs)?;
409 let types: IndexMap<AssocTypeId, _> = if self.monomorphize() {
410 IndexMap::new()
411 } else {
412 let tdecl_id = trait_decl_ref.skip_binder.id;
413 let mut type_map = IndexMap::new();
414 for (def_id, ty, trait_proofs) in types {
415 let assoc_type_id =
416 self.translate_assoc_type_id(tdecl_id, def_id)?;
417 let assoc_ty = TraitAssocTyImpl {
418 value: self.translate_ty(span, ty)?,
419 implied_trait_refs: self
420 .translate_trait_proofs(span, trait_proofs)?,
421 };
422 type_map.set_slot_extend(assoc_type_id, assoc_ty);
423 }
424 type_map
425 };
426 let vtable = self.translate_vtable_instance_ref_no_enqueue(
427 span,
428 tref.hax_skip_binder_ref(),
429 tref.hax_skip_binder_ref(),
430 TransImplSource::Marker,
431 )?;
432 TraitRefKind::BuiltinOrAuto {
433 builtin_data,
434 parent_trait_refs,
435 types,
436 vtable,
437 }
438 }
439 _ => raise_error!(
440 self,
441 span,
442 "found a built-in trait impl we did not recognize: \
443 {:?} (lang_item={:?})",
444 trait_def.def_id(),
445 trait_def.lang_item,
446 ),
447 }
448 }
449 TraitProofKind::Error(msg) => {
450 if self.error_on_trait_proof_error {
451 register_error!(self, span, "Error during trait resolution: {}", msg);
452 }
453 TraitRefKind::Unknown(msg.clone())
454 }
455 };
456 Ok(TraitRef::new(kind, trait_decl_ref))
457 }
458}