aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/ty.rs178
1 files changed, 177 insertions, 1 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index e659f903c..e63775f03 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -20,11 +20,84 @@ pub(crate) use lower::{TypableDef, CallableDef, type_for_def, type_for_field, ca
20pub(crate) use infer::{infer, InferenceResult, InferTy}; 20pub(crate) use infer::{infer, InferenceResult, InferTy};
21use display::{HirDisplay, HirFormatter}; 21use display::{HirDisplay, HirFormatter};
22 22
23#[derive(Copy, Clone, PartialEq, Eq, Debug)]
24pub enum TypeName {
25 /// The primitive boolean type. Written as `bool`.
26 Bool,
27
28 /// The primitive character type; holds a Unicode scalar value
29 /// (a non-surrogate code point). Written as `char`.
30 Char,
31
32 /// A primitive integer type. For example, `i32`.
33 Int(primitive::UncertainIntTy),
34
35 /// A primitive floating-point type. For example, `f64`.
36 Float(primitive::UncertainFloatTy),
37
38 /// Structures, enumerations and unions.
39 Adt(AdtDef),
40
41 /// The pointee of a string slice. Written as `str`.
42 Str,
43
44 /// The pointee of an array slice. Written as `[T]`.
45 Slice,
46
47 /// An array with the given length. Written as `[T; n]`.
48 Array,
49
50 /// A raw pointer. Written as `*mut T` or `*const T`
51 RawPtr(Mutability),
52
53 /// A reference; a pointer with an associated lifetime. Written as
54 /// `&'a mut T` or `&'a T`.
55 Ref(Mutability),
56
57 /// The anonymous type of a function declaration/definition. Each
58 /// function has a unique type, which is output (for a function
59 /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`.
60 ///
61 /// This includes tuple struct / enum variant constructors as well.
62 ///
63 /// For example the type of `bar` here:
64 ///
65 /// ```rust
66 /// fn foo() -> i32 { 1 }
67 /// let bar = foo; // bar: fn() -> i32 {foo}
68 /// ```
69 FnDef(CallableDef),
70
71 /// A pointer to a function. Written as `fn() -> i32`.
72 ///
73 /// For example the type of `bar` here:
74 ///
75 /// ```rust
76 /// fn foo() -> i32 { 1 }
77 /// let bar: fn() -> i32 = foo;
78 /// ```
79 FnPtr,
80
81 /// The never type `!`.
82 Never,
83
84 /// A tuple type. For example, `(i32, bool)`.
85 Tuple,
86}
87
88#[derive(Clone, PartialEq, Eq, Debug)]
89pub struct ApplicationTy {
90 pub name: TypeName,
91 pub parameters: Substs,
92}
93
23/// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs). 94/// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs).
24/// 95///
25/// This should be cheap to clone. 96/// This should be cheap to clone.
26#[derive(Clone, PartialEq, Eq, Debug)] 97#[derive(Clone, PartialEq, Eq, Debug)]
27pub enum Ty { 98pub enum Ty {
99 Apply(ApplicationTy),
100
28 /// The primitive boolean type. Written as `bool`. 101 /// The primitive boolean type. Written as `bool`.
29 Bool, 102 Bool,
30 103
@@ -139,6 +212,13 @@ impl Substs {
139 } 212 }
140 self.0 = v.into(); 213 self.0 = v.into();
141 } 214 }
215
216 pub fn as_single(&self) -> &Ty {
217 if self.0.len() != 1 {
218 panic!("expected substs of len 1, got {:?}", self);
219 }
220 &self.0[0]
221 }
142} 222}
143 223
144/// A function signature. 224/// A function signature.
@@ -176,12 +256,20 @@ impl FnSig {
176} 256}
177 257
178impl Ty { 258impl Ty {
259 pub fn apply(name: TypeName, parameters: Substs) -> Ty {
260 Ty::Apply(ApplicationTy { name, parameters })
261 }
179 pub fn unit() -> Self { 262 pub fn unit() -> Self {
180 Ty::Tuple(Substs::empty()) 263 Ty::apply(TypeName::Tuple, Substs::empty())
181 } 264 }
182 265
183 pub fn walk(&self, f: &mut impl FnMut(&Ty)) { 266 pub fn walk(&self, f: &mut impl FnMut(&Ty)) {
184 match self { 267 match self {
268 Ty::Apply(a_ty) => {
269 for t in a_ty.parameters.iter() {
270 t.walk(f);
271 }
272 }
185 Ty::Slice(t) | Ty::Array(t) => t.walk(f), 273 Ty::Slice(t) | Ty::Array(t) => t.walk(f),
186 Ty::RawPtr(t, _) => t.walk(f), 274 Ty::RawPtr(t, _) => t.walk(f),
187 Ty::Ref(t, _) => t.walk(f), 275 Ty::Ref(t, _) => t.walk(f),
@@ -220,6 +308,9 @@ impl Ty {
220 308
221 fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { 309 fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
222 match self { 310 match self {
311 Ty::Apply(a_ty) => {
312 a_ty.parameters.walk_mut(f);
313 }
223 Ty::Slice(t) | Ty::Array(t) => Arc::make_mut(t).walk_mut(f), 314 Ty::Slice(t) | Ty::Array(t) => Arc::make_mut(t).walk_mut(f),
224 Ty::RawPtr(t, _) => Arc::make_mut(t).walk_mut(f), 315 Ty::RawPtr(t, _) => Arc::make_mut(t).walk_mut(f),
225 Ty::Ref(t, _) => Arc::make_mut(t).walk_mut(f), 316 Ty::Ref(t, _) => Arc::make_mut(t).walk_mut(f),
@@ -258,6 +349,11 @@ impl Ty {
258 349
259 fn builtin_deref(&self) -> Option<Ty> { 350 fn builtin_deref(&self) -> Option<Ty> {
260 match self { 351 match self {
352 Ty::Apply(a_ty) => match a_ty.name {
353 TypeName::Ref(..) => Some(Ty::clone(a_ty.parameters.as_single())),
354 TypeName::RawPtr(..) => Some(Ty::clone(a_ty.parameters.as_single())),
355 _ => None,
356 },
261 Ty::Ref(t, _) => Some(Ty::clone(t)), 357 Ty::Ref(t, _) => Some(Ty::clone(t)),
262 Ty::RawPtr(t, _) => Some(Ty::clone(t)), 358 Ty::RawPtr(t, _) => Some(Ty::clone(t)),
263 _ => None, 359 _ => None,
@@ -270,6 +366,9 @@ impl Ty {
270 /// `Option<u32>` afterwards.) 366 /// `Option<u32>` afterwards.)
271 pub fn apply_substs(self, substs: Substs) -> Ty { 367 pub fn apply_substs(self, substs: Substs) -> Ty {
272 match self { 368 match self {
369 Ty::Apply(ApplicationTy { name, .. }) => {
370 Ty::Apply(ApplicationTy { name, parameters: substs })
371 }
273 Ty::Adt { def_id, .. } => Ty::Adt { def_id, substs }, 372 Ty::Adt { def_id, .. } => Ty::Adt { def_id, substs },
274 Ty::FnDef { def, .. } => Ty::FnDef { def, substs }, 373 Ty::FnDef { def, .. } => Ty::FnDef { def, substs },
275 _ => self, 374 _ => self,
@@ -296,6 +395,7 @@ impl Ty {
296 /// or function); so if `self` is `Option<u32>`, this returns the `u32`. 395 /// or function); so if `self` is `Option<u32>`, this returns the `u32`.
297 fn substs(&self) -> Option<Substs> { 396 fn substs(&self) -> Option<Substs> {
298 match self { 397 match self {
398 Ty::Apply(ApplicationTy { parameters, .. }) => Some(parameters.clone()),
299 Ty::Adt { substs, .. } | Ty::FnDef { substs, .. } => Some(substs.clone()), 399 Ty::Adt { substs, .. } | Ty::FnDef { substs, .. } => Some(substs.clone()),
300 _ => None, 400 _ => None,
301 } 401 }
@@ -308,9 +408,85 @@ impl HirDisplay for &Ty {
308 } 408 }
309} 409}
310 410
411impl HirDisplay for ApplicationTy {
412 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
413 match self.name {
414 TypeName::Bool => write!(f, "bool")?,
415 TypeName::Char => write!(f, "char")?,
416 TypeName::Int(t) => write!(f, "{}", t)?,
417 TypeName::Float(t) => write!(f, "{}", t)?,
418 TypeName::Str => write!(f, "str")?,
419 TypeName::Slice | TypeName::Array => {
420 let t = self.parameters.as_single();
421 write!(f, "[{}]", t.display(f.db))?;
422 }
423 TypeName::RawPtr(m) => {
424 let t = self.parameters.as_single();
425 write!(f, "*{}{}", m.as_keyword_for_ptr(), t.display(f.db))?;
426 }
427 TypeName::Ref(m) => {
428 let t = self.parameters.as_single();
429 write!(f, "&{}{}", m.as_keyword_for_ref(), t.display(f.db))?;
430 }
431 TypeName::Never => write!(f, "!")?,
432 TypeName::Tuple => {
433 let ts = &self.parameters;
434 if ts.0.len() == 1 {
435 write!(f, "({},)", ts.0[0].display(f.db))?;
436 } else {
437 write!(f, "(")?;
438 f.write_joined(&*ts.0, ", ")?;
439 write!(f, ")")?;
440 }
441 }
442 TypeName::FnPtr => {
443 let sig = FnSig::from_fn_ptr_substs(&self.parameters);
444 write!(f, "fn(")?;
445 f.write_joined(sig.params(), ", ")?;
446 write!(f, ") -> {}", sig.ret().display(f.db))?;
447 }
448 TypeName::FnDef(def) => {
449 let sig = f.db.callable_item_signature(def);
450 let name = match def {
451 CallableDef::Function(ff) => ff.name(f.db),
452 CallableDef::Struct(s) => s.name(f.db).unwrap_or_else(Name::missing),
453 CallableDef::EnumVariant(e) => e.name(f.db).unwrap_or_else(Name::missing),
454 };
455 match def {
456 CallableDef::Function(_) => write!(f, "fn {}", name)?,
457 CallableDef::Struct(_) | CallableDef::EnumVariant(_) => write!(f, "{}", name)?,
458 }
459 if self.parameters.0.len() > 0 {
460 write!(f, "<")?;
461 f.write_joined(&*self.parameters.0, ", ")?;
462 write!(f, ">")?;
463 }
464 write!(f, "(")?;
465 f.write_joined(sig.params(), ", ")?;
466 write!(f, ") -> {}", sig.ret().display(f.db))?;
467 }
468 TypeName::Adt(def_id) => {
469 let name = match def_id {
470 AdtDef::Struct(s) => s.name(f.db),
471 AdtDef::Enum(e) => e.name(f.db),
472 }
473 .unwrap_or_else(Name::missing);
474 write!(f, "{}", name)?;
475 if self.parameters.0.len() > 0 {
476 write!(f, "<")?;
477 f.write_joined(&*self.parameters.0, ", ")?;
478 write!(f, ">")?;
479 }
480 }
481 }
482 Ok(())
483 }
484}
485
311impl HirDisplay for Ty { 486impl HirDisplay for Ty {
312 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { 487 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
313 match self { 488 match self {
489 Ty::Apply(a_ty) => a_ty.hir_fmt(f)?,
314 Ty::Bool => write!(f, "bool")?, 490 Ty::Bool => write!(f, "bool")?,
315 Ty::Char => write!(f, "char")?, 491 Ty::Char => write!(f, "char")?,
316 Ty::Int(t) => write!(f, "{}", t)?, 492 Ty::Int(t) => write!(f, "{}", t)?,