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.rs173
1 files changed, 103 insertions, 70 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index bad811a56..2ea3b341f 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -9,16 +9,16 @@ pub(crate) mod method_resolution;
9mod op; 9mod op;
10mod lower; 10mod lower;
11mod infer; 11mod infer;
12pub(crate) mod display;
12 13
13use std::sync::Arc; 14use std::sync::Arc;
14use std::{fmt, mem}; 15use std::{fmt, mem};
15 16
16use join_to_string::join; 17use crate::{Name, AdtDef, type_ref::Mutability, db::HirDatabase};
17 18
18use crate::{Name, AdtDef, type_ref::Mutability}; 19pub(crate) use lower::{TypableDef, CallableDef, type_for_def, type_for_field, callable_item_sig};
19
20pub(crate) use lower::{TypableDef, CallableDef, type_for_def, type_for_field};
21pub(crate) use infer::{infer, InferenceResult, InferTy}; 20pub(crate) use infer::{infer, InferenceResult, InferTy};
21use display::{HirDisplay, HirFormatter};
22 22
23/// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs). 23/// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs).
24/// 24///
@@ -42,8 +42,6 @@ pub enum Ty {
42 Adt { 42 Adt {
43 /// The definition of the struct/enum. 43 /// The definition of the struct/enum.
44 def_id: AdtDef, 44 def_id: AdtDef,
45 /// The name, for displaying.
46 name: Name,
47 /// Substitutions for the generic parameters of the type. 45 /// Substitutions for the generic parameters of the type.
48 substs: Substs, 46 substs: Substs,
49 }, 47 },
@@ -79,10 +77,6 @@ pub enum Ty {
79 FnDef { 77 FnDef {
80 /// The definition of the function / constructor. 78 /// The definition of the function / constructor.
81 def: CallableDef, 79 def: CallableDef,
82 /// For display
83 name: Name,
84 /// Parameters and return type
85 sig: Arc<FnSig>,
86 /// Substitutions for the generic parameters of the type 80 /// Substitutions for the generic parameters of the type
87 substs: Substs, 81 substs: Substs,
88 }, 82 },
@@ -95,7 +89,7 @@ pub enum Ty {
95 /// fn foo() -> i32 { 1 } 89 /// fn foo() -> i32 { 1 }
96 /// let bar: fn() -> i32 = foo; 90 /// let bar: fn() -> i32 = foo;
97 /// ``` 91 /// ```
98 FnPtr(Arc<FnSig>), 92 FnPtr(FnSig),
99 93
100 /// The never type `!`. 94 /// The never type `!`.
101 Never, 95 Never,
@@ -132,13 +126,44 @@ impl Substs {
132 pub fn empty() -> Substs { 126 pub fn empty() -> Substs {
133 Substs(Arc::new([])) 127 Substs(Arc::new([]))
134 } 128 }
129
130 pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
131 // Without an Arc::make_mut_slice, we can't avoid the clone here:
132 let mut v: Vec<_> = self.0.iter().cloned().collect();
133 for t in &mut v {
134 t.walk_mut(f);
135 }
136 self.0 = v.into();
137 }
135} 138}
136 139
137/// A function signature. 140/// A function signature.
138#[derive(Clone, PartialEq, Eq, Debug)] 141#[derive(Clone, PartialEq, Eq, Debug)]
139pub struct FnSig { 142pub struct FnSig {
140 input: Vec<Ty>, 143 params_and_return: Arc<[Ty]>,
141 output: Ty, 144}
145
146impl FnSig {
147 pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty) -> FnSig {
148 params.push(ret);
149 FnSig { params_and_return: params.into() }
150 }
151 pub fn params(&self) -> &[Ty] {
152 &self.params_and_return[0..self.params_and_return.len() - 1]
153 }
154
155 pub fn ret(&self) -> &Ty {
156 &self.params_and_return[self.params_and_return.len() - 1]
157 }
158
159 pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
160 // Without an Arc::make_mut_slice, we can't avoid the clone here:
161 let mut v: Vec<_> = self.params_and_return.iter().cloned().collect();
162 for t in &mut v {
163 t.walk_mut(f);
164 }
165 self.params_and_return = v.into();
166 }
142} 167}
143 168
144impl Ty { 169impl Ty {
@@ -157,16 +182,12 @@ impl Ty {
157 } 182 }
158 } 183 }
159 Ty::FnPtr(sig) => { 184 Ty::FnPtr(sig) => {
160 for input in &sig.input { 185 for input in sig.params() {
161 input.walk(f); 186 input.walk(f);
162 } 187 }
163 sig.output.walk(f); 188 sig.ret().walk(f);
164 } 189 }
165 Ty::FnDef { substs, sig, .. } => { 190 Ty::FnDef { substs, .. } => {
166 for input in &sig.input {
167 input.walk(f);
168 }
169 sig.output.walk(f);
170 for t in substs.0.iter() { 191 for t in substs.0.iter() {
171 t.walk(f); 192 t.walk(f);
172 } 193 }
@@ -203,32 +224,13 @@ impl Ty {
203 *ts = v.into(); 224 *ts = v.into();
204 } 225 }
205 Ty::FnPtr(sig) => { 226 Ty::FnPtr(sig) => {
206 let sig_mut = Arc::make_mut(sig); 227 sig.walk_mut(f);
207 for input in &mut sig_mut.input {
208 input.walk_mut(f);
209 }
210 sig_mut.output.walk_mut(f);
211 } 228 }
212 Ty::FnDef { substs, sig, .. } => { 229 Ty::FnDef { substs, .. } => {
213 let sig_mut = Arc::make_mut(sig); 230 substs.walk_mut(f);
214 for input in &mut sig_mut.input {
215 input.walk_mut(f);
216 }
217 sig_mut.output.walk_mut(f);
218 // Without an Arc::make_mut_slice, we can't avoid the clone here:
219 let mut v: Vec<_> = substs.0.iter().cloned().collect();
220 for t in &mut v {
221 t.walk_mut(f);
222 }
223 substs.0 = v.into();
224 } 231 }
225 Ty::Adt { substs, .. } => { 232 Ty::Adt { substs, .. } => {
226 // Without an Arc::make_mut_slice, we can't avoid the clone here: 233 substs.walk_mut(f);
227 let mut v: Vec<_> = substs.0.iter().cloned().collect();
228 for t in &mut v {
229 t.walk_mut(f);
230 }
231 substs.0 = v.into();
232 } 234 }
233 Ty::Bool 235 Ty::Bool
234 | Ty::Char 236 | Ty::Char
@@ -265,8 +267,8 @@ impl Ty {
265 /// `Option<u32>` afterwards.) 267 /// `Option<u32>` afterwards.)
266 pub fn apply_substs(self, substs: Substs) -> Ty { 268 pub fn apply_substs(self, substs: Substs) -> Ty {
267 match self { 269 match self {
268 Ty::Adt { def_id, name, .. } => Ty::Adt { def_id, name, substs }, 270 Ty::Adt { def_id, .. } => Ty::Adt { def_id, substs },
269 Ty::FnDef { def, name, sig, .. } => Ty::FnDef { def, name, sig, substs }, 271 Ty::FnDef { def, .. } => Ty::FnDef { def, substs },
270 _ => self, 272 _ => self,
271 } 273 }
272 } 274 }
@@ -297,50 +299,81 @@ impl Ty {
297 } 299 }
298} 300}
299 301
300impl fmt::Display for Ty { 302impl HirDisplay for &Ty {
301 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 303 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
304 HirDisplay::hir_fmt(*self, f)
305 }
306}
307
308impl HirDisplay for Ty {
309 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
302 match self { 310 match self {
303 Ty::Bool => write!(f, "bool"), 311 Ty::Bool => write!(f, "bool")?,
304 Ty::Char => write!(f, "char"), 312 Ty::Char => write!(f, "char")?,
305 Ty::Int(t) => write!(f, "{}", t.ty_to_string()), 313 Ty::Int(t) => write!(f, "{}", t)?,
306 Ty::Float(t) => write!(f, "{}", t.ty_to_string()), 314 Ty::Float(t) => write!(f, "{}", t)?,
307 Ty::Str => write!(f, "str"), 315 Ty::Str => write!(f, "str")?,
308 Ty::Slice(t) | Ty::Array(t) => write!(f, "[{}]", t), 316 Ty::Slice(t) | Ty::Array(t) => {
309 Ty::RawPtr(t, m) => write!(f, "*{}{}", m.as_keyword_for_ptr(), t), 317 write!(f, "[{}]", t.display(f.db))?;
310 Ty::Ref(t, m) => write!(f, "&{}{}", m.as_keyword_for_ref(), t), 318 }
311 Ty::Never => write!(f, "!"), 319 Ty::RawPtr(t, m) => {
320 write!(f, "*{}{}", m.as_keyword_for_ptr(), t.display(f.db))?;
321 }
322 Ty::Ref(t, m) => {
323 write!(f, "&{}{}", m.as_keyword_for_ref(), t.display(f.db))?;
324 }
325 Ty::Never => write!(f, "!")?,
312 Ty::Tuple(ts) => { 326 Ty::Tuple(ts) => {
313 if ts.len() == 1 { 327 if ts.len() == 1 {
314 write!(f, "({},)", ts[0]) 328 write!(f, "({},)", ts[0].display(f.db))?;
315 } else { 329 } else {
316 join(ts.iter()).surround_with("(", ")").separator(", ").to_fmt(f) 330 write!(f, "(")?;
331 f.write_joined(&**ts, ", ")?;
332 write!(f, ")")?;
317 } 333 }
318 } 334 }
319 Ty::FnPtr(sig) => { 335 Ty::FnPtr(sig) => {
320 join(sig.input.iter()).surround_with("fn(", ")").separator(", ").to_fmt(f)?; 336 write!(f, "fn(")?;
321 write!(f, " -> {}", sig.output) 337 f.write_joined(sig.params(), ", ")?;
338 write!(f, ") -> {}", sig.ret().display(f.db))?;
322 } 339 }
323 Ty::FnDef { def, name, substs, sig, .. } => { 340 Ty::FnDef { def, substs, .. } => {
341 let sig = f.db.callable_item_signature(*def);
342 let name = match def {
343 CallableDef::Function(ff) => ff.name(f.db),
344 CallableDef::Struct(s) => s.name(f.db).unwrap_or_else(Name::missing),
345 CallableDef::EnumVariant(e) => e.name(f.db).unwrap_or_else(Name::missing),
346 };
324 match def { 347 match def {
325 CallableDef::Function(_) => write!(f, "fn {}", name)?, 348 CallableDef::Function(_) => write!(f, "fn {}", name)?,
326 CallableDef::Struct(_) | CallableDef::EnumVariant(_) => write!(f, "{}", name)?, 349 CallableDef::Struct(_) | CallableDef::EnumVariant(_) => write!(f, "{}", name)?,
327 } 350 }
328 if substs.0.len() > 0 { 351 if substs.0.len() > 0 {
329 join(substs.0.iter()).surround_with("<", ">").separator(", ").to_fmt(f)?; 352 write!(f, "<")?;
353 f.write_joined(&*substs.0, ", ")?;
354 write!(f, ">")?;
330 } 355 }
331 join(sig.input.iter()).surround_with("(", ")").separator(", ").to_fmt(f)?; 356 write!(f, "(")?;
332 write!(f, " -> {}", sig.output) 357 f.write_joined(sig.params(), ", ")?;
358 write!(f, ") -> {}", sig.ret().display(f.db))?;
333 } 359 }
334 Ty::Adt { name, substs, .. } => { 360 Ty::Adt { def_id, substs, .. } => {
361 let name = match def_id {
362 AdtDef::Struct(s) => s.name(f.db),
363 AdtDef::Enum(e) => e.name(f.db),
364 }
365 .unwrap_or_else(Name::missing);
335 write!(f, "{}", name)?; 366 write!(f, "{}", name)?;
336 if substs.0.len() > 0 { 367 if substs.0.len() > 0 {
337 join(substs.0.iter()).surround_with("<", ">").separator(", ").to_fmt(f)?; 368 write!(f, "<")?;
369 f.write_joined(&*substs.0, ", ")?;
370 write!(f, ">")?;
338 } 371 }
339 Ok(())
340 } 372 }
341 Ty::Param { name, .. } => write!(f, "{}", name), 373 Ty::Param { name, .. } => write!(f, "{}", name)?,
342 Ty::Unknown => write!(f, "{{unknown}}"), 374 Ty::Unknown => write!(f, "{{unknown}}")?,
343 Ty::Infer(..) => write!(f, "_"), 375 Ty::Infer(..) => write!(f, "_")?,
344 } 376 }
377 Ok(())
345 } 378 }
346} 379}