From 12f54eec2745d7e7dca766fd50913d68ebba778d Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 26 Feb 2025 07:40:42 +0100 Subject: [PATCH 1/4] Split assoc items out of `trait_data`/`impl_data` queries --- crates/hir-def/src/data.rs | 321 +------------------ crates/hir-def/src/db.rs | 25 +- crates/hir-def/src/expr_store/pretty.rs | 2 +- crates/hir-def/src/import_map.rs | 6 +- crates/hir-def/src/lang_item.rs | 4 +- crates/hir-def/src/nameres.rs | 1 + crates/hir-def/src/nameres/assoc.rs | 325 ++++++++++++++++++++ crates/hir-ty/src/autoderef.rs | 2 +- crates/hir-ty/src/chalk_db.rs | 12 +- crates/hir-ty/src/diagnostics/expr.rs | 2 +- crates/hir-ty/src/display.rs | 2 +- crates/hir-ty/src/dyn_compatibility.rs | 4 +- crates/hir-ty/src/infer.rs | 2 +- crates/hir-ty/src/infer/closure.rs | 2 +- crates/hir-ty/src/infer/expr.rs | 8 +- crates/hir-ty/src/infer/mutability.rs | 4 +- crates/hir-ty/src/infer/path.rs | 2 +- crates/hir-ty/src/infer/unify.rs | 2 +- crates/hir-ty/src/lib.rs | 2 +- crates/hir-ty/src/lower.rs | 4 +- crates/hir-ty/src/lower/path.rs | 2 +- crates/hir-ty/src/method_resolution.rs | 24 +- crates/hir-ty/src/mir/eval.rs | 12 +- crates/hir-ty/src/mir/eval/shim.rs | 2 +- crates/hir-ty/src/mir/lower/as_place.rs | 4 +- crates/hir-ty/src/tests.rs | 4 +- crates/hir-ty/src/utils.rs | 2 +- crates/hir/src/attrs.rs | 2 +- crates/hir/src/db.rs | 4 +- crates/hir/src/lib.rs | 37 ++- crates/hir/src/semantics/child_by_source.rs | 4 +- crates/hir/src/source_analyzer.rs | 6 +- crates/hir/src/symbols.rs | 4 +- crates/ide-db/src/apply_change.rs | 4 +- 34 files changed, 446 insertions(+), 397 deletions(-) create mode 100644 crates/hir-def/src/nameres/assoc.rs diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs index 9c87dc31dba9..8a1f07c92eff 100644 --- a/crates/hir-def/src/data.rs +++ b/crates/hir-def/src/data.rs @@ -3,33 +3,21 @@ 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)] @@ -256,23 +244,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, MacroCallId)>>>, } impl TraitData { #[inline] pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc { - db.trait_data_with_diagnostics(tr).0 - } - - pub(crate) fn trait_data_with_diagnostics_query( - db: &dyn DefDatabase, - tr: TraitId, - ) -> (Arc, 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 +295,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 + '_ { - 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 { - 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 { - 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, MacroCallId)> + '_ { - self.macro_calls.iter().flat_map(|it| it.iter()).copied() + Arc::new(TraitData { name, visibility, flags }) } } @@ -375,26 +320,16 @@ impl TraitAliasData { pub struct ImplData { pub target_trait: Option, 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, MacroCallId)>>>, pub types_map: Arc, } impl ImplData { #[inline] pub(crate) fn impl_data_query(db: &dyn DefDatabase, id: ImplId) -> Arc { - db.impl_data_with_diagnostics(id).0 - } - - pub(crate) fn impl_data_with_diagnostics_query( - db: &dyn DefDatabase, - id: ImplId, - ) -> (Arc, 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 +338,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, 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 +548,6 @@ impl StaticData { } } -struct AssocItemCollector<'a> { - db: &'a dyn DefDatabase, - module_id: ModuleId, - def_map: Arc, - local_def_map: Arc, - diagnostics: Vec, - container: ItemContainerId, - expander: Expander, - - items: Vec<(Name, AssocItemId)>, - macro_calls: Vec<(AstId, 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, MacroCallId)>>>, - Vec, - ) { - ( - 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::(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::(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)>>) { - 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); diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs index b6707af61811..ff3305653807 100644 --- a/crates/hir-def/src/db.rs +++ b/crates/hir-def/src/db.rs @@ -20,7 +20,11 @@ use crate::{ import_map::ImportMap, item_tree::{AttrOwner, ItemTree, ItemTreeSourceMaps}, lang_item::{self, LangItem, LangItemTarget, LangItems}, - nameres::{diagnostics::DefDiagnostics, DefMap, LocalDefMap}, + nameres::{ + assoc::{ImplItems, TraitItems}, + diagnostics::DefDiagnostics, + DefMap, LocalDefMap, + }, tt, type_ref::TypesSourceMap, visibility::{self, Visibility}, @@ -176,19 +180,26 @@ pub trait DefDatabase: #[salsa::transparent] #[salsa::invoke_actual(VariantData::variant_data)] fn variant_data(&self, id: VariantId) -> Arc; - #[salsa::transparent] + #[salsa::invoke_actual(ImplData::impl_data_query)] fn impl_data(&self, e: ImplId) -> Arc; - #[salsa::invoke_actual(ImplData::impl_data_with_diagnostics_query)] - fn impl_data_with_diagnostics(&self, e: ImplId) -> (Arc, DefDiagnostics); - #[salsa::transparent] + #[salsa::invoke_actual(ImplItems::impl_items_query)] + fn impl_items(&self, e: ImplId) -> Arc; + + #[salsa::invoke_actual(ImplItems::impl_items_with_diagnostics_query)] + fn impl_items_with_diagnostics(&self, e: ImplId) -> (Arc, DefDiagnostics); + #[salsa::invoke_actual(TraitData::trait_data_query)] fn trait_data(&self, e: TraitId) -> Arc; - #[salsa::invoke_actual(TraitData::trait_data_with_diagnostics_query)] - fn trait_data_with_diagnostics(&self, tr: TraitId) -> (Arc, DefDiagnostics); + #[salsa::transparent] + #[salsa::invoke_actual(TraitItems::trait_items_query)] + fn trait_items(&self, e: TraitId) -> Arc; + + #[salsa::invoke_actual(TraitItems::trait_items_with_diagnostics_query)] + fn trait_items_with_diagnostics(&self, tr: TraitId) -> (Arc, DefDiagnostics); #[salsa::invoke_actual(TraitAliasData::trait_alias_query)] fn trait_alias_data(&self, e: TraitAliasId) -> Arc; diff --git a/crates/hir-def/src/expr_store/pretty.rs b/crates/hir-def/src/expr_store/pretty.rs index 82ad756dc2c6..cc6d200051c3 100644 --- a/crates/hir-def/src/expr_store/pretty.rs +++ b/crates/hir-def/src/expr_store/pretty.rs @@ -82,7 +82,7 @@ pub(super) fn print_body_hir( p.buf.push_str(", "); }); // remove the last ", " in param list - if body.params.len() > 0 { + if !body.params.is_empty() { p.buf.truncate(p.buf.len() - 2); } p.buf.push(')'); diff --git a/crates/hir-def/src/import_map.rs b/crates/hir-def/src/import_map.rs index 1cdc4c025975..9e4479f05b42 100644 --- a/crates/hir-def/src/import_map.rs +++ b/crates/hir-def/src/import_map.rs @@ -222,7 +222,7 @@ impl ImportMap { trait_import_info: &ImportInfo, ) { let _p = tracing::info_span!("collect_trait_assoc_items").entered(); - for &(ref assoc_item_name, item) in &db.trait_data(tr).items { + for &(ref assoc_item_name, item) in &db.trait_items(tr).items { let module_def_id = match item { AssocItemId::FunctionId(f) => ModuleDefId::from(f), AssocItemId::ConstId(c) => ModuleDefId::from(c), @@ -575,8 +575,8 @@ mod tests { let trait_info = dependency_imports.import_info_for(ItemInNs::Types(trait_id.into()))?; - let trait_data = db.trait_data(trait_id); - let (assoc_item_name, _) = trait_data + let trait_items = db.trait_items(trait_id); + let (assoc_item_name, _) = trait_items .items .iter() .find(|(_, assoc_item_id)| &dependency_assoc_item_id == assoc_item_id)?; diff --git a/crates/hir-def/src/lang_item.rs b/crates/hir-def/src/lang_item.rs index 70c28009f4b9..67788576c13b 100644 --- a/crates/hir-def/src/lang_item.rs +++ b/crates/hir-def/src/lang_item.rs @@ -107,7 +107,7 @@ impl LangItems { for (_, module_data) in crate_def_map.modules() { for impl_def in module_data.scope.impls() { lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDef); - for &(_, assoc) in db.impl_data(impl_def).items.iter() { + for &(_, assoc) in db.impl_items(impl_def).items.iter() { match assoc { AssocItemId::FunctionId(f) => { lang_items.collect_lang_item(db, f, LangItemTarget::Function) @@ -124,7 +124,7 @@ impl LangItems { match def { ModuleDefId::TraitId(trait_) => { lang_items.collect_lang_item(db, trait_, LangItemTarget::Trait); - db.trait_data(trait_).items.iter().for_each( + db.trait_items(trait_).items.iter().for_each( |&(_, assoc_id)| match assoc_id { AssocItemId::FunctionId(f) => { lang_items.collect_lang_item(db, f, LangItemTarget::Function); diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index 054c285fa256..a34766ebc1dc 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -47,6 +47,7 @@ //! path and, upon success, we run macro expansion and "collect module" phase on //! the result +pub mod assoc; pub mod attr_resolution; mod collector; pub mod diagnostics; diff --git a/crates/hir-def/src/nameres/assoc.rs b/crates/hir-def/src/nameres/assoc.rs new file mode 100644 index 000000000000..dea6d334f8aa --- /dev/null +++ b/crates/hir-def/src/nameres/assoc.rs @@ -0,0 +1,325 @@ +//! Expansion of associated items + +use hir_expand::{ + name::Name, AstId, ExpandResult, InFile, Intern, Lookup, MacroCallKind, MacroDefKind, +}; +use smallvec::SmallVec; +use span::{HirFileId, MacroCallId}; +use syntax::{ast, Parse}; +use triomphe::Arc; + +use crate::{ + db::DefDatabase, + expander::{Expander, Mark}, + item_tree::{self, AssocItem, ItemTree, ItemTreeId, MacroCall, ModItem, TreeId}, + macro_call_as_call_id, + nameres::{ + attr_resolution::ResolvedAttr, + diagnostics::{DefDiagnostic, DefDiagnostics}, + DefMap, LocalDefMap, MacroSubNs, + }, + AssocItemId, AstIdWithPath, ConstLoc, FunctionId, FunctionLoc, ImplId, ItemContainerId, + ItemLoc, ModuleId, TraitId, TypeAliasId, TypeAliasLoc, +}; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct TraitItems { + pub items: Box<[(Name, AssocItemId)]>, + // box it as the vec is usually empty anyways + pub macro_calls: Option, MacroCallId)>>>, +} + +impl TraitItems { + #[inline] + pub(crate) fn trait_items_query(db: &dyn DefDatabase, tr: TraitId) -> Arc { + db.trait_items_with_diagnostics(tr).0 + } + + pub(crate) fn trait_items_with_diagnostics_query( + db: &dyn DefDatabase, + tr: TraitId, + ) -> (Arc, 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]; + + 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(TraitItems { macro_calls, items }), DefDiagnostics::new(diagnostics)) + } + + pub fn associated_types(&self) -> impl Iterator + '_ { + 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 { + 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 { + 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, MacroCallId)> + '_ { + self.macro_calls.iter().flat_map(|it| it.iter()).copied() + } +} + +#[derive(Debug, PartialEq, Eq)] +pub struct ImplItems { + pub items: Box<[(Name, AssocItemId)]>, + // box it as the vec is usually empty anyways + pub macro_calls: Option, MacroCallId)>>>, +} + +impl ImplItems { + #[inline] + pub(crate) fn impl_items_query(db: &dyn DefDatabase, id: ImplId) -> Arc { + db.impl_items_with_diagnostics(id).0 + } + + pub(crate) fn impl_items_with_diagnostics_query( + db: &dyn DefDatabase, + id: ImplId, + ) -> (Arc, DefDiagnostics) { + let _p = tracing::info_span!("impl_items_with_diagnostics_query").entered(); + let ItemLoc { container: module_id, id: tree_id } = id.lookup(db); + + let item_tree = tree_id.item_tree(db); + let impl_def = &item_tree[tree_id.value]; + 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(ImplItems { items, macro_calls }), DefDiagnostics::new(diagnostics)) + } + + pub fn attribute_calls(&self) -> impl Iterator, MacroCallId)> + '_ { + self.macro_calls.iter().flat_map(|it| it.iter()).copied() + } +} + +struct AssocItemCollector<'a> { + db: &'a dyn DefDatabase, + module_id: ModuleId, + def_map: Arc, + local_def_map: Arc, + diagnostics: Vec, + container: ItemContainerId, + expander: Expander, + + items: Vec<(Name, AssocItemId)>, + macro_calls: Vec<(AstId, 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, MacroCallId)>>>, + Vec, + ) { + ( + 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::(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::(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)>>) { + 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); + } +} diff --git a/crates/hir-ty/src/autoderef.rs b/crates/hir-ty/src/autoderef.rs index 171ba001c4a7..2c27f5e3bbf1 100644 --- a/crates/hir-ty/src/autoderef.rs +++ b/crates/hir-ty/src/autoderef.rs @@ -210,7 +210,7 @@ pub(crate) fn deref_by_trait( }; let trait_id = trait_id()?; let target = db - .trait_data(trait_id) + .trait_items(trait_id) .associated_type_by_name(&Name::new_symbol_root(sym::Target.clone()))?; let projection = { diff --git a/crates/hir-ty/src/chalk_db.rs b/crates/hir-ty/src/chalk_db.rs index 84eb964d564b..e5751a394dae 100644 --- a/crates/hir-ty/src/chalk_db.rs +++ b/crates/hir-ty/src/chalk_db.rs @@ -294,7 +294,7 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { .lang_item(self.krate, LangItem::Future) .and_then(|item| item.as_trait()) .and_then(|trait_| { - let alias = self.db.trait_data(trait_).associated_type_by_name( + let alias = self.db.trait_items(trait_).associated_type_by_name( &Name::new_symbol_root(sym::Output.clone()), )?; Some((trait_, alias)) @@ -684,7 +684,8 @@ pub(crate) fn trait_datum_query( fundamental: trait_data.flags.contains(TraitFlags::IS_FUNDAMENTAL), }; let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars); - let associated_ty_ids = trait_data.associated_types().map(to_assoc_type_id).collect(); + let associated_ty_ids = + db.trait_items(trait_).associated_types().map(to_assoc_type_id).collect(); let trait_datum_bound = rust_ir::TraitDatumBound { where_clauses }; let well_known = db.lang_attr(trait_.into()).and_then(well_known_trait_from_lang_item); let trait_datum = TraitDatum { @@ -856,8 +857,9 @@ fn impl_def_datum(db: &dyn HirDatabase, krate: Crate, impl_id: hir_def::ImplId) let polarity = if negative { rust_ir::Polarity::Negative } else { rust_ir::Polarity::Positive }; let impl_datum_bound = rust_ir::ImplDatumBound { trait_ref, where_clauses }; - let trait_data = db.trait_data(trait_); - let associated_ty_value_ids = impl_data + let trait_data = db.trait_items(trait_); + let associated_ty_value_ids = db + .impl_items(impl_id) .items .iter() .filter_map(|(_, item)| match item { @@ -908,7 +910,7 @@ fn type_alias_associated_ty_value( .0; // we don't return any assoc ty values if the impl'd trait can't be resolved let assoc_ty = db - .trait_data(trait_ref.hir_trait_id()) + .trait_items(trait_ref.hir_trait_id()) .associated_type_by_name(&type_alias_data.name) .expect("assoc ty value should not exist"); // validated when building the impl data as well let (ty, binders) = db.ty(type_alias.into()).into_value_and_skipped_binders(); diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs index 053d1cd41e9f..1035651692ec 100644 --- a/crates/hir-ty/src/diagnostics/expr.rs +++ b/crates/hir-ty/src/diagnostics/expr.rs @@ -492,7 +492,7 @@ impl FilterMapNextChecker { Some(next_function_id), match next_function_id.lookup(db.upcast()).container { ItemContainerId::TraitId(iterator_trait_id) => { - let iterator_trait_items = &db.trait_data(iterator_trait_id).items; + let iterator_trait_items = &db.trait_items(iterator_trait_id).items; iterator_trait_items.iter().find_map(|(name, it)| match it { &AssocItemId::FunctionId(id) if *name == sym::filter_map.clone() => { Some(id) diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index 2ae7e746ba20..be590b6101d6 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -1342,7 +1342,7 @@ impl HirDisplay for Ty { .lang_item(body.module(db.upcast()).krate(), LangItem::Future) .and_then(LangItemTarget::as_trait); let output = future_trait.and_then(|t| { - db.trait_data(t).associated_type_by_name(&Name::new_symbol_root( + db.trait_items(t).associated_type_by_name(&Name::new_symbol_root( sym::Output.clone(), )) }); diff --git a/crates/hir-ty/src/dyn_compatibility.rs b/crates/hir-ty/src/dyn_compatibility.rs index 6a01579bccc9..af16a2499ba0 100644 --- a/crates/hir-ty/src/dyn_compatibility.rs +++ b/crates/hir-ty/src/dyn_compatibility.rs @@ -103,7 +103,7 @@ where // rustc checks for non-lifetime binders here, but we don't support HRTB yet - let trait_data = db.trait_data(trait_); + let trait_data = db.trait_items(trait_); for (_, assoc_item) in &trait_data.items { dyn_compatibility_violation_for_assoc_item(db, trait_, *assoc_item, cb)?; } @@ -166,7 +166,7 @@ fn predicates_reference_self(db: &dyn HirDatabase, trait_: TraitId) -> bool { // Same as the above, `predicates_reference_self` fn bounds_reference_self(db: &dyn HirDatabase, trait_: TraitId) -> bool { - let trait_data = db.trait_data(trait_); + let trait_data = db.trait_items(trait_); trait_data .items .iter() diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index 556091c40461..9a4b7af85d8f 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -1723,7 +1723,7 @@ impl<'a> InferenceContext<'a> { fn resolve_output_on(&self, trait_: TraitId) -> Option { self.db - .trait_data(trait_) + .trait_items(trait_) .associated_type_by_name(&Name::new_symbol_root(sym::Output.clone())) } diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs index 50cac034e493..ef02762c80a5 100644 --- a/crates/hir-ty/src/infer/closure.rs +++ b/crates/hir-ty/src/infer/closure.rs @@ -815,7 +815,7 @@ impl InferenceContext<'_> { { if let Some(deref_fn) = self .db - .trait_data(deref_trait) + .trait_items(deref_trait) .method_by_name(&Name::new_symbol_root(sym::deref_mut.clone())) { break 'b deref_fn == f; diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index 131e98d72965..d0936185957f 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -772,7 +772,7 @@ impl InferenceContext<'_> { if let Some(deref_trait) = self.resolve_lang_trait(LangItem::Deref) { if let Some(deref_fn) = self .db - .trait_data(deref_trait) + .trait_items(deref_trait) .method_by_name(&Name::new_symbol_root(sym::deref.clone())) { // FIXME: this is wrong in multiple ways, subst is empty, and we emit it even for builtin deref (note that @@ -930,7 +930,7 @@ impl InferenceContext<'_> { self.write_expr_adj(*base, adj); if let Some(func) = self .db - .trait_data(index_trait) + .trait_items(index_trait) .method_by_name(&Name::new_symbol_root(sym::index.clone())) { let subst = TyBuilder::subst_for_def(self.db, index_trait, None); @@ -1258,7 +1258,7 @@ impl InferenceContext<'_> { let Some(trait_) = fn_x.get_id(self.db, self.table.trait_env.krate) else { return; }; - let trait_data = self.db.trait_data(trait_); + let trait_data = self.db.trait_items(trait_); if let Some(func) = trait_data.method_by_name(&fn_x.method_name()) { let subst = TyBuilder::subst_for_def(self.db, trait_, None) .push(callee_ty.clone()) @@ -1426,7 +1426,7 @@ impl InferenceContext<'_> { let trait_func = lang_items_for_bin_op(op).and_then(|(name, lang_item)| { let trait_id = self.resolve_lang_item(lang_item)?.as_trait()?; - let func = self.db.trait_data(trait_id).method_by_name(&name)?; + let func = self.db.trait_items(trait_id).method_by_name(&name)?; Some((trait_id, func)) }); let (trait_, func) = match trait_func { diff --git a/crates/hir-ty/src/infer/mutability.rs b/crates/hir-ty/src/infer/mutability.rs index d74a383f44ef..96d84cad9394 100644 --- a/crates/hir-ty/src/infer/mutability.rs +++ b/crates/hir-ty/src/infer/mutability.rs @@ -134,7 +134,7 @@ impl InferenceContext<'_> { { if let Some(index_fn) = self .db - .trait_data(index_trait) + .trait_items(index_trait) .method_by_name(&Name::new_symbol_root(sym::index_mut.clone())) { *f = index_fn; @@ -201,7 +201,7 @@ impl InferenceContext<'_> { mutability = Mutability::Not; } else if let Some(deref_fn) = self .db - .trait_data(deref_trait) + .trait_items(deref_trait) .method_by_name(&Name::new_symbol_root(sym::deref_mut.clone())) { *f = deref_fn; diff --git a/crates/hir-ty/src/infer/path.rs b/crates/hir-ty/src/infer/path.rs index 6254bc12392b..29f455a61b94 100644 --- a/crates/hir-ty/src/infer/path.rs +++ b/crates/hir-ty/src/infer/path.rs @@ -277,7 +277,7 @@ impl InferenceContext<'_> { ) -> Option<(ValueNs, Substitution)> { let trait_ = trait_ref.hir_trait_id(); let item = - self.db.trait_data(trait_).items.iter().map(|(_name, id)| *id).find_map(|item| { + self.db.trait_items(trait_).items.iter().map(|(_name, id)| *id).find_map(|item| { match item { AssocItemId::FunctionId(func) => { if segment.name == &self.db.function_data(func).name { diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs index 8a8992cf372d..a9332a5a9637 100644 --- a/crates/hir-ty/src/infer/unify.rs +++ b/crates/hir-ty/src/infer/unify.rs @@ -801,7 +801,7 @@ impl<'a> InferenceTable<'a> { ] { let krate = self.trait_env.krate; let fn_trait = fn_trait_name.get_id(self.db, krate)?; - let trait_data = self.db.trait_data(fn_trait); + let trait_data = self.db.trait_items(fn_trait); let output_assoc_type = trait_data.associated_type_by_name(&Name::new_symbol_root(output_assoc_name))?; diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index f35298846a85..836319431dfb 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -906,7 +906,7 @@ pub fn callable_sig_from_fn_trait( let krate = trait_env.krate; let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?; let output_assoc_type = db - .trait_data(fn_once_trait) + .trait_items(fn_once_trait) .associated_type_by_name(&Name::new_symbol_root(sym::Output.clone()))?; let mut table = InferenceTable::new(db, trait_env.clone()); diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 29ab0251f836..33e852aaee46 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -898,7 +898,7 @@ fn named_associated_type_shorthand_candidates( ) -> Option { let mut search = |t| { all_super_trait_refs(db, t, |t| { - let data = db.trait_data(t.hir_trait_id()); + let data = db.trait_items(t.hir_trait_id()); for (name, assoc_id) in &data.items { if let AssocItemId::TypeAliasId(alias) = assoc_id { @@ -1068,7 +1068,7 @@ pub(crate) fn generic_predicates_for_param_query( }; all_super_traits(db.upcast(), tr).iter().any(|tr| { - db.trait_data(*tr).items.iter().any(|(name, item)| { + db.trait_items(*tr).items.iter().any(|(name, item)| { matches!(item, AssocItemId::TypeAliasId(_)) && name == assoc_name }) }) diff --git a/crates/hir-ty/src/lower/path.rs b/crates/hir-ty/src/lower/path.rs index a165932ddcc8..a9e9e83e871f 100644 --- a/crates/hir-ty/src/lower/path.rs +++ b/crates/hir-ty/src/lower/path.rs @@ -169,7 +169,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { self.skip_resolved_segment(); let segment = self.current_or_prev_segment; let found = - self.ctx.db.trait_data(trait_).associated_type_by_name(segment.name); + self.ctx.db.trait_items(trait_).associated_type_by_name(segment.name); match found { Some(associated_ty) => { diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs index 50b0fce62f76..bb3aaef20b76 100644 --- a/crates/hir-ty/src/method_resolution.rs +++ b/crates/hir-ty/src/method_resolution.rs @@ -8,8 +8,8 @@ use arrayvec::ArrayVec; use base_db::Crate; use chalk_ir::{cast::Cast, UniverseIndex, WithKind}; use hir_def::{ - data::{adt::StructFlags, ImplData, TraitFlags}, - nameres::DefMap, + data::{adt::StructFlags, TraitFlags}, + nameres::{assoc::ImplItems, DefMap}, AssocItemId, BlockId, ConstId, FunctionId, HasModule, ImplId, ItemContainerId, Lookup, ModuleId, TraitId, }; @@ -325,7 +325,7 @@ impl InherentImpls { let self_ty = db.impl_self_ty(impl_id); let self_ty = self_ty.skip_binders(); - match is_inherent_impl_coherent(db, def_map, &data, self_ty) { + match is_inherent_impl_coherent(db, def_map, impl_id, self_ty) { true => { // `fp` should only be `None` in error cases (either erroneous code or incomplete name resolution) if let Some(fp) = TyFingerprint::for_inherent_impl(self_ty) { @@ -765,11 +765,10 @@ fn find_matching_impl( mut impls: impl Iterator, mut table: InferenceTable<'_>, actual_trait_ref: TraitRef, -) -> Option<(Arc, Substitution)> { +) -> Option<(Arc, Substitution)> { let db = table.db; impls.find_map(|impl_| { table.run_in_snapshot(|table| { - let impl_data = db.impl_data(impl_); let impl_substs = TyBuilder::subst_for_def(db, impl_, None).fill_with_inference_vars(table).build(); let trait_ref = db @@ -787,7 +786,7 @@ fn find_matching_impl( let goal = crate::Goal::all(Interner, wcs); table.try_obligation(goal.clone())?; table.register_obligation(goal); - Some((impl_data, table.resolve_completely(impl_substs))) + Some((db.impl_items(impl_), table.resolve_completely(impl_substs))) }) }) } @@ -795,7 +794,7 @@ fn find_matching_impl( fn is_inherent_impl_coherent( db: &dyn HirDatabase, def_map: &DefMap, - impl_data: &ImplData, + impl_id: ImplId, self_ty: &Ty, ) -> bool { let self_ty = self_ty.kind(Interner); @@ -848,9 +847,10 @@ fn is_inherent_impl_coherent( _ => false, }; + let items = db.impl_items(impl_id); rustc_has_incoherent_inherent_impls - && !impl_data.items.is_empty() - && impl_data.items.iter().all(|&(_, assoc)| match assoc { + && !items.items.is_empty() + && items.items.iter().all(|&(_, assoc)| match assoc { AssocItemId::FunctionId(it) => db.function_data(it).rustc_allow_incoherent_impl, AssocItemId::ConstId(it) => db.const_data(it).rustc_allow_incoherent_impl, AssocItemId::TypeAliasId(it) => db.type_alias_data(it).rustc_allow_incoherent_impl, @@ -1241,7 +1241,7 @@ fn iterate_trait_method_candidates( // trait, but if we find out it doesn't, we'll skip the rest of the // iteration let mut known_implemented = false; - for &(_, item) in data.items.iter() { + for &(_, item) in db.trait_items(t).items.iter() { // Don't pass a `visible_from_module` down to `is_valid_candidate`, // since only inherent methods should be included into visibility checking. let visible = @@ -1368,7 +1368,7 @@ fn iterate_inherent_methods( ) -> ControlFlow<()> { let db = table.db; for t in traits { - let data = db.trait_data(t); + let data = db.trait_items(t); for &(_, item) in data.items.iter() { // We don't pass `visible_from_module` as all trait items should be visible. let visible = match is_valid_trait_method_candidate( @@ -1401,7 +1401,7 @@ fn iterate_inherent_methods( callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, ) -> ControlFlow<()> { for &impl_id in impls.for_self_ty(self_ty) { - for &(ref item_name, item) in table.db.impl_data(impl_id).items.iter() { + for &(ref item_name, item) in table.db.impl_items(impl_id).items.iter() { let visible = match is_valid_impl_method_candidate( table, self_ty, diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index 597e6a3ef0bf..97710aab06c7 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -661,19 +661,19 @@ impl Evaluator<'_> { .lang_item(crate_id, LangItem::Fn) .and_then(|x| x.as_trait()) .and_then(|x| { - db.trait_data(x).method_by_name(&Name::new_symbol_root(sym::call.clone())) + db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call.clone())) }), cached_fn_mut_trait_func: db .lang_item(crate_id, LangItem::FnMut) .and_then(|x| x.as_trait()) .and_then(|x| { - db.trait_data(x).method_by_name(&Name::new_symbol_root(sym::call_mut.clone())) + db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call_mut.clone())) }), cached_fn_once_trait_func: db .lang_item(crate_id, LangItem::FnOnce) .and_then(|x| x.as_trait()) .and_then(|x| { - db.trait_data(x).method_by_name(&Name::new_symbol_root(sym::call_once.clone())) + db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call_once.clone())) }), }) } @@ -2818,7 +2818,9 @@ impl Evaluator<'_> { ) -> Result<()> { let Some(drop_fn) = (|| { let drop_trait = self.db.lang_item(self.crate_id, LangItem::Drop)?.as_trait()?; - self.db.trait_data(drop_trait).method_by_name(&Name::new_symbol_root(sym::drop.clone())) + self.db + .trait_items(drop_trait) + .method_by_name(&Name::new_symbol_root(sym::drop.clone())) })() else { // in some tests we don't have drop trait in minicore, and // we can ignore drop in them. @@ -2928,7 +2930,7 @@ pub fn render_const_using_debug_impl( not_supported!("core::fmt::Debug not found"); }; let Some(debug_fmt_fn) = - db.trait_data(debug_trait).method_by_name(&Name::new_symbol_root(sym::fmt.clone())) + db.trait_items(debug_trait).method_by_name(&Name::new_symbol_root(sym::fmt.clone())) else { not_supported!("core::fmt::Debug::fmt not found"); }; diff --git a/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs index 346dea82526f..edd028cdeb26 100644 --- a/crates/hir-ty/src/mir/eval/shim.rs +++ b/crates/hir-ty/src/mir/eval/shim.rs @@ -1261,7 +1261,7 @@ impl Evaluator<'_> { if let Some(target) = self.db.lang_item(self.crate_id, LangItem::FnOnce) { if let Some(def) = target.as_trait().and_then(|it| { self.db - .trait_data(it) + .trait_items(it) .method_by_name(&Name::new_symbol_root(sym::call_once.clone())) }) { self.exec_fn_trait( diff --git a/crates/hir-ty/src/mir/lower/as_place.rs b/crates/hir-ty/src/mir/lower/as_place.rs index 420f2aaff46d..7b0ee22d51fc 100644 --- a/crates/hir-ty/src/mir/lower/as_place.rs +++ b/crates/hir-ty/src/mir/lower/as_place.rs @@ -195,7 +195,7 @@ impl MirLowerCtx<'_> { self.resolve_lang_item(LangItem::DerefMut)?.as_trait() { if let Some(deref_fn) = - self.db.trait_data(deref_trait).method_by_name( + self.db.trait_items(deref_trait).method_by_name( &Name::new_symbol_root(sym::deref_mut.clone()), ) { @@ -353,7 +353,7 @@ impl MirLowerCtx<'_> { .ok_or(MirLowerError::LangItemNotFound(trait_lang_item))?; let deref_fn = self .db - .trait_data(deref_trait) + .trait_items(deref_trait) .method_by_name(&trait_method_name) .ok_or(MirLowerError::LangItemNotFound(trait_lang_item))?; let deref_fn_op = Operand::const_zst( diff --git a/crates/hir-ty/src/tests.rs b/crates/hir-ty/src/tests.rs index cdb9e9edf883..9ad07922fac7 100644 --- a/crates/hir-ty/src/tests.rs +++ b/crates/hir-ty/src/tests.rs @@ -439,7 +439,7 @@ pub(crate) fn visit_module( ) { visit_scope(db, crate_def_map, &crate_def_map[module_id].scope, cb); for impl_id in crate_def_map[module_id].scope.impls() { - let impl_data = db.impl_data(impl_id); + let impl_data = db.impl_items(impl_id); for &(_, item) in impl_data.items.iter() { match item { AssocItemId::FunctionId(it) => { @@ -488,7 +488,7 @@ pub(crate) fn visit_module( }); } ModuleDefId::TraitId(it) => { - let trait_data = db.trait_data(it); + let trait_data = db.trait_items(it); for &(_, item) in trait_data.items.iter() { match item { AssocItemId::FunctionId(it) => cb(it.into()), diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs index b90f4e4d7faa..cbb78ef40d84 100644 --- a/crates/hir-ty/src/utils.rs +++ b/crates/hir-ty/src/utils.rs @@ -226,7 +226,7 @@ pub(super) fn associated_type_by_name_including_super_traits( name: &Name, ) -> Option<(TraitRef, TypeAliasId)> { all_super_trait_refs(db, trait_ref, |t| { - let assoc_type = db.trait_data(t.hir_trait_id()).associated_type_by_name(name)?; + let assoc_type = db.trait_items(t.hir_trait_id()).associated_type_by_name(name)?; Some((t, assoc_type)) }) } diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs index 4351a34e8228..1c88e79933fb 100644 --- a/crates/hir/src/attrs.rs +++ b/crates/hir/src/attrs.rs @@ -194,7 +194,7 @@ fn resolve_assoc_or_field( // Doc paths in this context may only resolve to an item of this trait // (i.e. no items of its supertraits), so we need to handle them here // independently of others. - return db.trait_data(id).items.iter().find(|it| it.0 == name).map(|(_, assoc_id)| { + return db.trait_items(id).items.iter().find(|it| it.0 == name).map(|(_, assoc_id)| { let def = match *assoc_id { AssocItemId::FunctionId(it) => ModuleDef::Function(it.into()), AssocItemId::ConstId(it) => ModuleDef::Const(it.into()), diff --git a/crates/hir/src/db.rs b/crates/hir/src/db.rs index 9e8e87ecff00..64d97b3f2a23 100644 --- a/crates/hir/src/db.rs +++ b/crates/hir/src/db.rs @@ -11,7 +11,7 @@ pub use hir_def::db::DefDatabase; // ExpandProcAttrMacrosQuery, ExprScopesQuery, ExternCrateDeclDataQuery, FieldVisibilitiesQuery, // FieldsAttrsQuery, FieldsAttrsSourceMapQuery, FileItemTreeQuery, FileItemTreeWithSourceMapQuery, // FunctionDataQuery, FunctionVisibilityQuery, GenericParamsQuery, -// GenericParamsWithSourceMapQuery, ImplDataWithDiagnosticsQuery, ImportMapQuery, +// GenericParamsWithSourceMapQuery, ImplItemsWithDiagnosticsQuery, ImportMapQuery, // IncludeMacroInvocQuery, InternAnonymousConstQuery, InternBlockQuery, InternConstQuery, // InternDatabase, InternDatabaseStorage, InternEnumQuery, InternExternBlockQuery, // InternExternCrateQuery, InternFunctionQuery, InternImplQuery, InternInTypeConstQuery, @@ -19,7 +19,7 @@ pub use hir_def::db::DefDatabase; // InternStructQuery, InternTraitAliasQuery, InternTraitQuery, InternTypeAliasQuery, // InternUnionQuery, InternUseQuery, LangItemQuery, Macro2DataQuery, MacroDefQuery, // MacroRulesDataQuery, NotableTraitsInDepsQuery, ProcMacroDataQuery, StaticDataQuery, -// StructDataWithDiagnosticsQuery, TraitAliasDataQuery, TraitDataWithDiagnosticsQuery, +// StructDataWithDiagnosticsQuery, TraitAliasDataQuery, TraitItemsWithDiagnosticsQuery, // TypeAliasDataQuery, UnionDataWithDiagnosticsQuery, // }; pub use hir_expand::db::ExpandDatabase; diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 5da2b5ed0936..5cc330fb38f3 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -636,7 +636,7 @@ impl Module { acc.extend(def.diagnostics(db, style_lints)) } ModuleDef::Trait(t) => { - for diag in db.trait_data_with_diagnostics(t.id).1.iter() { + for diag in db.trait_items_with_diagnostics(t.id).1.iter() { emit_def_diagnostic(db, acc, diag, edition); } @@ -743,7 +743,7 @@ impl Module { let ast_id_map = db.ast_id_map(file_id); - for diag in db.impl_data_with_diagnostics(impl_def.id).1.iter() { + for diag in db.impl_items_with_diagnostics(impl_def.id).1.iter() { emit_def_diagnostic(db, acc, diag, edition); } @@ -801,13 +801,13 @@ impl Module { // Negative impls can't have items, don't emit missing items diagnostic for them if let (false, Some(trait_)) = (impl_is_negative, trait_) { - let items = &db.trait_data(trait_.into()).items; + let items = &db.trait_items(trait_.into()).items; let required_items = items.iter().filter(|&(_, assoc)| match *assoc { AssocItemId::FunctionId(it) => !db.function_data(it).has_body(), AssocItemId::ConstId(id) => !db.const_data(id).has_body, AssocItemId::TypeAliasId(it) => db.type_alias_data(it).type_ref.is_none(), }); - impl_assoc_items_scratch.extend(db.impl_data(impl_def.id).items.iter().cloned()); + impl_assoc_items_scratch.extend(db.impl_items(impl_def.id).items.iter().cloned()); let redundant = impl_assoc_items_scratch .iter() @@ -863,7 +863,7 @@ impl Module { source_map, ); - for &(_, item) in db.impl_data(impl_def.id).items.iter() { + for &(_, item) in db.impl_items(impl_def.id).items.iter() { AssocItem::from(item).diagnostics(db, acc, style_lints); } } @@ -2868,16 +2868,15 @@ impl Trait { } pub fn function(self, db: &dyn HirDatabase, name: impl PartialEq) -> Option { - db.trait_data(self.id).items.iter().find(|(n, _)| name == *n).and_then( - |&(_, it)| match it { - AssocItemId::FunctionId(id) => Some(Function { id }), - _ => None, - }, - ) + db.trait_items(self.id).items.iter().find(|(n, _)| name == *n).and_then(|&(_, it)| match it + { + AssocItemId::FunctionId(id) => Some(Function { id }), + _ => None, + }) } pub fn items(self, db: &dyn HirDatabase) -> Vec { - db.trait_data(self.id).items.iter().map(|(_name, it)| (*it).into()).collect() + db.trait_items(self.id).items.iter().map(|(_name, it)| (*it).into()).collect() } pub fn items_with_supertraits(self, db: &dyn HirDatabase) -> Vec { @@ -2921,7 +2920,7 @@ impl Trait { } fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId, MacroCallId)]> { - db.trait_data(self.id) + db.trait_items(self.id) .macro_calls .as_ref() .map(|it| it.as_ref().clone().into_boxed_slice()) @@ -4428,7 +4427,7 @@ impl Impl { } pub fn items(self, db: &dyn HirDatabase) -> Vec { - db.impl_data(self.id).items.iter().map(|&(_, it)| it.into()).collect() + db.impl_items(self.id).items.iter().map(|&(_, it)| it.into()).collect() } pub fn is_negative(self, db: &dyn HirDatabase) -> bool { @@ -4478,7 +4477,7 @@ impl Impl { } fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId, MacroCallId)]> { - db.impl_data(self.id) + db.impl_items(self.id) .macro_calls .as_ref() .map(|it| it.as_ref().clone().into_boxed_slice()) @@ -4959,7 +4958,7 @@ impl Type { } let output_assoc_type = db - .trait_data(trait_) + .trait_items(trait_) .associated_type_by_name(&Name::new_symbol_root(sym::Output.clone()))?; self.normalize_trait_assoc_type(db, &[], output_assoc_type.into()) } @@ -4975,7 +4974,7 @@ impl Type { pub fn iterator_item(self, db: &dyn HirDatabase) -> Option { let iterator_trait = db.lang_item(self.env.krate, LangItem::Iterator)?.as_trait()?; let iterator_item = db - .trait_data(iterator_trait) + .trait_items(iterator_trait) .associated_type_by_name(&Name::new_symbol_root(sym::Item.clone()))?; self.normalize_trait_assoc_type(db, &[], iterator_item.into()) } @@ -5007,7 +5006,7 @@ impl Type { } let into_iter_assoc_type = db - .trait_data(trait_) + .trait_items(trait_) .associated_type_by_name(&Name::new_symbol_root(sym::IntoIter.clone()))?; self.normalize_trait_assoc_type(db, &[], into_iter_assoc_type.into()) } @@ -5301,7 +5300,7 @@ impl Type { let impls = db.inherent_impls_in_crate(krate); for impl_def in impls.for_self_ty(&self.ty) { - for &(_, item) in db.impl_data(*impl_def).items.iter() { + for &(_, item) in db.impl_items(*impl_def).items.iter() { if callback(item) { return; } diff --git a/crates/hir/src/semantics/child_by_source.rs b/crates/hir/src/semantics/child_by_source.rs index da9bb8b15c8c..556b21124dd5 100644 --- a/crates/hir/src/semantics/child_by_source.rs +++ b/crates/hir/src/semantics/child_by_source.rs @@ -34,7 +34,7 @@ pub(crate) trait ChildBySource { impl ChildBySource for TraitId { fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) { - let data = db.trait_data(*self); + let data = db.trait_items(*self); data.attribute_calls().filter(|(ast_id, _)| ast_id.file_id == file_id).for_each( |(ast_id, call_id)| { @@ -49,7 +49,7 @@ impl ChildBySource for TraitId { impl ChildBySource for ImplId { fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) { - let data = db.impl_data(*self); + let data = db.impl_items(*self); // FIXME: Macro calls data.attribute_calls().filter(|(ast_id, _)| ast_id.file_id == file_id).for_each( |(ast_id, call_id)| { diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index aa0eac9478a2..e390fb0b935f 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -1291,7 +1291,7 @@ impl SourceAnalyzer { method_name: &Name, ) -> Option<(TraitId, FunctionId)> { let trait_id = db.lang_item(self.resolver.krate(), lang_trait)?.as_trait()?; - let fn_id = db.trait_data(trait_id).method_by_name(method_name)?; + let fn_id = db.trait_items(trait_id).method_by_name(method_name)?; Some((trait_id, fn_id)) } @@ -1453,7 +1453,7 @@ fn resolve_hir_path_( // within the trait's associated types. if let (Some(unresolved), &TypeNs::TraitId(trait_id)) = (&unresolved, &ty) { if let Some(type_alias_id) = - db.trait_data(trait_id).associated_type_by_name(unresolved.name) + db.trait_items(trait_id).associated_type_by_name(unresolved.name) { return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into())); } @@ -1586,7 +1586,7 @@ fn resolve_hir_path_qualifier( // within the trait's associated types. if let (Some(unresolved), &TypeNs::TraitId(trait_id)) = (&unresolved, &ty) { if let Some(type_alias_id) = - db.trait_data(trait_id).associated_type_by_name(unresolved.name) + db.trait_items(trait_id).associated_type_by_name(unresolved.name) { return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into())); } diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs index 2a6c15207a33..853df7ee2d88 100644 --- a/crates/hir/src/symbols.rs +++ b/crates/hir/src/symbols.rs @@ -313,7 +313,7 @@ impl<'a> SymbolCollector<'a> { .to_smolstr(), ); self.with_container_name(impl_name, |s| { - for &(ref name, assoc_item_id) in &impl_data.items { + for &(ref name, assoc_item_id) in &self.db.impl_items(impl_id).items { s.push_assoc_item(assoc_item_id, name) } }) @@ -322,7 +322,7 @@ impl<'a> SymbolCollector<'a> { fn collect_from_trait(&mut self, trait_id: TraitId) { let trait_data = self.db.trait_data(trait_id); self.with_container_name(Some(trait_data.name.as_str().into()), |s| { - for &(ref name, assoc_item_id) in &trait_data.items { + for &(ref name, assoc_item_id) in &self.db.trait_items(trait_id).items { s.push_assoc_item(assoc_item_id, name); } }); diff --git a/crates/ide-db/src/apply_change.rs b/crates/ide-db/src/apply_change.rs index 4c8940db95cc..6b08ada34b60 100644 --- a/crates/ide-db/src/apply_change.rs +++ b/crates/ide-db/src/apply_change.rs @@ -162,7 +162,7 @@ impl RootDatabase { // hir::db::FunctionVisibilityQuery // hir::db::GenericParamsQuery // hir::db::GenericParamsWithSourceMapQuery - // hir::db::ImplDataWithDiagnosticsQuery + // hir::db::ImplItemsWithDiagnosticsQuery // hir::db::ImportMapQuery // hir::db::IncludeMacroInvocQuery // hir::db::InternAnonymousConstQuery @@ -193,7 +193,7 @@ impl RootDatabase { // hir::db::StaticDataQuery // hir::db::StructDataWithDiagnosticsQuery // hir::db::TraitAliasDataQuery - // hir::db::TraitDataWithDiagnosticsQuery + // hir::db::TraitItemsWithDiagnosticsQuery // hir::db::TypeAliasDataQuery // hir::db::UnionDataWithDiagnosticsQuery From dff1896436504d3a9c67d12545bd6f8719ffbdd4 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 26 Feb 2025 07:55:00 +0100 Subject: [PATCH 2/4] Move attribute parsing out of data module --- crates/hir-def/src/attr.rs | 125 +++++++++++++++++++++++++++++++++ crates/hir-def/src/data.rs | 33 +-------- crates/hir-def/src/data/adt.rs | 94 +------------------------ 3 files changed, 128 insertions(+), 124 deletions(-) diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index 579ea12e6ae0..030d064584cd 100644 --- a/crates/hir-def/src/attr.rs +++ b/crates/hir-def/src/attr.rs @@ -12,6 +12,7 @@ use hir_expand::{ use intern::{sym, Symbol}; use la_arena::{ArenaMap, Idx, RawIdx}; use mbe::DelimiterKind; +use rustc_abi::ReprOptions; use syntax::{ ast::{self, HasAttrs}, AstPtr, @@ -221,6 +222,130 @@ impl Attrs { pub fn is_unstable(&self) -> bool { self.by_key(&sym::unstable).exists() } + + pub fn rustc_legacy_const_generics(&self) -> Option>> { + self.by_key(&sym::rustc_legacy_const_generics) + .tt_values() + .next() + .map(parse_rustc_legacy_const_generics) + .filter(|it| !it.is_empty()) + .map(Box::new) + } + + pub fn repr(&self) -> Option { + self.by_key(&sym::repr).tt_values().find_map(parse_repr_tt) + } +} + +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() +} + +fn parse_repr_tt(tt: &crate::tt::TopSubtree) -> Option { + use crate::builtin_type::{BuiltinInt, BuiltinUint}; + use rustc_abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions}; + + match tt.top_subtree().delimiter { + tt::Delimiter { kind: DelimiterKind::Parenthesis, .. } => {} + _ => return None, + } + + let mut flags = ReprFlags::empty(); + let mut int = None; + let mut max_align: Option = None; + let mut min_pack: Option = None; + + let mut tts = tt.iter(); + while let Some(tt) = tts.next() { + if let TtElement::Leaf(tt::Leaf::Ident(ident)) = tt { + flags.insert(match &ident.sym { + s if *s == sym::packed => { + let pack = if let Some(TtElement::Subtree(_, mut tt_iter)) = tts.peek() { + tts.next(); + if let Some(TtElement::Leaf(tt::Leaf::Literal(lit))) = tt_iter.next() { + lit.symbol.as_str().parse().unwrap_or_default() + } else { + 0 + } + } else { + 0 + }; + let pack = Align::from_bytes(pack).unwrap_or(Align::ONE); + min_pack = + Some(if let Some(min_pack) = min_pack { min_pack.min(pack) } else { pack }); + ReprFlags::empty() + } + s if *s == sym::align => { + if let Some(TtElement::Subtree(_, mut tt_iter)) = tts.peek() { + tts.next(); + if let Some(TtElement::Leaf(tt::Leaf::Literal(lit))) = tt_iter.next() { + if let Ok(align) = lit.symbol.as_str().parse() { + let align = Align::from_bytes(align).ok(); + max_align = max_align.max(align); + } + } + } + ReprFlags::empty() + } + s if *s == sym::C => ReprFlags::IS_C, + s if *s == sym::transparent => ReprFlags::IS_TRANSPARENT, + s if *s == sym::simd => ReprFlags::IS_SIMD, + repr => { + if let Some(builtin) = BuiltinInt::from_suffix_sym(repr) + .map(Either::Left) + .or_else(|| BuiltinUint::from_suffix_sym(repr).map(Either::Right)) + { + int = Some(match builtin { + Either::Left(bi) => match bi { + BuiltinInt::Isize => IntegerType::Pointer(true), + BuiltinInt::I8 => IntegerType::Fixed(Integer::I8, true), + BuiltinInt::I16 => IntegerType::Fixed(Integer::I16, true), + BuiltinInt::I32 => IntegerType::Fixed(Integer::I32, true), + BuiltinInt::I64 => IntegerType::Fixed(Integer::I64, true), + BuiltinInt::I128 => IntegerType::Fixed(Integer::I128, true), + }, + Either::Right(bu) => match bu { + BuiltinUint::Usize => IntegerType::Pointer(false), + BuiltinUint::U8 => IntegerType::Fixed(Integer::I8, false), + BuiltinUint::U16 => IntegerType::Fixed(Integer::I16, false), + BuiltinUint::U32 => IntegerType::Fixed(Integer::I32, false), + BuiltinUint::U64 => IntegerType::Fixed(Integer::I64, false), + BuiltinUint::U128 => IntegerType::Fixed(Integer::I128, false), + }, + }); + } + ReprFlags::empty() + } + }) + } + } + + Some(ReprOptions { + int, + align: max_align, + pack: min_pack, + flags, + field_shuffle_seed: rustc_hashes::Hash64::ZERO, + }) } #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs index 8a1f07c92eff..1a6bed6cabbd 100644 --- a/crates/hir-def/src/data.rs +++ b/crates/hir-def/src/data.rs @@ -7,7 +7,6 @@ use hir_expand::name::Name; use intern::{sym, Symbol}; use la_arena::{Idx, RawIdx}; use triomphe::Arc; -use tt::iter::TtElement; use crate::{ db::DefDatabase, @@ -73,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() @@ -106,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, @@ -156,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, diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs index bf8f5024c2d6..161b205c8094 100644 --- a/crates/hir-def/src/data/adt.rs +++ b/crates/hir-def/src/data/adt.rs @@ -3,18 +3,14 @@ use base_db::Crate; use bitflags::bitflags; use cfg::CfgOptions; -use either::Either; use hir_expand::name::Name; use intern::sym; use la_arena::Arena; -use rustc_abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions}; -use rustc_hashes::Hash64; +use rustc_abi::{IntegerType, ReprOptions}; use triomphe::Arc; -use tt::iter::TtElement; use crate::{ - builtin_type::{BuiltinInt, BuiltinUint}, db::DefDatabase, hir::Expr, item_tree::{ @@ -22,7 +18,6 @@ use crate::{ }, lang_item::LangItem, nameres::diagnostics::{DefDiagnostic, DefDiagnostics}, - tt::{Delimiter, DelimiterKind, Leaf, TopSubtree}, type_ref::{TypeRefId, TypesMap}, visibility::RawVisibility, EnumId, EnumVariantId, LocalFieldId, LocalModuleId, Lookup, StructId, UnionId, VariantId, @@ -94,92 +89,7 @@ fn repr_from_value( item_tree: &ItemTree, of: AttrOwner, ) -> Option { - item_tree.attrs(db, krate, of).by_key(&sym::repr).tt_values().find_map(parse_repr_tt) -} - -fn parse_repr_tt(tt: &TopSubtree) -> Option { - match tt.top_subtree().delimiter { - Delimiter { kind: DelimiterKind::Parenthesis, .. } => {} - _ => return None, - } - - let mut flags = ReprFlags::empty(); - let mut int = None; - let mut max_align: Option = None; - let mut min_pack: Option = None; - - let mut tts = tt.iter(); - while let Some(tt) = tts.next() { - if let TtElement::Leaf(Leaf::Ident(ident)) = tt { - flags.insert(match &ident.sym { - s if *s == sym::packed => { - let pack = if let Some(TtElement::Subtree(_, mut tt_iter)) = tts.peek() { - tts.next(); - if let Some(TtElement::Leaf(Leaf::Literal(lit))) = tt_iter.next() { - lit.symbol.as_str().parse().unwrap_or_default() - } else { - 0 - } - } else { - 0 - }; - let pack = Align::from_bytes(pack).unwrap_or(Align::ONE); - min_pack = - Some(if let Some(min_pack) = min_pack { min_pack.min(pack) } else { pack }); - ReprFlags::empty() - } - s if *s == sym::align => { - if let Some(TtElement::Subtree(_, mut tt_iter)) = tts.peek() { - tts.next(); - if let Some(TtElement::Leaf(Leaf::Literal(lit))) = tt_iter.next() { - if let Ok(align) = lit.symbol.as_str().parse() { - let align = Align::from_bytes(align).ok(); - max_align = max_align.max(align); - } - } - } - ReprFlags::empty() - } - s if *s == sym::C => ReprFlags::IS_C, - s if *s == sym::transparent => ReprFlags::IS_TRANSPARENT, - s if *s == sym::simd => ReprFlags::IS_SIMD, - repr => { - if let Some(builtin) = BuiltinInt::from_suffix_sym(repr) - .map(Either::Left) - .or_else(|| BuiltinUint::from_suffix_sym(repr).map(Either::Right)) - { - int = Some(match builtin { - Either::Left(bi) => match bi { - BuiltinInt::Isize => IntegerType::Pointer(true), - BuiltinInt::I8 => IntegerType::Fixed(Integer::I8, true), - BuiltinInt::I16 => IntegerType::Fixed(Integer::I16, true), - BuiltinInt::I32 => IntegerType::Fixed(Integer::I32, true), - BuiltinInt::I64 => IntegerType::Fixed(Integer::I64, true), - BuiltinInt::I128 => IntegerType::Fixed(Integer::I128, true), - }, - Either::Right(bu) => match bu { - BuiltinUint::Usize => IntegerType::Pointer(false), - BuiltinUint::U8 => IntegerType::Fixed(Integer::I8, false), - BuiltinUint::U16 => IntegerType::Fixed(Integer::I16, false), - BuiltinUint::U32 => IntegerType::Fixed(Integer::I32, false), - BuiltinUint::U64 => IntegerType::Fixed(Integer::I64, false), - BuiltinUint::U128 => IntegerType::Fixed(Integer::I128, false), - }, - }); - } - ReprFlags::empty() - } - }) - } - } - - Some(ReprOptions { - int, - align: max_align, - pack: min_pack, - flags, - field_shuffle_seed: Hash64::ZERO, - }) + item_tree.attrs(db, krate, of).repr() } impl StructData { From 8e8d997304f1fca517217d32d5be2738b0211a30 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 26 Feb 2025 08:02:53 +0100 Subject: [PATCH 3/4] Split enum variants out of `enum_data` query --- crates/hir-def/src/data/adt.rs | 60 ++++++++++++------- crates/hir-def/src/db.rs | 5 +- crates/hir-ty/src/chalk_db.rs | 2 +- crates/hir-ty/src/consteval.rs | 2 +- crates/hir-ty/src/diagnostics/decl_check.rs | 2 +- crates/hir-ty/src/diagnostics/expr.rs | 2 +- .../diagnostics/match_check/pat_analysis.rs | 4 +- crates/hir-ty/src/drop.rs | 2 +- crates/hir-ty/src/infer.rs | 4 +- crates/hir-ty/src/infer/cast.rs | 2 +- crates/hir-ty/src/infer/closure.rs | 2 +- crates/hir-ty/src/infer/path.rs | 2 +- crates/hir-ty/src/inhabitedness.rs | 2 +- crates/hir-ty/src/layout/adt.rs | 8 +-- crates/hir-ty/src/mir/eval.rs | 5 +- crates/hir-ty/src/tests.rs | 2 +- crates/hir-ty/src/utils.rs | 6 +- crates/hir-ty/src/variance.rs | 2 +- crates/hir/src/lib.rs | 6 +- crates/hir/src/semantics/child_by_source.rs | 2 +- .../ide-completion/src/completions/pattern.rs | 4 +- 21 files changed, 74 insertions(+), 52 deletions(-) diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs index 161b205c8094..c8429d8b6897 100644 --- a/crates/hir-def/src/data/adt.rs +++ b/crates/hir-def/src/data/adt.rs @@ -56,12 +56,16 @@ bitflags! { #[derive(Debug, Clone, PartialEq, Eq)] pub struct EnumData { pub name: Name, - pub variants: Box<[(EnumVariantId, Name)]>, pub repr: Option, pub visibility: RawVisibility, pub rustc_has_incoherent_inherent_impls: bool, } +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct EnumVariants { + pub variants: Box<[(EnumVariantId, Name)]>, +} + #[derive(Debug, Clone, PartialEq, Eq)] pub struct EnumVariantData { pub name: Name, @@ -203,28 +207,16 @@ impl StructData { } } -impl EnumData { - pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc { +impl EnumVariants { + pub(crate) fn enum_variants_query(db: &dyn DefDatabase, e: EnumId) -> Arc { let loc = e.lookup(db); - let krate = loc.container.krate; let item_tree = loc.id.item_tree(db); - let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); - let rustc_has_incoherent_inherent_impls = item_tree - .attrs(db, loc.container.krate, ModItem::from(loc.id.value).into()) - .by_key(&sym::rustc_has_incoherent_inherent_impls) - .exists(); - - let enum_ = &item_tree[loc.id.value]; - Arc::new(EnumData { - name: enum_.name.clone(), + Arc::new(EnumVariants { variants: loc.container.def_map(db).enum_definitions[&e] .iter() .map(|&id| (id, item_tree[id.lookup(db).id.value].name.clone())) .collect(), - repr, - visibility: item_tree[enum_.visibility].clone(), - rustc_has_incoherent_inherent_impls, }) } @@ -233,13 +225,6 @@ impl EnumData { Some(id) } - pub fn variant_body_type(&self) -> IntegerType { - match self.repr { - Some(ReprOptions { int: Some(builtin), .. }) => builtin, - _ => IntegerType::Pointer(true), - } - } - // [Adopted from rustc](https://github.com/rust-lang/rust/blob/bd53aa3bf7a24a70d763182303bd75e5fc51a9af/compiler/rustc_middle/src/ty/adt.rs#L446-L448) pub fn is_payload_free(&self, db: &dyn DefDatabase) -> bool { self.variants.iter().all(|(v, _)| { @@ -262,6 +247,35 @@ impl EnumData { } } +impl EnumData { + pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc { + let loc = e.lookup(db); + let krate = loc.container.krate; + let item_tree = loc.id.item_tree(db); + let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); + let rustc_has_incoherent_inherent_impls = item_tree + .attrs(db, loc.container.krate, ModItem::from(loc.id.value).into()) + .by_key(&sym::rustc_has_incoherent_inherent_impls) + .exists(); + + let enum_ = &item_tree[loc.id.value]; + + Arc::new(EnumData { + name: enum_.name.clone(), + repr, + visibility: item_tree[enum_.visibility].clone(), + rustc_has_incoherent_inherent_impls, + }) + } + + pub fn variant_body_type(&self) -> IntegerType { + match self.repr { + Some(ReprOptions { int: Some(builtin), .. }) => builtin, + _ => IntegerType::Pointer(true), + } + } +} + impl EnumVariantData { #[inline] pub(crate) fn enum_variant_data_query( diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs index ff3305653807..bc9fc8e07930 100644 --- a/crates/hir-def/src/db.rs +++ b/crates/hir-def/src/db.rs @@ -11,7 +11,7 @@ use triomphe::Arc; use crate::{ attr::{Attrs, AttrsWithOwner}, data::{ - adt::{EnumData, EnumVariantData, StructData, VariantData}, + adt::{EnumData, EnumVariantData, EnumVariants, StructData, VariantData}, ConstData, ExternCrateDeclData, FunctionData, ImplData, Macro2Data, MacroRulesData, ProcMacroData, StaticData, TraitAliasData, TraitData, TypeAliasData, }, @@ -167,6 +167,9 @@ pub trait DefDatabase: #[salsa::invoke_actual(EnumData::enum_data_query)] fn enum_data(&self, e: EnumId) -> Arc; + #[salsa::invoke_actual(EnumVariants::enum_variants_query)] + fn enum_variants(&self, e: EnumId) -> Arc; + #[salsa::transparent] #[salsa::invoke_actual(EnumVariantData::enum_variant_data_query)] fn enum_variant_data(&self, id: EnumVariantId) -> Arc; diff --git a/crates/hir-ty/src/chalk_db.rs b/crates/hir-ty/src/chalk_db.rs index e5751a394dae..ac4d1babd62b 100644 --- a/crates/hir-ty/src/chalk_db.rs +++ b/crates/hir-ty/src/chalk_db.rs @@ -801,7 +801,7 @@ pub(crate) fn adt_datum_query( } hir_def::AdtId::EnumId(id) => { let variants = db - .enum_data(id) + .enum_variants(id) .variants .iter() .map(|&(variant_id, _)| variant_id_to_fields(variant_id.into())) diff --git a/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs index 525672bc3995..ec8f9b7c3118 100644 --- a/crates/hir-ty/src/consteval.rs +++ b/crates/hir-ty/src/consteval.rs @@ -309,7 +309,7 @@ pub(crate) fn const_eval_discriminant_variant( let value = match prev_idx { Some(prev_idx) => { 1 + db.const_eval_discriminant( - db.enum_data(loc.parent).variants[prev_idx as usize].0, + db.enum_variants(loc.parent).variants[prev_idx as usize].0, )? } _ => 0, diff --git a/crates/hir-ty/src/diagnostics/decl_check.rs b/crates/hir-ty/src/diagnostics/decl_check.rs index a0b1fe32ce52..0b21ae7ade37 100644 --- a/crates/hir-ty/src/diagnostics/decl_check.rs +++ b/crates/hir-ty/src/diagnostics/decl_check.rs @@ -394,7 +394,7 @@ impl<'a> DeclValidator<'a> { /// Check incorrect names for enum variants. fn validate_enum_variants(&mut self, enum_id: EnumId) { - let data = self.db.enum_data(enum_id); + let data = self.db.enum_variants(enum_id); for (variant_id, _) in data.variants.iter() { self.validate_enum_variant_fields(*variant_id); diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs index 1035651692ec..6096439565cb 100644 --- a/crates/hir-ty/src/diagnostics/expr.rs +++ b/crates/hir-ty/src/diagnostics/expr.rs @@ -642,7 +642,7 @@ fn missing_match_arms<'p>( } let non_empty_enum = match scrut_ty.as_adt() { - Some((AdtId::EnumId(e), _)) => !cx.db.enum_data(e).variants.is_empty(), + Some((AdtId::EnumId(e), _)) => !cx.db.enum_variants(e).variants.is_empty(), _ => false, }; let display_target = DisplayTarget::from_crate(cx.db, krate); diff --git a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs index 91eb59fb3140..b7f8a0c610c5 100644 --- a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs +++ b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs @@ -49,7 +49,7 @@ impl EnumVariantContiguousIndex { } fn to_enum_variant_id(self, db: &dyn HirDatabase, eid: EnumId) -> EnumVariantId { - db.enum_data(eid).variants[self.0].0 + db.enum_variants(eid).variants[self.0].0 } } @@ -449,7 +449,7 @@ impl PatCx for MatchCheckCtx<'_> { TyKind::Scalar(Scalar::Int(..) | Scalar::Uint(..)) => unhandled(), TyKind::Array(..) | TyKind::Slice(..) => unhandled(), &TyKind::Adt(AdtId(adt @ hir_def::AdtId::EnumId(enum_id)), ref subst) => { - let enum_data = cx.db.enum_data(enum_id); + let enum_data = cx.db.enum_variants(enum_id); let is_declared_nonexhaustive = cx.is_foreign_non_exhaustive(adt); if enum_data.variants.is_empty() && !is_declared_nonexhaustive { diff --git a/crates/hir-ty/src/drop.rs b/crates/hir-ty/src/drop.rs index 4ad16cf8bcf7..ab17f86b5b2c 100644 --- a/crates/hir-ty/src/drop.rs +++ b/crates/hir-ty/src/drop.rs @@ -72,7 +72,7 @@ pub(crate) fn has_drop_glue(db: &dyn HirDatabase, ty: Ty, env: Arc DropGlue::None, AdtId::EnumId(id) => db - .enum_data(id) + .enum_variants(id) .variants .iter() .map(|&(variant, _)| { diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index 9a4b7af85d8f..ecadfccf0029 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -1587,7 +1587,7 @@ impl<'a> InferenceContext<'a> { // If we can resolve to an enum variant, it takes priority over associated type // of the same name. if let Some((AdtId::EnumId(id), _)) = ty.as_adt() { - let enum_data = self.db.enum_data(id); + let enum_data = self.db.enum_variants(id); if let Some(variant) = enum_data.variant(current_segment.name) { return if remaining_segments.len() == 1 { (ty, Some(variant.into())) @@ -1701,7 +1701,7 @@ impl<'a> InferenceContext<'a> { let segment = path.segments().last().unwrap(); // this could be an enum variant or associated type if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() { - let enum_data = self.db.enum_data(enum_id); + let enum_data = self.db.enum_variants(enum_id); if let Some(variant) = enum_data.variant(segment) { return (ty, Some(variant.into())); } diff --git a/crates/hir-ty/src/infer/cast.rs b/crates/hir-ty/src/infer/cast.rs index eb193686e967..6c0e0b027376 100644 --- a/crates/hir-ty/src/infer/cast.rs +++ b/crates/hir-ty/src/infer/cast.rs @@ -43,7 +43,7 @@ impl CastTy { let (AdtId::EnumId(id), _) = t.as_adt()? else { return None; }; - let enum_data = table.db.enum_data(id); + let enum_data = table.db.enum_variants(id); if enum_data.is_payload_free(table.db.upcast()) { Some(Self::Int(Int::CEnum)) } else { diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs index ef02762c80a5..6c50f056c18a 100644 --- a/crates/hir-ty/src/infer/closure.rs +++ b/crates/hir-ty/src/infer/closure.rs @@ -963,7 +963,7 @@ impl InferenceContext<'_> { if let Some(variant) = self.result.variant_resolution_for_pat(p) { let adt = variant.adt_id(self.db.upcast()); let is_multivariant = match adt { - hir_def::AdtId::EnumId(e) => self.db.enum_data(e).variants.len() != 1, + hir_def::AdtId::EnumId(e) => self.db.enum_variants(e).variants.len() != 1, _ => false, }; if is_multivariant { diff --git a/crates/hir-ty/src/infer/path.rs b/crates/hir-ty/src/infer/path.rs index 29f455a61b94..8ff0cf308224 100644 --- a/crates/hir-ty/src/infer/path.rs +++ b/crates/hir-ty/src/infer/path.rs @@ -398,7 +398,7 @@ impl InferenceContext<'_> { Some((AdtId::EnumId(e), subst)) => (e, subst), _ => return None, }; - let enum_data = self.db.enum_data(enum_id); + let enum_data = self.db.enum_variants(enum_id); let variant = enum_data.variant(name)?; self.write_variant_resolution(id, variant.into()); Some((ValueNs::EnumVariantId(variant), subst.clone())) diff --git a/crates/hir-ty/src/inhabitedness.rs b/crates/hir-ty/src/inhabitedness.rs index d6039c548b6f..800ba0d45449 100644 --- a/crates/hir-ty/src/inhabitedness.rs +++ b/crates/hir-ty/src/inhabitedness.rs @@ -98,7 +98,7 @@ impl UninhabitedFrom<'_> { AdtId::UnionId(_) => CONTINUE_OPAQUELY_INHABITED, AdtId::StructId(s) => self.visit_variant(s.into(), subst), AdtId::EnumId(e) => { - let enum_data = self.db.enum_data(e); + let enum_data = self.db.enum_variants(e); for &(variant, _) in enum_data.variants.iter() { let variant_inhabitedness = self.visit_variant(variant.into(), subst); diff --git a/crates/hir-ty/src/layout/adt.rs b/crates/hir-ty/src/layout/adt.rs index ab9c07779c07..40a1d4e6707a 100644 --- a/crates/hir-ty/src/layout/adt.rs +++ b/crates/hir-ty/src/layout/adt.rs @@ -54,13 +54,13 @@ pub fn layout_of_adt_query( (r, data.repr.unwrap_or_default()) } AdtId::EnumId(e) => { - let data = db.enum_data(e); - let r = data + let variants = db.enum_variants(e); + let r = variants .variants .iter() .map(|&(v, _)| handle_variant(v.into(), &db.enum_variant_data(v).variant_data)) .collect::, _>>()?; - (r, data.repr.unwrap_or_default()) + (r, db.enum_data(e).repr.unwrap_or_default()) } }; let variants = variants @@ -80,7 +80,7 @@ pub fn layout_of_adt_query( |min, max| repr_discr(dl, &repr, min, max).unwrap_or((Integer::I8, false)), variants.iter_enumerated().filter_map(|(id, _)| { let AdtId::EnumId(e) = def else { return None }; - let d = db.const_eval_discriminant(db.enum_data(e).variants[id.0].0).ok()?; + let d = db.const_eval_discriminant(db.enum_variants(e).variants[id.0].0).ok()?; Some((id, d)) }), // FIXME: The current code for niche-filling relies on variant indices diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index 97710aab06c7..25aa2606558c 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -1641,7 +1641,8 @@ impl Evaluator<'_> { match &layout.variants { Variants::Empty => unreachable!(), Variants::Single { index } => { - let r = self.const_eval_discriminant(self.db.enum_data(e).variants[index.0].0)?; + let r = + self.const_eval_discriminant(self.db.enum_variants(e).variants[index.0].0)?; Ok(r) } Variants::Multiple { tag, tag_encoding, variants, .. } => { @@ -1666,7 +1667,7 @@ impl Evaluator<'_> { .unwrap_or(*untagged_variant) .0; let result = - self.const_eval_discriminant(self.db.enum_data(e).variants[idx].0)?; + self.const_eval_discriminant(self.db.enum_variants(e).variants[idx].0)?; Ok(result) } } diff --git a/crates/hir-ty/src/tests.rs b/crates/hir-ty/src/tests.rs index 9ad07922fac7..13d74264c560 100644 --- a/crates/hir-ty/src/tests.rs +++ b/crates/hir-ty/src/tests.rs @@ -481,7 +481,7 @@ pub(crate) fn visit_module( visit_body(db, &body, cb); } ModuleDefId::AdtId(hir_def::AdtId::EnumId(it)) => { - db.enum_data(it).variants.iter().for_each(|&(it, _)| { + db.enum_variants(it).variants.iter().for_each(|&(it, _)| { let body = db.body(it.into()); cb(it.into()); visit_body(db, &body, cb); diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs index cbb78ef40d84..3bd04b21b285 100644 --- a/crates/hir-ty/src/utils.rs +++ b/crates/hir-ty/src/utils.rs @@ -369,7 +369,7 @@ pub(crate) fn detect_variant_from_bytes<'a>( let (var_id, var_layout) = match &layout.variants { hir_def::layout::Variants::Empty => unreachable!(), hir_def::layout::Variants::Single { index } => { - (db.enum_data(e).variants[index.0].0, layout) + (db.enum_variants(e).variants[index.0].0, layout) } hir_def::layout::Variants::Multiple { tag, tag_encoding, variants, .. } => { let size = tag.size(target_data_layout).bytes_usize(); @@ -379,7 +379,7 @@ pub(crate) fn detect_variant_from_bytes<'a>( TagEncoding::Direct => { let (var_idx, layout) = variants.iter_enumerated().find_map(|(var_idx, v)| { - let def = db.enum_data(e).variants[var_idx.0].0; + let def = db.enum_variants(e).variants[var_idx.0].0; (db.const_eval_discriminant(def) == Ok(tag)).then_some((def, v)) })?; (var_idx, layout) @@ -392,7 +392,7 @@ pub(crate) fn detect_variant_from_bytes<'a>( .filter(|x| x != untagged_variant) .nth(candidate_tag) .unwrap_or(*untagged_variant); - (db.enum_data(e).variants[variant.0].0, &variants[variant]) + (db.enum_variants(e).variants[variant.0].0, &variants[variant]) } } } diff --git a/crates/hir-ty/src/variance.rs b/crates/hir-ty/src/variance.rs index 425196d92f79..ab3d09890889 100644 --- a/crates/hir-ty/src/variance.rs +++ b/crates/hir-ty/src/variance.rs @@ -206,7 +206,7 @@ impl Context<'_> { AdtId::StructId(s) => add_constraints_from_variant(VariantId::StructId(s)), AdtId::UnionId(u) => add_constraints_from_variant(VariantId::UnionId(u)), AdtId::EnumId(e) => { - db.enum_data(e).variants.iter().for_each(|&(variant, _)| { + db.enum_variants(e).variants.iter().for_each(|&(variant, _)| { add_constraints_from_variant(VariantId::EnumVariantId(variant)) }); } diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 5cc330fb38f3..f78b7a5c435c 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -1519,7 +1519,11 @@ impl Enum { } pub fn variants(self, db: &dyn HirDatabase) -> Vec { - db.enum_data(self.id).variants.iter().map(|&(id, _)| Variant { id }).collect() + db.enum_variants(self.id).variants.iter().map(|&(id, _)| Variant { id }).collect() + } + + pub fn num_variants(self, db: &dyn HirDatabase) -> usize { + db.enum_variants(self.id).variants.len() } pub fn repr(self, db: &dyn HirDatabase) -> Option { diff --git a/crates/hir/src/semantics/child_by_source.rs b/crates/hir/src/semantics/child_by_source.rs index 556b21124dd5..b89d332238b6 100644 --- a/crates/hir/src/semantics/child_by_source.rs +++ b/crates/hir/src/semantics/child_by_source.rs @@ -182,7 +182,7 @@ impl ChildBySource for EnumId { let tree = loc.id.item_tree(db); let ast_id_map = db.ast_id_map(loc.id.file_id()); - db.enum_data(*self).variants.iter().for_each(|&(variant, _)| { + db.enum_variants(*self).variants.iter().for_each(|&(variant, _)| { res[keys::ENUM_VARIANT] .insert(ast_id_map.get(tree[variant.lookup(db).id.value].ast_id), variant); }); diff --git a/crates/ide-completion/src/completions/pattern.rs b/crates/ide-completion/src/completions/pattern.rs index 8f38e02ed768..9df13c5a4ef5 100644 --- a/crates/ide-completion/src/completions/pattern.rs +++ b/crates/ide-completion/src/completions/pattern.rs @@ -1,6 +1,6 @@ //! Completes constants and paths in unqualified patterns. -use hir::{db::DefDatabase, AssocItem, ScopeDef}; +use hir::{AssocItem, ScopeDef}; use ide_db::syntax_helpers::suggest_name; use syntax::ast::Pat; @@ -60,7 +60,7 @@ pub(crate) fn complete_pattern( } let refutable = pattern_ctx.refutability == PatternRefutability::Refutable; - let single_variant_enum = |enum_: hir::Enum| ctx.db.enum_data(enum_.into()).variants.len() == 1; + let single_variant_enum = |enum_: hir::Enum| enum_.num_variants(ctx.db) == 1; if let Some(hir::Adt::Enum(e)) = ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt()) From 2ea09b2e478476d18af7b9aa8843bd3ac54f7149 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 27 Feb 2025 11:22:29 +0100 Subject: [PATCH 4/4] Split `variant_data` into its own query --- crates/hir-def/src/attr.rs | 2 +- crates/hir-def/src/data/adt.rs | 215 +++++++++--------- crates/hir-def/src/db.rs | 24 +- crates/hir-def/src/expr_store/lower.rs | 2 +- crates/hir-def/src/item_tree.rs | 2 +- crates/hir-def/src/item_tree/lower.rs | 2 +- crates/hir-def/src/item_tree/pretty.rs | 7 +- crates/hir-def/src/lib.rs | 6 +- crates/hir-def/src/resolver.rs | 9 +- crates/hir-def/src/src.rs | 2 +- crates/hir-ty/src/chalk_db.rs | 2 +- crates/hir-ty/src/diagnostics/decl_check.rs | 8 +- crates/hir-ty/src/display.rs | 4 +- crates/hir-ty/src/infer/cast.rs | 4 +- crates/hir-ty/src/infer/closure.rs | 4 +- crates/hir-ty/src/infer/expr.rs | 12 +- crates/hir-ty/src/infer/unify.rs | 5 +- crates/hir-ty/src/layout.rs | 8 +- crates/hir-ty/src/layout/adt.rs | 6 +- crates/hir-ty/src/lower.rs | 26 +-- crates/hir-ty/src/mir/eval.rs | 10 +- crates/hir-ty/src/mir/eval/shim/simd.rs | 4 +- crates/hir-ty/src/mir/lower.rs | 5 +- .../hir-ty/src/mir/lower/pattern_matching.rs | 4 +- crates/hir/src/lib.rs | 23 +- crates/ide-db/src/apply_change.rs | 4 +- 26 files changed, 189 insertions(+), 211 deletions(-) diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index 030d064584cd..2775e1398c28 100644 --- a/crates/hir-def/src/attr.rs +++ b/crates/hir-def/src/attr.rs @@ -84,7 +84,7 @@ impl Attrs { let krate = loc.parent.lookup(db).container.krate; item_tree = loc.id.item_tree(db); let variant = &item_tree[loc.id.value]; - (FieldParent::Variant(loc.id.value), &variant.fields, krate) + (FieldParent::EnumVariant(loc.id.value), &variant.fields, krate) } VariantId::StructId(it) => { let loc = it.lookup(db); diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs index c8429d8b6897..9db66d6e91c9 100644 --- a/crates/hir-def/src/data/adt.rs +++ b/crates/hir-def/src/data/adt.rs @@ -27,7 +27,6 @@ use crate::{ #[derive(Debug, Clone, PartialEq, Eq)] pub struct StructData { pub name: Name, - pub variant_data: Arc, pub repr: Option, pub visibility: RawVisibility, pub flags: StructFlags, @@ -69,7 +68,6 @@ pub struct EnumVariants { #[derive(Debug, Clone, PartialEq, Eq)] pub struct EnumVariantData { pub name: Name, - pub variant_data: Arc, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -79,6 +77,94 @@ pub enum VariantData { Unit, } +impl VariantData { + #[inline] + pub(crate) fn variant_data_query(db: &dyn DefDatabase, id: VariantId) -> Arc { + db.variant_data_with_diagnostics(id).0 + } + + pub(crate) fn variant_data_with_diagnostics_query( + db: &dyn DefDatabase, + id: VariantId, + ) -> (Arc, DefDiagnostics) { + let (shape, types_map, (fields, diagnostics)) = match id { + VariantId::EnumVariantId(id) => { + let loc = id.lookup(db); + let item_tree = loc.id.item_tree(db); + let parent = loc.parent.lookup(db); + let krate = parent.container.krate; + let variant = &item_tree[loc.id.value]; + ( + variant.shape, + variant.types_map.clone(), + lower_fields( + db, + krate, + parent.container.local_id, + loc.id.tree_id(), + &item_tree, + krate.cfg_options(db), + FieldParent::EnumVariant(loc.id.value), + &variant.fields, + Some(item_tree[parent.id.value].visibility), + ), + ) + } + VariantId::StructId(id) => { + let loc = id.lookup(db); + let item_tree = loc.id.item_tree(db); + let krate = loc.container.krate; + let strukt = &item_tree[loc.id.value]; + ( + strukt.shape, + strukt.types_map.clone(), + lower_fields( + db, + krate, + loc.container.local_id, + loc.id.tree_id(), + &item_tree, + krate.cfg_options(db), + FieldParent::Struct(loc.id.value), + &strukt.fields, + None, + ), + ) + } + VariantId::UnionId(id) => { + let loc = id.lookup(db); + let item_tree = loc.id.item_tree(db); + let krate = loc.container.krate; + let union = &item_tree[loc.id.value]; + ( + FieldsShape::Record, + union.types_map.clone(), + lower_fields( + db, + krate, + loc.container.local_id, + loc.id.tree_id(), + &item_tree, + krate.cfg_options(db), + FieldParent::Union(loc.id.value), + &union.fields, + None, + ), + ) + } + }; + + ( + Arc::new(match shape { + FieldsShape::Record => VariantData::Record { fields, types_map }, + FieldsShape::Tuple => VariantData::Tuple { fields, types_map }, + FieldsShape::Unit => VariantData::Unit, + }), + DefDiagnostics::new(diagnostics), + ) + } +} + /// A single field of an enum variant or struct #[derive(Debug, Clone, PartialEq, Eq)] pub struct FieldData { @@ -99,13 +185,6 @@ fn repr_from_value( impl StructData { #[inline] pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc { - db.struct_data_with_diagnostics(id).0 - } - - pub(crate) fn struct_data_with_diagnostics_query( - db: &dyn DefDatabase, - id: StructId, - ) -> (Arc, DefDiagnostics) { let loc = id.lookup(db); let krate = loc.container.krate; let item_tree = loc.id.item_tree(db); @@ -130,44 +209,16 @@ impl StructData { } let strukt = &item_tree[loc.id.value]; - let (fields, diagnostics) = lower_fields( - db, - krate, - loc.container.local_id, - loc.id.tree_id(), - &item_tree, - krate.cfg_options(db), - FieldParent::Struct(loc.id.value), - &strukt.fields, - None, - ); - let types_map = strukt.types_map.clone(); - - ( - Arc::new(StructData { - name: strukt.name.clone(), - variant_data: Arc::new(match strukt.shape { - FieldsShape::Record => VariantData::Record { fields, types_map }, - FieldsShape::Tuple => VariantData::Tuple { fields, types_map }, - FieldsShape::Unit => VariantData::Unit, - }), - repr, - visibility: item_tree[strukt.visibility].clone(), - flags, - }), - DefDiagnostics::new(diagnostics), - ) + Arc::new(StructData { + name: strukt.name.clone(), + repr, + visibility: item_tree[strukt.visibility].clone(), + flags, + }) } #[inline] pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc { - db.union_data_with_diagnostics(id).0 - } - - pub(crate) fn union_data_with_diagnostics_query( - db: &dyn DefDatabase, - id: UnionId, - ) -> (Arc, DefDiagnostics) { let loc = id.lookup(db); let krate = loc.container.krate; let item_tree = loc.id.item_tree(db); @@ -182,28 +233,13 @@ impl StructData { } let union = &item_tree[loc.id.value]; - let (fields, diagnostics) = lower_fields( - db, - krate, - loc.container.local_id, - loc.id.tree_id(), - &item_tree, - krate.cfg_options(db), - FieldParent::Union(loc.id.value), - &union.fields, - None, - ); - let types_map = union.types_map.clone(); - ( - Arc::new(StructData { - name: union.name.clone(), - variant_data: Arc::new(VariantData::Record { fields, types_map }), - repr, - visibility: item_tree[union.visibility].clone(), - flags, - }), - DefDiagnostics::new(diagnostics), - ) + + Arc::new(StructData { + name: union.name.clone(), + repr, + visibility: item_tree[union.visibility].clone(), + flags, + }) } } @@ -227,16 +263,16 @@ impl EnumVariants { // [Adopted from rustc](https://github.com/rust-lang/rust/blob/bd53aa3bf7a24a70d763182303bd75e5fc51a9af/compiler/rustc_middle/src/ty/adt.rs#L446-L448) pub fn is_payload_free(&self, db: &dyn DefDatabase) -> bool { - self.variants.iter().all(|(v, _)| { + self.variants.iter().all(|&(v, _)| { // The condition check order is slightly modified from rustc // to improve performance by early returning with relatively fast checks - let variant = &db.enum_variant_data(*v).variant_data; + let variant = &db.variant_data(v.into()); if !variant.fields().is_empty() { return false; } // The outer if condition is whether this variant has const ctor or not if !matches!(variant.kind(), StructKind::Unit) { - let body = db.body((*v).into()); + let body = db.body(v.into()); // A variant with explicit discriminant if body.exprs[body.body_expr] != Expr::Missing { return false; @@ -282,43 +318,11 @@ impl EnumVariantData { db: &dyn DefDatabase, e: EnumVariantId, ) -> Arc { - db.enum_variant_data_with_diagnostics(e).0 - } - - pub(crate) fn enum_variant_data_with_diagnostics_query( - db: &dyn DefDatabase, - e: EnumVariantId, - ) -> (Arc, DefDiagnostics) { let loc = e.lookup(db); - let container = loc.parent.lookup(db).container; - let krate = container.krate; let item_tree = loc.id.item_tree(db); let variant = &item_tree[loc.id.value]; - let (fields, diagnostics) = lower_fields( - db, - krate, - container.local_id, - loc.id.tree_id(), - &item_tree, - krate.cfg_options(db), - FieldParent::Variant(loc.id.value), - &variant.fields, - Some(item_tree[loc.parent.lookup(db).id.value].visibility), - ); - let types_map = variant.types_map.clone(); - - ( - Arc::new(EnumVariantData { - name: variant.name.clone(), - variant_data: Arc::new(match variant.shape { - FieldsShape::Record => VariantData::Record { fields, types_map }, - FieldsShape::Tuple => VariantData::Tuple { fields, types_map }, - FieldsShape::Unit => VariantData::Unit, - }), - }), - DefDiagnostics::new(diagnostics), - ) + Arc::new(EnumVariantData { name: variant.name.clone() }) } } @@ -352,15 +356,6 @@ impl VariantData { VariantData::Unit => StructKind::Unit, } } - - #[allow(clippy::self_named_constructors)] - pub(crate) fn variant_data(db: &dyn DefDatabase, id: VariantId) -> Arc { - match id { - VariantId::StructId(it) => db.struct_data(it).variant_data.clone(), - VariantId::EnumVariantId(it) => db.enum_variant_data(it).variant_data.clone(), - VariantId::UnionId(it) => db.union_data(it).variant_data.clone(), - } - } } #[derive(Debug, Copy, Clone, PartialEq, Eq)] diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs index bc9fc8e07930..108968fe52e2 100644 --- a/crates/hir-def/src/db.rs +++ b/crates/hir-def/src/db.rs @@ -151,39 +151,27 @@ pub trait DefDatabase: // region:data #[salsa::transparent] + #[salsa::invoke_actual(VariantData::variant_data_query)] + fn variant_data(&self, id: VariantId) -> Arc; + + #[salsa::invoke_actual(VariantData::variant_data_with_diagnostics_query)] + fn variant_data_with_diagnostics(&self, id: VariantId) -> (Arc, DefDiagnostics); + #[salsa::invoke_actual(StructData::struct_data_query)] fn struct_data(&self, id: StructId) -> Arc; - #[salsa::invoke_actual(StructData::struct_data_with_diagnostics_query)] - fn struct_data_with_diagnostics(&self, id: StructId) -> (Arc, DefDiagnostics); - - #[salsa::transparent] #[salsa::invoke_actual(StructData::union_data_query)] fn union_data(&self, id: UnionId) -> Arc; - #[salsa::invoke_actual(StructData::union_data_with_diagnostics_query)] - fn union_data_with_diagnostics(&self, id: UnionId) -> (Arc, DefDiagnostics); - #[salsa::invoke_actual(EnumData::enum_data_query)] fn enum_data(&self, e: EnumId) -> Arc; #[salsa::invoke_actual(EnumVariants::enum_variants_query)] fn enum_variants(&self, e: EnumId) -> Arc; - #[salsa::transparent] #[salsa::invoke_actual(EnumVariantData::enum_variant_data_query)] fn enum_variant_data(&self, id: EnumVariantId) -> Arc; - #[salsa::invoke_actual(EnumVariantData::enum_variant_data_with_diagnostics_query)] - fn enum_variant_data_with_diagnostics( - &self, - id: EnumVariantId, - ) -> (Arc, DefDiagnostics); - - #[salsa::transparent] - #[salsa::invoke_actual(VariantData::variant_data)] - fn variant_data(&self, id: VariantId) -> Arc; - #[salsa::invoke_actual(ImplData::impl_data_query)] fn impl_data(&self, e: ImplId) -> Arc; diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs index c346cec242eb..b9b00108dcd2 100644 --- a/crates/hir-def/src/expr_store/lower.rs +++ b/crates/hir-def/src/expr_store/lower.rs @@ -1631,7 +1631,7 @@ impl ExprCollector<'_> { (None, Pat::Path(name.into())) } Some(ModuleDefId::AdtId(AdtId::StructId(s))) - if self.db.struct_data(s).variant_data.kind() != StructKind::Record => + if self.db.variant_data(s.into()).kind() != StructKind::Record => { (None, Pat::Path(name.into())) } diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 9acf98e62cd5..d42104faa2e0 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -506,7 +506,7 @@ impl AttrOwner { pub enum FieldParent { Struct(FileItemTreeId), Union(FileItemTreeId), - Variant(FileItemTreeId), + EnumVariant(FileItemTreeId), } pub type ItemTreeParamId = Idx; diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index b0546d4f33fd..05b99ae31f42 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -428,7 +428,7 @@ impl<'a> Ctx<'a> { for (idx, attr) in attrs { self.add_attrs( AttrOwner::Field( - FieldParent::Variant(FileItemTreeId(id)), + FieldParent::EnumVariant(FileItemTreeId(id)), Idx::from_raw(RawIdx::from_u32(idx as u32)), ), attr, diff --git a/crates/hir-def/src/item_tree/pretty.rs b/crates/hir-def/src/item_tree/pretty.rs index d113a500ef76..e666b1ea6bc2 100644 --- a/crates/hir-def/src/item_tree/pretty.rs +++ b/crates/hir-def/src/item_tree/pretty.rs @@ -382,7 +382,12 @@ impl Printer<'_> { this.print_ast_id(ast_id.erase()); this.print_attrs_of(variant, "\n"); w!(this, "{}", name.display(self.db.upcast(), edition)); - this.print_fields(FieldParent::Variant(variant), *kind, fields, types_map); + this.print_fields( + FieldParent::EnumVariant(variant), + *kind, + fields, + types_map, + ); wln!(this, ","); } }); diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index fbbeb4beb99b..5f8cd0fde04a 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -1104,11 +1104,7 @@ impl_from!(EnumVariantId, StructId, UnionId for VariantId); impl VariantId { pub fn variant_data(self, db: &dyn DefDatabase) -> Arc { - match self { - VariantId::StructId(it) => db.struct_data(it).variant_data.clone(), - VariantId::UnionId(it) => db.union_data(it).variant_data.clone(), - VariantId::EnumVariantId(it) => db.enum_variant_data(it).variant_data.clone(), - } + db.variant_data(self) } pub fn file_id(self, db: &dyn DefDatabase) -> HirFileId { diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index 72723499fc97..0ed26ca853e8 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -276,11 +276,16 @@ impl Resolver { db: &dyn DefDatabase, visibility: &RawVisibility, ) -> Option { - let within_impl = self.scopes().any(|scope| matches!(scope, Scope::ImplDefScope(_))); match visibility { RawVisibility::Module(_, _) => { let (item_map, item_local_map, module) = self.item_scope(); - item_map.resolve_visibility(item_local_map, db, module, visibility, within_impl) + item_map.resolve_visibility( + item_local_map, + db, + module, + visibility, + self.scopes().any(|scope| matches!(scope, Scope::ImplDefScope(_))), + ) } RawVisibility::Public => Some(Visibility::Public), } diff --git a/crates/hir-def/src/src.rs b/crates/hir-def/src/src.rs index 43d31aa503ce..347c4803be1c 100644 --- a/crates/hir-def/src/src.rs +++ b/crates/hir-def/src/src.rs @@ -131,7 +131,7 @@ impl HasChildSource for VariantId { item_tree = lookup.id.item_tree(db); ( lookup.source(db).map(|it| it.kind()), - FieldParent::Variant(lookup.id.value), + FieldParent::EnumVariant(lookup.id.value), lookup.parent.lookup(db).container, ) } diff --git a/crates/hir-ty/src/chalk_db.rs b/crates/hir-ty/src/chalk_db.rs index ac4d1babd62b..acaca24f54f9 100644 --- a/crates/hir-ty/src/chalk_db.rs +++ b/crates/hir-ty/src/chalk_db.rs @@ -137,7 +137,7 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { let fps: &[TyFingerprint] = match binder_kind(&ty, binders) { Some(chalk_ir::TyVariableKind::Integer) => &ALL_INT_FPS, Some(chalk_ir::TyVariableKind::Float) => &ALL_FLOAT_FPS, - _ => self_ty_fp.as_ref().map(std::slice::from_ref).unwrap_or(&[]), + _ => self_ty_fp.as_slice(), }; let id_to_chalk = |id: hir_def::ImplId| id.to_chalk(self.db); diff --git a/crates/hir-ty/src/diagnostics/decl_check.rs b/crates/hir-ty/src/diagnostics/decl_check.rs index 0b21ae7ade37..5106056d4097 100644 --- a/crates/hir-ty/src/diagnostics/decl_check.rs +++ b/crates/hir-ty/src/diagnostics/decl_check.rs @@ -307,8 +307,8 @@ impl<'a> DeclValidator<'a> { /// Check incorrect names for struct fields. fn validate_struct_fields(&mut self, struct_id: StructId) { - let data = self.db.struct_data(struct_id); - let VariantData::Record { fields, .. } = data.variant_data.as_ref() else { + let data = self.db.variant_data(struct_id.into()); + let VariantData::Record { fields, .. } = data.as_ref() else { return; }; let edition = self.edition(struct_id); @@ -467,8 +467,8 @@ impl<'a> DeclValidator<'a> { /// Check incorrect names for fields of enum variant. fn validate_enum_variant_fields(&mut self, variant_id: EnumVariantId) { - let variant_data = self.db.enum_variant_data(variant_id); - let VariantData::Record { fields, .. } = variant_data.variant_data.as_ref() else { + let variant_data = self.db.variant_data(variant_id.into()); + let VariantData::Record { fields, .. } = variant_data.as_ref() else { return; }; let edition = self.edition(variant_id); diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index be590b6101d6..7bce23f398a6 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -846,7 +846,7 @@ fn render_const_scalar( write!(f, "{}", data.name.display(f.db.upcast(), f.edition()))?; let field_types = f.db.field_types(s.into()); render_variant_after_name( - &data.variant_data, + &f.db.variant_data(s.into()), f, &field_types, f.db.trait_environment(adt.0.into()), @@ -872,7 +872,7 @@ fn render_const_scalar( write!(f, "{}", data.name.display(f.db.upcast(), f.edition()))?; let field_types = f.db.field_types(var_id.into()); render_variant_after_name( - &data.variant_data, + &f.db.variant_data(var_id.into()), f, &field_types, f.db.trait_environment(adt.0.into()), diff --git a/crates/hir-ty/src/infer/cast.rs b/crates/hir-ty/src/infer/cast.rs index 6c0e0b027376..8b43d0188a9d 100644 --- a/crates/hir-ty/src/infer/cast.rs +++ b/crates/hir-ty/src/infer/cast.rs @@ -389,8 +389,8 @@ fn pointer_kind(ty: &Ty, table: &mut InferenceTable<'_>) -> Result { self.consume_place(place) } VariantId::StructId(s) => { - let vd = &*self.db.struct_data(s).variant_data; + let vd = &*self.db.variant_data(s.into()); for field_pat in args.iter() { let arg = field_pat.pat; let Some(local_id) = vd.field(&field_pat.name) else { @@ -1211,7 +1211,7 @@ impl InferenceContext<'_> { self.consume_place(place) } VariantId::StructId(s) => { - let vd = &*self.db.struct_data(s).variant_data; + let vd = &*self.db.variant_data(s.into()); let (al, ar) = args.split_at(ellipsis.map_or(args.len(), |it| it as usize)); let fields = vd.fields().iter(); diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index d0936185957f..d0cbce70a2f1 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -1681,14 +1681,14 @@ impl InferenceContext<'_> { }) }); } - TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { - let local_id = self.db.struct_data(*s).variant_data.field(name)?; - let field = FieldId { parent: (*s).into(), local_id }; + &TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), ref parameters) => { + let local_id = self.db.variant_data(s.into()).field(name)?; + let field = FieldId { parent: s.into(), local_id }; (field, parameters.clone()) } - TyKind::Adt(AdtId(hir_def::AdtId::UnionId(u)), parameters) => { - let local_id = self.db.union_data(*u).variant_data.field(name)?; - let field = FieldId { parent: (*u).into(), local_id }; + &TyKind::Adt(AdtId(hir_def::AdtId::UnionId(u)), ref parameters) => { + let local_id = self.db.variant_data(u.into()).field(name)?; + let field = FieldId { parent: u.into(), local_id }; (field, parameters.clone()) } _ => return None, diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs index a9332a5a9637..e55fc0a9b83d 100644 --- a/crates/hir-ty/src/infer/unify.rs +++ b/crates/hir-ty/src/infer/unify.rs @@ -928,9 +928,8 @@ impl<'a> InferenceTable<'a> { // Must use a loop here and not recursion because otherwise users will conduct completely // artificial examples of structs that have themselves as the tail field and complain r-a crashes. while let Some((AdtId::StructId(id), subst)) = ty.as_adt() { - let struct_data = self.db.struct_data(id); - if let Some((last_field, _)) = struct_data.variant_data.fields().iter().next_back() - { + let struct_data = self.db.variant_data(id.into()); + if let Some((last_field, _)) = struct_data.fields().iter().next_back() { let last_field_ty = self.db.field_types(id.into())[last_field] .clone() .substitute(Interner, subst); diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs index 167dcec3bb3f..2f7ad2b99d25 100644 --- a/crates/hir-ty/src/layout.rs +++ b/crates/hir-ty/src/layout.rs @@ -377,12 +377,12 @@ pub(crate) fn layout_of_ty_recover( fn struct_tail_erasing_lifetimes(db: &dyn HirDatabase, pointee: Ty) -> Ty { match pointee.kind(Interner) { - TyKind::Adt(AdtId(hir_def::AdtId::StructId(i)), subst) => { - let data = db.struct_data(*i); - let mut it = data.variant_data.fields().iter().rev(); + &TyKind::Adt(AdtId(hir_def::AdtId::StructId(i)), ref subst) => { + let data = db.variant_data(i.into()); + let mut it = data.fields().iter().rev(); match it.next() { Some((f, _)) => { - let last_field_ty = field_ty(db, (*i).into(), f, subst); + let last_field_ty = field_ty(db, i.into(), f, subst); struct_tail_erasing_lifetimes(db, last_field_ty) } None => pointee, diff --git a/crates/hir-ty/src/layout/adt.rs b/crates/hir-ty/src/layout/adt.rs index 40a1d4e6707a..9f453162e30c 100644 --- a/crates/hir-ty/src/layout/adt.rs +++ b/crates/hir-ty/src/layout/adt.rs @@ -44,13 +44,13 @@ pub fn layout_of_adt_query( AdtId::StructId(s) => { let data = db.struct_data(s); let mut r = SmallVec::<[_; 1]>::new(); - r.push(handle_variant(s.into(), &data.variant_data)?); + r.push(handle_variant(s.into(), &db.variant_data(s.into()))?); (r, data.repr.unwrap_or_default()) } AdtId::UnionId(id) => { let data = db.union_data(id); let mut r = SmallVec::new(); - r.push(handle_variant(id.into(), &data.variant_data)?); + r.push(handle_variant(id.into(), &db.variant_data(id.into()))?); (r, data.repr.unwrap_or_default()) } AdtId::EnumId(e) => { @@ -58,7 +58,7 @@ pub fn layout_of_adt_query( let r = variants .variants .iter() - .map(|&(v, _)| handle_variant(v.into(), &db.enum_variant_data(v).variant_data)) + .map(|&(v, _)| handle_variant(v.into(), &db.variant_data(v.into()))) .collect::, _>>()?; (r, db.enum_data(e).repr.unwrap_or_default()) } diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 33e852aaee46..12f3a1138fcc 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -1491,16 +1491,12 @@ fn type_for_static(db: &dyn HirDatabase, def: StaticId) -> Binders { } fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnSig { - let struct_data = db.struct_data(def); - let fields = struct_data.variant_data.fields(); + let struct_data = db.variant_data(def.into()); + let fields = struct_data.fields(); let resolver = def.resolver(db.upcast()); - let mut ctx = TyLoweringContext::new( - db, - &resolver, - struct_data.variant_data.types_map(), - AdtId::from(def).into(), - ) - .with_type_param_mode(ParamLoweringMode::Variable); + let mut ctx = + TyLoweringContext::new(db, &resolver, struct_data.types_map(), AdtId::from(def).into()) + .with_type_param_mode(ParamLoweringMode::Variable); let params = fields.iter().map(|(_, field)| ctx.lower_ty(field.type_ref)); let (ret, binders) = type_for_adt(db, def.into()).into_value_and_skipped_binders(); Binders::new( @@ -1511,8 +1507,8 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS /// Build the type of a tuple struct constructor. fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Option> { - let struct_data = db.struct_data(def); - match struct_data.variant_data.kind() { + let struct_data = db.variant_data(def.into()); + match struct_data.kind() { StructKind::Record => None, StructKind::Unit => Some(type_for_adt(db, def.into())), StructKind::Tuple => { @@ -1528,13 +1524,13 @@ fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Option PolyFnSig { - let var_data = db.enum_variant_data(def); - let fields = var_data.variant_data.fields(); + let var_data = db.variant_data(def.into()); + let fields = var_data.fields(); let resolver = def.resolver(db.upcast()); let mut ctx = TyLoweringContext::new( db, &resolver, - var_data.variant_data.types_map(), + var_data.types_map(), DefWithBodyId::VariantId(def).into(), ) .with_type_param_mode(ParamLoweringMode::Variable); @@ -1553,7 +1549,7 @@ fn type_for_enum_variant_constructor( def: EnumVariantId, ) -> Option> { let e = def.lookup(db.upcast()).parent; - match db.enum_variant_data(def).variant_data.kind() { + match db.variant_data(def.into()).kind() { StructKind::Record => None, StructKind::Unit => Some(type_for_adt(db, e.into())), StructKind::Tuple => { diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index 25aa2606558c..45b438556819 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -1761,7 +1761,7 @@ impl Evaluator<'_> { AdtId::EnumId(_) => not_supported!("unsizing enums"), }; let Some((last_field, _)) = - self.db.struct_data(id).variant_data.fields().iter().next_back() + self.db.variant_data(id.into()).fields().iter().next_back() else { not_supported!("unsizing struct without field"); }; @@ -2243,10 +2243,10 @@ impl Evaluator<'_> { } chalk_ir::TyKind::Adt(adt, subst) => match adt.0 { AdtId::StructId(s) => { - let data = this.db.struct_data(s); + let data = this.db.variant_data(s.into()); let layout = this.layout(ty)?; let field_types = this.db.field_types(s.into()); - for (f, _) in data.variant_data.fields().iter() { + for (f, _) in data.fields().iter() { let offset = layout .fields .offset(u32::from(f.into_raw()) as usize) @@ -2272,7 +2272,7 @@ impl Evaluator<'_> { bytes, e, ) { - let data = &this.db.enum_variant_data(v).variant_data; + let data = &this.db.variant_data(v.into()); let field_types = this.db.field_types(v.into()); for (f, _) in data.fields().iter() { let offset = @@ -2851,7 +2851,7 @@ impl Evaluator<'_> { return Ok(()); } let layout = self.layout_adt(id.0, subst.clone())?; - match data.variant_data.as_ref() { + match self.db.variant_data(s.into()).as_ref() { VariantData::Record { fields, .. } | VariantData::Tuple { fields, .. } => { let field_types = self.db.field_types(s.into()); diff --git a/crates/hir-ty/src/mir/eval/shim/simd.rs b/crates/hir-ty/src/mir/eval/shim/simd.rs index e229a4ab3172..829ed9efa2bc 100644 --- a/crates/hir-ty/src/mir/eval/shim/simd.rs +++ b/crates/hir-ty/src/mir/eval/shim/simd.rs @@ -31,8 +31,8 @@ impl Evaluator<'_> { Some(len) => len, _ => { if let AdtId::StructId(id) = id.0 { - let struct_data = self.db.struct_data(id); - let fields = struct_data.variant_data.fields(); + let struct_data = self.db.variant_data(id.into()); + let fields = struct_data.fields(); let Some((first_field, _)) = fields.iter().next() else { not_supported!("simd type with no field"); }; diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index 57d4baa137ce..102048b3f4dc 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -499,7 +499,7 @@ impl<'ctx> MirLowerCtx<'ctx> { Ok(Some(current)) } ValueNs::EnumVariantId(variant_id) => { - let variant_data = &self.db.enum_variant_data(variant_id).variant_data; + let variant_data = &self.db.variant_data(variant_id.into()); if variant_data.kind() == StructKind::Unit { let ty = self.infer.type_of_expr[expr_id].clone(); current = self.lower_enum_variant( @@ -1165,8 +1165,7 @@ impl<'ctx> MirLowerCtx<'ctx> { Rvalue::Aggregate( AggregateKind::Adt(st.into(), subst.clone()), self.db - .struct_data(st) - .variant_data + .variant_data(st.into()) .fields() .iter() .map(|it| { diff --git a/crates/hir-ty/src/mir/lower/pattern_matching.rs b/crates/hir-ty/src/mir/lower/pattern_matching.rs index 783f92b2043f..1c6dc4fecd81 100644 --- a/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/crates/hir-ty/src/mir/lower/pattern_matching.rs @@ -597,7 +597,7 @@ impl MirLowerCtx<'_> { } self.pattern_matching_variant_fields( shape, - &self.db.enum_variant_data(v).variant_data, + &self.db.variant_data(v.into()), variant, current, current_else, @@ -607,7 +607,7 @@ impl MirLowerCtx<'_> { } VariantId::StructId(s) => self.pattern_matching_variant_fields( shape, - &self.db.struct_data(s).variant_data, + &self.db.variant_data(s.into()), variant, current, current_else, diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index f78b7a5c435c..9f91f155ea77 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -661,8 +661,7 @@ impl Module { db.field_types_with_diagnostics(s.id.into()).1, tree_source_maps.strukt(tree_id.value).item(), ); - - for diag in db.struct_data_with_diagnostics(s.id).1.iter() { + for diag in db.variant_data_with_diagnostics(s.id.into()).1.iter() { emit_def_diagnostic(db, acc, diag, edition); } } @@ -675,8 +674,7 @@ impl Module { db.field_types_with_diagnostics(u.id.into()).1, tree_source_maps.union(tree_id.value).item(), ); - - for diag in db.union_data_with_diagnostics(u.id).1.iter() { + for diag in db.variant_data_with_diagnostics(u.id.into()).1.iter() { emit_def_diagnostic(db, acc, diag, edition); } } @@ -692,7 +690,7 @@ impl Module { tree_source_maps.variant(tree_id.value), ); acc.extend(ModuleDef::Variant(v).diagnostics(db, style_lints)); - for diag in db.enum_variant_data_with_diagnostics(v.id).1.iter() { + for diag in db.variant_data_with_diagnostics(v.id.into()).1.iter() { emit_def_diagnostic(db, acc, diag, edition); } } @@ -1059,7 +1057,7 @@ fn emit_def_diagnostic_( AttrOwner::Variant(it) => { ast_id_map.get(item_tree[it].ast_id).syntax_node_ptr() } - AttrOwner::Field(FieldParent::Variant(parent), idx) => process_field_list( + AttrOwner::Field(FieldParent::EnumVariant(parent), idx) => process_field_list( ast_id_map .get(item_tree[parent].ast_id) .to_node(&db.parse_or_expand(tree.file_id())) @@ -1392,6 +1390,7 @@ impl HasVisibility for Field { let variant_data = self.parent.variant_data(db); let visibility = &variant_data.fields()[self.id].visibility; let parent_id: hir_def::VariantId = self.parent.into(); + // FIXME: RawVisibility::Public doesn't need to construct a resolver visibility.resolve(db.upcast(), &parent_id.resolver(db.upcast())) } } @@ -1411,8 +1410,7 @@ impl Struct { } pub fn fields(self, db: &dyn HirDatabase) -> Vec { - db.struct_data(self.id) - .variant_data + db.variant_data(self.id.into()) .fields() .iter() .map(|(id, _)| Field { parent: self.into(), id }) @@ -1440,7 +1438,7 @@ impl Struct { } fn variant_data(self, db: &dyn HirDatabase) -> Arc { - db.struct_data(self.id).variant_data.clone() + db.variant_data(self.id.into()).clone() } pub fn is_unstable(self, db: &dyn HirDatabase) -> bool { @@ -1481,8 +1479,7 @@ impl Union { } pub fn fields(self, db: &dyn HirDatabase) -> Vec { - db.union_data(self.id) - .variant_data + db.variant_data(self.id.into()) .fields() .iter() .map(|(id, _)| Field { parent: self.into(), id }) @@ -1490,7 +1487,7 @@ impl Union { } fn variant_data(self, db: &dyn HirDatabase) -> Arc { - db.union_data(self.id).variant_data.clone() + db.variant_data(self.id.into()).clone() } pub fn is_unstable(self, db: &dyn HirDatabase) -> bool { @@ -1633,7 +1630,7 @@ impl Variant { } pub(crate) fn variant_data(self, db: &dyn HirDatabase) -> Arc { - db.enum_variant_data(self.id).variant_data.clone() + db.variant_data(self.id.into()).clone() } pub fn value(self, db: &dyn HirDatabase) -> Option { diff --git a/crates/ide-db/src/apply_change.rs b/crates/ide-db/src/apply_change.rs index 6b08ada34b60..4e058bb0106a 100644 --- a/crates/ide-db/src/apply_change.rs +++ b/crates/ide-db/src/apply_change.rs @@ -149,7 +149,6 @@ impl RootDatabase { // hir::db::CrateNotableTraitsQuery // hir::db::CrateSupportsNoStdQuery // hir::db::EnumDataQuery - // hir::db::EnumVariantDataWithDiagnosticsQuery // hir::db::ExpandProcAttrMacrosQuery // hir::db::ExprScopesQuery // hir::db::ExternCrateDeclDataQuery @@ -191,11 +190,10 @@ impl RootDatabase { // hir::db::NotableTraitsInDepsQuery // hir::db::ProcMacroDataQuery // hir::db::StaticDataQuery - // hir::db::StructDataWithDiagnosticsQuery // hir::db::TraitAliasDataQuery // hir::db::TraitItemsWithDiagnosticsQuery // hir::db::TypeAliasDataQuery - // hir::db::UnionDataWithDiagnosticsQuery + // hir::db::VariantDataWithDiagnosticsQuery // // InternDatabase // hir::db::InternFunctionQuery