diff --git a/crates/hir-ty/src/chalk_ext.rs b/crates/hir-ty/src/chalk_ext.rs index 8fa1aff0ef..33ae099c69 100644 --- a/crates/hir-ty/src/chalk_ext.rs +++ b/crates/hir-ty/src/chalk_ext.rs @@ -306,7 +306,7 @@ impl TyExt for Ty { predicates.map(|it| it.into_value_and_skipped_binders().0) } TyKind::Placeholder(idx) => { - let id = from_placeholder_idx(db, *idx); + let id = from_placeholder_idx(db, *idx).0; let generic_params = db.generic_params(id.parent); let param_data = &generic_params[id.local_id]; match param_data { diff --git a/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs index abf97f3d0e..0f2cc17f56 100644 --- a/crates/hir-ty/src/consteval.rs +++ b/crates/hir-ty/src/consteval.rs @@ -107,25 +107,24 @@ pub(crate) fn path_to_const<'g>( match resolver.resolve_path_in_value_ns_fully(db, path, HygieneId::ROOT) { Some(ValueNs::GenericParam(p)) => { let ty = db.const_param_ty(p); + let args = args(); let value = match mode { ParamLoweringMode::Placeholder => { - ConstValue::Placeholder(to_placeholder_idx(db, p.into())) + let idx = args.type_or_const_param_idx(p.into()).unwrap(); + ConstValue::Placeholder(to_placeholder_idx(db, p.into(), idx as u32)) } - ParamLoweringMode::Variable => { - let args = args(); - match args.type_or_const_param_idx(p.into()) { - Some(it) => ConstValue::BoundVar(BoundVar::new(debruijn, it)), - None => { - never!( - "Generic list doesn't contain this param: {:?}, {:?}, {:?}", - args, - path, - p - ); - return None; - } + ParamLoweringMode::Variable => match args.type_or_const_param_idx(p.into()) { + Some(it) => ConstValue::BoundVar(BoundVar::new(debruijn, it)), + None => { + never!( + "Generic list doesn't contain this param: {:?}, {:?}, {:?}", + args, + path, + p + ); + return None; } - } + }, }; Some(ConstData { ty, value }.intern(Interner)) } diff --git a/crates/hir-ty/src/consteval_nextsolver.rs b/crates/hir-ty/src/consteval_nextsolver.rs index 00fc4e5610..4f95c9a13a 100644 --- a/crates/hir-ty/src/consteval_nextsolver.rs +++ b/crates/hir-ty/src/consteval_nextsolver.rs @@ -49,7 +49,7 @@ pub(crate) fn path_to_const<'a, 'g>( .and_then(|(idx, p)| p.const_param().map(|p| (idx, p.clone()))) { Some((idx, _param)) => { - Some(Const::new_param(interner, ParamConst { index: idx as u32 })) + Some(Const::new_param(interner, ParamConst { index: idx as u32, id: p })) } None => { never!( diff --git a/crates/hir-ty/src/db.rs b/crates/hir-ty/src/db.rs index 97754f4723..0b7213d785 100644 --- a/crates/hir-ty/src/db.rs +++ b/crates/hir-ty/src/db.rs @@ -410,13 +410,15 @@ fn hir_database_is_dyn_compatible() { #[salsa_macros::interned(no_lifetime, debug, revisions = usize::MAX)] #[derive(PartialOrd, Ord)] pub struct InternedTypeOrConstParamId { - pub loc: TypeOrConstParamId, + /// This stores the param and its index. + pub loc: (TypeOrConstParamId, u32), } #[salsa_macros::interned(no_lifetime, debug, revisions = usize::MAX)] #[derive(PartialOrd, Ord)] pub struct InternedLifetimeParamId { - pub loc: LifetimeParamId, + /// This stores the param and its index. + pub loc: (LifetimeParamId, u32), } #[salsa_macros::interned(no_lifetime, debug, revisions = usize::MAX)] diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index 0df727a8e5..5b8093f6b7 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -61,9 +61,8 @@ use crate::{ next_solver::{ BoundExistentialPredicate, Ctor, DbInterner, GenericArgs, SolverDefId, mapping::{ - ChalkToNextSolver, bound_var_to_lifetime_idx, bound_var_to_type_or_const_param_idx, - convert_args_for_result, convert_const_for_result, convert_region_for_result, - convert_ty_for_result, + ChalkToNextSolver, convert_args_for_result, convert_const_for_result, + convert_region_for_result, convert_ty_for_result, }, }, primitive, to_assoc_type_id, @@ -641,7 +640,7 @@ impl HirDisplay for ProjectionTy { && !f.bounds_formatting_ctx.contains(self) { let db = f.db; - let id = from_placeholder_idx(db, *idx); + let id = from_placeholder_idx(db, *idx).0; let generics = generics(db, id.parent); let substs = generics.placeholder_subst(db); @@ -736,14 +735,14 @@ impl HirDisplay for Const { impl<'db> HirDisplay for crate::next_solver::Const<'db> { fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { match self.kind() { + rustc_type_ir::ConstKind::Placeholder(_) => write!(f, ""), rustc_type_ir::ConstKind::Bound(db, bound_const) => { write!(f, "?{}.{}", db.as_u32(), bound_const.as_u32()) } rustc_type_ir::ConstKind::Infer(..) => write!(f, "#c#"), - rustc_type_ir::ConstKind::Placeholder(idx) => { - let id = bound_var_to_type_or_const_param_idx(f.db, idx.bound); - let generics = generics(f.db, id.parent); - let param_data = &generics[id.local_id]; + rustc_type_ir::ConstKind::Param(param) => { + let generics = generics(f.db, param.id.parent()); + let param_data = &generics[param.id.local_id()]; write!(f, "{}", param_data.name().unwrap().display(f.db, f.edition()))?; Ok(()) } @@ -765,7 +764,6 @@ impl<'db> HirDisplay for crate::next_solver::Const<'db> { } rustc_type_ir::ConstKind::Error(..) => f.write_char('_'), rustc_type_ir::ConstKind::Expr(..) => write!(f, ""), - rustc_type_ir::ConstKind::Param(_) => write!(f, ""), } } } @@ -1178,7 +1176,7 @@ impl<'db> HirDisplay for crate::next_solver::Ty<'db> { if let TyKind::Ref(l, _, _) = kind { f.write_char('&')?; if f.render_region(l) { - convert_region_for_result(l).hir_fmt(f)?; + convert_region_for_result(interner, l).hir_fmt(f)?; f.write_char(' ')?; } match m { @@ -1611,14 +1609,10 @@ impl<'db> HirDisplay for crate::next_solver::Ty<'db> { write!(f, "{{closure}}")?; } } - TyKind::Placeholder(idx) => { - let placeholder_index = chalk_ir::PlaceholderIndex { - idx: idx.bound.var.as_usize(), - ui: chalk_ir::UniverseIndex { counter: idx.universe.as_usize() }, - }; - let id = from_placeholder_idx(db, placeholder_index); - let generics = generics(db, id.parent); - let param_data = &generics[id.local_id]; + TyKind::Placeholder(_) => write!(f, "{{placeholder}}")?, + TyKind::Param(param) => { + let generics = generics(db, param.id.parent()); + let param_data = &generics[param.id.local_id()]; match param_data { TypeOrConstParamData::TypeParamData(p) => match p.provenance { TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => { @@ -1634,7 +1628,7 @@ impl<'db> HirDisplay for crate::next_solver::Ty<'db> { TypeParamProvenance::ArgumentImplTrait => { let substs = generics.placeholder_subst(db); let bounds = db - .generic_predicates(id.parent) + .generic_predicates(param.id.parent()) .iter() .map(|pred| pred.clone().substitute(Interner, &substs)) .filter(|wc| match wc.skip_binders() { @@ -1656,7 +1650,7 @@ impl<'db> HirDisplay for crate::next_solver::Ty<'db> { WhereClause::LifetimeOutlives(_) => false, }) .collect::>(); - let krate = id.parent.module(db).krate(); + let krate = param.id.parent().module(db).krate(); write_bounds_like_dyn_trait_with_prefix( f, "impl", @@ -1671,7 +1665,6 @@ impl<'db> HirDisplay for crate::next_solver::Ty<'db> { } } } - TyKind::Param(_) => write!(f, "{{param}}")?, TyKind::Bound(debruijn_index, ty) => { let idx = chalk_ir::BoundVar { debruijn: chalk_ir::DebruijnIndex::new(debruijn_index.as_u32()), @@ -2294,7 +2287,7 @@ impl HirDisplay for LifetimeData { fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { match self { LifetimeData::Placeholder(idx) => { - let id = lt_from_placeholder_idx(f.db, *idx); + let id = lt_from_placeholder_idx(f.db, *idx).0; let generics = generics(f.db, id.parent); let param_data = &generics[id.local_id]; write!(f, "{}", param_data.name.display(f.db, f.edition()))?; @@ -2319,10 +2312,9 @@ impl HirDisplay for LifetimeData { impl<'db> HirDisplay for crate::next_solver::Region<'db> { fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { match self.kind() { - rustc_type_ir::RegionKind::RePlaceholder(idx) => { - let id = bound_var_to_lifetime_idx(f.db, idx.bound.var); - let generics = generics(f.db, id.parent); - let param_data = &generics[id.local_id]; + rustc_type_ir::RegionKind::ReEarlyParam(param) => { + let generics = generics(f.db, param.id.parent); + let param_data = &generics[param.id.local_id]; write!(f, "{}", param_data.name.display(f.db, f.edition()))?; Ok(()) } @@ -2339,7 +2331,7 @@ impl<'db> HirDisplay for crate::next_solver::Region<'db> { } } rustc_type_ir::RegionKind::ReErased => write!(f, "'"), - rustc_type_ir::RegionKind::ReEarlyParam(_) => write!(f, ""), + rustc_type_ir::RegionKind::RePlaceholder(_) => write!(f, ""), rustc_type_ir::RegionKind::ReLateParam(_) => write!(f, ""), } } diff --git a/crates/hir-ty/src/dyn_compatibility.rs b/crates/hir-ty/src/dyn_compatibility.rs index b0c61c29db..23280b1f3b 100644 --- a/crates/hir-ty/src/dyn_compatibility.rs +++ b/crates/hir-ty/src/dyn_compatibility.rs @@ -2,10 +2,12 @@ use std::ops::ControlFlow; +use hir_def::hir::generics::LocalTypeOrConstParamId; use hir_def::{ AssocItemId, ConstId, CrateRootModuleId, FunctionId, GenericDefId, HasModule, TraitId, TypeAliasId, lang_item::LangItem, signatures::TraitFlags, }; +use hir_def::{TypeOrConstParamId, TypeParamId}; use intern::Symbol; use rustc_hash::FxHashSet; use rustc_type_ir::{ @@ -384,7 +386,6 @@ where } // Allow `impl AutoTrait` predicates - let interner = DbInterner::new_with(db, Some(trait_.krate(db)), None); if let ClauseKind::Trait(TraitPredicate { trait_ref: pred_trait_ref, polarity: PredicatePolarity::Positive, @@ -392,11 +393,8 @@ where && let SolverDefId::TraitId(trait_id) = pred_trait_ref.def_id && let trait_data = db.trait_signature(trait_id) && trait_data.flags.contains(TraitFlags::AUTO) - && pred_trait_ref.self_ty() - == crate::next_solver::Ty::new( - interner, - rustc_type_ir::TyKind::Param(crate::next_solver::ParamTy { index: 0 }), - ) + && let rustc_type_ir::TyKind::Param(crate::next_solver::ParamTy { index: 0, .. }) = + pred_trait_ref.self_ty().kind() { continue; } @@ -422,9 +420,13 @@ fn receiver_is_dispatchable<'db>( let sig = sig.instantiate_identity(); let interner: DbInterner<'_> = DbInterner::new_with(db, Some(trait_.krate(db)), None); + let self_param_id = TypeParamId::from_unchecked(TypeOrConstParamId { + parent: trait_.into(), + local_id: LocalTypeOrConstParamId::from_raw(la_arena::RawIdx::from_u32(0)), + }); let self_param_ty = crate::next_solver::Ty::new( interner, - rustc_type_ir::TyKind::Param(crate::next_solver::ParamTy { index: 0 }), + rustc_type_ir::TyKind::Param(crate::next_solver::ParamTy { index: 0, id: self_param_id }), ); // `self: Self` can't be dispatched on, but this is already considered dyn-compatible @@ -452,7 +454,9 @@ fn receiver_is_dispatchable<'db>( }; // Type `U` - let unsized_self_ty = crate::next_solver::Ty::new_param(interner, u32::MAX, Symbol::empty()); + // FIXME: That seems problematic to fake a generic param like that? + let unsized_self_ty = + crate::next_solver::Ty::new_param(interner, self_param_id, u32::MAX, Symbol::empty()); // `Receiver[Self => U]` let unsized_receiver_ty = receiver_for_self_ty(interner, func, receiver_ty, unsized_self_ty); diff --git a/crates/hir-ty/src/generics.rs b/crates/hir-ty/src/generics.rs index 412b3ac425..e179e41b1c 100644 --- a/crates/hir-ty/src/generics.rs +++ b/crates/hir-ty/src/generics.rs @@ -256,15 +256,15 @@ impl Generics { pub fn placeholder_subst(&self, db: &dyn HirDatabase) -> Substitution { Substitution::from_iter( Interner, - self.iter_id().map(|id| match id { + self.iter_id().enumerate().map(|(index, id)| match id { GenericParamId::TypeParamId(id) => { - to_placeholder_idx(db, id.into()).to_ty(Interner).cast(Interner) + to_placeholder_idx(db, id.into(), index as u32).to_ty(Interner).cast(Interner) } - GenericParamId::ConstParamId(id) => to_placeholder_idx(db, id.into()) + GenericParamId::ConstParamId(id) => to_placeholder_idx(db, id.into(), index as u32) .to_const(Interner, db.const_param_ty(id)) .cast(Interner), GenericParamId::LifetimeParamId(id) => { - lt_to_placeholder_idx(db, id).to_lifetime(Interner).cast(Interner) + lt_to_placeholder_idx(db, id, index as u32).to_lifetime(Interner).cast(Interner) } }), ) diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs index 38ac2e1170..9ef046afdb 100644 --- a/crates/hir-ty/src/infer/closure.rs +++ b/crates/hir-ty/src/infer/closure.rs @@ -866,7 +866,7 @@ impl CapturedItemWithoutTy { idx: chalk_ir::PlaceholderIndex, outer_binder: DebruijnIndex, ) -> Result, Self::Error> { - let x = from_placeholder_idx(self.db, idx); + let x = from_placeholder_idx(self.db, idx).0; let Some(idx) = self.generics.type_or_const_param_idx(x) else { return Err(()); }; @@ -878,7 +878,7 @@ impl CapturedItemWithoutTy { idx: chalk_ir::PlaceholderIndex, outer_binder: DebruijnIndex, ) -> std::result::Result { - let x = from_placeholder_idx(self.db, idx); + let x = from_placeholder_idx(self.db, idx).0; let Some(idx) = self.generics.type_or_const_param_idx(x) else { return Err(()); }; diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs index e2ee8935a8..f8abb3b7f6 100644 --- a/crates/hir-ty/src/layout.rs +++ b/crates/hir-ty/src/layout.rs @@ -19,14 +19,15 @@ use rustc_type_ir::{ }; use triomphe::Arc; +use crate::utils::ClosureSubst; use crate::{ - TraitEnvironment, + Interner, TraitEnvironment, consteval_nextsolver::try_const_usize, db::HirDatabase, next_solver::{ DbInterner, GenericArgs, ParamEnv, SolverDefId, Ty, TyKind, TypingMode, infer::{DbInternerInferExt, traits::ObligationCause}, - mapping::{ChalkToNextSolver, convert_binder_to_early_binder}, + mapping::{ChalkToNextSolver, convert_args_for_result}, project::solve_normalize::deeply_normalize, }, }; @@ -333,9 +334,15 @@ pub fn layout_of_ty_query<'db>( let fields = captures .iter() .map(|it| { - let ty = - convert_binder_to_early_binder(interner, it.ty.to_nextsolver(interner)) - .instantiate(interner, args); + let ty = it + .ty + .clone() + .substitute( + Interner, + ClosureSubst(&convert_args_for_result(interner, args.inner())) + .parent_subst(), + ) + .to_nextsolver(interner); db.layout_of_ty(ty, trait_env.clone()) }) .collect::, _>>()?; diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index 7fdfb20572..c16bbb7b99 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -124,7 +124,7 @@ pub use lower_nextsolver::associated_type_shorthand_candidates; pub use mapping::{ ToChalk, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx, lt_from_placeholder_idx, lt_to_placeholder_idx, to_assoc_type_id, to_chalk_trait_id, - to_foreign_def_id, to_placeholder_idx, + to_foreign_def_id, to_placeholder_idx, to_placeholder_idx_no_index, }; pub use method_resolution::check_orphan_rules; pub use target_feature::TargetFeatures; @@ -1007,7 +1007,7 @@ struct PlaceholderCollector<'db> { impl PlaceholderCollector<'_> { fn collect(&mut self, idx: PlaceholderIndex) { - let id = from_placeholder_idx(self.db, idx); + let id = from_placeholder_idx(self.db, idx).0; self.placeholders.insert(id); } } diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 098c62ba97..79f78c545e 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -340,7 +340,13 @@ impl<'a> TyLoweringContext<'a> { res = Some(TypeNs::GenericParam(type_param_id)); match self.type_param_mode { ParamLoweringMode::Placeholder => { - TyKind::Placeholder(to_placeholder_idx(self.db, type_param_id.into())) + let generics = self.generics(); + let idx = generics.type_or_const_param_idx(type_param_id.into()).unwrap(); + TyKind::Placeholder(to_placeholder_idx( + self.db, + type_param_id.into(), + idx as u32, + )) } ParamLoweringMode::Variable => { let idx = @@ -777,7 +783,9 @@ impl<'a> TyLoweringContext<'a> { LifetimeNs::Static => static_lifetime(), LifetimeNs::LifetimeParam(id) => match self.type_param_mode { ParamLoweringMode::Placeholder => { - LifetimeData::Placeholder(lt_to_placeholder_idx(self.db, id)) + let generics = self.generics(); + let idx = generics.lifetime_idx(id).unwrap(); + LifetimeData::Placeholder(lt_to_placeholder_idx(self.db, id, idx as u32)) } ParamLoweringMode::Variable => { let idx = match self.generics().lifetime_idx(id) { diff --git a/crates/hir-ty/src/lower/path.rs b/crates/hir-ty/src/lower/path.rs index fb85909d7f..b0132e4dcb 100644 --- a/crates/hir-ty/src/lower/path.rs +++ b/crates/hir-ty/src/lower/path.rs @@ -222,7 +222,13 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { } TypeNs::GenericParam(param_id) => match self.ctx.type_param_mode { ParamLoweringMode::Placeholder => { - TyKind::Placeholder(to_placeholder_idx(self.ctx.db, param_id.into())) + let generics = self.ctx.generics(); + let idx = generics.type_or_const_param_idx(param_id.into()).unwrap(); + TyKind::Placeholder(to_placeholder_idx( + self.ctx.db, + param_id.into(), + idx as u32, + )) } ParamLoweringMode::Variable => { let idx = match self.ctx.generics().type_or_const_param_idx(param_id.into()) { diff --git a/crates/hir-ty/src/lower_nextsolver.rs b/crates/hir-ty/src/lower_nextsolver.rs index d87181f545..4578922ce3 100644 --- a/crates/hir-ty/src/lower_nextsolver.rs +++ b/crates/hir-ty/src/lower_nextsolver.rs @@ -64,8 +64,7 @@ use crate::{ AdtDef, AliasTy, Binder, BoundExistentialPredicates, BoundRegionKind, BoundTyKind, BoundVarKind, BoundVarKinds, Clause, Clauses, Const, DbInterner, EarlyBinder, EarlyParamRegion, ErrorGuaranteed, GenericArgs, PolyFnSig, Predicate, Region, SolverDefId, - TraitPredicate, TraitRef, Ty, Tys, abi::Safety, generics::GenericParamDefKind, - mapping::ChalkToNextSolver, + TraitPredicate, TraitRef, Ty, Tys, abi::Safety, mapping::ChalkToNextSolver, }, }; @@ -322,6 +321,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { }; Ty::new_param( self.interner, + type_param_id, idx as u32, type_data .name @@ -866,7 +866,10 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { None => return Region::error(self.interner), Some(idx) => idx, }; - Region::new_early_param(self.interner, EarlyParamRegion { index: idx as u32 }) + Region::new_early_param( + self.interner, + EarlyParamRegion { index: idx as u32, id }, + ) } }, None => Region::error(self.interner), @@ -1344,11 +1347,11 @@ where { continue; } - let GenericParamDefKind::Type = p.kind else { + let GenericParamId::TypeParamId(param_id) = p.id else { continue; }; let idx = idx as u32 + generics.parent_count as u32; - let param_ty = Ty::new_param(interner, idx, p.name.clone()); + let param_ty = Ty::new_param(interner, param_id, idx, p.name.clone()); if explicitly_unsized_tys.contains(¶m_ty) { continue; } diff --git a/crates/hir-ty/src/lower_nextsolver/path.rs b/crates/hir-ty/src/lower_nextsolver/path.rs index e3efb38306..ccdb5a0bdb 100644 --- a/crates/hir-ty/src/lower_nextsolver/path.rs +++ b/crates/hir-ty/src/lower_nextsolver/path.rs @@ -281,6 +281,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { }; Ty::new_param( self.ctx.interner, + param_id, idx as u32, p.name .as_ref() @@ -758,6 +759,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { self.ctx.ctx.db.generic_defaults(def).get(preceding_args.len()).map(|default| { convert_binder_to_early_binder( self.ctx.ctx.interner, + def, default.to_nextsolver(self.ctx.ctx.interner), ) .instantiate(self.ctx.ctx.interner, preceding_args) diff --git a/crates/hir-ty/src/mapping.rs b/crates/hir-ty/src/mapping.rs index 448fbdf673..5125a38825 100644 --- a/crates/hir-ty/src/mapping.rs +++ b/crates/hir-ty/src/mapping.rs @@ -104,7 +104,10 @@ pub fn from_assoc_type_id(id: AssocTypeId) -> TypeAliasId { FromId::from_id(id.0) } -pub fn from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> TypeOrConstParamId { +pub fn from_placeholder_idx( + db: &dyn HirDatabase, + idx: PlaceholderIndex, +) -> (TypeOrConstParamId, u32) { assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT); // SAFETY: We cannot really encapsulate this unfortunately, so just hope this is sound. let interned_id = @@ -112,15 +115,32 @@ pub fn from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> Type interned_id.loc(db) } -pub fn to_placeholder_idx(db: &dyn HirDatabase, id: TypeOrConstParamId) -> PlaceholderIndex { - let interned_id = InternedTypeOrConstParamId::new(db, id); +pub fn to_placeholder_idx( + db: &dyn HirDatabase, + id: TypeOrConstParamId, + idx: u32, +) -> PlaceholderIndex { + let interned_id = InternedTypeOrConstParamId::new(db, (id, idx)); PlaceholderIndex { ui: chalk_ir::UniverseIndex::ROOT, idx: interned_id.as_id().index() as usize, } } -pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> LifetimeParamId { +pub fn to_placeholder_idx_no_index( + db: &dyn HirDatabase, + id: TypeOrConstParamId, +) -> PlaceholderIndex { + let index = crate::generics::generics(db, id.parent) + .type_or_const_param_idx(id) + .expect("param not found"); + to_placeholder_idx(db, id, index as u32) +} + +pub fn lt_from_placeholder_idx( + db: &dyn HirDatabase, + idx: PlaceholderIndex, +) -> (LifetimeParamId, u32) { assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT); // SAFETY: We cannot really encapsulate this unfortunately, so just hope this is sound. let interned_id = @@ -128,8 +148,12 @@ pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> L interned_id.loc(db) } -pub fn lt_to_placeholder_idx(db: &dyn HirDatabase, id: LifetimeParamId) -> PlaceholderIndex { - let interned_id = InternedLifetimeParamId::new(db, id); +pub fn lt_to_placeholder_idx( + db: &dyn HirDatabase, + id: LifetimeParamId, + idx: u32, +) -> PlaceholderIndex { + let interned_id = InternedLifetimeParamId::new(db, (id, idx)); PlaceholderIndex { ui: chalk_ir::UniverseIndex::ROOT, idx: interned_id.as_id().index() as usize, diff --git a/crates/hir-ty/src/mir/monomorphization.rs b/crates/hir-ty/src/mir/monomorphization.rs index d8f443145c..b0b9223169 100644 --- a/crates/hir-ty/src/mir/monomorphization.rs +++ b/crates/hir-ty/src/mir/monomorphization.rs @@ -99,7 +99,7 @@ impl FallibleTypeFolder for Filler<'_> { idx: chalk_ir::PlaceholderIndex, _outer_binder: DebruijnIndex, ) -> std::result::Result, Self::Error> { - let it = from_placeholder_idx(self.db, idx); + let it = from_placeholder_idx(self.db, idx).0; let Some(idx) = self.generics.as_ref().and_then(|g| g.type_or_const_param_idx(it)) else { not_supported!("missing idx in generics"); }; @@ -117,7 +117,7 @@ impl FallibleTypeFolder for Filler<'_> { idx: chalk_ir::PlaceholderIndex, _outer_binder: DebruijnIndex, ) -> std::result::Result { - let it = from_placeholder_idx(self.db, idx); + let it = from_placeholder_idx(self.db, idx).0; let Some(idx) = self.generics.as_ref().and_then(|g| g.type_or_const_param_idx(it)) else { not_supported!("missing idx in generics"); }; diff --git a/crates/hir-ty/src/next_solver/consts.rs b/crates/hir-ty/src/next_solver/consts.rs index ce581cfad4..cfafc65d18 100644 --- a/crates/hir-ty/src/next_solver/consts.rs +++ b/crates/hir-ty/src/next_solver/consts.rs @@ -2,6 +2,7 @@ use std::hash::Hash; +use hir_def::{ConstParamId, TypeOrConstParamId}; use intern::{Interned, Symbol}; use rustc_ast_ir::try_visit; use rustc_ast_ir::visit::VisitorResult; @@ -84,6 +85,8 @@ pub type PlaceholderConst = Placeholder; #[derive(Copy, Clone, Hash, Eq, PartialEq)] pub struct ParamConst { + // FIXME: See `ParamTy`. + pub id: ConstParamId, pub index: u32, } diff --git a/crates/hir-ty/src/next_solver/generic_arg.rs b/crates/hir-ty/src/next_solver/generic_arg.rs index 76186e3746..d284eb9c6b 100644 --- a/crates/hir-ty/src/next_solver/generic_arg.rs +++ b/crates/hir-ty/src/next_solver/generic_arg.rs @@ -1,5 +1,6 @@ //! Things related to generic args in the next-trait-solver. +use hir_def::GenericParamId; use intern::{Interned, Symbol}; use rustc_type_ir::{ ClosureArgs, CollectAndApply, ConstVid, CoroutineArgs, CoroutineClosureArgs, FnSig, FnSigTys, @@ -14,7 +15,7 @@ use crate::db::HirDatabase; use super::{ Const, DbInterner, EarlyParamRegion, ErrorGuaranteed, ParamConst, Region, SolverDefId, Ty, Tys, - generics::{GenericParamDef, GenericParamDefKind, Generics}, + generics::{GenericParamDef, Generics}, interned_vec_db, }; @@ -203,7 +204,7 @@ impl<'db> GenericArgs<'db> { mut mk_kind: F, ) -> GenericArgs<'db> where - F: FnMut(&Symbol, u32, GenericParamDefKind, &[GenericArg<'db>]) -> GenericArg<'db>, + F: FnMut(&Symbol, u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>, { let defs = interner.generics_of(def_id); let count = defs.count(); @@ -218,7 +219,7 @@ impl<'db> GenericArgs<'db> { defs: Generics, mk_kind: &mut F, ) where - F: FnMut(&Symbol, u32, GenericParamDefKind, &[GenericArg<'db>]) -> GenericArg<'db>, + F: FnMut(&Symbol, u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>, { let self_len = defs.own_params.len() as u32; if let Some(def_id) = defs.parent { @@ -230,12 +231,12 @@ impl<'db> GenericArgs<'db> { fn fill_single(args: &mut SmallVec<[GenericArg<'db>; 8]>, defs: &Generics, mk_kind: &mut F) where - F: FnMut(&Symbol, u32, GenericParamDefKind, &[GenericArg<'db>]) -> GenericArg<'db>, + F: FnMut(&Symbol, u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>, { let start_len = args.len(); args.reserve(defs.own_params.len()); for param in &defs.own_params { - let kind = mk_kind(¶m.name, args.len() as u32, param.kind, args); + let kind = mk_kind(¶m.name, args.len() as u32, param.id, args); args.push(kind); } } @@ -412,26 +413,25 @@ pub fn mk_param<'db>( interner: DbInterner<'db>, index: u32, name: &Symbol, - kind: GenericParamDefKind, + id: GenericParamId, ) -> GenericArg<'db> { let name = name.clone(); - match kind { - GenericParamDefKind::Lifetime => { - Region::new_early_param(interner, EarlyParamRegion { index }).into() + match id { + GenericParamId::LifetimeParamId(id) => { + Region::new_early_param(interner, EarlyParamRegion { index, id }).into() + } + GenericParamId::TypeParamId(id) => Ty::new_param(interner, id, index, name).into(), + GenericParamId::ConstParamId(id) => { + Const::new_param(interner, ParamConst { index, id }).into() } - GenericParamDefKind::Type => Ty::new_param(interner, index, name).into(), - GenericParamDefKind::Const => Const::new_param(interner, ParamConst { index }).into(), } } -pub fn error_for_param_kind<'db>( - kind: GenericParamDefKind, - interner: DbInterner<'db>, -) -> GenericArg<'db> { - match kind { - GenericParamDefKind::Lifetime => Region::error(interner).into(), - GenericParamDefKind::Type => Ty::new_error(interner, ErrorGuaranteed).into(), - GenericParamDefKind::Const => Const::error(interner).into(), +pub fn error_for_param_kind<'db>(id: GenericParamId, interner: DbInterner<'db>) -> GenericArg<'db> { + match id { + GenericParamId::LifetimeParamId(_) => Region::error(interner).into(), + GenericParamId::TypeParamId(_) => Ty::new_error(interner, ErrorGuaranteed).into(), + GenericParamId::ConstParamId(_) => Const::error(interner).into(), } } diff --git a/crates/hir-ty/src/next_solver/generics.rs b/crates/hir-ty/src/next_solver/generics.rs index a3ba8eb834..5ec9a18a6c 100644 --- a/crates/hir-ty/src/next_solver/generics.rs +++ b/crates/hir-ty/src/next_solver/generics.rs @@ -24,35 +24,40 @@ use super::{Const, EarlyParamRegion, ErrorGuaranteed, ParamConst, Region, Solver use super::{DbInterner, GenericArg}; pub(crate) fn generics(db: &dyn HirDatabase, def: SolverDefId) -> Generics { - let mk_lt = |index, lt: &LifetimeParamData| { + let mk_lt = |parent, index, local_id, lt: &LifetimeParamData| { let name = lt.name.symbol().clone(); - let kind = GenericParamDefKind::Lifetime; - GenericParamDef { name, index, kind } + let id = GenericParamId::LifetimeParamId(LifetimeParamId { parent, local_id }); + GenericParamDef { name, index, id } }; - let mk_ty = |index, p: &TypeOrConstParamData| { + let mk_ty = |parent, index, local_id, p: &TypeOrConstParamData| { let name = p.name().map(|n| n.symbol().clone()).unwrap_or_else(|| sym::MISSING_NAME); - let kind = match p { - TypeOrConstParamData::TypeParamData(_) => GenericParamDefKind::Type, - TypeOrConstParamData::ConstParamData(_) => GenericParamDefKind::Const, + let id = TypeOrConstParamId { parent, local_id }; + let id = match p { + TypeOrConstParamData::TypeParamData(_) => { + GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)) + } + TypeOrConstParamData::ConstParamData(_) => { + GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)) + } }; - GenericParamDef { name, index, kind } + GenericParamDef { name, index, id } }; - let own_params_for_generic_params = |params: &GenericParams| { + let own_params_for_generic_params = |parent, params: &GenericParams| { let mut result = Vec::with_capacity(params.len()); let mut type_and_consts = params.iter_type_or_consts(); let mut index = 0; if let Some(self_param) = params.trait_self_param() { - result.push(mk_ty(0, ¶ms[self_param])); + result.push(mk_ty(parent, 0, self_param, ¶ms[self_param])); type_and_consts.next(); index += 1; } - result.extend(params.iter_lt().map(|(_, data)| { - let lt = mk_lt(index, data); + result.extend(params.iter_lt().map(|(local_id, data)| { + let lt = mk_lt(parent, index, local_id, data); index += 1; lt })); - result.extend(type_and_consts.map(|(_, data)| { - let ty = mk_ty(index, data); + result.extend(type_and_consts.map(|(local_id, data)| { + let ty = mk_ty(parent, index, local_id, data); index += 1; ty })); @@ -60,9 +65,10 @@ pub(crate) fn generics(db: &dyn HirDatabase, def: SolverDefId) -> Generics { }; let (parent, own_params) = match (def.try_into(), def) { - (Ok(def), _) => { - (parent_generic_def(db, def), own_params_for_generic_params(&db.generic_params(def))) - } + (Ok(def), _) => ( + parent_generic_def(db, def), + own_params_for_generic_params(def, &db.generic_params(def)), + ), (_, SolverDefId::InternedOpaqueTyId(id)) => { match db.lookup_intern_impl_trait_id(id) { crate::ImplTraitId::ReturnTypeImplTrait(function_id, _) => { @@ -79,7 +85,19 @@ pub(crate) fn generics(db: &dyn HirDatabase, def: SolverDefId) -> Generics { provenance: TypeParamProvenance::TypeParamList, }); // Yes, there is a parent but we don't include it in the generics - (None, vec![mk_ty(0, ¶m)]) + // FIXME: It seems utterly sensitive to fake a generic param here. + // Also, what a horrible mess! + ( + None, + vec![mk_ty( + GenericDefId::FunctionId(salsa::plumbing::FromId::from_id(unsafe { + salsa::Id::from_index(salsa::Id::MAX_U32 - 1) + })), + 0, + LocalTypeOrConstParamId::from_raw(la_arena::RawIdx::from_u32(0)), + ¶m, + )], + ) } } } @@ -106,7 +124,7 @@ pub struct GenericParamDef { pub(crate) name: Symbol, //def_id: GenericDefId, index: u32, - pub(crate) kind: GenericParamDefKind, + pub(crate) id: GenericParamId, } impl GenericParamDef { @@ -117,13 +135,6 @@ impl GenericParamDef { } } -#[derive(Copy, Clone, Debug)] -pub enum GenericParamDefKind { - Lifetime, - Type, - Const, -} - impl<'db> rustc_type_ir::inherent::GenericsOf> for Generics { fn count(&self) -> usize { self.parent_count + self.own_params.len() diff --git a/crates/hir-ty/src/next_solver/infer/mod.rs b/crates/hir-ty/src/next_solver/infer/mod.rs index 19ae76f7e3..58832aef89 100644 --- a/crates/hir-ty/src/next_solver/infer/mod.rs +++ b/crates/hir-ty/src/next_solver/infer/mod.rs @@ -8,6 +8,7 @@ pub use BoundRegionConversionTime::*; pub use at::DefineOpaqueTypes; use ena::undo_log::UndoLogs; use ena::unify as ut; +use hir_def::GenericParamId; use intern::Symbol; use opaque_types::{OpaqueHiddenType, OpaqueTypeStorage}; use region_constraints::{ @@ -38,7 +39,7 @@ use crate::next_solver::fold::BoundVarReplacerDelegate; use crate::next_solver::infer::opaque_types::table::OpaqueTypeStorageEntries; use crate::next_solver::{BoundRegion, BoundTy, BoundVarKind}; -use super::generics::{GenericParamDef, GenericParamDefKind}; +use super::generics::GenericParamDef; use super::{ AliasTerm, Binder, BoundRegionKind, CanonicalQueryInput, CanonicalVarValues, Const, ConstKind, DbInterner, ErrorGuaranteed, FxIndexMap, GenericArg, GenericArgs, OpaqueTypeKey, ParamEnv, @@ -600,14 +601,14 @@ impl<'db> InferCtxt<'db> { self.next_region_var_in_universe(universe) } - fn var_for_def(&self, kind: GenericParamDefKind, name: &Symbol) -> GenericArg<'db> { - match kind { - GenericParamDefKind::Lifetime => { + fn var_for_def(&self, id: GenericParamId, name: &Symbol) -> GenericArg<'db> { + match id { + GenericParamId::LifetimeParamId(_) => { // Create a region inference variable for the given // region parameter definition. self.next_region_var().into() } - GenericParamDefKind::Type => { + GenericParamId::TypeParamId(_) => { // Create a type inference variable for the given // type parameter definition. The generic parameters are // for actual parameters that may be referred to by @@ -624,7 +625,7 @@ impl<'db> InferCtxt<'db> { Ty::new_var(self.interner, ty_var_id).into() } - GenericParamDefKind::Const => { + GenericParamId::ConstParamId(_) => { let origin = ConstVariableOrigin { param_def_id: None }; let const_var_id = self .inner diff --git a/crates/hir-ty/src/next_solver/mapping.rs b/crates/hir-ty/src/next_solver/mapping.rs index 203f030dfd..6755d065e1 100644 --- a/crates/hir-ty/src/next_solver/mapping.rs +++ b/crates/hir-ty/src/next_solver/mapping.rs @@ -9,6 +9,7 @@ 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 _, @@ -35,6 +36,9 @@ use crate::{ }, 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, @@ -44,47 +48,24 @@ use super::{ Region, SolverDefId, SubtypePredicate, Term, TraitRef, Ty, Tys, ValueConst, VariancesOf, }; -pub fn to_placeholder_idx( - db: &dyn HirDatabase, - id: TypeOrConstParamId, - map: impl Fn(BoundVar) -> T, -) -> Placeholder { - let interned_id = InternedTypeOrConstParamId::new(db, id); - Placeholder { - universe: UniverseIndex::ZERO, - bound: map(BoundVar::from_usize(interned_id.as_id().index() as usize)), - } -} - -pub fn bound_var_to_type_or_const_param_idx( - db: &dyn HirDatabase, - var: rustc_type_ir::BoundVar, -) -> TypeOrConstParamId { - // SAFETY: We cannot really encapsulate this unfortunately, so just hope this is sound. - let interned_id = InternedTypeOrConstParamId::from_id(unsafe { Id::from_index(var.as_u32()) }); - interned_id.loc(db) -} - -pub fn bound_var_to_lifetime_idx( - db: &dyn HirDatabase, - var: rustc_type_ir::BoundVar, -) -> LifetimeParamId { - // SAFETY: We cannot really encapsulate this unfortunately, so just hope this is sound. - let interned_id = InternedLifetimeParamId::from_id(unsafe { Id::from_index(var.as_u32()) }); - interned_id.loc(db) -} - +// 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>>( interner: DbInterner<'db>, + def: GenericDefId, binder: rustc_type_ir::Binder, T>, ) -> rustc_type_ir::EarlyBinder, T> { - let mut folder = BinderToEarlyBinder { interner, debruijn: rustc_type_ir::DebruijnIndex::ZERO }; + 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, } impl<'db> rustc_type_ir::TypeFolder> for BinderToEarlyBinder<'db> { @@ -109,7 +90,13 @@ impl<'db> rustc_type_ir::TypeFolder> for BinderToEarlyBinder<'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(); - Ty::new(self.cx(), rustc_type_ir::TyKind::Param(ParamTy { index: var.as_u32() })) + 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), } @@ -119,10 +106,15 @@ impl<'db> rustc_type_ir::TypeFolder> for BinderToEarlyBinder<'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, }), ) } @@ -133,9 +125,12 @@ impl<'db> rustc_type_ir::TypeFolder> for BinderToEarlyBinder<'db 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.as_usize()] else { + unreachable!() + }; Const::new( self.cx(), - rustc_type_ir::ConstKind::Param(ParamConst { index: var.as_u32() }), + rustc_type_ir::ConstKind::Param(ParamConst { index: var.as_u32(), id }), ) } _ => c.super_fold_with(self), @@ -274,12 +269,6 @@ impl<'db> ChalkToNextSolver<'db, Ty<'db>> for chalk_ir::Ty { SolverDefId::TypeAliasId(crate::from_foreign_def_id(*foreign_def_id)), ), chalk_ir::TyKind::Error => rustc_type_ir::TyKind::Error(ErrorGuaranteed), - chalk_ir::TyKind::Placeholder(placeholder_index) => { - rustc_type_ir::TyKind::Placeholder(PlaceholderTy::new_anon( - placeholder_index.ui.to_nextsolver(interner), - rustc_type_ir::BoundVar::from_usize(placeholder_index.idx), - )) - } chalk_ir::TyKind::Dyn(dyn_ty) => { // exists { for<...> ^1.0: ... } let bounds = BoundExistentialPredicates::new_from_iter( @@ -405,6 +394,26 @@ impl<'db> ChalkToNextSolver<'db, Ty<'db>> for chalk_ir::Ty { 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 { @@ -440,10 +449,8 @@ impl<'db> ChalkToNextSolver<'db, Region<'db>> for chalk_ir::Lifetime { )) } chalk_ir::LifetimeData::Placeholder(placeholder_index) => { - rustc_type_ir::RegionKind::RePlaceholder(PlaceholderRegion::new_anon( - rustc_type_ir::UniverseIndex::from_u32(placeholder_index.ui.counter as u32), - rustc_type_ir::BoundVar::from_u32(placeholder_index.idx as u32), - )) + 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, @@ -474,10 +481,11 @@ impl<'db> ChalkToNextSolver<'db, Const<'db>> for chalk_ir::Const { )) } chalk_ir::ConstValue::Placeholder(placeholder_index) => { - rustc_type_ir::ConstKind::Placeholder(PlaceholderConst::new( - placeholder_index.ui.to_nextsolver(interner), - rustc_type_ir::BoundVar::from_usize(placeholder_index.idx), - )) + 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) => { @@ -971,7 +979,7 @@ pub fn convert_args_for_result<'db>( substs.push(chalk_ir::GenericArgData::Ty(ty).intern(Interner)); } rustc_type_ir::GenericArgKind::Lifetime(region) => { - let lifetime = convert_region_for_result(region); + let lifetime = convert_region_for_result(interner, region); substs.push(chalk_ir::GenericArgData::Lifetime(lifetime).intern(Interner)); } rustc_type_ir::GenericArgKind::Const(const_) => { @@ -1074,7 +1082,7 @@ pub(crate) fn convert_ty_for_result<'db>(interner: DbInterner<'db>, ty: Ty<'db>) rustc_ast_ir::Mutability::Mut => chalk_ir::Mutability::Mut, rustc_ast_ir::Mutability::Not => chalk_ir::Mutability::Not, }; - let r = convert_region_for_result(r); + let r = convert_region_for_result(interner, r); let ty = convert_ty_for_result(interner, ty); TyKind::Ref(mutability, r, ty) } @@ -1122,17 +1130,23 @@ pub(crate) fn convert_ty_for_result<'db>(interner: DbInterner<'db>, ty: Ty<'db>) rustc_type_ir::AliasTyKind::Free => unimplemented!(), }, + // For `Placeholder`, `Bound` and `Param`, see the comment on the reverse conversion. rustc_type_ir::TyKind::Placeholder(placeholder) => { - let ui = chalk_ir::UniverseIndex { counter: placeholder.universe.as_usize() }; - let placeholder_index = - chalk_ir::PlaceholderIndex { idx: placeholder.bound.var.as_usize(), ui }; - TyKind::Placeholder(placeholder_index) + 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(); @@ -1254,7 +1268,8 @@ pub(crate) fn convert_ty_for_result<'db>(interner: DbInterner<'db>, ty: Ty<'db>) 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(region) }; + let dyn_ty = + chalk_ir::DynTy { bounds, lifetime: convert_region_for_result(interner, region) }; TyKind::Dyn(dyn_ty) } @@ -1316,7 +1331,6 @@ pub(crate) fn convert_ty_for_result<'db>(interner: DbInterner<'db>, ty: Ty<'db>) TyKind::CoroutineWitness(id.into(), subst) } - rustc_type_ir::TyKind::Param(_) => unimplemented!(), rustc_type_ir::TyKind::UnsafeBinder(_) => unimplemented!(), } .intern(Interner) @@ -1327,13 +1341,16 @@ pub fn convert_const_for_result<'db>( const_: Const<'db>, ) -> crate::Const { let value: chalk_ir::ConstValue = match const_.kind() { - rustc_type_ir::ConstKind::Param(_) => unimplemented!(), 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()), @@ -1341,10 +1358,12 @@ pub fn convert_const_for_result<'db>( )) } rustc_type_ir::ConstKind::Placeholder(placeholder_const) => { - chalk_ir::ConstValue::Placeholder(chalk_ir::PlaceholderIndex { - ui: chalk_ir::UniverseIndex { counter: placeholder_const.universe.as_usize() }, - idx: placeholder_const.bound.as_usize(), - }) + 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 { @@ -1381,36 +1400,34 @@ pub fn convert_const_for_result<'db>( chalk_ir::ConstData { ty: crate::TyKind::Error.intern(Interner), value }.intern(Interner) } -pub fn convert_region_for_result<'db>(region: Region<'db>) -> crate::Lifetime { - match region.kind() { - rustc_type_ir::RegionKind::ReEarlyParam(early) => unimplemented!(), - rustc_type_ir::RegionKind::ReBound(db, bound) => chalk_ir::Lifetime::new( - 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::Lifetime::new(Interner, chalk_ir::LifetimeData::Static) + 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::ReVar(vid) => chalk_ir::Lifetime::new( - Interner, - chalk_ir::LifetimeData::InferenceVar(chalk_ir::InferenceVar::from(vid.as_u32())), - ), - rustc_type_ir::RegionKind::RePlaceholder(placeholder) => chalk_ir::Lifetime::new( - Interner, - chalk_ir::LifetimeData::Placeholder(chalk_ir::PlaceholderIndex { - idx: placeholder.bound.var.as_usize(), - ui: chalk_ir::UniverseIndex { counter: placeholder.universe.as_usize() }, - }), - ), - rustc_type_ir::RegionKind::ReErased => { - chalk_ir::Lifetime::new(Interner, chalk_ir::LifetimeData::Erased) - } - rustc_type_ir::RegionKind::ReError(_) => { - chalk_ir::Lifetime::new(Interner, chalk_ir::LifetimeData::Error) - } - } + rustc_type_ir::RegionKind::ReErased => chalk_ir::LifetimeData::Erased, + rustc_type_ir::RegionKind::ReError(_) => chalk_ir::LifetimeData::Error, + }; + chalk_ir::Lifetime::new(Interner, lifetime) } diff --git a/crates/hir-ty/src/next_solver/region.rs b/crates/hir-ty/src/next_solver/region.rs index c59cdac5f9..d6214d9915 100644 --- a/crates/hir-ty/src/next_solver/region.rs +++ b/crates/hir-ty/src/next_solver/region.rs @@ -1,5 +1,6 @@ //! Things related to regions. +use hir_def::LifetimeParamId; use intern::{Interned, Symbol}; use rustc_type_ir::{ BoundVar, Flags, INNERMOST, RegionVid, TypeFlags, TypeFoldable, TypeVisitable, VisitorResult, @@ -110,6 +111,8 @@ pub type PlaceholderRegion = Placeholder; #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct EarlyParamRegion { + // FIXME: See `ParamTy`. + pub id: LifetimeParamId, pub index: u32, } diff --git a/crates/hir-ty/src/next_solver/ty.rs b/crates/hir-ty/src/next_solver/ty.rs index 5ffae981a6..92f1076e75 100644 --- a/crates/hir-ty/src/next_solver/ty.rs +++ b/crates/hir-ty/src/next_solver/ty.rs @@ -1,5 +1,6 @@ //! Things related to tys in the next-trait-solver. +use hir_def::{GenericDefId, TypeOrConstParamId, TypeParamId}; use intern::{Interned, Symbol, sym}; use rustc_abi::{Float, Integer, Size}; use rustc_ast_ir::{Mutability, try_visit, visit::VisitorResult}; @@ -64,8 +65,8 @@ impl<'db> Ty<'db> { .unwrap() } - pub fn new_param(interner: DbInterner<'db>, index: u32, name: Symbol) -> Self { - Ty::new(interner, TyKind::Param(ParamTy { index })) + pub fn new_param(interner: DbInterner<'db>, id: TypeParamId, index: u32, name: Symbol) -> Self { + Ty::new(interner, TyKind::Param(ParamTy { id, index })) } pub fn new_placeholder(interner: DbInterner<'db>, placeholder: PlaceholderTy) -> Self { @@ -847,12 +848,16 @@ pub type PlaceholderTy = Placeholder; #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct ParamTy { + // FIXME: I'm not pleased with this. Ideally a `Param` should only know its index - the defining item + // is known from the `EarlyBinder`. This should also be beneficial for memory usage. But code currently + // assumes it can get the definition from `Param` alone - so that's what we got. + pub id: TypeParamId, pub index: u32, } impl ParamTy { pub fn to_ty<'db>(self, interner: DbInterner<'db>) -> Ty<'db> { - Ty::new_param(interner, self.index, sym::MISSING_NAME.clone()) + Ty::new_param(interner, self.id, self.index, sym::MISSING_NAME.clone()) } } @@ -865,6 +870,7 @@ impl std::fmt::Debug for ParamTy { #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct BoundTy { pub var: BoundVar, + // FIXME: This is for diagnostics in rustc, do we really need it? pub kind: BoundTyKind, } diff --git a/crates/hir-ty/src/variance.rs b/crates/hir-ty/src/variance.rs index d8a058533f..a1ebff04bb 100644 --- a/crates/hir-ty/src/variance.rs +++ b/crates/hir-ty/src/variance.rs @@ -344,7 +344,7 @@ impl Context<'_> { // Chalk has no params, so use placeholders for now? TyKind::Placeholder(index) => { - let idx = crate::from_placeholder_idx(self.db, *index); + let idx = crate::from_placeholder_idx(self.db, *index).0; let index = self.generics.type_or_const_param_idx(idx).unwrap(); self.constrain(index, variance); } @@ -445,7 +445,7 @@ impl Context<'_> { ); match region.data(Interner) { LifetimeData::Placeholder(index) => { - let idx = crate::lt_from_placeholder_idx(self.db, *index); + let idx = crate::lt_from_placeholder_idx(self.db, *index).0; let inferred = self.generics.lifetime_idx(idx).unwrap(); self.constrain(inferred, variance); } diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index b9c5131ffb..833a9ef030 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -474,8 +474,8 @@ impl HirDisplay for TypeParam { let param_data = ¶ms[self.id.local_id()]; let substs = TyBuilder::placeholder_subst(f.db, self.id.parent()); let krate = self.id.parent().krate(f.db).id; - let ty = - TyKind::Placeholder(hir_ty::to_placeholder_idx(f.db, self.id.into())).intern(Interner); + let ty = TyKind::Placeholder(hir_ty::to_placeholder_idx_no_index(f.db, self.id.into())) + .intern(Interner); let predicates = f.db.generic_predicates(self.id.parent()); let predicates = predicates .iter() @@ -528,8 +528,11 @@ impl HirDisplay for TypeParam { f, ":", Either::Left( - &hir_ty::TyKind::Placeholder(hir_ty::to_placeholder_idx(f.db, self.id.into())) - .intern(Interner), + &hir_ty::TyKind::Placeholder(hir_ty::to_placeholder_idx_no_index( + f.db, + self.id.into(), + )) + .intern(Interner), ), &predicates, default_sized, diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index f03f542e5b..46d3a2bcd6 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -4239,8 +4239,8 @@ impl TypeParam { pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> { let resolver = self.id.parent().resolver(db); - let ty = - TyKind::Placeholder(hir_ty::to_placeholder_idx(db, self.id.into())).intern(Interner); + let ty = TyKind::Placeholder(hir_ty::to_placeholder_idx_no_index(db, self.id.into())) + .intern(Interner); Type::new_with_resolver_inner(db, &resolver, ty) } @@ -5933,7 +5933,7 @@ impl<'db> Type<'db> { pub fn as_type_param(&self, db: &'db dyn HirDatabase) -> Option { match self.ty.kind(Interner) { TyKind::Placeholder(p) => Some(TypeParam { - id: TypeParamId::from_unchecked(hir_ty::from_placeholder_idx(db, *p)), + id: TypeParamId::from_unchecked(hir_ty::from_placeholder_idx(db, *p).0), }), _ => None, }