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