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.rs128
1 files changed, 99 insertions, 29 deletions
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs
index 94ce83564..976cf72d0 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 ra_arena::Arena; 8use hir_expand::{
9 name::{self, AsName, Name},
10 InFile,
11};
12use ra_arena::{map::ArenaMap, Arena};
13use ra_db::FileId;
9use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; 14use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner};
10 15
11use crate::{ 16use crate::{
17 child_by_source::ChildBySource,
12 db::DefDatabase, 18 db::DefDatabase,
19 dyn_map::DynMap,
20 keys,
21 src::HasChildSource,
13 src::HasSource, 22 src::HasSource,
14 type_ref::{TypeBound, TypeRef}, 23 type_ref::{TypeBound, TypeRef},
15 AdtId, AstItemDef, GenericDefId, LocalGenericParamId, Lookup, 24 AdtId, AstItemDef, GenericDefId, LocalTypeParamId, Lookup, TypeParamId,
16}; 25};
17 26
18/// Data about a generic parameter (to a function, struct, impl, ...). 27/// Data about a generic parameter (to a function, struct, impl, ...).
19#[derive(Clone, PartialEq, Eq, Debug)] 28#[derive(Clone, PartialEq, Eq, Debug)]
20pub struct GenericParamData { 29pub struct TypeParamData {
21 pub name: Name, 30 pub name: Name,
22 pub default: Option<TypeRef>, 31 pub default: Option<TypeRef>,
23} 32}
@@ -25,7 +34,8 @@ pub struct GenericParamData {
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 params: Arena<LocalGenericParamId, GenericParamData>, 37 pub types: Arena<LocalTypeParamId, TypeParamData>,
38 // lifetimes: Arena<LocalLifetimeParamId, LifetimeParamData>,
29 pub where_predicates: Vec<WherePredicate>, 39 pub where_predicates: Vec<WherePredicate>,
30} 40}
31 41
@@ -39,52 +49,87 @@ pub struct WherePredicate {
39 pub bound: TypeBound, 49 pub bound: TypeBound,
40} 50}
41 51
52type SourceMap = ArenaMap<LocalTypeParamId, Either<ast::TraitDef, ast::TypeParam>>;
53
42impl GenericParams { 54impl GenericParams {
43 pub(crate) fn generic_params_query( 55 pub(crate) fn generic_params_query(
44 db: &impl DefDatabase, 56 db: &impl DefDatabase,
45 def: GenericDefId, 57 def: GenericDefId,
46 ) -> Arc<GenericParams> { 58 ) -> Arc<GenericParams> {
47 Arc::new(GenericParams::new(db, def.into())) 59 let (params, _source_map) = GenericParams::new(db, def.into());
60 Arc::new(params)
48 } 61 }
49 62
50 fn new(db: &impl DefDatabase, def: GenericDefId) -> GenericParams { 63 fn new(db: &impl DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) {
51 let mut generics = GenericParams { params: Arena::default(), where_predicates: Vec::new() }; 64 let mut generics = GenericParams { types: Arena::default(), where_predicates: Vec::new() };
65 let mut sm = ArenaMap::default();
52 // FIXME: add `: Sized` bound for everything except for `Self` in traits 66 // FIXME: add `: Sized` bound for everything except for `Self` in traits
53 match def { 67 let file_id = match def {
54 GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value), 68 GenericDefId::FunctionId(it) => {
55 GenericDefId::AdtId(AdtId::StructId(it)) => generics.fill(&it.source(db).value), 69 let src = it.lookup(db).source(db);
56 GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.source(db).value), 70 generics.fill(&mut sm, &src.value);
57 GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value), 71 src.file_id
72 }
73 GenericDefId::AdtId(AdtId::StructId(it)) => {
74 let src = it.source(db);
75 generics.fill(&mut sm, &src.value);
76 src.file_id
77 }
78 GenericDefId::AdtId(AdtId::UnionId(it)) => {
79 let src = it.source(db);
80 generics.fill(&mut sm, &src.value);
81 src.file_id
82 }
83 GenericDefId::AdtId(AdtId::EnumId(it)) => {
84 let src = it.source(db);
85 generics.fill(&mut sm, &src.value);
86 src.file_id
87 }
58 GenericDefId::TraitId(it) => { 88 GenericDefId::TraitId(it) => {
89 let src = it.source(db);
90
59 // traits get the Self type as an implicit first type parameter 91 // traits get the Self type as an implicit first type parameter
60 generics.params.alloc(GenericParamData { name: name::SELF_TYPE, default: None }); 92 let self_param_id =
61 generics.fill(&it.source(db).value); 93 generics.types.alloc(TypeParamData { name: name::SELF_TYPE, default: None });
94 sm.insert(self_param_id, Either::Left(src.value.clone()));
62 // add super traits as bounds on Self 95 // add super traits as bounds on Self
63 // 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
64 let self_param = TypeRef::Path(name::SELF_TYPE.into()); 97 let self_param = TypeRef::Path(name::SELF_TYPE.into());
65 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
66 } 107 }
67 GenericDefId::TypeAliasId(it) => generics.fill(&it.lookup(db).source(db).value),
68 // 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
69 // 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
70 // type, so this is handled by the resolver. 110 // type, so this is handled by the resolver.
71 GenericDefId::ImplId(it) => generics.fill(&it.source(db).value), 111 GenericDefId::ImplId(it) => {
72 GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {} 112 let src = it.source(db);
73 } 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 };
74 119
75 generics 120 (generics, InFile::new(file_id, sm))
76 } 121 }
77 122
78 fn fill(&mut self, node: &impl TypeParamsOwner) { 123 fn fill(&mut self, sm: &mut SourceMap, node: &dyn TypeParamsOwner) {
79 if let Some(params) = node.type_param_list() { 124 if let Some(params) = node.type_param_list() {
80 self.fill_params(params) 125 self.fill_params(sm, params)
81 } 126 }
82 if let Some(where_clause) = node.where_clause() { 127 if let Some(where_clause) = node.where_clause() {
83 self.fill_where_predicates(where_clause); 128 self.fill_where_predicates(where_clause);
84 } 129 }
85 } 130 }
86 131
87 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) {
88 for bound in 133 for bound in
89 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())
90 { 135 {
@@ -92,13 +137,14 @@ impl GenericParams {
92 } 137 }
93 } 138 }
94 139
95 fn fill_params(&mut self, params: ast::TypeParamList) { 140 fn fill_params(&mut self, sm: &mut SourceMap, params: ast::TypeParamList) {
96 for type_param in params.type_params() { 141 for type_param in params.type_params() {
97 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());
98 // FIXME: Use `Path::from_src` 143 // FIXME: Use `Path::from_src`
99 let default = type_param.default_type().map(TypeRef::from_ast); 144 let default = type_param.default_type().map(TypeRef::from_ast);
100 let param = GenericParamData { name: name.clone(), default }; 145 let param = TypeParamData { name: name.clone(), default };
101 self.params.alloc(param); 146 let param_id = self.types.alloc(param);
147 sm.insert(param_id, Either::Right(type_param.clone()));
102 148
103 let type_ref = TypeRef::Path(name.into()); 149 let type_ref = TypeRef::Path(name.into());
104 self.fill_bounds(&type_param, type_ref); 150 self.fill_bounds(&type_param, type_ref);
@@ -127,7 +173,31 @@ impl GenericParams {
127 self.where_predicates.push(WherePredicate { type_ref, bound }); 173 self.where_predicates.push(WherePredicate { type_ref, bound });
128 } 174 }
129 175
130 pub fn find_by_name(&self, name: &Name) -> Option<LocalGenericParamId> { 176 pub fn find_by_name(&self, name: &Name) -> Option<LocalTypeParamId> {
131 self.params.iter().find_map(|(id, p)| if &p.name == name { Some(id) } else { None }) 177 self.types.iter().find_map(|(id, p)| if &p.name == name { Some(id) } else { None })
178 }
179}
180
181impl HasChildSource for GenericDefId {
182 type ChildId = LocalTypeParamId;
183 type Value = Either<ast::TraitDef, ast::TypeParam>;
184 fn child_source(&self, db: &impl DefDatabase) -> InFile<SourceMap> {
185 let (_, sm) = GenericParams::new(db, *self);
186 sm
187 }
188}
189
190impl ChildBySource for GenericDefId {
191 fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
192 let mut res = DynMap::default();
193 let arena_map = self.child_source(db);
194 let arena_map = arena_map.as_ref();
195 for (local_id, src) in arena_map.value.iter() {
196 let id = TypeParamId { parent: *self, local_id };
197 if let Either::Right(type_param) = src {
198 res[keys::TYPE_PARAM].insert(arena_map.with_value(type_param.clone()), id)
199 }
200 }
201 res
132 } 202 }
133} 203}