diff options
Diffstat (limited to 'crates/ra_hir_ty/src/tests')
-rw-r--r-- | crates/ra_hir_ty/src/tests/coercion.rs | 861 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/display_source_code.rs | 41 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/macros.rs | 787 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/method_resolution.rs | 1053 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/never_type.rs | 409 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/patterns.rs | 656 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/regression.rs | 842 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/simple.rs | 2190 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/traits.rs | 3113 |
9 files changed, 0 insertions, 9952 deletions
diff --git a/crates/ra_hir_ty/src/tests/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs deleted file mode 100644 index 17efd75cb..000000000 --- a/crates/ra_hir_ty/src/tests/coercion.rs +++ /dev/null | |||
@@ -1,861 +0,0 @@ | |||
1 | use expect::expect; | ||
2 | use test_utils::mark; | ||
3 | |||
4 | use super::{check_infer, check_infer_with_mismatches}; | ||
5 | |||
6 | #[test] | ||
7 | fn infer_block_expr_type_mismatch() { | ||
8 | check_infer( | ||
9 | r" | ||
10 | fn test() { | ||
11 | let a: i32 = { 1i64 }; | ||
12 | } | ||
13 | ", | ||
14 | expect![[r" | ||
15 | 10..40 '{ ...4 }; }': () | ||
16 | 20..21 'a': i32 | ||
17 | 29..37 '{ 1i64 }': i64 | ||
18 | 31..35 '1i64': i64 | ||
19 | "]], | ||
20 | ); | ||
21 | } | ||
22 | |||
23 | #[test] | ||
24 | fn coerce_places() { | ||
25 | check_infer( | ||
26 | r#" | ||
27 | struct S<T> { a: T } | ||
28 | |||
29 | fn f<T>(_: &[T]) -> T { loop {} } | ||
30 | fn g<T>(_: S<&[T]>) -> T { loop {} } | ||
31 | |||
32 | fn gen<T>() -> *mut [T; 2] { loop {} } | ||
33 | fn test1<U>() -> *mut [U] { | ||
34 | gen() | ||
35 | } | ||
36 | |||
37 | fn test2() { | ||
38 | let arr: &[u8; 1] = &[1]; | ||
39 | |||
40 | let a: &[_] = arr; | ||
41 | let b = f(arr); | ||
42 | let c: &[_] = { arr }; | ||
43 | let d = g(S { a: arr }); | ||
44 | let e: [&[_]; 1] = [arr]; | ||
45 | let f: [&[_]; 2] = [arr; 2]; | ||
46 | let g: (&[_], &[_]) = (arr, arr); | ||
47 | } | ||
48 | |||
49 | #[lang = "sized"] | ||
50 | pub trait Sized {} | ||
51 | #[lang = "unsize"] | ||
52 | pub trait Unsize<T: ?Sized> {} | ||
53 | #[lang = "coerce_unsized"] | ||
54 | pub trait CoerceUnsized<T> {} | ||
55 | |||
56 | impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} | ||
57 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} | ||
58 | "#, | ||
59 | expect![[r" | ||
60 | 30..31 '_': &[T] | ||
61 | 44..55 '{ loop {} }': T | ||
62 | 46..53 'loop {}': ! | ||
63 | 51..53 '{}': () | ||
64 | 64..65 '_': S<&[T]> | ||
65 | 81..92 '{ loop {} }': T | ||
66 | 83..90 'loop {}': ! | ||
67 | 88..90 '{}': () | ||
68 | 121..132 '{ loop {} }': *mut [T; _] | ||
69 | 123..130 'loop {}': ! | ||
70 | 128..130 '{}': () | ||
71 | 159..172 '{ gen() }': *mut [U] | ||
72 | 165..168 'gen': fn gen<U>() -> *mut [U; _] | ||
73 | 165..170 'gen()': *mut [U; _] | ||
74 | 185..419 '{ ...rr); }': () | ||
75 | 195..198 'arr': &[u8; _] | ||
76 | 211..215 '&[1]': &[u8; _] | ||
77 | 212..215 '[1]': [u8; _] | ||
78 | 213..214 '1': u8 | ||
79 | 226..227 'a': &[u8] | ||
80 | 236..239 'arr': &[u8; _] | ||
81 | 249..250 'b': u8 | ||
82 | 253..254 'f': fn f<u8>(&[u8]) -> u8 | ||
83 | 253..259 'f(arr)': u8 | ||
84 | 255..258 'arr': &[u8; _] | ||
85 | 269..270 'c': &[u8] | ||
86 | 279..286 '{ arr }': &[u8] | ||
87 | 281..284 'arr': &[u8; _] | ||
88 | 296..297 'd': u8 | ||
89 | 300..301 'g': fn g<u8>(S<&[u8]>) -> u8 | ||
90 | 300..315 'g(S { a: arr })': u8 | ||
91 | 302..314 'S { a: arr }': S<&[u8]> | ||
92 | 309..312 'arr': &[u8; _] | ||
93 | 325..326 'e': [&[u8]; _] | ||
94 | 340..345 '[arr]': [&[u8]; _] | ||
95 | 341..344 'arr': &[u8; _] | ||
96 | 355..356 'f': [&[u8]; _] | ||
97 | 370..378 '[arr; 2]': [&[u8]; _] | ||
98 | 371..374 'arr': &[u8; _] | ||
99 | 376..377 '2': usize | ||
100 | 388..389 'g': (&[u8], &[u8]) | ||
101 | 406..416 '(arr, arr)': (&[u8], &[u8]) | ||
102 | 407..410 'arr': &[u8; _] | ||
103 | 412..415 'arr': &[u8; _] | ||
104 | "]], | ||
105 | ); | ||
106 | } | ||
107 | |||
108 | #[test] | ||
109 | fn infer_let_stmt_coerce() { | ||
110 | check_infer( | ||
111 | r" | ||
112 | fn test() { | ||
113 | let x: &[isize] = &[1]; | ||
114 | let x: *const [isize] = &[1]; | ||
115 | } | ||
116 | ", | ||
117 | expect![[r" | ||
118 | 10..75 '{ ...[1]; }': () | ||
119 | 20..21 'x': &[isize] | ||
120 | 34..38 '&[1]': &[isize; _] | ||
121 | 35..38 '[1]': [isize; _] | ||
122 | 36..37 '1': isize | ||
123 | 48..49 'x': *const [isize] | ||
124 | 68..72 '&[1]': &[isize; _] | ||
125 | 69..72 '[1]': [isize; _] | ||
126 | 70..71 '1': isize | ||
127 | "]], | ||
128 | ); | ||
129 | } | ||
130 | |||
131 | #[test] | ||
132 | fn infer_custom_coerce_unsized() { | ||
133 | check_infer( | ||
134 | r#" | ||
135 | struct A<T: ?Sized>(*const T); | ||
136 | struct B<T: ?Sized>(*const T); | ||
137 | struct C<T: ?Sized> { inner: *const T } | ||
138 | |||
139 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<B<U>> for B<T> {} | ||
140 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<C<U>> for C<T> {} | ||
141 | |||
142 | fn foo1<T>(x: A<[T]>) -> A<[T]> { x } | ||
143 | fn foo2<T>(x: B<[T]>) -> B<[T]> { x } | ||
144 | fn foo3<T>(x: C<[T]>) -> C<[T]> { x } | ||
145 | |||
146 | fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) { | ||
147 | let d = foo1(a); | ||
148 | let e = foo2(b); | ||
149 | let f = foo3(c); | ||
150 | } | ||
151 | |||
152 | |||
153 | #[lang = "sized"] | ||
154 | pub trait Sized {} | ||
155 | #[lang = "unsize"] | ||
156 | pub trait Unsize<T: ?Sized> {} | ||
157 | #[lang = "coerce_unsized"] | ||
158 | pub trait CoerceUnsized<T> {} | ||
159 | |||
160 | impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} | ||
161 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} | ||
162 | "#, | ||
163 | expect![[r" | ||
164 | 257..258 'x': A<[T]> | ||
165 | 278..283 '{ x }': A<[T]> | ||
166 | 280..281 'x': A<[T]> | ||
167 | 295..296 'x': B<[T]> | ||
168 | 316..321 '{ x }': B<[T]> | ||
169 | 318..319 'x': B<[T]> | ||
170 | 333..334 'x': C<[T]> | ||
171 | 354..359 '{ x }': C<[T]> | ||
172 | 356..357 'x': C<[T]> | ||
173 | 369..370 'a': A<[u8; _]> | ||
174 | 384..385 'b': B<[u8; _]> | ||
175 | 399..400 'c': C<[u8; _]> | ||
176 | 414..480 '{ ...(c); }': () | ||
177 | 424..425 'd': A<[{unknown}]> | ||
178 | 428..432 'foo1': fn foo1<{unknown}>(A<[{unknown}]>) -> A<[{unknown}]> | ||
179 | 428..435 'foo1(a)': A<[{unknown}]> | ||
180 | 433..434 'a': A<[u8; _]> | ||
181 | 445..446 'e': B<[u8]> | ||
182 | 449..453 'foo2': fn foo2<u8>(B<[u8]>) -> B<[u8]> | ||
183 | 449..456 'foo2(b)': B<[u8]> | ||
184 | 454..455 'b': B<[u8; _]> | ||
185 | 466..467 'f': C<[u8]> | ||
186 | 470..474 'foo3': fn foo3<u8>(C<[u8]>) -> C<[u8]> | ||
187 | 470..477 'foo3(c)': C<[u8]> | ||
188 | 475..476 'c': C<[u8; _]> | ||
189 | "]], | ||
190 | ); | ||
191 | } | ||
192 | |||
193 | #[test] | ||
194 | fn infer_if_coerce() { | ||
195 | check_infer( | ||
196 | r#" | ||
197 | fn foo<T>(x: &[T]) -> &[T] { loop {} } | ||
198 | fn test() { | ||
199 | let x = if true { | ||
200 | foo(&[1]) | ||
201 | } else { | ||
202 | &[1] | ||
203 | }; | ||
204 | } | ||
205 | |||
206 | |||
207 | #[lang = "sized"] | ||
208 | pub trait Sized {} | ||
209 | #[lang = "unsize"] | ||
210 | pub trait Unsize<T: ?Sized> {} | ||
211 | "#, | ||
212 | expect![[r" | ||
213 | 10..11 'x': &[T] | ||
214 | 27..38 '{ loop {} }': &[T] | ||
215 | 29..36 'loop {}': ! | ||
216 | 34..36 '{}': () | ||
217 | 49..125 '{ ... }; }': () | ||
218 | 59..60 'x': &[i32] | ||
219 | 63..122 'if tru... }': &[i32] | ||
220 | 66..70 'true': bool | ||
221 | 71..96 '{ ... }': &[i32] | ||
222 | 81..84 'foo': fn foo<i32>(&[i32]) -> &[i32] | ||
223 | 81..90 'foo(&[1])': &[i32] | ||
224 | 85..89 '&[1]': &[i32; _] | ||
225 | 86..89 '[1]': [i32; _] | ||
226 | 87..88 '1': i32 | ||
227 | 102..122 '{ ... }': &[i32; _] | ||
228 | 112..116 '&[1]': &[i32; _] | ||
229 | 113..116 '[1]': [i32; _] | ||
230 | 114..115 '1': i32 | ||
231 | "]], | ||
232 | ); | ||
233 | } | ||
234 | |||
235 | #[test] | ||
236 | fn infer_if_else_coerce() { | ||
237 | check_infer( | ||
238 | r#" | ||
239 | fn foo<T>(x: &[T]) -> &[T] { loop {} } | ||
240 | fn test() { | ||
241 | let x = if true { | ||
242 | &[1] | ||
243 | } else { | ||
244 | foo(&[1]) | ||
245 | }; | ||
246 | } | ||
247 | |||
248 | #[lang = "sized"] | ||
249 | pub trait Sized {} | ||
250 | #[lang = "unsize"] | ||
251 | pub trait Unsize<T: ?Sized> {} | ||
252 | #[lang = "coerce_unsized"] | ||
253 | pub trait CoerceUnsized<T> {} | ||
254 | |||
255 | impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} | ||
256 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} | ||
257 | "#, | ||
258 | expect![[r" | ||
259 | 10..11 'x': &[T] | ||
260 | 27..38 '{ loop {} }': &[T] | ||
261 | 29..36 'loop {}': ! | ||
262 | 34..36 '{}': () | ||
263 | 49..125 '{ ... }; }': () | ||
264 | 59..60 'x': &[i32] | ||
265 | 63..122 'if tru... }': &[i32] | ||
266 | 66..70 'true': bool | ||
267 | 71..91 '{ ... }': &[i32; _] | ||
268 | 81..85 '&[1]': &[i32; _] | ||
269 | 82..85 '[1]': [i32; _] | ||
270 | 83..84 '1': i32 | ||
271 | 97..122 '{ ... }': &[i32] | ||
272 | 107..110 'foo': fn foo<i32>(&[i32]) -> &[i32] | ||
273 | 107..116 'foo(&[1])': &[i32] | ||
274 | 111..115 '&[1]': &[i32; _] | ||
275 | 112..115 '[1]': [i32; _] | ||
276 | 113..114 '1': i32 | ||
277 | "]], | ||
278 | ) | ||
279 | } | ||
280 | |||
281 | #[test] | ||
282 | fn infer_match_first_coerce() { | ||
283 | check_infer( | ||
284 | r#" | ||
285 | fn foo<T>(x: &[T]) -> &[T] { loop {} } | ||
286 | fn test(i: i32) { | ||
287 | let x = match i { | ||
288 | 2 => foo(&[2]), | ||
289 | 1 => &[1], | ||
290 | _ => &[3], | ||
291 | }; | ||
292 | } | ||
293 | |||
294 | #[lang = "sized"] | ||
295 | pub trait Sized {} | ||
296 | #[lang = "unsize"] | ||
297 | pub trait Unsize<T: ?Sized> {} | ||
298 | "#, | ||
299 | expect![[r" | ||
300 | 10..11 'x': &[T] | ||
301 | 27..38 '{ loop {} }': &[T] | ||
302 | 29..36 'loop {}': ! | ||
303 | 34..36 '{}': () | ||
304 | 47..48 'i': i32 | ||
305 | 55..149 '{ ... }; }': () | ||
306 | 65..66 'x': &[i32] | ||
307 | 69..146 'match ... }': &[i32] | ||
308 | 75..76 'i': i32 | ||
309 | 87..88 '2': i32 | ||
310 | 87..88 '2': i32 | ||
311 | 92..95 'foo': fn foo<i32>(&[i32]) -> &[i32] | ||
312 | 92..101 'foo(&[2])': &[i32] | ||
313 | 96..100 '&[2]': &[i32; _] | ||
314 | 97..100 '[2]': [i32; _] | ||
315 | 98..99 '2': i32 | ||
316 | 111..112 '1': i32 | ||
317 | 111..112 '1': i32 | ||
318 | 116..120 '&[1]': &[i32; _] | ||
319 | 117..120 '[1]': [i32; _] | ||
320 | 118..119 '1': i32 | ||
321 | 130..131 '_': i32 | ||
322 | 135..139 '&[3]': &[i32; _] | ||
323 | 136..139 '[3]': [i32; _] | ||
324 | 137..138 '3': i32 | ||
325 | "]], | ||
326 | ); | ||
327 | } | ||
328 | |||
329 | #[test] | ||
330 | fn infer_match_second_coerce() { | ||
331 | check_infer( | ||
332 | r#" | ||
333 | fn foo<T>(x: &[T]) -> &[T] { loop {} } | ||
334 | fn test(i: i32) { | ||
335 | let x = match i { | ||
336 | 1 => &[1], | ||
337 | 2 => foo(&[2]), | ||
338 | _ => &[3], | ||
339 | }; | ||
340 | } | ||
341 | |||
342 | #[lang = "sized"] | ||
343 | pub trait Sized {} | ||
344 | #[lang = "unsize"] | ||
345 | pub trait Unsize<T: ?Sized> {} | ||
346 | #[lang = "coerce_unsized"] | ||
347 | pub trait CoerceUnsized<T> {} | ||
348 | |||
349 | impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} | ||
350 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} | ||
351 | "#, | ||
352 | expect![[r" | ||
353 | 10..11 'x': &[T] | ||
354 | 27..38 '{ loop {} }': &[T] | ||
355 | 29..36 'loop {}': ! | ||
356 | 34..36 '{}': () | ||
357 | 47..48 'i': i32 | ||
358 | 55..149 '{ ... }; }': () | ||
359 | 65..66 'x': &[i32] | ||
360 | 69..146 'match ... }': &[i32] | ||
361 | 75..76 'i': i32 | ||
362 | 87..88 '1': i32 | ||
363 | 87..88 '1': i32 | ||
364 | 92..96 '&[1]': &[i32; _] | ||
365 | 93..96 '[1]': [i32; _] | ||
366 | 94..95 '1': i32 | ||
367 | 106..107 '2': i32 | ||
368 | 106..107 '2': i32 | ||
369 | 111..114 'foo': fn foo<i32>(&[i32]) -> &[i32] | ||
370 | 111..120 'foo(&[2])': &[i32] | ||
371 | 115..119 '&[2]': &[i32; _] | ||
372 | 116..119 '[2]': [i32; _] | ||
373 | 117..118 '2': i32 | ||
374 | 130..131 '_': i32 | ||
375 | 135..139 '&[3]': &[i32; _] | ||
376 | 136..139 '[3]': [i32; _] | ||
377 | 137..138 '3': i32 | ||
378 | "]], | ||
379 | ); | ||
380 | } | ||
381 | |||
382 | #[test] | ||
383 | fn coerce_merge_one_by_one1() { | ||
384 | mark::check!(coerce_merge_fail_fallback); | ||
385 | |||
386 | check_infer( | ||
387 | r" | ||
388 | fn test() { | ||
389 | let t = &mut 1; | ||
390 | let x = match 1 { | ||
391 | 1 => t as *mut i32, | ||
392 | 2 => t as &i32, | ||
393 | _ => t as *const i32, | ||
394 | }; | ||
395 | } | ||
396 | ", | ||
397 | expect![[r" | ||
398 | 10..144 '{ ... }; }': () | ||
399 | 20..21 't': &mut i32 | ||
400 | 24..30 '&mut 1': &mut i32 | ||
401 | 29..30 '1': i32 | ||
402 | 40..41 'x': *const i32 | ||
403 | 44..141 'match ... }': *const i32 | ||
404 | 50..51 '1': i32 | ||
405 | 62..63 '1': i32 | ||
406 | 62..63 '1': i32 | ||
407 | 67..68 't': &mut i32 | ||
408 | 67..80 't as *mut i32': *mut i32 | ||
409 | 90..91 '2': i32 | ||
410 | 90..91 '2': i32 | ||
411 | 95..96 't': &mut i32 | ||
412 | 95..104 't as &i32': &i32 | ||
413 | 114..115 '_': i32 | ||
414 | 119..120 't': &mut i32 | ||
415 | 119..134 't as *const i32': *const i32 | ||
416 | "]], | ||
417 | ); | ||
418 | } | ||
419 | |||
420 | #[test] | ||
421 | fn return_coerce_unknown() { | ||
422 | check_infer_with_mismatches( | ||
423 | r" | ||
424 | fn foo() -> u32 { | ||
425 | return unknown; | ||
426 | } | ||
427 | ", | ||
428 | expect![[r" | ||
429 | 16..39 '{ ...own; }': u32 | ||
430 | 22..36 'return unknown': ! | ||
431 | 29..36 'unknown': u32 | ||
432 | "]], | ||
433 | ); | ||
434 | } | ||
435 | |||
436 | #[test] | ||
437 | fn coerce_autoderef() { | ||
438 | check_infer_with_mismatches( | ||
439 | r" | ||
440 | struct Foo; | ||
441 | fn takes_ref_foo(x: &Foo) {} | ||
442 | fn test() { | ||
443 | takes_ref_foo(&Foo); | ||
444 | takes_ref_foo(&&Foo); | ||
445 | takes_ref_foo(&&&Foo); | ||
446 | } | ||
447 | ", | ||
448 | expect![[r" | ||
449 | 29..30 'x': &Foo | ||
450 | 38..40 '{}': () | ||
451 | 51..132 '{ ...oo); }': () | ||
452 | 57..70 'takes_ref_foo': fn takes_ref_foo(&Foo) | ||
453 | 57..76 'takes_...(&Foo)': () | ||
454 | 71..75 '&Foo': &Foo | ||
455 | 72..75 'Foo': Foo | ||
456 | 82..95 'takes_ref_foo': fn takes_ref_foo(&Foo) | ||
457 | 82..102 'takes_...&&Foo)': () | ||
458 | 96..101 '&&Foo': &&Foo | ||
459 | 97..101 '&Foo': &Foo | ||
460 | 98..101 'Foo': Foo | ||
461 | 108..121 'takes_ref_foo': fn takes_ref_foo(&Foo) | ||
462 | 108..129 'takes_...&&Foo)': () | ||
463 | 122..128 '&&&Foo': &&&Foo | ||
464 | 123..128 '&&Foo': &&Foo | ||
465 | 124..128 '&Foo': &Foo | ||
466 | 125..128 'Foo': Foo | ||
467 | "]], | ||
468 | ); | ||
469 | } | ||
470 | |||
471 | #[test] | ||
472 | fn coerce_autoderef_generic() { | ||
473 | check_infer_with_mismatches( | ||
474 | r" | ||
475 | struct Foo; | ||
476 | fn takes_ref<T>(x: &T) -> T { *x } | ||
477 | fn test() { | ||
478 | takes_ref(&Foo); | ||
479 | takes_ref(&&Foo); | ||
480 | takes_ref(&&&Foo); | ||
481 | } | ||
482 | ", | ||
483 | expect![[r" | ||
484 | 28..29 'x': &T | ||
485 | 40..46 '{ *x }': T | ||
486 | 42..44 '*x': T | ||
487 | 43..44 'x': &T | ||
488 | 57..126 '{ ...oo); }': () | ||
489 | 63..72 'takes_ref': fn takes_ref<Foo>(&Foo) -> Foo | ||
490 | 63..78 'takes_ref(&Foo)': Foo | ||
491 | 73..77 '&Foo': &Foo | ||
492 | 74..77 'Foo': Foo | ||
493 | 84..93 'takes_ref': fn takes_ref<&Foo>(&&Foo) -> &Foo | ||
494 | 84..100 'takes_...&&Foo)': &Foo | ||
495 | 94..99 '&&Foo': &&Foo | ||
496 | 95..99 '&Foo': &Foo | ||
497 | 96..99 'Foo': Foo | ||
498 | 106..115 'takes_ref': fn takes_ref<&&Foo>(&&&Foo) -> &&Foo | ||
499 | 106..123 'takes_...&&Foo)': &&Foo | ||
500 | 116..122 '&&&Foo': &&&Foo | ||
501 | 117..122 '&&Foo': &&Foo | ||
502 | 118..122 '&Foo': &Foo | ||
503 | 119..122 'Foo': Foo | ||
504 | "]], | ||
505 | ); | ||
506 | } | ||
507 | |||
508 | #[test] | ||
509 | fn coerce_autoderef_block() { | ||
510 | check_infer_with_mismatches( | ||
511 | r#" | ||
512 | struct String {} | ||
513 | #[lang = "deref"] | ||
514 | trait Deref { type Target; } | ||
515 | impl Deref for String { type Target = str; } | ||
516 | fn takes_ref_str(x: &str) {} | ||
517 | fn returns_string() -> String { loop {} } | ||
518 | fn test() { | ||
519 | takes_ref_str(&{ returns_string() }); | ||
520 | } | ||
521 | "#, | ||
522 | expect![[r" | ||
523 | 126..127 'x': &str | ||
524 | 135..137 '{}': () | ||
525 | 168..179 '{ loop {} }': String | ||
526 | 170..177 'loop {}': ! | ||
527 | 175..177 '{}': () | ||
528 | 190..235 '{ ... }); }': () | ||
529 | 196..209 'takes_ref_str': fn takes_ref_str(&str) | ||
530 | 196..232 'takes_...g() })': () | ||
531 | 210..231 '&{ ret...ng() }': &String | ||
532 | 211..231 '{ retu...ng() }': String | ||
533 | 213..227 'returns_string': fn returns_string() -> String | ||
534 | 213..229 'return...ring()': String | ||
535 | "]], | ||
536 | ); | ||
537 | } | ||
538 | |||
539 | #[test] | ||
540 | fn closure_return_coerce() { | ||
541 | check_infer_with_mismatches( | ||
542 | r" | ||
543 | fn foo() { | ||
544 | let x = || { | ||
545 | if true { | ||
546 | return &1u32; | ||
547 | } | ||
548 | &&1u32 | ||
549 | }; | ||
550 | } | ||
551 | ", | ||
552 | expect![[r" | ||
553 | 9..105 '{ ... }; }': () | ||
554 | 19..20 'x': || -> &u32 | ||
555 | 23..102 '|| { ... }': || -> &u32 | ||
556 | 26..102 '{ ... }': &u32 | ||
557 | 36..81 'if tru... }': () | ||
558 | 39..43 'true': bool | ||
559 | 44..81 '{ ... }': () | ||
560 | 58..70 'return &1u32': ! | ||
561 | 65..70 '&1u32': &u32 | ||
562 | 66..70 '1u32': u32 | ||
563 | 90..96 '&&1u32': &&u32 | ||
564 | 91..96 '&1u32': &u32 | ||
565 | 92..96 '1u32': u32 | ||
566 | "]], | ||
567 | ); | ||
568 | } | ||
569 | |||
570 | #[test] | ||
571 | fn coerce_fn_item_to_fn_ptr() { | ||
572 | check_infer_with_mismatches( | ||
573 | r" | ||
574 | fn foo(x: u32) -> isize { 1 } | ||
575 | fn test() { | ||
576 | let f: fn(u32) -> isize = foo; | ||
577 | } | ||
578 | ", | ||
579 | expect![[r" | ||
580 | 7..8 'x': u32 | ||
581 | 24..29 '{ 1 }': isize | ||
582 | 26..27 '1': isize | ||
583 | 40..78 '{ ...foo; }': () | ||
584 | 50..51 'f': fn(u32) -> isize | ||
585 | 72..75 'foo': fn foo(u32) -> isize | ||
586 | "]], | ||
587 | ); | ||
588 | } | ||
589 | |||
590 | #[test] | ||
591 | fn coerce_fn_items_in_match_arms() { | ||
592 | mark::check!(coerce_fn_reification); | ||
593 | |||
594 | check_infer_with_mismatches( | ||
595 | r" | ||
596 | fn foo1(x: u32) -> isize { 1 } | ||
597 | fn foo2(x: u32) -> isize { 2 } | ||
598 | fn foo3(x: u32) -> isize { 3 } | ||
599 | fn test() { | ||
600 | let x = match 1 { | ||
601 | 1 => foo1, | ||
602 | 2 => foo2, | ||
603 | _ => foo3, | ||
604 | }; | ||
605 | } | ||
606 | ", | ||
607 | expect![[r" | ||
608 | 8..9 'x': u32 | ||
609 | 25..30 '{ 1 }': isize | ||
610 | 27..28 '1': isize | ||
611 | 39..40 'x': u32 | ||
612 | 56..61 '{ 2 }': isize | ||
613 | 58..59 '2': isize | ||
614 | 70..71 'x': u32 | ||
615 | 87..92 '{ 3 }': isize | ||
616 | 89..90 '3': isize | ||
617 | 103..192 '{ ... }; }': () | ||
618 | 113..114 'x': fn(u32) -> isize | ||
619 | 117..189 'match ... }': fn(u32) -> isize | ||
620 | 123..124 '1': i32 | ||
621 | 135..136 '1': i32 | ||
622 | 135..136 '1': i32 | ||
623 | 140..144 'foo1': fn foo1(u32) -> isize | ||
624 | 154..155 '2': i32 | ||
625 | 154..155 '2': i32 | ||
626 | 159..163 'foo2': fn foo2(u32) -> isize | ||
627 | 173..174 '_': i32 | ||
628 | 178..182 'foo3': fn foo3(u32) -> isize | ||
629 | "]], | ||
630 | ); | ||
631 | } | ||
632 | |||
633 | #[test] | ||
634 | fn coerce_closure_to_fn_ptr() { | ||
635 | check_infer_with_mismatches( | ||
636 | r" | ||
637 | fn test() { | ||
638 | let f: fn(u32) -> isize = |x| { 1 }; | ||
639 | } | ||
640 | ", | ||
641 | expect![[r" | ||
642 | 10..54 '{ ...1 }; }': () | ||
643 | 20..21 'f': fn(u32) -> isize | ||
644 | 42..51 '|x| { 1 }': |u32| -> isize | ||
645 | 43..44 'x': u32 | ||
646 | 46..51 '{ 1 }': isize | ||
647 | 48..49 '1': isize | ||
648 | "]], | ||
649 | ); | ||
650 | } | ||
651 | |||
652 | #[test] | ||
653 | fn coerce_placeholder_ref() { | ||
654 | // placeholders should unify, even behind references | ||
655 | check_infer_with_mismatches( | ||
656 | r" | ||
657 | struct S<T> { t: T } | ||
658 | impl<TT> S<TT> { | ||
659 | fn get(&self) -> &TT { | ||
660 | &self.t | ||
661 | } | ||
662 | } | ||
663 | ", | ||
664 | expect![[r" | ||
665 | 50..54 'self': &S<TT> | ||
666 | 63..86 '{ ... }': &TT | ||
667 | 73..80 '&self.t': &TT | ||
668 | 74..78 'self': &S<TT> | ||
669 | 74..80 'self.t': TT | ||
670 | "]], | ||
671 | ); | ||
672 | } | ||
673 | |||
674 | #[test] | ||
675 | fn coerce_unsize_array() { | ||
676 | check_infer_with_mismatches( | ||
677 | r#" | ||
678 | #[lang = "unsize"] | ||
679 | pub trait Unsize<T> {} | ||
680 | #[lang = "coerce_unsized"] | ||
681 | pub trait CoerceUnsized<T> {} | ||
682 | |||
683 | impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {} | ||
684 | |||
685 | fn test() { | ||
686 | let f: &[usize] = &[1, 2, 3]; | ||
687 | } | ||
688 | "#, | ||
689 | expect![[r" | ||
690 | 161..198 '{ ... 3]; }': () | ||
691 | 171..172 'f': &[usize] | ||
692 | 185..195 '&[1, 2, 3]': &[usize; _] | ||
693 | 186..195 '[1, 2, 3]': [usize; _] | ||
694 | 187..188 '1': usize | ||
695 | 190..191 '2': usize | ||
696 | 193..194 '3': usize | ||
697 | "]], | ||
698 | ); | ||
699 | } | ||
700 | |||
701 | #[test] | ||
702 | fn coerce_unsize_trait_object_simple() { | ||
703 | check_infer_with_mismatches( | ||
704 | r#" | ||
705 | #[lang = "sized"] | ||
706 | pub trait Sized {} | ||
707 | #[lang = "unsize"] | ||
708 | pub trait Unsize<T> {} | ||
709 | #[lang = "coerce_unsized"] | ||
710 | pub trait CoerceUnsized<T> {} | ||
711 | |||
712 | impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {} | ||
713 | |||
714 | trait Foo<T, U> {} | ||
715 | trait Bar<U, T, X>: Foo<T, U> {} | ||
716 | trait Baz<T, X>: Bar<usize, T, X> {} | ||
717 | |||
718 | struct S<T, X>; | ||
719 | impl<T, X> Foo<T, usize> for S<T, X> {} | ||
720 | impl<T, X> Bar<usize, T, X> for S<T, X> {} | ||
721 | impl<T, X> Baz<T, X> for S<T, X> {} | ||
722 | |||
723 | fn test() { | ||
724 | let obj: &dyn Baz<i8, i16> = &S; | ||
725 | let obj: &dyn Bar<_, i8, i16> = &S; | ||
726 | let obj: &dyn Foo<i8, _> = &S; | ||
727 | } | ||
728 | "#, | ||
729 | expect![[r" | ||
730 | 424..539 '{ ... &S; }': () | ||
731 | 434..437 'obj': &dyn Baz<i8, i16> | ||
732 | 459..461 '&S': &S<i8, i16> | ||
733 | 460..461 'S': S<i8, i16> | ||
734 | 471..474 'obj': &dyn Bar<usize, i8, i16> | ||
735 | 499..501 '&S': &S<i8, i16> | ||
736 | 500..501 'S': S<i8, i16> | ||
737 | 511..514 'obj': &dyn Foo<i8, usize> | ||
738 | 534..536 '&S': &S<i8, {unknown}> | ||
739 | 535..536 'S': S<i8, {unknown}> | ||
740 | "]], | ||
741 | ); | ||
742 | } | ||
743 | |||
744 | #[test] | ||
745 | // The rust reference says this should be possible, but rustc doesn't implement | ||
746 | // it. We used to support it, but Chalk doesn't. | ||
747 | #[ignore] | ||
748 | fn coerce_unsize_trait_object_to_trait_object() { | ||
749 | check_infer_with_mismatches( | ||
750 | r#" | ||
751 | #[lang = "sized"] | ||
752 | pub trait Sized {} | ||
753 | #[lang = "unsize"] | ||
754 | pub trait Unsize<T> {} | ||
755 | #[lang = "coerce_unsized"] | ||
756 | pub trait CoerceUnsized<T> {} | ||
757 | |||
758 | impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {} | ||
759 | |||
760 | trait Foo<T, U> {} | ||
761 | trait Bar<U, T, X>: Foo<T, U> {} | ||
762 | trait Baz<T, X>: Bar<usize, T, X> {} | ||
763 | |||
764 | struct S<T, X>; | ||
765 | impl<T, X> Foo<T, usize> for S<T, X> {} | ||
766 | impl<T, X> Bar<usize, T, X> for S<T, X> {} | ||
767 | impl<T, X> Baz<T, X> for S<T, X> {} | ||
768 | |||
769 | fn test() { | ||
770 | let obj: &dyn Baz<i8, i16> = &S; | ||
771 | let obj: &dyn Bar<_, _, _> = obj; | ||
772 | let obj: &dyn Foo<_, _> = obj; | ||
773 | let obj2: &dyn Baz<i8, i16> = &S; | ||
774 | let _: &dyn Foo<_, _> = obj2; | ||
775 | } | ||
776 | "#, | ||
777 | expect![[r" | ||
778 | 424..609 '{ ...bj2; }': () | ||
779 | 434..437 'obj': &dyn Baz<i8, i16> | ||
780 | 459..461 '&S': &S<i8, i16> | ||
781 | 460..461 'S': S<i8, i16> | ||
782 | 471..474 'obj': &dyn Bar<usize, i8, i16> | ||
783 | 496..499 'obj': &dyn Baz<i8, i16> | ||
784 | 509..512 'obj': &dyn Foo<i8, usize> | ||
785 | 531..534 'obj': &dyn Bar<usize, i8, i16> | ||
786 | 544..548 'obj2': &dyn Baz<i8, i16> | ||
787 | 570..572 '&S': &S<i8, i16> | ||
788 | 571..572 'S': S<i8, i16> | ||
789 | 582..583 '_': &dyn Foo<i8, usize> | ||
790 | 602..606 'obj2': &dyn Baz<i8, i16> | ||
791 | "]], | ||
792 | ); | ||
793 | } | ||
794 | |||
795 | #[test] | ||
796 | fn coerce_unsize_super_trait_cycle() { | ||
797 | check_infer_with_mismatches( | ||
798 | r#" | ||
799 | #[lang = "sized"] | ||
800 | pub trait Sized {} | ||
801 | #[lang = "unsize"] | ||
802 | pub trait Unsize<T> {} | ||
803 | #[lang = "coerce_unsized"] | ||
804 | pub trait CoerceUnsized<T> {} | ||
805 | |||
806 | impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {} | ||
807 | |||
808 | trait A {} | ||
809 | trait B: C + A {} | ||
810 | trait C: B {} | ||
811 | trait D: C | ||
812 | |||
813 | struct S; | ||
814 | impl A for S {} | ||
815 | impl B for S {} | ||
816 | impl C for S {} | ||
817 | impl D for S {} | ||
818 | |||
819 | fn test() { | ||
820 | let obj: &dyn D = &S; | ||
821 | let obj: &dyn A = &S; | ||
822 | } | ||
823 | "#, | ||
824 | expect![[r" | ||
825 | 328..383 '{ ... &S; }': () | ||
826 | 338..341 'obj': &dyn D | ||
827 | 352..354 '&S': &S | ||
828 | 353..354 'S': S | ||
829 | 364..367 'obj': &dyn A | ||
830 | 378..380 '&S': &S | ||
831 | 379..380 'S': S | ||
832 | "]], | ||
833 | ); | ||
834 | } | ||
835 | |||
836 | #[ignore] | ||
837 | #[test] | ||
838 | fn coerce_unsize_generic() { | ||
839 | // FIXME: Implement this | ||
840 | // https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions | ||
841 | check_infer_with_mismatches( | ||
842 | r#" | ||
843 | #[lang = "unsize"] | ||
844 | pub trait Unsize<T> {} | ||
845 | #[lang = "coerce_unsized"] | ||
846 | pub trait CoerceUnsized<T> {} | ||
847 | |||
848 | impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {} | ||
849 | |||
850 | struct Foo<T> { t: T }; | ||
851 | struct Bar<T>(Foo<T>); | ||
852 | |||
853 | fn test() { | ||
854 | let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] }; | ||
855 | let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] }); | ||
856 | } | ||
857 | "#, | ||
858 | expect![[r" | ||
859 | "]], | ||
860 | ); | ||
861 | } | ||
diff --git a/crates/ra_hir_ty/src/tests/display_source_code.rs b/crates/ra_hir_ty/src/tests/display_source_code.rs deleted file mode 100644 index b502135d8..000000000 --- a/crates/ra_hir_ty/src/tests/display_source_code.rs +++ /dev/null | |||
@@ -1,41 +0,0 @@ | |||
1 | use super::check_types_source_code; | ||
2 | |||
3 | #[test] | ||
4 | fn qualify_path_to_submodule() { | ||
5 | check_types_source_code( | ||
6 | r#" | ||
7 | mod foo { | ||
8 | pub struct Foo; | ||
9 | } | ||
10 | |||
11 | fn bar() { | ||
12 | let foo: foo::Foo = foo::Foo; | ||
13 | foo | ||
14 | } //^ foo::Foo | ||
15 | |||
16 | "#, | ||
17 | ); | ||
18 | } | ||
19 | |||
20 | #[test] | ||
21 | fn omit_default_type_parameters() { | ||
22 | check_types_source_code( | ||
23 | r#" | ||
24 | struct Foo<T = u8> { t: T } | ||
25 | fn main() { | ||
26 | let foo = Foo { t: 5u8 }; | ||
27 | foo; | ||
28 | } //^ Foo | ||
29 | "#, | ||
30 | ); | ||
31 | |||
32 | check_types_source_code( | ||
33 | r#" | ||
34 | struct Foo<K, T = u8> { k: K, t: T } | ||
35 | fn main() { | ||
36 | let foo = Foo { k: 400, t: 5u8 }; | ||
37 | foo; | ||
38 | } //^ Foo<i32> | ||
39 | "#, | ||
40 | ); | ||
41 | } | ||
diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs deleted file mode 100644 index 24c53eb02..000000000 --- a/crates/ra_hir_ty/src/tests/macros.rs +++ /dev/null | |||
@@ -1,787 +0,0 @@ | |||
1 | use std::fs; | ||
2 | |||
3 | use expect::expect; | ||
4 | use test_utils::project_dir; | ||
5 | |||
6 | use super::{check_infer, check_types}; | ||
7 | |||
8 | #[test] | ||
9 | fn cfg_impl_def() { | ||
10 | check_types( | ||
11 | r#" | ||
12 | //- /main.rs crate:main deps:foo cfg:test | ||
13 | use foo::S as T; | ||
14 | struct S; | ||
15 | |||
16 | #[cfg(test)] | ||
17 | impl S { | ||
18 | fn foo1(&self) -> i32 { 0 } | ||
19 | } | ||
20 | |||
21 | #[cfg(not(test))] | ||
22 | impl S { | ||
23 | fn foo2(&self) -> i32 { 0 } | ||
24 | } | ||
25 | |||
26 | fn test() { | ||
27 | let t = (S.foo1(), S.foo2(), T.foo3(), T.foo4()); | ||
28 | t; | ||
29 | } //^ (i32, {unknown}, i32, {unknown}) | ||
30 | |||
31 | //- /foo.rs crate:foo | ||
32 | struct S; | ||
33 | |||
34 | #[cfg(not(test))] | ||
35 | impl S { | ||
36 | fn foo3(&self) -> i32 { 0 } | ||
37 | } | ||
38 | |||
39 | #[cfg(test)] | ||
40 | impl S { | ||
41 | fn foo4(&self) -> i32 { 0 } | ||
42 | } | ||
43 | "#, | ||
44 | ); | ||
45 | } | ||
46 | |||
47 | #[test] | ||
48 | fn infer_macros_expanded() { | ||
49 | check_infer( | ||
50 | r#" | ||
51 | struct Foo(Vec<i32>); | ||
52 | |||
53 | macro_rules! foo { | ||
54 | ($($item:expr),*) => { | ||
55 | { | ||
56 | Foo(vec![$($item,)*]) | ||
57 | } | ||
58 | }; | ||
59 | } | ||
60 | |||
61 | fn main() { | ||
62 | let x = foo!(1,2); | ||
63 | } | ||
64 | "#, | ||
65 | expect![[r#" | ||
66 | !0..17 '{Foo(v...,2,])}': Foo | ||
67 | !1..4 'Foo': Foo({unknown}) -> Foo | ||
68 | !1..16 'Foo(vec![1,2,])': Foo | ||
69 | !5..15 'vec![1,2,]': {unknown} | ||
70 | 155..181 '{ ...,2); }': () | ||
71 | 165..166 'x': Foo | ||
72 | "#]], | ||
73 | ); | ||
74 | } | ||
75 | |||
76 | #[test] | ||
77 | fn infer_legacy_textual_scoped_macros_expanded() { | ||
78 | check_infer( | ||
79 | r#" | ||
80 | struct Foo(Vec<i32>); | ||
81 | |||
82 | #[macro_use] | ||
83 | mod m { | ||
84 | macro_rules! foo { | ||
85 | ($($item:expr),*) => { | ||
86 | { | ||
87 | Foo(vec![$($item,)*]) | ||
88 | } | ||
89 | }; | ||
90 | } | ||
91 | } | ||
92 | |||
93 | fn main() { | ||
94 | let x = foo!(1,2); | ||
95 | let y = crate::foo!(1,2); | ||
96 | } | ||
97 | "#, | ||
98 | expect![[r#" | ||
99 | !0..17 '{Foo(v...,2,])}': Foo | ||
100 | !1..4 'Foo': Foo({unknown}) -> Foo | ||
101 | !1..16 'Foo(vec![1,2,])': Foo | ||
102 | !5..15 'vec![1,2,]': {unknown} | ||
103 | 194..250 '{ ...,2); }': () | ||
104 | 204..205 'x': Foo | ||
105 | 227..228 'y': {unknown} | ||
106 | 231..247 'crate:...!(1,2)': {unknown} | ||
107 | "#]], | ||
108 | ); | ||
109 | } | ||
110 | |||
111 | #[test] | ||
112 | fn infer_path_qualified_macros_expanded() { | ||
113 | check_infer( | ||
114 | r#" | ||
115 | #[macro_export] | ||
116 | macro_rules! foo { | ||
117 | () => { 42i32 } | ||
118 | } | ||
119 | |||
120 | mod m { | ||
121 | pub use super::foo as bar; | ||
122 | } | ||
123 | |||
124 | fn main() { | ||
125 | let x = crate::foo!(); | ||
126 | let y = m::bar!(); | ||
127 | } | ||
128 | "#, | ||
129 | expect![[r#" | ||
130 | !0..5 '42i32': i32 | ||
131 | !0..5 '42i32': i32 | ||
132 | 110..163 '{ ...!(); }': () | ||
133 | 120..121 'x': i32 | ||
134 | 147..148 'y': i32 | ||
135 | "#]], | ||
136 | ); | ||
137 | } | ||
138 | |||
139 | #[test] | ||
140 | fn expr_macro_expanded_in_various_places() { | ||
141 | check_infer( | ||
142 | r#" | ||
143 | macro_rules! spam { | ||
144 | () => (1isize); | ||
145 | } | ||
146 | |||
147 | fn spam() { | ||
148 | spam!(); | ||
149 | (spam!()); | ||
150 | spam!().spam(spam!()); | ||
151 | for _ in spam!() {} | ||
152 | || spam!(); | ||
153 | while spam!() {} | ||
154 | break spam!(); | ||
155 | return spam!(); | ||
156 | match spam!() { | ||
157 | _ if spam!() => spam!(), | ||
158 | } | ||
159 | spam!()(spam!()); | ||
160 | Spam { spam: spam!() }; | ||
161 | spam!()[spam!()]; | ||
162 | await spam!(); | ||
163 | spam!() as usize; | ||
164 | &spam!(); | ||
165 | -spam!(); | ||
166 | spam!()..spam!(); | ||
167 | spam!() + spam!(); | ||
168 | } | ||
169 | "#, | ||
170 | expect![[r#" | ||
171 | !0..6 '1isize': isize | ||
172 | !0..6 '1isize': isize | ||
173 | !0..6 '1isize': isize | ||
174 | !0..6 '1isize': isize | ||
175 | !0..6 '1isize': isize | ||
176 | !0..6 '1isize': isize | ||
177 | !0..6 '1isize': isize | ||
178 | !0..6 '1isize': isize | ||
179 | !0..6 '1isize': isize | ||
180 | !0..6 '1isize': isize | ||
181 | !0..6 '1isize': isize | ||
182 | !0..6 '1isize': isize | ||
183 | !0..6 '1isize': isize | ||
184 | !0..6 '1isize': isize | ||
185 | !0..6 '1isize': isize | ||
186 | !0..6 '1isize': isize | ||
187 | !0..6 '1isize': isize | ||
188 | !0..6 '1isize': isize | ||
189 | !0..6 '1isize': isize | ||
190 | !0..6 '1isize': isize | ||
191 | !0..6 '1isize': isize | ||
192 | !0..6 '1isize': isize | ||
193 | !0..6 '1isize': isize | ||
194 | !0..6 '1isize': isize | ||
195 | !0..6 '1isize': isize | ||
196 | 53..456 '{ ...!(); }': () | ||
197 | 87..108 'spam!(...am!())': {unknown} | ||
198 | 114..133 'for _ ...!() {}': () | ||
199 | 118..119 '_': {unknown} | ||
200 | 131..133 '{}': () | ||
201 | 138..148 '|| spam!()': || -> isize | ||
202 | 154..170 'while ...!() {}': () | ||
203 | 168..170 '{}': () | ||
204 | 175..188 'break spam!()': ! | ||
205 | 194..208 'return spam!()': ! | ||
206 | 214..268 'match ... }': isize | ||
207 | 238..239 '_': isize | ||
208 | 273..289 'spam!(...am!())': {unknown} | ||
209 | 295..317 'Spam {...m!() }': {unknown} | ||
210 | 323..339 'spam!(...am!()]': {unknown} | ||
211 | 364..380 'spam!(... usize': usize | ||
212 | 386..394 '&spam!()': &isize | ||
213 | 400..408 '-spam!()': isize | ||
214 | 414..430 'spam!(...pam!()': {unknown} | ||
215 | 436..453 'spam!(...pam!()': isize | ||
216 | "#]], | ||
217 | ); | ||
218 | } | ||
219 | |||
220 | #[test] | ||
221 | fn infer_type_value_macro_having_same_name() { | ||
222 | check_infer( | ||
223 | r#" | ||
224 | #[macro_export] | ||
225 | macro_rules! foo { | ||
226 | () => { | ||
227 | mod foo { | ||
228 | pub use super::foo; | ||
229 | } | ||
230 | }; | ||
231 | ($x:tt) => { | ||
232 | $x | ||
233 | }; | ||
234 | } | ||
235 | |||
236 | foo!(); | ||
237 | |||
238 | fn foo() { | ||
239 | let foo = foo::foo!(42i32); | ||
240 | } | ||
241 | "#, | ||
242 | expect![[r#" | ||
243 | !0..5 '42i32': i32 | ||
244 | 170..205 '{ ...32); }': () | ||
245 | 180..183 'foo': i32 | ||
246 | "#]], | ||
247 | ); | ||
248 | } | ||
249 | |||
250 | #[test] | ||
251 | fn processes_impls_generated_by_macros() { | ||
252 | check_types( | ||
253 | r#" | ||
254 | macro_rules! m { | ||
255 | ($ident:ident) => (impl Trait for $ident {}) | ||
256 | } | ||
257 | trait Trait { fn foo(self) -> u128 {} } | ||
258 | struct S; | ||
259 | m!(S); | ||
260 | fn test() { S.foo(); } | ||
261 | //^ u128 | ||
262 | "#, | ||
263 | ); | ||
264 | } | ||
265 | |||
266 | #[test] | ||
267 | fn infer_assoc_items_generated_by_macros() { | ||
268 | check_types( | ||
269 | r#" | ||
270 | macro_rules! m { | ||
271 | () => (fn foo(&self) -> u128 {0}) | ||
272 | } | ||
273 | struct S; | ||
274 | impl S { | ||
275 | m!(); | ||
276 | } | ||
277 | |||
278 | fn test() { S.foo(); } | ||
279 | //^ u128 | ||
280 | "#, | ||
281 | ); | ||
282 | } | ||
283 | |||
284 | #[test] | ||
285 | fn infer_assoc_items_generated_by_macros_chain() { | ||
286 | check_types( | ||
287 | r#" | ||
288 | macro_rules! m_inner { | ||
289 | () => {fn foo(&self) -> u128 {0}} | ||
290 | } | ||
291 | macro_rules! m { | ||
292 | () => {m_inner!();} | ||
293 | } | ||
294 | |||
295 | struct S; | ||
296 | impl S { | ||
297 | m!(); | ||
298 | } | ||
299 | |||
300 | fn test() { S.foo(); } | ||
301 | //^ u128 | ||
302 | "#, | ||
303 | ); | ||
304 | } | ||
305 | |||
306 | #[test] | ||
307 | fn infer_macro_with_dollar_crate_is_correct_in_expr() { | ||
308 | check_types( | ||
309 | r#" | ||
310 | //- /main.rs crate:main deps:foo | ||
311 | fn test() { | ||
312 | let x = (foo::foo!(1), foo::foo!(2)); | ||
313 | x; | ||
314 | } //^ (i32, usize) | ||
315 | |||
316 | //- /lib.rs crate:foo | ||
317 | #[macro_export] | ||
318 | macro_rules! foo { | ||
319 | (1) => { $crate::bar!() }; | ||
320 | (2) => { 1 + $crate::baz() }; | ||
321 | } | ||
322 | |||
323 | #[macro_export] | ||
324 | macro_rules! bar { | ||
325 | () => { 42 } | ||
326 | } | ||
327 | |||
328 | pub fn baz() -> usize { 31usize } | ||
329 | "#, | ||
330 | ); | ||
331 | } | ||
332 | |||
333 | #[test] | ||
334 | fn infer_macro_with_dollar_crate_is_correct_in_trait_associate_type() { | ||
335 | check_types( | ||
336 | r#" | ||
337 | //- /main.rs crate:main deps:foo | ||
338 | use foo::Trait; | ||
339 | |||
340 | fn test() { | ||
341 | let msg = foo::Message(foo::MessageRef); | ||
342 | let r = msg.deref(); | ||
343 | r; | ||
344 | //^ &MessageRef | ||
345 | } | ||
346 | |||
347 | //- /lib.rs crate:foo | ||
348 | pub struct MessageRef; | ||
349 | pub struct Message(MessageRef); | ||
350 | |||
351 | pub trait Trait { | ||
352 | type Target; | ||
353 | fn deref(&self) -> &Self::Target; | ||
354 | } | ||
355 | |||
356 | #[macro_export] | ||
357 | macro_rules! expand { | ||
358 | () => { | ||
359 | impl Trait for Message { | ||
360 | type Target = $crate::MessageRef; | ||
361 | fn deref(&self) -> &Self::Target { | ||
362 | &self.0 | ||
363 | } | ||
364 | } | ||
365 | } | ||
366 | } | ||
367 | |||
368 | expand!(); | ||
369 | "#, | ||
370 | ); | ||
371 | } | ||
372 | |||
373 | #[test] | ||
374 | fn infer_type_value_non_legacy_macro_use_as() { | ||
375 | check_infer( | ||
376 | r#" | ||
377 | mod m { | ||
378 | macro_rules! _foo { | ||
379 | ($x:ident) => { type $x = u64; } | ||
380 | } | ||
381 | pub(crate) use _foo as foo; | ||
382 | } | ||
383 | |||
384 | m::foo!(foo); | ||
385 | use foo as bar; | ||
386 | fn f() -> bar { 0 } | ||
387 | fn main() { | ||
388 | let _a = f(); | ||
389 | } | ||
390 | "#, | ||
391 | expect![[r#" | ||
392 | 158..163 '{ 0 }': u64 | ||
393 | 160..161 '0': u64 | ||
394 | 174..196 '{ ...f(); }': () | ||
395 | 184..186 '_a': u64 | ||
396 | 190..191 'f': fn f() -> u64 | ||
397 | 190..193 'f()': u64 | ||
398 | "#]], | ||
399 | ); | ||
400 | } | ||
401 | |||
402 | #[test] | ||
403 | fn infer_local_macro() { | ||
404 | check_infer( | ||
405 | r#" | ||
406 | fn main() { | ||
407 | macro_rules! foo { | ||
408 | () => { 1usize } | ||
409 | } | ||
410 | let _a = foo!(); | ||
411 | } | ||
412 | "#, | ||
413 | expect![[r#" | ||
414 | !0..6 '1usize': usize | ||
415 | 10..89 '{ ...!(); }': () | ||
416 | 16..65 'macro_... }': {unknown} | ||
417 | 74..76 '_a': usize | ||
418 | "#]], | ||
419 | ); | ||
420 | } | ||
421 | |||
422 | #[test] | ||
423 | fn infer_local_inner_macros() { | ||
424 | check_types( | ||
425 | r#" | ||
426 | //- /main.rs crate:main deps:foo | ||
427 | fn test() { | ||
428 | let x = foo::foo!(1); | ||
429 | x; | ||
430 | } //^ i32 | ||
431 | |||
432 | //- /lib.rs crate:foo | ||
433 | #[macro_export(local_inner_macros)] | ||
434 | macro_rules! foo { | ||
435 | (1) => { bar!() }; | ||
436 | } | ||
437 | |||
438 | #[macro_export] | ||
439 | macro_rules! bar { | ||
440 | () => { 42 } | ||
441 | } | ||
442 | |||
443 | "#, | ||
444 | ); | ||
445 | } | ||
446 | |||
447 | #[test] | ||
448 | fn infer_builtin_macros_line() { | ||
449 | check_infer( | ||
450 | r#" | ||
451 | #[rustc_builtin_macro] | ||
452 | macro_rules! line {() => {}} | ||
453 | |||
454 | fn main() { | ||
455 | let x = line!(); | ||
456 | } | ||
457 | "#, | ||
458 | expect![[r#" | ||
459 | !0..1 '0': i32 | ||
460 | 63..87 '{ ...!(); }': () | ||
461 | 73..74 'x': i32 | ||
462 | "#]], | ||
463 | ); | ||
464 | } | ||
465 | |||
466 | #[test] | ||
467 | fn infer_builtin_macros_file() { | ||
468 | check_infer( | ||
469 | r#" | ||
470 | #[rustc_builtin_macro] | ||
471 | macro_rules! file {() => {}} | ||
472 | |||
473 | fn main() { | ||
474 | let x = file!(); | ||
475 | } | ||
476 | "#, | ||
477 | expect![[r#" | ||
478 | !0..2 '""': &str | ||
479 | 63..87 '{ ...!(); }': () | ||
480 | 73..74 'x': &str | ||
481 | "#]], | ||
482 | ); | ||
483 | } | ||
484 | |||
485 | #[test] | ||
486 | fn infer_builtin_macros_column() { | ||
487 | check_infer( | ||
488 | r#" | ||
489 | #[rustc_builtin_macro] | ||
490 | macro_rules! column {() => {}} | ||
491 | |||
492 | fn main() { | ||
493 | let x = column!(); | ||
494 | } | ||
495 | "#, | ||
496 | expect![[r#" | ||
497 | !0..1 '0': i32 | ||
498 | 65..91 '{ ...!(); }': () | ||
499 | 75..76 'x': i32 | ||
500 | "#]], | ||
501 | ); | ||
502 | } | ||
503 | |||
504 | #[test] | ||
505 | fn infer_builtin_macros_concat() { | ||
506 | check_infer( | ||
507 | r#" | ||
508 | #[rustc_builtin_macro] | ||
509 | macro_rules! concat {() => {}} | ||
510 | |||
511 | fn main() { | ||
512 | let x = concat!("hello", concat!("world", "!")); | ||
513 | } | ||
514 | "#, | ||
515 | expect![[r#" | ||
516 | !0..13 '"helloworld!"': &str | ||
517 | 65..121 '{ ...")); }': () | ||
518 | 75..76 'x': &str | ||
519 | "#]], | ||
520 | ); | ||
521 | } | ||
522 | |||
523 | #[test] | ||
524 | fn infer_builtin_macros_include() { | ||
525 | check_types( | ||
526 | r#" | ||
527 | //- /main.rs | ||
528 | #[rustc_builtin_macro] | ||
529 | macro_rules! include {() => {}} | ||
530 | |||
531 | include!("foo.rs"); | ||
532 | |||
533 | fn main() { | ||
534 | bar(); | ||
535 | } //^ u32 | ||
536 | |||
537 | //- /foo.rs | ||
538 | fn bar() -> u32 {0} | ||
539 | "#, | ||
540 | ); | ||
541 | } | ||
542 | |||
543 | #[test] | ||
544 | #[ignore] | ||
545 | fn include_accidentally_quadratic() { | ||
546 | let file = project_dir().join("crates/ra_syntax/test_data/accidentally_quadratic"); | ||
547 | let big_file = fs::read_to_string(file).unwrap(); | ||
548 | let big_file = vec![big_file; 10].join("\n"); | ||
549 | |||
550 | let fixture = r#" | ||
551 | //- /main.rs | ||
552 | #[rustc_builtin_macro] | ||
553 | macro_rules! include {() => {}} | ||
554 | |||
555 | include!("foo.rs"); | ||
556 | |||
557 | fn main() { | ||
558 | RegisterBlock { }; | ||
559 | //^ RegisterBlock | ||
560 | } | ||
561 | "#; | ||
562 | let fixture = format!("{}\n//- /foo.rs\n{}", fixture, big_file); | ||
563 | check_types(&fixture); | ||
564 | } | ||
565 | |||
566 | #[test] | ||
567 | fn infer_builtin_macros_include_concat() { | ||
568 | check_types( | ||
569 | r#" | ||
570 | //- /main.rs | ||
571 | #[rustc_builtin_macro] | ||
572 | macro_rules! include {() => {}} | ||
573 | |||
574 | #[rustc_builtin_macro] | ||
575 | macro_rules! concat {() => {}} | ||
576 | |||
577 | include!(concat!("f", "oo.rs")); | ||
578 | |||
579 | fn main() { | ||
580 | bar(); | ||
581 | } //^ u32 | ||
582 | |||
583 | //- /foo.rs | ||
584 | fn bar() -> u32 {0} | ||
585 | "#, | ||
586 | ); | ||
587 | } | ||
588 | |||
589 | #[test] | ||
590 | fn infer_builtin_macros_include_concat_with_bad_env_should_failed() { | ||
591 | check_types( | ||
592 | r#" | ||
593 | //- /main.rs | ||
594 | #[rustc_builtin_macro] | ||
595 | macro_rules! include {() => {}} | ||
596 | |||
597 | #[rustc_builtin_macro] | ||
598 | macro_rules! concat {() => {}} | ||
599 | |||
600 | #[rustc_builtin_macro] | ||
601 | macro_rules! env {() => {}} | ||
602 | |||
603 | include!(concat!(env!("OUT_DIR"), "/foo.rs")); | ||
604 | |||
605 | fn main() { | ||
606 | bar(); | ||
607 | } //^ {unknown} | ||
608 | |||
609 | //- /foo.rs | ||
610 | fn bar() -> u32 {0} | ||
611 | "#, | ||
612 | ); | ||
613 | } | ||
614 | |||
615 | #[test] | ||
616 | fn infer_builtin_macros_include_itself_should_failed() { | ||
617 | check_types( | ||
618 | r#" | ||
619 | #[rustc_builtin_macro] | ||
620 | macro_rules! include {() => {}} | ||
621 | |||
622 | include!("main.rs"); | ||
623 | |||
624 | fn main() { | ||
625 | 0 | ||
626 | } //^ i32 | ||
627 | "#, | ||
628 | ); | ||
629 | } | ||
630 | |||
631 | #[test] | ||
632 | fn infer_builtin_macros_concat_with_lazy() { | ||
633 | check_infer( | ||
634 | r#" | ||
635 | macro_rules! hello {() => {"hello"}} | ||
636 | |||
637 | #[rustc_builtin_macro] | ||
638 | macro_rules! concat {() => {}} | ||
639 | |||
640 | fn main() { | ||
641 | let x = concat!(hello!(), concat!("world", "!")); | ||
642 | } | ||
643 | "#, | ||
644 | expect![[r#" | ||
645 | !0..13 '"helloworld!"': &str | ||
646 | 103..160 '{ ...")); }': () | ||
647 | 113..114 'x': &str | ||
648 | "#]], | ||
649 | ); | ||
650 | } | ||
651 | |||
652 | #[test] | ||
653 | fn infer_builtin_macros_env() { | ||
654 | check_infer( | ||
655 | r#" | ||
656 | //- /main.rs env:foo=bar | ||
657 | #[rustc_builtin_macro] | ||
658 | macro_rules! env {() => {}} | ||
659 | |||
660 | fn main() { | ||
661 | let x = env!("foo"); | ||
662 | } | ||
663 | "#, | ||
664 | expect![[r#" | ||
665 | !0..22 '"__RA_...TED__"': &str | ||
666 | 62..90 '{ ...o"); }': () | ||
667 | 72..73 'x': &str | ||
668 | "#]], | ||
669 | ); | ||
670 | } | ||
671 | |||
672 | #[test] | ||
673 | fn infer_derive_clone_simple() { | ||
674 | check_types( | ||
675 | r#" | ||
676 | //- /main.rs crate:main deps:core | ||
677 | #[derive(Clone)] | ||
678 | struct S; | ||
679 | fn test() { | ||
680 | S.clone(); | ||
681 | } //^ S | ||
682 | |||
683 | //- /lib.rs crate:core | ||
684 | #[prelude_import] | ||
685 | use clone::*; | ||
686 | mod clone { | ||
687 | trait Clone { | ||
688 | fn clone(&self) -> Self; | ||
689 | } | ||
690 | } | ||
691 | "#, | ||
692 | ); | ||
693 | } | ||
694 | |||
695 | #[test] | ||
696 | fn infer_derive_clone_in_core() { | ||
697 | check_types( | ||
698 | r#" | ||
699 | //- /lib.rs crate:core | ||
700 | #[prelude_import] | ||
701 | use clone::*; | ||
702 | mod clone { | ||
703 | trait Clone { | ||
704 | fn clone(&self) -> Self; | ||
705 | } | ||
706 | } | ||
707 | #[derive(Clone)] | ||
708 | pub struct S; | ||
709 | |||
710 | //- /main.rs crate:main deps:core | ||
711 | use core::S; | ||
712 | fn test() { | ||
713 | S.clone(); | ||
714 | } //^ S | ||
715 | "#, | ||
716 | ); | ||
717 | } | ||
718 | |||
719 | #[test] | ||
720 | fn infer_derive_clone_with_params() { | ||
721 | check_types( | ||
722 | r#" | ||
723 | //- /main.rs crate:main deps:core | ||
724 | #[derive(Clone)] | ||
725 | struct S; | ||
726 | #[derive(Clone)] | ||
727 | struct Wrapper<T>(T); | ||
728 | struct NonClone; | ||
729 | fn test() { | ||
730 | (Wrapper(S).clone(), Wrapper(NonClone).clone()); | ||
731 | //^ (Wrapper<S>, {unknown}) | ||
732 | } | ||
733 | |||
734 | //- /lib.rs crate:core | ||
735 | #[prelude_import] | ||
736 | use clone::*; | ||
737 | mod clone { | ||
738 | trait Clone { | ||
739 | fn clone(&self) -> Self; | ||
740 | } | ||
741 | } | ||
742 | "#, | ||
743 | ); | ||
744 | } | ||
745 | |||
746 | #[test] | ||
747 | fn infer_custom_derive_simple() { | ||
748 | // FIXME: this test current now do nothing | ||
749 | check_types( | ||
750 | r#" | ||
751 | //- /main.rs crate:main | ||
752 | use foo::Foo; | ||
753 | |||
754 | #[derive(Foo)] | ||
755 | struct S{} | ||
756 | |||
757 | fn test() { | ||
758 | S{}; | ||
759 | } //^ S | ||
760 | "#, | ||
761 | ); | ||
762 | } | ||
763 | |||
764 | #[test] | ||
765 | fn macro_in_arm() { | ||
766 | check_infer( | ||
767 | r#" | ||
768 | macro_rules! unit { | ||
769 | () => { () }; | ||
770 | } | ||
771 | |||
772 | fn main() { | ||
773 | let x = match () { | ||
774 | unit!() => 92u32, | ||
775 | }; | ||
776 | } | ||
777 | "#, | ||
778 | expect![[r#" | ||
779 | 51..110 '{ ... }; }': () | ||
780 | 61..62 'x': u32 | ||
781 | 65..107 'match ... }': u32 | ||
782 | 71..73 '()': () | ||
783 | 84..91 'unit!()': () | ||
784 | 95..100 '92u32': u32 | ||
785 | "#]], | ||
786 | ); | ||
787 | } | ||
diff --git a/crates/ra_hir_ty/src/tests/method_resolution.rs b/crates/ra_hir_ty/src/tests/method_resolution.rs deleted file mode 100644 index fa68355aa..000000000 --- a/crates/ra_hir_ty/src/tests/method_resolution.rs +++ /dev/null | |||
@@ -1,1053 +0,0 @@ | |||
1 | use expect::expect; | ||
2 | |||
3 | use super::{check_infer, check_types}; | ||
4 | |||
5 | #[test] | ||
6 | fn infer_slice_method() { | ||
7 | check_infer( | ||
8 | r#" | ||
9 | #[lang = "slice"] | ||
10 | impl<T> [T] { | ||
11 | fn foo(&self) -> T { | ||
12 | loop {} | ||
13 | } | ||
14 | } | ||
15 | |||
16 | #[lang = "slice_alloc"] | ||
17 | impl<T> [T] {} | ||
18 | |||
19 | fn test(x: &[u8]) { | ||
20 | <[_]>::foo(x); | ||
21 | } | ||
22 | "#, | ||
23 | expect![[r#" | ||
24 | 44..48 'self': &[T] | ||
25 | 55..78 '{ ... }': T | ||
26 | 65..72 'loop {}': ! | ||
27 | 70..72 '{}': () | ||
28 | 130..131 'x': &[u8] | ||
29 | 140..162 '{ ...(x); }': () | ||
30 | 146..156 '<[_]>::foo': fn foo<u8>(&[u8]) -> u8 | ||
31 | 146..159 '<[_]>::foo(x)': u8 | ||
32 | 157..158 'x': &[u8] | ||
33 | "#]], | ||
34 | ); | ||
35 | } | ||
36 | |||
37 | #[test] | ||
38 | fn infer_associated_method_struct() { | ||
39 | check_infer( | ||
40 | r#" | ||
41 | struct A { x: u32 } | ||
42 | |||
43 | impl A { | ||
44 | fn new() -> A { | ||
45 | A { x: 0 } | ||
46 | } | ||
47 | } | ||
48 | fn test() { | ||
49 | let a = A::new(); | ||
50 | a.x; | ||
51 | } | ||
52 | "#, | ||
53 | expect![[r#" | ||
54 | 48..74 '{ ... }': A | ||
55 | 58..68 'A { x: 0 }': A | ||
56 | 65..66 '0': u32 | ||
57 | 87..121 '{ ...a.x; }': () | ||
58 | 97..98 'a': A | ||
59 | 101..107 'A::new': fn new() -> A | ||
60 | 101..109 'A::new()': A | ||
61 | 115..116 'a': A | ||
62 | 115..118 'a.x': u32 | ||
63 | "#]], | ||
64 | ); | ||
65 | } | ||
66 | |||
67 | #[test] | ||
68 | fn infer_associated_method_enum() { | ||
69 | check_infer( | ||
70 | r#" | ||
71 | enum A { B, C } | ||
72 | |||
73 | impl A { | ||
74 | pub fn b() -> A { | ||
75 | A::B | ||
76 | } | ||
77 | pub fn c() -> A { | ||
78 | A::C | ||
79 | } | ||
80 | } | ||
81 | fn test() { | ||
82 | let a = A::b(); | ||
83 | a; | ||
84 | let c = A::c(); | ||
85 | c; | ||
86 | } | ||
87 | "#, | ||
88 | expect![[r#" | ||
89 | 46..66 '{ ... }': A | ||
90 | 56..60 'A::B': A | ||
91 | 87..107 '{ ... }': A | ||
92 | 97..101 'A::C': A | ||
93 | 120..177 '{ ... c; }': () | ||
94 | 130..131 'a': A | ||
95 | 134..138 'A::b': fn b() -> A | ||
96 | 134..140 'A::b()': A | ||
97 | 146..147 'a': A | ||
98 | 157..158 'c': A | ||
99 | 161..165 'A::c': fn c() -> A | ||
100 | 161..167 'A::c()': A | ||
101 | 173..174 'c': A | ||
102 | "#]], | ||
103 | ); | ||
104 | } | ||
105 | |||
106 | #[test] | ||
107 | fn infer_associated_method_with_modules() { | ||
108 | check_infer( | ||
109 | r#" | ||
110 | mod a { | ||
111 | struct A; | ||
112 | impl A { pub fn thing() -> A { A {} }} | ||
113 | } | ||
114 | |||
115 | mod b { | ||
116 | struct B; | ||
117 | impl B { pub fn thing() -> u32 { 99 }} | ||
118 | |||
119 | mod c { | ||
120 | struct C; | ||
121 | impl C { pub fn thing() -> C { C {} }} | ||
122 | } | ||
123 | } | ||
124 | use b::c; | ||
125 | |||
126 | fn test() { | ||
127 | let x = a::A::thing(); | ||
128 | let y = b::B::thing(); | ||
129 | let z = c::C::thing(); | ||
130 | } | ||
131 | "#, | ||
132 | expect![[r#" | ||
133 | 55..63 '{ A {} }': A | ||
134 | 57..61 'A {}': A | ||
135 | 125..131 '{ 99 }': u32 | ||
136 | 127..129 '99': u32 | ||
137 | 201..209 '{ C {} }': C | ||
138 | 203..207 'C {}': C | ||
139 | 240..324 '{ ...g(); }': () | ||
140 | 250..251 'x': A | ||
141 | 254..265 'a::A::thing': fn thing() -> A | ||
142 | 254..267 'a::A::thing()': A | ||
143 | 277..278 'y': u32 | ||
144 | 281..292 'b::B::thing': fn thing() -> u32 | ||
145 | 281..294 'b::B::thing()': u32 | ||
146 | 304..305 'z': C | ||
147 | 308..319 'c::C::thing': fn thing() -> C | ||
148 | 308..321 'c::C::thing()': C | ||
149 | "#]], | ||
150 | ); | ||
151 | } | ||
152 | |||
153 | #[test] | ||
154 | fn infer_associated_method_generics() { | ||
155 | check_infer( | ||
156 | r#" | ||
157 | struct Gen<T> { | ||
158 | val: T | ||
159 | } | ||
160 | |||
161 | impl<T> Gen<T> { | ||
162 | pub fn make(val: T) -> Gen<T> { | ||
163 | Gen { val } | ||
164 | } | ||
165 | } | ||
166 | |||
167 | fn test() { | ||
168 | let a = Gen::make(0u32); | ||
169 | } | ||
170 | "#, | ||
171 | expect![[r#" | ||
172 | 63..66 'val': T | ||
173 | 81..108 '{ ... }': Gen<T> | ||
174 | 91..102 'Gen { val }': Gen<T> | ||
175 | 97..100 'val': T | ||
176 | 122..154 '{ ...32); }': () | ||
177 | 132..133 'a': Gen<u32> | ||
178 | 136..145 'Gen::make': fn make<u32>(u32) -> Gen<u32> | ||
179 | 136..151 'Gen::make(0u32)': Gen<u32> | ||
180 | 146..150 '0u32': u32 | ||
181 | "#]], | ||
182 | ); | ||
183 | } | ||
184 | |||
185 | #[test] | ||
186 | fn infer_associated_method_generics_without_args() { | ||
187 | check_infer( | ||
188 | r#" | ||
189 | struct Gen<T> { | ||
190 | val: T | ||
191 | } | ||
192 | |||
193 | impl<T> Gen<T> { | ||
194 | pub fn make() -> Gen<T> { | ||
195 | loop { } | ||
196 | } | ||
197 | } | ||
198 | |||
199 | fn test() { | ||
200 | let a = Gen::<u32>::make(); | ||
201 | } | ||
202 | "#, | ||
203 | expect![[r#" | ||
204 | 75..99 '{ ... }': Gen<T> | ||
205 | 85..93 'loop { }': ! | ||
206 | 90..93 '{ }': () | ||
207 | 113..148 '{ ...e(); }': () | ||
208 | 123..124 'a': Gen<u32> | ||
209 | 127..143 'Gen::<...::make': fn make<u32>() -> Gen<u32> | ||
210 | 127..145 'Gen::<...make()': Gen<u32> | ||
211 | "#]], | ||
212 | ); | ||
213 | } | ||
214 | |||
215 | #[test] | ||
216 | fn infer_associated_method_generics_2_type_params_without_args() { | ||
217 | check_infer( | ||
218 | r#" | ||
219 | struct Gen<T, U> { | ||
220 | val: T, | ||
221 | val2: U, | ||
222 | } | ||
223 | |||
224 | impl<T> Gen<u32, T> { | ||
225 | pub fn make() -> Gen<u32,T> { | ||
226 | loop { } | ||
227 | } | ||
228 | } | ||
229 | |||
230 | fn test() { | ||
231 | let a = Gen::<u32, u64>::make(); | ||
232 | } | ||
233 | "#, | ||
234 | expect![[r#" | ||
235 | 101..125 '{ ... }': Gen<u32, T> | ||
236 | 111..119 'loop { }': ! | ||
237 | 116..119 '{ }': () | ||
238 | 139..179 '{ ...e(); }': () | ||
239 | 149..150 'a': Gen<u32, u64> | ||
240 | 153..174 'Gen::<...::make': fn make<u64>() -> Gen<u32, u64> | ||
241 | 153..176 'Gen::<...make()': Gen<u32, u64> | ||
242 | "#]], | ||
243 | ); | ||
244 | } | ||
245 | |||
246 | #[test] | ||
247 | fn cross_crate_associated_method_call() { | ||
248 | check_types( | ||
249 | r#" | ||
250 | //- /main.rs crate:main deps:other_crate | ||
251 | fn test() { | ||
252 | let x = other_crate::foo::S::thing(); | ||
253 | x; | ||
254 | } //^ i128 | ||
255 | |||
256 | //- /lib.rs crate:other_crate | ||
257 | mod foo { | ||
258 | struct S; | ||
259 | impl S { | ||
260 | fn thing() -> i128 {} | ||
261 | } | ||
262 | } | ||
263 | "#, | ||
264 | ); | ||
265 | } | ||
266 | |||
267 | #[test] | ||
268 | fn infer_trait_method_simple() { | ||
269 | // the trait implementation is intentionally incomplete -- it shouldn't matter | ||
270 | check_infer( | ||
271 | r#" | ||
272 | trait Trait1 { | ||
273 | fn method(&self) -> u32; | ||
274 | } | ||
275 | struct S1; | ||
276 | impl Trait1 for S1 {} | ||
277 | trait Trait2 { | ||
278 | fn method(&self) -> i128; | ||
279 | } | ||
280 | struct S2; | ||
281 | impl Trait2 for S2 {} | ||
282 | fn test() { | ||
283 | S1.method(); // -> u32 | ||
284 | S2.method(); // -> i128 | ||
285 | } | ||
286 | "#, | ||
287 | expect![[r#" | ||
288 | 30..34 'self': &Self | ||
289 | 109..113 'self': &Self | ||
290 | 169..227 '{ ...i128 }': () | ||
291 | 175..177 'S1': S1 | ||
292 | 175..186 'S1.method()': u32 | ||
293 | 202..204 'S2': S2 | ||
294 | 202..213 'S2.method()': i128 | ||
295 | "#]], | ||
296 | ); | ||
297 | } | ||
298 | |||
299 | #[test] | ||
300 | fn infer_trait_method_scoped() { | ||
301 | // the trait implementation is intentionally incomplete -- it shouldn't matter | ||
302 | check_infer( | ||
303 | r#" | ||
304 | struct S; | ||
305 | mod foo { | ||
306 | pub trait Trait1 { | ||
307 | fn method(&self) -> u32; | ||
308 | } | ||
309 | impl Trait1 for super::S {} | ||
310 | } | ||
311 | mod bar { | ||
312 | pub trait Trait2 { | ||
313 | fn method(&self) -> i128; | ||
314 | } | ||
315 | impl Trait2 for super::S {} | ||
316 | } | ||
317 | |||
318 | mod foo_test { | ||
319 | use super::S; | ||
320 | use super::foo::Trait1; | ||
321 | fn test() { | ||
322 | S.method(); // -> u32 | ||
323 | } | ||
324 | } | ||
325 | |||
326 | mod bar_test { | ||
327 | use super::S; | ||
328 | use super::bar::Trait2; | ||
329 | fn test() { | ||
330 | S.method(); // -> i128 | ||
331 | } | ||
332 | } | ||
333 | "#, | ||
334 | expect![[r#" | ||
335 | 62..66 'self': &Self | ||
336 | 168..172 'self': &Self | ||
337 | 299..336 '{ ... }': () | ||
338 | 309..310 'S': S | ||
339 | 309..319 'S.method()': u32 | ||
340 | 415..453 '{ ... }': () | ||
341 | 425..426 'S': S | ||
342 | 425..435 'S.method()': i128 | ||
343 | "#]], | ||
344 | ); | ||
345 | } | ||
346 | |||
347 | #[test] | ||
348 | fn infer_trait_method_generic_1() { | ||
349 | // the trait implementation is intentionally incomplete -- it shouldn't matter | ||
350 | check_infer( | ||
351 | r#" | ||
352 | trait Trait<T> { | ||
353 | fn method(&self) -> T; | ||
354 | } | ||
355 | struct S; | ||
356 | impl Trait<u32> for S {} | ||
357 | fn test() { | ||
358 | S.method(); | ||
359 | } | ||
360 | "#, | ||
361 | expect![[r#" | ||
362 | 32..36 'self': &Self | ||
363 | 91..110 '{ ...d(); }': () | ||
364 | 97..98 'S': S | ||
365 | 97..107 'S.method()': u32 | ||
366 | "#]], | ||
367 | ); | ||
368 | } | ||
369 | |||
370 | #[test] | ||
371 | fn infer_trait_method_generic_more_params() { | ||
372 | // the trait implementation is intentionally incomplete -- it shouldn't matter | ||
373 | check_infer( | ||
374 | r#" | ||
375 | trait Trait<T1, T2, T3> { | ||
376 | fn method1(&self) -> (T1, T2, T3); | ||
377 | fn method2(&self) -> (T3, T2, T1); | ||
378 | } | ||
379 | struct S1; | ||
380 | impl Trait<u8, u16, u32> for S1 {} | ||
381 | struct S2; | ||
382 | impl<T> Trait<i8, i16, T> for S2 {} | ||
383 | fn test() { | ||
384 | S1.method1(); // u8, u16, u32 | ||
385 | S1.method2(); // u32, u16, u8 | ||
386 | S2.method1(); // i8, i16, {unknown} | ||
387 | S2.method2(); // {unknown}, i16, i8 | ||
388 | } | ||
389 | "#, | ||
390 | expect![[r#" | ||
391 | 42..46 'self': &Self | ||
392 | 81..85 'self': &Self | ||
393 | 209..360 '{ ..., i8 }': () | ||
394 | 215..217 'S1': S1 | ||
395 | 215..227 'S1.method1()': (u8, u16, u32) | ||
396 | 249..251 'S1': S1 | ||
397 | 249..261 'S1.method2()': (u32, u16, u8) | ||
398 | 283..285 'S2': S2 | ||
399 | 283..295 'S2.method1()': (i8, i16, {unknown}) | ||
400 | 323..325 'S2': S2 | ||
401 | 323..335 'S2.method2()': ({unknown}, i16, i8) | ||
402 | "#]], | ||
403 | ); | ||
404 | } | ||
405 | |||
406 | #[test] | ||
407 | fn infer_trait_method_generic_2() { | ||
408 | // the trait implementation is intentionally incomplete -- it shouldn't matter | ||
409 | check_infer( | ||
410 | r#" | ||
411 | trait Trait<T> { | ||
412 | fn method(&self) -> T; | ||
413 | } | ||
414 | struct S<T>(T); | ||
415 | impl<U> Trait<U> for S<U> {} | ||
416 | fn test() { | ||
417 | S(1u32).method(); | ||
418 | } | ||
419 | "#, | ||
420 | expect![[r#" | ||
421 | 32..36 'self': &Self | ||
422 | 101..126 '{ ...d(); }': () | ||
423 | 107..108 'S': S<u32>(u32) -> S<u32> | ||
424 | 107..114 'S(1u32)': S<u32> | ||
425 | 107..123 'S(1u32...thod()': u32 | ||
426 | 109..113 '1u32': u32 | ||
427 | "#]], | ||
428 | ); | ||
429 | } | ||
430 | |||
431 | #[test] | ||
432 | fn infer_trait_assoc_method() { | ||
433 | check_infer( | ||
434 | r#" | ||
435 | trait Default { | ||
436 | fn default() -> Self; | ||
437 | } | ||
438 | struct S; | ||
439 | impl Default for S {} | ||
440 | fn test() { | ||
441 | let s1: S = Default::default(); | ||
442 | let s2 = S::default(); | ||
443 | let s3 = <S as Default>::default(); | ||
444 | } | ||
445 | "#, | ||
446 | expect![[r#" | ||
447 | 86..192 '{ ...t(); }': () | ||
448 | 96..98 's1': S | ||
449 | 104..120 'Defaul...efault': fn default<S>() -> S | ||
450 | 104..122 'Defaul...ault()': S | ||
451 | 132..134 's2': S | ||
452 | 137..147 'S::default': fn default<S>() -> S | ||
453 | 137..149 'S::default()': S | ||
454 | 159..161 's3': S | ||
455 | 164..187 '<S as ...efault': fn default<S>() -> S | ||
456 | 164..189 '<S as ...ault()': S | ||
457 | "#]], | ||
458 | ); | ||
459 | } | ||
460 | |||
461 | #[test] | ||
462 | fn infer_trait_assoc_method_generics_1() { | ||
463 | check_infer( | ||
464 | r#" | ||
465 | trait Trait<T> { | ||
466 | fn make() -> T; | ||
467 | } | ||
468 | struct S; | ||
469 | impl Trait<u32> for S {} | ||
470 | struct G<T>; | ||
471 | impl<T> Trait<T> for G<T> {} | ||
472 | fn test() { | ||
473 | let a = S::make(); | ||
474 | let b = G::<u64>::make(); | ||
475 | let c: f64 = G::make(); | ||
476 | } | ||
477 | "#, | ||
478 | expect![[r#" | ||
479 | 126..210 '{ ...e(); }': () | ||
480 | 136..137 'a': u32 | ||
481 | 140..147 'S::make': fn make<S, u32>() -> u32 | ||
482 | 140..149 'S::make()': u32 | ||
483 | 159..160 'b': u64 | ||
484 | 163..177 'G::<u64>::make': fn make<G<u64>, u64>() -> u64 | ||
485 | 163..179 'G::<u6...make()': u64 | ||
486 | 189..190 'c': f64 | ||
487 | 198..205 'G::make': fn make<G<f64>, f64>() -> f64 | ||
488 | 198..207 'G::make()': f64 | ||
489 | "#]], | ||
490 | ); | ||
491 | } | ||
492 | |||
493 | #[test] | ||
494 | fn infer_trait_assoc_method_generics_2() { | ||
495 | check_infer( | ||
496 | r#" | ||
497 | trait Trait<T> { | ||
498 | fn make<U>() -> (T, U); | ||
499 | } | ||
500 | struct S; | ||
501 | impl Trait<u32> for S {} | ||
502 | struct G<T>; | ||
503 | impl<T> Trait<T> for G<T> {} | ||
504 | fn test() { | ||
505 | let a = S::make::<i64>(); | ||
506 | let b: (_, i64) = S::make(); | ||
507 | let c = G::<u32>::make::<i64>(); | ||
508 | let d: (u32, _) = G::make::<i64>(); | ||
509 | let e: (u32, i64) = G::make(); | ||
510 | } | ||
511 | "#, | ||
512 | expect![[r#" | ||
513 | 134..312 '{ ...e(); }': () | ||
514 | 144..145 'a': (u32, i64) | ||
515 | 148..162 'S::make::<i64>': fn make<S, u32, i64>() -> (u32, i64) | ||
516 | 148..164 'S::mak...i64>()': (u32, i64) | ||
517 | 174..175 'b': (u32, i64) | ||
518 | 188..195 'S::make': fn make<S, u32, i64>() -> (u32, i64) | ||
519 | 188..197 'S::make()': (u32, i64) | ||
520 | 207..208 'c': (u32, i64) | ||
521 | 211..232 'G::<u3...:<i64>': fn make<G<u32>, u32, i64>() -> (u32, i64) | ||
522 | 211..234 'G::<u3...i64>()': (u32, i64) | ||
523 | 244..245 'd': (u32, i64) | ||
524 | 258..272 'G::make::<i64>': fn make<G<u32>, u32, i64>() -> (u32, i64) | ||
525 | 258..274 'G::mak...i64>()': (u32, i64) | ||
526 | 284..285 'e': (u32, i64) | ||
527 | 300..307 'G::make': fn make<G<u32>, u32, i64>() -> (u32, i64) | ||
528 | 300..309 'G::make()': (u32, i64) | ||
529 | "#]], | ||
530 | ); | ||
531 | } | ||
532 | |||
533 | #[test] | ||
534 | fn infer_trait_assoc_method_generics_3() { | ||
535 | check_infer( | ||
536 | r#" | ||
537 | trait Trait<T> { | ||
538 | fn make() -> (Self, T); | ||
539 | } | ||
540 | struct S<T>; | ||
541 | impl Trait<i64> for S<i32> {} | ||
542 | fn test() { | ||
543 | let a = S::make(); | ||
544 | } | ||
545 | "#, | ||
546 | expect![[r#" | ||
547 | 100..126 '{ ...e(); }': () | ||
548 | 110..111 'a': (S<i32>, i64) | ||
549 | 114..121 'S::make': fn make<S<i32>, i64>() -> (S<i32>, i64) | ||
550 | 114..123 'S::make()': (S<i32>, i64) | ||
551 | "#]], | ||
552 | ); | ||
553 | } | ||
554 | |||
555 | #[test] | ||
556 | fn infer_trait_assoc_method_generics_4() { | ||
557 | check_infer( | ||
558 | r#" | ||
559 | trait Trait<T> { | ||
560 | fn make() -> (Self, T); | ||
561 | } | ||
562 | struct S<T>; | ||
563 | impl Trait<i64> for S<u64> {} | ||
564 | impl Trait<i32> for S<u32> {} | ||
565 | fn test() { | ||
566 | let a: (S<u64>, _) = S::make(); | ||
567 | let b: (_, i32) = S::make(); | ||
568 | } | ||
569 | "#, | ||
570 | expect![[r#" | ||
571 | 130..202 '{ ...e(); }': () | ||
572 | 140..141 'a': (S<u64>, i64) | ||
573 | 157..164 'S::make': fn make<S<u64>, i64>() -> (S<u64>, i64) | ||
574 | 157..166 'S::make()': (S<u64>, i64) | ||
575 | 176..177 'b': (S<u32>, i32) | ||
576 | 190..197 'S::make': fn make<S<u32>, i32>() -> (S<u32>, i32) | ||
577 | 190..199 'S::make()': (S<u32>, i32) | ||
578 | "#]], | ||
579 | ); | ||
580 | } | ||
581 | |||
582 | #[test] | ||
583 | fn infer_trait_assoc_method_generics_5() { | ||
584 | check_infer( | ||
585 | r#" | ||
586 | trait Trait<T> { | ||
587 | fn make<U>() -> (Self, T, U); | ||
588 | } | ||
589 | struct S<T>; | ||
590 | impl Trait<i64> for S<u64> {} | ||
591 | fn test() { | ||
592 | let a = <S as Trait<i64>>::make::<u8>(); | ||
593 | let b: (S<u64>, _, _) = Trait::<i64>::make::<u8>(); | ||
594 | } | ||
595 | "#, | ||
596 | expect![[r#" | ||
597 | 106..210 '{ ...>(); }': () | ||
598 | 116..117 'a': (S<u64>, i64, u8) | ||
599 | 120..149 '<S as ...::<u8>': fn make<S<u64>, i64, u8>() -> (S<u64>, i64, u8) | ||
600 | 120..151 '<S as ...<u8>()': (S<u64>, i64, u8) | ||
601 | 161..162 'b': (S<u64>, i64, u8) | ||
602 | 181..205 'Trait:...::<u8>': fn make<S<u64>, i64, u8>() -> (S<u64>, i64, u8) | ||
603 | 181..207 'Trait:...<u8>()': (S<u64>, i64, u8) | ||
604 | "#]], | ||
605 | ); | ||
606 | } | ||
607 | |||
608 | #[test] | ||
609 | fn infer_call_trait_method_on_generic_param_1() { | ||
610 | check_infer( | ||
611 | r#" | ||
612 | trait Trait { | ||
613 | fn method(&self) -> u32; | ||
614 | } | ||
615 | fn test<T: Trait>(t: T) { | ||
616 | t.method(); | ||
617 | } | ||
618 | "#, | ||
619 | expect![[r#" | ||
620 | 29..33 'self': &Self | ||
621 | 63..64 't': T | ||
622 | 69..88 '{ ...d(); }': () | ||
623 | 75..76 't': T | ||
624 | 75..85 't.method()': u32 | ||
625 | "#]], | ||
626 | ); | ||
627 | } | ||
628 | |||
629 | #[test] | ||
630 | fn infer_call_trait_method_on_generic_param_2() { | ||
631 | check_infer( | ||
632 | r#" | ||
633 | trait Trait<T> { | ||
634 | fn method(&self) -> T; | ||
635 | } | ||
636 | fn test<U, T: Trait<U>>(t: T) { | ||
637 | t.method(); | ||
638 | } | ||
639 | "#, | ||
640 | expect![[r#" | ||
641 | 32..36 'self': &Self | ||
642 | 70..71 't': T | ||
643 | 76..95 '{ ...d(); }': () | ||
644 | 82..83 't': T | ||
645 | 82..92 't.method()': U | ||
646 | "#]], | ||
647 | ); | ||
648 | } | ||
649 | |||
650 | #[test] | ||
651 | fn infer_with_multiple_trait_impls() { | ||
652 | check_infer( | ||
653 | r#" | ||
654 | trait Into<T> { | ||
655 | fn into(self) -> T; | ||
656 | } | ||
657 | struct S; | ||
658 | impl Into<u32> for S {} | ||
659 | impl Into<u64> for S {} | ||
660 | fn test() { | ||
661 | let x: u32 = S.into(); | ||
662 | let y: u64 = S.into(); | ||
663 | let z = Into::<u64>::into(S); | ||
664 | } | ||
665 | "#, | ||
666 | expect![[r#" | ||
667 | 28..32 'self': Self | ||
668 | 110..201 '{ ...(S); }': () | ||
669 | 120..121 'x': u32 | ||
670 | 129..130 'S': S | ||
671 | 129..137 'S.into()': u32 | ||
672 | 147..148 'y': u64 | ||
673 | 156..157 'S': S | ||
674 | 156..164 'S.into()': u64 | ||
675 | 174..175 'z': u64 | ||
676 | 178..195 'Into::...::into': fn into<S, u64>(S) -> u64 | ||
677 | 178..198 'Into::...nto(S)': u64 | ||
678 | 196..197 'S': S | ||
679 | "#]], | ||
680 | ); | ||
681 | } | ||
682 | |||
683 | #[test] | ||
684 | fn method_resolution_unify_impl_self_type() { | ||
685 | check_types( | ||
686 | r#" | ||
687 | struct S<T>; | ||
688 | impl S<u32> { fn foo(&self) -> u8 {} } | ||
689 | impl S<i32> { fn foo(&self) -> i8 {} } | ||
690 | fn test() { (S::<u32>.foo(), S::<i32>.foo()); } | ||
691 | //^ (u8, i8) | ||
692 | "#, | ||
693 | ); | ||
694 | } | ||
695 | |||
696 | #[test] | ||
697 | fn method_resolution_trait_before_autoref() { | ||
698 | check_types( | ||
699 | r#" | ||
700 | trait Trait { fn foo(self) -> u128; } | ||
701 | struct S; | ||
702 | impl S { fn foo(&self) -> i8 { 0 } } | ||
703 | impl Trait for S { fn foo(self) -> u128 { 0 } } | ||
704 | fn test() { S.foo(); } | ||
705 | //^ u128 | ||
706 | "#, | ||
707 | ); | ||
708 | } | ||
709 | |||
710 | #[test] | ||
711 | fn method_resolution_by_value_before_autoref() { | ||
712 | check_types( | ||
713 | r#" | ||
714 | trait Clone { fn clone(&self) -> Self; } | ||
715 | struct S; | ||
716 | impl Clone for S {} | ||
717 | impl Clone for &S {} | ||
718 | fn test() { (S.clone(), (&S).clone(), (&&S).clone()); } | ||
719 | //^ (S, S, &S) | ||
720 | "#, | ||
721 | ); | ||
722 | } | ||
723 | |||
724 | #[test] | ||
725 | fn method_resolution_trait_before_autoderef() { | ||
726 | check_types( | ||
727 | r#" | ||
728 | trait Trait { fn foo(self) -> u128; } | ||
729 | struct S; | ||
730 | impl S { fn foo(self) -> i8 { 0 } } | ||
731 | impl Trait for &S { fn foo(self) -> u128 { 0 } } | ||
732 | fn test() { (&S).foo(); } | ||
733 | //^ u128 | ||
734 | "#, | ||
735 | ); | ||
736 | } | ||
737 | |||
738 | #[test] | ||
739 | fn method_resolution_impl_before_trait() { | ||
740 | check_types( | ||
741 | r#" | ||
742 | trait Trait { fn foo(self) -> u128; } | ||
743 | struct S; | ||
744 | impl S { fn foo(self) -> i8 { 0 } } | ||
745 | impl Trait for S { fn foo(self) -> u128 { 0 } } | ||
746 | fn test() { S.foo(); } | ||
747 | //^ i8 | ||
748 | "#, | ||
749 | ); | ||
750 | } | ||
751 | |||
752 | #[test] | ||
753 | fn method_resolution_impl_ref_before_trait() { | ||
754 | check_types( | ||
755 | r#" | ||
756 | trait Trait { fn foo(self) -> u128; } | ||
757 | struct S; | ||
758 | impl S { fn foo(&self) -> i8 { 0 } } | ||
759 | impl Trait for &S { fn foo(self) -> u128 { 0 } } | ||
760 | fn test() { S.foo(); } | ||
761 | //^ i8 | ||
762 | "#, | ||
763 | ); | ||
764 | } | ||
765 | |||
766 | #[test] | ||
767 | fn method_resolution_trait_autoderef() { | ||
768 | check_types( | ||
769 | r#" | ||
770 | trait Trait { fn foo(self) -> u128; } | ||
771 | struct S; | ||
772 | impl Trait for S { fn foo(self) -> u128 { 0 } } | ||
773 | fn test() { (&S).foo(); } | ||
774 | //^ u128 | ||
775 | "#, | ||
776 | ); | ||
777 | } | ||
778 | |||
779 | #[test] | ||
780 | fn method_resolution_unsize_array() { | ||
781 | check_types( | ||
782 | r#" | ||
783 | #[lang = "slice"] | ||
784 | impl<T> [T] { | ||
785 | fn len(&self) -> usize { loop {} } | ||
786 | } | ||
787 | fn test() { | ||
788 | let a = [1, 2, 3]; | ||
789 | a.len(); | ||
790 | } //^ usize | ||
791 | "#, | ||
792 | ); | ||
793 | } | ||
794 | |||
795 | #[test] | ||
796 | fn method_resolution_trait_from_prelude() { | ||
797 | check_types( | ||
798 | r#" | ||
799 | //- /main.rs crate:main deps:other_crate | ||
800 | struct S; | ||
801 | impl Clone for S {} | ||
802 | |||
803 | fn test() { | ||
804 | S.clone(); | ||
805 | //^ S | ||
806 | } | ||
807 | |||
808 | //- /lib.rs crate:other_crate | ||
809 | #[prelude_import] use foo::*; | ||
810 | |||
811 | mod foo { | ||
812 | trait Clone { | ||
813 | fn clone(&self) -> Self; | ||
814 | } | ||
815 | } | ||
816 | "#, | ||
817 | ); | ||
818 | } | ||
819 | |||
820 | #[test] | ||
821 | fn method_resolution_where_clause_for_unknown_trait() { | ||
822 | // The blanket impl currently applies because we ignore the unresolved where clause | ||
823 | check_types( | ||
824 | r#" | ||
825 | trait Trait { fn foo(self) -> u128; } | ||
826 | struct S; | ||
827 | impl<T> Trait for T where T: UnknownTrait {} | ||
828 | fn test() { (&S).foo(); } | ||
829 | //^ u128 | ||
830 | "#, | ||
831 | ); | ||
832 | } | ||
833 | |||
834 | #[test] | ||
835 | fn method_resolution_where_clause_not_met() { | ||
836 | // The blanket impl shouldn't apply because we can't prove S: Clone | ||
837 | // This is also to make sure that we don't resolve to the foo method just | ||
838 | // because that's the only method named foo we can find, which would make | ||
839 | // the below tests not work | ||
840 | check_types( | ||
841 | r#" | ||
842 | trait Clone {} | ||
843 | trait Trait { fn foo(self) -> u128; } | ||
844 | struct S; | ||
845 | impl<T> Trait for T where T: Clone {} | ||
846 | fn test() { (&S).foo(); } | ||
847 | //^ {unknown} | ||
848 | "#, | ||
849 | ); | ||
850 | } | ||
851 | |||
852 | #[test] | ||
853 | fn method_resolution_where_clause_inline_not_met() { | ||
854 | // The blanket impl shouldn't apply because we can't prove S: Clone | ||
855 | check_types( | ||
856 | r#" | ||
857 | trait Clone {} | ||
858 | trait Trait { fn foo(self) -> u128; } | ||
859 | struct S; | ||
860 | impl<T: Clone> Trait for T {} | ||
861 | fn test() { (&S).foo(); } | ||
862 | //^ {unknown} | ||
863 | "#, | ||
864 | ); | ||
865 | } | ||
866 | |||
867 | #[test] | ||
868 | fn method_resolution_where_clause_1() { | ||
869 | check_types( | ||
870 | r#" | ||
871 | trait Clone {} | ||
872 | trait Trait { fn foo(self) -> u128; } | ||
873 | struct S; | ||
874 | impl Clone for S {} | ||
875 | impl<T> Trait for T where T: Clone {} | ||
876 | fn test() { S.foo(); } | ||
877 | //^ u128 | ||
878 | "#, | ||
879 | ); | ||
880 | } | ||
881 | |||
882 | #[test] | ||
883 | fn method_resolution_where_clause_2() { | ||
884 | check_types( | ||
885 | r#" | ||
886 | trait Into<T> { fn into(self) -> T; } | ||
887 | trait From<T> { fn from(other: T) -> Self; } | ||
888 | struct S1; | ||
889 | struct S2; | ||
890 | impl From<S2> for S1 {} | ||
891 | impl<T, U> Into<U> for T where U: From<T> {} | ||
892 | fn test() { S2.into(); } | ||
893 | //^ {unknown} | ||
894 | "#, | ||
895 | ); | ||
896 | } | ||
897 | |||
898 | #[test] | ||
899 | fn method_resolution_where_clause_inline() { | ||
900 | check_types( | ||
901 | r#" | ||
902 | trait Into<T> { fn into(self) -> T; } | ||
903 | trait From<T> { fn from(other: T) -> Self; } | ||
904 | struct S1; | ||
905 | struct S2; | ||
906 | impl From<S2> for S1 {} | ||
907 | impl<T, U: From<T>> Into<U> for T {} | ||
908 | fn test() { S2.into(); } | ||
909 | //^ {unknown} | ||
910 | "#, | ||
911 | ); | ||
912 | } | ||
913 | |||
914 | #[test] | ||
915 | fn method_resolution_overloaded_method() { | ||
916 | test_utils::mark::check!(impl_self_type_match_without_receiver); | ||
917 | check_types( | ||
918 | r#" | ||
919 | struct Wrapper<T>(T); | ||
920 | struct Foo<T>(T); | ||
921 | struct Bar<T>(T); | ||
922 | |||
923 | impl<T> Wrapper<Foo<T>> { | ||
924 | pub fn new(foo_: T) -> Self { | ||
925 | Wrapper(Foo(foo_)) | ||
926 | } | ||
927 | } | ||
928 | |||
929 | impl<T> Wrapper<Bar<T>> { | ||
930 | pub fn new(bar_: T) -> Self { | ||
931 | Wrapper(Bar(bar_)) | ||
932 | } | ||
933 | } | ||
934 | |||
935 | fn main() { | ||
936 | let a = Wrapper::<Foo<f32>>::new(1.0); | ||
937 | let b = Wrapper::<Bar<f32>>::new(1.0); | ||
938 | (a, b); | ||
939 | //^ (Wrapper<Foo<f32>>, Wrapper<Bar<f32>>) | ||
940 | } | ||
941 | "#, | ||
942 | ); | ||
943 | } | ||
944 | |||
945 | #[test] | ||
946 | fn method_resolution_encountering_fn_type() { | ||
947 | check_types( | ||
948 | r#" | ||
949 | //- /main.rs | ||
950 | fn foo() {} | ||
951 | trait FnOnce { fn call(self); } | ||
952 | fn test() { foo.call(); } | ||
953 | //^ {unknown} | ||
954 | "#, | ||
955 | ); | ||
956 | } | ||
957 | |||
958 | #[test] | ||
959 | fn method_resolution_non_parameter_type() { | ||
960 | check_types( | ||
961 | r#" | ||
962 | mod a { | ||
963 | pub trait Foo { | ||
964 | fn foo(&self); | ||
965 | } | ||
966 | } | ||
967 | |||
968 | struct Wrapper<T>(T); | ||
969 | fn foo<T>(t: Wrapper<T>) | ||
970 | where | ||
971 | Wrapper<T>: a::Foo, | ||
972 | { | ||
973 | t.foo(); | ||
974 | } //^ {unknown} | ||
975 | "#, | ||
976 | ); | ||
977 | } | ||
978 | |||
979 | #[test] | ||
980 | fn method_resolution_3373() { | ||
981 | check_types( | ||
982 | r#" | ||
983 | struct A<T>(T); | ||
984 | |||
985 | impl A<i32> { | ||
986 | fn from(v: i32) -> A<i32> { A(v) } | ||
987 | } | ||
988 | |||
989 | fn main() { | ||
990 | A::from(3); | ||
991 | } //^ A<i32> | ||
992 | "#, | ||
993 | ); | ||
994 | } | ||
995 | |||
996 | #[test] | ||
997 | fn method_resolution_slow() { | ||
998 | // this can get quite slow if we set the solver size limit too high | ||
999 | check_types( | ||
1000 | r#" | ||
1001 | trait SendX {} | ||
1002 | |||
1003 | struct S1; impl SendX for S1 {} | ||
1004 | struct S2; impl SendX for S2 {} | ||
1005 | struct U1; | ||
1006 | |||
1007 | trait Trait { fn method(self); } | ||
1008 | |||
1009 | struct X1<A, B> {} | ||
1010 | impl<A, B> SendX for X1<A, B> where A: SendX, B: SendX {} | ||
1011 | |||
1012 | struct S<B, C> {} | ||
1013 | |||
1014 | trait FnX {} | ||
1015 | |||
1016 | impl<B, C> Trait for S<B, C> where C: FnX, B: SendX {} | ||
1017 | |||
1018 | fn test() { (S {}).method(); } | ||
1019 | //^ () | ||
1020 | "#, | ||
1021 | ); | ||
1022 | } | ||
1023 | |||
1024 | #[test] | ||
1025 | fn dyn_trait_super_trait_not_in_scope() { | ||
1026 | check_infer( | ||
1027 | r#" | ||
1028 | mod m { | ||
1029 | pub trait SuperTrait { | ||
1030 | fn foo(&self) -> u32 { 0 } | ||
1031 | } | ||
1032 | } | ||
1033 | trait Trait: m::SuperTrait {} | ||
1034 | |||
1035 | struct S; | ||
1036 | impl m::SuperTrait for S {} | ||
1037 | impl Trait for S {} | ||
1038 | |||
1039 | fn test(d: &dyn Trait) { | ||
1040 | d.foo(); | ||
1041 | } | ||
1042 | "#, | ||
1043 | expect![[r#" | ||
1044 | 51..55 'self': &Self | ||
1045 | 64..69 '{ 0 }': u32 | ||
1046 | 66..67 '0': u32 | ||
1047 | 176..177 'd': &dyn Trait | ||
1048 | 191..207 '{ ...o(); }': () | ||
1049 | 197..198 'd': &dyn Trait | ||
1050 | 197..204 'd.foo()': u32 | ||
1051 | "#]], | ||
1052 | ); | ||
1053 | } | ||
diff --git a/crates/ra_hir_ty/src/tests/never_type.rs b/crates/ra_hir_ty/src/tests/never_type.rs deleted file mode 100644 index 49538b572..000000000 --- a/crates/ra_hir_ty/src/tests/never_type.rs +++ /dev/null | |||
@@ -1,409 +0,0 @@ | |||
1 | use expect::expect; | ||
2 | |||
3 | use super::{check_infer_with_mismatches, check_types}; | ||
4 | |||
5 | #[test] | ||
6 | fn infer_never1() { | ||
7 | check_types( | ||
8 | r#" | ||
9 | fn test() { | ||
10 | let t = return; | ||
11 | t; | ||
12 | } //^ ! | ||
13 | "#, | ||
14 | ); | ||
15 | } | ||
16 | |||
17 | #[test] | ||
18 | fn infer_never2() { | ||
19 | check_types( | ||
20 | r#" | ||
21 | fn gen<T>() -> T { loop {} } | ||
22 | |||
23 | fn test() { | ||
24 | let a = gen(); | ||
25 | if false { a } else { loop {} }; | ||
26 | a; | ||
27 | } //^ ! | ||
28 | "#, | ||
29 | ); | ||
30 | } | ||
31 | |||
32 | #[test] | ||
33 | fn infer_never3() { | ||
34 | check_types( | ||
35 | r#" | ||
36 | fn gen<T>() -> T { loop {} } | ||
37 | |||
38 | fn test() { | ||
39 | let a = gen(); | ||
40 | if false { loop {} } else { a }; | ||
41 | a; | ||
42 | //^ ! | ||
43 | } | ||
44 | "#, | ||
45 | ); | ||
46 | } | ||
47 | |||
48 | #[test] | ||
49 | fn never_type_in_generic_args() { | ||
50 | check_types( | ||
51 | r#" | ||
52 | enum Option<T> { None, Some(T) } | ||
53 | |||
54 | fn test() { | ||
55 | let a = if true { Option::None } else { Option::Some(return) }; | ||
56 | a; | ||
57 | } //^ Option<!> | ||
58 | "#, | ||
59 | ); | ||
60 | } | ||
61 | |||
62 | #[test] | ||
63 | fn never_type_can_be_reinferred1() { | ||
64 | check_types( | ||
65 | r#" | ||
66 | fn gen<T>() -> T { loop {} } | ||
67 | |||
68 | fn test() { | ||
69 | let a = gen(); | ||
70 | if false { loop {} } else { a }; | ||
71 | a; | ||
72 | //^ () | ||
73 | if false { a }; | ||
74 | } | ||
75 | "#, | ||
76 | ); | ||
77 | } | ||
78 | |||
79 | #[test] | ||
80 | fn never_type_can_be_reinferred2() { | ||
81 | check_types( | ||
82 | r#" | ||
83 | enum Option<T> { None, Some(T) } | ||
84 | |||
85 | fn test() { | ||
86 | let a = if true { Option::None } else { Option::Some(return) }; | ||
87 | a; | ||
88 | //^ Option<i32> | ||
89 | match 42 { | ||
90 | 42 => a, | ||
91 | _ => Option::Some(42), | ||
92 | }; | ||
93 | } | ||
94 | "#, | ||
95 | ); | ||
96 | } | ||
97 | |||
98 | #[test] | ||
99 | fn never_type_can_be_reinferred3() { | ||
100 | check_types( | ||
101 | r#" | ||
102 | enum Option<T> { None, Some(T) } | ||
103 | |||
104 | fn test() { | ||
105 | let a = if true { Option::None } else { Option::Some(return) }; | ||
106 | a; | ||
107 | //^ Option<&str> | ||
108 | match 42 { | ||
109 | 42 => a, | ||
110 | _ => Option::Some("str"), | ||
111 | }; | ||
112 | } | ||
113 | "#, | ||
114 | ); | ||
115 | } | ||
116 | |||
117 | #[test] | ||
118 | fn match_no_arm() { | ||
119 | check_types( | ||
120 | r#" | ||
121 | enum Void {} | ||
122 | |||
123 | fn test(a: Void) { | ||
124 | let t = match a {}; | ||
125 | t; | ||
126 | } //^ ! | ||
127 | "#, | ||
128 | ); | ||
129 | } | ||
130 | |||
131 | #[test] | ||
132 | fn match_unknown_arm() { | ||
133 | check_types( | ||
134 | r#" | ||
135 | fn test(a: Option) { | ||
136 | let t = match 0 { | ||
137 | _ => unknown, | ||
138 | }; | ||
139 | t; | ||
140 | } //^ {unknown} | ||
141 | "#, | ||
142 | ); | ||
143 | } | ||
144 | |||
145 | #[test] | ||
146 | fn if_never() { | ||
147 | check_types( | ||
148 | r#" | ||
149 | fn test() { | ||
150 | let i = if true { | ||
151 | loop {} | ||
152 | } else { | ||
153 | 3.0 | ||
154 | }; | ||
155 | i; | ||
156 | } //^ f64 | ||
157 | "#, | ||
158 | ); | ||
159 | } | ||
160 | |||
161 | #[test] | ||
162 | fn if_else_never() { | ||
163 | check_types( | ||
164 | r#" | ||
165 | fn test(input: bool) { | ||
166 | let i = if input { | ||
167 | 2.0 | ||
168 | } else { | ||
169 | return | ||
170 | }; | ||
171 | i; | ||
172 | } //^ f64 | ||
173 | "#, | ||
174 | ); | ||
175 | } | ||
176 | |||
177 | #[test] | ||
178 | fn match_first_arm_never() { | ||
179 | check_types( | ||
180 | r#" | ||
181 | fn test(a: i32) { | ||
182 | let i = match a { | ||
183 | 1 => return, | ||
184 | 2 => 2.0, | ||
185 | 3 => loop {}, | ||
186 | _ => 3.0, | ||
187 | }; | ||
188 | i; | ||
189 | } //^ f64 | ||
190 | "#, | ||
191 | ); | ||
192 | } | ||
193 | |||
194 | #[test] | ||
195 | fn match_second_arm_never() { | ||
196 | check_types( | ||
197 | r#" | ||
198 | fn test(a: i32) { | ||
199 | let i = match a { | ||
200 | 1 => 3.0, | ||
201 | 2 => loop {}, | ||
202 | 3 => 3.0, | ||
203 | _ => return, | ||
204 | }; | ||
205 | i; | ||
206 | } //^ f64 | ||
207 | "#, | ||
208 | ); | ||
209 | } | ||
210 | |||
211 | #[test] | ||
212 | fn match_all_arms_never() { | ||
213 | check_types( | ||
214 | r#" | ||
215 | fn test(a: i32) { | ||
216 | let i = match a { | ||
217 | 2 => return, | ||
218 | _ => loop {}, | ||
219 | }; | ||
220 | i; | ||
221 | } //^ ! | ||
222 | "#, | ||
223 | ); | ||
224 | } | ||
225 | |||
226 | #[test] | ||
227 | fn match_no_never_arms() { | ||
228 | check_types( | ||
229 | r#" | ||
230 | fn test(a: i32) { | ||
231 | let i = match a { | ||
232 | 2 => 2.0, | ||
233 | _ => 3.0, | ||
234 | }; | ||
235 | i; | ||
236 | } //^ f64 | ||
237 | "#, | ||
238 | ); | ||
239 | } | ||
240 | |||
241 | #[test] | ||
242 | fn diverging_expression_1() { | ||
243 | check_infer_with_mismatches( | ||
244 | r" | ||
245 | //- /main.rs | ||
246 | fn test1() { | ||
247 | let x: u32 = return; | ||
248 | } | ||
249 | fn test2() { | ||
250 | let x: u32 = { return; }; | ||
251 | } | ||
252 | fn test3() { | ||
253 | let x: u32 = loop {}; | ||
254 | } | ||
255 | fn test4() { | ||
256 | let x: u32 = { loop {} }; | ||
257 | } | ||
258 | fn test5() { | ||
259 | let x: u32 = { if true { loop {}; } else { loop {}; } }; | ||
260 | } | ||
261 | fn test6() { | ||
262 | let x: u32 = { let y: u32 = { loop {}; }; }; | ||
263 | } | ||
264 | ", | ||
265 | expect![[r" | ||
266 | 11..39 '{ ...urn; }': () | ||
267 | 21..22 'x': u32 | ||
268 | 30..36 'return': ! | ||
269 | 51..84 '{ ...; }; }': () | ||
270 | 61..62 'x': u32 | ||
271 | 70..81 '{ return; }': u32 | ||
272 | 72..78 'return': ! | ||
273 | 96..125 '{ ... {}; }': () | ||
274 | 106..107 'x': u32 | ||
275 | 115..122 'loop {}': ! | ||
276 | 120..122 '{}': () | ||
277 | 137..170 '{ ...} }; }': () | ||
278 | 147..148 'x': u32 | ||
279 | 156..167 '{ loop {} }': u32 | ||
280 | 158..165 'loop {}': ! | ||
281 | 163..165 '{}': () | ||
282 | 182..246 '{ ...} }; }': () | ||
283 | 192..193 'x': u32 | ||
284 | 201..243 '{ if t...}; } }': u32 | ||
285 | 203..241 'if tru... {}; }': u32 | ||
286 | 206..210 'true': bool | ||
287 | 211..223 '{ loop {}; }': u32 | ||
288 | 213..220 'loop {}': ! | ||
289 | 218..220 '{}': () | ||
290 | 229..241 '{ loop {}; }': u32 | ||
291 | 231..238 'loop {}': ! | ||
292 | 236..238 '{}': () | ||
293 | 258..310 '{ ...; }; }': () | ||
294 | 268..269 'x': u32 | ||
295 | 277..307 '{ let ...; }; }': u32 | ||
296 | 283..284 'y': u32 | ||
297 | 292..304 '{ loop {}; }': u32 | ||
298 | 294..301 'loop {}': ! | ||
299 | 299..301 '{}': () | ||
300 | "]], | ||
301 | ); | ||
302 | } | ||
303 | |||
304 | #[test] | ||
305 | fn diverging_expression_2() { | ||
306 | check_infer_with_mismatches( | ||
307 | r#" | ||
308 | //- /main.rs | ||
309 | fn test1() { | ||
310 | // should give type mismatch | ||
311 | let x: u32 = { loop {}; "foo" }; | ||
312 | } | ||
313 | "#, | ||
314 | expect![[r#" | ||
315 | 11..84 '{ ..." }; }': () | ||
316 | 54..55 'x': u32 | ||
317 | 63..81 '{ loop...foo" }': &str | ||
318 | 65..72 'loop {}': ! | ||
319 | 70..72 '{}': () | ||
320 | 74..79 '"foo"': &str | ||
321 | 63..81: expected u32, got &str | ||
322 | 74..79: expected u32, got &str | ||
323 | "#]], | ||
324 | ); | ||
325 | } | ||
326 | |||
327 | #[test] | ||
328 | fn diverging_expression_3_break() { | ||
329 | check_infer_with_mismatches( | ||
330 | r" | ||
331 | //- /main.rs | ||
332 | fn test1() { | ||
333 | // should give type mismatch | ||
334 | let x: u32 = { loop { break; } }; | ||
335 | } | ||
336 | fn test2() { | ||
337 | // should give type mismatch | ||
338 | let x: u32 = { for a in b { break; }; }; | ||
339 | // should give type mismatch as well | ||
340 | let x: u32 = { for a in b {}; }; | ||
341 | // should give type mismatch as well | ||
342 | let x: u32 = { for a in b { return; }; }; | ||
343 | } | ||
344 | fn test3() { | ||
345 | // should give type mismatch | ||
346 | let x: u32 = { while true { break; }; }; | ||
347 | // should give type mismatch as well -- there's an implicit break, even if it's never hit | ||
348 | let x: u32 = { while true {}; }; | ||
349 | // should give type mismatch as well | ||
350 | let x: u32 = { while true { return; }; }; | ||
351 | } | ||
352 | ", | ||
353 | expect![[r" | ||
354 | 11..85 '{ ...} }; }': () | ||
355 | 54..55 'x': u32 | ||
356 | 63..82 '{ loop...k; } }': () | ||
357 | 65..80 'loop { break; }': () | ||
358 | 70..80 '{ break; }': () | ||
359 | 72..77 'break': ! | ||
360 | 63..82: expected u32, got () | ||
361 | 65..80: expected u32, got () | ||
362 | 97..343 '{ ...; }; }': () | ||
363 | 140..141 'x': u32 | ||
364 | 149..175 '{ for ...; }; }': () | ||
365 | 151..172 'for a ...eak; }': () | ||
366 | 155..156 'a': {unknown} | ||
367 | 160..161 'b': {unknown} | ||
368 | 162..172 '{ break; }': () | ||
369 | 164..169 'break': ! | ||
370 | 226..227 'x': u32 | ||
371 | 235..253 '{ for ... {}; }': () | ||
372 | 237..250 'for a in b {}': () | ||
373 | 241..242 'a': {unknown} | ||
374 | 246..247 'b': {unknown} | ||
375 | 248..250 '{}': () | ||
376 | 304..305 'x': u32 | ||
377 | 313..340 '{ for ...; }; }': () | ||
378 | 315..337 'for a ...urn; }': () | ||
379 | 319..320 'a': {unknown} | ||
380 | 324..325 'b': {unknown} | ||
381 | 326..337 '{ return; }': () | ||
382 | 328..334 'return': ! | ||
383 | 149..175: expected u32, got () | ||
384 | 235..253: expected u32, got () | ||
385 | 313..340: expected u32, got () | ||
386 | 355..654 '{ ...; }; }': () | ||
387 | 398..399 'x': u32 | ||
388 | 407..433 '{ whil...; }; }': () | ||
389 | 409..430 'while ...eak; }': () | ||
390 | 415..419 'true': bool | ||
391 | 420..430 '{ break; }': () | ||
392 | 422..427 'break': ! | ||
393 | 537..538 'x': u32 | ||
394 | 546..564 '{ whil... {}; }': () | ||
395 | 548..561 'while true {}': () | ||
396 | 554..558 'true': bool | ||
397 | 559..561 '{}': () | ||
398 | 615..616 'x': u32 | ||
399 | 624..651 '{ whil...; }; }': () | ||
400 | 626..648 'while ...urn; }': () | ||
401 | 632..636 'true': bool | ||
402 | 637..648 '{ return; }': () | ||
403 | 639..645 'return': ! | ||
404 | 407..433: expected u32, got () | ||
405 | 546..564: expected u32, got () | ||
406 | 624..651: expected u32, got () | ||
407 | "]], | ||
408 | ); | ||
409 | } | ||
diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs deleted file mode 100644 index 39fabf7eb..000000000 --- a/crates/ra_hir_ty/src/tests/patterns.rs +++ /dev/null | |||
@@ -1,656 +0,0 @@ | |||
1 | use expect::expect; | ||
2 | use test_utils::mark; | ||
3 | |||
4 | use super::{check_infer, check_infer_with_mismatches}; | ||
5 | |||
6 | #[test] | ||
7 | fn infer_pattern() { | ||
8 | check_infer( | ||
9 | r#" | ||
10 | fn test(x: &i32) { | ||
11 | let y = x; | ||
12 | let &z = x; | ||
13 | let a = z; | ||
14 | let (c, d) = (1, "hello"); | ||
15 | |||
16 | for (e, f) in some_iter { | ||
17 | let g = e; | ||
18 | } | ||
19 | |||
20 | if let [val] = opt { | ||
21 | let h = val; | ||
22 | } | ||
23 | |||
24 | let lambda = |a: u64, b, c: i32| { a + b; c }; | ||
25 | |||
26 | let ref ref_to_x = x; | ||
27 | let mut mut_x = x; | ||
28 | let ref mut mut_ref_to_x = x; | ||
29 | let k = mut_ref_to_x; | ||
30 | } | ||
31 | "#, | ||
32 | expect![[r#" | ||
33 | 8..9 'x': &i32 | ||
34 | 17..368 '{ ...o_x; }': () | ||
35 | 27..28 'y': &i32 | ||
36 | 31..32 'x': &i32 | ||
37 | 42..44 '&z': &i32 | ||
38 | 43..44 'z': i32 | ||
39 | 47..48 'x': &i32 | ||
40 | 58..59 'a': i32 | ||
41 | 62..63 'z': i32 | ||
42 | 73..79 '(c, d)': (i32, &str) | ||
43 | 74..75 'c': i32 | ||
44 | 77..78 'd': &str | ||
45 | 82..94 '(1, "hello")': (i32, &str) | ||
46 | 83..84 '1': i32 | ||
47 | 86..93 '"hello"': &str | ||
48 | 101..151 'for (e... }': () | ||
49 | 105..111 '(e, f)': ({unknown}, {unknown}) | ||
50 | 106..107 'e': {unknown} | ||
51 | 109..110 'f': {unknown} | ||
52 | 115..124 'some_iter': {unknown} | ||
53 | 125..151 '{ ... }': () | ||
54 | 139..140 'g': {unknown} | ||
55 | 143..144 'e': {unknown} | ||
56 | 157..204 'if let... }': () | ||
57 | 164..169 '[val]': [{unknown}] | ||
58 | 165..168 'val': {unknown} | ||
59 | 172..175 'opt': [{unknown}] | ||
60 | 176..204 '{ ... }': () | ||
61 | 190..191 'h': {unknown} | ||
62 | 194..197 'val': {unknown} | ||
63 | 214..220 'lambda': |u64, u64, i32| -> i32 | ||
64 | 223..255 '|a: u6...b; c }': |u64, u64, i32| -> i32 | ||
65 | 224..225 'a': u64 | ||
66 | 232..233 'b': u64 | ||
67 | 235..236 'c': i32 | ||
68 | 243..255 '{ a + b; c }': i32 | ||
69 | 245..246 'a': u64 | ||
70 | 245..250 'a + b': u64 | ||
71 | 249..250 'b': u64 | ||
72 | 252..253 'c': i32 | ||
73 | 266..278 'ref ref_to_x': &&i32 | ||
74 | 281..282 'x': &i32 | ||
75 | 292..301 'mut mut_x': &i32 | ||
76 | 304..305 'x': &i32 | ||
77 | 315..335 'ref mu...f_to_x': &mut &i32 | ||
78 | 338..339 'x': &i32 | ||
79 | 349..350 'k': &mut &i32 | ||
80 | 353..365 'mut_ref_to_x': &mut &i32 | ||
81 | "#]], | ||
82 | ); | ||
83 | } | ||
84 | |||
85 | #[test] | ||
86 | fn infer_literal_pattern() { | ||
87 | check_infer_with_mismatches( | ||
88 | r#" | ||
89 | fn any<T>() -> T { loop {} } | ||
90 | fn test(x: &i32) { | ||
91 | if let "foo" = any() {} | ||
92 | if let 1 = any() {} | ||
93 | if let 1u32 = any() {} | ||
94 | if let 1f32 = any() {} | ||
95 | if let 1.0 = any() {} | ||
96 | if let true = any() {} | ||
97 | } | ||
98 | "#, | ||
99 | expect![[r#" | ||
100 | 17..28 '{ loop {} }': T | ||
101 | 19..26 'loop {}': ! | ||
102 | 24..26 '{}': () | ||
103 | 37..38 'x': &i32 | ||
104 | 46..208 '{ ...) {} }': () | ||
105 | 52..75 'if let...y() {}': () | ||
106 | 59..64 '"foo"': &str | ||
107 | 59..64 '"foo"': &str | ||
108 | 67..70 'any': fn any<&str>() -> &str | ||
109 | 67..72 'any()': &str | ||
110 | 73..75 '{}': () | ||
111 | 80..99 'if let...y() {}': () | ||
112 | 87..88 '1': i32 | ||
113 | 87..88 '1': i32 | ||
114 | 91..94 'any': fn any<i32>() -> i32 | ||
115 | 91..96 'any()': i32 | ||
116 | 97..99 '{}': () | ||
117 | 104..126 'if let...y() {}': () | ||
118 | 111..115 '1u32': u32 | ||
119 | 111..115 '1u32': u32 | ||
120 | 118..121 'any': fn any<u32>() -> u32 | ||
121 | 118..123 'any()': u32 | ||
122 | 124..126 '{}': () | ||
123 | 131..153 'if let...y() {}': () | ||
124 | 138..142 '1f32': f32 | ||
125 | 138..142 '1f32': f32 | ||
126 | 145..148 'any': fn any<f32>() -> f32 | ||
127 | 145..150 'any()': f32 | ||
128 | 151..153 '{}': () | ||
129 | 158..179 'if let...y() {}': () | ||
130 | 165..168 '1.0': f64 | ||
131 | 165..168 '1.0': f64 | ||
132 | 171..174 'any': fn any<f64>() -> f64 | ||
133 | 171..176 'any()': f64 | ||
134 | 177..179 '{}': () | ||
135 | 184..206 'if let...y() {}': () | ||
136 | 191..195 'true': bool | ||
137 | 191..195 'true': bool | ||
138 | 198..201 'any': fn any<bool>() -> bool | ||
139 | 198..203 'any()': bool | ||
140 | 204..206 '{}': () | ||
141 | "#]], | ||
142 | ); | ||
143 | } | ||
144 | |||
145 | #[test] | ||
146 | fn infer_range_pattern() { | ||
147 | check_infer_with_mismatches( | ||
148 | r#" | ||
149 | fn test(x: &i32) { | ||
150 | if let 1..76 = 2u32 {} | ||
151 | if let 1..=76 = 2u32 {} | ||
152 | } | ||
153 | "#, | ||
154 | expect![[r#" | ||
155 | 8..9 'x': &i32 | ||
156 | 17..75 '{ ...2 {} }': () | ||
157 | 23..45 'if let...u32 {}': () | ||
158 | 30..35 '1..76': u32 | ||
159 | 38..42 '2u32': u32 | ||
160 | 43..45 '{}': () | ||
161 | 50..73 'if let...u32 {}': () | ||
162 | 57..63 '1..=76': u32 | ||
163 | 66..70 '2u32': u32 | ||
164 | 71..73 '{}': () | ||
165 | "#]], | ||
166 | ); | ||
167 | } | ||
168 | |||
169 | #[test] | ||
170 | fn infer_pattern_match_ergonomics() { | ||
171 | check_infer( | ||
172 | r#" | ||
173 | struct A<T>(T); | ||
174 | |||
175 | fn test() { | ||
176 | let A(n) = &A(1); | ||
177 | let A(n) = &mut A(1); | ||
178 | } | ||
179 | "#, | ||
180 | expect![[r#" | ||
181 | 27..78 '{ ...(1); }': () | ||
182 | 37..41 'A(n)': A<i32> | ||
183 | 39..40 'n': &i32 | ||
184 | 44..49 '&A(1)': &A<i32> | ||
185 | 45..46 'A': A<i32>(i32) -> A<i32> | ||
186 | 45..49 'A(1)': A<i32> | ||
187 | 47..48 '1': i32 | ||
188 | 59..63 'A(n)': A<i32> | ||
189 | 61..62 'n': &mut i32 | ||
190 | 66..75 '&mut A(1)': &mut A<i32> | ||
191 | 71..72 'A': A<i32>(i32) -> A<i32> | ||
192 | 71..75 'A(1)': A<i32> | ||
193 | 73..74 '1': i32 | ||
194 | "#]], | ||
195 | ); | ||
196 | } | ||
197 | |||
198 | #[test] | ||
199 | fn infer_pattern_match_ergonomics_ref() { | ||
200 | mark::check!(match_ergonomics_ref); | ||
201 | check_infer( | ||
202 | r#" | ||
203 | fn test() { | ||
204 | let v = &(1, &2); | ||
205 | let (_, &w) = v; | ||
206 | } | ||
207 | "#, | ||
208 | expect![[r#" | ||
209 | 10..56 '{ ...= v; }': () | ||
210 | 20..21 'v': &(i32, &i32) | ||
211 | 24..32 '&(1, &2)': &(i32, &i32) | ||
212 | 25..32 '(1, &2)': (i32, &i32) | ||
213 | 26..27 '1': i32 | ||
214 | 29..31 '&2': &i32 | ||
215 | 30..31 '2': i32 | ||
216 | 42..49 '(_, &w)': (i32, &i32) | ||
217 | 43..44 '_': i32 | ||
218 | 46..48 '&w': &i32 | ||
219 | 47..48 'w': i32 | ||
220 | 52..53 'v': &(i32, &i32) | ||
221 | "#]], | ||
222 | ); | ||
223 | } | ||
224 | |||
225 | #[test] | ||
226 | fn infer_pattern_match_slice() { | ||
227 | check_infer( | ||
228 | r#" | ||
229 | fn test() { | ||
230 | let slice: &[f64] = &[0.0]; | ||
231 | match slice { | ||
232 | &[] => {}, | ||
233 | &[a] => { | ||
234 | a; | ||
235 | }, | ||
236 | &[b, c] => { | ||
237 | b; | ||
238 | c; | ||
239 | } | ||
240 | _ => {} | ||
241 | } | ||
242 | } | ||
243 | "#, | ||
244 | expect![[r#" | ||
245 | 10..209 '{ ... } }': () | ||
246 | 20..25 'slice': &[f64] | ||
247 | 36..42 '&[0.0]': &[f64; _] | ||
248 | 37..42 '[0.0]': [f64; _] | ||
249 | 38..41 '0.0': f64 | ||
250 | 48..207 'match ... }': () | ||
251 | 54..59 'slice': &[f64] | ||
252 | 70..73 '&[]': &[f64] | ||
253 | 71..73 '[]': [f64] | ||
254 | 77..79 '{}': () | ||
255 | 89..93 '&[a]': &[f64] | ||
256 | 90..93 '[a]': [f64] | ||
257 | 91..92 'a': f64 | ||
258 | 97..123 '{ ... }': () | ||
259 | 111..112 'a': f64 | ||
260 | 133..140 '&[b, c]': &[f64] | ||
261 | 134..140 '[b, c]': [f64] | ||
262 | 135..136 'b': f64 | ||
263 | 138..139 'c': f64 | ||
264 | 144..185 '{ ... }': () | ||
265 | 158..159 'b': f64 | ||
266 | 173..174 'c': f64 | ||
267 | 194..195 '_': &[f64] | ||
268 | 199..201 '{}': () | ||
269 | "#]], | ||
270 | ); | ||
271 | } | ||
272 | |||
273 | #[test] | ||
274 | fn infer_pattern_match_string_literal() { | ||
275 | check_infer_with_mismatches( | ||
276 | r#" | ||
277 | fn test() { | ||
278 | let s: &str = "hello"; | ||
279 | match s { | ||
280 | "hello" => {} | ||
281 | _ => {} | ||
282 | } | ||
283 | } | ||
284 | "#, | ||
285 | expect![[r#" | ||
286 | 10..98 '{ ... } }': () | ||
287 | 20..21 's': &str | ||
288 | 30..37 '"hello"': &str | ||
289 | 43..96 'match ... }': () | ||
290 | 49..50 's': &str | ||
291 | 61..68 '"hello"': &str | ||
292 | 61..68 '"hello"': &str | ||
293 | 72..74 '{}': () | ||
294 | 83..84 '_': &str | ||
295 | 88..90 '{}': () | ||
296 | "#]], | ||
297 | ); | ||
298 | } | ||
299 | |||
300 | #[test] | ||
301 | fn infer_pattern_match_or() { | ||
302 | check_infer_with_mismatches( | ||
303 | r#" | ||
304 | fn test() { | ||
305 | let s: &str = "hello"; | ||
306 | match s { | ||
307 | "hello" | "world" => {} | ||
308 | _ => {} | ||
309 | } | ||
310 | } | ||
311 | "#, | ||
312 | expect![[r#" | ||
313 | 10..108 '{ ... } }': () | ||
314 | 20..21 's': &str | ||
315 | 30..37 '"hello"': &str | ||
316 | 43..106 'match ... }': () | ||
317 | 49..50 's': &str | ||
318 | 61..68 '"hello"': &str | ||
319 | 61..68 '"hello"': &str | ||
320 | 61..78 '"hello...world"': &str | ||
321 | 71..78 '"world"': &str | ||
322 | 71..78 '"world"': &str | ||
323 | 82..84 '{}': () | ||
324 | 93..94 '_': &str | ||
325 | 98..100 '{}': () | ||
326 | "#]], | ||
327 | ); | ||
328 | } | ||
329 | |||
330 | #[test] | ||
331 | fn infer_pattern_match_arr() { | ||
332 | check_infer( | ||
333 | r#" | ||
334 | fn test() { | ||
335 | let arr: [f64; 2] = [0.0, 1.0]; | ||
336 | match arr { | ||
337 | [1.0, a] => { | ||
338 | a; | ||
339 | }, | ||
340 | [b, c] => { | ||
341 | b; | ||
342 | c; | ||
343 | } | ||
344 | } | ||
345 | } | ||
346 | "#, | ||
347 | expect![[r#" | ||
348 | 10..179 '{ ... } }': () | ||
349 | 20..23 'arr': [f64; _] | ||
350 | 36..46 '[0.0, 1.0]': [f64; _] | ||
351 | 37..40 '0.0': f64 | ||
352 | 42..45 '1.0': f64 | ||
353 | 52..177 'match ... }': () | ||
354 | 58..61 'arr': [f64; _] | ||
355 | 72..80 '[1.0, a]': [f64; _] | ||
356 | 73..76 '1.0': f64 | ||
357 | 73..76 '1.0': f64 | ||
358 | 78..79 'a': f64 | ||
359 | 84..110 '{ ... }': () | ||
360 | 98..99 'a': f64 | ||
361 | 120..126 '[b, c]': [f64; _] | ||
362 | 121..122 'b': f64 | ||
363 | 124..125 'c': f64 | ||
364 | 130..171 '{ ... }': () | ||
365 | 144..145 'b': f64 | ||
366 | 159..160 'c': f64 | ||
367 | "#]], | ||
368 | ); | ||
369 | } | ||
370 | |||
371 | #[test] | ||
372 | fn infer_adt_pattern() { | ||
373 | check_infer( | ||
374 | r#" | ||
375 | enum E { | ||
376 | A { x: usize }, | ||
377 | B | ||
378 | } | ||
379 | |||
380 | struct S(u32, E); | ||
381 | |||
382 | fn test() { | ||
383 | let e = E::A { x: 3 }; | ||
384 | |||
385 | let S(y, z) = foo; | ||
386 | let E::A { x: new_var } = e; | ||
387 | |||
388 | match e { | ||
389 | E::A { x } => x, | ||
390 | E::B if foo => 1, | ||
391 | E::B => 10, | ||
392 | }; | ||
393 | |||
394 | let ref d @ E::A { .. } = e; | ||
395 | d; | ||
396 | } | ||
397 | "#, | ||
398 | expect![[r#" | ||
399 | 67..288 '{ ... d; }': () | ||
400 | 77..78 'e': E | ||
401 | 81..94 'E::A { x: 3 }': E | ||
402 | 91..92 '3': usize | ||
403 | 105..112 'S(y, z)': S | ||
404 | 107..108 'y': u32 | ||
405 | 110..111 'z': E | ||
406 | 115..118 'foo': S | ||
407 | 128..147 'E::A {..._var }': E | ||
408 | 138..145 'new_var': usize | ||
409 | 150..151 'e': E | ||
410 | 158..244 'match ... }': usize | ||
411 | 164..165 'e': E | ||
412 | 176..186 'E::A { x }': E | ||
413 | 183..184 'x': usize | ||
414 | 190..191 'x': usize | ||
415 | 201..205 'E::B': E | ||
416 | 209..212 'foo': bool | ||
417 | 216..217 '1': usize | ||
418 | 227..231 'E::B': E | ||
419 | 235..237 '10': usize | ||
420 | 255..274 'ref d ...{ .. }': &E | ||
421 | 263..274 'E::A { .. }': E | ||
422 | 277..278 'e': E | ||
423 | 284..285 'd': &E | ||
424 | "#]], | ||
425 | ); | ||
426 | } | ||
427 | |||
428 | #[test] | ||
429 | fn enum_variant_through_self_in_pattern() { | ||
430 | check_infer( | ||
431 | r#" | ||
432 | enum E { | ||
433 | A { x: usize }, | ||
434 | B(usize), | ||
435 | C | ||
436 | } | ||
437 | |||
438 | impl E { | ||
439 | fn test() { | ||
440 | match (loop {}) { | ||
441 | Self::A { x } => { x; }, | ||
442 | Self::B(x) => { x; }, | ||
443 | Self::C => {}, | ||
444 | }; | ||
445 | } | ||
446 | } | ||
447 | "#, | ||
448 | expect![[r#" | ||
449 | 75..217 '{ ... }': () | ||
450 | 85..210 'match ... }': () | ||
451 | 92..99 'loop {}': ! | ||
452 | 97..99 '{}': () | ||
453 | 115..128 'Self::A { x }': E | ||
454 | 125..126 'x': usize | ||
455 | 132..138 '{ x; }': () | ||
456 | 134..135 'x': usize | ||
457 | 152..162 'Self::B(x)': E | ||
458 | 160..161 'x': usize | ||
459 | 166..172 '{ x; }': () | ||
460 | 168..169 'x': usize | ||
461 | 186..193 'Self::C': E | ||
462 | 197..199 '{}': () | ||
463 | "#]], | ||
464 | ); | ||
465 | } | ||
466 | |||
467 | #[test] | ||
468 | fn infer_generics_in_patterns() { | ||
469 | check_infer( | ||
470 | r#" | ||
471 | struct A<T> { | ||
472 | x: T, | ||
473 | } | ||
474 | |||
475 | enum Option<T> { | ||
476 | Some(T), | ||
477 | None, | ||
478 | } | ||
479 | |||
480 | fn test(a1: A<u32>, o: Option<u64>) { | ||
481 | let A { x: x2 } = a1; | ||
482 | let A::<i64> { x: x3 } = A { x: 1 }; | ||
483 | match o { | ||
484 | Option::Some(t) => t, | ||
485 | _ => 1, | ||
486 | }; | ||
487 | } | ||
488 | "#, | ||
489 | expect![[r#" | ||
490 | 78..80 'a1': A<u32> | ||
491 | 90..91 'o': Option<u64> | ||
492 | 106..243 '{ ... }; }': () | ||
493 | 116..127 'A { x: x2 }': A<u32> | ||
494 | 123..125 'x2': u32 | ||
495 | 130..132 'a1': A<u32> | ||
496 | 142..160 'A::<i6...: x3 }': A<i64> | ||
497 | 156..158 'x3': i64 | ||
498 | 163..173 'A { x: 1 }': A<i64> | ||
499 | 170..171 '1': i64 | ||
500 | 179..240 'match ... }': u64 | ||
501 | 185..186 'o': Option<u64> | ||
502 | 197..212 'Option::Some(t)': Option<u64> | ||
503 | 210..211 't': u64 | ||
504 | 216..217 't': u64 | ||
505 | 227..228 '_': Option<u64> | ||
506 | 232..233 '1': u64 | ||
507 | "#]], | ||
508 | ); | ||
509 | } | ||
510 | |||
511 | #[test] | ||
512 | fn infer_const_pattern() { | ||
513 | check_infer_with_mismatches( | ||
514 | r#" | ||
515 | enum Option<T> { None } | ||
516 | use Option::None; | ||
517 | struct Foo; | ||
518 | const Bar: usize = 1; | ||
519 | |||
520 | fn test() { | ||
521 | let a: Option<u32> = None; | ||
522 | let b: Option<i64> = match a { | ||
523 | None => None, | ||
524 | }; | ||
525 | let _: () = match () { Foo => Foo }; // Expected mismatch | ||
526 | let _: () = match () { Bar => Bar }; // Expected mismatch | ||
527 | } | ||
528 | "#, | ||
529 | expect![[r#" | ||
530 | 73..74 '1': usize | ||
531 | 87..309 '{ ...atch }': () | ||
532 | 97..98 'a': Option<u32> | ||
533 | 114..118 'None': Option<u32> | ||
534 | 128..129 'b': Option<i64> | ||
535 | 145..182 'match ... }': Option<i64> | ||
536 | 151..152 'a': Option<u32> | ||
537 | 163..167 'None': Option<u32> | ||
538 | 171..175 'None': Option<i64> | ||
539 | 192..193 '_': () | ||
540 | 200..223 'match ... Foo }': Foo | ||
541 | 206..208 '()': () | ||
542 | 211..214 'Foo': Foo | ||
543 | 218..221 'Foo': Foo | ||
544 | 254..255 '_': () | ||
545 | 262..285 'match ... Bar }': usize | ||
546 | 268..270 '()': () | ||
547 | 273..276 'Bar': usize | ||
548 | 280..283 'Bar': usize | ||
549 | 200..223: expected (), got Foo | ||
550 | 262..285: expected (), got usize | ||
551 | "#]], | ||
552 | ); | ||
553 | } | ||
554 | |||
555 | #[test] | ||
556 | fn infer_guard() { | ||
557 | check_infer( | ||
558 | r#" | ||
559 | struct S; | ||
560 | impl S { fn foo(&self) -> bool { false } } | ||
561 | |||
562 | fn main() { | ||
563 | match S { | ||
564 | s if s.foo() => (), | ||
565 | } | ||
566 | } | ||
567 | "#, | ||
568 | expect![[r#" | ||
569 | 27..31 'self': &S | ||
570 | 41..50 '{ false }': bool | ||
571 | 43..48 'false': bool | ||
572 | 64..115 '{ ... } }': () | ||
573 | 70..113 'match ... }': () | ||
574 | 76..77 'S': S | ||
575 | 88..89 's': S | ||
576 | 93..94 's': S | ||
577 | 93..100 's.foo()': bool | ||
578 | 104..106 '()': () | ||
579 | "#]], | ||
580 | ) | ||
581 | } | ||
582 | |||
583 | #[test] | ||
584 | fn match_ergonomics_in_closure_params() { | ||
585 | check_infer( | ||
586 | r#" | ||
587 | #[lang = "fn_once"] | ||
588 | trait FnOnce<Args> { | ||
589 | type Output; | ||
590 | } | ||
591 | |||
592 | fn foo<T, U, F: FnOnce(T) -> U>(t: T, f: F) -> U { loop {} } | ||
593 | |||
594 | fn test() { | ||
595 | foo(&(1, "a"), |&(x, y)| x); // normal, no match ergonomics | ||
596 | foo(&(1, "a"), |(x, y)| x); | ||
597 | } | ||
598 | "#, | ||
599 | expect![[r#" | ||
600 | 93..94 't': T | ||
601 | 99..100 'f': F | ||
602 | 110..121 '{ loop {} }': U | ||
603 | 112..119 'loop {}': ! | ||
604 | 117..119 '{}': () | ||
605 | 133..232 '{ ... x); }': () | ||
606 | 139..142 'foo': fn foo<&(i32, &str), i32, |&(i32, &str)| -> i32>(&(i32, &str), |&(i32, &str)| -> i32) -> i32 | ||
607 | 139..166 'foo(&(...y)| x)': i32 | ||
608 | 143..152 '&(1, "a")': &(i32, &str) | ||
609 | 144..152 '(1, "a")': (i32, &str) | ||
610 | 145..146 '1': i32 | ||
611 | 148..151 '"a"': &str | ||
612 | 154..165 '|&(x, y)| x': |&(i32, &str)| -> i32 | ||
613 | 155..162 '&(x, y)': &(i32, &str) | ||
614 | 156..162 '(x, y)': (i32, &str) | ||
615 | 157..158 'x': i32 | ||
616 | 160..161 'y': &str | ||
617 | 164..165 'x': i32 | ||
618 | 203..206 'foo': fn foo<&(i32, &str), &i32, |&(i32, &str)| -> &i32>(&(i32, &str), |&(i32, &str)| -> &i32) -> &i32 | ||
619 | 203..229 'foo(&(...y)| x)': &i32 | ||
620 | 207..216 '&(1, "a")': &(i32, &str) | ||
621 | 208..216 '(1, "a")': (i32, &str) | ||
622 | 209..210 '1': i32 | ||
623 | 212..215 '"a"': &str | ||
624 | 218..228 '|(x, y)| x': |&(i32, &str)| -> &i32 | ||
625 | 219..225 '(x, y)': (i32, &str) | ||
626 | 220..221 'x': &i32 | ||
627 | 223..224 'y': &&str | ||
628 | 227..228 'x': &i32 | ||
629 | "#]], | ||
630 | ); | ||
631 | } | ||
632 | |||
633 | #[test] | ||
634 | fn slice_tail_pattern() { | ||
635 | check_infer( | ||
636 | r#" | ||
637 | fn foo(params: &[i32]) { | ||
638 | match params { | ||
639 | [head, tail @ ..] => { | ||
640 | } | ||
641 | } | ||
642 | } | ||
643 | "#, | ||
644 | expect![[r#" | ||
645 | 7..13 'params': &[i32] | ||
646 | 23..92 '{ ... } }': () | ||
647 | 29..90 'match ... }': () | ||
648 | 35..41 'params': &[i32] | ||
649 | 52..69 '[head,... @ ..]': [i32] | ||
650 | 53..57 'head': &i32 | ||
651 | 59..68 'tail @ ..': &[i32] | ||
652 | 66..68 '..': [i32] | ||
653 | 73..84 '{ }': () | ||
654 | "#]], | ||
655 | ); | ||
656 | } | ||
diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs deleted file mode 100644 index b9ab0f357..000000000 --- a/crates/ra_hir_ty/src/tests/regression.rs +++ /dev/null | |||
@@ -1,842 +0,0 @@ | |||
1 | use expect::expect; | ||
2 | use test_utils::mark; | ||
3 | |||
4 | use super::{check_infer, check_types}; | ||
5 | |||
6 | #[test] | ||
7 | fn bug_484() { | ||
8 | check_infer( | ||
9 | r#" | ||
10 | fn test() { | ||
11 | let x = if true {}; | ||
12 | } | ||
13 | "#, | ||
14 | expect![[r#" | ||
15 | 10..37 '{ ... {}; }': () | ||
16 | 20..21 'x': () | ||
17 | 24..34 'if true {}': () | ||
18 | 27..31 'true': bool | ||
19 | 32..34 '{}': () | ||
20 | "#]], | ||
21 | ); | ||
22 | } | ||
23 | |||
24 | #[test] | ||
25 | fn no_panic_on_field_of_enum() { | ||
26 | check_infer( | ||
27 | r#" | ||
28 | enum X {} | ||
29 | |||
30 | fn test(x: X) { | ||
31 | x.some_field; | ||
32 | } | ||
33 | "#, | ||
34 | expect![[r#" | ||
35 | 19..20 'x': X | ||
36 | 25..46 '{ ...eld; }': () | ||
37 | 31..32 'x': X | ||
38 | 31..43 'x.some_field': {unknown} | ||
39 | "#]], | ||
40 | ); | ||
41 | } | ||
42 | |||
43 | #[test] | ||
44 | fn bug_585() { | ||
45 | check_infer( | ||
46 | r#" | ||
47 | fn test() { | ||
48 | X {}; | ||
49 | match x { | ||
50 | A::B {} => (), | ||
51 | A::Y() => (), | ||
52 | } | ||
53 | } | ||
54 | "#, | ||
55 | expect![[r#" | ||
56 | 10..88 '{ ... } }': () | ||
57 | 16..20 'X {}': {unknown} | ||
58 | 26..86 'match ... }': () | ||
59 | 32..33 'x': {unknown} | ||
60 | 44..51 'A::B {}': {unknown} | ||
61 | 55..57 '()': () | ||
62 | 67..73 'A::Y()': {unknown} | ||
63 | 77..79 '()': () | ||
64 | "#]], | ||
65 | ); | ||
66 | } | ||
67 | |||
68 | #[test] | ||
69 | fn bug_651() { | ||
70 | check_infer( | ||
71 | r#" | ||
72 | fn quux() { | ||
73 | let y = 92; | ||
74 | 1 + y; | ||
75 | } | ||
76 | "#, | ||
77 | expect![[r#" | ||
78 | 10..40 '{ ...+ y; }': () | ||
79 | 20..21 'y': i32 | ||
80 | 24..26 '92': i32 | ||
81 | 32..33 '1': i32 | ||
82 | 32..37 '1 + y': i32 | ||
83 | 36..37 'y': i32 | ||
84 | "#]], | ||
85 | ); | ||
86 | } | ||
87 | |||
88 | #[test] | ||
89 | fn recursive_vars() { | ||
90 | mark::check!(type_var_cycles_resolve_completely); | ||
91 | mark::check!(type_var_cycles_resolve_as_possible); | ||
92 | check_infer( | ||
93 | r#" | ||
94 | fn test() { | ||
95 | let y = unknown; | ||
96 | [y, &y]; | ||
97 | } | ||
98 | "#, | ||
99 | expect![[r#" | ||
100 | 10..47 '{ ...&y]; }': () | ||
101 | 20..21 'y': &{unknown} | ||
102 | 24..31 'unknown': &{unknown} | ||
103 | 37..44 '[y, &y]': [&&{unknown}; _] | ||
104 | 38..39 'y': &{unknown} | ||
105 | 41..43 '&y': &&{unknown} | ||
106 | 42..43 'y': &{unknown} | ||
107 | "#]], | ||
108 | ); | ||
109 | } | ||
110 | |||
111 | #[test] | ||
112 | fn recursive_vars_2() { | ||
113 | check_infer( | ||
114 | r#" | ||
115 | fn test() { | ||
116 | let x = unknown; | ||
117 | let y = unknown; | ||
118 | [(x, y), (&y, &x)]; | ||
119 | } | ||
120 | "#, | ||
121 | expect![[r#" | ||
122 | 10..79 '{ ...x)]; }': () | ||
123 | 20..21 'x': &&{unknown} | ||
124 | 24..31 'unknown': &&{unknown} | ||
125 | 41..42 'y': &&{unknown} | ||
126 | 45..52 'unknown': &&{unknown} | ||
127 | 58..76 '[(x, y..., &x)]': [(&&&{unknown}, &&&{unknown}); _] | ||
128 | 59..65 '(x, y)': (&&&{unknown}, &&&{unknown}) | ||
129 | 60..61 'x': &&{unknown} | ||
130 | 63..64 'y': &&{unknown} | ||
131 | 67..75 '(&y, &x)': (&&&{unknown}, &&&{unknown}) | ||
132 | 68..70 '&y': &&&{unknown} | ||
133 | 69..70 'y': &&{unknown} | ||
134 | 72..74 '&x': &&&{unknown} | ||
135 | 73..74 'x': &&{unknown} | ||
136 | "#]], | ||
137 | ); | ||
138 | } | ||
139 | |||
140 | #[test] | ||
141 | fn infer_std_crash_1() { | ||
142 | // caused stack overflow, taken from std | ||
143 | check_infer( | ||
144 | r#" | ||
145 | enum Maybe<T> { | ||
146 | Real(T), | ||
147 | Fake, | ||
148 | } | ||
149 | |||
150 | fn write() { | ||
151 | match something_unknown { | ||
152 | Maybe::Real(ref mut something) => (), | ||
153 | } | ||
154 | } | ||
155 | "#, | ||
156 | expect![[r#" | ||
157 | 53..138 '{ ... } }': () | ||
158 | 59..136 'match ... }': () | ||
159 | 65..82 'someth...nknown': Maybe<{unknown}> | ||
160 | 93..123 'Maybe:...thing)': Maybe<{unknown}> | ||
161 | 105..122 'ref mu...ething': &mut {unknown} | ||
162 | 127..129 '()': () | ||
163 | "#]], | ||
164 | ); | ||
165 | } | ||
166 | |||
167 | #[test] | ||
168 | fn infer_std_crash_2() { | ||
169 | mark::check!(type_var_resolves_to_int_var); | ||
170 | // caused "equating two type variables, ...", taken from std | ||
171 | check_infer( | ||
172 | r#" | ||
173 | fn test_line_buffer() { | ||
174 | &[0, b'\n', 1, b'\n']; | ||
175 | } | ||
176 | "#, | ||
177 | expect![[r#" | ||
178 | 22..52 '{ ...n']; }': () | ||
179 | 28..49 '&[0, b...b'\n']': &[u8; _] | ||
180 | 29..49 '[0, b'...b'\n']': [u8; _] | ||
181 | 30..31 '0': u8 | ||
182 | 33..38 'b'\n'': u8 | ||
183 | 40..41 '1': u8 | ||
184 | 43..48 'b'\n'': u8 | ||
185 | "#]], | ||
186 | ); | ||
187 | } | ||
188 | |||
189 | #[test] | ||
190 | fn infer_std_crash_3() { | ||
191 | // taken from rustc | ||
192 | check_infer( | ||
193 | r#" | ||
194 | pub fn compute() { | ||
195 | match nope!() { | ||
196 | SizeSkeleton::Pointer { non_zero: true, tail } => {} | ||
197 | } | ||
198 | } | ||
199 | "#, | ||
200 | expect![[r#" | ||
201 | 17..107 '{ ... } }': () | ||
202 | 23..105 'match ... }': () | ||
203 | 29..36 'nope!()': {unknown} | ||
204 | 47..93 'SizeSk...tail }': {unknown} | ||
205 | 81..85 'true': bool | ||
206 | 81..85 'true': bool | ||
207 | 87..91 'tail': {unknown} | ||
208 | 97..99 '{}': () | ||
209 | "#]], | ||
210 | ); | ||
211 | } | ||
212 | |||
213 | #[test] | ||
214 | fn infer_std_crash_4() { | ||
215 | // taken from rustc | ||
216 | check_infer( | ||
217 | r#" | ||
218 | pub fn primitive_type() { | ||
219 | match *self { | ||
220 | BorrowedRef { type_: Primitive(p), ..} => {}, | ||
221 | } | ||
222 | } | ||
223 | "#, | ||
224 | expect![[r#" | ||
225 | 24..105 '{ ... } }': () | ||
226 | 30..103 'match ... }': () | ||
227 | 36..41 '*self': {unknown} | ||
228 | 37..41 'self': {unknown} | ||
229 | 52..90 'Borrow...), ..}': {unknown} | ||
230 | 73..85 'Primitive(p)': {unknown} | ||
231 | 83..84 'p': {unknown} | ||
232 | 94..96 '{}': () | ||
233 | "#]], | ||
234 | ); | ||
235 | } | ||
236 | |||
237 | #[test] | ||
238 | fn infer_std_crash_5() { | ||
239 | // taken from rustc | ||
240 | check_infer( | ||
241 | r#" | ||
242 | fn extra_compiler_flags() { | ||
243 | for content in doesnt_matter { | ||
244 | let name = if doesnt_matter { | ||
245 | first | ||
246 | } else { | ||
247 | &content | ||
248 | }; | ||
249 | |||
250 | let content = if ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.contains(&name) { | ||
251 | name | ||
252 | } else { | ||
253 | content | ||
254 | }; | ||
255 | } | ||
256 | } | ||
257 | "#, | ||
258 | expect![[r#" | ||
259 | 26..322 '{ ... } }': () | ||
260 | 32..320 'for co... }': () | ||
261 | 36..43 'content': &{unknown} | ||
262 | 47..60 'doesnt_matter': {unknown} | ||
263 | 61..320 '{ ... }': () | ||
264 | 75..79 'name': &&{unknown} | ||
265 | 82..166 'if doe... }': &&{unknown} | ||
266 | 85..98 'doesnt_matter': bool | ||
267 | 99..128 '{ ... }': &&{unknown} | ||
268 | 113..118 'first': &&{unknown} | ||
269 | 134..166 '{ ... }': &&{unknown} | ||
270 | 148..156 '&content': &&{unknown} | ||
271 | 149..156 'content': &{unknown} | ||
272 | 181..188 'content': &{unknown} | ||
273 | 191..313 'if ICE... }': &{unknown} | ||
274 | 194..231 'ICE_RE..._VALUE': {unknown} | ||
275 | 194..247 'ICE_RE...&name)': bool | ||
276 | 241..246 '&name': &&&{unknown} | ||
277 | 242..246 'name': &&{unknown} | ||
278 | 248..276 '{ ... }': &&{unknown} | ||
279 | 262..266 'name': &&{unknown} | ||
280 | 282..313 '{ ... }': &{unknown} | ||
281 | 296..303 'content': &{unknown} | ||
282 | "#]], | ||
283 | ); | ||
284 | } | ||
285 | |||
286 | #[test] | ||
287 | fn infer_nested_generics_crash() { | ||
288 | // another crash found typechecking rustc | ||
289 | check_infer( | ||
290 | r#" | ||
291 | struct Canonical<V> { | ||
292 | value: V, | ||
293 | } | ||
294 | struct QueryResponse<V> { | ||
295 | value: V, | ||
296 | } | ||
297 | fn test<R>(query_response: Canonical<QueryResponse<R>>) { | ||
298 | &query_response.value; | ||
299 | } | ||
300 | "#, | ||
301 | expect![[r#" | ||
302 | 91..105 'query_response': Canonical<QueryResponse<R>> | ||
303 | 136..166 '{ ...lue; }': () | ||
304 | 142..163 '&query....value': &QueryResponse<R> | ||
305 | 143..157 'query_response': Canonical<QueryResponse<R>> | ||
306 | 143..163 'query_....value': QueryResponse<R> | ||
307 | "#]], | ||
308 | ); | ||
309 | } | ||
310 | |||
311 | #[test] | ||
312 | fn infer_paren_macro_call() { | ||
313 | check_infer( | ||
314 | r#" | ||
315 | macro_rules! bar { () => {0u32} } | ||
316 | fn test() { | ||
317 | let a = (bar!()); | ||
318 | } | ||
319 | "#, | ||
320 | expect![[r#" | ||
321 | !0..4 '0u32': u32 | ||
322 | 44..69 '{ ...()); }': () | ||
323 | 54..55 'a': u32 | ||
324 | "#]], | ||
325 | ); | ||
326 | } | ||
327 | |||
328 | #[test] | ||
329 | fn bug_1030() { | ||
330 | check_infer( | ||
331 | r#" | ||
332 | struct HashSet<T, H>; | ||
333 | struct FxHasher; | ||
334 | type FxHashSet<T> = HashSet<T, FxHasher>; | ||
335 | |||
336 | impl<T, H> HashSet<T, H> { | ||
337 | fn default() -> HashSet<T, H> {} | ||
338 | } | ||
339 | |||
340 | pub fn main_loop() { | ||
341 | FxHashSet::default(); | ||
342 | } | ||
343 | "#, | ||
344 | expect![[r#" | ||
345 | 143..145 '{}': () | ||
346 | 168..197 '{ ...t(); }': () | ||
347 | 174..192 'FxHash...efault': fn default<{unknown}, FxHasher>() -> HashSet<{unknown}, FxHasher> | ||
348 | 174..194 'FxHash...ault()': HashSet<{unknown}, FxHasher> | ||
349 | "#]], | ||
350 | ); | ||
351 | } | ||
352 | |||
353 | #[test] | ||
354 | fn issue_2669() { | ||
355 | check_infer( | ||
356 | r#" | ||
357 | trait A {} | ||
358 | trait Write {} | ||
359 | struct Response<T> {} | ||
360 | |||
361 | trait D { | ||
362 | fn foo(); | ||
363 | } | ||
364 | |||
365 | impl<T:A> D for Response<T> { | ||
366 | fn foo() { | ||
367 | end(); | ||
368 | fn end<W: Write>() { | ||
369 | let _x: T = loop {}; | ||
370 | } | ||
371 | } | ||
372 | } | ||
373 | "#, | ||
374 | expect![[r#" | ||
375 | 119..214 '{ ... }': () | ||
376 | 129..132 'end': fn end<{unknown}>() | ||
377 | 129..134 'end()': () | ||
378 | 163..208 '{ ... }': () | ||
379 | 181..183 '_x': ! | ||
380 | 190..197 'loop {}': ! | ||
381 | 195..197 '{}': () | ||
382 | "#]], | ||
383 | ) | ||
384 | } | ||
385 | |||
386 | #[test] | ||
387 | fn issue_2705() { | ||
388 | check_infer( | ||
389 | r#" | ||
390 | trait Trait {} | ||
391 | fn test() { | ||
392 | <Trait<u32>>::foo() | ||
393 | } | ||
394 | "#, | ||
395 | expect![[r#" | ||
396 | 25..52 '{ ...oo() }': () | ||
397 | 31..48 '<Trait...>::foo': {unknown} | ||
398 | 31..50 '<Trait...:foo()': () | ||
399 | "#]], | ||
400 | ); | ||
401 | } | ||
402 | |||
403 | #[test] | ||
404 | fn issue_2683_chars_impl() { | ||
405 | check_types( | ||
406 | r#" | ||
407 | //- /main.rs crate:main deps:std | ||
408 | fn test() { | ||
409 | let chars: std::str::Chars<'_>; | ||
410 | (chars.next(), chars.nth(1)); | ||
411 | } //^ (Option<char>, Option<char>) | ||
412 | |||
413 | //- /std.rs crate:std | ||
414 | #[prelude_import] | ||
415 | use prelude::*; | ||
416 | |||
417 | pub mod prelude { | ||
418 | pub use crate::iter::Iterator; | ||
419 | pub use crate::option::Option; | ||
420 | } | ||
421 | |||
422 | pub mod iter { | ||
423 | pub use self::traits::Iterator; | ||
424 | pub mod traits { | ||
425 | pub use self::iterator::Iterator; | ||
426 | |||
427 | pub mod iterator { | ||
428 | pub trait Iterator { | ||
429 | type Item; | ||
430 | fn next(&mut self) -> Option<Self::Item>; | ||
431 | fn nth(&mut self, n: usize) -> Option<Self::Item> {} | ||
432 | } | ||
433 | } | ||
434 | } | ||
435 | } | ||
436 | |||
437 | pub mod option { | ||
438 | pub enum Option<T> {} | ||
439 | } | ||
440 | |||
441 | pub mod str { | ||
442 | pub struct Chars<'a> {} | ||
443 | impl<'a> Iterator for Chars<'a> { | ||
444 | type Item = char; | ||
445 | fn next(&mut self) -> Option<char> {} | ||
446 | } | ||
447 | } | ||
448 | "#, | ||
449 | ); | ||
450 | } | ||
451 | |||
452 | #[test] | ||
453 | fn issue_3642_bad_macro_stackover() { | ||
454 | check_types( | ||
455 | r#" | ||
456 | #[macro_export] | ||
457 | macro_rules! match_ast { | ||
458 | (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) }; | ||
459 | |||
460 | (match ($node:expr) { | ||
461 | $( ast::$ast:ident($it:ident) => $res:expr, )* | ||
462 | _ => $catch_all:expr $(,)? | ||
463 | }) => {{ | ||
464 | $( if let Some($it) = ast::$ast::cast($node.clone()) { $res } else )* | ||
465 | { $catch_all } | ||
466 | }}; | ||
467 | } | ||
468 | |||
469 | fn main() { | ||
470 | let anchor = match_ast! { | ||
471 | //^ () | ||
472 | match parent { | ||
473 | as => {}, | ||
474 | _ => return None | ||
475 | } | ||
476 | }; | ||
477 | }"#, | ||
478 | ); | ||
479 | } | ||
480 | |||
481 | #[test] | ||
482 | fn issue_3999_slice() { | ||
483 | check_infer( | ||
484 | r#" | ||
485 | fn foo(params: &[usize]) { | ||
486 | match params { | ||
487 | [ps @ .., _] => {} | ||
488 | } | ||
489 | } | ||
490 | "#, | ||
491 | expect![[r#" | ||
492 | 7..13 'params': &[usize] | ||
493 | 25..80 '{ ... } }': () | ||
494 | 31..78 'match ... }': () | ||
495 | 37..43 'params': &[usize] | ||
496 | 54..66 '[ps @ .., _]': [usize] | ||
497 | 55..62 'ps @ ..': &[usize] | ||
498 | 60..62 '..': [usize] | ||
499 | 64..65 '_': usize | ||
500 | 70..72 '{}': () | ||
501 | "#]], | ||
502 | ); | ||
503 | } | ||
504 | |||
505 | #[test] | ||
506 | fn issue_3999_struct() { | ||
507 | // rust-analyzer should not panic on seeing this malformed | ||
508 | // record pattern. | ||
509 | check_infer( | ||
510 | r#" | ||
511 | struct Bar { | ||
512 | a: bool, | ||
513 | } | ||
514 | fn foo(b: Bar) { | ||
515 | match b { | ||
516 | Bar { a: .. } => {}, | ||
517 | } | ||
518 | } | ||
519 | "#, | ||
520 | expect![[r#" | ||
521 | 35..36 'b': Bar | ||
522 | 43..95 '{ ... } }': () | ||
523 | 49..93 'match ... }': () | ||
524 | 55..56 'b': Bar | ||
525 | 67..80 'Bar { a: .. }': Bar | ||
526 | 76..78 '..': bool | ||
527 | 84..86 '{}': () | ||
528 | "#]], | ||
529 | ); | ||
530 | } | ||
531 | |||
532 | #[test] | ||
533 | fn issue_4235_name_conflicts() { | ||
534 | check_infer( | ||
535 | r#" | ||
536 | struct FOO {} | ||
537 | static FOO:FOO = FOO {}; | ||
538 | |||
539 | impl FOO { | ||
540 | fn foo(&self) {} | ||
541 | } | ||
542 | |||
543 | fn main() { | ||
544 | let a = &FOO; | ||
545 | a.foo(); | ||
546 | } | ||
547 | "#, | ||
548 | expect![[r#" | ||
549 | 31..37 'FOO {}': FOO | ||
550 | 63..67 'self': &FOO | ||
551 | 69..71 '{}': () | ||
552 | 85..119 '{ ...o(); }': () | ||
553 | 95..96 'a': &FOO | ||
554 | 99..103 '&FOO': &FOO | ||
555 | 100..103 'FOO': FOO | ||
556 | 109..110 'a': &FOO | ||
557 | 109..116 'a.foo()': () | ||
558 | "#]], | ||
559 | ); | ||
560 | } | ||
561 | |||
562 | #[test] | ||
563 | fn issue_4465_dollar_crate_at_type() { | ||
564 | check_infer( | ||
565 | r#" | ||
566 | pub struct Foo {} | ||
567 | pub fn anything<T>() -> T { | ||
568 | loop {} | ||
569 | } | ||
570 | macro_rules! foo { | ||
571 | () => {{ | ||
572 | let r: $crate::Foo = anything(); | ||
573 | r | ||
574 | }}; | ||
575 | } | ||
576 | fn main() { | ||
577 | let _a = foo!(); | ||
578 | } | ||
579 | "#, | ||
580 | expect![[r#" | ||
581 | 44..59 '{ loop {} }': T | ||
582 | 50..57 'loop {}': ! | ||
583 | 55..57 '{}': () | ||
584 | !0..31 '{letr:...g();r}': Foo | ||
585 | !4..5 'r': Foo | ||
586 | !18..26 'anything': fn anything<Foo>() -> Foo | ||
587 | !18..28 'anything()': Foo | ||
588 | !29..30 'r': Foo | ||
589 | 163..187 '{ ...!(); }': () | ||
590 | 173..175 '_a': Foo | ||
591 | "#]], | ||
592 | ); | ||
593 | } | ||
594 | |||
595 | #[test] | ||
596 | fn issue_4053_diesel_where_clauses() { | ||
597 | check_infer( | ||
598 | r#" | ||
599 | trait BoxedDsl<DB> { | ||
600 | type Output; | ||
601 | fn internal_into_boxed(self) -> Self::Output; | ||
602 | } | ||
603 | |||
604 | struct SelectStatement<From, Select, Distinct, Where, Order, LimitOffset, GroupBy, Locking> { | ||
605 | order: Order, | ||
606 | } | ||
607 | |||
608 | trait QueryFragment<DB: Backend> {} | ||
609 | |||
610 | trait Into<T> { fn into(self) -> T; } | ||
611 | |||
612 | impl<F, S, D, W, O, LOf, DB> BoxedDsl<DB> | ||
613 | for SelectStatement<F, S, D, W, O, LOf, G> | ||
614 | where | ||
615 | O: Into<dyn QueryFragment<DB>>, | ||
616 | { | ||
617 | type Output = XXX; | ||
618 | |||
619 | fn internal_into_boxed(self) -> Self::Output { | ||
620 | self.order.into(); | ||
621 | } | ||
622 | } | ||
623 | "#, | ||
624 | expect![[r#" | ||
625 | 65..69 'self': Self | ||
626 | 267..271 'self': Self | ||
627 | 466..470 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}> | ||
628 | 488..522 '{ ... }': () | ||
629 | 498..502 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}> | ||
630 | 498..508 'self.order': O | ||
631 | 498..515 'self.o...into()': dyn QueryFragment<DB> | ||
632 | "#]], | ||
633 | ); | ||
634 | } | ||
635 | |||
636 | #[test] | ||
637 | fn issue_4953() { | ||
638 | check_infer( | ||
639 | r#" | ||
640 | pub struct Foo(pub i64); | ||
641 | impl Foo { | ||
642 | fn test() -> Self { Self(0i64) } | ||
643 | } | ||
644 | "#, | ||
645 | expect![[r#" | ||
646 | 58..72 '{ Self(0i64) }': Foo | ||
647 | 60..64 'Self': Foo(i64) -> Foo | ||
648 | 60..70 'Self(0i64)': Foo | ||
649 | 65..69 '0i64': i64 | ||
650 | "#]], | ||
651 | ); | ||
652 | check_infer( | ||
653 | r#" | ||
654 | pub struct Foo<T>(pub T); | ||
655 | impl Foo<i64> { | ||
656 | fn test() -> Self { Self(0i64) } | ||
657 | } | ||
658 | "#, | ||
659 | expect![[r#" | ||
660 | 64..78 '{ Self(0i64) }': Foo<i64> | ||
661 | 66..70 'Self': Foo<i64>(i64) -> Foo<i64> | ||
662 | 66..76 'Self(0i64)': Foo<i64> | ||
663 | 71..75 '0i64': i64 | ||
664 | "#]], | ||
665 | ); | ||
666 | } | ||
667 | |||
668 | #[test] | ||
669 | fn issue_4931() { | ||
670 | check_infer( | ||
671 | r#" | ||
672 | trait Div<T> { | ||
673 | type Output; | ||
674 | } | ||
675 | |||
676 | trait CheckedDiv: Div<()> {} | ||
677 | |||
678 | trait PrimInt: CheckedDiv<Output = ()> { | ||
679 | fn pow(self); | ||
680 | } | ||
681 | |||
682 | fn check<T: PrimInt>(i: T) { | ||
683 | i.pow(); | ||
684 | } | ||
685 | "#, | ||
686 | expect![[r#" | ||
687 | 117..121 'self': Self | ||
688 | 148..149 'i': T | ||
689 | 154..170 '{ ...w(); }': () | ||
690 | 160..161 'i': T | ||
691 | 160..167 'i.pow()': () | ||
692 | "#]], | ||
693 | ); | ||
694 | } | ||
695 | |||
696 | #[test] | ||
697 | fn issue_4885() { | ||
698 | check_infer( | ||
699 | r#" | ||
700 | #[lang = "coerce_unsized"] | ||
701 | pub trait CoerceUnsized<T> {} | ||
702 | |||
703 | trait Future { | ||
704 | type Output; | ||
705 | } | ||
706 | trait Foo<R> { | ||
707 | type Bar; | ||
708 | } | ||
709 | fn foo<R, K>(key: &K) -> impl Future<Output = K::Bar> | ||
710 | where | ||
711 | K: Foo<R>, | ||
712 | { | ||
713 | bar(key) | ||
714 | } | ||
715 | fn bar<R, K>(key: &K) -> impl Future<Output = K::Bar> | ||
716 | where | ||
717 | K: Foo<R>, | ||
718 | { | ||
719 | } | ||
720 | "#, | ||
721 | expect![[r#" | ||
722 | 136..139 'key': &K | ||
723 | 198..214 '{ ...key) }': impl Future<Output = <K as Foo<R>>::Bar> | ||
724 | 204..207 'bar': fn bar<R, K>(&K) -> impl Future<Output = <K as Foo<R>>::Bar> | ||
725 | 204..212 'bar(key)': impl Future<Output = <K as Foo<R>>::Bar> | ||
726 | 208..211 'key': &K | ||
727 | 228..231 'key': &K | ||
728 | 290..293 '{ }': () | ||
729 | "#]], | ||
730 | ); | ||
731 | } | ||
732 | |||
733 | #[test] | ||
734 | fn issue_4800() { | ||
735 | check_infer( | ||
736 | r#" | ||
737 | trait Debug {} | ||
738 | |||
739 | struct Foo<T>; | ||
740 | |||
741 | type E1<T> = (T, T, T); | ||
742 | type E2<T> = E1<E1<E1<(T, T, T)>>>; | ||
743 | |||
744 | impl Debug for Foo<E2<()>> {} | ||
745 | |||
746 | struct Request; | ||
747 | |||
748 | pub trait Future { | ||
749 | type Output; | ||
750 | } | ||
751 | |||
752 | pub struct PeerSet<D>; | ||
753 | |||
754 | impl<D> Service<Request> for PeerSet<D> | ||
755 | where | ||
756 | D: Discover, | ||
757 | D::Key: Debug, | ||
758 | { | ||
759 | type Error = (); | ||
760 | type Future = dyn Future<Output = Self::Error>; | ||
761 | |||
762 | fn call(&mut self) -> Self::Future { | ||
763 | loop {} | ||
764 | } | ||
765 | } | ||
766 | |||
767 | pub trait Discover { | ||
768 | type Key; | ||
769 | } | ||
770 | |||
771 | pub trait Service<Request> { | ||
772 | type Error; | ||
773 | type Future: Future<Output = Self::Error>; | ||
774 | fn call(&mut self) -> Self::Future; | ||
775 | } | ||
776 | "#, | ||
777 | expect![[r#" | ||
778 | 379..383 'self': &mut PeerSet<D> | ||
779 | 401..424 '{ ... }': dyn Future<Output = ()> | ||
780 | 411..418 'loop {}': ! | ||
781 | 416..418 '{}': () | ||
782 | 575..579 'self': &mut Self | ||
783 | "#]], | ||
784 | ); | ||
785 | } | ||
786 | |||
787 | #[test] | ||
788 | fn issue_4966() { | ||
789 | check_infer( | ||
790 | r#" | ||
791 | pub trait IntoIterator { | ||
792 | type Item; | ||
793 | } | ||
794 | |||
795 | struct Repeat<A> { element: A } | ||
796 | |||
797 | struct Map<F> { f: F } | ||
798 | |||
799 | struct Vec<T> {} | ||
800 | |||
801 | #[lang = "deref"] | ||
802 | pub trait Deref { | ||
803 | type Target; | ||
804 | } | ||
805 | |||
806 | impl<T> Deref for Vec<T> { | ||
807 | type Target = [T]; | ||
808 | } | ||
809 | |||
810 | fn from_iter<A, T: IntoIterator<Item = A>>(iter: T) -> Vec<A> {} | ||
811 | |||
812 | fn main() { | ||
813 | let inner = Map { f: |_: &f64| 0.0 }; | ||
814 | |||
815 | let repeat = Repeat { element: inner }; | ||
816 | |||
817 | let vec = from_iter(repeat); | ||
818 | |||
819 | vec.foo_bar(); | ||
820 | } | ||
821 | "#, | ||
822 | expect![[r#" | ||
823 | 270..274 'iter': T | ||
824 | 289..291 '{}': () | ||
825 | 303..447 '{ ...r(); }': () | ||
826 | 313..318 'inner': Map<|&f64| -> f64> | ||
827 | 321..345 'Map { ... 0.0 }': Map<|&f64| -> f64> | ||
828 | 330..343 '|_: &f64| 0.0': |&f64| -> f64 | ||
829 | 331..332 '_': &f64 | ||
830 | 340..343 '0.0': f64 | ||
831 | 356..362 'repeat': Repeat<Map<|&f64| -> f64>> | ||
832 | 365..390 'Repeat...nner }': Repeat<Map<|&f64| -> f64>> | ||
833 | 383..388 'inner': Map<|&f64| -> f64> | ||
834 | 401..404 'vec': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>> | ||
835 | 407..416 'from_iter': fn from_iter<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>, Repeat<Map<|&f64| -> f64>>>(Repeat<Map<|&f64| -> f64>>) -> Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>> | ||
836 | 407..424 'from_i...epeat)': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>> | ||
837 | 417..423 'repeat': Repeat<Map<|&f64| -> f64>> | ||
838 | 431..434 'vec': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>> | ||
839 | 431..444 'vec.foo_bar()': {unknown} | ||
840 | "#]], | ||
841 | ); | ||
842 | } | ||
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs deleted file mode 100644 index 3fd7d5cd4..000000000 --- a/crates/ra_hir_ty/src/tests/simple.rs +++ /dev/null | |||
@@ -1,2190 +0,0 @@ | |||
1 | use expect::expect; | ||
2 | |||
3 | use super::{check_infer, check_types}; | ||
4 | |||
5 | #[test] | ||
6 | fn infer_box() { | ||
7 | check_types( | ||
8 | r#" | ||
9 | //- /main.rs crate:main deps:std | ||
10 | fn test() { | ||
11 | let x = box 1; | ||
12 | let t = (x, box x, box &1, box [1]); | ||
13 | t; | ||
14 | } //^ (Box<i32>, Box<Box<i32>>, Box<&i32>, Box<[i32; _]>) | ||
15 | |||
16 | //- /std.rs crate:std | ||
17 | #[prelude_import] use prelude::*; | ||
18 | mod prelude {} | ||
19 | |||
20 | mod boxed { | ||
21 | #[lang = "owned_box"] | ||
22 | pub struct Box<T: ?Sized> { | ||
23 | inner: *mut T, | ||
24 | } | ||
25 | } | ||
26 | "#, | ||
27 | ); | ||
28 | } | ||
29 | |||
30 | #[test] | ||
31 | fn infer_adt_self() { | ||
32 | check_types( | ||
33 | r#" | ||
34 | enum Nat { Succ(Self), Demo(Nat), Zero } | ||
35 | |||
36 | fn test() { | ||
37 | let foo: Nat = Nat::Zero; | ||
38 | if let Nat::Succ(x) = foo { | ||
39 | x | ||
40 | } //^ Nat | ||
41 | } | ||
42 | "#, | ||
43 | ); | ||
44 | } | ||
45 | |||
46 | #[test] | ||
47 | fn self_in_struct_lit() { | ||
48 | check_infer( | ||
49 | r#" | ||
50 | //- /main.rs | ||
51 | struct S<T> { x: T } | ||
52 | |||
53 | impl S<u32> { | ||
54 | fn foo() { | ||
55 | Self { x: 1 }; | ||
56 | } | ||
57 | } | ||
58 | "#, | ||
59 | expect![[r#" | ||
60 | 49..79 '{ ... }': () | ||
61 | 59..72 'Self { x: 1 }': S<u32> | ||
62 | 69..70 '1': u32 | ||
63 | "#]], | ||
64 | ); | ||
65 | } | ||
66 | |||
67 | #[test] | ||
68 | fn type_alias_in_struct_lit() { | ||
69 | check_infer( | ||
70 | r#" | ||
71 | //- /main.rs | ||
72 | struct S<T> { x: T } | ||
73 | |||
74 | type SS = S<u32>; | ||
75 | |||
76 | fn foo() { | ||
77 | SS { x: 1 }; | ||
78 | } | ||
79 | "#, | ||
80 | expect![[r#" | ||
81 | 50..70 '{ ...1 }; }': () | ||
82 | 56..67 'SS { x: 1 }': S<u32> | ||
83 | 64..65 '1': u32 | ||
84 | "#]], | ||
85 | ); | ||
86 | } | ||
87 | |||
88 | #[test] | ||
89 | fn infer_ranges() { | ||
90 | check_types( | ||
91 | r#" | ||
92 | //- /main.rs crate:main deps:core | ||
93 | fn test() { | ||
94 | let a = ..; | ||
95 | let b = 1..; | ||
96 | let c = ..2u32; | ||
97 | let d = 1..2usize; | ||
98 | let e = ..=10; | ||
99 | let f = 'a'..='z'; | ||
100 | |||
101 | let t = (a, b, c, d, e, f); | ||
102 | t; | ||
103 | } //^ (RangeFull, RangeFrom<i32>, RangeTo<u32>, Range<usize>, RangeToInclusive<i32>, RangeInclusive<char>) | ||
104 | |||
105 | //- /core.rs crate:core | ||
106 | #[prelude_import] use prelude::*; | ||
107 | mod prelude {} | ||
108 | |||
109 | pub mod ops { | ||
110 | pub struct Range<Idx> { | ||
111 | pub start: Idx, | ||
112 | pub end: Idx, | ||
113 | } | ||
114 | pub struct RangeFrom<Idx> { | ||
115 | pub start: Idx, | ||
116 | } | ||
117 | struct RangeFull; | ||
118 | pub struct RangeInclusive<Idx> { | ||
119 | start: Idx, | ||
120 | end: Idx, | ||
121 | is_empty: u8, | ||
122 | } | ||
123 | pub struct RangeTo<Idx> { | ||
124 | pub end: Idx, | ||
125 | } | ||
126 | pub struct RangeToInclusive<Idx> { | ||
127 | pub end: Idx, | ||
128 | } | ||
129 | } | ||
130 | "#, | ||
131 | ); | ||
132 | } | ||
133 | |||
134 | #[test] | ||
135 | fn infer_while_let() { | ||
136 | check_types( | ||
137 | r#" | ||
138 | enum Option<T> { Some(T), None } | ||
139 | |||
140 | fn test() { | ||
141 | let foo: Option<f32> = None; | ||
142 | while let Option::Some(x) = foo { | ||
143 | x | ||
144 | } //^ f32 | ||
145 | } | ||
146 | "#, | ||
147 | ); | ||
148 | } | ||
149 | |||
150 | #[test] | ||
151 | fn infer_basics() { | ||
152 | check_infer( | ||
153 | r#" | ||
154 | fn test(a: u32, b: isize, c: !, d: &str) { | ||
155 | a; | ||
156 | b; | ||
157 | c; | ||
158 | d; | ||
159 | 1usize; | ||
160 | 1isize; | ||
161 | "test"; | ||
162 | 1.0f32; | ||
163 | }"#, | ||
164 | expect![[r#" | ||
165 | 8..9 'a': u32 | ||
166 | 16..17 'b': isize | ||
167 | 26..27 'c': ! | ||
168 | 32..33 'd': &str | ||
169 | 41..120 '{ ...f32; }': () | ||
170 | 47..48 'a': u32 | ||
171 | 54..55 'b': isize | ||
172 | 61..62 'c': ! | ||
173 | 68..69 'd': &str | ||
174 | 75..81 '1usize': usize | ||
175 | 87..93 '1isize': isize | ||
176 | 99..105 '"test"': &str | ||
177 | 111..117 '1.0f32': f32 | ||
178 | "#]], | ||
179 | ); | ||
180 | } | ||
181 | |||
182 | #[test] | ||
183 | fn infer_let() { | ||
184 | check_infer( | ||
185 | r#" | ||
186 | fn test() { | ||
187 | let a = 1isize; | ||
188 | let b: usize = 1; | ||
189 | let c = b; | ||
190 | let d: u32; | ||
191 | let e; | ||
192 | let f: i32 = e; | ||
193 | } | ||
194 | "#, | ||
195 | expect![[r#" | ||
196 | 10..117 '{ ...= e; }': () | ||
197 | 20..21 'a': isize | ||
198 | 24..30 '1isize': isize | ||
199 | 40..41 'b': usize | ||
200 | 51..52 '1': usize | ||
201 | 62..63 'c': usize | ||
202 | 66..67 'b': usize | ||
203 | 77..78 'd': u32 | ||
204 | 93..94 'e': i32 | ||
205 | 104..105 'f': i32 | ||
206 | 113..114 'e': i32 | ||
207 | "#]], | ||
208 | ); | ||
209 | } | ||
210 | |||
211 | #[test] | ||
212 | fn infer_paths() { | ||
213 | check_infer( | ||
214 | r#" | ||
215 | fn a() -> u32 { 1 } | ||
216 | |||
217 | mod b { | ||
218 | fn c() -> u32 { 1 } | ||
219 | } | ||
220 | |||
221 | fn test() { | ||
222 | a(); | ||
223 | b::c(); | ||
224 | } | ||
225 | "#, | ||
226 | expect![[r#" | ||
227 | 14..19 '{ 1 }': u32 | ||
228 | 16..17 '1': u32 | ||
229 | 47..52 '{ 1 }': u32 | ||
230 | 49..50 '1': u32 | ||
231 | 66..90 '{ ...c(); }': () | ||
232 | 72..73 'a': fn a() -> u32 | ||
233 | 72..75 'a()': u32 | ||
234 | 81..85 'b::c': fn c() -> u32 | ||
235 | 81..87 'b::c()': u32 | ||
236 | "#]], | ||
237 | ); | ||
238 | } | ||
239 | |||
240 | #[test] | ||
241 | fn infer_path_type() { | ||
242 | check_infer( | ||
243 | r#" | ||
244 | struct S; | ||
245 | |||
246 | impl S { | ||
247 | fn foo() -> i32 { 1 } | ||
248 | } | ||
249 | |||
250 | fn test() { | ||
251 | S::foo(); | ||
252 | <S>::foo(); | ||
253 | } | ||
254 | "#, | ||
255 | expect![[r#" | ||
256 | 40..45 '{ 1 }': i32 | ||
257 | 42..43 '1': i32 | ||
258 | 59..92 '{ ...o(); }': () | ||
259 | 65..71 'S::foo': fn foo() -> i32 | ||
260 | 65..73 'S::foo()': i32 | ||
261 | 79..87 '<S>::foo': fn foo() -> i32 | ||
262 | 79..89 '<S>::foo()': i32 | ||
263 | "#]], | ||
264 | ); | ||
265 | } | ||
266 | |||
267 | #[test] | ||
268 | fn infer_struct() { | ||
269 | check_infer( | ||
270 | r#" | ||
271 | struct A { | ||
272 | b: B, | ||
273 | c: C, | ||
274 | } | ||
275 | struct B; | ||
276 | struct C(usize); | ||
277 | |||
278 | fn test() { | ||
279 | let c = C(1); | ||
280 | B; | ||
281 | let a: A = A { b: B, c: C(1) }; | ||
282 | a.b; | ||
283 | a.c; | ||
284 | } | ||
285 | "#, | ||
286 | expect![[r#" | ||
287 | 71..153 '{ ...a.c; }': () | ||
288 | 81..82 'c': C | ||
289 | 85..86 'C': C(usize) -> C | ||
290 | 85..89 'C(1)': C | ||
291 | 87..88 '1': usize | ||
292 | 95..96 'B': B | ||
293 | 106..107 'a': A | ||
294 | 113..132 'A { b:...C(1) }': A | ||
295 | 120..121 'B': B | ||
296 | 126..127 'C': C(usize) -> C | ||
297 | 126..130 'C(1)': C | ||
298 | 128..129 '1': usize | ||
299 | 138..139 'a': A | ||
300 | 138..141 'a.b': B | ||
301 | 147..148 'a': A | ||
302 | 147..150 'a.c': C | ||
303 | "#]], | ||
304 | ); | ||
305 | } | ||
306 | |||
307 | #[test] | ||
308 | fn infer_enum() { | ||
309 | check_infer( | ||
310 | r#" | ||
311 | enum E { | ||
312 | V1 { field: u32 }, | ||
313 | V2 | ||
314 | } | ||
315 | fn test() { | ||
316 | E::V1 { field: 1 }; | ||
317 | E::V2; | ||
318 | }"#, | ||
319 | expect![[r#" | ||
320 | 51..89 '{ ...:V2; }': () | ||
321 | 57..75 'E::V1 ...d: 1 }': E | ||
322 | 72..73 '1': u32 | ||
323 | 81..86 'E::V2': E | ||
324 | "#]], | ||
325 | ); | ||
326 | } | ||
327 | |||
328 | #[test] | ||
329 | fn infer_union() { | ||
330 | check_infer( | ||
331 | r#" | ||
332 | union MyUnion { | ||
333 | foo: u32, | ||
334 | bar: f32, |