mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-28 05:53:45 +00:00
Extract generics module
This commit is contained in:
parent
67f7eb505e
commit
585cc9e014
15 changed files with 333 additions and 323 deletions
|
@ -14,10 +14,10 @@ use hir_def::{
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
consteval::unknown_const_as_generic, db::HirDatabase, error_lifetime,
|
consteval::unknown_const_as_generic, db::HirDatabase, error_lifetime, generics::generics,
|
||||||
infer::unify::InferenceTable, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics,
|
infer::unify::InferenceTable, primitive, to_assoc_type_id, to_chalk_trait_id, Binders,
|
||||||
Binders, BoundVar, CallableSig, GenericArg, GenericArgData, Interner, ProjectionTy,
|
BoundVar, CallableSig, GenericArg, GenericArgData, Interner, ProjectionTy, Substitution,
|
||||||
Substitution, TraitRef, Ty, TyDefId, TyExt, TyKind,
|
TraitRef, Ty, TyDefId, TyExt, TyKind,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
|
|
@ -20,13 +20,14 @@ use hir_expand::name::name;
|
||||||
use crate::{
|
use crate::{
|
||||||
db::{HirDatabase, InternedCoroutine},
|
db::{HirDatabase, InternedCoroutine},
|
||||||
display::HirDisplay,
|
display::HirDisplay,
|
||||||
from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, make_binders,
|
from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id,
|
||||||
make_single_type_binders,
|
generics::generics,
|
||||||
|
make_binders, make_single_type_binders,
|
||||||
mapping::{from_chalk, ToChalk, TypeAliasAsValue},
|
mapping::{from_chalk, ToChalk, TypeAliasAsValue},
|
||||||
method_resolution::{TraitImpls, TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
|
method_resolution::{TraitImpls, TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
|
||||||
to_assoc_type_id, to_chalk_trait_id,
|
to_assoc_type_id, to_chalk_trait_id,
|
||||||
traits::ChalkContext,
|
traits::ChalkContext,
|
||||||
utils::{generics, ClosureSubst},
|
utils::ClosureSubst,
|
||||||
wrap_empty_binders, AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId,
|
wrap_empty_binders, AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId,
|
||||||
Interner, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, Substitution, TraitRef,
|
Interner, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, Substitution, TraitRef,
|
||||||
TraitRefExt, Ty, TyBuilder, TyExt, TyKind, WhereClause,
|
TraitRefExt, Ty, TyBuilder, TyExt, TyKind, WhereClause,
|
||||||
|
|
|
@ -12,12 +12,10 @@ use hir_def::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db::HirDatabase,
|
db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id,
|
||||||
from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx,
|
from_placeholder_idx, generics::generics, to_chalk_trait_id, utils::ClosureSubst, AdtId,
|
||||||
to_chalk_trait_id,
|
AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, ClosureId,
|
||||||
utils::{generics, ClosureSubst},
|
DynTy, FnPointer, ImplTraitId, InEnvironment, Interner, Lifetime, ProjectionTy,
|
||||||
AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Canonical, CanonicalVarKinds,
|
|
||||||
ClosureId, DynTy, FnPointer, ImplTraitId, InEnvironment, Interner, Lifetime, ProjectionTy,
|
|
||||||
QuantifiedWhereClause, Substitution, TraitRef, Ty, TyBuilder, TyKind, TypeFlags, WhereClause,
|
QuantifiedWhereClause, Substitution, TraitRef, Ty, TyBuilder, TyKind, TypeFlags, WhereClause,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,9 @@ use stdx::never;
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db::HirDatabase, infer::InferenceContext, lower::ParamLoweringMode,
|
db::HirDatabase, generics::Generics, infer::InferenceContext, lower::ParamLoweringMode,
|
||||||
mir::monomorphize_mir_body_bad, to_placeholder_idx, utils::Generics, Const, ConstData,
|
mir::monomorphize_mir_body_bad, to_placeholder_idx, Const, ConstData, ConstScalar, ConstValue,
|
||||||
ConstScalar, ConstValue, GenericArg, Interner, MemoryMap, Substitution, TraitEnvironment, Ty,
|
GenericArg, Interner, MemoryMap, Substitution, TraitEnvironment, Ty, TyBuilder,
|
||||||
TyBuilder,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::mir::{interpret_mir, lower_to_mir, pad16, MirEvalError, MirLowerError};
|
use super::mir::{interpret_mir, lower_to_mir, pad16, MirEvalError, MirLowerError};
|
||||||
|
|
|
@ -36,12 +36,13 @@ use crate::{
|
||||||
consteval::try_const_usize,
|
consteval::try_const_usize,
|
||||||
db::{HirDatabase, InternedClosure},
|
db::{HirDatabase, InternedClosure},
|
||||||
from_assoc_type_id, from_foreign_def_id, from_placeholder_idx,
|
from_assoc_type_id, from_foreign_def_id, from_placeholder_idx,
|
||||||
|
generics::generics,
|
||||||
layout::Layout,
|
layout::Layout,
|
||||||
lt_from_placeholder_idx,
|
lt_from_placeholder_idx,
|
||||||
mapping::from_chalk,
|
mapping::from_chalk,
|
||||||
mir::pad16,
|
mir::pad16,
|
||||||
primitive, to_assoc_type_id,
|
primitive, to_assoc_type_id,
|
||||||
utils::{self, detect_variant_from_bytes, generics, ClosureSubst},
|
utils::{self, detect_variant_from_bytes, ClosureSubst},
|
||||||
AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, ConcreteConst, Const,
|
AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, ConcreteConst, Const,
|
||||||
ConstScalar, ConstValue, DomainGoal, FnAbi, GenericArg, ImplTraitId, Interner, Lifetime,
|
ConstScalar, ConstValue, DomainGoal, FnAbi, GenericArg, ImplTraitId, Interner, Lifetime,
|
||||||
LifetimeData, LifetimeOutlives, MemoryMap, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt,
|
LifetimeData, LifetimeOutlives, MemoryMap, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt,
|
||||||
|
|
286
crates/hir-ty/src/generics.rs
Normal file
286
crates/hir-ty/src/generics.rs
Normal file
|
@ -0,0 +1,286 @@
|
||||||
|
use chalk_ir::{cast::Cast as _, BoundVar, DebruijnIndex};
|
||||||
|
use hir_def::{
|
||||||
|
db::DefDatabase,
|
||||||
|
generics::{
|
||||||
|
GenericParamDataRef, GenericParams, LifetimeParamData, TypeOrConstParamData,
|
||||||
|
TypeParamProvenance,
|
||||||
|
},
|
||||||
|
ConstParamId, GenericDefId, GenericParamId, ItemContainerId, LifetimeParamId, Lookup,
|
||||||
|
TypeOrConstParamId, TypeParamId,
|
||||||
|
};
|
||||||
|
use intern::Interned;
|
||||||
|
|
||||||
|
use crate::{db::HirDatabase, Interner, Substitution};
|
||||||
|
|
||||||
|
pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics {
|
||||||
|
let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def)));
|
||||||
|
Generics { def, params: db.generic_params(def), parent_generics }
|
||||||
|
}
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub(crate) struct Generics {
|
||||||
|
def: GenericDefId,
|
||||||
|
pub(crate) params: Interned<GenericParams>,
|
||||||
|
parent_generics: Option<Box<Generics>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Generics {
|
||||||
|
pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
|
||||||
|
self.iter().map(|(id, _)| id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn def(&self) -> GenericDefId {
|
||||||
|
self.def
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Iterator over types and const params of self, then parent.
|
||||||
|
pub(crate) fn iter<'a>(
|
||||||
|
&'a self,
|
||||||
|
) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'a>)> + 'a {
|
||||||
|
let from_toc_id = |it: &'a Generics| {
|
||||||
|
move |(local_id, p): (_, &'a TypeOrConstParamData)| {
|
||||||
|
let id = TypeOrConstParamId { parent: it.def, local_id };
|
||||||
|
match p {
|
||||||
|
TypeOrConstParamData::TypeParamData(p) => (
|
||||||
|
GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
|
||||||
|
GenericParamDataRef::TypeParamData(p),
|
||||||
|
),
|
||||||
|
TypeOrConstParamData::ConstParamData(p) => (
|
||||||
|
GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
|
||||||
|
GenericParamDataRef::ConstParamData(p),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let from_lt_id = |it: &'a Generics| {
|
||||||
|
move |(local_id, p): (_, &'a LifetimeParamData)| {
|
||||||
|
(
|
||||||
|
GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
|
||||||
|
GenericParamDataRef::LifetimeParamData(p),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let lt_iter = self.params.iter_lt().map(from_lt_id(self));
|
||||||
|
self.params
|
||||||
|
.iter_type_or_consts()
|
||||||
|
.map(from_toc_id(self))
|
||||||
|
.chain(lt_iter)
|
||||||
|
.chain(self.iter_parent())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Iterate over types and const params without parent params.
|
||||||
|
pub(crate) fn iter_self<'a>(
|
||||||
|
&'a self,
|
||||||
|
) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'a>)> + 'a {
|
||||||
|
let from_toc_id = |it: &'a Generics| {
|
||||||
|
move |(local_id, p): (_, &'a TypeOrConstParamData)| {
|
||||||
|
let id = TypeOrConstParamId { parent: it.def, local_id };
|
||||||
|
match p {
|
||||||
|
TypeOrConstParamData::TypeParamData(p) => (
|
||||||
|
GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
|
||||||
|
GenericParamDataRef::TypeParamData(p),
|
||||||
|
),
|
||||||
|
TypeOrConstParamData::ConstParamData(p) => (
|
||||||
|
GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
|
||||||
|
GenericParamDataRef::ConstParamData(p),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let from_lt_id = |it: &'a Generics| {
|
||||||
|
move |(local_id, p): (_, &'a LifetimeParamData)| {
|
||||||
|
(
|
||||||
|
GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
|
||||||
|
GenericParamDataRef::LifetimeParamData(p),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.params
|
||||||
|
.iter_type_or_consts()
|
||||||
|
.map(from_toc_id(self))
|
||||||
|
.chain(self.params.iter_lt().map(from_lt_id(self)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Iterator over types and const params of parent.
|
||||||
|
pub(crate) fn iter_parent(
|
||||||
|
&self,
|
||||||
|
) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'_>)> + '_ {
|
||||||
|
self.parent_generics().into_iter().flat_map(|it| {
|
||||||
|
let from_toc_id = move |(local_id, p)| {
|
||||||
|
let p: &_ = p;
|
||||||
|
let id = TypeOrConstParamId { parent: it.def, local_id };
|
||||||
|
match p {
|
||||||
|
TypeOrConstParamData::TypeParamData(p) => (
|
||||||
|
GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
|
||||||
|
GenericParamDataRef::TypeParamData(p),
|
||||||
|
),
|
||||||
|
TypeOrConstParamData::ConstParamData(p) => (
|
||||||
|
GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
|
||||||
|
GenericParamDataRef::ConstParamData(p),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let from_lt_id = move |(local_id, p): (_, _)| {
|
||||||
|
(
|
||||||
|
GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
|
||||||
|
GenericParamDataRef::LifetimeParamData(p),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let lt_iter = it.params.iter_lt().map(from_lt_id);
|
||||||
|
it.params.iter_type_or_consts().map(from_toc_id).chain(lt_iter)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns total number of generic parameters in scope, including those from parent.
|
||||||
|
pub(crate) fn len(&self) -> usize {
|
||||||
|
let parent = self.parent_generics().map_or(0, Generics::len);
|
||||||
|
let child = self.params.len();
|
||||||
|
parent + child
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns numbers of generic parameters excluding those from parent.
|
||||||
|
pub(crate) fn len_self(&self) -> usize {
|
||||||
|
self.params.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns number of generic parameter excluding those from parent
|
||||||
|
fn len_type_and_const_params(&self) -> usize {
|
||||||
|
self.params.type_or_consts.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// (parent total, self param, type params, const params, impl trait list, lifetimes)
|
||||||
|
pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize, usize, usize) {
|
||||||
|
let mut self_params = 0;
|
||||||
|
let mut type_params = 0;
|
||||||
|
let mut impl_trait_params = 0;
|
||||||
|
let mut const_params = 0;
|
||||||
|
let mut lifetime_params = 0;
|
||||||
|
self.params.iter_type_or_consts().for_each(|(_, data)| match data {
|
||||||
|
TypeOrConstParamData::TypeParamData(p) => match p.provenance {
|
||||||
|
TypeParamProvenance::TypeParamList => type_params += 1,
|
||||||
|
TypeParamProvenance::TraitSelf => self_params += 1,
|
||||||
|
TypeParamProvenance::ArgumentImplTrait => impl_trait_params += 1,
|
||||||
|
},
|
||||||
|
TypeOrConstParamData::ConstParamData(_) => const_params += 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
self.params.iter_lt().for_each(|(_, _)| lifetime_params += 1);
|
||||||
|
|
||||||
|
let parent_len = self.parent_generics().map_or(0, Generics::len);
|
||||||
|
(parent_len, self_params, type_params, const_params, impl_trait_params, lifetime_params)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn type_or_const_param_idx(&self, param: TypeOrConstParamId) -> Option<usize> {
|
||||||
|
Some(self.find_type_or_const_param(param)?.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_type_or_const_param(
|
||||||
|
&self,
|
||||||
|
param: TypeOrConstParamId,
|
||||||
|
) -> Option<(usize, &TypeOrConstParamData)> {
|
||||||
|
if param.parent == self.def {
|
||||||
|
let idx = param.local_id.into_raw().into_u32() as usize;
|
||||||
|
if idx >= self.params.type_or_consts.len() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some((idx, &self.params.type_or_consts[param.local_id]))
|
||||||
|
} else {
|
||||||
|
self.parent_generics()
|
||||||
|
.and_then(|g| g.find_type_or_const_param(param))
|
||||||
|
// Remember that parent parameters come after parameters for self.
|
||||||
|
.map(|(idx, data)| (self.len_self() + idx, data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn lifetime_idx(&self, lifetime: LifetimeParamId) -> Option<usize> {
|
||||||
|
Some(self.find_lifetime(lifetime)?.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_lifetime(&self, lifetime: LifetimeParamId) -> Option<(usize, &LifetimeParamData)> {
|
||||||
|
if lifetime.parent == self.def {
|
||||||
|
let idx = lifetime.local_id.into_raw().into_u32() as usize;
|
||||||
|
if idx >= self.params.lifetimes.len() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some((
|
||||||
|
self.len_type_and_const_params() + idx,
|
||||||
|
&self.params.lifetimes[lifetime.local_id],
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
self.parent_generics()
|
||||||
|
.and_then(|g| g.find_lifetime(lifetime))
|
||||||
|
.map(|(idx, data)| (self.len_self() + idx, data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn parent_generics(&self) -> Option<&Generics> {
|
||||||
|
self.parent_generics.as_deref()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn parent_or_self(&self) -> &Generics {
|
||||||
|
self.parent_generics.as_deref().unwrap_or(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a Substitution that replaces each parameter by a bound variable.
|
||||||
|
pub(crate) fn bound_vars_subst(
|
||||||
|
&self,
|
||||||
|
db: &dyn HirDatabase,
|
||||||
|
debruijn: DebruijnIndex,
|
||||||
|
) -> Substitution {
|
||||||
|
Substitution::from_iter(
|
||||||
|
Interner,
|
||||||
|
self.iter_id().enumerate().map(|(idx, id)| match id {
|
||||||
|
GenericParamId::ConstParamId(id) => BoundVar::new(debruijn, idx)
|
||||||
|
.to_const(Interner, db.const_param_ty(id))
|
||||||
|
.cast(Interner),
|
||||||
|
GenericParamId::TypeParamId(_) => {
|
||||||
|
BoundVar::new(debruijn, idx).to_ty(Interner).cast(Interner)
|
||||||
|
}
|
||||||
|
GenericParamId::LifetimeParamId(_) => {
|
||||||
|
BoundVar::new(debruijn, idx).to_lifetime(Interner).cast(Interner)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a Substitution that replaces each parameter by itself (i.e. `Ty::Param`).
|
||||||
|
pub(crate) fn placeholder_subst(&self, db: &dyn HirDatabase) -> Substitution {
|
||||||
|
Substitution::from_iter(
|
||||||
|
Interner,
|
||||||
|
self.iter_id().map(|id| match id {
|
||||||
|
GenericParamId::TypeParamId(id) => {
|
||||||
|
crate::to_placeholder_idx(db, id.into()).to_ty(Interner).cast(Interner)
|
||||||
|
}
|
||||||
|
GenericParamId::ConstParamId(id) => crate::to_placeholder_idx(db, id.into())
|
||||||
|
.to_const(Interner, db.const_param_ty(id))
|
||||||
|
.cast(Interner),
|
||||||
|
GenericParamId::LifetimeParamId(id) => {
|
||||||
|
crate::lt_to_placeholder_idx(db, id).to_lifetime(Interner).cast(Interner)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<GenericDefId> {
|
||||||
|
let container = match def {
|
||||||
|
GenericDefId::FunctionId(it) => it.lookup(db).container,
|
||||||
|
GenericDefId::TypeAliasId(it) => it.lookup(db).container,
|
||||||
|
GenericDefId::ConstId(it) => it.lookup(db).container,
|
||||||
|
GenericDefId::EnumVariantId(it) => return Some(it.lookup(db).parent.into()),
|
||||||
|
GenericDefId::AdtId(_)
|
||||||
|
| GenericDefId::TraitId(_)
|
||||||
|
| GenericDefId::ImplId(_)
|
||||||
|
| GenericDefId::TraitAliasId(_) => return None,
|
||||||
|
};
|
||||||
|
|
||||||
|
match container {
|
||||||
|
ItemContainerId::ImplId(it) => Some(it.into()),
|
||||||
|
ItemContainerId::TraitId(it) => Some(it.into()),
|
||||||
|
ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => None,
|
||||||
|
}
|
||||||
|
}
|
|
@ -56,11 +56,12 @@ use triomphe::Arc;
|
||||||
use crate::{
|
use crate::{
|
||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
error_lifetime, fold_tys,
|
error_lifetime, fold_tys,
|
||||||
|
generics::Generics,
|
||||||
infer::{coerce::CoerceMany, unify::InferenceTable},
|
infer::{coerce::CoerceMany, unify::InferenceTable},
|
||||||
lower::ImplTraitLoweringMode,
|
lower::ImplTraitLoweringMode,
|
||||||
to_assoc_type_id,
|
to_assoc_type_id,
|
||||||
traits::FnTrait,
|
traits::FnTrait,
|
||||||
utils::{Generics, InTypeConstIdMetadata, UnevaluatedConstEvaluatorFolder},
|
utils::{InTypeConstIdMetadata, UnevaluatedConstEvaluatorFolder},
|
||||||
AliasEq, AliasTy, Binders, ClosureId, Const, DomainGoal, GenericArg, Goal, ImplTraitId,
|
AliasEq, AliasTy, Binders, ClosureId, Const, DomainGoal, GenericArg, Goal, ImplTraitId,
|
||||||
ImplTraitIdx, InEnvironment, Interner, Lifetime, OpaqueTyId, ProjectionTy, Substitution,
|
ImplTraitIdx, InEnvironment, Interner, Lifetime, OpaqueTyId, ProjectionTy, Substitution,
|
||||||
TraitEnvironment, Ty, TyBuilder, TyExt,
|
TraitEnvironment, Ty, TyBuilder, TyExt,
|
||||||
|
@ -633,7 +634,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn generics(&self) -> Option<Generics> {
|
pub(crate) fn generics(&self) -> Option<Generics> {
|
||||||
Some(crate::utils::generics(self.db.upcast(), self.resolver.generic_def()?))
|
Some(crate::generics::generics(self.db.upcast(), self.resolver.generic_def()?))
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: This function should be private in module. It is currently only used in the consteval, since we need
|
// FIXME: This function should be private in module. It is currently only used in the consteval, since we need
|
||||||
|
@ -1263,7 +1264,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
forbid_unresolved_segments((ty, Some(var.into())), unresolved)
|
forbid_unresolved_segments((ty, Some(var.into())), unresolved)
|
||||||
}
|
}
|
||||||
TypeNs::SelfType(impl_id) => {
|
TypeNs::SelfType(impl_id) => {
|
||||||
let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
|
let generics = crate::generics::generics(self.db.upcast(), impl_id.into());
|
||||||
let substs = generics.placeholder_subst(self.db);
|
let substs = generics.placeholder_subst(self.db);
|
||||||
let mut ty = self.db.impl_self_ty(impl_id).substitute(Interner, &substs);
|
let mut ty = self.db.impl_self_ty(impl_id).substitute(Interner, &substs);
|
||||||
|
|
||||||
|
|
|
@ -22,11 +22,13 @@ use stdx::never;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db::{HirDatabase, InternedClosure},
|
db::{HirDatabase, InternedClosure},
|
||||||
error_lifetime, from_chalk_trait_id, from_placeholder_idx, make_binders,
|
error_lifetime, from_chalk_trait_id, from_placeholder_idx,
|
||||||
|
generics::Generics,
|
||||||
|
make_binders,
|
||||||
mir::{BorrowKind, MirSpan, MutBorrowKind, ProjectionElem},
|
mir::{BorrowKind, MirSpan, MutBorrowKind, ProjectionElem},
|
||||||
to_chalk_trait_id,
|
to_chalk_trait_id,
|
||||||
traits::FnTrait,
|
traits::FnTrait,
|
||||||
utils::{self, elaborate_clause_supertraits, Generics},
|
utils::{self, elaborate_clause_supertraits},
|
||||||
Adjust, Adjustment, AliasEq, AliasTy, Binders, BindingMode, ChalkTraitId, ClosureId, DynTy,
|
Adjust, Adjustment, AliasEq, AliasTy, Binders, BindingMode, ChalkTraitId, ClosureId, DynTy,
|
||||||
DynTyExt, FnAbi, FnPointer, FnSig, Interner, OpaqueTy, ProjectionTyExt, Substitution, Ty,
|
DynTyExt, FnAbi, FnPointer, FnSig, Interner, OpaqueTy, ProjectionTyExt, Substitution, Ty,
|
||||||
TyExt, WhereClause,
|
TyExt, WhereClause,
|
||||||
|
|
|
@ -24,6 +24,7 @@ use crate::{
|
||||||
consteval,
|
consteval,
|
||||||
db::{InternedClosure, InternedCoroutine},
|
db::{InternedClosure, InternedCoroutine},
|
||||||
error_lifetime,
|
error_lifetime,
|
||||||
|
generics::{generics, Generics},
|
||||||
infer::{
|
infer::{
|
||||||
coerce::{CoerceMany, CoercionCause},
|
coerce::{CoerceMany, CoercionCause},
|
||||||
find_continuable,
|
find_continuable,
|
||||||
|
@ -39,7 +40,6 @@ use crate::{
|
||||||
primitive::{self, UintTy},
|
primitive::{self, UintTy},
|
||||||
static_lifetime, to_chalk_trait_id,
|
static_lifetime, to_chalk_trait_id,
|
||||||
traits::FnTrait,
|
traits::FnTrait,
|
||||||
utils::{generics, Generics},
|
|
||||||
Adjust, Adjustment, AdtId, AutoBorrow, Binders, CallableDefId, FnAbi, FnPointer, FnSig,
|
Adjust, Adjustment, AdtId, AutoBorrow, Binders, CallableDefId, FnAbi, FnPointer, FnSig,
|
||||||
FnSubst, Interner, Rawness, Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyBuilder,
|
FnSubst, Interner, Rawness, Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyBuilder,
|
||||||
TyExt, TyKind,
|
TyExt, TyKind,
|
||||||
|
|
|
@ -12,11 +12,10 @@ use stdx::never;
|
||||||
use crate::{
|
use crate::{
|
||||||
builder::ParamKind,
|
builder::ParamKind,
|
||||||
consteval, error_lifetime,
|
consteval, error_lifetime,
|
||||||
|
generics::generics,
|
||||||
method_resolution::{self, VisibleFromModule},
|
method_resolution::{self, VisibleFromModule},
|
||||||
to_chalk_trait_id,
|
to_chalk_trait_id, InferenceDiagnostic, Interner, Substitution, TraitRef, TraitRefExt, Ty,
|
||||||
utils::generics,
|
TyBuilder, TyExt, TyKind, ValueTyDefId,
|
||||||
InferenceDiagnostic, Interner, Substitution, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt,
|
|
||||||
TyKind, ValueTyDefId,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{ExprOrPatId, InferenceContext};
|
use super::{ExprOrPatId, InferenceContext};
|
||||||
|
@ -64,7 +63,7 @@ impl InferenceContext<'_> {
|
||||||
it.into()
|
it.into()
|
||||||
}
|
}
|
||||||
ValueNs::ImplSelf(impl_id) => {
|
ValueNs::ImplSelf(impl_id) => {
|
||||||
let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
|
let generics = crate::generics::generics(self.db.upcast(), impl_id.into());
|
||||||
let substs = generics.placeholder_subst(self.db);
|
let substs = generics.placeholder_subst(self.db);
|
||||||
let ty = self.db.impl_self_ty(impl_id).substitute(Interner, &substs);
|
let ty = self.db.impl_self_ty(impl_id).substitute(Interner, &substs);
|
||||||
if let Some((AdtId::StructId(struct_id), substs)) = ty.as_adt() {
|
if let Some((AdtId::StructId(struct_id), substs)) = ty.as_adt() {
|
||||||
|
|
|
@ -22,6 +22,7 @@ extern crate ra_ap_rustc_pattern_analysis as rustc_pattern_analysis;
|
||||||
mod builder;
|
mod builder;
|
||||||
mod chalk_db;
|
mod chalk_db;
|
||||||
mod chalk_ext;
|
mod chalk_ext;
|
||||||
|
mod generics;
|
||||||
mod infer;
|
mod infer;
|
||||||
mod inhabitedness;
|
mod inhabitedness;
|
||||||
mod interner;
|
mod interner;
|
||||||
|
@ -67,11 +68,10 @@ use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use syntax::ast::{make, ConstArg};
|
use syntax::ast::{make, ConstArg};
|
||||||
use traits::FnTrait;
|
use traits::FnTrait;
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
use utils::Generics;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
consteval::unknown_const, db::HirDatabase, display::HirDisplay, infer::unify::InferenceTable,
|
consteval::unknown_const, db::HirDatabase, display::HirDisplay, generics::Generics,
|
||||||
utils::generics,
|
infer::unify::InferenceTable,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use autoderef::autoderef;
|
pub use autoderef::autoderef;
|
||||||
|
@ -289,7 +289,7 @@ impl Hash for ConstScalar {
|
||||||
|
|
||||||
/// Return an index of a parameter in the generic type parameter list by it's id.
|
/// Return an index of a parameter in the generic type parameter list by it's id.
|
||||||
pub fn param_idx(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option<usize> {
|
pub fn param_idx(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option<usize> {
|
||||||
generics(db.upcast(), id.parent).type_or_const_param_idx(id)
|
generics::generics(db.upcast(), id.parent).type_or_const_param_idx(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn wrap_empty_binders<T>(value: T) -> Binders<T>
|
pub(crate) fn wrap_empty_binders<T>(value: T) -> Binders<T>
|
||||||
|
|
|
@ -58,12 +58,13 @@ use crate::{
|
||||||
unknown_const_as_generic,
|
unknown_const_as_generic,
|
||||||
},
|
},
|
||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
error_lifetime, make_binders,
|
error_lifetime,
|
||||||
|
generics::{generics, Generics},
|
||||||
|
make_binders,
|
||||||
mapping::{from_chalk_trait_id, lt_to_placeholder_idx, ToChalk},
|
mapping::{from_chalk_trait_id, lt_to_placeholder_idx, ToChalk},
|
||||||
static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
|
static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
|
||||||
utils::{
|
utils::{
|
||||||
self, all_super_trait_refs, associated_type_by_name_including_super_traits, generics,
|
all_super_trait_refs, associated_type_by_name_including_super_traits, InTypeConstIdMetadata,
|
||||||
Generics, InTypeConstIdMetadata,
|
|
||||||
},
|
},
|
||||||
AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy,
|
AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy,
|
||||||
FnAbi, FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, Lifetime,
|
FnAbi, FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, Lifetime,
|
||||||
|
@ -705,7 +706,8 @@ impl<'a> TyLoweringContext<'a> {
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
let len_self = utils::generics(self.db.upcast(), associated_ty.into()).len_self();
|
let len_self =
|
||||||
|
crate::generics::generics(self.db.upcast(), associated_ty.into()).len_self();
|
||||||
|
|
||||||
let substs = Substitution::from_iter(
|
let substs = Substitution::from_iter(
|
||||||
Interner,
|
Interner,
|
||||||
|
|
|
@ -28,6 +28,7 @@ use crate::{
|
||||||
db::{HirDatabase, InternedClosure},
|
db::{HirDatabase, InternedClosure},
|
||||||
display::HirDisplay,
|
display::HirDisplay,
|
||||||
error_lifetime,
|
error_lifetime,
|
||||||
|
generics::generics,
|
||||||
infer::{CaptureKind, CapturedItem, TypeMismatch},
|
infer::{CaptureKind, CapturedItem, TypeMismatch},
|
||||||
inhabitedness::is_ty_uninhabited_from,
|
inhabitedness::is_ty_uninhabited_from,
|
||||||
layout::LayoutError,
|
layout::LayoutError,
|
||||||
|
@ -42,7 +43,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
static_lifetime,
|
static_lifetime,
|
||||||
traits::FnTrait,
|
traits::FnTrait,
|
||||||
utils::{generics, ClosureSubst},
|
utils::ClosureSubst,
|
||||||
Adjust, Adjustment, AutoBorrow, CallableDefId, TyBuilder, TyExt,
|
Adjust, Adjustment, AutoBorrow, CallableDefId, TyBuilder, TyExt,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,8 @@ use crate::{
|
||||||
consteval::{intern_const_scalar, unknown_const},
|
consteval::{intern_const_scalar, unknown_const},
|
||||||
db::{HirDatabase, InternedClosure},
|
db::{HirDatabase, InternedClosure},
|
||||||
from_placeholder_idx,
|
from_placeholder_idx,
|
||||||
|
generics::{generics, Generics},
|
||||||
infer::normalize,
|
infer::normalize,
|
||||||
utils::{generics, Generics},
|
|
||||||
ClosureId, Const, Interner, ProjectionTy, Substitution, TraitEnvironment, Ty, TyKind,
|
ClosureId, Const, Interner, ProjectionTy, Substitution, TraitEnvironment, Ty, TyKind,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,25 +5,19 @@ use std::{hash::Hash, iter};
|
||||||
|
|
||||||
use base_db::CrateId;
|
use base_db::CrateId;
|
||||||
use chalk_ir::{
|
use chalk_ir::{
|
||||||
cast::Cast,
|
|
||||||
fold::{FallibleTypeFolder, Shift},
|
fold::{FallibleTypeFolder, Shift},
|
||||||
BoundVar, DebruijnIndex,
|
DebruijnIndex,
|
||||||
};
|
};
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
generics::{
|
generics::{WherePredicate, WherePredicateTypeTarget},
|
||||||
GenericParamDataRef, GenericParams, LifetimeParamData, TypeOrConstParamData,
|
|
||||||
TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
|
|
||||||
},
|
|
||||||
lang_item::LangItem,
|
lang_item::LangItem,
|
||||||
resolver::{HasResolver, TypeNs},
|
resolver::{HasResolver, TypeNs},
|
||||||
type_ref::{TraitBoundModifier, TypeRef},
|
type_ref::{TraitBoundModifier, TypeRef},
|
||||||
ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, GenericParamId, ItemContainerId,
|
EnumId, EnumVariantId, FunctionId, Lookup, OpaqueInternableThing, TraitId, TypeAliasId,
|
||||||
LifetimeParamId, Lookup, OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId,
|
TypeOrConstParamId,
|
||||||
TypeParamId,
|
|
||||||
};
|
};
|
||||||
use hir_expand::name::Name;
|
use hir_expand::name::Name;
|
||||||
use intern::Interned;
|
|
||||||
use rustc_abi::TargetDataLayout;
|
use rustc_abi::TargetDataLayout;
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
@ -226,11 +220,6 @@ pub(super) fn associated_type_by_name_including_super_traits(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics {
|
|
||||||
let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def)));
|
|
||||||
Generics { def, params: db.generic_params(def), parent_generics }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// It is a bit different from the rustc equivalent. Currently it stores:
|
/// It is a bit different from the rustc equivalent. Currently it stores:
|
||||||
/// - 0: the function signature, encoded as a function pointer type
|
/// - 0: the function signature, encoded as a function pointer type
|
||||||
/// - 1..n: generics of the parent
|
/// - 1..n: generics of the parent
|
||||||
|
@ -262,275 +251,6 @@ impl<'a> ClosureSubst<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub(crate) struct Generics {
|
|
||||||
def: GenericDefId,
|
|
||||||
pub(crate) params: Interned<GenericParams>,
|
|
||||||
parent_generics: Option<Box<Generics>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Generics {
|
|
||||||
pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
|
|
||||||
self.iter().map(|(id, _)| id)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn def(&self) -> GenericDefId {
|
|
||||||
self.def
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Iterator over types and const params of self, then parent.
|
|
||||||
pub(crate) fn iter<'a>(
|
|
||||||
&'a self,
|
|
||||||
) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'a>)> + 'a {
|
|
||||||
let from_toc_id = |it: &'a Generics| {
|
|
||||||
move |(local_id, p): (_, &'a TypeOrConstParamData)| {
|
|
||||||
let id = TypeOrConstParamId { parent: it.def, local_id };
|
|
||||||
match p {
|
|
||||||
TypeOrConstParamData::TypeParamData(p) => (
|
|
||||||
GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
|
|
||||||
GenericParamDataRef::TypeParamData(p),
|
|
||||||
),
|
|
||||||
TypeOrConstParamData::ConstParamData(p) => (
|
|
||||||
GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
|
|
||||||
GenericParamDataRef::ConstParamData(p),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let from_lt_id = |it: &'a Generics| {
|
|
||||||
move |(local_id, p): (_, &'a LifetimeParamData)| {
|
|
||||||
(
|
|
||||||
GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
|
|
||||||
GenericParamDataRef::LifetimeParamData(p),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let lt_iter = self.params.iter_lt().map(from_lt_id(self));
|
|
||||||
self.params
|
|
||||||
.iter_type_or_consts()
|
|
||||||
.map(from_toc_id(self))
|
|
||||||
.chain(lt_iter)
|
|
||||||
.chain(self.iter_parent())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Iterate over types and const params without parent params.
|
|
||||||
pub(crate) fn iter_self<'a>(
|
|
||||||
&'a self,
|
|
||||||
) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'a>)> + 'a {
|
|
||||||
let from_toc_id = |it: &'a Generics| {
|
|
||||||
move |(local_id, p): (_, &'a TypeOrConstParamData)| {
|
|
||||||
let id = TypeOrConstParamId { parent: it.def, local_id };
|
|
||||||
match p {
|
|
||||||
TypeOrConstParamData::TypeParamData(p) => (
|
|
||||||
GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
|
|
||||||
GenericParamDataRef::TypeParamData(p),
|
|
||||||
),
|
|
||||||
TypeOrConstParamData::ConstParamData(p) => (
|
|
||||||
GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
|
|
||||||
GenericParamDataRef::ConstParamData(p),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let from_lt_id = |it: &'a Generics| {
|
|
||||||
move |(local_id, p): (_, &'a LifetimeParamData)| {
|
|
||||||
(
|
|
||||||
GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
|
|
||||||
GenericParamDataRef::LifetimeParamData(p),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
self.params
|
|
||||||
.iter_type_or_consts()
|
|
||||||
.map(from_toc_id(self))
|
|
||||||
.chain(self.params.iter_lt().map(from_lt_id(self)))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Iterator over types and const params of parent.
|
|
||||||
pub(crate) fn iter_parent(
|
|
||||||
&self,
|
|
||||||
) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'_>)> + '_ {
|
|
||||||
self.parent_generics().into_iter().flat_map(|it| {
|
|
||||||
let from_toc_id = move |(local_id, p)| {
|
|
||||||
let p: &_ = p;
|
|
||||||
let id = TypeOrConstParamId { parent: it.def, local_id };
|
|
||||||
match p {
|
|
||||||
TypeOrConstParamData::TypeParamData(p) => (
|
|
||||||
GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
|
|
||||||
GenericParamDataRef::TypeParamData(p),
|
|
||||||
),
|
|
||||||
TypeOrConstParamData::ConstParamData(p) => (
|
|
||||||
GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
|
|
||||||
GenericParamDataRef::ConstParamData(p),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let from_lt_id = move |(local_id, p): (_, _)| {
|
|
||||||
(
|
|
||||||
GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
|
|
||||||
GenericParamDataRef::LifetimeParamData(p),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
let lt_iter = it.params.iter_lt().map(from_lt_id);
|
|
||||||
it.params.iter_type_or_consts().map(from_toc_id).chain(lt_iter)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns total number of generic parameters in scope, including those from parent.
|
|
||||||
pub(crate) fn len(&self) -> usize {
|
|
||||||
let parent = self.parent_generics().map_or(0, Generics::len);
|
|
||||||
let child = self.params.len();
|
|
||||||
parent + child
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns numbers of generic parameters and lifetimes excluding those from parent.
|
|
||||||
pub(crate) fn len_self(&self) -> usize {
|
|
||||||
self.params.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns number of generic parameter excluding those from parent
|
|
||||||
fn len_type_and_const_params(&self) -> usize {
|
|
||||||
self.params.type_or_consts.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// (parent total, self param, type params, const params, impl trait list, lifetimes)
|
|
||||||
pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize, usize, usize) {
|
|
||||||
let mut self_params = 0;
|
|
||||||
let mut type_params = 0;
|
|
||||||
let mut impl_trait_params = 0;
|
|
||||||
let mut const_params = 0;
|
|
||||||
let mut lifetime_params = 0;
|
|
||||||
self.params.iter_type_or_consts().for_each(|(_, data)| match data {
|
|
||||||
TypeOrConstParamData::TypeParamData(p) => match p.provenance {
|
|
||||||
TypeParamProvenance::TypeParamList => type_params += 1,
|
|
||||||
TypeParamProvenance::TraitSelf => self_params += 1,
|
|
||||||
TypeParamProvenance::ArgumentImplTrait => impl_trait_params += 1,
|
|
||||||
},
|
|
||||||
TypeOrConstParamData::ConstParamData(_) => const_params += 1,
|
|
||||||
});
|
|
||||||
|
|
||||||
self.params.iter_lt().for_each(|(_, _)| lifetime_params += 1);
|
|
||||||
|
|
||||||
let parent_len = self.parent_generics().map_or(0, Generics::len);
|
|
||||||
(parent_len, self_params, type_params, const_params, impl_trait_params, lifetime_params)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn type_or_const_param_idx(&self, param: TypeOrConstParamId) -> Option<usize> {
|
|
||||||
Some(self.find_type_or_const_param(param)?.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_type_or_const_param(
|
|
||||||
&self,
|
|
||||||
param: TypeOrConstParamId,
|
|
||||||
) -> Option<(usize, &TypeOrConstParamData)> {
|
|
||||||
if param.parent == self.def {
|
|
||||||
let idx = param.local_id.into_raw().into_u32() as usize;
|
|
||||||
if idx >= self.params.type_or_consts.len() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
Some((idx, &self.params.type_or_consts[param.local_id]))
|
|
||||||
} else {
|
|
||||||
self.parent_generics()
|
|
||||||
.and_then(|g| g.find_type_or_const_param(param))
|
|
||||||
// Remember that parent parameters come after parameters for self.
|
|
||||||
.map(|(idx, data)| (self.len_self() + idx, data))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn lifetime_idx(&self, lifetime: LifetimeParamId) -> Option<usize> {
|
|
||||||
Some(self.find_lifetime(lifetime)?.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_lifetime(&self, lifetime: LifetimeParamId) -> Option<(usize, &LifetimeParamData)> {
|
|
||||||
if lifetime.parent == self.def {
|
|
||||||
let idx = lifetime.local_id.into_raw().into_u32() as usize;
|
|
||||||
if idx >= self.params.lifetimes.len() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
Some((
|
|
||||||
self.len_type_and_const_params() + idx,
|
|
||||||
&self.params.lifetimes[lifetime.local_id],
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
self.parent_generics()
|
|
||||||
.and_then(|g| g.find_lifetime(lifetime))
|
|
||||||
.map(|(idx, data)| (self.len_self() + idx, data))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn parent_generics(&self) -> Option<&Generics> {
|
|
||||||
self.parent_generics.as_deref()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn parent_or_self(&self) -> &Generics {
|
|
||||||
self.parent_generics.as_deref().unwrap_or(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a Substitution that replaces each parameter by a bound variable.
|
|
||||||
pub(crate) fn bound_vars_subst(
|
|
||||||
&self,
|
|
||||||
db: &dyn HirDatabase,
|
|
||||||
debruijn: DebruijnIndex,
|
|
||||||
) -> Substitution {
|
|
||||||
Substitution::from_iter(
|
|
||||||
Interner,
|
|
||||||
self.iter_id().enumerate().map(|(idx, id)| match id {
|
|
||||||
GenericParamId::ConstParamId(id) => BoundVar::new(debruijn, idx)
|
|
||||||
.to_const(Interner, db.const_param_ty(id))
|
|
||||||
.cast(Interner),
|
|
||||||
GenericParamId::TypeParamId(_) => {
|
|
||||||
BoundVar::new(debruijn, idx).to_ty(Interner).cast(Interner)
|
|
||||||
}
|
|
||||||
GenericParamId::LifetimeParamId(_) => {
|
|
||||||
BoundVar::new(debruijn, idx).to_lifetime(Interner).cast(Interner)
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a Substitution that replaces each parameter by itself (i.e. `Ty::Param`).
|
|
||||||
pub(crate) fn placeholder_subst(&self, db: &dyn HirDatabase) -> Substitution {
|
|
||||||
Substitution::from_iter(
|
|
||||||
Interner,
|
|
||||||
self.iter_id().map(|id| match id {
|
|
||||||
GenericParamId::TypeParamId(id) => {
|
|
||||||
crate::to_placeholder_idx(db, id.into()).to_ty(Interner).cast(Interner)
|
|
||||||
}
|
|
||||||
GenericParamId::ConstParamId(id) => crate::to_placeholder_idx(db, id.into())
|
|
||||||
.to_const(Interner, db.const_param_ty(id))
|
|
||||||
.cast(Interner),
|
|
||||||
GenericParamId::LifetimeParamId(id) => {
|
|
||||||
crate::lt_to_placeholder_idx(db, id).to_lifetime(Interner).cast(Interner)
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<GenericDefId> {
|
|
||||||
let container = match def {
|
|
||||||
GenericDefId::FunctionId(it) => it.lookup(db).container,
|
|
||||||
GenericDefId::TypeAliasId(it) => it.lookup(db).container,
|
|
||||||
GenericDefId::ConstId(it) => it.lookup(db).container,
|
|
||||||
GenericDefId::EnumVariantId(it) => return Some(it.lookup(db).parent.into()),
|
|
||||||
GenericDefId::AdtId(_)
|
|
||||||
| GenericDefId::TraitId(_)
|
|
||||||
| GenericDefId::ImplId(_)
|
|
||||||
| GenericDefId::TraitAliasId(_) => return None,
|
|
||||||
};
|
|
||||||
|
|
||||||
match container {
|
|
||||||
ItemContainerId::ImplId(it) => Some(it.into()),
|
|
||||||
ItemContainerId::TraitId(it) => Some(it.into()),
|
|
||||||
ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_fn_unsafe_to_call(db: &dyn HirDatabase, func: FunctionId) -> bool {
|
pub fn is_fn_unsafe_to_call(db: &dyn HirDatabase, func: FunctionId) -> bool {
|
||||||
let data = db.function_data(func);
|
let data = db.function_data(func);
|
||||||
if data.has_unsafe_kw() {
|
if data.has_unsafe_kw() {
|
||||||
|
|
Loading…
Reference in a new issue