diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs index 3ef10297241..f2d8318f7d7 100644 --- a/crates/hir-def/src/data.rs +++ b/crates/hir-def/src/data.rs @@ -28,7 +28,7 @@ pub struct FunctionData { pub attrs: Attrs, pub visibility: RawVisibility, pub abi: Option>, - pub legacy_const_generics_indices: Vec, + pub legacy_const_generics_indices: Box<[u32]>, flags: FnFlags, } @@ -131,7 +131,7 @@ pub fn is_varargs(&self) -> bool { } } -fn parse_rustc_legacy_const_generics(tt: &tt::Subtree) -> Vec { +fn parse_rustc_legacy_const_generics(tt: &tt::Subtree) -> Box<[u32]> { let mut indices = Vec::new(); for args in tt.token_trees.chunks(2) { match &args[0] { @@ -150,7 +150,7 @@ fn parse_rustc_legacy_const_generics(tt: &tt::Subtree) -> Vec { } } - indices + indices.into_boxed_slice() } #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index 974a2ab8f25..4431d1b3c81 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -356,8 +356,8 @@ fn from(x: TypeParamId) -> Self { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] /// A TypeOrConstParamId with an invariant that it actually belongs to a const +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ConstParamId(TypeOrConstParamId); impl ConstParamId { diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index 2e645bf52ba..8be236421fb 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -1211,28 +1211,28 @@ fn register_obligations_for_call(&mut self, callable_ty: &Ty) { } /// Returns the argument indices to skip. - fn check_legacy_const_generics(&mut self, callee: Ty, args: &[ExprId]) -> Vec { + fn check_legacy_const_generics(&mut self, callee: Ty, args: &[ExprId]) -> Box<[u32]> { let (func, subst) = match callee.kind(Interner) { TyKind::FnDef(fn_id, subst) => { let callable = CallableDefId::from_chalk(self.db, *fn_id); let func = match callable { CallableDefId::FunctionId(f) => f, - _ => return Vec::new(), + _ => return Default::default(), }; (func, subst) } - _ => return Vec::new(), + _ => return Default::default(), }; let data = self.db.function_data(func); 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 if data.params.len() + data.legacy_const_generics_indices.len() != args.len() { if args.len() <= data.params.len() { - return Vec::new(); + return Default::default(); } else { // there are more parameters than there should be without legacy // const params; use them diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs index fb39e6095c0..e608f857741 100644 --- a/crates/hir-ty/src/utils.rs +++ b/crates/hir-ty/src/utils.rs @@ -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))); if parent_generics.is_some() && matches!(def, GenericDefId::TypeAliasId(_)) { let params = db.generic_params(def); - if params - .type_or_consts - .iter() - .any(|(_, x)| matches!(x, TypeOrConstParamData::ConstParamData(_))) - { + let has_consts = + params.iter().any(|(_, x)| matches!(x, TypeOrConstParamData::ConstParamData(_))); + return if has_consts { // XXX: treat const generic associated types as not existing to avoid crashes (#11769) // // Chalk expects the inner associated type's parameters to come // *before*, not after the trait's generics as we've always done it. // Adapting to this requires a larger refactoring 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 { - return Generics { def, params, parent_generics }; - } + Generics { def, params, parent_generics } + }; } Generics { def, params: db.generic_params(def), parent_generics } } @@ -219,68 +217,46 @@ pub(crate) fn iter_id<'a>( pub(crate) fn iter<'a>( &'a self, ) -> impl DoubleEndedIterator + 'a { - self.parent_generics - .as_ref() + let to_toc_id = |it: &'a Generics| { + move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p) + }; + self.parent_generics() .into_iter() - .flat_map(|it| { - it.params - .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) - }), - ) + .flat_map(move |it| it.params.iter().map(to_toc_id(it))) + .chain(self.params.iter().map(to_toc_id(self))) } /// Iterator over types and const params of parent. pub(crate) fn iter_parent<'a>( &'a self, ) -> impl Iterator + 'a { - self.parent_generics.as_ref().into_iter().flat_map(|it| { - it.params - .type_or_consts - .iter() - .map(move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p)) + self.parent_generics().into_iter().flat_map(|it| { + let to_toc_id = + move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p); + it.params.iter().map(to_toc_id) }) } pub(crate) fn len(&self) -> usize { - self.len_split().0 - } - - /// (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 parent = self.parent_generics().map_or(0, Generics::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) 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 self_params = self - .params - .iter() - .filter_map(|x| x.1.type_param()) - .filter(|p| p.provenance == TypeParamProvenance::TraitSelf) - .count(); - let type_params = self - .params - .type_or_consts - .iter() - .filter_map(|x| x.1.type_param()) - .filter(|p| p.provenance == TypeParamProvenance::TypeParamList) - .count(); + let ty_iter = || self.params.iter().filter_map(|x| x.1.type_param()); + + let self_params = + ty_iter().filter(|p| p.provenance == TypeParamProvenance::TraitSelf).count(); + let type_params = + ty_iter().filter(|p| p.provenance == TypeParamProvenance::TypeParamList).count(); + let impl_trait_params = + ty_iter().filter(|p| p.provenance == TypeParamProvenance::ArgumentImplTrait).count(); let const_params = self.params.iter().filter_map(|x| x.1.const_param()).count(); - let impl_trait_params = self - .params - .iter() - .filter_map(|x| x.1.type_param()) - .filter(|p| p.provenance == TypeParamProvenance::ArgumentImplTrait) - .count(); - (parent, self_params, type_params, const_params, impl_trait_params) + + let parent_len = self.parent_generics().map_or(0, Generics::len); + (parent_len, self_params, type_params, const_params, impl_trait_params) } pub(crate) fn param_idx(&self, param: TypeOrConstParamId) -> Option { @@ -291,18 +267,21 @@ fn find_param(&self, param: TypeOrConstParamId) -> Option<(usize, &TypeOrConstPa if param.parent == self.def { let (idx, (_local_id, data)) = self .params - .type_or_consts .iter() .enumerate() .find(|(_, (idx, _))| *idx == param.local_id) .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)) } 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. pub(crate) fn bound_vars_subst( &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 // `"rust-intrinsic"` ABI there are a few exceptions. let id = block.lookup(db.upcast()).id; - match id.item_tree(db.upcast())[id.value].abi.as_deref() { - Some("rust-intrinsic") => is_intrinsic_fn_unsafe(&data.name), - _ => true, - } + !matches!( + id.item_tree(db.upcast())[id.value].abi.as_deref(), + Some("rust-intrinsic") if !is_intrinsic_fn_unsafe(&data.name) + ) } _ => false, }