Auto merge of #17473 - Veykril:generics, r=Veykril
internal: Tidy up generics handling in hir-ty a bit
This commit is contained in:
commit
36c37313a0
@ -11,7 +11,7 @@
|
||||
ExpandResult,
|
||||
};
|
||||
use intern::Interned;
|
||||
use la_arena::Arena;
|
||||
use la_arena::{Arena, RawIdx};
|
||||
use once_cell::unsync::Lazy;
|
||||
use stdx::impl_from;
|
||||
use syntax::ast::{self, HasGenericParams, HasName, HasTypeBounds};
|
||||
@ -28,6 +28,9 @@
|
||||
LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
|
||||
};
|
||||
|
||||
const SELF_PARAM_ID_IN_SELF: la_arena::Idx<TypeOrConstParamData> =
|
||||
LocalTypeOrConstParamId::from_raw(RawIdx::from_u32(0));
|
||||
|
||||
/// Data about a generic type parameter (to a function, struct, impl, ...).
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct TypeParamData {
|
||||
@ -441,15 +444,18 @@ pub(crate) fn finish(self) -> GenericParams {
|
||||
|
||||
impl GenericParams {
|
||||
/// Number of Generic parameters (type_or_consts + lifetimes)
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
self.type_or_consts.len() + self.lifetimes.len()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
/// Iterator of type_or_consts field
|
||||
#[inline]
|
||||
pub fn iter_type_or_consts(
|
||||
&self,
|
||||
) -> impl DoubleEndedIterator<Item = (LocalTypeOrConstParamId, &TypeOrConstParamData)> {
|
||||
@ -457,6 +463,7 @@ pub fn iter_type_or_consts(
|
||||
}
|
||||
|
||||
/// Iterator of lifetimes field
|
||||
#[inline]
|
||||
pub fn iter_lt(
|
||||
&self,
|
||||
) -> impl DoubleEndedIterator<Item = (LocalLifetimeParamId, &LifetimeParamData)> {
|
||||
@ -605,17 +612,18 @@ pub fn find_const_by_name(&self, name: &Name, parent: GenericDefId) -> Option<Co
|
||||
})
|
||||
}
|
||||
|
||||
pub fn find_trait_self_param(&self) -> Option<LocalTypeOrConstParamId> {
|
||||
self.type_or_consts.iter().find_map(|(id, p)| {
|
||||
matches!(
|
||||
p,
|
||||
TypeOrConstParamData::TypeParamData(TypeParamData {
|
||||
provenance: TypeParamProvenance::TraitSelf,
|
||||
..
|
||||
})
|
||||
)
|
||||
.then(|| id)
|
||||
})
|
||||
pub fn trait_self_param(&self) -> Option<LocalTypeOrConstParamId> {
|
||||
if self.type_or_consts.is_empty() {
|
||||
return None;
|
||||
}
|
||||
matches!(
|
||||
self.type_or_consts[SELF_PARAM_ID_IN_SELF],
|
||||
TypeOrConstParamData::TypeParamData(TypeParamData {
|
||||
provenance: TypeParamProvenance::TraitSelf,
|
||||
..
|
||||
})
|
||||
)
|
||||
.then(|| SELF_PARAM_ID_IN_SELF)
|
||||
}
|
||||
|
||||
pub fn find_lifetime_by_name(
|
||||
|
@ -923,6 +923,7 @@ pub enum GenericDefId {
|
||||
ImplId(ImplId),
|
||||
// enum variants cannot have generics themselves, but their parent enums
|
||||
// can, and this makes some code easier to write
|
||||
// FIXME: Try to remove this as that will reduce the amount of query slots generated per enum?
|
||||
EnumVariantId(EnumVariantId),
|
||||
// consts can have type parameters from their parents (i.e. associated consts of traits)
|
||||
ConstId(ConstId),
|
||||
|
@ -14,10 +14,10 @@
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::{
|
||||
consteval::unknown_const_as_generic, db::HirDatabase, error_lifetime,
|
||||
infer::unify::InferenceTable, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics,
|
||||
Binders, BoundVar, CallableSig, GenericArg, GenericArgData, Interner, ProjectionTy,
|
||||
Substitution, TraitRef, Ty, TyDefId, TyExt, TyKind,
|
||||
consteval::unknown_const_as_generic, db::HirDatabase, error_lifetime, generics::generics,
|
||||
infer::unify::InferenceTable, primitive, to_assoc_type_id, to_chalk_trait_id, Binders,
|
||||
BoundVar, CallableSig, GenericArg, GenericArgData, Interner, ProjectionTy, Substitution,
|
||||
TraitRef, Ty, TyDefId, TyExt, TyKind,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
|
@ -20,13 +20,14 @@
|
||||
use crate::{
|
||||
db::{HirDatabase, InternedCoroutine},
|
||||
display::HirDisplay,
|
||||
from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, make_binders,
|
||||
make_single_type_binders,
|
||||
from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id,
|
||||
generics::generics,
|
||||
make_binders, make_single_type_binders,
|
||||
mapping::{from_chalk, ToChalk, TypeAliasAsValue},
|
||||
method_resolution::{TraitImpls, TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
|
||||
to_assoc_type_id, to_chalk_trait_id,
|
||||
traits::ChalkContext,
|
||||
utils::{generics, ClosureSubst},
|
||||
utils::ClosureSubst,
|
||||
wrap_empty_binders, AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId,
|
||||
Interner, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, Substitution, TraitRef,
|
||||
TraitRefExt, Ty, TyBuilder, TyExt, TyKind, WhereClause,
|
||||
|
@ -12,12 +12,10 @@
|
||||
};
|
||||
|
||||
use crate::{
|
||||
db::HirDatabase,
|
||||
from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx,
|
||||
to_chalk_trait_id,
|
||||
utils::{generics, ClosureSubst},
|
||||
AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Canonical, CanonicalVarKinds,
|
||||
ClosureId, DynTy, FnPointer, ImplTraitId, InEnvironment, Interner, Lifetime, ProjectionTy,
|
||||
db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id,
|
||||
from_placeholder_idx, generics::generics, to_chalk_trait_id, utils::ClosureSubst, AdtId,
|
||||
AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, ClosureId,
|
||||
DynTy, FnPointer, ImplTraitId, InEnvironment, Interner, Lifetime, ProjectionTy,
|
||||
QuantifiedWhereClause, Substitution, TraitRef, Ty, TyBuilder, TyKind, TypeFlags, WhereClause,
|
||||
};
|
||||
|
||||
|
@ -15,10 +15,9 @@
|
||||
use triomphe::Arc;
|
||||
|
||||
use crate::{
|
||||
db::HirDatabase, infer::InferenceContext, lower::ParamLoweringMode,
|
||||
mir::monomorphize_mir_body_bad, to_placeholder_idx, utils::Generics, Const, ConstData,
|
||||
ConstScalar, ConstValue, GenericArg, Interner, MemoryMap, Substitution, TraitEnvironment, Ty,
|
||||
TyBuilder,
|
||||
db::HirDatabase, generics::Generics, infer::InferenceContext, lower::ParamLoweringMode,
|
||||
mir::monomorphize_mir_body_bad, to_placeholder_idx, Const, ConstData, ConstScalar, ConstValue,
|
||||
GenericArg, Interner, MemoryMap, Substitution, TraitEnvironment, Ty, TyBuilder,
|
||||
};
|
||||
|
||||
use super::mir::{interpret_mir, lower_to_mir, pad16, MirEvalError, MirLowerError};
|
||||
@ -72,12 +71,12 @@ fn from(value: MirEvalError) -> Self {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn path_to_const(
|
||||
pub(crate) fn path_to_const<'g>(
|
||||
db: &dyn HirDatabase,
|
||||
resolver: &Resolver,
|
||||
path: &Path,
|
||||
mode: ParamLoweringMode,
|
||||
args: impl FnOnce() -> Option<Generics>,
|
||||
args: impl FnOnce() -> Option<&'g Generics>,
|
||||
debruijn: DebruijnIndex,
|
||||
expected_ty: Ty,
|
||||
) -> Option<Const> {
|
||||
@ -90,7 +89,7 @@ pub(crate) fn path_to_const(
|
||||
}
|
||||
ParamLoweringMode::Variable => {
|
||||
let args = args();
|
||||
match args.as_ref().and_then(|args| args.type_or_const_param_idx(p.into())) {
|
||||
match args.and_then(|args| args.type_or_const_param_idx(p.into())) {
|
||||
Some(it) => ConstValue::BoundVar(BoundVar::new(debruijn, it)),
|
||||
None => {
|
||||
never!(
|
||||
|
@ -36,12 +36,13 @@
|
||||
consteval::try_const_usize,
|
||||
db::{HirDatabase, InternedClosure},
|
||||
from_assoc_type_id, from_foreign_def_id, from_placeholder_idx,
|
||||
generics::generics,
|
||||
layout::Layout,
|
||||
lt_from_placeholder_idx,
|
||||
mapping::from_chalk,
|
||||
mir::pad16,
|
||||
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,
|
||||
ConstScalar, ConstValue, DomainGoal, FnAbi, GenericArg, ImplTraitId, Interner, Lifetime,
|
||||
LifetimeData, LifetimeOutlives, MemoryMap, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt,
|
||||
@ -493,7 +494,7 @@ fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
||||
ConstValue::Placeholder(idx) => {
|
||||
let id = from_placeholder_idx(f.db, *idx);
|
||||
let generics = generics(f.db.upcast(), id.parent);
|
||||
let param_data = &generics.params[id.local_id];
|
||||
let param_data = &generics[id.local_id];
|
||||
write!(f, "{}", param_data.name().unwrap().display(f.db.upcast()))?;
|
||||
Ok(())
|
||||
}
|
||||
@ -988,7 +989,7 @@ fn hir_fmt(
|
||||
|
||||
if parameters.len(Interner) > 0 {
|
||||
let generics = generics(db.upcast(), def.into());
|
||||
let (parent_len, self_, type_, const_, impl_, lifetime) =
|
||||
let (parent_len, self_param, type_, const_, impl_, lifetime) =
|
||||
generics.provenance_split();
|
||||
let parameters = parameters.as_slice(Interner);
|
||||
// We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
|
||||
@ -996,7 +997,7 @@ fn hir_fmt(
|
||||
// `parameters` are in the order of fn's params (including impl traits), fn's lifetimes
|
||||
// parent's params (those from enclosing impl or trait, if any).
|
||||
let (fn_params, other) =
|
||||
parameters.split_at(self_ + type_ + const_ + lifetime);
|
||||
parameters.split_at(self_param as usize + type_ + const_ + lifetime);
|
||||
let (_impl, parent_params) = other.split_at(impl_);
|
||||
debug_assert_eq!(parent_params.len(), parent_len);
|
||||
|
||||
@ -1215,7 +1216,7 @@ fn hir_fmt(
|
||||
TyKind::Placeholder(idx) => {
|
||||
let id = from_placeholder_idx(db, *idx);
|
||||
let generics = generics(db.upcast(), id.parent);
|
||||
let param_data = &generics.params[id.local_id];
|
||||
let param_data = &generics[id.local_id];
|
||||
match param_data {
|
||||
TypeOrConstParamData::TypeParamData(p) => match p.provenance {
|
||||
TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {
|
||||
@ -1797,7 +1798,7 @@ fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
||||
LifetimeData::Placeholder(idx) => {
|
||||
let id = lt_from_placeholder_idx(f.db, *idx);
|
||||
let generics = generics(f.db.upcast(), id.parent);
|
||||
let param_data = &generics.params[id.local_id];
|
||||
let param_data = &generics[id.local_id];
|
||||
write!(f, "{}", param_data.name.display(f.db.upcast()))?;
|
||||
Ok(())
|
||||
}
|
||||
|
263
src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
Normal file
263
src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
Normal file
@ -0,0 +1,263 @@
|
||||
//! Utilities for working with generics.
|
||||
//!
|
||||
//! The layout for generics as expected by chalk are as follows:
|
||||
//! - Optional Self parameter
|
||||
//! - Type or Const parameters
|
||||
//! - Lifetime parameters
|
||||
//! - Parent parameters
|
||||
//!
|
||||
//! where parent follows the same scheme.
|
||||
use std::ops;
|
||||
|
||||
use chalk_ir::{cast::Cast as _, BoundVar, DebruijnIndex};
|
||||
use hir_def::{
|
||||
db::DefDatabase,
|
||||
generics::{
|
||||
GenericParamDataRef, GenericParams, LifetimeParamData, TypeOrConstParamData,
|
||||
TypeParamProvenance,
|
||||
},
|
||||
ConstParamId, GenericDefId, GenericParamId, ItemContainerId, LifetimeParamId,
|
||||
LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
|
||||
};
|
||||
use intern::Interned;
|
||||
|
||||
use crate::{db::HirDatabase, lt_to_placeholder_idx, to_placeholder_idx, 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,
|
||||
params: Interned<GenericParams>,
|
||||
parent_generics: Option<Box<Generics>>,
|
||||
}
|
||||
|
||||
impl<T> ops::Index<T> for Generics
|
||||
where
|
||||
GenericParams: ops::Index<T>,
|
||||
{
|
||||
type Output = <GenericParams as ops::Index<T>>::Output;
|
||||
fn index(&self, index: T) -> &Self::Output {
|
||||
&self.params[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl Generics {
|
||||
pub(crate) fn def(&self) -> GenericDefId {
|
||||
self.def
|
||||
}
|
||||
|
||||
pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
|
||||
self.iter_self_id().chain(self.iter_parent_id())
|
||||
}
|
||||
|
||||
pub(crate) fn iter_self_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
|
||||
self.iter_self().map(|(id, _)| id)
|
||||
}
|
||||
|
||||
fn iter_parent_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
|
||||
self.iter_parent().map(|(id, _)| id)
|
||||
}
|
||||
|
||||
pub(crate) fn iter_self_type_or_consts(
|
||||
&self,
|
||||
) -> impl DoubleEndedIterator<Item = (LocalTypeOrConstParamId, &TypeOrConstParamData)> {
|
||||
self.params.iter_type_or_consts()
|
||||
}
|
||||
|
||||
/// Iterate over the params followed by the parent params.
|
||||
pub(crate) fn iter(
|
||||
&self,
|
||||
) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'_>)> + '_ {
|
||||
self.iter_self().chain(self.iter_parent())
|
||||
}
|
||||
|
||||
/// Iterate over the params without parent params.
|
||||
pub(crate) fn iter_self(
|
||||
&self,
|
||||
) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'_>)> + '_ {
|
||||
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.
|
||||
fn iter_parent(
|
||||
&self,
|
||||
) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'_>)> + '_ {
|
||||
self.parent_generics().into_iter().flat_map(|it| {
|
||||
let lt_iter = it.params.iter_lt().map(from_lt_id(it));
|
||||
it.params.iter_type_or_consts().map(from_toc_id(it)).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()
|
||||
}
|
||||
|
||||
/// (parent total, self param, type params, const params, impl trait list, lifetimes)
|
||||
pub(crate) fn provenance_split(&self) -> (usize, bool, usize, usize, usize, usize) {
|
||||
let mut self_param = false;
|
||||
let mut type_params = 0;
|
||||
let mut impl_trait_params = 0;
|
||||
let mut const_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_param |= true,
|
||||
TypeParamProvenance::ArgumentImplTrait => impl_trait_params += 1,
|
||||
},
|
||||
TypeOrConstParamData::ConstParamData(_) => const_params += 1,
|
||||
});
|
||||
|
||||
let lifetime_params = self.params.iter_lt().count();
|
||||
|
||||
let parent_len = self.parent_generics().map_or(0, Generics::len);
|
||||
(parent_len, self_param, type_params, const_params, impl_trait_params, lifetime_params)
|
||||
}
|
||||
|
||||
pub(crate) fn type_or_const_param_idx(&self, param: TypeOrConstParamId) -> Option<usize> {
|
||||
self.find_type_or_const_param(param)
|
||||
}
|
||||
|
||||
fn find_type_or_const_param(&self, param: TypeOrConstParamId) -> Option<usize> {
|
||||
if param.parent == self.def {
|
||||
let idx = param.local_id.into_raw().into_u32() as usize;
|
||||
debug_assert!(idx <= self.params.type_or_consts.len());
|
||||
Some(idx)
|
||||
} else {
|
||||
debug_assert_eq!(self.parent_generics().map(|it| it.def), Some(param.parent));
|
||||
self.parent_generics()
|
||||
.and_then(|g| g.find_type_or_const_param(param))
|
||||
// Remember that parent parameters come after parameters for self.
|
||||
.map(|idx| self.len_self() + idx)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn lifetime_idx(&self, lifetime: LifetimeParamId) -> Option<usize> {
|
||||
self.find_lifetime(lifetime)
|
||||
}
|
||||
|
||||
fn find_lifetime(&self, lifetime: LifetimeParamId) -> Option<usize> {
|
||||
if lifetime.parent == self.def {
|
||||
let idx = lifetime.local_id.into_raw().into_u32() as usize;
|
||||
debug_assert!(idx <= self.params.lifetimes.len());
|
||||
Some(self.params.type_or_consts.len() + idx)
|
||||
} else {
|
||||
debug_assert_eq!(self.parent_generics().map(|it| it.def), Some(lifetime.parent));
|
||||
self.parent_generics()
|
||||
.and_then(|g| g.find_lifetime(lifetime))
|
||||
.map(|idx| self.len_self() + idx)
|
||||
}
|
||||
}
|
||||
|
||||
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) => {
|
||||
to_placeholder_idx(db, id.into()).to_ty(Interner).cast(Interner)
|
||||
}
|
||||
GenericParamId::ConstParamId(id) => to_placeholder_idx(db, id.into())
|
||||
.to_const(Interner, db.const_param_ty(id))
|
||||
.cast(Interner),
|
||||
GenericParamId::LifetimeParamId(id) => {
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
fn from_toc_id<'a>(
|
||||
it: &'a Generics,
|
||||
) -> impl Fn(
|
||||
(LocalTypeOrConstParamId, &'a TypeOrConstParamData),
|
||||
) -> (GenericParamId, GenericParamDataRef<'a>) {
|
||||
move |(local_id, 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),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn from_lt_id<'a>(
|
||||
it: &'a Generics,
|
||||
) -> impl Fn((LocalLifetimeParamId, &'a LifetimeParamData)) -> (GenericParamId, GenericParamDataRef<'a>)
|
||||
{
|
||||
move |(local_id, p): (_, _)| {
|
||||
(
|
||||
GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
|
||||
GenericParamDataRef::LifetimeParamData(p),
|
||||
)
|
||||
}
|
||||
}
|
@ -49,6 +49,7 @@
|
||||
use hir_expand::name::{name, Name};
|
||||
use indexmap::IndexSet;
|
||||
use la_arena::{ArenaMap, Entry};
|
||||
use once_cell::unsync::OnceCell;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use stdx::{always, never};
|
||||
use triomphe::Arc;
|
||||
@ -56,11 +57,12 @@
|
||||
use crate::{
|
||||
db::HirDatabase,
|
||||
error_lifetime, fold_tys,
|
||||
generics::Generics,
|
||||
infer::{coerce::CoerceMany, unify::InferenceTable},
|
||||
lower::ImplTraitLoweringMode,
|
||||
to_assoc_type_id,
|
||||
traits::FnTrait,
|
||||
utils::{Generics, InTypeConstIdMetadata, UnevaluatedConstEvaluatorFolder},
|
||||
utils::{InTypeConstIdMetadata, UnevaluatedConstEvaluatorFolder},
|
||||
AliasEq, AliasTy, Binders, ClosureId, Const, DomainGoal, GenericArg, Goal, ImplTraitId,
|
||||
ImplTraitIdx, InEnvironment, Interner, Lifetime, OpaqueTyId, ProjectionTy, Substitution,
|
||||
TraitEnvironment, Ty, TyBuilder, TyExt,
|
||||
@ -526,6 +528,7 @@ pub(crate) struct InferenceContext<'a> {
|
||||
pub(crate) owner: DefWithBodyId,
|
||||
pub(crate) body: &'a Body,
|
||||
pub(crate) resolver: Resolver,
|
||||
generics: OnceCell<Option<Generics>>,
|
||||
table: unify::InferenceTable<'a>,
|
||||
/// The traits in scope, disregarding block modules. This is used for caching purposes.
|
||||
traits_in_scope: FxHashSet<TraitId>,
|
||||
@ -611,6 +614,7 @@ fn new(
|
||||
) -> Self {
|
||||
let trait_env = db.trait_environment_for_body(owner);
|
||||
InferenceContext {
|
||||
generics: OnceCell::new(),
|
||||
result: InferenceResult::default(),
|
||||
table: unify::InferenceTable::new(db, trait_env),
|
||||
tuple_field_accesses_rev: Default::default(),
|
||||
@ -632,8 +636,14 @@ fn new(
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn generics(&self) -> Option<Generics> {
|
||||
Some(crate::utils::generics(self.db.upcast(), self.resolver.generic_def()?))
|
||||
pub(crate) fn generics(&self) -> Option<&Generics> {
|
||||
self.generics
|
||||
.get_or_init(|| {
|
||||
self.resolver
|
||||
.generic_def()
|
||||
.map(|def| crate::generics::generics(self.db.upcast(), def))
|
||||
})
|
||||
.as_ref()
|
||||
}
|
||||
|
||||
// FIXME: This function should be private in module. It is currently only used in the consteval, since we need
|
||||
@ -1263,7 +1273,7 @@ fn resolve_variant(&mut self, path: Option<&Path>, value_ns: bool) -> (Ty, Optio
|
||||
forbid_unresolved_segments((ty, Some(var.into())), unresolved)
|
||||
}
|
||||
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 mut ty = self.db.impl_self_ty(impl_id).substitute(Interner, &substs);
|
||||
|
||||
|
@ -22,11 +22,13 @@
|
||||
|
||||
use crate::{
|
||||
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},
|
||||
to_chalk_trait_id,
|
||||
traits::FnTrait,
|
||||
utils::{self, elaborate_clause_supertraits, Generics},
|
||||
utils::{self, elaborate_clause_supertraits},
|
||||
Adjust, Adjustment, AliasEq, AliasTy, Binders, BindingMode, ChalkTraitId, ClosureId, DynTy,
|
||||
DynTyExt, FnAbi, FnPointer, FnSig, Interner, OpaqueTy, ProjectionTyExt, Substitution, Ty,
|
||||
TyExt, WhereClause,
|
||||
@ -337,7 +339,7 @@ fn with_ty(self, ctx: &mut InferenceContext<'_>) -> CapturedItem {
|
||||
fn replace_placeholder_with_binder(ctx: &mut InferenceContext<'_>, ty: Ty) -> Binders<Ty> {
|
||||
struct Filler<'a> {
|
||||
db: &'a dyn HirDatabase,
|
||||
generics: Generics,
|
||||
generics: &'a Generics,
|
||||
}
|
||||
impl FallibleTypeFolder<Interner> for Filler<'_> {
|
||||
type Error = ();
|
||||
@ -380,7 +382,7 @@ fn try_fold_free_placeholder_ty(
|
||||
};
|
||||
let filler = &mut Filler { db: ctx.db, generics };
|
||||
let result = ty.clone().try_fold_with(filler, DebruijnIndex::INNERMOST).unwrap_or(ty);
|
||||
make_binders(ctx.db, &filler.generics, result)
|
||||
make_binders(ctx.db, filler.generics, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
consteval,
|
||||
db::{InternedClosure, InternedCoroutine},
|
||||
error_lifetime,
|
||||
generics::{generics, Generics},
|
||||
infer::{
|
||||
coerce::{CoerceMany, CoercionCause},
|
||||
find_continuable,
|
||||
@ -39,7 +40,6 @@
|
||||
primitive::{self, UintTy},
|
||||
static_lifetime, to_chalk_trait_id,
|
||||
traits::FnTrait,
|
||||
utils::{generics, Generics},
|
||||
Adjust, Adjustment, AdtId, AutoBorrow, Binders, CallableDefId, FnAbi, FnPointer, FnSig,
|
||||
FnSubst, Interner, Rawness, Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyBuilder,
|
||||
TyExt, TyKind,
|
||||
@ -1830,13 +1830,13 @@ fn substs_for_method_call(
|
||||
) -> Substitution {
|
||||
let (
|
||||
parent_params,
|
||||
self_params,
|
||||
has_self_param,
|
||||
type_params,
|
||||
const_params,
|
||||
impl_trait_params,
|
||||
lifetime_params,
|
||||
) = def_generics.provenance_split();
|
||||
assert_eq!(self_params, 0); // method shouldn't have another Self param
|
||||
assert!(!has_self_param); // method shouldn't have another Self param
|
||||
let total_len =
|
||||
parent_params + type_params + const_params + impl_trait_params + lifetime_params;
|
||||
let mut substs = Vec::with_capacity(total_len);
|
||||
@ -1844,13 +1844,11 @@ fn substs_for_method_call(
|
||||
// handle provided arguments
|
||||
if let Some(generic_args) = generic_args {
|
||||
// if args are provided, it should be all of them, but we can't rely on that
|
||||
for (arg, kind_id) in generic_args
|
||||
.args
|
||||
.iter()
|
||||
.take(type_params + const_params + lifetime_params)
|
||||
.zip(def_generics.iter_id())
|
||||
let self_params = type_params + const_params + lifetime_params;
|
||||
for (arg, kind_id) in
|
||||
generic_args.args.iter().zip(def_generics.iter_self_id()).take(self_params)
|
||||
{
|
||||
if let Some(g) = generic_arg_to_chalk(
|
||||
let arg = generic_arg_to_chalk(
|
||||
self.db,
|
||||
kind_id,
|
||||
arg,
|
||||
@ -1869,9 +1867,8 @@ fn substs_for_method_call(
|
||||
)
|
||||
},
|
||||
|this, lt_ref| this.make_lifetime(lt_ref),
|
||||
) {
|
||||
substs.push(g);
|
||||
}
|
||||
);
|
||||
substs.push(arg);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -12,11 +12,10 @@
|
||||
use crate::{
|
||||
builder::ParamKind,
|
||||
consteval, error_lifetime,
|
||||
generics::generics,
|
||||
method_resolution::{self, VisibleFromModule},
|
||||
to_chalk_trait_id,
|
||||
utils::generics,
|
||||
InferenceDiagnostic, Interner, Substitution, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt,
|
||||
TyKind, ValueTyDefId,
|
||||
to_chalk_trait_id, InferenceDiagnostic, Interner, Substitution, TraitRef, TraitRefExt, Ty,
|
||||
TyBuilder, TyExt, TyKind, ValueTyDefId,
|
||||
};
|
||||
|
||||
use super::{ExprOrPatId, InferenceContext};
|
||||
@ -64,7 +63,7 @@ fn resolve_value_path(&mut self, path: &Path, id: ExprOrPatId) -> Option<ValuePa
|
||||
it.into()
|
||||
}
|
||||
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 ty = self.db.impl_self_ty(impl_id).substitute(Interner, &substs);
|
||||
if let Some((AdtId::StructId(struct_id), substs)) = ty.as_adt() {
|
||||
|
@ -22,6 +22,7 @@
|
||||
mod builder;
|
||||
mod chalk_db;
|
||||
mod chalk_ext;
|
||||
mod generics;
|
||||
mod infer;
|
||||
mod inhabitedness;
|
||||
mod interner;
|
||||
@ -67,11 +68,10 @@
|
||||
use syntax::ast::{make, ConstArg};
|
||||
use traits::FnTrait;
|
||||
use triomphe::Arc;
|
||||
use utils::Generics;
|
||||
|
||||
use crate::{
|
||||
consteval::unknown_const, db::HirDatabase, display::HirDisplay, infer::unify::InferenceTable,
|
||||
utils::generics,
|
||||
consteval::unknown_const, db::HirDatabase, display::HirDisplay, generics::Generics,
|
||||
infer::unify::InferenceTable,
|
||||
};
|
||||
|
||||
pub use autoderef::autoderef;
|
||||
@ -289,7 +289,7 @@ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
|
||||
/// 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> {
|
||||
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>
|
||||
|
@ -45,6 +45,7 @@
|
||||
use hir_expand::{name::Name, ExpandResult};
|
||||
use intern::Interned;
|
||||
use la_arena::{Arena, ArenaMap};
|
||||
use once_cell::unsync::OnceCell;
|
||||
use rustc_hash::FxHashSet;
|
||||
use smallvec::SmallVec;
|
||||
use stdx::{impl_from, never};
|
||||
@ -58,12 +59,13 @@
|
||||
unknown_const_as_generic,
|
||||
},
|
||||
db::HirDatabase,
|
||||
error_lifetime, make_binders,
|
||||
error_lifetime,
|
||||
generics::{generics, Generics},
|
||||
make_binders,
|
||||
mapping::{from_chalk_trait_id, lt_to_placeholder_idx, ToChalk},
|
||||
static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
|
||||
utils::{
|
||||
self, all_super_trait_refs, associated_type_by_name_including_super_traits, generics,
|
||||
Generics, InTypeConstIdMetadata,
|
||||
all_super_trait_refs, associated_type_by_name_including_super_traits, InTypeConstIdMetadata,
|
||||
},
|
||||
AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy,
|
||||
FnAbi, FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, Lifetime,
|
||||
@ -121,6 +123,7 @@ fn swap(&self, impl_trait_mode: &Self) {
|
||||
pub struct TyLoweringContext<'a> {
|
||||
pub db: &'a dyn HirDatabase,
|
||||
resolver: &'a Resolver,
|
||||
generics: OnceCell<Option<Generics>>,
|
||||
in_binders: DebruijnIndex,
|
||||
// FIXME: Should not be an `Option` but `Resolver` currently does not return owners in all cases
|
||||
// where expected
|
||||
@ -152,6 +155,7 @@ pub fn new_maybe_unowned(
|
||||
Self {
|
||||
db,
|
||||
resolver,
|
||||
generics: OnceCell::new(),
|
||||
owner,
|
||||
in_binders,
|
||||
impl_trait_mode,
|
||||
@ -174,6 +178,7 @@ pub fn with_debruijn<T>(
|
||||
impl_trait_mode,
|
||||
expander: RefCell::new(expander),
|
||||
unsized_types: RefCell::new(unsized_types),
|
||||
generics: self.generics.clone(),
|
||||
..*self
|
||||
};
|
||||
let result = f(&new_ctx);
|
||||
@ -245,8 +250,10 @@ pub fn lower_const(&self, const_ref: &ConstRef, const_type: Ty) -> Const {
|
||||
)
|
||||
}
|
||||
|
||||
fn generics(&self) -> Option<Generics> {
|
||||
Some(generics(self.db.upcast(), self.resolver.generic_def()?))
|
||||
fn generics(&self) -> Option<&Generics> {
|
||||
self.generics
|
||||
.get_or_init(|| self.resolver.generic_def().map(|def| generics(self.db.upcast(), def)))
|
||||
.as_ref()
|
||||
}
|
||||
|
||||
pub fn lower_ty_ext(&self, type_ref: &TypeRef) -> (Ty, Option<TypeNs>) {
|
||||
@ -374,7 +381,7 @@ pub fn lower_ty_ext(&self, type_ref: &TypeRef) -> (Ty, Option<TypeNs>) {
|
||||
counter.set(idx + count_impl_traits(type_ref) as u16);
|
||||
let (
|
||||
_parent_params,
|
||||
self_params,
|
||||
self_param,
|
||||
type_params,
|
||||
const_params,
|
||||
_impl_trait_params,
|
||||
@ -385,7 +392,7 @@ pub fn lower_ty_ext(&self, type_ref: &TypeRef) -> (Ty, Option<TypeNs>) {
|
||||
.provenance_split();
|
||||
TyKind::BoundVar(BoundVar::new(
|
||||
self.in_binders,
|
||||
idx as usize + self_params + type_params + const_params,
|
||||
idx as usize + self_param as usize + type_params + const_params,
|
||||
))
|
||||
.intern(Interner)
|
||||
}
|
||||
@ -705,7 +712,8 @@ fn select_associated_type(&self, res: Option<TypeNs>, segment: PathSegment<'_>)
|
||||
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(
|
||||
Interner,
|
||||
@ -815,14 +823,14 @@ fn substs_from_args_and_bindings(
|
||||
let def_generics = generics(self.db.upcast(), def);
|
||||
let (
|
||||
parent_params,
|
||||
self_params,
|
||||
self_param,
|
||||
type_params,
|
||||
const_params,
|
||||
impl_trait_params,
|
||||
lifetime_params,
|
||||
) = def_generics.provenance_split();
|
||||
let item_len =
|
||||
self_params + type_params + const_params + impl_trait_params + lifetime_params;
|
||||
self_param as usize + type_params + const_params + impl_trait_params + lifetime_params;
|
||||
let total_len = parent_params + item_len;
|
||||
|
||||
let ty_error = TyKind::Error.intern(Interner).cast(Interner);
|
||||
@ -830,18 +838,16 @@ fn substs_from_args_and_bindings(
|
||||
let mut def_generic_iter = def_generics.iter_id();
|
||||
|
||||
let fill_self_params = || {
|
||||
for x in explicit_self_ty
|
||||
.into_iter()
|
||||
.map(|x| x.cast(Interner))
|
||||
.chain(iter::repeat(ty_error.clone()))
|
||||
.take(self_params)
|
||||
{
|
||||
if self_param {
|
||||
let self_ty =
|
||||
explicit_self_ty.map(|x| x.cast(Interner)).unwrap_or_else(|| ty_error.clone());
|
||||
|
||||
if let Some(id) = def_generic_iter.next() {
|
||||
assert!(matches!(
|
||||
id,
|
||||
GenericParamId::TypeParamId(_) | GenericParamId::LifetimeParamId(_)
|
||||
));
|
||||
substs.push(x);
|
||||
substs.push(self_ty);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -852,11 +858,11 @@ fn substs_from_args_and_bindings(
|
||||
fill_self_params();
|
||||
}
|
||||
let expected_num = if generic_args.has_self_type {
|
||||
self_params + type_params + const_params
|
||||
self_param as usize + type_params + const_params
|
||||
} else {
|
||||
type_params + const_params
|
||||
};
|
||||
let skip = if generic_args.has_self_type && self_params == 0 { 1 } else { 0 };
|
||||
let skip = if generic_args.has_self_type && !self_param { 1 } else { 0 };
|
||||
// if args are provided, it should be all of them, but we can't rely on that
|
||||
for arg in generic_args
|
||||
.args
|
||||
@ -866,7 +872,7 @@ fn substs_from_args_and_bindings(
|
||||
.take(expected_num)
|
||||
{
|
||||
if let Some(id) = def_generic_iter.next() {
|
||||
if let Some(x) = generic_arg_to_chalk(
|
||||
let arg = generic_arg_to_chalk(
|
||||
self.db,
|
||||
id,
|
||||
arg,
|
||||
@ -874,13 +880,9 @@ fn substs_from_args_and_bindings(
|
||||
|_, type_ref| self.lower_ty(type_ref),
|
||||
|_, const_ref, ty| self.lower_const(const_ref, ty),
|
||||
|_, lifetime_ref| self.lower_lifetime(lifetime_ref),
|
||||
) {
|
||||
had_explicit_args = true;
|
||||
substs.push(x);
|
||||
} else {
|
||||
// we just filtered them out
|
||||
never!("Unexpected lifetime argument");
|
||||
}
|
||||
);
|
||||
had_explicit_args = true;
|
||||
substs.push(arg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -893,7 +895,7 @@ fn substs_from_args_and_bindings(
|
||||
// Taking into the fact that def_generic_iter will always have lifetimes at the end
|
||||
// Should have some test cases tho to test this behaviour more properly
|
||||
if let Some(id) = def_generic_iter.next() {
|
||||
if let Some(x) = generic_arg_to_chalk(
|
||||
let arg = generic_arg_to_chalk(
|
||||
self.db,
|
||||
id,
|
||||
arg,
|
||||
@ -901,13 +903,9 @@ fn substs_from_args_and_bindings(
|
||||
|_, type_ref| self.lower_ty(type_ref),
|
||||
|_, const_ref, ty| self.lower_const(const_ref, ty),
|
||||
|_, lifetime_ref| self.lower_lifetime(lifetime_ref),
|
||||
) {
|
||||
had_explicit_args = true;
|
||||
substs.push(x);
|
||||
} else {
|
||||
// Never return a None explicitly
|
||||
never!("Unexpected None by generic_arg_to_chalk");
|
||||
}
|
||||
);
|
||||
had_explicit_args = true;
|
||||
substs.push(arg);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -1176,7 +1174,7 @@ fn assoc_type_bindings_from_type_bound(
|
||||
let ty = if let Some(target_param_idx) = target_param_idx {
|
||||
let mut counter = 0;
|
||||
let generics = self.generics().expect("generics in scope");
|
||||
for (idx, data) in generics.params.type_or_consts.iter() {
|
||||
for (idx, data) in generics.iter_self_type_or_consts() {
|
||||
// Count the number of `impl Trait` things that appear before
|
||||
// the target of our `bound`.
|
||||
// Our counter within `impl_trait_mode` should be that number
|
||||
@ -1478,7 +1476,7 @@ fn named_associated_type_shorthand_candidates<R>(
|
||||
// Handle `Self::Type` referring to own associated type in trait definitions
|
||||
if let GenericDefId::TraitId(trait_id) = param_id.parent() {
|
||||
let trait_generics = generics(db.upcast(), trait_id.into());
|
||||
if trait_generics.params[param_id.local_id()].is_trait_self() {
|
||||
if trait_generics[param_id.local_id()].is_trait_self() {
|
||||
let def_generics = generics(db.upcast(), def);
|
||||
let starting_idx = match def {
|
||||
GenericDefId::TraitId(_) => 0,
|
||||
@ -2168,7 +2166,6 @@ pub(crate) fn lower_to_chalk_mutability(m: hir_def::type_ref::Mutability) -> Mut
|
||||
/// Checks if the provided generic arg matches its expected kind, then lower them via
|
||||
/// provided closures. Use unknown if there was kind mismatch.
|
||||
///
|
||||
/// Returns `Some` of the lowered generic arg. `None` if the provided arg is a lifetime.
|
||||
pub(crate) fn generic_arg_to_chalk<'a, T>(
|
||||
db: &dyn HirDatabase,
|
||||
kind_id: GenericParamId,
|
||||
@ -2177,7 +2174,7 @@ pub(crate) fn generic_arg_to_chalk<'a, T>(
|
||||
for_type: impl FnOnce(&mut T, &TypeRef) -> Ty + 'a,
|
||||
for_const: impl FnOnce(&mut T, &ConstRef, Ty) -> Const + 'a,
|
||||
for_lifetime: impl FnOnce(&mut T, &LifetimeRef) -> Lifetime + 'a,
|
||||
) -> Option<crate::GenericArg> {
|
||||
) -> crate::GenericArg {
|
||||
let kind = match kind_id {
|
||||
GenericParamId::TypeParamId(_) => ParamKind::Type,
|
||||
GenericParamId::ConstParamId(id) => {
|
||||
@ -2186,7 +2183,7 @@ pub(crate) fn generic_arg_to_chalk<'a, T>(
|
||||
}
|
||||
GenericParamId::LifetimeParamId(_) => ParamKind::Lifetime,
|
||||
};
|
||||
Some(match (arg, kind) {
|
||||
match (arg, kind) {
|
||||
(GenericArg::Type(type_ref), ParamKind::Type) => for_type(this, type_ref).cast(Interner),
|
||||
(GenericArg::Const(c), ParamKind::Const(c_ty)) => for_const(this, c, c_ty).cast(Interner),
|
||||
(GenericArg::Lifetime(lifetime_ref), ParamKind::Lifetime) => {
|
||||
@ -2199,11 +2196,12 @@ pub(crate) fn generic_arg_to_chalk<'a, T>(
|
||||
// as types. Maybe here is not the best place to do it, but
|
||||
// it works.
|
||||
if let TypeRef::Path(p) = t {
|
||||
let p = p.mod_path()?;
|
||||
if p.kind == PathKind::Plain {
|
||||
if let [n] = p.segments() {
|
||||
let c = ConstRef::Path(n.clone());
|
||||
return Some(for_const(this, &c, c_ty).cast(Interner));
|
||||
if let Some(p) = p.mod_path() {
|
||||
if p.kind == PathKind::Plain {
|
||||
if let [n] = p.segments() {
|
||||
let c = ConstRef::Path(n.clone());
|
||||
return for_const(this, &c, c_ty).cast(Interner);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2212,17 +2210,17 @@ pub(crate) fn generic_arg_to_chalk<'a, T>(
|
||||
(GenericArg::Lifetime(_), ParamKind::Const(c_ty)) => unknown_const_as_generic(c_ty),
|
||||
(GenericArg::Type(_), ParamKind::Lifetime) => error_lifetime().cast(Interner),
|
||||
(GenericArg::Const(_), ParamKind::Lifetime) => error_lifetime().cast(Interner),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn const_or_path_to_chalk(
|
||||
pub(crate) fn const_or_path_to_chalk<'g>(
|
||||
db: &dyn HirDatabase,
|
||||
resolver: &Resolver,
|
||||
owner: TypeOwnerId,
|
||||
expected_ty: Ty,
|
||||
value: &ConstRef,
|
||||
mode: ParamLoweringMode,
|
||||
args: impl FnOnce() -> Option<Generics>,
|
||||
args: impl FnOnce() -> Option<&'g Generics>,
|
||||
debruijn: DebruijnIndex,
|
||||
) -> Const {
|
||||
match value {
|
||||
|
@ -28,6 +28,7 @@
|
||||
db::{HirDatabase, InternedClosure},
|
||||
display::HirDisplay,
|
||||
error_lifetime,
|
||||
generics::generics,
|
||||
infer::{CaptureKind, CapturedItem, TypeMismatch},
|
||||
inhabitedness::is_ty_uninhabited_from,
|
||||
layout::LayoutError,
|
||||
@ -42,7 +43,7 @@
|
||||
},
|
||||
static_lifetime,
|
||||
traits::FnTrait,
|
||||
utils::{generics, ClosureSubst},
|
||||
utils::ClosureSubst,
|
||||
Adjust, Adjustment, AutoBorrow, CallableDefId, TyBuilder, TyExt,
|
||||
};
|
||||
|
||||
|
@ -21,8 +21,8 @@
|
||||
consteval::{intern_const_scalar, unknown_const},
|
||||
db::{HirDatabase, InternedClosure},
|
||||
from_placeholder_idx,
|
||||
generics::{generics, Generics},
|
||||
infer::normalize,
|
||||
utils::{generics, Generics},
|
||||
ClosureId, Const, Interner, ProjectionTy, Substitution, TraitEnvironment, Ty, TyKind,
|
||||
};
|
||||
|
||||
|
@ -5,25 +5,19 @@
|
||||
|
||||
use base_db::CrateId;
|
||||
use chalk_ir::{
|
||||
cast::Cast,
|
||||
fold::{FallibleTypeFolder, Shift},
|
||||
BoundVar, DebruijnIndex,
|
||||
DebruijnIndex,
|
||||
};
|
||||
use hir_def::{
|
||||
db::DefDatabase,
|
||||
generics::{
|
||||
GenericParamDataRef, GenericParams, LifetimeParamData, TypeOrConstParamData,
|
||||
TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
|
||||
},
|
||||
generics::{WherePredicate, WherePredicateTypeTarget},
|
||||
lang_item::LangItem,
|
||||
resolver::{HasResolver, TypeNs},
|
||||
type_ref::{TraitBoundModifier, TypeRef},
|
||||
ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, GenericParamId, ItemContainerId,
|
||||
LifetimeParamId, Lookup, OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId,
|
||||
TypeParamId,
|
||||
EnumId, EnumVariantId, FunctionId, Lookup, OpaqueInternableThing, TraitId, TypeAliasId,
|
||||
TypeOrConstParamId,
|
||||
};
|
||||
use hir_expand::name::Name;
|
||||
use intern::Interned;
|
||||
use rustc_abi::TargetDataLayout;
|
||||
use rustc_hash::FxHashSet;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
@ -161,7 +155,7 @@ fn next(&mut self) -> Option<Self::Item> {
|
||||
fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(TraitId)) {
|
||||
let resolver = trait_.resolver(db);
|
||||
let generic_params = db.generic_params(trait_.into());
|
||||
let trait_self = generic_params.find_trait_self_param();
|
||||
let trait_self = generic_params.trait_self_param();
|
||||
generic_params
|
||||
.where_predicates
|
||||
.iter()
|
||||
@ -194,7 +188,7 @@ fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(Tra
|
||||
|
||||
fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef, cb: impl FnMut(TraitRef)) {
|
||||
let generic_params = db.generic_params(trait_ref.hir_trait_id().into());
|
||||
let trait_self = match generic_params.find_trait_self_param() {
|
||||
let trait_self = match generic_params.trait_self_param() {
|
||||
Some(p) => TypeOrConstParamId { parent: trait_ref.hir_trait_id().into(), local_id: p },
|
||||
None => return,
|
||||
};
|
||||
@ -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:
|
||||
/// - 0: the function signature, encoded as a function pointer type
|
||||
/// - 1..n: generics of the parent
|
||||
@ -262,275 +251,6 @@ pub(crate) fn sig_ty(&self) -> &'a Ty {
|
||||
}
|
||||
}
|
||||
|
||||
#[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 {
|
||||
let data = db.function_data(func);
|
||||
if data.has_unsafe_kw() {
|
||||
|
Loading…
Reference in New Issue
Block a user