diff options
author | Florian Diebold <[email protected]> | 2019-09-26 20:37:03 +0100 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2019-09-26 22:03:39 +0100 |
commit | daaf46177e5dc63e20e5a1ec5692e53cc8f7bc34 (patch) | |
tree | 2229733948df98f119aee5eca600a50726192c68 /crates/ra_hir/src/ty.rs | |
parent | 1002e470747fe5887a2915689e21d9be3a1ca5d8 (diff) |
Add SubstsBuilder
+ further refactoring.
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 141 |
1 files changed, 135 insertions, 6 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index fae9c1e22..d161735e8 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -14,11 +14,11 @@ pub(crate) mod display; | |||
14 | 14 | ||
15 | use std::ops::Deref; | 15 | use std::ops::Deref; |
16 | use std::sync::Arc; | 16 | use std::sync::Arc; |
17 | use std::{fmt, mem}; | 17 | use std::{fmt, iter, mem}; |
18 | 18 | ||
19 | use crate::{ | 19 | use crate::{ |
20 | db::HirDatabase, expr::ExprId, type_ref::Mutability, Adt, DefWithBody, GenericParams, Name, | 20 | db::HirDatabase, expr::ExprId, type_ref::Mutability, Adt, Crate, DefWithBody, GenericParams, |
21 | Trait, TypeAlias, | 21 | HasGenericParams, Name, Trait, TypeAlias, |
22 | }; | 22 | }; |
23 | use display::{HirDisplay, HirFormatter}; | 23 | use display::{HirDisplay, HirFormatter}; |
24 | 24 | ||
@@ -111,6 +111,81 @@ pub enum TypeCtor { | |||
111 | Closure { def: DefWithBody, expr: ExprId }, | 111 | Closure { def: DefWithBody, expr: ExprId }, |
112 | } | 112 | } |
113 | 113 | ||
114 | impl TypeCtor { | ||
115 | pub fn num_ty_params(self, db: &impl HirDatabase) -> usize { | ||
116 | match self { | ||
117 | TypeCtor::Bool | ||
118 | | TypeCtor::Char | ||
119 | | TypeCtor::Int(_) | ||
120 | | TypeCtor::Float(_) | ||
121 | | TypeCtor::Str | ||
122 | | TypeCtor::Never => 0, | ||
123 | TypeCtor::Slice | ||
124 | | TypeCtor::Array | ||
125 | | TypeCtor::RawPtr(_) | ||
126 | | TypeCtor::Ref(_) | ||
127 | | TypeCtor::Closure { .. } // 1 param representing the signature of the closure | ||
128 | => 1, | ||
129 | TypeCtor::Adt(adt) => { | ||
130 | let generic_params = adt.generic_params(db); | ||
131 | generic_params.count_params_including_parent() | ||
132 | } | ||
133 | TypeCtor::FnDef(callable) => { | ||
134 | let generic_params = callable.generic_params(db); | ||
135 | generic_params.count_params_including_parent() | ||
136 | } | ||
137 | TypeCtor::AssociatedType(type_alias) => { | ||
138 | let generic_params = type_alias.generic_params(db); | ||
139 | generic_params.count_params_including_parent() | ||
140 | } | ||
141 | TypeCtor::FnPtr { num_args } => num_args as usize + 1, | ||
142 | TypeCtor::Tuple { cardinality } => cardinality as usize, | ||
143 | } | ||
144 | } | ||
145 | |||
146 | pub fn krate(self, db: &impl HirDatabase) -> Option<Crate> { | ||
147 | match self { | ||
148 | TypeCtor::Bool | ||
149 | | TypeCtor::Char | ||
150 | | TypeCtor::Int(_) | ||
151 | | TypeCtor::Float(_) | ||
152 | | TypeCtor::Str | ||
153 | | TypeCtor::Never | ||
154 | | TypeCtor::Slice | ||
155 | | TypeCtor::Array | ||
156 | | TypeCtor::RawPtr(_) | ||
157 | | TypeCtor::Ref(_) | ||
158 | | TypeCtor::FnPtr { .. } | ||
159 | | TypeCtor::Tuple { .. } => None, | ||
160 | TypeCtor::Closure { def, .. } => def.krate(db), | ||
161 | TypeCtor::Adt(adt) => adt.krate(db), | ||
162 | TypeCtor::FnDef(callable) => callable.krate(db), | ||
163 | TypeCtor::AssociatedType(type_alias) => type_alias.krate(db), | ||
164 | } | ||
165 | } | ||
166 | |||
167 | pub fn as_generic_def(self) -> Option<crate::generics::GenericDef> { | ||
168 | match self { | ||
169 | TypeCtor::Bool | ||
170 | | TypeCtor::Char | ||
171 | | TypeCtor::Int(_) | ||
172 | | TypeCtor::Float(_) | ||
173 | | TypeCtor::Str | ||
174 | | TypeCtor::Never | ||
175 | | TypeCtor::Slice | ||
176 | | TypeCtor::Array | ||
177 | | TypeCtor::RawPtr(_) | ||
178 | | TypeCtor::Ref(_) | ||
179 | | TypeCtor::FnPtr { .. } | ||
180 | | TypeCtor::Tuple { .. } | ||
181 | | TypeCtor::Closure { .. } => None, | ||
182 | TypeCtor::Adt(adt) => Some(adt.into()), | ||
183 | TypeCtor::FnDef(callable) => Some(callable.into()), | ||
184 | TypeCtor::AssociatedType(type_alias) => Some(type_alias.into()), | ||
185 | } | ||
186 | } | ||
187 | } | ||
188 | |||
114 | /// A nominal type with (maybe 0) type parameters. This might be a primitive | 189 | /// A nominal type with (maybe 0) type parameters. This might be a primitive |
115 | /// type like `bool`, a struct, tuple, function pointer, reference or | 190 | /// type like `bool`, a struct, tuple, function pointer, reference or |
116 | /// several other things. | 191 | /// several other things. |
@@ -271,11 +346,65 @@ impl Substs { | |||
271 | .into(), | 346 | .into(), |
272 | ) | 347 | ) |
273 | } | 348 | } |
349 | |||
350 | pub fn build_for_def( | ||
351 | db: &impl HirDatabase, | ||
352 | def: impl crate::HasGenericParams, | ||
353 | ) -> SubstsBuilder { | ||
354 | let params = def.generic_params(db); | ||
355 | let param_count = params.count_params_including_parent(); | ||
356 | Substs::builder(param_count) | ||
357 | } | ||
358 | |||
359 | pub fn build_for_generics(generic_params: &GenericParams) -> SubstsBuilder { | ||
360 | Substs::builder(generic_params.count_params_including_parent()) | ||
361 | } | ||
362 | |||
363 | pub fn build_for_type_ctor(db: &impl HirDatabase, type_ctor: TypeCtor) -> SubstsBuilder { | ||
364 | Substs::builder(type_ctor.num_ty_params(db)) | ||
365 | } | ||
366 | |||
367 | fn builder(param_count: usize) -> SubstsBuilder { | ||
368 | SubstsBuilder { vec: Vec::with_capacity(param_count), param_count } | ||
369 | } | ||
370 | } | ||
371 | |||
372 | #[derive(Debug, Clone)] | ||
373 | pub struct SubstsBuilder { | ||
374 | vec: Vec<Ty>, | ||
375 | param_count: usize, | ||
274 | } | 376 | } |
275 | 377 | ||
276 | impl From<Vec<Ty>> for Substs { | 378 | impl SubstsBuilder { |
277 | fn from(v: Vec<Ty>) -> Self { | 379 | pub fn build(self) -> Substs { |
278 | Substs(v.into()) | 380 | assert_eq!(self.vec.len(), self.param_count); |
381 | Substs(self.vec.into()) | ||
382 | } | ||
383 | |||
384 | pub fn push(mut self, ty: Ty) -> Self { | ||
385 | self.vec.push(ty); | ||
386 | self | ||
387 | } | ||
388 | |||
389 | fn remaining(&self) -> usize { | ||
390 | self.param_count - self.vec.len() | ||
391 | } | ||
392 | |||
393 | pub fn fill_with_bound_vars(mut self, starting_from: u32) -> Self { | ||
394 | self.vec.extend((starting_from..starting_from + self.remaining() as u32).map(Ty::Bound)); | ||
395 | self | ||
396 | } | ||
397 | |||
398 | pub fn fill_with_unknown(mut self) -> Self { | ||
399 | self.vec.extend(iter::repeat(Ty::Unknown).take(self.remaining())); | ||
400 | self | ||
401 | } | ||
402 | |||
403 | pub fn use_parent_substs(mut self, parent_substs: &Substs) -> Self { | ||
404 | assert!(self.vec.is_empty()); | ||
405 | assert!(parent_substs.len() <= self.param_count); | ||
406 | self.vec.extend(parent_substs.iter().cloned()); | ||
407 | self | ||
279 | } | 408 | } |
280 | } | 409 | } |
281 | 410 | ||