diff options
-rw-r--r-- | crates/hir_ty/src/display.rs | 104 | ||||
-rw-r--r-- | crates/hir_ty/src/tests.rs | 8 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/method_resolution.rs | 40 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/regression.rs | 8 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/traits.rs | 82 | ||||
-rw-r--r-- | crates/ide/src/inlay_hints.rs | 21 |
6 files changed, 108 insertions, 155 deletions
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index f1232a72f..ddfd8c8af 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -74,9 +74,29 @@ 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))] | ||
78 | display_target: DisplayTarget::SourceCode { module_id }, | 77 | display_target: DisplayTarget::SourceCode { module_id }, |
79 | #[cfg(test)] | 78 | }) { |
79 | Ok(()) => {} | ||
80 | Err(HirDisplayError::FmtError) => panic!("Writing to String can't fail!"), | ||
81 | Err(HirDisplayError::DisplaySourceCodeError(e)) => return Err(e), | ||
82 | }; | ||
83 | Ok(result) | ||
84 | } | ||
85 | |||
86 | /// Returns a String representation of `self` for test purposes | ||
87 | fn display_test<'a>( | ||
88 | &'a self, | ||
89 | db: &'a dyn HirDatabase, | ||
90 | module_id: ModuleId, | ||
91 | ) -> Result<String, DisplaySourceCodeError> { | ||
92 | let mut result = String::new(); | ||
93 | match self.hir_fmt(&mut HirFormatter { | ||
94 | db, | ||
95 | fmt: &mut result, | ||
96 | buf: String::with_capacity(20), | ||
97 | curr_size: 0, | ||
98 | max_size: None, | ||
99 | omit_verbose_types: false, | ||
80 | display_target: DisplayTarget::Test { module_id }, | 100 | display_target: DisplayTarget::Test { module_id }, |
81 | }) { | 101 | }) { |
82 | Ok(()) => {} | 102 | Ok(()) => {} |
@@ -138,7 +158,6 @@ enum DisplayTarget { | |||
138 | /// The generated code should compile, so paths need to be qualified. | 158 | /// The generated code should compile, so paths need to be qualified. |
139 | SourceCode { module_id: ModuleId }, | 159 | SourceCode { module_id: ModuleId }, |
140 | /// Only for test purpose to keep real types | 160 | /// Only for test purpose to keep real types |
141 | #[cfg(test)] | ||
142 | Test { module_id: ModuleId }, | 161 | Test { module_id: ModuleId }, |
143 | } | 162 | } |
144 | 163 | ||
@@ -147,14 +166,7 @@ impl DisplayTarget { | |||
147 | matches!(self, Self::SourceCode {..}) | 166 | matches!(self, Self::SourceCode {..}) |
148 | } | 167 | } |
149 | fn is_test(&self) -> bool { | 168 | fn is_test(&self) -> bool { |
150 | #[cfg(test)] | 169 | matches!(self, Self::Test {..}) |
151 | { | ||
152 | matches!(self, Self::Test {..}) | ||
153 | } | ||
154 | #[cfg(not(test))] | ||
155 | { | ||
156 | false | ||
157 | } | ||
158 | } | 170 | } |
159 | } | 171 | } |
160 | 172 | ||
@@ -344,21 +356,7 @@ impl HirDisplay for ApplicationTy { | |||
344 | }; | 356 | }; |
345 | write!(f, "{}", name)?; | 357 | write!(f, "{}", name)?; |
346 | } | 358 | } |
347 | DisplayTarget::SourceCode { module_id } => { | 359 | DisplayTarget::SourceCode { module_id } | DisplayTarget::Test { module_id } => { |
348 | if let Some(path) = find_path::find_path( | ||
349 | f.db.upcast(), | ||
350 | ItemInNs::Types(def_id.into()), | ||
351 | module_id, | ||
352 | ) { | ||
353 | write!(f, "{}", path)?; | ||
354 | } else { | ||
355 | return Err(HirDisplayError::DisplaySourceCodeError( | ||
356 | DisplaySourceCodeError::PathNotFound, | ||
357 | )); | ||
358 | } | ||
359 | } | ||
360 | #[cfg(test)] | ||
361 | DisplayTarget::Test { module_id } => { | ||
362 | if let Some(path) = find_path::find_path( | 360 | if let Some(path) = find_path::find_path( |
363 | f.db.upcast(), | 361 | f.db.upcast(), |
364 | ItemInNs::Types(def_id.into()), | 362 | ItemInNs::Types(def_id.into()), |
@@ -374,40 +372,38 @@ impl HirDisplay for ApplicationTy { | |||
374 | } | 372 | } |
375 | 373 | ||
376 | if self.parameters.len() > 0 { | 374 | if self.parameters.len() > 0 { |
377 | let parameters_to_write = if f.display_target.is_source_code() | 375 | let parameters_to_write = |
378 | || f.display_target.is_test() | 376 | if f.display_target.is_source_code() || f.omit_verbose_types() { |
379 | || f.omit_verbose_types() | 377 | match self |
380 | { | 378 | .ctor |
381 | match self | 379 | .as_generic_def() |
382 | .ctor | 380 | .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) |
383 | .as_generic_def() | 381 | .filter(|defaults| !defaults.is_empty()) |
384 | .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) | 382 | { |
385 | .filter(|defaults| !defaults.is_empty()) | 383 | None => self.parameters.0.as_ref(), |
386 | { | 384 | Some(default_parameters) => { |
387 | None => self.parameters.0.as_ref(), | 385 | let mut default_from = 0; |
388 | Some(default_parameters) => { | 386 | for (i, parameter) in self.parameters.iter().enumerate() { |
389 | let mut default_from = 0; | 387 | match (parameter, default_parameters.get(i)) { |
390 | for (i, parameter) in self.parameters.iter().enumerate() { | 388 | (&Ty::Unknown, _) | (_, None) => { |
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 { | ||
400 | default_from = i + 1; | 389 | default_from = i + 1; |
401 | } | 390 | } |
391 | (_, Some(default_parameter)) => { | ||
392 | let actual_default = default_parameter | ||
393 | .clone() | ||
394 | .subst(&self.parameters.prefix(i)); | ||
395 | if parameter != &actual_default { | ||
396 | default_from = i + 1; | ||
397 | } | ||
398 | } | ||
402 | } | 399 | } |
403 | } | 400 | } |
401 | &self.parameters.0[0..default_from] | ||
404 | } | 402 | } |
405 | &self.parameters.0[0..default_from] | ||
406 | } | 403 | } |
407 | } | 404 | } else { |
408 | } else { | 405 | self.parameters.0.as_ref() |
409 | self.parameters.0.as_ref() | 406 | }; |
410 | }; | ||
411 | if !parameters_to_write.is_empty() { | 407 | if !parameters_to_write.is_empty() { |
412 | write!(f, "<")?; | 408 | write!(f, "<")?; |
413 | f.write_joined(parameters_to_write, ", ")?; | 409 | f.write_joined(parameters_to_write, ", ")?; |
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs index 0445efc9e..510baadf2 100644 --- a/crates/hir_ty/src/tests.rs +++ b/crates/hir_ty/src/tests.rs | |||
@@ -157,13 +157,14 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { | |||
157 | (node.value.text_range(), node.value.text().to_string().replace("\n", " ")) | 157 | (node.value.text_range(), node.value.text().to_string().replace("\n", " ")) |
158 | }; | 158 | }; |
159 | let macro_prefix = if node.file_id != file_id.into() { "!" } else { "" }; | 159 | let macro_prefix = if node.file_id != file_id.into() { "!" } else { "" }; |
160 | let module = db.module_for_file(node.file_id.original_file(&db)); | ||
160 | format_to!( | 161 | format_to!( |
161 | buf, | 162 | buf, |
162 | "{}{:?} '{}': {}\n", | 163 | "{}{:?} '{}': {}\n", |
163 | macro_prefix, | 164 | macro_prefix, |
164 | range, | 165 | range, |
165 | ellipsize(text, 15), | 166 | ellipsize(text, 15), |
166 | ty.display(&db) | 167 | ty.display_test(&db, module).unwrap() |
167 | ); | 168 | ); |
168 | } | 169 | } |
169 | if include_mismatches { | 170 | if include_mismatches { |
@@ -174,13 +175,14 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { | |||
174 | for (src_ptr, mismatch) in &mismatches { | 175 | for (src_ptr, mismatch) in &mismatches { |
175 | let range = src_ptr.value.text_range(); | 176 | let range = src_ptr.value.text_range(); |
176 | let macro_prefix = if src_ptr.file_id != file_id.into() { "!" } else { "" }; | 177 | let macro_prefix = if src_ptr.file_id != file_id.into() { "!" } else { "" }; |
178 | let module = db.module_for_file(src_ptr.file_id.original_file(&db)); | ||
177 | format_to!( | 179 | format_to!( |
178 | buf, | 180 | buf, |
179 | "{}{:?}: expected {}, got {}\n", | 181 | "{}{:?}: expected {}, got {}\n", |
180 | macro_prefix, | 182 | macro_prefix, |
181 | range, | 183 | range, |
182 | mismatch.expected.display(&db), | 184 | mismatch.expected.display_test(&db, module).unwrap(), |
183 | mismatch.actual.display(&db), | 185 | mismatch.actual.display_test(&db, module).unwrap(), |
184 | ); | 186 | ); |
185 | } | 187 | } |
186 | } | 188 | } |
diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs index 0f17ff151..596d4f182 100644 --- a/crates/hir_ty/src/tests/method_resolution.rs +++ b/crates/hir_ty/src/tests/method_resolution.rs | |||
@@ -108,16 +108,16 @@ fn infer_associated_method_with_modules() { | |||
108 | check_infer( | 108 | check_infer( |
109 | r#" | 109 | r#" |
110 | mod a { | 110 | mod a { |
111 | struct A; | 111 | pub struct A; |
112 | impl A { pub fn thing() -> A { A {} }} | 112 | impl A { pub fn thing() -> A { A {} }} |
113 | } | 113 | } |
114 | 114 | ||
115 | mod b { | 115 | mod b { |
116 | struct B; | 116 | pub struct B; |
117 | impl B { pub fn thing() -> u32 { 99 }} | 117 | impl B { pub fn thing() -> u32 { 99 }} |
118 | 118 | ||
119 | mod c { | 119 | pub mod c { |
120 | struct C; | 120 | pub struct C; |
121 | impl C { pub fn thing() -> C { C {} }} | 121 | impl C { pub fn thing() -> C { C {} }} |
122 | } | 122 | } |
123 | } | 123 | } |
@@ -130,22 +130,22 @@ fn infer_associated_method_with_modules() { | |||
130 | } | 130 | } |
131 | "#, | 131 | "#, |
132 | expect![[r#" | 132 | expect![[r#" |
133 | 55..63 '{ A {} }': A | 133 | 59..67 '{ A {} }': a::A |
134 | 57..61 'A {}': A | 134 | 61..65 'A {}': a::A |
135 | 125..131 '{ 99 }': u32 | 135 | 133..139 '{ 99 }': u32 |
136 | 127..129 '99': u32 | 136 | 135..137 '99': u32 |
137 | 201..209 '{ C {} }': C | 137 | 217..225 '{ C {} }': c::C |
138 | 203..207 'C {}': C | 138 | 219..223 'C {}': c::C |
139 | 240..324 '{ ...g(); }': () | 139 | 256..340 '{ ...g(); }': () |
140 | 250..251 'x': A | 140 | 266..267 'x': a::A |
141 | 254..265 'a::A::thing': fn thing() -> A | 141 | 270..281 'a::A::thing': fn thing() -> A |
142 | 254..267 'a::A::thing()': A | 142 | 270..283 'a::A::thing()': a::A |
143 | 277..278 'y': u32 | 143 | 293..294 'y': u32 |
144 | 281..292 'b::B::thing': fn thing() -> u32 | 144 | 297..308 'b::B::thing': fn thing() -> u32 |
145 | 281..294 'b::B::thing()': u32 | 145 | 297..310 'b::B::thing()': u32 |
146 | 304..305 'z': C | 146 | 320..321 'z': c::C |
147 | 308..319 'c::C::thing': fn thing() -> C | 147 | 324..335 'c::C::thing': fn thing() -> C |
148 | 308..321 'c::C::thing()': C | 148 | 324..337 'c::C::thing()': c::C |
149 | "#]], | 149 | "#]], |
150 | ); | 150 | ); |
151 | } | 151 | } |
diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs index 66e171f24..42d08f12c 100644 --- a/crates/hir_ty/src/tests/regression.rs +++ b/crates/hir_ty/src/tests/regression.rs | |||
@@ -831,11 +831,11 @@ fn issue_4966() { | |||
831 | 356..362 'repeat': Repeat<Map<|&f64| -> f64>> | 831 | 356..362 'repeat': Repeat<Map<|&f64| -> f64>> |
832 | 365..390 'Repeat...nner }': Repeat<Map<|&f64| -> f64>> | 832 | 365..390 'Repeat...nner }': Repeat<Map<|&f64| -> f64>> |
833 | 383..388 'inner': Map<|&f64| -> f64> | 833 | 383..388 'inner': Map<|&f64| -> f64> |
834 | 401..404 'vec': Vec<<Repeat<Map<|&f64| -> f64>> as IntoIterator>::Item> | 834 | 401..404 'vec': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>> |
835 | 407..416 'from_iter': fn from_iter<<Repeat<Map<|&f64| -> f64>> as IntoIterator>::Item, Repeat<Map<|&f64| -> f64>>>(Repeat<Map<|&f64| -> f64>>) -> Vec<<Repeat<Map<|&f64| -> f64>> as IntoIterator>::Item> | 835 | 407..416 'from_iter': fn from_iter<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>, Repeat<Map<|&f64| -> f64>>>(Repeat<Map<|&f64| -> f64>>) -> Vec<<Repeat<Map<|&f64| -> f64>> as IntoIterator>::Item> |
836 | 407..424 'from_i...epeat)': Vec<<Repeat<Map<|&f64| -> f64>> as IntoIterator>::Item> | 836 | 407..424 'from_i...epeat)': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>> |
837 | 417..423 'repeat': Repeat<Map<|&f64| -> f64>> | 837 | 417..423 'repeat': Repeat<Map<|&f64| -> f64>> |
838 | 431..434 'vec': Vec<<Repeat<Map<|&f64| -> f64>> as IntoIterator>::Item> | 838 | 431..434 'vec': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>> |
839 | 431..444 'vec.foo_bar()': {unknown} | 839 | 431..444 'vec.foo_bar()': {unknown} |
840 | "#]], | 840 | "#]], |
841 | ); | 841 | ); |
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index e98d7c064..4d193dea9 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, check_types_source_code}; | 4 | use super::{check_infer, check_infer_with_mismatches, check_types}; |
5 | 5 | ||
6 | #[test] | 6 | #[test] |
7 | fn infer_await() { | 7 | fn infer_await() { |
@@ -384,12 +384,12 @@ fn infer_project_associated_type() { | |||
384 | 108..261 '{ ...ter; }': () | 384 | 108..261 '{ ...ter; }': () |
385 | 118..119 'x': u32 | 385 | 118..119 'x': u32 |
386 | 145..146 '1': u32 | 386 | 145..146 '1': u32 |
387 | 156..157 'y': <T as Iterable>::Item | 387 | 156..157 'y': Iterable::Item<T> |
388 | 183..192 'no_matter': <T as Iterable>::Item | 388 | 183..192 'no_matter': Iterable::Item<T> |
389 | 202..203 'z': <T as Iterable>::Item | 389 | 202..203 'z': Iterable::Item<T> |
390 | 215..224 'no_matter': <T as Iterable>::Item | 390 | 215..224 'no_matter': Iterable::Item<T> |
391 | 234..235 'a': <T as Iterable>::Item | 391 | 234..235 'a': Iterable::Item<T> |
392 | 249..258 'no_matter': <T as Iterable>::Item | 392 | 249..258 'no_matter': Iterable::Item<T> |
393 | "#]], | 393 | "#]], |
394 | ); | 394 | ); |
395 | } | 395 | } |
@@ -946,45 +946,6 @@ 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] | ||
988 | fn argument_impl_trait() { | 949 | fn argument_impl_trait() { |
989 | check_infer_with_mismatches( | 950 | check_infer_with_mismatches( |
990 | r#" | 951 | r#" |
@@ -2158,7 +2119,7 @@ fn unselected_projection_on_impl_self() { | |||
2158 | "#, | 2119 | "#, |
2159 | expect![[r#" | 2120 | expect![[r#" |
2160 | 40..44 'self': &Self | 2121 | 40..44 'self': &Self |
2161 | 46..47 'x': <Self as Trait>::Item | 2122 | 46..47 'x': Trait::Item<Self> |
2162 | 126..130 'self': &S | 2123 | 126..130 'self': &S |
2163 | 132..133 'x': u32 | 2124 | 132..133 'x': u32 |
2164 | 147..161 '{ let y = x; }': () | 2125 | 147..161 '{ let y = x; }': () |
@@ -3189,30 +3150,3 @@ fn test() { | |||
3189 | "#, | 3150 | "#, |
3190 | ); | 3151 | ); |
3191 | } | 3152 | } |
3192 | |||
3193 | #[test] | ||
3194 | fn infer_call_method_return_associated_types_with_generic() { | ||
3195 | check_infer( | ||
3196 | r#" | ||
3197 | pub trait Default { | ||
3198 | fn default() -> Self; | ||
3199 | } | ||
3200 | pub trait Foo { | ||
3201 | type Bar: Default; | ||
3202 | } | ||
3203 | |||
3204 | pub fn quux<T: Foo>() -> T::Bar { | ||
3205 | let y = Default::default(); | ||
3206 | |||
3207 | y | ||
3208 | } | ||
3209 | "#, | ||
3210 | expect![[r#" | ||
3211 | 122..164 '{ ... y }': <T as Foo>::Bar | ||
3212 | 132..133 'y': <T as Foo>::Bar | ||
3213 | 136..152 'Defaul...efault': fn default<<T as Foo>::Bar>() -> <T as Foo>::Bar | ||
3214 | 136..154 'Defaul...ault()': <T as Foo>::Bar | ||
3215 | 161..162 'y': <T as Foo>::Bar | ||
3216 | "#]], | ||
3217 | ); | ||
3218 | } | ||
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 | } |