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.rs174
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.
5use std::sync::Arc; 5use std::sync::Arc;
6 6
7use hir_expand::name::{self, AsName, Name}; 7use either::Either;
8use hir_expand::{
9 name::{name, AsName, Name},
10 InFile,
11};
12use ra_arena::{map::ArenaMap, Arena};
13use ra_db::FileId;
8use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; 14use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner};
9 15
10use crate::{ 16use 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)]
18pub struct GenericParam { 29pub 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)]
27pub struct GenericParams { 36pub 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
52type SourceMap = ArenaMap<LocalTypeParamId, Either<ast::TraitDef, ast::TypeParam>>;
53
43impl GenericParams { 54impl 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> { 181impl 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
169fn parent_generic_def(db: &impl DefDatabase, def: GenericDefId) -> Option<GenericDefId> { 190impl 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}