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.rs112
1 files changed, 84 insertions, 28 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 12e10c751..f4eee835f 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -13,9 +13,10 @@ mod infer;
13pub(crate) mod display; 13pub(crate) mod display;
14 14
15use std::sync::Arc; 15use std::sync::Arc;
16use std::ops::Deref;
16use std::{fmt, mem}; 17use std::{fmt, mem};
17 18
18use crate::{Name, AdtDef, type_ref::Mutability, db::HirDatabase, Trait}; 19use crate::{Name, AdtDef, type_ref::Mutability, db::HirDatabase, Trait, GenericParams};
19use display::{HirDisplay, HirFormatter}; 20use display::{HirDisplay, HirFormatter};
20 21
21pub(crate) use lower::{TypableDef, type_for_def, type_for_field, callable_item_sig}; 22pub(crate) use lower::{TypableDef, type_for_def, type_for_field, callable_item_sig};
@@ -81,13 +82,13 @@ pub enum TypeCtor {
81 /// fn foo() -> i32 { 1 } 82 /// fn foo() -> i32 { 1 }
82 /// let bar: fn() -> i32 = foo; 83 /// let bar: fn() -> i32 = foo;
83 /// ``` 84 /// ```
84 FnPtr, 85 FnPtr { num_args: u16 },
85 86
86 /// The never type `!`. 87 /// The never type `!`.
87 Never, 88 Never,
88 89
89 /// A tuple type. For example, `(i32, bool)`. 90 /// A tuple type. For example, `(i32, bool)`.
90 Tuple, 91 Tuple { cardinality: u16 },
91} 92}
92 93
93/// A nominal type with (maybe 0) type parameters. This might be a primitive 94/// A nominal type with (maybe 0) type parameters. This might be a primitive
@@ -118,9 +119,14 @@ pub enum Ty {
118 /// surrounding impl, then the current function). 119 /// surrounding impl, then the current function).
119 idx: u32, 120 idx: u32,
120 /// The name of the parameter, for displaying. 121 /// The name of the parameter, for displaying.
122 // FIXME get rid of this
121 name: Name, 123 name: Name,
122 }, 124 },
123 125
126 /// A bound type variable. Only used during trait resolution to represent
127 /// Chalk variables.
128 Bound(u32),
129
124 /// A type variable used during type checking. Not to be confused with a 130 /// A type variable used during type checking. Not to be confused with a
125 /// type parameter. 131 /// type parameter.
126 Infer(InferTy), 132 Infer(InferTy),
@@ -150,14 +156,6 @@ impl Substs {
150 Substs(self.0.iter().cloned().take(n).collect::<Vec<_>>().into()) 156 Substs(self.0.iter().cloned().take(n).collect::<Vec<_>>().into())
151 } 157 }
152 158
153 pub fn iter(&self) -> impl Iterator<Item = &Ty> {
154 self.0.iter()
155 }
156
157 pub fn len(&self) -> usize {
158 self.0.len()
159 }
160
161 pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { 159 pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
162 // Without an Arc::make_mut_slice, we can't avoid the clone here: 160 // Without an Arc::make_mut_slice, we can't avoid the clone here:
163 let mut v: Vec<_> = self.0.iter().cloned().collect(); 161 let mut v: Vec<_> = self.0.iter().cloned().collect();
@@ -173,6 +171,30 @@ impl Substs {
173 } 171 }
174 &self.0[0] 172 &self.0[0]
175 } 173 }
174
175 /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`).
176 pub fn identity(generic_params: &GenericParams) -> Substs {
177 Substs(
178 generic_params
179 .params_including_parent()
180 .into_iter()
181 .map(|p| Ty::Param { idx: p.idx, name: p.name.clone() })
182 .collect::<Vec<_>>()
183 .into(),
184 )
185 }
186
187 /// Return Substs that replace each parameter by a bound variable.
188 pub fn bound_vars(generic_params: &GenericParams) -> Substs {
189 Substs(
190 generic_params
191 .params_including_parent()
192 .into_iter()
193 .map(|p| Ty::Bound(p.idx))
194 .collect::<Vec<_>>()
195 .into(),
196 )
197 }
176} 198}
177 199
178impl From<Vec<Ty>> for Substs { 200impl From<Vec<Ty>> for Substs {
@@ -181,6 +203,14 @@ impl From<Vec<Ty>> for Substs {
181 } 203 }
182} 204}
183 205
206impl Deref for Substs {
207 type Target = [Ty];
208
209 fn deref(&self) -> &[Ty] {
210 &self.0
211 }
212}
213
184/// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. 214/// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait.
185/// Name to be bikeshedded: TraitBound? TraitImplements? 215/// Name to be bikeshedded: TraitBound? TraitImplements?
186#[derive(Clone, PartialEq, Eq, Debug, Hash)] 216#[derive(Clone, PartialEq, Eq, Debug, Hash)]
@@ -192,10 +222,29 @@ pub struct TraitRef {
192 222
193impl TraitRef { 223impl TraitRef {
194 pub fn self_ty(&self) -> &Ty { 224 pub fn self_ty(&self) -> &Ty {
195 &self.substs.0[0] 225 &self.substs[0]
226 }
227
228 pub fn subst(mut self, substs: &Substs) -> TraitRef {
229 self.substs.walk_mut(&mut |ty_mut| {
230 let ty = mem::replace(ty_mut, Ty::Unknown);
231 *ty_mut = ty.subst(substs);
232 });
233 self
196 } 234 }
197} 235}
198 236
237/// Basically a claim (currently not validated / checked) that the contained
238/// type / trait ref contains no inference variables; any inference variables it
239/// contained have been replaced by bound variables, and `num_vars` tells us how
240/// many there are. This is used to erase irrelevant differences between types
241/// before using them in queries.
242#[derive(Debug, Clone, PartialEq, Eq, Hash)]
243pub(crate) struct Canonical<T> {
244 pub value: T,
245 pub num_vars: usize,
246}
247
199/// A function signature as seen by type inference: Several parameter types and 248/// A function signature as seen by type inference: Several parameter types and
200/// one return type. 249/// one return type.
201#[derive(Clone, PartialEq, Eq, Debug)] 250#[derive(Clone, PartialEq, Eq, Debug)]
@@ -250,7 +299,7 @@ impl Ty {
250 Ty::Apply(ApplicationTy { ctor, parameters }) 299 Ty::Apply(ApplicationTy { ctor, parameters })
251 } 300 }
252 pub fn unit() -> Self { 301 pub fn unit() -> Self {
253 Ty::apply(TypeCtor::Tuple, Substs::empty()) 302 Ty::apply(TypeCtor::Tuple { cardinality: 0 }, Substs::empty())
254 } 303 }
255 304
256 pub fn walk(&self, f: &mut impl FnMut(&Ty)) { 305 pub fn walk(&self, f: &mut impl FnMut(&Ty)) {
@@ -260,7 +309,7 @@ impl Ty {
260 t.walk(f); 309 t.walk(f);
261 } 310 }
262 } 311 }
263 Ty::Param { .. } | Ty::Infer(_) | Ty::Unknown => {} 312 Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {}
264 } 313 }
265 f(self); 314 f(self);
266 } 315 }
@@ -270,7 +319,7 @@ impl Ty {
270 Ty::Apply(a_ty) => { 319 Ty::Apply(a_ty) => {
271 a_ty.parameters.walk_mut(f); 320 a_ty.parameters.walk_mut(f);
272 } 321 }
273 Ty::Param { .. } | Ty::Infer(_) | Ty::Unknown => {} 322 Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {}
274 } 323 }
275 f(self); 324 f(self);
276 } 325 }
@@ -303,7 +352,9 @@ impl Ty {
303 352
304 pub fn as_tuple(&self) -> Option<&Substs> { 353 pub fn as_tuple(&self) -> Option<&Substs> {
305 match self { 354 match self {
306 Ty::Apply(ApplicationTy { ctor: TypeCtor::Tuple, parameters }) => Some(parameters), 355 Ty::Apply(ApplicationTy { ctor: TypeCtor::Tuple { .. }, parameters }) => {
356 Some(parameters)
357 }
307 _ => None, 358 _ => None,
308 } 359 }
309 } 360 }
@@ -331,7 +382,7 @@ impl Ty {
331 fn callable_sig(&self, db: &impl HirDatabase) -> Option<FnSig> { 382 fn callable_sig(&self, db: &impl HirDatabase) -> Option<FnSig> {
332 match self { 383 match self {
333 Ty::Apply(a_ty) => match a_ty.ctor { 384 Ty::Apply(a_ty) => match a_ty.ctor {
334 TypeCtor::FnPtr => Some(FnSig::from_fn_ptr_substs(&a_ty.parameters)), 385 TypeCtor::FnPtr { .. } => Some(FnSig::from_fn_ptr_substs(&a_ty.parameters)),
335 TypeCtor::FnDef(def) => { 386 TypeCtor::FnDef(def) => {
336 let sig = db.callable_item_signature(def); 387 let sig = db.callable_item_signature(def);
337 Some(sig.subst(&a_ty.parameters)) 388 Some(sig.subst(&a_ty.parameters))
@@ -362,16 +413,20 @@ impl Ty {
362 pub fn subst(self, substs: &Substs) -> Ty { 413 pub fn subst(self, substs: &Substs) -> Ty {
363 self.fold(&mut |ty| match ty { 414 self.fold(&mut |ty| match ty {
364 Ty::Param { idx, name } => { 415 Ty::Param { idx, name } => {
365 if (idx as usize) < substs.0.len() { 416 substs.get(idx as usize).cloned().unwrap_or(Ty::Param { idx, name })
366 substs.0[idx as usize].clone()
367 } else {
368 Ty::Param { idx, name }
369 }
370 } 417 }
371 ty => ty, 418 ty => ty,
372 }) 419 })
373 } 420 }
374 421
422 /// Substitutes `Ty::Bound` vars (as opposed to type parameters).
423 pub fn subst_bound_vars(self, substs: &Substs) -> Ty {
424 self.fold(&mut |ty| match ty {
425 Ty::Bound(idx) => substs.get(idx as usize).cloned().unwrap_or(Ty::Bound(idx)),
426 ty => ty,
427 })
428 }
429
375 /// Returns the type parameters of this type if it has some (i.e. is an ADT 430 /// Returns the type parameters of this type if it has some (i.e. is an ADT
376 /// or function); so if `self` is `Option<u32>`, this returns the `u32`. 431 /// or function); so if `self` is `Option<u32>`, this returns the `u32`.
377 fn substs(&self) -> Option<Substs> { 432 fn substs(&self) -> Option<Substs> {
@@ -413,17 +468,17 @@ impl HirDisplay for ApplicationTy {
413 write!(f, "&{}{}", m.as_keyword_for_ref(), t.display(f.db))?; 468 write!(f, "&{}{}", m.as_keyword_for_ref(), t.display(f.db))?;
414 } 469 }
415 TypeCtor::Never => write!(f, "!")?, 470 TypeCtor::Never => write!(f, "!")?,
416 TypeCtor::Tuple => { 471 TypeCtor::Tuple { .. } => {
417 let ts = &self.parameters; 472 let ts = &self.parameters;
418 if ts.0.len() == 1 { 473 if ts.len() == 1 {
419 write!(f, "({},)", ts.0[0].display(f.db))?; 474 write!(f, "({},)", ts[0].display(f.db))?;
420 } else { 475 } else {
421 write!(f, "(")?; 476 write!(f, "(")?;
422 f.write_joined(&*ts.0, ", ")?; 477 f.write_joined(&*ts.0, ", ")?;
423 write!(f, ")")?; 478 write!(f, ")")?;
424 } 479 }
425 } 480 }
426 TypeCtor::FnPtr => { 481 TypeCtor::FnPtr { .. } => {
427 let sig = FnSig::from_fn_ptr_substs(&self.parameters); 482 let sig = FnSig::from_fn_ptr_substs(&self.parameters);
428 write!(f, "fn(")?; 483 write!(f, "fn(")?;
429 f.write_joined(sig.params(), ", ")?; 484 f.write_joined(sig.params(), ", ")?;
@@ -440,7 +495,7 @@ impl HirDisplay for ApplicationTy {
440 CallableDef::Function(_) => write!(f, "fn {}", name)?, 495 CallableDef::Function(_) => write!(f, "fn {}", name)?,
441 CallableDef::Struct(_) | CallableDef::EnumVariant(_) => write!(f, "{}", name)?, 496 CallableDef::Struct(_) | CallableDef::EnumVariant(_) => write!(f, "{}", name)?,
442 } 497 }
443 if self.parameters.0.len() > 0 { 498 if self.parameters.len() > 0 {
444 write!(f, "<")?; 499 write!(f, "<")?;
445 f.write_joined(&*self.parameters.0, ", ")?; 500 f.write_joined(&*self.parameters.0, ", ")?;
446 write!(f, ">")?; 501 write!(f, ">")?;
@@ -456,7 +511,7 @@ impl HirDisplay for ApplicationTy {
456 } 511 }
457 .unwrap_or_else(Name::missing); 512 .unwrap_or_else(Name::missing);
458 write!(f, "{}", name)?; 513 write!(f, "{}", name)?;
459 if self.parameters.0.len() > 0 { 514 if self.parameters.len() > 0 {
460 write!(f, "<")?; 515 write!(f, "<")?;
461 f.write_joined(&*self.parameters.0, ", ")?; 516 f.write_joined(&*self.parameters.0, ", ")?;
462 write!(f, ">")?; 517 write!(f, ">")?;
@@ -472,6 +527,7 @@ impl HirDisplay for Ty {
472 match self { 527 match self {
473 Ty::Apply(a_ty) => a_ty.hir_fmt(f)?, 528 Ty::Apply(a_ty) => a_ty.hir_fmt(f)?,
474 Ty::Param { name, .. } => write!(f, "{}", name)?, 529 Ty::Param { name, .. } => write!(f, "{}", name)?,
530 Ty::Bound(idx) => write!(f, "?{}", idx)?,
475 Ty::Unknown => write!(f, "{{unknown}}")?, 531 Ty::Unknown => write!(f, "{{unknown}}")?,
476 Ty::Infer(..) => write!(f, "_")?, 532 Ty::Infer(..) => write!(f, "_")?,
477 } 533 }