Merge pull request #20586 from ChayimFriedman2/placeholder-ns

fix: Make sense of the mess that were (are) different kind of generics in the solver
This commit is contained in:
Shoyu Vanilla (Flint) 2025-09-03 06:00:29 +00:00 committed by GitHub
commit a79e27b8d2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
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,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))
}

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::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)
}

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

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