diff options
Diffstat (limited to 'crates/ra_hir_def/src/generics.rs')
-rw-r--r-- | crates/ra_hir_def/src/generics.rs | 174 |
1 files changed, 97 insertions, 77 deletions
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index 3f94e40e4..e9c28c730 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs | |||
@@ -4,20 +4,29 @@ | |||
4 | //! in rustc. | 4 | //! in rustc. |
5 | use std::sync::Arc; | 5 | use std::sync::Arc; |
6 | 6 | ||
7 | use hir_expand::name::{self, AsName, Name}; | 7 | use either::Either; |
8 | use hir_expand::{ | ||
9 | name::{name, AsName, Name}, | ||
10 | InFile, | ||
11 | }; | ||
12 | use ra_arena::{map::ArenaMap, Arena}; | ||
13 | use ra_db::FileId; | ||
8 | use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; | 14 | use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; |
9 | 15 | ||
10 | use crate::{ | 16 | use crate::{ |
17 | child_by_source::ChildBySource, | ||
11 | db::DefDatabase, | 18 | db::DefDatabase, |
19 | dyn_map::DynMap, | ||
20 | keys, | ||
21 | src::HasChildSource, | ||
22 | src::HasSource, | ||
12 | type_ref::{TypeBound, TypeRef}, | 23 | type_ref::{TypeBound, TypeRef}, |
13 | AdtId, AstItemDef, ContainerId, GenericDefId, HasSource, Lookup, | 24 | AdtId, GenericDefId, LocalTypeParamId, Lookup, TypeParamId, |
14 | }; | 25 | }; |
15 | 26 | ||
16 | /// Data about a generic parameter (to a function, struct, impl, ...). | 27 | /// Data about a generic parameter (to a function, struct, impl, ...). |
17 | #[derive(Clone, PartialEq, Eq, Debug)] | 28 | #[derive(Clone, PartialEq, Eq, Debug)] |
18 | pub struct GenericParam { | 29 | pub struct TypeParamData { |
19 | // FIXME: give generic params proper IDs | ||
20 | pub idx: u32, | ||
21 | pub name: Name, | 30 | pub name: Name, |
22 | pub default: Option<TypeRef>, | 31 | pub default: Option<TypeRef>, |
23 | } | 32 | } |
@@ -25,8 +34,8 @@ pub struct GenericParam { | |||
25 | /// Data about the generic parameters of a function, struct, impl, etc. | 34 | /// Data about the generic parameters of a function, struct, impl, etc. |
26 | #[derive(Clone, PartialEq, Eq, Debug)] | 35 | #[derive(Clone, PartialEq, Eq, Debug)] |
27 | pub struct GenericParams { | 36 | pub struct GenericParams { |
28 | pub parent_params: Option<Arc<GenericParams>>, | 37 | pub types: Arena<LocalTypeParamId, TypeParamData>, |
29 | pub params: Vec<GenericParam>, | 38 | // lifetimes: Arena<LocalLifetimeParamId, LifetimeParamData>, |
30 | pub where_predicates: Vec<WherePredicate>, | 39 | pub where_predicates: Vec<WherePredicate>, |
31 | } | 40 | } |
32 | 41 | ||
@@ -40,63 +49,87 @@ pub struct WherePredicate { | |||
40 | pub bound: TypeBound, | 49 | pub bound: TypeBound, |
41 | } | 50 | } |
42 | 51 | ||
52 | type SourceMap = ArenaMap<LocalTypeParamId, Either<ast::TraitDef, ast::TypeParam>>; | ||
53 | |||
43 | impl GenericParams { | 54 | impl GenericParams { |
44 | pub(crate) fn generic_params_query( | 55 | pub(crate) fn generic_params_query( |
45 | db: &impl DefDatabase, | 56 | db: &impl DefDatabase, |
46 | def: GenericDefId, | 57 | def: GenericDefId, |
47 | ) -> Arc<GenericParams> { | 58 | ) -> Arc<GenericParams> { |
48 | let parent_generics = parent_generic_def(db, def).map(|it| db.generic_params(it)); | 59 | let (params, _source_map) = GenericParams::new(db, def.into()); |
49 | Arc::new(GenericParams::new(db, def.into(), parent_generics)) | 60 | Arc::new(params) |
50 | } | 61 | } |
51 | 62 | ||
52 | fn new( | 63 | fn new(db: &impl DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) { |
53 | db: &impl DefDatabase, | 64 | let mut generics = GenericParams { types: Arena::default(), where_predicates: Vec::new() }; |
54 | def: GenericDefId, | 65 | let mut sm = ArenaMap::default(); |
55 | parent_params: Option<Arc<GenericParams>>, | ||
56 | ) -> GenericParams { | ||
57 | let mut generics = | ||
58 | GenericParams { params: Vec::new(), parent_params, where_predicates: Vec::new() }; | ||
59 | let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32; | ||
60 | // FIXME: add `: Sized` bound for everything except for `Self` in traits | 66 | // FIXME: add `: Sized` bound for everything except for `Self` in traits |
61 | match def { | 67 | let file_id = match def { |
62 | GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value, start), | 68 | GenericDefId::FunctionId(it) => { |
63 | GenericDefId::AdtId(AdtId::StructId(it)) => generics.fill(&it.source(db).value, start), | 69 | let src = it.lookup(db).source(db); |
64 | GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.source(db).value, start), | 70 | generics.fill(&mut sm, &src.value); |
65 | GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value, start), | 71 | src.file_id |
72 | } | ||
73 | GenericDefId::AdtId(AdtId::StructId(it)) => { | ||
74 | let src = it.lookup(db).source(db); | ||
75 | generics.fill(&mut sm, &src.value); | ||
76 | src.file_id | ||
77 | } | ||
78 | GenericDefId::AdtId(AdtId::UnionId(it)) => { | ||
79 | let src = it.lookup(db).source(db); | ||
80 | generics.fill(&mut sm, &src.value); | ||
81 | src.file_id | ||
82 | } | ||
83 | GenericDefId::AdtId(AdtId::EnumId(it)) => { | ||
84 | let src = it.lookup(db).source(db); | ||
85 | generics.fill(&mut sm, &src.value); | ||
86 | src.file_id | ||
87 | } | ||
66 | GenericDefId::TraitId(it) => { | 88 | GenericDefId::TraitId(it) => { |
89 | let src = it.lookup(db).source(db); | ||
90 | |||
67 | // traits get the Self type as an implicit first type parameter | 91 | // traits get the Self type as an implicit first type parameter |
68 | generics.params.push(GenericParam { | 92 | let self_param_id = |
69 | idx: start, | 93 | generics.types.alloc(TypeParamData { name: name![Self], default: None }); |
70 | name: name::SELF_TYPE, | 94 | sm.insert(self_param_id, Either::Left(src.value.clone())); |
71 | default: None, | ||
72 | }); | ||
73 | generics.fill(&it.source(db).value, start + 1); | ||
74 | // add super traits as bounds on Self | 95 | // add super traits as bounds on Self |
75 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar | 96 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar |
76 | let self_param = TypeRef::Path(name::SELF_TYPE.into()); | 97 | let self_param = TypeRef::Path(name![Self].into()); |
77 | generics.fill_bounds(&it.source(db).value, self_param); | 98 | generics.fill_bounds(&src.value, self_param); |
99 | |||
100 | generics.fill(&mut sm, &src.value); | ||
101 | src.file_id | ||
102 | } | ||
103 | GenericDefId::TypeAliasId(it) => { | ||
104 | let src = it.lookup(db).source(db); | ||
105 | generics.fill(&mut sm, &src.value); | ||
106 | src.file_id | ||
78 | } | 107 | } |
79 | GenericDefId::TypeAliasId(it) => generics.fill(&it.lookup(db).source(db).value, start), | ||
80 | // Note that we don't add `Self` here: in `impl`s, `Self` is not a | 108 | // Note that we don't add `Self` here: in `impl`s, `Self` is not a |
81 | // type-parameter, but rather is a type-alias for impl's target | 109 | // type-parameter, but rather is a type-alias for impl's target |
82 | // type, so this is handled by the resolver. | 110 | // type, so this is handled by the resolver. |
83 | GenericDefId::ImplId(it) => generics.fill(&it.source(db).value, start), | 111 | GenericDefId::ImplId(it) => { |
84 | GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {} | 112 | let src = it.lookup(db).source(db); |
85 | } | 113 | generics.fill(&mut sm, &src.value); |
114 | src.file_id | ||
115 | } | ||
116 | // We won't be using this ID anyway | ||
117 | GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => FileId(!0).into(), | ||
118 | }; | ||
86 | 119 | ||
87 | generics | 120 | (generics, InFile::new(file_id, sm)) |
88 | } | 121 | } |
89 | 122 | ||
90 | fn fill(&mut self, node: &impl TypeParamsOwner, start: u32) { | 123 | fn fill(&mut self, sm: &mut SourceMap, node: &dyn TypeParamsOwner) { |
91 | if let Some(params) = node.type_param_list() { | 124 | if let Some(params) = node.type_param_list() { |
92 | self.fill_params(params, start) | 125 | self.fill_params(sm, params) |
93 | } | 126 | } |
94 | if let Some(where_clause) = node.where_clause() { | 127 | if let Some(where_clause) = node.where_clause() { |
95 | self.fill_where_predicates(where_clause); | 128 | self.fill_where_predicates(where_clause); |
96 | } | 129 | } |
97 | } | 130 | } |
98 | 131 | ||
99 | fn fill_bounds(&mut self, node: &impl ast::TypeBoundsOwner, type_ref: TypeRef) { | 132 | fn fill_bounds(&mut self, node: &dyn ast::TypeBoundsOwner, type_ref: TypeRef) { |
100 | for bound in | 133 | for bound in |
101 | node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds()) | 134 | node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds()) |
102 | { | 135 | { |
@@ -104,13 +137,14 @@ impl GenericParams { | |||
104 | } | 137 | } |
105 | } | 138 | } |
106 | 139 | ||
107 | fn fill_params(&mut self, params: ast::TypeParamList, start: u32) { | 140 | fn fill_params(&mut self, sm: &mut SourceMap, params: ast::TypeParamList) { |
108 | for (idx, type_param) in params.type_params().enumerate() { | 141 | for type_param in params.type_params() { |
109 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); | 142 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); |
110 | // FIXME: Use `Path::from_src` | 143 | // FIXME: Use `Path::from_src` |
111 | let default = type_param.default_type().map(TypeRef::from_ast); | 144 | let default = type_param.default_type().map(TypeRef::from_ast); |
112 | let param = GenericParam { idx: idx as u32 + start, name: name.clone(), default }; | 145 | let param = TypeParamData { name: name.clone(), default }; |
113 | self.params.push(param); | 146 | let param_id = self.types.alloc(param); |
147 | sm.insert(param_id, Either::Right(type_param.clone())); | ||
114 | 148 | ||
115 | let type_ref = TypeRef::Path(name.into()); | 149 | let type_ref = TypeRef::Path(name.into()); |
116 | self.fill_bounds(&type_param, type_ref); | 150 | self.fill_bounds(&type_param, type_ref); |
@@ -139,45 +173,31 @@ impl GenericParams { | |||
139 | self.where_predicates.push(WherePredicate { type_ref, bound }); | 173 | self.where_predicates.push(WherePredicate { type_ref, bound }); |
140 | } | 174 | } |
141 | 175 | ||
142 | pub fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { | 176 | pub fn find_by_name(&self, name: &Name) -> Option<LocalTypeParamId> { |
143 | self.params.iter().find(|p| &p.name == name) | 177 | self.types.iter().find_map(|(id, p)| if &p.name == name { Some(id) } else { None }) |
144 | } | ||
145 | |||
146 | pub fn count_parent_params(&self) -> usize { | ||
147 | self.parent_params.as_ref().map(|p| p.count_params_including_parent()).unwrap_or(0) | ||
148 | } | ||
149 | |||
150 | pub fn count_params_including_parent(&self) -> usize { | ||
151 | let parent_count = self.count_parent_params(); | ||
152 | parent_count + self.params.len() | ||
153 | } | ||
154 | |||
155 | fn for_each_param<'a>(&'a self, f: &mut impl FnMut(&'a GenericParam)) { | ||
156 | if let Some(parent) = &self.parent_params { | ||
157 | parent.for_each_param(f); | ||
158 | } | ||
159 | self.params.iter().for_each(f); | ||
160 | } | 178 | } |
179 | } | ||
161 | 180 | ||
162 | pub fn params_including_parent(&self) -> Vec<&GenericParam> { | 181 | impl HasChildSource for GenericDefId { |
163 | let mut vec = Vec::with_capacity(self.count_params_including_parent()); | 182 | type ChildId = LocalTypeParamId; |
164 | self.for_each_param(&mut |p| vec.push(p)); | 183 | type Value = Either<ast::TraitDef, ast::TypeParam>; |
165 | vec | 184 | fn child_source(&self, db: &impl DefDatabase) -> InFile<SourceMap> { |
185 | let (_, sm) = GenericParams::new(db, *self); | ||
186 | sm | ||
166 | } | 187 | } |
167 | } | 188 | } |
168 | 189 | ||
169 | fn parent_generic_def(db: &impl DefDatabase, def: GenericDefId) -> Option<GenericDefId> { | 190 | impl ChildBySource for GenericDefId { |
170 | let container = match def { | 191 | fn child_by_source(&self, db: &impl DefDatabase) -> DynMap { |
171 | GenericDefId::FunctionId(it) => it.lookup(db).container, | 192 | let mut res = DynMap::default(); |
172 | GenericDefId::TypeAliasId(it) => it.lookup(db).container, | 193 | let arena_map = self.child_source(db); |
173 | GenericDefId::ConstId(it) => it.lookup(db).container, | 194 | let arena_map = arena_map.as_ref(); |
174 | GenericDefId::EnumVariantId(it) => return Some(it.parent.into()), | 195 | for (local_id, src) in arena_map.value.iter() { |
175 | GenericDefId::AdtId(_) | GenericDefId::TraitId(_) | GenericDefId::ImplId(_) => return None, | 196 | let id = TypeParamId { parent: *self, local_id }; |
176 | }; | 197 | if let Either::Right(type_param) = src { |
177 | 198 | res[keys::TYPE_PARAM].insert(arena_map.with_value(type_param.clone()), id) | |
178 | match container { | 199 | } |
179 | ContainerId::ImplId(it) => Some(it.into()), | 200 | } |
180 | ContainerId::TraitId(it) => Some(it.into()), | 201 | res |
181 | ContainerId::ModuleId(_) => None, | ||
182 | } | 202 | } |
183 | } | 203 | } |