diff options
Diffstat (limited to 'crates/hir_ty/src/tests')
-rw-r--r-- | crates/hir_ty/src/tests/coercion.rs | 861 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/display_source_code.rs | 41 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/macros.rs | 787 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/method_resolution.rs | 1053 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/never_type.rs | 409 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/patterns.rs | 656 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/regression.rs | 842 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/simple.rs | 2218 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/traits.rs | 3113 |
9 files changed, 9980 insertions, 0 deletions
diff --git a/crates/hir_ty/src/tests/coercion.rs b/crates/hir_ty/src/tests/coercion.rs new file mode 100644 index 000000000..7bc6c79f3 --- /dev/null +++ b/crates/hir_ty/src/tests/coercion.rs | |||
@@ -0,0 +1,861 @@ | |||
1 | use expect_test::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/hir_ty/src/tests/display_source_code.rs b/crates/hir_ty/src/tests/display_source_code.rs new file mode 100644 index 000000000..b502135d8 --- /dev/null +++ b/crates/hir_ty/src/tests/display_source_code.rs | |||
@@ -0,0 +1,41 @@ | |||
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/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs new file mode 100644 index 000000000..597a195d0 --- /dev/null +++ b/crates/hir_ty/src/tests/macros.rs | |||
@@ -0,0 +1,787 @@ | |||
1 | use std::fs; | ||
2 | |||
3 | use expect_test::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/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/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs new file mode 100644 index 000000000..23b2601e6 --- /dev/null +++ b/crates/hir_ty/src/tests/method_resolution.rs | |||
@@ -0,0 +1,1053 @@ | |||
1 | use expect_test::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/hir_ty/src/tests/never_type.rs b/crates/hir_ty/src/tests/never_type.rs new file mode 100644 index 000000000..335c474df --- /dev/null +++ b/crates/hir_ty/src/tests/never_type.rs | |||
@@ -0,0 +1,409 @@ | |||
1 | use expect_test::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/hir_ty/src/tests/patterns.rs b/crates/hir_ty/src/tests/patterns.rs new file mode 100644 index 000000000..aeb191c79 --- /dev/null +++ b/crates/hir_ty/src/tests/patterns.rs | |||
@@ -0,0 +1,656 @@ | |||
1 | use expect_test::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/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs new file mode 100644 index 000000000..94d86b0d1 --- /dev/null +++ b/crates/hir_ty/src/tests/regression.rs | |||
@@ -0,0 +1,842 @@ | |||
1 | use expect_test::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/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs new file mode 100644 index 000000000..48db23a34 --- /dev/null +++ b/crates/hir_ty/src/tests/simple.rs | |||
@@ -0,0 +1,2218 @@ | |||
1 | use expect_test::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, | ||
335 | } | ||
336 | |||
337 | fn test() { | ||
338 | let u = MyUnion { foo: 0 }; | ||
339 | unsafe { baz(u); } | ||
340 | let u = MyUnion { bar: 0.0 }; | ||
341 | unsafe { baz(u); } | ||
342 | } | ||
343 | |||
344 | unsafe fn baz(u: MyUnion) { | ||
345 | let inner = u.foo; | ||
346 | let inner = u.bar; | ||
347 | } | ||
348 | "#, | ||
349 | expect![[r#" | ||
350 | 57..172 '{ ...); } }': () | ||
351 | 67..68 'u': MyUnion | ||
352 | 71..89 'MyUnio...o: 0 }': MyUnion | ||
353 | 86..87 '0': u32 | ||
354 | 95..113 'unsafe...(u); }': () | ||
355 | 102..113 '{ baz(u); }': () | ||
356 | 104..107 'baz': fn baz(MyUnion) | ||
357 | 104..110 'baz(u)': () | ||
358 | 108..109 'u': MyUnion | ||
359 | 122..123 'u': MyUnion | ||
360 | 126..146 'MyUnio... 0.0 }': MyUnion | ||
361 | 141..144 '0.0': f32 | ||
362 | 152..170 'unsafe...(u); }': () | ||
363 | 159..170 '{ baz(u); }': () | ||
364 | 161..164 'baz': fn baz(MyUnion) | ||
365 | 161..167 'baz(u)': () | ||
366 | 165..166 'u': MyUnion | ||
367 | 188..189 'u': MyUnion | ||
368 | 200..249 '{ ...bar; }': () | ||
369 | 210..215 'inner': u32 | ||
370 | 218..219 'u': MyUnion | ||
371 | 218..223 'u.foo': u32 | ||
372 | 233..238 'inner': f32 | ||
373 | 241..242 'u': MyUnion | ||
374 | 241..246 'u.bar': f32 | ||
375 | "#]], | ||
376 | ); | ||
377 | } | ||
378 | |||
379 | #[test] | ||
380 | fn infer_refs() { | ||
381 | check_infer( | ||
382 | r#" | ||
383 | fn test(a: &u32, b: &mut u32, c: *const u32, d: *mut u32) { | ||
384 | a; | ||
385 | *a; | ||
386 | &a; | ||
387 | &mut a; | ||
388 | b; | ||
389 | *b; | ||
390 | &b; | ||
391 | c; | ||
392 | *c; | ||
393 | d; | ||
394 | *d; | ||
395 | } | ||
396 | "#, | ||
397 | expect![[r#" | ||
398 | 8..9 'a': &u32 | ||
399 | 17..18 'b': &mut u32 | ||
400 | 30..31 'c': *const u32 | ||
401 | 45..46 'd': *mut u32 | ||
402 | 58..149 '{ ... *d; }': () | ||
403 | 64..65 'a': &u32 | ||
404 | 71..73 '*a': u32 | ||
405 | 72..73 'a': &u32 | ||
406 | 79..81 '&a': &&u32 | ||
407 | 80..81 'a': &u32 | ||
408 | 87..93 '&mut a': &mut &u32 | ||
409 | 92..93 'a': &u32 | ||
410 | 99..100 'b': &mut u32 | ||
411 | 106..108 '*b': u32 | ||
412 | 107..108 'b': &mut u32 | ||
413 | 114..116 '&b': &&mut u32 | ||
414 | 115..116 'b': &mut u32 | ||
415 | 122..123 'c': *const u32 | ||
416 | 129..131 '*c': u32 | ||
417 | 130..131 'c': *const u32 | ||
418 | 137..138 'd': *mut u32 | ||
419 | 144..146 '*d': u32 | ||
420 | 145..146 'd': *mut u32 | ||
421 | "#]], | ||
422 | ); | ||
423 | } | ||
424 | |||
425 | #[test] | ||
426 | fn infer_raw_ref() { | ||
427 | check_infer( | ||
428 | r#" | ||
429 | fn test(a: i32) { | ||
430 | &raw mut a; | ||
431 | &raw const a; | ||
432 | } | ||
433 | "#, | ||
434 | expect![[r#" | ||
435 | 8..9 'a': i32 | ||
436 | 16..53 '{ ...t a; }': () | ||
437 | 22..32 '&raw mut a': *mut i32 | ||
438 | 31..32 'a': i32 | ||
439 | 38..50 '&raw const a': *const i32 | ||
440 | 49..50 'a': i32 | ||
441 | "#]], | ||
442 | ); | ||
443 | } | ||
444 | |||
445 | #[test] | ||
446 | fn infer_literals() { | ||
447 | check_infer( | ||
448 | r##" | ||
449 | fn test() { | ||
450 | 5i32; | ||
451 | 5f32; | ||
452 | 5f64; | ||
453 | "hello"; | ||
454 | b"bytes"; | ||
455 | 'c'; | ||
456 | b'b'; | ||
457 | 3.14; | ||
458 | 5000; | ||
459 | false; | ||
460 | true; | ||
461 | r#" | ||
462 | //! doc | ||
463 | // non-doc | ||
464 | mod foo {} | ||
465 | "#; | ||
466 | br#"yolo"#; | ||
467 | } | ||
468 | "##, | ||
469 | expect![[r##" | ||
470 | 10..216 '{ ...o"#; }': () | ||
471 | 16..20 '5i32': i32 | ||
472 | 26..30 '5f32': f32 | ||
473 | 36..40 '5f64': f64 | ||
474 | 46..53 '"hello"': &str | ||
475 | 59..67 'b"bytes"': &[u8; _] | ||
476 | 73..76 ''c'': char | ||
477 | 82..86 'b'b'': u8 | ||
478 | 92..96 '3.14': f64 | ||
479 | 102..106 '5000': i32 | ||
480 | 112..117 'false': bool | ||
481 | 123..127 'true': bool | ||
482 | 133..197 'r#" ... "#': &str | ||
483 | 203..213 'br#"yolo"#': &[u8; _] | ||
484 | "##]], | ||
485 | ); | ||
486 | } | ||
487 | |||
488 | #[test] | ||
489 | fn infer_unary_op() { | ||
490 | check_infer( | ||
491 | r#" | ||
492 | enum SomeType {} | ||
493 | |||
494 | fn test(x: SomeType) { | ||
495 | let b = false; | ||
496 | let c = !b; | ||
497 | let a = 100; | ||
498 | let d: i128 = -a; | ||
499 | let e = -100; | ||
500 | let f = !!!true; | ||
501 | let g = !42; | ||
502 | let h = !10u32; | ||
503 | let j = !a; | ||
504 | -3.14; | ||
505 | !3; | ||
506 | -x; | ||
507 | !x; | ||
508 | -"hello"; | ||
509 | !"hello"; | ||
510 | } | ||
511 | "#, | ||
512 | expect![[r#" | ||
513 | 26..27 'x': SomeType | ||
514 | 39..271 '{ ...lo"; }': () | ||
515 | 49..50 'b': bool | ||
516 | 53..58 'false': bool | ||
517 | 68..69 'c': bool | ||
518 | 72..74 '!b': bool | ||
519 | 73..74 'b': bool | ||
520 | 84..85 'a': i128 | ||
521 | 88..91 '100': i128 | ||
522 | 101..102 'd': i128 | ||
523 | 111..113 '-a': i128 | ||
524 | 112..113 'a': i128 | ||
525 | 123..124 'e': i32 | ||
526 | 127..131 '-100': i32 | ||
527 | 128..131 '100': i32 | ||
528 | 141..142 'f': bool | ||
529 | 145..152 '!!!true': bool | ||
530 | 146..152 '!!true': bool | ||
531 | 147..152 '!true': bool | ||
532 | 148..152 'true': bool | ||
533 | 162..163 'g': i32 | ||
534 | 166..169 '!42': i32 | ||
535 | 167..169 '42': i32 | ||
536 | 179..180 'h': u32 | ||
537 | 183..189 '!10u32': u32 | ||
538 | 184..189 '10u32': u32 | ||
539 | 199..200 'j': i128 | ||
540 | 203..205 '!a': i128 | ||
541 | 204..205 'a': i128 | ||
542 | 211..216 '-3.14': f64 | ||
543 | 212..216 '3.14': f64 | ||
544 | 222..224 '!3': i32 | ||
545 | 223..224 '3': i32 | ||
546 | 230..232 '-x': {unknown} | ||
547 | 231..232 'x': SomeType | ||
548 | 238..240 '!x': {unknown} | ||
549 | 239..240 'x': SomeType | ||
550 | 246..254 '-"hello"': {unknown} | ||
551 | 247..254 '"hello"': &str | ||
552 | 260..268 '!"hello"': {unknown} | ||
553 | 261..268 '"hello"': &str | ||
554 | "#]], | ||
555 | ); | ||
556 | } | ||
557 | |||
558 | #[test] | ||
559 | fn infer_backwards() { | ||
560 | check_infer( | ||
561 | r#" | ||
562 | fn takes_u32(x: u32) {} | ||
563 | |||
564 | struct S { i32_field: i32 } | ||
565 | |||
566 | fn test() -> &mut &f64 { | ||
567 | let a = unknown_function(); | ||
568 | takes_u32(a); | ||
569 | let b = unknown_function(); | ||
570 | S { i32_field: b }; | ||
571 | let c = unknown_function(); | ||
572 | &mut &c | ||
573 | } | ||
574 | "#, | ||
575 | expect![[r#" | ||
576 | 13..14 'x': u32 | ||
577 | 21..23 '{}': () | ||
578 | 77..230 '{ ...t &c }': &mut &f64 | ||
579 | 87..88 'a': u32 | ||
580 | 91..107 'unknow...nction': {unknown} | ||
581 | 91..109 'unknow...tion()': u32 | ||
582 | 115..124 'takes_u32': fn takes_u32(u32) | ||
583 | 115..127 'takes_u32(a)': () | ||
584 | 125..126 'a': u32 | ||
585 | 137..138 'b': i32 | ||
586 | 141..157 'unknow...nction': {unknown} | ||
587 | 141..159 'unknow...tion()': i32 | ||
588 | 165..183 'S { i3...d: b }': S | ||
589 | 180..181 'b': i32 | ||
590 | 193..194 'c': f64 | ||
591 | 197..213 'unknow...nction': {unknown} | ||
592 | 197..215 'unknow...tion()': f64 | ||
593 | 221..228 '&mut &c': &mut &f64 | ||
594 | 226..228 '&c': &f64 | ||
595 | 227..228 'c': f64 | ||
596 | "#]], | ||
597 | ); | ||
598 | } | ||
599 | |||
600 | #[test] | ||
601 | fn infer_self() { | ||
602 | check_infer( | ||
603 | r#" | ||
604 | struct S; | ||
605 | |||
606 | impl S { | ||
607 | fn test(&self) { | ||
608 | self; | ||
609 | } | ||
610 | fn test2(self: &Self) { | ||
611 | self; | ||
612 | } | ||
613 | fn test3() -> Self { | ||
614 | S {} | ||
615 | } | ||
616 | fn test4() -> Self { | ||
617 | Self {} | ||
618 | } | ||
619 | } | ||
620 | "#, | ||
621 | expect![[r#" | ||
622 | 33..37 'self': &S | ||
623 | 39..60 '{ ... }': () | ||
624 | 49..53 'self': &S | ||
625 | 74..78 'self': &S | ||
626 | 87..108 '{ ... }': () | ||
627 | 97..101 'self': &S | ||
628 | 132..152 '{ ... }': S | ||
629 | 142..146 'S {}': S | ||
630 | 176..199 '{ ... }': S | ||
631 | 186..193 'Self {}': S | ||
632 | "#]], | ||
633 | ); | ||
634 | } | ||
635 | |||
636 | #[test] | ||
637 | fn infer_self_as_path() { | ||
638 | check_infer( | ||
639 | r#" | ||
640 | struct S1; | ||
641 | struct S2(isize); | ||
642 | enum E { | ||
643 | V1, | ||
644 | V2(u32), | ||
645 | } | ||
646 | |||
647 | impl S1 { | ||
648 | fn test() { | ||
649 | Self; | ||
650 | } | ||
651 | } | ||
652 | impl S2 { | ||
653 | fn test() { | ||
654 | Self(1); | ||
655 | } | ||
656 | } | ||
657 | impl E { | ||
658 | fn test() { | ||
659 | Self::V1; | ||
660 | Self::V2(1); | ||
661 | } | ||
662 | } | ||
663 | "#, | ||
664 | expect![[r#" | ||
665 | 86..107 '{ ... }': () | ||
666 | 96..100 'Self': S1 | ||
667 | 134..158 '{ ... }': () | ||
668 | 144..148 'Self': S2(isize) -> S2 | ||
669 | 144..151 'Self(1)': S2 | ||
670 | 149..150 '1': isize | ||
671 | 184..230 '{ ... }': () | ||
672 | 194..202 'Self::V1': E | ||
673 | 212..220 'Self::V2': V2(u32) -> E | ||
674 | 212..223 'Self::V2(1)': E | ||
675 | 221..222 '1': u32 | ||
676 | "#]], | ||
677 | ); | ||
678 | } | ||
679 | |||
680 | #[test] | ||
681 | fn infer_binary_op() { | ||
682 | check_infer( | ||
683 | r#" | ||
684 | fn f(x: bool) -> i32 { | ||
685 | 0i32 | ||
686 | } | ||
687 | |||
688 | fn test() -> bool { | ||
689 | let x = a && b; | ||
690 | let y = true || false; | ||
691 | let z = x == y; | ||
692 | let t = x != y; | ||
693 | let minus_forty: isize = -40isize; | ||
694 | let h = minus_forty <= CONST_2; | ||
695 | let c = f(z || y) + 5; | ||
696 | let d = b; | ||
697 | let g = minus_forty ^= i; | ||
698 | let ten: usize = 10; | ||
699 | let ten_is_eleven = ten == some_num; | ||
700 | |||
701 | ten < 3 | ||
702 | } | ||
703 | "#, | ||
704 | expect![[r#" | ||
705 | 5..6 'x': bool | ||
706 | 21..33 '{ 0i32 }': i32 | ||
707 | 27..31 '0i32': i32 | ||
708 | 53..369 '{ ... < 3 }': bool | ||
709 | 63..64 'x': bool | ||
710 | 67..68 'a': bool | ||
711 | 67..73 'a && b': bool | ||
712 | 72..73 'b': bool | ||
713 | 83..84 'y': bool | ||
714 | 87..91 'true': bool | ||
715 | 87..100 'true || false': bool | ||
716 | 95..100 'false': bool | ||
717 | 110..111 'z': bool | ||
718 | 114..115 'x': bool | ||
719 | 114..120 'x == y': bool | ||
720 | 119..120 'y': bool | ||
721 | 130..131 't': bool | ||
722 | 134..135 'x': bool | ||
723 | 134..140 'x != y': bool | ||
724 | 139..140 'y': bool | ||
725 | 150..161 'minus_forty': isize | ||
726 | 171..179 '-40isize': isize | ||
727 | 172..179 '40isize': isize | ||
728 | 189..190 'h': bool | ||
729 | 193..204 'minus_forty': isize | ||
730 | 193..215 'minus_...ONST_2': bool | ||
731 | 208..215 'CONST_2': isize | ||
732 | 225..226 'c': i32 | ||
733 | 229..230 'f': fn f(bool) -> i32 | ||
734 | 229..238 'f(z || y)': i32 | ||
735 | 229..242 'f(z || y) + 5': i32 | ||
736 | 231..232 'z': bool | ||
737 | 231..237 'z || y': bool | ||
738 | 236..237 'y': bool | ||
739 | 241..242 '5': i32 | ||
740 | 252..253 'd': {unknown} | ||
741 | 256..257 'b': {unknown} | ||
742 | 267..268 'g': () | ||
743 | 271..282 'minus_forty': isize | ||
744 | 271..287 'minus_...y ^= i': () | ||
745 | 286..287 'i': isize | ||
746 | 297..300 'ten': usize | ||
747 | 310..312 '10': usize | ||
748 | 322..335 'ten_is_eleven': bool | ||
749 | 338..341 'ten': usize | ||
750 | 338..353 'ten == some_num': bool | ||
751 | 345..353 'some_num': usize | ||
752 | 360..363 'ten': usize | ||
753 | 360..367 'ten < 3': bool | ||
754 | 366..367 '3': usize | ||
755 | "#]], | ||
756 | ); | ||
757 | } | ||
758 | |||
759 | #[test] | ||
760 | fn infer_shift_op() { | ||
761 | check_infer( | ||
762 | r#" | ||
763 | fn test() { | ||
764 | 1u32 << 5u8; | ||
765 | 1u32 >> 5u8; | ||
766 | } | ||
767 | "#, | ||
768 | expect![[r#" | ||
769 | 10..47 '{ ...5u8; }': () | ||
770 | 16..20 '1u32': u32 | ||
771 | 16..27 '1u32 << 5u8': u32 | ||
772 | 24..27 '5u8': u8 | ||
773 | 33..37 '1u32': u32 | ||
774 | 33..44 '1u32 >> 5u8': u32 | ||
775 | 41..44 '5u8': u8 | ||
776 | "#]], | ||
777 | ); | ||
778 | } | ||
779 | |||
780 | #[test] | ||
781 | fn infer_field_autoderef() { | ||
782 | check_infer( | ||
783 | r#" | ||
784 | struct A { | ||
785 | b: B, | ||
786 | } | ||
787 | struct B; | ||
788 | |||
789 | fn test1(a: A) { | ||
790 | let a1 = a; | ||
791 | a1.b; | ||
792 | let a2 = &a; | ||
793 | a2.b; | ||
794 | let a3 = &mut a; | ||
795 | a3.b; | ||
796 | let a4 = &&&&&&&a; | ||
797 | a4.b; | ||
798 | let a5 = &mut &&mut &&mut a; | ||
799 | a5.b; | ||
800 | } | ||
801 | |||
802 | fn test2(a1: *const A, a2: *mut A) { | ||
803 | a1.b; | ||
804 | a2.b; | ||
805 | } | ||
806 | "#, | ||
807 | expect![[r#" | ||
808 | 43..44 'a': A | ||
809 | 49..212 '{ ...5.b; }': () | ||
810 | 59..61 'a1': A | ||
811 | 64..65 'a': A | ||
812 | 71..73 'a1': A | ||
813 | 71..75 'a1.b': B | ||
814 | 85..87 'a2': &A | ||
815 | 90..92 '&a': &A | ||
816 | 91..92 'a': A | ||
817 | 98..100 'a2': &A | ||
818 | 98..102 'a2.b': B | ||
819 | 112..114 'a3': &mut A | ||
820 | 117..123 '&mut a': &mut A | ||
821 | 122..123 'a': A | ||
822 | 129..131 'a3': &mut A | ||
823 | 129..133 'a3.b': B | ||
824 | 143..145 'a4': &&&&&&&A | ||
825 | 148..156 '&&&&&&&a': &&&&&&&A | ||
826 | 149..156 '&&&&&&a': &&&&&&A | ||
827 | 150..156 '&&&&&a': &&&&&A | ||
828 | 151..156 '&&&&a': &&&&A | ||
829 | 152..156 '&&&a': &&&A | ||
830 | 153..156 '&&a': &&A | ||
831 | 154..156 '&a': &A | ||
832 | 155..156 'a': A | ||
833 | 162..164 'a4': &&&&&&&A | ||
834 | 162..166 'a4.b': B | ||
835 | 176..178 'a5': &mut &&mut &&mut A | ||
836 | 181..199 '&mut &...&mut a': &mut &&mut &&mut A | ||
837 | 186..199 '&&mut &&mut a': &&mut &&mut A | ||
838 | 187..199 '&mut &&mut a': &mut &&mut A | ||
839 | 192..199 '&&mut a': &&mut A | ||
840 | 193..199 '&mut a': &mut A | ||
841 | 198..199 'a': A | ||
842 | 205..207 'a5': &mut &&mut &&mut A | ||
843 | 205..209 'a5.b': B | ||
844 | 223..225 'a1': *const A | ||
845 | 237..239 'a2': *mut A | ||
846 | 249..272 '{ ...2.b; }': () | ||
847 | 255..257 'a1': *const A | ||
848 | 255..259 'a1.b': B | ||
849 | 265..267 'a2': *mut A | ||
850 | 265..269 'a2.b': B | ||
851 | "#]], | ||
852 | ); | ||
853 | } | ||
854 | |||
855 | #[test] | ||
856 | fn infer_argument_autoderef() { | ||
857 | check_infer( | ||
858 | r#" | ||
859 | #[lang = "deref"] | ||
860 | pub trait Deref { | ||
861 | type Target; | ||
862 | fn deref(&self) -> &Self::Target; | ||
863 | } | ||
864 | |||
865 | struct A<T>(T); | ||
866 | |||
867 | impl<T> A<T> { | ||
868 | fn foo(&self) -> &T { | ||
869 | &self.0 | ||
870 | } | ||
871 | } | ||
872 | |||
873 | struct B<T>(T); | ||
874 | |||
875 | impl<T> Deref for B<T> { | ||
876 | type Target = T; | ||
877 | fn deref(&self) -> &Self::Target { | ||
878 | &self.0 | ||
879 | } | ||
880 | } | ||
881 | |||
882 | fn test() { | ||
883 | let t = A::foo(&&B(B(A(42)))); | ||
884 | } | ||
885 | "#, | ||
886 | expect![[r#" | ||
887 | 67..71 'self': &Self | ||
888 | 138..142 'self': &A<T> | ||
889 | 150..173 '{ ... }': &T | ||
890 | 160..167 '&self.0': &T | ||
891 | 161..165 'self': &A<T> | ||
892 | 161..167 'self.0': T | ||
893 | 254..258 'self': &B<T> | ||
894 | 277..300 '{ ... }': &T | ||
895 | 287..294 '&self.0': &T | ||
896 | 288..292 'self': &B<T> | ||
897 | 288..294 'self.0': T | ||
898 | 314..352 '{ ...))); }': () | ||
899 | 324..325 't': &i32 | ||
900 | 328..334 'A::foo': fn foo<i32>(&A<i32>) -> &i32 | ||
901 | 328..349 'A::foo...42))))': &i32 | ||
902 | 335..348 '&&B(B(A(42)))': &&B<B<A<i32>>> | ||
903 | 336..348 '&B(B(A(42)))': &B<B<A<i32>>> | ||
904 | 337..338 'B': B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>> | ||
905 | 337..348 'B(B(A(42)))': B<B<A<i32>>> | ||
906 | 339..340 'B': B<A<i32>>(A<i32>) -> B<A<i32>> | ||
907 | 339..347 'B(A(42))': B<A<i32>> | ||
908 | 341..342 'A': A<i32>(i32) -> A<i32> | ||
909 | 341..346 'A(42)': A<i32> | ||
910 | 343..345 '42': i32 | ||
911 | "#]], | ||
912 | ); | ||
913 | } | ||
914 | |||
915 | #[test] | ||
916 | fn infer_method_argument_autoderef() { | ||
917 | check_infer( | ||
918 | r#" | ||
919 | #[lang = "deref"] | ||
920 | pub trait Deref { | ||
921 | type Target; | ||
922 | fn deref(&self) -> &Self::Target; | ||
923 | } | ||
924 | |||
925 | struct A<T>(*mut T); | ||
926 | |||
927 | impl<T> A<T> { | ||
928 | fn foo(&self, x: &A<T>) -> &T { | ||
929 | &*x.0 | ||
930 | } | ||
931 | } | ||
932 | |||
933 | struct B<T>(T); | ||
934 | |||
935 | impl<T> Deref for B<T> { | ||
936 | type Target = T; | ||
937 | fn deref(&self) -> &Self::Target { | ||
938 | &self.0 | ||
939 | } | ||
940 | } | ||
941 | |||
942 | fn test(a: A<i32>) { | ||
943 | let t = A(0 as *mut _).foo(&&B(B(a))); | ||
944 | } | ||
945 | "#, | ||
946 | expect![[r#" | ||
947 | 67..71 'self': &Self | ||
948 | 143..147 'self': &A<T> | ||
949 | 149..150 'x': &A<T> | ||
950 | 165..186 '{ ... }': &T | ||
951 | 175..180 '&*x.0': &T | ||
952 | 176..180 '*x.0': T | ||
953 | 177..178 'x': &A<T> | ||
954 | 177..180 'x.0': *mut T | ||
955 | 267..271 'self': &B<T> | ||
956 | 290..313 '{ ... }': &T | ||
957 | 300..307 '&self.0': &T | ||
958 | 301..305 'self': &B<T> | ||
959 | 301..307 'self.0': T | ||
960 | 325..326 'a': A<i32> | ||
961 | 336..382 '{ ...))); }': () | ||
962 | 346..347 't': &i32 | ||
963 | 350..351 'A': A<i32>(*mut i32) -> A<i32> | ||
964 | 350..364 'A(0 as *mut _)': A<i32> | ||
965 | 350..379 'A(0 as...B(a)))': &i32 | ||
966 | 352..353 '0': i32 | ||
967 | 352..363 '0 as *mut _': *mut i32 | ||
968 | 369..378 '&&B(B(a))': &&B<B<A<i32>>> | ||
969 | 370..378 '&B(B(a))': &B<B<A<i32>>> | ||
970 | 371..372 'B': B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>> | ||
971 | 371..378 'B(B(a))': B<B<A<i32>>> | ||
972 | 373..374 'B': B<A<i32>>(A<i32>) -> B<A<i32>> | ||
973 | 373..377 'B(a)': B<A<i32>> | ||
974 | 375..376 'a': A<i32> | ||
975 | "#]], | ||
976 | ); | ||
977 | } | ||
978 | |||
979 | #[test] | ||
980 | fn infer_in_elseif() { | ||
981 | check_infer( | ||
982 | r#" | ||
983 | struct Foo { field: i32 } | ||
984 | fn main(foo: Foo) { | ||
985 | if true { | ||
986 | |||
987 | } else if false { | ||
988 | foo.field | ||
989 | } | ||
990 | } | ||
991 | "#, | ||
992 | expect![[r#" | ||
993 | 34..37 'foo': Foo | ||
994 | 44..108 '{ ... } }': () | ||
995 | 50..106 'if tru... }': () | ||
996 | 53..57 'true': bool | ||
997 | 58..66 '{ }': () | ||
998 | 72..106 'if fal... }': i32 | ||
999 | 75..80 'false': bool | ||
1000 | 81..106 '{ ... }': i32 | ||
1001 | 91..94 'foo': Foo | ||
1002 | 91..100 'foo.field': i32 | ||
1003 | "#]], | ||
1004 | ) | ||
1005 | } | ||
1006 | |||
1007 | #[test] | ||
1008 | fn infer_if_match_with_return() { | ||
1009 | check_infer( | ||
1010 | r#" | ||
1011 | fn foo() { | ||
1012 | let _x1 = if true { | ||
1013 | 1 | ||
1014 | } else { | ||
1015 | return; | ||
1016 | }; | ||
1017 | let _x2 = if true { | ||
1018 | 2 | ||
1019 | } else { | ||
1020 | return | ||
1021 | }; | ||
1022 | let _x3 = match true { | ||
1023 | true => 3, | ||
1024 | _ => { | ||
1025 | return; | ||
1026 | } | ||
1027 | }; | ||
1028 | let _x4 = match true { | ||
1029 | true => 4, | ||
1030 | _ => return | ||
1031 | }; | ||
1032 | }"#, | ||
1033 | expect![[r#" | ||
1034 | 9..322 '{ ... }; }': () | ||
1035 | 19..22 '_x1': i32 | ||
1036 | 25..79 'if tru... }': i32 | ||
1037 | 28..32 'true': bool | ||
1038 | 33..50 '{ ... }': i32 | ||
1039 | 43..44 '1': i32 | ||
1040 | 56..79 '{ ... }': i32 | ||
1041 | 66..72 'return': ! | ||
1042 | 89..92 '_x2': i32 | ||
1043 | 95..148 'if tru... }': i32 | ||
1044 | 98..102 'true': bool | ||
1045 | 103..120 '{ ... }': i32 | ||
1046 | 113..114 '2': i32 | ||
1047 | 126..148 '{ ... }': ! | ||
1048 | 136..142 'return': ! | ||
1049 | 158..161 '_x3': i32 | ||
1050 | 164..246 'match ... }': i32 | ||
1051 | 170..174 'true': bool | ||
1052 | 185..189 'true': bool | ||
1053 | 185..189 'true': bool | ||
1054 | 193..194 '3': i32 | ||
1055 | 204..205 '_': bool | ||
1056 | 209..240 '{ ... }': i32 | ||
1057 | 223..229 'return': ! | ||
1058 | 256..259 '_x4': i32 | ||
1059 | 262..319 'match ... }': i32 | ||
1060 | 268..272 'true': bool | ||
1061 | 283..287 'true': bool | ||
1062 | 283..287 'true': bool | ||
1063 | 291..292 '4': i32 | ||
1064 | 302..303 '_': bool | ||
1065 | 307..313 'return': ! | ||
1066 | "#]], | ||
1067 | ) | ||
1068 | } | ||
1069 | |||
1070 | #[test] | ||
1071 | fn infer_inherent_method() { | ||
1072 | check_infer( | ||
1073 | r#" | ||
1074 | struct A; | ||
1075 | |||
1076 | impl A { | ||
1077 | fn foo(self, x: u32) -> i32 {} | ||
1078 | } | ||
1079 | |||
1080 | mod b { | ||
1081 | impl super::A { | ||
1082 | fn bar(&self, x: u64) -> i64 {} | ||
1083 | } | ||
1084 | } | ||
1085 | |||
1086 | fn test(a: A) { | ||
1087 | a.foo(1); | ||
1088 | (&a).bar(1); | ||
1089 | a.bar(1); | ||
1090 | } | ||
1091 | "#, | ||
1092 | expect![[r#" | ||
1093 | 31..35 'self': A | ||
1094 | 37..38 'x': u32 | ||
1095 | 52..54 '{}': () | ||
1096 | 102..106 'self': &A | ||
1097 | 108..109 'x': u64 | ||
1098 | 123..125 '{}': () | ||
1099 | 143..144 'a': A | ||
1100 | 149..197 '{ ...(1); }': () | ||
1101 | 155..156 'a': A | ||
1102 | 155..163 'a.foo(1)': i32 | ||
1103 | 161..162 '1': u32 | ||
1104 | 169..180 '(&a).bar(1)': i64 | ||
1105 | 170..172 '&a': &A | ||
1106 | 171..172 'a': A | ||
1107 | 178..179 '1': u64 | ||
1108 | 186..187 'a': A | ||
1109 | 186..194 'a.bar(1)': i64 | ||
1110 | 192..193 '1': u64 | ||
1111 | "#]], | ||
1112 | ); | ||
1113 | } | ||
1114 | |||
1115 | #[test] | ||
1116 | fn infer_inherent_method_str() { | ||
1117 | check_infer( | ||
1118 | r#" | ||
1119 | #[lang = "str"] | ||
1120 | impl str { | ||
1121 | fn foo(&self) -> i32 {} | ||
1122 | } | ||
1123 | |||
1124 | fn test() { | ||
1125 | "foo".foo(); | ||
1126 | } | ||
1127 | "#, | ||
1128 | expect![[r#" | ||
1129 | 39..43 'self': &str | ||
1130 | 52..54 '{}': () | ||
1131 | 68..88 '{ ...o(); }': () | ||
1132 | 74..79 '"foo"': &str | ||
1133 | 74..85 '"foo".foo()': i32 | ||
1134 | "#]], | ||
1135 | ); | ||
1136 | } | ||
1137 | |||
1138 | #[test] | ||
1139 | fn infer_tuple() { | ||
1140 | check_infer( | ||
1141 | r#" | ||
1142 | fn test(x: &str, y: isize) { | ||
1143 | let a: (u32, &str) = (1, "a"); | ||
1144 | let b = (a, x); | ||
1145 | let c = (y, x); | ||
1146 | let d = (c, x); | ||
1147 | let e = (1, "e"); | ||
1148 | let f = (e, "d"); | ||
1149 | } | ||
1150 | "#, | ||
1151 | expect![[r#" | ||
1152 | 8..9 'x': &str | ||
1153 | 17..18 'y': isize | ||
1154 | 27..169 '{ ...d"); }': () | ||
1155 | 37..38 'a': (u32, &str) | ||
1156 | 54..62 '(1, "a")': (u32, &str) | ||
1157 | 55..56 '1': u32 | ||
1158 | 58..61 '"a"': &str | ||
1159 | 72..73 'b': ((u32, &str), &str) | ||
1160 | 76..82 '(a, x)': ((u32, &str), &str) | ||
1161 | 77..78 'a': (u32, &str) | ||
1162 | 80..81 'x': &str | ||
1163 | 92..93 'c': (isize, &str) | ||
1164 | 96..102 '(y, x)': (isize, &str) | ||
1165 | 97..98 'y': isize | ||
1166 | 100..101 'x': &str | ||
1167 | 112..113 'd': ((isize, &str), &str) | ||
1168 | 116..122 '(c, x)': ((isize, &str), &str) | ||
1169 | 117..118 'c': (isize, &str) | ||
1170 | 120..121 'x': &str | ||
1171 | 132..133 'e': (i32, &str) | ||
1172 | 136..144 '(1, "e")': (i32, &str) | ||
1173 | 137..138 '1': i32 | ||
1174 | 140..143 '"e"': &str | ||
1175 | 154..155 'f': ((i32, &str), &str) | ||
1176 | 158..166 '(e, "d")': ((i32, &str), &str) | ||
1177 | 159..160 'e': (i32, &str) | ||
1178 | 162..165 '"d"': &str | ||
1179 | "#]], | ||
1180 | ); | ||
1181 | } | ||
1182 | |||
1183 | #[test] | ||
1184 | fn infer_array() { | ||
1185 | check_infer( | ||
1186 | r#" | ||
1187 | fn test(x: &str, y: isize) { | ||
1188 | let a = [x]; | ||
1189 | let b = [a, a]; | ||
1190 | let c = [b, b]; | ||
1191 | |||
1192 | let d = [y, 1, 2, 3]; | ||
1193 | let d = [1, y, 2, 3]; | ||
1194 | let e = [y]; | ||
1195 | let f = [d, d]; | ||
1196 | let g = [e, e]; | ||
1197 | |||
1198 | let h = [1, 2]; | ||
1199 | let i = ["a", "b"]; | ||
1200 | |||
1201 | let b = [a, ["b"]]; | ||
1202 | let x: [u8; 0] = []; | ||
1203 | } | ||
1204 | "#, | ||
1205 | expect![[r#" | ||
1206 | 8..9 'x': &str | ||
1207 | 17..18 'y': isize | ||
1208 | 27..292 '{ ... []; }': () | ||
1209 | 37..38 'a': [&str; _] | ||
1210 | 41..44 '[x]': [&str; _] | ||
1211 | 42..43 'x': &str | ||
1212 | 54..55 'b': [[&str; _]; _] | ||
1213 | 58..64 '[a, a]': [[&str; _]; _] | ||
1214 | 59..60 'a': [&str; _] | ||
1215 | 62..63 'a': [&str; _] | ||
1216 | 74..75 'c': [[[&str; _]; _]; _] | ||
1217 | 78..84 '[b, b]': [[[&str; _]; _]; _] | ||
1218 | 79..80 'b': [[&str; _]; _] | ||
1219 | 82..83 'b': [[&str; _]; _] | ||
1220 | 95..96 'd': [isize; _] | ||
1221 | 99..111 '[y, 1, 2, 3]': [isize; _] | ||
1222 | 100..101 'y': isize | ||
1223 | 103..104 '1': isize | ||
1224 | 106..107 '2': isize | ||
1225 | 109..110 '3': isize | ||
1226 | 121..122 'd': [isize; _] | ||
1227 | 125..137 '[1, y, 2, 3]': [isize; _] | ||
1228 | 126..127 '1': isize | ||
1229 | 129..130 'y': isize | ||
1230 | 132..133 '2': isize | ||
1231 | 135..136 '3': isize | ||
1232 | 147..148 'e': [isize; _] | ||
1233 | 151..154 '[y]': [isize; _] | ||
1234 | 152..153 'y': isize | ||
1235 | 164..165 'f': [[isize; _]; _] | ||
1236 | 168..174 '[d, d]': [[isize; _]; _] | ||
1237 | 169..170 'd': [isize; _] | ||
1238 | 172..173 'd': [isize; _] | ||
1239 | 184..185 'g': [[isize; _]; _] | ||
1240 | 188..194 '[e, e]': [[isize; _]; _] | ||
1241 | 189..190 'e': [isize; _] | ||
1242 | 192..193 'e': [isize; _] | ||
1243 | 205..206 'h': [i32; _] | ||
1244 | 209..215 '[1, 2]': [i32; _] | ||
1245 | 210..211 '1': i32 | ||
1246 | 213..214 '2': i32 | ||
1247 | 225..226 'i': [&str; _] | ||
1248 | 229..239 '["a", "b"]': [&str; _] | ||
1249 | 230..233 '"a"': &str | ||
1250 | 235..238 '"b"': &str | ||
1251 | 250..251 'b': [[&str; _]; _] | ||
1252 | 254..264 '[a, ["b"]]': [[&str; _]; _] | ||
1253 | 255..256 'a': [&str; _] | ||
1254 | 258..263 '["b"]': [&str; _] | ||
1255 | 259..262 '"b"': &str | ||
1256 | 274..275 'x': [u8; _] | ||
1257 | 287..289 '[]': [u8; _] | ||
1258 | "#]], | ||
1259 | ); | ||
1260 | } | ||
1261 | |||
1262 | #[test] | ||
1263 | fn infer_struct_generics() { | ||
1264 | check_infer( | ||
1265 | r#" | ||
1266 | struct A<T> { | ||
1267 | x: T, | ||
1268 | } | ||
1269 | |||
1270 | fn test(a1: A<u32>, i: i32) { | ||
1271 | a1.x; | ||
1272 | let a2 = A { x: i }; | ||
1273 | a2.x; | ||
1274 | let a3 = A::<i128> { x: 1 }; | ||
1275 | a3.x; | ||
1276 | } | ||
1277 | "#, | ||
1278 | expect![[r#" | ||
1279 | 35..37 'a1': A<u32> | ||
1280 | 47..48 'i': i32 | ||
1281 | 55..146 '{ ...3.x; }': () | ||
1282 | 61..63 'a1': A<u32> | ||
1283 | 61..65 'a1.x': u32 | ||
1284 | 75..77 'a2': A<i32> | ||
1285 | 80..90 'A { x: i }': A<i32> | ||
1286 | 87..88 'i': i32 | ||
1287 | 96..98 'a2': A<i32> | ||
1288 | 96..100 'a2.x': i32 | ||
1289 | 110..112 'a3': A<i128> | ||
1290 | 115..133 'A::<i1...x: 1 }': A<i128> | ||
1291 | 130..131 '1': i128 | ||
1292 | 139..141 'a3': A<i128> | ||
1293 | 139..143 'a3.x': i128 | ||
1294 | "#]], | ||
1295 | ); | ||
1296 | } | ||
1297 | |||
1298 | #[test] | ||
1299 | fn infer_tuple_struct_generics() { | ||
1300 | check_infer( | ||
1301 | r#" | ||
1302 | struct A<T>(T); | ||
1303 | enum Option<T> { Some(T), None } | ||
1304 | use Option::*; | ||
1305 | |||
1306 | fn test() { | ||
1307 | A(42); | ||
1308 | A(42u128); | ||
1309 | Some("x"); | ||
1310 | Option::Some("x"); | ||
1311 | None; | ||
1312 | let x: Option<i64> = None; | ||
1313 | } | ||
1314 | "#, | ||
1315 | expect![[r#" | ||
1316 | 75..183 '{ ...one; }': () | ||
1317 | 81..82 'A': A<i32>(i32) -> A<i32> | ||
1318 | 81..86 'A(42)': A<i32> | ||
1319 | 83..85 '42': i32 | ||
1320 | 92..93 'A': A<u128>(u128) -> A<u128> | ||
1321 | 92..101 'A(42u128)': A<u128> | ||
1322 | 94..100 '42u128': u128 | ||
1323 | 107..111 'Some': Some<&str>(&str) -> Option<&str> | ||
1324 | 107..116 'Some("x")': Option<&str> | ||
1325 | 112..115 '"x"': &str | ||
1326 | 122..134 'Option::Some': Some<&str>(&str) -> Option<&str> | ||
1327 | 122..139 'Option...e("x")': Option<&str> | ||
1328 | 135..138 '"x"': &str | ||
1329 | 145..149 'None': Option<{unknown}> | ||
1330 | 159..160 'x': Option<i64> | ||
1331 | 176..180 'None': Option<i64> | ||
1332 | "#]], | ||
1333 | ); | ||
1334 | } | ||
1335 | |||
1336 | #[test] | ||
1337 | fn infer_function_generics() { | ||
1338 | check_infer( | ||
1339 | r#" | ||
1340 | fn id<T>(t: T) -> T { t } | ||
1341 | |||
1342 | fn test() { | ||
1343 | id(1u32); | ||
1344 | id::<i128>(1); | ||
1345 | let x: u64 = id(1); | ||
1346 | } | ||
1347 | "#, | ||
1348 | expect![[r#" | ||
1349 | 9..10 't': T | ||
1350 | 20..25 '{ t }': T | ||
1351 | 22..23 't': T | ||
1352 | 37..97 '{ ...(1); }': () | ||
1353 | 43..45 'id': fn id<u32>(u32) -> u32 | ||
1354 | 43..51 'id(1u32)': u32 | ||
1355 | 46..50 '1u32': u32 | ||
1356 | 57..67 'id::<i128>': fn id<i128>(i128) -> i128 | ||
1357 | 57..70 'id::<i128>(1)': i128 | ||
1358 | 68..69 '1': i128 | ||
1359 | 80..81 'x': u64 | ||
1360 | 89..91 'id': fn id<u64>(u64) -> u64 | ||
1361 | 89..94 'id(1)': u64 | ||
1362 | 92..93 '1': u64 | ||
1363 | "#]], | ||
1364 | ); | ||
1365 | } | ||
1366 | |||
1367 | #[test] | ||
1368 | fn infer_impl_generics_basic() { | ||
1369 | check_infer( | ||
1370 | r#" | ||
1371 | struct A<T1, T2> { | ||
1372 | x: T1, | ||
1373 | y: T2, | ||
1374 | } | ||
1375 | impl<Y, X> A<X, Y> { | ||
1376 | fn x(self) -> X { | ||
1377 | self.x | ||
1378 | } | ||
1379 | fn y(self) -> Y { | ||
1380 | self.y | ||
1381 | } | ||
1382 | fn z<T>(self, t: T) -> (X, Y, T) { | ||
1383 | (self.x, self.y, t) | ||
1384 | } | ||
1385 | } | ||
1386 | |||
1387 | fn test() -> i128 { | ||
1388 | let a = A { x: 1u64, y: 1i64 }; | ||
1389 | a.x(); | ||
1390 | a.y(); | ||
1391 | a.z(1i128); | ||
1392 | a.z::<u128>(1); | ||
1393 | } | ||
1394 | "#, | ||
1395 | expect![[r#" | ||
1396 | 73..77 'self': A<X, Y> | ||
1397 | 84..106 '{ ... }': X | ||
1398 | 94..98 'self': A<X, Y> | ||
1399 | 94..100 'self.x': X | ||
1400 | 116..120 'self': A<X, Y> | ||
1401 | 127..149 '{ ... }': Y | ||
1402 | 137..141 'self': A<X, Y> | ||
1403 | 137..143 'self.y': Y | ||
1404 | 162..166 'self': A<X, Y> | ||
1405 | 168..169 't': T | ||
1406 | 187..222 '{ ... }': (X, Y, T) | ||
1407 | 197..216 '(self.....y, t)': (X, Y, T) | ||
1408 | 198..202 'self': A<X, Y> | ||
1409 | 198..204 'self.x': X | ||
1410 | 206..210 'self': A<X, Y> | ||
1411 | 206..212 'self.y': Y | ||
1412 | 214..215 't': T | ||
1413 | 244..341 '{ ...(1); }': () | ||
1414 | 254..255 'a': A<u64, i64> | ||
1415 | 258..280 'A { x:...1i64 }': A<u64, i64> | ||
1416 | 265..269 '1u64': u64 | ||
1417 | 274..278 '1i64': i64 | ||
1418 | 286..287 'a': A<u64, i64> | ||
1419 | 286..291 'a.x()': u64 | ||
1420 | 297..298 'a': A<u64, i64> | ||
1421 | 297..302 'a.y()': i64 | ||
1422 | 308..309 'a': A<u64, i64> | ||
1423 | 308..318 'a.z(1i128)': (u64, i64, i128) | ||
1424 | 312..317 '1i128': i128 | ||
1425 | 324..325 'a': A<u64, i64> | ||
1426 | 324..338 'a.z::<u128>(1)': (u64, i64, u128) | ||
1427 | 336..337 '1': u128 | ||
1428 | "#]], | ||
1429 | ); | ||
1430 | } | ||
1431 | |||
1432 | #[test] | ||
1433 | fn infer_impl_generics_with_autoderef() { | ||
1434 | check_infer( | ||
1435 | r#" | ||
1436 | enum Option<T> { | ||
1437 | Some(T), | ||
1438 | None, | ||
1439 | } | ||
1440 | impl<T> Option<T> { | ||
1441 | fn as_ref(&self) -> Option<&T> {} | ||
1442 | } | ||
1443 | fn test(o: Option<u32>) { | ||
1444 | (&o).as_ref(); | ||
1445 | o.as_ref(); | ||
1446 | } | ||
1447 | "#, | ||
1448 | expect![[r#" | ||
1449 | 77..81 'self': &Option<T> | ||
1450 | 97..99 '{}': () | ||
1451 | 110..111 'o': Option<u32> | ||
1452 | 126..164 '{ ...f(); }': () | ||
1453 | 132..145 '(&o).as_ref()': Option<&u32> | ||
1454 | 133..135 '&o': &Option<u32> | ||
1455 | 134..135 'o': Option<u32> | ||
1456 | 151..152 'o': Option<u32> | ||
1457 | 151..161 'o.as_ref()': Option<&u32> | ||
1458 | "#]], | ||
1459 | ); | ||
1460 | } | ||
1461 | |||
1462 | #[test] | ||
1463 | fn infer_generic_chain() { | ||
1464 | check_infer( | ||
1465 | r#" | ||
1466 | struct A<T> { | ||
1467 | x: T, | ||
1468 | } | ||
1469 | impl<T2> A<T2> { | ||
1470 | fn x(self) -> T2 { | ||
1471 | self.x | ||
1472 | } | ||
1473 | } | ||
1474 | fn id<T>(t: T) -> T { t } | ||
1475 | |||
1476 | fn test() -> i128 { | ||
1477 | let x = 1; | ||
1478 | let y = id(x); | ||
1479 | let a = A { x: id(y) }; | ||
1480 | let z = id(a.x); | ||
1481 | let b = A { x: z }; | ||
1482 | b.x() | ||
1483 | } | ||
1484 | "#, | ||
1485 | expect![[r#" | ||
1486 | 52..56 'self': A<T2> | ||
1487 | 64..86 '{ ... }': T2 | ||
1488 | 74..78 'self': A<T2> | ||
1489 | 74..80 'self.x': T2 | ||
1490 | 98..99 't': T | ||
1491 | 109..114 '{ t }': T | ||
1492 | 111..112 't': T | ||
1493 | 134..254 '{ ....x() }': i128 | ||
1494 | 144..145 'x': i128 | ||
1495 | 148..149 '1': i128 | ||
1496 | 159..160 'y': i128 | ||
1497 | 163..165 'id': fn id<i128>(i128) -> i128 | ||
1498 | 163..168 'id(x)': i128 | ||
1499 | 166..167 'x': i128 | ||
1500 | 178..179 'a': A<i128> | ||
1501 | 182..196 'A { x: id(y) }': A<i128> | ||
1502 | 189..191 'id': fn id<i128>(i128) -> i128 | ||
1503 | 189..194 'id(y)': i128 | ||
1504 | 192..193 'y': i128 | ||
1505 | 206..207 'z': i128 | ||
1506 | 210..212 'id': fn id<i128>(i128) -> i128 | ||
1507 | 210..217 'id(a.x)': i128 | ||
1508 | 213..214 'a': A<i128> | ||
1509 | 213..216 'a.x': i128 | ||
1510 | 227..228 'b': A<i128> | ||
1511 | 231..241 'A { x: z }': A<i128> | ||
1512 | 238..239 'z': i128 | ||
1513 | 247..248 'b': A<i128> | ||
1514 | 247..252 'b.x()': i128 | ||
1515 | "#]], | ||
1516 | ); | ||
1517 | } | ||
1518 | |||
1519 | #[test] | ||
1520 | fn infer_associated_const() { | ||
1521 | check_infer( | ||
1522 | r#" | ||
1523 | struct Struct; | ||
1524 | |||
1525 | impl Struct { | ||
1526 | const FOO: u32 = 1; | ||
1527 | } | ||
1528 | |||
1529 | enum Enum {} | ||
1530 | |||
1531 | impl Enum { | ||
1532 | const BAR: u32 = 2; | ||
1533 | } | ||
1534 | |||
1535 | trait Trait { | ||
1536 | const ID: u32; | ||
1537 | } | ||
1538 | |||
1539 | struct TraitTest; | ||
1540 | |||
1541 | impl Trait for TraitTest { | ||
1542 | const ID: u32 = 5; | ||
1543 | } | ||
1544 | |||
1545 | fn test() { | ||
1546 | let x = Struct::FOO; | ||
1547 | let y = Enum::BAR; | ||
1548 | let z = TraitTest::ID; | ||
1549 | } | ||
1550 | "#, | ||
1551 | expect![[r#" | ||
1552 | 51..52 '1': u32 | ||
1553 | 104..105 '2': u32 | ||
1554 | 212..213 '5': u32 | ||
1555 | 228..306 '{ ...:ID; }': () | ||
1556 | 238..239 'x': u32 | ||
1557 | 242..253 'Struct::FOO': u32 | ||
1558 | 263..264 'y': u32 | ||
1559 | 267..276 'Enum::BAR': u32 | ||
1560 | 286..287 'z': u32 | ||
1561 | 290..303 'TraitTest::ID': u32 | ||
1562 | "#]], | ||
1563 | ); | ||
1564 | } | ||
1565 | |||
1566 | #[test] | ||
1567 | fn infer_type_alias() { | ||
1568 | check_infer( | ||
1569 | r#" | ||
1570 | struct A<X, Y> { x: X, y: Y } | ||
1571 | type Foo = A<u32, i128>; | ||
1572 | type Bar<T> = A<T, u128>; | ||
1573 | type Baz<U, V> = A<V, U>; | ||
1574 | fn test(x: Foo, y: Bar<&str>, z: Baz<i8, u8>) { | ||
1575 | x.x; | ||
1576 | x.y; | ||
1577 | y.x; | ||
1578 | y.y; | ||
1579 | z.x; | ||
1580 | z.y; | ||
1581 | } | ||
1582 | "#, | ||
1583 | expect![[r#" | ||
1584 | 115..116 'x': A<u32, i128> | ||
1585 | 123..124 'y': A<&str, u128> | ||
1586 | 137..138 'z': A<u8, i8> | ||
1587 | 153..210 '{ ...z.y; }': () | ||
1588 | 159..160 'x': A<u32, i128> | ||
1589 | 159..162 'x.x': u32 | ||
1590 | 168..169 'x': A<u32, i128> | ||
1591 | 168..171 'x.y': i128 | ||
1592 | 177..178 'y': A<&str, u128> | ||
1593 | 177..180 'y.x': &str | ||
1594 | 186..187 'y': A<&str, u128> | ||
1595 | 186..189 'y.y': u128 | ||
1596 | 195..196 'z': A<u8, i8> | ||
1597 | 195..198 'z.x': u8 | ||
1598 | 204..205 'z': A<u8, i8> | ||
1599 | 204..207 'z.y': i8 | ||
1600 | "#]], | ||
1601 | ) | ||
1602 | } | ||
1603 | |||
1604 | #[test] | ||
1605 | fn recursive_type_alias() { | ||
1606 | check_infer( | ||
1607 | r#" | ||
1608 | struct A<X> {} | ||
1609 | type Foo = Foo; | ||
1610 | type Bar = A<Bar>; | ||
1611 | fn test(x: Foo) {} | ||
1612 | "#, | ||
1613 | expect![[r#" | ||
1614 | 58..59 'x': {unknown} | ||
1615 | 66..68 '{}': () | ||
1616 | "#]], | ||
1617 | ) | ||
1618 | } | ||
1619 | |||
1620 | #[test] | ||
1621 | fn infer_type_param() { | ||
1622 | check_infer( | ||
1623 | r#" | ||
1624 | fn id<T>(x: T) -> T { | ||
1625 | x | ||
1626 | } | ||
1627 | |||
1628 | fn clone<T>(x: &T) -> T { | ||
1629 | *x | ||
1630 | } | ||
1631 | |||
1632 | fn test() { | ||
1633 | let y = 10u32; | ||
1634 | id(y); | ||
1635 | let x: bool = clone(z); | ||
1636 | id::<i128>(1); | ||
1637 | } | ||
1638 | "#, | ||
1639 | expect![[r#" | ||
1640 | 9..10 'x': T | ||
1641 | 20..29 '{ x }': T | ||
1642 | 26..27 'x': T | ||
1643 | 43..44 'x': &T | ||
1644 | 55..65 '{ *x }': T | ||
1645 | 61..63 '*x': T | ||
1646 | 62..63 'x': &T | ||
1647 | 77..157 '{ ...(1); }': () | ||
1648 | 87..88 'y': u32 | ||
1649 | 91..96 '10u32': u32 | ||
1650 | 102..104 'id': fn id<u32>(u32) -> u32 | ||
1651 | 102..107 'id(y)': u32 | ||
1652 | 105..106 'y': u32 | ||
1653 | 117..118 'x': bool | ||
1654 | 127..132 'clone': fn clone<bool>(&bool) -> bool | ||
1655 | 127..135 'clone(z)': bool | ||
1656 | 133..134 'z': &bool | ||
1657 | 141..151 'id::<i128>': fn id<i128>(i128) -> i128 | ||
1658 | 141..154 'id::<i128>(1)': i128 | ||
1659 | 152..153 '1': i128 | ||
1660 | "#]], | ||
1661 | ); | ||
1662 | } | ||
1663 | |||
1664 | #[test] | ||
1665 | fn infer_const() { | ||
1666 | check_infer( | ||
1667 | r#" | ||
1668 | struct Foo; | ||
1669 | impl Foo { const ASSOC_CONST: u32 = 0; } | ||
1670 | const GLOBAL_CONST: u32 = 101; | ||
1671 | fn test() { | ||
1672 | const LOCAL_CONST: u32 = 99; | ||
1673 | let x = LOCAL_CONST; | ||
1674 | let z = GLOBAL_CONST; | ||
1675 | let id = Foo::ASSOC_CONST; | ||
1676 | } | ||
1677 | "#, | ||
1678 | expect![[r#" | ||
1679 | 48..49 '0': u32 | ||
1680 | 79..82 '101': u32 | ||
1681 | 94..212 '{ ...NST; }': () | ||
1682 | 137..138 'x': u32 | ||
1683 | 141..152 'LOCAL_CONST': u32 | ||
1684 | 162..163 'z': u32 | ||
1685 | 166..178 'GLOBAL_CONST': u32 | ||
1686 | 188..190 'id': u32 | ||
1687 | 193..209 'Foo::A..._CONST': u32 | ||
1688 | 125..127 '99': u32 | ||
1689 | "#]], | ||
1690 | ); | ||
1691 | } | ||
1692 | |||
1693 | #[test] | ||
1694 | fn infer_static() { | ||
1695 | check_infer( | ||
1696 | r#" | ||
1697 | static GLOBAL_STATIC: u32 = 101; | ||
1698 | static mut GLOBAL_STATIC_MUT: u32 = 101; | ||
1699 | fn test() { | ||
1700 | static LOCAL_STATIC: u32 = 99; | ||
1701 | static mut LOCAL_STATIC_MUT: u32 = 99; | ||
1702 | let x = LOCAL_STATIC; | ||
1703 | let y = LOCAL_STATIC_MUT; | ||
1704 | let z = GLOBAL_STATIC; | ||
1705 | let w = GLOBAL_STATIC_MUT; | ||
1706 | } | ||
1707 | "#, | ||
1708 | expect![[r#" | ||
1709 | 28..31 '101': u32 | ||
1710 | 69..72 '101': u32 | ||
1711 | 84..279 '{ ...MUT; }': () | ||
1712 | 172..173 'x': u32 | ||
1713 | 176..188 'LOCAL_STATIC': u32 | ||
1714 | 198..199 'y': u32 | ||
1715 | 202..218 'LOCAL_...IC_MUT': u32 | ||
1716 | 228..229 'z': u32 | ||
1717 | 232..245 'GLOBAL_STATIC': u32 | ||
1718 | 255..256 'w': u32 | ||
1719 | 259..276 'GLOBAL...IC_MUT': u32 | ||
1720 | 117..119 '99': u32 | ||
1721 | 160..162 '99': u32 | ||
1722 | "#]], | ||
1723 | ); | ||
1724 | } | ||
1725 | |||
1726 | #[test] | ||
1727 | fn shadowing_primitive() { | ||
1728 | check_types( | ||
1729 | r#" | ||
1730 | struct i32; | ||
1731 | struct Foo; | ||
1732 | |||
1733 | impl i32 { fn foo(&self) -> Foo { Foo } } | ||
1734 | |||
1735 | fn main() { | ||
1736 | let x: i32 = i32; | ||
1737 | x.foo(); | ||
1738 | //^ Foo | ||
1739 | }"#, | ||
1740 | ); | ||
1741 | } | ||
1742 | |||
1743 | #[test] | ||
1744 | fn not_shadowing_primitive_by_module() { | ||
1745 | check_types( | ||
1746 | r#" | ||
1747 | //- /str.rs | ||
1748 | fn foo() {} | ||
1749 | |||
1750 | //- /main.rs | ||
1751 | mod str; | ||
1752 | fn foo() -> &'static str { "" } | ||
1753 | |||
1754 | fn main() { | ||
1755 | foo(); | ||
1756 | //^ &str | ||
1757 | }"#, | ||
1758 | ); | ||
1759 | } | ||
1760 | |||
1761 | #[test] | ||
1762 | fn not_shadowing_module_by_primitive() { | ||
1763 | check_types( | ||
1764 | r#" | ||
1765 | //- /str.rs | ||
1766 | fn foo() -> u32 {0} | ||
1767 | |||
1768 | //- /main.rs | ||
1769 | mod str; | ||
1770 | fn foo() -> &'static str { "" } | ||
1771 | |||
1772 | fn main() { | ||
1773 | str::foo(); | ||
1774 | //^ u32 | ||
1775 | }"#, | ||
1776 | ); | ||
1777 | } | ||
1778 | |||
1779 | // This test is actually testing the shadowing behavior within hir_def. It | ||
1780 | // lives here because the testing infrastructure in hir_def isn't currently | ||
1781 | // capable of asserting the necessary conditions. | ||
1782 | #[test] | ||
1783 | fn should_be_shadowing_imports() { | ||
1784 | check_types( | ||
1785 | r#" | ||
1786 | mod a { | ||
1787 | pub fn foo() -> i8 {0} | ||
1788 | pub struct foo { a: i8 } | ||
1789 | } | ||
1790 | mod b { pub fn foo () -> u8 {0} } | ||
1791 | mod c { pub struct foo { a: u8 } } | ||
1792 | mod d { | ||
1793 | pub use super::a::*; | ||
1794 | pub use super::c::foo; | ||
1795 | pub use super::b::foo; | ||
1796 | } | ||
1797 | |||
1798 | fn main() { | ||
1799 | d::foo(); | ||
1800 | //^ u8 | ||
1801 | d::foo{a:0}; | ||
1802 | //^ u8 | ||
1803 | }"#, | ||
1804 | ); | ||
1805 | } | ||
1806 | |||
1807 | #[test] | ||
1808 | fn closure_return() { | ||
1809 | check_infer( | ||
1810 | r#" | ||
1811 | fn foo() -> u32 { | ||
1812 | let x = || -> usize { return 1; }; | ||
1813 | } | ||
1814 | "#, | ||
1815 | expect![[r#" | ||
1816 | 16..58 '{ ...; }; }': () | ||
1817 | 26..27 'x': || -> usize | ||
1818 | 30..55 '|| -> ...n 1; }': || -> usize | ||
1819 | 42..55 '{ return 1; }': usize | ||
1820 | 44..52 'return 1': ! | ||
1821 | 51..52 '1': usize | ||
1822 | "#]], | ||
1823 | ); | ||
1824 | } | ||
1825 | |||
1826 | #[test] | ||
1827 | fn closure_return_unit() { | ||
1828 | check_infer( | ||
1829 | r#" | ||
1830 | fn foo() -> u32 { | ||
1831 | let x = || { return; }; | ||
1832 | } | ||
1833 | "#, | ||
1834 | expect![[r#" | ||
1835 | 16..47 '{ ...; }; }': () | ||
1836 | 26..27 'x': || -> () | ||
1837 | 30..44 '|| { return; }': || -> () | ||
1838 | 33..44 '{ return; }': () | ||
1839 | 35..41 'return': ! | ||
1840 | "#]], | ||
1841 | ); | ||
1842 | } | ||
1843 | |||
1844 | #[test] | ||
1845 | fn closure_return_inferred() { | ||
1846 | check_infer( | ||
1847 | r#" | ||
1848 | fn foo() -> u32 { | ||
1849 | let x = || { "test" }; | ||
1850 | } | ||
1851 | "#, | ||
1852 | expect![[r#" | ||
1853 | 16..46 '{ ..." }; }': () | ||
1854 | 26..27 'x': || -> &str | ||
1855 | 30..43 '|| { "test" }': || -> &str | ||
1856 | 33..43 '{ "test" }': &str | ||
1857 | 35..41 '"test"': &str | ||
1858 | "#]], | ||
1859 | ); | ||
1860 | } | ||
1861 | |||
1862 | #[test] | ||
1863 | fn fn_pointer_return() { | ||
1864 | check_infer( | ||
1865 | r#" | ||
1866 | struct Vtable { | ||
1867 | method: fn(), | ||
1868 | } | ||
1869 | |||
1870 | fn main() { | ||
1871 | let vtable = Vtable { method: || {} }; | ||
1872 | let m = vtable.method; | ||
1873 | } | ||
1874 | "#, | ||
1875 | expect![[r#" | ||
1876 | 47..120 '{ ...hod; }': () | ||
1877 | 57..63 'vtable': Vtable | ||
1878 | 66..90 'Vtable...| {} }': Vtable | ||
1879 | 83..88 '|| {}': || -> () | ||
1880 | 86..88 '{}': () | ||
1881 | 100..101 'm': fn() | ||
1882 | 104..110 'vtable': Vtable | ||
1883 | 104..117 'vtable.method': fn() | ||
1884 | "#]], | ||
1885 | ); | ||
1886 | } | ||
1887 | |||
1888 | #[test] | ||
1889 | fn effects_smoke_test() { | ||
1890 | check_infer( | ||
1891 | r#" | ||
1892 | fn main() { | ||
1893 | let x = unsafe { 92 }; | ||
1894 | let y = async { async { () }.await }; | ||
1895 | let z = try { () }; | ||
1896 | let t = 'a: { 92 }; | ||
1897 | } | ||
1898 | "#, | ||
1899 | expect![[r#" | ||
1900 | 10..130 '{ ...2 }; }': () | ||
1901 | 20..21 'x': i32 | ||
1902 | 24..37 'unsafe { 92 }': i32 | ||
1903 | 31..37 '{ 92 }': i32 | ||
1904 | 33..35 '92': i32 | ||
1905 | 47..48 'y': {unknown} | ||
1906 | 57..79 '{ asyn...wait }': {unknown} | ||
1907 | 59..77 'async ....await': {unknown} | ||
1908 | 65..71 '{ () }': () | ||
1909 | 67..69 '()': () | ||
1910 | 89..90 'z': {unknown} | ||
1911 | 93..103 'try { () }': {unknown} | ||
1912 | 97..103 '{ () }': () | ||
1913 | 99..101 '()': () | ||
1914 | 113..114 't': i32 | ||
1915 | 121..127 '{ 92 }': i32 | ||
1916 | 123..125 '92': i32 | ||
1917 | "#]], | ||
1918 | ) | ||
1919 | } | ||
1920 | |||
1921 | #[test] | ||
1922 | fn infer_generic_from_later_assignment() { | ||
1923 | check_infer( | ||
1924 | r#" | ||
1925 | enum Option<T> { Some(T), None } | ||
1926 | use Option::*; | ||
1927 | |||
1928 | fn test() { | ||
1929 | let mut end = None; | ||
1930 | loop { | ||
1931 | end = Some(true); | ||
1932 | } | ||
1933 | } | ||
1934 | "#, | ||
1935 | expect![[r#" | ||
1936 | 59..129 '{ ... } }': () | ||
1937 | 69..76 'mut end': Option<bool> | ||
1938 | 79..83 'None': Option<bool> | ||
1939 | 89..127 'loop {... }': ! | ||
1940 | 94..127 '{ ... }': () | ||
1941 | 104..107 'end': Option<bool> | ||
1942 | 104..120 'end = ...(true)': () | ||
1943 | 110..114 'Some': Some<bool>(bool) -> Option<bool> | ||
1944 | 110..120 'Some(true)': Option<bool> | ||
1945 | 115..119 'true': bool | ||
1946 | "#]], | ||
1947 | ); | ||
1948 | } | ||
1949 | |||
1950 | #[test] | ||
1951 | fn infer_loop_break_with_val() { | ||
1952 | check_infer( | ||
1953 | r#" | ||
1954 | enum Option<T> { Some(T), None } | ||
1955 | use Option::*; | ||
1956 | |||
1957 | fn test() { | ||
1958 | let x = loop { | ||
1959 | if false { | ||
1960 | break None; | ||
1961 | } | ||
1962 | |||
1963 | break Some(true); | ||
1964 | }; | ||
1965 | } | ||
1966 | "#, | ||
1967 | expect![[r#" | ||
1968 | 59..168 '{ ... }; }': () | ||
1969 | 69..70 'x': Option<bool> | ||
1970 | 73..165 'loop {... }': Option<bool> | ||
1971 | 78..165 '{ ... }': () | ||
1972 | 88..132 'if fal... }': () | ||
1973 | 91..96 'false': bool | ||
1974 | 97..132 '{ ... }': () | ||
1975 | 111..121 'break None': ! | ||
1976 | 117..121 'None': Option<bool> | ||
1977 | 142..158 'break ...(true)': ! | ||
1978 | 148..152 'Some': Some<bool>(bool) -> Option<bool> | ||
1979 | 148..158 'Some(true)': Option<bool> | ||
1980 | 153..157 'true': bool | ||
1981 | "#]], | ||
1982 | ); | ||
1983 | } | ||
1984 | |||
1985 | #[test] | ||
1986 | fn infer_loop_break_without_val() { | ||
1987 | check_infer( | ||
1988 | r#" | ||
1989 | enum Option<T> { Some(T), None } | ||
1990 | use Option::*; | ||
1991 | |||
1992 | fn test() { | ||
1993 | let x = loop { | ||
1994 | if false { | ||
1995 | break; | ||
1996 | } | ||
1997 | }; | ||
1998 | } | ||
1999 | "#, | ||
2000 | expect![[r#" | ||
2001 | 59..136 '{ ... }; }': () | ||
2002 | 69..70 'x': () | ||
2003 | 73..133 'loop {... }': () | ||
2004 | 78..133 '{ ... }': () | ||
2005 | 88..127 'if fal... }': () | ||
2006 | 91..96 'false': bool | ||
2007 | 97..127 '{ ... }': () | ||
2008 | 111..116 'break': ! | ||
2009 | "#]], | ||
2010 | ); | ||
2011 | } | ||
2012 | |||
2013 | #[test] | ||
2014 | fn infer_labelled_break_with_val() { | ||
2015 | check_infer( | ||
2016 | r#" | ||
2017 | fn foo() { | ||
2018 | let _x = || 'outer: loop { | ||
2019 | let inner = 'inner: loop { | ||
2020 | let i = Default::default(); | ||
2021 | if (break 'outer i) { | ||
2022 | loop { break 'inner 5i8; }; | ||
2023 | } else if true { | ||
2024 | break 'inner 6; | ||
2025 | } | ||
2026 | break 7; | ||
2027 | }; | ||
2028 | break inner < 8; | ||
2029 | }; | ||
2030 | } | ||
2031 | "#, | ||
2032 | expect![[r#" | ||
2033 | 9..335 '{ ... }; }': () | ||
2034 | 19..21 '_x': || -> bool | ||
2035 | 24..332 '|| 'ou... }': || -> bool | ||
2036 | 27..332 ''outer... }': bool | ||
2037 | 40..332 '{ ... }': () | ||
2038 | 54..59 'inner': i8 | ||
2039 | 62..300 ''inner... }': i8 | ||
2040 | 75..300 '{ ... }': () | ||
2041 | 93..94 'i': bool | ||
2042 | 97..113 'Defaul...efault': {unknown} | ||
2043 | 97..115 'Defaul...ault()': bool | ||
2044 | 129..269 'if (br... }': () | ||
2045 | 133..147 'break 'outer i': ! | ||
2046 | 146..147 'i': bool | ||
2047 | 149..208 '{ ... }': () | ||
2048 | 167..193 'loop {...5i8; }': ! | ||
2049 | 172..193 '{ brea...5i8; }': () | ||
2050 | 174..190 'break ...er 5i8': ! | ||
2051 | 187..190 '5i8': i8 | ||
2052 | 214..269 'if tru... }': () | ||
2053 | 217..221 'true': bool | ||
2054 | 222..269 '{ ... }': () | ||
2055 | 240..254 'break 'inner 6': ! | ||
2056 | 253..254 '6': i8 | ||
2057 | 282..289 'break 7': ! | ||
2058 | 288..289 '7': i8 | ||
2059 | 310..325 'break inner < 8': ! | ||
2060 | 316..321 'inner': i8 | ||
2061 | 316..325 'inner < 8': bool | ||
2062 | 324..325 '8': i8 | ||
2063 | "#]], | ||
2064 | ); | ||
2065 | } | ||
2066 | |||
2067 | #[test] | ||
2068 | fn generic_default() { | ||
2069 | check_infer( | ||
2070 | r#" | ||
2071 | struct Thing<T = ()> { t: T } | ||
2072 | enum OtherThing<T = ()> { | ||
2073 | One { t: T }, | ||
2074 | Two(T), | ||
2075 | } | ||
2076 | |||
2077 | fn test(t1: Thing, t2: OtherThing, t3: Thing<i32>, t4: OtherThing<i32>) { | ||
2078 | t1.t; | ||
2079 | t3.t; | ||
2080 | match t2 { | ||
2081 | OtherThing::One { t } => { t; }, | ||
2082 | OtherThing::Two(t) => { t; }, | ||
2083 | } | ||
2084 | match t4 { | ||
2085 | OtherThing::One { t } => { t; }, | ||
2086 | OtherThing::Two(t) => { t; }, | ||
2087 | } | ||
2088 | } | ||
2089 | "#, | ||
2090 | expect![[r#" | ||
2091 | 97..99 't1': Thing<()> | ||
2092 | 108..110 't2': OtherThing<()> | ||
2093 | 124..126 't3': Thing<i32> | ||
2094 | 140..142 't4': OtherThing<i32> | ||
2095 | 161..384 '{ ... } }': () | ||
2096 | 167..169 't1': Thing<()> | ||
2097 | 167..171 't1.t': () | ||
2098 | 177..179 't3': Thing<i32> | ||
2099 | 177..181 't3.t': i32 | ||
2100 | 187..282 'match ... }': () | ||
2101 | 193..195 't2': OtherThing<()> | ||
2102 | 206..227 'OtherT... { t }': OtherThing<()> | ||
2103 | 224..225 't': () | ||
2104 | 231..237 '{ t; }': () | ||
2105 | 233..234 't': () | ||
2106 | 247..265 'OtherT...Two(t)': OtherThing<()> | ||
2107 | 263..264 't': () | ||
2108 | 269..275 '{ t; }': () | ||
2109 | 271..272 't': () | ||
2110 | 287..382 'match ... }': () | ||
2111 | 293..295 't4': OtherThing<i32> | ||
2112 | 306..327 'OtherT... { t }': OtherThing<i32> | ||
2113 | 324..325 't': i32 | ||
2114 | 331..337 '{ t; }': () | ||
2115 | 333..334 't': i32 | ||
2116 | 347..365 'OtherT...Two(t)': OtherThing<i32> | ||
2117 | 363..364 't': i32 | ||
2118 | 369..375 '{ t; }': () | ||
2119 | 371..372 't': i32 | ||
2120 | "#]], | ||
2121 | ); | ||
2122 | } | ||
2123 | |||
2124 | #[test] | ||
2125 | fn generic_default_in_struct_literal() { | ||
2126 | check_infer( | ||
2127 | r#" | ||
2128 | struct Thing<T = ()> { t: T } | ||
2129 | enum OtherThing<T = ()> { | ||
2130 | One { t: T }, | ||
2131 | Two(T), | ||
2132 | } | ||
2133 | |||
2134 | fn test() { | ||
2135 | let x = Thing { t: loop {} }; | ||
2136 | let y = Thing { t: () }; | ||
2137 | let z = Thing { t: 1i32 }; | ||
2138 | if let Thing { t } = z { | ||
2139 | t; | ||
2140 | } | ||
2141 | |||
2142 | let a = OtherThing::One { t: 1i32 }; | ||
2143 | let b = OtherThing::Two(1i32); | ||
2144 | } | ||
2145 | "#, | ||
2146 | expect![[r#" | ||
2147 | 99..319 '{ ...32); }': () | ||
2148 | 109..110 'x': Thing<!> | ||
2149 | 113..133 'Thing ...p {} }': Thing<!> | ||
2150 | 124..131 'loop {}': ! | ||
2151 | 129..131 '{}': () | ||
2152 | 143..144 'y': Thing<()> | ||
2153 | 147..162 'Thing { t: () }': Thing<()> | ||
2154 | 158..160 '()': () | ||
2155 | 172..173 'z': Thing<i32> | ||
2156 | 176..193 'Thing ...1i32 }': Thing<i32> | ||
2157 | 187..191 '1i32': i32 | ||
2158 | 199..240 'if let... }': () | ||
2159 | 206..217 'Thing { t }': Thing<i32> | ||
2160 | 214..215 't': i32 | ||
2161 | 220..221 'z': Thing<i32> | ||
2162 | 222..240 '{ ... }': () | ||
2163 | 232..233 't': i32 | ||
2164 | 250..251 'a': OtherThing<i32> | ||
2165 | 254..281 'OtherT...1i32 }': OtherThing<i32> | ||
2166 | 275..279 '1i32': i32 | ||
2167 | 291..292 'b': OtherThing<i32> | ||
2168 | 295..310 'OtherThing::Two': Two<i32>(i32) -> OtherThing<i32> | ||
2169 | 295..316 'OtherT...(1i32)': OtherThing<i32> | ||
2170 | 311..315 '1i32': i32 | ||
2171 | "#]], | ||
2172 | ); | ||
2173 | } | ||
2174 | |||
2175 | #[test] | ||
2176 | fn generic_default_depending_on_other_type_arg() { | ||
2177 | // FIXME: the {unknown} is a bug | ||
2178 | check_infer( | ||
2179 | r#" | ||
2180 | struct Thing<T = u128, F = fn() -> T> { t: T } | ||
2181 | |||
2182 | fn test(t1: Thing<u32>, t2: Thing) { | ||
2183 | t1; | ||
2184 | t2; | ||
2185 | Thing::<_> { t: 1u32 }; | ||
2186 | } | ||
2187 | "#, | ||
2188 | expect![[r#" | ||
2189 | 56..58 't1': Thing<u32, fn() -> u32> | ||
2190 | 72..74 't2': Thing<u128, fn() -> u128> | ||
2191 | 83..130 '{ ...2 }; }': () | ||
2192 | 89..91 't1': Thing<u32, fn() -> u32> | ||
2193 | 97..99 't2': Thing<u128, fn() -> u128> | ||
2194 | 105..127 'Thing:...1u32 }': Thing<u32, fn() -> {unknown}> | ||
2195 | 121..125 '1u32': u32 | ||
2196 | "#]], | ||
2197 | ); | ||
2198 | } | ||
2199 | |||
2200 | #[test] | ||
2201 | fn generic_default_depending_on_other_type_arg_forward() { | ||
2202 | // the {unknown} here is intentional, as defaults are not allowed to | ||
2203 | // refer to type parameters coming later | ||
2204 | check_infer( | ||
2205 | r#" | ||
2206 | struct Thing<F = fn() -> T, T = u128> { t: T } | ||
2207 | |||
2208 | fn test(t1: Thing) { | ||
2209 | t1; | ||
2210 | } | ||
2211 | "#, | ||
2212 | expect![[r#" | ||
2213 | 56..58 't1': Thing<fn() -> {unknown}, u128> | ||
2214 | 67..78 '{ t1; }': () | ||
2215 | 73..75 't1': Thing<fn() -> {unknown}, u128> | ||
2216 | "#]], | ||
2217 | ); | ||
2218 | } | ||
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs new file mode 100644 index 000000000..1f1056962 --- /dev/null +++ b/crates/hir_ty/src/tests/traits.rs | |||
@@ -0,0 +1,3113 @@ | |||
1 | use expect_test::expect; | ||
2 | use test_utils::mark; | ||
3 | |||
4 | use super::{check_infer, check_infer_with_mismatches, check_types}; | ||
5 | |||
6 | #[test] | ||
7 | fn infer_await() { | ||
8 | check_types( | ||
9 | r#" | ||
10 | //- /main.rs crate:main deps:core | ||
11 | struct IntFuture; | ||
12 | |||
13 | impl Future for IntFuture { | ||
14 | type Output = u64; | ||
15 | } | ||
16 | |||
17 | fn test() { | ||
18 | let r = IntFuture; | ||
19 | let v = r.await; | ||
20 | v; | ||
21 | } //^ u64 | ||
22 | |||
23 | //- /core.rs crate:core | ||
24 | #[prelude_import] use future::*; | ||
25 | mod future { | ||
26 | #[lang = "future_trait"] | ||
27 | trait Future { | ||
28 | type Output; | ||
29 | } | ||
30 | } | ||
31 | "#, | ||
32 | ); | ||
33 | } | ||
34 | |||
35 | #[test] | ||
36 | fn infer_async() { | ||
37 | check_types( | ||
38 | r#" | ||
39 | //- /main.rs crate:main deps:core | ||
40 | async fn foo() -> u64 { | ||
41 | 128 | ||
42 | } | ||
43 | |||
44 | fn test() { | ||
45 | let r = foo(); | ||
46 | let v = r.await; | ||
47 | v; | ||
48 | } //^ u64 | ||
49 | |||
50 | //- /core.rs crate:core | ||
51 | #[prelude_import] use future::*; | ||
52 | mod future { | ||
53 | #[lang = "future_trait"] | ||
54 | trait Future { | ||
55 | type Output; | ||
56 | } | ||
57 | } | ||
58 | "#, | ||
59 | ); | ||
60 | } | ||
61 | |||
62 | #[test] | ||
63 | fn infer_desugar_async() { | ||
64 | check_types( | ||
65 | r#" | ||
66 | //- /main.rs crate:main deps:core | ||
67 | async fn foo() -> u64 { | ||
68 | 128 | ||
69 | } | ||
70 | |||
71 | fn test() { | ||
72 | let r = foo(); | ||
73 | r; | ||
74 | } //^ impl Future<Output = u64> | ||
75 | |||
76 | //- /core.rs crate:core | ||
77 | #[prelude_import] use future::*; | ||
78 | mod future { | ||
79 | trait Future { | ||
80 | type Output; | ||
81 | } | ||
82 | } | ||
83 | |||
84 | "#, | ||
85 | ); | ||
86 | } | ||
87 | |||
88 | #[test] | ||
89 | fn infer_try() { | ||
90 | check_types( | ||
91 | r#" | ||
92 | //- /main.rs crate:main deps:core | ||
93 | fn test() { | ||
94 | let r: Result<i32, u64> = Result::Ok(1); | ||
95 | let v = r?; | ||
96 | v; | ||
97 | } //^ i32 | ||
98 | |||
99 | //- /core.rs crate:core | ||
100 | #[prelude_import] use ops::*; | ||
101 | mod ops { | ||
102 | trait Try { | ||
103 | type Ok; | ||
104 | type Error; | ||
105 | } | ||
106 | } | ||
107 | |||
108 | #[prelude_import] use result::*; | ||
109 | mod result { | ||
110 | enum Result<O, E> { | ||
111 | Ok(O), | ||
112 | Err(E) | ||
113 | } | ||
114 | |||
115 | impl<O, E> crate::ops::Try for Result<O, E> { | ||
116 | type Ok = O; | ||
117 | type Error = E; | ||
118 | } | ||
119 | } | ||
120 | "#, | ||
121 | ); | ||
122 | } | ||
123 | |||
124 | #[test] | ||
125 | fn infer_for_loop() { | ||
126 | check_types( | ||
127 | r#" | ||
128 | //- /main.rs crate:main deps:core,alloc | ||
129 | use alloc::collections::Vec; | ||
130 | |||
131 | fn test() { | ||
132 | let v = Vec::new(); | ||
133 | v.push("foo"); | ||
134 | for x in v { | ||
135 | x; | ||
136 | } //^ &str | ||
137 | } | ||
138 | |||
139 | //- /core.rs crate:core | ||
140 | #[prelude_import] use iter::*; | ||
141 | mod iter { | ||
142 | trait IntoIterator { | ||
143 | type Item; | ||
144 | } | ||
145 | } | ||
146 | |||
147 | //- /alloc.rs crate:alloc deps:core | ||
148 | mod collections { | ||
149 | struct Vec<T> {} | ||
150 | impl<T> Vec<T> { | ||
151 | fn new() -> Self { Vec {} } | ||
152 | fn push(&mut self, t: T) { } | ||
153 | } | ||
154 | |||
155 | impl<T> IntoIterator for Vec<T> { | ||
156 | type Item=T; | ||
157 | } | ||
158 | } | ||
159 | "#, | ||
160 | ); | ||
161 | } | ||
162 | |||
163 | #[test] | ||
164 | fn infer_ops_neg() { | ||
165 | check_types( | ||
166 | r#" | ||
167 | //- /main.rs crate:main deps:std | ||
168 | struct Bar; | ||
169 | struct Foo; | ||
170 | |||
171 | impl std::ops::Neg for Bar { | ||
172 | type Output = Foo; | ||
173 | } | ||
174 | |||
175 | fn test() { | ||
176 | let a = Bar; | ||
177 | let b = -a; | ||
178 | b; | ||
179 | } //^ Foo | ||
180 | |||
181 | //- /std.rs crate:std | ||
182 | #[prelude_import] use ops::*; | ||
183 | mod ops { | ||
184 | #[lang = "neg"] | ||
185 | pub trait Neg { | ||
186 | type Output; | ||
187 | } | ||
188 | } | ||
189 | "#, | ||
190 | ); | ||
191 | } | ||
192 | |||
193 | #[test] | ||
194 | fn infer_ops_not() { | ||
195 | check_types( | ||
196 | r#" | ||
197 | //- /main.rs crate:main deps:std | ||
198 | struct Bar; | ||
199 | struct Foo; | ||
200 | |||
201 | impl std::ops::Not for Bar { | ||
202 | type Output = Foo; | ||
203 | } | ||
204 | |||
205 | fn test() { | ||
206 | let a = Bar; | ||
207 | let b = !a; | ||
208 | b; | ||
209 | } //^ Foo | ||
210 | |||
211 | //- /std.rs crate:std | ||
212 | #[prelude_import] use ops::*; | ||
213 | mod ops { | ||
214 | #[lang = "not"] | ||
215 | pub trait Not { | ||
216 | type Output; | ||
217 | } | ||
218 | } | ||
219 | "#, | ||
220 | ); | ||
221 | } | ||
222 | |||
223 | #[test] | ||
224 | fn infer_from_bound_1() { | ||
225 | check_infer( | ||
226 | r#" | ||
227 | trait Trait<T> {} | ||
228 | struct S<T>(T); | ||
229 | impl<U> Trait<U> for S<U> {} | ||
230 | fn foo<T: Trait<u32>>(t: T) {} | ||
231 | fn test() { | ||
232 | let s = S(unknown); | ||
233 | foo(s); | ||
234 | } | ||
235 | "#, | ||
236 | expect![[r#" | ||
237 | 85..86 't': T | ||
238 | 91..93 '{}': () | ||
239 | 104..143 '{ ...(s); }': () | ||
240 | 114..115 's': S<u32> | ||
241 | 118..119 'S': S<u32>(u32) -> S<u32> | ||
242 | 118..128 'S(unknown)': S<u32> | ||
243 | 120..127 'unknown': u32 | ||
244 | 134..137 'foo': fn foo<S<u32>>(S<u32>) | ||
245 | 134..140 'foo(s)': () | ||
246 | 138..139 's': S<u32> | ||
247 | "#]], | ||
248 | ); | ||
249 | } | ||
250 | |||
251 | #[test] | ||
252 | fn infer_from_bound_2() { | ||
253 | check_infer( | ||
254 | r#" | ||
255 | trait Trait<T> {} | ||
256 | struct S<T>(T); | ||
257 | impl<U> Trait<U> for S<U> {} | ||
258 | fn foo<U, T: Trait<U>>(t: T) -> U {} | ||
259 | fn test() { | ||
260 | let s = S(unknown); | ||
261 | let x: u32 = foo(s); | ||
262 | } | ||
263 | "#, | ||
264 | expect![[r#" | ||
265 | 86..87 't': T | ||
266 | 97..99 '{}': () | ||
267 | 110..162 '{ ...(s); }': () | ||
268 | 120..121 's': S<u32> | ||
269 | 124..125 'S': S<u32>(u32) -> S<u32> | ||
270 | 124..134 'S(unknown)': S<u32> | ||
271 | 126..133 'unknown': u32 | ||
272 | 144..145 'x': u32 | ||
273 | 153..156 'foo': fn foo<u32, S<u32>>(S<u32>) -> u32 | ||
274 | 153..159 'foo(s)': u32 | ||
275 | 157..158 's': S<u32> | ||
276 | "#]], | ||
277 | ); | ||
278 | } | ||
279 | |||
280 | #[test] | ||
281 | fn trait_default_method_self_bound_implements_trait() { | ||
282 | mark::check!(trait_self_implements_self); | ||
283 | check_infer( | ||
284 | r#" | ||
285 | trait Trait { | ||
286 | fn foo(&self) -> i64; | ||
287 | fn bar(&self) -> { | ||
288 | let x = self.foo(); | ||
289 | } | ||
290 | } | ||
291 | "#, | ||
292 | expect![[r#" | ||
293 | 26..30 'self': &Self | ||
294 | 52..56 'self': &Self | ||
295 | 61..96 '{ ... }': () | ||
296 | 75..76 'x': i64 | ||
297 | 79..83 'self': &Self | ||
298 | 79..89 'self.foo()': i64 | ||
299 | "#]], | ||
300 | ); | ||
301 | } | ||
302 | |||
303 | #[test] | ||
304 | fn trait_default_method_self_bound_implements_super_trait() { | ||
305 | check_infer( | ||
306 | r#" | ||
307 | trait SuperTrait { | ||
308 | fn foo(&self) -> i64; | ||
309 | } | ||
310 | trait Trait: SuperTrait { | ||
311 | fn bar(&self) -> { | ||
312 | let x = self.foo(); | ||
313 | } | ||
314 | } | ||
315 | "#, | ||
316 | expect![[r#" | ||
317 | 31..35 'self': &Self | ||
318 | 85..89 'self': &Self | ||
319 | 94..129 '{ ... }': () | ||
320 | 108..109 'x': i64 | ||
321 | 112..116 'self': &Self | ||
322 | 112..122 'self.foo()': i64 | ||
323 | "#]], | ||
324 | ); | ||
325 | } | ||
326 | |||
327 | #[test] | ||
328 | fn infer_project_associated_type() { | ||
329 | check_infer( | ||
330 | r#" | ||
331 | trait Iterable { | ||
332 | type Item; | ||
333 | } | ||
334 | struct S; | ||
335 | impl Iterable for S { type Item = u32; } | ||
336 | fn test<T: Iterable>() { | ||
337 | let x: <S as Iterable>::Item = 1; | ||
338 | let y: <T as Iterable>::Item = no_matter; | ||
339 | let z: T::Item = no_matter; | ||
340 | let a: <T>::Item = no_matter; | ||
341 | } | ||
342 | "#, | ||
343 | expect![[r#" | ||
344 | 108..261 '{ ...ter; }': () | ||
345 | 118..119 'x': u32 | ||
346 | 145..146 '1': u32 | ||
347 | 156..157 'y': Iterable::Item<T> | ||
348 | 183..192 'no_matter': Iterable::Item<T> | ||
349 | 202..203 'z': Iterable::Item<T> | ||
350 | 215..224 'no_matter': Iterable::Item<T> | ||
351 | 234..235 'a': Iterable::Item<T> | ||
352 | 249..258 'no_matter': Iterable::Item<T> | ||
353 | "#]], | ||
354 | ); | ||
355 | } | ||
356 | |||
357 | #[test] | ||
358 | fn infer_return_associated_type() { | ||
359 | check_infer( | ||
360 | r#" | ||
361 | trait Iterable { | ||
362 | type Item; | ||
363 | } | ||
364 | struct S; | ||
365 | impl Iterable for S { type Item = u32; } | ||
366 | fn foo1<T: Iterable>(t: T) -> T::Item {} | ||
367 | fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item {} | ||
368 | fn foo3<T: Iterable>(t: T) -> <T>::Item {} | ||
369 | fn test() { | ||
370 | let x = foo1(S); | ||
371 | let y = foo2(S); | ||
372 | let z = foo3(S); | ||
373 | } | ||
374 | "#, | ||
375 | expect![[r#" | ||
376 | 106..107 't': T | ||
377 | 123..125 '{}': () | ||
378 | 147..148 't': T | ||
379 | 178..180 '{}': () | ||
380 | 202..203 't': T | ||
381 | 221..223 '{}': () | ||
382 | 234..300 '{ ...(S); }': () | ||
383 | 244..245 'x': u32 | ||
384 | 248..252 'foo1': fn foo1<S>(S) -> <S as Iterable>::Item | ||
385 | 248..255 'foo1(S)': u32 | ||
386 | 253..254 'S': S | ||
387 | 265..266 'y': u32 | ||
388 | 269..273 'foo2': fn foo2<S>(S) -> <S as Iterable>::Item | ||
389 | 269..276 'foo2(S)': u32 | ||
390 | 274..275 'S': S | ||
391 | 286..287 'z': u32 | ||
392 | 290..294 'foo3': fn foo3<S>(S) -> <S as Iterable>::Item | ||
393 | 290..297 'foo3(S)': u32 | ||
394 | 295..296 'S': S | ||
395 | "#]], | ||
396 | ); | ||
397 | } | ||
398 | |||
399 | #[test] | ||
400 | fn infer_associated_type_bound() { | ||
401 | check_infer( | ||
402 | r#" | ||
403 | trait Iterable { | ||
404 | type Item; | ||
405 | } | ||
406 | fn test<T: Iterable<Item=u32>>() { | ||
407 | let y: T::Item = unknown; | ||
408 | } | ||
409 | "#, | ||
410 | expect![[r#" | ||
411 | 67..100 '{ ...own; }': () | ||
412 | 77..78 'y': u32 | ||
413 | 90..97 'unknown': u32 | ||
414 | "#]], | ||
415 | ); | ||
416 | } | ||
417 | |||
418 | #[test] | ||
419 | fn infer_const_body() { | ||
420 | check_infer( | ||
421 | r#" | ||
422 | const A: u32 = 1 + 1; | ||
423 | static B: u64 = { let x = 1; x }; | ||
424 | "#, | ||
425 | expect![[r#" | ||
426 | 15..16 '1': u32 | ||
427 | 15..20 '1 + 1': u32 | ||
428 | 19..20 '1': u32 | ||
429 | 38..54 '{ let ...1; x }': u64 | ||
430 | 44..45 'x': u64 | ||
431 | 48..49 '1': u64 | ||
432 | 51..52 'x': u64 | ||
433 | "#]], | ||
434 | ); | ||
435 | } | ||
436 | |||
437 | #[test] | ||
438 | fn tuple_struct_fields() { | ||
439 | check_infer( | ||
440 | r#" | ||
441 | struct S(i32, u64); | ||
442 | fn test() -> u64 { | ||
443 | let a = S(4, 6); | ||
444 | let b = a.0; | ||
445 | a.1 | ||
446 | } | ||
447 | "#, | ||
448 | expect![[r#" | ||
449 | 37..86 '{ ... a.1 }': u64 | ||
450 | 47..48 'a': S | ||
451 | 51..52 'S': S(i32, u64) -> S | ||
452 | 51..58 'S(4, 6)': S | ||
453 | 53..54 '4': i32 | ||
454 | 56..57 '6': u64 | ||
455 | 68..69 'b': i32 | ||
456 | 72..73 'a': S | ||
457 | 72..75 'a.0': i32 | ||
458 | 81..82 'a': S | ||
459 | 81..84 'a.1': u64 | ||
460 | "#]], | ||
461 | ); | ||
462 | } | ||
463 | |||
464 | #[test] | ||
465 | fn tuple_struct_with_fn() { | ||
466 | check_infer( | ||
467 | r#" | ||
468 | struct S(fn(u32) -> u64); | ||
469 | fn test() -> u64 { | ||
470 | let a = S(|i| 2*i); | ||
471 | let b = a.0(4); | ||
472 | a.0(2) | ||
473 | } | ||
474 | "#, | ||
475 | expect![[r#" | ||
476 | 43..101 '{ ...0(2) }': u64 | ||
477 | 53..54 'a': S | ||
478 | 57..58 'S': S(fn(u32) -> u64) -> S | ||
479 | 57..67 'S(|i| 2*i)': S | ||
480 | 59..66 '|i| 2*i': |u32| -> u64 | ||
481 | 60..61 'i': u32 | ||
482 | 63..64 '2': u32 | ||
483 | 63..66 '2*i': u32 | ||
484 | 65..66 'i': u32 | ||
485 | 77..78 'b': u64 | ||
486 | 81..82 'a': S | ||
487 | 81..84 'a.0': fn(u32) -> u64 | ||
488 | 81..87 'a.0(4)': u64 | ||
489 | 85..86 '4': u32 | ||
490 | 93..94 'a': S | ||
491 | 93..96 'a.0': fn(u32) -> u64 | ||
492 | 93..99 'a.0(2)': u64 | ||
493 | 97..98 '2': u32 | ||
494 | "#]], | ||
495 | ); | ||
496 | } | ||
497 | |||
498 | #[test] | ||
499 | fn indexing_arrays() { | ||
500 | check_infer( | ||
501 | "fn main() { &mut [9][2]; }", | ||
502 | expect![[r#" | ||
503 | 10..26 '{ &mut...[2]; }': () | ||
504 | 12..23 '&mut [9][2]': &mut {unknown} | ||
505 | 17..20 '[9]': [i32; _] | ||
506 | 17..23 '[9][2]': {unknown} | ||
507 | 18..19 '9': i32 | ||
508 | 21..22 '2': i32 | ||
509 | "#]], | ||
510 | ) | ||
511 | } | ||
512 | |||
513 | #[test] | ||
514 | fn infer_ops_index() { | ||
515 | check_types( | ||
516 | r#" | ||
517 | //- /main.rs crate:main deps:std | ||
518 | struct Bar; | ||
519 | struct Foo; | ||
520 | |||
521 | impl std::ops::Index<u32> for Bar { | ||
522 | type Output = Foo; | ||
523 | } | ||
524 | |||
525 | fn test() { | ||
526 | let a = Bar; | ||
527 | let b = a[1u32]; | ||
528 | b; | ||
529 | } //^ Foo | ||
530 | |||
531 | //- /std.rs crate:std | ||
532 | #[prelude_import] use ops::*; | ||
533 | mod ops { | ||
534 | #[lang = "index"] | ||
535 | pub trait Index<Idx> { | ||
536 | type Output; | ||
537 | } | ||
538 | } | ||
539 | "#, | ||
540 | ); | ||
541 | } | ||
542 | |||
543 | #[test] | ||
544 | fn infer_ops_index_int() { | ||
545 | check_types( | ||
546 | r#" | ||
547 | //- /main.rs crate:main deps:std | ||
548 | struct Bar; | ||
549 | struct Foo; | ||
550 | |||
551 | impl std::ops::Index<u32> for Bar { | ||
552 | type Output = Foo; | ||
553 | } | ||
554 | |||
555 | struct Range; | ||
556 | impl std::ops::Index<Range> for Bar { | ||
557 | type Output = Bar; | ||
558 | } | ||
559 | |||
560 | fn test() { | ||
561 | let a = Bar; | ||
562 | let b = a[1]; | ||
563 | b; | ||
564 | //^ Foo | ||
565 | } | ||
566 | |||
567 | //- /std.rs crate:std | ||
568 | #[prelude_import] use ops::*; | ||
569 | mod ops { | ||
570 | #[lang = "index"] | ||
571 | pub trait Index<Idx> { | ||
572 | type Output; | ||
573 | } | ||
574 | } | ||
575 | "#, | ||
576 | ); | ||
577 | } | ||
578 | |||
579 | #[test] | ||
580 | fn infer_ops_index_autoderef() { | ||
581 | check_types( | ||
582 | r#" | ||
583 | //- /main.rs crate:main deps:std | ||
584 | fn test() { | ||
585 | let a = &[1u32, 2, 3]; | ||
586 | let b = a[1u32]; | ||
587 | b; | ||
588 | } //^ u32 | ||
589 | |||
590 | //- /std.rs crate:std | ||
591 | impl<T> ops::Index<u32> for [T] { | ||
592 | type Output = T; | ||
593 | } | ||
594 | |||
595 | #[prelude_import] use ops::*; | ||
596 | mod ops { | ||
597 | #[lang = "index"] | ||
598 | pub trait Index<Idx> { | ||
599 | type Output; | ||
600 | } | ||
601 | } | ||
602 | "#, | ||
603 | ); | ||
604 | } | ||
605 | |||
606 | #[test] | ||
607 | fn deref_trait() { | ||
608 | check_types( | ||
609 | r#" | ||
610 | #[lang = "deref"] | ||
611 | trait Deref { | ||
612 | type Target; | ||
613 | fn deref(&self) -> &Self::Target; | ||
614 | } | ||
615 | |||
616 | struct Arc<T>; | ||
617 | impl<T> Deref for Arc<T> { | ||
618 | type Target = T; | ||
619 | } | ||
620 | |||
621 | struct S; | ||
622 | impl S { | ||
623 | fn foo(&self) -> u128 {} | ||
624 | } | ||
625 | |||
626 | fn test(s: Arc<S>) { | ||
627 | (*s, s.foo()); | ||
628 | } //^ (S, u128) | ||
629 | "#, | ||
630 | ); | ||
631 | } | ||
632 | |||
633 | #[test] | ||
634 | fn deref_trait_with_inference_var() { | ||
635 | check_types( | ||
636 | r#" | ||
637 | //- /main.rs | ||
638 | #[lang = "deref"] | ||
639 | trait Deref { | ||
640 | type Target; | ||
641 | fn deref(&self) -> &Self::Target; | ||
642 | } | ||
643 | |||
644 | struct Arc<T>; | ||
645 | fn new_arc<T>() -> Arc<T> {} | ||
646 | impl<T> Deref for Arc<T> { | ||
647 | type Target = T; | ||
648 | } | ||
649 | |||
650 | struct S; | ||
651 | fn foo(a: Arc<S>) {} | ||
652 | |||
653 | fn test() { | ||
654 | let a = new_arc(); | ||
655 | let b = (*a); | ||
656 | //^ S | ||
657 | foo(a); | ||
658 | } | ||
659 | "#, | ||
660 | ); | ||
661 | } | ||
662 | |||
663 | #[test] | ||
664 | fn deref_trait_infinite_recursion() { | ||
665 | check_types( | ||
666 | r#" | ||
667 | #[lang = "deref"] | ||
668 | trait Deref { | ||
669 | type Target; | ||
670 | fn deref(&self) -> &Self::Target; | ||
671 | } | ||
672 | |||
673 | struct S; | ||
674 | |||
675 | impl Deref for S { | ||
676 | type Target = S; | ||
677 | } | ||
678 | |||
679 | fn test(s: S) { | ||
680 | s.foo(); | ||
681 | } //^ {unknown} | ||
682 | "#, | ||
683 | ); | ||
684 | } | ||
685 | |||
686 | #[test] | ||
687 | fn deref_trait_with_question_mark_size() { | ||
688 | check_types( | ||
689 | r#" | ||
690 | #[lang = "deref"] | ||
691 | trait Deref { | ||
692 | type Target; | ||
693 | fn deref(&self) -> &Self::Target; | ||
694 | } | ||
695 | |||
696 | struct Arc<T>; | ||
697 | impl<T> Deref for Arc<T> { | ||
698 | type Target = T; | ||
699 | } | ||
700 | |||
701 | struct S; | ||
702 | impl S { | ||
703 | fn foo(&self) -> u128 {} | ||
704 | } | ||
705 | |||
706 | fn test(s: Arc<S>) { | ||
707 | (*s, s.foo()); | ||
708 | } //^ (S, u128) | ||
709 | "#, | ||
710 | ); | ||
711 | } | ||
712 | |||
713 | #[test] | ||
714 | fn obligation_from_function_clause() { | ||
715 | check_types( | ||
716 | r#" | ||
717 | struct S; | ||
718 | |||
719 | trait Trait<T> {} | ||
720 | impl Trait<u32> for S {} | ||
721 | |||
722 | fn foo<T: Trait<U>, U>(t: T) -> U {} | ||
723 | |||
724 | fn test(s: S) { | ||
725 | (foo(s)); | ||
726 | } //^ u32 | ||
727 | "#, | ||
728 | ); | ||
729 | } | ||
730 | |||
731 | #[test] | ||
732 | fn obligation_from_method_clause() { | ||
733 | check_types( | ||
734 | r#" | ||
735 | //- /main.rs | ||
736 | struct S; | ||
737 | |||
738 | trait Trait<T> {} | ||
739 | impl Trait<isize> for S {} | ||
740 | |||
741 | struct O; | ||
742 | impl O { | ||
743 | fn foo<T: Trait<U>, U>(&self, t: T) -> U {} | ||
744 | } | ||
745 | |||
746 | fn test() { | ||
747 | O.foo(S); | ||
748 | } //^ isize | ||
749 | "#, | ||
750 | ); | ||
751 | } | ||
752 | |||
753 | #[test] | ||
754 | fn obligation_from_self_method_clause() { | ||
755 | check_types( | ||
756 | r#" | ||
757 | struct S; | ||
758 | |||
759 | trait Trait<T> {} | ||
760 | impl Trait<i64> for S {} | ||
761 | |||
762 | impl S { | ||
763 | fn foo<U>(&self) -> U where Self: Trait<U> {} | ||
764 | } | ||
765 | |||
766 | fn test() { | ||
767 | S.foo(); | ||
768 | } //^ i64 | ||
769 | "#, | ||
770 | ); | ||
771 | } | ||
772 | |||
773 | #[test] | ||
774 | fn obligation_from_impl_clause() { | ||
775 | check_types( | ||
776 | r#" | ||
777 | struct S; | ||
778 | |||
779 | trait Trait<T> {} | ||
780 | impl Trait<&str> for S {} | ||
781 | |||
782 | struct O<T>; | ||
783 | impl<U, T: Trait<U>> O<T> { | ||
784 | fn foo(&self) -> U {} | ||
785 | } | ||
786 | |||
787 | fn test(o: O<S>) { | ||
788 | o.foo(); | ||
789 | } //^ &str | ||
790 | "#, | ||
791 | ); | ||
792 | } | ||
793 | |||
794 | #[test] | ||
795 | fn generic_param_env_1() { | ||
796 | check_types( | ||
797 | r#" | ||
798 | trait Clone {} | ||
799 | trait Trait { fn foo(self) -> u128; } | ||
800 | struct S; | ||
801 | impl Clone for S {} | ||
802 | impl<T> Trait for T where T: Clone {} | ||
803 | fn test<T: Clone>(t: T) { t.foo(); } | ||
804 | //^ u128 | ||
805 | "#, | ||
806 | ); | ||
807 | } | ||
808 | |||
809 | #[test] | ||
810 | fn generic_param_env_1_not_met() { | ||
811 | check_types( | ||
812 | r#" | ||
813 | //- /main.rs | ||
814 | trait Clone {} | ||
815 | trait Trait { fn foo(self) -> u128; } | ||
816 | struct S; | ||
817 | impl Clone for S {} | ||
818 | impl<T> Trait for T where T: Clone {} | ||
819 | fn test<T>(t: T) { t.foo(); } | ||
820 | //^ {unknown} | ||
821 | "#, | ||
822 | ); | ||
823 | } | ||
824 | |||
825 | #[test] | ||
826 | fn generic_param_env_2() { | ||
827 | check_types( | ||
828 | r#" | ||
829 | trait Trait { fn foo(self) -> u128; } | ||
830 | struct S; | ||
831 | impl Trait for S {} | ||
832 | fn test<T: Trait>(t: T) { t.foo(); } | ||
833 | //^ u128 | ||
834 | "#, | ||
835 | ); | ||
836 | } | ||
837 | |||
838 | #[test] | ||
839 | fn generic_param_env_2_not_met() { | ||
840 | check_types( | ||
841 | r#" | ||
842 | trait Trait { fn foo(self) -> u128; } | ||
843 | struct S; | ||
844 | impl Trait for S {} | ||
845 | fn test<T>(t: T) { t.foo(); } | ||
846 | //^ {unknown} | ||
847 | "#, | ||
848 | ); | ||
849 | } | ||
850 | |||
851 | #[test] | ||
852 | fn generic_param_env_deref() { | ||
853 | check_types( | ||
854 | r#" | ||
855 | #[lang = "deref"] | ||
856 | trait Deref { | ||
857 | type Target; | ||
858 | } | ||
859 | trait Trait {} | ||
860 | impl<T> Deref for T where T: Trait { | ||
861 | type Target = i128; | ||
862 | } | ||
863 | fn test<T: Trait>(t: T) { (*t); } | ||
864 | //^ i128 | ||
865 | "#, | ||
866 | ); | ||
867 | } | ||
868 | |||
869 | #[test] | ||
870 | fn associated_type_placeholder() { | ||
871 | // inside the generic function, the associated type gets normalized to a placeholder `ApplL::Out<T>` [https://rust-lang.github.io/rustc-guide/traits/associated-types.html#placeholder-associated-types]. | ||
872 | check_types( | ||
873 | r#" | ||
874 | pub trait ApplyL { | ||
875 | type Out; | ||
876 | } | ||
877 | |||
878 | pub struct RefMutL<T>; | ||
879 | |||
880 | impl<T> ApplyL for RefMutL<T> { | ||
881 | type Out = <T as ApplyL>::Out; | ||
882 | } | ||
883 | |||
884 | fn test<T: ApplyL>() { | ||
885 | let y: <RefMutL<T> as ApplyL>::Out = no_matter; | ||
886 | y; | ||
887 | } //^ ApplyL::Out<T> | ||
888 | "#, | ||
889 | ); | ||
890 | } | ||
891 | |||
892 | #[test] | ||
893 | fn associated_type_placeholder_2() { | ||
894 | check_types( | ||
895 | r#" | ||
896 | pub trait ApplyL { | ||
897 | type Out; | ||
898 | } | ||
899 | fn foo<T: ApplyL>(t: T) -> <T as ApplyL>::Out; | ||
900 | |||
901 | fn test<T: ApplyL>(t: T) { | ||
902 | let y = foo(t); | ||
903 | y; | ||
904 | } //^ ApplyL::Out<T> | ||
905 | "#, | ||
906 | ); | ||
907 | } | ||
908 | |||
909 | #[test] | ||
910 | fn argument_impl_trait() { | ||
911 | check_infer_with_mismatches( | ||
912 | r#" | ||
913 | trait Trait<T> { | ||
914 | fn foo(&self) -> T; | ||
915 | fn foo2(&self) -> i64; | ||
916 | } | ||
917 | fn bar(x: impl Trait<u16>) {} | ||
918 | struct S<T>(T); | ||
919 | impl<T> Trait<T> for S<T> {} | ||
920 | |||
921 | fn test(x: impl Trait<u64>, y: &impl Trait<u32>) { | ||
922 | x; | ||
923 | y; | ||
924 | let z = S(1); | ||
925 | bar(z); | ||
926 | x.foo(); | ||
927 | y.foo(); | ||
928 | z.foo(); | ||
929 | x.foo2(); | ||
930 | y.foo2(); | ||
931 | z.foo2(); | ||
932 | } | ||
933 | "#, | ||
934 | expect![[r#" | ||
935 | 29..33 'self': &Self | ||
936 | 54..58 'self': &Self | ||
937 | 77..78 'x': impl Trait<u16> | ||
938 | 97..99 '{}': () | ||
939 | 154..155 'x': impl Trait<u64> | ||
940 | 174..175 'y': &impl Trait<u32> | ||
941 | 195..323 '{ ...2(); }': () | ||
942 | 201..202 'x': impl Trait<u64> | ||
943 | 208..209 'y': &impl Trait<u32> | ||
944 | 219..220 'z': S<u16> | ||
945 | 223..224 'S': S<u16>(u16) -> S<u16> | ||
946 | 223..227 'S(1)': S<u16> | ||
947 | 225..226 '1': u16 | ||
948 | 233..236 'bar': fn bar(S<u16>) | ||
949 | 233..239 'bar(z)': () | ||
950 | 237..238 'z': S<u16> | ||
951 | 245..246 'x': impl Trait<u64> | ||
952 | 245..252 'x.foo()': u64 | ||
953 | 258..259 'y': &impl Trait<u32> | ||
954 | 258..265 'y.foo()': u32 | ||
955 | 271..272 'z': S<u16> | ||
956 | 271..278 'z.foo()': u16 | ||
957 | 284..285 'x': impl Trait<u64> | ||
958 | 284..292 'x.foo2()': i64 | ||
959 | 298..299 'y': &impl Trait<u32> | ||
960 | 298..306 'y.foo2()': i64 | ||
961 | 312..313 'z': S<u16> | ||
962 | 312..320 'z.foo2()': i64 | ||
963 | "#]], | ||
964 | ); | ||
965 | } | ||
966 | |||
967 | #[test] | ||
968 | fn argument_impl_trait_type_args_1() { | ||
969 | check_infer_with_mismatches( | ||
970 | r#" | ||
971 | trait Trait {} | ||
972 | trait Foo { | ||
973 | // this function has an implicit Self param, an explicit type param, | ||
974 | // and an implicit impl Trait param! | ||
975 | fn bar<T>(x: impl Trait) -> T { loop {} } | ||
976 | } | ||
977 | fn foo<T>(x: impl Trait) -> T { loop {} } | ||
978 | struct S; | ||
979 | impl Trait for S {} | ||
980 | struct F; | ||
981 | impl Foo for F {} | ||
982 | |||
983 | fn test() { | ||
984 | Foo::bar(S); | ||
985 | <F as Foo>::bar(S); | ||
986 | F::bar(S); | ||
987 | Foo::bar::<u32>(S); | ||
988 | <F as Foo>::bar::<u32>(S); | ||
989 | |||
990 | foo(S); | ||
991 | foo::<u32>(S); | ||
992 | foo::<u32, i32>(S); // we should ignore the extraneous i32 | ||
993 | } | ||
994 | "#, | ||
995 | expect![[r#" | ||
996 | 155..156 'x': impl Trait | ||
997 | 175..186 '{ loop {} }': T | ||
998 | 177..184 'loop {}': ! | ||
999 | 182..184 '{}': () | ||
1000 | 199..200 'x': impl Trait | ||
1001 | 219..230 '{ loop {} }': T | ||
1002 | 221..228 'loop {}': ! | ||
1003 | 226..228 '{}': () | ||
1004 | 300..509 '{ ... i32 }': () | ||
1005 | 306..314 'Foo::bar': fn bar<{unknown}, {unknown}>(S) -> {unknown} | ||
1006 | 306..317 'Foo::bar(S)': {unknown} | ||
1007 | 315..316 'S': S | ||
1008 | 323..338 '<F as Foo>::bar': fn bar<F, {unknown}>(S) -> {unknown} | ||
1009 | 323..341 '<F as ...bar(S)': {unknown} | ||
1010 | 339..340 'S': S | ||
1011 | 347..353 'F::bar': fn bar<F, {unknown}>(S) -> {unknown} | ||
1012 | 347..356 'F::bar(S)': {unknown} | ||
1013 | 354..355 'S': S | ||
1014 | 362..377 'Foo::bar::<u32>': fn bar<{unknown}, u32>(S) -> u32 | ||
1015 | 362..380 'Foo::b...32>(S)': u32 | ||
1016 | 378..379 'S': S | ||
1017 | 386..408 '<F as ...:<u32>': fn bar<F, u32>(S) -> u32 | ||
1018 | 386..411 '<F as ...32>(S)': u32 | ||
1019 | 409..410 'S': S | ||
1020 | 418..421 'foo': fn foo<{unknown}>(S) -> {unknown} | ||
1021 | 418..424 'foo(S)': {unknown} | ||
1022 | 422..423 'S': S | ||
1023 | 430..440 'foo::<u32>': fn foo<u32>(S) -> u32 | ||
1024 | 430..443 'foo::<u32>(S)': u32 | ||
1025 | 441..442 'S': S | ||
1026 | 449..464 'foo::<u32, i32>': fn foo<u32>(S) -> u32 | ||
1027 | 449..467 'foo::<...32>(S)': u32 | ||
1028 | 465..466 'S': S | ||
1029 | "#]], | ||
1030 | ); | ||
1031 | } | ||
1032 | |||
1033 | #[test] | ||
1034 | fn argument_impl_trait_type_args_2() { | ||
1035 | check_infer_with_mismatches( | ||
1036 | r#" | ||
1037 | trait Trait {} | ||
1038 | struct S; | ||
1039 | impl Trait for S {} | ||
1040 | struct F<T>; | ||
1041 | impl<T> F<T> { | ||
1042 | fn foo<U>(self, x: impl Trait) -> (T, U) { loop {} } | ||
1043 | } | ||
1044 | |||
1045 | fn test() { | ||
1046 | F.foo(S); | ||
1047 | F::<u32>.foo(S); | ||
1048 | F::<u32>.foo::<i32>(S); | ||
1049 | F::<u32>.foo::<i32, u32>(S); // extraneous argument should be ignored | ||
1050 | } | ||
1051 | "#, | ||
1052 | expect![[r#" | ||
1053 | 87..91 'self': F<T> | ||
1054 | 93..94 'x': impl Trait | ||
1055 | 118..129 '{ loop {} }': (T, U) | ||
1056 | 120..127 'loop {}': ! | ||
1057 | 125..127 '{}': () | ||
1058 | 143..283 '{ ...ored }': () | ||
1059 | 149..150 'F': F<{unknown}> | ||
1060 | 149..157 'F.foo(S)': ({unknown}, {unknown}) | ||
1061 | 155..156 'S': S | ||
1062 | 163..171 'F::<u32>': F<u32> | ||
1063 | 163..178 'F::<u32>.foo(S)': (u32, {unknown}) | ||
1064 | 176..177 'S': S | ||
1065 | 184..192 'F::<u32>': F<u32> | ||
1066 | 184..206 'F::<u3...32>(S)': (u32, i32) | ||
1067 | 204..205 'S': S | ||
1068 | 212..220 'F::<u32>': F<u32> | ||
1069 | 212..239 'F::<u3...32>(S)': (u32, i32) | ||
1070 | 237..238 'S': S | ||
1071 | "#]], | ||
1072 | ); | ||
1073 | } | ||
1074 | |||
1075 | #[test] | ||
1076 | fn argument_impl_trait_to_fn_pointer() { | ||
1077 | check_infer_with_mismatches( | ||
1078 | r#" | ||
1079 | trait Trait {} | ||
1080 | fn foo(x: impl Trait) { loop {} } | ||
1081 | struct S; | ||
1082 | impl Trait for S {} | ||
1083 | |||
1084 | fn test() { | ||
1085 | let f: fn(S) -> () = foo; | ||
1086 | } | ||
1087 | "#, | ||
1088 | expect![[r#" | ||
1089 | 22..23 'x': impl Trait | ||
1090 | 37..48 '{ loop {} }': () | ||
1091 | 39..46 'loop {}': ! | ||
1092 | 44..46 '{}': () | ||
1093 | 90..123 '{ ...foo; }': () | ||
1094 | 100..101 'f': fn(S) | ||
1095 | 117..120 'foo': fn foo(S) | ||
1096 | "#]], | ||
1097 | ); | ||
1098 | } | ||
1099 | |||
1100 | #[test] | ||
1101 | fn impl_trait() { | ||
1102 | check_infer( | ||
1103 | r#" | ||
1104 | trait Trait<T> { | ||
1105 | fn foo(&self) -> T; | ||
1106 | fn foo2(&self) -> i64; | ||
1107 | } | ||
1108 | fn bar() -> impl Trait<u64> {} | ||
1109 | |||
1110 | fn test(x: impl Trait<u64>, y: &impl Trait<u64>) { | ||
1111 | x; | ||
1112 | y; | ||
1113 | let z = bar(); | ||
1114 | x.foo(); | ||
1115 | y.foo(); | ||
1116 | z.foo(); | ||
1117 | x.foo2(); | ||
1118 | y.foo2(); | ||
1119 | z.foo2(); | ||
1120 | } | ||
1121 | "#, | ||
1122 | expect![[r#" | ||
1123 | 29..33 'self': &Self | ||
1124 | 54..58 'self': &Self | ||
1125 | 98..100 '{}': () | ||
1126 | 110..111 'x': impl Trait<u64> | ||
1127 | 130..131 'y': &impl Trait<u64> | ||
1128 | 151..268 '{ ...2(); }': () | ||
1129 | 157..158 'x': impl Trait<u64> | ||
1130 | 164..165 'y': &impl Trait<u64> | ||
1131 | 175..176 'z': impl Trait<u64> | ||
1132 | 179..182 'bar': fn bar() -> impl Trait<u64> | ||
1133 | 179..184 'bar()': impl Trait<u64> | ||
1134 | 190..191 'x': impl Trait<u64> | ||
1135 | 190..197 'x.foo()': u64 | ||
1136 | 203..204 'y': &impl Trait<u64> | ||
1137 | 203..210 'y.foo()': u64 | ||
1138 | 216..217 'z': impl Trait<u64> | ||
1139 | 216..223 'z.foo()': u64 | ||
1140 | 229..230 'x': impl Trait<u64> | ||
1141 | 229..237 'x.foo2()': i64 | ||
1142 | 243..244 'y': &impl Trait<u64> | ||
1143 | 243..251 'y.foo2()': i64 | ||
1144 | 257..258 'z': impl Trait<u64> | ||
1145 | 257..265 'z.foo2()': i64 | ||
1146 | "#]], | ||
1147 | ); | ||
1148 | } | ||
1149 | |||
1150 | #[test] | ||
1151 | fn simple_return_pos_impl_trait() { | ||
1152 | mark::check!(lower_rpit); | ||
1153 | check_infer( | ||
1154 | r#" | ||
1155 | trait Trait<T> { | ||
1156 | fn foo(&self) -> T; | ||
1157 | } | ||
1158 | fn bar() -> impl Trait<u64> { loop {} } | ||
1159 | |||
1160 | fn test() { | ||
1161 | let a = bar(); | ||
1162 | a.foo(); | ||
1163 | } | ||
1164 | "#, | ||
1165 | expect![[r#" | ||
1166 | 29..33 'self': &Self | ||
1167 | 71..82 '{ loop {} }': ! | ||
1168 | 73..80 'loop {}': ! | ||
1169 | 78..80 '{}': () | ||
1170 | 94..129 '{ ...o(); }': () | ||
1171 | 104..105 'a': impl Trait<u64> | ||
1172 | 108..111 'bar': fn bar() -> impl Trait<u64> | ||
1173 | 108..113 'bar()': impl Trait<u64> | ||
1174 | 119..120 'a': impl Trait<u64> | ||
1175 | 119..126 'a.foo()': u64 | ||
1176 | "#]], | ||
1177 | ); | ||
1178 | } | ||
1179 | |||
1180 | #[test] | ||
1181 | fn more_return_pos_impl_trait() { | ||
1182 | check_infer( | ||
1183 | r#" | ||
1184 | trait Iterator { | ||
1185 | type Item; | ||
1186 | fn next(&mut self) -> Self::Item; | ||
1187 | } | ||
1188 | trait Trait<T> { | ||
1189 | fn foo(&self) -> T; | ||
1190 | } | ||
1191 | fn bar() -> (impl Iterator<Item = impl Trait<u32>>, impl Trait<u64>) { loop {} } | ||
1192 | fn baz<T>(t: T) -> (impl Iterator<Item = impl Trait<T>>, impl Trait<T>) { loop {} } | ||
1193 | |||
1194 | fn test() { | ||
1195 | let (a, b) = bar(); | ||
1196 | a.next().foo(); | ||
1197 | b.foo(); | ||
1198 | let (c, d) = baz(1u128); | ||
1199 | c.next().foo(); | ||
1200 | d.foo(); | ||
1201 | } | ||
1202 | "#, | ||
1203 | expect![[r#" | ||
1204 | 49..53 'self': &mut Self | ||
1205 | 101..105 'self': &Self | ||
1206 | 184..195 '{ loop {} }': ({unknown}, {unknown}) | ||
1207 | 186..193 'loop {}': ! | ||
1208 | 191..193 '{}': () | ||
1209 | 206..207 't': T | ||
1210 | 268..279 '{ loop {} }': ({unknown}, {unknown}) | ||
1211 | 270..277 'loop {}': ! | ||
1212 | 275..277 '{}': () | ||
1213 | 291..413 '{ ...o(); }': () | ||
1214 | 301..307 '(a, b)': (impl Iterator<Item = impl Trait<u32>>, impl Trait<u64>) | ||
1215 | 302..303 'a': impl Iterator<Item = impl Trait<u32>> | ||
1216 | 305..306 'b': impl Trait<u64> | ||
1217 | 310..313 'bar': fn bar() -> (impl Iterator<Item = impl Trait<u32>>, impl Trait<u64>) | ||
1218 | 310..315 'bar()': (impl Iterator<Item = impl Trait<u32>>, impl Trait<u64>) | ||
1219 | 321..322 'a': impl Iterator<Item = impl Trait<u32>> | ||
1220 | 321..329 'a.next()': impl Trait<u32> | ||
1221 | 321..335 'a.next().foo()': u32 | ||
1222 | 341..342 'b': impl Trait<u64> | ||
1223 | 341..348 'b.foo()': u64 | ||
1224 | 358..364 '(c, d)': (impl Iterator<Item = impl Trait<u128>>, impl Trait<u128>) | ||
1225 | 359..360 'c': impl Iterator<Item = impl Trait<u128>> | ||
1226 | 362..363 'd': impl Trait<u128> | ||
1227 | 367..370 'baz': fn baz<u128>(u128) -> (impl Iterator<Item = impl Trait<u128>>, impl Trait<u128>) | ||
1228 | 367..377 'baz(1u128)': (impl Iterator<Item = impl Trait<u128>>, impl Trait<u128>) | ||
1229 | 371..376 '1u128': u128 | ||
1230 | 383..384 'c': impl Iterator<Item = impl Trait<u128>> | ||
1231 | 383..391 'c.next()': impl Trait<u128> | ||
1232 | 383..397 'c.next().foo()': u128 | ||
1233 | 403..404 'd': impl Trait<u128> | ||
1234 | 403..410 'd.foo()': u128 | ||
1235 | "#]], | ||
1236 | ); | ||
1237 | } | ||
1238 | |||
1239 | #[test] | ||
1240 | fn dyn_trait() { | ||
1241 | check_infer( | ||
1242 | r#" | ||
1243 | trait Trait<T> { | ||
1244 | fn foo(&self) -> T; | ||
1245 | fn foo2(&self) -> i64; | ||
1246 | } | ||
1247 | fn bar() -> dyn Trait<u64> {} | ||
1248 | |||
1249 | fn test(x: dyn Trait<u64>, y: &dyn Trait<u64>) { | ||
1250 | x; | ||
1251 | y; | ||
1252 | let z = bar(); | ||
1253 | x.foo(); | ||
1254 | y.foo(); | ||
1255 | z.foo(); | ||
1256 | x.foo2(); | ||
1257 | y.foo2(); | ||
1258 | z.foo2(); | ||
1259 | } | ||
1260 | "#, | ||
1261 | expect![[r#" | ||
1262 | 29..33 'self': &Self | ||
1263 | 54..58 'self': &Self | ||
1264 | 97..99 '{}': () | ||
1265 | 109..110 'x': dyn Trait<u64> | ||
1266 | 128..129 'y': &dyn Trait<u64> | ||
1267 | 148..265 '{ ...2(); }': () | ||
1268 | 154..155 'x': dyn Trait<u64> | ||
1269 | 161..162 'y': &dyn Trait<u64> | ||
1270 | 172..173 'z': dyn Trait<u64> | ||
1271 | 176..179 'bar': fn bar() -> dyn Trait<u64> | ||
1272 | 176..181 'bar()': dyn Trait<u64> | ||
1273 | 187..188 'x': dyn Trait<u64> | ||
1274 | 187..194 'x.foo()': u64 | ||
1275 | 200..201 'y': &dyn Trait<u64> | ||
1276 | 200..207 'y.foo()': u64 | ||
1277 | 213..214 'z': dyn Trait<u64> | ||
1278 | 213..220 'z.foo()': u64 | ||
1279 | 226..227 'x': dyn Trait<u64> | ||
1280 | 226..234 'x.foo2()': i64 | ||
1281 | 240..241 'y': &dyn Trait<u64> | ||
1282 | 240..248 'y.foo2()': i64 | ||
1283 | 254..255 'z': dyn Trait<u64> | ||
1284 | 254..262 'z.foo2()': i64 | ||
1285 | "#]], | ||
1286 | ); | ||
1287 | } | ||
1288 | |||
1289 | #[test] | ||
1290 | fn dyn_trait_in_impl() { | ||
1291 | check_infer( | ||
1292 | r#" | ||
1293 | trait Trait<T, U> { | ||
1294 | fn foo(&self) -> (T, U); | ||
1295 | } | ||
1296 | struct S<T, U> {} | ||
1297 | impl<T, U> S<T, U> { | ||
1298 | fn bar(&self) -> &dyn Trait<T, U> { loop {} } | ||
1299 | } | ||
1300 | trait Trait2<T, U> { | ||
1301 | fn baz(&self) -> (T, U); | ||
1302 | } | ||
1303 | impl<T, U> Trait2<T, U> for dyn Trait<T, U> { } | ||
1304 | |||
1305 | fn test(s: S<u32, i32>) { | ||
1306 | s.bar().baz(); | ||
1307 | } | ||
1308 | "#, | ||
1309 | expect![[r#" | ||
1310 | 32..36 'self': &Self | ||
1311 | 102..106 'self': &S<T, U> | ||
1312 | 128..139 '{ loop {} }': &dyn Trait<T, U> | ||
1313 | 130..137 'loop {}': ! | ||
1314 | 135..137 '{}': () | ||
1315 | 175..179 'self': &Self | ||
1316 | 251..252 's': S<u32, i32> | ||
1317 | 267..289 '{ ...z(); }': () | ||
1318 | 273..274 's': S<u32, i32> | ||
1319 | 273..280 's.bar()': &dyn Trait<u32, i32> | ||
1320 | 273..286 's.bar().baz()': (u32, i32) | ||
1321 | "#]], | ||
1322 | ); | ||
1323 | } | ||
1324 | |||
1325 | #[test] | ||
1326 | fn dyn_trait_bare() { | ||
1327 | check_infer( | ||
1328 | r#" | ||
1329 | trait Trait { | ||
1330 | fn foo(&self) -> u64; | ||
1331 | } | ||
1332 | fn bar() -> Trait {} | ||
1333 | |||
1334 | fn test(x: Trait, y: &Trait) -> u64 { | ||
1335 | x; | ||
1336 | y; | ||
1337 | let z = bar(); | ||
1338 | x.foo(); | ||
1339 | y.foo(); | ||
1340 | z.foo(); | ||
1341 | } | ||
1342 | "#, | ||
1343 | expect![[r#" | ||
1344 | 26..30 'self': &Self | ||
1345 | 60..62 '{}': () | ||
1346 | 72..73 'x': dyn Trait | ||
1347 | 82..83 'y': &dyn Trait | ||
1348 | 100..175 '{ ...o(); }': () | ||
1349 | 106..107 'x': dyn Trait | ||
1350 | 113..114 'y': &dyn Trait | ||
1351 | 124..125 'z': dyn Trait | ||
1352 | 128..131 'bar': fn bar() -> dyn Trait | ||
1353 | 128..133 'bar()': dyn Trait | ||
1354 | 139..140 'x': dyn Trait | ||
1355 | 139..146 'x.foo()': u64 | ||
1356 | 152..153 'y': &dyn Trait | ||
1357 | 152..159 'y.foo()': u64 | ||
1358 | 165..166 'z': dyn Trait | ||
1359 | 165..172 'z.foo()': u64 | ||
1360 | "#]], | ||
1361 | ); | ||
1362 | } | ||
1363 | |||
1364 | #[test] | ||
1365 | fn weird_bounds() { | ||
1366 | check_infer( | ||
1367 | r#" | ||
1368 | trait Trait {} | ||
1369 | fn test(a: impl Trait + 'lifetime, b: impl 'lifetime, c: impl (Trait), d: impl ('lifetime), e: impl ?Sized, f: impl Trait + ?Sized) {} | ||
1370 | "#, | ||
1371 | expect![[r#" | ||
1372 | 23..24 'a': impl Trait + {error} | ||
1373 | 50..51 'b': impl {error} | ||
1374 | 69..70 'c': impl Trait | ||
1375 | 86..87 'd': impl {error} | ||
1376 | 107..108 'e': impl {error} | ||
1377 | 123..124 'f': impl Trait + {error} | ||
1378 | 147..149 '{}': () | ||
1379 | "#]], | ||
1380 | ); | ||
1381 | } | ||
1382 | |||
1383 | #[test] | ||
1384 | #[ignore] | ||
1385 | fn error_bound_chalk() { | ||
1386 | check_types( | ||
1387 | r#" | ||
1388 | trait Trait { | ||
1389 | fn foo(&self) -> u32 {} | ||
1390 | } | ||
1391 | |||
1392 | fn test(x: (impl Trait + UnknownTrait)) { | ||
1393 | x.foo(); | ||
1394 | } //^ u32 | ||
1395 | "#, | ||
1396 | ); | ||
1397 | } | ||
1398 | |||
1399 | #[test] | ||
1400 | fn assoc_type_bindings() { | ||
1401 | check_infer( | ||
1402 | r#" | ||
1403 | trait Trait { | ||
1404 | type Type; | ||
1405 | } | ||
1406 | |||
1407 | fn get<T: Trait>(t: T) -> <T as Trait>::Type {} | ||
1408 | fn get2<U, T: Trait<Type = U>>(t: T) -> U {} | ||
1409 | fn set<T: Trait<Type = u64>>(t: T) -> T {t} | ||
1410 | |||
1411 | struct S<T>; | ||
1412 | impl<T> Trait for S<T> { type Type = T; } | ||
1413 | |||
1414 | fn test<T: Trait<Type = u32>>(x: T, y: impl Trait<Type = i64>) { | ||
1415 | get(x); | ||
1416 | get2(x); | ||
1417 | get(y); | ||
1418 | get2(y); | ||
1419 | get(set(S)); | ||
1420 | get2(set(S)); | ||
1421 | get2(S::<str>); | ||
1422 | } | ||
1423 | "#, | ||
1424 | expect![[r#" | ||
1425 | 49..50 't': T | ||
1426 | 77..79 '{}': () | ||
1427 | 111..112 't': T | ||
1428 | 122..124 '{}': () | ||
1429 | 154..155 't': T | ||
1430 | 165..168 '{t}': T | ||
1431 | 166..167 't': T | ||
1432 | 256..257 'x': T | ||
1433 | 262..263 'y': impl Trait<Type = i64> | ||
1434 | 289..397 '{ ...r>); }': () | ||
1435 | 295..298 'get': fn get<T>(T) -> <T as Trait>::Type | ||
1436 | 295..301 'get(x)': u32 | ||
1437 | 299..300 'x': T | ||
1438 | 307..311 'get2': fn get2<u32, T>(T) -> u32 | ||
1439 | 307..314 'get2(x)': u32 | ||
1440 | 312..313 'x': T | ||
1441 | 320..323 'get': fn get<impl Trait<Type = i64>>(impl Trait<Type = i64>) -> <impl Trait<Type = i64> as Trait>::Type | ||
1442 | 320..326 'get(y)': i64 | ||
1443 | 324..325 'y': impl Trait<Type = i64> | ||
1444 | 332..336 'get2': fn get2<i64, impl Trait<Type = i64>>(impl Trait<Type = i64>) -> i64 | ||
1445 | 332..339 'get2(y)': i64 | ||
1446 | 337..338 'y': impl Trait<Type = i64> | ||
1447 | 345..348 'get': fn get<S<u64>>(S<u64>) -> <S<u64> as Trait>::Type | ||
1448 | 345..356 'get(set(S))': u64 | ||
1449 | 349..352 'set': fn set<S<u64>>(S<u64>) -> S<u64> | ||
1450 | 349..355 'set(S)': S<u64> | ||
1451 | 353..354 'S': S<u64> | ||
1452 | 362..366 'get2': fn get2<u64, S<u64>>(S<u64>) -> u64 | ||
1453 | 362..374 'get2(set(S))': u64 | ||
1454 | 367..370 'set': fn set<S<u64>>(S<u64>) -> S<u64> | ||
1455 | 367..373 'set(S)': S<u64> | ||
1456 | 371..372 'S': S<u64> | ||
1457 | 380..384 'get2': fn get2<str, S<str>>(S<str>) -> str | ||
1458 | 380..394 'get2(S::<str>)': str | ||
1459 | 385..393 'S::<str>': S<str> | ||
1460 | "#]], | ||
1461 | ); | ||
1462 | } | ||
1463 | |||
1464 | #[test] | ||
1465 | fn impl_trait_assoc_binding_projection_bug() { | ||
1466 | check_types( | ||
1467 | r#" | ||
1468 | //- /main.rs crate:main deps:std | ||
1469 | pub trait Language { | ||
1470 | type Kind; | ||
1471 | } | ||
1472 | pub enum RustLanguage {} | ||
1473 | impl Language for RustLanguage { | ||
1474 | type Kind = SyntaxKind; | ||
1475 | } | ||
1476 | struct SyntaxNode<L> {} | ||
1477 | fn foo() -> impl Iterator<Item = SyntaxNode<RustLanguage>> {} | ||
1478 | |||
1479 | trait Clone { | ||
1480 | fn clone(&self) -> Self; | ||
1481 | } | ||
1482 | |||
1483 | fn api_walkthrough() { | ||
1484 | for node in foo() { | ||
1485 | node.clone(); | ||
1486 | } //^ {unknown} | ||
1487 | } | ||
1488 | |||
1489 | //- /std.rs crate:std | ||
1490 | #[prelude_import] use iter::*; | ||
1491 | mod iter { | ||
1492 | trait IntoIterator { | ||
1493 | type Item; | ||
1494 | } | ||
1495 | trait Iterator { | ||
1496 | type Item; | ||
1497 | } | ||
1498 | impl<T: Iterator> IntoIterator for T { | ||
1499 | type Item = <T as Iterator>::Item; | ||
1500 | } | ||
1501 | } | ||
1502 | "#, | ||
1503 | ); | ||
1504 | } | ||
1505 | |||
1506 | #[test] | ||
1507 | fn projection_eq_within_chalk() { | ||
1508 | check_infer( | ||
1509 | r#" | ||
1510 | trait Trait1 { | ||
1511 | type Type; | ||
1512 | } | ||
1513 | trait Trait2<T> { | ||
1514 | fn foo(self) -> T; | ||
1515 | } | ||
1516 | impl<T, U> Trait2<T> for U where U: Trait1<Type = T> {} | ||
1517 | |||
1518 | fn test<T: Trait1<Type = u32>>(x: T) { | ||
1519 | x.foo(); | ||
1520 | } | ||
1521 | "#, | ||
1522 | expect![[r#" | ||
1523 | 61..65 'self': Self | ||
1524 | 163..164 'x': T | ||
1525 | 169..185 '{ ...o(); }': () | ||
1526 | 175..176 'x': T | ||
1527 | 175..182 'x.foo()': u32 | ||
1528 | "#]], | ||
1529 | ); | ||
1530 | } | ||
1531 | |||
1532 | #[test] | ||
1533 | fn where_clause_trait_in_scope_for_method_resolution() { | ||
1534 | check_types( | ||
1535 | r#" | ||
1536 | mod foo { | ||
1537 | trait Trait { | ||
1538 | fn foo(&self) -> u32 {} | ||
1539 | } | ||
1540 | } | ||
1541 | |||
1542 | fn test<T: foo::Trait>(x: T) { | ||
1543 | x.foo(); | ||
1544 | } //^ u32 | ||
1545 | "#, | ||
1546 | ); | ||
1547 | } | ||
1548 | |||
1549 | #[test] | ||
1550 | fn super_trait_method_resolution() { | ||
1551 | check_infer( | ||
1552 | r#" | ||
1553 | mod foo { | ||
1554 | trait SuperTrait { | ||
1555 | fn foo(&self) -> u32 {} | ||
1556 | } | ||
1557 | } | ||
1558 | trait Trait1: foo::SuperTrait {} | ||
1559 | trait Trait2 where Self: foo::SuperTrait {} | ||
1560 | |||
1561 | fn test<T: Trait1, U: Trait2>(x: T, y: U) { | ||
1562 | x.foo(); | ||
1563 | y.foo(); | ||
1564 | } | ||
1565 | "#, | ||
1566 | expect![[r#" | ||
1567 | 49..53 'self': &Self | ||
1568 | 62..64 '{}': () | ||
1569 | 181..182 'x': T | ||
1570 | 187..188 'y': U | ||
1571 | 193..222 '{ ...o(); }': () | ||
1572 | 199..200 'x': T | ||
1573 | 199..206 'x.foo()': u32 | ||
1574 | 212..213 'y': U | ||
1575 | 212..219 'y.foo()': u32 | ||
1576 | "#]], | ||
1577 | ); | ||
1578 | } | ||
1579 | |||
1580 | #[test] | ||
1581 | fn super_trait_impl_trait_method_resolution() { | ||
1582 | check_infer( | ||
1583 | r#" | ||
1584 | mod foo { | ||
1585 | trait SuperTrait { | ||
1586 | fn foo(&self) -> u32 {} | ||
1587 | } | ||
1588 | } | ||
1589 | trait Trait1: foo::SuperTrait {} | ||
1590 | |||
1591 | fn test(x: &impl Trait1) { | ||
1592 | x.foo(); | ||
1593 | } | ||
1594 | "#, | ||
1595 | expect![[r#" | ||
1596 | 49..53 'self': &Self | ||
1597 | 62..64 '{}': () | ||
1598 | 115..116 'x': &impl Trait1 | ||
1599 | 132..148 '{ ...o(); }': () | ||
1600 | 138..139 'x': &impl Trait1 | ||
1601 | 138..145 'x.foo()': u32 | ||
1602 | "#]], | ||
1603 | ); | ||
1604 | } | ||
1605 | |||
1606 | #[test] | ||
1607 | fn super_trait_cycle() { | ||
1608 | // This just needs to not crash | ||
1609 | check_infer( | ||
1610 | r#" | ||
1611 | trait A: B {} | ||
1612 | trait B: A {} | ||
1613 | |||
1614 | fn test<T: A>(x: T) { | ||
1615 | x.foo(); | ||
1616 | } | ||
1617 | "#, | ||
1618 | expect![[r#" | ||
1619 | 43..44 'x': T | ||
1620 | 49..65 '{ ...o(); }': () | ||
1621 | 55..56 'x': T | ||
1622 | 55..62 'x.foo()': {unknown} | ||
1623 | "#]], | ||
1624 | ); | ||
1625 | } | ||
1626 | |||
1627 | #[test] | ||
1628 | fn super_trait_assoc_type_bounds() { | ||
1629 | check_infer( | ||
1630 | r#" | ||
1631 | trait SuperTrait { type Type; } | ||
1632 | trait Trait where Self: SuperTrait {} | ||
1633 | |||
1634 | fn get2<U, T: Trait<Type = U>>(t: T) -> U {} | ||
1635 | fn set<T: Trait<Type = u64>>(t: T) -> T {t} | ||
1636 | |||
1637 | struct S<T>; | ||
1638 | impl<T> SuperTrait for S<T> { type Type = T; } | ||
1639 | impl<T> Trait for S<T> {} | ||
1640 | |||
1641 | fn test() { | ||
1642 | get2(set(S)); | ||
1643 | } | ||
1644 | "#, | ||
1645 | expect![[r#" | ||
1646 | 102..103 't': T | ||
1647 | 113..115 '{}': () | ||
1648 | 145..146 't': T | ||
1649 | 156..159 '{t}': T | ||
1650 | 157..158 't': T | ||
1651 | 258..279 '{ ...S)); }': () | ||
1652 | 264..268 'get2': fn get2<u64, S<u64>>(S<u64>) -> u64 | ||
1653 | 264..276 'get2(set(S))': u64 | ||
1654 | 269..272 'set': fn set<S<u64>>(S<u64>) -> S<u64> | ||
1655 | 269..275 'set(S)': S<u64> | ||
1656 | 273..274 'S': S<u64> | ||
1657 | "#]], | ||
1658 | ); | ||
1659 | } | ||
1660 | |||
1661 | #[test] | ||
1662 | fn fn_trait() { | ||
1663 | check_infer( | ||
1664 | r#" | ||
1665 | trait FnOnce<Args> { | ||
1666 | type Output; | ||
1667 | |||
1668 | fn call_once(self, args: Args) -> <Self as FnOnce<Args>>::Output; | ||
1669 | } | ||
1670 | |||
1671 | fn test<F: FnOnce(u32, u64) -> u128>(f: F) { | ||
1672 | f.call_once((1, 2)); | ||
1673 | } | ||
1674 | "#, | ||
1675 | expect![[r#" | ||
1676 | 56..60 'self': Self | ||
1677 | 62..66 'args': Args | ||
1678 | 149..150 'f': F | ||
1679 | 155..183 '{ ...2)); }': () | ||
1680 | 161..162 'f': F | ||
1681 | 161..180 'f.call...1, 2))': u128 | ||
1682 | 173..179 '(1, 2)': (u32, u64) | ||
1683 | 174..175 '1': u32 | ||
1684 | 177..178 '2': u64 | ||
1685 | "#]], | ||
1686 | ); | ||
1687 | } | ||
1688 | |||
1689 | #[test] | ||
1690 | fn fn_ptr_and_item() { | ||
1691 | check_infer( | ||
1692 | r#" | ||
1693 | #[lang="fn_once"] | ||
1694 | trait FnOnce<Args> { | ||
1695 | type Output; | ||
1696 | |||
1697 | fn call_once(self, args: Args) -> Self::Output; | ||
1698 | } | ||
1699 | |||
1700 | trait Foo<T> { | ||
1701 | fn foo(&self) -> T; | ||
1702 | } | ||
1703 | |||
1704 | struct Bar<T>(T); | ||
1705 | |||
1706 | impl<A1, R, F: FnOnce(A1) -> R> Foo<(A1, R)> for Bar<F> { | ||
1707 | fn foo(&self) -> (A1, R) {} | ||
1708 | } | ||
1709 | |||
1710 | enum Opt<T> { None, Some(T) } | ||
1711 | impl<T> Opt<T> { | ||
1712 | fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Opt<U> {} | ||
1713 | } | ||
1714 | |||
1715 | fn test() { | ||
1716 | let bar: Bar<fn(u8) -> u32>; | ||
1717 | bar.foo(); | ||
1718 | |||
1719 | let opt: Opt<u8>; | ||
1720 | let f: fn(u8) -> u32; | ||
1721 | opt.map(f); | ||
1722 | } | ||
1723 | "#, | ||
1724 | expect![[r#" | ||
1725 | 74..78 'self': Self | ||
1726 | 80..84 'args': Args | ||
1727 | 139..143 'self': &Self | ||
1728 | 243..247 'self': &Bar<F> | ||
1729 | 260..262 '{}': () | ||
1730 | 346..350 'self': Opt<T> | ||
1731 | 352..353 'f': F | ||
1732 | 368..370 '{}': () | ||
1733 | 384..500 '{ ...(f); }': () | ||
1734 | 394..397 'bar': Bar<fn(u8) -> u32> | ||
1735 | 423..426 'bar': Bar<fn(u8) -> u32> | ||
1736 | 423..432 'bar.foo()': (u8, u32) | ||
1737 | 443..446 'opt': Opt<u8> | ||
1738 | 465..466 'f': fn(u8) -> u32 | ||
1739 | 487..490 'opt': Opt<u8> | ||
1740 | 487..497 'opt.map(f)': Opt<u32> | ||
1741 | 495..496 'f': fn(u8) -> u32 | ||
1742 | "#]], | ||
1743 | ); | ||
1744 | } | ||
1745 | |||
1746 | #[test] | ||
1747 | fn fn_trait_deref_with_ty_default() { | ||
1748 | check_infer( | ||
1749 | r#" | ||
1750 | #[lang = "deref"] | ||
1751 | trait Deref { | ||
1752 | type Target; | ||
1753 | |||
1754 | fn deref(&self) -> &Self::Target; | ||
1755 | } | ||
1756 | |||
1757 | #[lang="fn_once"] | ||
1758 | trait FnOnce<Args> { | ||
1759 | type Output; | ||
1760 | |||
1761 | fn call_once(self, args: Args) -> Self::Output; | ||
1762 | } | ||
1763 | |||
1764 | struct Foo; | ||
1765 | |||
1766 | impl Foo { | ||
1767 | fn foo(&self) -> usize {} | ||
1768 | } | ||
1769 | |||
1770 | struct Lazy<T, F = fn() -> T>(F); | ||
1771 | |||
1772 | impl<T, F> Lazy<T, F> { | ||
1773 | pub fn new(f: F) -> Lazy<T, F> {} | ||
1774 | } | ||
1775 | |||
1776 | impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> { | ||
1777 | type Target = T; | ||
1778 | } | ||
1779 | |||
1780 | fn test() { | ||
1781 | let lazy1: Lazy<Foo, _> = Lazy::new(|| Foo); | ||
1782 | let r1 = lazy1.foo(); | ||
1783 | |||
1784 | fn make_foo_fn() -> Foo {} | ||
1785 | let make_foo_fn_ptr: fn() -> Foo = make_foo_fn; | ||
1786 | let lazy2: Lazy<Foo, _> = Lazy::new(make_foo_fn_ptr); | ||
1787 | let r2 = lazy2.foo(); | ||
1788 | } | ||
1789 | "#, | ||
1790 | expect![[r#" | ||
1791 | 64..68 'self': &Self | ||
1792 | 165..169 'self': Self | ||
1793 | 171..175 'args': Args | ||
1794 | 239..243 'self': &Foo | ||
1795 | 254..256 '{}': () | ||
1796 | 334..335 'f': F | ||
1797 | 354..356 '{}': () | ||
1798 | 443..689 '{ ...o(); }': () | ||
1799 | 453..458 'lazy1': Lazy<Foo, || -> Foo> | ||
1800 | 475..484 'Lazy::new': fn new<Foo, || -> Foo>(|| -> Foo) -> Lazy<Foo, || -> Foo> | ||
1801 | 475..492 'Lazy::...| Foo)': Lazy<Foo, || -> Foo> | ||
1802 | 485..491 '|| Foo': || -> Foo | ||
1803 | 488..491 'Foo': Foo | ||
1804 | 502..504 'r1': usize | ||
1805 | 507..512 'lazy1': Lazy<Foo, || -> Foo> | ||
1806 | 507..518 'lazy1.foo()': usize | ||
1807 | 560..575 'make_foo_fn_ptr': fn() -> Foo | ||
1808 | 591..602 'make_foo_fn': fn make_foo_fn() -> Foo | ||
1809 | 612..617 'lazy2': Lazy<Foo, fn() -> Foo> | ||
1810 | 634..643 'Lazy::new': fn new<Foo, fn() -> Foo>(fn() -> Foo) -> Lazy<Foo, fn() -> Foo> | ||
1811 | 634..660 'Lazy::...n_ptr)': Lazy<Foo, fn() -> Foo> | ||
1812 | 644..659 'make_foo_fn_ptr': fn() -> Foo | ||
1813 | 670..672 'r2': usize | ||
1814 | 675..680 'lazy2': Lazy<Foo, fn() -> Foo> | ||
1815 | 675..686 'lazy2.foo()': usize | ||
1816 | 549..551 '{}': () | ||
1817 | "#]], | ||
1818 | ); | ||
1819 | } | ||
1820 | |||
1821 | #[test] | ||
1822 | fn closure_1() { | ||
1823 | check_infer( | ||
1824 | r#" | ||
1825 | #[lang = "fn_once"] | ||
1826 | trait FnOnce<Args> { | ||
1827 | type Output; | ||
1828 | } | ||
1829 | |||
1830 | enum Option<T> { Some(T), None } | ||
1831 | impl<T> Option<T> { | ||
1832 | fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> {} | ||
1833 | } | ||
1834 | |||
1835 | fn test() { | ||
1836 | let x = Option::Some(1u32); | ||
1837 | x.map(|v| v + 1); | ||
1838 | x.map(|_v| 1u64); | ||
1839 | let y: Option<i64> = x.map(|_v| 1); | ||
1840 | } | ||
1841 | "#, | ||
1842 | expect![[r#" | ||
1843 | 147..151 'self': Option<T> | ||
1844 | 153..154 'f': F | ||
1845 | 172..174 '{}': () | ||
1846 | 188..307 '{ ... 1); }': () | ||
1847 | 198..199 'x': Option<u32> | ||
1848 | 202..214 'Option::Some': Some<u32>(u32) -> Option<u32> | ||
1849 | 202..220 'Option...(1u32)': Option<u32> | ||
1850 | 215..219 '1u32': u32 | ||
1851 | 226..227 'x': Option<u32> | ||
1852 | 226..242 'x.map(...v + 1)': Option<u32> | ||
1853 | 232..241 '|v| v + 1': |u32| -> u32 | ||
1854 | 233..234 'v': u32 | ||
1855 | 236..237 'v': u32 | ||
1856 | 236..241 'v + 1': u32 | ||
1857 | 240..241 '1': u32 | ||
1858 | 248..249 'x': Option<u32> | ||
1859 | 248..264 'x.map(... 1u64)': Option<u64> | ||
1860 | 254..263 '|_v| 1u64': |u32| -> u64 | ||
1861 | 255..257 '_v': u32 | ||
1862 | 259..263 '1u64': u64 | ||
1863 | 274..275 'y': Option<i64> | ||
1864 | 291..292 'x': Option<u32> | ||
1865 | 291..304 'x.map(|_v| 1)': Option<i64> | ||
1866 | 297..303 '|_v| 1': |u32| -> i64 | ||
1867 | 298..300 '_v': u32 | ||
1868 | 302..303 '1': i64 | ||
1869 | "#]], | ||
1870 | ); | ||
1871 | } | ||
1872 | |||
1873 | #[test] | ||
1874 | fn closure_2() { | ||
1875 | check_infer( | ||
1876 | r#" | ||
1877 | trait FnOnce<Args> { | ||
1878 | type Output; | ||
1879 | } | ||
1880 | |||
1881 | fn test<F: FnOnce(u32) -> u64>(f: F) { | ||
1882 | f(1); | ||
1883 | let g = |v| v + 1; | ||
1884 | g(1u64); | ||
1885 | let h = |v| 1u128 + v; | ||
1886 | } | ||
1887 | "#, | ||
1888 | expect![[r#" | ||
1889 | 72..73 'f': F | ||
1890 | 78..154 '{ ...+ v; }': () | ||
1891 | 84..85 'f': F | ||
1892 | 84..88 'f(1)': {unknown} | ||
1893 | 86..87 '1': i32 | ||
1894 | 98..99 'g': |u64| -> i32 | ||
1895 | 102..111 '|v| v + 1': |u64| -> i32 | ||
1896 | 103..104 'v': u64 | ||
1897 | 106..107 'v': u64 | ||
1898 | 106..111 'v + 1': i32 | ||
1899 | 110..111 '1': i32 | ||
1900 | 117..118 'g': |u64| -> i32 | ||
1901 | 117..124 'g(1u64)': i32 | ||
1902 | 119..123 '1u64': u64 | ||
1903 | 134..135 'h': |u128| -> u128 | ||
1904 | 138..151 '|v| 1u128 + v': |u128| -> u128 | ||
1905 | 139..140 'v': u128 | ||
1906 | 142..147 '1u128': u128 | ||
1907 | 142..151 '1u128 + v': u128 | ||
1908 | 150..151 'v': u128 | ||
1909 | "#]], | ||
1910 | ); | ||
1911 | } | ||
1912 | |||
1913 | #[test] | ||
1914 | fn closure_as_argument_inference_order() { | ||
1915 | check_infer( | ||
1916 | r#" | ||
1917 | #[lang = "fn_once"] | ||
1918 | trait FnOnce<Args> { | ||
1919 | type Output; | ||
1920 | } | ||
1921 | |||
1922 | fn foo1<T, U, F: FnOnce(T) -> U>(x: T, f: F) -> U {} | ||
1923 | fn foo2<T, U, F: FnOnce(T) -> U>(f: F, x: T) -> U {} | ||
1924 | |||
1925 | struct S; | ||
1926 | impl S { | ||
1927 | fn method(self) -> u64; | ||
1928 | |||
1929 | fn foo1<T, U, F: FnOnce(T) -> U>(self, x: T, f: F) -> U {} | ||
1930 | fn foo2<T, U, F: FnOnce(T) -> U>(self, f: F, x: T) -> U {} | ||
1931 | } | ||
1932 | |||
1933 | fn test() { | ||
1934 | let x1 = foo1(S, |s| s.method()); | ||
1935 | let x2 = foo2(|s| s.method(), S); | ||
1936 | let x3 = S.foo1(S, |s| s.method()); | ||
1937 | let x4 = S.foo2(|s| s.method(), S); | ||
1938 | } | ||
1939 | "#, | ||
1940 | expect![[r#" | ||
1941 | 94..95 'x': T | ||
1942 | 100..101 'f': F | ||
1943 | 111..113 '{}': () | ||
1944 | 147..148 'f': F | ||
1945 | 153..154 'x': T | ||
1946 | 164..166 '{}': () | ||
1947 | 201..205 'self': S | ||
1948 | 253..257 'self': S | ||
1949 | 259..260 'x': T | ||
1950 | 265..266 'f': F | ||
1951 | 276..278 '{}': () | ||
1952 | 316..320 'self': S | ||
1953 | 322..323 'f': F | ||
1954 | 328..329 'x': T | ||
1955 | 339..341 '{}': () | ||
1956 | 355..514 '{ ... S); }': () | ||
1957 | 365..367 'x1': u64 | ||
1958 | 370..374 'foo1': fn foo1<S, u64, |S| -> u64>(S, |S| -> u64) -> u64 | ||
1959 | 370..393 'foo1(S...hod())': u64 | ||
1960 | 375..376 'S': S | ||
1961 | 378..392 '|s| s.method()': |S| -> u64 | ||
1962 | 379..380 's': S | ||
1963 | 382..383 's': S | ||
1964 | 382..392 's.method()': u64 | ||
1965 | 403..405 'x2': u64 | ||
1966 | 408..412 'foo2': fn foo2<S, u64, |S| -> u64>(|S| -> u64, S) -> u64 | ||
1967 | 408..431 'foo2(|...(), S)': u64 | ||
1968 | 413..427 '|s| s.method()': |S| -> u64 | ||
1969 | 414..415 's': S | ||
1970 | 417..418 's': S | ||
1971 | 417..427 's.method()': u64 | ||
1972 | 429..430 'S': S | ||
1973 | 441..443 'x3': u64 | ||
1974 | 446..447 'S': S | ||
1975 | 446..471 'S.foo1...hod())': u64 | ||
1976 | 453..454 'S': S | ||
1977 | 456..470 '|s| s.method()': |S| -> u64 | ||
1978 | 457..458 's': S | ||
1979 | 460..461 's': S | ||
1980 | 460..470 's.method()': u64 | ||
1981 | 481..483 'x4': u64 | ||
1982 | 486..487 'S': S | ||
1983 | 486..511 'S.foo2...(), S)': u64 | ||
1984 | 493..507 '|s| s.method()': |S| -> u64 | ||
1985 | 494..495 's': S | ||
1986 | 497..498 's': S | ||
1987 | 497..507 's.method()': u64 | ||
1988 | 509..510 'S': S | ||
1989 | "#]], | ||
1990 | ); | ||
1991 | } | ||
1992 | |||
1993 | #[test] | ||
1994 | fn fn_item_fn_trait() { | ||
1995 | check_types( | ||
1996 | r#" | ||
1997 | #[lang = "fn_once"] | ||
1998 | trait FnOnce<Args> { | ||
1999 | type Output; | ||
2000 | } | ||
2001 | |||
2002 | struct S; | ||
2003 | |||
2004 | fn foo() -> S {} | ||
2005 | |||
2006 | fn takes_closure<U, F: FnOnce() -> U>(f: F) -> U { f() } | ||
2007 | |||
2008 | fn test() { | ||
2009 | takes_closure(foo); | ||
2010 | } //^^^^^^^^^^^^^^^^^^ S | ||
2011 | "#, | ||
2012 | ); | ||
2013 | } | ||
2014 | |||
2015 | #[test] | ||
2016 | fn unselected_projection_in_trait_env_1() { | ||
2017 | check_types( | ||
2018 | r#" | ||
2019 | //- /main.rs | ||
2020 | trait Trait { | ||
2021 | type Item; | ||
2022 | } | ||
2023 | |||
2024 | trait Trait2 { | ||
2025 | fn foo(&self) -> u32; | ||
2026 | } | ||
2027 | |||
2028 | fn test<T: Trait>() where T::Item: Trait2 { | ||
2029 | let x: T::Item = no_matter; | ||
2030 | x.foo(); | ||
2031 | } //^ u32 | ||
2032 | "#, | ||
2033 | ); | ||
2034 | } | ||
2035 | |||
2036 | #[test] | ||
2037 | fn unselected_projection_in_trait_env_2() { | ||
2038 | check_types( | ||
2039 | r#" | ||
2040 | trait Trait<T> { | ||
2041 | type Item; | ||
2042 | } | ||
2043 | |||
2044 | trait Trait2 { | ||
2045 | fn foo(&self) -> u32; | ||
2046 | } | ||
2047 | |||
2048 | fn test<T, U>() where T::Item: Trait2, T: Trait<U::Item>, U: Trait<()> { | ||
2049 | let x: T::Item = no_matter; | ||
2050 | x.foo(); | ||
2051 | } //^ u32 | ||
2052 | "#, | ||
2053 | ); | ||
2054 | } | ||
2055 | |||
2056 | #[test] | ||
2057 | fn unselected_projection_on_impl_self() { | ||
2058 | check_infer( | ||
2059 | r#" | ||
2060 | //- /main.rs | ||
2061 | trait Trait { | ||
2062 | type Item; | ||
2063 | |||
2064 | fn f(&self, x: Self::Item); | ||
2065 | } | ||
2066 | |||
2067 | struct S; | ||
2068 | |||
2069 | impl Trait for S { | ||
2070 | type Item = u32; | ||
2071 | fn f(&self, x: Self::Item) { let y = x; } | ||
2072 | } | ||
2073 | |||
2074 | struct S2; | ||
2075 | |||
2076 | impl Trait for S2 { | ||
2077 | type Item = i32; | ||
2078 | fn f(&self, x: <Self>::Item) { let y = x; } | ||
2079 | } | ||
2080 | "#, | ||
2081 | expect![[r#" | ||
2082 | 40..44 'self': &Self | ||
2083 | 46..47 'x': Trait::Item<Self> | ||
2084 | 126..130 'self': &S | ||
2085 | 132..133 'x': u32 | ||
2086 | 147..161 '{ let y = x; }': () | ||
2087 | 153..154 'y': u32 | ||
2088 | 157..158 'x': u32 | ||
2089 | 228..232 'self': &S2 | ||
2090 | 234..235 'x': i32 | ||
2091 | 251..265 '{ let y = x; }': () | ||
2092 | 257..258 'y': i32 | ||
2093 | 261..262 'x': i32 | ||
2094 | "#]], | ||
2095 | ); | ||
2096 | } | ||
2097 | |||
2098 | #[test] | ||
2099 | fn unselected_projection_on_trait_self() { | ||
2100 | check_types( | ||
2101 | r#" | ||
2102 | trait Trait { | ||
2103 | type Item; | ||
2104 | |||
2105 | fn f(&self) -> Self::Item { loop {} } | ||
2106 | } | ||
2107 | |||
2108 | struct S; | ||
2109 | impl Trait for S { | ||
2110 | type Item = u32; | ||
2111 | } | ||
2112 | |||
2113 | fn test() { | ||
2114 | S.f(); | ||
2115 | } //^ u32 | ||
2116 | "#, | ||
2117 | ); | ||
2118 | } | ||
2119 | |||
2120 | #[test] | ||
2121 | fn unselected_projection_chalk_fold() { | ||
2122 | check_types( | ||
2123 | r#" | ||
2124 | trait Interner {} | ||
2125 | trait Fold<I: Interner, TI = I> { | ||
2126 | type Result; | ||
2127 | } | ||
2128 | |||
2129 | struct Ty<I: Interner> {} | ||
2130 | impl<I: Interner, TI: Interner> Fold<I, TI> for Ty<I> { | ||
2131 | type Result = Ty<TI>; | ||
2132 | } | ||
2133 | |||
2134 | fn fold<I: Interner, T>(interner: &I, t: T) -> T::Result | ||
2135 | where | ||
2136 | T: Fold<I, I>, | ||
2137 | { | ||
2138 | loop {} | ||
2139 | } | ||
2140 | |||
2141 | fn foo<I: Interner>(interner: &I, t: Ty<I>) { | ||
2142 | fold(interner, t); | ||
2143 | } //^ Ty<I> | ||
2144 | "#, | ||
2145 | ); | ||
2146 | } | ||
2147 | |||
2148 | #[test] | ||
2149 | fn trait_impl_self_ty() { | ||
2150 | check_types( | ||
2151 | r#" | ||
2152 | trait Trait<T> { | ||
2153 | fn foo(&self); | ||
2154 | } | ||
2155 | |||
2156 | struct S; | ||
2157 | |||
2158 | impl Trait<Self> for S {} | ||
2159 | |||
2160 | fn test() { | ||
2161 | S.foo(); | ||
2162 | } //^ () | ||
2163 | "#, | ||
2164 | ); | ||
2165 | } | ||
2166 | |||
2167 | #[test] | ||
2168 | fn trait_impl_self_ty_cycle() { | ||
2169 | check_types( | ||
2170 | r#" | ||
2171 | trait Trait { | ||
2172 | fn foo(&self); | ||
2173 | } | ||
2174 | |||
2175 | struct S<T>; | ||
2176 | |||
2177 | impl Trait for S<Self> {} | ||
2178 | |||
2179 | fn test() { | ||
2180 | S.foo(); | ||
2181 | } //^ {unknown} | ||
2182 | "#, | ||
2183 | ); | ||
2184 | } | ||
2185 | |||
2186 | #[test] | ||
2187 | fn unselected_projection_in_trait_env_cycle_1() { | ||
2188 | // this is a legitimate cycle | ||
2189 | check_types( | ||
2190 | r#" | ||
2191 | trait Trait { | ||
2192 | type Item; | ||
2193 | } | ||
2194 | |||
2195 | trait Trait2<T> {} | ||
2196 | |||
2197 | fn test<T: Trait>() where T: Trait2<T::Item> { | ||
2198 | let x: T::Item = no_matter; | ||
2199 | } //^ {unknown} | ||
2200 | "#, | ||
2201 | ); | ||
2202 | } | ||
2203 | |||
2204 | #[test] | ||
2205 | fn unselected_projection_in_trait_env_cycle_2() { | ||
2206 | // this is a legitimate cycle | ||
2207 | check_types( | ||
2208 | r#" | ||
2209 | //- /main.rs | ||
2210 | trait Trait<T> { | ||
2211 | type Item; | ||
2212 | } | ||
2213 | |||
2214 | fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> { | ||
2215 | let x: T::Item = no_matter; | ||
2216 | } //^ {unknown} | ||
2217 | "#, | ||
2218 | ); | ||
2219 | } | ||
2220 | |||
2221 | #[test] | ||
2222 | fn inline_assoc_type_bounds_1() { | ||
2223 | check_types( | ||
2224 | r#" | ||
2225 | trait Iterator { | ||
2226 | type Item; | ||
2227 | } | ||
2228 | trait OtherTrait<T> { | ||
2229 | fn foo(&self) -> T; | ||
2230 | } | ||
2231 | |||
2232 | // workaround for Chalk assoc type normalization problems | ||
2233 | pub struct S<T>; | ||
2234 | impl<T: Iterator> Iterator for S<T> { | ||
2235 | type Item = <T as Iterator>::Item; | ||
2236 | } | ||
2237 | |||
2238 | fn test<I: Iterator<Item: OtherTrait<u32>>>() { | ||
2239 | let x: <S<I> as Iterator>::Item; | ||
2240 | x.foo(); | ||
2241 | } //^ u32 | ||
2242 | "#, | ||
2243 | ); | ||
2244 | } | ||
2245 | |||
2246 | #[test] | ||
2247 | fn inline_assoc_type_bounds_2() { | ||
2248 | check_types( | ||
2249 | r#" | ||
2250 | trait Iterator { | ||
2251 | type Item; | ||
2252 | } | ||
2253 | |||
2254 | fn test<I: Iterator<Item: Iterator<Item = u32>>>() { | ||
2255 | let x: <<I as Iterator>::Item as Iterator>::Item; | ||
2256 | x; | ||
2257 | } //^ u32 | ||
2258 | "#, | ||
2259 | ); | ||
2260 | } | ||
2261 | |||
2262 | #[test] | ||
2263 | fn proc_macro_server_types() { | ||
2264 | check_infer( | ||
2265 | r#" | ||
2266 | macro_rules! with_api { | ||
2267 | ($S:ident, $self:ident, $m:ident) => { | ||
2268 | $m! { | ||
2269 | TokenStream { | ||
2270 | fn new() -> $S::TokenStream; | ||
2271 | }, | ||
2272 | Group { | ||
2273 | }, | ||
2274 | } | ||
2275 | }; | ||
2276 | } | ||
2277 | macro_rules! associated_item { | ||
2278 | (type TokenStream) => | ||
2279 | (type TokenStream: 'static;); | ||
2280 | (type Group) => | ||
2281 | (type Group: 'static;); | ||
2282 | ($($item:tt)*) => ($($item)*;) | ||
2283 | } | ||
2284 | macro_rules! declare_server_traits { | ||
2285 | ($($name:ident { | ||
2286 | $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?;)* | ||
2287 | }),* $(,)?) => { | ||
2288 | pub trait Types { | ||
2289 | $(associated_item!(type $name);)* | ||
2290 | } | ||
2291 | |||
2292 | $(pub trait $name: Types { | ||
2293 | $(associated_item!(fn $method($($arg: $arg_ty),*) $(-> $ret_ty)?);)* | ||
2294 | })* | ||
2295 | |||
2296 | pub trait Server: Types $(+ $name)* {} | ||
2297 | impl<S: Types $(+ $name)*> Server for S {} | ||
2298 | } | ||
2299 | } | ||
2300 | |||
2301 | with_api!(Self, self_, declare_server_traits); | ||
2302 | struct G {} | ||
2303 | struct T {} | ||
2304 | struct Rustc; | ||
2305 | impl Types for Rustc { | ||
2306 | type TokenStream = T; | ||
2307 | type Group = G; | ||
2308 | } | ||
2309 | |||
2310 | fn make<T>() -> T { loop {} } | ||
2311 | impl TokenStream for Rustc { | ||
2312 | fn new() -> Self::TokenStream { | ||
2313 | let group: Self::Group = make(); | ||
2314 | make() | ||
2315 | } | ||
2316 | } | ||
2317 | "#, | ||
2318 | expect![[r#" | ||
2319 | 1061..1072 '{ loop {} }': T | ||
2320 | 1063..1070 'loop {}': ! | ||
2321 | 1068..1070 '{}': () | ||
2322 | 1136..1199 '{ ... }': T | ||
2323 | 1150..1155 'group': G | ||
2324 | 1171..1175 'make': fn make<G>() -> G | ||
2325 | 1171..1177 'make()': G | ||
2326 | 1187..1191 'make': fn make<T>() -> T | ||
2327 | 1187..1193 'make()': T | ||
2328 | "#]], | ||
2329 | ); | ||
2330 | } | ||
2331 | |||
2332 | #[test] | ||
2333 | fn unify_impl_trait() { | ||
2334 | check_infer_with_mismatches( | ||
2335 | r#" | ||
2336 | trait Trait<T> {} | ||
2337 | |||
2338 | fn foo(x: impl Trait<u32>) { loop {} } | ||
2339 | fn bar<T>(x: impl Trait<T>) -> T { loop {} } | ||
2340 | |||
2341 | struct S<T>(T); | ||
2342 | impl<T> Trait<T> for S<T> {} | ||
2343 | |||
2344 | fn default<T>() -> T { loop {} } | ||
2345 | |||
2346 | fn test() -> impl Trait<i32> { | ||
2347 | let s1 = S(default()); | ||
2348 | foo(s1); | ||
2349 | let x: i32 = bar(S(default())); | ||
2350 | S(default()) | ||
2351 | } | ||
2352 | "#, | ||
2353 | expect![[r#" | ||
2354 | 26..27 'x': impl Trait<u32> | ||
2355 | 46..57 '{ loop {} }': () | ||
2356 | 48..55 'loop {}': ! | ||
2357 | 53..55 '{}': () | ||
2358 | 68..69 'x': impl Trait<T> | ||
2359 | 91..102 '{ loop {} }': T | ||
2360 | 93..100 'loop {}': ! | ||
2361 | 98..100 '{}': () | ||
2362 | 171..182 '{ loop {} }': T | ||
2363 | 173..180 'loop {}': ! | ||
2364 | 178..180 '{}': () | ||
2365 | 213..309 '{ ...t()) }': S<{unknown}> | ||
2366 | 223..225 's1': S<u32> | ||
2367 | 228..229 'S': S<u32>(u32) -> S<u32> | ||
2368 | 228..240 'S(default())': S<u32> | ||
2369 | 230..237 'default': fn default<u32>() -> u32 | ||
2370 | 230..239 'default()': u32 | ||
2371 | 246..249 'foo': fn foo(S<u32>) | ||
2372 | 246..253 'foo(s1)': () | ||
2373 | 250..252 's1': S<u32> | ||
2374 | 263..264 'x': i32 | ||
2375 | 272..275 'bar': fn bar<i32>(S<i32>) -> i32 | ||
2376 | 272..289 'bar(S(...lt()))': i32 | ||
2377 | 276..277 'S': S<i32>(i32) -> S<i32> | ||
2378 | 276..288 'S(default())': S<i32> | ||
2379 | 278..285 'default': fn default<i32>() -> i32 | ||
2380 | 278..287 'default()': i32 | ||
2381 | 295..296 'S': S<{unknown}>({unknown}) -> S<{unknown}> | ||
2382 | 295..307 'S(default())': S<{unknown}> | ||
2383 | 297..304 'default': fn default<{unknown}>() -> {unknown} | ||
2384 | 297..306 'default()': {unknown} | ||
2385 | "#]], | ||
2386 | ); | ||
2387 | } | ||
2388 | |||
2389 | #[test] | ||
2390 | fn assoc_types_from_bounds() { | ||
2391 | check_infer( | ||
2392 | r#" | ||
2393 | //- /main.rs | ||
2394 | #[lang = "fn_once"] | ||
2395 | trait FnOnce<Args> { | ||
2396 | type Output; | ||
2397 | } | ||
2398 | |||
2399 | trait T { | ||
2400 | type O; | ||
2401 | } | ||
2402 | |||
2403 | impl T for () { | ||
2404 | type O = (); | ||
2405 | } | ||
2406 | |||
2407 | fn f<X, F>(_v: F) | ||
2408 | where | ||
2409 | X: T, | ||
2410 | F: FnOnce(&X::O), | ||
2411 | { } | ||
2412 | |||
2413 | fn main() { | ||
2414 | f::<(), _>(|z| { z; }); | ||
2415 | } | ||
2416 | "#, | ||
2417 | expect![[r#" | ||
2418 | 133..135 '_v': F | ||
2419 | 178..181 '{ }': () | ||
2420 | 193..224 '{ ... }); }': () | ||
2421 | 199..209 'f::<(), _>': fn f<(), |&()| -> ()>(|&()| -> ()) | ||
2422 | 199..221 'f::<()... z; })': () | ||
2423 | 210..220 '|z| { z; }': |&()| -> () | ||
2424 | 211..212 'z': &() | ||
2425 | 214..220 '{ z; }': () | ||
2426 | 216..217 'z': &() | ||
2427 | "#]], | ||
2428 | ); | ||
2429 | } | ||
2430 | |||
2431 | #[test] | ||
2432 | fn associated_type_bound() { | ||
2433 | check_types( | ||
2434 | r#" | ||
2435 | pub trait Trait { | ||
2436 | type Item: OtherTrait<u32>; | ||
2437 | } | ||
2438 | pub trait OtherTrait<T> { | ||
2439 | fn foo(&self) -> T; | ||
2440 | } | ||
2441 | |||
2442 | // this is just a workaround for chalk#234 | ||
2443 | pub struct S<T>; | ||
2444 | impl<T: Trait> Trait for S<T> { | ||
2445 | type Item = <T as Trait>::Item; | ||
2446 | } | ||
2447 | |||
2448 | fn test<T: Trait>() { | ||
2449 | let y: <S<T> as Trait>::Item = no_matter; | ||
2450 | y.foo(); | ||
2451 | } //^ u32 | ||
2452 | "#, | ||
2453 | ); | ||
2454 | } | ||
2455 | |||
2456 | #[test] | ||
2457 | fn dyn_trait_through_chalk() { | ||
2458 | check_types( | ||
2459 | r#" | ||
2460 | struct Box<T> {} | ||
2461 | #[lang = "deref"] | ||
2462 | trait Deref { | ||
2463 | type Target; | ||
2464 | } | ||
2465 | impl<T> Deref for Box<T> { | ||
2466 | type Target = T; | ||
2467 | } | ||
2468 | trait Trait { | ||
2469 | fn foo(&self); | ||
2470 | } | ||
2471 | |||
2472 | fn test(x: Box<dyn Trait>) { | ||
2473 | x.foo(); | ||
2474 | } //^ () | ||
2475 | "#, | ||
2476 | ); | ||
2477 | } | ||
2478 | |||
2479 | #[test] | ||
2480 | fn string_to_owned() { | ||
2481 | check_types( | ||
2482 | r#" | ||
2483 | struct String {} | ||
2484 | pub trait ToOwned { | ||
2485 | type Owned; | ||
2486 | fn to_owned(&self) -> Self::Owned; | ||
2487 | } | ||
2488 | impl ToOwned for str { | ||
2489 | type Owned = String; | ||
2490 | } | ||
2491 | fn test() { | ||
2492 | "foo".to_owned(); | ||
2493 | } //^ String | ||
2494 | "#, | ||
2495 | ); | ||
2496 | } | ||
2497 | |||
2498 | #[test] | ||
2499 | fn iterator_chain() { | ||
2500 | check_infer( | ||
2501 | r#" | ||
2502 | //- /main.rs | ||
2503 | #[lang = "fn_once"] | ||
2504 | trait FnOnce<Args> { | ||
2505 | type Output; | ||
2506 | } | ||
2507 | #[lang = "fn_mut"] | ||
2508 | trait FnMut<Args>: FnOnce<Args> { } | ||
2509 | |||
2510 | enum Option<T> { Some(T), None } | ||
2511 | use Option::*; | ||
2512 | |||
2513 | pub trait Iterator { | ||
2514 | type Item; | ||
2515 | |||
2516 | fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> | ||
2517 | where | ||
2518 | F: FnMut(Self::Item) -> Option<B>, | ||
2519 | { loop {} } | ||
2520 | |||
2521 | fn for_each<F>(self, f: F) | ||
2522 | where | ||
2523 | F: FnMut(Self::Item), | ||
2524 | { loop {} } | ||
2525 | } | ||
2526 | |||
2527 | pub trait IntoIterator { | ||
2528 | type Item; | ||
2529 | type IntoIter: Iterator<Item = Self::Item>; | ||
2530 | fn into_iter(self) -> Self::IntoIter; | ||
2531 | } | ||
2532 | |||
2533 | pub struct FilterMap<I, F> { } | ||
2534 | impl<B, I: Iterator, F> Iterator for FilterMap<I, F> | ||
2535 | where | ||
2536 | F: FnMut(I::Item) -> Option<B>, | ||
2537 | { | ||
2538 | type Item = B; | ||
2539 | } | ||
2540 | |||
2541 | #[stable(feature = "rust1", since = "1.0.0")] | ||
2542 | impl<I: Iterator> IntoIterator for I { | ||
2543 | type Item = I::Item; | ||
2544 | type IntoIter = I; | ||
2545 | |||
2546 | fn into_iter(self) -> I { | ||
2547 | self | ||
2548 | } | ||
2549 | } | ||
2550 | |||
2551 | struct Vec<T> {} | ||
2552 | impl<T> Vec<T> { | ||
2553 | fn new() -> Self { loop {} } | ||
2554 | } | ||
2555 | |||
2556 | impl<T> IntoIterator for Vec<T> { | ||
2557 | type Item = T; | ||
2558 | type IntoIter = IntoIter<T>; | ||
2559 | } | ||
2560 | |||
2561 | pub struct IntoIter<T> { } | ||
2562 | impl<T> Iterator for IntoIter<T> { | ||
2563 | type Item = T; | ||
2564 | } | ||
2565 | |||
2566 | fn main() { | ||
2567 | Vec::<i32>::new().into_iter() | ||
2568 | .filter_map(|x| if x > 0 { Some(x as u32) } else { None }) | ||
2569 | .for_each(|y| { y; }); | ||
2570 | } | ||
2571 | "#, | ||
2572 | expect![[r#" | ||
2573 | 226..230 'self': Self | ||
2574 | 232..233 'f': F | ||
2575 | 317..328 '{ loop {} }': FilterMap<Self, F> | ||
2576 | 319..326 'loop {}': ! | ||
2577 | 324..326 '{}': () | ||
2578 | 349..353 'self': Self | ||
2579 | 355..356 'f': F | ||
2580 | 405..416 '{ loop {} }': () | ||
2581 | 407..414 'loop {}': ! | ||
2582 | 412..414 '{}': () | ||
2583 | 525..529 'self': Self | ||
2584 | 854..858 'self': I | ||
2585 | 865..885 '{ ... }': I | ||
2586 | 875..879 'self': I | ||
2587 | 944..955 '{ loop {} }': Vec<T> | ||
2588 | 946..953 'loop {}': ! | ||
2589 | 951..953 '{}': () | ||
2590 | 1142..1269 '{ ... }); }': () | ||
2591 | 1148..1163 'Vec::<i32>::new': fn new<i32>() -> Vec<i32> | ||
2592 | 1148..1165 'Vec::<...:new()': Vec<i32> | ||
2593 | 1148..1177 'Vec::<...iter()': IntoIter<i32> | ||
2594 | 1148..1240 'Vec::<...one })': FilterMap<IntoIter<i32>, |i32| -> Option<u32>> | ||
2595 | 1148..1266 'Vec::<... y; })': () | ||
2596 | 1194..1239 '|x| if...None }': |i32| -> Option<u32> | ||
2597 | 1195..1196 'x': i32 | ||
2598 | 1198..1239 'if x >...None }': Option<u32> | ||
2599 | 1201..1202 'x': i32 | ||
2600 | 1201..1206 'x > 0': bool | ||
2601 | 1205..1206 '0': i32 | ||
2602 | 1207..1225 '{ Some...u32) }': Option<u32> | ||
2603 | 1209..1213 'Some': Some<u32>(u32) -> Option<u32> | ||
2604 | 1209..1223 'Some(x as u32)': Option<u32> | ||
2605 | 1214..1215 'x': i32 | ||
2606 | 1214..1222 'x as u32': u32 | ||
2607 | 1231..1239 '{ None }': Option<u32> | ||
2608 | 1233..1237 'None': Option<u32> | ||
2609 | 1255..1265 '|y| { y; }': |u32| -> () | ||
2610 | 1256..1257 'y': u32 | ||
2611 | 1259..1265 '{ y; }': () | ||
2612 | 1261..1262 'y': u32 | ||
2613 | "#]], | ||
2614 | ); | ||
2615 | } | ||
2616 | |||
2617 | #[test] | ||
2618 | fn nested_assoc() { | ||
2619 | check_types( | ||
2620 | r#" | ||
2621 | struct Bar; | ||
2622 | struct Foo; | ||
2623 | |||
2624 | trait A { | ||
2625 | type OutputA; | ||
2626 | } | ||
2627 | |||
2628 | impl A for Bar { | ||
2629 | type OutputA = Foo; | ||
2630 | } | ||
2631 | |||
2632 | trait B { | ||
2633 | type Output; | ||
2634 | fn foo() -> Self::Output; | ||
2635 | } | ||
2636 | |||
2637 | impl<T:A> B for T { | ||
2638 | type Output = T::OutputA; | ||
2639 | fn foo() -> Self::Output { loop {} } | ||
2640 | } | ||
2641 | |||
2642 | fn main() { | ||
2643 | Bar::foo(); | ||
2644 | } //^ Foo | ||
2645 | "#, | ||
2646 | ); | ||
2647 | } | ||
2648 | |||
2649 | #[test] | ||
2650 | fn trait_object_no_coercion() { | ||
2651 | check_infer_with_mismatches( | ||
2652 | r#" | ||
2653 | trait Foo {} | ||
2654 | |||
2655 | fn foo(x: &dyn Foo) {} | ||
2656 | |||
2657 | fn test(x: &dyn Foo) { | ||
2658 | foo(x); | ||
2659 | } | ||
2660 | "#, | ||
2661 | expect![[r#" | ||
2662 | 21..22 'x': &dyn Foo | ||
2663 | 34..36 '{}': () | ||
2664 | 46..47 'x': &dyn Foo | ||
2665 | 59..74 '{ foo(x); }': () | ||
2666 | 65..68 'foo': fn foo(&dyn Foo) | ||
2667 | 65..71 'foo(x)': () | ||
2668 | 69..70 'x': &dyn Foo | ||
2669 | "#]], | ||
2670 | ); | ||
2671 | } | ||
2672 | |||
2673 | #[test] | ||
2674 | fn builtin_copy() { | ||
2675 | check_infer_with_mismatches( | ||
2676 | r#" | ||
2677 | #[lang = "copy"] | ||
2678 | trait Copy {} | ||
2679 | |||
2680 | struct IsCopy; | ||
2681 | impl Copy for IsCopy {} | ||
2682 | struct NotCopy; | ||
2683 | |||
2684 | trait Test { fn test(&self) -> bool; } | ||
2685 | impl<T: Copy> Test for T {} | ||
2686 | |||
2687 | fn test() { | ||
2688 | IsCopy.test(); | ||
2689 | NotCopy.test(); | ||
2690 | (IsCopy, IsCopy).test(); | ||
2691 | (IsCopy, NotCopy).test(); | ||
2692 | } | ||
2693 | "#, | ||
2694 | expect![[r#" | ||
2695 | 110..114 'self': &Self | ||
2696 | 166..267 '{ ...t(); }': () | ||
2697 | 172..178 'IsCopy': IsCopy | ||
2698 | 172..185 'IsCopy.test()': bool | ||
2699 | 191..198 'NotCopy': NotCopy | ||
2700 | 191..205 'NotCopy.test()': {unknown} | ||
2701 | 211..227 '(IsCop...sCopy)': (IsCopy, IsCopy) | ||
2702 | 211..234 '(IsCop...test()': bool | ||
2703 | 212..218 'IsCopy': IsCopy | ||
2704 | 220..226 'IsCopy': IsCopy | ||
2705 | 240..257 '(IsCop...tCopy)': (IsCopy, NotCopy) | ||
2706 | 240..264 '(IsCop...test()': {unknown} | ||
2707 | 241..247 'IsCopy': IsCopy | ||
2708 | 249..256 'NotCopy': NotCopy | ||
2709 | "#]], | ||
2710 | ); | ||
2711 | } | ||
2712 | |||
2713 | #[test] | ||
2714 | fn builtin_fn_def_copy() { | ||
2715 | check_infer_with_mismatches( | ||
2716 | r#" | ||
2717 | #[lang = "copy"] | ||
2718 | trait Copy {} | ||
2719 | |||
2720 | fn foo() {} | ||
2721 | fn bar<T: Copy>(T) -> T {} | ||
2722 | struct Struct(usize); | ||
2723 | enum Enum { Variant(usize) } | ||
2724 | |||
2725 | trait Test { fn test(&self) -> bool; } | ||
2726 | impl<T: Copy> Test for T {} | ||
2727 | |||
2728 | fn test() { | ||
2729 | foo.test(); | ||
2730 | bar.test(); | ||
2731 | Struct.test(); | ||
2732 | Enum::Variant.test(); | ||
2733 | } | ||
2734 | "#, | ||
2735 | expect![[r#" | ||
2736 | 41..43 '{}': () | ||
2737 | 60..61 'T': {unknown} | ||
2738 | 68..70 '{}': () | ||
2739 | 68..70: expected T, got () | ||
2740 | 145..149 'self': &Self | ||
2741 | 201..281 '{ ...t(); }': () | ||
2742 | 207..210 'foo': fn foo() | ||
2743 | 207..217 'foo.test()': bool | ||
2744 | 223..226 'bar': fn bar<{unknown}>({unknown}) -> {unknown} | ||
2745 | 223..233 'bar.test()': bool | ||
2746 | 239..245 'Struct': Struct(usize) -> Struct | ||
2747 | 239..252 'Struct.test()': bool | ||
2748 | 258..271 'Enum::Variant': Variant(usize) -> Enum | ||
2749 | 258..278 'Enum::...test()': bool | ||
2750 | "#]], | ||
2751 | ); | ||
2752 | } | ||
2753 | |||
2754 | #[test] | ||
2755 | fn builtin_fn_ptr_copy() { | ||
2756 | check_infer_with_mismatches( | ||
2757 | r#" | ||
2758 | #[lang = "copy"] | ||
2759 | trait Copy {} | ||
2760 | |||
2761 | trait Test { fn test(&self) -> bool; } | ||
2762 | impl<T: Copy> Test for T {} | ||
2763 | |||
2764 | fn test(f1: fn(), f2: fn(usize) -> u8, f3: fn(u8, u8) -> &u8) { | ||
2765 | f1.test(); | ||
2766 | f2.test(); | ||
2767 | f3.test(); | ||
2768 | } | ||
2769 | "#, | ||
2770 | expect![[r#" | ||
2771 | 54..58 'self': &Self | ||
2772 | 108..110 'f1': fn() | ||
2773 | 118..120 'f2': fn(usize) -> u8 | ||
2774 | 139..141 'f3': fn(u8, u8) -> &u8 | ||
2775 | 162..210 '{ ...t(); }': () | ||
2776 | 168..170 'f1': fn() | ||
2777 | 168..177 'f1.test()': bool | ||
2778 | 183..185 'f2': fn(usize) -> u8 | ||
2779 | 183..192 'f2.test()': bool | ||
2780 | 198..200 'f3': fn(u8, u8) -> &u8 | ||
2781 | 198..207 'f3.test()': bool | ||
2782 | "#]], | ||
2783 | ); | ||
2784 | } | ||
2785 | |||
2786 | #[test] | ||
2787 | fn builtin_sized() { | ||
2788 | check_infer_with_mismatches( | ||
2789 | r#" | ||
2790 | #[lang = "sized"] | ||
2791 | trait Sized {} | ||
2792 | |||
2793 | trait Test { fn test(&self) -> bool; } | ||
2794 | impl<T: Sized> Test for T {} | ||
2795 | |||
2796 | fn test() { | ||
2797 | 1u8.test(); | ||
2798 | (*"foo").test(); // not Sized | ||
2799 | (1u8, 1u8).test(); | ||
2800 | (1u8, *"foo").test(); // not Sized | ||
2801 | } | ||
2802 | "#, | ||
2803 | expect![[r#" | ||
2804 | 56..60 'self': &Self | ||
2805 | 113..228 '{ ...ized }': () | ||
2806 | 119..122 '1u8': u8 | ||
2807 | 119..129 '1u8.test()': bool | ||
2808 | 135..150 '(*"foo").test()': {unknown} | ||
2809 | 136..142 '*"foo"': str | ||
2810 | 137..142 '"foo"': &str | ||
2811 | 169..179 '(1u8, 1u8)': (u8, u8) | ||
2812 | 169..186 '(1u8, ...test()': bool | ||
2813 | 170..173 '1u8': u8 | ||
2814 | 175..178 '1u8': u8 | ||
2815 | 192..205 '(1u8, *"foo")': (u8, str) | ||
2816 | 192..212 '(1u8, ...test()': {unknown} | ||
2817 | 193..196 '1u8': u8 | ||
2818 | 198..204 '*"foo"': str | ||
2819 | 199..204 '"foo"': &str | ||
2820 | "#]], | ||
2821 | ); | ||
2822 | } | ||
2823 | |||
2824 | #[test] | ||
2825 | fn integer_range_iterate() { | ||
2826 | check_types( | ||
2827 | r#" | ||
2828 | //- /main.rs crate:main deps:core | ||
2829 | fn test() { | ||
2830 | for x in 0..100 { x; } | ||
2831 | } //^ i32 | ||
2832 | |||
2833 | //- /core.rs crate:core | ||
2834 | pub mod ops { | ||
2835 | pub struct Range<Idx> { | ||
2836 | pub start: Idx, | ||
2837 | pub end: Idx, | ||
2838 | } | ||
2839 | } | ||
2840 | |||
2841 | pub mod iter { | ||
2842 | pub trait Iterator { | ||
2843 | type Item; | ||
2844 | } | ||
2845 | |||
2846 | pub trait IntoIterator { | ||
2847 | type Item; | ||
2848 | type IntoIter: Iterator<Item = Self::Item>; | ||
2849 | } | ||
2850 | |||
2851 | impl<T> IntoIterator for T where T: Iterator { | ||
2852 | type Item = <T as Iterator>::Item; | ||
2853 | type IntoIter = Self; | ||
2854 | } | ||
2855 | } | ||
2856 | |||
2857 | trait Step {} | ||
2858 | impl Step for i32 {} | ||
2859 | impl Step for i64 {} | ||
2860 | |||
2861 | impl<A: Step> iter::Iterator for ops::Range<A> { | ||
2862 | type Item = A; | ||
2863 | } | ||
2864 | "#, | ||
2865 | ); | ||
2866 | } | ||
2867 | |||
2868 | #[test] | ||
2869 | fn infer_closure_arg() { | ||
2870 | check_infer( | ||
2871 | r#" | ||
2872 | //- /lib.rs | ||
2873 | |||
2874 | enum Option<T> { | ||
2875 | None, | ||
2876 | Some(T) | ||
2877 | } | ||
2878 | |||
2879 | fn foo() { | ||
2880 | let s = Option::None; | ||
2881 | let f = |x: Option<i32>| {}; | ||
2882 | (&f)(s) | ||
2883 | } | ||
2884 | "#, | ||
2885 | expect![[r#" | ||
2886 | 52..126 '{ ...)(s) }': () | ||
2887 | 62..63 's': Option<i32> | ||
2888 | 66..78 'Option::None': Option<i32> | ||
2889 | 88..89 'f': |Option<i32>| -> () | ||
2890 | 92..111 '|x: Op...2>| {}': |Option<i32>| -> () | ||
2891 | 93..94 'x': Option<i32> | ||
2892 | 109..111 '{}': () | ||
2893 | 117..124 '(&f)(s)': () | ||
2894 | 118..120 '&f': &|Option<i32>| -> () | ||
2895 | 119..120 'f': |Option<i32>| -> () | ||
2896 | 122..123 's': Option<i32> | ||
2897 | "#]], | ||
2898 | ); | ||
2899 | } | ||
2900 | |||
2901 | #[test] | ||
2902 | fn infer_fn_trait_arg() { | ||
2903 | check_infer( | ||
2904 | r#" | ||
2905 | //- /lib.rs deps:std | ||
2906 | |||
2907 | #[lang = "fn_once"] | ||
2908 | pub trait FnOnce<Args> { | ||
2909 | type Output; | ||
2910 | |||
2911 | extern "rust-call" fn call_once(&self, args: Args) -> Self::Output; | ||
2912 | } | ||
2913 | |||
2914 | #[lang = "fn"] | ||
2915 | pub trait Fn<Args>:FnOnce<Args> { | ||
2916 | extern "rust-call" fn call(&self, args: Args) -> Self::Output; | ||
2917 | } | ||
2918 | |||
2919 | enum Option<T> { | ||
2920 | None, | ||
2921 | Some(T) | ||
2922 | } | ||
2923 | |||
2924 | fn foo<F, T>(f: F) -> T | ||
2925 | where | ||
2926 | F: Fn(Option<i32>) -> T, | ||
2927 | { | ||
2928 | let s = None; | ||
2929 | f(s) | ||
2930 | } | ||
2931 | "#, | ||
2932 | expect![[r#" | ||
2933 | 101..105 'self': &Self | ||
2934 | 107..111 'args': Args | ||
2935 | 220..224 'self': &Self | ||
2936 | 226..230 'args': Args | ||
2937 | 313..314 'f': F | ||
2938 | 359..389 '{ ...f(s) }': T | ||
2939 | 369..370 's': Option<i32> | ||
2940 | 373..377 'None': Option<i32> | ||
2941 | 383..384 'f': F | ||
2942 | 383..387 'f(s)': T | ||
2943 | 385..386 's': Option<i32> | ||
2944 | "#]], | ||
2945 | ); | ||
2946 | } | ||
2947 | |||
2948 | #[test] | ||
2949 | fn infer_box_fn_arg() { | ||
2950 | check_infer( | ||
2951 | r#" | ||
2952 | //- /lib.rs deps:std | ||
2953 | |||
2954 | #[lang = "fn_once"] | ||
2955 | pub trait FnOnce<Args> { | ||
2956 | type Output; | ||
2957 | |||
2958 | extern "rust-call" fn call_once(self, args: Args) -> Self::Output; | ||
2959 | } | ||
2960 | |||
2961 | #[lang = "deref"] | ||
2962 | pub trait Deref { | ||
2963 | type Target: ?Sized; | ||
2964 | |||
2965 | fn deref(&self) -> &Self::Target; | ||
2966 | } | ||
2967 | |||
2968 | #[lang = "owned_box"] | ||
2969 | pub struct Box<T: ?Sized> { | ||
2970 | inner: *mut T, | ||
2971 | } | ||
2972 | |||
2973 | impl<T: ?Sized> Deref for Box<T> { | ||
2974 | type Target = T; | ||
2975 | |||
2976 | fn deref(&self) -> &T { | ||
2977 | &self.inner | ||
2978 | } | ||
2979 | } | ||
2980 | |||
2981 | enum Option<T> { | ||
2982 | None, | ||
2983 | Some(T) | ||
2984 | } | ||
2985 | |||
2986 | fn foo() { | ||
2987 | let s = Option::None; | ||
2988 | let f: Box<dyn FnOnce(&Option<i32>)> = box (|ps| {}); | ||
2989 | f(&s) | ||
2990 | } | ||
2991 | "#, | ||
2992 | expect![[r#" | ||
2993 | 100..104 'self': Self | ||
2994 | 106..110 'args': Args | ||
2995 | 214..218 'self': &Self | ||
2996 | 384..388 'self': &Box<T> | ||
2997 | 396..423 '{ ... }': &T | ||
2998 | 406..417 '&self.inner': &*mut T | ||
2999 | 407..411 'self': &Box<T> | ||
3000 | 407..417 'self.inner': *mut T | ||
3001 | 478..575 '{ ...(&s) }': FnOnce::Output<dyn FnOnce<(&Option<i32>,)>, (&Option<i32>,)> | ||
3002 | 488..489 's': Option<i32> | ||
3003 | 492..504 'Option::None': Option<i32> | ||
3004 | 514..515 'f': Box<dyn FnOnce<(&Option<i32>,)>> | ||
3005 | 549..562 'box (|ps| {})': Box<|{unknown}| -> ()> | ||
3006 | 554..561 '|ps| {}': |{unknown}| -> () | ||
3007 | 555..557 'ps': {unknown} | ||
3008 | 559..561 '{}': () | ||
3009 | 568..569 'f': Box<dyn FnOnce<(&Option<i32>,)>> | ||
3010 | 568..573 'f(&s)': FnOnce::Output<dyn FnOnce<(&Option<i32>,)>, (&Option<i32>,)> | ||
3011 | 570..572 '&s': &Option<i32> | ||
3012 | 571..572 's': Option<i32> | ||
3013 | "#]], | ||
3014 | ); | ||
3015 | } | ||
3016 | |||
3017 | #[test] | ||
3018 | fn infer_dyn_fn_output() { | ||
3019 | check_types( | ||
3020 | r#" | ||
3021 | #[lang = "fn_once"] | ||
3022 | pub trait FnOnce<Args> { | ||
3023 | type Output; | ||
3024 | extern "rust-call" fn call_once(self, args: Args) -> Self::Output; | ||
3025 | } | ||
3026 | |||
3027 | #[lang = "fn"] | ||
3028 | pub trait Fn<Args>: FnOnce<Args> { | ||
3029 | extern "rust-call" fn call(&self, args: Args) -> Self::Output; | ||
3030 | } | ||
3031 | |||
3032 | fn foo() { | ||
3033 | let f: &dyn Fn() -> i32; | ||
3034 | f(); | ||
3035 | //^^^ i32 | ||
3036 | }"#, | ||
3037 | ); | ||
3038 | } | ||
3039 | |||
3040 | #[test] | ||
3041 | fn infer_dyn_fn_once_output() { | ||
3042 | check_types( | ||
3043 | r#" | ||
3044 | #[lang = "fn_once"] | ||
3045 | pub trait FnOnce<Args> { | ||
3046 | type Output; | ||
3047 | extern "rust-call" fn call_once(self, args: Args) -> Self::Output; | ||
3048 | } | ||
3049 | |||
3050 | fn foo() { | ||
3051 | let f: dyn FnOnce() -> i32; | ||
3052 | f(); | ||
3053 | //^^^ i32 | ||
3054 | }"#, | ||
3055 | ); | ||
3056 | } | ||
3057 | |||
3058 | #[test] | ||
3059 | fn variable_kinds_1() { | ||
3060 | check_types( | ||
3061 | r#" | ||
3062 | trait Trait<T> { fn get(self, t: T) -> T; } | ||
3063 | struct S; | ||
3064 | impl Trait<u128> for S {} | ||
3065 | impl Trait<f32> for S {} | ||
3066 | fn test() { | ||
3067 | S.get(1); | ||
3068 | //^^^^^^^^ u128 | ||
3069 | S.get(1.); | ||
3070 | //^^^^^^^^ f32 | ||
3071 | } | ||
3072 | "#, | ||
3073 | ); | ||
3074 | } | ||
3075 | |||
3076 | #[test] | ||
3077 | fn variable_kinds_2() { | ||
3078 | check_types( | ||
3079 | r#" | ||
3080 | trait Trait { fn get(self) -> Self; } | ||
3081 | impl Trait for u128 {} | ||
3082 | impl Trait for f32 {} | ||
3083 | fn test() { | ||
3084 | 1.get(); | ||
3085 | //^^^^^^^ u128 | ||
3086 | (1.).get(); | ||
3087 | //^^^^^^^^^^ f32 | ||
3088 | } | ||
3089 | "#, | ||
3090 | ); | ||
3091 | } | ||
3092 | |||
3093 | #[test] | ||
3094 | fn underscore_import() { | ||
3095 | check_types( | ||
3096 | r#" | ||
3097 | mod tr { | ||
3098 | pub trait Tr { | ||
3099 | fn method(&self) -> u8 { 0 } | ||
3100 | } | ||
3101 | } | ||
3102 | |||
3103 | struct Tr; | ||
3104 | impl crate::tr::Tr for Tr {} | ||
3105 | |||
3106 | use crate::tr::Tr as _; | ||
3107 | fn test() { | ||
3108 | Tr.method(); | ||
3109 | //^^^^^^^^^^^ u8 | ||
3110 | } | ||
3111 | "#, | ||
3112 | ); | ||
3113 | } | ||