Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/lib.rs')
| -rw-r--r-- | crates/hir-def/src/lib.rs | 158 |
1 files changed, 129 insertions, 29 deletions
diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index 8d6c418d75..9a7fbc812f 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -49,7 +49,6 @@ pub mod visibility; use intern::{Interned, Symbol}; pub use rustc_abi as layout; use thin_vec::ThinVec; -use triomphe::Arc; pub use crate::signatures::LocalFieldId; @@ -86,14 +85,19 @@ use crate::{ builtin_type::BuiltinType, db::DefDatabase, expr_store::ExpressionStoreSourceMap, - hir::generics::{LocalLifetimeParamId, LocalTypeOrConstParamId}, + hir::{ + ExprId, + generics::{GenericParams, LocalLifetimeParamId, LocalTypeOrConstParamId}, + }, nameres::{ LocalDefMap, assoc::{ImplItems, TraitItems}, block_def_map, crate_def_map, crate_local_def_map, diagnostics::DefDiagnostics, }, - signatures::{EnumVariants, InactiveEnumVariantCode, VariantFields}, + signatures::{ + ConstSignature, EnumVariants, InactiveEnumVariantCode, StaticSignature, VariantFields, + }, }; type FxIndexMap<K, V> = indexmap::IndexMap<K, V, rustc_hash::FxBuildHasher>; @@ -255,14 +259,15 @@ impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct); impl StructId { pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields { - VariantFields::firewall(db, self.into()) + VariantFields::of(db, self.into()) } pub fn fields_with_source_map( self, db: &dyn DefDatabase, - ) -> (Arc<VariantFields>, Arc<ExpressionStoreSourceMap>) { - VariantFields::query(db, self.into()) + ) -> (&VariantFields, &ExpressionStoreSourceMap) { + let r = VariantFields::with_source_map(db, self.into()); + (&r.0, &r.1) } } @@ -271,14 +276,15 @@ impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union); impl UnionId { pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields { - VariantFields::firewall(db, self.into()) + VariantFields::of(db, self.into()) } pub fn fields_with_source_map( self, db: &dyn DefDatabase, - ) -> (Arc<VariantFields>, Arc<ExpressionStoreSourceMap>) { - VariantFields::query(db, self.into()) + ) -> (&VariantFields, &ExpressionStoreSourceMap) { + let r = VariantFields::with_source_map(db, self.into()); + (&r.0, &r.1) } } @@ -306,6 +312,19 @@ impl_intern!(ConstId, ConstLoc, intern_const, lookup_intern_const); pub type StaticLoc = AssocItemLoc<ast::Static>; impl_intern!(StaticId, StaticLoc, intern_static, lookup_intern_static); +/// An anonymous const expression that appears in a type position (e.g., array lengths, +/// const generic arguments like `{ N + 1 }`). Unlike named constants, these don't have +/// their own `Body` — their expressions live in the parent's signature `ExpressionStore`. +#[derive(Debug, Hash, PartialEq, Eq, Clone)] +pub struct AnonConstLoc { + /// The owner store containing this expression. + pub owner: ExpressionStoreOwnerId, + /// The ExprId within the owner's ExpressionStore that is the root + /// of this anonymous const expression. + pub expr: ExprId, +} +impl_intern!(AnonConstId, AnonConstLoc, intern_anon_const, lookup_intern_anon_const); + pub type TraitLoc = ItemLoc<ast::Trait>; impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait); @@ -377,14 +396,15 @@ impl_loc!(EnumVariantLoc, id: Variant, parent: EnumId); impl EnumVariantId { pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields { - VariantFields::firewall(db, self.into()) + VariantFields::of(db, self.into()) } pub fn fields_with_source_map( self, db: &dyn DefDatabase, - ) -> (Arc<VariantFields>, Arc<ExpressionStoreSourceMap>) { - VariantFields::query(db, self.into()) + ) -> (&VariantFields, &ExpressionStoreSourceMap) { + let r = VariantFields::with_source_map(db, self.into()); + (&r.0, &r.1) } } @@ -553,15 +573,25 @@ pub struct TypeOrConstParamId { pub struct TypeParamId(TypeOrConstParamId); impl TypeParamId { + #[inline] pub fn parent(&self) -> GenericDefId { self.0.parent } + + #[inline] pub fn local_id(&self) -> LocalTypeOrConstParamId { self.0.local_id } -} -impl TypeParamId { + #[inline] + pub fn trait_self(trait_: TraitId) -> TypeParamId { + TypeParamId::from_unchecked(TypeOrConstParamId { + parent: trait_.into(), + local_id: GenericParams::SELF_PARAM_ID_IN_SELF, + }) + } + + #[inline] /// Caller should check if this toc id really belongs to a type pub fn from_unchecked(it: TypeOrConstParamId) -> Self { Self(it) @@ -696,46 +726,47 @@ impl From<DefWithBodyId> for ModuleDefId { pub enum GeneralConstId { ConstId(ConstId), StaticId(StaticId), + AnonConstId(AnonConstId), } -impl_from!(ConstId, StaticId for GeneralConstId); +impl_from!(ConstId, StaticId, AnonConstId for GeneralConstId); impl GeneralConstId { - pub fn generic_def(self, _db: &dyn DefDatabase) -> Option<GenericDefId> { + pub fn generic_def(self, db: &dyn DefDatabase) -> Option<GenericDefId> { match self { GeneralConstId::ConstId(it) => Some(it.into()), GeneralConstId::StaticId(it) => Some(it.into()), + GeneralConstId::AnonConstId(it) => Some(it.lookup(db).owner.generic_def(db)), } } pub fn name(self, db: &dyn DefDatabase) -> String { match self { GeneralConstId::StaticId(it) => { - db.static_signature(it).name.display(db, Edition::CURRENT).to_string() + StaticSignature::of(db, it).name.display(db, Edition::CURRENT).to_string() } GeneralConstId::ConstId(const_id) => { - db.const_signature(const_id).name.as_ref().map_or_else( + ConstSignature::of(db, const_id).name.as_ref().map_or_else( || "_".to_owned(), |name| name.display(db, Edition::CURRENT).to_string(), ) } + GeneralConstId::AnonConstId(_) => "{anon const}".to_owned(), } } } -/// The defs which have a body (have root expressions for type inference). +/// The defs which have a body. #[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)] pub enum DefWithBodyId { + /// A function body. FunctionId(FunctionId), + /// A static item initializer. StaticId(StaticId), + /// A const item initializer ConstId(ConstId), + /// An enum variant discrimiant VariantId(EnumVariantId), - // /// All fields of a variant are inference roots - // VariantId(VariantId), - // /// The signature can contain inference roots in a bunch of places - // /// like const parameters or const arguments in paths - // This should likely be kept on its own with a separate query - // GenericDefId(GenericDefId), } impl_from!(FunctionId, ConstId, StaticId for DefWithBodyId); @@ -804,6 +835,62 @@ impl_from!( for GenericDefId ); +/// Owner of an expression store - either a body or a signature. +/// This is used for queries that operate on expression stores generically, +/// such as `expr_scopes`. +// NOTE: This type cannot be `salsa::Supertype` as its variants are overlapping. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord /* !salsa::Supertype */)] +pub enum ExpressionStoreOwnerId { + Signature(GenericDefId), + /// A body, something with a root expression. + /// + /// An enum variant's body is considered its discriminant initializer. + Body(DefWithBodyId), + VariantFields(VariantId), +} + +impl ExpressionStoreOwnerId { + // FIXME: Check callers of this, this method likely can be removed + pub fn as_def_with_body(self) -> Option<DefWithBodyId> { + if let Self::Body(v) = self { Some(v) } else { None } + } + + pub fn generic_def(self, db: &dyn DefDatabase) -> GenericDefId { + match self { + ExpressionStoreOwnerId::Signature(generic_def_id) => generic_def_id, + ExpressionStoreOwnerId::Body(def_with_body_id) => match def_with_body_id { + DefWithBodyId::FunctionId(id) => GenericDefId::FunctionId(id), + DefWithBodyId::StaticId(id) => GenericDefId::StaticId(id), + DefWithBodyId::ConstId(id) => GenericDefId::ConstId(id), + DefWithBodyId::VariantId(it) => it.lookup(db).parent.into(), + }, + ExpressionStoreOwnerId::VariantFields(variant_id) => match variant_id { + VariantId::EnumVariantId(it) => it.lookup(db).parent.into(), + VariantId::StructId(it) => it.into(), + VariantId::UnionId(it) => it.into(), + }, + } + } +} + +impl From<GenericDefId> for ExpressionStoreOwnerId { + fn from(id: GenericDefId) -> Self { + ExpressionStoreOwnerId::Signature(id) + } +} + +impl From<DefWithBodyId> for ExpressionStoreOwnerId { + fn from(id: DefWithBodyId) -> Self { + ExpressionStoreOwnerId::Body(id) + } +} + +impl From<VariantId> for ExpressionStoreOwnerId { + fn from(id: VariantId) -> Self { + ExpressionStoreOwnerId::VariantFields(id) + } +} + impl GenericDefId { pub fn file_id_and_params_of( self, @@ -944,7 +1031,9 @@ impl From<VariantId> for AttrDefId { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype, salsa::Update)] +#[derive( + Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, salsa_macros::Supertype, salsa::Update, +)] pub enum VariantId { EnumVariantId(EnumVariantId), StructId(StructId), @@ -954,14 +1043,15 @@ impl_from!(EnumVariantId, StructId, UnionId for VariantId); impl VariantId { pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields { - VariantFields::firewall(db, self) + VariantFields::of(db, self) } pub fn fields_with_source_map( self, db: &dyn DefDatabase, - ) -> (Arc<VariantFields>, Arc<ExpressionStoreSourceMap>) { - VariantFields::query(db, self) + ) -> (&VariantFields, &ExpressionStoreSourceMap) { + let r = VariantFields::with_source_map(db, self); + (&r.0, &r.1) } pub fn file_id(self, db: &dyn DefDatabase) -> HirFileId { @@ -1162,6 +1252,16 @@ impl HasModule for DefWithBodyId { } } +impl HasModule for ExpressionStoreOwnerId { + fn module(&self, db: &dyn DefDatabase) -> ModuleId { + match self { + ExpressionStoreOwnerId::Signature(def) => def.module(db), + ExpressionStoreOwnerId::Body(def) => def.module(db), + ExpressionStoreOwnerId::VariantFields(variant_id) => variant_id.module(db), + } + } +} + impl HasModule for GenericDefId { fn module(&self, db: &dyn DefDatabase) -> ModuleId { match self { |