mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 12:54:58 +00:00
Intern TypeRef
s in the containing ItemTree
This commit is contained in:
parent
663d404a4e
commit
003ee0086a
4 changed files with 67 additions and 21 deletions
|
@ -351,7 +351,7 @@ fn lower_field(
|
||||||
) -> FieldData {
|
) -> FieldData {
|
||||||
FieldData {
|
FieldData {
|
||||||
name: field.name.clone(),
|
name: field.name.clone(),
|
||||||
type_ref: field.type_ref.clone(),
|
type_ref: item_tree[field.type_ref].clone(),
|
||||||
visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(),
|
visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,8 +41,8 @@ impl FunctionData {
|
||||||
|
|
||||||
Arc::new(FunctionData {
|
Arc::new(FunctionData {
|
||||||
name: func.name.clone(),
|
name: func.name.clone(),
|
||||||
params: func.params.to_vec(),
|
params: func.params.iter().map(|id| item_tree[*id].clone()).collect(),
|
||||||
ret_type: func.ret_type.clone(),
|
ret_type: item_tree[func.ret_type].clone(),
|
||||||
attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()).clone(),
|
attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()).clone(),
|
||||||
has_self_param: func.has_self_param,
|
has_self_param: func.has_self_param,
|
||||||
has_body: func.has_body,
|
has_body: func.has_body,
|
||||||
|
@ -75,7 +75,7 @@ impl TypeAliasData {
|
||||||
|
|
||||||
Arc::new(TypeAliasData {
|
Arc::new(TypeAliasData {
|
||||||
name: typ.name.clone(),
|
name: typ.name.clone(),
|
||||||
type_ref: typ.type_ref.clone(),
|
type_ref: typ.type_ref.map(|id| item_tree[id].clone()),
|
||||||
visibility: item_tree[typ.visibility].clone(),
|
visibility: item_tree[typ.visibility].clone(),
|
||||||
is_extern: typ.is_extern,
|
is_extern: typ.is_extern,
|
||||||
bounds: typ.bounds.to_vec(),
|
bounds: typ.bounds.to_vec(),
|
||||||
|
@ -144,8 +144,8 @@ impl ImplData {
|
||||||
|
|
||||||
let item_tree = db.item_tree(impl_loc.id.file_id);
|
let item_tree = db.item_tree(impl_loc.id.file_id);
|
||||||
let impl_def = &item_tree[impl_loc.id.value];
|
let impl_def = &item_tree[impl_loc.id.value];
|
||||||
let target_trait = impl_def.target_trait.clone();
|
let target_trait = impl_def.target_trait.map(|id| item_tree[id].clone());
|
||||||
let target_type = impl_def.target_type.clone();
|
let target_type = item_tree[impl_def.target_type].clone();
|
||||||
let is_negative = impl_def.is_negative;
|
let is_negative = impl_def.is_negative;
|
||||||
let module_id = impl_loc.container.module(db);
|
let module_id = impl_loc.container.module(db);
|
||||||
let container = AssocContainerId::ImplId(id);
|
let container = AssocContainerId::ImplId(id);
|
||||||
|
@ -182,7 +182,7 @@ impl ConstData {
|
||||||
|
|
||||||
Arc::new(ConstData {
|
Arc::new(ConstData {
|
||||||
name: konst.name.clone(),
|
name: konst.name.clone(),
|
||||||
type_ref: konst.type_ref.clone(),
|
type_ref: item_tree[konst.type_ref].clone(),
|
||||||
visibility: item_tree[konst.visibility].clone(),
|
visibility: item_tree[konst.visibility].clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -205,7 +205,7 @@ impl StaticData {
|
||||||
|
|
||||||
Arc::new(StaticData {
|
Arc::new(StaticData {
|
||||||
name: Some(statik.name.clone()),
|
name: Some(statik.name.clone()),
|
||||||
type_ref: statik.type_ref.clone(),
|
type_ref: item_tree[statik.type_ref].clone(),
|
||||||
visibility: item_tree[statik.visibility].clone(),
|
visibility: item_tree[statik.visibility].clone(),
|
||||||
mutable: statik.mutable,
|
mutable: statik.mutable,
|
||||||
is_extern: statik.is_extern,
|
is_extern: statik.is_extern,
|
||||||
|
|
|
@ -146,6 +146,7 @@ impl ItemTree {
|
||||||
macro_defs,
|
macro_defs,
|
||||||
vis,
|
vis,
|
||||||
generics,
|
generics,
|
||||||
|
type_refs,
|
||||||
inner_items,
|
inner_items,
|
||||||
} = &mut **data;
|
} = &mut **data;
|
||||||
|
|
||||||
|
@ -169,6 +170,8 @@ impl ItemTree {
|
||||||
|
|
||||||
vis.arena.shrink_to_fit();
|
vis.arena.shrink_to_fit();
|
||||||
generics.arena.shrink_to_fit();
|
generics.arena.shrink_to_fit();
|
||||||
|
type_refs.arena.shrink_to_fit();
|
||||||
|
type_refs.map.shrink_to_fit();
|
||||||
|
|
||||||
inner_items.shrink_to_fit();
|
inner_items.shrink_to_fit();
|
||||||
}
|
}
|
||||||
|
@ -279,6 +282,32 @@ static EMPTY_GENERICS: GenericParams = GenericParams {
|
||||||
where_predicates: Vec::new(),
|
where_predicates: Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// `TypeRef` interner.
|
||||||
|
#[derive(Default, Debug, Eq, PartialEq)]
|
||||||
|
struct TypeRefStorage {
|
||||||
|
arena: Arena<Arc<TypeRef>>,
|
||||||
|
map: FxHashMap<Arc<TypeRef>, Idx<Arc<TypeRef>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeRefStorage {
|
||||||
|
// Note: We lie about the `Idx<TypeRef>` to hide the interner details.
|
||||||
|
|
||||||
|
fn intern(&mut self, ty: TypeRef) -> Idx<TypeRef> {
|
||||||
|
if let Some(id) = self.map.get(&ty) {
|
||||||
|
return Idx::from_raw(id.into_raw());
|
||||||
|
}
|
||||||
|
|
||||||
|
let ty = Arc::new(ty);
|
||||||
|
let idx = self.arena.alloc(ty.clone());
|
||||||
|
self.map.insert(ty, idx);
|
||||||
|
Idx::from_raw(idx.into_raw())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lookup(&self, id: Idx<TypeRef>) -> &TypeRef {
|
||||||
|
&self.arena[Idx::from_raw(id.into_raw())]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Eq, PartialEq)]
|
#[derive(Default, Debug, Eq, PartialEq)]
|
||||||
struct ItemTreeData {
|
struct ItemTreeData {
|
||||||
imports: Arena<Import>,
|
imports: Arena<Import>,
|
||||||
|
@ -301,6 +330,7 @@ struct ItemTreeData {
|
||||||
|
|
||||||
vis: ItemVisibilities,
|
vis: ItemVisibilities,
|
||||||
generics: GenericParamsStorage,
|
generics: GenericParamsStorage,
|
||||||
|
type_refs: TypeRefStorage,
|
||||||
|
|
||||||
inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>,
|
inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>,
|
||||||
}
|
}
|
||||||
|
@ -489,6 +519,14 @@ impl Index<GenericParamsId> for ItemTree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Index<Idx<TypeRef>> for ItemTree {
|
||||||
|
type Output = TypeRef;
|
||||||
|
|
||||||
|
fn index(&self, id: Idx<TypeRef>) -> &Self::Output {
|
||||||
|
self.data().type_refs.lookup(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree {
|
impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree {
|
||||||
type Output = N;
|
type Output = N;
|
||||||
fn index(&self, id: FileItemTreeId<N>) -> &N {
|
fn index(&self, id: FileItemTreeId<N>) -> &N {
|
||||||
|
@ -532,9 +570,9 @@ pub struct Function {
|
||||||
/// Whether the function is located in an `extern` block (*not* whether it is an
|
/// Whether the function is located in an `extern` block (*not* whether it is an
|
||||||
/// `extern "abi" fn`).
|
/// `extern "abi" fn`).
|
||||||
pub is_extern: bool,
|
pub is_extern: bool,
|
||||||
pub params: Box<[TypeRef]>,
|
pub params: Box<[Idx<TypeRef>]>,
|
||||||
pub is_varargs: bool,
|
pub is_varargs: bool,
|
||||||
pub ret_type: TypeRef,
|
pub ret_type: Idx<TypeRef>,
|
||||||
pub ast_id: FileAstId<ast::Fn>,
|
pub ast_id: FileAstId<ast::Fn>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -581,7 +619,7 @@ pub struct Const {
|
||||||
/// const _: () = ();
|
/// const _: () = ();
|
||||||
pub name: Option<Name>,
|
pub name: Option<Name>,
|
||||||
pub visibility: RawVisibilityId,
|
pub visibility: RawVisibilityId,
|
||||||
pub type_ref: TypeRef,
|
pub type_ref: Idx<TypeRef>,
|
||||||
pub ast_id: FileAstId<ast::Const>,
|
pub ast_id: FileAstId<ast::Const>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -592,7 +630,7 @@ pub struct Static {
|
||||||
pub mutable: bool,
|
pub mutable: bool,
|
||||||
/// Whether the static is in an `extern` block.
|
/// Whether the static is in an `extern` block.
|
||||||
pub is_extern: bool,
|
pub is_extern: bool,
|
||||||
pub type_ref: TypeRef,
|
pub type_ref: Idx<TypeRef>,
|
||||||
pub ast_id: FileAstId<ast::Static>,
|
pub ast_id: FileAstId<ast::Static>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -609,8 +647,8 @@ pub struct Trait {
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
pub struct Impl {
|
pub struct Impl {
|
||||||
pub generic_params: GenericParamsId,
|
pub generic_params: GenericParamsId,
|
||||||
pub target_trait: Option<TypeRef>,
|
pub target_trait: Option<Idx<TypeRef>>,
|
||||||
pub target_type: TypeRef,
|
pub target_type: Idx<TypeRef>,
|
||||||
pub is_negative: bool,
|
pub is_negative: bool,
|
||||||
pub items: Box<[AssocItem]>,
|
pub items: Box<[AssocItem]>,
|
||||||
pub ast_id: FileAstId<ast::Impl>,
|
pub ast_id: FileAstId<ast::Impl>,
|
||||||
|
@ -623,7 +661,7 @@ pub struct TypeAlias {
|
||||||
/// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`.
|
/// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`.
|
||||||
pub bounds: Box<[TypeBound]>,
|
pub bounds: Box<[TypeBound]>,
|
||||||
pub generic_params: GenericParamsId,
|
pub generic_params: GenericParamsId,
|
||||||
pub type_ref: Option<TypeRef>,
|
pub type_ref: Option<Idx<TypeRef>>,
|
||||||
pub is_extern: bool,
|
pub is_extern: bool,
|
||||||
pub ast_id: FileAstId<ast::TypeAlias>,
|
pub ast_id: FileAstId<ast::TypeAlias>,
|
||||||
}
|
}
|
||||||
|
@ -806,6 +844,6 @@ pub enum Fields {
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct Field {
|
pub struct Field {
|
||||||
pub name: Name,
|
pub name: Name,
|
||||||
pub type_ref: TypeRef,
|
pub type_ref: Idx<TypeRef>,
|
||||||
pub visibility: RawVisibilityId,
|
pub visibility: RawVisibilityId,
|
||||||
}
|
}
|
||||||
|
|
|
@ -364,6 +364,7 @@ impl Ctx {
|
||||||
params.push(type_ref);
|
params.push(type_ref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let params = params.into_iter().map(|param| self.data().type_refs.intern(param)).collect();
|
||||||
|
|
||||||
let mut is_varargs = false;
|
let mut is_varargs = false;
|
||||||
if let Some(params) = func.param_list() {
|
if let Some(params) = func.param_list() {
|
||||||
|
@ -385,6 +386,8 @@ impl Ctx {
|
||||||
ret_type
|
ret_type
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let ret_type = self.data().type_refs.intern(ret_type);
|
||||||
|
|
||||||
let has_body = func.body().is_some();
|
let has_body = func.body().is_some();
|
||||||
|
|
||||||
let ast_id = self.source_ast_id_map.ast_id(func);
|
let ast_id = self.source_ast_id_map.ast_id(func);
|
||||||
|
@ -396,7 +399,7 @@ impl Ctx {
|
||||||
has_body,
|
has_body,
|
||||||
is_unsafe: func.unsafe_token().is_some(),
|
is_unsafe: func.unsafe_token().is_some(),
|
||||||
is_extern: false,
|
is_extern: false,
|
||||||
params: params.into_boxed_slice(),
|
params,
|
||||||
is_varargs,
|
is_varargs,
|
||||||
ret_type,
|
ret_type,
|
||||||
ast_id,
|
ast_id,
|
||||||
|
@ -657,6 +660,7 @@ impl Ctx {
|
||||||
generics.fill(&self.body_ctx, sm, node);
|
generics.fill(&self.body_ctx, sm, node);
|
||||||
// lower `impl Trait` in arguments
|
// lower `impl Trait` in arguments
|
||||||
for param in &*func.params {
|
for param in &*func.params {
|
||||||
|
let param = self.data().type_refs.lookup(*param);
|
||||||
generics.fill_implicit_impl_trait_args(param);
|
generics.fill_implicit_impl_trait_args(param);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -709,11 +713,15 @@ impl Ctx {
|
||||||
self.data().vis.alloc(vis)
|
self.data().vis.alloc(vis)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_type_ref(&self, type_ref: &ast::Type) -> TypeRef {
|
fn lower_type_ref(&mut self, type_ref: &ast::Type) -> Idx<TypeRef> {
|
||||||
TypeRef::from_ast(&self.body_ctx, type_ref.clone())
|
let tyref = TypeRef::from_ast(&self.body_ctx, type_ref.clone());
|
||||||
|
self.data().type_refs.intern(tyref)
|
||||||
}
|
}
|
||||||
fn lower_type_ref_opt(&self, type_ref: Option<ast::Type>) -> TypeRef {
|
fn lower_type_ref_opt(&mut self, type_ref: Option<ast::Type>) -> Idx<TypeRef> {
|
||||||
type_ref.map(|ty| self.lower_type_ref(&ty)).unwrap_or(TypeRef::Error)
|
match type_ref.map(|ty| self.lower_type_ref(&ty)) {
|
||||||
|
Some(it) => it,
|
||||||
|
None => self.data().type_refs.intern(TypeRef::Error),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Forces the visibility `vis` to be used for all items lowered during execution of `f`.
|
/// Forces the visibility `vis` to be used for all items lowered during execution of `f`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue