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::AsyncFnOnceOutput => return None,
35 SolverTraitLangItem::AsyncIterator => return None,
36 SolverTraitLangItem::BikeshedGuaranteedNoDrop => return None,
37 SolverTraitLangItem::Clone => BuiltinImplData::Clone,
38 SolverTraitLangItem::Copy => BuiltinImplData::Copy,
39 SolverTraitLangItem::Coroutine => BuiltinImplData::Coroutine,
40 SolverTraitLangItem::Destruct => BuiltinImplData::UntrackedDestruct,
41 SolverTraitLangItem::DiscriminantKind => BuiltinImplData::DiscriminantKind,
42 SolverTraitLangItem::Drop => 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 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 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, TraitImplSource::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 => TraitRefKind::Dyn,
316 TraitProofKind::Builtin {
317 trait_data,
318 proofs: trait_proofs,
319 types,
320 ..
321 } => {
322 let tref = &impl_source.pred;
323 let trait_def = self.poly_hax_def(&tref.hax_skip_binder_ref().def_id)?;
324 if let hax::FullDefKind::TraitAlias { .. } = trait_def.kind() {
325 let mut impl_ref: TraitImplRef = self.translate_item(
327 span,
328 &tref.hax_skip_binder_ref().erase(self.hax_state_with_id()),
329 TransItemSourceKind::TraitImpl(TraitImplSource::TraitAlias),
330 )?;
331 assert!(
332 impl_ref.generics.trait_refs.is_empty(),
333 "found trait alias with non-empty required predicates"
334 );
335 impl_ref.generics.trait_refs =
336 self.translate_trait_proofs(span, trait_proofs)?;
337 TraitRefKind::TraitImpl(impl_ref)
338 } else if let hax::BuiltinTraitData::Destruct(DestructData::Glue { ty, .. }) =
339 trait_data
340 {
341 let (hax::TyKind::Adt(item)
342 | hax::TyKind::Closure(hax::ClosureArgs { item, .. })
343 | hax::TyKind::Array(item)
344 | hax::TyKind::Slice(item)
345 | hax::TyKind::Tuple(item)) = ty.kind()
346 else {
347 raise_error!(self, span, "failed to translate drop glue for type {ty:?}")
348 };
349 TraitRefKind::TraitImpl(self.translate_trait_impl_ref(
350 span,
351 item,
352 TraitImplSource::ImplicitDestruct,
353 )?)
354 } else {
355 let Some(builtin_data) = self.recognize_builtin_impl(trait_data, &trait_def)
356 else {
357 raise_error!(
358 self,
359 span,
360 "found a built-in trait impl we did not recognize: \
361 {:?} (lang_item={:?})",
362 trait_def.def_id(),
363 trait_def.lang_item,
364 )
365 };
366 if let Some(closure_kind) = builtin_data.as_closure_kind()
369 && let Some(hax::GenericArg::Type(closure_ty)) =
370 impl_source.pred.hax_skip_binder_ref().generic_args.first()
371 && let hax::TyKind::Closure(closure_args) = closure_ty.kind()
372 {
373 let binder =
374 self.translate_region_binder(span, &impl_source.pred, |ctx, _tref| {
375 ctx.translate_closure_impl_ref(span, closure_args, closure_kind)
376 })?;
377 TraitRefKind::TraitImpl(self.erase_region_binder(binder))
378 } else {
379 let parent_trait_refs = self.translate_trait_proofs(span, trait_proofs)?;
380 let types: IndexMap<AssocTypeId, _> = if self.monomorphize() {
381 IndexMap::new()
382 } else {
383 let tdecl_id = trait_decl_ref.skip_binder.id;
384 let mut type_map = IndexMap::new();
385 for (def_id, ty, trait_proofs) in types {
386 let assoc_type_id =
387 self.translate_assoc_type_id(tdecl_id, def_id)?;
388 let assoc_ty = TraitAssocTyImpl {
389 value: self.translate_ty(span, ty)?,
390 implied_trait_refs: self
391 .translate_trait_proofs(span, trait_proofs)?,
392 };
393 type_map.set_slot_extend(assoc_type_id, assoc_ty);
394 }
395 type_map
396 };
397 TraitRefKind::BuiltinOrAuto {
398 builtin_data,
399 parent_trait_refs,
400 types,
401 }
402 }
403 }
404 }
405 TraitProofKind::Error(msg) => {
406 if self.error_on_trait_proof_error {
407 register_error!(self, span, "Error during trait resolution: {}", msg);
408 }
409 TraitRefKind::Unknown(msg.clone())
410 }
411 };
412 Ok(TraitRef::new(kind, trait_decl_ref))
413 }
414}