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