mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-25 11:17:13 +00:00
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:
commit
a79e27b8d2
@ -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 {
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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!(
|
||||
|
@ -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)]
|
||||
|
@ -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>"),
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}),
|
||||
)
|
||||
|
@ -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(());
|
||||
};
|
||||
|
@ -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<_>, _>>()?;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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()) {
|
||||
|
@ -64,8 +64,7 @@ use crate::{
|
||||
AdtDef, AliasTy, Binder, BoundExistentialPredicates, BoundRegionKind, BoundTyKind,
|
||||
BoundVarKind, BoundVarKinds, Clause, Clauses, Const, DbInterner, EarlyBinder,
|
||||
EarlyParamRegion, ErrorGuaranteed, GenericArgs, PolyFnSig, Predicate, Region, SolverDefId,
|
||||
TraitPredicate, TraitRef, Ty, Tys, abi::Safety, generics::GenericParamDefKind,
|
||||
mapping::ChalkToNextSolver,
|
||||
TraitPredicate, TraitRef, Ty, Tys, abi::Safety, mapping::ChalkToNextSolver,
|
||||
},
|
||||
};
|
||||
|
||||
@ -322,6 +321,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
|
||||
};
|
||||
Ty::new_param(
|
||||
self.interner,
|
||||
type_param_id,
|
||||
idx as u32,
|
||||
type_data
|
||||
.name
|
||||
@ -866,7 +866,10 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
|
||||
None => return Region::error(self.interner),
|
||||
Some(idx) => idx,
|
||||
};
|
||||
Region::new_early_param(self.interner, EarlyParamRegion { index: idx as u32 })
|
||||
Region::new_early_param(
|
||||
self.interner,
|
||||
EarlyParamRegion { index: idx as u32, id },
|
||||
)
|
||||
}
|
||||
},
|
||||
None => Region::error(self.interner),
|
||||
@ -1344,11 +1347,11 @@ where
|
||||
{
|
||||
continue;
|
||||
}
|
||||
let GenericParamDefKind::Type = p.kind else {
|
||||
let GenericParamId::TypeParamId(param_id) = p.id else {
|
||||
continue;
|
||||
};
|
||||
let idx = idx as u32 + generics.parent_count as u32;
|
||||
let param_ty = Ty::new_param(interner, idx, p.name.clone());
|
||||
let param_ty = Ty::new_param(interner, param_id, idx, p.name.clone());
|
||||
if explicitly_unsized_tys.contains(¶m_ty) {
|
||||
continue;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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");
|
||||
};
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
@ -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(¶m.name, args.len() as u32, param.kind, args);
|
||||
let kind = mk_kind(¶m.name, args.len() as u32, param.id, args);
|
||||
args.push(kind);
|
||||
}
|
||||
}
|
||||
@ -412,26 +413,25 @@ pub fn mk_param<'db>(
|
||||
interner: DbInterner<'db>,
|
||||
index: u32,
|
||||
name: &Symbol,
|
||||
kind: GenericParamDefKind,
|
||||
id: GenericParamId,
|
||||
) -> GenericArg<'db> {
|
||||
let name = name.clone();
|
||||
match kind {
|
||||
GenericParamDefKind::Lifetime => {
|
||||
Region::new_early_param(interner, EarlyParamRegion { index }).into()
|
||||
match id {
|
||||
GenericParamId::LifetimeParamId(id) => {
|
||||
Region::new_early_param(interner, EarlyParamRegion { index, id }).into()
|
||||
}
|
||||
GenericParamId::TypeParamId(id) => Ty::new_param(interner, id, index, name).into(),
|
||||
GenericParamId::ConstParamId(id) => {
|
||||
Const::new_param(interner, ParamConst { index, id }).into()
|
||||
}
|
||||
GenericParamDefKind::Type => Ty::new_param(interner, index, name).into(),
|
||||
GenericParamDefKind::Const => Const::new_param(interner, ParamConst { index }).into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn error_for_param_kind<'db>(
|
||||
kind: GenericParamDefKind,
|
||||
interner: DbInterner<'db>,
|
||||
) -> GenericArg<'db> {
|
||||
match kind {
|
||||
GenericParamDefKind::Lifetime => Region::error(interner).into(),
|
||||
GenericParamDefKind::Type => Ty::new_error(interner, ErrorGuaranteed).into(),
|
||||
GenericParamDefKind::Const => Const::error(interner).into(),
|
||||
pub fn error_for_param_kind<'db>(id: GenericParamId, interner: DbInterner<'db>) -> GenericArg<'db> {
|
||||
match id {
|
||||
GenericParamId::LifetimeParamId(_) => Region::error(interner).into(),
|
||||
GenericParamId::TypeParamId(_) => Ty::new_error(interner, ErrorGuaranteed).into(),
|
||||
GenericParamId::ConstParamId(_) => Const::error(interner).into(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,35 +24,40 @@ use super::{Const, EarlyParamRegion, ErrorGuaranteed, ParamConst, Region, Solver
|
||||
use super::{DbInterner, GenericArg};
|
||||
|
||||
pub(crate) fn generics(db: &dyn HirDatabase, def: SolverDefId) -> Generics {
|
||||
let mk_lt = |index, lt: &LifetimeParamData| {
|
||||
let mk_lt = |parent, index, local_id, lt: &LifetimeParamData| {
|
||||
let name = lt.name.symbol().clone();
|
||||
let kind = GenericParamDefKind::Lifetime;
|
||||
GenericParamDef { name, index, kind }
|
||||
let id = GenericParamId::LifetimeParamId(LifetimeParamId { parent, local_id });
|
||||
GenericParamDef { name, index, id }
|
||||
};
|
||||
let mk_ty = |index, p: &TypeOrConstParamData| {
|
||||
let mk_ty = |parent, index, local_id, p: &TypeOrConstParamData| {
|
||||
let name = p.name().map(|n| n.symbol().clone()).unwrap_or_else(|| sym::MISSING_NAME);
|
||||
let kind = match p {
|
||||
TypeOrConstParamData::TypeParamData(_) => GenericParamDefKind::Type,
|
||||
TypeOrConstParamData::ConstParamData(_) => GenericParamDefKind::Const,
|
||||
let id = TypeOrConstParamId { parent, local_id };
|
||||
let id = match p {
|
||||
TypeOrConstParamData::TypeParamData(_) => {
|
||||
GenericParamId::TypeParamId(TypeParamId::from_unchecked(id))
|
||||
}
|
||||
TypeOrConstParamData::ConstParamData(_) => {
|
||||
GenericParamId::ConstParamId(ConstParamId::from_unchecked(id))
|
||||
}
|
||||
};
|
||||
GenericParamDef { name, index, kind }
|
||||
GenericParamDef { name, index, id }
|
||||
};
|
||||
let own_params_for_generic_params = |params: &GenericParams| {
|
||||
let own_params_for_generic_params = |parent, params: &GenericParams| {
|
||||
let mut result = Vec::with_capacity(params.len());
|
||||
let mut type_and_consts = params.iter_type_or_consts();
|
||||
let mut index = 0;
|
||||
if let Some(self_param) = params.trait_self_param() {
|
||||
result.push(mk_ty(0, ¶ms[self_param]));
|
||||
result.push(mk_ty(parent, 0, self_param, ¶ms[self_param]));
|
||||
type_and_consts.next();
|
||||
index += 1;
|
||||
}
|
||||
result.extend(params.iter_lt().map(|(_, data)| {
|
||||
let lt = mk_lt(index, data);
|
||||
result.extend(params.iter_lt().map(|(local_id, data)| {
|
||||
let lt = mk_lt(parent, index, local_id, data);
|
||||
index += 1;
|
||||
lt
|
||||
}));
|
||||
result.extend(type_and_consts.map(|(_, data)| {
|
||||
let ty = mk_ty(index, data);
|
||||
result.extend(type_and_consts.map(|(local_id, data)| {
|
||||
let ty = mk_ty(parent, index, local_id, data);
|
||||
index += 1;
|
||||
ty
|
||||
}));
|
||||
@ -60,9 +65,10 @@ pub(crate) fn generics(db: &dyn HirDatabase, def: SolverDefId) -> Generics {
|
||||
};
|
||||
|
||||
let (parent, own_params) = match (def.try_into(), def) {
|
||||
(Ok(def), _) => {
|
||||
(parent_generic_def(db, def), own_params_for_generic_params(&db.generic_params(def)))
|
||||
}
|
||||
(Ok(def), _) => (
|
||||
parent_generic_def(db, def),
|
||||
own_params_for_generic_params(def, &db.generic_params(def)),
|
||||
),
|
||||
(_, SolverDefId::InternedOpaqueTyId(id)) => {
|
||||
match db.lookup_intern_impl_trait_id(id) {
|
||||
crate::ImplTraitId::ReturnTypeImplTrait(function_id, _) => {
|
||||
@ -79,7 +85,19 @@ pub(crate) fn generics(db: &dyn HirDatabase, def: SolverDefId) -> Generics {
|
||||
provenance: TypeParamProvenance::TypeParamList,
|
||||
});
|
||||
// Yes, there is a parent but we don't include it in the generics
|
||||
(None, vec![mk_ty(0, ¶m)])
|
||||
// FIXME: It seems utterly sensitive to fake a generic param here.
|
||||
// Also, what a horrible mess!
|
||||
(
|
||||
None,
|
||||
vec![mk_ty(
|
||||
GenericDefId::FunctionId(salsa::plumbing::FromId::from_id(unsafe {
|
||||
salsa::Id::from_index(salsa::Id::MAX_U32 - 1)
|
||||
})),
|
||||
0,
|
||||
LocalTypeOrConstParamId::from_raw(la_arena::RawIdx::from_u32(0)),
|
||||
¶m,
|
||||
)],
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -106,7 +124,7 @@ pub struct GenericParamDef {
|
||||
pub(crate) name: Symbol,
|
||||
//def_id: GenericDefId,
|
||||
index: u32,
|
||||
pub(crate) kind: GenericParamDefKind,
|
||||
pub(crate) id: GenericParamId,
|
||||
}
|
||||
|
||||
impl GenericParamDef {
|
||||
@ -117,13 +135,6 @@ impl GenericParamDef {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum GenericParamDefKind {
|
||||
Lifetime,
|
||||
Type,
|
||||
Const,
|
||||
}
|
||||
|
||||
impl<'db> rustc_type_ir::inherent::GenericsOf<DbInterner<'db>> for Generics {
|
||||
fn count(&self) -> usize {
|
||||
self.parent_count + self.own_params.len()
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -474,8 +474,8 @@ impl HirDisplay for TypeParam {
|
||||
let param_data = ¶ms[self.id.local_id()];
|
||||
let substs = TyBuilder::placeholder_subst(f.db, self.id.parent());
|
||||
let krate = self.id.parent().krate(f.db).id;
|
||||
let ty =
|
||||
TyKind::Placeholder(hir_ty::to_placeholder_idx(f.db, self.id.into())).intern(Interner);
|
||||
let ty = TyKind::Placeholder(hir_ty::to_placeholder_idx_no_index(f.db, self.id.into()))
|
||||
.intern(Interner);
|
||||
let predicates = f.db.generic_predicates(self.id.parent());
|
||||
let predicates = predicates
|
||||
.iter()
|
||||
@ -528,8 +528,11 @@ impl HirDisplay for TypeParam {
|
||||
f,
|
||||
":",
|
||||
Either::Left(
|
||||
&hir_ty::TyKind::Placeholder(hir_ty::to_placeholder_idx(f.db, self.id.into()))
|
||||
.intern(Interner),
|
||||
&hir_ty::TyKind::Placeholder(hir_ty::to_placeholder_idx_no_index(
|
||||
f.db,
|
||||
self.id.into(),
|
||||
))
|
||||
.intern(Interner),
|
||||
),
|
||||
&predicates,
|
||||
default_sized,
|
||||
|
@ -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,
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user