diff options
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 94 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/display.rs | 56 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 23 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 5 |
5 files changed, 126 insertions, 54 deletions
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index ac5f33079..4508a873e 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -56,7 +56,7 @@ pub use self::{ | |||
56 | ids::{HirFileId, MacroCallId, MacroCallLoc, HirInterner}, | 56 | ids::{HirFileId, MacroCallId, MacroCallLoc, HirInterner}, |
57 | macros::{MacroDef, MacroInput, MacroExpansion}, | 57 | macros::{MacroDef, MacroInput, MacroExpansion}, |
58 | nameres::{ItemMap, PerNs, Namespace}, | 58 | nameres::{ItemMap, PerNs, Namespace}, |
59 | ty::{Ty, Substs}, | 59 | ty::{Ty, Substs, display::HirDisplay}, |
60 | impl_block::{ImplBlock, ImplItem}, | 60 | impl_block::{ImplBlock, ImplItem}, |
61 | docs::{Docs, Documentation}, | 61 | docs::{Docs, Documentation}, |
62 | adt::AdtDef, | 62 | adt::AdtDef, |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index bad811a56..f64877f3b 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 | use crate::{Name, AdtDef, type_ref::Mutability}; | ||
19 | 18 | ||
20 | pub(crate) use lower::{TypableDef, CallableDef, type_for_def, type_for_field}; | 19 | 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,8 +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 | 80 | /// Parameters and return type |
85 | sig: Arc<FnSig>, | 81 | sig: Arc<FnSig>, |
86 | /// Substitutions for the generic parameters of the type | 82 | /// Substitutions for the generic parameters of the type |
@@ -265,8 +261,8 @@ impl Ty { | |||
265 | /// `Option<u32>` afterwards.) | 261 | /// `Option<u32>` afterwards.) |
266 | pub fn apply_substs(self, substs: Substs) -> Ty { | 262 | pub fn apply_substs(self, substs: Substs) -> Ty { |
267 | match self { | 263 | match self { |
268 | Ty::Adt { def_id, name, .. } => Ty::Adt { def_id, name, substs }, | 264 | Ty::Adt { def_id, .. } => Ty::Adt { def_id, substs }, |
269 | Ty::FnDef { def, name, sig, .. } => Ty::FnDef { def, name, sig, substs }, | 265 | Ty::FnDef { def, sig, .. } => Ty::FnDef { def, sig, substs }, |
270 | _ => self, | 266 | _ => self, |
271 | } | 267 | } |
272 | } | 268 | } |
@@ -297,50 +293,80 @@ impl Ty { | |||
297 | } | 293 | } |
298 | } | 294 | } |
299 | 295 | ||
300 | impl fmt::Display for Ty { | 296 | impl HirDisplay for &Ty { |
301 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | 297 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { |
298 | HirDisplay::hir_fmt(*self, f) | ||
299 | } | ||
300 | } | ||
301 | |||
302 | impl HirDisplay for Ty { | ||
303 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | ||
302 | match self { | 304 | match self { |
303 | Ty::Bool => write!(f, "bool"), | 305 | Ty::Bool => write!(f, "bool")?, |
304 | Ty::Char => write!(f, "char"), | 306 | Ty::Char => write!(f, "char")?, |
305 | Ty::Int(t) => write!(f, "{}", t.ty_to_string()), | 307 | Ty::Int(t) => write!(f, "{}", t.ty_to_string())?, |
306 | Ty::Float(t) => write!(f, "{}", t.ty_to_string()), | 308 | Ty::Float(t) => write!(f, "{}", t.ty_to_string())?, |
307 | Ty::Str => write!(f, "str"), | 309 | Ty::Str => write!(f, "str")?, |
308 | Ty::Slice(t) | Ty::Array(t) => write!(f, "[{}]", t), | 310 | Ty::Slice(t) | Ty::Array(t) => { |
309 | Ty::RawPtr(t, m) => write!(f, "*{}{}", m.as_keyword_for_ptr(), t), | 311 | write!(f, "[{}]", t.display(f.db))?; |
310 | Ty::Ref(t, m) => write!(f, "&{}{}", m.as_keyword_for_ref(), t), | 312 | } |
311 | Ty::Never => write!(f, "!"), | 313 | Ty::RawPtr(t, m) => { |
314 | write!(f, "*{}{}", m.as_keyword_for_ptr(), t.display(f.db))?; | ||
315 | } | ||
316 | Ty::Ref(t, m) => { | ||
317 | write!(f, "&{}{}", m.as_keyword_for_ref(), t.display(f.db))?; | ||
318 | } | ||
319 | Ty::Never => write!(f, "!")?, | ||
312 | Ty::Tuple(ts) => { | 320 | Ty::Tuple(ts) => { |
313 | if ts.len() == 1 { | 321 | if ts.len() == 1 { |
314 | write!(f, "({},)", ts[0]) | 322 | write!(f, "({},)", ts[0].display(f.db))?; |
315 | } else { | 323 | } else { |
316 | join(ts.iter()).surround_with("(", ")").separator(", ").to_fmt(f) | 324 | write!(f, "(")?; |
325 | f.write_joined(&**ts, ", ")?; | ||
326 | write!(f, ")")?; | ||
317 | } | 327 | } |
318 | } | 328 | } |
319 | Ty::FnPtr(sig) => { | 329 | Ty::FnPtr(sig) => { |
320 | join(sig.input.iter()).surround_with("fn(", ")").separator(", ").to_fmt(f)?; | 330 | write!(f, "fn(")?; |
321 | write!(f, " -> {}", sig.output) | 331 | f.write_joined(&sig.input, ", ")?; |
332 | write!(f, ") -> {}", sig.output.display(f.db))?; | ||
322 | } | 333 | } |
323 | Ty::FnDef { def, name, substs, sig, .. } => { | 334 | Ty::FnDef { def, substs, sig, .. } => { |
335 | let name = match def { | ||
336 | CallableDef::Function(ff) => ff.name(f.db), | ||
337 | CallableDef::Struct(s) => s.name(f.db).unwrap_or_else(Name::missing), | ||
338 | CallableDef::EnumVariant(e) => e.name(f.db).unwrap_or_else(Name::missing), | ||
339 | }; | ||
324 | match def { | 340 | match def { |
325 | CallableDef::Function(_) => write!(f, "fn {}", name)?, | 341 | CallableDef::Function(_) => write!(f, "fn {}", name)?, |
326 | CallableDef::Struct(_) | CallableDef::EnumVariant(_) => write!(f, "{}", name)?, | 342 | CallableDef::Struct(_) | CallableDef::EnumVariant(_) => write!(f, "{}", name)?, |
327 | } | 343 | } |
328 | if substs.0.len() > 0 { | 344 | if substs.0.len() > 0 { |
329 | join(substs.0.iter()).surround_with("<", ">").separator(", ").to_fmt(f)?; | 345 | write!(f, "<")?; |
346 | f.write_joined(&*substs.0, ", ")?; | ||
347 | write!(f, ">")?; | ||
330 | } | 348 | } |
331 | join(sig.input.iter()).surround_with("(", ")").separator(", ").to_fmt(f)?; | 349 | write!(f, "(")?; |
332 | write!(f, " -> {}", sig.output) | 350 | f.write_joined(&sig.input, ", ")?; |
351 | write!(f, ") -> {}", sig.output.display(f.db))?; | ||
333 | } | 352 | } |
334 | Ty::Adt { name, substs, .. } => { | 353 | Ty::Adt { def_id, substs, .. } => { |
354 | let name = match def_id { | ||
355 | AdtDef::Struct(s) => s.name(f.db), | ||
356 | AdtDef::Enum(e) => e.name(f.db), | ||
357 | } | ||
358 | .unwrap_or_else(Name::missing); | ||
335 | write!(f, "{}", name)?; | 359 | write!(f, "{}", name)?; |
336 | if substs.0.len() > 0 { | 360 | if substs.0.len() > 0 { |
337 | join(substs.0.iter()).surround_with("<", ">").separator(", ").to_fmt(f)?; | 361 | write!(f, "<")?; |
362 | f.write_joined(&*substs.0, ", ")?; | ||
363 | write!(f, ">")?; | ||
338 | } | 364 | } |
339 | Ok(()) | ||
340 | } | 365 | } |
341 | Ty::Param { name, .. } => write!(f, "{}", name), | 366 | Ty::Param { name, .. } => write!(f, "{}", name)?, |
342 | Ty::Unknown => write!(f, "{{unknown}}"), | 367 | Ty::Unknown => write!(f, "{{unknown}}")?, |
343 | Ty::Infer(..) => write!(f, "_"), | 368 | Ty::Infer(..) => write!(f, "_")?, |
344 | } | 369 | } |
370 | Ok(()) | ||
345 | } | 371 | } |
346 | } | 372 | } |
diff --git a/crates/ra_hir/src/ty/display.rs b/crates/ra_hir/src/ty/display.rs new file mode 100644 index 000000000..63ec9d7e1 --- /dev/null +++ b/crates/ra_hir/src/ty/display.rs | |||
@@ -0,0 +1,56 @@ | |||
1 | use std::fmt; | ||
2 | |||
3 | use crate::db::HirDatabase; | ||
4 | |||
5 | pub struct HirFormatter<'a, 'b, DB> { | ||
6 | pub db: &'a DB, | ||
7 | fmt: &'a mut fmt::Formatter<'b>, | ||
8 | } | ||
9 | |||
10 | pub trait HirDisplay { | ||
11 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result; | ||
12 | fn display<'a, DB>(&'a self, db: &'a DB) -> HirDisplayWrapper<'a, DB, Self> | ||
13 | where | ||
14 | Self: Sized, | ||
15 | { | ||
16 | HirDisplayWrapper(db, self) | ||
17 | } | ||
18 | } | ||
19 | |||
20 | impl<'a, 'b, DB> HirFormatter<'a, 'b, DB> | ||
21 | where | ||
22 | DB: HirDatabase, | ||
23 | { | ||
24 | pub fn write_joined<T: HirDisplay>( | ||
25 | &mut self, | ||
26 | iter: impl IntoIterator<Item = T>, | ||
27 | sep: &str, | ||
28 | ) -> fmt::Result { | ||
29 | let mut first = true; | ||
30 | for e in iter { | ||
31 | if !first { | ||
32 | write!(self, "{}", sep)?; | ||
33 | } | ||
34 | first = false; | ||
35 | e.hir_fmt(self)?; | ||
36 | } | ||
37 | Ok(()) | ||
38 | } | ||
39 | |||
40 | /// This allows using the `write!` macro directly with a `HirFormatter`. | ||
41 | pub fn write_fmt(&mut self, args: fmt::Arguments) -> fmt::Result { | ||
42 | fmt::write(self.fmt, args) | ||
43 | } | ||
44 | } | ||
45 | |||
46 | pub struct HirDisplayWrapper<'a, DB, T>(&'a DB, &'a T); | ||
47 | |||
48 | impl<'a, DB, T> fmt::Display for HirDisplayWrapper<'a, DB, T> | ||
49 | where | ||
50 | DB: HirDatabase, | ||
51 | T: HirDisplay, | ||
52 | { | ||
53 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
54 | self.1.hir_fmt(&mut HirFormatter { db: self.0, fmt: f }) | ||
55 | } | ||
56 | } | ||
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index f4e055feb..ee4508bb2 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -9,7 +9,7 @@ | |||
9 | use std::sync::Arc; | 9 | use std::sync::Arc; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | Function, Struct, StructField, Enum, EnumVariant, Path, Name, | 12 | Function, Struct, StructField, Enum, EnumVariant, Path, |
13 | ModuleDef, TypeAlias, | 13 | ModuleDef, TypeAlias, |
14 | Const, Static, | 14 | Const, Static, |
15 | HirDatabase, | 15 | HirDatabase, |
@@ -232,13 +232,12 @@ fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { | |||
232 | let signature = def.signature(db); | 232 | let signature = def.signature(db); |
233 | let resolver = def.resolver(db); | 233 | let resolver = def.resolver(db); |
234 | let generics = def.generic_params(db); | 234 | let generics = def.generic_params(db); |
235 | let name = def.name(db); | ||
236 | let input = | 235 | let input = |
237 | signature.params().iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>(); | 236 | signature.params().iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>(); |
238 | let output = Ty::from_hir(db, &resolver, signature.ret_type()); | 237 | let output = Ty::from_hir(db, &resolver, signature.ret_type()); |
239 | let sig = Arc::new(FnSig { input, output }); | 238 | let sig = Arc::new(FnSig { input, output }); |
240 | let substs = make_substs(&generics); | 239 | let substs = make_substs(&generics); |
241 | Ty::FnDef { def: def.into(), sig, name, substs } | 240 | Ty::FnDef { def: def.into(), sig, substs } |
242 | } | 241 | } |
243 | 242 | ||
244 | /// Build the declared type of a const. | 243 | /// Build the declared type of a const. |
@@ -266,7 +265,6 @@ fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { | |||
266 | }; | 265 | }; |
267 | let resolver = def.resolver(db); | 266 | let resolver = def.resolver(db); |
268 | let generics = def.generic_params(db); | 267 | let generics = def.generic_params(db); |
269 | let name = def.name(db).unwrap_or_else(Name::missing); | ||
270 | let input = fields | 268 | let input = fields |
271 | .iter() | 269 | .iter() |
272 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) | 270 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) |
@@ -274,7 +272,7 @@ fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { | |||
274 | let output = type_for_struct(db, def); | 272 | let output = type_for_struct(db, def); |
275 | let sig = Arc::new(FnSig { input, output }); | 273 | let sig = Arc::new(FnSig { input, output }); |
276 | let substs = make_substs(&generics); | 274 | let substs = make_substs(&generics); |
277 | Ty::FnDef { def: def.into(), sig, name, substs } | 275 | Ty::FnDef { def: def.into(), sig, substs } |
278 | } | 276 | } |
279 | 277 | ||
280 | /// Build the type of a tuple enum variant constructor. | 278 | /// Build the type of a tuple enum variant constructor. |
@@ -286,7 +284,6 @@ fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> | |||
286 | }; | 284 | }; |
287 | let resolver = def.parent_enum(db).resolver(db); | 285 | let resolver = def.parent_enum(db).resolver(db); |
288 | let generics = def.parent_enum(db).generic_params(db); | 286 | let generics = def.parent_enum(db).generic_params(db); |
289 | let name = def.name(db).unwrap_or_else(Name::missing); | ||
290 | let input = fields | 287 | let input = fields |
291 | .iter() | 288 | .iter() |
292 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) | 289 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) |
@@ -294,7 +291,7 @@ fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> | |||
294 | let substs = make_substs(&generics); | 291 | let substs = make_substs(&generics); |
295 | let output = type_for_enum(db, def.parent_enum(db)).subst(&substs); | 292 | let output = type_for_enum(db, def.parent_enum(db)).subst(&substs); |
296 | let sig = Arc::new(FnSig { input, output }); | 293 | let sig = Arc::new(FnSig { input, output }); |
297 | Ty::FnDef { def: def.into(), sig, name, substs } | 294 | Ty::FnDef { def: def.into(), sig, substs } |
298 | } | 295 | } |
299 | 296 | ||
300 | fn make_substs(generics: &GenericParams) -> Substs { | 297 | fn make_substs(generics: &GenericParams) -> Substs { |
@@ -310,20 +307,12 @@ fn make_substs(generics: &GenericParams) -> Substs { | |||
310 | 307 | ||
311 | fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { | 308 | fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { |
312 | let generics = s.generic_params(db); | 309 | let generics = s.generic_params(db); |
313 | Ty::Adt { | 310 | Ty::Adt { def_id: s.into(), substs: make_substs(&generics) } |
314 | def_id: s.into(), | ||
315 | name: s.name(db).unwrap_or_else(Name::missing), | ||
316 | substs: make_substs(&generics), | ||
317 | } | ||
318 | } | 311 | } |
319 | 312 | ||
320 | fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { | 313 | fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { |
321 | let generics = s.generic_params(db); | 314 | let generics = s.generic_params(db); |
322 | Ty::Adt { | 315 | Ty::Adt { def_id: s.into(), substs: make_substs(&generics) } |
323 | def_id: s.into(), | ||
324 | name: s.name(db).unwrap_or_else(Name::missing), | ||
325 | substs: make_substs(&generics), | ||
326 | } | ||
327 | } | 316 | } |
328 | 317 | ||
329 | fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { | 318 | fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index c7d409e6d..acae71c26 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -10,6 +10,7 @@ use test_utils::covers; | |||
10 | use crate::{ | 10 | use crate::{ |
11 | source_binder, | 11 | source_binder, |
12 | mock::MockDatabase, | 12 | mock::MockDatabase, |
13 | ty::display::HirDisplay, | ||
13 | }; | 14 | }; |
14 | 15 | ||
15 | // These tests compare the inference results for all expressions in a file | 16 | // These tests compare the inference results for all expressions in a file |
@@ -2142,7 +2143,7 @@ fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { | |||
2142 | let node = algo::find_node_at_offset::<ast::Expr>(syntax.syntax(), pos.offset).unwrap(); | 2143 | let node = algo::find_node_at_offset::<ast::Expr>(syntax.syntax(), pos.offset).unwrap(); |
2143 | let expr = body_source_map.node_expr(node).unwrap(); | 2144 | let expr = body_source_map.node_expr(node).unwrap(); |
2144 | let ty = &inference_result[expr]; | 2145 | let ty = &inference_result[expr]; |
2145 | ty.to_string() | 2146 | ty.display(db).to_string() |
2146 | } | 2147 | } |
2147 | 2148 | ||
2148 | fn infer(content: &str) -> String { | 2149 | fn infer(content: &str) -> String { |
@@ -2178,7 +2179,7 @@ fn infer(content: &str) -> String { | |||
2178 | "{} '{}': {}\n", | 2179 | "{} '{}': {}\n", |
2179 | syntax_ptr.range(), | 2180 | syntax_ptr.range(), |
2180 | ellipsize(node.text().to_string().replace("\n", " "), 15), | 2181 | ellipsize(node.text().to_string().replace("\n", " "), 15), |
2181 | ty | 2182 | ty.display(&db) |
2182 | ) | 2183 | ) |
2183 | .unwrap(); | 2184 | .unwrap(); |
2184 | } | 2185 | } |