mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-11 12:48:47 +00:00
Intern GenericParams
Also share the same instance between `ItemTree` and `generic_params` query.
This commit is contained in:
parent
adcf18e27d
commit
7c0c713a10
9 changed files with 47 additions and 82 deletions
|
@ -13,6 +13,7 @@ use crate::{
|
|||
data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData},
|
||||
generics::GenericParams,
|
||||
import_map::ImportMap,
|
||||
intern::Interned,
|
||||
item_tree::ItemTree,
|
||||
lang_item::{LangItemTarget, LangItems},
|
||||
nameres::DefMap,
|
||||
|
@ -113,7 +114,7 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
|
|||
fn expr_scopes(&self, def: DefWithBodyId) -> Arc<ExprScopes>;
|
||||
|
||||
#[salsa::invoke(GenericParams::generic_params_query)]
|
||||
fn generic_params(&self, def: GenericDefId) -> Arc<GenericParams>;
|
||||
fn generic_params(&self, def: GenericDefId) -> Interned<GenericParams>;
|
||||
|
||||
#[salsa::invoke(Attrs::variants_attrs_query)]
|
||||
fn variants_attrs(&self, def: EnumId) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>>;
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
//! structs, impls, traits, etc. This module provides a common HIR for these
|
||||
//! generic parameters. See also the `Generics` type and the `generics_of` query
|
||||
//! in rustc.
|
||||
use std::sync::Arc;
|
||||
|
||||
use base_db::FileId;
|
||||
use either::Either;
|
||||
|
@ -27,7 +26,7 @@ use crate::{
|
|||
};
|
||||
|
||||
/// Data about a generic type parameter (to a function, struct, impl, ...).
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct TypeParamData {
|
||||
pub name: Option<Name>,
|
||||
pub default: Option<Interned<TypeRef>>,
|
||||
|
@ -35,19 +34,19 @@ pub struct TypeParamData {
|
|||
}
|
||||
|
||||
/// Data about a generic lifetime parameter (to a function, struct, impl, ...).
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct LifetimeParamData {
|
||||
pub name: Name,
|
||||
}
|
||||
|
||||
/// Data about a generic const parameter (to a function, struct, impl, ...).
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct ConstParamData {
|
||||
pub name: Name,
|
||||
pub ty: Interned<TypeRef>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum TypeParamProvenance {
|
||||
TypeParamList,
|
||||
TraitSelf,
|
||||
|
@ -55,7 +54,7 @@ pub enum TypeParamProvenance {
|
|||
}
|
||||
|
||||
/// Data about the generic parameters of a function, struct, impl, etc.
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Default)]
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Default, Hash)]
|
||||
pub struct GenericParams {
|
||||
pub types: Arena<TypeParamData>,
|
||||
pub lifetimes: Arena<LifetimeParamData>,
|
||||
|
@ -67,14 +66,14 @@ pub struct GenericParams {
|
|||
/// where clauses like `where T: Foo + Bar` are turned into multiple of these.
|
||||
/// It might still result in multiple actual predicates though, because of
|
||||
/// associated type bindings like `Iterator<Item = u32>`.
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum WherePredicate {
|
||||
TypeBound { target: WherePredicateTypeTarget, bound: TypeBound },
|
||||
Lifetime { target: LifetimeRef, bound: LifetimeRef },
|
||||
ForLifetime { lifetimes: Box<[Name]>, target: WherePredicateTypeTarget, bound: TypeBound },
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum WherePredicateTypeTarget {
|
||||
TypeRef(Interned<TypeRef>),
|
||||
/// For desugared where predicates that can directly refer to a type param.
|
||||
|
@ -92,7 +91,7 @@ impl GenericParams {
|
|||
pub(crate) fn generic_params_query(
|
||||
db: &dyn DefDatabase,
|
||||
def: GenericDefId,
|
||||
) -> Arc<GenericParams> {
|
||||
) -> Interned<GenericParams> {
|
||||
let _p = profile::span("generic_params_query");
|
||||
|
||||
let generics = match def {
|
||||
|
@ -100,47 +99,49 @@ impl GenericParams {
|
|||
let id = id.lookup(db).id;
|
||||
let tree = id.item_tree(db);
|
||||
let item = &tree[id.value];
|
||||
tree[item.generic_params].clone()
|
||||
item.generic_params.clone()
|
||||
}
|
||||
GenericDefId::AdtId(AdtId::StructId(id)) => {
|
||||
let id = id.lookup(db).id;
|
||||
let tree = id.item_tree(db);
|
||||
let item = &tree[id.value];
|
||||
tree[item.generic_params].clone()
|
||||
item.generic_params.clone()
|
||||
}
|
||||
GenericDefId::AdtId(AdtId::EnumId(id)) => {
|
||||
let id = id.lookup(db).id;
|
||||
let tree = id.item_tree(db);
|
||||
let item = &tree[id.value];
|
||||
tree[item.generic_params].clone()
|
||||
item.generic_params.clone()
|
||||
}
|
||||
GenericDefId::AdtId(AdtId::UnionId(id)) => {
|
||||
let id = id.lookup(db).id;
|
||||
let tree = id.item_tree(db);
|
||||
let item = &tree[id.value];
|
||||
tree[item.generic_params].clone()
|
||||
item.generic_params.clone()
|
||||
}
|
||||
GenericDefId::TraitId(id) => {
|
||||
let id = id.lookup(db).id;
|
||||
let tree = id.item_tree(db);
|
||||
let item = &tree[id.value];
|
||||
tree[item.generic_params].clone()
|
||||
item.generic_params.clone()
|
||||
}
|
||||
GenericDefId::TypeAliasId(id) => {
|
||||
let id = id.lookup(db).id;
|
||||
let tree = id.item_tree(db);
|
||||
let item = &tree[id.value];
|
||||
tree[item.generic_params].clone()
|
||||
item.generic_params.clone()
|
||||
}
|
||||
GenericDefId::ImplId(id) => {
|
||||
let id = id.lookup(db).id;
|
||||
let tree = id.item_tree(db);
|
||||
let item = &tree[id.value];
|
||||
tree[item.generic_params].clone()
|
||||
item.generic_params.clone()
|
||||
}
|
||||
GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {
|
||||
Interned::new(GenericParams::default())
|
||||
}
|
||||
GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => GenericParams::default(),
|
||||
};
|
||||
Arc::new(generics)
|
||||
generics
|
||||
}
|
||||
|
||||
fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) {
|
||||
|
|
|
@ -14,6 +14,8 @@ use dashmap::{lock::RwLockWriteGuard, DashMap, SharedValue};
|
|||
use once_cell::sync::OnceCell;
|
||||
use rustc_hash::FxHasher;
|
||||
|
||||
use crate::generics::GenericParams;
|
||||
|
||||
type InternMap<T> = DashMap<Arc<T>, (), BuildHasherDefault<FxHasher>>;
|
||||
type Guard<T> =
|
||||
RwLockWriteGuard<'static, HashMap<Arc<T>, SharedValue<()>, BuildHasherDefault<FxHasher>>>;
|
||||
|
@ -194,4 +196,10 @@ macro_rules! impl_internable {
|
|||
)+ };
|
||||
}
|
||||
|
||||
impl_internable!(crate::type_ref::TypeRef, crate::type_ref::TraitRef, crate::path::ModPath, str);
|
||||
impl_internable!(
|
||||
crate::type_ref::TypeRef,
|
||||
crate::type_ref::TraitRef,
|
||||
crate::path::ModPath,
|
||||
GenericParams,
|
||||
str
|
||||
);
|
||||
|
|
|
@ -58,13 +58,6 @@ impl fmt::Debug for RawVisibilityId {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub struct GenericParamsId(u32);
|
||||
|
||||
impl GenericParamsId {
|
||||
pub const EMPTY: Self = GenericParamsId(u32::max_value());
|
||||
}
|
||||
|
||||
/// The item tree of a source file.
|
||||
#[derive(Debug, Default, Eq, PartialEq)]
|
||||
pub struct ItemTree {
|
||||
|
@ -146,7 +139,6 @@ impl ItemTree {
|
|||
macro_rules,
|
||||
macro_defs,
|
||||
vis,
|
||||
generics,
|
||||
inner_items,
|
||||
} = &mut **data;
|
||||
|
||||
|
@ -170,7 +162,6 @@ impl ItemTree {
|
|||
macro_defs.shrink_to_fit();
|
||||
|
||||
vis.arena.shrink_to_fit();
|
||||
generics.arena.shrink_to_fit();
|
||||
|
||||
inner_items.shrink_to_fit();
|
||||
}
|
||||
|
@ -241,32 +232,6 @@ static VIS_PUB: RawVisibility = RawVisibility::Public;
|
|||
static VIS_PRIV: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)));
|
||||
static VIS_PUB_CRATE: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Crate));
|
||||
|
||||
#[derive(Default, Debug, Eq, PartialEq)]
|
||||
struct GenericParamsStorage {
|
||||
arena: Arena<GenericParams>,
|
||||
}
|
||||
|
||||
impl GenericParamsStorage {
|
||||
fn alloc(&mut self, params: GenericParams) -> GenericParamsId {
|
||||
if params.types.is_empty()
|
||||
&& params.lifetimes.is_empty()
|
||||
&& params.consts.is_empty()
|
||||
&& params.where_predicates.is_empty()
|
||||
{
|
||||
return GenericParamsId::EMPTY;
|
||||
}
|
||||
|
||||
GenericParamsId(self.arena.alloc(params).into_raw().into())
|
||||
}
|
||||
}
|
||||
|
||||
static EMPTY_GENERICS: GenericParams = GenericParams {
|
||||
types: Arena::new(),
|
||||
lifetimes: Arena::new(),
|
||||
consts: Arena::new(),
|
||||
where_predicates: Vec::new(),
|
||||
};
|
||||
|
||||
#[derive(Default, Debug, Eq, PartialEq)]
|
||||
struct ItemTreeData {
|
||||
imports: Arena<Import>,
|
||||
|
@ -289,7 +254,6 @@ struct ItemTreeData {
|
|||
macro_defs: Arena<MacroDef>,
|
||||
|
||||
vis: ItemVisibilities,
|
||||
generics: GenericParamsStorage,
|
||||
|
||||
inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>,
|
||||
}
|
||||
|
@ -508,17 +472,6 @@ impl Index<RawVisibilityId> for ItemTree {
|
|||
}
|
||||
}
|
||||
|
||||
impl Index<GenericParamsId> for ItemTree {
|
||||
type Output = GenericParams;
|
||||
|
||||
fn index(&self, index: GenericParamsId) -> &Self::Output {
|
||||
match index {
|
||||
GenericParamsId::EMPTY => &EMPTY_GENERICS,
|
||||
_ => &self.data().generics.arena[Idx::from_raw(index.0.into())],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree {
|
||||
type Output = N;
|
||||
fn index(&self, id: FileItemTreeId<N>) -> &N {
|
||||
|
@ -555,7 +508,7 @@ pub struct ExternCrate {
|
|||
pub struct Function {
|
||||
pub name: Name,
|
||||
pub visibility: RawVisibilityId,
|
||||
pub generic_params: GenericParamsId,
|
||||
pub generic_params: Interned<GenericParams>,
|
||||
pub abi: Option<Interned<str>>,
|
||||
pub params: IdRange<Param>,
|
||||
pub ret_type: Interned<TypeRef>,
|
||||
|
@ -590,7 +543,7 @@ impl FnFlags {
|
|||
pub struct Struct {
|
||||
pub name: Name,
|
||||
pub visibility: RawVisibilityId,
|
||||
pub generic_params: GenericParamsId,
|
||||
pub generic_params: Interned<GenericParams>,
|
||||
pub fields: Fields,
|
||||
pub ast_id: FileAstId<ast::Struct>,
|
||||
pub kind: StructDefKind,
|
||||
|
@ -610,7 +563,7 @@ pub enum StructDefKind {
|
|||
pub struct Union {
|
||||
pub name: Name,
|
||||
pub visibility: RawVisibilityId,
|
||||
pub generic_params: GenericParamsId,
|
||||
pub generic_params: Interned<GenericParams>,
|
||||
pub fields: Fields,
|
||||
pub ast_id: FileAstId<ast::Union>,
|
||||
}
|
||||
|
@ -619,7 +572,7 @@ pub struct Union {
|
|||
pub struct Enum {
|
||||
pub name: Name,
|
||||
pub visibility: RawVisibilityId,
|
||||
pub generic_params: GenericParamsId,
|
||||
pub generic_params: Interned<GenericParams>,
|
||||
pub variants: IdRange<Variant>,
|
||||
pub ast_id: FileAstId<ast::Enum>,
|
||||
}
|
||||
|
@ -648,7 +601,7 @@ pub struct Static {
|
|||
pub struct Trait {
|
||||
pub name: Name,
|
||||
pub visibility: RawVisibilityId,
|
||||
pub generic_params: GenericParamsId,
|
||||
pub generic_params: Interned<GenericParams>,
|
||||
pub is_auto: bool,
|
||||
pub is_unsafe: bool,
|
||||
pub bounds: Box<[TypeBound]>,
|
||||
|
@ -658,7 +611,7 @@ pub struct Trait {
|
|||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct Impl {
|
||||
pub generic_params: GenericParamsId,
|
||||
pub generic_params: Interned<GenericParams>,
|
||||
pub target_trait: Option<Interned<TraitRef>>,
|
||||
pub self_ty: Interned<TypeRef>,
|
||||
pub is_negative: bool,
|
||||
|
@ -672,7 +625,7 @@ pub struct TypeAlias {
|
|||
pub visibility: RawVisibilityId,
|
||||
/// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`.
|
||||
pub bounds: Box<[TypeBound]>,
|
||||
pub generic_params: GenericParamsId,
|
||||
pub generic_params: Interned<GenericParams>,
|
||||
pub type_ref: Option<Interned<TypeRef>>,
|
||||
pub is_extern: bool,
|
||||
pub ast_id: FileAstId<ast::TypeAlias>,
|
||||
|
|
|
@ -434,7 +434,7 @@ impl Ctx {
|
|||
let mut res = Function {
|
||||
name,
|
||||
visibility,
|
||||
generic_params: GenericParamsId::EMPTY,
|
||||
generic_params: Interned::new(GenericParams::default()),
|
||||
abi,
|
||||
params,
|
||||
ret_type: Interned::new(ret_type),
|
||||
|
@ -682,7 +682,7 @@ impl Ctx {
|
|||
&mut self,
|
||||
owner: GenericsOwner<'_>,
|
||||
node: &impl ast::GenericParamsOwner,
|
||||
) -> GenericParamsId {
|
||||
) -> Interned<GenericParams> {
|
||||
// Generics are part of item headers and may contain inner items we need to collect.
|
||||
if let Some(params) = node.generic_param_list() {
|
||||
self.collect_inner_items(params.syntax());
|
||||
|
@ -698,7 +698,7 @@ impl Ctx {
|
|||
&mut self,
|
||||
owner: GenericsOwner<'_>,
|
||||
node: &impl ast::GenericParamsOwner,
|
||||
) -> GenericParamsId {
|
||||
) -> Interned<GenericParams> {
|
||||
let mut sm = &mut Default::default();
|
||||
let mut generics = GenericParams::default();
|
||||
match owner {
|
||||
|
@ -740,7 +740,7 @@ impl Ctx {
|
|||
}
|
||||
|
||||
generics.shrink_to_fit();
|
||||
self.data().generics.alloc(generics)
|
||||
Interned::new(generics)
|
||||
}
|
||||
|
||||
fn lower_type_bounds(&mut self, node: &impl ast::TypeBoundsOwner) -> Vec<TypeBound> {
|
||||
|
|
|
@ -27,6 +27,7 @@ pub mod dyn_map;
|
|||
pub mod keys;
|
||||
|
||||
pub mod item_tree;
|
||||
pub mod intern;
|
||||
|
||||
pub mod adt;
|
||||
pub mod data;
|
||||
|
@ -49,7 +50,6 @@ pub mod import_map;
|
|||
|
||||
#[cfg(test)]
|
||||
mod test_db;
|
||||
mod intern;
|
||||
|
||||
use std::{
|
||||
hash::{Hash, Hasher},
|
||||
|
|
|
@ -14,6 +14,7 @@ use crate::{
|
|||
db::DefDatabase,
|
||||
expr::{ExprId, LabelId, PatId},
|
||||
generics::GenericParams,
|
||||
intern::Interned,
|
||||
item_scope::{BuiltinShadowMode, BUILTIN_SCOPE},
|
||||
nameres::DefMap,
|
||||
path::{ModPath, PathKind},
|
||||
|
@ -50,7 +51,7 @@ enum Scope {
|
|||
/// All the items and imported names of a module
|
||||
ModuleScope(ModuleItemMap),
|
||||
/// Brings the generic parameters of an item into scope
|
||||
GenericParams { def: GenericDefId, params: Arc<GenericParams> },
|
||||
GenericParams { def: GenericDefId, params: Interned<GenericParams> },
|
||||
/// Brings `Self` in `impl` block into scope
|
||||
ImplDefScope(ImplId),
|
||||
/// Brings `Self` in enum, struct and union definitions into scope
|
||||
|
|
|
@ -9,6 +9,7 @@ use hir_def::{
|
|||
generics::{
|
||||
GenericParams, TypeParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
|
||||
},
|
||||
intern::Interned,
|
||||
path::Path,
|
||||
resolver::{HasResolver, TypeNs},
|
||||
type_ref::TypeRef,
|
||||
|
@ -158,7 +159,7 @@ pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics {
|
|||
#[derive(Debug)]
|
||||
pub(crate) struct Generics {
|
||||
def: GenericDefId,
|
||||
pub(crate) params: Arc<GenericParams>,
|
||||
pub(crate) params: Interned<GenericParams>,
|
||||
parent_generics: Option<Box<Generics>>,
|
||||
}
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ impl<T> Idx<T> {
|
|||
}
|
||||
|
||||
/// Yet another index-based arena.
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Arena<T> {
|
||||
data: Vec<T>,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue