1use 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
51pub 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 let bounds = BoundExistentialPredicates::new_from_iter(
275 interner,
276 dyn_ty.bounds.skip_binders().iter(Interner).filter_map(|pred| {
277 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 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 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 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 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}