1use super::translate_ctx::*;
2use super::translate_traits::PredicateLocation;
3use charon_lib::ast::*;
4use charon_lib::formatter::IntoFormatter;
5use charon_lib::ids::Vector;
6use charon_lib::pretty::FmtWithCtx;
7use hax_frontend_exporter as hax;
8
9impl<'tcx, 'ctx> ItemTransCtx<'tcx, 'ctx> {
10 pub(crate) fn register_predicates(
13 &mut self,
14 preds: &hax::GenericPredicates,
15 origin: PredicateOrigin,
16 location: &PredicateLocation,
17 ) -> Result<(), Error> {
18 for (clause, span) in &preds.predicates {
22 if matches!(clause.kind.value, hax::ClauseKind::Trait(_)) {
23 self.register_predicate(clause, span, origin.clone(), location)?;
24 }
25 }
26 for (clause, span) in &preds.predicates {
27 if !matches!(clause.kind.value, hax::ClauseKind::Trait(_)) {
28 self.register_predicate(clause, span, origin.clone(), location)?;
29 }
30 }
31 Ok(())
32 }
33
34 pub(crate) fn translate_poly_trait_ref(
35 &mut self,
36 span: Span,
37 bound_trait_ref: &hax::Binder<hax::TraitRef>,
38 ) -> Result<PolyTraitDeclRef, Error> {
39 self.translate_region_binder(span, bound_trait_ref, move |ctx, trait_ref| {
40 ctx.translate_trait_ref(span, trait_ref)
41 })
42 }
43
44 pub(crate) fn translate_trait_predicate(
45 &mut self,
46 span: Span,
47 trait_pred: &hax::TraitPredicate,
48 ) -> Result<TraitDeclRef, Error> {
49 assert!(trait_pred.is_positive);
51 self.translate_trait_ref(span, &trait_pred.trait_ref)
52 }
53
54 pub(crate) fn translate_trait_ref(
55 &mut self,
56 span: Span,
57 trait_ref: &hax::TraitRef,
58 ) -> Result<TraitDeclRef, Error> {
59 let trait_id = self.register_trait_decl_id(span, &trait_ref.def_id);
60 let generics = self.translate_generic_args(
62 span,
63 &trait_ref.generic_args,
64 &[],
65 None,
66 GenericsSource::item(trait_id),
67 )?;
68 Ok(TraitDeclRef { trait_id, generics })
69 }
70
71 pub(crate) fn register_predicate(
72 &mut self,
73 clause: &hax::Clause,
74 hspan: &hax::Span,
75 origin: PredicateOrigin,
76 location: &PredicateLocation,
77 ) -> Result<(), Error> {
78 use hax::ClauseKind;
79 trace!("{:?}", clause);
80 let span = self.translate_span_from_hax(hspan);
81 match clause.kind.hax_skip_binder_ref() {
82 ClauseKind::Trait(trait_pred) => {
83 let pred = self.translate_region_binder(span, &clause.kind, |ctx, _| {
84 ctx.translate_trait_predicate(span, trait_pred)
85 })?;
86 let location = match location {
87 PredicateLocation::Base => &mut self.innermost_generics_mut().trait_clauses,
88 PredicateLocation::Parent => &mut self.parent_trait_clauses,
89 PredicateLocation::Item(item_name) => self
90 .item_trait_clauses
91 .entry(item_name.clone())
92 .or_default(),
93 };
94 location.push_with(|clause_id| TraitClause {
95 clause_id,
96 origin,
97 span: Some(span),
98 trait_: pred,
99 });
100 }
101 ClauseKind::RegionOutlives(p) => {
102 let pred = self.translate_region_binder(span, &clause.kind, |ctx, _| {
103 let r0 = ctx.translate_region(span, &p.lhs)?;
104 let r1 = ctx.translate_region(span, &p.rhs)?;
105 Ok(OutlivesPred(r0, r1))
106 })?;
107 self.innermost_generics_mut().regions_outlive.push(pred);
108 }
109 ClauseKind::TypeOutlives(p) => {
110 let pred = self.translate_region_binder(span, &clause.kind, |ctx, _| {
111 let ty = ctx.translate_ty(span, &p.lhs)?;
112 let r = ctx.translate_region(span, &p.rhs)?;
113 Ok(OutlivesPred(ty, r))
114 })?;
115 self.innermost_generics_mut().types_outlive.push(pred);
116 }
117 ClauseKind::Projection(p) => {
118 let pred = self.translate_region_binder(span, &clause.kind, |ctx, _| {
125 let trait_ref = ctx.translate_trait_impl_expr(span, &p.impl_expr)?;
126 let ty = ctx.translate_ty(span, &p.ty)?;
127 let type_name = TraitItemName(p.assoc_item.name.clone());
128 Ok(TraitTypeConstraint {
129 trait_ref,
130 type_name,
131 ty,
132 })
133 })?;
134 self.innermost_generics_mut()
135 .trait_type_constraints
136 .push(pred);
137 }
138 ClauseKind::ConstArgHasType(..) => {
139 }
143 ClauseKind::WellFormed(_) => {
144 raise_error!(self, span, "Well-formedness clauses are unsupported")
145 }
146 kind => {
147 raise_error!(self, span, "Unsupported clause: {:?}", kind)
148 }
149 }
150 Ok(())
151 }
152
153 pub(crate) fn translate_trait_impl_exprs(
154 &mut self,
155 span: Span,
156 impl_sources: &[hax::ImplExpr],
157 ) -> Result<Vector<TraitClauseId, TraitRef>, Error> {
158 impl_sources
159 .iter()
160 .map(|x| self.translate_trait_impl_expr(span, x))
161 .try_collect()
162 }
163
164 #[tracing::instrument(skip(self, span, impl_expr))]
165 pub(crate) fn translate_trait_impl_expr(
166 &mut self,
167 span: Span,
168 impl_expr: &hax::ImplExpr,
169 ) -> Result<TraitRef, Error> {
170 let trait_decl_ref = self.translate_poly_trait_ref(span, &impl_expr.r#trait)?;
171
172 match self.translate_trait_impl_expr_aux(span, impl_expr, trait_decl_ref.clone()) {
173 Ok(res) => Ok(res),
174 Err(err) => {
175 register_error!(self, span, "Error during trait resolution: {}", &err.msg);
176 Ok(TraitRef {
177 kind: TraitRefKind::Unknown(err.msg),
178 trait_decl_ref,
179 })
180 }
181 }
182 }
183
184 pub(crate) fn translate_trait_impl_expr_aux(
185 &mut self,
186 span: Span,
187 impl_source: &hax::ImplExpr,
188 trait_decl_ref: PolyTraitDeclRef,
189 ) -> Result<TraitRef, Error> {
190 trace!("impl_expr: {:#?}", impl_source);
191 use hax::ImplExprAtom;
192
193 let trait_ref = match &impl_source.r#impl {
194 ImplExprAtom::Concrete {
195 id: impl_def_id,
196 generics,
197 impl_exprs,
198 } => {
199 let impl_id = self.register_trait_impl_id(span, impl_def_id);
200 let generics = self.translate_generic_args(
201 span,
202 generics,
203 impl_exprs,
204 None,
205 GenericsSource::item(impl_id),
206 )?;
207 TraitRef {
208 kind: TraitRefKind::TraitImpl(impl_id, generics),
209 trait_decl_ref,
210 }
211 }
212 ImplExprAtom::SelfImpl {
214 r#trait: trait_ref,
215 path,
216 }
217 | ImplExprAtom::LocalBound {
218 r#trait: trait_ref,
219 path,
220 ..
221 } => {
222 trace!(
223 "impl source (self or clause): param:\n- trait_ref: {:?}\n- path: {:?}",
224 trait_ref,
225 path,
226 );
227 let mut trait_id = match &impl_source.r#impl {
230 ImplExprAtom::SelfImpl { .. } => TraitRefKind::SelfId,
231 ImplExprAtom::LocalBound { index, .. } => {
232 let var = self.lookup_clause_var(span, *index)?;
233 TraitRefKind::Clause(var)
234 }
235 _ => unreachable!(),
236 };
237
238 let mut current_trait_decl_id =
239 self.register_trait_decl_id(span, &trait_ref.hax_skip_binder_ref().def_id);
240
241 for path_elem in path {
243 use hax::ImplExprPathChunk::*;
244 match path_elem {
245 AssocItem {
246 item,
247 generic_args,
248 predicate,
249 index,
250 ..
251 } => {
252 if !generic_args.is_empty() {
253 raise_error!(
254 self,
255 span,
256 "Found unsupported GAT `{}` when resolving trait `{}`",
257 item.name,
258 trait_decl_ref.fmt_with_ctx(&self.into_fmt())
259 )
260 }
261 trait_id = TraitRefKind::ItemClause(
262 Box::new(trait_id),
263 current_trait_decl_id,
264 TraitItemName(item.name.clone()),
265 TraitClauseId::new(*index),
266 );
267 current_trait_decl_id = self.register_trait_decl_id(
268 span,
269 &predicate.hax_skip_binder_ref().trait_ref.def_id,
270 );
271 }
272 Parent {
273 predicate, index, ..
274 } => {
275 trait_id = TraitRefKind::ParentClause(
276 Box::new(trait_id),
277 current_trait_decl_id,
278 TraitClauseId::new(*index),
279 );
280 current_trait_decl_id = self.register_trait_decl_id(
281 span,
282 &predicate.hax_skip_binder_ref().trait_ref.def_id,
283 );
284 }
285 }
286 }
287
288 TraitRef {
291 kind: trait_id,
292 trait_decl_ref,
293 }
294 }
295 ImplExprAtom::Dyn => TraitRef {
296 kind: TraitRefKind::Dyn(trait_decl_ref.clone()),
297 trait_decl_ref,
298 },
299 ImplExprAtom::Builtin {
300 impl_exprs, types, ..
301 } => {
302 let parent_trait_refs = self.translate_trait_impl_exprs(span, &impl_exprs)?;
303 let types = types
304 .iter()
305 .map(|(def_id, ty)| {
306 let item_def = self.hax_def(def_id)?;
307 let ty = self.translate_ty(span, ty)?;
308 let hax::FullDefKind::AssocTy {
309 associated_item, ..
310 } = item_def.kind()
311 else {
312 unreachable!()
313 };
314 let name = TraitItemName(associated_item.name.clone());
315 Ok((name, ty))
316 })
317 .try_collect()?;
318 TraitRef {
319 kind: TraitRefKind::BuiltinOrAuto {
320 trait_decl_ref: trait_decl_ref.clone(),
321 parent_trait_refs,
322 types,
323 },
324 trait_decl_ref,
325 }
326 }
327 ImplExprAtom::Error(msg) => {
328 let trait_ref = TraitRef {
329 kind: TraitRefKind::Unknown(msg.clone()),
330 trait_decl_ref,
331 };
332 if self.error_on_impl_expr_error {
333 register_error!(self, span, "Error during trait resolution: {}", msg);
334 }
335 trait_ref
336 }
337 };
338 Ok(trait_ref)
339 }
340}