diff options
-rw-r--r-- | crates/hir_ty/src/display.rs | 88 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/traits.rs | 45 |
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 | ||
139 | impl DisplayTarget { | 145 | impl 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 @@ | |||
1 | use expect_test::expect; | 1 | use expect_test::expect; |
2 | use test_utils::mark; | 2 | use test_utils::mark; |
3 | 3 | ||
4 | use super::{check_infer, check_infer_with_mismatches, check_types}; | 4 | use super::{check_infer, check_infer_with_mismatches, check_types, check_types_source_code}; |
5 | 5 | ||
6 | #[test] | 6 | #[test] |
7 | fn infer_await() { | 7 | fn infer_await() { |
@@ -907,7 +907,7 @@ fn test<T: Trait>(t: T) { (*t); } | |||
907 | } | 907 | } |
908 | 908 | ||
909 | #[test] | 909 | #[test] |
910 | fn associated_type_placeholder() { | 910 | fn associated_type_inlay_hints() { |
911 | check_types( | 911 | check_types( |
912 | r#" | 912 | r#" |
913 | pub trait ApplyL { | 913 | pub trait ApplyL { |
@@ -929,7 +929,7 @@ fn test<T: ApplyL>() { | |||
929 | } | 929 | } |
930 | 930 | ||
931 | #[test] | 931 | #[test] |
932 | fn associated_type_placeholder_2() { | 932 | fn associated_type_inlay_hints_2() { |
933 | check_types( | 933 | check_types( |
934 | r#" | 934 | r#" |
935 | pub trait ApplyL { | 935 | pub trait ApplyL { |
@@ -946,6 +946,45 @@ fn test<T: ApplyL>(t: T) { | |||
946 | } | 946 | } |
947 | 947 | ||
948 | #[test] | 948 | #[test] |
949 | fn associated_type_placeholder() { | ||
950 | check_types_source_code( | ||
951 | r#" | ||
952 | pub trait ApplyL { | ||
953 | type Out; | ||
954 | } | ||
955 | |||
956 | pub struct RefMutL<T>; | ||
957 | |||
958 | impl<T> ApplyL for RefMutL<T> { | ||
959 | type Out = <T as ApplyL>::Out; | ||
960 | } | ||
961 | |||
962 | fn 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] | ||
971 | fn associated_type_placeholder_2() { | ||
972 | check_types_source_code( | ||
973 | r#" | ||
974 | pub trait ApplyL { | ||
975 | type Out; | ||
976 | } | ||
977 | fn foo<T: ApplyL>(t: T) -> <T as ApplyL>::Out; | ||
978 | |||
979 | fn test<T: ApplyL>(t: T) { | ||
980 | let y = foo(t); | ||
981 | y; | ||
982 | } //^ ApplyL::Out<T> | ||
983 | "#, | ||
984 | ); | ||
985 | } | ||
986 | |||
987 | #[test] | ||
949 | fn argument_impl_trait() { | 988 | fn argument_impl_trait() { |
950 | check_infer_with_mismatches( | 989 | check_infer_with_mismatches( |
951 | r#" | 990 | r#" |