diff options
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 112 |
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; | |||
13 | pub(crate) mod display; | 13 | pub(crate) mod display; |
14 | 14 | ||
15 | use std::sync::Arc; | 15 | use std::sync::Arc; |
16 | use std::ops::Deref; | ||
16 | use std::{fmt, mem}; | 17 | use std::{fmt, mem}; |
17 | 18 | ||
18 | use crate::{Name, AdtDef, type_ref::Mutability, db::HirDatabase, Trait}; | 19 | use crate::{Name, AdtDef, type_ref::Mutability, db::HirDatabase, Trait, GenericParams}; |
19 | use display::{HirDisplay, HirFormatter}; | 20 | use display::{HirDisplay, HirFormatter}; |
20 | 21 | ||
21 | pub(crate) use lower::{TypableDef, type_for_def, type_for_field, callable_item_sig}; | 22 | pub(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 | ||
178 | impl From<Vec<Ty>> for Substs { | 200 | impl From<Vec<Ty>> for Substs { |
@@ -181,6 +203,14 @@ impl From<Vec<Ty>> for Substs { | |||
181 | } | 203 | } |
182 | } | 204 | } |
183 | 205 | ||
206 | impl 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 | ||
193 | impl TraitRef { | 223 | impl 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)] | ||
243 | pub(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 | } |