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 match path_elem {
300 hax::TraitProofImpliedPredicate::AssocItem { item, index, .. } => {
301 let assoc_type_id =
302 self.translate_assoc_type_id(trait_ref.trait_id(), &item.def_id)?;
303 TraitRefKind::ItemClause(
304 trait_ref,
305 assoc_type_id,
306 TraitClauseId::new(*index),
307 )
308 }
309 hax::TraitProofImpliedPredicate::Parent { index, .. } => {
310 TraitRefKind::ParentClause(trait_ref, TraitClauseId::new(*index))
311 }
312 }
313 }
314 TraitProofKind::Dyn(proof) => {
315 let bound_proof = self.translate_dyn_binder(span, proof, |ctx, _, proof| {
317 ctx.translate_trait_proof(span, proof)
318 })?;
319
320 let args = {
324 let dyn_ty = trait_decl_ref.clone().erase().generics.types[0].clone();
325 assert!(dyn_ty.is_dyn_trait());
326 let mut args = GenericArgs::new_types([dyn_ty].into());
327 args.trait_refs = bound_proof
328 .params
329 .trait_clauses
330 .clone()
331 .substitute(&args)
332 .map(|clause| TraitRef::new(TraitRefKind::Dyn, clause.trait_));
333 args
334 };
335 let trait_ref = bound_proof.apply(&args);
336 assert_eq!(trait_ref.trait_id(), trait_decl_ref.skip_binder.id);
337 trait_ref.kind.clone()
338 }
339 TraitProofKind::Builtin {
340 trait_data,
341 proofs: trait_proofs,
342 types,
343 ..
344 } => {
345 let tref = &impl_source.pred;
346 let trait_def = self.poly_hax_def(&tref.hax_skip_binder_ref().def_id)?;
347 match trait_data {
348 hax::BuiltinTraitData::Alias => {
349 let mut impl_ref: TraitImplRef = self.translate_item(
351 span,
352 &tref.hax_skip_binder_ref().erase(self.hax_state_with_id()),
353 TransItemSourceKind::TraitImpl(TransImplSource::TraitAlias),
354 )?;
355 assert!(
356 impl_ref.generics.trait_refs.is_empty(),
357 "found trait alias with non-empty required predicates"
358 );
359 impl_ref.generics.trait_refs =
360 self.translate_trait_proofs(span, trait_proofs)?;
361 TraitRefKind::TraitImpl(impl_ref)
362 }
363 hax::BuiltinTraitData::Destruct(DestructData::Glue { ty, .. }) => {
364 let (hax::TyKind::Adt(item)
365 | hax::TyKind::Closure(hax::ClosureArgs { item, .. })
366 | hax::TyKind::Array(item)
367 | hax::TyKind::Slice(item)
368 | hax::TyKind::Tuple(item)) = ty.kind()
369 else {
370 raise_error!(
371 self,
372 span,
373 "failed to translate drop glue for type {ty:?}"
374 )
375 };
376 TraitRefKind::TraitImpl(self.translate_trait_impl_ref(
377 span,
378 item,
379 TransImplSource::ImplicitDestruct,
380 )?)
381 }
382 _ if let Some((item, closure_kind)) =
383 self.recognize_callable_impl_proof(impl_source) =>
384 {
385 TraitRefKind::TraitImpl(self.translate_callable_impl_ref(
386 span,
387 &item,
388 closure_kind,
389 )?)
390 }
391 _ if let Some(builtin_data) = self.recognize_builtin_impl(trait_data) => {
392 let parent_trait_refs = self.translate_trait_proofs(span, trait_proofs)?;
393 let types: IndexMap<AssocTypeId, _> = if self.monomorphize() {
394 IndexMap::new()
395 } else {
396 let tdecl_id = trait_decl_ref.skip_binder.id;
397 let mut type_map = IndexMap::new();
398 for (def_id, ty, trait_proofs) in types {
399 let assoc_type_id =
400 self.translate_assoc_type_id(tdecl_id, def_id)?;
401 let assoc_ty = TraitAssocTyImpl {
402 value: self.translate_ty(span, ty)?,
403 implied_trait_refs: self
404 .translate_trait_proofs(span, trait_proofs)?,
405 };
406 type_map.set_slot_extend(assoc_type_id, assoc_ty);
407 }
408 type_map
409 };
410 let vtable = self.translate_region_binder(span, tref, |ctx, tref| {
411 ctx.translate_vtable_instance_ref_no_enqueue(
412 span,
413 tref,
414 tref,
415 TransImplSource::Marker,
416 )
417 })?;
418 let vtable = self.erase_region_binder(vtable);
419 TraitRefKind::BuiltinOrAuto {
420 builtin_data,
421 parent_trait_refs,
422 types,
423 vtable,
424 }
425 }
426 _ => raise_error!(
427 self,
428 span,
429 "found a built-in trait impl we did not recognize: \
430 {:?} (lang_item={:?})",
431 trait_def.def_id(),
432 trait_def.lang_item,
433 ),
434 }
435 }
436 TraitProofKind::Error(msg) => {
437 if self.error_on_trait_proof_error {
438 register_error!(self, span, "Error during trait resolution: {}", msg);
439 }
440 TraitRefKind::Unknown(msg.clone())
441 }
442 };
443 Ok(TraitRef::new(kind, trait_decl_ref))
444 }
445}