Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/data.rs')
| -rw-r--r-- | crates/hir-def/src/data.rs | 354 |
1 files changed, 16 insertions, 338 deletions
diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs index 9c87dc31db..1a6bed6cab 100644 --- a/crates/hir-def/src/data.rs +++ b/crates/hir-def/src/data.rs @@ -3,33 +3,20 @@ pub mod adt; use base_db::Crate; -use hir_expand::{ - name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind, -}; +use hir_expand::name::Name; use intern::{sym, Symbol}; use la_arena::{Idx, RawIdx}; -use smallvec::SmallVec; -use syntax::{ast, Parse}; use triomphe::Arc; -use tt::iter::TtElement; use crate::{ db::DefDatabase, - expander::{Expander, Mark}, - item_tree::{self, AssocItem, FnFlags, ItemTree, ItemTreeId, MacroCall, ModItem, TreeId}, - macro_call_as_call_id, - nameres::{ - attr_resolution::ResolvedAttr, - diagnostics::{DefDiagnostic, DefDiagnostics}, - proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroKind}, - DefMap, LocalDefMap, MacroSubNs, - }, + item_tree::{self, FnFlags, ModItem}, + nameres::proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroKind}, path::ImportAlias, type_ref::{TraitRef, TypeBound, TypeRefId, TypesMap}, visibility::RawVisibility, - AssocItemId, AstIdWithPath, ConstId, ConstLoc, ExternCrateId, FunctionId, FunctionLoc, - HasModule, ImplId, Intern, ItemContainerId, ItemLoc, Lookup, Macro2Id, MacroRulesId, ModuleId, - ProcMacroId, StaticId, TraitAliasId, TraitId, TypeAliasId, TypeAliasLoc, + ConstId, ExternCrateId, FunctionId, HasModule, ImplId, ItemContainerId, ItemLoc, Lookup, + Macro2Id, MacroRulesId, ProcMacroId, StaticId, TraitAliasId, TraitId, TypeAliasId, }; #[derive(Debug, Clone, PartialEq, Eq)] @@ -85,13 +72,6 @@ impl FunctionData { } let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()); - let legacy_const_generics_indices = attrs - .by_key(&sym::rustc_legacy_const_generics) - .tt_values() - .next() - .map(parse_rustc_legacy_const_generics) - .filter(|it| !it.is_empty()) - .map(Box::new); let rustc_allow_incoherent_impl = attrs.by_key(&sym::rustc_allow_incoherent_impl).exists(); if flags.contains(FnFlags::HAS_UNSAFE_KW) && attrs.by_key(&sym::rustc_deprecated_safe_2024).exists() @@ -118,7 +98,7 @@ impl FunctionData { ret_type: func.ret_type, visibility, abi: func.abi.clone(), - legacy_const_generics_indices, + legacy_const_generics_indices: attrs.rustc_legacy_const_generics(), types_map: func.types_map.clone(), flags, rustc_allow_incoherent_impl, @@ -168,29 +148,6 @@ impl FunctionData { } } -fn parse_rustc_legacy_const_generics(tt: &crate::tt::TopSubtree) -> Box<[u32]> { - let mut indices = Vec::new(); - let mut iter = tt.iter(); - while let (Some(first), second) = (iter.next(), iter.next()) { - match first { - TtElement::Leaf(tt::Leaf::Literal(lit)) => match lit.symbol.as_str().parse() { - Ok(index) => indices.push(index), - Err(_) => break, - }, - _ => break, - } - - if let Some(comma) = second { - match comma { - TtElement::Leaf(tt::Leaf::Punct(punct)) if punct.char == ',' => {} - _ => break, - } - } - } - - indices.into_boxed_slice() -} - #[derive(Debug, Clone, PartialEq, Eq)] pub struct TypeAliasData { pub name: Name, @@ -256,23 +213,13 @@ bitflags::bitflags! { #[derive(Debug, Clone, PartialEq, Eq)] pub struct TraitData { pub name: Name, - pub items: Box<[(Name, AssocItemId)]>, pub flags: TraitFlags, pub visibility: RawVisibility, - // box it as the vec is usually empty anyways - pub macro_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>, } impl TraitData { #[inline] pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> { - db.trait_data_with_diagnostics(tr).0 - } - - pub(crate) fn trait_data_with_diagnostics_query( - db: &dyn DefDatabase, - tr: TraitId, - ) -> (Arc<TraitData>, DefDiagnostics) { let ItemLoc { container: module_id, id: tree_id } = tr.lookup(db); let item_tree = tree_id.item_tree(db); let tr_def = &item_tree[tree_id.value]; @@ -317,40 +264,7 @@ impl TraitData { flags |= TraitFlags::SKIP_BOXED_SLICE_DURING_METHOD_DISPATCH; } - let mut collector = - AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::TraitId(tr)); - collector.collect(&item_tree, tree_id.tree_id(), &tr_def.items); - let (items, macro_calls, diagnostics) = collector.finish(); - - ( - Arc::new(TraitData { name, macro_calls, items, visibility, flags }), - DefDiagnostics::new(diagnostics), - ) - } - - pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ { - self.items.iter().filter_map(|(_name, item)| match item { - AssocItemId::TypeAliasId(t) => Some(*t), - _ => None, - }) - } - - pub fn associated_type_by_name(&self, name: &Name) -> Option<TypeAliasId> { - self.items.iter().find_map(|(item_name, item)| match item { - AssocItemId::TypeAliasId(t) if item_name == name => Some(*t), - _ => None, - }) - } - - pub fn method_by_name(&self, name: &Name) -> Option<FunctionId> { - self.items.iter().find_map(|(item_name, item)| match item { - AssocItemId::FunctionId(t) if item_name == name => Some(*t), - _ => None, - }) - } - - pub fn attribute_calls(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ { - self.macro_calls.iter().flat_map(|it| it.iter()).copied() + Arc::new(TraitData { name, visibility, flags }) } } @@ -375,26 +289,16 @@ impl TraitAliasData { pub struct ImplData { pub target_trait: Option<TraitRef>, pub self_ty: TypeRefId, - pub items: Box<[(Name, AssocItemId)]>, pub is_negative: bool, pub is_unsafe: bool, - // box it as the vec is usually empty anyways - pub macro_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>, pub types_map: Arc<TypesMap>, } impl ImplData { #[inline] pub(crate) fn impl_data_query(db: &dyn DefDatabase, id: ImplId) -> Arc<ImplData> { - db.impl_data_with_diagnostics(id).0 - } - - pub(crate) fn impl_data_with_diagnostics_query( - db: &dyn DefDatabase, - id: ImplId, - ) -> (Arc<ImplData>, DefDiagnostics) { - let _p = tracing::info_span!("impl_data_with_diagnostics_query").entered(); - let ItemLoc { container: module_id, id: tree_id } = id.lookup(db); + let _p = tracing::info_span!("impl_data_query").entered(); + let ItemLoc { id: tree_id, .. } = id.lookup(db); let item_tree = tree_id.item_tree(db); let impl_def = &item_tree[tree_id.value]; @@ -403,28 +307,13 @@ impl ImplData { let is_negative = impl_def.is_negative; let is_unsafe = impl_def.is_unsafe; - let mut collector = - AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::ImplId(id)); - collector.collect(&item_tree, tree_id.tree_id(), &impl_def.items); - - let (items, macro_calls, diagnostics) = collector.finish(); - - ( - Arc::new(ImplData { - target_trait, - self_ty, - items, - is_negative, - is_unsafe, - macro_calls, - types_map: impl_def.types_map.clone(), - }), - DefDiagnostics::new(diagnostics), - ) - } - - pub fn attribute_calls(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ { - self.macro_calls.iter().flat_map(|it| it.iter()).copied() + Arc::new(ImplData { + target_trait, + self_ty, + is_negative, + is_unsafe, + types_map: impl_def.types_map.clone(), + }) } } @@ -628,217 +517,6 @@ impl StaticData { } } -struct AssocItemCollector<'a> { - db: &'a dyn DefDatabase, - module_id: ModuleId, - def_map: Arc<DefMap>, - local_def_map: Arc<LocalDefMap>, - diagnostics: Vec<DefDiagnostic>, - container: ItemContainerId, - expander: Expander, - - items: Vec<(Name, AssocItemId)>, - macro_calls: Vec<(AstId<ast::Item>, MacroCallId)>, -} - -impl<'a> AssocItemCollector<'a> { - fn new( - db: &'a dyn DefDatabase, - module_id: ModuleId, - file_id: HirFileId, - container: ItemContainerId, - ) -> Self { - let (def_map, local_def_map) = module_id.local_def_map(db); - Self { - db, - module_id, - def_map, - local_def_map, - container, - expander: Expander::new(db, file_id, module_id), - items: Vec::new(), - macro_calls: Vec::new(), - diagnostics: Vec::new(), - } - } - - fn finish( - self, - ) -> ( - Box<[(Name, AssocItemId)]>, - Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>, - Vec<DefDiagnostic>, - ) { - ( - self.items.into_boxed_slice(), - if self.macro_calls.is_empty() { None } else { Some(Box::new(self.macro_calls)) }, - self.diagnostics, - ) - } - - fn collect(&mut self, item_tree: &ItemTree, tree_id: TreeId, assoc_items: &[AssocItem]) { - let container = self.container; - self.items.reserve(assoc_items.len()); - - 'items: for &item in assoc_items { - let attrs = item_tree.attrs(self.db, self.module_id.krate, ModItem::from(item).into()); - if !attrs.is_cfg_enabled(self.expander.cfg_options()) { - self.diagnostics.push(DefDiagnostic::unconfigured_code( - self.module_id.local_id, - tree_id, - ModItem::from(item).into(), - attrs.cfg().unwrap(), - self.expander.cfg_options().clone(), - )); - continue; - } - - 'attrs: for attr in &*attrs { - let ast_id = - AstId::new(self.expander.current_file_id(), item.ast_id(item_tree).upcast()); - let ast_id_with_path = AstIdWithPath { path: attr.path.clone(), ast_id }; - - match self.def_map.resolve_attr_macro( - &self.local_def_map, - self.db, - self.module_id.local_id, - ast_id_with_path, - attr, - ) { - Ok(ResolvedAttr::Macro(call_id)) => { - let loc = self.db.lookup_intern_macro_call(call_id); - if let MacroDefKind::ProcMacro(_, exp, _) = loc.def.kind { - // If there's no expander for the proc macro (e.g. the - // proc macro is ignored, or building the proc macro - // crate failed), skip expansion like we would if it was - // disabled. This is analogous to the handling in - // `DefCollector::collect_macros`. - if let Some(err) = exp.as_expand_error(self.module_id.krate) { - self.diagnostics.push(DefDiagnostic::macro_error( - self.module_id.local_id, - ast_id, - (*attr.path).clone(), - err, - )); - continue 'attrs; - } - } - - self.macro_calls.push((ast_id, call_id)); - let res = - self.expander.enter_expand_id::<ast::MacroItems>(self.db, call_id); - self.collect_macro_items(res); - continue 'items; - } - Ok(_) => (), - Err(_) => { - self.diagnostics.push(DefDiagnostic::unresolved_macro_call( - self.module_id.local_id, - MacroCallKind::Attr { - ast_id, - attr_args: None, - invoc_attr_index: attr.id, - }, - attr.path().clone(), - )); - } - } - } - - self.collect_item(item_tree, tree_id, container, item); - } - } - - fn collect_item( - &mut self, - item_tree: &ItemTree, - tree_id: TreeId, - container: ItemContainerId, - item: AssocItem, - ) { - match item { - AssocItem::Function(id) => { - let item = &item_tree[id]; - let def = - FunctionLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db); - self.items.push((item.name.clone(), def.into())); - } - AssocItem::TypeAlias(id) => { - let item = &item_tree[id]; - let def = - TypeAliasLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db); - self.items.push((item.name.clone(), def.into())); - } - AssocItem::Const(id) => { - let item = &item_tree[id]; - let Some(name) = item.name.clone() else { return }; - let def = ConstLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db); - self.items.push((name, def.into())); - } - AssocItem::MacroCall(call) => { - let file_id = self.expander.current_file_id(); - let MacroCall { ast_id, expand_to, ctxt, ref path } = item_tree[call]; - let module = self.expander.module.local_id; - - let resolver = |path: &_| { - self.def_map - .resolve_path( - &self.local_def_map, - self.db, - module, - path, - crate::item_scope::BuiltinShadowMode::Other, - Some(MacroSubNs::Bang), - ) - .0 - .take_macros() - .map(|it| self.db.macro_def(it)) - }; - match macro_call_as_call_id( - self.db.upcast(), - &AstIdWithPath::new(file_id, ast_id, Clone::clone(path)), - ctxt, - expand_to, - self.expander.krate(), - resolver, - ) { - Ok(Some(call_id)) => { - let res = - self.expander.enter_expand_id::<ast::MacroItems>(self.db, call_id); - self.macro_calls.push((InFile::new(file_id, ast_id.upcast()), call_id)); - self.collect_macro_items(res); - } - Ok(None) => (), - Err(_) => { - self.diagnostics.push(DefDiagnostic::unresolved_macro_call( - self.module_id.local_id, - MacroCallKind::FnLike { - ast_id: InFile::new(file_id, ast_id), - expand_to, - eager: None, - }, - Clone::clone(path), - )); - } - } - } - } - } - - fn collect_macro_items(&mut self, res: ExpandResult<Option<(Mark, Parse<ast::MacroItems>)>>) { - let Some((mark, _parse)) = res.value else { return }; - - let tree_id = item_tree::TreeId::new(self.expander.current_file_id(), None); - let item_tree = tree_id.item_tree(self.db); - let iter: SmallVec<[_; 2]> = - item_tree.top_level_items().iter().filter_map(ModItem::as_assoc_item).collect(); - - self.collect(&item_tree, tree_id, &iter); - - self.expander.exit(mark); - } -} - fn trait_vis(db: &dyn DefDatabase, trait_id: TraitId) -> RawVisibility { let ItemLoc { id: tree_id, .. } = trait_id.lookup(db); let item_tree = tree_id.item_tree(db); |