diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-11-20 09:35:50 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2019-11-20 09:35:50 +0000 |
commit | fa50b16cb2309c0c4fcb4e90378993a1f3d2ffb6 (patch) | |
tree | be32707506b562828759e3c9dc72414796a817ca /crates | |
parent | d24e8f9ea42dd2d08b2e02f8106690fd4baa8071 (diff) | |
parent | e1a6e38767c1e47e5e88a97a9ef5b4547390803c (diff) |
Merge #2322
2322: Move Generics to hir_def r=matklad a=matklad
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/db.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/from_id.rs | 44 | ||||
-rw-r--r-- | crates/ra_hir/src/generics.rs | 182 | ||||
-rw-r--r-- | crates/ra_hir/src/resolve.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_def/src/generics.rs | 163 | ||||
-rw-r--r-- | crates/ra_hir_def/src/lib.rs | 24 |
6 files changed, 247 insertions, 170 deletions
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index d75d71d66..0d35014a0 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -43,7 +43,7 @@ pub trait DefDatabase: HirDebugDatabase + DefDatabase2 { | |||
43 | #[salsa::invoke(crate::traits::TraitItemsIndex::trait_items_index)] | 43 | #[salsa::invoke(crate::traits::TraitItemsIndex::trait_items_index)] |
44 | fn trait_items_index(&self, module: Module) -> crate::traits::TraitItemsIndex; | 44 | fn trait_items_index(&self, module: Module) -> crate::traits::TraitItemsIndex; |
45 | 45 | ||
46 | #[salsa::invoke(crate::generics::GenericParams::generic_params_query)] | 46 | #[salsa::invoke(crate::generics::generic_params_query)] |
47 | fn generic_params(&self, def: GenericDef) -> Arc<GenericParams>; | 47 | fn generic_params(&self, def: GenericDef) -> Arc<GenericParams>; |
48 | 48 | ||
49 | #[salsa::invoke(FnData::fn_data_query)] | 49 | #[salsa::invoke(FnData::fn_data_query)] |
diff --git a/crates/ra_hir/src/from_id.rs b/crates/ra_hir/src/from_id.rs index f2203e995..b7692d407 100644 --- a/crates/ra_hir/src/from_id.rs +++ b/crates/ra_hir/src/from_id.rs | |||
@@ -3,9 +3,9 @@ | |||
3 | //! It's unclear if we need this long-term, but it's definitelly useful while we | 3 | //! It's unclear if we need this long-term, but it's definitelly useful while we |
4 | //! are splitting the hir. | 4 | //! are splitting the hir. |
5 | 5 | ||
6 | use hir_def::{AdtId, AssocItemId, DefWithBodyId, EnumVariantId, ModuleDefId}; | 6 | use hir_def::{AdtId, AssocItemId, DefWithBodyId, EnumVariantId, GenericDefId, ModuleDefId}; |
7 | 7 | ||
8 | use crate::{Adt, AssocItem, DefWithBody, EnumVariant, ModuleDef}; | 8 | use crate::{Adt, AssocItem, DefWithBody, EnumVariant, GenericDef, ModuleDef}; |
9 | 9 | ||
10 | macro_rules! from_id { | 10 | macro_rules! from_id { |
11 | ($(($id:path, $ty:path)),*) => {$( | 11 | ($(($id:path, $ty:path)),*) => {$( |
@@ -41,6 +41,16 @@ impl From<AdtId> for Adt { | |||
41 | } | 41 | } |
42 | } | 42 | } |
43 | 43 | ||
44 | impl From<Adt> for AdtId { | ||
45 | fn from(id: Adt) -> Self { | ||
46 | match id { | ||
47 | Adt::Struct(it) => AdtId::StructId(it.id), | ||
48 | Adt::Union(it) => AdtId::UnionId(it.id), | ||
49 | Adt::Enum(it) => AdtId::EnumId(it.id), | ||
50 | } | ||
51 | } | ||
52 | } | ||
53 | |||
44 | impl From<EnumVariantId> for EnumVariant { | 54 | impl From<EnumVariantId> for EnumVariant { |
45 | fn from(id: EnumVariantId) -> Self { | 55 | fn from(id: EnumVariantId) -> Self { |
46 | EnumVariant { parent: id.parent.into(), id: id.local_id } | 56 | EnumVariant { parent: id.parent.into(), id: id.local_id } |
@@ -82,3 +92,33 @@ impl From<AssocItemId> for AssocItem { | |||
82 | } | 92 | } |
83 | } | 93 | } |
84 | } | 94 | } |
95 | |||
96 | impl From<GenericDef> for GenericDefId { | ||
97 | fn from(def: GenericDef) -> Self { | ||
98 | match def { | ||
99 | GenericDef::Function(it) => GenericDefId::FunctionId(it.id), | ||
100 | GenericDef::Adt(it) => GenericDefId::AdtId(it.into()), | ||
101 | GenericDef::Trait(it) => GenericDefId::TraitId(it.id), | ||
102 | GenericDef::TypeAlias(it) => GenericDefId::TypeAliasId(it.id), | ||
103 | GenericDef::ImplBlock(it) => GenericDefId::ImplId(it.id), | ||
104 | GenericDef::EnumVariant(it) => { | ||
105 | GenericDefId::EnumVariantId(EnumVariantId { parent: it.parent.id, local_id: it.id }) | ||
106 | } | ||
107 | GenericDef::Const(it) => GenericDefId::ConstId(it.id), | ||
108 | } | ||
109 | } | ||
110 | } | ||
111 | |||
112 | impl From<GenericDefId> for GenericDef { | ||
113 | fn from(def: GenericDefId) -> Self { | ||
114 | match def { | ||
115 | GenericDefId::FunctionId(it) => GenericDef::Function(it.into()), | ||
116 | GenericDefId::AdtId(it) => GenericDef::Adt(it.into()), | ||
117 | GenericDefId::TraitId(it) => GenericDef::Trait(it.into()), | ||
118 | GenericDefId::TypeAliasId(it) => GenericDef::TypeAlias(it.into()), | ||
119 | GenericDefId::ImplId(it) => GenericDef::ImplBlock(it.into()), | ||
120 | GenericDefId::EnumVariantId(it) => GenericDef::EnumVariant(it.into()), | ||
121 | GenericDefId::ConstId(it) => GenericDef::Const(it.into()), | ||
122 | } | ||
123 | } | ||
124 | } | ||
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index 78fab1a13..caedb90e6 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs | |||
@@ -1,47 +1,12 @@ | |||
1 | //! Many kinds of items or constructs can have generic parameters: functions, | 1 | //! Temp module to wrap hir_def::generics |
2 | //! structs, impls, traits, etc. This module provides a common HIR for these | ||
3 | //! generic parameters. See also the `Generics` type and the `generics_of` query | ||
4 | //! in rustc. | ||
5 | |||
6 | use std::sync::Arc; | 2 | use std::sync::Arc; |
7 | 3 | ||
8 | use hir_def::type_ref::{TypeBound, TypeRef}; | ||
9 | use hir_expand::name::{self, AsName}; | ||
10 | use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; | ||
11 | |||
12 | use crate::{ | 4 | use crate::{ |
13 | db::{AstDatabase, DefDatabase, HirDatabase}, | 5 | db::{AstDatabase, DefDatabase, HirDatabase}, |
14 | Adt, Const, Container, Enum, EnumVariant, Function, HasSource, ImplBlock, Name, Struct, Trait, | 6 | Adt, Const, Container, Enum, EnumVariant, Function, ImplBlock, Struct, Trait, TypeAlias, Union, |
15 | TypeAlias, Union, | ||
16 | }; | 7 | }; |
17 | 8 | ||
18 | /// Data about a generic parameter (to a function, struct, impl, ...). | 9 | pub use hir_def::generics::{GenericParam, GenericParams, WherePredicate}; |
19 | #[derive(Clone, PartialEq, Eq, Debug)] | ||
20 | pub struct GenericParam { | ||
21 | // FIXME: give generic params proper IDs | ||
22 | pub idx: u32, | ||
23 | pub name: Name, | ||
24 | pub default: Option<TypeRef>, | ||
25 | } | ||
26 | |||
27 | /// Data about the generic parameters of a function, struct, impl, etc. | ||
28 | #[derive(Clone, PartialEq, Eq, Debug)] | ||
29 | pub struct GenericParams { | ||
30 | pub(crate) def: GenericDef, | ||
31 | pub(crate) parent_params: Option<Arc<GenericParams>>, | ||
32 | pub(crate) params: Vec<GenericParam>, | ||
33 | pub(crate) where_predicates: Vec<WherePredicate>, | ||
34 | } | ||
35 | |||
36 | /// A single predicate from a where clause, i.e. `where Type: Trait`. Combined | ||
37 | /// where clauses like `where T: Foo + Bar` are turned into multiple of these. | ||
38 | /// It might still result in multiple actual predicates though, because of | ||
39 | /// associated type bindings like `Iterator<Item = u32>`. | ||
40 | #[derive(Clone, PartialEq, Eq, Debug)] | ||
41 | pub struct WherePredicate { | ||
42 | pub(crate) type_ref: TypeRef, | ||
43 | pub(crate) bound: TypeBound, | ||
44 | } | ||
45 | 10 | ||
46 | #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] | 11 | #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] |
47 | pub enum GenericDef { | 12 | pub enum GenericDef { |
@@ -66,134 +31,19 @@ impl_froms!( | |||
66 | Const | 31 | Const |
67 | ); | 32 | ); |
68 | 33 | ||
69 | impl GenericParams { | 34 | pub(crate) fn generic_params_query( |
70 | pub(crate) fn generic_params_query( | 35 | db: &(impl DefDatabase + AstDatabase), |
71 | db: &(impl DefDatabase + AstDatabase), | 36 | def: GenericDef, |
72 | def: GenericDef, | 37 | ) -> Arc<GenericParams> { |
73 | ) -> Arc<GenericParams> { | 38 | let parent = match def { |
74 | let parent = match def { | 39 | GenericDef::Function(it) => it.container(db).map(GenericDef::from), |
75 | GenericDef::Function(it) => it.container(db).map(GenericDef::from), | 40 | GenericDef::TypeAlias(it) => it.container(db).map(GenericDef::from), |
76 | GenericDef::TypeAlias(it) => it.container(db).map(GenericDef::from), | 41 | GenericDef::Const(it) => it.container(db).map(GenericDef::from), |
77 | GenericDef::Const(it) => it.container(db).map(GenericDef::from), | 42 | GenericDef::EnumVariant(it) => Some(it.parent_enum(db).into()), |
78 | GenericDef::EnumVariant(it) => Some(it.parent_enum(db).into()), | 43 | GenericDef::Adt(_) | GenericDef::Trait(_) => None, |
79 | GenericDef::Adt(_) | GenericDef::Trait(_) => None, | 44 | GenericDef::ImplBlock(_) => None, |
80 | GenericDef::ImplBlock(_) => None, | 45 | }; |
81 | }; | 46 | Arc::new(GenericParams::new(db, def.into(), parent.map(|it| db.generic_params(it)))) |
82 | let mut generics = GenericParams { | ||
83 | def, | ||
84 | params: Vec::new(), | ||
85 | parent_params: parent.map(|p| db.generic_params(p)), | ||
86 | where_predicates: Vec::new(), | ||
87 | }; | ||
88 | let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32; | ||
89 | // FIXME: add `: Sized` bound for everything except for `Self` in traits | ||
90 | match def { | ||
91 | GenericDef::Function(it) => generics.fill(&it.source(db).value, start), | ||
92 | GenericDef::Adt(Adt::Struct(it)) => generics.fill(&it.source(db).value, start), | ||
93 | GenericDef::Adt(Adt::Union(it)) => generics.fill(&it.source(db).value, start), | ||
94 | GenericDef::Adt(Adt::Enum(it)) => generics.fill(&it.source(db).value, start), | ||
95 | GenericDef::Trait(it) => { | ||
96 | // traits get the Self type as an implicit first type parameter | ||
97 | generics.params.push(GenericParam { | ||
98 | idx: start, | ||
99 | name: name::SELF_TYPE, | ||
100 | default: None, | ||
101 | }); | ||
102 | generics.fill(&it.source(db).value, start + 1); | ||
103 | // add super traits as bounds on Self | ||
104 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar | ||
105 | let self_param = TypeRef::Path(name::SELF_TYPE.into()); | ||
106 | generics.fill_bounds(&it.source(db).value, self_param); | ||
107 | } | ||
108 | GenericDef::TypeAlias(it) => generics.fill(&it.source(db).value, start), | ||
109 | // Note that we don't add `Self` here: in `impl`s, `Self` is not a | ||
110 | // type-parameter, but rather is a type-alias for impl's target | ||
111 | // type, so this is handled by the resolver. | ||
112 | GenericDef::ImplBlock(it) => generics.fill(&it.source(db).value, start), | ||
113 | GenericDef::EnumVariant(_) | GenericDef::Const(_) => {} | ||
114 | } | ||
115 | |||
116 | Arc::new(generics) | ||
117 | } | ||
118 | |||
119 | fn fill(&mut self, node: &impl TypeParamsOwner, start: u32) { | ||
120 | if let Some(params) = node.type_param_list() { | ||
121 | self.fill_params(params, start) | ||
122 | } | ||
123 | if let Some(where_clause) = node.where_clause() { | ||
124 | self.fill_where_predicates(where_clause); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | fn fill_bounds(&mut self, node: &impl ast::TypeBoundsOwner, type_ref: TypeRef) { | ||
129 | for bound in | ||
130 | node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds()) | ||
131 | { | ||
132 | self.add_where_predicate_from_bound(bound, type_ref.clone()); | ||
133 | } | ||
134 | } | ||
135 | |||
136 | fn fill_params(&mut self, params: ast::TypeParamList, start: u32) { | ||
137 | for (idx, type_param) in params.type_params().enumerate() { | ||
138 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); | ||
139 | // FIXME: Use `Path::from_src` | ||
140 | let default = type_param.default_type().map(TypeRef::from_ast); | ||
141 | |||
142 | let param = GenericParam { idx: idx as u32 + start, name: name.clone(), default }; | ||
143 | self.params.push(param); | ||
144 | |||
145 | let type_ref = TypeRef::Path(name.into()); | ||
146 | self.fill_bounds(&type_param, type_ref); | ||
147 | } | ||
148 | } | ||
149 | |||
150 | fn fill_where_predicates(&mut self, where_clause: ast::WhereClause) { | ||
151 | for pred in where_clause.predicates() { | ||
152 | let type_ref = match pred.type_ref() { | ||
153 | Some(type_ref) => type_ref, | ||
154 | None => continue, | ||
155 | }; | ||
156 | let type_ref = TypeRef::from_ast(type_ref); | ||
157 | for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) { | ||
158 | self.add_where_predicate_from_bound(bound, type_ref.clone()); | ||
159 | } | ||
160 | } | ||
161 | } | ||
162 | |||
163 | fn add_where_predicate_from_bound(&mut self, bound: ast::TypeBound, type_ref: TypeRef) { | ||
164 | if bound.has_question_mark() { | ||
165 | // FIXME: remove this bound | ||
166 | return; | ||
167 | } | ||
168 | let bound = TypeBound::from_ast(bound); | ||
169 | self.where_predicates.push(WherePredicate { type_ref, bound }); | ||
170 | } | ||
171 | |||
172 | pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { | ||
173 | self.params.iter().find(|p| &p.name == name) | ||
174 | } | ||
175 | |||
176 | pub fn count_parent_params(&self) -> usize { | ||
177 | self.parent_params.as_ref().map(|p| p.count_params_including_parent()).unwrap_or(0) | ||
178 | } | ||
179 | |||
180 | pub fn count_params_including_parent(&self) -> usize { | ||
181 | let parent_count = self.count_parent_params(); | ||
182 | parent_count + self.params.len() | ||
183 | } | ||
184 | |||
185 | fn for_each_param<'a>(&'a self, f: &mut impl FnMut(&'a GenericParam)) { | ||
186 | if let Some(parent) = &self.parent_params { | ||
187 | parent.for_each_param(f); | ||
188 | } | ||
189 | self.params.iter().for_each(f); | ||
190 | } | ||
191 | |||
192 | pub fn params_including_parent(&self) -> Vec<&GenericParam> { | ||
193 | let mut vec = Vec::with_capacity(self.count_params_including_parent()); | ||
194 | self.for_each_param(&mut |p| vec.push(p)); | ||
195 | vec | ||
196 | } | ||
197 | } | 47 | } |
198 | 48 | ||
199 | impl GenericDef { | 49 | impl GenericDef { |
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index 79b92180a..a2fa0bb79 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs | |||
@@ -369,7 +369,7 @@ impl Resolver { | |||
369 | 369 | ||
370 | pub(crate) fn generic_def(&self) -> Option<crate::generics::GenericDef> { | 370 | pub(crate) fn generic_def(&self) -> Option<crate::generics::GenericDef> { |
371 | self.scopes.iter().find_map(|scope| match scope { | 371 | self.scopes.iter().find_map(|scope| match scope { |
372 | Scope::GenericParams(params) => Some(params.def), | 372 | Scope::GenericParams(params) => Some(params.def.into()), |
373 | _ => None, | 373 | _ => None, |
374 | }) | 374 | }) |
375 | } | 375 | } |
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs new file mode 100644 index 000000000..4adfc16bb --- /dev/null +++ b/crates/ra_hir_def/src/generics.rs | |||
@@ -0,0 +1,163 @@ | |||
1 | //! Many kinds of items or constructs can have generic parameters: functions, | ||
2 | //! structs, impls, traits, etc. This module provides a common HIR for these | ||
3 | //! generic parameters. See also the `Generics` type and the `generics_of` query | ||
4 | //! in rustc. | ||
5 | use std::sync::Arc; | ||
6 | |||
7 | use hir_expand::name::{self, AsName, Name}; | ||
8 | |||
9 | use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; | ||
10 | |||
11 | use crate::{ | ||
12 | db::DefDatabase2, | ||
13 | type_ref::{TypeBound, TypeRef}, | ||
14 | AdtId, AstItemDef, GenericDefId, | ||
15 | }; | ||
16 | |||
17 | /// Data about a generic parameter (to a function, struct, impl, ...). | ||
18 | #[derive(Clone, PartialEq, Eq, Debug)] | ||
19 | pub struct GenericParam { | ||
20 | // FIXME: give generic params proper IDs | ||
21 | pub idx: u32, | ||
22 | pub name: Name, | ||
23 | pub default: Option<TypeRef>, | ||
24 | } | ||
25 | |||
26 | /// Data about the generic parameters of a function, struct, impl, etc. | ||
27 | #[derive(Clone, PartialEq, Eq, Debug)] | ||
28 | pub struct GenericParams { | ||
29 | pub def: GenericDefId, | ||
30 | pub parent_params: Option<Arc<GenericParams>>, | ||
31 | pub params: Vec<GenericParam>, | ||
32 | pub where_predicates: Vec<WherePredicate>, | ||
33 | } | ||
34 | |||
35 | /// A single predicate from a where clause, i.e. `where Type: Trait`. Combined | ||
36 | /// where clauses like `where T: Foo + Bar` are turned into multiple of these. | ||
37 | /// It might still result in multiple actual predicates though, because of | ||
38 | /// associated type bindings like `Iterator<Item = u32>`. | ||
39 | #[derive(Clone, PartialEq, Eq, Debug)] | ||
40 | pub struct WherePredicate { | ||
41 | pub type_ref: TypeRef, | ||
42 | pub bound: TypeBound, | ||
43 | } | ||
44 | |||
45 | impl GenericParams { | ||
46 | pub fn new( | ||
47 | db: &impl DefDatabase2, | ||
48 | def: GenericDefId, | ||
49 | parent_params: Option<Arc<GenericParams>>, | ||
50 | ) -> GenericParams { | ||
51 | let mut generics = | ||
52 | GenericParams { def, params: Vec::new(), parent_params, where_predicates: Vec::new() }; | ||
53 | let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32; | ||
54 | // FIXME: add `: Sized` bound for everything except for `Self` in traits | ||
55 | match def { | ||
56 | GenericDefId::FunctionId(it) => generics.fill(&it.source(db).value, start), | ||
57 | GenericDefId::AdtId(AdtId::StructId(it)) => { | ||
58 | generics.fill(&it.0.source(db).value, start) | ||
59 | } | ||
60 | GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.0.source(db).value, start), | ||
61 | GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value, start), | ||
62 | GenericDefId::TraitId(it) => { | ||
63 | // traits get the Self type as an implicit first type parameter | ||
64 | generics.params.push(GenericParam { | ||
65 | idx: start, | ||
66 | name: name::SELF_TYPE, | ||
67 | default: None, | ||
68 | }); | ||
69 | generics.fill(&it.source(db).value, start + 1); | ||
70 | // add super traits as bounds on Self | ||
71 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar | ||
72 | let self_param = TypeRef::Path(name::SELF_TYPE.into()); | ||
73 | generics.fill_bounds(&it.source(db).value, self_param); | ||
74 | } | ||
75 | GenericDefId::TypeAliasId(it) => generics.fill(&it.source(db).value, start), | ||
76 | // Note that we don't add `Self` here: in `impl`s, `Self` is not a | ||
77 | // type-parameter, but rather is a type-alias for impl's target | ||
78 | // type, so this is handled by the resolver. | ||
79 | GenericDefId::ImplId(it) => generics.fill(&it.source(db).value, start), | ||
80 | GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {} | ||
81 | } | ||
82 | |||
83 | generics | ||
84 | } | ||
85 | |||
86 | fn fill(&mut self, node: &impl TypeParamsOwner, start: u32) { | ||
87 | if let Some(params) = node.type_param_list() { | ||
88 | self.fill_params(params, start) | ||
89 | } | ||
90 | if let Some(where_clause) = node.where_clause() { | ||
91 | self.fill_where_predicates(where_clause); | ||
92 | } | ||
93 | } | ||
94 | |||
95 | fn fill_bounds(&mut self, node: &impl ast::TypeBoundsOwner, type_ref: TypeRef) { | ||
96 | for bound in | ||
97 | node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds()) | ||
98 | { | ||
99 | self.add_where_predicate_from_bound(bound, type_ref.clone()); | ||
100 | } | ||
101 | } | ||
102 | |||
103 | fn fill_params(&mut self, params: ast::TypeParamList, start: u32) { | ||
104 | for (idx, type_param) in params.type_params().enumerate() { | ||
105 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); | ||
106 | // FIXME: Use `Path::from_src` | ||
107 | let default = type_param.default_type().map(TypeRef::from_ast); | ||
108 | let param = GenericParam { idx: idx as u32 + start, name: name.clone(), default }; | ||
109 | self.params.push(param); | ||
110 | |||
111 | let type_ref = TypeRef::Path(name.into()); | ||
112 | self.fill_bounds(&type_param, type_ref); | ||
113 | } | ||
114 | } | ||
115 | |||
116 | fn fill_where_predicates(&mut self, where_clause: ast::WhereClause) { | ||
117 | for pred in where_clause.predicates() { | ||
118 | let type_ref = match pred.type_ref() { | ||
119 | Some(type_ref) => type_ref, | ||
120 | None => continue, | ||
121 | }; | ||
122 | let type_ref = TypeRef::from_ast(type_ref); | ||
123 | for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) { | ||
124 | self.add_where_predicate_from_bound(bound, type_ref.clone()); | ||
125 | } | ||
126 | } | ||
127 | } | ||
128 | |||
129 | fn add_where_predicate_from_bound(&mut self, bound: ast::TypeBound, type_ref: TypeRef) { | ||
130 | if bound.has_question_mark() { | ||
131 | // FIXME: remove this bound | ||
132 | return; | ||
133 | } | ||
134 | let bound = TypeBound::from_ast(bound); | ||
135 | self.where_predicates.push(WherePredicate { type_ref, bound }); | ||
136 | } | ||
137 | |||
138 | pub fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { | ||
139 | self.params.iter().find(|p| &p.name == name) | ||
140 | } | ||
141 | |||
142 | pub fn count_parent_params(&self) -> usize { | ||
143 | self.parent_params.as_ref().map(|p| p.count_params_including_parent()).unwrap_or(0) | ||
144 | } | ||
145 | |||
146 | pub fn count_params_including_parent(&self) -> usize { | ||
147 | let parent_count = self.count_parent_params(); | ||
148 | parent_count + self.params.len() | ||
149 | } | ||
150 | |||
151 | fn for_each_param<'a>(&'a self, f: &mut impl FnMut(&'a GenericParam)) { | ||
152 | if let Some(parent) = &self.parent_params { | ||
153 | parent.for_each_param(f); | ||
154 | } | ||
155 | self.params.iter().for_each(f); | ||
156 | } | ||
157 | |||
158 | pub fn params_including_parent(&self) -> Vec<&GenericParam> { | ||
159 | let mut vec = Vec::with_capacity(self.count_params_including_parent()); | ||
160 | self.for_each_param(&mut |p| vec.push(p)); | ||
161 | vec | ||
162 | } | ||
163 | } | ||
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 50caf4f83..dffc82ff8 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs | |||
@@ -17,6 +17,7 @@ pub mod imp; | |||
17 | pub mod diagnostics; | 17 | pub mod diagnostics; |
18 | pub mod expr; | 18 | pub mod expr; |
19 | pub mod body; | 19 | pub mod body; |
20 | pub mod generics; | ||
20 | 21 | ||
21 | #[cfg(test)] | 22 | #[cfg(test)] |
22 | mod test_db; | 23 | mod test_db; |
@@ -408,3 +409,26 @@ pub enum AssocItemId { | |||
408 | // require not implementing From, and instead having some checked way of | 409 | // require not implementing From, and instead having some checked way of |
409 | // casting them, and somehow making the constructors private, which would be annoying. | 410 | // casting them, and somehow making the constructors private, which would be annoying. |
410 | impl_froms!(AssocItemId: FunctionId, ConstId, TypeAliasId); | 411 | impl_froms!(AssocItemId: FunctionId, ConstId, TypeAliasId); |
412 | |||
413 | #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] | ||
414 | pub enum GenericDefId { | ||
415 | FunctionId(FunctionId), | ||
416 | AdtId(AdtId), | ||
417 | TraitId(TraitId), | ||
418 | TypeAliasId(TypeAliasId), | ||
419 | ImplId(ImplId), | ||
420 | // enum variants cannot have generics themselves, but their parent enums | ||
421 | // can, and this makes some code easier to write | ||
422 | EnumVariantId(EnumVariantId), | ||
423 | // consts can have type parameters from their parents (i.e. associated consts of traits) | ||
424 | ConstId(ConstId), | ||
425 | } | ||
426 | impl_froms!( | ||
427 | GenericDefId: FunctionId, | ||
428 | AdtId(StructId, EnumId, UnionId), | ||
429 | TraitId, | ||
430 | TypeAliasId, | ||
431 | ImplId, | ||
432 | EnumVariantId, | ||
433 | ConstId | ||
434 | ); | ||