hir_ty/next_solver/
mapping.rs

1//! Things useful for mapping to/from Chalk and next-trait-solver types.
2
3use base_db::Crate;
4use chalk_ir::{
5    CanonicalVarKind, CanonicalVarKinds, ForeignDefId, InferenceVar, Substitution, TyVariableKind,
6    WellFormed, fold::Shift, interner::HasInterner,
7};
8use hir_def::{
9    CallableDefId, ConstParamId, FunctionId, GeneralConstId, LifetimeParamId, TypeAliasId,
10    TypeOrConstParamId, TypeParamId, signatures::TraitFlags,
11};
12use hir_def::{GenericDefId, GenericParamId};
13use intern::sym;
14use rustc_type_ir::{
15    AliasTerm, BoundVar, DebruijnIndex, ExistentialProjection, ExistentialTraitRef, Interner as _,
16    OutlivesPredicate, ProjectionPredicate, TypeFoldable, TypeSuperFoldable, TypeVisitable,
17    TypeVisitableExt, UniverseIndex, elaborate,
18    inherent::{BoundVarLike, Clause as _, IntoKind, PlaceholderLike, SliceLike, Ty as _},
19    shift_vars,
20    solve::Goal,
21};
22use salsa::plumbing::FromId;
23use salsa::{Id, plumbing::AsId};
24
25use crate::{
26    ConcreteConst, ConstScalar, ImplTraitId, Interner, MemoryMap,
27    db::{
28        HirDatabase, InternedClosureId, InternedCoroutineId, InternedLifetimeParamId,
29        InternedOpaqueTyId, InternedTypeOrConstParamId,
30    },
31    from_assoc_type_id, from_chalk_trait_id,
32    mapping::ToChalk,
33    next_solver::{
34        Binder, ClauseKind, ConstBytes, TraitPredicate, UnevaluatedConst,
35        interner::{AdtDef, BoundVarKind, BoundVarKinds, DbInterner},
36    },
37    to_assoc_type_id, to_chalk_trait_id, to_foreign_def_id,
38};
39use crate::{
40    from_placeholder_idx, lt_from_placeholder_idx, lt_to_placeholder_idx, to_placeholder_idx,
41};
42
43use super::{
44    BoundExistentialPredicate, BoundExistentialPredicates, BoundRegion, BoundRegionKind, BoundTy,
45    BoundTyKind, Canonical, CanonicalVars, Clause, Clauses, Const, Ctor, EarlyParamRegion,
46    ErrorGuaranteed, ExistentialPredicate, GenericArg, GenericArgs, ParamConst, ParamEnv, ParamTy,
47    Placeholder, PlaceholderConst, PlaceholderRegion, PlaceholderTy, Predicate, PredicateKind,
48    Region, SolverDefId, SubtypePredicate, Term, TraitRef, Ty, Tys, ValueConst, VariancesOf,
49};
50
51// FIXME: This should urgently go (as soon as we finish the migration off Chalk, that is).
52pub fn convert_binder_to_early_binder<'db, T: rustc_type_ir::TypeFoldable<DbInterner<'db>>>(
53    interner: DbInterner<'db>,
54    def: GenericDefId,
55    binder: rustc_type_ir::Binder<DbInterner<'db>, T>,
56) -> rustc_type_ir::EarlyBinder<DbInterner<'db>, T> {
57    let mut folder = BinderToEarlyBinder {
58        interner,
59        debruijn: rustc_type_ir::DebruijnIndex::ZERO,
60        params: crate::generics::generics(interner.db, def).iter_id().collect(),
61    };
62    rustc_type_ir::EarlyBinder::bind(binder.skip_binder().fold_with(&mut folder))
63}
64
65struct BinderToEarlyBinder<'db> {
66    interner: DbInterner<'db>,
67    debruijn: rustc_type_ir::DebruijnIndex,
68    params: Vec<GenericParamId>,
69}
70
71impl<'db> rustc_type_ir::TypeFolder<DbInterner<'db>> for BinderToEarlyBinder<'db> {
72    fn cx(&self) -> DbInterner<'db> {
73        self.interner
74    }
75
76    fn fold_binder<T>(
77        &mut self,
78        t: rustc_type_ir::Binder<DbInterner<'db>, T>,
79    ) -> rustc_type_ir::Binder<DbInterner<'db>, T>
80    where
81        T: TypeFoldable<DbInterner<'db>>,
82    {
83        self.debruijn.shift_in(1);
84        let result = t.super_fold_with(self);
85        self.debruijn.shift_out(1);
86        result
87    }
88
89    fn fold_ty(&mut self, t: Ty<'db>) -> Ty<'db> {
90        match t.kind() {
91            rustc_type_ir::TyKind::Bound(debruijn, bound_ty) if self.debruijn == debruijn => {
92                let var: rustc_type_ir::BoundVar = bound_ty.var();
93                let GenericParamId::TypeParamId(id) = self.params[bound_ty.var.as_usize()] else {
94                    unreachable!()
95                };
96                Ty::new(
97                    self.cx(),
98                    rustc_type_ir::TyKind::Param(ParamTy { index: var.as_u32(), id }),
99                )
100            }
101            _ => t.super_fold_with(self),
102        }
103    }
104
105    fn fold_region(&mut self, r: Region<'db>) -> Region<'db> {
106        match r.kind() {
107            rustc_type_ir::ReBound(debruijn, bound_region) if self.debruijn == debruijn => {
108                let var: rustc_type_ir::BoundVar = bound_region.var();
109                let GenericParamId::LifetimeParamId(id) = self.params[bound_region.var.as_usize()]
110                else {
111                    unreachable!()
112                };
113                Region::new(
114                    self.cx(),
115                    rustc_type_ir::RegionKind::ReEarlyParam(EarlyParamRegion {
116                        index: var.as_u32(),
117                        id,
118                    }),
119                )
120            }
121            _ => r,
122        }
123    }
124
125    fn fold_const(&mut self, c: Const<'db>) -> Const<'db> {
126        match c.kind() {
127            rustc_type_ir::ConstKind::Bound(debruijn, var) if self.debruijn == debruijn => {
128                let GenericParamId::ConstParamId(id) = self.params[var.as_usize()] else {
129                    unreachable!()
130                };
131                Const::new(
132                    self.cx(),
133                    rustc_type_ir::ConstKind::Param(ParamConst { index: var.as_u32(), id }),
134                )
135            }
136            _ => c.super_fold_with(self),
137        }
138    }
139}
140
141pub trait ChalkToNextSolver<'db, Out> {
142    fn to_nextsolver(&self, interner: DbInterner<'db>) -> Out;
143}
144
145impl<'db> ChalkToNextSolver<'db, Ty<'db>> for chalk_ir::Ty<Interner> {
146    fn to_nextsolver(&self, interner: DbInterner<'db>) -> Ty<'db> {
147        Ty::new(
148            interner,
149            match self.kind(Interner) {
150                chalk_ir::TyKind::Adt(adt_id, substitution) => {
151                    let def = AdtDef::new(adt_id.0, interner);
152                    let args = substitution.to_nextsolver(interner);
153                    rustc_type_ir::TyKind::Adt(def, args)
154                }
155                chalk_ir::TyKind::AssociatedType(assoc_type_id, substitution) => {
156                    let def_id = SolverDefId::TypeAliasId(from_assoc_type_id(*assoc_type_id));
157                    let args: GenericArgs<'db> = substitution.to_nextsolver(interner);
158                    let alias_ty = rustc_type_ir::AliasTy::new(interner, def_id, args.iter());
159                    rustc_type_ir::TyKind::Alias(rustc_type_ir::AliasTyKind::Projection, alias_ty)
160                }
161                chalk_ir::TyKind::Scalar(scalar) => match scalar {
162                    chalk_ir::Scalar::Bool => rustc_type_ir::TyKind::Bool,
163                    chalk_ir::Scalar::Char => rustc_type_ir::TyKind::Char,
164                    chalk_ir::Scalar::Int(chalk_ir::IntTy::Isize) => {
165                        rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::Isize)
166                    }
167                    chalk_ir::Scalar::Int(chalk_ir::IntTy::I8) => {
168                        rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I8)
169                    }
170                    chalk_ir::Scalar::Int(chalk_ir::IntTy::I16) => {
171                        rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I16)
172                    }
173                    chalk_ir::Scalar::Int(chalk_ir::IntTy::I32) => {
174                        rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I32)
175                    }
176                    chalk_ir::Scalar::Int(chalk_ir::IntTy::I64) => {
177                        rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I64)
178                    }
179                    chalk_ir::Scalar::Int(chalk_ir::IntTy::I128) => {
180                        rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I128)
181                    }
182                    chalk_ir::Scalar::Uint(chalk_ir::UintTy::Usize) => {
183                        rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::Usize)
184                    }
185                    chalk_ir::Scalar::Uint(chalk_ir::UintTy::U8) => {
186                        rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U8)
187                    }
188                    chalk_ir::Scalar::Uint(chalk_ir::UintTy::U16) => {
189                        rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U16)
190                    }
191                    chalk_ir::Scalar::Uint(chalk_ir::UintTy::U32) => {
192                        rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U32)
193                    }
194                    chalk_ir::Scalar::Uint(chalk_ir::UintTy::U64) => {
195                        rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U64)
196                    }
197                    chalk_ir::Scalar::Uint(chalk_ir::UintTy::U128) => {
198                        rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U128)
199                    }
200                    chalk_ir::Scalar::Float(chalk_ir::FloatTy::F16) => {
201                        rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F16)
202                    }
203                    chalk_ir::Scalar::Float(chalk_ir::FloatTy::F32) => {
204                        rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F32)
205                    }
206                    chalk_ir::Scalar::Float(chalk_ir::FloatTy::F64) => {
207                        rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F64)
208                    }
209                    chalk_ir::Scalar::Float(chalk_ir::FloatTy::F128) => {
210                        rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F128)
211                    }
212                },
213                chalk_ir::TyKind::Tuple(_, substitution) => {
214                    let args = substitution.to_nextsolver(interner);
215                    rustc_type_ir::TyKind::Tuple(args)
216                }
217                chalk_ir::TyKind::Array(ty, len) => rustc_type_ir::TyKind::Array(
218                    ty.to_nextsolver(interner),
219                    len.to_nextsolver(interner),
220                ),
221                chalk_ir::TyKind::Slice(ty) => {
222                    rustc_type_ir::TyKind::Slice(ty.to_nextsolver(interner))
223                }
224                chalk_ir::TyKind::Raw(mutability, ty) => rustc_type_ir::RawPtr(
225                    ty.to_nextsolver(interner),
226                    mutability.to_nextsolver(interner),
227                ),
228                chalk_ir::TyKind::Ref(mutability, lifetime, ty) => rustc_type_ir::TyKind::Ref(
229                    lifetime.to_nextsolver(interner),
230                    ty.to_nextsolver(interner),
231                    mutability.to_nextsolver(interner),
232                ),
233                chalk_ir::TyKind::OpaqueType(def_id, substitution) => {
234                    let id: InternedOpaqueTyId = (*def_id).into();
235                    let args: GenericArgs<'db> = substitution.to_nextsolver(interner);
236                    let alias_ty = rustc_type_ir::AliasTy::new(interner, id.into(), args);
237                    rustc_type_ir::TyKind::Alias(rustc_type_ir::AliasTyKind::Opaque, alias_ty)
238                }
239                chalk_ir::TyKind::FnDef(fn_def_id, substitution) => {
240                    let def_id = CallableDefId::from_chalk(interner.db(), *fn_def_id);
241                    let id: SolverDefId = match def_id {
242                        CallableDefId::FunctionId(id) => id.into(),
243                        CallableDefId::StructId(id) => SolverDefId::Ctor(Ctor::Struct(id)),
244                        CallableDefId::EnumVariantId(id) => SolverDefId::Ctor(Ctor::Enum(id)),
245                    };
246                    rustc_type_ir::TyKind::FnDef(id, substitution.to_nextsolver(interner))
247                }
248                chalk_ir::TyKind::Str => rustc_type_ir::TyKind::Str,
249                chalk_ir::TyKind::Never => rustc_type_ir::TyKind::Never,
250                chalk_ir::TyKind::Closure(closure_id, substitution) => {
251                    let id: InternedClosureId = (*closure_id).into();
252                    rustc_type_ir::TyKind::Closure(id.into(), substitution.to_nextsolver(interner))
253                }
254                chalk_ir::TyKind::Coroutine(coroutine_id, substitution) => {
255                    let id: InternedCoroutineId = (*coroutine_id).into();
256                    rustc_type_ir::TyKind::Coroutine(
257                        id.into(),
258                        substitution.to_nextsolver(interner),
259                    )
260                }
261                chalk_ir::TyKind::CoroutineWitness(coroutine_id, substitution) => {
262                    let id: InternedCoroutineId = (*coroutine_id).into();
263                    rustc_type_ir::TyKind::CoroutineWitness(
264                        id.into(),
265                        substitution.to_nextsolver(interner),
266                    )
267                }
268                chalk_ir::TyKind::Foreign(foreign_def_id) => rustc_type_ir::TyKind::Foreign(
269                    SolverDefId::TypeAliasId(crate::from_foreign_def_id(*foreign_def_id)),
270                ),
271                chalk_ir::TyKind::Error => rustc_type_ir::TyKind::Error(ErrorGuaranteed),
272                chalk_ir::TyKind::Dyn(dyn_ty) => {
273                    // exists<type> { for<...> ^1.0: ... }
274                    let bounds = BoundExistentialPredicates::new_from_iter(
275                        interner,
276                        dyn_ty.bounds.skip_binders().iter(Interner).filter_map(|pred| {
277                            // for<...> ^1.0: ...
278                            let (val, binders) = pred.clone().into_value_and_skipped_binders();
279                            let bound_vars = binders.to_nextsolver(interner);
280                            let clause = match val {
281                                chalk_ir::WhereClause::Implemented(trait_ref) => {
282                                    let trait_id = from_chalk_trait_id(trait_ref.trait_id);
283                                    if interner
284                                        .db()
285                                        .trait_signature(trait_id)
286                                        .flags
287                                        .contains(TraitFlags::AUTO)
288                                    {
289                                        ExistentialPredicate::AutoTrait(SolverDefId::TraitId(
290                                            trait_id,
291                                        ))
292                                    } else {
293                                        let def_id = SolverDefId::TraitId(trait_id);
294                                        let args = GenericArgs::new_from_iter(
295                                            interner,
296                                            trait_ref
297                                                .substitution
298                                                .iter(Interner)
299                                                .skip(1)
300                                                .map(|a| a.clone().shifted_out(Interner).unwrap())
301                                                .map(|a| a.to_nextsolver(interner)),
302                                        );
303                                        let trait_ref = ExistentialTraitRef::new_from_args(
304                                            interner, def_id, args,
305                                        );
306                                        ExistentialPredicate::Trait(trait_ref)
307                                    }
308                                }
309                                chalk_ir::WhereClause::AliasEq(alias_eq) => {
310                                    let (def_id, args) = match &alias_eq.alias {
311                                        chalk_ir::AliasTy::Projection(projection) => {
312                                            let id =
313                                                from_assoc_type_id(projection.associated_ty_id);
314                                            let def_id = SolverDefId::TypeAliasId(id);
315                                            let generics = interner.generics_of(def_id);
316                                            let parent_len = generics.parent_count;
317                                            let substs = projection.substitution.iter(Interner).skip(1);
318
319                                            let args = GenericArgs::new_from_iter(
320                                                interner,
321                                                substs
322                                                    .map(|a| {
323                                                        a.clone().shifted_out(Interner).unwrap()
324                                                    })
325                                                    .map(|a| a.to_nextsolver(interner)),
326                                            );
327                                            (def_id, args)
328                                        }
329                                        chalk_ir::AliasTy::Opaque(opaque_ty) => {
330                                            panic!("Invalid ExistentialPredicate (opaques can't be named).");
331                                        }
332                                    };
333                                    let term = alias_eq
334                                        .ty
335                                        .clone()
336                                        .shifted_out(Interner)
337                                        .unwrap()
338                                        .to_nextsolver(interner)
339                                        .into();
340                                    let projection = ExistentialProjection::new_from_args(
341                                        interner, def_id, args, term,
342                                    );
343                                    ExistentialPredicate::Projection(projection)
344                                }
345                                chalk_ir::WhereClause::LifetimeOutlives(lifetime_outlives) => {
346                                    return None;
347                                }
348                                chalk_ir::WhereClause::TypeOutlives(type_outlives) => return None,
349                            };
350
351                            Some(Binder::bind_with_vars(clause, bound_vars))
352                        }),
353                    );
354                    let region = dyn_ty.lifetime.to_nextsolver(interner);
355                    let kind = rustc_type_ir::DynKind::Dyn;
356                    rustc_type_ir::TyKind::Dynamic(bounds, region, kind)
357                }
358                chalk_ir::TyKind::Alias(alias_ty) => match alias_ty {
359                    chalk_ir::AliasTy::Projection(projection_ty) => {
360                        let def_id = SolverDefId::TypeAliasId(from_assoc_type_id(
361                            projection_ty.associated_ty_id,
362                        ));
363                        let alias_ty = rustc_type_ir::AliasTy::new_from_args(
364                            interner,
365                            def_id,
366                            projection_ty.substitution.to_nextsolver(interner),
367                        );
368                        rustc_type_ir::TyKind::Alias(
369                            rustc_type_ir::AliasTyKind::Projection,
370                            alias_ty,
371                        )
372                    }
373                    chalk_ir::AliasTy::Opaque(opaque_ty) => {
374                        let id: InternedOpaqueTyId = opaque_ty.opaque_ty_id.into();
375                        let def_id = SolverDefId::InternedOpaqueTyId(id);
376                        let alias_ty = rustc_type_ir::AliasTy::new_from_args(
377                            interner,
378                            def_id,
379                            opaque_ty.substitution.to_nextsolver(interner),
380                        );
381                        rustc_type_ir::TyKind::Alias(rustc_type_ir::AliasTyKind::Opaque, alias_ty)
382                    }
383                },
384                chalk_ir::TyKind::Function(fn_pointer) => {
385                    let sig_tys = fn_pointer.clone().into_binders(Interner).to_nextsolver(interner);
386                    let header = rustc_type_ir::FnHeader {
387                        abi: fn_pointer.sig.abi,
388                        c_variadic: fn_pointer.sig.variadic,
389                        safety: match fn_pointer.sig.safety {
390                            chalk_ir::Safety::Safe => super::abi::Safety::Safe,
391                            chalk_ir::Safety::Unsafe => super::abi::Safety::Unsafe,
392                        },
393                    };
394
395                    rustc_type_ir::TyKind::FnPtr(sig_tys, header)
396                }
397                // The schema here is quite confusing.
398                // The new solver, like rustc, uses `Param` and `EarlyBinder` for generic params. It uses `BoundVar`
399                // and `Placeholder` together with `Binder` for HRTB, which we mostly don't handle.
400                // Chalk uses `Placeholder` for generic params and `BoundVar` quite liberally, and this is quite a
401                // problem. `chalk_ir::TyKind::BoundVar` can represent either HRTB or generic params, depending on the
402                // context. When returned from signature queries, the outer `Binders` represent the generic params.
403                // But there are also inner `Binders` for HRTB.
404                // AFAIK there is no way to tell which of the meanings is relevant, so we just use `rustc_type_ir::Bound`
405                // here, and hope for the best. If you are working with new solver types, therefore, use the new solver
406                // lower queries.
407                // Hopefully sooner than later Chalk will be ripped from the codebase and we can avoid that problem.
408                // For details about the rustc setup, read: https://rustc-dev-guide.rust-lang.org/generic_parameters_summary.html
409                // and the following chapters.
410                chalk_ir::TyKind::Placeholder(placeholder_index) => {
411                    let (id, index) = from_placeholder_idx(interner.db, *placeholder_index);
412                    rustc_type_ir::TyKind::Param(ParamTy {
413                        id: TypeParamId::from_unchecked(id),
414                        index,
415                    })
416                }
417                chalk_ir::TyKind::BoundVar(bound_var) => rustc_type_ir::TyKind::Bound(
418                    bound_var.debruijn.to_nextsolver(interner),
419                    BoundTy {
420                        var: rustc_type_ir::BoundVar::from_usize(bound_var.index),
421                        kind: BoundTyKind::Anon,
422                    },
423                ),
424                chalk_ir::TyKind::InferenceVar(inference_var, ty_variable_kind) => {
425                    rustc_type_ir::TyKind::Infer(
426                        (*inference_var, *ty_variable_kind).to_nextsolver(interner),
427                    )
428                }
429            },
430        )
431    }
432}
433
434impl<'db> ChalkToNextSolver<'db, Region<'db>> for chalk_ir::Lifetime<Interner> {
435    fn to_nextsolver(&self, interner: DbInterner<'db>) -> Region<'db> {
436        Region::new(
437            interner,
438            match self.data(Interner) {
439                chalk_ir::LifetimeData::BoundVar(bound_var) => rustc_type_ir::RegionKind::ReBound(
440                    bound_var.debruijn.to_nextsolver(interner),
441                    BoundRegion {
442                        var: rustc_type_ir::BoundVar::from_u32(bound_var.index as u32),
443                        kind: BoundRegionKind::Anon,
444                    },
445                ),
446                chalk_ir::LifetimeData::InferenceVar(inference_var) => {
447                    rustc_type_ir::RegionKind::ReVar(rustc_type_ir::RegionVid::from_u32(
448                        inference_var.index(),
449                    ))
450                }
451                chalk_ir::LifetimeData::Placeholder(placeholder_index) => {
452                    let (id, index) = lt_from_placeholder_idx(interner.db, *placeholder_index);
453                    rustc_type_ir::RegionKind::ReEarlyParam(EarlyParamRegion { id, index })
454                }
455                chalk_ir::LifetimeData::Static => rustc_type_ir::RegionKind::ReStatic,
456                chalk_ir::LifetimeData::Erased => rustc_type_ir::RegionKind::ReErased,
457                chalk_ir::LifetimeData::Phantom(_, _) => {
458                    unreachable!()
459                }
460                chalk_ir::LifetimeData::Error => {
461                    rustc_type_ir::RegionKind::ReError(ErrorGuaranteed)
462                }
463            },
464        )
465    }
466}
467
468impl<'db> ChalkToNextSolver<'db, Const<'db>> for chalk_ir::Const<Interner> {
469    fn to_nextsolver(&self, interner: DbInterner<'db>) -> Const<'db> {
470        let data = self.data(Interner);
471        Const::new(
472            interner,
473            match &data.value {
474                chalk_ir::ConstValue::BoundVar(bound_var) => rustc_type_ir::ConstKind::Bound(
475                    bound_var.debruijn.to_nextsolver(interner),
476                    rustc_type_ir::BoundVar::from_usize(bound_var.index),
477                ),
478                chalk_ir::ConstValue::InferenceVar(inference_var) => {
479                    rustc_type_ir::ConstKind::Infer(rustc_type_ir::InferConst::Var(
480                        rustc_type_ir::ConstVid::from_u32(inference_var.index()),
481                    ))
482                }
483                chalk_ir::ConstValue::Placeholder(placeholder_index) => {
484                    let (id, index) = from_placeholder_idx(interner.db, *placeholder_index);
485                    rustc_type_ir::ConstKind::Param(ParamConst {
486                        id: ConstParamId::from_unchecked(id),
487                        index,
488                    })
489                }
490                chalk_ir::ConstValue::Concrete(concrete_const) => match &concrete_const.interned {
491                    ConstScalar::Bytes(bytes, memory) => {
492                        rustc_type_ir::ConstKind::Value(ValueConst::new(
493                            data.ty.to_nextsolver(interner),
494                            ConstBytes(bytes.clone(), memory.clone()),
495                        ))
496                    }
497                    ConstScalar::UnevaluatedConst(c, subst) => {
498                        let def = match *c {
499                            GeneralConstId::ConstId(id) => SolverDefId::ConstId(id),
500                            GeneralConstId::StaticId(id) => SolverDefId::StaticId(id),
501                        };
502                        let args = subst.to_nextsolver(interner);
503                        rustc_type_ir::ConstKind::Unevaluated(UnevaluatedConst::new(def, args))
504                    }
505                    ConstScalar::Unknown => rustc_type_ir::ConstKind::Error(ErrorGuaranteed),
506                },
507            },
508        )
509    }
510}
511
512impl<'db> ChalkToNextSolver<'db, rustc_type_ir::FnSigTys<DbInterner<'db>>>
513    for chalk_ir::FnSubst<Interner>
514{
515    fn to_nextsolver(&self, interner: DbInterner<'db>) -> rustc_type_ir::FnSigTys<DbInterner<'db>> {
516        rustc_type_ir::FnSigTys {
517            inputs_and_output: Tys::new_from_iter(
518                interner,
519                self.0.iter(Interner).map(|g| g.assert_ty_ref(Interner).to_nextsolver(interner)),
520            ),
521        }
522    }
523}
524
525impl<
526    'db,
527    U: TypeVisitable<DbInterner<'db>>,
528    T: Clone + ChalkToNextSolver<'db, U> + HasInterner<Interner = Interner>,
529> ChalkToNextSolver<'db, rustc_type_ir::Binder<DbInterner<'db>, U>> for chalk_ir::Binders<T>
530{
531    fn to_nextsolver(
532        &self,
533        interner: DbInterner<'db>,
534    ) -> rustc_type_ir::Binder<DbInterner<'db>, U> {
535        let (val, binders) = self.clone().into_value_and_skipped_binders();
536        rustc_type_ir::Binder::bind_with_vars(
537            val.to_nextsolver(interner),
538            binders.to_nextsolver(interner),
539        )
540    }
541}
542
543impl<'db> ChalkToNextSolver<'db, BoundVarKinds> for chalk_ir::VariableKinds<Interner> {
544    fn to_nextsolver(&self, interner: DbInterner<'db>) -> BoundVarKinds {
545        BoundVarKinds::new_from_iter(
546            interner,
547            self.iter(Interner).map(|v| v.to_nextsolver(interner)),
548        )
549    }
550}
551
552impl<'db> ChalkToNextSolver<'db, BoundVarKind> for chalk_ir::VariableKind<Interner> {
553    fn to_nextsolver(&self, interner: DbInterner<'db>) -> BoundVarKind {
554        match self {
555            chalk_ir::VariableKind::Ty(_ty_variable_kind) => BoundVarKind::Ty(BoundTyKind::Anon),
556            chalk_ir::VariableKind::Lifetime => BoundVarKind::Region(BoundRegionKind::Anon),
557            chalk_ir::VariableKind::Const(_ty) => BoundVarKind::Const,
558        }
559    }
560}
561
562impl<'db> ChalkToNextSolver<'db, GenericArg<'db>> for chalk_ir::GenericArg<Interner> {
563    fn to_nextsolver(&self, interner: DbInterner<'db>) -> GenericArg<'db> {
564        match self.data(Interner) {
565            chalk_ir::GenericArgData::Ty(ty) => ty.to_nextsolver(interner).into(),
566            chalk_ir::GenericArgData::Lifetime(lifetime) => lifetime.to_nextsolver(interner).into(),
567            chalk_ir::GenericArgData::Const(const_) => const_.to_nextsolver(interner).into(),
568        }
569    }
570}
571impl<'db> ChalkToNextSolver<'db, GenericArgs<'db>> for chalk_ir::Substitution<Interner> {
572    fn to_nextsolver(&self, interner: DbInterner<'db>) -> GenericArgs<'db> {
573        GenericArgs::new_from_iter(
574            interner,
575            self.iter(Interner).map(|arg| -> GenericArg<'db> { arg.to_nextsolver(interner) }),
576        )
577    }
578}
579
580impl<'db> ChalkToNextSolver<'db, Tys<'db>> for chalk_ir::Substitution<Interner> {
581    fn to_nextsolver(&self, interner: DbInterner<'db>) -> Tys<'db> {
582        Tys::new_from_iter(
583            interner,
584            self.iter(Interner).map(|arg| -> Ty<'db> {
585                match arg.data(Interner) {
586                    chalk_ir::GenericArgData::Ty(ty) => ty.to_nextsolver(interner),
587                    chalk_ir::GenericArgData::Lifetime(_) => unreachable!(),
588                    chalk_ir::GenericArgData::Const(_) => unreachable!(),
589                }
590            }),
591        )
592    }
593}
594
595impl<'db> ChalkToNextSolver<'db, rustc_type_ir::DebruijnIndex> for chalk_ir::DebruijnIndex {
596    fn to_nextsolver(&self, interner: DbInterner<'db>) -> rustc_type_ir::DebruijnIndex {
597        rustc_type_ir::DebruijnIndex::from_u32(self.depth())
598    }
599}
600
601impl<'db> ChalkToNextSolver<'db, rustc_type_ir::UniverseIndex> for chalk_ir::UniverseIndex {
602    fn to_nextsolver(&self, interner: DbInterner<'db>) -> rustc_type_ir::UniverseIndex {
603        rustc_type_ir::UniverseIndex::from_u32(self.counter as u32)
604    }
605}
606
607impl<'db> ChalkToNextSolver<'db, rustc_type_ir::InferTy>
608    for (chalk_ir::InferenceVar, chalk_ir::TyVariableKind)
609{
610    fn to_nextsolver(&self, interner: DbInterner<'db>) -> rustc_type_ir::InferTy {
611        match self.1 {
612            chalk_ir::TyVariableKind::General => {
613                rustc_type_ir::InferTy::TyVar(rustc_type_ir::TyVid::from_u32(self.0.index()))
614            }
615            chalk_ir::TyVariableKind::Integer => {
616                rustc_type_ir::InferTy::IntVar(rustc_type_ir::IntVid::from_u32(self.0.index()))
617            }
618            chalk_ir::TyVariableKind::Float => {
619                rustc_type_ir::InferTy::FloatVar(rustc_type_ir::FloatVid::from_u32(self.0.index()))
620            }
621        }
622    }
623}
624
625impl<'db> ChalkToNextSolver<'db, rustc_ast_ir::Mutability> for chalk_ir::Mutability {
626    fn to_nextsolver(&self, interner: DbInterner<'db>) -> rustc_ast_ir::Mutability {
627        match self {
628            chalk_ir::Mutability::Mut => rustc_ast_ir::Mutability::Mut,
629            chalk_ir::Mutability::Not => rustc_ast_ir::Mutability::Not,
630        }
631    }
632}
633
634impl<'db> ChalkToNextSolver<'db, rustc_type_ir::Variance> for crate::Variance {
635    fn to_nextsolver(&self, interner: DbInterner<'db>) -> rustc_type_ir::Variance {
636        match self {
637            crate::Variance::Covariant => rustc_type_ir::Variance::Covariant,
638            crate::Variance::Invariant => rustc_type_ir::Variance::Invariant,
639            crate::Variance::Contravariant => rustc_type_ir::Variance::Contravariant,
640            crate::Variance::Bivariant => rustc_type_ir::Variance::Bivariant,
641        }
642    }
643}
644
645impl<'db> ChalkToNextSolver<'db, Canonical<'db, Goal<DbInterner<'db>, Predicate<'db>>>>
646    for chalk_ir::Canonical<chalk_ir::InEnvironment<chalk_ir::Goal<Interner>>>
647{
648    fn to_nextsolver(
649        &self,
650        interner: DbInterner<'db>,
651    ) -> Canonical<'db, Goal<DbInterner<'db>, Predicate<'db>>> {
652        let param_env = self.value.environment.to_nextsolver(interner);
653        let variables = CanonicalVars::new_from_iter(
654            interner,
655            self.binders.iter(Interner).map(|k| match &k.kind {
656                chalk_ir::VariableKind::Ty(ty_variable_kind) => match ty_variable_kind {
657                    TyVariableKind::General => rustc_type_ir::CanonicalVarKind::Ty(
658                        rustc_type_ir::CanonicalTyVarKind::General(UniverseIndex::ROOT),
659                    ),
660                    TyVariableKind::Integer => {
661                        rustc_type_ir::CanonicalVarKind::Ty(rustc_type_ir::CanonicalTyVarKind::Int)
662                    }
663                    TyVariableKind::Float => rustc_type_ir::CanonicalVarKind::Ty(
664                        rustc_type_ir::CanonicalTyVarKind::Float,
665                    ),
666                },
667                chalk_ir::VariableKind::Lifetime => {
668                    rustc_type_ir::CanonicalVarKind::Region(UniverseIndex::ROOT)
669                }
670                chalk_ir::VariableKind::Const(ty) => {
671                    rustc_type_ir::CanonicalVarKind::Const(UniverseIndex::ROOT)
672                }
673            }),
674        );
675        Canonical {
676            max_universe: UniverseIndex::ROOT,
677            value: Goal::new(interner, param_env, self.value.goal.to_nextsolver(interner)),
678            variables,
679        }
680    }
681}
682
683impl<'db> ChalkToNextSolver<'db, Predicate<'db>> for chalk_ir::Goal<Interner> {
684    fn to_nextsolver(&self, interner: DbInterner<'db>) -> Predicate<'db> {
685        match self.data(Interner) {
686            chalk_ir::GoalData::Quantified(quantifier_kind, binders) => {
687                if !binders.binders.is_empty(Interner) {
688                    panic!("Should not be constructed.");
689                }
690                let (val, _) = binders.clone().into_value_and_skipped_binders();
691                val.shifted_out(Interner).unwrap().to_nextsolver(interner)
692            }
693            chalk_ir::GoalData::Implies(program_clauses, goal) => {
694                panic!("Should not be constructed.")
695            }
696            chalk_ir::GoalData::All(goals) => panic!("Should not be constructed."),
697            chalk_ir::GoalData::Not(goal) => panic!("Should not be constructed."),
698            chalk_ir::GoalData::EqGoal(eq_goal) => panic!("Should not be constructed."),
699            chalk_ir::GoalData::SubtypeGoal(subtype_goal) => {
700                let subtype_predicate = SubtypePredicate {
701                    a: subtype_goal.a.to_nextsolver(interner),
702                    b: subtype_goal.b.to_nextsolver(interner),
703                    a_is_expected: true,
704                };
705                let pred_kind = PredicateKind::Subtype(subtype_predicate);
706                let pred_kind = Binder::bind_with_vars(
707                    shift_vars(interner, pred_kind, 1),
708                    BoundVarKinds::new_from_iter(interner, []),
709                );
710                Predicate::new(interner, pred_kind)
711            }
712            chalk_ir::GoalData::DomainGoal(domain_goal) => {
713                let pred_kind = domain_goal.to_nextsolver(interner);
714                let pred_kind = Binder::bind_with_vars(
715                    shift_vars(interner, pred_kind, 1),
716                    BoundVarKinds::new_from_iter(interner, []),
717                );
718                Predicate::new(interner, pred_kind)
719            }
720            chalk_ir::GoalData::CannotProve => panic!("Should not be constructed."),
721        }
722    }
723}
724
725impl<'db> ChalkToNextSolver<'db, ParamEnv<'db>> for chalk_ir::Environment<Interner> {
726    fn to_nextsolver(&self, interner: DbInterner<'db>) -> ParamEnv<'db> {
727        let clauses = Clauses::new_from_iter(
728            interner,
729            self.clauses.iter(Interner).map(|c| c.to_nextsolver(interner)),
730        );
731        let clauses =
732            Clauses::new_from_iter(interner, elaborate::elaborate(interner, clauses.iter()));
733        ParamEnv { clauses }
734    }
735}
736
737impl<'db> ChalkToNextSolver<'db, Clause<'db>> for chalk_ir::ProgramClause<Interner> {
738    fn to_nextsolver(&self, interner: DbInterner<'db>) -> Clause<'db> {
739        Clause(Predicate::new(interner, self.data(Interner).0.to_nextsolver(interner)))
740    }
741}
742
743impl<'db> ChalkToNextSolver<'db, PredicateKind<'db>>
744    for chalk_ir::ProgramClauseImplication<Interner>
745{
746    fn to_nextsolver(&self, interner: DbInterner<'db>) -> PredicateKind<'db> {
747        assert!(self.conditions.is_empty(Interner));
748        assert!(self.constraints.is_empty(Interner));
749        self.consequence.to_nextsolver(interner)
750    }
751}
752
753impl<'db> ChalkToNextSolver<'db, PredicateKind<'db>> for chalk_ir::DomainGoal<Interner> {
754    fn to_nextsolver(&self, interner: DbInterner<'db>) -> PredicateKind<'db> {
755        match self {
756            chalk_ir::DomainGoal::Holds(where_clause) => match where_clause {
757                chalk_ir::WhereClause::Implemented(trait_ref) => {
758                    let predicate = TraitPredicate {
759                        trait_ref: trait_ref.to_nextsolver(interner),
760                        polarity: rustc_type_ir::PredicatePolarity::Positive,
761                    };
762                    PredicateKind::Clause(ClauseKind::Trait(predicate))
763                }
764                chalk_ir::WhereClause::AliasEq(alias_eq) => match &alias_eq.alias {
765                    chalk_ir::AliasTy::Projection(p) => {
766                        let def_id =
767                            SolverDefId::TypeAliasId(from_assoc_type_id(p.associated_ty_id));
768                        let args = p.substitution.to_nextsolver(interner);
769                        let term: Ty<'db> = alias_eq.ty.to_nextsolver(interner);
770                        let term: Term<'db> = term.into();
771                        let predicate = ProjectionPredicate {
772                            projection_term: AliasTerm::new_from_args(interner, def_id, args),
773                            term,
774                        };
775                        PredicateKind::Clause(ClauseKind::Projection(predicate))
776                    }
777                    chalk_ir::AliasTy::Opaque(opaque) => {
778                        let id: InternedOpaqueTyId = opaque.opaque_ty_id.into();
779                        let def_id = SolverDefId::InternedOpaqueTyId(id);
780                        let args = opaque.substitution.to_nextsolver(interner);
781                        let term: Ty<'db> = alias_eq.ty.to_nextsolver(interner);
782                        let term: Term<'db> = term.into();
783                        let opaque_ty = Ty::new(
784                            interner,
785                            rustc_type_ir::TyKind::Alias(
786                                rustc_type_ir::AliasTyKind::Opaque,
787                                rustc_type_ir::AliasTy::new_from_args(interner, def_id, args),
788                            ),
789                        )
790                        .into();
791                        PredicateKind::AliasRelate(
792                            opaque_ty,
793                            term,
794                            rustc_type_ir::AliasRelationDirection::Equate,
795                        )
796                    }
797                },
798                chalk_ir::WhereClause::LifetimeOutlives(lifetime_outlives) => {
799                    let predicate = OutlivesPredicate(
800                        lifetime_outlives.a.to_nextsolver(interner),
801                        lifetime_outlives.b.to_nextsolver(interner),
802                    );
803                    PredicateKind::Clause(ClauseKind::RegionOutlives(predicate))
804                }
805                chalk_ir::WhereClause::TypeOutlives(type_outlives) => {
806                    let predicate = OutlivesPredicate(
807                        type_outlives.ty.to_nextsolver(interner),
808                        type_outlives.lifetime.to_nextsolver(interner),
809                    );
810                    PredicateKind::Clause(ClauseKind::TypeOutlives(predicate))
811                }
812            },
813            chalk_ir::DomainGoal::Normalize(normalize) => {
814                let proj_ty = match &normalize.alias {
815                    chalk_ir::AliasTy::Projection(proj) => proj,
816                    _ => unimplemented!(),
817                };
818                let args: GenericArgs<'db> = proj_ty.substitution.to_nextsolver(interner);
819                let alias = Ty::new(
820                    interner,
821                    rustc_type_ir::TyKind::Alias(
822                        rustc_type_ir::AliasTyKind::Projection,
823                        rustc_type_ir::AliasTy::new(
824                            interner,
825                            from_assoc_type_id(proj_ty.associated_ty_id).into(),
826                            args,
827                        ),
828                    ),
829                )
830                .into();
831                let term = normalize.ty.to_nextsolver(interner).into();
832                PredicateKind::AliasRelate(
833                    alias,
834                    term,
835                    rustc_type_ir::AliasRelationDirection::Equate,
836                )
837            }
838            chalk_ir::DomainGoal::WellFormed(well_formed) => {
839                let term = match well_formed {
840                    WellFormed::Trait(_) => panic!("Should not be constructed."),
841                    WellFormed::Ty(ty) => Term::Ty(ty.to_nextsolver(interner)),
842                };
843                PredicateKind::Clause(rustc_type_ir::ClauseKind::WellFormed(term))
844            }
845            chalk_ir::DomainGoal::FromEnv(from_env) => match from_env {
846                chalk_ir::FromEnv::Trait(trait_ref) => {
847                    let predicate = TraitPredicate {
848                        trait_ref: trait_ref.to_nextsolver(interner),
849                        polarity: rustc_type_ir::PredicatePolarity::Positive,
850                    };
851                    PredicateKind::Clause(ClauseKind::Trait(predicate))
852                }
853                chalk_ir::FromEnv::Ty(ty) => PredicateKind::Clause(ClauseKind::WellFormed(
854                    Term::Ty(ty.to_nextsolver(interner)),
855                )),
856            },
857            chalk_ir::DomainGoal::IsLocal(ty) => panic!("Should not be constructed."),
858            chalk_ir::DomainGoal::IsUpstream(ty) => panic!("Should not be constructed."),
859            chalk_ir::DomainGoal::IsFullyVisible(ty) => panic!("Should not be constructed."),
860            chalk_ir::DomainGoal::LocalImplAllowed(trait_ref) => {
861                panic!("Should not be constructed.")
862            }
863            chalk_ir::DomainGoal::Compatible => panic!("Should not be constructed."),
864            chalk_ir::DomainGoal::DownstreamType(ty) => panic!("Should not be constructed."),
865            chalk_ir::DomainGoal::Reveal => panic!("Should not be constructed."),
866            chalk_ir::DomainGoal::ObjectSafe(trait_id) => panic!("Should not be constructed."),
867        }
868    }
869}
870
871impl<'db> ChalkToNextSolver<'db, TraitRef<'db>> for chalk_ir::TraitRef<Interner> {
872    fn to_nextsolver(&self, interner: DbInterner<'db>) -> TraitRef<'db> {
873        let args = self.substitution.to_nextsolver(interner);
874        TraitRef::new_from_args(
875            interner,
876            SolverDefId::TraitId(from_chalk_trait_id(self.trait_id)),
877            args,
878        )
879    }
880}
881
882impl<'db> ChalkToNextSolver<'db, PredicateKind<'db>> for chalk_ir::WhereClause<Interner> {
883    fn to_nextsolver(&self, interner: DbInterner<'db>) -> PredicateKind<'db> {
884        match self {
885            chalk_ir::WhereClause::Implemented(trait_ref) => {
886                let predicate = TraitPredicate {
887                    trait_ref: trait_ref.to_nextsolver(interner),
888                    polarity: rustc_type_ir::PredicatePolarity::Positive,
889                };
890                PredicateKind::Clause(ClauseKind::Trait(predicate))
891            }
892            chalk_ir::WhereClause::AliasEq(alias_eq) => {
893                let projection = match &alias_eq.alias {
894                    chalk_ir::AliasTy::Projection(p) => p,
895                    _ => unimplemented!(),
896                };
897                let def_id =
898                    SolverDefId::TypeAliasId(from_assoc_type_id(projection.associated_ty_id));
899                let args = projection.substitution.to_nextsolver(interner);
900                let term: Ty<'db> = alias_eq.ty.to_nextsolver(interner);
901                let term: Term<'db> = term.into();
902                let predicate = ProjectionPredicate {
903                    projection_term: AliasTerm::new_from_args(interner, def_id, args),
904                    term,
905                };
906                PredicateKind::Clause(ClauseKind::Projection(predicate))
907            }
908            chalk_ir::WhereClause::TypeOutlives(type_outlives) => {
909                let ty = type_outlives.ty.to_nextsolver(interner);
910                let r = type_outlives.lifetime.to_nextsolver(interner);
911                PredicateKind::Clause(ClauseKind::TypeOutlives(OutlivesPredicate(ty, r)))
912            }
913            chalk_ir::WhereClause::LifetimeOutlives(lifetime_outlives) => {
914                let a = lifetime_outlives.a.to_nextsolver(interner);
915                let b = lifetime_outlives.b.to_nextsolver(interner);
916                PredicateKind::Clause(ClauseKind::RegionOutlives(OutlivesPredicate(a, b)))
917            }
918        }
919    }
920}
921
922pub fn convert_canonical_args_for_result<'db>(
923    interner: DbInterner<'db>,
924    args: Canonical<'db, Vec<GenericArg<'db>>>,
925) -> chalk_ir::Canonical<chalk_ir::ConstrainedSubst<Interner>> {
926    let Canonical { value, variables, max_universe } = args;
927    let binders = CanonicalVarKinds::from_iter(
928        Interner,
929        variables.iter().map(|v| match v {
930            rustc_type_ir::CanonicalVarKind::Ty(rustc_type_ir::CanonicalTyVarKind::General(_)) => {
931                CanonicalVarKind::new(
932                    chalk_ir::VariableKind::Ty(TyVariableKind::General),
933                    chalk_ir::UniverseIndex::ROOT,
934                )
935            }
936            rustc_type_ir::CanonicalVarKind::Ty(rustc_type_ir::CanonicalTyVarKind::Int) => {
937                CanonicalVarKind::new(
938                    chalk_ir::VariableKind::Ty(TyVariableKind::Integer),
939                    chalk_ir::UniverseIndex::ROOT,
940                )
941            }
942            rustc_type_ir::CanonicalVarKind::Ty(rustc_type_ir::CanonicalTyVarKind::Float) => {
943                CanonicalVarKind::new(
944                    chalk_ir::VariableKind::Ty(TyVariableKind::Float),
945                    chalk_ir::UniverseIndex::ROOT,
946                )
947            }
948            rustc_type_ir::CanonicalVarKind::Region(universe_index) => CanonicalVarKind::new(
949                chalk_ir::VariableKind::Lifetime,
950                chalk_ir::UniverseIndex::ROOT,
951            ),
952            rustc_type_ir::CanonicalVarKind::Const(universe_index) => CanonicalVarKind::new(
953                chalk_ir::VariableKind::Const(crate::TyKind::Error.intern(Interner)),
954                chalk_ir::UniverseIndex::ROOT,
955            ),
956            rustc_type_ir::CanonicalVarKind::PlaceholderTy(_) => unimplemented!(),
957            rustc_type_ir::CanonicalVarKind::PlaceholderRegion(_) => unimplemented!(),
958            rustc_type_ir::CanonicalVarKind::PlaceholderConst(_) => unimplemented!(),
959        }),
960    );
961    chalk_ir::Canonical {
962        binders,
963        value: chalk_ir::ConstrainedSubst {
964            constraints: chalk_ir::Constraints::empty(Interner),
965            subst: convert_args_for_result(interner, &value),
966        },
967    }
968}
969
970pub fn convert_args_for_result<'db>(
971    interner: DbInterner<'db>,
972    args: &[GenericArg<'db>],
973) -> crate::Substitution {
974    let mut substs = Vec::with_capacity(args.len());
975    for arg in args {
976        match (*arg).kind() {
977            rustc_type_ir::GenericArgKind::Type(ty) => {
978                let ty = convert_ty_for_result(interner, ty);
979                substs.push(chalk_ir::GenericArgData::Ty(ty).intern(Interner));
980            }
981            rustc_type_ir::GenericArgKind::Lifetime(region) => {
982                let lifetime = convert_region_for_result(interner, region);
983                substs.push(chalk_ir::GenericArgData::Lifetime(lifetime).intern(Interner));
984            }
985            rustc_type_ir::GenericArgKind::Const(const_) => {
986                substs.push(
987                    chalk_ir::GenericArgData::Const(convert_const_for_result(interner, const_))
988                        .intern(Interner),
989                );
990            }
991        }
992    }
993    Substitution::from_iter(Interner, substs)
994}
995
996pub(crate) fn convert_ty_for_result<'db>(interner: DbInterner<'db>, ty: Ty<'db>) -> crate::Ty {
997    use crate::{Scalar, TyKind};
998    use chalk_ir::{FloatTy, IntTy, UintTy};
999    match ty.kind() {
1000        rustc_type_ir::TyKind::Bool => TyKind::Scalar(Scalar::Bool),
1001        rustc_type_ir::TyKind::Char => TyKind::Scalar(Scalar::Char),
1002        rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I8) => {
1003            TyKind::Scalar(Scalar::Int(IntTy::I8))
1004        }
1005        rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I16) => {
1006            TyKind::Scalar(Scalar::Int(IntTy::I16))
1007        }
1008        rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I32) => {
1009            TyKind::Scalar(Scalar::Int(IntTy::I32))
1010        }
1011        rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I64) => {
1012            TyKind::Scalar(Scalar::Int(IntTy::I64))
1013        }
1014        rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I128) => {
1015            TyKind::Scalar(Scalar::Int(IntTy::I128))
1016        }
1017        rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::Isize) => {
1018            TyKind::Scalar(Scalar::Int(IntTy::Isize))
1019        }
1020        rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U8) => {
1021            TyKind::Scalar(Scalar::Uint(UintTy::U8))
1022        }
1023        rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U16) => {
1024            TyKind::Scalar(Scalar::Uint(UintTy::U16))
1025        }
1026        rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U32) => {
1027            TyKind::Scalar(Scalar::Uint(UintTy::U32))
1028        }
1029        rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U64) => {
1030            TyKind::Scalar(Scalar::Uint(UintTy::U64))
1031        }
1032        rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U128) => {
1033            TyKind::Scalar(Scalar::Uint(UintTy::U128))
1034        }
1035        rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::Usize) => {
1036            TyKind::Scalar(Scalar::Uint(UintTy::Usize))
1037        }
1038        rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F16) => {
1039            TyKind::Scalar(Scalar::Float(FloatTy::F16))
1040        }
1041        rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F32) => {
1042            TyKind::Scalar(Scalar::Float(FloatTy::F32))
1043        }
1044        rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F64) => {
1045            TyKind::Scalar(Scalar::Float(FloatTy::F64))
1046        }
1047        rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F128) => {
1048            TyKind::Scalar(Scalar::Float(FloatTy::F128))
1049        }
1050        rustc_type_ir::TyKind::Str => TyKind::Str,
1051        rustc_type_ir::TyKind::Error(_) => TyKind::Error,
1052        rustc_type_ir::TyKind::Never => TyKind::Never,
1053
1054        rustc_type_ir::TyKind::Adt(def, args) => {
1055            let adt_id = def.inner().id;
1056            let subst = convert_args_for_result(interner, args.as_slice());
1057            TyKind::Adt(chalk_ir::AdtId(adt_id), subst)
1058        }
1059
1060        rustc_type_ir::TyKind::Infer(infer_ty) => {
1061            let (var, kind) = match infer_ty {
1062                rustc_type_ir::InferTy::TyVar(var) => {
1063                    (InferenceVar::from(var.as_u32()), TyVariableKind::General)
1064                }
1065                rustc_type_ir::InferTy::IntVar(var) => {
1066                    (InferenceVar::from(var.as_u32()), TyVariableKind::Integer)
1067                }
1068                rustc_type_ir::InferTy::FloatVar(var) => {
1069                    (InferenceVar::from(var.as_u32()), TyVariableKind::Float)
1070                }
1071                rustc_type_ir::InferTy::FreshFloatTy(..)
1072                | rustc_type_ir::InferTy::FreshIntTy(..)
1073                | rustc_type_ir::InferTy::FreshTy(..) => {
1074                    panic!("Freshening shouldn't happen.")
1075                }
1076            };
1077            TyKind::InferenceVar(var, kind)
1078        }
1079
1080        rustc_type_ir::TyKind::Ref(r, ty, mutability) => {
1081            let mutability = match mutability {
1082                rustc_ast_ir::Mutability::Mut => chalk_ir::Mutability::Mut,
1083                rustc_ast_ir::Mutability::Not => chalk_ir::Mutability::Not,
1084            };
1085            let r = convert_region_for_result(interner, r);
1086            let ty = convert_ty_for_result(interner, ty);
1087            TyKind::Ref(mutability, r, ty)
1088        }
1089
1090        rustc_type_ir::TyKind::Tuple(tys) => {
1091            let size = tys.len();
1092            let subst = Substitution::from_iter(
1093                Interner,
1094                tys.iter().map(|ty| {
1095                    chalk_ir::GenericArgData::Ty(convert_ty_for_result(interner, ty))
1096                        .intern(Interner)
1097                }),
1098            );
1099            TyKind::Tuple(size, subst)
1100        }
1101
1102        rustc_type_ir::TyKind::Array(ty, const_) => {
1103            let ty = convert_ty_for_result(interner, ty);
1104            let const_ = convert_const_for_result(interner, const_);
1105            TyKind::Array(ty, const_)
1106        }
1107
1108        rustc_type_ir::TyKind::Alias(alias_ty_kind, alias_ty) => match alias_ty_kind {
1109            rustc_type_ir::AliasTyKind::Projection => {
1110                let assoc_ty_id = match alias_ty.def_id {
1111                    SolverDefId::TypeAliasId(id) => id,
1112                    _ => unreachable!(),
1113                };
1114                let associated_ty_id = to_assoc_type_id(assoc_ty_id);
1115                let substitution = convert_args_for_result(interner, alias_ty.args.as_slice());
1116                TyKind::AssociatedType(associated_ty_id, substitution)
1117            }
1118            rustc_type_ir::AliasTyKind::Opaque => {
1119                let opaque_ty_id = match alias_ty.def_id {
1120                    SolverDefId::InternedOpaqueTyId(id) => id,
1121                    _ => unreachable!(),
1122                };
1123                let substitution = convert_args_for_result(interner, alias_ty.args.as_slice());
1124                TyKind::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy {
1125                    opaque_ty_id: opaque_ty_id.into(),
1126                    substitution,
1127                }))
1128            }
1129            rustc_type_ir::AliasTyKind::Inherent => unimplemented!(),
1130            rustc_type_ir::AliasTyKind::Free => unimplemented!(),
1131        },
1132
1133        // For `Placeholder`, `Bound` and `Param`, see the comment on the reverse conversion.
1134        rustc_type_ir::TyKind::Placeholder(placeholder) => {
1135            unimplemented!(
1136                "A `rustc_type_ir::TyKind::Placeholder` doesn't have a direct \
1137                correspondence in Chalk, as it represents a universally instantiated `Bound`.\n\
1138                It therefore feels safer to leave it panicking, but if you hit this panic \
1139                feel free to do the same as in `rustc_type_ir::TyKind::Bound` here."
1140            )
1141        }
1142        rustc_type_ir::TyKind::Bound(debruijn_index, ty) => TyKind::BoundVar(chalk_ir::BoundVar {
1143            debruijn: chalk_ir::DebruijnIndex::new(debruijn_index.as_u32()),
1144            index: ty.var.as_usize(),
1145        }),
1146        rustc_type_ir::TyKind::Param(param) => {
1147            let placeholder = to_placeholder_idx(interner.db, param.id.into(), param.index);
1148            TyKind::Placeholder(placeholder)
1149        }
1150
1151        rustc_type_ir::TyKind::FnPtr(bound_sig, fn_header) => {
1152            let num_binders = bound_sig.bound_vars().len();
1153            let sig = chalk_ir::FnSig {
1154                abi: fn_header.abi,
1155                safety: match fn_header.safety {
1156                    crate::next_solver::abi::Safety::Safe => chalk_ir::Safety::Safe,
1157                    crate::next_solver::abi::Safety::Unsafe => chalk_ir::Safety::Unsafe,
1158                },
1159                variadic: fn_header.c_variadic,
1160            };
1161            let args = GenericArgs::new_from_iter(
1162                interner,
1163                bound_sig.skip_binder().inputs_and_output.iter().map(|a| a.into()),
1164            );
1165            let substitution = convert_args_for_result(interner, args.as_slice());
1166            let substitution = chalk_ir::FnSubst(substitution);
1167            let fnptr = chalk_ir::FnPointer { num_binders, sig, substitution };
1168            TyKind::Function(fnptr)
1169        }
1170
1171        rustc_type_ir::TyKind::Dynamic(preds, region, dyn_kind) => {
1172            assert!(matches!(dyn_kind, rustc_type_ir::DynKind::Dyn));
1173            let self_ty = Ty::new_bound(
1174                interner,
1175                DebruijnIndex::from_u32(1),
1176                BoundTy { kind: BoundTyKind::Anon, var: BoundVar::from_u32(0) },
1177            );
1178            let bounds = chalk_ir::QuantifiedWhereClauses::from_iter(
1179                Interner,
1180                preds.iter().map(|p| {
1181                    let binders = chalk_ir::VariableKinds::from_iter(
1182                        Interner,
1183                        p.bound_vars().iter().map(|b| match b {
1184                            BoundVarKind::Ty(kind) => {
1185                                chalk_ir::VariableKind::Ty(TyVariableKind::General)
1186                            }
1187                            BoundVarKind::Region(kind) => chalk_ir::VariableKind::Lifetime,
1188                            BoundVarKind::Const => {
1189                                chalk_ir::VariableKind::Const(crate::TyKind::Error.intern(Interner))
1190                            }
1191                        }),
1192                    );
1193
1194                    // Rust and chalk have slightly different
1195                    // representation for trait objects.
1196                    //
1197                    // Chalk uses `for<T0> for<'a> T0: Trait<'a>` while rustc
1198                    // uses `ExistentialPredicate`s, which do not have a self ty.
1199                    // We need to shift escaping bound vars by 1 to accommodate
1200                    // the newly introduced `for<T0>` binder.
1201                    let p = shift_vars(interner, p, 1);
1202
1203                    let where_clause = match p.skip_binder() {
1204                        rustc_type_ir::ExistentialPredicate::Trait(trait_ref) => {
1205                            let trait_ref = TraitRef::new(
1206                                interner,
1207                                trait_ref.def_id,
1208                                [self_ty.into()].into_iter().chain(trait_ref.args.iter()),
1209                            );
1210                            let trait_id = match trait_ref.def_id {
1211                                SolverDefId::TraitId(id) => to_chalk_trait_id(id),
1212                                _ => unreachable!(),
1213                            };
1214                            let substitution =
1215                                convert_args_for_result(interner, trait_ref.args.as_slice());
1216                            let trait_ref = chalk_ir::TraitRef { trait_id, substitution };
1217                            chalk_ir::WhereClause::Implemented(trait_ref)
1218                        }
1219                        rustc_type_ir::ExistentialPredicate::AutoTrait(trait_) => {
1220                            let trait_id = match trait_ {
1221                                SolverDefId::TraitId(id) => to_chalk_trait_id(id),
1222                                _ => unreachable!(),
1223                            };
1224                            let substitution = chalk_ir::Substitution::from1(
1225                                Interner,
1226                                convert_ty_for_result(interner, self_ty),
1227                            );
1228                            let trait_ref = chalk_ir::TraitRef { trait_id, substitution };
1229                            chalk_ir::WhereClause::Implemented(trait_ref)
1230                        }
1231                        rustc_type_ir::ExistentialPredicate::Projection(existential_projection) => {
1232                            let projection = ProjectionPredicate {
1233                                projection_term: AliasTerm::new(
1234                                    interner,
1235                                    existential_projection.def_id,
1236                                    [self_ty.into()]
1237                                        .iter()
1238                                        .chain(existential_projection.args.iter()),
1239                                ),
1240                                term: existential_projection.term,
1241                            };
1242                            let associated_ty_id = match projection.projection_term.def_id {
1243                                SolverDefId::TypeAliasId(id) => to_assoc_type_id(id),
1244                                _ => unreachable!(),
1245                            };
1246                            let substitution = convert_args_for_result(
1247                                interner,
1248                                projection.projection_term.args.as_slice(),
1249                            );
1250                            let alias = chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
1251                                associated_ty_id,
1252                                substitution,
1253                            });
1254                            let ty = match projection.term {
1255                                Term::Ty(ty) => ty,
1256                                _ => unreachable!(),
1257                            };
1258                            let ty = convert_ty_for_result(interner, ty);
1259                            let alias_eq = chalk_ir::AliasEq { alias, ty };
1260                            chalk_ir::WhereClause::AliasEq(alias_eq)
1261                        }
1262                    };
1263                    chalk_ir::Binders::new(binders, where_clause)
1264                }),
1265            );
1266            let binders = chalk_ir::VariableKinds::from1(
1267                Interner,
1268                chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General),
1269            );
1270            let bounds = chalk_ir::Binders::new(binders, bounds);
1271            let dyn_ty =
1272                chalk_ir::DynTy { bounds, lifetime: convert_region_for_result(interner, region) };
1273            TyKind::Dyn(dyn_ty)
1274        }
1275
1276        rustc_type_ir::TyKind::Slice(ty) => {
1277            let ty = convert_ty_for_result(interner, ty);
1278            TyKind::Slice(ty)
1279        }
1280
1281        rustc_type_ir::TyKind::Foreign(foreign) => {
1282            let def_id = match foreign {
1283                SolverDefId::TypeAliasId(id) => id,
1284                _ => unreachable!(),
1285            };
1286            TyKind::Foreign(to_foreign_def_id(def_id))
1287        }
1288        rustc_type_ir::TyKind::Pat(_, _) => unimplemented!(),
1289        rustc_type_ir::TyKind::RawPtr(ty, mutability) => {
1290            let mutability = match mutability {
1291                rustc_ast_ir::Mutability::Mut => chalk_ir::Mutability::Mut,
1292                rustc_ast_ir::Mutability::Not => chalk_ir::Mutability::Not,
1293            };
1294            let ty = convert_ty_for_result(interner, ty);
1295            TyKind::Raw(mutability, ty)
1296        }
1297        rustc_type_ir::TyKind::FnDef(def_id, args) => {
1298            let id = match def_id {
1299                SolverDefId::FunctionId(id) => CallableDefId::FunctionId(id),
1300                SolverDefId::Ctor(Ctor::Struct(id)) => CallableDefId::StructId(id),
1301                SolverDefId::Ctor(Ctor::Enum(id)) => CallableDefId::EnumVariantId(id),
1302                _ => unreachable!(),
1303            };
1304            let subst = convert_args_for_result(interner, args.as_slice());
1305            TyKind::FnDef(id.to_chalk(interner.db()), subst)
1306        }
1307
1308        rustc_type_ir::TyKind::Closure(def_id, args) => {
1309            let id = match def_id {
1310                SolverDefId::InternedClosureId(id) => id,
1311                _ => unreachable!(),
1312            };
1313            let subst = convert_args_for_result(interner, args.as_slice());
1314            TyKind::Closure(id.into(), subst)
1315        }
1316        rustc_type_ir::TyKind::CoroutineClosure(_, _) => unimplemented!(),
1317        rustc_type_ir::TyKind::Coroutine(def_id, args) => {
1318            let id = match def_id {
1319                SolverDefId::InternedCoroutineId(id) => id,
1320                _ => unreachable!(),
1321            };
1322            let subst = convert_args_for_result(interner, args.as_slice());
1323            TyKind::Coroutine(id.into(), subst)
1324        }
1325        rustc_type_ir::TyKind::CoroutineWitness(def_id, args) => {
1326            let id = match def_id {
1327                SolverDefId::InternedCoroutineId(id) => id,
1328                _ => unreachable!(),
1329            };
1330            let subst = convert_args_for_result(interner, args.as_slice());
1331            TyKind::CoroutineWitness(id.into(), subst)
1332        }
1333
1334        rustc_type_ir::TyKind::UnsafeBinder(_) => unimplemented!(),
1335    }
1336    .intern(Interner)
1337}
1338
1339pub fn convert_const_for_result<'db>(
1340    interner: DbInterner<'db>,
1341    const_: Const<'db>,
1342) -> crate::Const {
1343    let value: chalk_ir::ConstValue<Interner> = match const_.kind() {
1344        rustc_type_ir::ConstKind::Infer(rustc_type_ir::InferConst::Var(var)) => {
1345            chalk_ir::ConstValue::InferenceVar(chalk_ir::InferenceVar::from(var.as_u32()))
1346        }
1347        rustc_type_ir::ConstKind::Infer(rustc_type_ir::InferConst::Fresh(fresh)) => {
1348            panic!("Vars should not be freshened.")
1349        }
1350        rustc_type_ir::ConstKind::Param(param) => {
1351            let placeholder = to_placeholder_idx(interner.db, param.id.into(), param.index);
1352            chalk_ir::ConstValue::Placeholder(placeholder)
1353        }
1354        rustc_type_ir::ConstKind::Bound(debruijn_index, var) => {
1355            chalk_ir::ConstValue::BoundVar(chalk_ir::BoundVar::new(
1356                chalk_ir::DebruijnIndex::new(debruijn_index.as_u32()),
1357                var.index(),
1358            ))
1359        }
1360        rustc_type_ir::ConstKind::Placeholder(placeholder_const) => {
1361            unimplemented!(
1362                "A `rustc_type_ir::ConstKind::Placeholder` doesn't have a direct \
1363                correspondence in Chalk, as it represents a universally instantiated `Bound`.\n\
1364                It therefore feels safer to leave it panicking, but if you hit this panic \
1365                feel free to do the same as in `rustc_type_ir::ConstKind::Bound` here."
1366            )
1367        }
1368        rustc_type_ir::ConstKind::Unevaluated(unevaluated_const) => {
1369            let id = match unevaluated_const.def {
1370                SolverDefId::ConstId(id) => GeneralConstId::ConstId(id),
1371                SolverDefId::StaticId(id) => GeneralConstId::StaticId(id),
1372                _ => unreachable!(),
1373            };
1374            let subst = convert_args_for_result(interner, unevaluated_const.args.as_slice());
1375            chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst {
1376                interned: ConstScalar::UnevaluatedConst(id, subst),
1377            })
1378        }
1379        rustc_type_ir::ConstKind::Value(value_const) => {
1380            let bytes = value_const.value.inner();
1381            let value = chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst {
1382                // SAFETY: we will never actually use this without a database
1383                interned: ConstScalar::Bytes(bytes.0.clone(), unsafe {
1384                    std::mem::transmute::<MemoryMap<'db>, MemoryMap<'static>>(bytes.1.clone())
1385                }),
1386            });
1387            return chalk_ir::ConstData {
1388                ty: convert_ty_for_result(interner, value_const.ty),
1389                value,
1390            }
1391            .intern(Interner);
1392        }
1393        rustc_type_ir::ConstKind::Error(_) => {
1394            chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst {
1395                interned: ConstScalar::Unknown,
1396            })
1397        }
1398        rustc_type_ir::ConstKind::Expr(_) => unimplemented!(),
1399    };
1400    chalk_ir::ConstData { ty: crate::TyKind::Error.intern(Interner), value }.intern(Interner)
1401}
1402
1403pub fn convert_region_for_result<'db>(
1404    interner: DbInterner<'db>,
1405    region: Region<'db>,
1406) -> crate::Lifetime {
1407    let lifetime = match region.kind() {
1408        rustc_type_ir::RegionKind::ReEarlyParam(early) => {
1409            let placeholder = lt_to_placeholder_idx(interner.db, early.id, early.index);
1410            chalk_ir::LifetimeData::Placeholder(placeholder)
1411        }
1412        rustc_type_ir::RegionKind::ReBound(db, bound) => {
1413            chalk_ir::LifetimeData::BoundVar(chalk_ir::BoundVar::new(
1414                chalk_ir::DebruijnIndex::new(db.as_u32()),
1415                bound.var.as_usize(),
1416            ))
1417        }
1418        rustc_type_ir::RegionKind::RePlaceholder(placeholder) => unimplemented!(
1419            "A `rustc_type_ir::RegionKind::RePlaceholder` doesn't have a direct \
1420            correspondence in Chalk, as it represents a universally instantiated `Bound`.\n\
1421            It therefore feels safer to leave it panicking, but if you hit this panic \
1422            feel free to do the same as in `rustc_type_ir::RegionKind::ReBound` here."
1423        ),
1424        rustc_type_ir::RegionKind::ReLateParam(_) => unimplemented!(),
1425        rustc_type_ir::RegionKind::ReStatic => chalk_ir::LifetimeData::Static,
1426        rustc_type_ir::RegionKind::ReVar(vid) => {
1427            chalk_ir::LifetimeData::InferenceVar(chalk_ir::InferenceVar::from(vid.as_u32()))
1428        }
1429        rustc_type_ir::RegionKind::ReErased => chalk_ir::LifetimeData::Erased,
1430        rustc_type_ir::RegionKind::ReError(_) => chalk_ir::LifetimeData::Error,
1431    };
1432    chalk_ir::Lifetime::new(Interner, lifetime)
1433}