Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/item_tree.rs')
| -rw-r--r-- | crates/hir-def/src/item_tree.rs | 195 |
1 files changed, 159 insertions, 36 deletions
diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 91a8cbab1a..74500fd76e 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -61,7 +61,7 @@ use crate::{ db::DefDatabase, generics::GenericParams, path::{GenericArgs, ImportAlias, ModPath, Path, PathKind}, - type_ref::{Mutability, TraitRef, TypeBound, TypeRef}, + type_ref::{Mutability, TraitRef, TypeBound, TypeRefId, TypesMap, TypesSourceMap}, visibility::{RawVisibility, VisibilityExplicitness}, BlockId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, }; @@ -100,13 +100,20 @@ pub struct ItemTree { impl ItemTree { pub(crate) fn file_item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> { + db.file_item_tree_with_source_map(file_id).0 + } + + pub(crate) fn file_item_tree_with_source_map_query( + db: &dyn DefDatabase, + file_id: HirFileId, + ) -> (Arc<ItemTree>, Arc<ItemTreeSourceMaps>) { let _p = tracing::info_span!("file_item_tree_query", ?file_id).entered(); - static EMPTY: OnceLock<Arc<ItemTree>> = OnceLock::new(); + static EMPTY: OnceLock<(Arc<ItemTree>, Arc<ItemTreeSourceMaps>)> = OnceLock::new(); let ctx = lower::Ctx::new(db, file_id); let syntax = db.parse_or_expand(file_id); let mut top_attrs = None; - let mut item_tree = match_ast! { + let (mut item_tree, mut source_maps) = match_ast! { match syntax { ast::SourceFile(file) => { top_attrs = Some(RawAttrs::new(db.upcast(), &file, ctx.span_map())); @@ -136,42 +143,57 @@ impl ItemTree { { EMPTY .get_or_init(|| { - Arc::new(ItemTree { - top_level: SmallVec::new_const(), - attrs: FxHashMap::default(), - data: None, - }) + ( + Arc::new(ItemTree { + top_level: SmallVec::new_const(), + attrs: FxHashMap::default(), + data: None, + }), + Arc::default(), + ) }) .clone() } else { item_tree.shrink_to_fit(); - Arc::new(item_tree) + source_maps.shrink_to_fit(); + (Arc::new(item_tree), Arc::new(source_maps)) } } pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc<ItemTree> { + db.block_item_tree_with_source_map(block).0 + } + + pub(crate) fn block_item_tree_with_source_map_query( + db: &dyn DefDatabase, + block: BlockId, + ) -> (Arc<ItemTree>, Arc<ItemTreeSourceMaps>) { let _p = tracing::info_span!("block_item_tree_query", ?block).entered(); - static EMPTY: OnceLock<Arc<ItemTree>> = OnceLock::new(); + static EMPTY: OnceLock<(Arc<ItemTree>, Arc<ItemTreeSourceMaps>)> = OnceLock::new(); let loc = block.lookup(db); let block = loc.ast_id.to_node(db.upcast()); let ctx = lower::Ctx::new(db, loc.ast_id.file_id); - let mut item_tree = ctx.lower_block(&block); + let (mut item_tree, mut source_maps) = ctx.lower_block(&block); if item_tree.data.is_none() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty() { EMPTY .get_or_init(|| { - Arc::new(ItemTree { - top_level: SmallVec::new_const(), - attrs: FxHashMap::default(), - data: None, - }) + ( + Arc::new(ItemTree { + top_level: SmallVec::new_const(), + attrs: FxHashMap::default(), + data: None, + }), + Arc::default(), + ) }) .clone() } else { item_tree.shrink_to_fit(); - Arc::new(item_tree) + source_maps.shrink_to_fit(); + (Arc::new(item_tree), Arc::new(source_maps)) } } @@ -308,6 +330,82 @@ struct ItemTreeData { vis: ItemVisibilities, } +#[derive(Default, Debug, Eq, PartialEq)] +pub struct GenericItemSourceMap { + pub item: TypesSourceMap, + pub generics: TypesSourceMap, +} + +#[derive(Default, Debug, Eq, PartialEq)] +pub struct ItemTreeSourceMaps { + functions: Vec<GenericItemSourceMap>, + structs: Vec<GenericItemSourceMap>, + unions: Vec<GenericItemSourceMap>, + enum_generics: Vec<TypesSourceMap>, + variants: Vec<TypesSourceMap>, + consts: Vec<TypesSourceMap>, + statics: Vec<TypesSourceMap>, + trait_generics: Vec<TypesSourceMap>, + trait_alias_generics: Vec<TypesSourceMap>, + impls: Vec<GenericItemSourceMap>, + type_aliases: Vec<GenericItemSourceMap>, +} + +impl ItemTreeSourceMaps { + fn shrink_to_fit(&mut self) { + let ItemTreeSourceMaps { + functions, + structs, + unions, + enum_generics, + variants, + consts, + statics, + trait_generics, + trait_alias_generics, + impls, + type_aliases, + } = self; + functions.shrink_to_fit(); + structs.shrink_to_fit(); + unions.shrink_to_fit(); + enum_generics.shrink_to_fit(); + variants.shrink_to_fit(); + consts.shrink_to_fit(); + statics.shrink_to_fit(); + trait_generics.shrink_to_fit(); + trait_alias_generics.shrink_to_fit(); + impls.shrink_to_fit(); + type_aliases.shrink_to_fit(); + } +} + +macro_rules! index_source_maps { + ( $( $field:ident[$tree_id:ident] = $result:ident, )* ) => { + $( + impl Index<FileItemTreeId<$tree_id>> for ItemTreeSourceMaps { + type Output = $result; + fn index(&self, index: FileItemTreeId<$tree_id>) -> &Self::Output { + &self.$field[index.0.into_raw().into_u32() as usize] + } + } + )* + }; +} +index_source_maps! { + functions[Function] = GenericItemSourceMap, + structs[Struct] = GenericItemSourceMap, + unions[Union] = GenericItemSourceMap, + enum_generics[Enum] = TypesSourceMap, + variants[Variant] = TypesSourceMap, + consts[Const] = TypesSourceMap, + statics[Static] = TypesSourceMap, + trait_generics[Trait] = TypesSourceMap, + trait_alias_generics[TraitAlias] = TypesSourceMap, + impls[Impl] = GenericItemSourceMap, + type_aliases[TypeAlias] = GenericItemSourceMap, +} + #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub enum AttrOwner { /// Attributes on an item. @@ -363,7 +461,7 @@ pub trait ItemTreeNode: Clone { fn attr_owner(id: FileItemTreeId<Self>) -> AttrOwner; } pub trait GenericsItemTreeNode: ItemTreeNode { - fn generic_params(&self) -> &Interned<GenericParams>; + fn generic_params(&self) -> &Arc<GenericParams>; } pub struct FileItemTreeId<N>(Idx<N>); @@ -428,6 +526,16 @@ impl TreeId { } } + pub fn item_tree_with_source_map( + &self, + db: &dyn DefDatabase, + ) -> (Arc<ItemTree>, Arc<ItemTreeSourceMaps>) { + match self.block { + Some(block) => db.block_item_tree_with_source_map(block), + None => db.file_item_tree_with_source_map(self.file), + } + } + pub fn file_id(self) -> HirFileId { self.file } @@ -460,6 +568,13 @@ impl<N> ItemTreeId<N> { self.tree.item_tree(db) } + pub fn item_tree_with_source_map( + self, + db: &dyn DefDatabase, + ) -> (Arc<ItemTree>, Arc<ItemTreeSourceMaps>) { + self.tree.item_tree_with_source_map(db) + } + pub fn resolved<R>(self, db: &dyn DefDatabase, cb: impl FnOnce(&N) -> R) -> R where ItemTree: Index<FileItemTreeId<N>, Output = N>, @@ -592,7 +707,7 @@ macro_rules! mod_items { $( impl GenericsItemTreeNode for $typ { - fn generic_params(&self) -> &Interned<GenericParams> { + fn generic_params(&self) -> &Arc<GenericParams> { &self.$generic_params } } @@ -730,17 +845,18 @@ pub struct ExternBlock { pub struct Function { pub name: Name, pub visibility: RawVisibilityId, - pub explicit_generic_params: Interned<GenericParams>, + pub explicit_generic_params: Arc<GenericParams>, pub abi: Option<Symbol>, pub params: Box<[Param]>, - pub ret_type: Interned<TypeRef>, + pub ret_type: TypeRefId, pub ast_id: FileAstId<ast::Fn>, + pub types_map: Arc<TypesMap>, pub(crate) flags: FnFlags, } #[derive(Debug, Clone, PartialEq, Eq)] pub struct Param { - pub type_ref: Option<Interned<TypeRef>>, + pub type_ref: Option<TypeRefId>, } bitflags::bitflags! { @@ -761,26 +877,28 @@ bitflags::bitflags! { pub struct Struct { pub name: Name, pub visibility: RawVisibilityId, - pub generic_params: Interned<GenericParams>, + pub generic_params: Arc<GenericParams>, pub fields: Box<[Field]>, pub shape: FieldsShape, pub ast_id: FileAstId<ast::Struct>, + pub types_map: Arc<TypesMap>, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Union { pub name: Name, pub visibility: RawVisibilityId, - pub generic_params: Interned<GenericParams>, + pub generic_params: Arc<GenericParams>, pub fields: Box<[Field]>, pub ast_id: FileAstId<ast::Union>, + pub types_map: Arc<TypesMap>, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Enum { pub name: Name, pub visibility: RawVisibilityId, - pub generic_params: Interned<GenericParams>, + pub generic_params: Arc<GenericParams>, pub variants: Range<FileItemTreeId<Variant>>, pub ast_id: FileAstId<ast::Enum>, } @@ -791,6 +909,7 @@ pub struct Variant { pub fields: Box<[Field]>, pub shape: FieldsShape, pub ast_id: FileAstId<ast::Variant>, + pub types_map: Arc<TypesMap>, } #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -804,7 +923,7 @@ pub enum FieldsShape { #[derive(Debug, Clone, PartialEq, Eq)] pub struct Field { pub name: Name, - pub type_ref: Interned<TypeRef>, + pub type_ref: TypeRefId, pub visibility: RawVisibilityId, } @@ -813,9 +932,10 @@ pub struct Const { /// `None` for `const _: () = ();` pub name: Option<Name>, pub visibility: RawVisibilityId, - pub type_ref: Interned<TypeRef>, + pub type_ref: TypeRefId, pub ast_id: FileAstId<ast::Const>, pub has_body: bool, + pub types_map: Arc<TypesMap>, } #[derive(Debug, Clone, Eq, PartialEq)] @@ -826,15 +946,16 @@ pub struct Static { pub mutable: bool, pub has_safe_kw: bool, pub has_unsafe_kw: bool, - pub type_ref: Interned<TypeRef>, + pub type_ref: TypeRefId, pub ast_id: FileAstId<ast::Static>, + pub types_map: Arc<TypesMap>, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Trait { pub name: Name, pub visibility: RawVisibilityId, - pub generic_params: Interned<GenericParams>, + pub generic_params: Arc<GenericParams>, pub is_auto: bool, pub is_unsafe: bool, pub items: Box<[AssocItem]>, @@ -845,19 +966,20 @@ pub struct Trait { pub struct TraitAlias { pub name: Name, pub visibility: RawVisibilityId, - pub generic_params: Interned<GenericParams>, + pub generic_params: Arc<GenericParams>, pub ast_id: FileAstId<ast::TraitAlias>, } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Impl { - pub generic_params: Interned<GenericParams>, - pub target_trait: Option<Interned<TraitRef>>, - pub self_ty: Interned<TypeRef>, + pub generic_params: Arc<GenericParams>, + pub target_trait: Option<TraitRef>, + pub self_ty: TypeRefId, pub is_negative: bool, pub is_unsafe: bool, pub items: Box<[AssocItem]>, pub ast_id: FileAstId<ast::Impl>, + pub types_map: Arc<TypesMap>, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -865,10 +987,11 @@ pub struct TypeAlias { pub name: Name, pub visibility: RawVisibilityId, /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`. - pub bounds: Box<[Interned<TypeBound>]>, - pub generic_params: Interned<GenericParams>, - pub type_ref: Option<Interned<TypeRef>>, + pub bounds: Box<[TypeBound]>, + pub generic_params: Arc<GenericParams>, + pub type_ref: Option<TypeRefId>, pub ast_id: FileAstId<ast::TypeAlias>, + pub types_map: Arc<TypesMap>, } #[derive(Debug, Clone, Eq, PartialEq)] |