diff options
Diffstat (limited to 'crates/ra_hir_def/src')
-rw-r--r-- | crates/ra_hir_def/src/generics.rs | 128 | ||||
-rw-r--r-- | crates/ra_hir_def/src/keys.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir_def/src/lib.rs | 22 | ||||
-rw-r--r-- | crates/ra_hir_def/src/resolver.rs | 18 |
4 files changed, 128 insertions, 43 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. |
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 ra_arena::Arena; | 8 | use hir_expand::{ |
9 | name::{self, AsName, Name}, | ||
10 | InFile, | ||
11 | }; | ||
12 | use ra_arena::{map::ArenaMap, Arena}; | ||
13 | use ra_db::FileId; | ||
9 | use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; | 14 | use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; |
10 | 15 | ||
11 | use crate::{ | 16 | use 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)] |
20 | pub struct GenericParamData { | 29 | pub 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)] |
27 | pub struct GenericParams { | 36 | pub 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 | ||
52 | type SourceMap = ArenaMap<LocalTypeParamId, Either<ast::TraitDef, ast::TypeParam>>; | ||
53 | |||
42 | impl GenericParams { | 54 | impl 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 | |||
181 | impl 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 | |||
190 | impl 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 | } |
diff --git a/crates/ra_hir_def/src/keys.rs b/crates/ra_hir_def/src/keys.rs index 447b7e3ba..be702a4f8 100644 --- a/crates/ra_hir_def/src/keys.rs +++ b/crates/ra_hir_def/src/keys.rs | |||
@@ -8,7 +8,7 @@ use rustc_hash::FxHashMap; | |||
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | dyn_map::{DynMap, Policy}, | 10 | dyn_map::{DynMap, Policy}, |
11 | ConstId, EnumVariantId, FunctionId, StaticId, StructFieldId, TypeAliasId, | 11 | ConstId, EnumVariantId, FunctionId, StaticId, StructFieldId, TypeAliasId, TypeParamId, |
12 | }; | 12 | }; |
13 | 13 | ||
14 | type Key<K, V> = crate::dyn_map::Key<InFile<K>, V, AstPtrPolicy<K, V>>; | 14 | type Key<K, V> = crate::dyn_map::Key<InFile<K>, V, AstPtrPolicy<K, V>>; |
@@ -20,6 +20,7 @@ pub const ENUM_VARIANT: Key<ast::EnumVariant, EnumVariantId> = Key::new(); | |||
20 | pub const TYPE_ALIAS: Key<ast::TypeAliasDef, TypeAliasId> = Key::new(); | 20 | pub const TYPE_ALIAS: Key<ast::TypeAliasDef, TypeAliasId> = Key::new(); |
21 | pub const TUPLE_FIELD: Key<ast::TupleFieldDef, StructFieldId> = Key::new(); | 21 | pub const TUPLE_FIELD: Key<ast::TupleFieldDef, StructFieldId> = Key::new(); |
22 | pub const RECORD_FIELD: Key<ast::RecordFieldDef, StructFieldId> = Key::new(); | 22 | pub const RECORD_FIELD: Key<ast::RecordFieldDef, StructFieldId> = Key::new(); |
23 | pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new(); | ||
23 | 24 | ||
24 | /// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are | 25 | /// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are |
25 | /// equal if they point to exactly the same object. | 26 | /// equal if they point to exactly the same object. |
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index b8dfc0ab1..569da4f28 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs | |||
@@ -318,14 +318,14 @@ macro_rules! impl_froms { | |||
318 | } | 318 | } |
319 | 319 | ||
320 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 320 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
321 | pub struct GenericParamId { | 321 | pub struct TypeParamId { |
322 | pub parent: GenericDefId, | 322 | pub parent: GenericDefId, |
323 | pub local_id: LocalGenericParamId, | 323 | pub local_id: LocalTypeParamId, |
324 | } | 324 | } |
325 | 325 | ||
326 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 326 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
327 | pub struct LocalGenericParamId(RawId); | 327 | pub struct LocalTypeParamId(RawId); |
328 | impl_arena_id!(LocalGenericParamId); | 328 | impl_arena_id!(LocalTypeParamId); |
329 | 329 | ||
330 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 330 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
331 | pub enum ContainerId { | 331 | pub enum ContainerId { |
@@ -525,6 +525,20 @@ impl HasModule for DefWithBodyId { | |||
525 | } | 525 | } |
526 | } | 526 | } |
527 | 527 | ||
528 | impl HasModule for GenericDefId { | ||
529 | fn module(&self, db: &impl db::DefDatabase) -> ModuleId { | ||
530 | match self { | ||
531 | GenericDefId::FunctionId(it) => it.lookup(db).module(db), | ||
532 | GenericDefId::AdtId(it) => it.module(db), | ||
533 | GenericDefId::TraitId(it) => it.module(db), | ||
534 | GenericDefId::TypeAliasId(it) => it.lookup(db).module(db), | ||
535 | GenericDefId::ImplId(it) => it.module(db), | ||
536 | GenericDefId::EnumVariantId(it) => it.parent.module(db), | ||
537 | GenericDefId::ConstId(it) => it.lookup(db).module(db), | ||
538 | } | ||
539 | } | ||
540 | } | ||
541 | |||
528 | impl HasModule for StaticLoc { | 542 | impl HasModule for StaticLoc { |
529 | fn module(&self, _db: &impl db::DefDatabase) -> ModuleId { | 543 | fn module(&self, _db: &impl db::DefDatabase) -> ModuleId { |
530 | self.container | 544 | self.container |
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index e00bd03d5..4c859e497 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs | |||
@@ -18,8 +18,8 @@ use crate::{ | |||
18 | path::{Path, PathKind}, | 18 | path::{Path, PathKind}, |
19 | per_ns::PerNs, | 19 | per_ns::PerNs, |
20 | AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, | 20 | AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, |
21 | GenericDefId, GenericParamId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, | 21 | GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, |
22 | StaticId, StructId, TraitId, TypeAliasId, | 22 | StructId, TraitId, TypeAliasId, TypeParamId, |
23 | }; | 23 | }; |
24 | 24 | ||
25 | #[derive(Debug, Clone, Default)] | 25 | #[derive(Debug, Clone, Default)] |
@@ -59,7 +59,7 @@ enum Scope { | |||
59 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 59 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
60 | pub enum TypeNs { | 60 | pub enum TypeNs { |
61 | SelfType(ImplId), | 61 | SelfType(ImplId), |
62 | GenericParam(GenericParamId), | 62 | GenericParam(TypeParamId), |
63 | AdtId(AdtId), | 63 | AdtId(AdtId), |
64 | AdtSelfType(AdtId), | 64 | AdtSelfType(AdtId), |
65 | // Yup, enum variants are added to the types ns, but any usage of variant as | 65 | // Yup, enum variants are added to the types ns, but any usage of variant as |
@@ -157,7 +157,7 @@ impl Resolver { | |||
157 | if let Some(local_id) = params.find_by_name(first_name) { | 157 | if let Some(local_id) = params.find_by_name(first_name) { |
158 | let idx = if path.segments.len() == 1 { None } else { Some(1) }; | 158 | let idx = if path.segments.len() == 1 { None } else { Some(1) }; |
159 | return Some(( | 159 | return Some(( |
160 | TypeNs::GenericParam(GenericParamId { local_id, parent: *def }), | 160 | TypeNs::GenericParam(TypeParamId { local_id, parent: *def }), |
161 | idx, | 161 | idx, |
162 | )); | 162 | )); |
163 | } | 163 | } |
@@ -252,7 +252,7 @@ impl Resolver { | |||
252 | 252 | ||
253 | Scope::GenericParams { params, def } if n_segments > 1 => { | 253 | Scope::GenericParams { params, def } if n_segments > 1 => { |
254 | if let Some(local_id) = params.find_by_name(first_name) { | 254 | if let Some(local_id) = params.find_by_name(first_name) { |
255 | let ty = TypeNs::GenericParam(GenericParamId { local_id, parent: *def }); | 255 | let ty = TypeNs::GenericParam(TypeParamId { local_id, parent: *def }); |
256 | return Some(ResolveValueResult::Partial(ty, 1)); | 256 | return Some(ResolveValueResult::Partial(ty, 1)); |
257 | } | 257 | } |
258 | } | 258 | } |
@@ -399,7 +399,7 @@ pub enum ScopeDef { | |||
399 | PerNs(PerNs), | 399 | PerNs(PerNs), |
400 | ImplSelfType(ImplId), | 400 | ImplSelfType(ImplId), |
401 | AdtSelfType(AdtId), | 401 | AdtSelfType(AdtId), |
402 | GenericParam(GenericParamId), | 402 | GenericParam(TypeParamId), |
403 | Local(PatId), | 403 | Local(PatId), |
404 | } | 404 | } |
405 | 405 | ||
@@ -431,10 +431,10 @@ impl Scope { | |||
431 | } | 431 | } |
432 | } | 432 | } |
433 | Scope::GenericParams { params, def } => { | 433 | Scope::GenericParams { params, def } => { |
434 | for (local_id, param) in params.params.iter() { | 434 | for (local_id, param) in params.types.iter() { |
435 | f( | 435 | f( |
436 | param.name.clone(), | 436 | param.name.clone(), |
437 | ScopeDef::GenericParam(GenericParamId { local_id, parent: *def }), | 437 | ScopeDef::GenericParam(TypeParamId { local_id, parent: *def }), |
438 | ) | 438 | ) |
439 | } | 439 | } |
440 | } | 440 | } |
@@ -481,7 +481,7 @@ impl Resolver { | |||
481 | 481 | ||
482 | fn push_generic_params_scope(self, db: &impl DefDatabase, def: GenericDefId) -> Resolver { | 482 | fn push_generic_params_scope(self, db: &impl DefDatabase, def: GenericDefId) -> Resolver { |
483 | let params = db.generic_params(def); | 483 | let params = db.generic_params(def); |
484 | if params.params.is_empty() { | 484 | if params.types.is_empty() { |
485 | self | 485 | self |
486 | } else { | 486 | } else { |
487 | self.push_scope(Scope::GenericParams { def, params }) | 487 | self.push_scope(Scope::GenericParams { def, params }) |