diff options
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r-- | crates/ra_hir_def/src/generics.rs | 93 |
1 files changed, 72 insertions, 21 deletions
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index b3e345082..0df5a20f5 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs | |||
@@ -4,12 +4,18 @@ | |||
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::{ |
12 | db::DefDatabase, | 17 | db::DefDatabase, |
18 | src::HasChildSource, | ||
13 | src::HasSource, | 19 | src::HasSource, |
14 | type_ref::{TypeBound, TypeRef}, | 20 | type_ref::{TypeBound, TypeRef}, |
15 | AdtId, AstItemDef, GenericDefId, LocalGenericParamId, Lookup, | 21 | AdtId, AstItemDef, GenericDefId, LocalGenericParamId, Lookup, |
@@ -39,46 +45,81 @@ pub struct WherePredicate { | |||
39 | pub bound: TypeBound, | 45 | pub bound: TypeBound, |
40 | } | 46 | } |
41 | 47 | ||
48 | type SourceMap = ArenaMap<LocalGenericParamId, Either<ast::TraitDef, ast::TypeParam>>; | ||
49 | |||
42 | impl GenericParams { | 50 | impl GenericParams { |
43 | pub(crate) fn generic_params_query( | 51 | pub(crate) fn generic_params_query( |
44 | db: &impl DefDatabase, | 52 | db: &impl DefDatabase, |
45 | def: GenericDefId, | 53 | def: GenericDefId, |
46 | ) -> Arc<GenericParams> { | 54 | ) -> Arc<GenericParams> { |
47 | Arc::new(GenericParams::new(db, def.into())) | 55 | let (params, _source_map) = GenericParams::new(db, def.into()); |
56 | Arc::new(params) | ||
48 | } | 57 | } |
49 | 58 | ||
50 | fn new(db: &impl DefDatabase, def: GenericDefId) -> GenericParams { | 59 | fn new(db: &impl DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) { |
51 | let mut generics = GenericParams { params: Arena::default(), where_predicates: Vec::new() }; | 60 | let mut generics = GenericParams { params: Arena::default(), where_predicates: Vec::new() }; |
61 | let mut sm = ArenaMap::default(); | ||
52 | // FIXME: add `: Sized` bound for everything except for `Self` in traits | 62 | // FIXME: add `: Sized` bound for everything except for `Self` in traits |
53 | match def { | 63 | let file_id = match def { |
54 | GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value), | 64 | GenericDefId::FunctionId(it) => { |
55 | GenericDefId::AdtId(AdtId::StructId(it)) => generics.fill(&it.source(db).value), | 65 | let src = it.lookup(db).source(db); |
56 | GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.source(db).value), | 66 | generics.fill(&mut sm, &src.value); |
57 | GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value), | 67 | src.file_id |
68 | } | ||
69 | GenericDefId::AdtId(AdtId::StructId(it)) => { | ||
70 | let src = it.source(db); | ||
71 | generics.fill(&mut sm, &src.value); | ||
72 | src.file_id | ||
73 | } | ||
74 | GenericDefId::AdtId(AdtId::UnionId(it)) => { | ||
75 | let src = it.source(db); | ||
76 | generics.fill(&mut sm, &src.value); | ||
77 | src.file_id | ||
78 | } | ||
79 | GenericDefId::AdtId(AdtId::EnumId(it)) => { | ||
80 | let src = it.source(db); | ||
81 | generics.fill(&mut sm, &src.value); | ||
82 | src.file_id | ||
83 | } | ||
58 | GenericDefId::TraitId(it) => { | 84 | GenericDefId::TraitId(it) => { |
85 | let src = it.source(db); | ||
86 | |||
59 | // traits get the Self type as an implicit first type parameter | 87 | // traits get the Self type as an implicit first type parameter |
60 | generics.params.alloc(GenericParamData { name: name::SELF_TYPE, default: None }); | 88 | let self_param_id = generics |
89 | .params | ||
90 | .alloc(GenericParamData { name: name::SELF_TYPE, default: None }); | ||
91 | sm.insert(self_param_id, Either::Left(src.value.clone())); | ||
61 | // add super traits as bounds on Self | 92 | // add super traits as bounds on Self |
62 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar | 93 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar |
63 | let self_param = TypeRef::Path(name::SELF_TYPE.into()); | 94 | let self_param = TypeRef::Path(name::SELF_TYPE.into()); |
64 | generics.fill_bounds(&it.source(db).value, self_param); | 95 | generics.fill_bounds(&src.value, self_param); |
65 | 96 | ||
66 | generics.fill(&it.source(db).value); | 97 | generics.fill(&mut sm, &src.value); |
98 | src.file_id | ||
99 | } | ||
100 | GenericDefId::TypeAliasId(it) => { | ||
101 | let src = it.lookup(db).source(db); | ||
102 | generics.fill(&mut sm, &src.value); | ||
103 | src.file_id | ||
67 | } | 104 | } |
68 | GenericDefId::TypeAliasId(it) => generics.fill(&it.lookup(db).source(db).value), | ||
69 | // Note that we don't add `Self` here: in `impl`s, `Self` is not a | 105 | // Note that we don't add `Self` here: in `impl`s, `Self` is not a |
70 | // type-parameter, but rather is a type-alias for impl's target | 106 | // type-parameter, but rather is a type-alias for impl's target |
71 | // type, so this is handled by the resolver. | 107 | // type, so this is handled by the resolver. |
72 | GenericDefId::ImplId(it) => generics.fill(&it.source(db).value), | 108 | GenericDefId::ImplId(it) => { |
73 | GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {} | 109 | let src = it.source(db); |
74 | } | 110 | generics.fill(&mut sm, &src.value); |
111 | src.file_id | ||
112 | } | ||
113 | // We won't be using this ID anyway | ||
114 | GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => FileId(!0).into(), | ||
115 | }; | ||
75 | 116 | ||
76 | generics | 117 | (generics, InFile::new(file_id, sm)) |
77 | } | 118 | } |
78 | 119 | ||
79 | fn fill(&mut self, node: &dyn TypeParamsOwner) { | 120 | fn fill(&mut self, sm: &mut SourceMap, node: &dyn TypeParamsOwner) { |
80 | if let Some(params) = node.type_param_list() { | 121 | if let Some(params) = node.type_param_list() { |
81 | self.fill_params(params) | 122 | self.fill_params(sm, params) |
82 | } | 123 | } |
83 | if let Some(where_clause) = node.where_clause() { | 124 | if let Some(where_clause) = node.where_clause() { |
84 | self.fill_where_predicates(where_clause); | 125 | self.fill_where_predicates(where_clause); |
@@ -93,13 +134,14 @@ impl GenericParams { | |||
93 | } | 134 | } |
94 | } | 135 | } |
95 | 136 | ||
96 | fn fill_params(&mut self, params: ast::TypeParamList) { | 137 | fn fill_params(&mut self, sm: &mut SourceMap, params: ast::TypeParamList) { |
97 | for type_param in params.type_params() { | 138 | for type_param in params.type_params() { |
98 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); | 139 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); |
99 | // FIXME: Use `Path::from_src` | 140 | // FIXME: Use `Path::from_src` |
100 | let default = type_param.default_type().map(TypeRef::from_ast); | 141 | let default = type_param.default_type().map(TypeRef::from_ast); |
101 | let param = GenericParamData { name: name.clone(), default }; | 142 | let param = GenericParamData { name: name.clone(), default }; |
102 | self.params.alloc(param); | 143 | let param_id = self.params.alloc(param); |
144 | sm.insert(param_id, Either::Right(type_param.clone())); | ||
103 | 145 | ||
104 | let type_ref = TypeRef::Path(name.into()); | 146 | let type_ref = TypeRef::Path(name.into()); |
105 | self.fill_bounds(&type_param, type_ref); | 147 | self.fill_bounds(&type_param, type_ref); |
@@ -132,3 +174,12 @@ impl GenericParams { | |||
132 | self.params.iter().find_map(|(id, p)| if &p.name == name { Some(id) } else { None }) | 174 | self.params.iter().find_map(|(id, p)| if &p.name == name { Some(id) } else { None }) |
133 | } | 175 | } |
134 | } | 176 | } |
177 | |||
178 | impl HasChildSource for GenericDefId { | ||
179 | type ChildId = LocalGenericParamId; | ||
180 | type Value = Either<ast::TraitDef, ast::TypeParam>; | ||
181 | fn child_source(&self, db: &impl DefDatabase) -> InFile<SourceMap> { | ||
182 | let (_, sm) = GenericParams::new(db, *self); | ||
183 | sm | ||
184 | } | ||
185 | } | ||