diff options
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 173 |
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; | |||
9 | mod op; | 9 | mod op; |
10 | mod lower; | 10 | mod lower; |
11 | mod infer; | 11 | mod infer; |
12 | pub(crate) mod display; | ||
12 | 13 | ||
13 | use std::sync::Arc; | 14 | use std::sync::Arc; |
14 | use std::{fmt, mem}; | 15 | use std::{fmt, mem}; |
15 | 16 | ||
16 | use join_to_string::join; | 17 | use crate::{Name, AdtDef, type_ref::Mutability, db::HirDatabase}; |
17 | 18 | ||
18 | use crate::{Name, AdtDef, type_ref::Mutability}; | 19 | pub(crate) use lower::{TypableDef, CallableDef, type_for_def, type_for_field, callable_item_sig}; |
19 | |||
20 | pub(crate) use lower::{TypableDef, CallableDef, type_for_def, type_for_field}; | ||
21 | pub(crate) use infer::{infer, InferenceResult, InferTy}; | 20 | pub(crate) use infer::{infer, InferenceResult, InferTy}; |
21 | use 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)] |
139 | pub struct FnSig { | 142 | pub struct FnSig { |
140 | input: Vec<Ty>, | 143 | params_and_return: Arc<[Ty]>, |
141 | output: Ty, | 144 | } |
145 | |||
146 | impl 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 | ||
144 | impl Ty { | 169 | impl 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 | ||
300 | impl fmt::Display for Ty { | 302 | impl 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 | |||
308 | impl 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 | } |