diff options
Diffstat (limited to 'crates/ra_hir/src/ty')
-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 |
3 files changed, 65 insertions, 19 deletions
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 | } |