diff options
Diffstat (limited to 'crates/hir_def/src')
-rw-r--r-- | crates/hir_def/src/attr.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/body.rs | 24 | ||||
-rw-r--r-- | crates/hir_def/src/body/lower.rs | 12 | ||||
-rw-r--r-- | crates/hir_def/src/child_by_source.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/data.rs | 57 | ||||
-rw-r--r-- | crates/hir_def/src/db.rs | 3 | ||||
-rw-r--r-- | crates/hir_def/src/generics.rs | 62 | ||||
-rw-r--r-- | crates/hir_def/src/intern.rs | 10 | ||||
-rw-r--r-- | crates/hir_def/src/item_scope.rs | 22 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 95 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 77 | ||||
-rw-r--r-- | crates/hir_def/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/nameres.rs | 25 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 12 | ||||
-rw-r--r-- | crates/hir_def/src/path.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/path/lower.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/resolver.rs | 3 | ||||
-rw-r--r-- | crates/hir_def/src/visibility.rs | 6 |
18 files changed, 259 insertions, 159 deletions
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index 2bab121d9..442c5fb5b 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -533,7 +533,7 @@ impl Attr { | |||
533 | }; | 533 | }; |
534 | Some(AttrInput::Literal(value)) | 534 | Some(AttrInput::Literal(value)) |
535 | } else if let Some(tt) = ast.token_tree() { | 535 | } else if let Some(tt) = ast.token_tree() { |
536 | Some(AttrInput::TokenTree(ast_to_token_tree(&tt)?.0)) | 536 | Some(AttrInput::TokenTree(ast_to_token_tree(&tt).0)) |
537 | } else { | 537 | } else { |
538 | None | 538 | None |
539 | }; | 539 | }; |
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs index 1080d9c2c..96b959967 100644 --- a/crates/hir_def/src/body.rs +++ b/crates/hir_def/src/body.rs | |||
@@ -226,7 +226,7 @@ pub struct Body { | |||
226 | /// The `ExprId` of the actual body expression. | 226 | /// The `ExprId` of the actual body expression. |
227 | pub body_expr: ExprId, | 227 | pub body_expr: ExprId, |
228 | /// Block expressions in this body that may contain inner items. | 228 | /// Block expressions in this body that may contain inner items. |
229 | pub block_scopes: Vec<BlockId>, | 229 | block_scopes: Vec<BlockId>, |
230 | _c: Count<Self>, | 230 | _c: Count<Self>, |
231 | } | 231 | } |
232 | 232 | ||
@@ -302,7 +302,8 @@ impl Body { | |||
302 | } | 302 | } |
303 | }; | 303 | }; |
304 | let expander = Expander::new(db, file_id, module); | 304 | let expander = Expander::new(db, file_id, module); |
305 | let (body, source_map) = Body::new(db, expander, params, body); | 305 | let (mut body, source_map) = Body::new(db, expander, params, body); |
306 | body.shrink_to_fit(); | ||
306 | (Arc::new(body), Arc::new(source_map)) | 307 | (Arc::new(body), Arc::new(source_map)) |
307 | } | 308 | } |
308 | 309 | ||
@@ -310,6 +311,16 @@ impl Body { | |||
310 | db.body_with_source_map(def).0 | 311 | db.body_with_source_map(def).0 |
311 | } | 312 | } |
312 | 313 | ||
314 | /// Returns an iterator over all block expressions in this body that define inner items. | ||
315 | pub fn blocks<'a>( | ||
316 | &'a self, | ||
317 | db: &'a dyn DefDatabase, | ||
318 | ) -> impl Iterator<Item = (BlockId, Arc<DefMap>)> + '_ { | ||
319 | self.block_scopes | ||
320 | .iter() | ||
321 | .map(move |block| (*block, db.block_def_map(*block).expect("block ID without DefMap"))) | ||
322 | } | ||
323 | |||
313 | fn new( | 324 | fn new( |
314 | db: &dyn DefDatabase, | 325 | db: &dyn DefDatabase, |
315 | expander: Expander, | 326 | expander: Expander, |
@@ -318,6 +329,15 @@ impl Body { | |||
318 | ) -> (Body, BodySourceMap) { | 329 | ) -> (Body, BodySourceMap) { |
319 | lower::lower(db, expander, params, body) | 330 | lower::lower(db, expander, params, body) |
320 | } | 331 | } |
332 | |||
333 | fn shrink_to_fit(&mut self) { | ||
334 | let Self { _c: _, body_expr: _, block_scopes, exprs, labels, params, pats } = self; | ||
335 | block_scopes.shrink_to_fit(); | ||
336 | exprs.shrink_to_fit(); | ||
337 | labels.shrink_to_fit(); | ||
338 | params.shrink_to_fit(); | ||
339 | pats.shrink_to_fit(); | ||
340 | } | ||
321 | } | 341 | } |
322 | 342 | ||
323 | impl Index<ExprId> for Body { | 343 | impl Index<ExprId> for Body { |
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 229e81dd4..63e89a1f4 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -673,12 +673,14 @@ impl ExprCollector<'_> { | |||
673 | let block_loc = | 673 | let block_loc = |
674 | BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) }; | 674 | BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) }; |
675 | let block_id = self.db.intern_block(block_loc); | 675 | let block_id = self.db.intern_block(block_loc); |
676 | self.body.block_scopes.push(block_id); | ||
677 | 676 | ||
678 | let opt_def_map = self.db.block_def_map(block_id); | 677 | let (module, def_map) = match self.db.block_def_map(block_id) { |
679 | let has_def_map = opt_def_map.is_some(); | 678 | Some(def_map) => { |
680 | let def_map = opt_def_map.unwrap_or_else(|| self.expander.def_map.clone()); | 679 | self.body.block_scopes.push(block_id); |
681 | let module = if has_def_map { def_map.root() } else { self.expander.module }; | 680 | (def_map.root(), def_map) |
681 | } | ||
682 | None => (self.expander.module, self.expander.def_map.clone()), | ||
683 | }; | ||
682 | let prev_def_map = mem::replace(&mut self.expander.def_map, def_map); | 684 | let prev_def_map = mem::replace(&mut self.expander.def_map, def_map); |
683 | let prev_local_module = mem::replace(&mut self.expander.module, module); | 685 | let prev_local_module = mem::replace(&mut self.expander.module, module); |
684 | let prev_statements = std::mem::take(&mut self.statements_in_scope); | 686 | let prev_statements = std::mem::take(&mut self.statements_in_scope); |
diff --git a/crates/hir_def/src/child_by_source.rs b/crates/hir_def/src/child_by_source.rs index 2a331dcaf..f40a7f80d 100644 --- a/crates/hir_def/src/child_by_source.rs +++ b/crates/hir_def/src/child_by_source.rs | |||
@@ -160,7 +160,7 @@ impl ChildBySource for EnumId { | |||
160 | impl ChildBySource for DefWithBodyId { | 160 | impl ChildBySource for DefWithBodyId { |
161 | fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { | 161 | fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { |
162 | let body = db.body(*self); | 162 | let body = db.body(*self); |
163 | for def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) { | 163 | for (_, def_map) in body.blocks(db) { |
164 | // All block expressions are merged into the same map, because they logically all add | 164 | // All block expressions are merged into the same map, because they logically all add |
165 | // inner items to the containing `DefWithBodyId`. | 165 | // inner items to the containing `DefWithBodyId`. |
166 | def_map[def_map.root()].scope.child_by_source_to(db, res); | 166 | def_map[def_map.root()].scope.child_by_source_to(db, res); |
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index 31f994681..135a6698e 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs | |||
@@ -10,7 +10,7 @@ use crate::{ | |||
10 | body::Expander, | 10 | body::Expander, |
11 | db::DefDatabase, | 11 | db::DefDatabase, |
12 | intern::Interned, | 12 | intern::Interned, |
13 | item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem, Param}, | 13 | item_tree::{AssocItem, FnFlags, ItemTreeId, ModItem, Param}, |
14 | type_ref::{TraitRef, TypeBound, TypeRef}, | 14 | type_ref::{TraitRef, TypeBound, TypeRef}, |
15 | visibility::RawVisibility, | 15 | visibility::RawVisibility, |
16 | AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, | 16 | AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, |
@@ -23,14 +23,9 @@ pub struct FunctionData { | |||
23 | pub params: Vec<Interned<TypeRef>>, | 23 | pub params: Vec<Interned<TypeRef>>, |
24 | pub ret_type: Interned<TypeRef>, | 24 | pub ret_type: Interned<TypeRef>, |
25 | pub attrs: Attrs, | 25 | pub attrs: Attrs, |
26 | /// True if the first param is `self`. This is relevant to decide whether this | ||
27 | /// can be called as a method. | ||
28 | pub has_self_param: bool, | ||
29 | pub has_body: bool, | ||
30 | pub qualifier: FunctionQualifier, | ||
31 | pub is_in_extern_block: bool, | ||
32 | pub is_varargs: bool, | ||
33 | pub visibility: RawVisibility, | 26 | pub visibility: RawVisibility, |
27 | pub abi: Option<Interned<str>>, | ||
28 | flags: FnFlags, | ||
34 | } | 29 | } |
35 | 30 | ||
36 | impl FunctionData { | 31 | impl FunctionData { |
@@ -53,6 +48,11 @@ impl FunctionData { | |||
53 | .next_back() | 48 | .next_back() |
54 | .map_or(false, |param| matches!(item_tree[param], Param::Varargs)); | 49 | .map_or(false, |param| matches!(item_tree[param], Param::Varargs)); |
55 | 50 | ||
51 | let mut flags = func.flags; | ||
52 | if is_varargs { | ||
53 | flags.bits |= FnFlags::IS_VARARGS; | ||
54 | } | ||
55 | |||
56 | Arc::new(FunctionData { | 56 | Arc::new(FunctionData { |
57 | name: func.name.clone(), | 57 | name: func.name.clone(), |
58 | params: enabled_params | 58 | params: enabled_params |
@@ -64,14 +64,45 @@ impl FunctionData { | |||
64 | .collect(), | 64 | .collect(), |
65 | ret_type: func.ret_type.clone(), | 65 | ret_type: func.ret_type.clone(), |
66 | attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), | 66 | attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), |
67 | has_self_param: func.has_self_param, | ||
68 | has_body: func.has_body, | ||
69 | qualifier: func.qualifier.clone(), | ||
70 | is_in_extern_block: func.is_in_extern_block, | ||
71 | is_varargs, | ||
72 | visibility: item_tree[func.visibility].clone(), | 67 | visibility: item_tree[func.visibility].clone(), |
68 | abi: func.abi.clone(), | ||
69 | flags, | ||
73 | }) | 70 | }) |
74 | } | 71 | } |
72 | |||
73 | pub fn has_body(&self) -> bool { | ||
74 | self.flags.bits & FnFlags::HAS_BODY != 0 | ||
75 | } | ||
76 | |||
77 | /// True if the first param is `self`. This is relevant to decide whether this | ||
78 | /// can be called as a method. | ||
79 | pub fn has_self_param(&self) -> bool { | ||
80 | self.flags.bits & FnFlags::HAS_SELF_PARAM != 0 | ||
81 | } | ||
82 | |||
83 | pub fn is_default(&self) -> bool { | ||
84 | self.flags.bits & FnFlags::IS_DEFAULT != 0 | ||
85 | } | ||
86 | |||
87 | pub fn is_const(&self) -> bool { | ||
88 | self.flags.bits & FnFlags::IS_CONST != 0 | ||
89 | } | ||
90 | |||
91 | pub fn is_async(&self) -> bool { | ||
92 | self.flags.bits & FnFlags::IS_ASYNC != 0 | ||
93 | } | ||
94 | |||
95 | pub fn is_unsafe(&self) -> bool { | ||
96 | self.flags.bits & FnFlags::IS_UNSAFE != 0 | ||
97 | } | ||
98 | |||
99 | pub fn is_in_extern_block(&self) -> bool { | ||
100 | self.flags.bits & FnFlags::IS_IN_EXTERN_BLOCK != 0 | ||
101 | } | ||
102 | |||
103 | pub fn is_varargs(&self) -> bool { | ||
104 | self.flags.bits & FnFlags::IS_VARARGS != 0 | ||
105 | } | ||
75 | } | 106 | } |
76 | 107 | ||
77 | #[derive(Debug, Clone, PartialEq, Eq)] | 108 | #[derive(Debug, Clone, PartialEq, Eq)] |
diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs index 068b2ee38..9b7a213a1 100644 --- a/crates/hir_def/src/db.rs +++ b/crates/hir_def/src/db.rs | |||
@@ -13,6 +13,7 @@ use crate::{ | |||
13 | data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData}, | 13 | data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData}, |
14 | generics::GenericParams, | 14 | generics::GenericParams, |
15 | import_map::ImportMap, | 15 | import_map::ImportMap, |
16 | intern::Interned, | ||
16 | item_tree::ItemTree, | 17 | item_tree::ItemTree, |
17 | lang_item::{LangItemTarget, LangItems}, | 18 | lang_item::{LangItemTarget, LangItems}, |
18 | nameres::DefMap, | 19 | nameres::DefMap, |
@@ -113,7 +114,7 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { | |||
113 | fn expr_scopes(&self, def: DefWithBodyId) -> Arc<ExprScopes>; | 114 | fn expr_scopes(&self, def: DefWithBodyId) -> Arc<ExprScopes>; |
114 | 115 | ||
115 | #[salsa::invoke(GenericParams::generic_params_query)] | 116 | #[salsa::invoke(GenericParams::generic_params_query)] |
116 | fn generic_params(&self, def: GenericDefId) -> Arc<GenericParams>; | 117 | fn generic_params(&self, def: GenericDefId) -> Interned<GenericParams>; |
117 | 118 | ||
118 | #[salsa::invoke(Attrs::variants_attrs_query)] | 119 | #[salsa::invoke(Attrs::variants_attrs_query)] |
119 | fn variants_attrs(&self, def: EnumId) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>>; | 120 | fn variants_attrs(&self, def: EnumId) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>>; |
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs index 7c6cbff11..de5acced8 100644 --- a/crates/hir_def/src/generics.rs +++ b/crates/hir_def/src/generics.rs | |||
@@ -2,7 +2,6 @@ | |||
2 | //! structs, impls, traits, etc. This module provides a common HIR for these | 2 | //! structs, impls, traits, etc. This module provides a common HIR for these |
3 | //! generic parameters. See also the `Generics` type and the `generics_of` query | 3 | //! generic parameters. See also the `Generics` type and the `generics_of` query |
4 | //! in rustc. | 4 | //! in rustc. |
5 | use std::sync::Arc; | ||
6 | 5 | ||
7 | use base_db::FileId; | 6 | use base_db::FileId; |
8 | use either::Either; | 7 | use either::Either; |
@@ -18,6 +17,7 @@ use crate::{ | |||
18 | child_by_source::ChildBySource, | 17 | child_by_source::ChildBySource, |
19 | db::DefDatabase, | 18 | db::DefDatabase, |
20 | dyn_map::DynMap, | 19 | dyn_map::DynMap, |
20 | intern::Interned, | ||
21 | keys, | 21 | keys, |
22 | src::{HasChildSource, HasSource}, | 22 | src::{HasChildSource, HasSource}, |
23 | type_ref::{LifetimeRef, TypeBound, TypeRef}, | 23 | type_ref::{LifetimeRef, TypeBound, TypeRef}, |
@@ -26,27 +26,27 @@ use crate::{ | |||
26 | }; | 26 | }; |
27 | 27 | ||
28 | /// Data about a generic type parameter (to a function, struct, impl, ...). | 28 | /// Data about a generic type parameter (to a function, struct, impl, ...). |
29 | #[derive(Clone, PartialEq, Eq, Debug)] | 29 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
30 | pub struct TypeParamData { | 30 | pub struct TypeParamData { |
31 | pub name: Option<Name>, | 31 | pub name: Option<Name>, |
32 | pub default: Option<TypeRef>, | 32 | pub default: Option<Interned<TypeRef>>, |
33 | pub provenance: TypeParamProvenance, | 33 | pub provenance: TypeParamProvenance, |
34 | } | 34 | } |
35 | 35 | ||
36 | /// Data about a generic lifetime parameter (to a function, struct, impl, ...). | 36 | /// Data about a generic lifetime parameter (to a function, struct, impl, ...). |
37 | #[derive(Clone, PartialEq, Eq, Debug)] | 37 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
38 | pub struct LifetimeParamData { | 38 | pub struct LifetimeParamData { |
39 | pub name: Name, | 39 | pub name: Name, |
40 | } | 40 | } |
41 | 41 | ||
42 | /// Data about a generic const parameter (to a function, struct, impl, ...). | 42 | /// Data about a generic const parameter (to a function, struct, impl, ...). |
43 | #[derive(Clone, PartialEq, Eq, Debug)] | 43 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
44 | pub struct ConstParamData { | 44 | pub struct ConstParamData { |
45 | pub name: Name, | 45 | pub name: Name, |
46 | pub ty: TypeRef, | 46 | pub ty: Interned<TypeRef>, |
47 | } | 47 | } |
48 | 48 | ||
49 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] | 49 | #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] |
50 | pub enum TypeParamProvenance { | 50 | pub enum TypeParamProvenance { |
51 | TypeParamList, | 51 | TypeParamList, |
52 | TraitSelf, | 52 | TraitSelf, |
@@ -54,7 +54,7 @@ pub enum TypeParamProvenance { | |||
54 | } | 54 | } |
55 | 55 | ||
56 | /// Data about the generic parameters of a function, struct, impl, etc. | 56 | /// Data about the generic parameters of a function, struct, impl, etc. |
57 | #[derive(Clone, PartialEq, Eq, Debug, Default)] | 57 | #[derive(Clone, PartialEq, Eq, Debug, Default, Hash)] |
58 | pub struct GenericParams { | 58 | pub struct GenericParams { |
59 | pub types: Arena<TypeParamData>, | 59 | pub types: Arena<TypeParamData>, |
60 | pub lifetimes: Arena<LifetimeParamData>, | 60 | pub lifetimes: Arena<LifetimeParamData>, |
@@ -66,16 +66,16 @@ pub struct GenericParams { | |||
66 | /// where clauses like `where T: Foo + Bar` are turned into multiple of these. | 66 | /// where clauses like `where T: Foo + Bar` are turned into multiple of these. |
67 | /// It might still result in multiple actual predicates though, because of | 67 | /// It might still result in multiple actual predicates though, because of |
68 | /// associated type bindings like `Iterator<Item = u32>`. | 68 | /// associated type bindings like `Iterator<Item = u32>`. |
69 | #[derive(Clone, PartialEq, Eq, Debug)] | 69 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
70 | pub enum WherePredicate { | 70 | pub enum WherePredicate { |
71 | TypeBound { target: WherePredicateTypeTarget, bound: TypeBound }, | 71 | TypeBound { target: WherePredicateTypeTarget, bound: TypeBound }, |
72 | Lifetime { target: LifetimeRef, bound: LifetimeRef }, | 72 | Lifetime { target: LifetimeRef, bound: LifetimeRef }, |
73 | ForLifetime { lifetimes: Box<[Name]>, target: WherePredicateTypeTarget, bound: TypeBound }, | 73 | ForLifetime { lifetimes: Box<[Name]>, target: WherePredicateTypeTarget, bound: TypeBound }, |
74 | } | 74 | } |
75 | 75 | ||
76 | #[derive(Clone, PartialEq, Eq, Debug)] | 76 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
77 | pub enum WherePredicateTypeTarget { | 77 | pub enum WherePredicateTypeTarget { |
78 | TypeRef(TypeRef), | 78 | TypeRef(Interned<TypeRef>), |
79 | /// For desugared where predicates that can directly refer to a type param. | 79 | /// For desugared where predicates that can directly refer to a type param. |
80 | TypeParam(LocalTypeParamId), | 80 | TypeParam(LocalTypeParamId), |
81 | } | 81 | } |
@@ -91,7 +91,7 @@ impl GenericParams { | |||
91 | pub(crate) fn generic_params_query( | 91 | pub(crate) fn generic_params_query( |
92 | db: &dyn DefDatabase, | 92 | db: &dyn DefDatabase, |
93 | def: GenericDefId, | 93 | def: GenericDefId, |
94 | ) -> Arc<GenericParams> { | 94 | ) -> Interned<GenericParams> { |
95 | let _p = profile::span("generic_params_query"); | 95 | let _p = profile::span("generic_params_query"); |
96 | 96 | ||
97 | let generics = match def { | 97 | let generics = match def { |
@@ -99,47 +99,49 @@ impl GenericParams { | |||
99 | let id = id.lookup(db).id; | 99 | let id = id.lookup(db).id; |
100 | let tree = id.item_tree(db); | 100 | let tree = id.item_tree(db); |
101 | let item = &tree[id.value]; | 101 | let item = &tree[id.value]; |
102 | tree[item.generic_params].clone() | 102 | item.generic_params.clone() |
103 | } | 103 | } |
104 | GenericDefId::AdtId(AdtId::StructId(id)) => { | 104 | GenericDefId::AdtId(AdtId::StructId(id)) => { |
105 | let id = id.lookup(db).id; | 105 | let id = id.lookup(db).id; |
106 | let tree = id.item_tree(db); | 106 | let tree = id.item_tree(db); |
107 | let item = &tree[id.value]; | 107 | let item = &tree[id.value]; |
108 | tree[item.generic_params].clone() | 108 | item.generic_params.clone() |
109 | } | 109 | } |
110 | GenericDefId::AdtId(AdtId::EnumId(id)) => { | 110 | GenericDefId::AdtId(AdtId::EnumId(id)) => { |
111 | let id = id.lookup(db).id; | 111 | let id = id.lookup(db).id; |
112 | let tree = id.item_tree(db); | 112 | let tree = id.item_tree(db); |
113 | let item = &tree[id.value]; | 113 | let item = &tree[id.value]; |
114 | tree[item.generic_params].clone() | 114 | item.generic_params.clone() |
115 | } | 115 | } |
116 | GenericDefId::AdtId(AdtId::UnionId(id)) => { | 116 | GenericDefId::AdtId(AdtId::UnionId(id)) => { |
117 | let id = id.lookup(db).id; | 117 | let id = id.lookup(db).id; |
118 | let tree = id.item_tree(db); | 118 | let tree = id.item_tree(db); |
119 | let item = &tree[id.value]; | 119 | let item = &tree[id.value]; |
120 | tree[item.generic_params].clone() | 120 | item.generic_params.clone() |
121 | } | 121 | } |
122 | GenericDefId::TraitId(id) => { | 122 | GenericDefId::TraitId(id) => { |
123 | let id = id.lookup(db).id; | 123 | let id = id.lookup(db).id; |
124 | let tree = id.item_tree(db); | 124 | let tree = id.item_tree(db); |
125 | let item = &tree[id.value]; | 125 | let item = &tree[id.value]; |
126 | tree[item.generic_params].clone() | 126 | item.generic_params.clone() |
127 | } | 127 | } |
128 | GenericDefId::TypeAliasId(id) => { | 128 | GenericDefId::TypeAliasId(id) => { |
129 | let id = id.lookup(db).id; | 129 | let id = id.lookup(db).id; |
130 | let tree = id.item_tree(db); | 130 | let tree = id.item_tree(db); |
131 | let item = &tree[id.value]; | 131 | let item = &tree[id.value]; |
132 | tree[item.generic_params].clone() | 132 | item.generic_params.clone() |
133 | } | 133 | } |
134 | GenericDefId::ImplId(id) => { | 134 | GenericDefId::ImplId(id) => { |
135 | let id = id.lookup(db).id; | 135 | let id = id.lookup(db).id; |
136 | let tree = id.item_tree(db); | 136 | let tree = id.item_tree(db); |
137 | let item = &tree[id.value]; | 137 | let item = &tree[id.value]; |
138 | tree[item.generic_params].clone() | 138 | item.generic_params.clone() |
139 | } | ||
140 | GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => { | ||
141 | Interned::new(GenericParams::default()) | ||
139 | } | 142 | } |
140 | GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => GenericParams::default(), | ||
141 | }; | 143 | }; |
142 | Arc::new(generics) | 144 | generics |
143 | } | 145 | } |
144 | 146 | ||
145 | fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) { | 147 | fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) { |
@@ -217,6 +219,7 @@ impl GenericParams { | |||
217 | GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => FileId(!0).into(), | 219 | GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => FileId(!0).into(), |
218 | }; | 220 | }; |
219 | 221 | ||
222 | generics.shrink_to_fit(); | ||
220 | (generics, InFile::new(file_id, sm)) | 223 | (generics, InFile::new(file_id, sm)) |
221 | } | 224 | } |
222 | 225 | ||
@@ -256,7 +259,8 @@ impl GenericParams { | |||
256 | for type_param in params.type_params() { | 259 | for type_param in params.type_params() { |
257 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); | 260 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); |
258 | // FIXME: Use `Path::from_src` | 261 | // FIXME: Use `Path::from_src` |
259 | let default = type_param.default_type().map(|it| TypeRef::from_ast(lower_ctx, it)); | 262 | let default = |
263 | type_param.default_type().map(|it| Interned::new(TypeRef::from_ast(lower_ctx, it))); | ||
260 | let param = TypeParamData { | 264 | let param = TypeParamData { |
261 | name: Some(name.clone()), | 265 | name: Some(name.clone()), |
262 | default, | 266 | default, |
@@ -280,7 +284,7 @@ impl GenericParams { | |||
280 | for const_param in params.const_params() { | 284 | for const_param in params.const_params() { |
281 | let name = const_param.name().map_or_else(Name::missing, |it| it.as_name()); | 285 | let name = const_param.name().map_or_else(Name::missing, |it| it.as_name()); |
282 | let ty = const_param.ty().map_or(TypeRef::Error, |it| TypeRef::from_ast(lower_ctx, it)); | 286 | let ty = const_param.ty().map_or(TypeRef::Error, |it| TypeRef::from_ast(lower_ctx, it)); |
283 | let param = ConstParamData { name, ty }; | 287 | let param = ConstParamData { name, ty: Interned::new(ty) }; |
284 | let param_id = self.consts.alloc(param); | 288 | let param_id = self.consts.alloc(param); |
285 | sm.const_params.insert(param_id, const_param.clone()); | 289 | sm.const_params.insert(param_id, const_param.clone()); |
286 | } | 290 | } |
@@ -334,11 +338,11 @@ impl GenericParams { | |||
334 | (Either::Left(type_ref), bound) => match hrtb_lifetimes { | 338 | (Either::Left(type_ref), bound) => match hrtb_lifetimes { |
335 | Some(hrtb_lifetimes) => WherePredicate::ForLifetime { | 339 | Some(hrtb_lifetimes) => WherePredicate::ForLifetime { |
336 | lifetimes: hrtb_lifetimes.clone(), | 340 | lifetimes: hrtb_lifetimes.clone(), |
337 | target: WherePredicateTypeTarget::TypeRef(type_ref), | 341 | target: WherePredicateTypeTarget::TypeRef(Interned::new(type_ref)), |
338 | bound, | 342 | bound, |
339 | }, | 343 | }, |
340 | None => WherePredicate::TypeBound { | 344 | None => WherePredicate::TypeBound { |
341 | target: WherePredicateTypeTarget::TypeRef(type_ref), | 345 | target: WherePredicateTypeTarget::TypeRef(Interned::new(type_ref)), |
342 | bound, | 346 | bound, |
343 | }, | 347 | }, |
344 | }, | 348 | }, |
@@ -369,6 +373,14 @@ impl GenericParams { | |||
369 | }); | 373 | }); |
370 | } | 374 | } |
371 | 375 | ||
376 | pub(crate) fn shrink_to_fit(&mut self) { | ||
377 | let Self { consts, lifetimes, types, where_predicates } = self; | ||
378 | consts.shrink_to_fit(); | ||
379 | lifetimes.shrink_to_fit(); | ||
380 | types.shrink_to_fit(); | ||
381 | where_predicates.shrink_to_fit(); | ||
382 | } | ||
383 | |||
372 | pub fn find_type_by_name(&self, name: &Name) -> Option<LocalTypeParamId> { | 384 | pub fn find_type_by_name(&self, name: &Name) -> Option<LocalTypeParamId> { |
373 | self.types | 385 | self.types |
374 | .iter() | 386 | .iter() |
diff --git a/crates/hir_def/src/intern.rs b/crates/hir_def/src/intern.rs index d163f633f..2467e9299 100644 --- a/crates/hir_def/src/intern.rs +++ b/crates/hir_def/src/intern.rs | |||
@@ -14,6 +14,8 @@ use dashmap::{lock::RwLockWriteGuard, DashMap, SharedValue}; | |||
14 | use once_cell::sync::OnceCell; | 14 | use once_cell::sync::OnceCell; |
15 | use rustc_hash::FxHasher; | 15 | use rustc_hash::FxHasher; |
16 | 16 | ||
17 | use crate::generics::GenericParams; | ||
18 | |||
17 | type InternMap<T> = DashMap<Arc<T>, (), BuildHasherDefault<FxHasher>>; | 19 | type InternMap<T> = DashMap<Arc<T>, (), BuildHasherDefault<FxHasher>>; |
18 | type Guard<T> = | 20 | type Guard<T> = |
19 | RwLockWriteGuard<'static, HashMap<Arc<T>, SharedValue<()>, BuildHasherDefault<FxHasher>>>; | 21 | RwLockWriteGuard<'static, HashMap<Arc<T>, SharedValue<()>, BuildHasherDefault<FxHasher>>>; |
@@ -194,4 +196,10 @@ macro_rules! impl_internable { | |||
194 | )+ }; | 196 | )+ }; |
195 | } | 197 | } |
196 | 198 | ||
197 | impl_internable!(crate::type_ref::TypeRef, crate::type_ref::TraitRef, crate::path::ModPath, str); | 199 | impl_internable!( |
200 | crate::type_ref::TypeRef, | ||
201 | crate::type_ref::TraitRef, | ||
202 | crate::path::ModPath, | ||
203 | GenericParams, | ||
204 | str | ||
205 | ); | ||
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs index f3ebe7c72..a8ee5eeac 100644 --- a/crates/hir_def/src/item_scope.rs +++ b/crates/hir_def/src/item_scope.rs | |||
@@ -285,6 +285,28 @@ impl ItemScope { | |||
285 | buf.push('\n'); | 285 | buf.push('\n'); |
286 | } | 286 | } |
287 | } | 287 | } |
288 | |||
289 | pub(crate) fn shrink_to_fit(&mut self) { | ||
290 | // Exhaustive match to require handling new fields. | ||
291 | let Self { | ||
292 | types, | ||
293 | values, | ||
294 | macros, | ||
295 | unresolved, | ||
296 | defs, | ||
297 | impls, | ||
298 | unnamed_trait_imports, | ||
299 | legacy_macros, | ||
300 | } = self; | ||
301 | types.shrink_to_fit(); | ||
302 | values.shrink_to_fit(); | ||
303 | macros.shrink_to_fit(); | ||
304 | unresolved.shrink_to_fit(); | ||
305 | defs.shrink_to_fit(); | ||
306 | impls.shrink_to_fit(); | ||
307 | unnamed_trait_imports.shrink_to_fit(); | ||
308 | legacy_macros.shrink_to_fit(); | ||
309 | } | ||
288 | } | 310 | } |
289 | 311 | ||
290 | impl PerNs { | 312 | impl PerNs { |
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 69a313c7e..240662486 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -24,7 +24,7 @@ use la_arena::{Arena, Idx, RawIdx}; | |||
24 | use profile::Count; | 24 | use profile::Count; |
25 | use rustc_hash::FxHashMap; | 25 | use rustc_hash::FxHashMap; |
26 | use smallvec::SmallVec; | 26 | use smallvec::SmallVec; |
27 | use syntax::{ast, match_ast, SmolStr, SyntaxKind}; | 27 | use syntax::{ast, match_ast, SyntaxKind}; |
28 | 28 | ||
29 | use crate::{ | 29 | use crate::{ |
30 | attr::{Attrs, RawAttrs}, | 30 | attr::{Attrs, RawAttrs}, |
@@ -58,13 +58,6 @@ impl fmt::Debug for RawVisibilityId { | |||
58 | } | 58 | } |
59 | } | 59 | } |
60 | 60 | ||
61 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] | ||
62 | pub struct GenericParamsId(u32); | ||
63 | |||
64 | impl GenericParamsId { | ||
65 | pub const EMPTY: Self = GenericParamsId(u32::max_value()); | ||
66 | } | ||
67 | |||
68 | /// The item tree of a source file. | 61 | /// The item tree of a source file. |
69 | #[derive(Debug, Default, Eq, PartialEq)] | 62 | #[derive(Debug, Default, Eq, PartialEq)] |
70 | pub struct ItemTree { | 63 | pub struct ItemTree { |
@@ -146,7 +139,6 @@ impl ItemTree { | |||
146 | macro_rules, | 139 | macro_rules, |
147 | macro_defs, | 140 | macro_defs, |
148 | vis, | 141 | vis, |
149 | generics, | ||
150 | inner_items, | 142 | inner_items, |
151 | } = &mut **data; | 143 | } = &mut **data; |
152 | 144 | ||
@@ -170,7 +162,6 @@ impl ItemTree { | |||
170 | macro_defs.shrink_to_fit(); | 162 | macro_defs.shrink_to_fit(); |
171 | 163 | ||
172 | vis.arena.shrink_to_fit(); | 164 | vis.arena.shrink_to_fit(); |
173 | generics.arena.shrink_to_fit(); | ||
174 | 165 | ||
175 | inner_items.shrink_to_fit(); | 166 | inner_items.shrink_to_fit(); |
176 | } | 167 | } |
@@ -242,32 +233,6 @@ static VIS_PRIV: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKi | |||
242 | static VIS_PUB_CRATE: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Crate)); | 233 | static VIS_PUB_CRATE: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Crate)); |
243 | 234 | ||
244 | #[derive(Default, Debug, Eq, PartialEq)] | 235 | #[derive(Default, Debug, Eq, PartialEq)] |
245 | struct GenericParamsStorage { | ||
246 | arena: Arena<GenericParams>, | ||
247 | } | ||
248 | |||
249 | impl GenericParamsStorage { | ||
250 | fn alloc(&mut self, params: GenericParams) -> GenericParamsId { | ||
251 | if params.types.is_empty() | ||
252 | && params.lifetimes.is_empty() | ||
253 | && params.consts.is_empty() | ||
254 | && params.where_predicates.is_empty() | ||
255 | { | ||
256 | return GenericParamsId::EMPTY; | ||
257 | } | ||
258 | |||
259 | GenericParamsId(self.arena.alloc(params).into_raw().into()) | ||
260 | } | ||
261 | } | ||
262 | |||
263 | static EMPTY_GENERICS: GenericParams = GenericParams { | ||
264 | types: Arena::new(), | ||
265 | lifetimes: Arena::new(), | ||
266 | consts: Arena::new(), | ||
267 | where_predicates: Vec::new(), | ||
268 | }; | ||
269 | |||
270 | #[derive(Default, Debug, Eq, PartialEq)] | ||
271 | struct ItemTreeData { | 236 | struct ItemTreeData { |
272 | imports: Arena<Import>, | 237 | imports: Arena<Import>, |
273 | extern_crates: Arena<ExternCrate>, | 238 | extern_crates: Arena<ExternCrate>, |
@@ -289,7 +254,6 @@ struct ItemTreeData { | |||
289 | macro_defs: Arena<MacroDef>, | 254 | macro_defs: Arena<MacroDef>, |
290 | 255 | ||
291 | vis: ItemVisibilities, | 256 | vis: ItemVisibilities, |
292 | generics: GenericParamsStorage, | ||
293 | 257 | ||
294 | inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>, | 258 | inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>, |
295 | } | 259 | } |
@@ -508,17 +472,6 @@ impl Index<RawVisibilityId> for ItemTree { | |||
508 | } | 472 | } |
509 | } | 473 | } |
510 | 474 | ||
511 | impl Index<GenericParamsId> for ItemTree { | ||
512 | type Output = GenericParams; | ||
513 | |||
514 | fn index(&self, index: GenericParamsId) -> &Self::Output { | ||
515 | match index { | ||
516 | GenericParamsId::EMPTY => &EMPTY_GENERICS, | ||
517 | _ => &self.data().generics.arena[Idx::from_raw(index.0.into())], | ||
518 | } | ||
519 | } | ||
520 | } | ||
521 | |||
522 | impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { | 475 | impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { |
523 | type Output = N; | 476 | type Output = N; |
524 | fn index(&self, id: FileItemTreeId<N>) -> &N { | 477 | fn index(&self, id: FileItemTreeId<N>) -> &N { |
@@ -529,7 +482,7 @@ impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { | |||
529 | /// A desugared `use` import. | 482 | /// A desugared `use` import. |
530 | #[derive(Debug, Clone, Eq, PartialEq)] | 483 | #[derive(Debug, Clone, Eq, PartialEq)] |
531 | pub struct Import { | 484 | pub struct Import { |
532 | pub path: ModPath, | 485 | pub path: Interned<ModPath>, |
533 | pub alias: Option<ImportAlias>, | 486 | pub alias: Option<ImportAlias>, |
534 | pub visibility: RawVisibilityId, | 487 | pub visibility: RawVisibilityId, |
535 | pub is_glob: bool, | 488 | pub is_glob: bool, |
@@ -555,16 +508,12 @@ pub struct ExternCrate { | |||
555 | pub struct Function { | 508 | pub struct Function { |
556 | pub name: Name, | 509 | pub name: Name, |
557 | pub visibility: RawVisibilityId, | 510 | pub visibility: RawVisibilityId, |
558 | pub generic_params: GenericParamsId, | 511 | pub generic_params: Interned<GenericParams>, |
559 | pub has_self_param: bool, | 512 | pub abi: Option<Interned<str>>, |
560 | pub has_body: bool, | ||
561 | pub qualifier: FunctionQualifier, | ||
562 | /// Whether the function is located in an `extern` block (*not* whether it is an | ||
563 | /// `extern "abi" fn`). | ||
564 | pub is_in_extern_block: bool, | ||
565 | pub params: IdRange<Param>, | 513 | pub params: IdRange<Param>, |
566 | pub ret_type: Interned<TypeRef>, | 514 | pub ret_type: Interned<TypeRef>, |
567 | pub ast_id: FileAstId<ast::Fn>, | 515 | pub ast_id: FileAstId<ast::Fn>, |
516 | pub(crate) flags: FnFlags, | ||
568 | } | 517 | } |
569 | 518 | ||
570 | #[derive(Debug, Clone, Eq, PartialEq)] | 519 | #[derive(Debug, Clone, Eq, PartialEq)] |
@@ -573,20 +522,28 @@ pub enum Param { | |||
573 | Varargs, | 522 | Varargs, |
574 | } | 523 | } |
575 | 524 | ||
576 | #[derive(Debug, Clone, PartialEq, Eq)] | 525 | #[derive(Debug, Clone, Copy, Eq, PartialEq, Default)] |
577 | pub struct FunctionQualifier { | 526 | pub(crate) struct FnFlags { |
578 | pub is_default: bool, | 527 | pub(crate) bits: u8, |
579 | pub is_const: bool, | 528 | } |
580 | pub is_async: bool, | 529 | impl FnFlags { |
581 | pub is_unsafe: bool, | 530 | pub(crate) const HAS_SELF_PARAM: u8 = 1 << 0; |
582 | pub abi: Option<SmolStr>, | 531 | pub(crate) const HAS_BODY: u8 = 1 << 1; |
532 | pub(crate) const IS_DEFAULT: u8 = 1 << 2; | ||
533 | pub(crate) const IS_CONST: u8 = 1 << 3; | ||
534 | pub(crate) const IS_ASYNC: u8 = 1 << 4; | ||
535 | pub(crate) const IS_UNSAFE: u8 = 1 << 5; | ||
536 | /// Whether the function is located in an `extern` block (*not* whether it is an | ||
537 | /// `extern "abi" fn`). | ||
538 | pub(crate) const IS_IN_EXTERN_BLOCK: u8 = 1 << 6; | ||
539 | pub(crate) const IS_VARARGS: u8 = 1 << 7; | ||
583 | } | 540 | } |
584 | 541 | ||
585 | #[derive(Debug, Clone, Eq, PartialEq)] | 542 | #[derive(Debug, Clone, Eq, PartialEq)] |
586 | pub struct Struct { | 543 | pub struct Struct { |
587 | pub name: Name, | 544 | pub name: Name, |
588 | pub visibility: RawVisibilityId, | 545 | pub visibility: RawVisibilityId, |
589 | pub generic_params: GenericParamsId, | 546 | pub generic_params: Interned<GenericParams>, |
590 | pub fields: Fields, | 547 | pub fields: Fields, |
591 | pub ast_id: FileAstId<ast::Struct>, | 548 | pub ast_id: FileAstId<ast::Struct>, |
592 | pub kind: StructDefKind, | 549 | pub kind: StructDefKind, |
@@ -606,7 +563,7 @@ pub enum StructDefKind { | |||
606 | pub struct Union { | 563 | pub struct Union { |
607 | pub name: Name, | 564 | pub name: Name, |
608 | pub visibility: RawVisibilityId, | 565 | pub visibility: RawVisibilityId, |
609 | pub generic_params: GenericParamsId, | 566 | pub generic_params: Interned<GenericParams>, |
610 | pub fields: Fields, | 567 | pub fields: Fields, |
611 | pub ast_id: FileAstId<ast::Union>, | 568 | pub ast_id: FileAstId<ast::Union>, |
612 | } | 569 | } |
@@ -615,7 +572,7 @@ pub struct Union { | |||
615 | pub struct Enum { | 572 | pub struct Enum { |
616 | pub name: Name, | 573 | pub name: Name, |
617 | pub visibility: RawVisibilityId, | 574 | pub visibility: RawVisibilityId, |
618 | pub generic_params: GenericParamsId, | 575 | pub generic_params: Interned<GenericParams>, |
619 | pub variants: IdRange<Variant>, | 576 | pub variants: IdRange<Variant>, |
620 | pub ast_id: FileAstId<ast::Enum>, | 577 | pub ast_id: FileAstId<ast::Enum>, |
621 | } | 578 | } |
@@ -644,7 +601,7 @@ pub struct Static { | |||
644 | pub struct Trait { | 601 | pub struct Trait { |
645 | pub name: Name, | 602 | pub name: Name, |
646 | pub visibility: RawVisibilityId, | 603 | pub visibility: RawVisibilityId, |
647 | pub generic_params: GenericParamsId, | 604 | pub generic_params: Interned<GenericParams>, |
648 | pub is_auto: bool, | 605 | pub is_auto: bool, |
649 | pub is_unsafe: bool, | 606 | pub is_unsafe: bool, |
650 | pub bounds: Box<[TypeBound]>, | 607 | pub bounds: Box<[TypeBound]>, |
@@ -654,7 +611,7 @@ pub struct Trait { | |||
654 | 611 | ||
655 | #[derive(Debug, Clone, Eq, PartialEq)] | 612 | #[derive(Debug, Clone, Eq, PartialEq)] |
656 | pub struct Impl { | 613 | pub struct Impl { |
657 | pub generic_params: GenericParamsId, | 614 | pub generic_params: Interned<GenericParams>, |
658 | pub target_trait: Option<Interned<TraitRef>>, | 615 | pub target_trait: Option<Interned<TraitRef>>, |
659 | pub self_ty: Interned<TypeRef>, | 616 | pub self_ty: Interned<TypeRef>, |
660 | pub is_negative: bool, | 617 | pub is_negative: bool, |
@@ -668,7 +625,7 @@ pub struct TypeAlias { | |||
668 | pub visibility: RawVisibilityId, | 625 | pub visibility: RawVisibilityId, |
669 | /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`. | 626 | /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`. |
670 | pub bounds: Box<[TypeBound]>, | 627 | pub bounds: Box<[TypeBound]>, |
671 | pub generic_params: GenericParamsId, | 628 | pub generic_params: Interned<GenericParams>, |
672 | pub type_ref: Option<Interned<TypeRef>>, | 629 | pub type_ref: Option<Interned<TypeRef>>, |
673 | pub is_extern: bool, | 630 | pub is_extern: bool, |
674 | pub ast_id: FileAstId<ast::TypeAlias>, | 631 | pub ast_id: FileAstId<ast::TypeAlias>, |
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 5247379c5..c5629af24 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs | |||
@@ -395,39 +395,51 @@ impl Ctx { | |||
395 | ret_type | 395 | ret_type |
396 | }; | 396 | }; |
397 | 397 | ||
398 | let has_body = func.body().is_some(); | 398 | let abi = func.abi().map(|abi| { |
399 | // FIXME: Abi::abi() -> Option<SyntaxToken>? | ||
400 | match abi.syntax().last_token() { | ||
401 | Some(tok) if tok.kind() == SyntaxKind::STRING => { | ||
402 | // FIXME: Better way to unescape? | ||
403 | Interned::new_str(tok.text().trim_matches('"')) | ||
404 | } | ||
405 | _ => { | ||
406 | // `extern` default to be `extern "C"`. | ||
407 | Interned::new_str("C") | ||
408 | } | ||
409 | } | ||
410 | }); | ||
399 | 411 | ||
400 | let ast_id = self.source_ast_id_map.ast_id(func); | 412 | let ast_id = self.source_ast_id_map.ast_id(func); |
401 | let qualifier = FunctionQualifier { | 413 | |
402 | is_default: func.default_token().is_some(), | 414 | let mut flags = FnFlags::default(); |
403 | is_const: func.const_token().is_some(), | 415 | if func.body().is_some() { |
404 | is_async: func.async_token().is_some(), | 416 | flags.bits |= FnFlags::HAS_BODY; |
405 | is_unsafe: func.unsafe_token().is_some(), | 417 | } |
406 | abi: func.abi().map(|abi| { | 418 | if has_self_param { |
407 | // FIXME: Abi::abi() -> Option<SyntaxToken>? | 419 | flags.bits |= FnFlags::HAS_SELF_PARAM; |
408 | match abi.syntax().last_token() { | 420 | } |
409 | Some(tok) if tok.kind() == SyntaxKind::STRING => { | 421 | if func.default_token().is_some() { |
410 | // FIXME: Better way to unescape? | 422 | flags.bits |= FnFlags::IS_DEFAULT; |
411 | tok.text().trim_matches('"').into() | 423 | } |
412 | } | 424 | if func.const_token().is_some() { |
413 | _ => { | 425 | flags.bits |= FnFlags::IS_CONST; |
414 | // `extern` default to be `extern "C"`. | 426 | } |
415 | "C".into() | 427 | if func.async_token().is_some() { |
416 | } | 428 | flags.bits |= FnFlags::IS_ASYNC; |
417 | } | 429 | } |
418 | }), | 430 | if func.unsafe_token().is_some() { |
419 | }; | 431 | flags.bits |= FnFlags::IS_UNSAFE; |
432 | } | ||
433 | |||
420 | let mut res = Function { | 434 | let mut res = Function { |
421 | name, | 435 | name, |
422 | visibility, | 436 | visibility, |
423 | generic_params: GenericParamsId::EMPTY, | 437 | generic_params: Interned::new(GenericParams::default()), |
424 | has_self_param, | 438 | abi, |
425 | has_body, | ||
426 | qualifier, | ||
427 | is_in_extern_block: false, | ||
428 | params, | 439 | params, |
429 | ret_type: Interned::new(ret_type), | 440 | ret_type: Interned::new(ret_type), |
430 | ast_id, | 441 | ast_id, |
442 | flags, | ||
431 | }; | 443 | }; |
432 | res.generic_params = self.lower_generic_params(GenericsOwner::Function(&res), func); | 444 | res.generic_params = self.lower_generic_params(GenericsOwner::Function(&res), func); |
433 | 445 | ||
@@ -577,7 +589,7 @@ impl Ctx { | |||
577 | &self.hygiene, | 589 | &self.hygiene, |
578 | |path, _use_tree, is_glob, alias| { | 590 | |path, _use_tree, is_glob, alias| { |
579 | imports.push(id(tree.imports.alloc(Import { | 591 | imports.push(id(tree.imports.alloc(Import { |
580 | path, | 592 | path: Interned::new(path), |
581 | alias, | 593 | alias, |
582 | visibility, | 594 | visibility, |
583 | is_glob, | 595 | is_glob, |
@@ -640,8 +652,10 @@ impl Ctx { | |||
640 | ast::ExternItem::Fn(ast) => { | 652 | ast::ExternItem::Fn(ast) => { |
641 | let func_id = self.lower_function(&ast)?; | 653 | let func_id = self.lower_function(&ast)?; |
642 | let func = &mut self.data().functions[func_id.index]; | 654 | let func = &mut self.data().functions[func_id.index]; |
643 | func.qualifier.is_unsafe = is_intrinsic_fn_unsafe(&func.name); | 655 | if is_intrinsic_fn_unsafe(&func.name) { |
644 | func.is_in_extern_block = true; | 656 | func.flags.bits |= FnFlags::IS_UNSAFE; |
657 | } | ||
658 | func.flags.bits |= FnFlags::IS_IN_EXTERN_BLOCK; | ||
645 | func_id.into() | 659 | func_id.into() |
646 | } | 660 | } |
647 | ast::ExternItem::Static(ast) => { | 661 | ast::ExternItem::Static(ast) => { |
@@ -668,7 +682,7 @@ impl Ctx { | |||
668 | &mut self, | 682 | &mut self, |
669 | owner: GenericsOwner<'_>, | 683 | owner: GenericsOwner<'_>, |
670 | node: &impl ast::GenericParamsOwner, | 684 | node: &impl ast::GenericParamsOwner, |
671 | ) -> GenericParamsId { | 685 | ) -> Interned<GenericParams> { |
672 | // Generics are part of item headers and may contain inner items we need to collect. | 686 | // Generics are part of item headers and may contain inner items we need to collect. |
673 | if let Some(params) = node.generic_param_list() { | 687 | if let Some(params) = node.generic_param_list() { |
674 | self.collect_inner_items(params.syntax()); | 688 | self.collect_inner_items(params.syntax()); |
@@ -684,7 +698,7 @@ impl Ctx { | |||
684 | &mut self, | 698 | &mut self, |
685 | owner: GenericsOwner<'_>, | 699 | owner: GenericsOwner<'_>, |
686 | node: &impl ast::GenericParamsOwner, | 700 | node: &impl ast::GenericParamsOwner, |
687 | ) -> GenericParamsId { | 701 | ) -> Interned<GenericParams> { |
688 | let mut sm = &mut Default::default(); | 702 | let mut sm = &mut Default::default(); |
689 | let mut generics = GenericParams::default(); | 703 | let mut generics = GenericParams::default(); |
690 | match owner { | 704 | match owner { |
@@ -725,7 +739,8 @@ impl Ctx { | |||
725 | } | 739 | } |
726 | } | 740 | } |
727 | 741 | ||
728 | self.data().generics.alloc(generics) | 742 | generics.shrink_to_fit(); |
743 | Interned::new(generics) | ||
729 | } | 744 | } |
730 | 745 | ||
731 | fn lower_type_bounds(&mut self, node: &impl ast::TypeBoundsOwner) -> Vec<TypeBound> { | 746 | fn lower_type_bounds(&mut self, node: &impl ast::TypeBoundsOwner) -> Vec<TypeBound> { |
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index f408e510a..be9a5e1a0 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs | |||
@@ -27,6 +27,7 @@ pub mod dyn_map; | |||
27 | pub mod keys; | 27 | pub mod keys; |
28 | 28 | ||
29 | pub mod item_tree; | 29 | pub mod item_tree; |
30 | pub mod intern; | ||
30 | 31 | ||
31 | pub mod adt; | 32 | pub mod adt; |
32 | pub mod data; | 33 | pub mod data; |
@@ -49,7 +50,6 @@ pub mod import_map; | |||
49 | 50 | ||
50 | #[cfg(test)] | 51 | #[cfg(test)] |
51 | mod test_db; | 52 | mod test_db; |
52 | mod intern; | ||
53 | 53 | ||
54 | use std::{ | 54 | use std::{ |
55 | hash::{Hash, Hasher}, | 55 | hash::{Hash, Hasher}, |
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index 9e8e4e9ec..7dd68219f 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs | |||
@@ -409,6 +409,31 @@ impl DefMap { | |||
409 | } | 409 | } |
410 | } | 410 | } |
411 | } | 411 | } |
412 | |||
413 | fn shrink_to_fit(&mut self) { | ||
414 | // Exhaustive match to require handling new fields. | ||
415 | let Self { | ||
416 | _c: _, | ||
417 | exported_proc_macros, | ||
418 | extern_prelude, | ||
419 | diagnostics, | ||
420 | modules, | ||
421 | block: _, | ||
422 | edition: _, | ||
423 | krate: _, | ||
424 | prelude: _, | ||
425 | root: _, | ||
426 | } = self; | ||
427 | |||
428 | extern_prelude.shrink_to_fit(); | ||
429 | exported_proc_macros.shrink_to_fit(); | ||
430 | diagnostics.shrink_to_fit(); | ||
431 | modules.shrink_to_fit(); | ||
432 | for (_, module) in modules.iter_mut() { | ||
433 | module.children.shrink_to_fit(); | ||
434 | module.scope.shrink_to_fit(); | ||
435 | } | ||
436 | } | ||
412 | } | 437 | } |
413 | 438 | ||
414 | impl ModuleData { | 439 | impl ModuleData { |
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index c8f494707..4ddc791ce 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -23,6 +23,7 @@ use crate::{ | |||
23 | attr::Attrs, | 23 | attr::Attrs, |
24 | db::DefDatabase, | 24 | db::DefDatabase, |
25 | derive_macro_as_call_id, | 25 | derive_macro_as_call_id, |
26 | intern::Interned, | ||
26 | item_scope::{ImportType, PerNsGlobImports}, | 27 | item_scope::{ImportType, PerNsGlobImports}, |
27 | item_tree::{ | 28 | item_tree::{ |
28 | self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroDef, MacroRules, Mod, ModItem, | 29 | self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroDef, MacroRules, Mod, ModItem, |
@@ -108,7 +109,9 @@ pub(super) fn collect_defs( | |||
108 | } | 109 | } |
109 | } | 110 | } |
110 | collector.collect(); | 111 | collector.collect(); |
111 | collector.finish() | 112 | let mut def_map = collector.finish(); |
113 | def_map.shrink_to_fit(); | ||
114 | def_map | ||
112 | } | 115 | } |
113 | 116 | ||
114 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] | 117 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] |
@@ -139,7 +142,7 @@ enum ImportSource { | |||
139 | 142 | ||
140 | #[derive(Clone, Debug, Eq, PartialEq)] | 143 | #[derive(Clone, Debug, Eq, PartialEq)] |
141 | struct Import { | 144 | struct Import { |
142 | path: ModPath, | 145 | path: Interned<ModPath>, |
143 | alias: Option<ImportAlias>, | 146 | alias: Option<ImportAlias>, |
144 | visibility: RawVisibility, | 147 | visibility: RawVisibility, |
145 | is_glob: bool, | 148 | is_glob: bool, |
@@ -181,7 +184,10 @@ impl Import { | |||
181 | let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into()); | 184 | let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into()); |
182 | let visibility = &tree[it.visibility]; | 185 | let visibility = &tree[it.visibility]; |
183 | Self { | 186 | Self { |
184 | path: ModPath::from_segments(PathKind::Plain, iter::once(it.name.clone())), | 187 | path: Interned::new(ModPath::from_segments( |
188 | PathKind::Plain, | ||
189 | iter::once(it.name.clone()), | ||
190 | )), | ||
185 | alias: it.alias.clone(), | 191 | alias: it.alias.clone(), |
186 | visibility: visibility.clone(), | 192 | visibility: visibility.clone(), |
187 | is_glob: false, | 193 | is_glob: false, |
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs index a3e83e2cf..f9c8328f0 100644 --- a/crates/hir_def/src/path.rs +++ b/crates/hir_def/src/path.rs | |||
@@ -122,7 +122,7 @@ impl ModPath { | |||
122 | pub struct Path { | 122 | pub struct Path { |
123 | /// Type based path like `<T>::foo`. | 123 | /// Type based path like `<T>::foo`. |
124 | /// Note that paths like `<Type as Trait>::foo` are desugard to `Trait::<Self=Type>::foo`. | 124 | /// Note that paths like `<Type as Trait>::foo` are desugard to `Trait::<Self=Type>::foo`. |
125 | type_anchor: Option<Box<TypeRef>>, | 125 | type_anchor: Option<Interned<TypeRef>>, |
126 | mod_path: Interned<ModPath>, | 126 | mod_path: Interned<ModPath>, |
127 | /// Invariant: the same len as `self.mod_path.segments` | 127 | /// Invariant: the same len as `self.mod_path.segments` |
128 | generic_args: Vec<Option<Arc<GenericArgs>>>, | 128 | generic_args: Vec<Option<Arc<GenericArgs>>>, |
diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs index 28f6244da..7b29d9d4f 100644 --- a/crates/hir_def/src/path/lower.rs +++ b/crates/hir_def/src/path/lower.rs | |||
@@ -69,7 +69,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> | |||
69 | match trait_ref { | 69 | match trait_ref { |
70 | // <T>::foo | 70 | // <T>::foo |
71 | None => { | 71 | None => { |
72 | type_anchor = Some(Box::new(self_type)); | 72 | type_anchor = Some(Interned::new(self_type)); |
73 | kind = PathKind::Plain; | 73 | kind = PathKind::Plain; |
74 | } | 74 | } |
75 | // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo | 75 | // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo |
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index a73585ee7..0391cc49b 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs | |||
@@ -14,6 +14,7 @@ use crate::{ | |||
14 | db::DefDatabase, | 14 | db::DefDatabase, |
15 | expr::{ExprId, LabelId, PatId}, | 15 | expr::{ExprId, LabelId, PatId}, |
16 | generics::GenericParams, | 16 | generics::GenericParams, |
17 | intern::Interned, | ||
17 | item_scope::{BuiltinShadowMode, BUILTIN_SCOPE}, | 18 | item_scope::{BuiltinShadowMode, BUILTIN_SCOPE}, |
18 | nameres::DefMap, | 19 | nameres::DefMap, |
19 | path::{ModPath, PathKind}, | 20 | path::{ModPath, PathKind}, |
@@ -50,7 +51,7 @@ enum Scope { | |||
50 | /// All the items and imported names of a module | 51 | /// All the items and imported names of a module |
51 | ModuleScope(ModuleItemMap), | 52 | ModuleScope(ModuleItemMap), |
52 | /// Brings the generic parameters of an item into scope | 53 | /// Brings the generic parameters of an item into scope |
53 | GenericParams { def: GenericDefId, params: Arc<GenericParams> }, | 54 | GenericParams { def: GenericDefId, params: Interned<GenericParams> }, |
54 | /// Brings `Self` in `impl` block into scope | 55 | /// Brings `Self` in `impl` block into scope |
55 | ImplDefScope(ImplId), | 56 | ImplDefScope(ImplId), |
56 | /// Brings `Self` in enum, struct and union definitions into scope | 57 | /// Brings `Self` in enum, struct and union definitions into scope |
diff --git a/crates/hir_def/src/visibility.rs b/crates/hir_def/src/visibility.rs index 7d00a37c4..9908cd926 100644 --- a/crates/hir_def/src/visibility.rs +++ b/crates/hir_def/src/visibility.rs | |||
@@ -11,7 +11,7 @@ use crate::{ | |||
11 | nameres::DefMap, | 11 | nameres::DefMap, |
12 | path::{ModPath, PathKind}, | 12 | path::{ModPath, PathKind}, |
13 | resolver::HasResolver, | 13 | resolver::HasResolver, |
14 | FunctionId, HasModule, LocalFieldId, ModuleDefId, ModuleId, VariantId, | 14 | FunctionId, HasModule, LocalFieldId, ModuleId, VariantId, |
15 | }; | 15 | }; |
16 | 16 | ||
17 | /// Visibility of an item, not yet resolved. | 17 | /// Visibility of an item, not yet resolved. |
@@ -25,7 +25,7 @@ pub enum RawVisibility { | |||
25 | } | 25 | } |
26 | 26 | ||
27 | impl RawVisibility { | 27 | impl RawVisibility { |
28 | pub(crate) const fn private() -> RawVisibility { | 28 | pub(crate) fn private() -> RawVisibility { |
29 | RawVisibility::Module(ModPath::from_kind(PathKind::Super(0))) | 29 | RawVisibility::Module(ModPath::from_kind(PathKind::Super(0))) |
30 | } | 30 | } |
31 | 31 | ||
@@ -217,6 +217,6 @@ pub(crate) fn field_visibilities_query( | |||
217 | 217 | ||
218 | /// Resolve visibility of a function. | 218 | /// Resolve visibility of a function. |
219 | pub(crate) fn function_visibility_query(db: &dyn DefDatabase, def: FunctionId) -> Visibility { | 219 | pub(crate) fn function_visibility_query(db: &dyn DefDatabase, def: FunctionId) -> Visibility { |
220 | let resolver = ModuleDefId::from(def).module(db).unwrap().resolver(db); | 220 | let resolver = def.resolver(db); |
221 | db.function_data(def).visibility.resolve(db, &resolver) | 221 | db.function_data(def).visibility.resolve(db, &resolver) |
222 | } | 222 | } |