aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir_ty/src/display.rs88
-rw-r--r--crates/hir_ty/src/tests/traits.rs45
2 files changed, 102 insertions, 31 deletions
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index 43db24882..f1232a72f 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -74,7 +74,10 @@ pub trait HirDisplay {
74 curr_size: 0, 74 curr_size: 0,
75 max_size: None, 75 max_size: None,
76 omit_verbose_types: false, 76 omit_verbose_types: false,
77 #[cfg(not(test))]
77 display_target: DisplayTarget::SourceCode { module_id }, 78 display_target: DisplayTarget::SourceCode { module_id },
79 #[cfg(test)]
80 display_target: DisplayTarget::Test { module_id },
78 }) { 81 }) {
79 Ok(()) => {} 82 Ok(()) => {}
80 Err(HirDisplayError::FmtError) => panic!("Writing to String can't fail!"), 83 Err(HirDisplayError::FmtError) => panic!("Writing to String can't fail!"),
@@ -134,12 +137,25 @@ enum DisplayTarget {
134 /// Display types for inserting them in source files. 137 /// Display types for inserting them in source files.
135 /// The generated code should compile, so paths need to be qualified. 138 /// The generated code should compile, so paths need to be qualified.
136 SourceCode { module_id: ModuleId }, 139 SourceCode { module_id: ModuleId },
140 /// Only for test purpose to keep real types
141 #[cfg(test)]
142 Test { module_id: ModuleId },
137} 143}
138 144
139impl DisplayTarget { 145impl DisplayTarget {
140 fn is_source_code(&self) -> bool { 146 fn is_source_code(&self) -> bool {
141 matches!(self, Self::SourceCode {..}) 147 matches!(self, Self::SourceCode {..})
142 } 148 }
149 fn is_test(&self) -> bool {
150 #[cfg(test)]
151 {
152 matches!(self, Self::Test {..})
153 }
154 #[cfg(not(test))]
155 {
156 false
157 }
158 }
143} 159}
144 160
145#[derive(Debug)] 161#[derive(Debug)]
@@ -341,41 +357,57 @@ impl HirDisplay for ApplicationTy {
341 )); 357 ));
342 } 358 }
343 } 359 }
360 #[cfg(test)]
361 DisplayTarget::Test { module_id } => {
362 if let Some(path) = find_path::find_path(
363 f.db.upcast(),
364 ItemInNs::Types(def_id.into()),
365 module_id,
366 ) {
367 write!(f, "{}", path)?;
368 } else {
369 return Err(HirDisplayError::DisplaySourceCodeError(
370 DisplaySourceCodeError::PathNotFound,
371 ));
372 }
373 }
344 } 374 }
345 375
346 if self.parameters.len() > 0 { 376 if self.parameters.len() > 0 {
347 let parameters_to_write = 377 let parameters_to_write = if f.display_target.is_source_code()
348 if f.display_target.is_source_code() || f.omit_verbose_types() { 378 || f.display_target.is_test()
349 match self 379 || f.omit_verbose_types()
350 .ctor 380 {
351 .as_generic_def() 381 match self
352 .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) 382 .ctor
353 .filter(|defaults| !defaults.is_empty()) 383 .as_generic_def()
354 { 384 .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
355 None => self.parameters.0.as_ref(), 385 .filter(|defaults| !defaults.is_empty())
356 Some(default_parameters) => { 386 {
357 let mut default_from = 0; 387 None => self.parameters.0.as_ref(),
358 for (i, parameter) in self.parameters.iter().enumerate() { 388 Some(default_parameters) => {
359 match (parameter, default_parameters.get(i)) { 389 let mut default_from = 0;
360 (&Ty::Unknown, _) | (_, None) => { 390 for (i, parameter) in self.parameters.iter().enumerate() {
391 match (parameter, default_parameters.get(i)) {
392 (&Ty::Unknown, _) | (_, None) => {
393 default_from = i + 1;
394 }
395 (_, Some(default_parameter)) => {
396 let actual_default = default_parameter
397 .clone()
398 .subst(&self.parameters.prefix(i));
399 if parameter != &actual_default {
361 default_from = i + 1; 400 default_from = i + 1;
362 } 401 }
363 (_, Some(default_parameter)) => {
364 let actual_default = default_parameter
365 .clone()
366 .subst(&self.parameters.prefix(i));
367 if parameter != &actual_default {
368 default_from = i + 1;
369 }
370 }
371 } 402 }
372 } 403 }
373 &self.parameters.0[0..default_from]
374 } 404 }
405 &self.parameters.0[0..default_from]
375 } 406 }
376 } else { 407 }
377 self.parameters.0.as_ref() 408 } else {
378 }; 409 self.parameters.0.as_ref()
410 };
379 if !parameters_to_write.is_empty() { 411 if !parameters_to_write.is_empty() {
380 write!(f, "<")?; 412 write!(f, "<")?;
381 f.write_joined(parameters_to_write, ", ")?; 413 f.write_joined(parameters_to_write, ", ")?;
@@ -391,8 +423,8 @@ impl HirDisplay for ApplicationTy {
391 let trait_ = f.db.trait_data(trait_); 423 let trait_ = f.db.trait_data(trait_);
392 let type_alias = f.db.type_alias_data(type_alias); 424 let type_alias = f.db.type_alias_data(type_alias);
393 425
394 // Use placeholder associated types when the target is source code (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) 426 // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types)
395 if f.display_target.is_source_code() || self.parameters.len() > 1 { 427 if f.display_target.is_test() || self.parameters.len() > 1 {
396 write!(f, "{}::{}", trait_.name, type_alias.name)?; 428 write!(f, "{}::{}", trait_.name, type_alias.name)?;
397 if self.parameters.len() > 0 { 429 if self.parameters.len() > 0 {
398 write!(f, "<")?; 430 write!(f, "<")?;
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs
index 7ad8b5830..e98d7c064 100644
--- a/crates/hir_ty/src/tests/traits.rs
+++ b/crates/hir_ty/src/tests/traits.rs
@@ -1,7 +1,7 @@
1use expect_test::expect; 1use expect_test::expect;
2use test_utils::mark; 2use test_utils::mark;
3 3
4use super::{check_infer, check_infer_with_mismatches, check_types}; 4use super::{check_infer, check_infer_with_mismatches, check_types, check_types_source_code};
5 5
6#[test] 6#[test]
7fn infer_await() { 7fn infer_await() {
@@ -907,7 +907,7 @@ fn test<T: Trait>(t: T) { (*t); }
907} 907}
908 908
909#[test] 909#[test]
910fn associated_type_placeholder() { 910fn associated_type_inlay_hints() {
911 check_types( 911 check_types(
912 r#" 912 r#"
913pub trait ApplyL { 913pub trait ApplyL {
@@ -929,7 +929,7 @@ fn test<T: ApplyL>() {
929} 929}
930 930
931#[test] 931#[test]
932fn associated_type_placeholder_2() { 932fn associated_type_inlay_hints_2() {
933 check_types( 933 check_types(
934 r#" 934 r#"
935pub trait ApplyL { 935pub trait ApplyL {
@@ -946,6 +946,45 @@ fn test<T: ApplyL>(t: T) {
946} 946}
947 947
948#[test] 948#[test]
949fn associated_type_placeholder() {
950 check_types_source_code(
951 r#"
952pub trait ApplyL {
953 type Out;
954}
955
956pub struct RefMutL<T>;
957
958impl<T> ApplyL for RefMutL<T> {
959 type Out = <T as ApplyL>::Out;
960}
961
962fn test<T: ApplyL>() {
963 let y: <RefMutL<T> as ApplyL>::Out = no_matter;
964 y;
965} //^ ApplyL::Out<T>
966"#,
967 );
968}
969
970#[test]
971fn associated_type_placeholder_2() {
972 check_types_source_code(
973 r#"
974pub trait ApplyL {
975 type Out;
976}
977fn foo<T: ApplyL>(t: T) -> <T as ApplyL>::Out;
978
979fn test<T: ApplyL>(t: T) {
980 let y = foo(t);
981 y;
982} //^ ApplyL::Out<T>
983"#,
984 );
985}
986
987#[test]
949fn argument_impl_trait() { 988fn argument_impl_trait() {
950 check_infer_with_mismatches( 989 check_infer_with_mismatches(
951 r#" 990 r#"