| //! Things useful for mapping to/from Chalk and next-trait-solver types. |
| |
| use base_db::Crate; |
| use chalk_ir::{ |
| CanonicalVarKind, CanonicalVarKinds, FnPointer, InferenceVar, Substitution, TyVariableKind, |
| WellFormed, cast::Cast, fold::Shift, interner::HasInterner, |
| }; |
| use hir_def::{ |
| CallableDefId, ConstParamId, FunctionId, GeneralConstId, LifetimeParamId, TypeAliasId, |
| TypeOrConstParamId, TypeParamId, signatures::TraitFlags, |
| }; |
| use hir_def::{GenericDefId, GenericParamId}; |
| use intern::sym; |
| use rustc_type_ir::{ |
| AliasTerm, BoundVar, DebruijnIndex, ExistentialProjection, ExistentialTraitRef, Interner as _, |
| OutlivesPredicate, ProjectionPredicate, TypeFoldable, TypeSuperFoldable, TypeVisitable, |
| TypeVisitableExt, UniverseIndex, elaborate, |
| inherent::{BoundVarLike, Clause as _, IntoKind, PlaceholderLike, SliceLike, Ty as _}, |
| shift_vars, |
| solve::Goal, |
| }; |
| use salsa::plumbing::FromId; |
| use salsa::{Id, plumbing::AsId}; |
| |
| use crate::next_solver::BoundConst; |
| use crate::{ |
| ConstScalar, ImplTraitId, Interner, MemoryMap, |
| db::{ |
| HirDatabase, InternedClosureId, InternedCoroutineId, InternedLifetimeParamId, |
| InternedOpaqueTyId, InternedTypeOrConstParamId, |
| }, |
| from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, |
| mapping::ToChalk, |
| next_solver::{ |
| Binder, ClauseKind, ConstBytes, TraitPredicate, UnevaluatedConst, |
| interner::{AdtDef, BoundVarKind, BoundVarKinds, DbInterner}, |
| }, |
| to_assoc_type_id, to_chalk_trait_id, to_foreign_def_id, |
| }; |
| use crate::{ |
| from_placeholder_idx, lt_from_placeholder_idx, lt_to_placeholder_idx, to_placeholder_idx, |
| }; |
| |
| use super::{ |
| BoundExistentialPredicate, BoundExistentialPredicates, BoundRegion, BoundRegionKind, BoundTy, |
| BoundTyKind, Canonical, CanonicalVars, Clause, Clauses, Const, Ctor, EarlyParamRegion, |
| ErrorGuaranteed, ExistentialPredicate, GenericArg, GenericArgs, ParamConst, ParamEnv, ParamTy, |
| Placeholder, PlaceholderConst, PlaceholderRegion, PlaceholderTy, Predicate, PredicateKind, |
| Region, SolverDefId, SubtypePredicate, Term, TraitRef, Ty, Tys, ValueConst, VariancesOf, |
| }; |
| |
| // FIXME: This should urgently go (as soon as we finish the migration off Chalk, that is). |
| pub fn convert_binder_to_early_binder<'db, T: rustc_type_ir::TypeFoldable<DbInterner<'db>>>( |
| interner: DbInterner<'db>, |
| def: GenericDefId, |
| binder: rustc_type_ir::Binder<DbInterner<'db>, T>, |
| ) -> rustc_type_ir::EarlyBinder<DbInterner<'db>, T> { |
| let mut folder = BinderToEarlyBinder { |
| interner, |
| debruijn: rustc_type_ir::DebruijnIndex::ZERO, |
| params: crate::generics::generics(interner.db, def).iter_id().collect(), |
| }; |
| rustc_type_ir::EarlyBinder::bind(binder.skip_binder().fold_with(&mut folder)) |
| } |
| |
| struct BinderToEarlyBinder<'db> { |
| interner: DbInterner<'db>, |
| debruijn: rustc_type_ir::DebruijnIndex, |
| params: Vec<GenericParamId>, |
| } |
| |
| impl<'db> rustc_type_ir::TypeFolder<DbInterner<'db>> for BinderToEarlyBinder<'db> { |
| fn cx(&self) -> DbInterner<'db> { |
| self.interner |
| } |
| |
| fn fold_binder<T>( |
| &mut self, |
| t: rustc_type_ir::Binder<DbInterner<'db>, T>, |
| ) -> rustc_type_ir::Binder<DbInterner<'db>, T> |
| where |
| T: TypeFoldable<DbInterner<'db>>, |
| { |
| self.debruijn.shift_in(1); |
| let result = t.super_fold_with(self); |
| self.debruijn.shift_out(1); |
| result |
| } |
| |
| fn fold_ty(&mut self, t: Ty<'db>) -> Ty<'db> { |
| match t.kind() { |
| rustc_type_ir::TyKind::Bound(debruijn, bound_ty) if self.debruijn == debruijn => { |
| let var: rustc_type_ir::BoundVar = bound_ty.var(); |
| let GenericParamId::TypeParamId(id) = self.params[bound_ty.var.as_usize()] else { |
| unreachable!() |
| }; |
| Ty::new( |
| self.cx(), |
| rustc_type_ir::TyKind::Param(ParamTy { index: var.as_u32(), id }), |
| ) |
| } |
| _ => t.super_fold_with(self), |
| } |
| } |
| |
| fn fold_region(&mut self, r: Region<'db>) -> Region<'db> { |
| match r.kind() { |
| rustc_type_ir::ReBound(debruijn, bound_region) if self.debruijn == debruijn => { |
| let var: rustc_type_ir::BoundVar = bound_region.var(); |
| let GenericParamId::LifetimeParamId(id) = self.params[bound_region.var.as_usize()] |
| else { |
| unreachable!() |
| }; |
| Region::new( |
| self.cx(), |
| rustc_type_ir::RegionKind::ReEarlyParam(EarlyParamRegion { |
| index: var.as_u32(), |
| id, |
| }), |
| ) |
| } |
| _ => r, |
| } |
| } |
| |
| fn fold_const(&mut self, c: Const<'db>) -> Const<'db> { |
| match c.kind() { |
| rustc_type_ir::ConstKind::Bound(debruijn, var) if self.debruijn == debruijn => { |
| let GenericParamId::ConstParamId(id) = self.params[var.var.as_usize()] else { |
| unreachable!() |
| }; |
| Const::new( |
| self.cx(), |
| rustc_type_ir::ConstKind::Param(ParamConst { index: var.var.as_u32(), id }), |
| ) |
| } |
| _ => c.super_fold_with(self), |
| } |
| } |
| } |
| |
| pub trait ChalkToNextSolver<'db, Out> { |
| fn to_nextsolver(&self, interner: DbInterner<'db>) -> Out; |
| } |
| |
| pub trait NextSolverToChalk<'db, Out> { |
| fn to_chalk(self, interner: DbInterner<'db>) -> Out; |
| } |
| |
| impl<'db> ChalkToNextSolver<'db, Ty<'db>> for chalk_ir::Ty<Interner> { |
| fn to_nextsolver(&self, interner: DbInterner<'db>) -> Ty<'db> { |
| Ty::new( |
| interner, |
| match self.kind(Interner) { |
| chalk_ir::TyKind::Adt(adt_id, substitution) => { |
| let def = AdtDef::new(adt_id.0, interner); |
| let args = substitution.to_nextsolver(interner); |
| rustc_type_ir::TyKind::Adt(def, args) |
| } |
| chalk_ir::TyKind::AssociatedType(assoc_type_id, substitution) => { |
| let def_id = SolverDefId::TypeAliasId(from_assoc_type_id(*assoc_type_id)); |
| let args: GenericArgs<'db> = substitution.to_nextsolver(interner); |
| let alias_ty = rustc_type_ir::AliasTy::new(interner, def_id, args.iter()); |
| rustc_type_ir::TyKind::Alias(rustc_type_ir::AliasTyKind::Projection, alias_ty) |
| } |
| chalk_ir::TyKind::Scalar(scalar) => match scalar { |
| chalk_ir::Scalar::Bool => rustc_type_ir::TyKind::Bool, |
| chalk_ir::Scalar::Char => rustc_type_ir::TyKind::Char, |
| chalk_ir::Scalar::Int(chalk_ir::IntTy::Isize) => { |
| rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::Isize) |
| } |
| chalk_ir::Scalar::Int(chalk_ir::IntTy::I8) => { |
| rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I8) |
| } |
| chalk_ir::Scalar::Int(chalk_ir::IntTy::I16) => { |
| rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I16) |
| } |
| chalk_ir::Scalar::Int(chalk_ir::IntTy::I32) => { |
| rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I32) |
| } |
| chalk_ir::Scalar::Int(chalk_ir::IntTy::I64) => { |
| rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I64) |
| } |
| chalk_ir::Scalar::Int(chalk_ir::IntTy::I128) => { |
| rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I128) |
| } |
| chalk_ir::Scalar::Uint(chalk_ir::UintTy::Usize) => { |
| rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::Usize) |
| } |
| chalk_ir::Scalar::Uint(chalk_ir::UintTy::U8) => { |
| rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U8) |
| } |
| chalk_ir::Scalar::Uint(chalk_ir::UintTy::U16) => { |
| rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U16) |
| } |
| chalk_ir::Scalar::Uint(chalk_ir::UintTy::U32) => { |
| rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U32) |
| } |
| chalk_ir::Scalar::Uint(chalk_ir::UintTy::U64) => { |
| rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U64) |
| } |
| chalk_ir::Scalar::Uint(chalk_ir::UintTy::U128) => { |
| rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U128) |
| } |
| chalk_ir::Scalar::Float(chalk_ir::FloatTy::F16) => { |
| rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F16) |
| } |
| chalk_ir::Scalar::Float(chalk_ir::FloatTy::F32) => { |
| rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F32) |
| } |
| chalk_ir::Scalar::Float(chalk_ir::FloatTy::F64) => { |
| rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F64) |
| } |
| chalk_ir::Scalar::Float(chalk_ir::FloatTy::F128) => { |
| rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F128) |
| } |
| }, |
| chalk_ir::TyKind::Tuple(_, substitution) => { |
| let args = substitution.to_nextsolver(interner); |
| rustc_type_ir::TyKind::Tuple(args) |
| } |
| chalk_ir::TyKind::Array(ty, len) => rustc_type_ir::TyKind::Array( |
| ty.to_nextsolver(interner), |
| len.to_nextsolver(interner), |
| ), |
| chalk_ir::TyKind::Slice(ty) => { |
| rustc_type_ir::TyKind::Slice(ty.to_nextsolver(interner)) |
| } |
| chalk_ir::TyKind::Raw(mutability, ty) => rustc_type_ir::RawPtr( |
| ty.to_nextsolver(interner), |
| mutability.to_nextsolver(interner), |
| ), |
| chalk_ir::TyKind::Ref(mutability, lifetime, ty) => rustc_type_ir::TyKind::Ref( |
| lifetime.to_nextsolver(interner), |
| ty.to_nextsolver(interner), |
| mutability.to_nextsolver(interner), |
| ), |
| chalk_ir::TyKind::OpaqueType(def_id, substitution) => { |
| let id: InternedOpaqueTyId = (*def_id).into(); |
| let args: GenericArgs<'db> = substitution.to_nextsolver(interner); |
| let alias_ty = rustc_type_ir::AliasTy::new(interner, id.into(), args); |
| rustc_type_ir::TyKind::Alias(rustc_type_ir::AliasTyKind::Opaque, alias_ty) |
| } |
| chalk_ir::TyKind::FnDef(fn_def_id, substitution) => { |
| let def_id = CallableDefId::from_chalk(interner.db(), *fn_def_id); |
| rustc_type_ir::TyKind::FnDef( |
| def_id.into(), |
| substitution.to_nextsolver(interner), |
| ) |
| } |
| chalk_ir::TyKind::Str => rustc_type_ir::TyKind::Str, |
| chalk_ir::TyKind::Never => rustc_type_ir::TyKind::Never, |
| chalk_ir::TyKind::Closure(closure_id, substitution) => { |
| let id: InternedClosureId = (*closure_id).into(); |
| rustc_type_ir::TyKind::Closure(id.into(), substitution.to_nextsolver(interner)) |
| } |
| chalk_ir::TyKind::Coroutine(coroutine_id, substitution) => { |
| let id: InternedCoroutineId = (*coroutine_id).into(); |
| rustc_type_ir::TyKind::Coroutine( |
| id.into(), |
| substitution.to_nextsolver(interner), |
| ) |
| } |
| chalk_ir::TyKind::CoroutineWitness(coroutine_id, substitution) => { |
| let id: InternedCoroutineId = (*coroutine_id).into(); |
| rustc_type_ir::TyKind::CoroutineWitness( |
| id.into(), |
| substitution.to_nextsolver(interner), |
| ) |
| } |
| chalk_ir::TyKind::Foreign(foreign_def_id) => rustc_type_ir::TyKind::Foreign( |
| crate::from_foreign_def_id(*foreign_def_id).into(), |
| ), |
| chalk_ir::TyKind::Error => rustc_type_ir::TyKind::Error(ErrorGuaranteed), |
| chalk_ir::TyKind::Dyn(dyn_ty) => { |
| // exists<type> { for<...> ^1.0: ... } |
| let bounds = BoundExistentialPredicates::new_from_iter( |
| interner, |
| dyn_ty.bounds.skip_binders().iter(Interner).filter_map(|pred| { |
| // for<...> ^1.0: ... |
| let (val, binders) = pred.clone().into_value_and_skipped_binders(); |
| let bound_vars = binders.to_nextsolver(interner); |
| let clause = match val { |
| chalk_ir::WhereClause::Implemented(trait_ref) => { |
| let trait_id = from_chalk_trait_id(trait_ref.trait_id); |
| if interner |
| .db() |
| .trait_signature(trait_id) |
| .flags |
| .contains(TraitFlags::AUTO) |
| { |
| ExistentialPredicate::AutoTrait(trait_id.into()) |
| } else { |
| let args = GenericArgs::new_from_iter( |
| interner, |
| trait_ref |
| .substitution |
| .iter(Interner) |
| .skip(1) |
| .map(|a| a.clone().shifted_out(Interner).unwrap()) |
| .map(|a| a.to_nextsolver(interner)), |
| ); |
| let trait_ref = ExistentialTraitRef::new_from_args( |
| interner, trait_id.into(), args, |
| ); |
| ExistentialPredicate::Trait(trait_ref) |
| } |
| } |
| chalk_ir::WhereClause::AliasEq(alias_eq) => { |
| let (def_id, args) = match &alias_eq.alias { |
| chalk_ir::AliasTy::Projection(projection) => { |
| let id = |
| from_assoc_type_id(projection.associated_ty_id); |
| let def_id = SolverDefId::TypeAliasId(id); |
| let generics = interner.generics_of(def_id); |
| let parent_len = generics.parent_count; |
| let substs = projection.substitution.iter(Interner).skip(1); |
| |
| let args = GenericArgs::new_from_iter( |
| interner, |
| substs |
| .map(|a| { |
| a.clone().shifted_out(Interner).unwrap() |
| }) |
| .map(|a| a.to_nextsolver(interner)), |
| ); |
| (def_id, args) |
| } |
| chalk_ir::AliasTy::Opaque(opaque_ty) => { |
| panic!("Invalid ExistentialPredicate (opaques can't be named)."); |
| } |
| }; |
| let term = alias_eq |
| .ty |
| .clone() |
| .shifted_out(Interner) |
| .unwrap() |
| .to_nextsolver(interner) |
| .into(); |
| let projection = ExistentialProjection::new_from_args( |
| interner, def_id, args, term, |
| ); |
| ExistentialPredicate::Projection(projection) |
| } |
| chalk_ir::WhereClause::LifetimeOutlives(lifetime_outlives) => { |
| return None; |
| } |
| chalk_ir::WhereClause::TypeOutlives(type_outlives) => return None, |
| }; |
| |
| Some(Binder::bind_with_vars(clause, bound_vars)) |
| }), |
| ); |
| let region = dyn_ty.lifetime.to_nextsolver(interner); |
| let kind = rustc_type_ir::DynKind::Dyn; |
| rustc_type_ir::TyKind::Dynamic(bounds, region, kind) |
| } |
| chalk_ir::TyKind::Alias(alias_ty) => match alias_ty { |
| chalk_ir::AliasTy::Projection(projection_ty) => { |
| let def_id = SolverDefId::TypeAliasId(from_assoc_type_id( |
| projection_ty.associated_ty_id, |
| )); |
| let alias_ty = rustc_type_ir::AliasTy::new_from_args( |
| interner, |
| def_id, |
| projection_ty.substitution.to_nextsolver(interner), |
| ); |
| rustc_type_ir::TyKind::Alias( |
| rustc_type_ir::AliasTyKind::Projection, |
| alias_ty, |
| ) |
| } |
| chalk_ir::AliasTy::Opaque(opaque_ty) => { |
| let id: InternedOpaqueTyId = opaque_ty.opaque_ty_id.into(); |
| let def_id = SolverDefId::InternedOpaqueTyId(id); |
| let alias_ty = rustc_type_ir::AliasTy::new_from_args( |
| interner, |
| def_id, |
| opaque_ty.substitution.to_nextsolver(interner), |
| ); |
| rustc_type_ir::TyKind::Alias(rustc_type_ir::AliasTyKind::Opaque, alias_ty) |
| } |
| }, |
| chalk_ir::TyKind::Function(fn_pointer) => { |
| let sig_tys = fn_pointer.clone().into_binders(Interner).to_nextsolver(interner); |
| let header = rustc_type_ir::FnHeader { |
| abi: fn_pointer.sig.abi, |
| c_variadic: fn_pointer.sig.variadic, |
| safety: match fn_pointer.sig.safety { |
| chalk_ir::Safety::Safe => super::abi::Safety::Safe, |
| chalk_ir::Safety::Unsafe => super::abi::Safety::Unsafe, |
| }, |
| }; |
| |
| rustc_type_ir::TyKind::FnPtr(sig_tys, header) |
| } |
| // The schema here is quite confusing. |
| // The new solver, like rustc, uses `Param` and `EarlyBinder` for generic params. It uses `BoundVar` |
| // and `Placeholder` together with `Binder` for HRTB, which we mostly don't handle. |
| // Chalk uses `Placeholder` for generic params and `BoundVar` quite liberally, and this is quite a |
| // problem. `chalk_ir::TyKind::BoundVar` can represent either HRTB or generic params, depending on the |
| // context. When returned from signature queries, the outer `Binders` represent the generic params. |
| // But there are also inner `Binders` for HRTB. |
| // AFAIK there is no way to tell which of the meanings is relevant, so we just use `rustc_type_ir::Bound` |
| // here, and hope for the best. If you are working with new solver types, therefore, use the new solver |
| // lower queries. |
| // Hopefully sooner than later Chalk will be ripped from the codebase and we can avoid that problem. |
| // For details about the rustc setup, read: https://rustc-dev-guide.rust-lang.org/generic_parameters_summary.html |
| // and the following chapters. |
| chalk_ir::TyKind::Placeholder(placeholder_index) => { |
| let (id, index) = from_placeholder_idx(interner.db, *placeholder_index); |
| rustc_type_ir::TyKind::Param(ParamTy { |
| id: TypeParamId::from_unchecked(id), |
| index, |
| }) |
| } |
| chalk_ir::TyKind::BoundVar(bound_var) => rustc_type_ir::TyKind::Bound( |
| bound_var.debruijn.to_nextsolver(interner), |
| BoundTy { |
| var: rustc_type_ir::BoundVar::from_usize(bound_var.index), |
| kind: BoundTyKind::Anon, |
| }, |
| ), |
| chalk_ir::TyKind::InferenceVar(inference_var, ty_variable_kind) => { |
| rustc_type_ir::TyKind::Infer( |
| (*inference_var, *ty_variable_kind).to_nextsolver(interner), |
| ) |
| } |
| }, |
| ) |
| } |
| } |
| |
| impl<'db> NextSolverToChalk<'db, chalk_ir::Ty<Interner>> for Ty<'db> { |
| fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::Ty<Interner> { |
| convert_ty_for_result(interner, self) |
| } |
| } |
| |
| impl<'db> ChalkToNextSolver<'db, Region<'db>> for chalk_ir::Lifetime<Interner> { |
| fn to_nextsolver(&self, interner: DbInterner<'db>) -> Region<'db> { |
| Region::new( |
| interner, |
| match self.data(Interner) { |
| chalk_ir::LifetimeData::BoundVar(bound_var) => rustc_type_ir::RegionKind::ReBound( |
| bound_var.debruijn.to_nextsolver(interner), |
| BoundRegion { |
| var: rustc_type_ir::BoundVar::from_u32(bound_var.index as u32), |
| kind: BoundRegionKind::Anon, |
| }, |
| ), |
| chalk_ir::LifetimeData::InferenceVar(inference_var) => { |
| rustc_type_ir::RegionKind::ReVar(rustc_type_ir::RegionVid::from_u32( |
| inference_var.index(), |
| )) |
| } |
| chalk_ir::LifetimeData::Placeholder(placeholder_index) => { |
| let (id, index) = lt_from_placeholder_idx(interner.db, *placeholder_index); |
| rustc_type_ir::RegionKind::ReEarlyParam(EarlyParamRegion { id, index }) |
| } |
| chalk_ir::LifetimeData::Static => rustc_type_ir::RegionKind::ReStatic, |
| chalk_ir::LifetimeData::Erased => rustc_type_ir::RegionKind::ReErased, |
| chalk_ir::LifetimeData::Phantom(_, _) => { |
| unreachable!() |
| } |
| chalk_ir::LifetimeData::Error => { |
| rustc_type_ir::RegionKind::ReError(ErrorGuaranteed) |
| } |
| }, |
| ) |
| } |
| } |
| |
| impl<'db> NextSolverToChalk<'db, chalk_ir::Lifetime<Interner>> for Region<'db> { |
| fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::Lifetime<Interner> { |
| convert_region_for_result(interner, self) |
| } |
| } |
| |
| impl<'db> ChalkToNextSolver<'db, Const<'db>> for chalk_ir::Const<Interner> { |
| fn to_nextsolver(&self, interner: DbInterner<'db>) -> Const<'db> { |
| let data = self.data(Interner); |
| Const::new( |
| interner, |
| match &data.value { |
| chalk_ir::ConstValue::BoundVar(bound_var) => rustc_type_ir::ConstKind::Bound( |
| bound_var.debruijn.to_nextsolver(interner), |
| BoundConst { var: rustc_type_ir::BoundVar::from_usize(bound_var.index) }, |
| ), |
| chalk_ir::ConstValue::InferenceVar(inference_var) => { |
| rustc_type_ir::ConstKind::Infer(rustc_type_ir::InferConst::Var( |
| rustc_type_ir::ConstVid::from_u32(inference_var.index()), |
| )) |
| } |
| chalk_ir::ConstValue::Placeholder(placeholder_index) => { |
| let (id, index) = from_placeholder_idx(interner.db, *placeholder_index); |
| rustc_type_ir::ConstKind::Param(ParamConst { |
| id: ConstParamId::from_unchecked(id), |
| index, |
| }) |
| } |
| chalk_ir::ConstValue::Concrete(concrete_const) => match &concrete_const.interned { |
| ConstScalar::Bytes(bytes, memory) => { |
| rustc_type_ir::ConstKind::Value(ValueConst::new( |
| data.ty.to_nextsolver(interner), |
| ConstBytes(bytes.clone(), memory.clone()), |
| )) |
| } |
| ConstScalar::UnevaluatedConst(c, subst) => { |
| let def = match *c { |
| GeneralConstId::ConstId(id) => SolverDefId::ConstId(id), |
| GeneralConstId::StaticId(id) => SolverDefId::StaticId(id), |
| }; |
| let args = subst.to_nextsolver(interner); |
| rustc_type_ir::ConstKind::Unevaluated(UnevaluatedConst::new(def, args)) |
| } |
| ConstScalar::Unknown => rustc_type_ir::ConstKind::Error(ErrorGuaranteed), |
| }, |
| }, |
| ) |
| } |
| } |
| |
| impl<'db> NextSolverToChalk<'db, chalk_ir::Const<Interner>> for Const<'db> { |
| fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::Const<Interner> { |
| convert_const_for_result(interner, self) |
| } |
| } |
| |
| impl<'db> ChalkToNextSolver<'db, rustc_type_ir::FnSigTys<DbInterner<'db>>> |
| for chalk_ir::FnSubst<Interner> |
| { |
| fn to_nextsolver(&self, interner: DbInterner<'db>) -> rustc_type_ir::FnSigTys<DbInterner<'db>> { |
| rustc_type_ir::FnSigTys { |
| inputs_and_output: Tys::new_from_iter( |
| interner, |
| self.0.iter(Interner).map(|g| g.assert_ty_ref(Interner).to_nextsolver(interner)), |
| ), |
| } |
| } |
| } |
| |
| impl< |
| 'db, |
| U: TypeVisitable<DbInterner<'db>>, |
| T: Clone + ChalkToNextSolver<'db, U> + HasInterner<Interner = Interner>, |
| > ChalkToNextSolver<'db, rustc_type_ir::Binder<DbInterner<'db>, U>> for chalk_ir::Binders<T> |
| { |
| fn to_nextsolver( |
| &self, |
| interner: DbInterner<'db>, |
| ) -> rustc_type_ir::Binder<DbInterner<'db>, U> { |
| let (val, binders) = self.clone().into_value_and_skipped_binders(); |
| rustc_type_ir::Binder::bind_with_vars( |
| val.to_nextsolver(interner), |
| binders.to_nextsolver(interner), |
| ) |
| } |
| } |
| |
| impl<'db> ChalkToNextSolver<'db, BoundVarKinds> for chalk_ir::VariableKinds<Interner> { |
| fn to_nextsolver(&self, interner: DbInterner<'db>) -> BoundVarKinds { |
| BoundVarKinds::new_from_iter( |
| interner, |
| self.iter(Interner).map(|v| v.to_nextsolver(interner)), |
| ) |
| } |
| } |
| |
| impl<'db> ChalkToNextSolver<'db, BoundVarKind> for chalk_ir::VariableKind<Interner> { |
| fn to_nextsolver(&self, interner: DbInterner<'db>) -> BoundVarKind { |
| match self { |
| chalk_ir::VariableKind::Ty(_ty_variable_kind) => BoundVarKind::Ty(BoundTyKind::Anon), |
| chalk_ir::VariableKind::Lifetime => BoundVarKind::Region(BoundRegionKind::Anon), |
| chalk_ir::VariableKind::Const(_ty) => BoundVarKind::Const, |
| } |
| } |
| } |
| |
| impl<'db> ChalkToNextSolver<'db, GenericArg<'db>> for chalk_ir::GenericArg<Interner> { |
| fn to_nextsolver(&self, interner: DbInterner<'db>) -> GenericArg<'db> { |
| match self.data(Interner) { |
| chalk_ir::GenericArgData::Ty(ty) => ty.to_nextsolver(interner).into(), |
| chalk_ir::GenericArgData::Lifetime(lifetime) => lifetime.to_nextsolver(interner).into(), |
| chalk_ir::GenericArgData::Const(const_) => const_.to_nextsolver(interner).into(), |
| } |
| } |
| } |
| |
| impl<'db> ChalkToNextSolver<'db, GenericArgs<'db>> for chalk_ir::Substitution<Interner> { |
| fn to_nextsolver(&self, interner: DbInterner<'db>) -> GenericArgs<'db> { |
| GenericArgs::new_from_iter( |
| interner, |
| self.iter(Interner).map(|arg| -> GenericArg<'db> { arg.to_nextsolver(interner) }), |
| ) |
| } |
| } |
| |
| impl<'db> NextSolverToChalk<'db, chalk_ir::Substitution<Interner>> for GenericArgs<'db> { |
| fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::Substitution<Interner> { |
| convert_args_for_result(interner, self.as_slice()) |
| } |
| } |
| |
| impl<'db> ChalkToNextSolver<'db, Tys<'db>> for chalk_ir::Substitution<Interner> { |
| fn to_nextsolver(&self, interner: DbInterner<'db>) -> Tys<'db> { |
| Tys::new_from_iter( |
| interner, |
| self.iter(Interner).map(|arg| -> Ty<'db> { |
| match arg.data(Interner) { |
| chalk_ir::GenericArgData::Ty(ty) => ty.to_nextsolver(interner), |
| chalk_ir::GenericArgData::Lifetime(_) => unreachable!(), |
| chalk_ir::GenericArgData::Const(_) => unreachable!(), |
| } |
| }), |
| ) |
| } |
| } |
| |
| impl<'db> ChalkToNextSolver<'db, rustc_type_ir::DebruijnIndex> for chalk_ir::DebruijnIndex { |
| fn to_nextsolver(&self, _interner: DbInterner<'db>) -> rustc_type_ir::DebruijnIndex { |
| rustc_type_ir::DebruijnIndex::from_u32(self.depth()) |
| } |
| } |
| |
| impl<'db> NextSolverToChalk<'db, chalk_ir::DebruijnIndex> for rustc_type_ir::DebruijnIndex { |
| fn to_chalk(self, _interner: DbInterner<'db>) -> chalk_ir::DebruijnIndex { |
| chalk_ir::DebruijnIndex::new(self.index() as u32) |
| } |
| } |
| |
| impl<'db> ChalkToNextSolver<'db, rustc_type_ir::UniverseIndex> for chalk_ir::UniverseIndex { |
| fn to_nextsolver(&self, _interner: DbInterner<'db>) -> rustc_type_ir::UniverseIndex { |
| rustc_type_ir::UniverseIndex::from_u32(self.counter as u32) |
| } |
| } |
| |
| impl<'db> NextSolverToChalk<'db, chalk_ir::UniverseIndex> for rustc_type_ir::UniverseIndex { |
| fn to_chalk(self, _interner: DbInterner<'db>) -> chalk_ir::UniverseIndex { |
| chalk_ir::UniverseIndex { counter: self.index() } |
| } |
| } |
| |
| impl<'db> ChalkToNextSolver<'db, rustc_type_ir::InferTy> |
| for (chalk_ir::InferenceVar, chalk_ir::TyVariableKind) |
| { |
| fn to_nextsolver(&self, interner: DbInterner<'db>) -> rustc_type_ir::InferTy { |
| match self.1 { |
| chalk_ir::TyVariableKind::General => { |
| rustc_type_ir::InferTy::TyVar(rustc_type_ir::TyVid::from_u32(self.0.index())) |
| } |
| chalk_ir::TyVariableKind::Integer => { |
| rustc_type_ir::InferTy::IntVar(rustc_type_ir::IntVid::from_u32(self.0.index())) |
| } |
| chalk_ir::TyVariableKind::Float => { |
| rustc_type_ir::InferTy::FloatVar(rustc_type_ir::FloatVid::from_u32(self.0.index())) |
| } |
| } |
| } |
| } |
| |
| impl<'db> ChalkToNextSolver<'db, rustc_ast_ir::Mutability> for chalk_ir::Mutability { |
| fn to_nextsolver(&self, interner: DbInterner<'db>) -> rustc_ast_ir::Mutability { |
| match self { |
| chalk_ir::Mutability::Mut => rustc_ast_ir::Mutability::Mut, |
| chalk_ir::Mutability::Not => rustc_ast_ir::Mutability::Not, |
| } |
| } |
| } |
| |
| impl<'db> ChalkToNextSolver<'db, rustc_type_ir::Variance> for crate::Variance { |
| fn to_nextsolver(&self, interner: DbInterner<'db>) -> rustc_type_ir::Variance { |
| match self { |
| crate::Variance::Covariant => rustc_type_ir::Variance::Covariant, |
| crate::Variance::Invariant => rustc_type_ir::Variance::Invariant, |
| crate::Variance::Contravariant => rustc_type_ir::Variance::Contravariant, |
| crate::Variance::Bivariant => rustc_type_ir::Variance::Bivariant, |
| } |
| } |
| } |
| |
| impl<'db> ChalkToNextSolver<'db, rustc_type_ir::Variance> for chalk_ir::Variance { |
| fn to_nextsolver(&self, interner: DbInterner<'db>) -> rustc_type_ir::Variance { |
| match self { |
| chalk_ir::Variance::Covariant => rustc_type_ir::Variance::Covariant, |
| chalk_ir::Variance::Invariant => rustc_type_ir::Variance::Invariant, |
| chalk_ir::Variance::Contravariant => rustc_type_ir::Variance::Contravariant, |
| } |
| } |
| } |
| |
| impl<'db> ChalkToNextSolver<'db, VariancesOf> for chalk_ir::Variances<Interner> { |
| fn to_nextsolver(&self, interner: DbInterner<'db>) -> VariancesOf { |
| VariancesOf::new_from_iter( |
| interner, |
| self.as_slice(Interner).iter().map(|v| v.to_nextsolver(interner)), |
| ) |
| } |
| } |
| |
| impl<'db> ChalkToNextSolver<'db, Goal<DbInterner<'db>, Predicate<'db>>> |
| for chalk_ir::InEnvironment<chalk_ir::Goal<Interner>> |
| { |
| fn to_nextsolver(&self, interner: DbInterner<'db>) -> Goal<DbInterner<'db>, Predicate<'db>> { |
| Goal::new( |
| interner, |
| self.environment.to_nextsolver(interner), |
| self.goal.to_nextsolver(interner), |
| ) |
| } |
| } |
| |
| impl<'db> NextSolverToChalk<'db, chalk_ir::InEnvironment<chalk_ir::Goal<Interner>>> |
| for Goal<DbInterner<'db>, Predicate<'db>> |
| { |
| fn to_chalk( |
| self, |
| interner: DbInterner<'db>, |
| ) -> chalk_ir::InEnvironment<chalk_ir::Goal<Interner>> { |
| chalk_ir::InEnvironment { |
| environment: self.param_env.to_chalk(interner), |
| goal: self.predicate.to_chalk(interner), |
| } |
| } |
| } |
| |
| impl<'db, T: HasInterner<Interner = Interner> + ChalkToNextSolver<'db, U>, U> |
| ChalkToNextSolver<'db, Canonical<'db, U>> for chalk_ir::Canonical<T> |
| { |
| fn to_nextsolver(&self, interner: DbInterner<'db>) -> Canonical<'db, U> { |
| let variables = CanonicalVars::new_from_iter( |
| interner, |
| self.binders.iter(Interner).map(|k| match &k.kind { |
| chalk_ir::VariableKind::Ty(ty_variable_kind) => match ty_variable_kind { |
| // FIXME(next-solver): the info is incorrect, but we have no way to store the information in Chalk. |
| TyVariableKind::General => rustc_type_ir::CanonicalVarKind::Ty { |
| ui: UniverseIndex::ROOT, |
| sub_root: BoundVar::from_u32(0), |
| }, |
| TyVariableKind::Integer => rustc_type_ir::CanonicalVarKind::Int, |
| TyVariableKind::Float => rustc_type_ir::CanonicalVarKind::Float, |
| }, |
| chalk_ir::VariableKind::Lifetime => { |
| rustc_type_ir::CanonicalVarKind::Region(UniverseIndex::ROOT) |
| } |
| chalk_ir::VariableKind::Const(ty) => { |
| rustc_type_ir::CanonicalVarKind::Const(UniverseIndex::ROOT) |
| } |
| }), |
| ); |
| Canonical { |
| max_universe: UniverseIndex::ROOT, |
| value: self.value.to_nextsolver(interner), |
| variables, |
| } |
| } |
| } |
| |
| impl<'db, T: NextSolverToChalk<'db, U>, U: HasInterner<Interner = Interner>> |
| NextSolverToChalk<'db, chalk_ir::Canonical<U>> for Canonical<'db, T> |
| { |
| fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::Canonical<U> { |
| let binders = chalk_ir::CanonicalVarKinds::from_iter( |
| Interner, |
| self.variables.iter().map(|v| match v { |
| rustc_type_ir::CanonicalVarKind::Ty { ui, sub_root: _ } => { |
| chalk_ir::CanonicalVarKind::new( |
| chalk_ir::VariableKind::Ty(TyVariableKind::General), |
| chalk_ir::UniverseIndex { counter: ui.as_usize() }, |
| ) |
| } |
| rustc_type_ir::CanonicalVarKind::Int => chalk_ir::CanonicalVarKind::new( |
| chalk_ir::VariableKind::Ty(TyVariableKind::Integer), |
| chalk_ir::UniverseIndex::root(), |
| ), |
| rustc_type_ir::CanonicalVarKind::Float => chalk_ir::CanonicalVarKind::new( |
| chalk_ir::VariableKind::Ty(TyVariableKind::Float), |
| chalk_ir::UniverseIndex::root(), |
| ), |
| rustc_type_ir::CanonicalVarKind::Region(ui) => chalk_ir::CanonicalVarKind::new( |
| chalk_ir::VariableKind::Lifetime, |
| chalk_ir::UniverseIndex { counter: ui.as_usize() }, |
| ), |
| rustc_type_ir::CanonicalVarKind::Const(ui) => chalk_ir::CanonicalVarKind::new( |
| chalk_ir::VariableKind::Const(chalk_ir::TyKind::Error.intern(Interner)), |
| chalk_ir::UniverseIndex { counter: ui.as_usize() }, |
| ), |
| rustc_type_ir::CanonicalVarKind::PlaceholderTy(_) => unimplemented!(), |
| rustc_type_ir::CanonicalVarKind::PlaceholderRegion(_) => unimplemented!(), |
| rustc_type_ir::CanonicalVarKind::PlaceholderConst(_) => unimplemented!(), |
| }), |
| ); |
| let value = self.value.to_chalk(interner); |
| chalk_ir::Canonical { binders, value } |
| } |
| } |
| |
| impl<'db> ChalkToNextSolver<'db, Predicate<'db>> for chalk_ir::Goal<Interner> { |
| fn to_nextsolver(&self, interner: DbInterner<'db>) -> Predicate<'db> { |
| match self.data(Interner) { |
| chalk_ir::GoalData::Quantified(quantifier_kind, binders) => { |
| if !binders.binders.is_empty(Interner) { |
| panic!("Should not be constructed."); |
| } |
| let (val, _) = binders.clone().into_value_and_skipped_binders(); |
| val.shifted_out(Interner).unwrap().to_nextsolver(interner) |
| } |
| chalk_ir::GoalData::Implies(program_clauses, goal) => { |
| panic!("Should not be constructed.") |
| } |
| chalk_ir::GoalData::All(goals) => panic!("Should not be constructed."), |
| chalk_ir::GoalData::Not(goal) => panic!("Should not be constructed."), |
| chalk_ir::GoalData::EqGoal(eq_goal) => { |
| let arg_to_term = |g: &chalk_ir::GenericArg<Interner>| match g.data(Interner) { |
| chalk_ir::GenericArgData::Ty(ty) => Term::Ty(ty.to_nextsolver(interner)), |
| chalk_ir::GenericArgData::Const(const_) => { |
| Term::Const(const_.to_nextsolver(interner)) |
| } |
| chalk_ir::GenericArgData::Lifetime(lifetime) => unreachable!(), |
| }; |
| let pred_kind = PredicateKind::AliasRelate( |
| arg_to_term(&eq_goal.a), |
| arg_to_term(&eq_goal.b), |
| rustc_type_ir::AliasRelationDirection::Equate, |
| ); |
| let pred_kind = |
| Binder::bind_with_vars(pred_kind, BoundVarKinds::new_from_iter(interner, [])); |
| Predicate::new(interner, pred_kind) |
| } |
| chalk_ir::GoalData::SubtypeGoal(subtype_goal) => { |
| let subtype_predicate = SubtypePredicate { |
| a: subtype_goal.a.to_nextsolver(interner), |
| b: subtype_goal.b.to_nextsolver(interner), |
| a_is_expected: true, |
| }; |
| let pred_kind = PredicateKind::Subtype(subtype_predicate); |
| let pred_kind = Binder::bind_with_vars( |
| shift_vars(interner, pred_kind, 1), |
| BoundVarKinds::new_from_iter(interner, []), |
| ); |
| Predicate::new(interner, pred_kind) |
| } |
| chalk_ir::GoalData::DomainGoal(domain_goal) => { |
| let pred_kind = domain_goal.to_nextsolver(interner); |
| let pred_kind = Binder::bind_with_vars( |
| shift_vars(interner, pred_kind, 1), |
| BoundVarKinds::new_from_iter(interner, []), |
| ); |
| Predicate::new(interner, pred_kind) |
| } |
| chalk_ir::GoalData::CannotProve => panic!("Should not be constructed."), |
| } |
| } |
| } |
| |
| impl<'db> NextSolverToChalk<'db, chalk_ir::Goal<Interner>> for Predicate<'db> { |
| fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::Goal<Interner> { |
| chalk_ir::Goal::new(Interner, self.kind().skip_binder().to_chalk(interner)) |
| } |
| } |
| |
| impl<'db> ChalkToNextSolver<'db, ParamEnv<'db>> for chalk_ir::Environment<Interner> { |
| fn to_nextsolver(&self, interner: DbInterner<'db>) -> ParamEnv<'db> { |
| let clauses = Clauses::new_from_iter( |
| interner, |
| self.clauses.iter(Interner).map(|c| c.to_nextsolver(interner)), |
| ); |
| let clauses = |
| Clauses::new_from_iter(interner, elaborate::elaborate(interner, clauses.iter())); |
| ParamEnv { clauses } |
| } |
| } |
| |
| impl<'db> NextSolverToChalk<'db, chalk_ir::Environment<Interner>> for ParamEnv<'db> { |
| fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::Environment<Interner> { |
| let clauses = chalk_ir::ProgramClauses::from_iter( |
| Interner, |
| self.clauses.iter().filter_map(|c| -> Option<chalk_ir::ProgramClause<Interner>> { |
| c.to_chalk(interner) |
| }), |
| ); |
| chalk_ir::Environment { clauses } |
| } |
| } |
| |
| impl<'db> ChalkToNextSolver<'db, Clause<'db>> for chalk_ir::ProgramClause<Interner> { |
| fn to_nextsolver(&self, interner: DbInterner<'db>) -> Clause<'db> { |
| Clause(Predicate::new(interner, self.data(Interner).0.to_nextsolver(interner))) |
| } |
| } |
| |
| impl<'db> NextSolverToChalk<'db, Option<chalk_ir::ProgramClause<Interner>>> for Clause<'db> { |
| fn to_chalk(self, interner: DbInterner<'db>) -> Option<chalk_ir::ProgramClause<Interner>> { |
| let value: chalk_ir::ProgramClauseImplication<Interner> = |
| <PredicateKind<'db> as NextSolverToChalk< |
| 'db, |
| Option<chalk_ir::ProgramClauseImplication<Interner>>, |
| >>::to_chalk(self.0.kind().skip_binder(), interner)?; |
| Some(chalk_ir::ProgramClause::new( |
| Interner, |
| chalk_ir::ProgramClauseData(chalk_ir::Binders::empty(Interner, value)), |
| )) |
| } |
| } |
| |
| impl<'db> ChalkToNextSolver<'db, PredicateKind<'db>> |
| for chalk_ir::ProgramClauseImplication<Interner> |
| { |
| fn to_nextsolver(&self, interner: DbInterner<'db>) -> PredicateKind<'db> { |
| assert!(self.conditions.is_empty(Interner)); |
| assert!(self.constraints.is_empty(Interner)); |
| self.consequence.to_nextsolver(interner) |
| } |
| } |
| |
| impl<'db> NextSolverToChalk<'db, Option<chalk_ir::ProgramClauseImplication<Interner>>> |
| for PredicateKind<'db> |
| { |
| fn to_chalk( |
| self, |
| interner: DbInterner<'db>, |
| ) -> Option<chalk_ir::ProgramClauseImplication<Interner>> { |
| let chalk_ir::GoalData::DomainGoal(consequence) = self.to_chalk(interner) else { |
| return None; |
| }; |
| |
| Some(chalk_ir::ProgramClauseImplication { |
| consequence, |
| conditions: chalk_ir::Goals::empty(Interner), |
| constraints: chalk_ir::Constraints::empty(Interner), |
| priority: chalk_ir::ClausePriority::High, |
| }) |
| } |
| } |
| |
| impl<'db> ChalkToNextSolver<'db, PredicateKind<'db>> for chalk_ir::DomainGoal<Interner> { |
| fn to_nextsolver(&self, interner: DbInterner<'db>) -> PredicateKind<'db> { |
| match self { |
| chalk_ir::DomainGoal::Holds(where_clause) => match where_clause { |
| chalk_ir::WhereClause::Implemented(trait_ref) => { |
| let predicate = TraitPredicate { |
| trait_ref: trait_ref.to_nextsolver(interner), |
| polarity: rustc_type_ir::PredicatePolarity::Positive, |
| }; |
| PredicateKind::Clause(ClauseKind::Trait(predicate)) |
| } |
| chalk_ir::WhereClause::AliasEq(alias_eq) => match &alias_eq.alias { |
| chalk_ir::AliasTy::Projection(p) => { |
| let def_id = |
| SolverDefId::TypeAliasId(from_assoc_type_id(p.associated_ty_id)); |
| let args = p.substitution.to_nextsolver(interner); |
| let term: Ty<'db> = alias_eq.ty.to_nextsolver(interner); |
| let term: Term<'db> = term.into(); |
| let predicate = ProjectionPredicate { |
| projection_term: AliasTerm::new_from_args(interner, def_id, args), |
| term, |
| }; |
| PredicateKind::Clause(ClauseKind::Projection(predicate)) |
| } |
| chalk_ir::AliasTy::Opaque(opaque) => { |
| let id: InternedOpaqueTyId = opaque.opaque_ty_id.into(); |
| let def_id = SolverDefId::InternedOpaqueTyId(id); |
| let args = opaque.substitution.to_nextsolver(interner); |
| let term: Ty<'db> = alias_eq.ty.to_nextsolver(interner); |
| let term: Term<'db> = term.into(); |
| let opaque_ty = Ty::new( |
| interner, |
| rustc_type_ir::TyKind::Alias( |
| rustc_type_ir::AliasTyKind::Opaque, |
| rustc_type_ir::AliasTy::new_from_args(interner, def_id, args), |
| ), |
| ) |
| .into(); |
| PredicateKind::AliasRelate( |
| opaque_ty, |
| term, |
| rustc_type_ir::AliasRelationDirection::Equate, |
| ) |
| } |
| }, |
| chalk_ir::WhereClause::LifetimeOutlives(lifetime_outlives) => { |
| let predicate = OutlivesPredicate( |
| lifetime_outlives.a.to_nextsolver(interner), |
| lifetime_outlives.b.to_nextsolver(interner), |
| ); |
| PredicateKind::Clause(ClauseKind::RegionOutlives(predicate)) |
| } |
| chalk_ir::WhereClause::TypeOutlives(type_outlives) => { |
| let predicate = OutlivesPredicate( |
| type_outlives.ty.to_nextsolver(interner), |
| type_outlives.lifetime.to_nextsolver(interner), |
| ); |
| PredicateKind::Clause(ClauseKind::TypeOutlives(predicate)) |
| } |
| }, |
| chalk_ir::DomainGoal::Normalize(normalize) => { |
| let proj_ty = match &normalize.alias { |
| chalk_ir::AliasTy::Projection(proj) => proj, |
| _ => unimplemented!(), |
| }; |
| let args: GenericArgs<'db> = proj_ty.substitution.to_nextsolver(interner); |
| let alias = Ty::new( |
| interner, |
| rustc_type_ir::TyKind::Alias( |
| rustc_type_ir::AliasTyKind::Projection, |
| rustc_type_ir::AliasTy::new( |
| interner, |
| from_assoc_type_id(proj_ty.associated_ty_id).into(), |
| args, |
| ), |
| ), |
| ) |
| .into(); |
| let term = normalize.ty.to_nextsolver(interner).into(); |
| PredicateKind::AliasRelate( |
| alias, |
| term, |
| rustc_type_ir::AliasRelationDirection::Equate, |
| ) |
| } |
| chalk_ir::DomainGoal::WellFormed(well_formed) => { |
| let term = match well_formed { |
| WellFormed::Trait(_) => panic!("Should not be constructed."), |
| WellFormed::Ty(ty) => Term::Ty(ty.to_nextsolver(interner)), |
| }; |
| PredicateKind::Clause(rustc_type_ir::ClauseKind::WellFormed(term)) |
| } |
| chalk_ir::DomainGoal::FromEnv(from_env) => match from_env { |
| chalk_ir::FromEnv::Trait(trait_ref) => { |
| let predicate = TraitPredicate { |
| trait_ref: trait_ref.to_nextsolver(interner), |
| polarity: rustc_type_ir::PredicatePolarity::Positive, |
| }; |
| PredicateKind::Clause(ClauseKind::Trait(predicate)) |
| } |
| chalk_ir::FromEnv::Ty(ty) => PredicateKind::Clause(ClauseKind::WellFormed( |
| Term::Ty(ty.to_nextsolver(interner)), |
| )), |
| }, |
| chalk_ir::DomainGoal::IsLocal(ty) => panic!("Should not be constructed."), |
| chalk_ir::DomainGoal::IsUpstream(ty) => panic!("Should not be constructed."), |
| chalk_ir::DomainGoal::IsFullyVisible(ty) => panic!("Should not be constructed."), |
| chalk_ir::DomainGoal::LocalImplAllowed(trait_ref) => { |
| panic!("Should not be constructed.") |
| } |
| chalk_ir::DomainGoal::Compatible => panic!("Should not be constructed."), |
| chalk_ir::DomainGoal::DownstreamType(ty) => panic!("Should not be constructed."), |
| chalk_ir::DomainGoal::Reveal => panic!("Should not be constructed."), |
| chalk_ir::DomainGoal::ObjectSafe(trait_id) => panic!("Should not be constructed."), |
| } |
| } |
| } |
| |
| impl<'db> NextSolverToChalk<'db, chalk_ir::GoalData<Interner>> for PredicateKind<'db> { |
| fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::GoalData<Interner> { |
| match self { |
| rustc_type_ir::PredicateKind::Clause(rustc_type_ir::ClauseKind::Trait(trait_pred)) => { |
| let trait_ref = trait_pred.trait_ref.to_chalk(interner); |
| let where_clause = chalk_ir::WhereClause::Implemented(trait_ref); |
| chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(where_clause)) |
| } |
| rustc_type_ir::PredicateKind::Clause(rustc_type_ir::ClauseKind::Projection( |
| proj_predicate, |
| )) => { |
| let associated_ty_id = match proj_predicate.def_id() { |
| SolverDefId::TypeAliasId(id) => to_assoc_type_id(id), |
| _ => unreachable!(), |
| }; |
| let substitution = proj_predicate.projection_term.args.to_chalk(interner); |
| let alias = chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy { |
| associated_ty_id, |
| substitution, |
| }); |
| let ty = match proj_predicate.term.kind() { |
| rustc_type_ir::TermKind::Ty(ty) => ty, |
| rustc_type_ir::TermKind::Const(_) => unimplemented!(), |
| }; |
| let ty = ty.to_chalk(interner); |
| let alias_eq = chalk_ir::AliasEq { alias, ty }; |
| let where_clause = chalk_ir::WhereClause::AliasEq(alias_eq); |
| chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(where_clause)) |
| } |
| rustc_type_ir::PredicateKind::Clause(rustc_type_ir::ClauseKind::TypeOutlives( |
| outlives, |
| )) => { |
| let lifetime = outlives.1.to_chalk(interner); |
| let ty = outlives.0.to_chalk(interner); |
| let where_clause = |
| chalk_ir::WhereClause::TypeOutlives(chalk_ir::TypeOutlives { lifetime, ty }); |
| chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(where_clause)) |
| } |
| rustc_type_ir::PredicateKind::Clause(rustc_type_ir::ClauseKind::RegionOutlives( |
| outlives, |
| )) => { |
| let a = outlives.0.to_chalk(interner); |
| let b = outlives.1.to_chalk(interner); |
| let where_clause = |
| chalk_ir::WhereClause::LifetimeOutlives(chalk_ir::LifetimeOutlives { a, b }); |
| chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(where_clause)) |
| } |
| rustc_type_ir::PredicateKind::AliasRelate( |
| alias_term, |
| target_term, |
| alias_relation_direction, |
| ) => { |
| let term_to_generic_arg = |term: Term<'db>| match term { |
| Term::Ty(ty) => chalk_ir::GenericArg::new( |
| Interner, |
| chalk_ir::GenericArgData::Ty(ty.to_chalk(interner)), |
| ), |
| Term::Const(const_) => chalk_ir::GenericArg::new( |
| Interner, |
| chalk_ir::GenericArgData::Const(const_.to_chalk(interner)), |
| ), |
| }; |
| |
| chalk_ir::GoalData::EqGoal(chalk_ir::EqGoal { |
| a: term_to_generic_arg(alias_term), |
| b: term_to_generic_arg(target_term), |
| }) |
| } |
| rustc_type_ir::PredicateKind::Clause(_) => unimplemented!(), |
| rustc_type_ir::PredicateKind::DynCompatible(_) => unimplemented!(), |
| rustc_type_ir::PredicateKind::Subtype(_) => unimplemented!(), |
| rustc_type_ir::PredicateKind::Coerce(_) => unimplemented!(), |
| rustc_type_ir::PredicateKind::ConstEquate(_, _) => unimplemented!(), |
| rustc_type_ir::PredicateKind::Ambiguous => unimplemented!(), |
| rustc_type_ir::PredicateKind::NormalizesTo(_) => unimplemented!(), |
| } |
| } |
| } |
| |
| impl<'db> ChalkToNextSolver<'db, TraitRef<'db>> for chalk_ir::TraitRef<Interner> { |
| fn to_nextsolver(&self, interner: DbInterner<'db>) -> TraitRef<'db> { |
| let args = self.substitution.to_nextsolver(interner); |
| TraitRef::new_from_args(interner, from_chalk_trait_id(self.trait_id).into(), args) |
| } |
| } |
| |
| impl<'db> NextSolverToChalk<'db, chalk_ir::TraitRef<Interner>> for TraitRef<'db> { |
| fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::TraitRef<Interner> { |
| let trait_id = to_chalk_trait_id(self.def_id.0); |
| let substitution = self.args.to_chalk(interner); |
| chalk_ir::TraitRef { trait_id, substitution } |
| } |
| } |
| |
| impl<'db> ChalkToNextSolver<'db, PredicateKind<'db>> for chalk_ir::WhereClause<Interner> { |
| fn to_nextsolver(&self, interner: DbInterner<'db>) -> PredicateKind<'db> { |
| match self { |
| chalk_ir::WhereClause::Implemented(trait_ref) => { |
| let predicate = TraitPredicate { |
| trait_ref: trait_ref.to_nextsolver(interner), |
| polarity: rustc_type_ir::PredicatePolarity::Positive, |
| }; |
| PredicateKind::Clause(ClauseKind::Trait(predicate)) |
| } |
| chalk_ir::WhereClause::AliasEq(alias_eq) => { |
| let projection = match &alias_eq.alias { |
| chalk_ir::AliasTy::Projection(p) => p, |
| _ => unimplemented!(), |
| }; |
| let def_id = |
| SolverDefId::TypeAliasId(from_assoc_type_id(projection.associated_ty_id)); |
| let args = projection.substitution.to_nextsolver(interner); |
| let term: Ty<'db> = alias_eq.ty.to_nextsolver(interner); |
| let term: Term<'db> = term.into(); |
| let predicate = ProjectionPredicate { |
| projection_term: AliasTerm::new_from_args(interner, def_id, args), |
| term, |
| }; |
| PredicateKind::Clause(ClauseKind::Projection(predicate)) |
| } |
| chalk_ir::WhereClause::TypeOutlives(type_outlives) => { |
| let ty = type_outlives.ty.to_nextsolver(interner); |
| let r = type_outlives.lifetime.to_nextsolver(interner); |
| PredicateKind::Clause(ClauseKind::TypeOutlives(OutlivesPredicate(ty, r))) |
| } |
| chalk_ir::WhereClause::LifetimeOutlives(lifetime_outlives) => { |
| let a = lifetime_outlives.a.to_nextsolver(interner); |
| let b = lifetime_outlives.b.to_nextsolver(interner); |
| PredicateKind::Clause(ClauseKind::RegionOutlives(OutlivesPredicate(a, b))) |
| } |
| } |
| } |
| } |
| |
| impl<'db, I> NextSolverToChalk<'db, chalk_ir::ConstrainedSubst<Interner>> for I |
| where |
| I: IntoIterator<Item = GenericArg<'db>>, |
| { |
| fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::ConstrainedSubst<Interner> { |
| chalk_ir::ConstrainedSubst { |
| constraints: chalk_ir::Constraints::empty(Interner), |
| subst: GenericArgs::new_from_iter(interner, self).to_chalk(interner), |
| } |
| } |
| } |
| |
| pub fn convert_canonical_args_for_result<'db>( |
| interner: DbInterner<'db>, |
| args: Canonical<'db, Vec<GenericArg<'db>>>, |
| ) -> chalk_ir::Canonical<chalk_ir::ConstrainedSubst<Interner>> { |
| args.to_chalk(interner) |
| } |
| |
| pub fn convert_args_for_result<'db>( |
| interner: DbInterner<'db>, |
| args: &[GenericArg<'db>], |
| ) -> crate::Substitution { |
| let mut substs = Vec::with_capacity(args.len()); |
| for arg in args { |
| match (*arg).kind() { |
| rustc_type_ir::GenericArgKind::Type(ty) => { |
| let ty = convert_ty_for_result(interner, ty); |
| substs.push(chalk_ir::GenericArgData::Ty(ty).intern(Interner)); |
| } |
| rustc_type_ir::GenericArgKind::Lifetime(region) => { |
| let lifetime = convert_region_for_result(interner, region); |
| substs.push(chalk_ir::GenericArgData::Lifetime(lifetime).intern(Interner)); |
| } |
| rustc_type_ir::GenericArgKind::Const(const_) => { |
| substs.push( |
| chalk_ir::GenericArgData::Const(convert_const_for_result(interner, const_)) |
| .intern(Interner), |
| ); |
| } |
| } |
| } |
| Substitution::from_iter(Interner, substs) |
| } |
| |
| pub(crate) fn convert_ty_for_result<'db>(interner: DbInterner<'db>, ty: Ty<'db>) -> crate::Ty { |
| use crate::{Scalar, TyKind}; |
| use chalk_ir::{FloatTy, IntTy, UintTy}; |
| match ty.kind() { |
| rustc_type_ir::TyKind::Bool => TyKind::Scalar(Scalar::Bool), |
| rustc_type_ir::TyKind::Char => TyKind::Scalar(Scalar::Char), |
| rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I8) => { |
| TyKind::Scalar(Scalar::Int(IntTy::I8)) |
| } |
| rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I16) => { |
| TyKind::Scalar(Scalar::Int(IntTy::I16)) |
| } |
| rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I32) => { |
| TyKind::Scalar(Scalar::Int(IntTy::I32)) |
| } |
| rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I64) => { |
| TyKind::Scalar(Scalar::Int(IntTy::I64)) |
| } |
| rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I128) => { |
| TyKind::Scalar(Scalar::Int(IntTy::I128)) |
| } |
| rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::Isize) => { |
| TyKind::Scalar(Scalar::Int(IntTy::Isize)) |
| } |
| rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U8) => { |
| TyKind::Scalar(Scalar::Uint(UintTy::U8)) |
| } |
| rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U16) => { |
| TyKind::Scalar(Scalar::Uint(UintTy::U16)) |
| } |
| rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U32) => { |
| TyKind::Scalar(Scalar::Uint(UintTy::U32)) |
| } |
| rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U64) => { |
| TyKind::Scalar(Scalar::Uint(UintTy::U64)) |
| } |
| rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U128) => { |
| TyKind::Scalar(Scalar::Uint(UintTy::U128)) |
| } |
| rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::Usize) => { |
| TyKind::Scalar(Scalar::Uint(UintTy::Usize)) |
| } |
| rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F16) => { |
| TyKind::Scalar(Scalar::Float(FloatTy::F16)) |
| } |
| rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F32) => { |
| TyKind::Scalar(Scalar::Float(FloatTy::F32)) |
| } |
| rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F64) => { |
| TyKind::Scalar(Scalar::Float(FloatTy::F64)) |
| } |
| rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F128) => { |
| TyKind::Scalar(Scalar::Float(FloatTy::F128)) |
| } |
| rustc_type_ir::TyKind::Str => TyKind::Str, |
| rustc_type_ir::TyKind::Error(_) => TyKind::Error, |
| rustc_type_ir::TyKind::Never => TyKind::Never, |
| |
| rustc_type_ir::TyKind::Adt(def, args) => { |
| let adt_id = def.inner().id; |
| let subst = convert_args_for_result(interner, args.as_slice()); |
| TyKind::Adt(chalk_ir::AdtId(adt_id), subst) |
| } |
| |
| rustc_type_ir::TyKind::Infer(infer_ty) => { |
| let (var, kind) = match infer_ty { |
| rustc_type_ir::InferTy::TyVar(var) => { |
| (InferenceVar::from(var.as_u32()), TyVariableKind::General) |
| } |
| rustc_type_ir::InferTy::IntVar(var) => { |
| (InferenceVar::from(var.as_u32()), TyVariableKind::Integer) |
| } |
| rustc_type_ir::InferTy::FloatVar(var) => { |
| (InferenceVar::from(var.as_u32()), TyVariableKind::Float) |
| } |
| rustc_type_ir::InferTy::FreshFloatTy(..) |
| | rustc_type_ir::InferTy::FreshIntTy(..) |
| | rustc_type_ir::InferTy::FreshTy(..) => { |
| panic!("Freshening shouldn't happen.") |
| } |
| }; |
| TyKind::InferenceVar(var, kind) |
| } |
| |
| rustc_type_ir::TyKind::Ref(r, ty, mutability) => { |
| let mutability = match mutability { |
| rustc_ast_ir::Mutability::Mut => chalk_ir::Mutability::Mut, |
| rustc_ast_ir::Mutability::Not => chalk_ir::Mutability::Not, |
| }; |
| let r = convert_region_for_result(interner, r); |
| let ty = convert_ty_for_result(interner, ty); |
| TyKind::Ref(mutability, r, ty) |
| } |
| |
| rustc_type_ir::TyKind::Tuple(tys) => { |
| let size = tys.len(); |
| let subst = Substitution::from_iter( |
| Interner, |
| tys.iter().map(|ty| { |
| chalk_ir::GenericArgData::Ty(convert_ty_for_result(interner, ty)) |
| .intern(Interner) |
| }), |
| ); |
| TyKind::Tuple(size, subst) |
| } |
| |
| rustc_type_ir::TyKind::Array(ty, const_) => { |
| let ty = convert_ty_for_result(interner, ty); |
| let const_ = convert_const_for_result(interner, const_); |
| TyKind::Array(ty, const_) |
| } |
| |
| rustc_type_ir::TyKind::Alias(alias_ty_kind, alias_ty) => match alias_ty_kind { |
| rustc_type_ir::AliasTyKind::Projection => { |
| let assoc_ty_id = match alias_ty.def_id { |
| SolverDefId::TypeAliasId(id) => id, |
| _ => unreachable!(), |
| }; |
| let associated_ty_id = to_assoc_type_id(assoc_ty_id); |
| let substitution = convert_args_for_result(interner, alias_ty.args.as_slice()); |
| TyKind::AssociatedType(associated_ty_id, substitution) |
| } |
| rustc_type_ir::AliasTyKind::Opaque => { |
| let opaque_ty_id = match alias_ty.def_id { |
| SolverDefId::InternedOpaqueTyId(id) => id, |
| _ => unreachable!(), |
| }; |
| let substitution = convert_args_for_result(interner, alias_ty.args.as_slice()); |
| TyKind::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy { |
| opaque_ty_id: opaque_ty_id.into(), |
| substitution, |
| })) |
| } |
| rustc_type_ir::AliasTyKind::Inherent => unimplemented!(), |
| rustc_type_ir::AliasTyKind::Free => unimplemented!(), |
| }, |
| |
| // For `Placeholder`, `Bound` and `Param`, see the comment on the reverse conversion. |
| rustc_type_ir::TyKind::Placeholder(placeholder) => { |
| unimplemented!( |
| "A `rustc_type_ir::TyKind::Placeholder` doesn't have a direct \ |
| correspondence in Chalk, as it represents a universally instantiated `Bound`.\n\ |
| It therefore feels safer to leave it panicking, but if you hit this panic \ |
| feel free to do the same as in `rustc_type_ir::TyKind::Bound` here." |
| ) |
| } |
| rustc_type_ir::TyKind::Bound(debruijn_index, ty) => TyKind::BoundVar(chalk_ir::BoundVar { |
| debruijn: chalk_ir::DebruijnIndex::new(debruijn_index.as_u32()), |
| index: ty.var.as_usize(), |
| }), |
| rustc_type_ir::TyKind::Param(param) => { |
| let placeholder = to_placeholder_idx(interner.db, param.id.into(), param.index); |
| TyKind::Placeholder(placeholder) |
| } |
| |
| rustc_type_ir::TyKind::FnPtr(bound_sig, fn_header) => { |
| let num_binders = bound_sig.bound_vars().len(); |
| let sig = chalk_ir::FnSig { |
| abi: fn_header.abi, |
| safety: match fn_header.safety { |
| crate::next_solver::abi::Safety::Safe => chalk_ir::Safety::Safe, |
| crate::next_solver::abi::Safety::Unsafe => chalk_ir::Safety::Unsafe, |
| }, |
| variadic: fn_header.c_variadic, |
| }; |
| let args = GenericArgs::new_from_iter( |
| interner, |
| bound_sig.skip_binder().inputs_and_output.iter().map(|a| a.into()), |
| ); |
| let substitution = convert_args_for_result(interner, args.as_slice()); |
| let substitution = chalk_ir::FnSubst(substitution); |
| let fnptr = chalk_ir::FnPointer { num_binders, sig, substitution }; |
| TyKind::Function(fnptr) |
| } |
| |
| rustc_type_ir::TyKind::Dynamic(preds, region, dyn_kind) => { |
| assert!(matches!(dyn_kind, rustc_type_ir::DynKind::Dyn)); |
| let self_ty = Ty::new_bound( |
| interner, |
| DebruijnIndex::from_u32(1), |
| BoundTy { kind: BoundTyKind::Anon, var: BoundVar::from_u32(0) }, |
| ); |
| let bounds = chalk_ir::QuantifiedWhereClauses::from_iter( |
| Interner, |
| preds.iter().map(|p| { |
| let binders = chalk_ir::VariableKinds::from_iter( |
| Interner, |
| p.bound_vars().iter().map(|b| match b { |
| BoundVarKind::Ty(kind) => { |
| chalk_ir::VariableKind::Ty(TyVariableKind::General) |
| } |
| BoundVarKind::Region(kind) => chalk_ir::VariableKind::Lifetime, |
| BoundVarKind::Const => { |
| chalk_ir::VariableKind::Const(crate::TyKind::Error.intern(Interner)) |
| } |
| }), |
| ); |
| |
| // Rust and chalk have slightly different |
| // representation for trait objects. |
| // |
| // Chalk uses `for<T0> for<'a> T0: Trait<'a>` while rustc |
| // uses `ExistentialPredicate`s, which do not have a self ty. |
| // We need to shift escaping bound vars by 1 to accommodate |
| // the newly introduced `for<T0>` binder. |
| let p = shift_vars(interner, p, 1); |
| |
| let where_clause = match p.skip_binder() { |
| rustc_type_ir::ExistentialPredicate::Trait(trait_ref) => { |
| let trait_ref = TraitRef::new( |
| interner, |
| trait_ref.def_id, |
| [self_ty.into()].into_iter().chain(trait_ref.args.iter()), |
| ); |
| let trait_id = to_chalk_trait_id(trait_ref.def_id.0); |
| let substitution = |
| convert_args_for_result(interner, trait_ref.args.as_slice()); |
| let trait_ref = chalk_ir::TraitRef { trait_id, substitution }; |
| chalk_ir::WhereClause::Implemented(trait_ref) |
| } |
| rustc_type_ir::ExistentialPredicate::AutoTrait(trait_) => { |
| let trait_id = to_chalk_trait_id(trait_.0); |
| let substitution = chalk_ir::Substitution::from1( |
| Interner, |
| convert_ty_for_result(interner, self_ty), |
| ); |
| let trait_ref = chalk_ir::TraitRef { trait_id, substitution }; |
| chalk_ir::WhereClause::Implemented(trait_ref) |
| } |
| rustc_type_ir::ExistentialPredicate::Projection(existential_projection) => { |
| let projection = ProjectionPredicate { |
| projection_term: AliasTerm::new( |
| interner, |
| existential_projection.def_id, |
| [self_ty.into()] |
| .iter() |
| .chain(existential_projection.args.iter()), |
| ), |
| term: existential_projection.term, |
| }; |
| let associated_ty_id = match projection.projection_term.def_id { |
| SolverDefId::TypeAliasId(id) => to_assoc_type_id(id), |
| _ => unreachable!(), |
| }; |
| let substitution = convert_args_for_result( |
| interner, |
| projection.projection_term.args.as_slice(), |
| ); |
| let alias = chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy { |
| associated_ty_id, |
| substitution, |
| }); |
| let ty = match projection.term { |
| Term::Ty(ty) => ty, |
| _ => unreachable!(), |
| }; |
| let ty = convert_ty_for_result(interner, ty); |
| let alias_eq = chalk_ir::AliasEq { alias, ty }; |
| chalk_ir::WhereClause::AliasEq(alias_eq) |
| } |
| }; |
| chalk_ir::Binders::new(binders, where_clause) |
| }), |
| ); |
| let binders = chalk_ir::VariableKinds::from1( |
| Interner, |
| chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), |
| ); |
| let bounds = chalk_ir::Binders::new(binders, bounds); |
| let dyn_ty = |
| chalk_ir::DynTy { bounds, lifetime: convert_region_for_result(interner, region) }; |
| TyKind::Dyn(dyn_ty) |
| } |
| |
| rustc_type_ir::TyKind::Slice(ty) => { |
| let ty = convert_ty_for_result(interner, ty); |
| TyKind::Slice(ty) |
| } |
| |
| rustc_type_ir::TyKind::Foreign(foreign) => TyKind::Foreign(to_foreign_def_id(foreign.0)), |
| rustc_type_ir::TyKind::Pat(_, _) => unimplemented!(), |
| rustc_type_ir::TyKind::RawPtr(ty, mutability) => { |
| let mutability = match mutability { |
| rustc_ast_ir::Mutability::Mut => chalk_ir::Mutability::Mut, |
| rustc_ast_ir::Mutability::Not => chalk_ir::Mutability::Not, |
| }; |
| let ty = convert_ty_for_result(interner, ty); |
| TyKind::Raw(mutability, ty) |
| } |
| rustc_type_ir::TyKind::FnDef(def_id, args) => { |
| let subst = convert_args_for_result(interner, args.as_slice()); |
| TyKind::FnDef(def_id.0.to_chalk(interner.db()), subst) |
| } |
| |
| rustc_type_ir::TyKind::Closure(def_id, args) => { |
| let subst = convert_args_for_result(interner, args.as_slice()); |
| TyKind::Closure(def_id.0.into(), subst) |
| } |
| rustc_type_ir::TyKind::CoroutineClosure(_, _) => unimplemented!(), |
| rustc_type_ir::TyKind::Coroutine(def_id, args) => { |
| let subst = convert_args_for_result(interner, args.as_slice()); |
| TyKind::Coroutine(def_id.0.into(), subst) |
| } |
| rustc_type_ir::TyKind::CoroutineWitness(def_id, args) => { |
| let subst = convert_args_for_result(interner, args.as_slice()); |
| TyKind::CoroutineWitness(def_id.0.into(), subst) |
| } |
| |
| rustc_type_ir::TyKind::UnsafeBinder(_) => unimplemented!(), |
| } |
| .intern(Interner) |
| } |
| |
| pub fn convert_const_for_result<'db>( |
| interner: DbInterner<'db>, |
| const_: Const<'db>, |
| ) -> crate::Const { |
| let value: chalk_ir::ConstValue<Interner> = match const_.kind() { |
| rustc_type_ir::ConstKind::Infer(rustc_type_ir::InferConst::Var(var)) => { |
| chalk_ir::ConstValue::InferenceVar(chalk_ir::InferenceVar::from(var.as_u32())) |
| } |
| rustc_type_ir::ConstKind::Infer(rustc_type_ir::InferConst::Fresh(fresh)) => { |
| panic!("Vars should not be freshened.") |
| } |
| rustc_type_ir::ConstKind::Param(param) => { |
| let placeholder = to_placeholder_idx(interner.db, param.id.into(), param.index); |
| chalk_ir::ConstValue::Placeholder(placeholder) |
| } |
| rustc_type_ir::ConstKind::Bound(debruijn_index, var) => { |
| chalk_ir::ConstValue::BoundVar(chalk_ir::BoundVar::new( |
| chalk_ir::DebruijnIndex::new(debruijn_index.as_u32()), |
| var.var.index(), |
| )) |
| } |
| rustc_type_ir::ConstKind::Placeholder(placeholder_const) => { |
| unimplemented!( |
| "A `rustc_type_ir::ConstKind::Placeholder` doesn't have a direct \ |
| correspondence in Chalk, as it represents a universally instantiated `Bound`.\n\ |
| It therefore feels safer to leave it panicking, but if you hit this panic \ |
| feel free to do the same as in `rustc_type_ir::ConstKind::Bound` here." |
| ) |
| } |
| rustc_type_ir::ConstKind::Unevaluated(unevaluated_const) => { |
| let id = match unevaluated_const.def { |
| SolverDefId::ConstId(id) => GeneralConstId::ConstId(id), |
| SolverDefId::StaticId(id) => GeneralConstId::StaticId(id), |
| _ => unreachable!(), |
| }; |
| let subst = convert_args_for_result(interner, unevaluated_const.args.as_slice()); |
| chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { |
| interned: ConstScalar::UnevaluatedConst(id, subst), |
| }) |
| } |
| rustc_type_ir::ConstKind::Value(value_const) => { |
| let bytes = value_const.value.inner(); |
| let value = chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { |
| // SAFETY: we will never actually use this without a database |
| interned: ConstScalar::Bytes(bytes.0.clone(), unsafe { |
| std::mem::transmute::<MemoryMap<'db>, MemoryMap<'static>>(bytes.1.clone()) |
| }), |
| }); |
| return chalk_ir::ConstData { |
| ty: convert_ty_for_result(interner, value_const.ty), |
| value, |
| } |
| .intern(Interner); |
| } |
| rustc_type_ir::ConstKind::Error(_) => { |
| chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { |
| interned: ConstScalar::Unknown, |
| }) |
| } |
| rustc_type_ir::ConstKind::Expr(_) => unimplemented!(), |
| }; |
| chalk_ir::ConstData { ty: crate::TyKind::Error.intern(Interner), value }.intern(Interner) |
| } |
| |
| pub fn convert_region_for_result<'db>( |
| interner: DbInterner<'db>, |
| region: Region<'db>, |
| ) -> crate::Lifetime { |
| let lifetime = match region.kind() { |
| rustc_type_ir::RegionKind::ReEarlyParam(early) => { |
| let placeholder = lt_to_placeholder_idx(interner.db, early.id, early.index); |
| chalk_ir::LifetimeData::Placeholder(placeholder) |
| } |
| rustc_type_ir::RegionKind::ReBound(db, bound) => { |
| chalk_ir::LifetimeData::BoundVar(chalk_ir::BoundVar::new( |
| chalk_ir::DebruijnIndex::new(db.as_u32()), |
| bound.var.as_usize(), |
| )) |
| } |
| rustc_type_ir::RegionKind::RePlaceholder(placeholder) => unimplemented!( |
| "A `rustc_type_ir::RegionKind::RePlaceholder` doesn't have a direct \ |
| correspondence in Chalk, as it represents a universally instantiated `Bound`.\n\ |
| It therefore feels safer to leave it panicking, but if you hit this panic \ |
| feel free to do the same as in `rustc_type_ir::RegionKind::ReBound` here." |
| ), |
| rustc_type_ir::RegionKind::ReLateParam(_) => unimplemented!(), |
| rustc_type_ir::RegionKind::ReStatic => chalk_ir::LifetimeData::Static, |
| rustc_type_ir::RegionKind::ReVar(vid) => { |
| chalk_ir::LifetimeData::InferenceVar(chalk_ir::InferenceVar::from(vid.as_u32())) |
| } |
| rustc_type_ir::RegionKind::ReErased => chalk_ir::LifetimeData::Erased, |
| rustc_type_ir::RegionKind::ReError(_) => chalk_ir::LifetimeData::Error, |
| }; |
| chalk_ir::Lifetime::new(Interner, lifetime) |
| } |
| |
| pub trait InferenceVarExt { |
| fn to_vid(self) -> rustc_type_ir::TyVid; |
| fn from_vid(vid: rustc_type_ir::TyVid) -> InferenceVar; |
| } |
| |
| impl InferenceVarExt for InferenceVar { |
| fn to_vid(self) -> rustc_type_ir::TyVid { |
| rustc_type_ir::TyVid::from_u32(self.index()) |
| } |
| fn from_vid(vid: rustc_type_ir::TyVid) -> InferenceVar { |
| InferenceVar::from(vid.as_u32()) |
| } |
| } |