internal: Simplify hir_ty::utils

This commit is contained in:
Lukas Wirth 2022-06-12 16:07:08 +02:00
parent 7a0ab1358c
commit 9153f17382
4 changed files with 48 additions and 69 deletions

View file

@ -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)]

View file

@ -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 {

View file

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

View file

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