From 3ab1519cb27b927074ed7fbbb18a856e6e7fabb8 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 23 Jan 2019 23:14:13 +0300 Subject: [PATCH 01/26] Change ids strategy this is a part of larghish hir refactoring which aims to * replace per-source-root module trees with per crate trees * switch from a monotyped DedId to type-specific ids --- crates/ra_db/src/input.rs | 12 ++ crates/ra_db/src/lib.rs | 2 +- crates/ra_hir/src/adt.rs | 2 +- crates/ra_hir/src/code_model_api.rs | 32 +++- crates/ra_hir/src/code_model_impl/krate.rs | 24 +-- crates/ra_hir/src/code_model_impl/module.rs | 178 +++++++----------- crates/ra_hir/src/db.rs | 36 +--- crates/ra_hir/src/ids.rs | 22 +-- crates/ra_hir/src/impl_block.rs | 25 +-- crates/ra_hir/src/lib.rs | 2 +- crates/ra_hir/src/mock.rs | 13 +- crates/ra_hir/src/module_tree.rs | 36 ++-- crates/ra_hir/src/nameres.rs | 56 +++--- crates/ra_hir/src/nameres/lower.rs | 74 +++----- crates/ra_hir/src/nameres/tests.rs | 35 ++-- crates/ra_hir/src/query_definitions.rs | 20 +- crates/ra_hir/src/source_binder.rs | 28 +-- crates/ra_hir/src/ty.rs | 21 ++- crates/ra_hir/src/ty/method_resolution.rs | 26 ++- .../src/completion/complete_path.rs | 37 ++-- .../src/completion/completion_item.rs | 61 +++--- crates/ra_ide_api/src/db.rs | 1 + crates/ra_ide_api/src/goto_definition.rs | 4 +- crates/ra_ide_api/src/navigation_target.rs | 13 +- crates/ra_ide_api/src/rename.rs | 25 +-- .../src/snapshots/tests__rename_mod.snap | 10 +- 26 files changed, 365 insertions(+), 430 deletions(-) diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs index b5d63e8201..9825d52cfc 100644 --- a/crates/ra_db/src/input.rs +++ b/crates/ra_db/src/input.rs @@ -160,6 +160,7 @@ pub trait FilesDatabase: salsa::Database { /// Contents of the source root. #[salsa::input] fn source_root(&self, id: SourceRootId) -> Arc; + fn source_root_crates(&self, id: SourceRootId) -> Arc>; /// The set of "local" (that is, from the current workspace) roots. /// Files in local roots are assumed to change frequently. #[salsa::input] @@ -173,6 +174,17 @@ pub trait FilesDatabase: salsa::Database { fn crate_graph(&self) -> Arc; } +fn source_root_crates(db: &impl FilesDatabase, id: SourceRootId) -> Arc> { + let root = db.source_root(id); + let graph = db.crate_graph(); + let res = root + .files + .values() + .filter_map(|&it| graph.crate_id_for_crate_root(it)) + .collect::>(); + Arc::new(res) +} + #[cfg(test)] mod tests { use super::{CrateGraph, FileId, SmolStr}; diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs index 32d7e09b99..84759c75af 100644 --- a/crates/ra_db/src/lib.rs +++ b/crates/ra_db/src/lib.rs @@ -13,7 +13,7 @@ pub use crate::{ cancellation::Canceled, input::{ FilesDatabase, FileId, CrateId, SourceRoot, SourceRootId, CrateGraph, Dependency, - FileTextQuery, FileSourceRootQuery, SourceRootQuery, LocalRootsQuery, LibraryRootsQuery, CrateGraphQuery, + FileTextQuery, FileSourceRootQuery, SourceRootQuery, SourceRootCratesQuery, LocalRootsQuery, LibraryRootsQuery, CrateGraphQuery, FileRelativePathQuery }, loc2id::LocationIntener, diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index ab1c428db7..4cca093517 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs @@ -64,9 +64,9 @@ fn get_def_id( ..same_file_loc.source_item_id }; let loc = DefLoc { + module: same_file_loc.module, kind: expected_kind, source_item_id, - ..*same_file_loc }; loc.id(db) } diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 3ff07bd60c..f59a60c07e 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -14,13 +14,14 @@ use crate::{ adt::VariantData, generics::GenericParams, code_model_impl::def_id_to_ast, - docs::{Documentation, Docs, docs_from_ast} + docs::{Documentation, Docs, docs_from_ast}, + module_tree::ModuleId, }; /// hir::Crate describes a single crate. It's the main interface with which /// a crate's dependencies interact. Mostly, it should be just a proxy for the /// root module. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Crate { pub(crate) crate_id: CrateId, } @@ -45,7 +46,6 @@ impl Crate { #[derive(Debug)] pub enum Def { - Module(Module), Struct(Struct), Enum(Enum), EnumVariant(EnumVariant), @@ -57,9 +57,29 @@ pub enum Def { Item, } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Module { - pub(crate) def_id: DefId, + pub(crate) krate: CrateId, + pub(crate) module_id: ModuleId, +} + +/// The defs which can be visible in the module. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ModuleDef { + Module(Module), + Def(DefId), +} + +impl Into for Module { + fn into(self) -> ModuleDef { + ModuleDef::Module(self) + } +} + +impl Into for DefId { + fn into(self) -> ModuleDef { + ModuleDef::Def(self) + } } pub enum ModuleSource { @@ -149,7 +169,7 @@ impl Module { self.scope_impl(db) } - pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PerNs { + pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PerNs { self.resolve_path_impl(db, path) } diff --git a/crates/ra_hir/src/code_model_impl/krate.rs b/crates/ra_hir/src/code_model_impl/krate.rs index 8c6e34873b..cdd30b402c 100644 --- a/crates/ra_hir/src/code_model_impl/krate.rs +++ b/crates/ra_hir/src/code_model_impl/krate.rs @@ -1,7 +1,7 @@ use ra_db::CrateId; use crate::{ - HirFileId, Crate, CrateDependency, AsName, DefLoc, DefKind, Module, SourceItemId, + Crate, CrateDependency, AsName, Module, db::HirDatabase, }; @@ -21,27 +21,13 @@ impl Crate { .collect() } pub(crate) fn root_module_impl(&self, db: &impl HirDatabase) -> Option { - let crate_graph = db.crate_graph(); - let file_id = crate_graph.crate_root(self.crate_id); - let source_root_id = db.file_source_root(file_id); - let file_id = HirFileId::from(file_id); - let module_tree = db.module_tree(source_root_id); - // FIXME: teach module tree about crate roots instead of guessing - let source = SourceItemId { - file_id, - item_id: None, - }; - let module_id = module_tree.find_module_by_source(source)?; + let module_tree = db.module_tree(self.crate_id); + let module_id = module_tree.modules().next()?; - let def_loc = DefLoc { - kind: DefKind::Module, - source_root_id, + let module = Module { + krate: self.crate_id, module_id, - source_item_id: module_id.source(&module_tree), }; - let def_id = def_loc.id(db); - - let module = Module::new(def_id); Some(module) } } diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs index d94079f11c..5d00e905b6 100644 --- a/crates/ra_hir/src/code_model_impl/module.rs +++ b/crates/ra_hir/src/code_model_impl/module.rs @@ -1,52 +1,33 @@ -use ra_db::{SourceRootId, FileId}; -use ra_syntax::{ast, SyntaxNode, AstNode, TreeArc}; +use ra_db::FileId; +use ra_syntax::{ast, SyntaxNode, TreeArc}; use crate::{ - Module, ModuleSource, Problem, - Crate, DefId, DefLoc, DefKind, Name, Path, PathKind, PerNs, Def, + Module, ModuleSource, Problem, ModuleDef, + Crate, Name, Path, PathKind, PerNs, Def, module_tree::ModuleId, nameres::{ModuleScope, lower::ImportId}, db::HirDatabase, }; impl Module { - pub(crate) fn new(def_id: DefId) -> Self { - crate::code_model_api::Module { def_id } - } - - pub(crate) fn from_module_id( - db: &impl HirDatabase, - source_root_id: SourceRootId, - module_id: ModuleId, - ) -> Self { - let module_tree = db.module_tree(source_root_id); - let def_loc = DefLoc { - kind: DefKind::Module, - source_root_id, + fn with_module_id(&self, module_id: ModuleId) -> Module { + Module { module_id, - source_item_id: module_id.source(&module_tree), - }; - let def_id = def_loc.id(db); - Module::new(def_id) + krate: self.krate, + } } pub(crate) fn name_impl(&self, db: &impl HirDatabase) -> Option { - let loc = self.def_id.loc(db); - let module_tree = db.module_tree(loc.source_root_id); - let link = loc.module_id.parent_link(&module_tree)?; + let module_tree = db.module_tree(self.krate); + let link = self.module_id.parent_link(&module_tree)?; Some(link.name(&module_tree).clone()) } pub(crate) fn definition_source_impl(&self, db: &impl HirDatabase) -> (FileId, ModuleSource) { - let loc = self.def_id.loc(db); - let file_id = loc.source_item_id.file_id.as_original_file(); - let syntax_node = db.file_item(loc.source_item_id); - let module_source = if let Some(source_file) = ast::SourceFile::cast(&syntax_node) { - ModuleSource::SourceFile(source_file.to_owned()) - } else { - let module = ast::Module::cast(&syntax_node).unwrap(); - ModuleSource::Module(module.to_owned()) - }; + let module_tree = db.module_tree(self.krate); + let source = self.module_id.source(&module_tree); + let module_source = ModuleSource::from_source_item_id(db, source); + let file_id = source.file_id.as_original_file(); (file_id, module_source) } @@ -54,9 +35,8 @@ impl Module { &self, db: &impl HirDatabase, ) -> Option<(FileId, TreeArc)> { - let loc = self.def_id.loc(db); - let module_tree = db.module_tree(loc.source_root_id); - let link = loc.module_id.parent_link(&module_tree)?; + let module_tree = db.module_tree(self.krate); + let link = self.module_id.parent_link(&module_tree)?; let file_id = link .owner(&module_tree) .source(&module_tree) @@ -71,85 +51,67 @@ impl Module { db: &impl HirDatabase, import: ImportId, ) -> TreeArc { - let loc = self.def_id.loc(db); - let source_map = db.lower_module_source_map(loc.source_root_id, loc.module_id); + let source_map = db.lower_module_source_map(self.clone()); let (_, source) = self.definition_source(db); source_map.get(&source, import) } - pub(crate) fn krate_impl(&self, db: &impl HirDatabase) -> Option { - let root = self.crate_root(db); - let loc = root.def_id.loc(db); - let file_id = loc.source_item_id.file_id.as_original_file(); - - let crate_graph = db.crate_graph(); - let crate_id = crate_graph.crate_id_for_crate_root(file_id)?; - Some(Crate::new(crate_id)) + pub(crate) fn krate_impl(&self, _db: &impl HirDatabase) -> Option { + Some(Crate::new(self.krate)) } pub(crate) fn crate_root_impl(&self, db: &impl HirDatabase) -> Module { - let loc = self.def_id.loc(db); - let module_tree = db.module_tree(loc.source_root_id); - let module_id = loc.module_id.crate_root(&module_tree); - Module::from_module_id(db, loc.source_root_id, module_id) + let module_tree = db.module_tree(self.krate); + let module_id = self.module_id.crate_root(&module_tree); + self.with_module_id(module_id) } /// Finds a child module with the specified name. pub(crate) fn child_impl(&self, db: &impl HirDatabase, name: &Name) -> Option { - let loc = self.def_id.loc(db); - let module_tree = db.module_tree(loc.source_root_id); - let child_id = loc.module_id.child(&module_tree, name)?; - Some(Module::from_module_id(db, loc.source_root_id, child_id)) + let module_tree = db.module_tree(self.krate); + let child_id = self.module_id.child(&module_tree, name)?; + Some(self.with_module_id(child_id)) } /// Iterates over all child modules. pub(crate) fn children_impl(&self, db: &impl HirDatabase) -> impl Iterator { - // FIXME this should be implementable without collecting into a vec, but - // it's kind of hard since the iterator needs to keep a reference to the - // module tree. - let loc = self.def_id.loc(db); - let module_tree = db.module_tree(loc.source_root_id); - let children = loc + let module_tree = db.module_tree(self.krate); + let children = self .module_id .children(&module_tree) - .map(|(_, module_id)| Module::from_module_id(db, loc.source_root_id, module_id)) + .map(|(_, module_id)| self.with_module_id(module_id)) .collect::>(); children.into_iter() } pub(crate) fn parent_impl(&self, db: &impl HirDatabase) -> Option { - let loc = self.def_id.loc(db); - let module_tree = db.module_tree(loc.source_root_id); - let parent_id = loc.module_id.parent(&module_tree)?; - Some(Module::from_module_id(db, loc.source_root_id, parent_id)) + let module_tree = db.module_tree(self.krate); + let parent_id = self.module_id.parent(&module_tree)?; + Some(self.with_module_id(parent_id)) } /// Returns a `ModuleScope`: a set of items, visible in this module. pub(crate) fn scope_impl(&self, db: &impl HirDatabase) -> ModuleScope { - let loc = self.def_id.loc(db); - let item_map = db.item_map(loc.source_root_id); - item_map.per_module[&loc.module_id].clone() + let item_map = db.item_map(self.krate); + item_map.per_module[&self.module_id].clone() } - pub(crate) fn resolve_path_impl(&self, db: &impl HirDatabase, path: &Path) -> PerNs { - let mut curr_per_ns = PerNs::types( - match path.kind { - PathKind::Crate => self.crate_root(db), - PathKind::Self_ | PathKind::Plain => self.clone(), - PathKind::Super => { - if let Some(p) = self.parent(db) { - p - } else { - return PerNs::none(); - } - } - PathKind::Abs => { - // TODO: absolute use is not supported + pub(crate) fn resolve_path_impl(&self, db: &impl HirDatabase, path: &Path) -> PerNs { + let mut curr_per_ns: PerNs = PerNs::types(match path.kind { + PathKind::Crate => self.crate_root(db).into(), + PathKind::Self_ | PathKind::Plain => self.clone().into(), + PathKind::Super => { + if let Some(p) = self.parent(db) { + p.into() + } else { return PerNs::none(); } } - .def_id, - ); + PathKind::Abs => { + // TODO: absolute use is not supported + return PerNs::none(); + } + }); for segment in path.segments.iter() { let curr = match curr_per_ns.as_ref().take_types() { @@ -164,32 +126,39 @@ impl Module { } }; // resolve segment in curr - curr_per_ns = match curr.resolve(db) { - Def::Module(m) => { + + curr_per_ns = match curr { + ModuleDef::Module(m) => { let scope = m.scope(db); match scope.get(&segment.name) { - Some(r) => r.def_id, + Some(r) => r.def_id.clone(), None => PerNs::none(), } } - Def::Enum(e) => { - // enum variant - let matching_variant = e - .variants(db) - .into_iter() - .find(|(n, _variant)| n == &segment.name); + ModuleDef::Def(def) => { + match def.resolve(db) { + Def::Enum(e) => { + // enum variant + let matching_variant = e + .variants(db) + .into_iter() + .find(|(n, _variant)| n == &segment.name); - match matching_variant { - Some((_n, variant)) => PerNs::both(variant.def_id(), e.def_id()), - None => PerNs::none(), + match matching_variant { + Some((_n, variant)) => { + PerNs::both(variant.def_id().into(), e.def_id().into()) + } + None => PerNs::none(), + } + } + _ => { + // could be an inherent method call in UFCS form + // (`Struct::method`), or some other kind of associated + // item... Which we currently don't handle (TODO) + PerNs::none() + } } } - _ => { - // could be an inherent method call in UFCS form - // (`Struct::method`), or some other kind of associated - // item... Which we currently don't handle (TODO) - PerNs::none() - } }; } curr_per_ns @@ -199,8 +168,7 @@ impl Module { &self, db: &impl HirDatabase, ) -> Vec<(TreeArc, Problem)> { - let loc = self.def_id.loc(db); - let module_tree = db.module_tree(loc.source_root_id); - loc.module_id.problems(&module_tree, db) + let module_tree = db.module_tree(self.krate); + self.module_id.problems(&module_tree, db) } } diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index cc03da1e25..0898daa3c4 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -1,15 +1,15 @@ use std::sync::Arc; use ra_syntax::{SyntaxNode, TreeArc, SourceFile}; -use ra_db::{SourceRootId, SyntaxDatabase, salsa}; +use ra_db::{SyntaxDatabase, CrateId, salsa}; use crate::{ - HirInterner, DefId, MacroCallId, Name, HirFileId, - SourceFileItems, SourceItemId, Crate, + DefId, MacroCallId, Name, HirFileId, + SourceFileItems, SourceItemId, Crate, Module, HirInterner, query_definitions, FnSignature, FnScopes, macros::MacroExpansion, - module_tree::{ModuleId, ModuleTree}, + module_tree::ModuleTree, nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}}, ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks}, adt::{StructData, EnumData, EnumVariantData}, @@ -56,38 +56,22 @@ pub trait HirDatabase: SyntaxDatabase + AsRef { fn submodules(&self, source: SourceItemId) -> Arc>; #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_query)] - fn lower_module( - &self, - source_root_id: SourceRootId, - module_id: ModuleId, - ) -> (Arc, Arc); + fn lower_module(&self, module: Module) -> (Arc, Arc); #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_module_query)] - fn lower_module_module( - &self, - source_root_id: SourceRootId, - module_id: ModuleId, - ) -> Arc; + fn lower_module_module(&self, module: Module) -> Arc; #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_source_map_query)] - fn lower_module_source_map( - &self, - source_root_id: SourceRootId, - module_id: ModuleId, - ) -> Arc; + fn lower_module_source_map(&self, module: Module) -> Arc; #[salsa::invoke(query_definitions::item_map)] - fn item_map(&self, source_root_id: SourceRootId) -> Arc; + fn item_map(&self, crate_id: CrateId) -> Arc; #[salsa::invoke(crate::module_tree::ModuleTree::module_tree_query)] - fn module_tree(&self, source_root_id: SourceRootId) -> Arc; + fn module_tree(&self, crate_id: CrateId) -> Arc; #[salsa::invoke(crate::impl_block::impls_in_module)] - fn impls_in_module( - &self, - source_root_id: SourceRootId, - module_id: ModuleId, - ) -> Arc; + fn impls_in_module(&self, module: Module) -> Arc; #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)] fn impls_in_crate(&self, krate: Crate) -> Arc; diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 43f0e81f9f..99f04e4ef5 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs @@ -1,11 +1,10 @@ -use ra_db::{SourceRootId, LocationIntener, FileId}; +use ra_db::{LocationIntener, FileId}; use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, ast}; use ra_arena::{Arena, RawId, impl_arena_id}; use crate::{ HirDatabase, Def, Function, Struct, Enum, EnumVariant, ImplBlock, Crate, Module, Trait, Type, Static, Const, - module_tree::ModuleId, }; #[derive(Debug, Default)] @@ -110,10 +109,9 @@ impl From for HirFileId { pub struct MacroCallId(RawId); impl_arena_id!(MacroCallId); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct MacroCallLoc { - pub(crate) source_root_id: SourceRootId, - pub(crate) module_id: ModuleId, + pub(crate) module: Module, pub(crate) source_item_id: SourceItemId, } @@ -139,14 +137,12 @@ impl_arena_id!(DefId); #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct DefLoc { pub(crate) kind: DefKind, - pub(crate) source_root_id: SourceRootId, - pub(crate) module_id: ModuleId, + pub(crate) module: Module, pub(crate) source_item_id: SourceItemId, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub(crate) enum DefKind { - Module, Function, Struct, Enum, @@ -177,10 +173,6 @@ impl DefId { pub fn resolve(self, db: &impl HirDatabase) -> Def { let loc = self.loc(db); match loc.kind { - DefKind::Module => { - let module = Module::from_module_id(db, loc.source_root_id, loc.module_id); - Def::Module(module) - } DefKind::Function => { let function = Function::new(self); Def::Function(function) @@ -221,8 +213,7 @@ impl DefId { /// For a module, returns that module; for any other def, returns the containing module. pub fn module(self, db: &impl HirDatabase) -> Module { - let loc = self.loc(db); - Module::from_module_id(db, loc.source_root_id, loc.module_id) + self.loc(db).module } /// Returns the containing crate. @@ -232,8 +223,7 @@ impl DefId { /// Returns the containing impl block, if this is an impl item. pub fn impl_block(self, db: &impl HirDatabase) -> Option { - let loc = self.loc(db); - let module_impls = db.impls_in_module(loc.source_root_id, loc.module_id); + let module_impls = db.impls_in_module(self.loc(db).module); ImplBlock::containing(module_impls, self) } } diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index 551d0d149d..ba8b84da2c 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs @@ -3,14 +3,12 @@ use rustc_hash::FxHashMap; use ra_arena::{Arena, RawId, impl_arena_id}; use ra_syntax::ast::{self, AstNode}; -use ra_db::{SourceRootId}; use crate::{ DefId, DefLoc, DefKind, SourceItemId, SourceFileItems, - Function, HirInterner, + Function, HirFileId, HirInterner, db::HirDatabase, type_ref::TypeRef, - module_tree::ModuleId, }; use crate::code_model_api::{Module, ModuleSource}; @@ -67,13 +65,13 @@ pub struct ImplData { impl ImplData { pub(crate) fn from_ast( db: &impl AsRef, + file_id: HirFileId, file_items: &SourceFileItems, - module: &Module, + module: Module, node: &ast::ImplBlock, ) -> Self { let target_trait = node.target_trait().map(TypeRef::from_ast); let target_type = TypeRef::from_ast_opt(node.target_type()); - let module_loc = module.def_id.loc(db); let items = if let Some(item_list) = node.item_list() { item_list .impl_items() @@ -85,13 +83,13 @@ impl ImplData { }; let item_id = file_items.id_of_unchecked(item_node.syntax()); let source_item_id = SourceItemId { - file_id: module_loc.source_item_id.file_id, + file_id, item_id: Some(item_id), }; let def_loc = DefLoc { + module, kind, source_item_id, - ..module_loc }; let def_id = def_loc.id(db); match item_node.kind() { @@ -168,6 +166,7 @@ impl ModuleImplBlocks { fn collect(&mut self, db: &impl HirDatabase, module: Module) { let (file_id, module_source) = module.definition_source(db); + let file_id: HirFileId = file_id.into(); let node = match &module_source { ModuleSource::SourceFile(node) => node.syntax(), ModuleSource::Module(node) => node @@ -176,10 +175,11 @@ impl ModuleImplBlocks { .syntax(), }; - let source_file_items = db.file_items(file_id.into()); + let source_file_items = db.file_items(file_id); for impl_block_ast in node.children().filter_map(ast::ImplBlock::cast) { - let impl_block = ImplData::from_ast(db, &source_file_items, &module, impl_block_ast); + let impl_block = + ImplData::from_ast(db, file_id, &source_file_items, module, impl_block_ast); let id = self.impls.alloc(impl_block); for impl_item in &self.impls[id].items { self.impls_by_def.insert(impl_item.def_id(), id); @@ -188,13 +188,8 @@ impl ModuleImplBlocks { } } -pub(crate) fn impls_in_module( - db: &impl HirDatabase, - source_root_id: SourceRootId, - module_id: ModuleId, -) -> Arc { +pub(crate) fn impls_in_module(db: &impl HirDatabase, module: Module) -> Arc { let mut result = ModuleImplBlocks::new(); - let module = Module::from_module_id(db, source_root_id, module_id); result.collect(db, module); Arc::new(result) } diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 87b5a8b8a0..a6246a5e94 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -52,7 +52,7 @@ pub use self::{ pub use self::code_model_api::{ Crate, CrateDependency, Def, - Module, ModuleSource, Problem, + Module, ModuleDef, ModuleSource, Problem, Struct, Enum, EnumVariant, Function, FnSignature, ScopeEntryWithSyntax, StructField, diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs index 4145c80487..361366f6a1 100644 --- a/crates/ra_hir/src/mock.rs +++ b/crates/ra_hir/src/mock.rs @@ -35,10 +35,6 @@ impl MockDatabase { let file_id = db.add_file(WORKSPACE, &mut source_root, "/main.rs", text); db.query_mut(ra_db::SourceRootQuery) .set(WORKSPACE, Arc::new(source_root.clone())); - - let mut crate_graph = CrateGraph::default(); - crate_graph.add_crate_root(file_id); - db.set_crate_graph(crate_graph); (db, source_root, file_id) } @@ -97,6 +93,8 @@ impl MockDatabase { text: &str, ) -> FileId { assert!(path.starts_with('/')); + let is_crate_root = path == "/lib.rs" || path == "/main.rs"; + let path = RelativePathBuf::from_path(&path[1..]).unwrap(); let file_id = FileId(self.file_counter); self.file_counter += 1; @@ -107,6 +105,12 @@ impl MockDatabase { self.query_mut(ra_db::FileSourceRootQuery) .set(file_id, source_root_id); source_root.files.insert(path, file_id); + + if is_crate_root { + let mut crate_graph = CrateGraph::default(); + crate_graph.add_crate_root(file_id); + self.set_crate_graph(crate_graph); + } file_id } @@ -202,6 +206,7 @@ salsa::database_storage! { fn file_relative_path() for ra_db::FileRelativePathQuery; fn file_source_root() for ra_db::FileSourceRootQuery; fn source_root() for ra_db::SourceRootQuery; + fn source_root_crates() for ra_db::SourceRootCratesQuery; fn local_roots() for ra_db::LocalRootsQuery; fn library_roots() for ra_db::LibraryRootsQuery; fn crate_graph() for ra_db::CrateGraphQuery; diff --git a/crates/ra_hir/src/module_tree.rs b/crates/ra_hir/src/module_tree.rs index b201bf69bf..c00834c4c1 100644 --- a/crates/ra_hir/src/module_tree.rs +++ b/crates/ra_hir/src/module_tree.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use rustc_hash::{FxHashMap, FxHashSet}; use arrayvec::ArrayVec; use relative_path::RelativePathBuf; -use ra_db::{FileId, SourceRootId, SourceRoot}; +use ra_db::{FileId, SourceRoot, CrateId}; use ra_syntax::{ SyntaxNode, TreeArc, algo::generate, @@ -126,13 +126,10 @@ struct LinkData { } impl ModuleTree { - pub(crate) fn module_tree_query( - db: &impl HirDatabase, - source_root: SourceRootId, - ) -> Arc { + pub(crate) fn module_tree_query(db: &impl HirDatabase, crate_id: CrateId) -> Arc { db.check_canceled(); let mut res = ModuleTree::default(); - res.init(db, source_root); + res.init_crate(db, crate_id); Arc::new(res) } @@ -145,24 +142,21 @@ impl ModuleTree { Some(res) } - fn init(&mut self, db: &impl HirDatabase, source_root: SourceRootId) { + fn init_crate(&mut self, db: &impl HirDatabase, crate_id: CrateId) { + let crate_graph = db.crate_graph(); + let file_id = crate_graph.crate_root(crate_id); + let source_root_id = db.file_source_root(file_id); + let mut roots = FxHashMap::default(); let mut visited = FxHashSet::default(); - let source_root = db.source_root(source_root); - for &file_id in source_root.files.values() { - let source = SourceItemId { - file_id: file_id.into(), - item_id: None, - }; - if visited.contains(&source) { - continue; // TODO: use explicit crate_roots here - } - assert!(!roots.contains_key(&file_id)); - let module_id = - self.init_subtree(db, &source_root, &mut visited, &mut roots, None, source); - roots.insert(file_id, module_id); - } + let source_root = db.source_root(source_root_id); + let source = SourceItemId { + file_id: file_id.into(), + item_id: None, + }; + let module_id = self.init_subtree(db, &source_root, &mut visited, &mut roots, None, source); + roots.insert(file_id, module_id); } fn init_subtree( diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index 1d163edf7d..a3bc989580 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs @@ -16,19 +16,19 @@ //! structure itself is modified. pub(crate) mod lower; -use crate::nameres::lower::*; - use std::sync::Arc; +use ra_db::CrateId; use rustc_hash::{FxHashMap, FxHashSet}; -use ra_db::SourceRootId; use crate::{ - DefId, DefLoc, DefKind, + Module, ModuleDef, Path, PathKind, HirDatabase, Crate, Name, module_tree::{ModuleId, ModuleTree}, +//FIXME: deglobify + nameres::lower::*, }; /// `ItemMap` is the result of name resolution. It contains, for each @@ -58,7 +58,7 @@ impl ModuleScope { #[derive(Debug, Clone, PartialEq, Eq)] pub struct Resolution { /// None for unresolved - pub def_id: PerNs, + pub def_id: PerNs, /// ident by which this is imported into local scope. pub import: Option, } @@ -152,7 +152,7 @@ impl PerNs { pub(crate) struct Resolver<'a, DB> { db: &'a DB, input: &'a FxHashMap>, - source_root: SourceRootId, + krate: CrateId, module_tree: Arc, processed_imports: FxHashSet<(ModuleId, ImportId)>, result: ItemMap, @@ -165,13 +165,13 @@ where pub(crate) fn new( db: &'a DB, input: &'a FxHashMap>, - source_root: SourceRootId, - module_tree: Arc, + krate: CrateId, ) -> Resolver<'a, DB> { + let module_tree = db.module_tree(krate); Resolver { db, input, - source_root, + krate, module_tree, processed_imports: FxHashSet::default(), result: ItemMap::default(), @@ -210,7 +210,7 @@ where let krate = Crate::new(crate_id); for dep in krate.dependencies(self.db) { if let Some(module) = dep.krate.root_module(self.db) { - let def_id = module.def_id; + let def_id = module.into(); self.add_module_item( &mut module_items, dep.name.clone(), @@ -244,20 +244,22 @@ where // Populate modules for (name, module_id) in module_id.children(&self.module_tree) { - let def_loc = DefLoc { - kind: DefKind::Module, - source_root_id: self.source_root, + let module = Module { module_id, - source_item_id: module_id.source(&self.module_tree), + krate: self.krate, }; - let def_id = def_loc.id(self.db); - self.add_module_item(&mut module_items, name, PerNs::types(def_id)); + self.add_module_item(&mut module_items, name, PerNs::types(module.into())); } self.result.per_module.insert(module_id, module_items); } - fn add_module_item(&self, module_items: &mut ModuleScope, name: Name, def_id: PerNs) { + fn add_module_item( + &self, + module_items: &mut ModuleScope, + name: Name, + def_id: PerNs, + ) { let resolution = Resolution { def_id, import: None, @@ -329,17 +331,11 @@ where ); return false; }; - curr = match type_def_id.loc(self.db) { - DefLoc { - kind: DefKind::Module, - module_id: target_module_id, - source_root_id, - .. - } => { - if source_root_id == self.source_root { - target_module_id + curr = match type_def_id { + ModuleDef::Module(module) => { + if module.krate == self.krate { + module.module_id } else { - let module = crate::code_model_api::Module::new(type_def_id); let path = Path { segments: import.path.segments[i + 1..].iter().cloned().collect(), kind: PathKind::Crate, @@ -359,7 +355,7 @@ where "resolved import {:?} ({:?}) cross-source root to {:?}", last_segment.name, import, - def_id.map(|did| did.loc(self.db)) + def_id, ); return true; } else { @@ -372,7 +368,7 @@ where log::debug!( "path segment {:?} resolved to non-module {:?}, but is not last", segment.name, - type_def_id.loc(self.db) + type_def_id, ); return true; // this resolved to a non-module, so the path won't ever resolve } @@ -382,7 +378,7 @@ where "resolved import {:?} ({:?}) within source root to {:?}", segment.name, import, - def_id.map(|did| did.loc(self.db)) + def_id, ); self.update(module_id, |items| { let res = Resolution { diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs index 4eea6ff1de..6f003bd666 100644 --- a/crates/ra_hir/src/nameres/lower.rs +++ b/crates/ra_hir/src/nameres/lower.rs @@ -4,14 +4,13 @@ use ra_syntax::{ SyntaxKind, AstNode, SourceFile, TreeArc, AstPtr, ast::{self, ModuleItemOwner, NameOwner}, }; -use ra_db::SourceRootId; use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; use rustc_hash::FxHashMap; use crate::{ SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems, - HirFileId, MacroCallLoc, AsName, PerNs, DefId, DefKind, DefLoc, - module_tree::ModuleId + HirFileId, MacroCallLoc, AsName, PerNs, DefKind, DefLoc, + ModuleDef, Module, }; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -32,7 +31,7 @@ pub(super) struct ImportData { /// can avoid redoing name resolution. #[derive(Debug, Default, PartialEq, Eq)] pub struct LoweredModule { - pub(crate) declarations: FxHashMap>, + pub(crate) declarations: FxHashMap>, pub(super) imports: Arena, } @@ -59,37 +58,31 @@ impl ImportSourceMap { impl LoweredModule { pub(crate) fn lower_module_module_query( db: &impl HirDatabase, - source_root_id: SourceRootId, - module_id: ModuleId, + module: Module, ) -> Arc { - db.lower_module(source_root_id, module_id).0 + db.lower_module(module).0 } pub(crate) fn lower_module_source_map_query( db: &impl HirDatabase, - source_root_id: SourceRootId, - module_id: ModuleId, + module: Module, ) -> Arc { - db.lower_module(source_root_id, module_id).1 + db.lower_module(module).1 } pub(crate) fn lower_module_query( db: &impl HirDatabase, - source_root_id: SourceRootId, - module_id: ModuleId, + module: Module, ) -> (Arc, Arc) { - let module_tree = db.module_tree(source_root_id); - let source = module_id.source(&module_tree); - let file_id = source.file_id; - let source = ModuleSource::from_source_item_id(db, source); + let (file_id, source) = module.definition_source(db); + let file_id: HirFileId = file_id.into(); let mut source_map = ImportSourceMap::default(); let mut res = LoweredModule::default(); match source { ModuleSource::SourceFile(it) => res.fill( &mut source_map, db, - source_root_id, - module_id, + module, file_id, &mut it.items_with_macros(), ), @@ -98,8 +91,7 @@ impl LoweredModule { res.fill( &mut source_map, db, - source_root_id, - module_id, + module, file_id, &mut item_list.items_with_macros(), ) @@ -113,8 +105,7 @@ impl LoweredModule { &mut self, source_map: &mut ImportSourceMap, db: &impl HirDatabase, - source_root_id: SourceRootId, - module_id: ModuleId, + module: Module, file_id: HirFileId, items: &mut Iterator, ) { @@ -123,21 +114,12 @@ impl LoweredModule { for item in items { match item { ast::ItemOrMacro::Item(it) => { - self.add_def_id( - source_map, - db, - source_root_id, - module_id, - file_id, - &file_items, - it, - ); + self.add_def_id(source_map, db, module, file_id, &file_items, it); } ast::ItemOrMacro::Macro(macro_call) => { let item_id = file_items.id_of_unchecked(macro_call.syntax()); let loc = MacroCallLoc { - source_root_id, - module_id, + module, source_item_id: SourceItemId { file_id, item_id: Some(item_id), @@ -148,15 +130,7 @@ impl LoweredModule { let file_items = db.file_items(file_id); //FIXME: expand recursively for item in db.hir_source_file(file_id).items() { - self.add_def_id( - source_map, - db, - source_root_id, - module_id, - file_id, - &file_items, - item, - ); + self.add_def_id(source_map, db, module, file_id, &file_items, item); } } } @@ -167,8 +141,7 @@ impl LoweredModule { &mut self, source_map: &mut ImportSourceMap, db: &impl HirDatabase, - source_root_id: SourceRootId, - module_id: ModuleId, + module: Module, file_id: HirFileId, file_items: &SourceFileItems, item: &ast::ModuleItem, @@ -199,7 +172,7 @@ impl LoweredModule { } }; if let Some(name) = name { - let def_id = assign_def_id(db, source_root_id, module_id, file_id, file_items, item); + let def_id = assign_def_id(db, module, file_id, file_items, item); self.declarations.insert(name.as_name(), def_id); } } @@ -219,12 +192,11 @@ impl LoweredModule { fn assign_def_id( db: &impl HirDatabase, - source_root_id: SourceRootId, - module_id: ModuleId, + module: Module, file_id: HirFileId, file_items: &SourceFileItems, item: &ast::ModuleItem, -) -> PerNs { +) -> PerNs { // depending on the item kind, the location can define something in // the values namespace, the types namespace, or both let kind = DefKind::for_syntax_kind(item.syntax().kind()); @@ -232,14 +204,13 @@ fn assign_def_id( let item_id = file_items.id_of_unchecked(item.syntax()); let def_loc = DefLoc { kind: k, - source_root_id, - module_id, + module, source_item_id: SourceItemId { file_id, item_id: Some(item_id), }, }; - def_loc.id(db) + def_loc.id(db).into() }); def_id } @@ -248,7 +219,6 @@ impl DefKind { fn for_syntax_kind(kind: SyntaxKind) -> PerNs { match kind { SyntaxKind::FN_DEF => PerNs::values(DefKind::Function), - SyntaxKind::MODULE => PerNs::types(DefKind::Module), SyntaxKind::STRUCT_DEF => PerNs::both(DefKind::Struct, DefKind::StructCtor), SyntaxKind::ENUM_DEF => PerNs::types(DefKind::Enum), SyntaxKind::TRAIT_DEF => PerNs::types(DefKind::Trait), diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs index e920074533..9322bf08ce 100644 --- a/crates/ra_hir/src/nameres/tests.rs +++ b/crates/ra_hir/src/nameres/tests.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use ra_db::{FilesDatabase, CrateGraph, SourceRootId, salsa::Database}; +use ra_db::{CrateGraph, SourceRootId, salsa::Database}; use relative_path::RelativePath; use test_utils::{assert_eq_text, covers}; @@ -13,10 +13,10 @@ use crate::{ fn item_map(fixture: &str) -> (Arc, ModuleId) { let (db, pos) = MockDatabase::with_position(fixture); - let source_root = db.file_source_root(pos.file_id); let module = crate::source_binder::module_from_position(&db, pos).unwrap(); - let module_id = module.def_id.loc(&db).module_id; - (db.item_map(source_root), module_id) + let krate = module.krate(&db).unwrap(); + let module_id = module.module_id; + (db.item_map(krate.crate_id), module_id) } fn check_module_item_map(map: &ItemMap, module_id: ModuleId, expected: &str) { @@ -238,14 +238,13 @@ fn item_map_across_crates() { db.set_crate_graph(crate_graph); - let source_root = db.file_source_root(main_id); let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); - let module_id = module.def_id.loc(&db).module_id; - let item_map = db.item_map(source_root); + let krate = module.krate(&db).unwrap(); + let item_map = db.item_map(krate.crate_id); check_module_item_map( &item_map, - module_id, + module.module_id, " Baz: t v test_crate: t @@ -292,12 +291,12 @@ fn import_across_source_roots() { db.set_crate_graph(crate_graph); let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); - let module_id = module.def_id.loc(&db).module_id; - let item_map = db.item_map(source_root); + let krate = module.krate(&db).unwrap(); + let item_map = db.item_map(krate.crate_id); check_module_item_map( &item_map, - module_id, + module.module_id, " C: t v test_crate: t @@ -333,14 +332,13 @@ fn reexport_across_crates() { db.set_crate_graph(crate_graph); - let source_root = db.file_source_root(main_id); let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); - let module_id = module.def_id.loc(&db).module_id; - let item_map = db.item_map(source_root); + let krate = module.krate(&db).unwrap(); + let item_map = db.item_map(krate.crate_id); check_module_item_map( &item_map, - module_id, + module.module_id, " Baz: t v test_crate: t @@ -350,10 +348,11 @@ fn reexport_across_crates() { fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) { let (mut db, pos) = MockDatabase::with_position(initial); - let source_root = db.file_source_root(pos.file_id); + let module = crate::source_binder::module_from_file_id(&db, pos.file_id).unwrap(); + let krate = module.krate(&db).unwrap(); { let events = db.log_executed(|| { - db.item_map(source_root); + db.item_map(krate.crate_id); }); assert!(format!("{:?}", events).contains("item_map")) } @@ -362,7 +361,7 @@ fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) { { let events = db.log_executed(|| { - db.item_map(source_root); + db.item_map(krate.crate_id); }); assert!( !format!("{:?}", events).contains("item_map"), diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs index 0741538626..a8ed887b34 100644 --- a/crates/ra_hir/src/query_definitions.rs +++ b/crates/ra_hir/src/query_definitions.rs @@ -7,11 +7,11 @@ use rustc_hash::FxHashMap; use ra_syntax::{ AstNode, SyntaxNode, TreeArc, }; -use ra_db::SourceRootId; +use ra_db::{CrateId}; use crate::{ SourceFileItems, SourceItemId, DefId, HirFileId, - FnScopes, + FnScopes, Module, db::HirDatabase, nameres::{ItemMap, Resolver}, }; @@ -41,15 +41,23 @@ pub(super) fn file_item( } } -pub(super) fn item_map(db: &impl HirDatabase, source_root: SourceRootId) -> Arc { +pub(super) fn item_map(db: &impl HirDatabase, crate_id: CrateId) -> Arc { let start = Instant::now(); - let module_tree = db.module_tree(source_root); + let module_tree = db.module_tree(crate_id); let input = module_tree .modules() - .map(|id| (id, db.lower_module_module(source_root, id))) + .map(|module_id| { + ( + module_id, + db.lower_module_module(Module { + krate: crate_id, + module_id, + }), + ) + }) .collect::>(); - let resolver = Resolver::new(db, &input, source_root, module_tree); + let resolver = Resolver::new(db, &input, crate_id); let res = resolver.resolve(); let elapsed = start.elapsed(); log::info!("item_map: {:?}", elapsed); diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index bde0be37b6..c3bd31d6b1 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -13,7 +13,7 @@ use ra_syntax::{ }; use crate::{ - HirDatabase, Function, SourceItemId, + HirDatabase, Function, SourceItemId, ModuleDef, DefKind, DefLoc, AsName, Module, }; @@ -84,9 +84,13 @@ pub fn module_from_child_node( fn module_from_source(db: &impl HirDatabase, source: SourceItemId) -> Option { let source_root_id = db.file_source_root(source.file_id.as_original_file()); - let module_tree = db.module_tree(source_root_id); - let module_id = module_tree.find_module_by_source(source)?; - Some(Module::from_module_id(db, source_root_id, module_id)) + db.source_root_crates(source_root_id) + .iter() + .find_map(|&krate| { + let module_tree = db.module_tree(krate); + let module_id = module_tree.find_module_by_source(source)?; + Some(Module { krate, module_id }) + }) } pub fn function_from_position(db: &impl HirDatabase, position: FilePosition) -> Option { @@ -110,8 +114,8 @@ pub fn function_from_module( module: &Module, fn_def: &ast::FnDef, ) -> Function { - let loc = module.def_id.loc(db); - let file_id = loc.source_item_id.file_id; + let (file_id, _) = module.definition_source(db); + let file_id = file_id.into(); let file_items = db.file_items(file_id); let item_id = file_items.id_of(file_id, fn_def.syntax()); let source_item_id = SourceItemId { @@ -119,9 +123,8 @@ pub fn function_from_module( item_id: Some(item_id), }; let def_loc = DefLoc { + module: module.clone(), kind: DefKind::Function, - source_root_id: loc.source_root_id, - module_id: loc.module_id, source_item_id, }; Function::new(def_loc.id(db)) @@ -141,14 +144,17 @@ pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, Te Some(it) => it, None => return Vec::new(), }; - let loc = module.def_id.loc(db); - let items = db.lower_module_module(loc.source_root_id, loc.module_id); + let items = db.lower_module_module(module); let mut res = Vec::new(); for macro_call_id in items .declarations .iter() - .filter_map(|(_, it)| it.take_types()) + .filter_map(|(_, it)| it.clone().take_types()) + .filter_map(|it| match it { + ModuleDef::Def(it) => Some(it), + _ => None, + }) .filter_map(|it| it.loc(db).source_item_id.file_id.as_macro_call_id()) { if let Some(exp) = db.expand_macro_invocation(macro_call_id) { diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index e690ae1582..4c96579eeb 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -32,7 +32,7 @@ use rustc_hash::FxHashMap; use crate::{ Def, DefId, Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock, - FnSignature, FnScopes, + FnSignature, FnScopes, ModuleDef, db::HirDatabase, type_ref::{TypeRef, Mutability}, name::KnownName, @@ -382,8 +382,8 @@ impl Ty { // Resolve in module (in type namespace) let resolved = match module.resolve_path(db, path).take_types() { - Some(r) => r, - None => return Ty::Unknown, + Some(ModuleDef::Def(r)) => r, + None | Some(ModuleDef::Module(_)) => return Ty::Unknown, }; let ty = db.type_for_def(resolved); let substs = Ty::substs_from_path(db, module, impl_block, generics, path, resolved); @@ -663,10 +663,6 @@ pub(crate) fn type_for_enum_variant(db: &impl HirDatabase, ev: EnumVariant) -> T pub(super) fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Ty { let def = def_id.resolve(db); match def { - Def::Module(..) => { - log::debug!("trying to get type for module {:?}", def_id); - Ty::Unknown - } Def::Function(f) => type_for_fn(db, f), Def::Struct(s) => type_for_struct(db, s), Def::Enum(e) => type_for_enum(db, e), @@ -1063,7 +1059,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { }; // resolve in module - let resolved = self.module.resolve_path(self.db, &path).take_values()?; + let resolved = match self.module.resolve_path(self.db, &path).take_values()? { + ModuleDef::Def(it) => it, + ModuleDef::Module(_) => return None, + }; let ty = self.db.type_for_def(resolved); let ty = self.insert_type_vars(ty); Some(ty) @@ -1075,7 +1074,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { None => return (Ty::Unknown, None), }; let def_id = match self.module.resolve_path(self.db, &path).take_types() { - Some(def_id) => def_id, + Some(ModuleDef::Def(def_id)) => def_id, _ => return (Ty::Unknown, None), }; // TODO remove the duplication between here and `Ty::from_path`? @@ -1216,6 +1215,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { .module .resolve_path(self.db, &path) .take_values() + .and_then(|module_def| match module_def { + ModuleDef::Def(it) => Some(it), + ModuleDef::Module(_) => None, + }) .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)), Pat::Bind { mode, diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 9f65c5fe1d..a5567a78fb 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs @@ -6,8 +6,6 @@ use std::sync::Arc; use rustc_hash::FxHashMap; -use ra_db::SourceRootId; - use crate::{ HirDatabase, DefId, module_tree::ModuleId, Module, Crate, Name, Function, impl_block::{ImplId, ImplBlock, ImplItem}, @@ -37,7 +35,7 @@ impl TyFingerprint { #[derive(Debug, PartialEq, Eq)] pub struct CrateImplBlocks { /// To make sense of the ModuleIds, we need the source root. - source_root_id: SourceRootId, + krate: Crate, impls: FxHashMap>, } @@ -53,14 +51,17 @@ impl CrateImplBlocks { .into_iter() .flat_map(|i| i.iter()) .map(move |(module_id, impl_id)| { - let module_impl_blocks = db.impls_in_module(self.source_root_id, *module_id); + let module = Module { + krate: self.krate.crate_id, + module_id: *module_id, + }; + let module_impl_blocks = db.impls_in_module(module); ImplBlock::from_id(module_impl_blocks, *impl_id) }) } - fn collect_recursive(&mut self, db: &impl HirDatabase, module: Module) { - let module_id = module.def_id.loc(db).module_id; - let module_impl_blocks = db.impls_in_module(self.source_root_id, module_id); + fn collect_recursive(&mut self, db: &impl HirDatabase, module: &Module) { + let module_impl_blocks = db.impls_in_module(module.clone()); for (impl_id, impl_data) in module_impl_blocks.impls.iter() { let impl_block = ImplBlock::from_id(Arc::clone(&module_impl_blocks), impl_id); @@ -81,13 +82,13 @@ impl CrateImplBlocks { self.impls .entry(target_ty_fp) .or_insert_with(Vec::new) - .push((module_id, impl_id)); + .push((module.module_id, impl_id)); } } } for child in module.children(db) { - self.collect_recursive(db, child); + self.collect_recursive(db, &child); } } @@ -95,15 +96,12 @@ impl CrateImplBlocks { db: &impl HirDatabase, krate: Crate, ) -> Arc { - let crate_graph = db.crate_graph(); - let file_id = crate_graph.crate_root(krate.crate_id); - let source_root_id = db.file_source_root(file_id); let mut crate_impl_blocks = CrateImplBlocks { - source_root_id, + krate: krate.clone(), impls: FxHashMap::default(), }; if let Some(module) = krate.root_module(db) { - crate_impl_blocks.collect_recursive(db, module); + crate_impl_blocks.collect_recursive(db, &module); } Arc::new(crate_impl_blocks) } diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index e44b76c4a9..0d79424968 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs @@ -13,8 +13,8 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { Some(it) => it, None => return, }; - match def_id.resolve(ctx.db) { - hir::Def::Module(module) => { + match def_id { + hir::ModuleDef::Module(module) => { let module_scope = module.scope(ctx.db); for (name, res) in module_scope.entries() { CompletionItem::new( @@ -26,21 +26,24 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { .add_to(acc); } } - hir::Def::Enum(e) => { - e.variants(ctx.db) - .into_iter() - .for_each(|(variant_name, variant)| { - CompletionItem::new( - CompletionKind::Reference, - ctx.source_range(), - variant_name.to_string(), - ) - .kind(CompletionItemKind::EnumVariant) - .set_documentation(variant.docs(ctx.db)) - .add_to(acc) - }); - } - _ => return, + + hir::ModuleDef::Def(def_id) => match def_id.resolve(ctx.db) { + hir::Def::Enum(e) => { + e.variants(ctx.db) + .into_iter() + .for_each(|(variant_name, variant)| { + CompletionItem::new( + CompletionKind::Reference, + ctx.source_range(), + variant_name.to_string(), + ) + .kind(CompletionItemKind::EnumVariant) + .set_documentation(variant.docs(ctx.db)) + .add_to(acc) + }); + } + _ => return, + }, }; } diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs index 18c151932a..5d6718a8d0 100644 --- a/crates/ra_ide_api/src/completion/completion_item.rs +++ b/crates/ra_ide_api/src/completion/completion_item.rs @@ -1,6 +1,4 @@ -use hir::{Docs, Documentation, PerNs}; - -use crate::completion::completion_context::CompletionContext; +use hir::{Docs, Documentation}; use ra_syntax::{ ast::{self, AstNode}, TextRange, @@ -8,6 +6,8 @@ use ra_syntax::{ use ra_text_edit::TextEdit; use test_utils::tested_by; +use crate::completion::completion_context::CompletionContext; + /// `CompletionItem` describes a single completion variant in the editor pop-up. /// It is basically a POD with various properties. To construct a /// `CompletionItem`, use `new` method and the `Builder` struct. @@ -209,41 +209,26 @@ impl Builder { ctx: &CompletionContext, resolution: &hir::Resolution, ) -> Builder { - let resolved = resolution.def_id.map(|d| d.resolve(ctx.db)); - let (kind, docs) = match resolved { - PerNs { - types: Some(hir::Def::Module(..)), - .. - } => (CompletionItemKind::Module, None), - PerNs { - types: Some(hir::Def::Struct(s)), - .. - } => (CompletionItemKind::Struct, s.docs(ctx.db)), - PerNs { - types: Some(hir::Def::Enum(e)), - .. - } => (CompletionItemKind::Enum, e.docs(ctx.db)), - PerNs { - types: Some(hir::Def::Trait(t)), - .. - } => (CompletionItemKind::Trait, t.docs(ctx.db)), - PerNs { - types: Some(hir::Def::Type(t)), - .. - } => (CompletionItemKind::TypeAlias, t.docs(ctx.db)), - PerNs { - values: Some(hir::Def::Const(c)), - .. - } => (CompletionItemKind::Const, c.docs(ctx.db)), - PerNs { - values: Some(hir::Def::Static(s)), - .. - } => (CompletionItemKind::Static, s.docs(ctx.db)), - PerNs { - values: Some(hir::Def::Function(function)), - .. - } => return self.from_function(ctx, function), - _ => return self, + let def = resolution + .def_id + .take_types() + .or(resolution.def_id.take_values()); + let def = match def { + None => return self, + Some(it) => it, + }; + let (kind, docs) = match def { + hir::ModuleDef::Module(_) => (CompletionItemKind::Module, None), + hir::ModuleDef::Def(def_id) => match def_id.resolve(ctx.db) { + hir::Def::Struct(it) => (CompletionItemKind::Struct, it.docs(ctx.db)), + hir::Def::Enum(it) => (CompletionItemKind::Enum, it.docs(ctx.db)), + hir::Def::Trait(it) => (CompletionItemKind::Trait, it.docs(ctx.db)), + hir::Def::Type(it) => (CompletionItemKind::TypeAlias, it.docs(ctx.db)), + hir::Def::Const(it) => (CompletionItemKind::Const, it.docs(ctx.db)), + hir::Def::Static(it) => (CompletionItemKind::Static, it.docs(ctx.db)), + hir::Def::Function(function) => return self.from_function(ctx, function), + _ => return self, + }, }; self.kind = Some(kind); self.documentation = docs; diff --git a/crates/ra_ide_api/src/db.rs b/crates/ra_ide_api/src/db.rs index ba0eb1cb8a..bff6b7237a 100644 --- a/crates/ra_ide_api/src/db.rs +++ b/crates/ra_ide_api/src/db.rs @@ -72,6 +72,7 @@ salsa::database_storage! { fn file_relative_path() for ra_db::FileRelativePathQuery; fn file_source_root() for ra_db::FileSourceRootQuery; fn source_root() for ra_db::SourceRootQuery; + fn source_root_crates() for ra_db::SourceRootCratesQuery; fn local_roots() for ra_db::LocalRootsQuery; fn library_roots() for ra_db::LibraryRootsQuery; fn crate_graph() for ra_db::CrateGraphQuery; diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index b1becca031..323bb1cc11 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs @@ -67,7 +67,7 @@ pub(crate) fn reference_definition( .node_expr(expr) .and_then(|it| infer_result.method_resolution(it)) { - if let Some(target) = NavigationTarget::from_def(db, def_id.resolve(db)) { + if let Some(target) = NavigationTarget::from_def(db, hir::ModuleDef::Def(def_id)) { return Exact(target); } }; @@ -84,7 +84,7 @@ pub(crate) fn reference_definition( { let resolved = module.resolve_path(db, &path); if let Some(def_id) = resolved.take_types().or(resolved.take_values()) { - if let Some(target) = NavigationTarget::from_def(db, def_id.resolve(db)) { + if let Some(target) = NavigationTarget::from_def(db, def_id) { return Exact(target); } } diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs index 21c15c0c00..1eb1776653 100644 --- a/crates/ra_ide_api/src/navigation_target.rs +++ b/crates/ra_ide_api/src/navigation_target.rs @@ -97,7 +97,17 @@ impl NavigationTarget { } // TODO once Def::Item is gone, this should be able to always return a NavigationTarget - pub(crate) fn from_def(db: &RootDatabase, def: Def) -> Option { + pub(crate) fn from_def( + db: &RootDatabase, + module_def: hir::ModuleDef, + ) -> Option { + let def = match module_def { + hir::ModuleDef::Def(def_id) => def_id.resolve(db), + hir::ModuleDef::Module(module) => { + return Some(NavigationTarget::from_module(db, module)); + } + }; + let res = match def { Def::Struct(s) => { let (file_id, node) = s.source(db); @@ -131,7 +141,6 @@ impl NavigationTarget { let (file_id, node) = f.source(db); NavigationTarget::from_named(file_id.original_file(db), &*node) } - Def::Module(m) => NavigationTarget::from_module(db, m), Def::Item => return None, }; Some(res) diff --git a/crates/ra_ide_api/src/rename.rs b/crates/ra_ide_api/src/rename.rs index 53dc273c63..5b767addd3 100644 --- a/crates/ra_ide_api/src/rename.rs +++ b/crates/ra_ide_api/src/rename.rs @@ -57,7 +57,6 @@ fn rename_mod( ) -> Option { let mut source_file_edits = Vec::new(); let mut file_system_edits = Vec::new(); - if let Some(module) = module_from_declaration(db, position.file_id, &ast_module) { let (file_id, module_source) = module.definition_source(db); match module_source { @@ -223,11 +222,15 @@ mod tests { fn test_rename_mod() { let (analysis, position) = analysis_and_position( " - //- /bar.rs - mod fo<|>o; - //- /bar/foo.rs - // emtpy - ", + //- /lib.rs + mod bar; + + //- /bar.rs + mod foo<|>; + + //- /bar/foo.rs + // emtpy + ", ); let new_name = "foo2"; let source_change = analysis.rename(position, new_name).unwrap(); @@ -238,11 +241,11 @@ mod tests { fn test_rename_mod_in_dir() { let (analysis, position) = analysis_and_position( " - //- /lib.rs - mod fo<|>o; - //- /foo/mod.rs - // emtpy - ", + //- /lib.rs + mod fo<|>o; + //- /foo/mod.rs + // emtpy + ", ); let new_name = "foo2"; let source_change = analysis.rename(position, new_name).unwrap(); diff --git a/crates/ra_ide_api/src/snapshots/tests__rename_mod.snap b/crates/ra_ide_api/src/snapshots/tests__rename_mod.snap index 3267d1ac5a..890426db77 100644 --- a/crates/ra_ide_api/src/snapshots/tests__rename_mod.snap +++ b/crates/ra_ide_api/src/snapshots/tests__rename_mod.snap @@ -1,8 +1,8 @@ --- -created: "2019-01-22T14:45:00.975229300+00:00" -creator: insta@0.4.0 +created: "2019-01-24T08:39:53.759318522+00:00" +creator: insta@0.5.2 expression: "&source_change" -source: "crates\\ra_ide_api\\src\\rename.rs" +source: crates/ra_ide_api/src/rename.rs --- Some( SourceChange { @@ -10,7 +10,7 @@ Some( source_file_edits: [ SourceFileEdit { file_id: FileId( - 1 + 2 ), edit: TextEdit { atoms: [ @@ -25,7 +25,7 @@ Some( file_system_edits: [ MoveFile { src: FileId( - 2 + 3 ), dst_source_root: SourceRootId( 0 From f1959bbae0cf2f99e63d074278cec165c274b4e5 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 24 Jan 2019 13:34:41 +0300 Subject: [PATCH 02/26] add FunctionId --- crates/ra_hir/src/ids.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 99f04e4ef5..73f1379f13 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs @@ -11,6 +11,7 @@ use crate::{ pub struct HirInterner { defs: LocationIntener, macros: LocationIntener, + fns: LocationIntener, } impl HirInterner { @@ -128,6 +129,28 @@ impl MacroCallLoc { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct FunctionId(RawId); +impl_arena_id!(FunctionId); + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct FunctionLoc { + pub(crate) module: Module, + pub(crate) source_item_id: SourceItemId, +} + +impl FunctionId { + pub(crate) fn loc(self, db: &impl AsRef) -> FunctionLoc { + db.as_ref().fns.id2loc(self) + } +} + +impl FunctionLoc { + pub(crate) fn id(&self, db: &impl AsRef) -> FunctionId { + db.as_ref().fns.loc2id(&self) + } +} + /// Def's are a core concept of hir. A `Def` is an Item (function, module, etc) /// in a specific module. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] From ec7ed054e06cb2e23fd3911932766b32014c8fa1 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 24 Jan 2019 15:28:50 +0300 Subject: [PATCH 03/26] Functions use new id scheme --- crates/ra_hir/src/code_model_api.rs | 39 ++-- crates/ra_hir/src/code_model_impl/function.rs | 29 +-- crates/ra_hir/src/code_model_impl/module.rs | 1 + crates/ra_hir/src/db.rs | 20 +- crates/ra_hir/src/expr.rs | 22 +-- crates/ra_hir/src/generics.rs | 66 +++++-- crates/ra_hir/src/ids.rs | 66 +++++-- crates/ra_hir/src/impl_block.rs | 31 ++- crates/ra_hir/src/nameres/lower.rs | 13 +- crates/ra_hir/src/query_definitions.rs | 8 +- crates/ra_hir/src/source_binder.rs | 19 +- crates/ra_hir/src/ty.rs | 180 ++++++++++-------- crates/ra_hir/src/ty/method_resolution.rs | 4 +- 13 files changed, 297 insertions(+), 201 deletions(-) diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index f59a60c07e..9056151277 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -16,6 +16,7 @@ use crate::{ code_model_impl::def_id_to_ast, docs::{Documentation, Docs, docs_from_ast}, module_tree::ModuleId, + ids::FunctionId, }; /// hir::Crate describes a single crate. It's the main interface with which @@ -49,7 +50,6 @@ pub enum Def { Struct(Struct), Enum(Enum), EnumVariant(EnumVariant), - Function(Function), Const(Const), Static(Static), Trait(Trait), @@ -67,6 +67,7 @@ pub struct Module { #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ModuleDef { Module(Module), + Function(Function), Def(DefId), } @@ -76,6 +77,12 @@ impl Into for Module { } } +impl Into for Function { + fn into(self) -> ModuleDef { + ModuleDef::Function(self) + } +} + impl Into for DefId { fn into(self) -> ModuleDef { ModuleDef::Def(self) @@ -225,7 +232,7 @@ impl Struct { } pub fn generic_params(&self, db: &impl HirDatabase) -> Arc { - db.generic_params(self.def_id) + db.generic_params(self.def_id.into()) } } @@ -262,7 +269,7 @@ impl Enum { } pub fn generic_params(&self, db: &impl HirDatabase) -> Arc { - db.generic_params(self.def_id) + db.generic_params(self.def_id.into()) } } @@ -320,9 +327,9 @@ impl Docs for EnumVariant { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Function { - pub(crate) def_id: DefId, + pub(crate) id: FunctionId, } pub use crate::code_model_impl::function::ScopeEntryWithSyntax; @@ -359,21 +366,17 @@ impl FnSignature { } impl Function { - pub fn def_id(&self) -> DefId { - self.def_id - } - pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc) { - def_id_to_ast(db, self.def_id) + self.id.loc(db).source(db) } pub fn body_syntax_mapping(&self, db: &impl HirDatabase) -> Arc { - db.body_syntax_mapping(self.def_id) + db.body_syntax_mapping(*self) } pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSyntaxMapping { - let scopes = db.fn_scopes(self.def_id); - let syntax_mapping = db.body_syntax_mapping(self.def_id); + let scopes = db.fn_scopes(*self); + let syntax_mapping = db.body_syntax_mapping(*self); ScopesWithSyntaxMapping { scopes, syntax_mapping, @@ -381,15 +384,15 @@ impl Function { } pub fn signature(&self, db: &impl HirDatabase) -> Arc { - db.fn_signature(self.def_id) + db.fn_signature(*self) } pub fn infer(&self, db: &impl HirDatabase) -> Arc { - db.infer(self.def_id) + db.infer(*self) } pub fn generic_params(&self, db: &impl HirDatabase) -> Arc { - db.generic_params(self.def_id) + db.generic_params((*self).into()) } } @@ -456,7 +459,7 @@ impl Trait { } pub fn generic_params(&self, db: &impl HirDatabase) -> Arc { - db.generic_params(self.def_id) + db.generic_params(self.def_id.into()) } } @@ -481,7 +484,7 @@ impl Type { } pub fn generic_params(&self, db: &impl HirDatabase) -> Arc { - db.generic_params(self.def_id) + db.generic_params(self.def_id.into()) } } diff --git a/crates/ra_hir/src/code_model_impl/function.rs b/crates/ra_hir/src/code_model_impl/function.rs index c68c6bfbf0..d8dafb10e4 100644 --- a/crates/ra_hir/src/code_model_impl/function.rs +++ b/crates/ra_hir/src/code_model_impl/function.rs @@ -2,41 +2,48 @@ mod scope; use std::sync::Arc; -use ra_syntax::{TreeArc, ast::{self, NameOwner}}; +use ra_syntax::ast::{self, NameOwner}; use crate::{ - DefId, HirDatabase, Name, AsName, Function, FnSignature, Module, + HirDatabase, Name, AsName, Function, FnSignature, Module, HirFileId, type_ref::{TypeRef, Mutability}, expr::Body, impl_block::ImplBlock, - code_model_impl::def_id_to_ast, + ids::FunctionLoc, }; pub use self::scope::{FnScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax}; impl Function { - pub(crate) fn new(def_id: DefId) -> Function { - Function { def_id } + pub(crate) fn from_ast( + db: &impl HirDatabase, + module: Module, + file_id: HirFileId, + ast: &ast::FnDef, + ) -> Function { + let loc: FunctionLoc = FunctionLoc::from_ast(db, module, file_id, ast); + let id = loc.id(db); + Function { id } } pub(crate) fn body(&self, db: &impl HirDatabase) -> Arc { - db.body_hir(self.def_id) + db.body_hir(*self) } pub(crate) fn module(&self, db: &impl HirDatabase) -> Module { - self.def_id.module(db) + self.id.loc(db).module } /// The containing impl block, if this is a method. pub(crate) fn impl_block(&self, db: &impl HirDatabase) -> Option { - self.def_id.impl_block(db) + let module_impls = db.impls_in_module(self.module(db)); + ImplBlock::containing(module_impls, (*self).into()) } } impl FnSignature { - pub(crate) fn fn_signature_query(db: &impl HirDatabase, def_id: DefId) -> Arc { - // FIXME: we're using def_id_to_ast here to avoid returning Cancelable... this is a bit hacky - let node: TreeArc = def_id_to_ast(db, def_id).1; + pub(crate) fn fn_signature_query(db: &impl HirDatabase, func: Function) -> Arc { + let (_, node) = func.source(db); let name = node .name() .map(|n| n.as_name()) diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs index 5d00e905b6..b2828c7be0 100644 --- a/crates/ra_hir/src/code_model_impl/module.rs +++ b/crates/ra_hir/src/code_model_impl/module.rs @@ -135,6 +135,7 @@ impl Module { None => PerNs::none(), } } + ModuleDef::Function(_) => PerNs::none(), ModuleDef::Def(def) => { match def.resolve(db) { Def::Enum(e) => { diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 0898daa3c4..97de7da317 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -7,14 +7,14 @@ use crate::{ DefId, MacroCallId, Name, HirFileId, SourceFileItems, SourceItemId, Crate, Module, HirInterner, query_definitions, - FnSignature, FnScopes, + Function, FnSignature, FnScopes, macros::MacroExpansion, module_tree::ModuleTree, nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}}, - ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks}, + ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef}, adt::{StructData, EnumData, EnumVariantData}, impl_block::ModuleImplBlocks, - generics::GenericParams, + generics::{GenericParams, GenericDef}, }; #[salsa::query_group] @@ -26,7 +26,7 @@ pub trait HirDatabase: SyntaxDatabase + AsRef { fn expand_macro_invocation(&self, invoc: MacroCallId) -> Option>; #[salsa::invoke(query_definitions::fn_scopes)] - fn fn_scopes(&self, def_id: DefId) -> Arc; + fn fn_scopes(&self, func: Function) -> Arc; #[salsa::invoke(crate::adt::StructData::struct_data_query)] fn struct_data(&self, def_id: DefId) -> Arc; @@ -38,10 +38,10 @@ pub trait HirDatabase: SyntaxDatabase + AsRef { fn enum_variant_data(&self, def_id: DefId) -> Arc; #[salsa::invoke(crate::ty::infer)] - fn infer(&self, def_id: DefId) -> Arc; + fn infer(&self, func: Function) -> Arc; #[salsa::invoke(crate::ty::type_for_def)] - fn type_for_def(&self, def_id: DefId) -> Ty; + fn type_for_def(&self, def: TypableDef) -> Ty; #[salsa::invoke(crate::ty::type_for_field)] fn type_for_field(&self, def_id: DefId, field: Name) -> Option; @@ -77,14 +77,14 @@ pub trait HirDatabase: SyntaxDatabase + AsRef { fn impls_in_crate(&self, krate: Crate) -> Arc; #[salsa::invoke(crate::expr::body_hir)] - fn body_hir(&self, def_id: DefId) -> Arc; + fn body_hir(&self, func: Function) -> Arc; #[salsa::invoke(crate::expr::body_syntax_mapping)] - fn body_syntax_mapping(&self, def_id: DefId) -> Arc; + fn body_syntax_mapping(&self, func: Function) -> Arc; #[salsa::invoke(crate::generics::GenericParams::generic_params_query)] - fn generic_params(&self, def_id: DefId) -> Arc; + fn generic_params(&self, def: GenericDef) -> Arc; #[salsa::invoke(crate::FnSignature::fn_signature_query)] - fn fn_signature(&self, def_id: DefId) -> Arc; + fn fn_signature(&self, func: Function) -> Arc; } diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 1a38216922..29469af2cf 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs @@ -9,7 +9,11 @@ use ra_syntax::{ ast::{self, LoopBodyOwner, ArgListOwner, NameOwner, LiteralFlavor} }; -use crate::{Path, type_ref::{Mutability, TypeRef}, Name, HirDatabase, DefId, Def, name::AsName}; +use crate::{ + Path, Name, HirDatabase, Function, + name::AsName, + type_ref::{Mutability, TypeRef}, +}; use crate::ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy}; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -435,8 +439,8 @@ impl Pat { // Queries -pub(crate) fn body_hir(db: &impl HirDatabase, def_id: DefId) -> Arc { - Arc::clone(&body_syntax_mapping(db, def_id).body) +pub(crate) fn body_hir(db: &impl HirDatabase, func: Function) -> Arc { + Arc::clone(&body_syntax_mapping(db, func).body) } struct ExprCollector { @@ -955,14 +959,8 @@ pub(crate) fn collect_fn_body_syntax(node: &ast::FnDef) -> BodySyntaxMapping { collector.into_body_syntax_mapping(params, body) } -pub(crate) fn body_syntax_mapping(db: &impl HirDatabase, def_id: DefId) -> Arc { - let def = def_id.resolve(db); - - let body_syntax_mapping = match def { - Def::Function(f) => collect_fn_body_syntax(&f.source(db).1), - // TODO: consts, etc. - _ => panic!("Trying to get body for item type without body"), - }; - +pub(crate) fn body_syntax_mapping(db: &impl HirDatabase, func: Function) -> Arc { + let (_, fn_def) = func.source(db); + let body_syntax_mapping = collect_fn_body_syntax(&fn_def); Arc::new(body_syntax_mapping) } diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index d8248ad491..88c53705fa 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs @@ -5,9 +5,9 @@ use std::sync::Arc; -use ra_syntax::ast::{TypeParamList, AstNode, NameOwner}; +use ra_syntax::ast::{self, AstNode, NameOwner, TypeParamsOwner}; -use crate::{db::HirDatabase, DefId, Name, AsName}; +use crate::{db::HirDatabase, DefId, Name, AsName, Function}; /// Data about a generic parameter (to a function, struct, impl, ...). #[derive(Clone, PartialEq, Eq, Debug)] @@ -22,26 +22,62 @@ pub struct GenericParams { pub(crate) params: Vec, } +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +pub enum GenericDef { + Function(Function), + Def(DefId), +} + +impl From for GenericDef { + fn from(func: Function) -> GenericDef { + GenericDef::Function(func) + } +} + +impl From for GenericDef { + fn from(def_id: DefId) -> GenericDef { + GenericDef::Def(def_id) + } +} + impl GenericParams { - pub(crate) fn generic_params_query(db: &impl HirDatabase, def_id: DefId) -> Arc { - let (_file_id, node) = def_id.source(db); + pub(crate) fn generic_params_query( + db: &impl HirDatabase, + def: GenericDef, + ) -> Arc { let mut generics = GenericParams::default(); - if let Some(type_param_list) = node.children().find_map(TypeParamList::cast) { - for (idx, type_param) in type_param_list.type_params().enumerate() { - let name = type_param - .name() - .map(AsName::as_name) - .unwrap_or_else(Name::missing); - let param = GenericParam { - idx: idx as u32, - name, - }; - generics.params.push(param); + match def { + GenericDef::Function(func) => { + let (_, fn_def) = func.source(db); + if let Some(type_param_list) = fn_def.type_param_list() { + generics.fill(type_param_list) + } + } + GenericDef::Def(def_id) => { + let (_file_id, node) = def_id.source(db); + if let Some(type_param_list) = node.children().find_map(ast::TypeParamList::cast) { + generics.fill(type_param_list) + } } } + Arc::new(generics) } + fn fill(&mut self, params: &ast::TypeParamList) { + for (idx, type_param) in params.type_params().enumerate() { + let name = type_param + .name() + .map(AsName::as_name) + .unwrap_or_else(Name::missing); + let param = GenericParam { + idx: idx as u32, + name, + }; + self.params.push(param); + } + } + pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { self.params.iter().find(|p| &p.name == name) } diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 73f1379f13..913341bd51 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs @@ -1,9 +1,11 @@ +use std::marker::PhantomData; + use ra_db::{LocationIntener, FileId}; use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, ast}; use ra_arena::{Arena, RawId, impl_arena_id}; use crate::{ - HirDatabase, Def, Function, Struct, Enum, EnumVariant, ImplBlock, Crate, + HirDatabase, Def, Struct, Enum, EnumVariant, Crate, Module, Trait, Type, Static, Const, }; @@ -129,15 +131,56 @@ impl MacroCallLoc { } } +#[derive(Debug, PartialEq, Eq, Hash)] +pub struct ItemLoc { + pub(crate) module: Module, + raw: SourceItemId, + _ty: PhantomData, +} + +impl ItemLoc { + pub(crate) fn from_ast( + db: &impl HirDatabase, + module: Module, + file_id: HirFileId, + ast: &N, + ) -> ItemLoc { + let items = db.file_items(file_id); + let raw = SourceItemId { + file_id, + item_id: Some(items.id_of(file_id, ast.syntax())), + }; + ItemLoc { + module, + raw, + _ty: PhantomData, + } + } + + pub(crate) fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc) { + let syntax = db.file_item(self.raw); + let ast = N::cast(&syntax) + .unwrap_or_else(|| panic!("invalid ItemLoc: {:?}", self.raw)) + .to_owned(); + (self.raw.file_id, ast) + } +} + +impl Clone for ItemLoc { + fn clone(&self) -> ItemLoc { + ItemLoc { + module: self.module, + raw: self.raw, + _ty: PhantomData, + } + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct FunctionId(RawId); impl_arena_id!(FunctionId); -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct FunctionLoc { - pub(crate) module: Module, - pub(crate) source_item_id: SourceItemId, -} +pub(crate) type FunctionLoc = ItemLoc; impl FunctionId { pub(crate) fn loc(self, db: &impl AsRef) -> FunctionLoc { @@ -196,10 +239,7 @@ impl DefId { pub fn resolve(self, db: &impl HirDatabase) -> Def { let loc = self.loc(db); match loc.kind { - DefKind::Function => { - let function = Function::new(self); - Def::Function(function) - } + DefKind::Function => unreachable!(), DefKind::Struct => { let struct_def = Struct::new(self); Def::Struct(struct_def) @@ -243,12 +283,6 @@ impl DefId { pub fn krate(&self, db: &impl HirDatabase) -> Option { self.module(db).krate(db) } - - /// Returns the containing impl block, if this is an impl item. - pub fn impl_block(self, db: &impl HirDatabase) -> Option { - let module_impls = db.impls_in_module(self.loc(db).module); - ImplBlock::containing(module_impls, self) - } } impl DefLoc { diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index ba8b84da2c..29becd3176 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs @@ -6,7 +6,7 @@ use ra_syntax::ast::{self, AstNode}; use crate::{ DefId, DefLoc, DefKind, SourceItemId, SourceFileItems, - Function, HirFileId, HirInterner, + Function, HirFileId, db::HirDatabase, type_ref::TypeRef, }; @@ -22,9 +22,9 @@ pub struct ImplBlock { impl ImplBlock { pub(crate) fn containing( module_impl_blocks: Arc, - def_id: DefId, + item: ImplItem, ) -> Option { - let impl_id = *module_impl_blocks.impls_by_def.get(&def_id)?; + let impl_id = *module_impl_blocks.impls_by_def.get(&item)?; Some(ImplBlock { module_impl_blocks, impl_id, @@ -64,7 +64,7 @@ pub struct ImplData { impl ImplData { pub(crate) fn from_ast( - db: &impl AsRef, + db: &impl HirDatabase, file_id: HirFileId, file_items: &SourceFileItems, module: Module, @@ -93,7 +93,9 @@ impl ImplData { }; let def_id = def_loc.id(db); match item_node.kind() { - ast::ImplItemKind::FnDef(..) => ImplItem::Method(Function::new(def_id)), + ast::ImplItemKind::FnDef(it) => { + ImplItem::Method(Function::from_ast(db, module, file_id, it)) + } ast::ImplItemKind::ConstDef(..) => ImplItem::Const(def_id), ast::ImplItemKind::TypeDef(..) => ImplItem::Type(def_id), } @@ -122,7 +124,8 @@ impl ImplData { } } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +//TODO: rename to ImplDef? pub enum ImplItem { Method(Function), // these don't have their own types yet @@ -131,13 +134,9 @@ pub enum ImplItem { // Existential } -impl ImplItem { - pub fn def_id(&self) -> DefId { - match self { - ImplItem::Method(f) => f.def_id(), - ImplItem::Const(def_id) => *def_id, - ImplItem::Type(def_id) => *def_id, - } +impl From for ImplItem { + fn from(func: Function) -> ImplItem { + ImplItem::Method(func) } } @@ -153,7 +152,7 @@ impl_arena_id!(ImplId); #[derive(Debug, PartialEq, Eq)] pub struct ModuleImplBlocks { pub(crate) impls: Arena, - impls_by_def: FxHashMap, + impls_by_def: FxHashMap, } impl ModuleImplBlocks { @@ -181,8 +180,8 @@ impl ModuleImplBlocks { let impl_block = ImplData::from_ast(db, file_id, &source_file_items, module, impl_block_ast); let id = self.impls.alloc(impl_block); - for impl_item in &self.impls[id].items { - self.impls_by_def.insert(impl_item.def_id(), id); + for &impl_item in &self.impls[id].items { + self.impls_by_def.insert(impl_item, id); } } } diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs index 6f003bd666..1f8adc7eb1 100644 --- a/crates/ra_hir/src/nameres/lower.rs +++ b/crates/ra_hir/src/nameres/lower.rs @@ -9,7 +9,7 @@ use rustc_hash::FxHashMap; use crate::{ SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems, - HirFileId, MacroCallLoc, AsName, PerNs, DefKind, DefLoc, + HirFileId, MacroCallLoc, AsName, PerNs, DefKind, DefLoc, Function, ModuleDef, Module, }; @@ -149,7 +149,14 @@ impl LoweredModule { let name = match item.kind() { ast::ModuleItemKind::StructDef(it) => it.name(), ast::ModuleItemKind::EnumDef(it) => it.name(), - ast::ModuleItemKind::FnDef(it) => it.name(), + ast::ModuleItemKind::FnDef(it) => { + if let Some(name) = it.name() { + let func = Function::from_ast(db, module, file_id, it); + self.declarations + .insert(name.as_name(), PerNs::values(func.into())); + } + return; + } ast::ModuleItemKind::TraitDef(it) => it.name(), ast::ModuleItemKind::TypeDef(it) => it.name(), ast::ModuleItemKind::ImplBlock(_) => { @@ -218,7 +225,7 @@ fn assign_def_id( impl DefKind { fn for_syntax_kind(kind: SyntaxKind) -> PerNs { match kind { - SyntaxKind::FN_DEF => PerNs::values(DefKind::Function), + SyntaxKind::FN_DEF => unreachable!(), SyntaxKind::STRUCT_DEF => PerNs::both(DefKind::Struct, DefKind::StructCtor), SyntaxKind::ENUM_DEF => PerNs::types(DefKind::Enum), SyntaxKind::TRAIT_DEF => PerNs::types(DefKind::Trait), diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs index a8ed887b34..cf8c7e4354 100644 --- a/crates/ra_hir/src/query_definitions.rs +++ b/crates/ra_hir/src/query_definitions.rs @@ -10,14 +10,14 @@ use ra_syntax::{ use ra_db::{CrateId}; use crate::{ - SourceFileItems, SourceItemId, DefId, HirFileId, - FnScopes, Module, + SourceFileItems, SourceItemId, HirFileId, + Function, FnScopes, Module, db::HirDatabase, nameres::{ItemMap, Resolver}, }; -pub(super) fn fn_scopes(db: &impl HirDatabase, def_id: DefId) -> Arc { - let body = db.body_hir(def_id); +pub(super) fn fn_scopes(db: &impl HirDatabase, func: Function) -> Arc { + let body = db.body_hir(func); let res = FnScopes::new(body); Arc::new(res) } diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index c3bd31d6b1..d1bf163d14 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -14,7 +14,7 @@ use ra_syntax::{ use crate::{ HirDatabase, Function, SourceItemId, ModuleDef, - DefKind, DefLoc, AsName, Module, + AsName, Module, }; /// Locates the module by `FileId`. Picks topmost module in the file. @@ -105,29 +105,18 @@ pub fn function_from_source( fn_def: &ast::FnDef, ) -> Option { let module = module_from_child_node(db, file_id, fn_def.syntax())?; - let res = function_from_module(db, &module, fn_def); + let res = function_from_module(db, module, fn_def); Some(res) } pub fn function_from_module( db: &impl HirDatabase, - module: &Module, + module: Module, fn_def: &ast::FnDef, ) -> Function { let (file_id, _) = module.definition_source(db); let file_id = file_id.into(); - let file_items = db.file_items(file_id); - let item_id = file_items.id_of(file_id, fn_def.syntax()); - let source_item_id = SourceItemId { - file_id, - item_id: Some(item_id), - }; - let def_loc = DefLoc { - module: module.clone(), - kind: DefKind::Function, - source_item_id, - }; - Function::new(def_loc.id(db)) + Function::from_ast(db, module, file_id, fn_def) } pub fn function_from_child_node( diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 4c96579eeb..f9cdbcab33 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -382,7 +382,8 @@ impl Ty { // Resolve in module (in type namespace) let resolved = match module.resolve_path(db, path).take_types() { - Some(ModuleDef::Def(r)) => r, + Some(ModuleDef::Def(r)) => r.into(), + Some(ModuleDef::Function(f)) => f.into(), None | Some(ModuleDef::Module(_)) => return Ty::Unknown, }; let ty = db.type_for_def(resolved); @@ -399,36 +400,38 @@ impl Ty { impl_block: Option<&ImplBlock>, outer_generics: &GenericParams, path: &Path, - resolved: DefId, + resolved: TypableDef, ) -> Substs { let mut substs = Vec::new(); - let def = resolved.resolve(db); let last = path .segments .last() .expect("path should have at least one segment"); - let (def_generics, segment) = match def { - Def::Struct(s) => (s.generic_params(db), last), - Def::Enum(e) => (e.generic_params(db), last), - Def::Function(f) => (f.generic_params(db), last), - Def::Trait(t) => (t.generic_params(db), last), - Def::EnumVariant(ev) => { - // the generic args for an enum variant may be either specified - // on the segment referring to the enum, or on the segment - // referring to the variant. So `Option::::None` and - // `Option::None::` are both allowed (though the former is - // preferred). See also `def_ids_for_path_segments` in rustc. - let len = path.segments.len(); - let segment = if len >= 2 && path.segments[len - 2].args_and_bindings.is_some() { - // Option::::None - &path.segments[len - 2] - } else { - // Option::None:: - last - }; - (ev.parent_enum(db).generic_params(db), segment) - } - _ => return Substs::empty(), + let (def_generics, segment) = match resolved { + TypableDef::Function(func) => (func.generic_params(db), last), + TypableDef::Def(def_id) => match def_id.resolve(db) { + Def::Struct(s) => (s.generic_params(db), last), + Def::Enum(e) => (e.generic_params(db), last), + Def::Trait(t) => (t.generic_params(db), last), + Def::EnumVariant(ev) => { + // the generic args for an enum variant may be either specified + // on the segment referring to the enum, or on the segment + // referring to the variant. So `Option::::None` and + // `Option::None::` are both allowed (though the former is + // preferred). See also `def_ids_for_path_segments` in rustc. + let len = path.segments.len(); + let segment = if len >= 2 && path.segments[len - 2].args_and_bindings.is_some() + { + // Option::::None + &path.segments[len - 2] + } else { + // Option::None:: + last + }; + (ev.parent_enum(db).generic_params(db), segment) + } + _ => return Substs::empty(), + }, }; // substs_from_path if let Some(generic_args) = &segment.args_and_bindings { @@ -660,21 +663,40 @@ pub(crate) fn type_for_enum_variant(db: &impl HirDatabase, ev: EnumVariant) -> T type_for_enum(db, enum_parent) } -pub(super) fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Ty { - let def = def_id.resolve(db); +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub enum TypableDef { + Function(Function), + Def(DefId), +} + +impl From for TypableDef { + fn from(func: Function) -> TypableDef { + TypableDef::Function(func) + } +} + +impl From for TypableDef { + fn from(func: DefId) -> TypableDef { + TypableDef::Def(func) + } +} + +pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty { match def { - Def::Function(f) => type_for_fn(db, f), - Def::Struct(s) => type_for_struct(db, s), - Def::Enum(e) => type_for_enum(db, e), - Def::EnumVariant(ev) => type_for_enum_variant(db, ev), - _ => { - log::debug!( - "trying to get type for item of unknown type {:?} {:?}", - def_id, - def - ); - Ty::Unknown - } + TypableDef::Function(f) => type_for_fn(db, f), + TypableDef::Def(def_id) => match def_id.resolve(db) { + Def::Struct(s) => type_for_struct(db, s), + Def::Enum(e) => type_for_enum(db, e), + Def::EnumVariant(ev) => type_for_enum_variant(db, ev), + _ => { + log::debug!( + "trying to get type for item of unknown type {:?} {:?}", + def_id, + def + ); + Ty::Unknown + } + }, } } @@ -694,28 +716,23 @@ pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name) ), }; let module = def_id.module(db); - let impl_block = def_id.impl_block(db); + // We can't have an impl block ere, right? + // let impl_block = def_id.impl_block(db); let type_ref = variant_data.get_field_type_ref(&field)?; - Some(Ty::from_hir( - db, - &module, - impl_block.as_ref(), - &generics, - &type_ref, - )) + Some(Ty::from_hir(db, &module, None, &generics, &type_ref)) } /// The result of type inference: A mapping from expressions and patterns to types. #[derive(Clone, PartialEq, Eq, Debug)] pub struct InferenceResult { /// For each method call expr, record the function it resolved to. - method_resolutions: FxHashMap, + method_resolutions: FxHashMap, type_of_expr: ArenaMap, type_of_pat: ArenaMap, } impl InferenceResult { - pub fn method_resolution(&self, expr: ExprId) -> Option { + pub fn method_resolution(&self, expr: ExprId) -> Option { self.method_resolutions.get(&expr).map(|it| *it) } } @@ -745,7 +762,7 @@ struct InferenceContext<'a, D: HirDatabase> { module: Module, impl_block: Option, var_unification_table: InPlaceUnificationTable, - method_resolutions: FxHashMap, + method_resolutions: FxHashMap, type_of_expr: ArenaMap, type_of_pat: ArenaMap, /// The return type of the function being inferred. @@ -871,8 +888,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { self.type_of_expr.insert(expr, ty); } - fn write_method_resolution(&mut self, expr: ExprId, def_id: DefId) { - self.method_resolutions.insert(expr, def_id); + fn write_method_resolution(&mut self, expr: ExprId, func: Function) { + self.method_resolutions.insert(expr, func); } fn write_pat_ty(&mut self, pat: PatId, ty: Ty) { @@ -1060,7 +1077,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { // resolve in module let resolved = match self.module.resolve_path(self.db, &path).take_values()? { - ModuleDef::Def(it) => it, + ModuleDef::Def(it) => it.into(), + ModuleDef::Function(func) => func.into(), ModuleDef::Module(_) => return None, }; let ty = self.db.type_for_def(resolved); @@ -1073,8 +1091,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Some(path) => path, None => return (Ty::Unknown, None), }; - let def_id = match self.module.resolve_path(self.db, &path).take_types() { - Some(ModuleDef::Def(def_id)) => def_id, + let def = match self.module.resolve_path(self.db, &path).take_types() { + Some(ModuleDef::Def(def_id)) => def_id.into(), + Some(ModuleDef::Function(func)) => func.into(), _ => return (Ty::Unknown, None), }; // TODO remove the duplication between here and `Ty::from_path`? @@ -1086,20 +1105,23 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { self.impl_block.as_ref(), &generics, path, - def_id, + def, ); - match def_id.resolve(self.db) { - Def::Struct(s) => { - let ty = type_for_struct(self.db, s); - let ty = self.insert_type_vars(ty.apply_substs(substs)); - (ty, Some(def_id)) - } - Def::EnumVariant(ev) => { - let ty = type_for_enum_variant(self.db, ev); - let ty = self.insert_type_vars(ty.apply_substs(substs)); - (ty, Some(def_id)) - } - _ => (Ty::Unknown, None), + match def { + TypableDef::Def(def_id) => match def_id.resolve(self.db) { + Def::Struct(s) => { + let ty = type_for_struct(self.db, s); + let ty = self.insert_type_vars(ty.apply_substs(substs)); + (ty, Some(def_id)) + } + Def::EnumVariant(ev) => { + let ty = type_for_enum_variant(self.db, ev); + let ty = self.insert_type_vars(ty.apply_substs(substs)); + (ty, Some(def_id)) + } + _ => (Ty::Unknown, None), + }, + TypableDef::Function(_) => (Ty::Unknown, None), } } @@ -1216,7 +1238,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { .resolve_path(self.db, &path) .take_values() .and_then(|module_def| match module_def { - ModuleDef::Def(it) => Some(it), + ModuleDef::Def(it) => Some(it.into()), + ModuleDef::Function(func) => Some(func.into()), ModuleDef::Module(_) => None, }) .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)), @@ -1339,9 +1362,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let receiver_ty = self.infer_expr(*receiver, &Expectation::none()); let resolved = receiver_ty.clone().lookup_method(self.db, method_name); let method_ty = match resolved { - Some(def_id) => { - self.write_method_resolution(expr, def_id); - self.db.type_for_def(def_id) + Some(func) => { + self.write_method_resolution(expr, func); + self.db.type_for_def(func.into()) } None => Ty::Unknown, }; @@ -1610,16 +1633,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } } -pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Arc { +pub fn infer(db: &impl HirDatabase, func: Function) -> Arc { db.check_canceled(); - let function = Function::new(def_id); // TODO: consts also need inference - let body = function.body(db); - let scopes = db.fn_scopes(def_id); - let module = function.module(db); - let impl_block = function.impl_block(db); + let body = func.body(db); + let scopes = db.fn_scopes(func); + let module = func.module(db); + let impl_block = func.impl_block(db); let mut ctx = InferenceContext::new(db, body, scopes, module, impl_block); - let signature = function.signature(db); + let signature = func.signature(db); ctx.collect_fn_signature(&signature); ctx.infer_body(); diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index a5567a78fb..0084b24dc7 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs @@ -118,11 +118,11 @@ impl Ty { // TODO: cache this as a query? // - if so, what signature? (TyFingerprint, Name)? // - or maybe cache all names and def_ids of methods per fingerprint? - pub fn lookup_method(self, db: &impl HirDatabase, name: &Name) -> Option { + pub fn lookup_method(self, db: &impl HirDatabase, name: &Name) -> Option { self.iterate_methods(db, |f| { let sig = f.signature(db); if sig.name() == name && sig.has_self_param() { - Some(f.def_id()) + Some(f) } else { None } From 1754dd9fdd1bf7d3d72aa2bcb25f33fd8885cd7c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 24 Jan 2019 15:31:12 +0300 Subject: [PATCH 04/26] remove DefKind::Function --- crates/ra_hir/src/ids.rs | 2 -- crates/ra_hir/src/impl_block.rs | 8 ++++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 913341bd51..f00448081c 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs @@ -209,7 +209,6 @@ pub struct DefLoc { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub(crate) enum DefKind { - Function, Struct, Enum, EnumVariant, @@ -239,7 +238,6 @@ impl DefId { pub fn resolve(self, db: &impl HirDatabase) -> Def { let loc = self.loc(db); match loc.kind { - DefKind::Function => unreachable!(), DefKind::Struct => { let struct_def = Struct::new(self); Def::Struct(struct_def) diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index 29becd3176..274169f93d 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs @@ -77,7 +77,9 @@ impl ImplData { .impl_items() .map(|item_node| { let kind = match item_node.kind() { - ast::ImplItemKind::FnDef(..) => DefKind::Function, + ast::ImplItemKind::FnDef(it) => { + return ImplItem::Method(Function::from_ast(db, module, file_id, it)); + } ast::ImplItemKind::ConstDef(..) => DefKind::Item, ast::ImplItemKind::TypeDef(..) => DefKind::Item, }; @@ -93,9 +95,7 @@ impl ImplData { }; let def_id = def_loc.id(db); match item_node.kind() { - ast::ImplItemKind::FnDef(it) => { - ImplItem::Method(Function::from_ast(db, module, file_id, it)) - } + ast::ImplItemKind::FnDef(_) => unreachable!(), ast::ImplItemKind::ConstDef(..) => ImplItem::Const(def_id), ast::ImplItemKind::TypeDef(..) => ImplItem::Type(def_id), } From 2734636c532101565b1a4c4715790d4cc910ad47 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 24 Jan 2019 15:40:52 +0300 Subject: [PATCH 05/26] update ide_api to new hir --- crates/ra_ide_api/src/completion/complete_path.rs | 2 ++ .../ra_ide_api/src/completion/completion_context.rs | 2 +- crates/ra_ide_api/src/completion/completion_item.rs | 2 +- crates/ra_ide_api/src/goto_definition.rs | 6 ++---- crates/ra_ide_api/src/navigation_target.rs | 12 ++++++++---- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index 0d79424968..3aef479d97 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs @@ -44,6 +44,8 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { } _ => return, }, + + hir::ModuleDef::Function(_) => return, }; } diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs index ca2069e2a7..578af6e5b3 100644 --- a/crates/ra_ide_api/src/completion/completion_context.rs +++ b/crates/ra_ide_api/src/completion/completion_context.rs @@ -127,7 +127,7 @@ impl<'a> CompletionContext<'a> { .ancestors() .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE) .find_map(ast::FnDef::cast); - match (&self.module, self.function_syntax) { + match (self.module, self.function_syntax) { (Some(module), Some(fn_def)) => { let function = source_binder::function_from_module(self.db, module, fn_def); self.function = Some(function); diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs index 5d6718a8d0..5b2ba7e4a4 100644 --- a/crates/ra_ide_api/src/completion/completion_item.rs +++ b/crates/ra_ide_api/src/completion/completion_item.rs @@ -219,6 +219,7 @@ impl Builder { }; let (kind, docs) = match def { hir::ModuleDef::Module(_) => (CompletionItemKind::Module, None), + hir::ModuleDef::Function(func) => return self.from_function(ctx, func), hir::ModuleDef::Def(def_id) => match def_id.resolve(ctx.db) { hir::Def::Struct(it) => (CompletionItemKind::Struct, it.docs(ctx.db)), hir::Def::Enum(it) => (CompletionItemKind::Enum, it.docs(ctx.db)), @@ -226,7 +227,6 @@ impl Builder { hir::Def::Type(it) => (CompletionItemKind::TypeAlias, it.docs(ctx.db)), hir::Def::Const(it) => (CompletionItemKind::Const, it.docs(ctx.db)), hir::Def::Static(it) => (CompletionItemKind::Static, it.docs(ctx.db)), - hir::Def::Function(function) => return self.from_function(ctx, function), _ => return self, }, }; diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 323bb1cc11..46bdde00d7 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs @@ -63,13 +63,11 @@ pub(crate) fn reference_definition( let infer_result = function.infer(db); let syntax_mapping = function.body_syntax_mapping(db); let expr = ast::Expr::cast(method_call.syntax()).unwrap(); - if let Some(def_id) = syntax_mapping + if let Some(func) = syntax_mapping .node_expr(expr) .and_then(|it| infer_result.method_resolution(it)) { - if let Some(target) = NavigationTarget::from_def(db, hir::ModuleDef::Def(def_id)) { - return Exact(target); - } + return Exact(NavigationTarget::from_function(db, func)); }; } } diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs index 1eb1776653..19cea2fd67 100644 --- a/crates/ra_ide_api/src/navigation_target.rs +++ b/crates/ra_ide_api/src/navigation_target.rs @@ -96,6 +96,11 @@ impl NavigationTarget { NavigationTarget::from_module(db, module) } + pub(crate) fn from_function(db: &RootDatabase, func: hir::Function) -> NavigationTarget { + let (file_id, fn_def) = func.source(db); + NavigationTarget::from_named(file_id.original_file(db), &*fn_def) + } + // TODO once Def::Item is gone, this should be able to always return a NavigationTarget pub(crate) fn from_def( db: &RootDatabase, @@ -106,6 +111,9 @@ impl NavigationTarget { hir::ModuleDef::Module(module) => { return Some(NavigationTarget::from_module(db, module)); } + hir::ModuleDef::Function(func) => { + return Some(NavigationTarget::from_function(db, func)); + } }; let res = match def { @@ -121,10 +129,6 @@ impl NavigationTarget { let (file_id, node) = ev.source(db); NavigationTarget::from_named(file_id.original_file(db), &*node) } - Def::Function(f) => { - let (file_id, node) = f.source(db); - NavigationTarget::from_named(file_id.original_file(db), &*node) - } Def::Trait(f) => { let (file_id, node) = f.source(db); NavigationTarget::from_named(file_id.original_file(db), &*node) From c57a8579888643e73e12dd0ca23e81f88608c52f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 24 Jan 2019 16:18:20 +0300 Subject: [PATCH 06/26] add StructId --- crates/ra_hir/src/ids.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index f00448081c..51e3cfb813 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs @@ -14,6 +14,7 @@ pub struct HirInterner { defs: LocationIntener, macros: LocationIntener, fns: LocationIntener, + structs: LocationIntener, } impl HirInterner { @@ -194,6 +195,24 @@ impl FunctionLoc { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct StructId(RawId); +impl_arena_id!(StructId); + +pub(crate) type StructLoc = ItemLoc; + +impl StructId { + pub(crate) fn loc(self, db: &impl AsRef) -> StructLoc { + db.as_ref().structs.id2loc(self) + } +} + +impl StructLoc { + pub(crate) fn id(&self, db: &impl AsRef) -> StructId { + db.as_ref().structs.loc2id(&self) + } +} + /// Def's are a core concept of hir. A `Def` is an Item (function, module, etc) /// in a specific module. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] From 60a607d33f1c50acd0a4218da32abe35b2941e38 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 24 Jan 2019 17:54:18 +0300 Subject: [PATCH 07/26] new struct id --- crates/ra_hir/src/adt.rs | 26 +-- crates/ra_hir/src/code_model_api.rs | 33 ++-- crates/ra_hir/src/code_model_impl/module.rs | 2 +- crates/ra_hir/src/db.rs | 7 +- crates/ra_hir/src/generics.rs | 15 +- crates/ra_hir/src/ids.rs | 7 +- crates/ra_hir/src/lib.rs | 2 +- crates/ra_hir/src/nameres/lower.rs | 11 +- crates/ra_hir/src/ty.rs | 150 +++++++++++++----- crates/ra_hir/src/ty/method_resolution.rs | 8 +- .../src/ty/snapshots/tests__infer_struct.snap | 12 +- .../ra_ide_api/src/completion/complete_dot.rs | 33 ++-- 12 files changed, 200 insertions(+), 106 deletions(-) diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index 4cca093517..3caf60ee6d 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs @@ -9,19 +9,27 @@ use ra_syntax::{ }; use crate::{ - DefId, DefLoc, Name, AsName, Struct, Enum, EnumVariant, + DefId, DefLoc, Name, AsName, Struct, Enum, EnumVariant, Module, HirFileId, HirDatabase, DefKind, SourceItemId, type_ref::TypeRef, + ids::{StructLoc}, }; impl Struct { - pub(crate) fn new(def_id: DefId) -> Self { - Struct { def_id } + pub(crate) fn from_ast( + db: &impl HirDatabase, + module: Module, + file_id: HirFileId, + ast: &ast::StructDef, + ) -> Struct { + let loc: StructLoc = StructLoc::from_ast(db, module, file_id, ast); + let id = loc.id(db); + Struct { id } } pub(crate) fn variant_data(&self, db: &impl HirDatabase) -> Arc { - db.struct_data(self.def_id).variant_data.clone() + db.struct_data((*self).into()).variant_data.clone() } } @@ -39,13 +47,9 @@ impl StructData { StructData { name, variant_data } } - pub(crate) fn struct_data_query(db: &impl HirDatabase, def_id: DefId) -> Arc { - let def_loc = def_id.loc(db); - assert!(def_loc.kind == DefKind::Struct); - let syntax = db.file_item(def_loc.source_item_id); - let struct_def = - ast::StructDef::cast(&syntax).expect("struct def should point to StructDef node"); - Arc::new(StructData::new(struct_def)) + pub(crate) fn struct_data_query(db: &impl HirDatabase, struct_: Struct) -> Arc { + let (_, struct_def) = struct_.source(db); + Arc::new(StructData::new(&*struct_def)) } } diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 9056151277..948718aa62 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -10,13 +10,13 @@ use crate::{ nameres::{ModuleScope, lower::ImportId}, db::HirDatabase, expr::BodySyntaxMapping, - ty::InferenceResult, + ty::{InferenceResult, VariantDef}, adt::VariantData, generics::GenericParams, code_model_impl::def_id_to_ast, docs::{Documentation, Docs, docs_from_ast}, module_tree::ModuleId, - ids::FunctionId, + ids::{FunctionId, StructId}, }; /// hir::Crate describes a single crate. It's the main interface with which @@ -68,6 +68,7 @@ pub struct Module { pub enum ModuleDef { Module(Module), Function(Function), + Struct(Struct), Def(DefId), } @@ -83,6 +84,12 @@ impl Into for Function { } } +impl Into for Struct { + fn into(self) -> ModuleDef { + ModuleDef::Struct(self) + } +} + impl Into for DefId { fn into(self) -> ModuleDef { ModuleDef::Def(self) @@ -187,7 +194,7 @@ impl Module { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct StructField { - parent: DefId, + parent: VariantDef, name: Name, } @@ -201,38 +208,38 @@ impl StructField { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Struct { - pub(crate) def_id: DefId, + pub(crate) id: StructId, } impl Struct { - pub fn def_id(&self) -> DefId { - self.def_id + pub fn module(&self, db: &impl HirDatabase) -> Module { + self.id.loc(db).module } pub fn name(&self, db: &impl HirDatabase) -> Option { - db.struct_data(self.def_id).name.clone() + db.struct_data(*self).name.clone() } pub fn fields(&self, db: &impl HirDatabase) -> Vec { - db.struct_data(self.def_id) + db.struct_data(*self) .variant_data .fields() .iter() .map(|it| StructField { - parent: self.def_id, + parent: (*self).into(), name: it.name.clone(), }) .collect() } pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc) { - def_id_to_ast(db, self.def_id) + self.id.loc(db).source(db) } pub fn generic_params(&self, db: &impl HirDatabase) -> Arc { - db.generic_params(self.def_id.into()) + db.generic_params((*self).into()) } } @@ -310,7 +317,7 @@ impl EnumVariant { .fields() .iter() .map(|it| StructField { - parent: self.def_id, + parent: self.def_id.into(), name: it.name.clone(), }) .collect() diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs index b2828c7be0..42f10e9415 100644 --- a/crates/ra_hir/src/code_model_impl/module.rs +++ b/crates/ra_hir/src/code_model_impl/module.rs @@ -135,7 +135,7 @@ impl Module { None => PerNs::none(), } } - ModuleDef::Function(_) => PerNs::none(), + ModuleDef::Function(_) | ModuleDef::Struct(_) => PerNs::none(), ModuleDef::Def(def) => { match def.resolve(db) { Def::Enum(e) => { diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 97de7da317..75935c30f5 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -8,10 +8,11 @@ use crate::{ SourceFileItems, SourceItemId, Crate, Module, HirInterner, query_definitions, Function, FnSignature, FnScopes, + Struct, macros::MacroExpansion, module_tree::ModuleTree, nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}}, - ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef}, + ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef, VariantDef}, adt::{StructData, EnumData, EnumVariantData}, impl_block::ModuleImplBlocks, generics::{GenericParams, GenericDef}, @@ -29,7 +30,7 @@ pub trait HirDatabase: SyntaxDatabase + AsRef { fn fn_scopes(&self, func: Function) -> Arc; #[salsa::invoke(crate::adt::StructData::struct_data_query)] - fn struct_data(&self, def_id: DefId) -> Arc; + fn struct_data(&self, struct_: Struct) -> Arc; #[salsa::invoke(crate::adt::EnumData::enum_data_query)] fn enum_data(&self, def_id: DefId) -> Arc; @@ -44,7 +45,7 @@ pub trait HirDatabase: SyntaxDatabase + AsRef { fn type_for_def(&self, def: TypableDef) -> Ty; #[salsa::invoke(crate::ty::type_for_field)] - fn type_for_field(&self, def_id: DefId, field: Name) -> Option; + fn type_for_field(&self, def: VariantDef, field: Name) -> Option; #[salsa::invoke(query_definitions::file_items)] fn file_items(&self, file_id: HirFileId) -> Arc; diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index 88c53705fa..e10b85ec90 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs @@ -7,7 +7,7 @@ use std::sync::Arc; use ra_syntax::ast::{self, AstNode, NameOwner, TypeParamsOwner}; -use crate::{db::HirDatabase, DefId, Name, AsName, Function}; +use crate::{db::HirDatabase, DefId, Name, AsName, Function, Struct}; /// Data about a generic parameter (to a function, struct, impl, ...). #[derive(Clone, PartialEq, Eq, Debug)] @@ -25,6 +25,7 @@ pub struct GenericParams { #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] pub enum GenericDef { Function(Function), + Struct(Struct), Def(DefId), } @@ -34,6 +35,12 @@ impl From for GenericDef { } } +impl From for GenericDef { + fn from(func: Struct) -> GenericDef { + GenericDef::Struct(func) + } +} + impl From for GenericDef { fn from(def_id: DefId) -> GenericDef { GenericDef::Def(def_id) @@ -53,6 +60,12 @@ impl GenericParams { generics.fill(type_param_list) } } + GenericDef::Struct(s) => { + let (_, struct_def) = s.source(db); + if let Some(type_param_list) = struct_def.type_param_list() { + generics.fill(type_param_list) + } + } GenericDef::Def(def_id) => { let (_file_id, node) = def_id.source(db); if let Some(type_param_list) = node.children().find_map(ast::TypeParamList::cast) { diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 51e3cfb813..2791149dd9 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs @@ -5,7 +5,7 @@ use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, ast}; use ra_arena::{Arena, RawId, impl_arena_id}; use crate::{ - HirDatabase, Def, Struct, Enum, EnumVariant, Crate, + HirDatabase, Def, Enum, EnumVariant, Crate, Module, Trait, Type, Static, Const, }; @@ -257,10 +257,7 @@ impl DefId { pub fn resolve(self, db: &impl HirDatabase) -> Def { let loc = self.loc(db); match loc.kind { - DefKind::Struct => { - let struct_def = Struct::new(self); - Def::Struct(struct_def) - } + DefKind::Struct => unreachable!(), DefKind::Enum => Def::Enum(Enum::new(self)), DefKind::EnumVariant => Def::EnumVariant(EnumVariant::new(self)), DefKind::Const => { diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index a6246a5e94..5d63718924 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -43,7 +43,7 @@ pub use self::{ ids::{HirFileId, DefId, DefLoc, MacroCallId, MacroCallLoc, HirInterner}, macros::{MacroDef, MacroInput, MacroExpansion}, nameres::{ItemMap, PerNs, Namespace, Resolution}, - ty::Ty, + ty::{Ty, AdtDef}, impl_block::{ImplBlock, ImplItem}, code_model_impl::function::{FnScopes, ScopesWithSyntaxMapping}, docs::{Docs, Documentation} diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs index 1f8adc7eb1..b0c4aa819d 100644 --- a/crates/ra_hir/src/nameres/lower.rs +++ b/crates/ra_hir/src/nameres/lower.rs @@ -10,7 +10,7 @@ use rustc_hash::FxHashMap; use crate::{ SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems, HirFileId, MacroCallLoc, AsName, PerNs, DefKind, DefLoc, Function, - ModuleDef, Module, + ModuleDef, Module, Struct, }; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -147,7 +147,14 @@ impl LoweredModule { item: &ast::ModuleItem, ) { let name = match item.kind() { - ast::ModuleItemKind::StructDef(it) => it.name(), + ast::ModuleItemKind::StructDef(it) => { + if let Some(name) = it.name() { + let s = Struct::from_ast(db, module, file_id, it); + let s: ModuleDef = s.into(); + self.declarations.insert(name.as_name(), PerNs::both(s, s)); + } + return; + } ast::ModuleItemKind::EnumDef(it) => it.name(), ast::ModuleItemKind::FnDef(it) => { if let Some(name) = it.name() { diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index f9cdbcab33..fc699a2ae2 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -32,7 +32,7 @@ use rustc_hash::FxHashMap; use crate::{ Def, DefId, Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock, - FnSignature, FnScopes, ModuleDef, + FnSignature, FnScopes, ModuleDef, Crate, db::HirDatabase, type_ref::{TypeRef, Mutability}, name::KnownName, @@ -163,6 +163,33 @@ impl Substs { } } +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub enum AdtDef { + Struct(Struct), + Def(DefId), // Enum +} + +impl From for AdtDef { + fn from(struct_: Struct) -> AdtDef { + AdtDef::Struct(struct_) + } +} + +impl From for AdtDef { + fn from(def_id: DefId) -> AdtDef { + AdtDef::Def(def_id) + } +} + +impl AdtDef { + fn krate(self, db: &impl HirDatabase) -> Option { + match self { + AdtDef::Struct(s) => s.module(db).krate(db), + AdtDef::Def(def_id) => def_id.krate(db), + } + } +} + /// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs). /// /// This should be cheap to clone. @@ -184,7 +211,7 @@ pub enum Ty { /// Structures, enumerations and unions. Adt { /// The DefId of the struct/enum. - def_id: DefId, + def_id: AdtDef, /// The name, for displaying. name: Name, /// Substitutions for the generic parameters of the type. @@ -384,6 +411,7 @@ impl Ty { let resolved = match module.resolve_path(db, path).take_types() { Some(ModuleDef::Def(r)) => r.into(), Some(ModuleDef::Function(f)) => f.into(), + Some(ModuleDef::Struct(s)) => s.into(), None | Some(ModuleDef::Module(_)) => return Ty::Unknown, }; let ty = db.type_for_def(resolved); @@ -409,6 +437,7 @@ impl Ty { .expect("path should have at least one segment"); let (def_generics, segment) = match resolved { TypableDef::Function(func) => (func.generic_params(db), last), + TypableDef::Struct(s) => (s.generic_params(db), last), TypableDef::Def(def_id) => match def_id.resolve(db) { Def::Struct(s) => (s.generic_params(db), last), Def::Enum(e) => (e.generic_params(db), last), @@ -642,7 +671,7 @@ fn make_substs(generics: &GenericParams) -> Substs { fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { let generics = s.generic_params(db); Ty::Adt { - def_id: s.def_id(), + def_id: s.into(), name: s.name(db).unwrap_or_else(Name::missing), substs: make_substs(&generics), } @@ -651,7 +680,7 @@ fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { let generics = s.generic_params(db); Ty::Adt { - def_id: s.def_id(), + def_id: s.def_id().into(), name: s.name(db).unwrap_or_else(Name::missing), substs: make_substs(&generics), } @@ -666,6 +695,7 @@ pub(crate) fn type_for_enum_variant(db: &impl HirDatabase, ev: EnumVariant) -> T #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum TypableDef { Function(Function), + Struct(Struct), Def(DefId), } @@ -675,6 +705,12 @@ impl From for TypableDef { } } +impl From for TypableDef { + fn from(struct_: Struct) -> TypableDef { + TypableDef::Struct(struct_) + } +} + impl From for TypableDef { fn from(func: DefId) -> TypableDef { TypableDef::Def(func) @@ -684,8 +720,8 @@ impl From for TypableDef { pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty { match def { TypableDef::Function(f) => type_for_fn(db, f), + TypableDef::Struct(s) => type_for_struct(db, s), TypableDef::Def(def_id) => match def_id.resolve(db) { - Def::Struct(s) => type_for_struct(db, s), Def::Enum(e) => type_for_enum(db, e), Def::EnumVariant(ev) => type_for_enum_variant(db, ev), _ => { @@ -700,22 +736,44 @@ pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty { } } -pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name) -> Option { - let def = def_id.resolve(db); - let (variant_data, generics) = match def { - Def::Struct(s) => (s.variant_data(db), s.generic_params(db)), - Def::EnumVariant(ev) => (ev.variant_data(db), ev.parent_enum(db).generic_params(db)), - // TODO: unions - Def::Enum(_) => { - // this can happen in (invalid) code, but enums don't have fields themselves - return None; - } - _ => panic!( - "trying to get type for field {:?} in non-struct/variant {:?}", - field, def_id - ), +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub enum VariantDef { + Struct(Struct), + Def(DefId), // EnumVariant +} + +impl From for VariantDef { + fn from(struct_: Struct) -> VariantDef { + VariantDef::Struct(struct_) + } +} + +impl From for VariantDef { + fn from(def_id: DefId) -> VariantDef { + VariantDef::Def(def_id) + } +} + +pub(super) fn type_for_field(db: &impl HirDatabase, def: VariantDef, field: Name) -> Option { + let (variant_data, generics, module) = match def { + VariantDef::Struct(s) => (s.variant_data(db), s.generic_params(db), s.module(db)), + VariantDef::Def(def_id) => match def_id.resolve(db) { + Def::EnumVariant(ev) => ( + ev.variant_data(db), + ev.parent_enum(db).generic_params(db), + def_id.module(db), + ), + // TODO: unions + Def::Enum(_) => { + // this can happen in (invalid) code, but enums don't have fields themselves + return None; + } + _ => panic!( + "trying to get type for field {:?} in non-struct/variant {:?}", + field, def_id + ), + }, }; - let module = def_id.module(db); // We can't have an impl block ere, right? // let impl_block = def_id.impl_block(db); let type_ref = variant_data.get_field_type_ref(&field)?; @@ -1076,17 +1134,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { }; // resolve in module - let resolved = match self.module.resolve_path(self.db, &path).take_values()? { + let typable = match self.module.resolve_path(self.db, &path).take_values()? { ModuleDef::Def(it) => it.into(), ModuleDef::Function(func) => func.into(), + ModuleDef::Struct(s) => s.into(), ModuleDef::Module(_) => return None, }; - let ty = self.db.type_for_def(resolved); + let ty = self.db.type_for_def(typable); let ty = self.insert_type_vars(ty); Some(ty) } - fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option) { + fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option) { let path = match path { Some(path) => path, None => return (Ty::Unknown, None), @@ -1094,7 +1153,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let def = match self.module.resolve_path(self.db, &path).take_types() { Some(ModuleDef::Def(def_id)) => def_id.into(), Some(ModuleDef::Function(func)) => func.into(), - _ => return (Ty::Unknown, None), + Some(ModuleDef::Struct(s)) => s.into(), + None | Some(ModuleDef::Module(_)) => return (Ty::Unknown, None), }; // TODO remove the duplication between here and `Ty::from_path`? // TODO provide generics of function @@ -1109,37 +1169,36 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ); match def { TypableDef::Def(def_id) => match def_id.resolve(self.db) { - Def::Struct(s) => { - let ty = type_for_struct(self.db, s); - let ty = self.insert_type_vars(ty.apply_substs(substs)); - (ty, Some(def_id)) - } Def::EnumVariant(ev) => { let ty = type_for_enum_variant(self.db, ev); let ty = self.insert_type_vars(ty.apply_substs(substs)); - (ty, Some(def_id)) + (ty, Some(def_id.into())) } _ => (Ty::Unknown, None), }, TypableDef::Function(_) => (Ty::Unknown, None), + TypableDef::Struct(s) => { + let ty = type_for_struct(self.db, s); + let ty = self.insert_type_vars(ty.apply_substs(substs)); + (ty, Some(s.into())) + } } } fn resolve_fields(&mut self, path: Option<&Path>) -> Option<(Ty, Vec)> { - let (ty, def_id) = self.resolve_variant(path); - let def_id = def_id?; - let def = def_id.resolve(self.db); - - match def { - Def::Struct(s) => { + let (ty, def) = self.resolve_variant(path); + match def? { + VariantDef::Struct(s) => { let fields = s.fields(self.db); Some((ty, fields)) } - Def::EnumVariant(ev) => { - let fields = ev.fields(self.db); - Some((ty, fields)) - } - _ => None, + VariantDef::Def(def_id) => match def_id.resolve(self.db) { + Def::EnumVariant(ev) => { + let fields = ev.fields(self.db); + Some((ty, fields)) + } + _ => None, + }, } } @@ -1240,6 +1299,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { .and_then(|module_def| match module_def { ModuleDef::Def(it) => Some(it.into()), ModuleDef::Function(func) => Some(func.into()), + ModuleDef::Struct(s) => Some(s.into()), ModuleDef::Module(_) => None, }) .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)), @@ -1433,7 +1493,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { for field in fields { let field_ty = if let Some(def_id) = def_id { self.db - .type_for_field(def_id, field.name.clone()) + .type_for_field(def_id.into(), field.name.clone()) .unwrap_or(Ty::Unknown) .subst(&substs) } else { @@ -1457,10 +1517,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { i.and_then(|i| fields.get(i).cloned()) } Ty::Adt { - def_id, ref substs, .. + def_id: AdtDef::Struct(s), + ref substs, + .. } => self .db - .type_for_field(def_id, name.clone()) + .type_for_field(s.into(), name.clone()) .map(|ty| ty.subst(substs)), _ => None, }) diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 0084b24dc7..9a571c2aaf 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs @@ -7,16 +7,16 @@ use std::sync::Arc; use rustc_hash::FxHashMap; use crate::{ - HirDatabase, DefId, module_tree::ModuleId, Module, Crate, Name, Function, + HirDatabase, module_tree::ModuleId, Module, Crate, Name, Function, impl_block::{ImplId, ImplBlock, ImplItem}, - generics::GenericParams + generics::GenericParams, + ty::{AdtDef, Ty} }; -use super::Ty; /// This is used as a key for indexing impls. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum TyFingerprint { - Adt(DefId), + Adt(AdtDef), // we'll also want to index impls for primitive types etc. } diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap index c4a2d5cf8b..8747fae181 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap @@ -1,19 +1,19 @@ --- -created: "2019-01-22T14:45:00.058678600+00:00" -creator: insta@0.4.0 +created: "2019-01-24T14:51:32.808861856+00:00" +creator: insta@0.5.2 expression: "&result" -source: "crates\\ra_hir\\src\\ty\\tests.rs" +source: crates/ra_hir/src/ty/tests.rs --- [72; 154) '{ ...a.c; }': () [82; 83) 'c': [unknown] -[86; 87) 'C': [unknown] +[86; 87) 'C': C [86; 90) 'C(1)': [unknown] [88; 89) '1': i32 -[96; 97) 'B': [unknown] +[96; 97) 'B': B [107; 108) 'a': A [114; 133) 'A { b:...C(1) }': A [121; 122) 'B': B -[127; 128) 'C': [unknown] +[127; 128) 'C': C [127; 131) 'C(1)': C [129; 130) '1': i32 [139; 140) 'a': A diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index 32fd497be9..1a2b0b2f68 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs @@ -1,4 +1,4 @@ -use hir::{Ty, Def}; +use hir::{Ty, Def, AdtDef}; use crate::completion::{CompletionContext, Completions, CompletionItem, CompletionItemKind}; use crate::completion::completion_item::CompletionKind; @@ -28,21 +28,24 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) Ty::Adt { def_id, ref substs, .. } => { - match def_id.resolve(ctx.db) { - Def::Struct(s) => { - for field in s.fields(ctx.db) { - CompletionItem::new( - CompletionKind::Reference, - ctx.source_range(), - field.name().to_string(), - ) - .kind(CompletionItemKind::Field) - .set_detail(field.ty(ctx.db).map(|ty| ty.subst(substs).to_string())) - .add_to(acc); + match def_id { + AdtDef::Struct() => {} + AdtDef::Def(def_id) => match def_id.resolve(ctx.db) { + Def::Struct(s) => { + for field in s.fields(ctx.db) { + CompletionItem::new( + CompletionKind::Reference, + ctx.source_range(), + field.name().to_string(), + ) + .kind(CompletionItemKind::Field) + .set_detail(field.ty(ctx.db).map(|ty| ty.subst(substs).to_string())) + .add_to(acc); + } } - } - // TODO unions - _ => {} + // TODO unions + _ => {} + }, } } Ty::Tuple(fields) => { From cefc5cbb4a95d2a473ea656efe603bef979b5c49 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 24 Jan 2019 17:56:00 +0300 Subject: [PATCH 08/26] introduce EnumId --- crates/ra_hir/src/ids.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 2791149dd9..530fdf5cd8 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs @@ -15,6 +15,7 @@ pub struct HirInterner { macros: LocationIntener, fns: LocationIntener, structs: LocationIntener, + enums: LocationIntener, } impl HirInterner { @@ -213,6 +214,24 @@ impl StructLoc { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct EnumId(RawId); +impl_arena_id!(EnumId); + +pub(crate) type EnumLoc = ItemLoc; + +impl EnumId { + pub(crate) fn loc(self, db: &impl AsRef) -> EnumLoc { + db.as_ref().enums.id2loc(self) + } +} + +impl EnumLoc { + pub(crate) fn id(&self, db: &impl AsRef) -> EnumId { + db.as_ref().enums.loc2id(&self) + } +} + /// Def's are a core concept of hir. A `Def` is an Item (function, module, etc) /// in a specific module. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] From 566c8e321e89e5ff8996daa615cc47aea0012881 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 24 Jan 2019 18:56:38 +0300 Subject: [PATCH 09/26] migrate enums to new id --- crates/ra_hir/src/adt.rs | 52 +++++++----- crates/ra_hir/src/code_model_api.rs | 55 +++++++------ crates/ra_hir/src/code_model_impl/module.rs | 40 ++++----- crates/ra_hir/src/db.rs | 6 +- crates/ra_hir/src/generics.rs | 38 +++++---- crates/ra_hir/src/ids.rs | 29 +++---- crates/ra_hir/src/nameres/lower.rs | 15 +++- crates/ra_hir/src/ty.rs | 90 ++++++++++++++------- crates/ra_syntax/src/ast.rs | 7 ++ 9 files changed, 190 insertions(+), 142 deletions(-) diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index 3caf60ee6d..baf853a3a4 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs @@ -13,7 +13,7 @@ use crate::{ HirDatabase, DefKind, SourceItemId, type_ref::TypeRef, - ids::{StructLoc}, + ids::{StructLoc, EnumLoc}, }; impl Struct { @@ -33,6 +33,19 @@ impl Struct { } } +impl Enum { + pub(crate) fn from_ast( + db: &impl HirDatabase, + module: Module, + file_id: HirFileId, + ast: &ast::EnumDef, + ) -> Enum { + let loc: EnumLoc = EnumLoc::from_ast(db, module, file_id, ast); + let id = loc.id(db); + Enum { id } + } +} + #[derive(Debug, Clone, PartialEq, Eq)] pub struct StructData { pub(crate) name: Option, @@ -55,20 +68,20 @@ impl StructData { fn get_def_id( db: &impl HirDatabase, - same_file_loc: &DefLoc, + module: Module, + file_id: HirFileId, node: &SyntaxNode, expected_kind: DefKind, ) -> DefId { - let file_id = same_file_loc.source_item_id.file_id; let file_items = db.file_items(file_id); let item_id = file_items.id_of(file_id, node); let source_item_id = SourceItemId { + file_id, item_id: Some(item_id), - ..same_file_loc.source_item_id }; let loc = DefLoc { - module: same_file_loc.module, + module, kind: expected_kind, source_item_id, }; @@ -87,19 +100,22 @@ impl EnumData { EnumData { name, variants } } - pub(crate) fn enum_data_query(db: &impl HirDatabase, def_id: DefId) -> Arc { - let def_loc = def_id.loc(db); - assert!(def_loc.kind == DefKind::Enum); - let syntax = db.file_item(def_loc.source_item_id); - let enum_def = ast::EnumDef::cast(&syntax).expect("enum def should point to EnumDef node"); + pub(crate) fn enum_data_query(db: &impl HirDatabase, e: Enum) -> Arc { + let (file_id, enum_def) = e.source(db); + let module = e.module(db); let variants = if let Some(vl) = enum_def.variant_list() { vl.variants() .filter_map(|variant_def| { let name = variant_def.name().map(|n| n.as_name()); name.map(|n| { - let def_id = - get_def_id(db, &def_loc, variant_def.syntax(), DefKind::EnumVariant); + let def_id = get_def_id( + db, + module, + file_id, + variant_def.syntax(), + DefKind::EnumVariant, + ); (n, EnumVariant::new(def_id)) }) }) @@ -107,7 +123,7 @@ impl EnumData { } else { Vec::new() }; - Arc::new(EnumData::new(enum_def, variants)) + Arc::new(EnumData::new(&*enum_def, variants)) } } @@ -139,14 +155,10 @@ impl EnumVariantData { let syntax = db.file_item(def_loc.source_item_id); let variant_def = ast::EnumVariant::cast(&syntax) .expect("enum variant def should point to EnumVariant node"); - let enum_node = syntax - .parent() - .expect("enum variant should have enum variant list ancestor") - .parent() - .expect("enum variant list should have enum ancestor"); - let enum_def_id = get_def_id(db, &def_loc, enum_node, DefKind::Enum); + let enum_def = variant_def.parent_enum(); + let e = Enum::from_ast(db, def_loc.module, def_loc.source_item_id.file_id, enum_def); - Arc::new(EnumVariantData::new(variant_def, Enum::new(enum_def_id))) + Arc::new(EnumVariantData::new(variant_def, e)) } } diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 948718aa62..0a96d6f6d3 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -16,7 +16,7 @@ use crate::{ code_model_impl::def_id_to_ast, docs::{Documentation, Docs, docs_from_ast}, module_tree::ModuleId, - ids::{FunctionId, StructId}, + ids::{FunctionId, StructId, EnumId}, }; /// hir::Crate describes a single crate. It's the main interface with which @@ -69,30 +69,37 @@ pub enum ModuleDef { Module(Module), Function(Function), Struct(Struct), + Enum(Enum), Def(DefId), } - -impl Into for Module { - fn into(self) -> ModuleDef { - ModuleDef::Module(self) +//FIXME: change to from +impl From for ModuleDef { + fn from(it: Module) -> ModuleDef { + ModuleDef::Module(it) } } -impl Into for Function { - fn into(self) -> ModuleDef { - ModuleDef::Function(self) +impl From for ModuleDef { + fn from(it: Function) -> ModuleDef { + ModuleDef::Function(it) } } -impl Into for Struct { - fn into(self) -> ModuleDef { - ModuleDef::Struct(self) +impl From for ModuleDef { + fn from(it: Struct) -> ModuleDef { + ModuleDef::Struct(it) } } -impl Into for DefId { - fn into(self) -> ModuleDef { - ModuleDef::Def(self) +impl From for ModuleDef { + fn from(it: Enum) -> ModuleDef { + ModuleDef::Enum(it) + } +} + +impl From for ModuleDef { + fn from(it: DefId) -> ModuleDef { + ModuleDef::Def(it) } } @@ -249,34 +256,30 @@ impl Docs for Struct { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Enum { - pub(crate) def_id: DefId, + pub(crate) id: EnumId, } impl Enum { - pub(crate) fn new(def_id: DefId) -> Self { - Enum { def_id } - } - - pub fn def_id(&self) -> DefId { - self.def_id + pub fn module(&self, db: &impl HirDatabase) -> Module { + self.id.loc(db).module } pub fn name(&self, db: &impl HirDatabase) -> Option { - db.enum_data(self.def_id).name.clone() + db.enum_data(*self).name.clone() } pub fn variants(&self, db: &impl HirDatabase) -> Vec<(Name, EnumVariant)> { - db.enum_data(self.def_id).variants.clone() + db.enum_data(*self).variants.clone() } pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc) { - def_id_to_ast(db, self.def_id) + self.id.loc(db).source(db) } pub fn generic_params(&self, db: &impl HirDatabase) -> Arc { - db.generic_params(self.def_id.into()) + db.generic_params((*self).into()) } } diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs index 42f10e9415..4ea649770e 100644 --- a/crates/ra_hir/src/code_model_impl/module.rs +++ b/crates/ra_hir/src/code_model_impl/module.rs @@ -3,7 +3,7 @@ use ra_syntax::{ast, SyntaxNode, TreeArc}; use crate::{ Module, ModuleSource, Problem, ModuleDef, - Crate, Name, Path, PathKind, PerNs, Def, + Crate, Name, Path, PathKind, PerNs, module_tree::ModuleId, nameres::{ModuleScope, lower::ImportId}, db::HirDatabase, @@ -135,31 +135,25 @@ impl Module { None => PerNs::none(), } } - ModuleDef::Function(_) | ModuleDef::Struct(_) => PerNs::none(), - ModuleDef::Def(def) => { - match def.resolve(db) { - Def::Enum(e) => { - // enum variant - let matching_variant = e - .variants(db) - .into_iter() - .find(|(n, _variant)| n == &segment.name); + ModuleDef::Enum(e) => { + // enum variant + let matching_variant = e + .variants(db) + .into_iter() + .find(|(n, _variant)| n == &segment.name); - match matching_variant { - Some((_n, variant)) => { - PerNs::both(variant.def_id().into(), e.def_id().into()) - } - None => PerNs::none(), - } - } - _ => { - // could be an inherent method call in UFCS form - // (`Struct::method`), or some other kind of associated - // item... Which we currently don't handle (TODO) - PerNs::none() - } + match matching_variant { + Some((_n, variant)) => PerNs::both(variant.def_id().into(), (*e).into()), + None => PerNs::none(), } } + ModuleDef::Function(_) | ModuleDef::Struct(_) => { + // could be an inherent method call in UFCS form + // (`Struct::method`), or some other kind of associated + // item... Which we currently don't handle (TODO) + PerNs::none() + } + ModuleDef::Def(_) => PerNs::none(), }; } curr_per_ns diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 75935c30f5..34e41017b9 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -8,7 +8,7 @@ use crate::{ SourceFileItems, SourceItemId, Crate, Module, HirInterner, query_definitions, Function, FnSignature, FnScopes, - Struct, + Struct, Enum, macros::MacroExpansion, module_tree::ModuleTree, nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}}, @@ -30,10 +30,10 @@ pub trait HirDatabase: SyntaxDatabase + AsRef { fn fn_scopes(&self, func: Function) -> Arc; #[salsa::invoke(crate::adt::StructData::struct_data_query)] - fn struct_data(&self, struct_: Struct) -> Arc; + fn struct_data(&self, s: Struct) -> Arc; #[salsa::invoke(crate::adt::EnumData::enum_data_query)] - fn enum_data(&self, def_id: DefId) -> Arc; + fn enum_data(&self, e: Enum) -> Arc; #[salsa::invoke(crate::adt::EnumVariantData::enum_variant_data_query)] fn enum_variant_data(&self, def_id: DefId) -> Arc; diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index e10b85ec90..df23871c76 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs @@ -7,7 +7,7 @@ use std::sync::Arc; use ra_syntax::ast::{self, AstNode, NameOwner, TypeParamsOwner}; -use crate::{db::HirDatabase, DefId, Name, AsName, Function, Struct}; +use crate::{db::HirDatabase, DefId, Name, AsName, Function, Struct, Enum}; /// Data about a generic parameter (to a function, struct, impl, ...). #[derive(Clone, PartialEq, Eq, Debug)] @@ -26,6 +26,7 @@ pub struct GenericParams { pub enum GenericDef { Function(Function), Struct(Struct), + Enum(Enum), Def(DefId), } @@ -36,8 +37,14 @@ impl From for GenericDef { } impl From for GenericDef { - fn from(func: Struct) -> GenericDef { - GenericDef::Struct(func) + fn from(s: Struct) -> GenericDef { + GenericDef::Struct(s) + } +} + +impl From for GenericDef { + fn from(e: Enum) -> GenericDef { + GenericDef::Enum(e) } } @@ -54,22 +61,13 @@ impl GenericParams { ) -> Arc { let mut generics = GenericParams::default(); match def { - GenericDef::Function(func) => { - let (_, fn_def) = func.source(db); - if let Some(type_param_list) = fn_def.type_param_list() { - generics.fill(type_param_list) - } - } - GenericDef::Struct(s) => { - let (_, struct_def) = s.source(db); - if let Some(type_param_list) = struct_def.type_param_list() { - generics.fill(type_param_list) - } - } + GenericDef::Function(it) => generics.fill(&*it.source(db).1), + GenericDef::Struct(it) => generics.fill(&*it.source(db).1), + GenericDef::Enum(it) => generics.fill(&*it.source(db).1), GenericDef::Def(def_id) => { let (_file_id, node) = def_id.source(db); if let Some(type_param_list) = node.children().find_map(ast::TypeParamList::cast) { - generics.fill(type_param_list) + generics.fill_params(type_param_list) } } } @@ -77,7 +75,13 @@ impl GenericParams { Arc::new(generics) } - fn fill(&mut self, params: &ast::TypeParamList) { + fn fill(&mut self, node: &impl TypeParamsOwner) { + if let Some(params) = node.type_param_list() { + self.fill_params(params) + } + } + + fn fill_params(&mut self, params: &ast::TypeParamList) { for (idx, type_param) in params.type_params().enumerate() { let name = type_param .name() diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 530fdf5cd8..332cec9c86 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs @@ -5,7 +5,7 @@ use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, ast}; use ra_arena::{Arena, RawId, impl_arena_id}; use crate::{ - HirDatabase, Def, Enum, EnumVariant, Crate, + HirDatabase, Def, EnumVariant, Crate, Module, Trait, Type, Static, Const, }; @@ -247,25 +247,22 @@ pub struct DefLoc { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub(crate) enum DefKind { - Struct, - Enum, EnumVariant, Const, Static, Trait, Type, Item, - - /// The constructor of a struct. E.g. if we have `struct Foo(usize)`, the - /// name `Foo` needs to resolve to different types depending on whether we - /// are in the types or values namespace: As a type, `Foo` of course refers - /// to the struct `Foo`; as a value, `Foo` is a callable type with signature - /// `(usize) -> Foo`. The cleanest approach to handle this seems to be to - /// have different defs in the two namespaces. - /// - /// rustc does the same; note that it even creates a struct constructor if - /// the struct isn't a tuple struct (see `CtorKind::Fictive` in rustc). - StructCtor, + // /// The constructor of a struct. E.g. if we have `struct Foo(usize)`, the + // /// name `Foo` needs to resolve to different types depending on whether we + // /// are in the types or values namespace: As a type, `Foo` of course refers + // /// to the struct `Foo`; as a value, `Foo` is a callable type with signature + // /// `(usize) -> Foo`. The cleanest approach to handle this seems to be to + // /// have different defs in the two namespaces. + // /// + // /// rustc does the same; note that it even creates a struct constructor if + // /// the struct isn't a tuple struct (see `CtorKind::Fictive` in rustc). + // StructCtor, } impl DefId { @@ -276,8 +273,6 @@ impl DefId { pub fn resolve(self, db: &impl HirDatabase) -> Def { let loc = self.loc(db); match loc.kind { - DefKind::Struct => unreachable!(), - DefKind::Enum => Def::Enum(Enum::new(self)), DefKind::EnumVariant => Def::EnumVariant(EnumVariant::new(self)), DefKind::Const => { let def = Const::new(self); @@ -295,8 +290,6 @@ impl DefId { let def = Type::new(self); Def::Type(def) } - - DefKind::StructCtor => Def::Item, DefKind::Item => Def::Item, } } diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs index b0c4aa819d..435804e2d0 100644 --- a/crates/ra_hir/src/nameres/lower.rs +++ b/crates/ra_hir/src/nameres/lower.rs @@ -10,7 +10,7 @@ use rustc_hash::FxHashMap; use crate::{ SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems, HirFileId, MacroCallLoc, AsName, PerNs, DefKind, DefLoc, Function, - ModuleDef, Module, Struct, + ModuleDef, Module, Struct, Enum, }; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -155,7 +155,14 @@ impl LoweredModule { } return; } - ast::ModuleItemKind::EnumDef(it) => it.name(), + ast::ModuleItemKind::EnumDef(it) => { + if let Some(name) = it.name() { + let e = Enum::from_ast(db, module, file_id, it); + let e: ModuleDef = e.into(); + self.declarations.insert(name.as_name(), PerNs::types(e)); + } + return; + } ast::ModuleItemKind::FnDef(it) => { if let Some(name) = it.name() { let func = Function::from_ast(db, module, file_id, it); @@ -233,8 +240,8 @@ impl DefKind { fn for_syntax_kind(kind: SyntaxKind) -> PerNs { match kind { SyntaxKind::FN_DEF => unreachable!(), - SyntaxKind::STRUCT_DEF => PerNs::both(DefKind::Struct, DefKind::StructCtor), - SyntaxKind::ENUM_DEF => PerNs::types(DefKind::Enum), + SyntaxKind::STRUCT_DEF => unreachable!(), + SyntaxKind::ENUM_DEF => unreachable!(), SyntaxKind::TRAIT_DEF => PerNs::types(DefKind::Trait), SyntaxKind::TYPE_DEF => PerNs::types(DefKind::Type), SyntaxKind::CONST_DEF => PerNs::values(DefKind::Const), diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index fc699a2ae2..6a5f4fae64 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -166,27 +166,28 @@ impl Substs { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum AdtDef { Struct(Struct), - Def(DefId), // Enum + Enum(Enum), } impl From for AdtDef { - fn from(struct_: Struct) -> AdtDef { - AdtDef::Struct(struct_) + fn from(s: Struct) -> AdtDef { + AdtDef::Struct(s) } } -impl From for AdtDef { - fn from(def_id: DefId) -> AdtDef { - AdtDef::Def(def_id) +impl From for AdtDef { + fn from(e: Enum) -> AdtDef { + AdtDef::Enum(e) } } impl AdtDef { fn krate(self, db: &impl HirDatabase) -> Option { match self { - AdtDef::Struct(s) => s.module(db).krate(db), - AdtDef::Def(def_id) => def_id.krate(db), + AdtDef::Struct(s) => s.module(db), + AdtDef::Enum(e) => e.module(db), } + .krate(db) } } @@ -408,14 +409,16 @@ impl Ty { } // Resolve in module (in type namespace) - let resolved = match module.resolve_path(db, path).take_types() { - Some(ModuleDef::Def(r)) => r.into(), - Some(ModuleDef::Function(f)) => f.into(), - Some(ModuleDef::Struct(s)) => s.into(), - None | Some(ModuleDef::Module(_)) => return Ty::Unknown, + let typable: TypableDef = match module + .resolve_path(db, path) + .take_types() + .and_then(|it| it.into()) + { + None => return Ty::Unknown, + Some(it) => it, }; - let ty = db.type_for_def(resolved); - let substs = Ty::substs_from_path(db, module, impl_block, generics, path, resolved); + let ty = db.type_for_def(typable); + let substs = Ty::substs_from_path(db, module, impl_block, generics, path, typable); ty.apply_substs(substs) } @@ -438,9 +441,8 @@ impl Ty { let (def_generics, segment) = match resolved { TypableDef::Function(func) => (func.generic_params(db), last), TypableDef::Struct(s) => (s.generic_params(db), last), + TypableDef::Enum(e) => (e.generic_params(db), last), TypableDef::Def(def_id) => match def_id.resolve(db) { - Def::Struct(s) => (s.generic_params(db), last), - Def::Enum(e) => (e.generic_params(db), last), Def::Trait(t) => (t.generic_params(db), last), Def::EnumVariant(ev) => { // the generic args for an enum variant may be either specified @@ -680,7 +682,7 @@ fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { let generics = s.generic_params(db); Ty::Adt { - def_id: s.def_id().into(), + def_id: s.into(), name: s.name(db).unwrap_or_else(Name::missing), substs: make_substs(&generics), } @@ -696,6 +698,7 @@ pub(crate) fn type_for_enum_variant(db: &impl HirDatabase, ev: EnumVariant) -> T pub enum TypableDef { Function(Function), Struct(Struct), + Enum(Enum), Def(DefId), } @@ -706,8 +709,14 @@ impl From for TypableDef { } impl From for TypableDef { - fn from(struct_: Struct) -> TypableDef { - TypableDef::Struct(struct_) + fn from(s: Struct) -> TypableDef { + TypableDef::Struct(s) + } +} + +impl From for TypableDef { + fn from(e: Enum) -> TypableDef { + TypableDef::Enum(e) } } @@ -717,10 +726,24 @@ impl From for TypableDef { } } +impl From for Option { + fn from(def: ModuleDef) -> Option { + let res = match def { + ModuleDef::Def(r) => r.into(), + ModuleDef::Function(f) => f.into(), + ModuleDef::Struct(s) => s.into(), + ModuleDef::Enum(e) => e.into(), + ModuleDef::Module(_) => return None, + }; + Some(res) + } +} + pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty { match def { TypableDef::Function(f) => type_for_fn(db, f), TypableDef::Struct(s) => type_for_struct(db, s), + TypableDef::Enum(e) => type_for_enum(db, e), TypableDef::Def(def_id) => match def_id.resolve(db) { Def::Enum(e) => type_for_enum(db, e), Def::EnumVariant(ev) => type_for_enum_variant(db, ev), @@ -1134,12 +1157,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { }; // resolve in module - let typable = match self.module.resolve_path(self.db, &path).take_values()? { - ModuleDef::Def(it) => it.into(), - ModuleDef::Function(func) => func.into(), - ModuleDef::Struct(s) => s.into(), - ModuleDef::Module(_) => return None, - }; + let typable: Option = self + .module + .resolve_path(self.db, &path) + .take_values()? + .into(); + let typable = typable?; let ty = self.db.type_for_def(typable); let ty = self.insert_type_vars(ty); Some(ty) @@ -1150,11 +1173,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Some(path) => path, None => return (Ty::Unknown, None), }; - let def = match self.module.resolve_path(self.db, &path).take_types() { - Some(ModuleDef::Def(def_id)) => def_id.into(), - Some(ModuleDef::Function(func)) => func.into(), - Some(ModuleDef::Struct(s)) => s.into(), - None | Some(ModuleDef::Module(_)) => return (Ty::Unknown, None), + let typable: Option = self + .module + .resolve_path(self.db, &path) + .take_types() + .and_then(|it| it.into()); + let def = match typable { + None => return (Ty::Unknown, None), + Some(it) => it, }; // TODO remove the duplication between here and `Ty::from_path`? // TODO provide generics of function @@ -1182,6 +1208,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let ty = self.insert_type_vars(ty.apply_substs(substs)); (ty, Some(s.into())) } + TypableDef::Enum(_) => (Ty::Unknown, None), } } @@ -1300,6 +1327,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ModuleDef::Def(it) => Some(it.into()), ModuleDef::Function(func) => Some(func.into()), ModuleDef::Struct(s) => Some(s.into()), + ModuleDef::Enum(e) => Some(e.into()), ModuleDef::Module(_) => None, }) .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)), diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index bcbd4c60c7..fd65264b27 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs @@ -430,6 +430,13 @@ impl StructDef { } impl EnumVariant { + pub fn parent_enum(&self) -> &EnumDef { + self.syntax() + .parent() + .and_then(|it| it.parent()) + .and_then(EnumDef::cast) + .expect("EnumVariants are always nested in Enums") + } pub fn flavor(&self) -> StructFlavor { StructFlavor::from_node(self) } From ce2041252aba52662945e36a4afad454d19388ae Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 24 Jan 2019 18:57:38 +0300 Subject: [PATCH 10/26] kill unused defs --- crates/ra_hir/src/code_model_api.rs | 2 -- crates/ra_hir/src/ty.rs | 5 ----- 2 files changed, 7 deletions(-) diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 0a96d6f6d3..a094268cae 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -47,8 +47,6 @@ impl Crate { #[derive(Debug)] pub enum Def { - Struct(Struct), - Enum(Enum), EnumVariant(EnumVariant), Const(Const), Static(Static), diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 6a5f4fae64..b818996614 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -745,7 +745,6 @@ pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty { TypableDef::Struct(s) => type_for_struct(db, s), TypableDef::Enum(e) => type_for_enum(db, e), TypableDef::Def(def_id) => match def_id.resolve(db) { - Def::Enum(e) => type_for_enum(db, e), Def::EnumVariant(ev) => type_for_enum_variant(db, ev), _ => { log::debug!( @@ -787,10 +786,6 @@ pub(super) fn type_for_field(db: &impl HirDatabase, def: VariantDef, field: Name def_id.module(db), ), // TODO: unions - Def::Enum(_) => { - // this can happen in (invalid) code, but enums don't have fields themselves - return None; - } _ => panic!( "trying to get type for field {:?} in non-struct/variant {:?}", field, def_id From aea1f95a665b56da5953907a122475db0c9a9c44 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 24 Jan 2019 19:04:02 +0300 Subject: [PATCH 11/26] adapt ide_api to the new API --- .../ra_ide_api/src/completion/complete_dot.rs | 32 ++++++++--------- .../src/completion/complete_path.rs | 35 ++++++++----------- .../src/completion/completion_item.rs | 4 +-- crates/ra_ide_api/src/navigation_target.rs | 22 +++++++----- 4 files changed, 46 insertions(+), 47 deletions(-) diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index 1a2b0b2f68..d0fa8146c4 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs @@ -1,4 +1,4 @@ -use hir::{Ty, Def, AdtDef}; +use hir::{Ty, AdtDef}; use crate::completion::{CompletionContext, Completions, CompletionItem, CompletionItemKind}; use crate::completion::completion_item::CompletionKind; @@ -29,23 +29,21 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) def_id, ref substs, .. } => { match def_id { - AdtDef::Struct() => {} - AdtDef::Def(def_id) => match def_id.resolve(ctx.db) { - Def::Struct(s) => { - for field in s.fields(ctx.db) { - CompletionItem::new( - CompletionKind::Reference, - ctx.source_range(), - field.name().to_string(), - ) - .kind(CompletionItemKind::Field) - .set_detail(field.ty(ctx.db).map(|ty| ty.subst(substs).to_string())) - .add_to(acc); - } + AdtDef::Struct(s) => { + for field in s.fields(ctx.db) { + CompletionItem::new( + CompletionKind::Reference, + ctx.source_range(), + field.name().to_string(), + ) + .kind(CompletionItemKind::Field) + .set_detail(field.ty(ctx.db).map(|ty| ty.subst(substs).to_string())) + .add_to(acc); } - // TODO unions - _ => {} - }, + } + + // TODO unions + AdtDef::Enum(_) => (), } } Ty::Tuple(fields) => { diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index 3aef479d97..e039a333c9 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs @@ -26,26 +26,21 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { .add_to(acc); } } - - hir::ModuleDef::Def(def_id) => match def_id.resolve(ctx.db) { - hir::Def::Enum(e) => { - e.variants(ctx.db) - .into_iter() - .for_each(|(variant_name, variant)| { - CompletionItem::new( - CompletionKind::Reference, - ctx.source_range(), - variant_name.to_string(), - ) - .kind(CompletionItemKind::EnumVariant) - .set_documentation(variant.docs(ctx.db)) - .add_to(acc) - }); - } - _ => return, - }, - - hir::ModuleDef::Function(_) => return, + hir::ModuleDef::Enum(e) => { + e.variants(ctx.db) + .into_iter() + .for_each(|(variant_name, variant)| { + CompletionItem::new( + CompletionKind::Reference, + ctx.source_range(), + variant_name.to_string(), + ) + .kind(CompletionItemKind::EnumVariant) + .set_documentation(variant.docs(ctx.db)) + .add_to(acc) + }); + } + hir::ModuleDef::Function(_) | hir::ModuleDef::Struct(_) | hir::ModuleDef::Def(_) => return, }; } diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs index 5b2ba7e4a4..f2301653a5 100644 --- a/crates/ra_ide_api/src/completion/completion_item.rs +++ b/crates/ra_ide_api/src/completion/completion_item.rs @@ -220,9 +220,9 @@ impl Builder { let (kind, docs) = match def { hir::ModuleDef::Module(_) => (CompletionItemKind::Module, None), hir::ModuleDef::Function(func) => return self.from_function(ctx, func), + hir::ModuleDef::Struct(it) => (CompletionItemKind::Struct, it.docs(ctx.db)), + hir::ModuleDef::Enum(it) => (CompletionItemKind::Enum, it.docs(ctx.db)), hir::ModuleDef::Def(def_id) => match def_id.resolve(ctx.db) { - hir::Def::Struct(it) => (CompletionItemKind::Struct, it.docs(ctx.db)), - hir::Def::Enum(it) => (CompletionItemKind::Enum, it.docs(ctx.db)), hir::Def::Trait(it) => (CompletionItemKind::Trait, it.docs(ctx.db)), hir::Def::Type(it) => (CompletionItemKind::TypeAlias, it.docs(ctx.db)), hir::Def::Const(it) => (CompletionItemKind::Const, it.docs(ctx.db)), diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs index 19cea2fd67..b92670f36b 100644 --- a/crates/ra_ide_api/src/navigation_target.rs +++ b/crates/ra_ide_api/src/navigation_target.rs @@ -114,17 +114,23 @@ impl NavigationTarget { hir::ModuleDef::Function(func) => { return Some(NavigationTarget::from_function(db, func)); } + hir::ModuleDef::Struct(s) => { + let (file_id, node) = s.source(db); + return Some(NavigationTarget::from_named( + file_id.original_file(db), + &*node, + )); + } + hir::ModuleDef::Enum(e) => { + let (file_id, node) = e.source(db); + return Some(NavigationTarget::from_named( + file_id.original_file(db), + &*node, + )); + } }; let res = match def { - Def::Struct(s) => { - let (file_id, node) = s.source(db); - NavigationTarget::from_named(file_id.original_file(db), &*node) - } - Def::Enum(e) => { - let (file_id, node) = e.source(db); - NavigationTarget::from_named(file_id.original_file(db), &*node) - } Def::EnumVariant(ev) => { let (file_id, node) = ev.source(db); NavigationTarget::from_named(file_id.original_file(db), &*node) From a7c0336a7516e4973a9efb86bfb97cf290441413 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 24 Jan 2019 19:12:11 +0300 Subject: [PATCH 12/26] macro-generate froms --- crates/ra_hir/src/code_model_api.rs | 25 +----------------- crates/ra_hir/src/generics.rs | 19 +------------- crates/ra_hir/src/lib.rs | 12 +++++++++ crates/ra_hir/src/ty.rs | 39 +++-------------------------- 4 files changed, 17 insertions(+), 78 deletions(-) diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index a094268cae..4b79358e4b 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -70,30 +70,7 @@ pub enum ModuleDef { Enum(Enum), Def(DefId), } -//FIXME: change to from -impl From for ModuleDef { - fn from(it: Module) -> ModuleDef { - ModuleDef::Module(it) - } -} - -impl From for ModuleDef { - fn from(it: Function) -> ModuleDef { - ModuleDef::Function(it) - } -} - -impl From for ModuleDef { - fn from(it: Struct) -> ModuleDef { - ModuleDef::Struct(it) - } -} - -impl From for ModuleDef { - fn from(it: Enum) -> ModuleDef { - ModuleDef::Enum(it) - } -} +impl_froms!(ModuleDef: Module, Function, Struct, Enum); impl From for ModuleDef { fn from(it: DefId) -> ModuleDef { diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index df23871c76..a8cacbb4ad 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs @@ -29,24 +29,7 @@ pub enum GenericDef { Enum(Enum), Def(DefId), } - -impl From for GenericDef { - fn from(func: Function) -> GenericDef { - GenericDef::Function(func) - } -} - -impl From for GenericDef { - fn from(s: Struct) -> GenericDef { - GenericDef::Struct(s) - } -} - -impl From for GenericDef { - fn from(e: Enum) -> GenericDef { - GenericDef::Enum(e) - } -} +impl_froms!(GenericDef: Function, Struct, Enum); impl From for GenericDef { fn from(def_id: DefId) -> GenericDef { diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 5d63718924..33438509c7 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -5,6 +5,18 @@ //! to a particular crate instance. That is, it has cfg flags and features //! applied. So, the relation between syntax and HIR is many-to-one. +macro_rules! impl_froms { + ($e:ident: $($v:ident), *) => { + $( + impl From<$v> for $e { + fn from(it: $v) -> $e { + $e::$v(it) + } + } + )* + } +} + pub mod db; #[cfg(test)] mod mock; diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index b818996614..fcf8a1dbb0 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -168,18 +168,7 @@ pub enum AdtDef { Struct(Struct), Enum(Enum), } - -impl From for AdtDef { - fn from(s: Struct) -> AdtDef { - AdtDef::Struct(s) - } -} - -impl From for AdtDef { - fn from(e: Enum) -> AdtDef { - AdtDef::Enum(e) - } -} +impl_froms!(AdtDef: Struct, Enum); impl AdtDef { fn krate(self, db: &impl HirDatabase) -> Option { @@ -701,24 +690,7 @@ pub enum TypableDef { Enum(Enum), Def(DefId), } - -impl From for TypableDef { - fn from(func: Function) -> TypableDef { - TypableDef::Function(func) - } -} - -impl From for TypableDef { - fn from(s: Struct) -> TypableDef { - TypableDef::Struct(s) - } -} - -impl From for TypableDef { - fn from(e: Enum) -> TypableDef { - TypableDef::Enum(e) - } -} +impl_froms!(TypableDef: Function, Struct, Enum); impl From for TypableDef { fn from(func: DefId) -> TypableDef { @@ -763,12 +735,7 @@ pub enum VariantDef { Struct(Struct), Def(DefId), // EnumVariant } - -impl From for VariantDef { - fn from(struct_: Struct) -> VariantDef { - VariantDef::Struct(struct_) - } -} +impl_froms!(VariantDef: Struct); impl From for VariantDef { fn from(def_id: DefId) -> VariantDef { From 11dda8a0fb905a1b41a64001d564632eb062b9aa Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 24 Jan 2019 19:29:44 +0300 Subject: [PATCH 13/26] remove useless aliases --- crates/ra_hir/src/adt.rs | 10 +++--- crates/ra_hir/src/code_model_impl/function.rs | 6 ++-- crates/ra_hir/src/ids.rs | 36 ++++--------------- 3 files changed, 14 insertions(+), 38 deletions(-) diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index baf853a3a4..17ece93a75 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs @@ -13,7 +13,7 @@ use crate::{ HirDatabase, DefKind, SourceItemId, type_ref::TypeRef, - ids::{StructLoc, EnumLoc}, + ids::ItemLoc, }; impl Struct { @@ -23,8 +23,8 @@ impl Struct { file_id: HirFileId, ast: &ast::StructDef, ) -> Struct { - let loc: StructLoc = StructLoc::from_ast(db, module, file_id, ast); - let id = loc.id(db); + let loc = ItemLoc::from_ast(db, module, file_id, ast); + let id = db.as_ref().structs.loc2id(&loc); Struct { id } } @@ -40,8 +40,8 @@ impl Enum { file_id: HirFileId, ast: &ast::EnumDef, ) -> Enum { - let loc: EnumLoc = EnumLoc::from_ast(db, module, file_id, ast); - let id = loc.id(db); + let loc = ItemLoc::from_ast(db, module, file_id, ast); + let id = db.as_ref().enums.loc2id(&loc); Enum { id } } } diff --git a/crates/ra_hir/src/code_model_impl/function.rs b/crates/ra_hir/src/code_model_impl/function.rs index d8dafb10e4..8a2ab5714c 100644 --- a/crates/ra_hir/src/code_model_impl/function.rs +++ b/crates/ra_hir/src/code_model_impl/function.rs @@ -9,7 +9,7 @@ use crate::{ type_ref::{TypeRef, Mutability}, expr::Body, impl_block::ImplBlock, - ids::FunctionLoc, + ids::ItemLoc, }; pub use self::scope::{FnScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax}; @@ -21,8 +21,8 @@ impl Function { file_id: HirFileId, ast: &ast::FnDef, ) -> Function { - let loc: FunctionLoc = FunctionLoc::from_ast(db, module, file_id, ast); - let id = loc.id(db); + let loc = ItemLoc::from_ast(db, module, file_id, ast); + let id = db.as_ref().fns.loc2id(&loc); Function { id } } diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 332cec9c86..6375c76c9c 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs @@ -13,9 +13,9 @@ use crate::{ pub struct HirInterner { defs: LocationIntener, macros: LocationIntener, - fns: LocationIntener, - structs: LocationIntener, - enums: LocationIntener, + pub(crate) fns: LocationIntener, FunctionId>, + pub(crate) structs: LocationIntener, StructId>, + pub(crate) enums: LocationIntener, EnumId>, } impl HirInterner { @@ -182,56 +182,32 @@ impl Clone for ItemLoc { pub struct FunctionId(RawId); impl_arena_id!(FunctionId); -pub(crate) type FunctionLoc = ItemLoc; - impl FunctionId { - pub(crate) fn loc(self, db: &impl AsRef) -> FunctionLoc { + pub(crate) fn loc(self, db: &impl AsRef) -> ItemLoc { db.as_ref().fns.id2loc(self) } } -impl FunctionLoc { - pub(crate) fn id(&self, db: &impl AsRef) -> FunctionId { - db.as_ref().fns.loc2id(&self) - } -} - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct StructId(RawId); impl_arena_id!(StructId); -pub(crate) type StructLoc = ItemLoc; - impl StructId { - pub(crate) fn loc(self, db: &impl AsRef) -> StructLoc { + pub(crate) fn loc(self, db: &impl AsRef) -> ItemLoc { db.as_ref().structs.id2loc(self) } } -impl StructLoc { - pub(crate) fn id(&self, db: &impl AsRef) -> StructId { - db.as_ref().structs.loc2id(&self) - } -} - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct EnumId(RawId); impl_arena_id!(EnumId); -pub(crate) type EnumLoc = ItemLoc; - impl EnumId { - pub(crate) fn loc(self, db: &impl AsRef) -> EnumLoc { + pub(crate) fn loc(self, db: &impl AsRef) -> ItemLoc { db.as_ref().enums.id2loc(self) } } -impl EnumLoc { - pub(crate) fn id(&self, db: &impl AsRef) -> EnumId { - db.as_ref().enums.loc2id(&self) - } -} - /// Def's are a core concept of hir. A `Def` is an Item (function, module, etc) /// in a specific module. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] From 4c514a3e02b019cdd3a17c9bcd78d93c210ab267 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 24 Jan 2019 23:32:41 +0300 Subject: [PATCH 14/26] move enum variant to the new API --- crates/ra_hir/src/adt.rs | 64 +++-------- crates/ra_hir/src/code_model_api.rs | 29 +++-- crates/ra_hir/src/code_model_impl/module.rs | 4 +- crates/ra_hir/src/db.rs | 6 +- crates/ra_hir/src/ids.rs | 15 ++- crates/ra_hir/src/ty.rs | 121 ++++++++------------ 6 files changed, 97 insertions(+), 142 deletions(-) diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index 17ece93a75..b2631d6a69 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs @@ -4,14 +4,12 @@ use std::sync::Arc; use ra_syntax::{ - SyntaxNode, - ast::{self, NameOwner, StructFlavor, AstNode} + ast::{self, NameOwner, StructFlavor} }; use crate::{ - DefId, DefLoc, Name, AsName, Struct, Enum, EnumVariant, Module, HirFileId, - HirDatabase, DefKind, - SourceItemId, + Name, AsName, Struct, Enum, EnumVariant, Module, HirFileId, + HirDatabase, type_ref::TypeRef, ids::ItemLoc, }; @@ -66,26 +64,17 @@ impl StructData { } } -fn get_def_id( - db: &impl HirDatabase, - module: Module, - file_id: HirFileId, - node: &SyntaxNode, - expected_kind: DefKind, -) -> DefId { - let file_items = db.file_items(file_id); - - let item_id = file_items.id_of(file_id, node); - let source_item_id = SourceItemId { - file_id, - item_id: Some(item_id), - }; - let loc = DefLoc { - module, - kind: expected_kind, - source_item_id, - }; - loc.id(db) +impl EnumVariant { + pub(crate) fn from_ast( + db: &impl HirDatabase, + module: Module, + file_id: HirFileId, + ast: &ast::EnumVariant, + ) -> EnumVariant { + let loc = ItemLoc::from_ast(db, module, file_id, ast); + let id = db.as_ref().enum_variants.loc2id(&loc); + EnumVariant { id } + } } #[derive(Debug, Clone, PartialEq, Eq)] @@ -107,17 +96,7 @@ impl EnumData { vl.variants() .filter_map(|variant_def| { let name = variant_def.name().map(|n| n.as_name()); - - name.map(|n| { - let def_id = get_def_id( - db, - module, - file_id, - variant_def.syntax(), - DefKind::EnumVariant, - ); - (n, EnumVariant::new(def_id)) - }) + name.map(|n| (n, EnumVariant::from_ast(db, module, file_id, variant_def))) }) .collect() } else { @@ -148,17 +127,12 @@ impl EnumVariantData { pub(crate) fn enum_variant_data_query( db: &impl HirDatabase, - def_id: DefId, + var: EnumVariant, ) -> Arc { - let def_loc = def_id.loc(db); - assert!(def_loc.kind == DefKind::EnumVariant); - let syntax = db.file_item(def_loc.source_item_id); - let variant_def = ast::EnumVariant::cast(&syntax) - .expect("enum variant def should point to EnumVariant node"); + let (file_id, variant_def) = var.source(db); let enum_def = variant_def.parent_enum(); - let e = Enum::from_ast(db, def_loc.module, def_loc.source_item_id.file_id, enum_def); - - Arc::new(EnumVariantData::new(variant_def, e)) + let e = Enum::from_ast(db, var.module(db), file_id, enum_def); + Arc::new(EnumVariantData::new(&*variant_def, e)) } } diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 4b79358e4b..5e927e41dc 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -16,7 +16,7 @@ use crate::{ code_model_impl::def_id_to_ast, docs::{Documentation, Docs, docs_from_ast}, module_tree::ModuleId, - ids::{FunctionId, StructId, EnumId}, + ids::{FunctionId, StructId, EnumId, EnumVariantId}, }; /// hir::Crate describes a single crate. It's the main interface with which @@ -68,9 +68,11 @@ pub enum ModuleDef { Function(Function), Struct(Struct), Enum(Enum), + // Can't be directly declared, but can be imported. + EnumVariant(EnumVariant), Def(DefId), } -impl_froms!(ModuleDef: Module, Function, Struct, Enum); +impl_froms!(ModuleDef: Module, Function, Struct, Enum, EnumVariant); impl From for ModuleDef { fn from(it: DefId) -> ModuleDef { @@ -264,30 +266,25 @@ impl Docs for Enum { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct EnumVariant { - pub(crate) def_id: DefId, + pub(crate) id: EnumVariantId, } impl EnumVariant { - pub(crate) fn new(def_id: DefId) -> Self { - EnumVariant { def_id } + pub fn module(&self, db: &impl HirDatabase) -> Module { + self.id.loc(db).module } - - pub fn def_id(&self) -> DefId { - self.def_id - } - pub fn parent_enum(&self, db: &impl HirDatabase) -> Enum { - db.enum_variant_data(self.def_id).parent_enum.clone() + db.enum_variant_data(*self).parent_enum.clone() } pub fn name(&self, db: &impl HirDatabase) -> Option { - db.enum_variant_data(self.def_id).name.clone() + db.enum_variant_data(*self).name.clone() } pub fn variant_data(&self, db: &impl HirDatabase) -> Arc { - db.enum_variant_data(self.def_id).variant_data.clone() + db.enum_variant_data(*self).variant_data.clone() } pub fn fields(&self, db: &impl HirDatabase) -> Vec { @@ -295,14 +292,14 @@ impl EnumVariant { .fields() .iter() .map(|it| StructField { - parent: self.def_id.into(), + parent: (*self).into(), name: it.name.clone(), }) .collect() } pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc) { - def_id_to_ast(db, self.def_id) + self.id.loc(db).source(db) } } diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs index 4ea649770e..aa5e5d6895 100644 --- a/crates/ra_hir/src/code_model_impl/module.rs +++ b/crates/ra_hir/src/code_model_impl/module.rs @@ -143,11 +143,11 @@ impl Module { .find(|(n, _variant)| n == &segment.name); match matching_variant { - Some((_n, variant)) => PerNs::both(variant.def_id().into(), (*e).into()), + Some((_n, variant)) => PerNs::both(variant.into(), (*e).into()), None => PerNs::none(), } } - ModuleDef::Function(_) | ModuleDef::Struct(_) => { + ModuleDef::Function(_) | ModuleDef::Struct(_) | ModuleDef::EnumVariant(_) => { // could be an inherent method call in UFCS form // (`Struct::method`), or some other kind of associated // item... Which we currently don't handle (TODO) diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 34e41017b9..5304f5d313 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -4,11 +4,11 @@ use ra_syntax::{SyntaxNode, TreeArc, SourceFile}; use ra_db::{SyntaxDatabase, CrateId, salsa}; use crate::{ - DefId, MacroCallId, Name, HirFileId, + MacroCallId, Name, HirFileId, SourceFileItems, SourceItemId, Crate, Module, HirInterner, query_definitions, Function, FnSignature, FnScopes, - Struct, Enum, + Struct, Enum, EnumVariant, macros::MacroExpansion, module_tree::ModuleTree, nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}}, @@ -36,7 +36,7 @@ pub trait HirDatabase: SyntaxDatabase + AsRef { fn enum_data(&self, e: Enum) -> Arc; #[salsa::invoke(crate::adt::EnumVariantData::enum_variant_data_query)] - fn enum_variant_data(&self, def_id: DefId) -> Arc; + fn enum_variant_data(&self, var: EnumVariant) -> Arc; #[salsa::invoke(crate::ty::infer)] fn infer(&self, func: Function) -> Arc; diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 6375c76c9c..8cdc7ee56b 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs @@ -5,7 +5,7 @@ use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, ast}; use ra_arena::{Arena, RawId, impl_arena_id}; use crate::{ - HirDatabase, Def, EnumVariant, Crate, + HirDatabase, Def, Crate, Module, Trait, Type, Static, Const, }; @@ -16,6 +16,7 @@ pub struct HirInterner { pub(crate) fns: LocationIntener, FunctionId>, pub(crate) structs: LocationIntener, StructId>, pub(crate) enums: LocationIntener, EnumId>, + pub(crate) enum_variants: LocationIntener, EnumVariantId>, } impl HirInterner { @@ -208,6 +209,16 @@ impl EnumId { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct EnumVariantId(RawId); +impl_arena_id!(EnumVariantId); + +impl EnumVariantId { + pub(crate) fn loc(self, db: &impl AsRef) -> ItemLoc { + db.as_ref().enum_variants.id2loc(self) + } +} + /// Def's are a core concept of hir. A `Def` is an Item (function, module, etc) /// in a specific module. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -223,7 +234,6 @@ pub struct DefLoc { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub(crate) enum DefKind { - EnumVariant, Const, Static, Trait, @@ -249,7 +259,6 @@ impl DefId { pub fn resolve(self, db: &impl HirDatabase) -> Def { let loc = self.loc(db); match loc.kind { - DefKind::EnumVariant => Def::EnumVariant(EnumVariant::new(self)), DefKind::Const => { let def = Const::new(self); Def::Const(def) diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index fcf8a1dbb0..66cf2bd645 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -431,25 +431,24 @@ impl Ty { TypableDef::Function(func) => (func.generic_params(db), last), TypableDef::Struct(s) => (s.generic_params(db), last), TypableDef::Enum(e) => (e.generic_params(db), last), + TypableDef::EnumVariant(var) => { + // the generic args for an enum variant may be either specified + // on the segment referring to the enum, or on the segment + // referring to the variant. So `Option::::None` and + // `Option::None::` are both allowed (though the former is + // preferred). See also `def_ids_for_path_segments` in rustc. + let len = path.segments.len(); + let segment = if len >= 2 && path.segments[len - 2].args_and_bindings.is_some() { + // Option::::None + &path.segments[len - 2] + } else { + // Option::None:: + last + }; + (var.parent_enum(db).generic_params(db), segment) + } TypableDef::Def(def_id) => match def_id.resolve(db) { Def::Trait(t) => (t.generic_params(db), last), - Def::EnumVariant(ev) => { - // the generic args for an enum variant may be either specified - // on the segment referring to the enum, or on the segment - // referring to the variant. So `Option::::None` and - // `Option::None::` are both allowed (though the former is - // preferred). See also `def_ids_for_path_segments` in rustc. - let len = path.segments.len(); - let segment = if len >= 2 && path.segments[len - 2].args_and_bindings.is_some() - { - // Option::::None - &path.segments[len - 2] - } else { - // Option::None:: - last - }; - (ev.parent_enum(db).generic_params(db), segment) - } _ => return Substs::empty(), }, }; @@ -688,9 +687,10 @@ pub enum TypableDef { Function(Function), Struct(Struct), Enum(Enum), + EnumVariant(EnumVariant), Def(DefId), } -impl_froms!(TypableDef: Function, Struct, Enum); +impl_froms!(TypableDef: Function, Struct, Enum, EnumVariant); impl From for TypableDef { fn from(func: DefId) -> TypableDef { @@ -705,6 +705,7 @@ impl From for Option { ModuleDef::Function(f) => f.into(), ModuleDef::Struct(s) => s.into(), ModuleDef::Enum(e) => e.into(), + ModuleDef::EnumVariant(v) => v.into(), ModuleDef::Module(_) => return None, }; Some(res) @@ -716,48 +717,33 @@ pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty { TypableDef::Function(f) => type_for_fn(db, f), TypableDef::Struct(s) => type_for_struct(db, s), TypableDef::Enum(e) => type_for_enum(db, e), - TypableDef::Def(def_id) => match def_id.resolve(db) { - Def::EnumVariant(ev) => type_for_enum_variant(db, ev), - _ => { - log::debug!( - "trying to get type for item of unknown type {:?} {:?}", - def_id, - def - ); - Ty::Unknown - } - }, + TypableDef::EnumVariant(v) => type_for_enum_variant(db, v), + TypableDef::Def(def_id) => { + log::debug!( + "trying to get type for item of unknown type {:?} {:?}", + def_id, + def + ); + Ty::Unknown + } } } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum VariantDef { Struct(Struct), - Def(DefId), // EnumVariant -} -impl_froms!(VariantDef: Struct); - -impl From for VariantDef { - fn from(def_id: DefId) -> VariantDef { - VariantDef::Def(def_id) - } + EnumVariant(EnumVariant), } +impl_froms!(VariantDef: Struct, EnumVariant); pub(super) fn type_for_field(db: &impl HirDatabase, def: VariantDef, field: Name) -> Option { let (variant_data, generics, module) = match def { VariantDef::Struct(s) => (s.variant_data(db), s.generic_params(db), s.module(db)), - VariantDef::Def(def_id) => match def_id.resolve(db) { - Def::EnumVariant(ev) => ( - ev.variant_data(db), - ev.parent_enum(db).generic_params(db), - def_id.module(db), - ), - // TODO: unions - _ => panic!( - "trying to get type for field {:?} in non-struct/variant {:?}", - field, def_id - ), - }, + VariantDef::EnumVariant(var) => ( + var.variant_data(db), + var.parent_enum(db).generic_params(db), + var.module(db), + ), }; // We can't have an impl block ere, right? // let impl_block = def_id.impl_block(db); @@ -1156,21 +1142,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { def, ); match def { - TypableDef::Def(def_id) => match def_id.resolve(self.db) { - Def::EnumVariant(ev) => { - let ty = type_for_enum_variant(self.db, ev); - let ty = self.insert_type_vars(ty.apply_substs(substs)); - (ty, Some(def_id.into())) - } - _ => (Ty::Unknown, None), - }, - TypableDef::Function(_) => (Ty::Unknown, None), TypableDef::Struct(s) => { let ty = type_for_struct(self.db, s); let ty = self.insert_type_vars(ty.apply_substs(substs)); (ty, Some(s.into())) } - TypableDef::Enum(_) => (Ty::Unknown, None), + TypableDef::EnumVariant(var) => { + let ty = type_for_enum_variant(self.db, var); + let ty = self.insert_type_vars(ty.apply_substs(substs)); + (ty, Some(var.into())) + } + TypableDef::Def(_) | TypableDef::Enum(_) | TypableDef::Function(_) => { + (Ty::Unknown, None) + } } } @@ -1181,13 +1165,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let fields = s.fields(self.db); Some((ty, fields)) } - VariantDef::Def(def_id) => match def_id.resolve(self.db) { - Def::EnumVariant(ev) => { - let fields = ev.fields(self.db); - Some((ty, fields)) - } - _ => None, - }, + VariantDef::EnumVariant(var) => { + let fields = var.fields(self.db); + Some((ty, fields)) + } } } @@ -1285,13 +1266,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { .module .resolve_path(self.db, &path) .take_values() - .and_then(|module_def| match module_def { - ModuleDef::Def(it) => Some(it.into()), - ModuleDef::Function(func) => Some(func.into()), - ModuleDef::Struct(s) => Some(s.into()), - ModuleDef::Enum(e) => Some(e.into()), - ModuleDef::Module(_) => None, - }) + .and_then(|module_def| module_def.into()) .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)), Pat::Bind { mode, From 6a5a1f590201ba962a1f77ce1a7ff5870712728d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 24 Jan 2019 23:36:16 +0300 Subject: [PATCH 15/26] adapt ide_api to the new API --- crates/ra_hir/src/code_model_api.rs | 1 - crates/ra_ide_api/src/completion/complete_path.rs | 5 ++++- crates/ra_ide_api/src/completion/completion_item.rs | 1 + crates/ra_ide_api/src/navigation_target.rs | 11 +++++++---- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 5e927e41dc..e16013956f 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -47,7 +47,6 @@ impl Crate { #[derive(Debug)] pub enum Def { - EnumVariant(EnumVariant), Const(Const), Static(Static), Trait(Trait), diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index e039a333c9..4768efdc19 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs @@ -40,7 +40,10 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { .add_to(acc) }); } - hir::ModuleDef::Function(_) | hir::ModuleDef::Struct(_) | hir::ModuleDef::Def(_) => return, + hir::ModuleDef::Function(_) + | hir::ModuleDef::Struct(_) + | hir::ModuleDef::Def(_) + | hir::ModuleDef::EnumVariant(_) => return, }; } diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs index f2301653a5..ee1f8bce06 100644 --- a/crates/ra_ide_api/src/completion/completion_item.rs +++ b/crates/ra_ide_api/src/completion/completion_item.rs @@ -222,6 +222,7 @@ impl Builder { hir::ModuleDef::Function(func) => return self.from_function(ctx, func), hir::ModuleDef::Struct(it) => (CompletionItemKind::Struct, it.docs(ctx.db)), hir::ModuleDef::Enum(it) => (CompletionItemKind::Enum, it.docs(ctx.db)), + hir::ModuleDef::EnumVariant(it) => (CompletionItemKind::EnumVariant, it.docs(ctx.db)), hir::ModuleDef::Def(def_id) => match def_id.resolve(ctx.db) { hir::Def::Trait(it) => (CompletionItemKind::Trait, it.docs(ctx.db)), hir::Def::Type(it) => (CompletionItemKind::TypeAlias, it.docs(ctx.db)), diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs index b92670f36b..fc76338d22 100644 --- a/crates/ra_ide_api/src/navigation_target.rs +++ b/crates/ra_ide_api/src/navigation_target.rs @@ -128,13 +128,16 @@ impl NavigationTarget { &*node, )); } + hir::ModuleDef::EnumVariant(var) => { + let (file_id, node) = var.source(db); + return Some(NavigationTarget::from_named( + file_id.original_file(db), + &*node, + )); + } }; let res = match def { - Def::EnumVariant(ev) => { - let (file_id, node) = ev.source(db); - NavigationTarget::from_named(file_id.original_file(db), &*node) - } Def::Trait(f) => { let (file_id, node) = f.source(db); NavigationTarget::from_named(file_id.original_file(db), &*node) From f3a37522a027a10c257f4dfdc2369e7853e0c80e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 24 Jan 2019 23:39:39 +0300 Subject: [PATCH 16/26] removed untyped typabledef --- crates/ra_hir/src/ty.rs | 29 +++-------------------------- 1 file changed, 3 insertions(+), 26 deletions(-) diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 66cf2bd645..9a1a90eed8 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -24,14 +24,13 @@ use std::ops::Index; use std::sync::Arc; use std::{fmt, mem}; -use log; use ena::unify::{InPlaceUnificationTable, UnifyKey, UnifyValue, NoError}; use ra_arena::map::ArenaMap; use join_to_string::join; use rustc_hash::FxHashMap; use crate::{ - Def, DefId, Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock, + Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock, FnSignature, FnScopes, ModuleDef, Crate, db::HirDatabase, type_ref::{TypeRef, Mutability}, @@ -447,10 +446,6 @@ impl Ty { }; (var.parent_enum(db).generic_params(db), segment) } - TypableDef::Def(def_id) => match def_id.resolve(db) { - Def::Trait(t) => (t.generic_params(db), last), - _ => return Substs::empty(), - }, }; // substs_from_path if let Some(generic_args) = &segment.args_and_bindings { @@ -688,25 +683,17 @@ pub enum TypableDef { Struct(Struct), Enum(Enum), EnumVariant(EnumVariant), - Def(DefId), } impl_froms!(TypableDef: Function, Struct, Enum, EnumVariant); -impl From for TypableDef { - fn from(func: DefId) -> TypableDef { - TypableDef::Def(func) - } -} - impl From for Option { fn from(def: ModuleDef) -> Option { let res = match def { - ModuleDef::Def(r) => r.into(), ModuleDef::Function(f) => f.into(), ModuleDef::Struct(s) => s.into(), ModuleDef::Enum(e) => e.into(), ModuleDef::EnumVariant(v) => v.into(), - ModuleDef::Module(_) => return None, + ModuleDef::Def(_) | ModuleDef::Module(_) => return None, }; Some(res) } @@ -718,14 +705,6 @@ pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty { TypableDef::Struct(s) => type_for_struct(db, s), TypableDef::Enum(e) => type_for_enum(db, e), TypableDef::EnumVariant(v) => type_for_enum_variant(db, v), - TypableDef::Def(def_id) => { - log::debug!( - "trying to get type for item of unknown type {:?} {:?}", - def_id, - def - ); - Ty::Unknown - } } } @@ -1152,9 +1131,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let ty = self.insert_type_vars(ty.apply_substs(substs)); (ty, Some(var.into())) } - TypableDef::Def(_) | TypableDef::Enum(_) | TypableDef::Function(_) => { - (Ty::Unknown, None) - } + TypableDef::Enum(_) | TypableDef::Function(_) => (Ty::Unknown, None), } } From 1a5f32fcb516c1647c7581f21be9b11c8f1f94ba Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 24 Jan 2019 23:46:48 +0300 Subject: [PATCH 17/26] remove dead code --- crates/ra_hir/src/ids.rs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 8cdc7ee56b..7ed5dbec74 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs @@ -5,7 +5,7 @@ use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, ast}; use ra_arena::{Arena, RawId, impl_arena_id}; use crate::{ - HirDatabase, Def, Crate, + HirDatabase, Def, Module, Trait, Type, Static, Const, }; @@ -284,16 +284,6 @@ impl DefId { let syntax = db.file_item(loc.source_item_id); (loc.source_item_id.file_id, syntax) } - - /// For a module, returns that module; for any other def, returns the containing module. - pub fn module(self, db: &impl HirDatabase) -> Module { - self.loc(db).module - } - - /// Returns the containing crate. - pub fn krate(&self, db: &impl HirDatabase) -> Option { - self.module(db).krate(db) - } } impl DefLoc { From 90215eb5a026d446ae7e5d4e62c43d6d8c82edf1 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 25 Jan 2019 00:02:18 +0300 Subject: [PATCH 18/26] generalize boilerplate --- crates/ra_hir/src/code_model_api.rs | 37 +++++++------- crates/ra_hir/src/code_model_impl/function.rs | 4 -- crates/ra_hir/src/ids.rs | 49 ++++++++++++------- 3 files changed, 51 insertions(+), 39 deletions(-) diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index e16013956f..1fa591ea44 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -16,7 +16,7 @@ use crate::{ code_model_impl::def_id_to_ast, docs::{Documentation, Docs, docs_from_ast}, module_tree::ModuleId, - ids::{FunctionId, StructId, EnumId, EnumVariantId}, + ids::{FunctionId, StructId, EnumId, EnumVariantId, AstItemDef}, }; /// hir::Crate describes a single crate. It's the main interface with which @@ -197,8 +197,12 @@ pub struct Struct { } impl Struct { + pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc) { + self.id.source(db) + } + pub fn module(&self, db: &impl HirDatabase) -> Module { - self.id.loc(db).module + self.id.module(db) } pub fn name(&self, db: &impl HirDatabase) -> Option { @@ -217,10 +221,6 @@ impl Struct { .collect() } - pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc) { - self.id.loc(db).source(db) - } - pub fn generic_params(&self, db: &impl HirDatabase) -> Arc { db.generic_params((*self).into()) } @@ -238,8 +238,12 @@ pub struct Enum { } impl Enum { + pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc) { + self.id.source(db) + } + pub fn module(&self, db: &impl HirDatabase) -> Module { - self.id.loc(db).module + self.id.module(db) } pub fn name(&self, db: &impl HirDatabase) -> Option { @@ -250,10 +254,6 @@ impl Enum { db.enum_data(*self).variants.clone() } - pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc) { - self.id.loc(db).source(db) - } - pub fn generic_params(&self, db: &impl HirDatabase) -> Arc { db.generic_params((*self).into()) } @@ -271,8 +271,11 @@ pub struct EnumVariant { } impl EnumVariant { + pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc) { + self.id.source(db) + } pub fn module(&self, db: &impl HirDatabase) -> Module { - self.id.loc(db).module + self.id.module(db) } pub fn parent_enum(&self, db: &impl HirDatabase) -> Enum { db.enum_variant_data(*self).parent_enum.clone() @@ -296,10 +299,6 @@ impl EnumVariant { }) .collect() } - - pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc) { - self.id.loc(db).source(db) - } } impl Docs for EnumVariant { @@ -348,7 +347,11 @@ impl FnSignature { impl Function { pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc) { - self.id.loc(db).source(db) + self.id.source(db) + } + + pub fn module(&self, db: &impl HirDatabase) -> Module { + self.id.module(db) } pub fn body_syntax_mapping(&self, db: &impl HirDatabase) -> Arc { diff --git a/crates/ra_hir/src/code_model_impl/function.rs b/crates/ra_hir/src/code_model_impl/function.rs index 8a2ab5714c..6ce5c77b13 100644 --- a/crates/ra_hir/src/code_model_impl/function.rs +++ b/crates/ra_hir/src/code_model_impl/function.rs @@ -30,10 +30,6 @@ impl Function { db.body_hir(*self) } - pub(crate) fn module(&self, db: &impl HirDatabase) -> Module { - self.id.loc(db).module - } - /// The containing impl block, if this is a method. pub(crate) fn impl_block(&self, db: &impl HirDatabase) -> Option { let module_impls = db.impls_in_module(self.module(db)); diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 7ed5dbec74..262047849f 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs @@ -1,8 +1,11 @@ -use std::marker::PhantomData; +use std::{ + marker::PhantomData, + hash::Hash, +}; use ra_db::{LocationIntener, FileId}; use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, ast}; -use ra_arena::{Arena, RawId, impl_arena_id}; +use ra_arena::{Arena, RawId, ArenaId, impl_arena_id}; use crate::{ HirDatabase, Def, @@ -179,43 +182,53 @@ impl Clone for ItemLoc { } } +pub(crate) trait AstItemDef: ArenaId + Clone { + fn interner(interner: &HirInterner) -> &LocationIntener, Self>; + fn source(self, db: &impl HirDatabase) -> (HirFileId, TreeArc) { + let int = Self::interner(db.as_ref()); + let loc = int.id2loc(self); + loc.source(db) + } + fn module(self, db: &impl HirDatabase) -> Module { + let int = Self::interner(db.as_ref()); + let loc = int.id2loc(self); + loc.module + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct FunctionId(RawId); impl_arena_id!(FunctionId); - -impl FunctionId { - pub(crate) fn loc(self, db: &impl AsRef) -> ItemLoc { - db.as_ref().fns.id2loc(self) +impl AstItemDef for FunctionId { + fn interner(interner: &HirInterner) -> &LocationIntener, Self> { + &interner.fns } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct StructId(RawId); impl_arena_id!(StructId); - -impl StructId { - pub(crate) fn loc(self, db: &impl AsRef) -> ItemLoc { - db.as_ref().structs.id2loc(self) +impl AstItemDef for StructId { + fn interner(interner: &HirInterner) -> &LocationIntener, Self> { + &interner.structs } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct EnumId(RawId); impl_arena_id!(EnumId); - -impl EnumId { - pub(crate) fn loc(self, db: &impl AsRef) -> ItemLoc { - db.as_ref().enums.id2loc(self) +impl AstItemDef for EnumId { + fn interner(interner: &HirInterner) -> &LocationIntener, Self> { + &interner.enums } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct EnumVariantId(RawId); impl_arena_id!(EnumVariantId); - -impl EnumVariantId { - pub(crate) fn loc(self, db: &impl AsRef) -> ItemLoc { - db.as_ref().enum_variants.id2loc(self) +impl AstItemDef for EnumVariantId { + fn interner(interner: &HirInterner) -> &LocationIntener, Self> { + &interner.enum_variants } } From f588535273db261c32e23c1b0221d03ad82cd94d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 25 Jan 2019 00:26:54 +0300 Subject: [PATCH 19/26] remove boilerplate --- crates/ra_hir/src/adt.rs | 54 +++---------- crates/ra_hir/src/code_model_impl/function.rs | 14 +--- crates/ra_hir/src/ids.rs | 80 +++++++++++-------- crates/ra_hir/src/impl_block.rs | 4 +- crates/ra_hir/src/nameres/lower.rs | 8 +- crates/ra_hir/src/source_binder.rs | 6 +- 6 files changed, 73 insertions(+), 93 deletions(-) diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index b2631d6a69..ad3f9c4059 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs @@ -8,42 +8,18 @@ use ra_syntax::{ }; use crate::{ - Name, AsName, Struct, Enum, EnumVariant, Module, HirFileId, + Name, AsName, Struct, Enum, EnumVariant, HirDatabase, type_ref::TypeRef, - ids::ItemLoc, + ids::LocationCtx, }; impl Struct { - pub(crate) fn from_ast( - db: &impl HirDatabase, - module: Module, - file_id: HirFileId, - ast: &ast::StructDef, - ) -> Struct { - let loc = ItemLoc::from_ast(db, module, file_id, ast); - let id = db.as_ref().structs.loc2id(&loc); - Struct { id } - } - pub(crate) fn variant_data(&self, db: &impl HirDatabase) -> Arc { db.struct_data((*self).into()).variant_data.clone() } } -impl Enum { - pub(crate) fn from_ast( - db: &impl HirDatabase, - module: Module, - file_id: HirFileId, - ast: &ast::EnumDef, - ) -> Enum { - let loc = ItemLoc::from_ast(db, module, file_id, ast); - let id = db.as_ref().enums.loc2id(&loc); - Enum { id } - } -} - #[derive(Debug, Clone, PartialEq, Eq)] pub struct StructData { pub(crate) name: Option, @@ -64,19 +40,6 @@ impl StructData { } } -impl EnumVariant { - pub(crate) fn from_ast( - db: &impl HirDatabase, - module: Module, - file_id: HirFileId, - ast: &ast::EnumVariant, - ) -> EnumVariant { - let loc = ItemLoc::from_ast(db, module, file_id, ast); - let id = db.as_ref().enum_variants.loc2id(&loc); - EnumVariant { id } - } -} - #[derive(Debug, Clone, PartialEq, Eq)] pub struct EnumData { pub(crate) name: Option, @@ -92,11 +55,15 @@ impl EnumData { pub(crate) fn enum_data_query(db: &impl HirDatabase, e: Enum) -> Arc { let (file_id, enum_def) = e.source(db); let module = e.module(db); + let ctx = LocationCtx::new(db, module, file_id); let variants = if let Some(vl) = enum_def.variant_list() { vl.variants() .filter_map(|variant_def| { - let name = variant_def.name().map(|n| n.as_name()); - name.map(|n| (n, EnumVariant::from_ast(db, module, file_id, variant_def))) + let name = variant_def.name()?.as_name(); + let var = EnumVariant { + id: ctx.to_def(variant_def), + }; + Some((name, var)) }) .collect() } else { @@ -131,7 +98,10 @@ impl EnumVariantData { ) -> Arc { let (file_id, variant_def) = var.source(db); let enum_def = variant_def.parent_enum(); - let e = Enum::from_ast(db, var.module(db), file_id, enum_def); + let ctx = LocationCtx::new(db, var.module(db), file_id); + let e = Enum { + id: ctx.to_def(enum_def), + }; Arc::new(EnumVariantData::new(&*variant_def, e)) } } diff --git a/crates/ra_hir/src/code_model_impl/function.rs b/crates/ra_hir/src/code_model_impl/function.rs index 6ce5c77b13..e0dd4d6290 100644 --- a/crates/ra_hir/src/code_model_impl/function.rs +++ b/crates/ra_hir/src/code_model_impl/function.rs @@ -5,27 +5,15 @@ use std::sync::Arc; use ra_syntax::ast::{self, NameOwner}; use crate::{ - HirDatabase, Name, AsName, Function, FnSignature, Module, HirFileId, + HirDatabase, Name, AsName, Function, FnSignature, type_ref::{TypeRef, Mutability}, expr::Body, impl_block::ImplBlock, - ids::ItemLoc, }; pub use self::scope::{FnScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax}; impl Function { - pub(crate) fn from_ast( - db: &impl HirDatabase, - module: Module, - file_id: HirFileId, - ast: &ast::FnDef, - ) -> Function { - let loc = ItemLoc::from_ast(db, module, file_id, ast); - let id = db.as_ref().fns.loc2id(&loc); - Function { id } - } - pub(crate) fn body(&self, db: &impl HirDatabase) -> Arc { db.body_hir(*self) } diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 262047849f..4b4e07e587 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs @@ -16,10 +16,10 @@ use crate::{ pub struct HirInterner { defs: LocationIntener, macros: LocationIntener, - pub(crate) fns: LocationIntener, FunctionId>, - pub(crate) structs: LocationIntener, StructId>, - pub(crate) enums: LocationIntener, EnumId>, - pub(crate) enum_variants: LocationIntener, EnumVariantId>, + fns: LocationIntener, FunctionId>, + structs: LocationIntener, StructId>, + enums: LocationIntener, EnumId>, + enum_variants: LocationIntener, EnumVariantId>, } impl HirInterner { @@ -144,34 +144,6 @@ pub struct ItemLoc { _ty: PhantomData, } -impl ItemLoc { - pub(crate) fn from_ast( - db: &impl HirDatabase, - module: Module, - file_id: HirFileId, - ast: &N, - ) -> ItemLoc { - let items = db.file_items(file_id); - let raw = SourceItemId { - file_id, - item_id: Some(items.id_of(file_id, ast.syntax())), - }; - ItemLoc { - module, - raw, - _ty: PhantomData, - } - } - - pub(crate) fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc) { - let syntax = db.file_item(self.raw); - let ast = N::cast(&syntax) - .unwrap_or_else(|| panic!("invalid ItemLoc: {:?}", self.raw)) - .to_owned(); - (self.raw.file_id, ast) - } -} - impl Clone for ItemLoc { fn clone(&self) -> ItemLoc { ItemLoc { @@ -182,12 +154,54 @@ impl Clone for ItemLoc { } } +#[derive(Clone, Copy)] +pub(crate) struct LocationCtx { + db: DB, + module: Module, + file_id: HirFileId, +} + +impl<'a, DB: HirDatabase> LocationCtx<&'a DB> { + pub(crate) fn new(db: &'a DB, module: Module, file_id: HirFileId) -> LocationCtx<&'a DB> { + LocationCtx { + db, + module, + file_id, + } + } + pub(crate) fn to_def(self, ast: &N) -> DEF + where + N: AstNode + Eq + Hash, + DEF: AstItemDef, + { + DEF::from_ast(self, ast) + } +} + pub(crate) trait AstItemDef: ArenaId + Clone { fn interner(interner: &HirInterner) -> &LocationIntener, Self>; + fn from_ast(ctx: LocationCtx<&impl HirDatabase>, ast: &N) -> Self { + let items = ctx.db.file_items(ctx.file_id); + let raw = SourceItemId { + file_id: ctx.file_id, + item_id: Some(items.id_of(ctx.file_id, ast.syntax())), + }; + let loc = ItemLoc { + module: ctx.module, + raw, + _ty: PhantomData, + }; + + Self::interner(ctx.db.as_ref()).loc2id(&loc) + } fn source(self, db: &impl HirDatabase) -> (HirFileId, TreeArc) { let int = Self::interner(db.as_ref()); let loc = int.id2loc(self); - loc.source(db) + let syntax = db.file_item(loc.raw); + let ast = N::cast(&syntax) + .unwrap_or_else(|| panic!("invalid ItemLoc: {:?}", loc.raw)) + .to_owned(); + (loc.raw.file_id, ast) } fn module(self, db: &impl HirDatabase) -> Module { let int = Self::interner(db.as_ref()); diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index 274169f93d..3df0d3a3b8 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs @@ -9,6 +9,7 @@ use crate::{ Function, HirFileId, db::HirDatabase, type_ref::TypeRef, + ids::LocationCtx, }; use crate::code_model_api::{Module, ModuleSource}; @@ -72,13 +73,14 @@ impl ImplData { ) -> Self { let target_trait = node.target_trait().map(TypeRef::from_ast); let target_type = TypeRef::from_ast_opt(node.target_type()); + let ctx = LocationCtx::new(db, module, file_id); let items = if let Some(item_list) = node.item_list() { item_list .impl_items() .map(|item_node| { let kind = match item_node.kind() { ast::ImplItemKind::FnDef(it) => { - return ImplItem::Method(Function::from_ast(db, module, file_id, it)); + return ImplItem::Method(Function { id: ctx.to_def(it) }); } ast::ImplItemKind::ConstDef(..) => DefKind::Item, ast::ImplItemKind::TypeDef(..) => DefKind::Item, diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs index 435804e2d0..0056bdd5a1 100644 --- a/crates/ra_hir/src/nameres/lower.rs +++ b/crates/ra_hir/src/nameres/lower.rs @@ -11,6 +11,7 @@ use crate::{ SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems, HirFileId, MacroCallLoc, AsName, PerNs, DefKind, DefLoc, Function, ModuleDef, Module, Struct, Enum, + ids::LocationCtx, }; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -146,10 +147,11 @@ impl LoweredModule { file_items: &SourceFileItems, item: &ast::ModuleItem, ) { + let ctx = LocationCtx::new(db, module, file_id); let name = match item.kind() { ast::ModuleItemKind::StructDef(it) => { if let Some(name) = it.name() { - let s = Struct::from_ast(db, module, file_id, it); + let s = Struct { id: ctx.to_def(it) }; let s: ModuleDef = s.into(); self.declarations.insert(name.as_name(), PerNs::both(s, s)); } @@ -157,7 +159,7 @@ impl LoweredModule { } ast::ModuleItemKind::EnumDef(it) => { if let Some(name) = it.name() { - let e = Enum::from_ast(db, module, file_id, it); + let e = Enum { id: ctx.to_def(it) }; let e: ModuleDef = e.into(); self.declarations.insert(name.as_name(), PerNs::types(e)); } @@ -165,7 +167,7 @@ impl LoweredModule { } ast::ModuleItemKind::FnDef(it) => { if let Some(name) = it.name() { - let func = Function::from_ast(db, module, file_id, it); + let func = Function { id: ctx.to_def(it) }; self.declarations .insert(name.as_name(), PerNs::values(func.into())); } diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index d1bf163d14..ea81858535 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -15,6 +15,7 @@ use ra_syntax::{ use crate::{ HirDatabase, Function, SourceItemId, ModuleDef, AsName, Module, + ids::LocationCtx, }; /// Locates the module by `FileId`. Picks topmost module in the file. @@ -116,7 +117,10 @@ pub fn function_from_module( ) -> Function { let (file_id, _) = module.definition_source(db); let file_id = file_id.into(); - Function::from_ast(db, module, file_id, fn_def) + let ctx = LocationCtx::new(db, module, file_id); + Function { + id: ctx.to_def(fn_def), + } } pub fn function_from_child_node( From 1db2cbcb8bd61b4f19f61cc6319343e5ad894515 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 25 Jan 2019 00:50:08 +0300 Subject: [PATCH 20/26] move consts&statics to new id --- crates/ra_hir/src/code_model_api.rs | 38 +++++++++---------- crates/ra_hir/src/code_model_impl/module.rs | 6 ++- crates/ra_hir/src/ids.rs | 32 ++++++++++------ crates/ra_hir/src/nameres/lower.rs | 24 +++++++++--- crates/ra_hir/src/ty.rs | 5 ++- .../src/completion/complete_path.rs | 2 + .../src/completion/completion_item.rs | 4 +- crates/ra_ide_api/src/navigation_target.rs | 22 +++++++---- 8 files changed, 86 insertions(+), 47 deletions(-) diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 1fa591ea44..d82dda79a7 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -16,7 +16,7 @@ use crate::{ code_model_impl::def_id_to_ast, docs::{Documentation, Docs, docs_from_ast}, module_tree::ModuleId, - ids::{FunctionId, StructId, EnumId, EnumVariantId, AstItemDef}, + ids::{FunctionId, StructId, EnumId, EnumVariantId, AstItemDef, ConstId, StaticId}, }; /// hir::Crate describes a single crate. It's the main interface with which @@ -47,8 +47,6 @@ impl Crate { #[derive(Debug)] pub enum Def { - Const(Const), - Static(Static), Trait(Trait), Type(Type), Item, @@ -67,11 +65,21 @@ pub enum ModuleDef { Function(Function), Struct(Struct), Enum(Enum), - // Can't be directly declared, but can be imported. EnumVariant(EnumVariant), + Const(Const), + Static(Static), + // Can't be directly declared, but can be imported. Def(DefId), } -impl_froms!(ModuleDef: Module, Function, Struct, Enum, EnumVariant); +impl_froms!( + ModuleDef: Module, + Function, + Struct, + Enum, + EnumVariant, + Const, + Static +); impl From for ModuleDef { fn from(it: DefId) -> ModuleDef { @@ -386,18 +394,14 @@ impl Docs for Function { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Const { - pub(crate) def_id: DefId, + pub(crate) id: ConstId, } impl Const { - pub(crate) fn new(def_id: DefId) -> Const { - Const { def_id } - } - pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc) { - def_id_to_ast(db, self.def_id) + self.id.source(db) } } @@ -407,18 +411,14 @@ impl Docs for Const { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Static { - pub(crate) def_id: DefId, + pub(crate) id: StaticId, } impl Static { - pub(crate) fn new(def_id: DefId) -> Static { - Static { def_id } - } - pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc) { - def_id_to_ast(db, self.def_id) + self.id.source(db) } } diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs index aa5e5d6895..1518825c71 100644 --- a/crates/ra_hir/src/code_model_impl/module.rs +++ b/crates/ra_hir/src/code_model_impl/module.rs @@ -147,7 +147,11 @@ impl Module { None => PerNs::none(), } } - ModuleDef::Function(_) | ModuleDef::Struct(_) | ModuleDef::EnumVariant(_) => { + ModuleDef::Function(_) + | ModuleDef::Struct(_) + | ModuleDef::Const(_) + | ModuleDef::Static(_) + | ModuleDef::EnumVariant(_) => { // could be an inherent method call in UFCS form // (`Struct::method`), or some other kind of associated // item... Which we currently don't handle (TODO) diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 4b4e07e587..9aae58bb63 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs @@ -9,7 +9,7 @@ use ra_arena::{Arena, RawId, ArenaId, impl_arena_id}; use crate::{ HirDatabase, Def, - Module, Trait, Type, Static, Const, + Module, Trait, Type, }; #[derive(Debug, Default)] @@ -20,6 +20,8 @@ pub struct HirInterner { structs: LocationIntener, StructId>, enums: LocationIntener, EnumId>, enum_variants: LocationIntener, EnumVariantId>, + consts: LocationIntener, ConstId>, + statics: LocationIntener, StaticId>, } impl HirInterner { @@ -246,6 +248,24 @@ impl AstItemDef for EnumVariantId { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct ConstId(RawId); +impl_arena_id!(ConstId); +impl AstItemDef for ConstId { + fn interner(interner: &HirInterner) -> &LocationIntener, Self> { + &interner.consts + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct StaticId(RawId); +impl_arena_id!(StaticId); +impl AstItemDef for StaticId { + fn interner(interner: &HirInterner) -> &LocationIntener, Self> { + &interner.statics + } +} + /// Def's are a core concept of hir. A `Def` is an Item (function, module, etc) /// in a specific module. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -261,8 +281,6 @@ pub struct DefLoc { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub(crate) enum DefKind { - Const, - Static, Trait, Type, Item, @@ -286,14 +304,6 @@ impl DefId { pub fn resolve(self, db: &impl HirDatabase) -> Def { let loc = self.loc(db); match loc.kind { - DefKind::Const => { - let def = Const::new(self); - Def::Const(def) - } - DefKind::Static => { - let def = Static::new(self); - Def::Static(def) - } DefKind::Trait => { let def = Trait::new(self); Def::Trait(def) diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs index 0056bdd5a1..6a86e5fd4f 100644 --- a/crates/ra_hir/src/nameres/lower.rs +++ b/crates/ra_hir/src/nameres/lower.rs @@ -10,7 +10,7 @@ use rustc_hash::FxHashMap; use crate::{ SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems, HirFileId, MacroCallLoc, AsName, PerNs, DefKind, DefLoc, Function, - ModuleDef, Module, Struct, Enum, + ModuleDef, Module, Struct, Enum, Const, Static, ids::LocationCtx, }; @@ -187,8 +187,22 @@ impl LoweredModule { // TODO return; } - ast::ModuleItemKind::ConstDef(it) => it.name(), - ast::ModuleItemKind::StaticDef(it) => it.name(), + ast::ModuleItemKind::ConstDef(it) => { + if let Some(name) = it.name() { + let c = Const { id: ctx.to_def(it) }; + self.declarations + .insert(name.as_name(), PerNs::values(c.into())); + } + return; + } + ast::ModuleItemKind::StaticDef(it) => { + if let Some(name) = it.name() { + let s = Static { id: ctx.to_def(it) }; + self.declarations + .insert(name.as_name(), PerNs::values(s.into())); + } + return; + } ast::ModuleItemKind::Module(_) => { // modules are handled separately direclty by nameres return; @@ -246,8 +260,8 @@ impl DefKind { SyntaxKind::ENUM_DEF => unreachable!(), SyntaxKind::TRAIT_DEF => PerNs::types(DefKind::Trait), SyntaxKind::TYPE_DEF => PerNs::types(DefKind::Type), - SyntaxKind::CONST_DEF => PerNs::values(DefKind::Const), - SyntaxKind::STATIC_DEF => PerNs::values(DefKind::Static), + SyntaxKind::CONST_DEF => unreachable!(), + SyntaxKind::STATIC_DEF => unreachable!(), _ => PerNs::none(), } } diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 9a1a90eed8..6d61500967 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -693,7 +693,10 @@ impl From for Option { ModuleDef::Struct(s) => s.into(), ModuleDef::Enum(e) => e.into(), ModuleDef::EnumVariant(v) => v.into(), - ModuleDef::Def(_) | ModuleDef::Module(_) => return None, + ModuleDef::Const(_) + | ModuleDef::Static(_) + | ModuleDef::Def(_) + | ModuleDef::Module(_) => return None, }; Some(res) } diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index 4768efdc19..bd54845166 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs @@ -43,6 +43,8 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { hir::ModuleDef::Function(_) | hir::ModuleDef::Struct(_) | hir::ModuleDef::Def(_) + | hir::ModuleDef::Const(_) + | hir::ModuleDef::Static(_) | hir::ModuleDef::EnumVariant(_) => return, }; } diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs index ee1f8bce06..2f8ec41d27 100644 --- a/crates/ra_ide_api/src/completion/completion_item.rs +++ b/crates/ra_ide_api/src/completion/completion_item.rs @@ -223,11 +223,11 @@ impl Builder { hir::ModuleDef::Struct(it) => (CompletionItemKind::Struct, it.docs(ctx.db)), hir::ModuleDef::Enum(it) => (CompletionItemKind::Enum, it.docs(ctx.db)), hir::ModuleDef::EnumVariant(it) => (CompletionItemKind::EnumVariant, it.docs(ctx.db)), + hir::ModuleDef::Const(it) => (CompletionItemKind::Const, it.docs(ctx.db)), + hir::ModuleDef::Static(it) => (CompletionItemKind::Static, it.docs(ctx.db)), hir::ModuleDef::Def(def_id) => match def_id.resolve(ctx.db) { hir::Def::Trait(it) => (CompletionItemKind::Trait, it.docs(ctx.db)), hir::Def::Type(it) => (CompletionItemKind::TypeAlias, it.docs(ctx.db)), - hir::Def::Const(it) => (CompletionItemKind::Const, it.docs(ctx.db)), - hir::Def::Static(it) => (CompletionItemKind::Static, it.docs(ctx.db)), _ => return self, }, }; diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs index fc76338d22..8406fee31c 100644 --- a/crates/ra_ide_api/src/navigation_target.rs +++ b/crates/ra_ide_api/src/navigation_target.rs @@ -121,6 +121,20 @@ impl NavigationTarget { &*node, )); } + hir::ModuleDef::Const(s) => { + let (file_id, node) = s.source(db); + return Some(NavigationTarget::from_named( + file_id.original_file(db), + &*node, + )); + } + hir::ModuleDef::Static(s) => { + let (file_id, node) = s.source(db); + return Some(NavigationTarget::from_named( + file_id.original_file(db), + &*node, + )); + } hir::ModuleDef::Enum(e) => { let (file_id, node) = e.source(db); return Some(NavigationTarget::from_named( @@ -146,14 +160,6 @@ impl NavigationTarget { let (file_id, node) = f.source(db); NavigationTarget::from_named(file_id.original_file(db), &*node) } - Def::Static(f) => { - let (file_id, node) = f.source(db); - NavigationTarget::from_named(file_id.original_file(db), &*node) - } - Def::Const(f) => { - let (file_id, node) = f.source(db); - NavigationTarget::from_named(file_id.original_file(db), &*node) - } Def::Item => return None, }; Some(res) From 00ba70a0957b8af2813940787238a733298dfa5f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 25 Jan 2019 01:05:50 +0300 Subject: [PATCH 21/26] generalize --- crates/ra_hir/src/ids.rs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 9aae58bb63..2cc175bdae 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs @@ -1,6 +1,6 @@ use std::{ marker::PhantomData, - hash::Hash, + hash::{Hash, Hasher}, }; use ra_db::{LocationIntener, FileId}; @@ -139,13 +139,26 @@ impl MacroCallLoc { } } -#[derive(Debug, PartialEq, Eq, Hash)] +#[derive(Debug)] pub struct ItemLoc { pub(crate) module: Module, raw: SourceItemId, _ty: PhantomData, } +impl PartialEq for ItemLoc { + fn eq(&self, other: &Self) -> bool { + self.module == other.module && self.raw == other.raw + } +} +impl Eq for ItemLoc {} +impl Hash for ItemLoc { + fn hash(&self, hasher: &mut H) { + self.module.hash(hasher); + self.raw.hash(hasher); + } +} + impl Clone for ItemLoc { fn clone(&self) -> ItemLoc { ItemLoc { @@ -173,14 +186,14 @@ impl<'a, DB: HirDatabase> LocationCtx<&'a DB> { } pub(crate) fn to_def(self, ast: &N) -> DEF where - N: AstNode + Eq + Hash, + N: AstNode, DEF: AstItemDef, { DEF::from_ast(self, ast) } } -pub(crate) trait AstItemDef: ArenaId + Clone { +pub(crate) trait AstItemDef: ArenaId + Clone { fn interner(interner: &HirInterner) -> &LocationIntener, Self>; fn from_ast(ctx: LocationCtx<&impl HirDatabase>, ast: &N) -> Self { let items = ctx.db.file_items(ctx.file_id); From 0f2f3a21e7e624f920d182869896347af309e909 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 25 Jan 2019 01:31:32 +0300 Subject: [PATCH 22/26] Migrate trait & type to new ids --- crates/ra_hir/src/code_model_api.rs | 35 +++----- crates/ra_hir/src/code_model_impl.rs | 15 ---- crates/ra_hir/src/code_model_impl/module.rs | 7 +- crates/ra_hir/src/generics.rs | 23 ++--- crates/ra_hir/src/ids.rs | 38 +++++---- crates/ra_hir/src/nameres/lower.rs | 85 +++++-------------- crates/ra_hir/src/source_binder.rs | 4 +- crates/ra_hir/src/ty.rs | 4 +- .../src/completion/complete_path.rs | 7 +- .../src/completion/completion_item.rs | 8 +- crates/ra_ide_api/src/navigation_target.rs | 59 ++++++------- crates/ra_syntax/src/ast/generated.rs | 1 + crates/ra_syntax/src/grammar.ron | 4 +- 13 files changed, 104 insertions(+), 186 deletions(-) diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index d82dda79a7..e2979617da 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -13,10 +13,9 @@ use crate::{ ty::{InferenceResult, VariantDef}, adt::VariantData, generics::GenericParams, - code_model_impl::def_id_to_ast, docs::{Documentation, Docs, docs_from_ast}, module_tree::ModuleId, - ids::{FunctionId, StructId, EnumId, EnumVariantId, AstItemDef, ConstId, StaticId}, + ids::{FunctionId, StructId, EnumId, EnumVariantId, AstItemDef, ConstId, StaticId, TraitId, TypeId}, }; /// hir::Crate describes a single crate. It's the main interface with which @@ -47,8 +46,6 @@ impl Crate { #[derive(Debug)] pub enum Def { - Trait(Trait), - Type(Type), Item, } @@ -68,6 +65,8 @@ pub enum ModuleDef { EnumVariant(EnumVariant), Const(Const), Static(Static), + Trait(Trait), + Type(Type), // Can't be directly declared, but can be imported. Def(DefId), } @@ -78,7 +77,9 @@ impl_froms!( Enum, EnumVariant, Const, - Static + Static, + Trait, + Type ); impl From for ModuleDef { @@ -428,22 +429,18 @@ impl Docs for Static { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Trait { - pub(crate) def_id: DefId, + pub(crate) id: TraitId, } impl Trait { - pub(crate) fn new(def_id: DefId) -> Trait { - Trait { def_id } - } - pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc) { - def_id_to_ast(db, self.def_id) + self.id.source(db) } pub fn generic_params(&self, db: &impl HirDatabase) -> Arc { - db.generic_params(self.def_id.into()) + db.generic_params((*self).into()) } } @@ -453,22 +450,18 @@ impl Docs for Trait { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Type { - pub(crate) def_id: DefId, + pub(crate) id: TypeId, } impl Type { - pub(crate) fn new(def_id: DefId) -> Type { - Type { def_id } - } - pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc) { - def_id_to_ast(db, self.def_id) + self.id.source(db) } pub fn generic_params(&self, db: &impl HirDatabase) -> Arc { - db.generic_params(self.def_id.into()) + db.generic_params((*self).into()) } } diff --git a/crates/ra_hir/src/code_model_impl.rs b/crates/ra_hir/src/code_model_impl.rs index 0cea9f7b6f..1f28fab748 100644 --- a/crates/ra_hir/src/code_model_impl.rs +++ b/crates/ra_hir/src/code_model_impl.rs @@ -1,18 +1,3 @@ mod krate; // `crate` is invalid ident :( mod module; pub(crate) mod function; - -use ra_syntax::{AstNode, TreeArc}; - -use crate::{HirDatabase, DefId, HirFileId}; - -pub(crate) fn def_id_to_ast( - db: &impl HirDatabase, - def_id: DefId, -) -> (HirFileId, TreeArc) { - let (file_id, syntax) = def_id.source(db); - let ast = N::cast(&syntax) - .unwrap_or_else(|| panic!("def points to wrong source {:?} {:?}", def_id, syntax)) - .to_owned(); - (file_id, ast) -} diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs index 1518825c71..6419d3934c 100644 --- a/crates/ra_hir/src/code_model_impl/module.rs +++ b/crates/ra_hir/src/code_model_impl/module.rs @@ -147,17 +147,12 @@ impl Module { None => PerNs::none(), } } - ModuleDef::Function(_) - | ModuleDef::Struct(_) - | ModuleDef::Const(_) - | ModuleDef::Static(_) - | ModuleDef::EnumVariant(_) => { + _ => { // could be an inherent method call in UFCS form // (`Struct::method`), or some other kind of associated // item... Which we currently don't handle (TODO) PerNs::none() } - ModuleDef::Def(_) => PerNs::none(), }; } curr_per_ns diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index a8cacbb4ad..64c20a4622 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs @@ -5,9 +5,9 @@ use std::sync::Arc; -use ra_syntax::ast::{self, AstNode, NameOwner, TypeParamsOwner}; +use ra_syntax::ast::{self, NameOwner, TypeParamsOwner}; -use crate::{db::HirDatabase, DefId, Name, AsName, Function, Struct, Enum}; +use crate::{db::HirDatabase, Name, AsName, Function, Struct, Enum, Trait, Type}; /// Data about a generic parameter (to a function, struct, impl, ...). #[derive(Clone, PartialEq, Eq, Debug)] @@ -27,15 +27,10 @@ pub enum GenericDef { Function(Function), Struct(Struct), Enum(Enum), - Def(DefId), -} -impl_froms!(GenericDef: Function, Struct, Enum); - -impl From for GenericDef { - fn from(def_id: DefId) -> GenericDef { - GenericDef::Def(def_id) - } + Trait(Trait), + Type(Type), } +impl_froms!(GenericDef: Function, Struct, Enum, Trait, Type); impl GenericParams { pub(crate) fn generic_params_query( @@ -47,12 +42,8 @@ impl GenericParams { GenericDef::Function(it) => generics.fill(&*it.source(db).1), GenericDef::Struct(it) => generics.fill(&*it.source(db).1), GenericDef::Enum(it) => generics.fill(&*it.source(db).1), - GenericDef::Def(def_id) => { - let (_file_id, node) = def_id.source(db); - if let Some(type_param_list) = node.children().find_map(ast::TypeParamList::cast) { - generics.fill_params(type_param_list) - } - } + GenericDef::Trait(it) => generics.fill(&*it.source(db).1), + GenericDef::Type(it) => generics.fill(&*it.source(db).1), } Arc::new(generics) diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 2cc175bdae..311c0b98a0 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs @@ -9,7 +9,7 @@ use ra_arena::{Arena, RawId, ArenaId, impl_arena_id}; use crate::{ HirDatabase, Def, - Module, Trait, Type, + Module, }; #[derive(Debug, Default)] @@ -22,6 +22,8 @@ pub struct HirInterner { enum_variants: LocationIntener, EnumVariantId>, consts: LocationIntener, ConstId>, statics: LocationIntener, StaticId>, + traits: LocationIntener, TraitId>, + types: LocationIntener, TypeId>, } impl HirInterner { @@ -279,6 +281,24 @@ impl AstItemDef for StaticId { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct TraitId(RawId); +impl_arena_id!(TraitId); +impl AstItemDef for TraitId { + fn interner(interner: &HirInterner) -> &LocationIntener, Self> { + &interner.traits + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct TypeId(RawId); +impl_arena_id!(TypeId); +impl AstItemDef for TypeId { + fn interner(interner: &HirInterner) -> &LocationIntener, Self> { + &interner.types + } +} + /// Def's are a core concept of hir. A `Def` is an Item (function, module, etc) /// in a specific module. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -294,8 +314,6 @@ pub struct DefLoc { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub(crate) enum DefKind { - Trait, - Type, Item, // /// The constructor of a struct. E.g. if we have `struct Foo(usize)`, the // /// name `Foo` needs to resolve to different types depending on whether we @@ -317,23 +335,9 @@ impl DefId { pub fn resolve(self, db: &impl HirDatabase) -> Def { let loc = self.loc(db); match loc.kind { - DefKind::Trait => { - let def = Trait::new(self); - Def::Trait(def) - } - DefKind::Type => { - let def = Type::new(self); - Def::Type(def) - } DefKind::Item => Def::Item, } } - - pub(crate) fn source(self, db: &impl HirDatabase) -> (HirFileId, TreeArc) { - let loc = self.loc(db); - let syntax = db.file_item(loc.source_item_id); - (loc.source_item_id.file_id, syntax) - } } impl DefLoc { diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs index 6a86e5fd4f..b4fe99ea70 100644 --- a/crates/ra_hir/src/nameres/lower.rs +++ b/crates/ra_hir/src/nameres/lower.rs @@ -1,16 +1,16 @@ use std::sync::Arc; use ra_syntax::{ - SyntaxKind, AstNode, SourceFile, TreeArc, AstPtr, + AstNode, SourceFile, TreeArc, AstPtr, ast::{self, ModuleItemOwner, NameOwner}, }; use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; use rustc_hash::FxHashMap; use crate::{ - SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems, - HirFileId, MacroCallLoc, AsName, PerNs, DefKind, DefLoc, Function, - ModuleDef, Module, Struct, Enum, Const, Static, + SourceItemId, Path, ModuleSource, HirDatabase, Name, + HirFileId, MacroCallLoc, AsName, PerNs, Function, + ModuleDef, Module, Struct, Enum, Const, Static, Trait, Type, ids::LocationCtx, }; @@ -115,7 +115,7 @@ impl LoweredModule { for item in items { match item { ast::ItemOrMacro::Item(it) => { - self.add_def_id(source_map, db, module, file_id, &file_items, it); + self.add_def_id(source_map, db, module, file_id, it); } ast::ItemOrMacro::Macro(macro_call) => { let item_id = file_items.id_of_unchecked(macro_call.syntax()); @@ -128,10 +128,9 @@ impl LoweredModule { }; let id = loc.id(db); let file_id = HirFileId::from(id); - let file_items = db.file_items(file_id); //FIXME: expand recursively for item in db.hir_source_file(file_id).items() { - self.add_def_id(source_map, db, module, file_id, &file_items, item); + self.add_def_id(source_map, db, module, file_id, item); } } } @@ -144,18 +143,16 @@ impl LoweredModule { db: &impl HirDatabase, module: Module, file_id: HirFileId, - file_items: &SourceFileItems, item: &ast::ModuleItem, ) { let ctx = LocationCtx::new(db, module, file_id); - let name = match item.kind() { + match item.kind() { ast::ModuleItemKind::StructDef(it) => { if let Some(name) = it.name() { let s = Struct { id: ctx.to_def(it) }; let s: ModuleDef = s.into(); self.declarations.insert(name.as_name(), PerNs::both(s, s)); } - return; } ast::ModuleItemKind::EnumDef(it) => { if let Some(name) = it.name() { @@ -163,7 +160,6 @@ impl LoweredModule { let e: ModuleDef = e.into(); self.declarations.insert(name.as_name(), PerNs::types(e)); } - return; } ast::ModuleItemKind::FnDef(it) => { if let Some(name) = it.name() { @@ -171,21 +167,29 @@ impl LoweredModule { self.declarations .insert(name.as_name(), PerNs::values(func.into())); } - return; } - ast::ModuleItemKind::TraitDef(it) => it.name(), - ast::ModuleItemKind::TypeDef(it) => it.name(), + ast::ModuleItemKind::TraitDef(it) => { + if let Some(name) = it.name() { + let t = Trait { id: ctx.to_def(it) }; + self.declarations + .insert(name.as_name(), PerNs::types(t.into())); + } + } + ast::ModuleItemKind::TypeDef(it) => { + if let Some(name) = it.name() { + let t = Type { id: ctx.to_def(it) }; + self.declarations + .insert(name.as_name(), PerNs::types(t.into())); + } + } ast::ModuleItemKind::ImplBlock(_) => { // impls don't define items - return; } ast::ModuleItemKind::UseItem(it) => { self.add_use_item(source_map, it); - return; } ast::ModuleItemKind::ExternCrateItem(_) => { // TODO - return; } ast::ModuleItemKind::ConstDef(it) => { if let Some(name) = it.name() { @@ -193,7 +197,6 @@ impl LoweredModule { self.declarations .insert(name.as_name(), PerNs::values(c.into())); } - return; } ast::ModuleItemKind::StaticDef(it) => { if let Some(name) = it.name() { @@ -201,17 +204,11 @@ impl LoweredModule { self.declarations .insert(name.as_name(), PerNs::values(s.into())); } - return; } ast::ModuleItemKind::Module(_) => { // modules are handled separately direclty by nameres - return; } }; - if let Some(name) = name { - let def_id = assign_def_id(db, module, file_id, file_items, item); - self.declarations.insert(name.as_name(), def_id); - } } fn add_use_item(&mut self, source_map: &mut ImportSourceMap, item: &ast::UseItem) { @@ -226,43 +223,3 @@ impl LoweredModule { }) } } - -fn assign_def_id( - db: &impl HirDatabase, - module: Module, - file_id: HirFileId, - file_items: &SourceFileItems, - item: &ast::ModuleItem, -) -> PerNs { - // depending on the item kind, the location can define something in - // the values namespace, the types namespace, or both - let kind = DefKind::for_syntax_kind(item.syntax().kind()); - let def_id = kind.map(|k| { - let item_id = file_items.id_of_unchecked(item.syntax()); - let def_loc = DefLoc { - kind: k, - module, - source_item_id: SourceItemId { - file_id, - item_id: Some(item_id), - }, - }; - def_loc.id(db).into() - }); - def_id -} - -impl DefKind { - fn for_syntax_kind(kind: SyntaxKind) -> PerNs { - match kind { - SyntaxKind::FN_DEF => unreachable!(), - SyntaxKind::STRUCT_DEF => unreachable!(), - SyntaxKind::ENUM_DEF => unreachable!(), - SyntaxKind::TRAIT_DEF => PerNs::types(DefKind::Trait), - SyntaxKind::TYPE_DEF => PerNs::types(DefKind::Type), - SyntaxKind::CONST_DEF => unreachable!(), - SyntaxKind::STATIC_DEF => unreachable!(), - _ => PerNs::none(), - } - } -} diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index ea81858535..dbe040805e 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -145,10 +145,10 @@ pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, Te .iter() .filter_map(|(_, it)| it.clone().take_types()) .filter_map(|it| match it { - ModuleDef::Def(it) => Some(it), + ModuleDef::Trait(it) => Some(it), _ => None, }) - .filter_map(|it| it.loc(db).source_item_id.file_id.as_macro_call_id()) + .filter_map(|it| it.source(db).0.as_macro_call_id()) { if let Some(exp) = db.expand_macro_invocation(macro_call_id) { let loc = macro_call_id.loc(db); diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 6d61500967..3801e498e0 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -696,7 +696,9 @@ impl From for Option { ModuleDef::Const(_) | ModuleDef::Static(_) | ModuleDef::Def(_) - | ModuleDef::Module(_) => return None, + | ModuleDef::Module(_) + | ModuleDef::Trait(_) + | ModuleDef::Type(_) => return None, }; Some(res) } diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index bd54845166..e72586e2e5 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs @@ -40,12 +40,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { .add_to(acc) }); } - hir::ModuleDef::Function(_) - | hir::ModuleDef::Struct(_) - | hir::ModuleDef::Def(_) - | hir::ModuleDef::Const(_) - | hir::ModuleDef::Static(_) - | hir::ModuleDef::EnumVariant(_) => return, + _ => return, }; } diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs index 2f8ec41d27..4e679281c5 100644 --- a/crates/ra_ide_api/src/completion/completion_item.rs +++ b/crates/ra_ide_api/src/completion/completion_item.rs @@ -225,11 +225,9 @@ impl Builder { hir::ModuleDef::EnumVariant(it) => (CompletionItemKind::EnumVariant, it.docs(ctx.db)), hir::ModuleDef::Const(it) => (CompletionItemKind::Const, it.docs(ctx.db)), hir::ModuleDef::Static(it) => (CompletionItemKind::Static, it.docs(ctx.db)), - hir::ModuleDef::Def(def_id) => match def_id.resolve(ctx.db) { - hir::Def::Trait(it) => (CompletionItemKind::Trait, it.docs(ctx.db)), - hir::Def::Type(it) => (CompletionItemKind::TypeAlias, it.docs(ctx.db)), - _ => return self, - }, + hir::ModuleDef::Trait(it) => (CompletionItemKind::Trait, it.docs(ctx.db)), + hir::ModuleDef::Type(it) => (CompletionItemKind::TypeAlias, it.docs(ctx.db)), + hir::ModuleDef::Def(_) => return self, }; self.kind = Some(kind); self.documentation = docs; diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs index 8406fee31c..2e11d2de3a 100644 --- a/crates/ra_ide_api/src/navigation_target.rs +++ b/crates/ra_ide_api/src/navigation_target.rs @@ -3,7 +3,7 @@ use ra_syntax::{ SyntaxNode, AstNode, SmolStr, TextRange, ast, SyntaxKind::{self, NAME}, }; -use hir::{Def, ModuleSource}; +use hir::{ModuleSource}; use crate::{FileSymbol, db::RootDatabase}; @@ -106,63 +106,60 @@ impl NavigationTarget { db: &RootDatabase, module_def: hir::ModuleDef, ) -> Option { - let def = match module_def { - hir::ModuleDef::Def(def_id) => def_id.resolve(db), - hir::ModuleDef::Module(module) => { - return Some(NavigationTarget::from_module(db, module)); - } - hir::ModuleDef::Function(func) => { - return Some(NavigationTarget::from_function(db, func)); - } + match module_def { + hir::ModuleDef::Def(_) => return None, + hir::ModuleDef::Module(module) => Some(NavigationTarget::from_module(db, module)), + hir::ModuleDef::Function(func) => Some(NavigationTarget::from_function(db, func)), hir::ModuleDef::Struct(s) => { let (file_id, node) = s.source(db); - return Some(NavigationTarget::from_named( + Some(NavigationTarget::from_named( file_id.original_file(db), &*node, - )); + )) } hir::ModuleDef::Const(s) => { let (file_id, node) = s.source(db); - return Some(NavigationTarget::from_named( + Some(NavigationTarget::from_named( file_id.original_file(db), &*node, - )); + )) } hir::ModuleDef::Static(s) => { let (file_id, node) = s.source(db); - return Some(NavigationTarget::from_named( + Some(NavigationTarget::from_named( file_id.original_file(db), &*node, - )); + )) } hir::ModuleDef::Enum(e) => { let (file_id, node) = e.source(db); - return Some(NavigationTarget::from_named( + Some(NavigationTarget::from_named( file_id.original_file(db), &*node, - )); + )) } hir::ModuleDef::EnumVariant(var) => { let (file_id, node) = var.source(db); - return Some(NavigationTarget::from_named( + Some(NavigationTarget::from_named( file_id.original_file(db), &*node, - )); + )) } - }; - - let res = match def { - Def::Trait(f) => { - let (file_id, node) = f.source(db); - NavigationTarget::from_named(file_id.original_file(db), &*node) + hir::ModuleDef::Trait(e) => { + let (file_id, node) = e.source(db); + Some(NavigationTarget::from_named( + file_id.original_file(db), + &*node, + )) } - Def::Type(f) => { - let (file_id, node) = f.source(db); - NavigationTarget::from_named(file_id.original_file(db), &*node) + hir::ModuleDef::Type(e) => { + let (file_id, node) = e.source(db); + Some(NavigationTarget::from_named( + file_id.original_file(db), + &*node, + )) } - Def::Item => return None, - }; - Some(res) + } } #[cfg(test)] diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index ac6c8a8359..a207f8429f 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs @@ -3229,6 +3229,7 @@ impl ast::VisibilityOwner for TraitDef {} impl ast::NameOwner for TraitDef {} impl ast::AttrsOwner for TraitDef {} impl ast::DocCommentsOwner for TraitDef {} +impl ast::TypeParamsOwner for TraitDef {} impl TraitDef {} // TrueKw diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index c5297e46dd..dedefea591 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron @@ -280,7 +280,7 @@ Grammar( ], options: [["variant_list", "EnumVariantList"]] ), "EnumVariantList": ( collections: [["variants", "EnumVariant"]] ), "EnumVariant": ( traits: ["NameOwner", "DocCommentsOwner"], options: ["Expr"] ), - "TraitDef": ( traits: ["VisibilityOwner", "NameOwner", "AttrsOwner", "DocCommentsOwner"] ), + "TraitDef": ( traits: ["VisibilityOwner", "NameOwner", "AttrsOwner", "DocCommentsOwner", "TypeParamsOwner"] ), "Module": ( traits: ["VisibilityOwner", "NameOwner", "AttrsOwner", "DocCommentsOwner" ], options: [ "ItemList" ] @@ -489,7 +489,7 @@ Grammar( ), "RefPat": ( options: [ "Pat" ]), - "BindPat": ( + "BindPat": ( options: [ "Pat" ], traits: ["NameOwner"] ), From ff9c5bef7b198cde4358610c565cd0b6dc466de5 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 25 Jan 2019 01:32:47 +0300 Subject: [PATCH 23/26] ModuleDef is Def-free --- crates/ra_hir/src/code_model_api.rs | 11 ++--------- crates/ra_hir/src/ty.rs | 1 - crates/ra_ide_api/src/completion/completion_item.rs | 1 - crates/ra_ide_api/src/navigation_target.rs | 1 - 4 files changed, 2 insertions(+), 12 deletions(-) diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index e2979617da..6739627b4e 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -5,7 +5,7 @@ use ra_db::{CrateId, FileId}; use ra_syntax::{ast::self, TreeArc, SyntaxNode}; use crate::{ - Name, DefId, Path, PerNs, ScopesWithSyntaxMapping, Ty, HirFileId, + Name, Path, PerNs, ScopesWithSyntaxMapping, Ty, HirFileId, type_ref::TypeRef, nameres::{ModuleScope, lower::ImportId}, db::HirDatabase, @@ -62,13 +62,12 @@ pub enum ModuleDef { Function(Function), Struct(Struct), Enum(Enum), + // Can't be directly declared, but can be imported. EnumVariant(EnumVariant), Const(Const), Static(Static), Trait(Trait), Type(Type), - // Can't be directly declared, but can be imported. - Def(DefId), } impl_froms!( ModuleDef: Module, @@ -82,12 +81,6 @@ impl_froms!( Type ); -impl From for ModuleDef { - fn from(it: DefId) -> ModuleDef { - ModuleDef::Def(it) - } -} - pub enum ModuleSource { SourceFile(TreeArc), Module(TreeArc), diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 3801e498e0..1d5624f8fc 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -695,7 +695,6 @@ impl From for Option { ModuleDef::EnumVariant(v) => v.into(), ModuleDef::Const(_) | ModuleDef::Static(_) - | ModuleDef::Def(_) | ModuleDef::Module(_) | ModuleDef::Trait(_) | ModuleDef::Type(_) => return None, diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs index 4e679281c5..3ba6c33ee6 100644 --- a/crates/ra_ide_api/src/completion/completion_item.rs +++ b/crates/ra_ide_api/src/completion/completion_item.rs @@ -227,7 +227,6 @@ impl Builder { hir::ModuleDef::Static(it) => (CompletionItemKind::Static, it.docs(ctx.db)), hir::ModuleDef::Trait(it) => (CompletionItemKind::Trait, it.docs(ctx.db)), hir::ModuleDef::Type(it) => (CompletionItemKind::TypeAlias, it.docs(ctx.db)), - hir::ModuleDef::Def(_) => return self, }; self.kind = Some(kind); self.documentation = docs; diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs index 2e11d2de3a..c5be8e01be 100644 --- a/crates/ra_ide_api/src/navigation_target.rs +++ b/crates/ra_ide_api/src/navigation_target.rs @@ -107,7 +107,6 @@ impl NavigationTarget { module_def: hir::ModuleDef, ) -> Option { match module_def { - hir::ModuleDef::Def(_) => return None, hir::ModuleDef::Module(module) => Some(NavigationTarget::from_module(db, module)), hir::ModuleDef::Function(func) => Some(NavigationTarget::from_function(db, func)), hir::ModuleDef::Struct(s) => { From 1ccf73c836d8a70d6f04b621bd6461f133669131 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 25 Jan 2019 01:38:21 +0300 Subject: [PATCH 24/26] kill DefKindc --- crates/ra_hir/src/ids.rs | 24 ++---------------- crates/ra_hir/src/impl_block.rs | 44 +++++++++------------------------ crates/ra_hir/src/lib.rs | 2 +- 3 files changed, 15 insertions(+), 55 deletions(-) diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 311c0b98a0..cbe31f8306 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs @@ -313,19 +313,7 @@ pub struct DefLoc { } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub(crate) enum DefKind { - Item, - // /// The constructor of a struct. E.g. if we have `struct Foo(usize)`, the - // /// name `Foo` needs to resolve to different types depending on whether we - // /// are in the types or values namespace: As a type, `Foo` of course refers - // /// to the struct `Foo`; as a value, `Foo` is a callable type with signature - // /// `(usize) -> Foo`. The cleanest approach to handle this seems to be to - // /// have different defs in the two namespaces. - // /// - // /// rustc does the same; note that it even creates a struct constructor if - // /// the struct isn't a tuple struct (see `CtorKind::Fictive` in rustc). - // StructCtor, -} +pub(crate) enum DefKind {} impl DefId { pub(crate) fn loc(self, db: &impl AsRef) -> DefLoc { @@ -334,15 +322,7 @@ impl DefId { pub fn resolve(self, db: &impl HirDatabase) -> Def { let loc = self.loc(db); - match loc.kind { - DefKind::Item => Def::Item, - } - } -} - -impl DefLoc { - pub(crate) fn id(&self, db: &impl AsRef) -> DefId { - db.as_ref().defs.loc2id(&self) + match loc.kind {} } } diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index 3df0d3a3b8..222e473491 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs @@ -5,7 +5,7 @@ use ra_arena::{Arena, RawId, impl_arena_id}; use ra_syntax::ast::{self, AstNode}; use crate::{ - DefId, DefLoc, DefKind, SourceItemId, SourceFileItems, + Const, Type, Function, HirFileId, db::HirDatabase, type_ref::TypeRef, @@ -67,7 +67,6 @@ impl ImplData { pub(crate) fn from_ast( db: &impl HirDatabase, file_id: HirFileId, - file_items: &SourceFileItems, module: Module, node: &ast::ImplBlock, ) -> Self { @@ -77,30 +76,14 @@ impl ImplData { let items = if let Some(item_list) = node.item_list() { item_list .impl_items() - .map(|item_node| { - let kind = match item_node.kind() { - ast::ImplItemKind::FnDef(it) => { - return ImplItem::Method(Function { id: ctx.to_def(it) }); - } - ast::ImplItemKind::ConstDef(..) => DefKind::Item, - ast::ImplItemKind::TypeDef(..) => DefKind::Item, - }; - let item_id = file_items.id_of_unchecked(item_node.syntax()); - let source_item_id = SourceItemId { - file_id, - item_id: Some(item_id), - }; - let def_loc = DefLoc { - module, - kind, - source_item_id, - }; - let def_id = def_loc.id(db); - match item_node.kind() { - ast::ImplItemKind::FnDef(_) => unreachable!(), - ast::ImplItemKind::ConstDef(..) => ImplItem::Const(def_id), - ast::ImplItemKind::TypeDef(..) => ImplItem::Type(def_id), + .map(|item_node| match item_node.kind() { + ast::ImplItemKind::FnDef(it) => { + ImplItem::Method(Function { id: ctx.to_def(it) }) } + ast::ImplItemKind::ConstDef(it) => { + ImplItem::Const(Const { id: ctx.to_def(it) }) + } + ast::ImplItemKind::TypeDef(it) => ImplItem::Type(Type { id: ctx.to_def(it) }), }) .collect() } else { @@ -130,11 +113,11 @@ impl ImplData { //TODO: rename to ImplDef? pub enum ImplItem { Method(Function), - // these don't have their own types yet - Const(DefId), - Type(DefId), + Const(Const), + Type(Type), // Existential } +impl_froms!(ImplItem: Const, Type); impl From for ImplItem { fn from(func: Function) -> ImplItem { @@ -176,11 +159,8 @@ impl ModuleImplBlocks { .syntax(), }; - let source_file_items = db.file_items(file_id); - for impl_block_ast in node.children().filter_map(ast::ImplBlock::cast) { - let impl_block = - ImplData::from_ast(db, file_id, &source_file_items, module, impl_block_ast); + let impl_block = ImplData::from_ast(db, file_id, module, impl_block_ast); let id = self.impls.alloc(impl_block); for &impl_item in &self.impls[id].items { self.impls_by_def.insert(impl_item, id); diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 33438509c7..6cbece95e7 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -46,7 +46,7 @@ mod marks; use crate::{ db::HirDatabase, name::{AsName, KnownName}, - ids::{DefKind, SourceItemId, SourceFileItems}, + ids::{SourceItemId, SourceFileItems}, }; pub use self::{ From a03c109f50a01d646cd2e63c190b0bb08760dcd8 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 25 Jan 2019 01:41:36 +0300 Subject: [PATCH 25/26] Kill DefId --- crates/ra_hir/src/ids.rs | 40 ++++++++++------------------------------ crates/ra_hir/src/lib.rs | 2 +- 2 files changed, 11 insertions(+), 31 deletions(-) diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index cbe31f8306..b125a15184 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs @@ -8,13 +8,12 @@ use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, ast}; use ra_arena::{Arena, RawId, ArenaId, impl_arena_id}; use crate::{ - HirDatabase, Def, + HirDatabase, Module, }; #[derive(Debug, Default)] pub struct HirInterner { - defs: LocationIntener, macros: LocationIntener, fns: LocationIntener, FunctionId>, structs: LocationIntener, StructId>, @@ -28,7 +27,15 @@ pub struct HirInterner { impl HirInterner { pub fn len(&self) -> usize { - self.defs.len() + self.macros.len() + self.macros.len() + + self.fns.len() + + self.structs.len() + + self.enums.len() + + self.enum_variants.len() + + self.consts.len() + + self.statics.len() + + self.traits.len() + + self.types.len() } } @@ -299,33 +306,6 @@ impl AstItemDef for TypeId { } } -/// Def's are a core concept of hir. A `Def` is an Item (function, module, etc) -/// in a specific module. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct DefId(RawId); -impl_arena_id!(DefId); - -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct DefLoc { - pub(crate) kind: DefKind, - pub(crate) module: Module, - pub(crate) source_item_id: SourceItemId, -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub(crate) enum DefKind {} - -impl DefId { - pub(crate) fn loc(self, db: &impl AsRef) -> DefLoc { - db.as_ref().defs.id2loc(self) - } - - pub fn resolve(self, db: &impl HirDatabase) -> Def { - let loc = self.loc(db); - match loc.kind {} - } -} - /// Identifier of item within a specific file. This is stable over reparses, so /// it's OK to use it as a salsa key/value. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 6cbece95e7..644affd445 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -52,7 +52,7 @@ use crate::{ pub use self::{ path::{Path, PathKind}, name::Name, - ids::{HirFileId, DefId, DefLoc, MacroCallId, MacroCallLoc, HirInterner}, + ids::{HirFileId, MacroCallId, MacroCallLoc, HirInterner}, macros::{MacroDef, MacroInput, MacroExpansion}, nameres::{ItemMap, PerNs, Namespace, Resolution}, ty::{Ty, AdtDef}, From 31d3a56b1865c33ef54e5d76e606965c87676695 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 25 Jan 2019 01:53:07 +0300 Subject: [PATCH 26/26] move adt to adt --- crates/ra_hir/src/adt.rs | 23 +++++++++++++++++++---- crates/ra_hir/src/lib.rs | 5 +++-- crates/ra_hir/src/ty.rs | 19 +------------------ 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index ad3f9c4059..6b13b464d2 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs @@ -3,17 +3,32 @@ use std::sync::Arc; -use ra_syntax::{ - ast::{self, NameOwner, StructFlavor} -}; +use ra_syntax::ast::{self, NameOwner, StructFlavor}; use crate::{ - Name, AsName, Struct, Enum, EnumVariant, + Name, AsName, Struct, Enum, EnumVariant, Crate, HirDatabase, type_ref::TypeRef, ids::LocationCtx, }; +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub enum AdtDef { + Struct(Struct), + Enum(Enum), +} +impl_froms!(AdtDef: Struct, Enum); + +impl AdtDef { + pub(crate) fn krate(self, db: &impl HirDatabase) -> Option { + match self { + AdtDef::Struct(s) => s.module(db), + AdtDef::Enum(e) => e.module(db), + } + .krate(db) + } +} + impl Struct { pub(crate) fn variant_data(&self, db: &impl HirDatabase) -> Arc { db.struct_data((*self).into()).variant_data.clone() diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 644affd445..596f9c38c3 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -55,10 +55,11 @@ pub use self::{ ids::{HirFileId, MacroCallId, MacroCallLoc, HirInterner}, macros::{MacroDef, MacroInput, MacroExpansion}, nameres::{ItemMap, PerNs, Namespace, Resolution}, - ty::{Ty, AdtDef}, + ty::Ty, impl_block::{ImplBlock, ImplItem}, code_model_impl::function::{FnScopes, ScopesWithSyntaxMapping}, - docs::{Docs, Documentation} + docs::{Docs, Documentation}, + adt::AdtDef, }; pub use self::code_model_api::{ diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 1d5624f8fc..c7f77e7a39 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -31,7 +31,7 @@ use rustc_hash::FxHashMap; use crate::{ Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock, - FnSignature, FnScopes, ModuleDef, Crate, + FnSignature, FnScopes, ModuleDef, AdtDef, db::HirDatabase, type_ref::{TypeRef, Mutability}, name::KnownName, @@ -162,23 +162,6 @@ impl Substs { } } -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub enum AdtDef { - Struct(Struct), - Enum(Enum), -} -impl_froms!(AdtDef: Struct, Enum); - -impl AdtDef { - fn krate(self, db: &impl HirDatabase) -> Option { - match self { - AdtDef::Struct(s) => s.module(db), - AdtDef::Enum(e) => e.module(db), - } - .krate(db) - } -} - /// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs). /// /// This should be cheap to clone.