diff options
Diffstat (limited to 'crates/hir_ty/src/display.rs')
-rw-r--r-- | crates/hir_ty/src/display.rs | 149 |
1 files changed, 105 insertions, 44 deletions
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index d2e151f25..14e8c0633 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -26,6 +26,20 @@ pub trait HirDisplay { | |||
26 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError>; | 26 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError>; |
27 | 27 | ||
28 | /// Returns a `Display`able type that is human-readable. | 28 | /// Returns a `Display`able type that is human-readable. |
29 | fn into_displayable<'a>( | ||
30 | &'a self, | ||
31 | db: &'a dyn HirDatabase, | ||
32 | max_size: Option<usize>, | ||
33 | omit_verbose_types: bool, | ||
34 | display_target: DisplayTarget, | ||
35 | ) -> HirDisplayWrapper<'a, Self> | ||
36 | where | ||
37 | Self: Sized, | ||
38 | { | ||
39 | HirDisplayWrapper { db, t: self, max_size, omit_verbose_types, display_target } | ||
40 | } | ||
41 | |||
42 | /// Returns a `Display`able type that is human-readable. | ||
29 | /// Use this for showing types to the user (e.g. diagnostics) | 43 | /// Use this for showing types to the user (e.g. diagnostics) |
30 | fn display<'a>(&'a self, db: &'a dyn HirDatabase) -> HirDisplayWrapper<'a, Self> | 44 | fn display<'a>(&'a self, db: &'a dyn HirDatabase) -> HirDisplayWrapper<'a, Self> |
31 | where | 45 | where |
@@ -82,6 +96,20 @@ pub trait HirDisplay { | |||
82 | }; | 96 | }; |
83 | Ok(result) | 97 | Ok(result) |
84 | } | 98 | } |
99 | |||
100 | /// Returns a String representation of `self` for test purposes | ||
101 | fn display_test<'a>(&'a self, db: &'a dyn HirDatabase) -> HirDisplayWrapper<'a, Self> | ||
102 | where | ||
103 | Self: Sized, | ||
104 | { | ||
105 | HirDisplayWrapper { | ||
106 | db, | ||
107 | t: self, | ||
108 | max_size: None, | ||
109 | omit_verbose_types: false, | ||
110 | display_target: DisplayTarget::Test, | ||
111 | } | ||
112 | } | ||
85 | } | 113 | } |
86 | 114 | ||
87 | impl<'a> HirFormatter<'a> { | 115 | impl<'a> HirFormatter<'a> { |
@@ -126,7 +154,7 @@ impl<'a> HirFormatter<'a> { | |||
126 | } | 154 | } |
127 | 155 | ||
128 | #[derive(Clone, Copy)] | 156 | #[derive(Clone, Copy)] |
129 | enum DisplayTarget { | 157 | pub enum DisplayTarget { |
130 | /// Display types for inlays, doc popups, autocompletion, etc... | 158 | /// Display types for inlays, doc popups, autocompletion, etc... |
131 | /// Showing `{unknown}` or not qualifying paths is fine here. | 159 | /// Showing `{unknown}` or not qualifying paths is fine here. |
132 | /// There's no reason for this to fail. | 160 | /// There's no reason for this to fail. |
@@ -134,12 +162,17 @@ enum DisplayTarget { | |||
134 | /// Display types for inserting them in source files. | 162 | /// Display types for inserting them in source files. |
135 | /// The generated code should compile, so paths need to be qualified. | 163 | /// The generated code should compile, so paths need to be qualified. |
136 | SourceCode { module_id: ModuleId }, | 164 | SourceCode { module_id: ModuleId }, |
165 | /// Only for test purpose to keep real types | ||
166 | Test, | ||
137 | } | 167 | } |
138 | 168 | ||
139 | impl DisplayTarget { | 169 | impl DisplayTarget { |
140 | fn is_source_code(&self) -> bool { | 170 | fn is_source_code(&self) -> bool { |
141 | matches!(self, Self::SourceCode {..}) | 171 | matches!(self, Self::SourceCode {..}) |
142 | } | 172 | } |
173 | fn is_test(&self) -> bool { | ||
174 | matches!(self, Self::Test) | ||
175 | } | ||
143 | } | 176 | } |
144 | 177 | ||
145 | #[derive(Debug)] | 178 | #[derive(Debug)] |
@@ -213,32 +246,32 @@ impl HirDisplay for ApplicationTy { | |||
213 | TypeCtor::Str => write!(f, "str")?, | 246 | TypeCtor::Str => write!(f, "str")?, |
214 | TypeCtor::Slice => { | 247 | TypeCtor::Slice => { |
215 | let t = self.parameters.as_single(); | 248 | let t = self.parameters.as_single(); |
216 | write!(f, "[{}]", t.display(f.db))?; | 249 | write!(f, "[")?; |
250 | t.hir_fmt(f)?; | ||
251 | write!(f, "]")?; | ||
217 | } | 252 | } |
218 | TypeCtor::Array => { | 253 | TypeCtor::Array => { |
219 | let t = self.parameters.as_single(); | 254 | let t = self.parameters.as_single(); |
220 | write!(f, "[{}; _]", t.display(f.db))?; | 255 | write!(f, "[")?; |
256 | t.hir_fmt(f)?; | ||
257 | write!(f, "; _]")?; | ||
221 | } | 258 | } |
222 | TypeCtor::RawPtr(m) => { | 259 | TypeCtor::RawPtr(m) => { |
223 | let t = self.parameters.as_single(); | 260 | let t = self.parameters.as_single(); |
224 | let ty_display = t.display(f.db); | ||
225 | 261 | ||
226 | write!(f, "*{}", m.as_keyword_for_ptr())?; | 262 | write!(f, "*{}", m.as_keyword_for_ptr())?; |
227 | if matches!(t, Ty::Dyn(predicates) if predicates.len() > 1) { | 263 | if matches!(t, Ty::Dyn(predicates) if predicates.len() > 1) { |
228 | write!(f, "(")?; | 264 | write!(f, "(")?; |
229 | write!(f, "{}", ty_display)?; | 265 | t.hir_fmt(f)?; |
230 | write!(f, ")")?; | 266 | write!(f, ")")?; |
231 | } else { | 267 | } else { |
232 | write!(f, "{}", ty_display)?; | 268 | t.hir_fmt(f)?; |
233 | } | 269 | } |
234 | } | 270 | } |
235 | TypeCtor::Ref(m) => { | 271 | TypeCtor::Ref(m) => { |
236 | let t = self.parameters.as_single(); | 272 | let t = self.parameters.as_single(); |
237 | let ty_display = if f.omit_verbose_types() { | 273 | let ty_display = |
238 | t.display_truncated(f.db, f.max_size) | 274 | t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); |
239 | } else { | ||
240 | t.display(f.db) | ||
241 | }; | ||
242 | 275 | ||
243 | write!(f, "&{}", m.as_keyword_for_ref())?; | 276 | write!(f, "&{}", m.as_keyword_for_ref())?; |
244 | if matches!(t, Ty::Dyn(predicates) if predicates.len() > 1) { | 277 | if matches!(t, Ty::Dyn(predicates) if predicates.len() > 1) { |
@@ -253,7 +286,9 @@ impl HirDisplay for ApplicationTy { | |||
253 | TypeCtor::Tuple { .. } => { | 286 | TypeCtor::Tuple { .. } => { |
254 | let ts = &self.parameters; | 287 | let ts = &self.parameters; |
255 | if ts.len() == 1 { | 288 | if ts.len() == 1 { |
256 | write!(f, "({},)", ts[0].display(f.db))?; | 289 | write!(f, "(")?; |
290 | ts[0].hir_fmt(f)?; | ||
291 | write!(f, ",)")?; | ||
257 | } else { | 292 | } else { |
258 | write!(f, "(")?; | 293 | write!(f, "(")?; |
259 | f.write_joined(&*ts.0, ", ")?; | 294 | f.write_joined(&*ts.0, ", ")?; |
@@ -274,11 +309,12 @@ impl HirDisplay for ApplicationTy { | |||
274 | write!(f, ")")?; | 309 | write!(f, ")")?; |
275 | let ret = sig.ret(); | 310 | let ret = sig.ret(); |
276 | if *ret != Ty::unit() { | 311 | if *ret != Ty::unit() { |
277 | let ret_display = if f.omit_verbose_types() { | 312 | let ret_display = ret.into_displayable( |
278 | ret.display_truncated(f.db, f.max_size) | 313 | f.db, |
279 | } else { | 314 | f.max_size, |
280 | ret.display(f.db) | 315 | f.omit_verbose_types, |
281 | }; | 316 | f.display_target, |
317 | ); | ||
282 | write!(f, " -> {}", ret_display)?; | 318 | write!(f, " -> {}", ret_display)?; |
283 | } | 319 | } |
284 | } | 320 | } |
@@ -310,17 +346,19 @@ impl HirDisplay for ApplicationTy { | |||
310 | write!(f, ")")?; | 346 | write!(f, ")")?; |
311 | let ret = sig.ret(); | 347 | let ret = sig.ret(); |
312 | if *ret != Ty::unit() { | 348 | if *ret != Ty::unit() { |
313 | let ret_display = if f.omit_verbose_types() { | 349 | let ret_display = ret.into_displayable( |
314 | ret.display_truncated(f.db, f.max_size) | 350 | f.db, |
315 | } else { | 351 | f.max_size, |
316 | ret.display(f.db) | 352 | f.omit_verbose_types, |
317 | }; | 353 | f.display_target, |
354 | ); | ||
355 | |||
318 | write!(f, " -> {}", ret_display)?; | 356 | write!(f, " -> {}", ret_display)?; |
319 | } | 357 | } |
320 | } | 358 | } |
321 | TypeCtor::Adt(def_id) => { | 359 | TypeCtor::Adt(def_id) => { |
322 | match f.display_target { | 360 | match f.display_target { |
323 | DisplayTarget::Diagnostics => { | 361 | DisplayTarget::Diagnostics | DisplayTarget::Test => { |
324 | let name = match def_id { | 362 | let name = match def_id { |
325 | AdtId::StructId(it) => f.db.struct_data(it).name.clone(), | 363 | AdtId::StructId(it) => f.db.struct_data(it).name.clone(), |
326 | AdtId::UnionId(it) => f.db.union_data(it).name.clone(), | 364 | AdtId::UnionId(it) => f.db.union_data(it).name.clone(), |
@@ -389,12 +427,23 @@ impl HirDisplay for ApplicationTy { | |||
389 | _ => panic!("not an associated type"), | 427 | _ => panic!("not an associated type"), |
390 | }; | 428 | }; |
391 | let trait_ = f.db.trait_data(trait_); | 429 | let trait_ = f.db.trait_data(trait_); |
392 | let type_alias = f.db.type_alias_data(type_alias); | 430 | let type_alias_data = f.db.type_alias_data(type_alias); |
393 | write!(f, "{}::{}", trait_.name, type_alias.name)?; | 431 | |
394 | if self.parameters.len() > 0 { | 432 | // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) |
395 | write!(f, "<")?; | 433 | if f.display_target.is_test() { |
396 | f.write_joined(&*self.parameters.0, ", ")?; | 434 | write!(f, "{}::{}", trait_.name, type_alias_data.name)?; |
397 | write!(f, ">")?; | 435 | if self.parameters.len() > 0 { |
436 | write!(f, "<")?; | ||
437 | f.write_joined(&*self.parameters.0, ", ")?; | ||
438 | write!(f, ">")?; | ||
439 | } | ||
440 | } else { | ||
441 | let projection_ty = ProjectionTy { | ||
442 | associated_ty: type_alias, | ||
443 | parameters: self.parameters.clone(), | ||
444 | }; | ||
445 | |||
446 | projection_ty.hir_fmt(f)?; | ||
398 | } | 447 | } |
399 | } | 448 | } |
400 | TypeCtor::ForeignType(type_alias) => { | 449 | TypeCtor::ForeignType(type_alias) => { |
@@ -439,11 +488,12 @@ impl HirDisplay for ApplicationTy { | |||
439 | write!(f, "|")?; | 488 | write!(f, "|")?; |
440 | }; | 489 | }; |
441 | 490 | ||
442 | let ret_display = if f.omit_verbose_types() { | 491 | let ret_display = sig.ret().into_displayable( |
443 | sig.ret().display_truncated(f.db, f.max_size) | 492 | f.db, |
444 | } else { | 493 | f.max_size, |
445 | sig.ret().display(f.db) | 494 | f.omit_verbose_types, |
446 | }; | 495 | f.display_target, |
496 | ); | ||
447 | write!(f, " -> {}", ret_display)?; | 497 | write!(f, " -> {}", ret_display)?; |
448 | } else { | 498 | } else { |
449 | write!(f, "{{closure}}")?; | 499 | write!(f, "{{closure}}")?; |
@@ -461,7 +511,13 @@ impl HirDisplay for ProjectionTy { | |||
461 | } | 511 | } |
462 | 512 | ||
463 | let trait_ = f.db.trait_data(self.trait_(f.db)); | 513 | let trait_ = f.db.trait_data(self.trait_(f.db)); |
464 | write!(f, "<{} as {}", self.parameters[0].display(f.db), trait_.name)?; | 514 | let first_parameter = self.parameters[0].into_displayable( |
515 | f.db, | ||
516 | f.max_size, | ||
517 | f.omit_verbose_types, | ||
518 | f.display_target, | ||
519 | ); | ||
520 | write!(f, "<{} as {}", first_parameter, trait_.name)?; | ||
465 | if self.parameters.len() > 1 { | 521 | if self.parameters.len() > 1 { |
466 | write!(f, "<")?; | 522 | write!(f, "<")?; |
467 | f.write_joined(&self.parameters[1..], ", ")?; | 523 | f.write_joined(&self.parameters[1..], ", ")?; |
@@ -640,10 +696,10 @@ impl HirDisplay for GenericPredicate { | |||
640 | projection_pred.projection_ty.trait_ref(f.db).hir_fmt_ext(f, true)?; | 696 | projection_pred.projection_ty.trait_ref(f.db).hir_fmt_ext(f, true)?; |
641 | write!( | 697 | write!( |
642 | f, | 698 | f, |
643 | ">::{} = {}", | 699 | ">::{} = ", |
644 | f.db.type_alias_data(projection_pred.projection_ty.associated_ty).name, | 700 | f.db.type_alias_data(projection_pred.projection_ty.associated_ty).name, |
645 | projection_pred.ty.display(f.db) | ||
646 | )?; | 701 | )?; |
702 | projection_pred.ty.hir_fmt(f)?; | ||
647 | } | 703 | } |
648 | GenericPredicate::Error => write!(f, "{{error}}")?, | 704 | GenericPredicate::Error => write!(f, "{{error}}")?, |
649 | } | 705 | } |
@@ -654,13 +710,18 @@ impl HirDisplay for GenericPredicate { | |||
654 | impl HirDisplay for Obligation { | 710 | impl HirDisplay for Obligation { |
655 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 711 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
656 | match self { | 712 | match self { |
657 | Obligation::Trait(tr) => write!(f, "Implements({})", tr.display(f.db)), | 713 | Obligation::Trait(tr) => { |
658 | Obligation::Projection(proj) => write!( | 714 | write!(f, "Implements(")?; |
659 | f, | 715 | tr.hir_fmt(f)?; |
660 | "Normalize({} => {})", | 716 | write!(f, ")") |
661 | proj.projection_ty.display(f.db), | 717 | } |
662 | proj.ty.display(f.db) | 718 | Obligation::Projection(proj) => { |
663 | ), | 719 | write!(f, "Normalize(")?; |
720 | proj.projection_ty.hir_fmt(f)?; | ||
721 | write!(f, " => ")?; | ||
722 | proj.ty.hir_fmt(f)?; | ||
723 | write!(f, ")") | ||
724 | } | ||
664 | } | 725 | } |
665 | } | 726 | } |
666 | } | 727 | } |