Make sense of the mess that were (are) different kind of generics in the solver

To the extent possible.

Previously they were confused. Sometimes generic params were treated as `Param` and sometimes as `Placeholder`. A completely redundant (in the new solver) mapping of salsa::Id to ints to intern some info where we could just store it uninterned (not in Chalk though, for some weird reason).

Plus fix a cute bug in closure substitution that was caught by the assertions of Chalk but the next solver did not have such assertions. Do we need more assertions?
This commit is contained in:
Chayim Refael Friedman 2025-09-02 06:39:32 +03:00
parent 21614ed2d3
commit 41611b19e5
26 changed files with 324 additions and 233 deletions

View file

@ -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 {

View file

@ -107,13 +107,13 @@ 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()) {
ParamLoweringMode::Variable => match args.type_or_const_param_idx(p.into()) {
Some(it) => ConstValue::BoundVar(BoundVar::new(debruijn, it)),
None => {
never!(
@ -124,8 +124,7 @@ pub(crate) fn path_to_const<'g>(
);
return None;
}
}
}
},
};
Some(ConstData { ty, value }.intern(Interner))
}

View file

@ -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!(

View file

@ -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)]

View file

@ -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, "<placeholder>"),
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, "<const-expr>"),
rustc_type_ir::ConstKind::Param(_) => write!(f, "<param>"),
}
}
}
@ -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::<Vec<_>>();
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, "'<erased>"),
rustc_type_ir::RegionKind::ReEarlyParam(_) => write!(f, "<param>"),
rustc_type_ir::RegionKind::RePlaceholder(_) => write!(f, "<placeholder>"),
rustc_type_ir::RegionKind::ReLateParam(_) => write!(f, "<late-param>"),
}
}

View file

@ -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);

View file

@ -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)
}
}),
)

View file

@ -866,7 +866,7 @@ impl CapturedItemWithoutTy {
idx: chalk_ir::PlaceholderIndex,
outer_binder: DebruijnIndex,
) -> Result<chalk_ir::Const<Interner>, 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<Ty, 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(());
};

View file

@ -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::<Result<Vec<_>, _>>()?;

View file

@ -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);
}
}

View file

@ -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) {

View file

@ -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()) {

View file

@ -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(&param_ty) {
continue;
}

View file

@ -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)

View file

@ -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,

View file

@ -99,7 +99,7 @@ impl FallibleTypeFolder<Interner> for Filler<'_> {
idx: chalk_ir::PlaceholderIndex,
_outer_binder: DebruijnIndex,
) -> std::result::Result<chalk_ir::Const<Interner>, 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<Interner> for Filler<'_> {
idx: chalk_ir::PlaceholderIndex,
_outer_binder: DebruijnIndex,
) -> std::result::Result<Ty, 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");
};

View file

@ -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<rustc_type_ir::BoundVar>;
#[derive(Copy, Clone, Hash, Eq, PartialEq)]
pub struct ParamConst {
// FIXME: See `ParamTy`.
pub id: ConstParamId,
pub index: u32,
}

View file

@ -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<F>(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(&param.name, args.len() as u32, param.kind, args);
let kind = mk_kind(&param.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(),
}
}

View file

@ -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, &params[self_param]));
result.push(mk_ty(parent, 0, self_param, &params[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, &param)])
// 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)),
&param,
)],
)
}
}
}
@ -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<DbInterner<'db>> for Generics {
fn count(&self) -> usize {
self.parent_count + self.own_params.len()

View file

@ -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

View file

@ -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<T: Clone + std::fmt::Debug>(
db: &dyn HirDatabase,
id: TypeOrConstParamId,
map: impl Fn(BoundVar) -> T,
) -> Placeholder<T> {
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<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 };
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> {
@ -109,7 +90,13 @@ impl<'db> rustc_type_ir::TypeFolder<DbInterner<'db>> 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<DbInterner<'db>> 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<DbInterner<'db>> 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<Interner> {
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<type> { for<...> ^1.0: ... }
let bounds = BoundExistentialPredicates::new_from_iter(
@ -405,6 +394,26 @@ impl<'db> ChalkToNextSolver<'db, Ty<'db>> for chalk_ir::Ty<Interner> {
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<Interner> {
))
}
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<Interner> {
))
}
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<Interner> = 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::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::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)
}

View file

@ -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<BoundRegion>;
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct EarlyParamRegion {
// FIXME: See `ParamTy`.
pub id: LifetimeParamId,
pub index: u32,
}

View file

@ -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<BoundTy>;
#[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,
}

View file

@ -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);
}

View file

@ -474,8 +474,8 @@ impl HirDisplay for TypeParam {
let param_data = &params[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,7 +528,10 @@ impl HirDisplay for TypeParam {
f,
":",
Either::Left(
&hir_ty::TyKind::Placeholder(hir_ty::to_placeholder_idx(f.db, self.id.into()))
&hir_ty::TyKind::Placeholder(hir_ty::to_placeholder_idx_no_index(
f.db,
self.id.into(),
))
.intern(Interner),
),
&predicates,

View file

@ -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<TypeParam> {
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,
}