From b28c54a2c239acd73f2eea80fda9ee3960d2c046 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 13 Aug 2020 16:28:27 +0200 Subject: Rename ra_hir_def -> hir_def --- crates/hir_def/src/lib.rs | 541 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 541 insertions(+) create mode 100644 crates/hir_def/src/lib.rs (limited to 'crates/hir_def/src/lib.rs') diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs new file mode 100644 index 000000000..f24a1dd77 --- /dev/null +++ b/crates/hir_def/src/lib.rs @@ -0,0 +1,541 @@ +//! `hir_def` crate contains everything between macro expansion and type +//! inference. +//! +//! It defines various items (structs, enums, traits) which comprises Rust code, +//! as well as an algorithm for resolving paths to such entities. +//! +//! Note that `hir_def` is a work in progress, so not all of the above is +//! actually true. + +#[allow(unused)] +macro_rules! eprintln { + ($($tt:tt)*) => { stdx::eprintln!($($tt)*) }; +} + +pub mod db; + +pub mod attr; +pub mod path; +pub mod type_ref; +pub mod builtin_type; +pub mod diagnostics; +pub mod per_ns; +pub mod item_scope; + +pub mod dyn_map; +pub mod keys; + +pub mod item_tree; + +pub mod adt; +pub mod data; +pub mod generics; +pub mod lang_item; +pub mod docs; + +pub mod expr; +pub mod body; +pub mod resolver; + +mod trace; +pub mod nameres; + +pub mod src; +pub mod child_by_source; + +pub mod visibility; +pub mod find_path; +pub mod import_map; + +#[cfg(test)] +mod test_db; + +use std::hash::{Hash, Hasher}; + +use arena::Idx; +use base_db::{impl_intern_key, salsa, CrateId}; +use hir_expand::{ + ast_id_map::FileAstId, eager::expand_eager_macro, hygiene::Hygiene, AstId, HirFileId, InFile, + MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, +}; +use syntax::ast; + +use crate::builtin_type::BuiltinType; +use item_tree::{ + Const, Enum, Function, Impl, ItemTreeId, ItemTreeNode, ModItem, Static, Struct, Trait, + TypeAlias, Union, +}; +use stdx::impl_from; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct ModuleId { + pub krate: CrateId, + pub local_id: LocalModuleId, +} + +/// An ID of a module, **local** to a specific crate +pub type LocalModuleId = Idx; + +#[derive(Debug)] +pub struct ItemLoc { + pub container: ContainerId, + pub id: ItemTreeId, +} + +impl Clone for ItemLoc { + fn clone(&self) -> Self { + Self { container: self.container, id: self.id } + } +} + +impl Copy for ItemLoc {} + +impl PartialEq for ItemLoc { + fn eq(&self, other: &Self) -> bool { + self.container == other.container && self.id == other.id + } +} + +impl Eq for ItemLoc {} + +impl Hash for ItemLoc { + fn hash(&self, state: &mut H) { + self.container.hash(state); + self.id.hash(state); + } +} + +#[derive(Debug)] +pub struct AssocItemLoc { + pub container: AssocContainerId, + pub id: ItemTreeId, +} + +impl Clone for AssocItemLoc { + fn clone(&self) -> Self { + Self { container: self.container, id: self.id } + } +} + +impl Copy for AssocItemLoc {} + +impl PartialEq for AssocItemLoc { + fn eq(&self, other: &Self) -> bool { + self.container == other.container && self.id == other.id + } +} + +impl Eq for AssocItemLoc {} + +impl Hash for AssocItemLoc { + fn hash(&self, state: &mut H) { + self.container.hash(state); + self.id.hash(state); + } +} + +macro_rules! impl_intern { + ($id:ident, $loc:ident, $intern:ident, $lookup:ident) => { + impl_intern_key!($id); + + impl Intern for $loc { + type ID = $id; + fn intern(self, db: &dyn db::DefDatabase) -> $id { + db.$intern(self) + } + } + + impl Lookup for $id { + type Data = $loc; + fn lookup(&self, db: &dyn db::DefDatabase) -> $loc { + db.$lookup(*self) + } + } + }; +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct FunctionId(salsa::InternId); +type FunctionLoc = AssocItemLoc; +impl_intern!(FunctionId, FunctionLoc, intern_function, lookup_intern_function); + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct StructId(salsa::InternId); +type StructLoc = ItemLoc; +impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct); + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct UnionId(salsa::InternId); +pub type UnionLoc = ItemLoc; +impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union); + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct EnumId(salsa::InternId); +pub type EnumLoc = ItemLoc; +impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum); + +// FIXME: rename to `VariantId`, only enums can ave variants +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct EnumVariantId { + pub parent: EnumId, + pub local_id: LocalEnumVariantId, +} + +pub type LocalEnumVariantId = Idx; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct FieldId { + pub parent: VariantId, + pub local_id: LocalFieldId, +} + +pub type LocalFieldId = Idx; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct ConstId(salsa::InternId); +type ConstLoc = AssocItemLoc; +impl_intern!(ConstId, ConstLoc, intern_const, lookup_intern_const); + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct StaticId(salsa::InternId); +pub type StaticLoc = ItemLoc; +impl_intern!(StaticId, StaticLoc, intern_static, lookup_intern_static); + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct TraitId(salsa::InternId); +pub type TraitLoc = ItemLoc; +impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait); + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct TypeAliasId(salsa::InternId); +type TypeAliasLoc = AssocItemLoc; +impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_alias); + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] +pub struct ImplId(salsa::InternId); +type ImplLoc = ItemLoc; +impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl); + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct TypeParamId { + pub parent: GenericDefId, + pub local_id: LocalTypeParamId, +} + +pub type LocalTypeParamId = Idx; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum ContainerId { + ModuleId(ModuleId), + DefWithBodyId(DefWithBodyId), +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum AssocContainerId { + ContainerId(ContainerId), + ImplId(ImplId), + TraitId(TraitId), +} +impl_from!(ContainerId for AssocContainerId); + +/// A Data Type +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub enum AdtId { + StructId(StructId), + UnionId(UnionId), + EnumId(EnumId), +} +impl_from!(StructId, UnionId, EnumId for AdtId); + +/// The defs which can be visible in the module. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum ModuleDefId { + ModuleId(ModuleId), + FunctionId(FunctionId), + AdtId(AdtId), + // Can't be directly declared, but can be imported. + EnumVariantId(EnumVariantId), + ConstId(ConstId), + StaticId(StaticId), + TraitId(TraitId), + TypeAliasId(TypeAliasId), + BuiltinType(BuiltinType), +} +impl_from!( + ModuleId, + FunctionId, + AdtId(StructId, EnumId, UnionId), + EnumVariantId, + ConstId, + StaticId, + TraitId, + TypeAliasId, + BuiltinType + for ModuleDefId +); + +/// The defs which have a body. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum DefWithBodyId { + FunctionId(FunctionId), + StaticId(StaticId), + ConstId(ConstId), +} + +impl_from!(FunctionId, ConstId, StaticId for DefWithBodyId); + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum AssocItemId { + FunctionId(FunctionId), + ConstId(ConstId), + TypeAliasId(TypeAliasId), +} +// FIXME: not every function, ... is actually an assoc item. maybe we should make +// sure that you can only turn actual assoc items into AssocItemIds. This would +// require not implementing From, and instead having some checked way of +// casting them, and somehow making the constructors private, which would be annoying. +impl_from!(FunctionId, ConstId, TypeAliasId for AssocItemId); + +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +pub enum GenericDefId { + FunctionId(FunctionId), + AdtId(AdtId), + TraitId(TraitId), + TypeAliasId(TypeAliasId), + ImplId(ImplId), + // enum variants cannot have generics themselves, but their parent enums + // can, and this makes some code easier to write + EnumVariantId(EnumVariantId), + // consts can have type parameters from their parents (i.e. associated consts of traits) + ConstId(ConstId), +} +impl_from!( + FunctionId, + AdtId(StructId, EnumId, UnionId), + TraitId, + TypeAliasId, + ImplId, + EnumVariantId, + ConstId + for GenericDefId +); + +impl From for GenericDefId { + fn from(item: AssocItemId) -> Self { + match item { + AssocItemId::FunctionId(f) => f.into(), + AssocItemId::ConstId(c) => c.into(), + AssocItemId::TypeAliasId(t) => t.into(), + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub enum AttrDefId { + ModuleId(ModuleId), + FieldId(FieldId), + AdtId(AdtId), + FunctionId(FunctionId), + EnumVariantId(EnumVariantId), + StaticId(StaticId), + ConstId(ConstId), + TraitId(TraitId), + TypeAliasId(TypeAliasId), + MacroDefId(MacroDefId), + ImplId(ImplId), +} + +impl_from!( + ModuleId, + FieldId, + AdtId(StructId, EnumId, UnionId), + EnumVariantId, + StaticId, + ConstId, + FunctionId, + TraitId, + TypeAliasId, + MacroDefId, + ImplId + for AttrDefId +); + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum VariantId { + EnumVariantId(EnumVariantId), + StructId(StructId), + UnionId(UnionId), +} +impl_from!(EnumVariantId, StructId, UnionId for VariantId); + +trait Intern { + type ID; + fn intern(self, db: &dyn db::DefDatabase) -> Self::ID; +} + +pub trait Lookup { + type Data; + fn lookup(&self, db: &dyn db::DefDatabase) -> Self::Data; +} + +pub trait HasModule { + fn module(&self, db: &dyn db::DefDatabase) -> ModuleId; +} + +impl HasModule for ContainerId { + fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { + match *self { + ContainerId::ModuleId(it) => it, + ContainerId::DefWithBodyId(it) => it.module(db), + } + } +} + +impl HasModule for AssocContainerId { + fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { + match *self { + AssocContainerId::ContainerId(it) => it.module(db), + AssocContainerId::ImplId(it) => it.lookup(db).container.module(db), + AssocContainerId::TraitId(it) => it.lookup(db).container.module(db), + } + } +} + +impl HasModule for AssocItemLoc { + fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { + self.container.module(db) + } +} + +impl HasModule for AdtId { + fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { + match self { + AdtId::StructId(it) => it.lookup(db).container, + AdtId::UnionId(it) => it.lookup(db).container, + AdtId::EnumId(it) => it.lookup(db).container, + } + .module(db) + } +} + +impl HasModule for DefWithBodyId { + fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { + match self { + DefWithBodyId::FunctionId(it) => it.lookup(db).module(db), + DefWithBodyId::StaticId(it) => it.lookup(db).module(db), + DefWithBodyId::ConstId(it) => it.lookup(db).module(db), + } + } +} + +impl DefWithBodyId { + pub fn as_mod_item(self, db: &dyn db::DefDatabase) -> ModItem { + match self { + DefWithBodyId::FunctionId(it) => it.lookup(db).id.value.into(), + DefWithBodyId::StaticId(it) => it.lookup(db).id.value.into(), + DefWithBodyId::ConstId(it) => it.lookup(db).id.value.into(), + } + } +} + +impl HasModule for GenericDefId { + fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { + match self { + GenericDefId::FunctionId(it) => it.lookup(db).module(db), + GenericDefId::AdtId(it) => it.module(db), + GenericDefId::TraitId(it) => it.lookup(db).container.module(db), + GenericDefId::TypeAliasId(it) => it.lookup(db).module(db), + GenericDefId::ImplId(it) => it.lookup(db).container.module(db), + GenericDefId::EnumVariantId(it) => it.parent.lookup(db).container.module(db), + GenericDefId::ConstId(it) => it.lookup(db).module(db), + } + } +} + +impl HasModule for StaticLoc { + fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { + self.container.module(db) + } +} + +/// A helper trait for converting to MacroCallId +pub trait AsMacroCall { + fn as_call_id( + &self, + db: &dyn db::DefDatabase, + krate: CrateId, + resolver: impl Fn(path::ModPath) -> Option, + ) -> Option; +} + +impl AsMacroCall for InFile<&ast::MacroCall> { + fn as_call_id( + &self, + db: &dyn db::DefDatabase, + krate: CrateId, + resolver: impl Fn(path::ModPath) -> Option, + ) -> Option { + let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value)); + let h = Hygiene::new(db.upcast(), self.file_id); + let path = path::ModPath::from_src(self.value.path()?, &h)?; + + AstIdWithPath::new(ast_id.file_id, ast_id.value, path).as_call_id(db, krate, resolver) + } +} + +/// Helper wrapper for `AstId` with `ModPath` +#[derive(Clone, Debug, Eq, PartialEq)] +struct AstIdWithPath { + pub ast_id: AstId, + pub path: path::ModPath, +} + +impl AstIdWithPath { + pub fn new(file_id: HirFileId, ast_id: FileAstId, path: path::ModPath) -> AstIdWithPath { + AstIdWithPath { ast_id: AstId::new(file_id, ast_id), path } + } +} + +impl AsMacroCall for AstIdWithPath { + fn as_call_id( + &self, + db: &dyn db::DefDatabase, + krate: CrateId, + resolver: impl Fn(path::ModPath) -> Option, + ) -> Option { + let def: MacroDefId = resolver(self.path.clone())?; + + if let MacroDefKind::BuiltInEager(_) = def.kind { + let macro_call = InFile::new(self.ast_id.file_id, self.ast_id.to_node(db.upcast())); + let hygiene = Hygiene::new(db.upcast(), self.ast_id.file_id); + + Some( + expand_eager_macro(db.upcast(), krate, macro_call, def, &|path: ast::Path| { + resolver(path::ModPath::from_src(path, &hygiene)?) + })? + .into(), + ) + } else { + Some(def.as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike(self.ast_id)).into()) + } + } +} + +impl AsMacroCall for AstIdWithPath { + fn as_call_id( + &self, + db: &dyn db::DefDatabase, + krate: CrateId, + resolver: impl Fn(path::ModPath) -> Option, + ) -> Option { + let def = resolver(self.path.clone())?; + Some( + def.as_lazy_macro( + db.upcast(), + krate, + MacroCallKind::Attr(self.ast_id, self.path.segments.last()?.to_string()), + ) + .into(), + ) + } +} -- cgit v1.2.3