aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir_ty/src/display.rs104
-rw-r--r--crates/hir_ty/src/tests.rs8
-rw-r--r--crates/hir_ty/src/tests/method_resolution.rs40
-rw-r--r--crates/hir_ty/src/tests/regression.rs8
-rw-r--r--crates/hir_ty/src/tests/traits.rs82
-rw-r--r--crates/ide/src/inlay_hints.rs21
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 @@
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, check_types_source_code}; 4use super::{check_infer, check_infer_with_mismatches, check_types};
5 5
6#[test] 6#[test]
7fn infer_await() { 7fn 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]
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]
988fn argument_impl_trait() { 949fn 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]
3194fn 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}