1use super::translate_ctx::*;
2use crate::hax;
3use charon_lib::{ast::*, ids::IndexVec};
4use rustc_span::{kw, sym};
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::Other => match &trait_def.lang_item {
22 _ if self
23 .tcx
24 .trait_is_auto(trait_def.def_id().real_rust_def_id()) =>
25 {
26 BuiltinImplData::Auto
27 }
28 None => return None,
29 Some(litem) => match *litem {
30 sym::sized => BuiltinImplData::Sized,
31 sym::meta_sized => BuiltinImplData::MetaSized,
32 sym::tuple_trait => BuiltinImplData::Tuple,
33 kw::Fn => BuiltinImplData::Fn,
34 sym::fn_mut => BuiltinImplData::FnMut,
35 sym::fn_once => BuiltinImplData::FnOnce,
36 sym::pointee_trait => BuiltinImplData::Pointee,
37 sym::clone => BuiltinImplData::Clone,
38 sym::copy => BuiltinImplData::Copy,
39 sym::discriminant_kind => BuiltinImplData::DiscriminantKind,
40 _ => return None,
41 },
42 },
43 })
44 }
45}
46
47impl<'tcx, 'ctx> ItemTransCtx<'tcx, 'ctx> {
48 pub(crate) fn register_predicates(
54 &mut self,
55 preds: &hax::GenericPredicates,
56 origin: PredicateOrigin,
57 ) -> Result<(), Error> {
58 self.translate_predicates(preds, origin, None)?;
59 Ok(())
60 }
61
62 pub(crate) fn translate_predicates(
65 &mut self,
66 preds: &hax::GenericPredicates,
67 origin: PredicateOrigin,
68 mut trait_clauses: Option<&mut IndexVec<TraitClauseId, TraitParam>>,
70 ) -> Result<(), Error> {
71 if trait_clauses.is_none() {
72 let next_clause_id = self.innermost_generics_mut().trait_clauses.next_idx();
77 for (i, pred) in preds
78 .predicates
79 .iter()
80 .filter(|pred| {
81 matches!(
82 pred.clause.kind.hax_skip_binder_ref(),
83 hax::ClauseKind::Trait(_)
84 )
85 })
86 .enumerate()
87 {
88 self.innermost_binder_mut()
89 .trait_preds
90 .insert(pred.id.clone(), next_clause_id + i);
91 }
92 }
93
94 for pred in &preds.predicates {
95 self.translate_predicate(pred, origin.clone(), trait_clauses.as_deref_mut())?;
96 }
97 Ok(())
98 }
99
100 pub(crate) fn translate_poly_trait_ref(
101 &mut self,
102 span: Span,
103 bound_trait_ref: &hax::Binder<hax::TraitRef>,
104 ) -> Result<PolyTraitDeclRef, Error> {
105 self.translate_region_binder(span, bound_trait_ref, move |ctx, trait_ref| {
106 ctx.translate_trait_ref(span, trait_ref)
107 })
108 }
109
110 pub(crate) fn translate_trait_predicate(
111 &mut self,
112 span: Span,
113 trait_pred: &hax::TraitPredicate,
114 ) -> Result<TraitDeclRef, Error> {
115 assert!(trait_pred.is_positive);
117 self.translate_trait_ref(span, &trait_pred.trait_ref)
118 }
119
120 pub(crate) fn translate_trait_ref(
121 &mut self,
122 span: Span,
123 trait_ref: &hax::TraitRef,
124 ) -> Result<TraitDeclRef, Error> {
125 self.translate_trait_decl_ref(span, trait_ref)
126 }
127
128 pub(crate) fn translate_predicate(
129 &mut self,
130 pred: &hax::GenericPredicate,
131 origin: PredicateOrigin,
132 mut trait_clauses: Option<&mut IndexVec<TraitClauseId, TraitParam>>,
134 ) -> Result<(), Error> {
135 use crate::hax::ClauseKind;
136 let clause = &pred.clause;
137 trace!("{:?}", clause);
138 let span = self.translate_span(&pred.span);
139 match clause.kind.hax_skip_binder_ref() {
140 ClauseKind::Trait(trait_pred) => {
141 let trait_pred = self.translate_region_binder(span, &clause.kind, |ctx, _| {
142 ctx.translate_trait_predicate(span, trait_pred)
143 })?;
144 let clause_id = trait_clauses
145 .as_deref_mut()
146 .unwrap_or(&mut self.innermost_generics_mut().trait_clauses)
147 .push_with(|clause_id| TraitParam {
148 clause_id,
149 origin,
150 span: Some(span),
151 trait_: trait_pred,
152 });
153
154 if trait_clauses.is_none() {
155 let expected_clause_id = self
157 .innermost_binder_mut()
158 .trait_preds
159 .get(&pred.id)
160 .unwrap();
161 debug_assert_eq!(clause_id, *expected_clause_id);
162 }
163 }
164 ClauseKind::RegionOutlives(p) => {
165 let pred = self.translate_region_binder(span, &clause.kind, |ctx, _| {
166 let r0 = ctx.translate_region(span, &p.lhs)?;
167 let r1 = ctx.translate_region(span, &p.rhs)?;
168 Ok(OutlivesPred(r0, r1))
169 })?;
170 self.innermost_generics_mut().regions_outlive.push(pred);
171 }
172 ClauseKind::TypeOutlives(p) => {
173 let pred = self.translate_region_binder(span, &clause.kind, |ctx, _| {
174 let ty = ctx.translate_ty(span, &p.lhs)?;
175 let r = ctx.translate_region(span, &p.rhs)?;
176 Ok(OutlivesPred(ty, r))
177 })?;
178 self.innermost_generics_mut().types_outlive.push(pred);
179 }
180 ClauseKind::Projection(p) => {
181 let pred = self.translate_region_binder(span, &clause.kind, |ctx, _| {
188 let trait_ref = ctx.translate_trait_impl_expr(span, &p.impl_expr)?;
189 let ty = ctx.translate_ty(span, &p.ty)?;
190 let type_id =
191 ctx.translate_assoc_type_id(trait_ref.trait_id(), &p.assoc_item.def_id)?;
192 Ok(TraitTypeConstraint {
193 trait_ref,
194 type_id,
195 ty,
196 })
197 })?;
198 self.innermost_generics_mut()
199 .trait_type_constraints
200 .push(pred);
201 }
202 ClauseKind::ConstArgHasType(..) => {
203 }
206 ClauseKind::HostEffect(..) => {
207 }
210 ClauseKind::WellFormed(..) | ClauseKind::ConstEvaluatable(..) => {
211 }
215 ClauseKind::UnstableFeature(..) => {
216 }
218 #[expect(unreachable_patterns)]
219 kind => raise_error!(self, span, "Unsupported clause: {:?}", kind),
220 }
221 Ok(())
222 }
223
224 pub(crate) fn translate_trait_impl_exprs(
225 &mut self,
226 span: Span,
227 impl_sources: &[hax::ImplExpr],
228 ) -> Result<IndexVec<TraitClauseId, TraitRef>, Error> {
229 impl_sources
230 .iter()
231 .map(|x| self.translate_trait_impl_expr(span, x))
232 .try_collect()
233 }
234
235 #[tracing::instrument(skip(self, span, impl_expr))]
236 pub(crate) fn translate_trait_impl_expr(
237 &mut self,
238 span: Span,
239 impl_expr: &hax::ImplExpr,
240 ) -> Result<TraitRef, Error> {
241 let trait_decl_ref = self.translate_poly_trait_ref(span, &impl_expr.r#trait)?;
242
243 match self.translate_trait_impl_expr_aux(span, impl_expr, trait_decl_ref.clone()) {
244 Ok(res) => Ok(res),
245 Err(err) => {
246 register_error!(self, span, "Error during trait resolution: {}", &err.msg);
247 Ok(TraitRef::new(
248 TraitRefKind::Unknown(err.msg),
249 trait_decl_ref,
250 ))
251 }
252 }
253 }
254
255 pub(crate) fn translate_trait_impl_expr_aux(
256 &mut self,
257 span: Span,
258 impl_source: &hax::ImplExpr,
259 trait_decl_ref: PolyTraitDeclRef,
260 ) -> Result<TraitRef, Error> {
261 trace!("impl_expr: {:#?}", impl_source);
262 use crate::hax::DestructData;
263 use crate::hax::ImplExprAtom;
264
265 let trait_ref = match &impl_source.r#impl {
266 ImplExprAtom::Concrete(item) => {
267 let impl_ref =
268 self.translate_trait_impl_ref(span, item, TraitImplSource::Normal)?;
269 TraitRef::new(TraitRefKind::TraitImpl(impl_ref), trait_decl_ref)
270 }
271 ImplExprAtom::SelfImpl {
272 r#trait: trait_ref,
273 path,
274 }
275 | ImplExprAtom::LocalBound {
276 r#trait: trait_ref,
277 path,
278 ..
279 } => {
280 trace!(
281 "impl source (self or clause): param:\n- trait_ref: {:?}\n- path: {:?}",
282 trait_ref, path,
283 );
284 let mut tref_kind = match &impl_source.r#impl {
286 ImplExprAtom::SelfImpl { .. } => TraitRefKind::SelfId,
287 ImplExprAtom::LocalBound { id, .. } => match self.lookup_clause_var(span, id) {
288 Ok(var) => TraitRefKind::Clause(var),
289 Err(err) => TraitRefKind::Unknown(err.msg),
290 },
291 _ => unreachable!(),
292 };
293
294 let mut current_pred = self.translate_poly_trait_ref(span, trait_ref)?;
295
296 for path_elem in path {
298 use crate::hax::ImplExprPathChunk::*;
299 let current_trait_id = current_pred.skip_binder.id;
300 let trait_ref = Box::new(TraitRef::new(tref_kind, current_pred));
301 match path_elem {
302 AssocItem {
303 item,
304 predicate,
305 index,
306 ..
307 } => {
308 let assoc_type_id =
309 self.translate_assoc_type_id(current_trait_id, &item.def_id)?;
310 tref_kind = TraitRefKind::ItemClause(
311 trait_ref,
312 assoc_type_id,
313 TraitClauseId::new(*index),
314 );
315 current_pred = self.translate_poly_trait_ref(span, predicate)?;
316 }
317 Parent {
318 predicate, index, ..
319 } => {
320 tref_kind =
321 TraitRefKind::ParentClause(trait_ref, TraitClauseId::new(*index));
322 current_pred = self.translate_poly_trait_ref(span, predicate)?;
323 }
324 }
325 }
326
327 TraitRef::new(tref_kind, trait_decl_ref)
328 }
329 ImplExprAtom::Dyn => TraitRef::new(TraitRefKind::Dyn, trait_decl_ref),
330 ImplExprAtom::Builtin {
331 trait_data,
332 impl_exprs,
333 types,
334 ..
335 } => {
336 let tref = &impl_source.r#trait;
337 let trait_def = self.poly_hax_def(&tref.hax_skip_binder_ref().def_id)?;
338 let kind = if let hax::FullDefKind::TraitAlias { .. } = trait_def.kind() {
339 let mut impl_ref: TraitImplRef = self.translate_item(
341 span,
342 &tref.hax_skip_binder_ref().erase(self.hax_state_with_id()),
343 TransItemSourceKind::TraitImpl(TraitImplSource::TraitAlias),
344 )?;
345 assert!(
346 impl_ref.generics.trait_refs.is_empty(),
347 "found trait alias with non-empty required predicates"
348 );
349 impl_ref.generics.trait_refs =
350 self.translate_trait_impl_exprs(span, impl_exprs)?;
351 TraitRefKind::TraitImpl(impl_ref)
352 } else if let hax::BuiltinTraitData::Destruct(DestructData::Glue { ty, .. }) =
353 trait_data
354 {
355 let (hax::TyKind::Adt(item)
356 | hax::TyKind::Closure(hax::ClosureArgs { item, .. })
357 | hax::TyKind::Array(item)
358 | hax::TyKind::Slice(item)
359 | hax::TyKind::Tuple(item)) = ty.kind()
360 else {
361 raise_error!(self, span, "failed to translate drop glue for type {ty:?}")
362 };
363 TraitRefKind::TraitImpl(self.translate_trait_impl_ref(
364 span,
365 item,
366 TraitImplSource::ImplicitDestruct,
367 )?)
368 } else {
369 let Some(builtin_data) = self.recognize_builtin_impl(trait_data, &trait_def)
370 else {
371 raise_error!(
372 self,
373 span,
374 "found a built-in trait impl we did not recognize: \
375 {:?} (lang_item={:?})",
376 trait_def.def_id(),
377 trait_def.lang_item,
378 )
379 };
380 if let Some(closure_kind) = builtin_data.as_closure_kind()
383 && let Some(hax::GenericArg::Type(closure_ty)) = impl_source
384 .r#trait
385 .hax_skip_binder_ref()
386 .generic_args
387 .first()
388 && let hax::TyKind::Closure(closure_args) = closure_ty.kind()
389 {
390 let binder = self.translate_region_binder(
391 span,
392 &impl_source.r#trait,
393 |ctx, _tref| {
394 ctx.translate_closure_impl_ref(span, closure_args, closure_kind)
395 },
396 )?;
397 TraitRefKind::TraitImpl(self.erase_region_binder(binder))
398 } else {
399 let parent_trait_refs =
400 self.translate_trait_impl_exprs(span, impl_exprs)?;
401 let types: IndexMap<AssocTypeId, _> = if self.monomorphize() {
402 IndexMap::new()
403 } else {
404 let tdecl_id = trait_decl_ref.skip_binder.id;
405 let mut type_map = IndexMap::new();
406 for (def_id, ty, impl_exprs) in types {
407 let assoc_type_id =
408 self.translate_assoc_type_id(tdecl_id, def_id)?;
409 let assoc_ty = TraitAssocTyImpl {
410 value: self.translate_ty(span, ty)?,
411 implied_trait_refs: self
412 .translate_trait_impl_exprs(span, impl_exprs)?,
413 };
414 type_map.set_slot_extend(assoc_type_id, assoc_ty);
415 }
416 type_map
417 };
418 TraitRefKind::BuiltinOrAuto {
419 builtin_data,
420 parent_trait_refs,
421 types,
422 }
423 }
424 };
425 TraitRef::new(kind, trait_decl_ref)
426 }
427 ImplExprAtom::Error(msg) => {
428 let trait_ref = TraitRef::new(TraitRefKind::Unknown(msg.clone()), trait_decl_ref);
429 if self.error_on_impl_expr_error {
430 register_error!(self, span, "Error during trait resolution: {}", msg);
431 }
432 trait_ref
433 }
434 };
435 Ok(trait_ref)
436 }
437}