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