diff options
Diffstat (limited to 'crates/ra_hir/src/generics.rs')
-rw-r--r-- | crates/ra_hir/src/generics.rs | 62 |
1 files changed, 43 insertions, 19 deletions
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index 2e52c5871..c29b96f50 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs | |||
@@ -8,7 +8,7 @@ use std::sync::Arc; | |||
8 | use ra_syntax::ast::{self, NameOwner, TypeParamsOwner, TypeBoundsOwner}; | 8 | use ra_syntax::ast::{self, NameOwner, TypeParamsOwner, TypeBoundsOwner}; |
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | db::DefDatabase, | 11 | db::{ HirDatabase, DefDatabase}, |
12 | Name, AsName, Function, Struct, Enum, Trait, TypeAlias, ImplBlock, Container, path::Path, type_ref::TypeRef, AdtDef | 12 | Name, AsName, Function, Struct, Enum, Trait, TypeAlias, ImplBlock, Container, path::Path, type_ref::TypeRef, AdtDef |
13 | }; | 13 | }; |
14 | 14 | ||
@@ -32,8 +32,8 @@ pub struct GenericParams { | |||
32 | /// where clauses like `where T: Foo + Bar` are turned into multiple of these. | 32 | /// where clauses like `where T: Foo + Bar` are turned into multiple of these. |
33 | #[derive(Clone, PartialEq, Eq, Debug)] | 33 | #[derive(Clone, PartialEq, Eq, Debug)] |
34 | pub struct WherePredicate { | 34 | pub struct WherePredicate { |
35 | type_ref: TypeRef, | 35 | pub(crate) type_ref: TypeRef, |
36 | trait_ref: Path, | 36 | pub(crate) trait_ref: Path, |
37 | } | 37 | } |
38 | 38 | ||
39 | // FIXME: consts can have type parameters from their parents (i.e. associated consts of traits) | 39 | // FIXME: consts can have type parameters from their parents (i.e. associated consts of traits) |
@@ -90,8 +90,17 @@ impl GenericParams { | |||
90 | fn fill_params(&mut self, params: &ast::TypeParamList, start: u32) { | 90 | fn fill_params(&mut self, params: &ast::TypeParamList, start: u32) { |
91 | for (idx, type_param) in params.type_params().enumerate() { | 91 | for (idx, type_param) in params.type_params().enumerate() { |
92 | let name = type_param.name().map(AsName::as_name).unwrap_or_else(Name::missing); | 92 | let name = type_param.name().map(AsName::as_name).unwrap_or_else(Name::missing); |
93 | let param = GenericParam { idx: idx as u32 + start, name }; | 93 | let param = GenericParam { idx: idx as u32 + start, name: name.clone() }; |
94 | self.params.push(param); | 94 | self.params.push(param); |
95 | |||
96 | let type_ref = TypeRef::Path(name.into()); | ||
97 | for bound in type_param | ||
98 | .type_bound_list() | ||
99 | .iter() | ||
100 | .flat_map(|type_bound_list| type_bound_list.bounds()) | ||
101 | { | ||
102 | self.add_where_predicate_from_bound(bound, type_ref.clone()); | ||
103 | } | ||
95 | } | 104 | } |
96 | } | 105 | } |
97 | 106 | ||
@@ -101,26 +110,28 @@ impl GenericParams { | |||
101 | Some(type_ref) => type_ref, | 110 | Some(type_ref) => type_ref, |
102 | None => continue, | 111 | None => continue, |
103 | }; | 112 | }; |
113 | let type_ref = TypeRef::from_ast(type_ref); | ||
104 | for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) { | 114 | for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) { |
105 | let path = bound | 115 | self.add_where_predicate_from_bound(bound, type_ref.clone()); |
106 | .type_ref() | ||
107 | .and_then(|tr| match tr.kind() { | ||
108 | ast::TypeRefKind::PathType(path) => path.path(), | ||
109 | _ => None, | ||
110 | }) | ||
111 | .and_then(Path::from_ast); | ||
112 | let path = match path { | ||
113 | Some(p) => p, | ||
114 | None => continue, | ||
115 | }; | ||
116 | self.where_predicates.push(WherePredicate { | ||
117 | type_ref: TypeRef::from_ast(type_ref), | ||
118 | trait_ref: path, | ||
119 | }); | ||
120 | } | 116 | } |
121 | } | 117 | } |
122 | } | 118 | } |
123 | 119 | ||
120 | fn add_where_predicate_from_bound(&mut self, bound: &ast::TypeBound, type_ref: TypeRef) { | ||
121 | let path = bound | ||
122 | .type_ref() | ||
123 | .and_then(|tr| match tr.kind() { | ||
124 | ast::TypeRefKind::PathType(path) => path.path(), | ||
125 | _ => None, | ||
126 | }) | ||
127 | .and_then(Path::from_ast); | ||
128 | let path = match path { | ||
129 | Some(p) => p, | ||
130 | None => return, | ||
131 | }; | ||
132 | self.where_predicates.push(WherePredicate { type_ref, trait_ref: path }); | ||
133 | } | ||
134 | |||
124 | pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { | 135 | pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { |
125 | self.params.iter().find(|p| &p.name == name) | 136 | self.params.iter().find(|p| &p.name == name) |
126 | } | 137 | } |
@@ -148,6 +159,19 @@ impl GenericParams { | |||
148 | } | 159 | } |
149 | } | 160 | } |
150 | 161 | ||
162 | impl GenericDef { | ||
163 | pub(crate) fn resolver(&self, db: &impl HirDatabase) -> crate::Resolver { | ||
164 | match self { | ||
165 | GenericDef::Function(inner) => inner.resolver(db), | ||
166 | GenericDef::Struct(inner) => inner.resolver(db), | ||
167 | GenericDef::Enum(inner) => inner.resolver(db), | ||
168 | GenericDef::Trait(inner) => inner.resolver(db), | ||
169 | GenericDef::TypeAlias(inner) => inner.resolver(db), | ||
170 | GenericDef::ImplBlock(inner) => inner.resolver(db), | ||
171 | } | ||
172 | } | ||
173 | } | ||
174 | |||
151 | impl From<Container> for GenericDef { | 175 | impl From<Container> for GenericDef { |
152 | fn from(c: Container) -> Self { | 176 | fn from(c: Container) -> Self { |
153 | match c { | 177 | match c { |