aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir_ty/src/display.rs56
-rw-r--r--crates/hir_ty/src/tests.rs8
-rw-r--r--crates/ide/src/inlay_hints.rs21
3 files changed, 72 insertions, 13 deletions
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index d2e151f25..822ef4477 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -82,6 +82,20 @@ pub trait HirDisplay {
82 }; 82 };
83 Ok(result) 83 Ok(result)
84 } 84 }
85
86 /// Returns a String representation of `self` for test purposes
87 fn display_test<'a>(&'a self, db: &'a dyn HirDatabase) -> HirDisplayWrapper<'a, Self>
88 where
89 Self: Sized,
90 {
91 HirDisplayWrapper {
92 db,
93 t: self,
94 max_size: None,
95 omit_verbose_types: false,
96 display_target: DisplayTarget::Test,
97 }
98 }
85} 99}
86 100
87impl<'a> HirFormatter<'a> { 101impl<'a> HirFormatter<'a> {
@@ -134,12 +148,17 @@ enum DisplayTarget {
134 /// Display types for inserting them in source files. 148 /// Display types for inserting them in source files.
135 /// The generated code should compile, so paths need to be qualified. 149 /// The generated code should compile, so paths need to be qualified.
136 SourceCode { module_id: ModuleId }, 150 SourceCode { module_id: ModuleId },
151 /// Only for test purpose to keep real types
152 Test,
137} 153}
138 154
139impl DisplayTarget { 155impl DisplayTarget {
140 fn is_source_code(&self) -> bool { 156 fn is_source_code(&self) -> bool {
141 matches!(self, Self::SourceCode {..}) 157 matches!(self, Self::SourceCode {..})
142 } 158 }
159 fn is_test(&self) -> bool {
160 matches!(self, Self::Test)
161 }
143} 162}
144 163
145#[derive(Debug)] 164#[derive(Debug)]
@@ -313,14 +332,18 @@ impl HirDisplay for ApplicationTy {
313 let ret_display = if f.omit_verbose_types() { 332 let ret_display = if f.omit_verbose_types() {
314 ret.display_truncated(f.db, f.max_size) 333 ret.display_truncated(f.db, f.max_size)
315 } else { 334 } else {
316 ret.display(f.db) 335 if f.display_target.is_test() {
336 ret.display_test(f.db)
337 } else {
338 ret.display(f.db)
339 }
317 }; 340 };
318 write!(f, " -> {}", ret_display)?; 341 write!(f, " -> {}", ret_display)?;
319 } 342 }
320 } 343 }
321 TypeCtor::Adt(def_id) => { 344 TypeCtor::Adt(def_id) => {
322 match f.display_target { 345 match f.display_target {
323 DisplayTarget::Diagnostics => { 346 DisplayTarget::Diagnostics | DisplayTarget::Test => {
324 let name = match def_id { 347 let name = match def_id {
325 AdtId::StructId(it) => f.db.struct_data(it).name.clone(), 348 AdtId::StructId(it) => f.db.struct_data(it).name.clone(),
326 AdtId::UnionId(it) => f.db.union_data(it).name.clone(), 349 AdtId::UnionId(it) => f.db.union_data(it).name.clone(),
@@ -389,12 +412,23 @@ impl HirDisplay for ApplicationTy {
389 _ => panic!("not an associated type"), 412 _ => panic!("not an associated type"),
390 }; 413 };
391 let trait_ = f.db.trait_data(trait_); 414 let trait_ = f.db.trait_data(trait_);
392 let type_alias = f.db.type_alias_data(type_alias); 415 let type_alias_data = f.db.type_alias_data(type_alias);
393 write!(f, "{}::{}", trait_.name, type_alias.name)?; 416
394 if self.parameters.len() > 0 { 417 // 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, "<")?; 418 if f.display_target.is_test() {
396 f.write_joined(&*self.parameters.0, ", ")?; 419 write!(f, "{}::{}", trait_.name, type_alias_data.name)?;
397 write!(f, ">")?; 420 if self.parameters.len() > 0 {
421 write!(f, "<")?;
422 f.write_joined(&*self.parameters.0, ", ")?;
423 write!(f, ">")?;
424 }
425 } else {
426 let projection_ty = ProjectionTy {
427 associated_ty: type_alias,
428 parameters: self.parameters.clone(),
429 };
430
431 projection_ty.hir_fmt(f)?;
398 } 432 }
399 } 433 }
400 TypeCtor::ForeignType(type_alias) => { 434 TypeCtor::ForeignType(type_alias) => {
@@ -442,7 +476,11 @@ impl HirDisplay for ApplicationTy {
442 let ret_display = if f.omit_verbose_types() { 476 let ret_display = if f.omit_verbose_types() {
443 sig.ret().display_truncated(f.db, f.max_size) 477 sig.ret().display_truncated(f.db, f.max_size)
444 } else { 478 } else {
445 sig.ret().display(f.db) 479 if f.display_target.is_test() {
480 sig.ret().display_test(f.db)
481 } else {
482 sig.ret().display(f.db)
483 }
446 }; 484 };
447 write!(f, " -> {}", ret_display)?; 485 write!(f, " -> {}", ret_display)?;
448 } else { 486 } else {
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs
index 0445efc9e..104ef334c 100644
--- a/crates/hir_ty/src/tests.rs
+++ b/crates/hir_ty/src/tests.rs
@@ -74,7 +74,7 @@ fn check_types_impl(ra_fixture: &str, display_source: bool) {
74 let module = db.module_for_file(file_id); 74 let module = db.module_for_file(file_id);
75 ty.display_source_code(&db, module).unwrap() 75 ty.display_source_code(&db, module).unwrap()
76 } else { 76 } else {
77 ty.display(&db).to_string() 77 ty.display_test(&db).to_string()
78 }; 78 };
79 assert_eq!(expected, actual); 79 assert_eq!(expected, actual);
80 checked_one = true; 80 checked_one = true;
@@ -163,7 +163,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
163 macro_prefix, 163 macro_prefix,
164 range, 164 range,
165 ellipsize(text, 15), 165 ellipsize(text, 15),
166 ty.display(&db) 166 ty.display_test(&db)
167 ); 167 );
168 } 168 }
169 if include_mismatches { 169 if include_mismatches {
@@ -179,8 +179,8 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
179 "{}{:?}: expected {}, got {}\n", 179 "{}{:?}: expected {}, got {}\n",
180 macro_prefix, 180 macro_prefix,
181 range, 181 range,
182 mismatch.expected.display(&db), 182 mismatch.expected.display_test(&db),
183 mismatch.actual.display(&db), 183 mismatch.actual.display_test(&db),
184 ); 184 );
185 } 185 }
186 } 186 }
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs
index 49d8e4ae1..adb93efd7 100644
--- a/crates/ide/src/inlay_hints.rs
+++ b/crates/ide/src/inlay_hints.rs
@@ -1235,4 +1235,25 @@ fn main() {
1235"#, 1235"#,
1236 ); 1236 );
1237 } 1237 }
1238
1239 #[test]
1240 fn infer_call_method_return_associated_types_with_generic() {
1241 check(
1242 r#"
1243 pub trait Default {
1244 fn default() -> Self;
1245 }
1246 pub trait Foo {
1247 type Bar: Default;
1248 }
1249
1250 pub fn quux<T: Foo>() -> T::Bar {
1251 let y = Default::default();
1252 //^ <T as Foo>::Bar
1253
1254 y
1255 }
1256 "#,
1257 );
1258 }
1238} 1259}