diff options
Diffstat (limited to 'crates/ra_hir_ty/src/tests/simple.rs')
-rw-r--r-- | crates/ra_hir_ty/src/tests/simple.rs | 1663 |
1 files changed, 1663 insertions, 0 deletions
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs new file mode 100644 index 000000000..3e5e163e3 --- /dev/null +++ b/crates/ra_hir_ty/src/tests/simple.rs | |||
@@ -0,0 +1,1663 @@ | |||
1 | use super::{infer, type_at, type_at_pos}; | ||
2 | use crate::test_db::TestDB; | ||
3 | use insta::assert_snapshot; | ||
4 | use ra_db::fixture::WithFixture; | ||
5 | |||
6 | #[test] | ||
7 | fn infer_box() { | ||
8 | let (db, pos) = TestDB::with_position( | ||
9 | r#" | ||
10 | //- /main.rs crate:main deps:std | ||
11 | |||
12 | fn test() { | ||
13 | let x = box 1; | ||
14 | let t = (x, box x, box &1, box [1]); | ||
15 | t<|>; | ||
16 | } | ||
17 | |||
18 | //- /std.rs crate:std | ||
19 | #[prelude_import] use prelude::*; | ||
20 | mod prelude {} | ||
21 | |||
22 | mod boxed { | ||
23 | pub struct Box<T: ?Sized> { | ||
24 | inner: *mut T, | ||
25 | } | ||
26 | } | ||
27 | |||
28 | "#, | ||
29 | ); | ||
30 | assert_eq!("(Box<i32>, Box<Box<i32>>, Box<&i32>, Box<[i32;_]>)", type_at_pos(&db, pos)); | ||
31 | } | ||
32 | |||
33 | #[test] | ||
34 | fn infer_adt_self() { | ||
35 | let (db, pos) = TestDB::with_position( | ||
36 | r#" | ||
37 | //- /main.rs | ||
38 | enum Nat { Succ(Self), Demo(Nat), Zero } | ||
39 | |||
40 | fn test() { | ||
41 | let foo: Nat = Nat::Zero; | ||
42 | if let Nat::Succ(x) = foo { | ||
43 | x<|> | ||
44 | } | ||
45 | } | ||
46 | |||
47 | "#, | ||
48 | ); | ||
49 | assert_eq!("Nat", type_at_pos(&db, pos)); | ||
50 | } | ||
51 | |||
52 | #[test] | ||
53 | fn infer_ranges() { | ||
54 | let (db, pos) = TestDB::with_position( | ||
55 | r#" | ||
56 | //- /main.rs crate:main deps:std | ||
57 | fn test() { | ||
58 | let a = ..; | ||
59 | let b = 1..; | ||
60 | let c = ..2u32; | ||
61 | let d = 1..2usize; | ||
62 | let e = ..=10; | ||
63 | let f = 'a'..='z'; | ||
64 | |||
65 | let t = (a, b, c, d, e, f); | ||
66 | t<|>; | ||
67 | } | ||
68 | |||
69 | //- /std.rs crate:std | ||
70 | #[prelude_import] use prelude::*; | ||
71 | mod prelude {} | ||
72 | |||
73 | pub mod ops { | ||
74 | pub struct Range<Idx> { | ||
75 | pub start: Idx, | ||
76 | pub end: Idx, | ||
77 | } | ||
78 | pub struct RangeFrom<Idx> { | ||
79 | pub start: Idx, | ||
80 | } | ||
81 | struct RangeFull; | ||
82 | pub struct RangeInclusive<Idx> { | ||
83 | start: Idx, | ||
84 | end: Idx, | ||
85 | is_empty: u8, | ||
86 | } | ||
87 | pub struct RangeTo<Idx> { | ||
88 | pub end: Idx, | ||
89 | } | ||
90 | pub struct RangeToInclusive<Idx> { | ||
91 | pub end: Idx, | ||
92 | } | ||
93 | } | ||
94 | "#, | ||
95 | ); | ||
96 | assert_eq!( | ||
97 | "(RangeFull, RangeFrom<i32>, RangeTo<u32>, Range<usize>, RangeToInclusive<i32>, RangeInclusive<char>)", | ||
98 | type_at_pos(&db, pos), | ||
99 | ); | ||
100 | } | ||
101 | |||
102 | #[test] | ||
103 | fn infer_while_let() { | ||
104 | let (db, pos) = TestDB::with_position( | ||
105 | r#" | ||
106 | //- /main.rs | ||
107 | enum Option<T> { Some(T), None } | ||
108 | |||
109 | fn test() { | ||
110 | let foo: Option<f32> = None; | ||
111 | while let Option::Some(x) = foo { | ||
112 | <|>x | ||
113 | } | ||
114 | } | ||
115 | |||
116 | "#, | ||
117 | ); | ||
118 | assert_eq!("f32", type_at_pos(&db, pos)); | ||
119 | } | ||
120 | |||
121 | #[test] | ||
122 | fn infer_basics() { | ||
123 | assert_snapshot!( | ||
124 | infer(r#" | ||
125 | fn test(a: u32, b: isize, c: !, d: &str) { | ||
126 | a; | ||
127 | b; | ||
128 | c; | ||
129 | d; | ||
130 | 1usize; | ||
131 | 1isize; | ||
132 | "test"; | ||
133 | 1.0f32; | ||
134 | }"#), | ||
135 | @r###" | ||
136 | [9; 10) 'a': u32 | ||
137 | [17; 18) 'b': isize | ||
138 | [27; 28) 'c': ! | ||
139 | [33; 34) 'd': &str | ||
140 | [42; 121) '{ ...f32; }': ! | ||
141 | [48; 49) 'a': u32 | ||
142 | [55; 56) 'b': isize | ||
143 | [62; 63) 'c': ! | ||
144 | [69; 70) 'd': &str | ||
145 | [76; 82) '1usize': usize | ||
146 | [88; 94) '1isize': isize | ||
147 | [100; 106) '"test"': &str | ||
148 | [112; 118) '1.0f32': f32 | ||
149 | "### | ||
150 | ); | ||
151 | } | ||
152 | |||
153 | #[test] | ||
154 | fn infer_let() { | ||
155 | assert_snapshot!( | ||
156 | infer(r#" | ||
157 | fn test() { | ||
158 | let a = 1isize; | ||
159 | let b: usize = 1; | ||
160 | let c = b; | ||
161 | let d: u32; | ||
162 | let e; | ||
163 | let f: i32 = e; | ||
164 | } | ||
165 | "#), | ||
166 | @r###" | ||
167 | [11; 118) '{ ...= e; }': () | ||
168 | [21; 22) 'a': isize | ||
169 | [25; 31) '1isize': isize | ||
170 | [41; 42) 'b': usize | ||
171 | [52; 53) '1': usize | ||
172 | [63; 64) 'c': usize | ||
173 | [67; 68) 'b': usize | ||
174 | [78; 79) 'd': u32 | ||
175 | [94; 95) 'e': i32 | ||
176 | [105; 106) 'f': i32 | ||
177 | [114; 115) 'e': i32 | ||
178 | "### | ||
179 | ); | ||
180 | } | ||
181 | |||
182 | #[test] | ||
183 | fn infer_paths() { | ||
184 | assert_snapshot!( | ||
185 | infer(r#" | ||
186 | fn a() -> u32 { 1 } | ||
187 | |||
188 | mod b { | ||
189 | fn c() -> u32 { 1 } | ||
190 | } | ||
191 | |||
192 | fn test() { | ||
193 | a(); | ||
194 | b::c(); | ||
195 | } | ||
196 | "#), | ||
197 | @r###" | ||
198 | [15; 20) '{ 1 }': u32 | ||
199 | [17; 18) '1': u32 | ||
200 | [48; 53) '{ 1 }': u32 | ||
201 | [50; 51) '1': u32 | ||
202 | [67; 91) '{ ...c(); }': () | ||
203 | [73; 74) 'a': fn a() -> u32 | ||
204 | [73; 76) 'a()': u32 | ||
205 | [82; 86) 'b::c': fn c() -> u32 | ||
206 | [82; 88) 'b::c()': u32 | ||
207 | "### | ||
208 | ); | ||
209 | } | ||
210 | |||
211 | #[test] | ||
212 | fn infer_path_type() { | ||
213 | assert_snapshot!( | ||
214 | infer(r#" | ||
215 | struct S; | ||
216 | |||
217 | impl S { | ||
218 | fn foo() -> i32 { 1 } | ||
219 | } | ||
220 | |||
221 | fn test() { | ||
222 | S::foo(); | ||
223 | <S>::foo(); | ||
224 | } | ||
225 | "#), | ||
226 | @r###" | ||
227 | [41; 46) '{ 1 }': i32 | ||
228 | [43; 44) '1': i32 | ||
229 | [60; 93) '{ ...o(); }': () | ||
230 | [66; 72) 'S::foo': fn foo() -> i32 | ||
231 | [66; 74) 'S::foo()': i32 | ||
232 | [80; 88) '<S>::foo': fn foo() -> i32 | ||
233 | [80; 90) '<S>::foo()': i32 | ||
234 | "### | ||
235 | ); | ||
236 | } | ||
237 | |||
238 | #[test] | ||
239 | fn infer_struct() { | ||
240 | assert_snapshot!( | ||
241 | infer(r#" | ||
242 | struct A { | ||
243 | b: B, | ||
244 | c: C, | ||
245 | } | ||
246 | struct B; | ||
247 | struct C(usize); | ||
248 | |||
249 | fn test() { | ||
250 | let c = C(1); | ||
251 | B; | ||
252 | let a: A = A { b: B, c: C(1) }; | ||
253 | a.b; | ||
254 | a.c; | ||
255 | } | ||
256 | "#), | ||
257 | @r###" | ||
258 | [72; 154) '{ ...a.c; }': () | ||
259 | [82; 83) 'c': C | ||
260 | [86; 87) 'C': C(usize) -> C | ||
261 | [86; 90) 'C(1)': C | ||
262 | [88; 89) '1': usize | ||
263 | [96; 97) 'B': B | ||
264 | [107; 108) 'a': A | ||
265 | [114; 133) 'A { b:...C(1) }': A | ||
266 | [121; 122) 'B': B | ||
267 | [127; 128) 'C': C(usize) -> C | ||
268 | [127; 131) 'C(1)': C | ||
269 | [129; 130) '1': usize | ||
270 | [139; 140) 'a': A | ||
271 | [139; 142) 'a.b': B | ||
272 | [148; 149) 'a': A | ||
273 | [148; 151) 'a.c': C | ||
274 | "### | ||
275 | ); | ||
276 | } | ||
277 | |||
278 | #[test] | ||
279 | fn infer_enum() { | ||
280 | assert_snapshot!( | ||
281 | infer(r#" | ||
282 | enum E { | ||
283 | V1 { field: u32 }, | ||
284 | V2 | ||
285 | } | ||
286 | fn test() { | ||
287 | E::V1 { field: 1 }; | ||
288 | E::V2; | ||
289 | }"#), | ||
290 | @r###" | ||
291 | [48; 82) '{ E:...:V2; }': () | ||
292 | [52; 70) 'E::V1 ...d: 1 }': E | ||
293 | [67; 68) '1': u32 | ||
294 | [74; 79) 'E::V2': E | ||
295 | "### | ||
296 | ); | ||
297 | } | ||
298 | |||
299 | #[test] | ||
300 | fn infer_refs() { | ||
301 | assert_snapshot!( | ||
302 | infer(r#" | ||
303 | fn test(a: &u32, b: &mut u32, c: *const u32, d: *mut u32) { | ||
304 | a; | ||
305 | *a; | ||
306 | &a; | ||
307 | &mut a; | ||
308 | b; | ||
309 | *b; | ||
310 | &b; | ||
311 | c; | ||
312 | *c; | ||
313 | d; | ||
314 | *d; | ||
315 | } | ||
316 | "#), | ||
317 | @r###" | ||
318 | [9; 10) 'a': &u32 | ||
319 | [18; 19) 'b': &mut u32 | ||
320 | [31; 32) 'c': *const u32 | ||
321 | [46; 47) 'd': *mut u32 | ||
322 | [59; 150) '{ ... *d; }': () | ||
323 | [65; 66) 'a': &u32 | ||
324 | [72; 74) '*a': u32 | ||
325 | [73; 74) 'a': &u32 | ||
326 | [80; 82) '&a': &&u32 | ||
327 | [81; 82) 'a': &u32 | ||
328 | [88; 94) '&mut a': &mut &u32 | ||
329 | [93; 94) 'a': &u32 | ||
330 | [100; 101) 'b': &mut u32 | ||
331 | [107; 109) '*b': u32 | ||
332 | [108; 109) 'b': &mut u32 | ||
333 | [115; 117) '&b': &&mut u32 | ||
334 | [116; 117) 'b': &mut u32 | ||
335 | [123; 124) 'c': *const u32 | ||
336 | [130; 132) '*c': u32 | ||
337 | [131; 132) 'c': *const u32 | ||
338 | [138; 139) 'd': *mut u32 | ||
339 | [145; 147) '*d': u32 | ||
340 | [146; 147) 'd': *mut u32 | ||
341 | "### | ||
342 | ); | ||
343 | } | ||
344 | |||
345 | #[test] | ||
346 | fn infer_literals() { | ||
347 | assert_snapshot!( | ||
348 | infer(r##" | ||
349 | fn test() { | ||
350 | 5i32; | ||
351 | 5f32; | ||
352 | 5f64; | ||
353 | "hello"; | ||
354 | b"bytes"; | ||
355 | 'c'; | ||
356 | b'b'; | ||
357 | 3.14; | ||
358 | 5000; | ||
359 | false; | ||
360 | true; | ||
361 | r#" | ||
362 | //! doc | ||
363 | // non-doc | ||
364 | mod foo {} | ||
365 | "#; | ||
366 | br#"yolo"#; | ||
367 | } | ||
368 | "##), | ||
369 | @r###" | ||
370 | [11; 221) '{ ...o"#; }': () | ||
371 | [17; 21) '5i32': i32 | ||
372 | [27; 31) '5f32': f32 | ||
373 | [37; 41) '5f64': f64 | ||
374 | [47; 54) '"hello"': &str | ||
375 | [60; 68) 'b"bytes"': &[u8] | ||
376 | [74; 77) ''c'': char | ||
377 | [83; 87) 'b'b'': u8 | ||
378 | [93; 97) '3.14': f64 | ||
379 | [103; 107) '5000': i32 | ||
380 | [113; 118) 'false': bool | ||
381 | [124; 128) 'true': bool | ||
382 | [134; 202) 'r#" ... "#': &str | ||
383 | [208; 218) 'br#"yolo"#': &[u8] | ||
384 | "### | ||
385 | ); | ||
386 | } | ||
387 | |||
388 | #[test] | ||
389 | fn infer_unary_op() { | ||
390 | assert_snapshot!( | ||
391 | infer(r#" | ||
392 | enum SomeType {} | ||
393 | |||
394 | fn test(x: SomeType) { | ||
395 | let b = false; | ||
396 | let c = !b; | ||
397 | let a = 100; | ||
398 | let d: i128 = -a; | ||
399 | let e = -100; | ||
400 | let f = !!!true; | ||
401 | let g = !42; | ||
402 | let h = !10u32; | ||
403 | let j = !a; | ||
404 | -3.14; | ||
405 | !3; | ||
406 | -x; | ||
407 | !x; | ||
408 | -"hello"; | ||
409 | !"hello"; | ||
410 | } | ||
411 | "#), | ||
412 | @r###" | ||
413 | [27; 28) 'x': SomeType | ||
414 | [40; 272) '{ ...lo"; }': () | ||
415 | [50; 51) 'b': bool | ||
416 | [54; 59) 'false': bool | ||
417 | [69; 70) 'c': bool | ||
418 | [73; 75) '!b': bool | ||
419 | [74; 75) 'b': bool | ||
420 | [85; 86) 'a': i128 | ||
421 | [89; 92) '100': i128 | ||
422 | [102; 103) 'd': i128 | ||
423 | [112; 114) '-a': i128 | ||
424 | [113; 114) 'a': i128 | ||
425 | [124; 125) 'e': i32 | ||
426 | [128; 132) '-100': i32 | ||
427 | [129; 132) '100': i32 | ||
428 | [142; 143) 'f': bool | ||
429 | [146; 153) '!!!true': bool | ||
430 | [147; 153) '!!true': bool | ||
431 | [148; 153) '!true': bool | ||
432 | [149; 153) 'true': bool | ||
433 | [163; 164) 'g': i32 | ||
434 | [167; 170) '!42': i32 | ||
435 | [168; 170) '42': i32 | ||
436 | [180; 181) 'h': u32 | ||
437 | [184; 190) '!10u32': u32 | ||
438 | [185; 190) '10u32': u32 | ||
439 | [200; 201) 'j': i128 | ||
440 | [204; 206) '!a': i128 | ||
441 | [205; 206) 'a': i128 | ||
442 | [212; 217) '-3.14': f64 | ||
443 | [213; 217) '3.14': f64 | ||
444 | [223; 225) '!3': i32 | ||
445 | [224; 225) '3': i32 | ||
446 | [231; 233) '-x': {unknown} | ||
447 | [232; 233) 'x': SomeType | ||
448 | [239; 241) '!x': {unknown} | ||
449 | [240; 241) 'x': SomeType | ||
450 | [247; 255) '-"hello"': {unknown} | ||
451 | [248; 255) '"hello"': &str | ||
452 | [261; 269) '!"hello"': {unknown} | ||
453 | [262; 269) '"hello"': &str | ||
454 | "### | ||
455 | ); | ||
456 | } | ||
457 | |||
458 | #[test] | ||
459 | fn infer_backwards() { | ||
460 | assert_snapshot!( | ||
461 | infer(r#" | ||
462 | fn takes_u32(x: u32) {} | ||
463 | |||
464 | struct S { i32_field: i32 } | ||
465 | |||
466 | fn test() -> &mut &f64 { | ||
467 | let a = unknown_function(); | ||
468 | takes_u32(a); | ||
469 | let b = unknown_function(); | ||
470 | S { i32_field: b }; | ||
471 | let c = unknown_function(); | ||
472 | &mut &c | ||
473 | } | ||
474 | "#), | ||
475 | @r###" | ||
476 | [14; 15) 'x': u32 | ||
477 | [22; 24) '{}': () | ||
478 | [78; 231) '{ ...t &c }': &mut &f64 | ||
479 | [88; 89) 'a': u32 | ||
480 | [92; 108) 'unknow...nction': {unknown} | ||
481 | [92; 110) 'unknow...tion()': u32 | ||
482 | [116; 125) 'takes_u32': fn takes_u32(u32) -> () | ||
483 | [116; 128) 'takes_u32(a)': () | ||
484 | [126; 127) 'a': u32 | ||
485 | [138; 139) 'b': i32 | ||
486 | [142; 158) 'unknow...nction': {unknown} | ||
487 | [142; 160) 'unknow...tion()': i32 | ||
488 | [166; 184) 'S { i3...d: b }': S | ||
489 | [181; 182) 'b': i32 | ||
490 | [194; 195) 'c': f64 | ||
491 | [198; 214) 'unknow...nction': {unknown} | ||
492 | [198; 216) 'unknow...tion()': f64 | ||
493 | [222; 229) '&mut &c': &mut &f64 | ||
494 | [227; 229) '&c': &f64 | ||
495 | [228; 229) 'c': f64 | ||
496 | "### | ||
497 | ); | ||
498 | } | ||
499 | |||
500 | #[test] | ||
501 | fn infer_self() { | ||
502 | assert_snapshot!( | ||
503 | infer(r#" | ||
504 | struct S; | ||
505 | |||
506 | impl S { | ||
507 | fn test(&self) { | ||
508 | self; | ||
509 | } | ||
510 | fn test2(self: &Self) { | ||
511 | self; | ||
512 | } | ||
513 | fn test3() -> Self { | ||
514 | S {} | ||
515 | } | ||
516 | fn test4() -> Self { | ||
517 | Self {} | ||
518 | } | ||
519 | } | ||
520 | "#), | ||
521 | @r###" | ||
522 | [34; 38) 'self': &S | ||
523 | [40; 61) '{ ... }': () | ||
524 | [50; 54) 'self': &S | ||
525 | [75; 79) 'self': &S | ||
526 | [88; 109) '{ ... }': () | ||
527 | [98; 102) 'self': &S | ||
528 | [133; 153) '{ ... }': S | ||
529 | [143; 147) 'S {}': S | ||
530 | [177; 200) '{ ... }': S | ||
531 | [187; 194) 'Self {}': S | ||
532 | "### | ||
533 | ); | ||
534 | } | ||
535 | |||
536 | #[test] | ||
537 | fn infer_binary_op() { | ||
538 | assert_snapshot!( | ||
539 | infer(r#" | ||
540 | fn f(x: bool) -> i32 { | ||
541 | 0i32 | ||
542 | } | ||
543 | |||
544 | fn test() -> bool { | ||
545 | let x = a && b; | ||
546 | let y = true || false; | ||
547 | let z = x == y; | ||
548 | let t = x != y; | ||
549 | let minus_forty: isize = -40isize; | ||
550 | let h = minus_forty <= CONST_2; | ||
551 | let c = f(z || y) + 5; | ||
552 | let d = b; | ||
553 | let g = minus_forty ^= i; | ||
554 | let ten: usize = 10; | ||
555 | let ten_is_eleven = ten == some_num; | ||
556 | |||
557 | ten < 3 | ||
558 | } | ||
559 | "#), | ||
560 | @r###" | ||
561 | [6; 7) 'x': bool | ||
562 | [22; 34) '{ 0i32 }': i32 | ||
563 | [28; 32) '0i32': i32 | ||
564 | [54; 370) '{ ... < 3 }': bool | ||
565 | [64; 65) 'x': bool | ||
566 | [68; 69) 'a': bool | ||
567 | [68; 74) 'a && b': bool | ||
568 | [73; 74) 'b': bool | ||
569 | [84; 85) 'y': bool | ||
570 | [88; 92) 'true': bool | ||
571 | [88; 101) 'true || false': bool | ||
572 | [96; 101) 'false': bool | ||
573 | [111; 112) 'z': bool | ||
574 | [115; 116) 'x': bool | ||
575 | [115; 121) 'x == y': bool | ||
576 | [120; 121) 'y': bool | ||
577 | [131; 132) 't': bool | ||
578 | [135; 136) 'x': bool | ||
579 | [135; 141) 'x != y': bool | ||
580 | [140; 141) 'y': bool | ||
581 | [151; 162) 'minus_forty': isize | ||
582 | [172; 180) '-40isize': isize | ||
583 | [173; 180) '40isize': isize | ||
584 | [190; 191) 'h': bool | ||
585 | [194; 205) 'minus_forty': isize | ||
586 | [194; 216) 'minus_...ONST_2': bool | ||
587 | [209; 216) 'CONST_2': isize | ||
588 | [226; 227) 'c': i32 | ||
589 | [230; 231) 'f': fn f(bool) -> i32 | ||
590 | [230; 239) 'f(z || y)': i32 | ||
591 | [230; 243) 'f(z || y) + 5': i32 | ||
592 | [232; 233) 'z': bool | ||
593 | [232; 238) 'z || y': bool | ||
594 | [237; 238) 'y': bool | ||
595 | [242; 243) '5': i32 | ||
596 | [253; 254) 'd': {unknown} | ||
597 | [257; 258) 'b': {unknown} | ||
598 | [268; 269) 'g': () | ||
599 | [272; 283) 'minus_forty': isize | ||
600 | [272; 288) 'minus_...y ^= i': () | ||
601 | [287; 288) 'i': isize | ||
602 | [298; 301) 'ten': usize | ||
603 | [311; 313) '10': usize | ||
604 | [323; 336) 'ten_is_eleven': bool | ||
605 | [339; 342) 'ten': usize | ||
606 | [339; 354) 'ten == some_num': bool | ||
607 | [346; 354) 'some_num': usize | ||
608 | [361; 364) 'ten': usize | ||
609 | [361; 368) 'ten < 3': bool | ||
610 | [367; 368) '3': usize | ||
611 | "### | ||
612 | ); | ||
613 | } | ||
614 | |||
615 | #[test] | ||
616 | fn infer_field_autoderef() { | ||
617 | assert_snapshot!( | ||
618 | infer(r#" | ||
619 | struct A { | ||
620 | b: B, | ||
621 | } | ||
622 | struct B; | ||
623 | |||
624 | fn test1(a: A) { | ||
625 | let a1 = a; | ||
626 | a1.b; | ||
627 | let a2 = &a; | ||
628 | a2.b; | ||
629 | let a3 = &mut a; | ||
630 | a3.b; | ||
631 | let a4 = &&&&&&&a; | ||
632 | a4.b; | ||
633 | let a5 = &mut &&mut &&mut a; | ||
634 | a5.b; | ||
635 | } | ||
636 | |||
637 | fn test2(a1: *const A, a2: *mut A) { | ||
638 | a1.b; | ||
639 | a2.b; | ||
640 | } | ||
641 | "#), | ||
642 | @r###" | ||
643 | [44; 45) 'a': A | ||
644 | [50; 213) '{ ...5.b; }': () | ||
645 | [60; 62) 'a1': A | ||
646 | [65; 66) 'a': A | ||
647 | [72; 74) 'a1': A | ||
648 | [72; 76) 'a1.b': B | ||
649 | [86; 88) 'a2': &A | ||
650 | [91; 93) '&a': &A | ||
651 | [92; 93) 'a': A | ||
652 | [99; 101) 'a2': &A | ||
653 | [99; 103) 'a2.b': B | ||
654 | [113; 115) 'a3': &mut A | ||
655 | [118; 124) '&mut a': &mut A | ||
656 | [123; 124) 'a': A | ||
657 | [130; 132) 'a3': &mut A | ||
658 | [130; 134) 'a3.b': B | ||
659 | [144; 146) 'a4': &&&&&&&A | ||
660 | [149; 157) '&&&&&&&a': &&&&&&&A | ||
661 | [150; 157) '&&&&&&a': &&&&&&A | ||
662 | [151; 157) '&&&&&a': &&&&&A | ||
663 | [152; 157) '&&&&a': &&&&A | ||
664 | [153; 157) '&&&a': &&&A | ||
665 | [154; 157) '&&a': &&A | ||
666 | [155; 157) '&a': &A | ||
667 | [156; 157) 'a': A | ||
668 | [163; 165) 'a4': &&&&&&&A | ||
669 | [163; 167) 'a4.b': B | ||
670 | [177; 179) 'a5': &mut &&mut &&mut A | ||
671 | [182; 200) '&mut &...&mut a': &mut &&mut &&mut A | ||
672 | [187; 200) '&&mut &&mut a': &&mut &&mut A | ||
673 | [188; 200) '&mut &&mut a': &mut &&mut A | ||
674 | [193; 200) '&&mut a': &&mut A | ||
675 | [194; 200) '&mut a': &mut A | ||
676 | [199; 200) 'a': A | ||
677 | [206; 208) 'a5': &mut &&mut &&mut A | ||
678 | [206; 210) 'a5.b': B | ||
679 | [224; 226) 'a1': *const A | ||
680 | [238; 240) 'a2': *mut A | ||
681 | [250; 273) '{ ...2.b; }': () | ||
682 | [256; 258) 'a1': *const A | ||
683 | [256; 260) 'a1.b': B | ||
684 | [266; 268) 'a2': *mut A | ||
685 | [266; 270) 'a2.b': B | ||
686 | "### | ||
687 | ); | ||
688 | } | ||
689 | |||
690 | #[test] | ||
691 | fn infer_argument_autoderef() { | ||
692 | assert_snapshot!( | ||
693 | infer(r#" | ||
694 | #[lang = "deref"] | ||
695 | pub trait Deref { | ||
696 | type Target; | ||
697 | fn deref(&self) -> &Self::Target; | ||
698 | } | ||
699 | |||
700 | struct A<T>(T); | ||
701 | |||
702 | impl<T> A<T> { | ||
703 | fn foo(&self) -> &T { | ||
704 | &self.0 | ||
705 | } | ||
706 | } | ||
707 | |||
708 | struct B<T>(T); | ||
709 | |||
710 | impl<T> Deref for B<T> { | ||
711 | type Target = T; | ||
712 | fn deref(&self) -> &Self::Target { | ||
713 | &self.0 | ||
714 | } | ||
715 | } | ||
716 | |||
717 | fn test() { | ||
718 | let t = A::foo(&&B(B(A(42)))); | ||
719 | } | ||
720 | "#), | ||
721 | @r###" | ||
722 | [68; 72) 'self': &Self | ||
723 | [139; 143) 'self': &A<T> | ||
724 | [151; 174) '{ ... }': &T | ||
725 | [161; 168) '&self.0': &T | ||
726 | [162; 166) 'self': &A<T> | ||
727 | [162; 168) 'self.0': T | ||
728 | [255; 259) 'self': &B<T> | ||
729 | [278; 301) '{ ... }': &T | ||
730 | [288; 295) '&self.0': &T | ||
731 | [289; 293) 'self': &B<T> | ||
732 | [289; 295) 'self.0': T | ||
733 | [315; 353) '{ ...))); }': () | ||
734 | [325; 326) 't': &i32 | ||
735 | [329; 335) 'A::foo': fn foo<i32>(&A<T>) -> &T | ||
736 | [329; 350) 'A::foo...42))))': &i32 | ||
737 | [336; 349) '&&B(B(A(42)))': &&B<B<A<i32>>> | ||
738 | [337; 349) '&B(B(A(42)))': &B<B<A<i32>>> | ||
739 | [338; 339) 'B': B<B<A<i32>>>(T) -> B<T> | ||
740 | [338; 349) 'B(B(A(42)))': B<B<A<i32>>> | ||
741 | [340; 341) 'B': B<A<i32>>(T) -> B<T> | ||
742 | [340; 348) 'B(A(42))': B<A<i32>> | ||
743 | [342; 343) 'A': A<i32>(T) -> A<T> | ||
744 | [342; 347) 'A(42)': A<i32> | ||
745 | [344; 346) '42': i32 | ||
746 | "### | ||
747 | ); | ||
748 | } | ||
749 | |||
750 | #[test] | ||
751 | fn infer_method_argument_autoderef() { | ||
752 | assert_snapshot!( | ||
753 | infer(r#" | ||
754 | #[lang = "deref"] | ||
755 | pub trait Deref { | ||
756 | type Target; | ||
757 | fn deref(&self) -> &Self::Target; | ||
758 | } | ||
759 | |||
760 | struct A<T>(*mut T); | ||
761 | |||
762 | impl<T> A<T> { | ||
763 | fn foo(&self, x: &A<T>) -> &T { | ||
764 | &*x.0 | ||
765 | } | ||
766 | } | ||
767 | |||
768 | struct B<T>(T); | ||
769 | |||
770 | impl<T> Deref for B<T> { | ||
771 | type Target = T; | ||
772 | fn deref(&self) -> &Self::Target { | ||
773 | &self.0 | ||
774 | } | ||
775 | } | ||
776 | |||
777 | fn test(a: A<i32>) { | ||
778 | let t = A(0 as *mut _).foo(&&B(B(a))); | ||
779 | } | ||
780 | "#), | ||
781 | @r###" | ||
782 | [68; 72) 'self': &Self | ||
783 | [144; 148) 'self': &A<T> | ||
784 | [150; 151) 'x': &A<T> | ||
785 | [166; 187) '{ ... }': &T | ||
786 | [176; 181) '&*x.0': &T | ||
787 | [177; 181) '*x.0': T | ||
788 | [178; 179) 'x': &A<T> | ||
789 | [178; 181) 'x.0': *mut T | ||
790 | [268; 272) 'self': &B<T> | ||
791 | [291; 314) '{ ... }': &T | ||
792 | [301; 308) '&self.0': &T | ||
793 | [302; 306) 'self': &B<T> | ||
794 | [302; 308) 'self.0': T | ||
795 | [326; 327) 'a': A<i32> | ||
796 | [337; 383) '{ ...))); }': () | ||
797 | [347; 348) 't': &i32 | ||
798 | [351; 352) 'A': A<i32>(*mut T) -> A<T> | ||
799 | [351; 365) 'A(0 as *mut _)': A<i32> | ||
800 | [351; 380) 'A(0 as...B(a)))': &i32 | ||
801 | [353; 354) '0': i32 | ||
802 | [353; 364) '0 as *mut _': *mut i32 | ||
803 | [370; 379) '&&B(B(a))': &&B<B<A<i32>>> | ||
804 | [371; 379) '&B(B(a))': &B<B<A<i32>>> | ||
805 | [372; 373) 'B': B<B<A<i32>>>(T) -> B<T> | ||
806 | [372; 379) 'B(B(a))': B<B<A<i32>>> | ||
807 | [374; 375) 'B': B<A<i32>>(T) -> B<T> | ||
808 | [374; 378) 'B(a)': B<A<i32>> | ||
809 | [376; 377) 'a': A<i32> | ||
810 | "### | ||
811 | ); | ||
812 | } | ||
813 | |||
814 | #[test] | ||
815 | fn infer_in_elseif() { | ||
816 | assert_snapshot!( | ||
817 | infer(r#" | ||
818 | struct Foo { field: i32 } | ||
819 | fn main(foo: Foo) { | ||
820 | if true { | ||
821 | |||
822 | } else if false { | ||
823 | foo.field | ||
824 | } | ||
825 | } | ||
826 | "#), | ||
827 | @r###" | ||
828 | [35; 38) 'foo': Foo | ||
829 | [45; 109) '{ ... } }': () | ||
830 | [51; 107) 'if tru... }': () | ||
831 | [54; 58) 'true': bool | ||
832 | [59; 67) '{ }': () | ||
833 | [73; 107) 'if fal... }': () | ||
834 | [76; 81) 'false': bool | ||
835 | [82; 107) '{ ... }': i32 | ||
836 | [92; 95) 'foo': Foo | ||
837 | [92; 101) 'foo.field': i32 | ||
838 | "### | ||
839 | ) | ||
840 | } | ||
841 | |||
842 | #[test] | ||
843 | fn infer_if_match_with_return() { | ||
844 | assert_snapshot!( | ||
845 | infer(r#" | ||
846 | fn foo() { | ||
847 | let _x1 = if true { | ||
848 | 1 | ||
849 | } else { | ||
850 | return; | ||
851 | }; | ||
852 | let _x2 = if true { | ||
853 | 2 | ||
854 | } else { | ||
855 | return | ||
856 | }; | ||
857 | let _x3 = match true { | ||
858 | true => 3, | ||
859 | _ => { | ||
860 | return; | ||
861 | } | ||
862 | }; | ||
863 | let _x4 = match true { | ||
864 | true => 4, | ||
865 | _ => return | ||
866 | }; | ||
867 | }"#), | ||
868 | @r###" | ||
869 | [10; 323) '{ ... }; }': () | ||
870 | [20; 23) '_x1': i32 | ||
871 | [26; 80) 'if tru... }': i32 | ||
872 | [29; 33) 'true': bool | ||
873 | [34; 51) '{ ... }': i32 | ||
874 | [44; 45) '1': i32 | ||
875 | [57; 80) '{ ... }': ! | ||
876 | [67; 73) 'return': ! | ||
877 | [90; 93) '_x2': i32 | ||
878 | [96; 149) 'if tru... }': i32 | ||
879 | [99; 103) 'true': bool | ||
880 | [104; 121) '{ ... }': i32 | ||
881 | [114; 115) '2': i32 | ||
882 | [127; 149) '{ ... }': ! | ||
883 | [137; 143) 'return': ! | ||
884 | [159; 162) '_x3': i32 | ||
885 | [165; 247) 'match ... }': i32 | ||
886 | [171; 175) 'true': bool | ||
887 | [186; 190) 'true': bool | ||
888 | [194; 195) '3': i32 | ||
889 | [205; 206) '_': bool | ||
890 | [210; 241) '{ ... }': ! | ||
891 | [224; 230) 'return': ! | ||
892 | [257; 260) '_x4': i32 | ||
893 | [263; 320) 'match ... }': i32 | ||
894 | [269; 273) 'true': bool | ||
895 | [284; 288) 'true': bool | ||
896 | [292; 293) '4': i32 | ||
897 | [303; 304) '_': bool | ||
898 | [308; 314) 'return': ! | ||
899 | "### | ||
900 | ) | ||
901 | } | ||
902 | |||
903 | #[test] | ||
904 | fn infer_inherent_method() { | ||
905 | assert_snapshot!( | ||
906 | infer(r#" | ||
907 | struct A; | ||
908 | |||
909 | impl A { | ||
910 | fn foo(self, x: u32) -> i32 {} | ||
911 | } | ||
912 | |||
913 | mod b { | ||
914 | impl super::A { | ||
915 | fn bar(&self, x: u64) -> i64 {} | ||
916 | } | ||
917 | } | ||
918 | |||
919 | fn test(a: A) { | ||
920 | a.foo(1); | ||
921 | (&a).bar(1); | ||
922 | a.bar(1); | ||
923 | } | ||
924 | "#), | ||
925 | @r###" | ||
926 | [32; 36) 'self': A | ||
927 | [38; 39) 'x': u32 | ||
928 | [53; 55) '{}': () | ||
929 | [103; 107) 'self': &A | ||
930 | [109; 110) 'x': u64 | ||
931 | [124; 126) '{}': () | ||
932 | [144; 145) 'a': A | ||
933 | [150; 198) '{ ...(1); }': () | ||
934 | [156; 157) 'a': A | ||
935 | [156; 164) 'a.foo(1)': i32 | ||
936 | [162; 163) '1': u32 | ||
937 | [170; 181) '(&a).bar(1)': i64 | ||
938 | [171; 173) '&a': &A | ||
939 | [172; 173) 'a': A | ||
940 | [179; 180) '1': u64 | ||
941 | [187; 188) 'a': A | ||
942 | [187; 195) 'a.bar(1)': i64 | ||
943 | [193; 194) '1': u64 | ||
944 | "### | ||
945 | ); | ||
946 | } | ||
947 | |||
948 | #[test] | ||
949 | fn infer_inherent_method_str() { | ||
950 | assert_snapshot!( | ||
951 | infer(r#" | ||
952 | #[lang = "str"] | ||
953 | impl str { | ||
954 | fn foo(&self) -> i32 {} | ||
955 | } | ||
956 | |||
957 | fn test() { | ||
958 | "foo".foo(); | ||
959 | } | ||
960 | "#), | ||
961 | @r###" | ||
962 | [40; 44) 'self': &str | ||
963 | [53; 55) '{}': () | ||
964 | [69; 89) '{ ...o(); }': () | ||
965 | [75; 80) '"foo"': &str | ||
966 | [75; 86) '"foo".foo()': i32 | ||
967 | "### | ||
968 | ); | ||
969 | } | ||
970 | |||
971 | #[test] | ||
972 | fn infer_tuple() { | ||
973 | assert_snapshot!( | ||
974 | infer(r#" | ||
975 | fn test(x: &str, y: isize) { | ||
976 | let a: (u32, &str) = (1, "a"); | ||
977 | let b = (a, x); | ||
978 | let c = (y, x); | ||
979 | let d = (c, x); | ||
980 | let e = (1, "e"); | ||
981 | let f = (e, "d"); | ||
982 | } | ||
983 | "#), | ||
984 | @r###" | ||
985 | [9; 10) 'x': &str | ||
986 | [18; 19) 'y': isize | ||
987 | [28; 170) '{ ...d"); }': () | ||
988 | [38; 39) 'a': (u32, &str) | ||
989 | [55; 63) '(1, "a")': (u32, &str) | ||
990 | [56; 57) '1': u32 | ||
991 | [59; 62) '"a"': &str | ||
992 | [73; 74) 'b': ((u32, &str), &str) | ||
993 | [77; 83) '(a, x)': ((u32, &str), &str) | ||
994 | [78; 79) 'a': (u32, &str) | ||
995 | [81; 82) 'x': &str | ||
996 | [93; 94) 'c': (isize, &str) | ||
997 | [97; 103) '(y, x)': (isize, &str) | ||
998 | [98; 99) 'y': isize | ||
999 | [101; 102) 'x': &str | ||
1000 | [113; 114) 'd': ((isize, &str), &str) | ||
1001 | [117; 123) '(c, x)': ((isize, &str), &str) | ||
1002 | [118; 119) 'c': (isize, &str) | ||
1003 | [121; 122) 'x': &str | ||
1004 | [133; 134) 'e': (i32, &str) | ||
1005 | [137; 145) '(1, "e")': (i32, &str) | ||
1006 | [138; 139) '1': i32 | ||
1007 | [141; 144) '"e"': &str | ||
1008 | [155; 156) 'f': ((i32, &str), &str) | ||
1009 | [159; 167) '(e, "d")': ((i32, &str), &str) | ||
1010 | [160; 161) 'e': (i32, &str) | ||
1011 | [163; 166) '"d"': &str | ||
1012 | "### | ||
1013 | ); | ||
1014 | } | ||
1015 | |||
1016 | #[test] | ||
1017 | fn infer_array() { | ||
1018 | assert_snapshot!( | ||
1019 | infer(r#" | ||
1020 | fn test(x: &str, y: isize) { | ||
1021 | let a = [x]; | ||
1022 | let b = [a, a]; | ||
1023 | let c = [b, b]; | ||
1024 | |||
1025 | let d = [y, 1, 2, 3]; | ||
1026 | let d = [1, y, 2, 3]; | ||
1027 | let e = [y]; | ||
1028 | let f = [d, d]; | ||
1029 | let g = [e, e]; | ||
1030 | |||
1031 | let h = [1, 2]; | ||
1032 | let i = ["a", "b"]; | ||
1033 | |||
1034 | let b = [a, ["b"]]; | ||
1035 | let x: [u8; 0] = []; | ||
1036 | } | ||
1037 | "#), | ||
1038 | @r###" | ||
1039 | [9; 10) 'x': &str | ||
1040 | [18; 19) 'y': isize | ||
1041 | [28; 293) '{ ... []; }': () | ||
1042 | [38; 39) 'a': [&str;_] | ||
1043 | [42; 45) '[x]': [&str;_] | ||
1044 | [43; 44) 'x': &str | ||
1045 | [55; 56) 'b': [[&str;_];_] | ||
1046 | [59; 65) '[a, a]': [[&str;_];_] | ||
1047 | [60; 61) 'a': [&str;_] | ||
1048 | [63; 64) 'a': [&str;_] | ||
1049 | [75; 76) 'c': [[[&str;_];_];_] | ||
1050 | [79; 85) '[b, b]': [[[&str;_];_];_] | ||
1051 | [80; 81) 'b': [[&str;_];_] | ||
1052 | [83; 84) 'b': [[&str;_];_] | ||
1053 | [96; 97) 'd': [isize;_] | ||
1054 | [100; 112) '[y, 1, 2, 3]': [isize;_] | ||
1055 | [101; 102) 'y': isize | ||
1056 | [104; 105) '1': isize | ||
1057 | [107; 108) '2': isize | ||
1058 | [110; 111) '3': isize | ||
1059 | [122; 123) 'd': [isize;_] | ||
1060 | [126; 138) '[1, y, 2, 3]': [isize;_] | ||
1061 | [127; 128) '1': isize | ||
1062 | [130; 131) 'y': isize | ||
1063 | [133; 134) '2': isize | ||
1064 | [136; 137) '3': isize | ||
1065 | [148; 149) 'e': [isize;_] | ||
1066 | [152; 155) '[y]': [isize;_] | ||
1067 | [153; 154) 'y': isize | ||
1068 | [165; 166) 'f': [[isize;_];_] | ||
1069 | [169; 175) '[d, d]': [[isize;_];_] | ||
1070 | [170; 171) 'd': [isize;_] | ||
1071 | [173; 174) 'd': [isize;_] | ||
1072 | [185; 186) 'g': [[isize;_];_] | ||
1073 | [189; 195) '[e, e]': [[isize;_];_] | ||
1074 | [190; 191) 'e': [isize;_] | ||
1075 | [193; 194) 'e': [isize;_] | ||
1076 | [206; 207) 'h': [i32;_] | ||
1077 | [210; 216) '[1, 2]': [i32;_] | ||
1078 | [211; 212) '1': i32 | ||
1079 | [214; 215) '2': i32 | ||
1080 | [226; 227) 'i': [&str;_] | ||
1081 | [230; 240) '["a", "b"]': [&str;_] | ||
1082 | [231; 234) '"a"': &str | ||
1083 | [236; 239) '"b"': &str | ||
1084 | [251; 252) 'b': [[&str;_];_] | ||
1085 | [255; 265) '[a, ["b"]]': [[&str;_];_] | ||
1086 | [256; 257) 'a': [&str;_] | ||
1087 | [259; 264) '["b"]': [&str;_] | ||
1088 | [260; 263) '"b"': &str | ||
1089 | [275; 276) 'x': [u8;_] | ||
1090 | [288; 290) '[]': [u8;_] | ||
1091 | "### | ||
1092 | ); | ||
1093 | } | ||
1094 | |||
1095 | #[test] | ||
1096 | fn infer_struct_generics() { | ||
1097 | assert_snapshot!( | ||
1098 | infer(r#" | ||
1099 | struct A<T> { | ||
1100 | x: T, | ||
1101 | } | ||
1102 | |||
1103 | fn test(a1: A<u32>, i: i32) { | ||
1104 | a1.x; | ||
1105 | let a2 = A { x: i }; | ||
1106 | a2.x; | ||
1107 | let a3 = A::<i128> { x: 1 }; | ||
1108 | a3.x; | ||
1109 | } | ||
1110 | "#), | ||
1111 | @r###" | ||
1112 | [36; 38) 'a1': A<u32> | ||
1113 | [48; 49) 'i': i32 | ||
1114 | [56; 147) '{ ...3.x; }': () | ||
1115 | [62; 64) 'a1': A<u32> | ||
1116 | [62; 66) 'a1.x': u32 | ||
1117 | [76; 78) 'a2': A<i32> | ||
1118 | [81; 91) 'A { x: i }': A<i32> | ||
1119 | [88; 89) 'i': i32 | ||
1120 | [97; 99) 'a2': A<i32> | ||
1121 | [97; 101) 'a2.x': i32 | ||
1122 | [111; 113) 'a3': A<i128> | ||
1123 | [116; 134) 'A::<i1...x: 1 }': A<i128> | ||
1124 | [131; 132) '1': i128 | ||
1125 | [140; 142) 'a3': A<i128> | ||
1126 | [140; 144) 'a3.x': i128 | ||
1127 | "### | ||
1128 | ); | ||
1129 | } | ||
1130 | |||
1131 | #[test] | ||
1132 | fn infer_tuple_struct_generics() { | ||
1133 | assert_snapshot!( | ||
1134 | infer(r#" | ||
1135 | struct A<T>(T); | ||
1136 | enum Option<T> { Some(T), None } | ||
1137 | use Option::*; | ||
1138 | |||
1139 | fn test() { | ||
1140 | A(42); | ||
1141 | A(42u128); | ||
1142 | Some("x"); | ||
1143 | Option::Some("x"); | ||
1144 | None; | ||
1145 | let x: Option<i64> = None; | ||
1146 | } | ||
1147 | "#), | ||
1148 | @r###" | ||
1149 | [76; 184) '{ ...one; }': () | ||
1150 | [82; 83) 'A': A<i32>(T) -> A<T> | ||
1151 | [82; 87) 'A(42)': A<i32> | ||
1152 | [84; 86) '42': i32 | ||
1153 | [93; 94) 'A': A<u128>(T) -> A<T> | ||
1154 | [93; 102) 'A(42u128)': A<u128> | ||
1155 | [95; 101) '42u128': u128 | ||
1156 | [108; 112) 'Some': Some<&str>(T) -> Option<T> | ||
1157 | [108; 117) 'Some("x")': Option<&str> | ||
1158 | [113; 116) '"x"': &str | ||
1159 | [123; 135) 'Option::Some': Some<&str>(T) -> Option<T> | ||
1160 | [123; 140) 'Option...e("x")': Option<&str> | ||
1161 | [136; 139) '"x"': &str | ||
1162 | [146; 150) 'None': Option<{unknown}> | ||
1163 | [160; 161) 'x': Option<i64> | ||
1164 | [177; 181) 'None': Option<i64> | ||
1165 | "### | ||
1166 | ); | ||
1167 | } | ||
1168 | |||
1169 | #[test] | ||
1170 | fn infer_function_generics() { | ||
1171 | assert_snapshot!( | ||
1172 | infer(r#" | ||
1173 | fn id<T>(t: T) -> T { t } | ||
1174 | |||
1175 | fn test() { | ||
1176 | id(1u32); | ||
1177 | id::<i128>(1); | ||
1178 | let x: u64 = id(1); | ||
1179 | } | ||
1180 | "#), | ||
1181 | @r###" | ||
1182 | [10; 11) 't': T | ||
1183 | [21; 26) '{ t }': T | ||
1184 | [23; 24) 't': T | ||
1185 | [38; 98) '{ ...(1); }': () | ||
1186 | [44; 46) 'id': fn id<u32>(T) -> T | ||
1187 | [44; 52) 'id(1u32)': u32 | ||
1188 | [47; 51) '1u32': u32 | ||
1189 | [58; 68) 'id::<i128>': fn id<i128>(T) -> T | ||
1190 | [58; 71) 'id::<i128>(1)': i128 | ||
1191 | [69; 70) '1': i128 | ||
1192 | [81; 82) 'x': u64 | ||
1193 | [90; 92) 'id': fn id<u64>(T) -> T | ||
1194 | [90; 95) 'id(1)': u64 | ||
1195 | [93; 94) '1': u64 | ||
1196 | "### | ||
1197 | ); | ||
1198 | } | ||
1199 | |||
1200 | #[test] | ||
1201 | fn infer_impl_generics() { | ||
1202 | assert_snapshot!( | ||
1203 | infer(r#" | ||
1204 | struct A<T1, T2> { | ||
1205 | x: T1, | ||
1206 | y: T2, | ||
1207 | } | ||
1208 | impl<Y, X> A<X, Y> { | ||
1209 | fn x(self) -> X { | ||
1210 | self.x | ||
1211 | } | ||
1212 | fn y(self) -> Y { | ||
1213 | self.y | ||
1214 | } | ||
1215 | fn z<T>(self, t: T) -> (X, Y, T) { | ||
1216 | (self.x, self.y, t) | ||
1217 | } | ||
1218 | } | ||
1219 | |||
1220 | fn test() -> i128 { | ||
1221 | let a = A { x: 1u64, y: 1i64 }; | ||
1222 | a.x(); | ||
1223 | a.y(); | ||
1224 | a.z(1i128); | ||
1225 | a.z::<u128>(1); | ||
1226 | } | ||
1227 | "#), | ||
1228 | @r###" | ||
1229 | [74; 78) 'self': A<X, Y> | ||
1230 | [85; 107) '{ ... }': X | ||
1231 | [95; 99) 'self': A<X, Y> | ||
1232 | [95; 101) 'self.x': X | ||
1233 | [117; 121) 'self': A<X, Y> | ||
1234 | [128; 150) '{ ... }': Y | ||
1235 | [138; 142) 'self': A<X, Y> | ||
1236 | [138; 144) 'self.y': Y | ||
1237 | [163; 167) 'self': A<X, Y> | ||
1238 | [169; 170) 't': T | ||
1239 | [188; 223) '{ ... }': (X, Y, T) | ||
1240 | [198; 217) '(self.....y, t)': (X, Y, T) | ||
1241 | [199; 203) 'self': A<X, Y> | ||
1242 | [199; 205) 'self.x': X | ||
1243 | [207; 211) 'self': A<X, Y> | ||
1244 | [207; 213) 'self.y': Y | ||
1245 | [215; 216) 't': T | ||
1246 | [245; 342) '{ ...(1); }': () | ||
1247 | [255; 256) 'a': A<u64, i64> | ||
1248 | [259; 281) 'A { x:...1i64 }': A<u64, i64> | ||
1249 | [266; 270) '1u64': u64 | ||
1250 | [275; 279) '1i64': i64 | ||
1251 | [287; 288) 'a': A<u64, i64> | ||
1252 | [287; 292) 'a.x()': u64 | ||
1253 | [298; 299) 'a': A<u64, i64> | ||
1254 | [298; 303) 'a.y()': i64 | ||
1255 | [309; 310) 'a': A<u64, i64> | ||
1256 | [309; 319) 'a.z(1i128)': (u64, i64, i128) | ||
1257 | [313; 318) '1i128': i128 | ||
1258 | [325; 326) 'a': A<u64, i64> | ||
1259 | [325; 339) 'a.z::<u128>(1)': (u64, i64, u128) | ||
1260 | [337; 338) '1': u128 | ||
1261 | "### | ||
1262 | ); | ||
1263 | } | ||
1264 | |||
1265 | #[test] | ||
1266 | fn infer_impl_generics_with_autoderef() { | ||
1267 | assert_snapshot!( | ||
1268 | infer(r#" | ||
1269 | enum Option<T> { | ||
1270 | Some(T), | ||
1271 | None, | ||
1272 | } | ||
1273 | impl<T> Option<T> { | ||
1274 | fn as_ref(&self) -> Option<&T> {} | ||
1275 | } | ||
1276 | fn test(o: Option<u32>) { | ||
1277 | (&o).as_ref(); | ||
1278 | o.as_ref(); | ||
1279 | } | ||
1280 | "#), | ||
1281 | @r###" | ||
1282 | [78; 82) 'self': &Option<T> | ||
1283 | [98; 100) '{}': () | ||
1284 | [111; 112) 'o': Option<u32> | ||
1285 | [127; 165) '{ ...f(); }': () | ||
1286 | [133; 146) '(&o).as_ref()': Option<&u32> | ||
1287 | [134; 136) '&o': &Option<u32> | ||
1288 | [135; 136) 'o': Option<u32> | ||
1289 | [152; 153) 'o': Option<u32> | ||
1290 | [152; 162) 'o.as_ref()': Option<&u32> | ||
1291 | "### | ||
1292 | ); | ||
1293 | } | ||
1294 | |||
1295 | #[test] | ||
1296 | fn infer_generic_chain() { | ||
1297 | assert_snapshot!( | ||
1298 | infer(r#" | ||
1299 | struct A<T> { | ||
1300 | x: T, | ||
1301 | } | ||
1302 | impl<T2> A<T2> { | ||
1303 | fn x(self) -> T2 { | ||
1304 | self.x | ||
1305 | } | ||
1306 | } | ||
1307 | fn id<T>(t: T) -> T { t } | ||
1308 | |||
1309 | fn test() -> i128 { | ||
1310 | let x = 1; | ||
1311 | let y = id(x); | ||
1312 | let a = A { x: id(y) }; | ||
1313 | let z = id(a.x); | ||
1314 | let b = A { x: z }; | ||
1315 | b.x() | ||
1316 | } | ||
1317 | "#), | ||
1318 | @r###" | ||
1319 | [53; 57) 'self': A<T2> | ||
1320 | [65; 87) '{ ... }': T2 | ||
1321 | [75; 79) 'self': A<T2> | ||
1322 | [75; 81) 'self.x': T2 | ||
1323 | [99; 100) 't': T | ||
1324 | [110; 115) '{ t }': T | ||
1325 | [112; 113) 't': T | ||
1326 | [135; 261) '{ ....x() }': i128 | ||
1327 | [146; 147) 'x': i128 | ||
1328 | [150; 151) '1': i128 | ||
1329 | [162; 163) 'y': i128 | ||
1330 | [166; 168) 'id': fn id<i128>(T) -> T | ||
1331 | [166; 171) 'id(x)': i128 | ||
1332 | [169; 170) 'x': i128 | ||
1333 | [182; 183) 'a': A<i128> | ||
1334 | [186; 200) 'A { x: id(y) }': A<i128> | ||
1335 | [193; 195) 'id': fn id<i128>(T) -> T | ||
1336 | [193; 198) 'id(y)': i128 | ||
1337 | [196; 197) 'y': i128 | ||
1338 | [211; 212) 'z': i128 | ||
1339 | [215; 217) 'id': fn id<i128>(T) -> T | ||
1340 | [215; 222) 'id(a.x)': i128 | ||
1341 | [218; 219) 'a': A<i128> | ||
1342 | [218; 221) 'a.x': i128 | ||
1343 | [233; 234) 'b': A<i128> | ||
1344 | [237; 247) 'A { x: z }': A<i128> | ||
1345 | [244; 245) 'z': i128 | ||
1346 | [254; 255) 'b': A<i128> | ||
1347 | [254; 259) 'b.x()': i128 | ||
1348 | "### | ||
1349 | ); | ||
1350 | } | ||
1351 | |||
1352 | #[test] | ||
1353 | fn infer_associated_const() { | ||
1354 | assert_snapshot!( | ||
1355 | infer(r#" | ||
1356 | struct Struct; | ||
1357 | |||
1358 | impl Struct { | ||
1359 | const FOO: u32 = 1; | ||
1360 | } | ||
1361 | |||
1362 | enum Enum {} | ||
1363 | |||
1364 | impl Enum { | ||
1365 | const BAR: u32 = 2; | ||
1366 | } | ||
1367 | |||
1368 | trait Trait { | ||
1369 | const ID: u32; | ||
1370 | } | ||
1371 | |||
1372 | struct TraitTest; | ||
1373 | |||
1374 | impl Trait for TraitTest { | ||
1375 | const ID: u32 = 5; | ||
1376 | } | ||
1377 | |||
1378 | fn test() { | ||
1379 | let x = Struct::FOO; | ||
1380 | let y = Enum::BAR; | ||
1381 | let z = TraitTest::ID; | ||
1382 | } | ||
1383 | "#), | ||
1384 | @r###" | ||
1385 | [52; 53) '1': u32 | ||
1386 | [105; 106) '2': u32 | ||
1387 | [213; 214) '5': u32 | ||
1388 | [229; 307) '{ ...:ID; }': () | ||
1389 | [239; 240) 'x': u32 | ||
1390 | [243; 254) 'Struct::FOO': u32 | ||
1391 | [264; 265) 'y': u32 | ||
1392 | [268; 277) 'Enum::BAR': u32 | ||
1393 | [287; 288) 'z': u32 | ||
1394 | [291; 304) 'TraitTest::ID': u32 | ||
1395 | "### | ||
1396 | ); | ||
1397 | } | ||
1398 | |||
1399 | #[test] | ||
1400 | fn infer_type_alias() { | ||
1401 | assert_snapshot!( | ||
1402 | infer(r#" | ||
1403 | struct A<X, Y> { x: X, y: Y } | ||
1404 | type Foo = A<u32, i128>; | ||
1405 | type Bar<T> = A<T, u128>; | ||
1406 | type Baz<U, V> = A<V, U>; | ||
1407 | fn test(x: Foo, y: Bar<&str>, z: Baz<i8, u8>) { | ||
1408 | x.x; | ||
1409 | x.y; | ||
1410 | y.x; | ||
1411 | y.y; | ||
1412 | z.x; | ||
1413 | z.y; | ||
1414 | } | ||
1415 | "#), | ||
1416 | @r###" | ||
1417 | [116; 117) 'x': A<u32, i128> | ||
1418 | [124; 125) 'y': A<&str, u128> | ||
1419 | [138; 139) 'z': A<u8, i8> | ||
1420 | [154; 211) '{ ...z.y; }': () | ||
1421 | [160; 161) 'x': A<u32, i128> | ||
1422 | [160; 163) 'x.x': u32 | ||
1423 | [169; 170) 'x': A<u32, i128> | ||
1424 | [169; 172) 'x.y': i128 | ||
1425 | [178; 179) 'y': A<&str, u128> | ||
1426 | [178; 181) 'y.x': &str | ||
1427 | [187; 188) 'y': A<&str, u128> | ||
1428 | [187; 190) 'y.y': u128 | ||
1429 | [196; 197) 'z': A<u8, i8> | ||
1430 | [196; 199) 'z.x': u8 | ||
1431 | [205; 206) 'z': A<u8, i8> | ||
1432 | [205; 208) 'z.y': i8 | ||
1433 | "### | ||
1434 | ) | ||
1435 | } | ||
1436 | |||
1437 | #[test] | ||
1438 | fn recursive_type_alias() { | ||
1439 | assert_snapshot!( | ||
1440 | infer(r#" | ||
1441 | struct A<X> {} | ||
1442 | type Foo = Foo; | ||
1443 | type Bar = A<Bar>; | ||
1444 | fn test(x: Foo) {} | ||
1445 | "#), | ||
1446 | @r###" | ||
1447 | [59; 60) 'x': {unknown} | ||
1448 | [67; 69) '{}': () | ||
1449 | "### | ||
1450 | ) | ||
1451 | } | ||
1452 | |||
1453 | #[test] | ||
1454 | fn infer_type_param() { | ||
1455 | assert_snapshot!( | ||
1456 | infer(r#" | ||
1457 | fn id<T>(x: T) -> T { | ||
1458 | x | ||
1459 | } | ||
1460 | |||
1461 | fn clone<T>(x: &T) -> T { | ||
1462 | *x | ||
1463 | } | ||
1464 | |||
1465 | fn test() { | ||
1466 | let y = 10u32; | ||
1467 | id(y); | ||
1468 | let x: bool = clone(z); | ||
1469 | id::<i128>(1); | ||
1470 | } | ||
1471 | "#), | ||
1472 | @r###" | ||
1473 | [10; 11) 'x': T | ||
1474 | [21; 30) '{ x }': T | ||
1475 | [27; 28) 'x': T | ||
1476 | [44; 45) 'x': &T | ||
1477 | [56; 66) '{ *x }': T | ||
1478 | [62; 64) '*x': T | ||
1479 | [63; 64) 'x': &T | ||
1480 | [78; 158) '{ ...(1); }': () | ||
1481 | [88; 89) 'y': u32 | ||
1482 | [92; 97) '10u32': u32 | ||
1483 | [103; 105) 'id': fn id<u32>(T) -> T | ||
1484 | [103; 108) 'id(y)': u32 | ||
1485 | [106; 107) 'y': u32 | ||
1486 | [118; 119) 'x': bool | ||
1487 | [128; 133) 'clone': fn clone<bool>(&T) -> T | ||
1488 | [128; 136) 'clone(z)': bool | ||
1489 | [134; 135) 'z': &bool | ||
1490 | [142; 152) 'id::<i128>': fn id<i128>(T) -> T | ||
1491 | [142; 155) 'id::<i128>(1)': i128 | ||
1492 | [153; 154) '1': i128 | ||
1493 | "### | ||
1494 | ); | ||
1495 | } | ||
1496 | |||
1497 | #[test] | ||
1498 | fn infer_const() { | ||
1499 | assert_snapshot!( | ||
1500 | infer(r#" | ||
1501 | struct Foo; | ||
1502 | impl Foo { const ASSOC_CONST: u32 = 0; } | ||
1503 | const GLOBAL_CONST: u32 = 101; | ||
1504 | fn test() { | ||
1505 | const LOCAL_CONST: u32 = 99; | ||
1506 | let x = LOCAL_CONST; | ||
1507 | let z = GLOBAL_CONST; | ||
1508 | let id = Foo::ASSOC_CONST; | ||
1509 | } | ||
1510 | "#), | ||
1511 | @r###" | ||
1512 | [49; 50) '0': u32 | ||
1513 | [80; 83) '101': u32 | ||
1514 | [95; 213) '{ ...NST; }': () | ||
1515 | [138; 139) 'x': u32 | ||
1516 | [142; 153) 'LOCAL_CONST': u32 | ||
1517 | [163; 164) 'z': u32 | ||
1518 | [167; 179) 'GLOBAL_CONST': u32 | ||
1519 | [189; 191) 'id': u32 | ||
1520 | [194; 210) 'Foo::A..._CONST': u32 | ||
1521 | "### | ||
1522 | ); | ||
1523 | } | ||
1524 | |||
1525 | #[test] | ||
1526 | fn infer_static() { | ||
1527 | assert_snapshot!( | ||
1528 | infer(r#" | ||
1529 | static GLOBAL_STATIC: u32 = 101; | ||
1530 | static mut GLOBAL_STATIC_MUT: u32 = 101; | ||
1531 | fn test() { | ||
1532 | static LOCAL_STATIC: u32 = 99; | ||
1533 | static mut LOCAL_STATIC_MUT: u32 = 99; | ||
1534 | let x = LOCAL_STATIC; | ||
1535 | let y = LOCAL_STATIC_MUT; | ||
1536 | let z = GLOBAL_STATIC; | ||
1537 | let w = GLOBAL_STATIC_MUT; | ||
1538 | } | ||
1539 | "#), | ||
1540 | @r###" | ||
1541 | [29; 32) '101': u32 | ||
1542 | [70; 73) '101': u32 | ||
1543 | [85; 280) '{ ...MUT; }': () | ||
1544 | [173; 174) 'x': u32 | ||
1545 | [177; 189) 'LOCAL_STATIC': u32 | ||
1546 | [199; 200) 'y': u32 | ||
1547 | [203; 219) 'LOCAL_...IC_MUT': u32 | ||
1548 | [229; 230) 'z': u32 | ||
1549 | [233; 246) 'GLOBAL_STATIC': u32 | ||
1550 | [256; 257) 'w': u32 | ||
1551 | [260; 277) 'GLOBAL...IC_MUT': u32 | ||
1552 | "### | ||
1553 | ); | ||
1554 | } | ||
1555 | |||
1556 | #[test] | ||
1557 | fn shadowing_primitive() { | ||
1558 | let t = type_at( | ||
1559 | r#" | ||
1560 | //- /main.rs | ||
1561 | struct i32; | ||
1562 | struct Foo; | ||
1563 | |||
1564 | impl i32 { fn foo(&self) -> Foo { Foo } } | ||
1565 | |||
1566 | fn main() { | ||
1567 | let x: i32 = i32; | ||
1568 | x.foo()<|>; | ||
1569 | }"#, | ||
1570 | ); | ||
1571 | assert_eq!(t, "Foo"); | ||
1572 | } | ||
1573 | |||
1574 | #[test] | ||
1575 | fn not_shadowing_primitive_by_module() { | ||
1576 | let t = type_at( | ||
1577 | r#" | ||
1578 | //- /str.rs | ||
1579 | fn foo() {} | ||
1580 | |||
1581 | //- /main.rs | ||
1582 | mod str; | ||
1583 | fn foo() -> &'static str { "" } | ||
1584 | |||
1585 | fn main() { | ||
1586 | foo()<|>; | ||
1587 | }"#, | ||
1588 | ); | ||
1589 | assert_eq!(t, "&str"); | ||
1590 | } | ||
1591 | |||
1592 | #[test] | ||
1593 | fn not_shadowing_module_by_primitive() { | ||
1594 | let t = type_at( | ||
1595 | r#" | ||
1596 | //- /str.rs | ||
1597 | fn foo() -> u32 {0} | ||
1598 | |||
1599 | //- /main.rs | ||
1600 | mod str; | ||
1601 | fn foo() -> &'static str { "" } | ||
1602 | |||
1603 | fn main() { | ||
1604 | str::foo()<|>; | ||
1605 | }"#, | ||
1606 | ); | ||
1607 | assert_eq!(t, "u32"); | ||
1608 | } | ||
1609 | |||
1610 | #[test] | ||
1611 | fn closure_return() { | ||
1612 | assert_snapshot!( | ||
1613 | infer(r#" | ||
1614 | fn foo() -> u32 { | ||
1615 | let x = || -> usize { return 1; }; | ||
1616 | } | ||
1617 | "#), | ||
1618 | @r###" | ||
1619 | [17; 59) '{ ...; }; }': () | ||
1620 | [27; 28) 'x': || -> usize | ||
1621 | [31; 56) '|| -> ...n 1; }': || -> usize | ||
1622 | [43; 56) '{ return 1; }': ! | ||
1623 | [45; 53) 'return 1': ! | ||
1624 | [52; 53) '1': usize | ||
1625 | "### | ||
1626 | ); | ||
1627 | } | ||
1628 | |||
1629 | #[test] | ||
1630 | fn closure_return_unit() { | ||
1631 | assert_snapshot!( | ||
1632 | infer(r#" | ||
1633 | fn foo() -> u32 { | ||
1634 | let x = || { return; }; | ||
1635 | } | ||
1636 | "#), | ||
1637 | @r###" | ||
1638 | [17; 48) '{ ...; }; }': () | ||
1639 | [27; 28) 'x': || -> () | ||
1640 | [31; 45) '|| { return; }': || -> () | ||
1641 | [34; 45) '{ return; }': ! | ||
1642 | [36; 42) 'return': ! | ||
1643 | "### | ||
1644 | ); | ||
1645 | } | ||
1646 | |||
1647 | #[test] | ||
1648 | fn closure_return_inferred() { | ||
1649 | assert_snapshot!( | ||
1650 | infer(r#" | ||
1651 | fn foo() -> u32 { | ||
1652 | let x = || { "test" }; | ||
1653 | } | ||
1654 | "#), | ||
1655 | @r###" | ||
1656 | [17; 47) '{ ..." }; }': () | ||
1657 | [27; 28) 'x': || -> &str | ||
1658 | [31; 44) '|| { "test" }': || -> &str | ||
1659 | [34; 44) '{ "test" }': &str | ||
1660 | [36; 42) '"test"': &str | ||
1661 | "### | ||
1662 | ); | ||
1663 | } | ||