aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r--crates/ra_hir/src/ty.rs141
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
15use std::ops::Deref; 15use std::ops::Deref;
16use std::sync::Arc; 16use std::sync::Arc;
17use std::{fmt, mem}; 17use std::{fmt, iter, mem};
18 18
19use crate::{ 19use 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};
23use display::{HirDisplay, HirFormatter}; 23use 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
114impl 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)]
373pub struct SubstsBuilder {
374 vec: Vec<Ty>,
375 param_count: usize,
274} 376}
275 377
276impl From<Vec<Ty>> for Substs { 378impl 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