Skip to content

Commit 2941f7b

Browse files
committed
Add Ty::Apply
1 parent 84dd6b8 commit 2941f7b

File tree

1 file changed

+177
-1
lines changed

1 file changed

+177
-1
lines changed

crates/ra_hir/src/ty.rs

Lines changed: 177 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,84 @@ pub(crate) use lower::{TypableDef, CallableDef, type_for_def, type_for_field, ca
2020
pub(crate) use infer::{infer, InferenceResult, InferTy};
2121
use display::{HirDisplay, HirFormatter};
2222

23+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
24+
pub 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)]
89+
pub struct ApplicationTy {
90+
pub name: TypeName,
91+
pub parameters: Substs,
92+
}
93+
2394
/// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs).
2495
///
2596
/// This should be cheap to clone.
2697
#[derive(Clone, PartialEq, Eq, Debug)]
2798
pub enum Ty {
99+
Apply(ApplicationTy),
100+
28101
/// The primitive boolean type. Written as `bool`.
29102
Bool,
30103

@@ -139,6 +212,13 @@ impl Substs {
139212
}
140213
self.0 = v.into();
141214
}
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+
}
142222
}
143223

144224
/// A function signature.
@@ -176,12 +256,20 @@ impl FnSig {
176256
}
177257

178258
impl Ty {
259+
pub fn apply(name: TypeName, parameters: Substs) -> Ty {
260+
Ty::Apply(ApplicationTy { name, parameters })
261+
}
179262
pub fn unit() -> Self {
180-
Ty::Tuple(Substs::empty())
263+
Ty::apply(TypeName::Tuple, Substs::empty())
181264
}
182265

183266
pub fn walk(&self, f: &mut impl FnMut(&Ty)) {
184267
match self {
268+
Ty::Apply(a_ty) => {
269+
for t in a_ty.parameters.iter() {
270+
t.walk(f);
271+
}
272+
}
185273
Ty::Slice(t) | Ty::Array(t) => t.walk(f),
186274
Ty::RawPtr(t, _) => t.walk(f),
187275
Ty::Ref(t, _) => t.walk(f),
@@ -220,6 +308,9 @@ impl Ty {
220308

221309
fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
222310
match self {
311+
Ty::Apply(a_ty) => {
312+
a_ty.parameters.walk_mut(f);
313+
}
223314
Ty::Slice(t) | Ty::Array(t) => Arc::make_mut(t).walk_mut(f),
224315
Ty::RawPtr(t, _) => Arc::make_mut(t).walk_mut(f),
225316
Ty::Ref(t, _) => Arc::make_mut(t).walk_mut(f),
@@ -258,6 +349,11 @@ impl Ty {
258349

259350
fn builtin_deref(&self) -> Option<Ty> {
260351
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+
},
261357
Ty::Ref(t, _) => Some(Ty::clone(t)),
262358
Ty::RawPtr(t, _) => Some(Ty::clone(t)),
263359
_ => None,
@@ -270,6 +366,9 @@ impl Ty {
270366
/// `Option<u32>` afterwards.)
271367
pub fn apply_substs(self, substs: Substs) -> Ty {
272368
match self {
369+
Ty::Apply(ApplicationTy { name, .. }) => {
370+
Ty::Apply(ApplicationTy { name, parameters: substs })
371+
}
273372
Ty::Adt { def_id, .. } => Ty::Adt { def_id, substs },
274373
Ty::FnDef { def, .. } => Ty::FnDef { def, substs },
275374
_ => self,
@@ -296,6 +395,7 @@ impl Ty {
296395
/// or function); so if `self` is `Option<u32>`, this returns the `u32`.
297396
fn substs(&self) -> Option<Substs> {
298397
match self {
398+
Ty::Apply(ApplicationTy { parameters, .. }) => Some(parameters.clone()),
299399
Ty::Adt { substs, .. } | Ty::FnDef { substs, .. } => Some(substs.clone()),
300400
_ => None,
301401
}
@@ -308,9 +408,85 @@ impl HirDisplay for &Ty {
308408
}
309409
}
310410

411+
impl 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+
311486
impl HirDisplay for Ty {
312487
fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
313488
match self {
489+
Ty::Apply(a_ty) => a_ty.hir_fmt(f)?,
314490
Ty::Bool => write!(f, "bool")?,
315491
Ty::Char => write!(f, "char")?,
316492
Ty::Int(t) => write!(f, "{}", t)?,

0 commit comments

Comments
 (0)