diff options
Diffstat (limited to 'crates/ra_hir_def/src/generics.rs')
-rw-r--r-- | crates/ra_hir_def/src/generics.rs | 90 |
1 files changed, 19 insertions, 71 deletions
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index abe749a40..94ce83564 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs | |||
@@ -12,14 +12,12 @@ use crate::{ | |||
12 | db::DefDatabase, | 12 | db::DefDatabase, |
13 | src::HasSource, | 13 | src::HasSource, |
14 | type_ref::{TypeBound, TypeRef}, | 14 | type_ref::{TypeBound, TypeRef}, |
15 | AdtId, AstItemDef, ContainerId, GenericDefId, LocalGenericParamId, Lookup, | 15 | AdtId, AstItemDef, GenericDefId, LocalGenericParamId, Lookup, |
16 | }; | 16 | }; |
17 | 17 | ||
18 | /// Data about a generic parameter (to a function, struct, impl, ...). | 18 | /// Data about a generic parameter (to a function, struct, impl, ...). |
19 | #[derive(Clone, PartialEq, Eq, Debug)] | 19 | #[derive(Clone, PartialEq, Eq, Debug)] |
20 | pub struct GenericParamData { | 20 | pub struct GenericParamData { |
21 | // FIXME: give generic params proper IDs | ||
22 | pub idx: u32, | ||
23 | pub name: Name, | 21 | pub name: Name, |
24 | pub default: Option<TypeRef>, | 22 | pub default: Option<TypeRef>, |
25 | } | 23 | } |
@@ -27,7 +25,6 @@ pub struct GenericParamData { | |||
27 | /// Data about the generic parameters of a function, struct, impl, etc. | 25 | /// Data about the generic parameters of a function, struct, impl, etc. |
28 | #[derive(Clone, PartialEq, Eq, Debug)] | 26 | #[derive(Clone, PartialEq, Eq, Debug)] |
29 | pub struct GenericParams { | 27 | pub struct GenericParams { |
30 | pub parent_params: Option<Arc<GenericParams>>, | ||
31 | pub params: Arena<LocalGenericParamId, GenericParamData>, | 28 | pub params: Arena<LocalGenericParamId, GenericParamData>, |
32 | pub where_predicates: Vec<WherePredicate>, | 29 | pub where_predicates: Vec<WherePredicate>, |
33 | } | 30 | } |
@@ -47,51 +44,40 @@ impl GenericParams { | |||
47 | db: &impl DefDatabase, | 44 | db: &impl DefDatabase, |
48 | def: GenericDefId, | 45 | def: GenericDefId, |
49 | ) -> Arc<GenericParams> { | 46 | ) -> Arc<GenericParams> { |
50 | let parent_generics = parent_generic_def(db, def).map(|it| db.generic_params(it)); | 47 | Arc::new(GenericParams::new(db, def.into())) |
51 | Arc::new(GenericParams::new(db, def.into(), parent_generics)) | ||
52 | } | 48 | } |
53 | 49 | ||
54 | fn new( | 50 | fn new(db: &impl DefDatabase, def: GenericDefId) -> GenericParams { |
55 | db: &impl DefDatabase, | 51 | let mut generics = GenericParams { params: Arena::default(), where_predicates: Vec::new() }; |
56 | def: GenericDefId, | ||
57 | parent_params: Option<Arc<GenericParams>>, | ||
58 | ) -> GenericParams { | ||
59 | let mut generics = | ||
60 | GenericParams { params: Arena::default(), parent_params, where_predicates: Vec::new() }; | ||
61 | let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32; | ||
62 | // FIXME: add `: Sized` bound for everything except for `Self` in traits | 52 | // FIXME: add `: Sized` bound for everything except for `Self` in traits |
63 | match def { | 53 | match def { |
64 | GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value, start), | 54 | GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value), |
65 | GenericDefId::AdtId(AdtId::StructId(it)) => generics.fill(&it.source(db).value, start), | 55 | GenericDefId::AdtId(AdtId::StructId(it)) => generics.fill(&it.source(db).value), |
66 | GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.source(db).value, start), | 56 | GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.source(db).value), |
67 | GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value, start), | 57 | GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value), |
68 | GenericDefId::TraitId(it) => { | 58 | GenericDefId::TraitId(it) => { |
69 | // traits get the Self type as an implicit first type parameter | 59 | // traits get the Self type as an implicit first type parameter |
70 | generics.params.alloc(GenericParamData { | 60 | generics.params.alloc(GenericParamData { name: name::SELF_TYPE, default: None }); |
71 | idx: start, | 61 | generics.fill(&it.source(db).value); |
72 | name: name::SELF_TYPE, | ||
73 | default: None, | ||
74 | }); | ||
75 | generics.fill(&it.source(db).value, start + 1); | ||
76 | // add super traits as bounds on Self | 62 | // add super traits as bounds on Self |
77 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar | 63 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar |
78 | let self_param = TypeRef::Path(name::SELF_TYPE.into()); | 64 | let self_param = TypeRef::Path(name::SELF_TYPE.into()); |
79 | generics.fill_bounds(&it.source(db).value, self_param); | 65 | generics.fill_bounds(&it.source(db).value, self_param); |
80 | } | 66 | } |
81 | GenericDefId::TypeAliasId(it) => generics.fill(&it.lookup(db).source(db).value, start), | 67 | GenericDefId::TypeAliasId(it) => generics.fill(&it.lookup(db).source(db).value), |
82 | // Note that we don't add `Self` here: in `impl`s, `Self` is not a | 68 | // Note that we don't add `Self` here: in `impl`s, `Self` is not a |
83 | // type-parameter, but rather is a type-alias for impl's target | 69 | // type-parameter, but rather is a type-alias for impl's target |
84 | // type, so this is handled by the resolver. | 70 | // type, so this is handled by the resolver. |
85 | GenericDefId::ImplId(it) => generics.fill(&it.source(db).value, start), | 71 | GenericDefId::ImplId(it) => generics.fill(&it.source(db).value), |
86 | GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {} | 72 | GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {} |
87 | } | 73 | } |
88 | 74 | ||
89 | generics | 75 | generics |
90 | } | 76 | } |
91 | 77 | ||
92 | fn fill(&mut self, node: &impl TypeParamsOwner, start: u32) { | 78 | fn fill(&mut self, node: &impl TypeParamsOwner) { |
93 | if let Some(params) = node.type_param_list() { | 79 | if let Some(params) = node.type_param_list() { |
94 | self.fill_params(params, start) | 80 | self.fill_params(params) |
95 | } | 81 | } |
96 | if let Some(where_clause) = node.where_clause() { | 82 | if let Some(where_clause) = node.where_clause() { |
97 | self.fill_where_predicates(where_clause); | 83 | self.fill_where_predicates(where_clause); |
@@ -106,12 +92,12 @@ impl GenericParams { | |||
106 | } | 92 | } |
107 | } | 93 | } |
108 | 94 | ||
109 | fn fill_params(&mut self, params: ast::TypeParamList, start: u32) { | 95 | fn fill_params(&mut self, params: ast::TypeParamList) { |
110 | for (idx, type_param) in params.type_params().enumerate() { | 96 | for type_param in params.type_params() { |
111 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); | 97 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); |
112 | // FIXME: Use `Path::from_src` | 98 | // FIXME: Use `Path::from_src` |
113 | let default = type_param.default_type().map(TypeRef::from_ast); | 99 | let default = type_param.default_type().map(TypeRef::from_ast); |
114 | let param = GenericParamData { idx: idx as u32 + start, name: name.clone(), default }; | 100 | let param = GenericParamData { name: name.clone(), default }; |
115 | self.params.alloc(param); | 101 | self.params.alloc(param); |
116 | 102 | ||
117 | let type_ref = TypeRef::Path(name.into()); | 103 | let type_ref = TypeRef::Path(name.into()); |
@@ -141,45 +127,7 @@ impl GenericParams { | |||
141 | self.where_predicates.push(WherePredicate { type_ref, bound }); | 127 | self.where_predicates.push(WherePredicate { type_ref, bound }); |
142 | } | 128 | } |
143 | 129 | ||
144 | pub fn find_by_name(&self, name: &Name) -> Option<&GenericParamData> { | 130 | pub fn find_by_name(&self, name: &Name) -> Option<LocalGenericParamId> { |
145 | self.params.iter().map(|(_id, data)| data).find(|p| &p.name == name) | 131 | self.params.iter().find_map(|(id, p)| if &p.name == name { Some(id) } else { None }) |
146 | } | ||
147 | |||
148 | pub fn count_parent_params(&self) -> usize { | ||
149 | self.parent_params.as_ref().map(|p| p.count_params_including_parent()).unwrap_or(0) | ||
150 | } | ||
151 | |||
152 | pub fn count_params_including_parent(&self) -> usize { | ||
153 | let parent_count = self.count_parent_params(); | ||
154 | parent_count + self.params.len() | ||
155 | } | ||
156 | |||
157 | fn for_each_param<'a>(&'a self, f: &mut impl FnMut(&'a GenericParamData)) { | ||
158 | if let Some(parent) = &self.parent_params { | ||
159 | parent.for_each_param(f); | ||
160 | } | ||
161 | self.params.iter().map(|(_id, data)| data).for_each(f); | ||
162 | } | ||
163 | |||
164 | pub fn params_including_parent(&self) -> Vec<&GenericParamData> { | ||
165 | let mut vec = Vec::with_capacity(self.count_params_including_parent()); | ||
166 | self.for_each_param(&mut |p| vec.push(p)); | ||
167 | vec | ||
168 | } | ||
169 | } | ||
170 | |||
171 | fn parent_generic_def(db: &impl DefDatabase, def: GenericDefId) -> Option<GenericDefId> { | ||
172 | let container = match def { | ||
173 | GenericDefId::FunctionId(it) => it.lookup(db).container, | ||
174 | GenericDefId::TypeAliasId(it) => it.lookup(db).container, | ||
175 | GenericDefId::ConstId(it) => it.lookup(db).container, | ||
176 | GenericDefId::EnumVariantId(it) => return Some(it.parent.into()), | ||
177 | GenericDefId::AdtId(_) | GenericDefId::TraitId(_) | GenericDefId::ImplId(_) => return None, | ||
178 | }; | ||
179 | |||
180 | match container { | ||
181 | ContainerId::ImplId(it) => Some(it.into()), | ||
182 | ContainerId::TraitId(it) => Some(it.into()), | ||
183 | ContainerId::ModuleId(_) => None, | ||
184 | } | 132 | } |
185 | } | 133 | } |