diff options
Diffstat (limited to 'crates/ra_hir/src/generics.rs')
-rw-r--r-- | crates/ra_hir/src/generics.rs | 37 |
1 files changed, 32 insertions, 5 deletions
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index 84fe94289..5625c2459 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs | |||
@@ -9,7 +9,7 @@ use ra_syntax::ast::{self, NameOwner, TypeParamsOwner}; | |||
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | db::DefDatabase, | 11 | db::DefDatabase, |
12 | Name, AsName, Function, Struct, Enum, Trait, TypeAlias, ImplBlock | 12 | Name, AsName, Function, Struct, Enum, Trait, TypeAlias, ImplBlock, Container |
13 | }; | 13 | }; |
14 | 14 | ||
15 | /// Data about a generic parameter (to a function, struct, impl, ...). | 15 | /// Data about a generic parameter (to a function, struct, impl, ...). |
@@ -27,6 +27,7 @@ pub struct GenericParams { | |||
27 | pub(crate) params: Vec<GenericParam>, | 27 | pub(crate) params: Vec<GenericParam>, |
28 | } | 28 | } |
29 | 29 | ||
30 | // FIXME: consts can have type parameters from their parents (i.e. associated consts of traits) | ||
30 | #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] | 31 | #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] |
31 | pub enum GenericDef { | 32 | pub enum GenericDef { |
32 | Function(Function), | 33 | Function(Function), |
@@ -45,18 +46,22 @@ impl GenericParams { | |||
45 | ) -> Arc<GenericParams> { | 46 | ) -> Arc<GenericParams> { |
46 | let mut generics = GenericParams::default(); | 47 | let mut generics = GenericParams::default(); |
47 | let parent = match def { | 48 | let parent = match def { |
48 | GenericDef::Function(it) => it.impl_block(db), | 49 | GenericDef::Function(it) => it.container(db).map(GenericDef::from), |
49 | GenericDef::TypeAlias(it) => it.impl_block(db), | 50 | GenericDef::TypeAlias(it) => it.container(db).map(GenericDef::from), |
50 | GenericDef::Struct(_) | GenericDef::Enum(_) | GenericDef::Trait(_) => None, | 51 | GenericDef::Struct(_) | GenericDef::Enum(_) | GenericDef::Trait(_) => None, |
51 | GenericDef::ImplBlock(_) => None, | 52 | GenericDef::ImplBlock(_) => None, |
52 | }; | 53 | }; |
53 | generics.parent_params = parent.map(|p| p.generic_params(db)); | 54 | generics.parent_params = parent.map(|p| db.generic_params(p)); |
54 | let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32; | 55 | let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32; |
55 | match def { | 56 | match def { |
56 | GenericDef::Function(it) => generics.fill(&*it.source(db).1, start), | 57 | GenericDef::Function(it) => generics.fill(&*it.source(db).1, start), |
57 | GenericDef::Struct(it) => generics.fill(&*it.source(db).1, start), | 58 | GenericDef::Struct(it) => generics.fill(&*it.source(db).1, start), |
58 | GenericDef::Enum(it) => generics.fill(&*it.source(db).1, start), | 59 | GenericDef::Enum(it) => generics.fill(&*it.source(db).1, start), |
59 | GenericDef::Trait(it) => generics.fill(&*it.source(db).1, start), | 60 | GenericDef::Trait(it) => { |
61 | // traits get the Self type as an implicit first type parameter | ||
62 | generics.params.push(GenericParam { idx: start, name: Name::self_type() }); | ||
63 | generics.fill(&*it.source(db).1, start + 1); | ||
64 | } | ||
60 | GenericDef::TypeAlias(it) => generics.fill(&*it.source(db).1, start), | 65 | GenericDef::TypeAlias(it) => generics.fill(&*it.source(db).1, start), |
61 | GenericDef::ImplBlock(it) => generics.fill(&*it.source(db).1, start), | 66 | GenericDef::ImplBlock(it) => generics.fill(&*it.source(db).1, start), |
62 | } | 67 | } |
@@ -104,3 +109,25 @@ impl GenericParams { | |||
104 | vec | 109 | vec |
105 | } | 110 | } |
106 | } | 111 | } |
112 | |||
113 | impl From<Container> for GenericDef { | ||
114 | fn from(c: Container) -> Self { | ||
115 | match c { | ||
116 | Container::Trait(trait_) => trait_.into(), | ||
117 | Container::ImplBlock(impl_block) => impl_block.into(), | ||
118 | } | ||
119 | } | ||
120 | } | ||
121 | |||
122 | pub trait HasGenericParams { | ||
123 | fn generic_params(self, db: &impl DefDatabase) -> Arc<GenericParams>; | ||
124 | } | ||
125 | |||
126 | impl<T> HasGenericParams for T | ||
127 | where | ||
128 | T: Into<GenericDef>, | ||
129 | { | ||
130 | fn generic_params(self, db: &impl DefDatabase) -> Arc<GenericParams> { | ||
131 | db.generic_params(self.into()) | ||
132 | } | ||
133 | } | ||