aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/lib.rs2
-rw-r--r--crates/ra_hir/src/ty.rs94
-rw-r--r--crates/ra_hir/src/ty/display.rs56
-rw-r--r--crates/ra_hir/src/ty/lower.rs23
-rw-r--r--crates/ra_hir/src/ty/tests.rs5
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;
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
18use crate::{Name, AdtDef, type_ref::Mutability};
19 18
20pub(crate) use lower::{TypableDef, CallableDef, type_for_def, type_for_field}; 19pub(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,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
300impl fmt::Display for Ty { 296impl 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
302impl 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 @@
1use std::fmt;
2
3use crate::db::HirDatabase;
4
5pub struct HirFormatter<'a, 'b, DB> {
6 pub db: &'a DB,
7 fmt: &'a mut fmt::Formatter<'b>,
8}
9
10pub 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
20impl<'a, 'b, DB> HirFormatter<'a, 'b, DB>
21where
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
46pub struct HirDisplayWrapper<'a, DB, T>(&'a DB, &'a T);
47
48impl<'a, DB, T> fmt::Display for HirDisplayWrapper<'a, DB, T>
49where
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 @@
9use std::sync::Arc; 9use std::sync::Arc;
10 10
11use crate::{ 11use 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
300fn make_substs(generics: &GenericParams) -> Substs { 297fn make_substs(generics: &GenericParams) -> Substs {
@@ -310,20 +307,12 @@ fn make_substs(generics: &GenericParams) -> Substs {
310 307
311fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { 308fn 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
320fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { 313fn 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
329fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { 318fn 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;
10use crate::{ 10use 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
2148fn infer(content: &str) -> String { 2149fn 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 }