mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 20:42:04 +00:00
internal: Simplify hir_ty::utils
This commit is contained in:
parent
7a0ab1358c
commit
9153f17382
4 changed files with 48 additions and 69 deletions
|
@ -28,7 +28,7 @@ pub struct FunctionData {
|
||||||
pub attrs: Attrs,
|
pub attrs: Attrs,
|
||||||
pub visibility: RawVisibility,
|
pub visibility: RawVisibility,
|
||||||
pub abi: Option<Interned<str>>,
|
pub abi: Option<Interned<str>>,
|
||||||
pub legacy_const_generics_indices: Vec<u32>,
|
pub legacy_const_generics_indices: Box<[u32]>,
|
||||||
flags: FnFlags,
|
flags: FnFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ impl FunctionData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_rustc_legacy_const_generics(tt: &tt::Subtree) -> Vec<u32> {
|
fn parse_rustc_legacy_const_generics(tt: &tt::Subtree) -> Box<[u32]> {
|
||||||
let mut indices = Vec::new();
|
let mut indices = Vec::new();
|
||||||
for args in tt.token_trees.chunks(2) {
|
for args in tt.token_trees.chunks(2) {
|
||||||
match &args[0] {
|
match &args[0] {
|
||||||
|
@ -150,7 +150,7 @@ fn parse_rustc_legacy_const_generics(tt: &tt::Subtree) -> Vec<u32> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
indices
|
indices.into_boxed_slice()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
|
|
@ -356,8 +356,8 @@ impl From<TypeParamId> for TypeOrConstParamId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
||||||
/// A TypeOrConstParamId with an invariant that it actually belongs to a const
|
/// A TypeOrConstParamId with an invariant that it actually belongs to a const
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct ConstParamId(TypeOrConstParamId);
|
pub struct ConstParamId(TypeOrConstParamId);
|
||||||
|
|
||||||
impl ConstParamId {
|
impl ConstParamId {
|
||||||
|
|
|
@ -1211,28 +1211,28 @@ impl<'a> InferenceContext<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the argument indices to skip.
|
/// Returns the argument indices to skip.
|
||||||
fn check_legacy_const_generics(&mut self, callee: Ty, args: &[ExprId]) -> Vec<u32> {
|
fn check_legacy_const_generics(&mut self, callee: Ty, args: &[ExprId]) -> Box<[u32]> {
|
||||||
let (func, subst) = match callee.kind(Interner) {
|
let (func, subst) = match callee.kind(Interner) {
|
||||||
TyKind::FnDef(fn_id, subst) => {
|
TyKind::FnDef(fn_id, subst) => {
|
||||||
let callable = CallableDefId::from_chalk(self.db, *fn_id);
|
let callable = CallableDefId::from_chalk(self.db, *fn_id);
|
||||||
let func = match callable {
|
let func = match callable {
|
||||||
CallableDefId::FunctionId(f) => f,
|
CallableDefId::FunctionId(f) => f,
|
||||||
_ => return Vec::new(),
|
_ => return Default::default(),
|
||||||
};
|
};
|
||||||
(func, subst)
|
(func, subst)
|
||||||
}
|
}
|
||||||
_ => return Vec::new(),
|
_ => return Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let data = self.db.function_data(func);
|
let data = self.db.function_data(func);
|
||||||
if data.legacy_const_generics_indices.is_empty() {
|
if data.legacy_const_generics_indices.is_empty() {
|
||||||
return Vec::new();
|
return Default::default();
|
||||||
}
|
}
|
||||||
|
|
||||||
// only use legacy const generics if the param count matches with them
|
// only use legacy const generics if the param count matches with them
|
||||||
if data.params.len() + data.legacy_const_generics_indices.len() != args.len() {
|
if data.params.len() + data.legacy_const_generics_indices.len() != args.len() {
|
||||||
if args.len() <= data.params.len() {
|
if args.len() <= data.params.len() {
|
||||||
return Vec::new();
|
return Default::default();
|
||||||
} else {
|
} else {
|
||||||
// there are more parameters than there should be without legacy
|
// there are more parameters than there should be without legacy
|
||||||
// const params; use them
|
// const params; use them
|
||||||
|
|
|
@ -177,21 +177,19 @@ 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)));
|
let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def)));
|
||||||
if parent_generics.is_some() && matches!(def, GenericDefId::TypeAliasId(_)) {
|
if parent_generics.is_some() && matches!(def, GenericDefId::TypeAliasId(_)) {
|
||||||
let params = db.generic_params(def);
|
let params = db.generic_params(def);
|
||||||
if params
|
let has_consts =
|
||||||
.type_or_consts
|
params.iter().any(|(_, x)| matches!(x, TypeOrConstParamData::ConstParamData(_)));
|
||||||
.iter()
|
return if has_consts {
|
||||||
.any(|(_, x)| matches!(x, TypeOrConstParamData::ConstParamData(_)))
|
|
||||||
{
|
|
||||||
// XXX: treat const generic associated types as not existing to avoid crashes (#11769)
|
// XXX: treat const generic associated types as not existing to avoid crashes (#11769)
|
||||||
//
|
//
|
||||||
// Chalk expects the inner associated type's parameters to come
|
// Chalk expects the inner associated type's parameters to come
|
||||||
// *before*, not after the trait's generics as we've always done it.
|
// *before*, not after the trait's generics as we've always done it.
|
||||||
// Adapting to this requires a larger refactoring
|
// Adapting to this requires a larger refactoring
|
||||||
cov_mark::hit!(ignore_gats);
|
cov_mark::hit!(ignore_gats);
|
||||||
return Generics { def, params: Interned::new(Default::default()), parent_generics };
|
Generics { def, params: Interned::new(Default::default()), parent_generics }
|
||||||
} else {
|
} else {
|
||||||
return Generics { def, params, parent_generics };
|
Generics { def, params, parent_generics }
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
Generics { def, params: db.generic_params(def), parent_generics }
|
Generics { def, params: db.generic_params(def), parent_generics }
|
||||||
}
|
}
|
||||||
|
@ -219,68 +217,46 @@ impl Generics {
|
||||||
pub(crate) fn iter<'a>(
|
pub(crate) fn iter<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
|
) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
|
||||||
self.parent_generics
|
let to_toc_id = |it: &'a Generics| {
|
||||||
.as_ref()
|
move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p)
|
||||||
|
};
|
||||||
|
self.parent_generics()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flat_map(|it| {
|
.flat_map(move |it| it.params.iter().map(to_toc_id(it)))
|
||||||
it.params
|
.chain(self.params.iter().map(to_toc_id(self)))
|
||||||
.iter()
|
|
||||||
.map(move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p))
|
|
||||||
})
|
|
||||||
.chain(
|
|
||||||
self.params.iter().map(move |(local_id, p)| {
|
|
||||||
(TypeOrConstParamId { parent: self.def, local_id }, p)
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterator over types and const params of parent.
|
/// Iterator over types and const params of parent.
|
||||||
pub(crate) fn iter_parent<'a>(
|
pub(crate) fn iter_parent<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
) -> impl Iterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
|
) -> impl Iterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
|
||||||
self.parent_generics.as_ref().into_iter().flat_map(|it| {
|
self.parent_generics().into_iter().flat_map(|it| {
|
||||||
it.params
|
let to_toc_id =
|
||||||
.type_or_consts
|
move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p);
|
||||||
.iter()
|
it.params.iter().map(to_toc_id)
|
||||||
.map(move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p))
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn len(&self) -> usize {
|
pub(crate) fn len(&self) -> usize {
|
||||||
self.len_split().0
|
let parent = self.parent_generics().map_or(0, Generics::len);
|
||||||
}
|
|
||||||
|
|
||||||
/// (total, parents, child)
|
|
||||||
pub(crate) fn len_split(&self) -> (usize, usize, usize) {
|
|
||||||
let parent = self.parent_generics.as_ref().map_or(0, |p| p.len());
|
|
||||||
let child = self.params.type_or_consts.len();
|
let child = self.params.type_or_consts.len();
|
||||||
(parent + child, parent, child)
|
parent + child
|
||||||
}
|
}
|
||||||
|
|
||||||
/// (parent total, self param, type param list, const param list, impl trait)
|
/// (parent total, self param, type param list, const param list, impl trait)
|
||||||
pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize, usize) {
|
pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize, usize) {
|
||||||
let parent = self.parent_generics.as_ref().map_or(0, |p| p.len());
|
let ty_iter = || self.params.iter().filter_map(|x| x.1.type_param());
|
||||||
let self_params = self
|
|
||||||
.params
|
let self_params =
|
||||||
.iter()
|
ty_iter().filter(|p| p.provenance == TypeParamProvenance::TraitSelf).count();
|
||||||
.filter_map(|x| x.1.type_param())
|
let type_params =
|
||||||
.filter(|p| p.provenance == TypeParamProvenance::TraitSelf)
|
ty_iter().filter(|p| p.provenance == TypeParamProvenance::TypeParamList).count();
|
||||||
.count();
|
let impl_trait_params =
|
||||||
let type_params = self
|
ty_iter().filter(|p| p.provenance == TypeParamProvenance::ArgumentImplTrait).count();
|
||||||
.params
|
|
||||||
.type_or_consts
|
|
||||||
.iter()
|
|
||||||
.filter_map(|x| x.1.type_param())
|
|
||||||
.filter(|p| p.provenance == TypeParamProvenance::TypeParamList)
|
|
||||||
.count();
|
|
||||||
let const_params = self.params.iter().filter_map(|x| x.1.const_param()).count();
|
let const_params = self.params.iter().filter_map(|x| x.1.const_param()).count();
|
||||||
let impl_trait_params = self
|
|
||||||
.params
|
let parent_len = self.parent_generics().map_or(0, Generics::len);
|
||||||
.iter()
|
(parent_len, self_params, type_params, const_params, impl_trait_params)
|
||||||
.filter_map(|x| x.1.type_param())
|
|
||||||
.filter(|p| p.provenance == TypeParamProvenance::ArgumentImplTrait)
|
|
||||||
.count();
|
|
||||||
(parent, self_params, type_params, const_params, impl_trait_params)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn param_idx(&self, param: TypeOrConstParamId) -> Option<usize> {
|
pub(crate) fn param_idx(&self, param: TypeOrConstParamId) -> Option<usize> {
|
||||||
|
@ -291,18 +267,21 @@ impl Generics {
|
||||||
if param.parent == self.def {
|
if param.parent == self.def {
|
||||||
let (idx, (_local_id, data)) = self
|
let (idx, (_local_id, data)) = self
|
||||||
.params
|
.params
|
||||||
.type_or_consts
|
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.find(|(_, (idx, _))| *idx == param.local_id)
|
.find(|(_, (idx, _))| *idx == param.local_id)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let (_total, parent_len, _child) = self.len_split();
|
let parent_len = self.parent_generics().map_or(0, Generics::len);
|
||||||
Some((parent_len + idx, data))
|
Some((parent_len + idx, data))
|
||||||
} else {
|
} else {
|
||||||
self.parent_generics.as_ref().and_then(|g| g.find_param(param))
|
self.parent_generics().and_then(|g| g.find_param(param))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parent_generics(&self) -> Option<&Generics> {
|
||||||
|
self.parent_generics.as_ref().map(|it| &**it)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a Substitution that replaces each parameter by a bound variable.
|
/// Returns a Substitution that replaces each parameter by a bound variable.
|
||||||
pub(crate) fn bound_vars_subst(
|
pub(crate) fn bound_vars_subst(
|
||||||
&self,
|
&self,
|
||||||
|
@ -377,10 +356,10 @@ pub fn is_fn_unsafe_to_call(db: &dyn HirDatabase, func: FunctionId) -> bool {
|
||||||
// Function in an `extern` block are always unsafe to call, except when it has
|
// Function in an `extern` block are always unsafe to call, except when it has
|
||||||
// `"rust-intrinsic"` ABI there are a few exceptions.
|
// `"rust-intrinsic"` ABI there are a few exceptions.
|
||||||
let id = block.lookup(db.upcast()).id;
|
let id = block.lookup(db.upcast()).id;
|
||||||
match id.item_tree(db.upcast())[id.value].abi.as_deref() {
|
!matches!(
|
||||||
Some("rust-intrinsic") => is_intrinsic_fn_unsafe(&data.name),
|
id.item_tree(db.upcast())[id.value].abi.as_deref(),
|
||||||
_ => true,
|
Some("rust-intrinsic") if !is_intrinsic_fn_unsafe(&data.name)
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue