diff options
Diffstat (limited to 'crates/ra_hir_ty/src/tests/simple.rs')
-rw-r--r-- | crates/ra_hir_ty/src/tests/simple.rs | 2190 |
1 files changed, 0 insertions, 2190 deletions
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs deleted file mode 100644 index 3fd7d5cd4..000000000 --- a/crates/ra_hir_ty/src/tests/simple.rs +++ /dev/null | |||
@@ -1,2190 +0,0 @@ | |||
1 | use expect::expect; | ||
2 | |||
3 | use super::{check_infer, check_types}; | ||
4 | |||
5 | #[test] | ||
6 | fn infer_box() { | ||
7 | check_types( | ||
8 | r#" | ||
9 | //- /main.rs crate:main deps:std | ||
10 | fn test() { | ||
11 | let x = box 1; | ||
12 | let t = (x, box x, box &1, box [1]); | ||
13 | t; | ||
14 | } //^ (Box<i32>, Box<Box<i32>>, Box<&i32>, Box<[i32; _]>) | ||
15 | |||
16 | //- /std.rs crate:std | ||
17 | #[prelude_import] use prelude::*; | ||
18 | mod prelude {} | ||
19 | |||
20 | mod boxed { | ||
21 | #[lang = "owned_box"] | ||
22 | pub struct Box<T: ?Sized> { | ||
23 | inner: *mut T, | ||
24 | } | ||
25 | } | ||
26 | "#, | ||
27 | ); | ||
28 | } | ||
29 | |||
30 | #[test] | ||
31 | fn infer_adt_self() { | ||
32 | check_types( | ||
33 | r#" | ||
34 | enum Nat { Succ(Self), Demo(Nat), Zero } | ||
35 | |||
36 | fn test() { | ||
37 | let foo: Nat = Nat::Zero; | ||
38 | if let Nat::Succ(x) = foo { | ||
39 | x | ||
40 | } //^ Nat | ||
41 | } | ||
42 | "#, | ||
43 | ); | ||
44 | } | ||
45 | |||
46 | #[test] | ||
47 | fn self_in_struct_lit() { | ||
48 | check_infer( | ||
49 | r#" | ||
50 | //- /main.rs | ||
51 | struct S<T> { x: T } | ||
52 | |||
53 | impl S<u32> { | ||
54 | fn foo() { | ||
55 | Self { x: 1 }; | ||
56 | } | ||
57 | } | ||
58 | "#, | ||
59 | expect![[r#" | ||
60 | 49..79 '{ ... }': () | ||
61 | 59..72 'Self { x: 1 }': S<u32> | ||
62 | 69..70 '1': u32 | ||
63 | "#]], | ||
64 | ); | ||
65 | } | ||
66 | |||
67 | #[test] | ||
68 | fn type_alias_in_struct_lit() { | ||
69 | check_infer( | ||
70 | r#" | ||
71 | //- /main.rs | ||
72 | struct S<T> { x: T } | ||
73 | |||
74 | type SS = S<u32>; | ||
75 | |||
76 | fn foo() { | ||
77 | SS { x: 1 }; | ||
78 | } | ||
79 | "#, | ||
80 | expect![[r#" | ||
81 | 50..70 '{ ...1 }; }': () | ||
82 | 56..67 'SS { x: 1 }': S<u32> | ||
83 | 64..65 '1': u32 | ||
84 | "#]], | ||
85 | ); | ||
86 | } | ||
87 | |||
88 | #[test] | ||
89 | fn infer_ranges() { | ||
90 | check_types( | ||
91 | r#" | ||
92 | //- /main.rs crate:main deps:core | ||
93 | fn test() { | ||
94 | let a = ..; | ||
95 | let b = 1..; | ||
96 | let c = ..2u32; | ||
97 | let d = 1..2usize; | ||
98 | let e = ..=10; | ||
99 | let f = 'a'..='z'; | ||
100 | |||
101 | let t = (a, b, c, d, e, f); | ||
102 | t; | ||
103 | } //^ (RangeFull, RangeFrom<i32>, RangeTo<u32>, Range<usize>, RangeToInclusive<i32>, RangeInclusive<char>) | ||
104 | |||
105 | //- /core.rs crate:core | ||
106 | #[prelude_import] use prelude::*; | ||
107 | mod prelude {} | ||
108 | |||
109 | pub mod ops { | ||
110 | pub struct Range<Idx> { | ||
111 | pub start: Idx, | ||
112 | pub end: Idx, | ||
113 | } | ||
114 | pub struct RangeFrom<Idx> { | ||
115 | pub start: Idx, | ||
116 | } | ||
117 | struct RangeFull; | ||
118 | pub struct RangeInclusive<Idx> { | ||
119 | start: Idx, | ||
120 | end: Idx, | ||
121 | is_empty: u8, | ||
122 | } | ||
123 | pub struct RangeTo<Idx> { | ||
124 | pub end: Idx, | ||
125 | } | ||
126 | pub struct RangeToInclusive<Idx> { | ||
127 | pub end: Idx, | ||
128 | } | ||
129 | } | ||
130 | "#, | ||
131 | ); | ||
132 | } | ||
133 | |||
134 | #[test] | ||
135 | fn infer_while_let() { | ||
136 | check_types( | ||
137 | r#" | ||
138 | enum Option<T> { Some(T), None } | ||
139 | |||
140 | fn test() { | ||
141 | let foo: Option<f32> = None; | ||
142 | while let Option::Some(x) = foo { | ||
143 | x | ||
144 | } //^ f32 | ||
145 | } | ||
146 | "#, | ||
147 | ); | ||
148 | } | ||
149 | |||
150 | #[test] | ||
151 | fn infer_basics() { | ||
152 | check_infer( | ||
153 | r#" | ||
154 | fn test(a: u32, b: isize, c: !, d: &str) { | ||
155 | a; | ||
156 | b; | ||
157 | c; | ||
158 | d; | ||
159 | 1usize; | ||
160 | 1isize; | ||
161 | "test"; | ||
162 | 1.0f32; | ||
163 | }"#, | ||
164 | expect![[r#" | ||
165 | 8..9 'a': u32 | ||
166 | 16..17 'b': isize | ||
167 | 26..27 'c': ! | ||
168 | 32..33 'd': &str | ||
169 | 41..120 '{ ...f32; }': () | ||
170 | 47..48 'a': u32 | ||
171 | 54..55 'b': isize | ||
172 | 61..62 'c': ! | ||
173 | 68..69 'd': &str | ||
174 | 75..81 '1usize': usize | ||
175 | 87..93 '1isize': isize | ||
176 | 99..105 '"test"': &str | ||
177 | 111..117 '1.0f32': f32 | ||
178 | "#]], | ||
179 | ); | ||
180 | } | ||
181 | |||
182 | #[test] | ||
183 | fn infer_let() { | ||
184 | check_infer( | ||
185 | r#" | ||
186 | fn test() { | ||
187 | let a = 1isize; | ||
188 | let b: usize = 1; | ||
189 | let c = b; | ||
190 | let d: u32; | ||
191 | let e; | ||
192 | let f: i32 = e; | ||
193 | } | ||
194 | "#, | ||
195 | expect![[r#" | ||
196 | 10..117 '{ ...= e; }': () | ||
197 | 20..21 'a': isize | ||
198 | 24..30 '1isize': isize | ||
199 | 40..41 'b': usize | ||
200 | 51..52 '1': usize | ||
201 | 62..63 'c': usize | ||
202 | 66..67 'b': usize | ||
203 | 77..78 'd': u32 | ||
204 | 93..94 'e': i32 | ||
205 | 104..105 'f': i32 | ||
206 | 113..114 'e': i32 | ||
207 | "#]], | ||
208 | ); | ||
209 | } | ||
210 | |||
211 | #[test] | ||
212 | fn infer_paths() { | ||
213 | check_infer( | ||
214 | r#" | ||
215 | fn a() -> u32 { 1 } | ||
216 | |||
217 | mod b { | ||
218 | fn c() -> u32 { 1 } | ||
219 | } | ||
220 | |||
221 | fn test() { | ||
222 | a(); | ||
223 | b::c(); | ||
224 | } | ||
225 | "#, | ||
226 | expect![[r#" | ||
227 | 14..19 '{ 1 }': u32 | ||
228 | 16..17 '1': u32 | ||
229 | 47..52 '{ 1 }': u32 | ||
230 | 49..50 '1': u32 | ||
231 | 66..90 '{ ...c(); }': () | ||
232 | 72..73 'a': fn a() -> u32 | ||
233 | 72..75 'a()': u32 | ||
234 | 81..85 'b::c': fn c() -> u32 | ||
235 | 81..87 'b::c()': u32 | ||
236 | "#]], | ||
237 | ); | ||
238 | } | ||
239 | |||
240 | #[test] | ||
241 | fn infer_path_type() { | ||
242 | check_infer( | ||
243 | r#" | ||
244 | struct S; | ||
245 | |||
246 | impl S { | ||
247 | fn foo() -> i32 { 1 } | ||
248 | } | ||
249 | |||
250 | fn test() { | ||
251 | S::foo(); | ||
252 | <S>::foo(); | ||
253 | } | ||
254 | "#, | ||
255 | expect![[r#" | ||
256 | 40..45 '{ 1 }': i32 | ||
257 | 42..43 '1': i32 | ||
258 | 59..92 '{ ...o(); }': () | ||
259 | 65..71 'S::foo': fn foo() -> i32 | ||
260 | 65..73 'S::foo()': i32 | ||
261 | 79..87 '<S>::foo': fn foo() -> i32 | ||
262 | 79..89 '<S>::foo()': i32 | ||
263 | "#]], | ||
264 | ); | ||
265 | } | ||
266 | |||
267 | #[test] | ||
268 | fn infer_struct() { | ||
269 | check_infer( | ||
270 | r#" | ||
271 | struct A { | ||
272 | b: B, | ||
273 | c: C, | ||
274 | } | ||
275 | struct B; | ||
276 | struct C(usize); | ||
277 | |||
278 | fn test() { | ||
279 | let c = C(1); | ||
280 | B; | ||
281 | let a: A = A { b: B, c: C(1) }; | ||
282 | a.b; | ||
283 | a.c; | ||
284 | } | ||
285 | "#, | ||
286 | expect![[r#" | ||
287 | 71..153 '{ ...a.c; }': () | ||
288 | 81..82 'c': C | ||
289 | 85..86 'C': C(usize) -> C | ||
290 | 85..89 'C(1)': C | ||
291 | 87..88 '1': usize | ||
292 | 95..96 'B': B | ||
293 | 106..107 'a': A | ||
294 | 113..132 'A { b:...C(1) }': A | ||
295 | 120..121 'B': B | ||
296 | 126..127 'C': C(usize) -> C | ||
297 | 126..130 'C(1)': C | ||
298 | 128..129 '1': usize | ||
299 | 138..139 'a': A | ||
300 | 138..141 'a.b': B | ||
301 | 147..148 'a': A | ||
302 | 147..150 'a.c': C | ||
303 | "#]], | ||
304 | ); | ||
305 | } | ||
306 | |||
307 | #[test] | ||
308 | fn infer_enum() { | ||
309 | check_infer( | ||
310 | r#" | ||
311 | enum E { | ||
312 | V1 { field: u32 }, | ||
313 | V2 | ||
314 | } | ||
315 | fn test() { | ||
316 | E::V1 { field: 1 }; | ||
317 | E::V2; | ||
318 | }"#, | ||
319 | expect![[r#" | ||
320 | 51..89 '{ ...:V2; }': () | ||
321 | 57..75 'E::V1 ...d: 1 }': E | ||
322 | 72..73 '1': u32 | ||
323 | 81..86 'E::V2': E | ||
324 | "#]], | ||
325 | ); | ||
326 | } | ||
327 | |||
328 | #[test] | ||
329 | fn infer_union() { | ||
330 | check_infer( | ||
331 | r#" | ||
332 | union MyUnion { | ||
333 | foo: u32, | ||
334 | bar: f32, | ||
335 | } | ||
336 | |||
337 | unsafe fn baz(u: MyUnion) { | ||
338 | let inner = u.foo; | ||
339 | } | ||
340 | "#, | ||
341 | expect![[r#" | ||
342 | 61..62 'u': MyUnion | ||
343 | 73..99 '{ ...foo; }': () | ||
344 | 83..88 'inner': u32 | ||
345 | 91..92 'u': MyUnion | ||
346 | 91..96 'u.foo': u32 | ||
347 | "#]], | ||
348 | ); | ||
349 | } | ||
350 | |||
351 | #[test] | ||
352 | fn infer_refs() { | ||
353 | check_infer( | ||
354 | r#" | ||
355 | fn test(a: &u32, b: &mut u32, c: *const u32, d: *mut u32) { | ||
356 | a; | ||
357 | *a; | ||
358 | &a; | ||
359 | &mut a; | ||
360 | b; | ||
361 | *b; | ||
362 | &b; | ||
363 | c; | ||
364 | *c; | ||
365 | d; | ||
366 | *d; | ||
367 | } | ||
368 | "#, | ||
369 | expect![[r#" | ||
370 | 8..9 'a': &u32 | ||
371 | 17..18 'b': &mut u32 | ||
372 | 30..31 'c': *const u32 | ||
373 | 45..46 'd': *mut u32 | ||
374 | 58..149 '{ ... *d; }': () | ||
375 | 64..65 'a': &u32 | ||
376 | 71..73 '*a': u32 | ||
377 | 72..73 'a': &u32 | ||
378 | 79..81 '&a': &&u32 | ||
379 | 80..81 'a': &u32 | ||
380 | 87..93 '&mut a': &mut &u32 | ||
381 | 92..93 'a': &u32 | ||
382 | 99..100 'b': &mut u32 | ||
383 | 106..108 '*b': u32 | ||
384 | 107..108 'b': &mut u32 | ||
385 | 114..116 '&b': &&mut u32 | ||
386 | 115..116 'b': &mut u32 | ||
387 | 122..123 'c': *const u32 | ||
388 | 129..131 '*c': u32 | ||
389 | 130..131 'c': *const u32 | ||
390 | 137..138 'd': *mut u32 | ||
391 | 144..146 '*d': u32 | ||
392 | 145..146 'd': *mut u32 | ||
393 | "#]], | ||
394 | ); | ||
395 | } | ||
396 | |||
397 | #[test] | ||
398 | fn infer_raw_ref() { | ||
399 | check_infer( | ||
400 | r#" | ||
401 | fn test(a: i32) { | ||
402 | &raw mut a; | ||
403 | &raw const a; | ||
404 | } | ||
405 | "#, | ||
406 | expect![[r#" | ||
407 | 8..9 'a': i32 | ||
408 | 16..53 '{ ...t a; }': () | ||
409 | 22..32 '&raw mut a': *mut i32 | ||
410 | 31..32 'a': i32 | ||
411 | 38..50 '&raw const a': *const i32 | ||
412 | 49..50 'a': i32 | ||
413 | "#]], | ||
414 | ); | ||
415 | } | ||
416 | |||
417 | #[test] | ||
418 | fn infer_literals() { | ||
419 | check_infer( | ||
420 | r##" | ||
421 | fn test() { | ||
422 | 5i32; | ||
423 | 5f32; | ||
424 | 5f64; | ||
425 | "hello"; | ||
426 | b"bytes"; | ||
427 | 'c'; | ||
428 | b'b'; | ||
429 | 3.14; | ||
430 | 5000; | ||
431 | false; | ||
432 | true; | ||
433 | r#" | ||
434 | //! doc | ||
435 | // non-doc | ||
436 | mod foo {} | ||
437 | "#; | ||
438 | br#"yolo"#; | ||
439 | } | ||
440 | "##, | ||
441 | expect![[r##" | ||
442 | 10..216 '{ ...o"#; }': () | ||
443 | 16..20 '5i32': i32 | ||
444 | 26..30 '5f32': f32 | ||
445 | 36..40 '5f64': f64 | ||
446 | 46..53 '"hello"': &str | ||
447 | 59..67 'b"bytes"': &[u8; _] | ||
448 | 73..76 ''c'': char | ||
449 | 82..86 'b'b'': u8 | ||
450 | 92..96 '3.14': f64 | ||
451 | 102..106 '5000': i32 | ||
452 | 112..117 'false': bool | ||
453 | 123..127 'true': bool | ||
454 | 133..197 'r#" ... "#': &str | ||
455 | 203..213 'br#"yolo"#': &[u8; _] | ||
456 | "##]], | ||
457 | ); | ||
458 | } | ||
459 | |||
460 | #[test] | ||
461 | fn infer_unary_op() { | ||
462 | check_infer( | ||
463 | r#" | ||
464 | enum SomeType {} | ||
465 | |||
466 | fn test(x: SomeType) { | ||
467 | let b = false; | ||
468 | let c = !b; | ||
469 | let a = 100; | ||
470 | let d: i128 = -a; | ||
471 | let e = -100; | ||
472 | let f = !!!true; | ||
473 | let g = !42; | ||
474 | let h = !10u32; | ||
475 | let j = !a; | ||
476 | -3.14; | ||
477 | !3; | ||
478 | -x; | ||
479 | !x; | ||
480 | -"hello"; | ||
481 | !"hello"; | ||
482 | } | ||
483 | "#, | ||
484 | expect![[r#" | ||
485 | 26..27 'x': SomeType | ||
486 | 39..271 '{ ...lo"; }': () | ||
487 | 49..50 'b': bool | ||
488 | 53..58 'false': bool | ||
489 | 68..69 'c': bool | ||
490 | 72..74 '!b': bool | ||
491 | 73..74 'b': bool | ||
492 | 84..85 'a': i128 | ||
493 | 88..91 '100': i128 | ||
494 | 101..102 'd': i128 | ||
495 | 111..113 '-a': i128 | ||
496 | 112..113 'a': i128 | ||
497 | 123..124 'e': i32 | ||
498 | 127..131 '-100': i32 | ||
499 | 128..131 '100': i32 | ||
500 | 141..142 'f': bool | ||
501 | 145..152 '!!!true': bool | ||
502 | 146..152 '!!true': bool | ||
503 | 147..152 '!true': bool | ||
504 | 148..152 'true': bool | ||
505 | 162..163 'g': i32 | ||
506 | 166..169 '!42': i32 | ||
507 | 167..169 '42': i32 | ||
508 | 179..180 'h': u32 | ||
509 | 183..189 '!10u32': u32 | ||
510 | 184..189 '10u32': u32 | ||
511 | 199..200 'j': i128 | ||
512 | 203..205 '!a': i128 | ||
513 | 204..205 'a': i128 | ||
514 | 211..216 '-3.14': f64 | ||
515 | 212..216 '3.14': f64 | ||
516 | 222..224 '!3': i32 | ||
517 | 223..224 '3': i32 | ||
518 | 230..232 '-x': {unknown} | ||
519 | 231..232 'x': SomeType | ||
520 | 238..240 '!x': {unknown} | ||
521 | 239..240 'x': SomeType | ||
522 | 246..254 '-"hello"': {unknown} | ||
523 | 247..254 '"hello"': &str | ||
524 | 260..268 '!"hello"': {unknown} | ||
525 | 261..268 '"hello"': &str | ||
526 | "#]], | ||
527 | ); | ||
528 | } | ||
529 | |||
530 | #[test] | ||
531 | fn infer_backwards() { | ||
532 | check_infer( | ||
533 | r#" | ||
534 | fn takes_u32(x: u32) {} | ||
535 | |||
536 | struct S { i32_field: i32 } | ||
537 | |||
538 | fn test() -> &mut &f64 { | ||
539 | let a = unknown_function(); | ||
540 | takes_u32(a); | ||
541 | let b = unknown_function(); | ||
542 | S { i32_field: b }; | ||
543 | let c = unknown_function(); | ||
544 | &mut &c | ||
545 | } | ||
546 | "#, | ||
547 | expect![[r#" | ||
548 | 13..14 'x': u32 | ||
549 | 21..23 '{}': () | ||
550 | 77..230 '{ ...t &c }': &mut &f64 | ||
551 | 87..88 'a': u32 | ||
552 | 91..107 'unknow...nction': {unknown} | ||
553 | 91..109 'unknow...tion()': u32 | ||
554 | 115..124 'takes_u32': fn takes_u32(u32) | ||
555 | 115..127 'takes_u32(a)': () | ||
556 | 125..126 'a': u32 | ||
557 | 137..138 'b': i32 | ||
558 | 141..157 'unknow...nction': {unknown} | ||
559 | 141..159 'unknow...tion()': i32 | ||
560 | 165..183 'S { i3...d: b }': S | ||
561 | 180..181 'b': i32 | ||
562 | 193..194 'c': f64 | ||
563 | 197..213 'unknow...nction': {unknown} | ||
564 | 197..215 'unknow...tion()': f64 | ||
565 | 221..228 '&mut &c': &mut &f64 | ||
566 | 226..228 '&c': &f64 | ||
567 | 227..228 'c': f64 | ||
568 | "#]], | ||
569 | ); | ||
570 | } | ||
571 | |||
572 | #[test] | ||
573 | fn infer_self() { | ||
574 | check_infer( | ||
575 | r#" | ||
576 | struct S; | ||
577 | |||
578 | impl S { | ||
579 | fn test(&self) { | ||
580 | self; | ||
581 | } | ||
582 | fn test2(self: &Self) { | ||
583 | self; | ||
584 | } | ||
585 | fn test3() -> Self { | ||
586 | S {} | ||
587 | } | ||
588 | fn test4() -> Self { | ||
589 | Self {} | ||
590 | } | ||
591 | } | ||
592 | "#, | ||
593 | expect![[r#" | ||
594 | 33..37 'self': &S | ||
595 | 39..60 '{ ... }': () | ||
596 | 49..53 'self': &S | ||
597 | 74..78 'self': &S | ||
598 | 87..108 '{ ... }': () | ||
599 | 97..101 'self': &S | ||
600 | 132..152 '{ ... }': S | ||
601 | 142..146 'S {}': S | ||
602 | 176..199 '{ ... }': S | ||
603 | 186..193 'Self {}': S | ||
604 | "#]], | ||
605 | ); | ||
606 | } | ||
607 | |||
608 | #[test] | ||
609 | fn infer_self_as_path() { | ||
610 | check_infer( | ||
611 | r#" | ||
612 | struct S1; | ||
613 | struct S2(isize); | ||
614 | enum E { | ||
615 | V1, | ||
616 | V2(u32), | ||
617 | } | ||
618 | |||
619 | impl S1 { | ||
620 | fn test() { | ||
621 | Self; | ||
622 | } | ||
623 | } | ||
624 | impl S2 { | ||
625 | fn test() { | ||
626 | Self(1); | ||
627 | } | ||
628 | } | ||
629 | impl E { | ||
630 | fn test() { | ||
631 | Self::V1; | ||
632 | Self::V2(1); | ||
633 | } | ||
634 | } | ||
635 | "#, | ||
636 | expect![[r#" | ||
637 | 86..107 '{ ... }': () | ||
638 | 96..100 'Self': S1 | ||
639 | 134..158 '{ ... }': () | ||
640 | 144..148 'Self': S2(isize) -> S2 | ||
641 | 144..151 'Self(1)': S2 | ||
642 | 149..150 '1': isize | ||
643 | 184..230 '{ ... }': () | ||
644 | 194..202 'Self::V1': E | ||
645 | 212..220 'Self::V2': V2(u32) -> E | ||
646 | 212..223 'Self::V2(1)': E | ||
647 | 221..222 '1': u32 | ||
648 | "#]], | ||
649 | ); | ||
650 | } | ||
651 | |||
652 | #[test] | ||
653 | fn infer_binary_op() { | ||
654 | check_infer( | ||
655 | r#" | ||
656 | fn f(x: bool) -> i32 { | ||
657 | 0i32 | ||
658 | } | ||
659 | |||
660 | fn test() -> bool { | ||
661 | let x = a && b; | ||
662 | let y = true || false; | ||
663 | let z = x == y; | ||
664 | let t = x != y; | ||
665 | let minus_forty: isize = -40isize; | ||
666 | let h = minus_forty <= CONST_2; | ||
667 | let c = f(z || y) + 5; | ||
668 | let d = b; | ||
669 | let g = minus_forty ^= i; | ||
670 | let ten: usize = 10; | ||
671 | let ten_is_eleven = ten == some_num; | ||
672 | |||
673 | ten < 3 | ||
674 | } | ||
675 | "#, | ||
676 | expect![[r#" | ||
677 | 5..6 'x': bool | ||
678 | 21..33 '{ 0i32 }': i32 | ||
679 | 27..31 '0i32': i32 | ||
680 | 53..369 '{ ... < 3 }': bool | ||
681 | 63..64 'x': bool | ||
682 | 67..68 'a': bool | ||
683 | 67..73 'a && b': bool | ||
684 | 72..73 'b': bool | ||
685 | 83..84 'y': bool | ||
686 | 87..91 'true': bool | ||
687 | 87..100 'true || false': bool | ||
688 | 95..100 'false': bool | ||
689 | 110..111 'z': bool | ||
690 | 114..115 'x': bool | ||
691 | 114..120 'x == y': bool | ||
692 | 119..120 'y': bool | ||
693 | 130..131 't': bool | ||
694 | 134..135 'x': bool | ||
695 | 134..140 'x != y': bool | ||
696 | 139..140 'y': bool | ||
697 | 150..161 'minus_forty': isize | ||
698 | 171..179 '-40isize': isize | ||
699 | 172..179 '40isize': isize | ||
700 | 189..190 'h': bool | ||
701 | 193..204 'minus_forty': isize | ||
702 | 193..215 'minus_...ONST_2': bool | ||
703 | 208..215 'CONST_2': isize | ||
704 | 225..226 'c': i32 | ||
705 | 229..230 'f': fn f(bool) -> i32 | ||
706 | 229..238 'f(z || y)': i32 | ||
707 | 229..242 'f(z || y) + 5': i32 | ||
708 | 231..232 'z': bool | ||
709 | 231..237 'z || y': bool | ||
710 | 236..237 'y': bool | ||
711 | 241..242 '5': i32 | ||
712 | 252..253 'd': {unknown} | ||
713 | 256..257 'b': {unknown} | ||
714 | 267..268 'g': () | ||
715 | 271..282 'minus_forty': isize | ||
716 | 271..287 'minus_...y ^= i': () | ||
717 | 286..287 'i': isize | ||
718 | 297..300 'ten': usize | ||
719 | 310..312 '10': usize | ||
720 | 322..335 'ten_is_eleven': bool | ||
721 | 338..341 'ten': usize | ||
722 | 338..353 'ten == some_num': bool | ||
723 | 345..353 'some_num': usize | ||
724 | 360..363 'ten': usize | ||
725 | 360..367 'ten < 3': bool | ||
726 | 366..367 '3': usize | ||
727 | "#]], | ||
728 | ); | ||
729 | } | ||
730 | |||
731 | #[test] | ||
732 | fn infer_shift_op() { | ||
733 | check_infer( | ||
734 | r#" | ||
735 | fn test() { | ||
736 | 1u32 << 5u8; | ||
737 | 1u32 >> 5u8; | ||
738 | } | ||
739 | "#, | ||
740 | expect![[r#" | ||
741 | 10..47 '{ ...5u8; }': () | ||
742 | 16..20 '1u32': u32 | ||
743 | 16..27 '1u32 << 5u8': u32 | ||
744 | 24..27 '5u8': u8 | ||
745 | 33..37 '1u32': u32 | ||
746 | 33..44 '1u32 >> 5u8': u32 | ||
747 | 41..44 '5u8': u8 | ||
748 | "#]], | ||
749 | ); | ||
750 | } | ||
751 | |||
752 | #[test] | ||
753 | fn infer_field_autoderef() { | ||
754 | check_infer( | ||
755 | r#" | ||
756 | struct A { | ||
757 | b: B, | ||
758 | } | ||
759 | struct B; | ||
760 | |||
761 | fn test1(a: A) { | ||
762 | let a1 = a; | ||
763 | a1.b; | ||
764 | let a2 = &a; | ||
765 | a2.b; | ||
766 | let a3 = &mut a; | ||
767 | a3.b; | ||
768 | let a4 = &&&&&&&a; | ||
769 | a4.b; | ||
770 | let a5 = &mut &&mut &&mut a; | ||
771 | a5.b; | ||
772 | } | ||
773 | |||
774 | fn test2(a1: *const A, a2: *mut A) { | ||
775 | a1.b; | ||
776 | a2.b; | ||
777 | } | ||
778 | "#, | ||
779 | expect![[r#" | ||
780 | 43..44 'a': A | ||
781 | 49..212 '{ ...5.b; }': () | ||
782 | 59..61 'a1': A | ||
783 | 64..65 'a': A | ||
784 | 71..73 'a1': A | ||
785 | 71..75 'a1.b': B | ||
786 | 85..87 'a2': &A | ||
787 | 90..92 '&a': &A | ||
788 | 91..92 'a': A | ||
789 | 98..100 'a2': &A | ||
790 | 98..102 'a2.b': B | ||
791 | 112..114 'a3': &mut A | ||
792 | 117..123 '&mut a': &mut A | ||
793 | 122..123 'a': A | ||
794 | 129..131 'a3': &mut A | ||
795 | 129..133 'a3.b': B | ||
796 | 143..145 'a4': &&&&&&&A | ||
797 | 148..156 '&&&&&&&a': &&&&&&&A | ||
798 | 149..156 '&&&&&&a': &&&&&&A | ||
799 | 150..156 '&&&&&a': &&&&&A | ||
800 | 151..156 '&&&&a': &&&&A | ||
801 | 152..156 '&&&a': &&&A | ||
802 | 153..156 '&&a': &&A | ||
803 | 154..156 '&a': &A | ||
804 | 155..156 'a': A | ||
805 | 162..164 'a4': &&&&&&&A | ||
806 | 162..166 'a4.b': B | ||
807 | 176..178 'a5': &mut &&mut &&mut A | ||
808 | 181..199 '&mut &...&mut a': &mut &&mut &&mut A | ||
809 | 186..199 '&&mut &&mut a': &&mut &&mut A | ||
810 | 187..199 '&mut &&mut a': &mut &&mut A | ||
811 | 192..199 '&&mut a': &&mut A | ||
812 | 193..199 '&mut a': &mut A | ||
813 | 198..199 'a': A | ||
814 | 205..207 'a5': &mut &&mut &&mut A | ||
815 | 205..209 'a5.b': B | ||
816 | 223..225 'a1': *const A | ||
817 | 237..239 'a2': *mut A | ||
818 | 249..272 '{ ...2.b; }': () | ||
819 | 255..257 'a1': *const A | ||
820 | 255..259 'a1.b': B | ||
821 | 265..267 'a2': *mut A | ||
822 | 265..269 'a2.b': B | ||
823 | "#]], | ||
824 | ); | ||
825 | } | ||
826 | |||
827 | #[test] | ||
828 | fn infer_argument_autoderef() { | ||
829 | check_infer( | ||
830 | r#" | ||
831 | #[lang = "deref"] | ||
832 | pub trait Deref { | ||
833 | type Target; | ||
834 | fn deref(&self) -> &Self::Target; | ||
835 | } | ||
836 | |||
837 | struct A<T>(T); | ||
838 | |||
839 | impl<T> A<T> { | ||
840 | fn foo(&self) -> &T { | ||
841 | &self.0 | ||
842 | } | ||
843 | } | ||
844 | |||
845 | struct B<T>(T); | ||
846 | |||
847 | impl<T> Deref for B<T> { | ||
848 | type Target = T; | ||
849 | fn deref(&self) -> &Self::Target { | ||
850 | &self.0 | ||
851 | } | ||
852 | } | ||
853 | |||
854 | fn test() { | ||
855 | let t = A::foo(&&B(B(A(42)))); | ||
856 | } | ||
857 | "#, | ||
858 | expect![[r#" | ||
859 | 67..71 'self': &Self | ||
860 | 138..142 'self': &A<T> | ||
861 | 150..173 '{ ... }': &T | ||
862 | 160..167 '&self.0': &T | ||
863 | 161..165 'self': &A<T> | ||
864 | 161..167 'self.0': T | ||
865 | 254..258 'self': &B<T> | ||
866 | 277..300 '{ ... }': &T | ||
867 | 287..294 '&self.0': &T | ||
868 | 288..292 'self': &B<T> | ||
869 | 288..294 'self.0': T | ||
870 | 314..352 '{ ...))); }': () | ||
871 | 324..325 't': &i32 | ||
872 | 328..334 'A::foo': fn foo<i32>(&A<i32>) -> &i32 | ||
873 | 328..349 'A::foo...42))))': &i32 | ||
874 | 335..348 '&&B(B(A(42)))': &&B<B<A<i32>>> | ||
875 | 336..348 '&B(B(A(42)))': &B<B<A<i32>>> | ||
876 | 337..338 'B': B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>> | ||
877 | 337..348 'B(B(A(42)))': B<B<A<i32>>> | ||
878 | 339..340 'B': B<A<i32>>(A<i32>) -> B<A<i32>> | ||
879 | 339..347 'B(A(42))': B<A<i32>> | ||
880 | 341..342 'A': A<i32>(i32) -> A<i32> | ||
881 | 341..346 'A(42)': A<i32> | ||
882 | 343..345 '42': i32 | ||
883 | "#]], | ||
884 | ); | ||
885 | } | ||
886 | |||
887 | #[test] | ||
888 | fn infer_method_argument_autoderef() { | ||
889 | check_infer( | ||
890 | r#" | ||
891 | #[lang = "deref"] | ||
892 | pub trait Deref { | ||
893 | type Target; | ||
894 | fn deref(&self) -> &Self::Target; | ||
895 | } | ||
896 | |||
897 | struct A<T>(*mut T); | ||
898 | |||
899 | impl<T> A<T> { | ||
900 | fn foo(&self, x: &A<T>) -> &T { | ||
901 | &*x.0 | ||
902 | } | ||
903 | } | ||
904 | |||
905 | struct B<T>(T); | ||
906 | |||
907 | impl<T> Deref for B<T> { | ||
908 | type Target = T; | ||
909 | fn deref(&self) -> &Self::Target { | ||
910 | &self.0 | ||
911 | } | ||
912 | } | ||
913 | |||
914 | fn test(a: A<i32>) { | ||
915 | let t = A(0 as *mut _).foo(&&B(B(a))); | ||
916 | } | ||
917 | "#, | ||
918 | expect![[r#" | ||
919 | 67..71 'self': &Self | ||
920 | 143..147 'self': &A<T> | ||
921 | 149..150 'x': &A<T> | ||
922 | 165..186 '{ ... }': &T | ||
923 | 175..180 '&*x.0': &T | ||
924 | 176..180 '*x.0': T | ||
925 | 177..178 'x': &A<T> | ||
926 | 177..180 'x.0': *mut T | ||
927 | 267..271 'self': &B<T> | ||
928 | 290..313 '{ ... }': &T | ||
929 | 300..307 '&self.0': &T | ||
930 | 301..305 'self': &B<T> | ||
931 | 301..307 'self.0': T | ||
932 | 325..326 'a': A<i32> | ||
933 | 336..382 '{ ...))); }': () | ||
934 | 346..347 't': &i32 | ||
935 | 350..351 'A': A<i32>(*mut i32) -> A<i32> | ||
936 | 350..364 'A(0 as *mut _)': A<i32> | ||
937 | 350..379 'A(0 as...B(a)))': &i32 | ||
938 | 352..353 '0': i32 | ||
939 | 352..363 '0 as *mut _': *mut i32 | ||
940 | 369..378 '&&B(B(a))': &&B<B<A<i32>>> | ||
941 | 370..378 '&B(B(a))': &B<B<A<i32>>> | ||
942 | 371..372 'B': B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>> | ||
943 | 371..378 'B(B(a))': B<B<A<i32>>> | ||
944 | 373..374 'B': B<A<i32>>(A<i32>) -> B<A<i32>> | ||
945 | 373..377 'B(a)': B<A<i32>> | ||
946 | 375..376 'a': A<i32> | ||
947 | "#]], | ||
948 | ); | ||
949 | } | ||
950 | |||
951 | #[test] | ||
952 | fn infer_in_elseif() { | ||
953 | check_infer( | ||
954 | r#" | ||
955 | struct Foo { field: i32 } | ||
956 | fn main(foo: Foo) { | ||
957 | if true { | ||
958 | |||
959 | } else if false { | ||
960 | foo.field | ||
961 | } | ||
962 | } | ||
963 | "#, | ||
964 | expect![[r#" | ||
965 | 34..37 'foo': Foo | ||
966 | 44..108 '{ ... } }': () | ||
967 | 50..106 'if tru... }': () | ||
968 | 53..57 'true': bool | ||
969 | 58..66 '{ }': () | ||
970 | 72..106 'if fal... }': i32 | ||
971 | 75..80 'false': bool | ||
972 | 81..106 '{ ... }': i32 | ||
973 | 91..94 'foo': Foo | ||
974 | 91..100 'foo.field': i32 | ||
975 | "#]], | ||
976 | ) | ||
977 | } | ||
978 | |||
979 | #[test] | ||
980 | fn infer_if_match_with_return() { | ||
981 | check_infer( | ||
982 | r#" | ||
983 | fn foo() { | ||
984 | let _x1 = if true { | ||
985 | 1 | ||
986 | } else { | ||
987 | return; | ||
988 | }; | ||
989 | let _x2 = if true { | ||
990 | 2 | ||
991 | } else { | ||
992 | return | ||
993 | }; | ||
994 | let _x3 = match true { | ||
995 | true => 3, | ||
996 | _ => { | ||
997 | return; | ||
998 | } | ||
999 | }; | ||
1000 | let _x4 = match true { | ||
1001 | true => 4, | ||
1002 | _ => return | ||
1003 | }; | ||
1004 | }"#, | ||
1005 | expect![[r#" | ||
1006 | 9..322 '{ ... }; }': () | ||
1007 | 19..22 '_x1': i32 | ||
1008 | 25..79 'if tru... }': i32 | ||
1009 | 28..32 'true': bool | ||
1010 | 33..50 '{ ... }': i32 | ||
1011 | 43..44 '1': i32 | ||
1012 | 56..79 '{ ... }': i32 | ||
1013 | 66..72 'return': ! | ||
1014 | 89..92 '_x2': i32 | ||
1015 | 95..148 'if tru... }': i32 | ||
1016 | 98..102 'true': bool | ||
1017 | 103..120 '{ ... }': i32 | ||
1018 | 113..114 '2': i32 | ||
1019 | 126..148 '{ ... }': ! | ||
1020 | 136..142 'return': ! | ||
1021 | 158..161 '_x3': i32 | ||
1022 | 164..246 'match ... }': i32 | ||
1023 | 170..174 'true': bool | ||
1024 | 185..189 'true': bool | ||
1025 | 185..189 'true': bool | ||
1026 | 193..194 '3': i32 | ||
1027 | 204..205 '_': bool | ||
1028 | 209..240 '{ ... }': i32 | ||
1029 | 223..229 'return': ! | ||
1030 | 256..259 '_x4': i32 | ||
1031 | 262..319 'match ... }': i32 | ||
1032 | 268..272 'true': bool | ||
1033 | 283..287 'true': bool | ||
1034 | 283..287 'true': bool | ||
1035 | 291..292 '4': i32 | ||
1036 | 302..303 '_': bool | ||
1037 | 307..313 'return': ! | ||
1038 | "#]], | ||
1039 | ) | ||
1040 | } | ||
1041 | |||
1042 | #[test] | ||
1043 | fn infer_inherent_method() { | ||
1044 | check_infer( | ||
1045 | r#" | ||
1046 | struct A; | ||
1047 | |||
1048 | impl A { | ||
1049 | fn foo(self, x: u32) -> i32 {} | ||
1050 | } | ||
1051 | |||
1052 | mod b { | ||
1053 | impl super::A { | ||
1054 | fn bar(&self, x: u64) -> i64 {} | ||
1055 | } | ||
1056 | } | ||
1057 | |||
1058 | fn test(a: A) { | ||
1059 | a.foo(1); | ||
1060 | (&a).bar(1); | ||
1061 | a.bar(1); | ||
1062 | } | ||
1063 | "#, | ||
1064 | expect![[r#" | ||
1065 | 31..35 'self': A | ||
1066 | 37..38 'x': u32 | ||
1067 | 52..54 '{}': () | ||
1068 | 102..106 'self': &A | ||
1069 | 108..109 'x': u64 | ||
1070 | 123..125 '{}': () | ||
1071 | 143..144 'a': A | ||
1072 | 149..197 '{ ...(1); }': () | ||
1073 | 155..156 'a': A | ||
1074 | 155..163 'a.foo(1)': i32 | ||
1075 | 161..162 '1': u32 | ||
1076 | 169..180 '(&a).bar(1)': i64 | ||
1077 | 170..172 '&a': &A | ||
1078 | 171..172 'a': A | ||
1079 | 178..179 '1': u64 | ||
1080 | 186..187 'a': A | ||
1081 | 186..194 'a.bar(1)': i64 | ||
1082 | 192..193 '1': u64 | ||
1083 | "#]], | ||
1084 | ); | ||
1085 | } | ||
1086 | |||
1087 | #[test] | ||
1088 | fn infer_inherent_method_str() { | ||
1089 | check_infer( | ||
1090 | r#" | ||
1091 | #[lang = "str"] | ||
1092 | impl str { | ||
1093 | fn foo(&self) -> i32 {} | ||
1094 | } | ||
1095 | |||
1096 | fn test() { | ||
1097 | "foo".foo(); | ||
1098 | } | ||
1099 | "#, | ||
1100 | expect![[r#" | ||
1101 | 39..43 'self': &str | ||
1102 | 52..54 '{}': () | ||
1103 | 68..88 '{ ...o(); }': () | ||
1104 | 74..79 '"foo"': &str | ||
1105 | 74..85 '"foo".foo()': i32 | ||
1106 | "#]], | ||
1107 | ); | ||
1108 | } | ||
1109 | |||
1110 | #[test] | ||
1111 | fn infer_tuple() { | ||
1112 | check_infer( | ||
1113 | r#" | ||
1114 | fn test(x: &str, y: isize) { | ||
1115 | let a: (u32, &str) = (1, "a"); | ||
1116 | let b = (a, x); | ||
1117 | let c = (y, x); | ||
1118 | let d = (c, x); | ||
1119 | let e = (1, "e"); | ||
1120 | let f = (e, "d"); | ||
1121 | } | ||
1122 | "#, | ||
1123 | expect![[r#" | ||
1124 | 8..9 'x': &str | ||
1125 | 17..18 'y': isize | ||
1126 | 27..169 '{ ...d"); }': () | ||
1127 | 37..38 'a': (u32, &str) | ||
1128 | 54..62 '(1, "a")': (u32, &str) | ||
1129 | 55..56 '1': u32 | ||
1130 | 58..61 '"a"': &str | ||
1131 | 72..73 'b': ((u32, &str), &str) | ||
1132 | 76..82 '(a, x)': ((u32, &str), &str) | ||
1133 | 77..78 'a': (u32, &str) | ||
1134 | 80..81 'x': &str | ||
1135 | 92..93 'c': (isize, &str) | ||
1136 | 96..102 '(y, x)': (isize, &str) | ||
1137 | 97..98 'y': isize | ||
1138 | 100..101 'x': &str | ||
1139 | 112..113 'd': ((isize, &str), &str) | ||
1140 | 116..122 '(c, x)': ((isize, &str), &str) | ||
1141 | 117..118 'c': (isize, &str) | ||
1142 | 120..121 'x': &str | ||
1143 | 132..133 'e': (i32, &str) | ||
1144 | 136..144 '(1, "e")': (i32, &str) | ||
1145 | 137..138 '1': i32 | ||
1146 | 140..143 '"e"': &str | ||
1147 | 154..155 'f': ((i32, &str), &str) | ||
1148 | 158..166 '(e, "d")': ((i32, &str), &str) | ||
1149 | 159..160 'e': (i32, &str) | ||
1150 | 162..165 '"d"': &str | ||
1151 | "#]], | ||
1152 | ); | ||
1153 | } | ||
1154 | |||
1155 | #[test] | ||
1156 | fn infer_array() { | ||
1157 | check_infer( | ||
1158 | r#" | ||
1159 | fn test(x: &str, y: isize) { | ||
1160 | let a = [x]; | ||
1161 | let b = [a, a]; | ||
1162 | let c = [b, b]; | ||
1163 | |||
1164 | let d = [y, 1, 2, 3]; | ||
1165 | let d = [1, y, 2, 3]; | ||
1166 | let e = [y]; | ||
1167 | let f = [d, d]; | ||
1168 | let g = [e, e]; | ||
1169 | |||
1170 | let h = [1, 2]; | ||
1171 | let i = ["a", "b"]; | ||
1172 | |||
1173 | let b = [a, ["b"]]; | ||
1174 | let x: [u8; 0] = []; | ||
1175 | } | ||
1176 | "#, | ||
1177 | expect![[r#" | ||
1178 | 8..9 'x': &str | ||
1179 | 17..18 'y': isize | ||
1180 | 27..292 '{ ... []; }': () | ||
1181 | 37..38 'a': [&str; _] | ||
1182 | 41..44 '[x]': [&str; _] | ||
1183 | 42..43 'x': &str | ||
1184 | 54..55 'b': [[&str; _]; _] | ||
1185 | 58..64 '[a, a]': [[&str; _]; _] | ||
1186 | 59..60 'a': [&str; _] | ||
1187 | 62..63 'a': [&str; _] | ||
1188 | 74..75 'c': [[[&str; _]; _]; _] | ||
1189 | 78..84 '[b, b]': [[[&str; _]; _]; _] | ||
1190 | 79..80 'b': [[&str; _]; _] | ||
1191 | 82..83 'b': [[&str; _]; _] | ||
1192 | 95..96 'd': [isize; _] | ||
1193 | 99..111 '[y, 1, 2, 3]': [isize; _] | ||
1194 | 100..101 'y': isize | ||
1195 | 103..104 '1': isize | ||
1196 | 106..107 '2': isize | ||
1197 | 109..110 '3': isize | ||
1198 | 121..122 'd': [isize; _] | ||
1199 | 125..137 '[1, y, 2, 3]': [isize; _] | ||
1200 | 126..127 '1': isize | ||
1201 | 129..130 'y': isize | ||
1202 | 132..133 '2': isize | ||
1203 | 135..136 '3': isize | ||
1204 | 147..148 'e': [isize; _] | ||
1205 | 151..154 '[y]': [isize; _] | ||
1206 | 152..153 'y': isize | ||
1207 | 164..165 'f': [[isize; _]; _] | ||
1208 | 168..174 '[d, d]': [[isize; _]; _] | ||
1209 | 169..170 'd': [isize; _] | ||
1210 | 172..173 'd': [isize; _] | ||
1211 | 184..185 'g': [[isize; _]; _] | ||
1212 | 188..194 '[e, e]': [[isize; _]; _] | ||
1213 | 189..190 'e': [isize; _] | ||
1214 | 192..193 'e': [isize; _] | ||
1215 | 205..206 'h': [i32; _] | ||
1216 | 209..215 '[1, 2]': [i32; _] | ||
1217 | 210..211 '1': i32 | ||
1218 | 213..214 '2': i32 | ||
1219 | 225..226 'i': [&str; _] | ||
1220 | 229..239 '["a", "b"]': [&str; _] | ||
1221 | 230..233 '"a"': &str | ||
1222 | 235..238 '"b"': &str | ||
1223 | 250..251 'b': [[&str; _]; _] | ||
1224 | 254..264 '[a, ["b"]]': [[&str; _]; _] | ||
1225 | 255..256 'a': [&str; _] | ||
1226 | 258..263 '["b"]': [&str; _] | ||
1227 | 259..262 '"b"': &str | ||
1228 | 274..275 'x': [u8; _] | ||
1229 | 287..289 '[]': [u8; _] | ||
1230 | "#]], | ||
1231 | ); | ||
1232 | } | ||
1233 | |||
1234 | #[test] | ||
1235 | fn infer_struct_generics() { | ||
1236 | check_infer( | ||
1237 | r#" | ||
1238 | struct A<T> { | ||
1239 | x: T, | ||
1240 | } | ||
1241 | |||
1242 | fn test(a1: A<u32>, i: i32) { | ||
1243 | a1.x; | ||
1244 | let a2 = A { x: i }; | ||
1245 | a2.x; | ||
1246 | let a3 = A::<i128> { x: 1 }; | ||
1247 | a3.x; | ||
1248 | } | ||
1249 | "#, | ||
1250 | expect![[r#" | ||
1251 | 35..37 'a1': A<u32> | ||
1252 | 47..48 'i': i32 | ||
1253 | 55..146 '{ ...3.x; }': () | ||
1254 | 61..63 'a1': A<u32> | ||
1255 | 61..65 'a1.x': u32 | ||
1256 | 75..77 'a2': A<i32> | ||
1257 | 80..90 'A { x: i }': A<i32> | ||
1258 | 87..88 'i': i32 | ||
1259 | 96..98 'a2': A<i32> | ||
1260 | 96..100 'a2.x': i32 | ||
1261 | 110..112 'a3': A<i128> | ||
1262 | 115..133 'A::<i1...x: 1 }': A<i128> | ||
1263 | 130..131 '1': i128 | ||
1264 | 139..141 'a3': A<i128> | ||
1265 | 139..143 'a3.x': i128 | ||
1266 | "#]], | ||
1267 | ); | ||
1268 | } | ||
1269 | |||
1270 | #[test] | ||
1271 | fn infer_tuple_struct_generics() { | ||
1272 | check_infer( | ||
1273 | r#" | ||
1274 | struct A<T>(T); | ||
1275 | enum Option<T> { Some(T), None } | ||
1276 | use Option::*; | ||
1277 | |||
1278 | fn test() { | ||
1279 | A(42); | ||
1280 | A(42u128); | ||
1281 | Some("x"); | ||
1282 | Option::Some("x"); | ||
1283 | None; | ||
1284 | let x: Option<i64> = None; | ||
1285 | } | ||
1286 | "#, | ||
1287 | expect![[r#" | ||
1288 | 75..183 '{ ...one; }': () | ||
1289 | 81..82 'A': A<i32>(i32) -> A<i32> | ||
1290 | 81..86 'A(42)': A<i32> | ||
1291 | 83..85 '42': i32 | ||
1292 | 92..93 'A': A<u128>(u128) -> A<u128> | ||
1293 | 92..101 'A(42u128)': A<u128> | ||
1294 | 94..100 '42u128': u128 | ||
1295 | 107..111 'Some': Some<&str>(&str) -> Option<&str> | ||
1296 | 107..116 'Some("x")': Option<&str> | ||
1297 | 112..115 '"x"': &str | ||
1298 | 122..134 'Option::Some': Some<&str>(&str) -> Option<&str> | ||
1299 | 122..139 'Option...e("x")': Option<&str> | ||
1300 | 135..138 '"x"': &str | ||
1301 | 145..149 'None': Option<{unknown}> | ||
1302 | 159..160 'x': Option<i64> | ||
1303 | 176..180 'None': Option<i64> | ||
1304 | "#]], | ||
1305 | ); | ||
1306 | } | ||
1307 | |||
1308 | #[test] | ||
1309 | fn infer_function_generics() { | ||
1310 | check_infer( | ||
1311 | r#" | ||
1312 | fn id<T>(t: T) -> T { t } | ||
1313 | |||
1314 | fn test() { | ||
1315 | id(1u32); | ||
1316 | id::<i128>(1); | ||
1317 | let x: u64 = id(1); | ||
1318 | } | ||
1319 | "#, | ||
1320 | expect![[r#" | ||
1321 | 9..10 't': T | ||
1322 | 20..25 '{ t }': T | ||
1323 | 22..23 't': T | ||
1324 | 37..97 '{ ...(1); }': () | ||
1325 | 43..45 'id': fn id<u32>(u32) -> u32 | ||
1326 | 43..51 'id(1u32)': u32 | ||
1327 | 46..50 '1u32': u32 | ||
1328 | 57..67 'id::<i128>': fn id<i128>(i128) -> i128 | ||
1329 | 57..70 'id::<i128>(1)': i128 | ||
1330 | 68..69 '1': i128 | ||
1331 | 80..81 'x': u64 | ||
1332 | 89..91 'id': fn id<u64>(u64) -> u64 | ||
1333 | 89..94 'id(1)': u64 | ||
1334 | 92..93 '1': u64 | ||
1335 | "#]], | ||
1336 | ); | ||
1337 | } | ||
1338 | |||
1339 | #[test] | ||
1340 | fn infer_impl_generics_basic() { | ||
1341 | check_infer( | ||
1342 | r#" | ||
1343 | struct A<T1, T2> { | ||
1344 | x: T1, | ||
1345 | y: T2, | ||
1346 | } | ||
1347 | impl<Y, X> A<X, Y> { | ||
1348 | fn x(self) -> X { | ||
1349 | self.x | ||
1350 | } | ||
1351 | fn y(self) -> Y { | ||
1352 | self.y | ||
1353 | } | ||
1354 | fn z<T>(self, t: T) -> (X, Y, T) { | ||
1355 | (self.x, self.y, t) | ||
1356 | } | ||
1357 | } | ||
1358 | |||
1359 | fn test() -> i128 { | ||
1360 | let a = A { x: 1u64, y: 1i64 }; | ||
1361 | a.x(); | ||
1362 | a.y(); | ||
1363 | a.z(1i128); | ||
1364 | a.z::<u128>(1); | ||
1365 | } | ||
1366 | "#, | ||
1367 | expect![[r#" | ||
1368 | 73..77 'self': A<X, Y> | ||
1369 | 84..106 '{ ... }': X | ||
1370 | 94..98 'self': A<X, Y> | ||
1371 | 94..100 'self.x': X | ||
1372 | 116..120 'self': A<X, Y> | ||
1373 | 127..149 '{ ... }': Y | ||
1374 | 137..141 'self': A<X, Y> | ||
1375 | 137..143 'self.y': Y | ||
1376 | 162..166 'self': A<X, Y> | ||
1377 | 168..169 't': T | ||
1378 | 187..222 '{ ... }': (X, Y, T) | ||
1379 | 197..216 '(self.....y, t)': (X, Y, T) | ||
1380 | 198..202 'self': A<X, Y> | ||
1381 | 198..204 'self.x': X | ||
1382 | 206..210 'self': A<X, Y> | ||
1383 | 206..212 'self.y': Y | ||
1384 | 214..215 't': T | ||
1385 | 244..341 '{ ...(1); }': () | ||
1386 | 254..255 'a': A<u64, i64> | ||
1387 | 258..280 'A { x:...1i64 }': A<u64, i64> | ||
1388 | 265..269 '1u64': u64 | ||
1389 | 274..278 '1i64': i64 | ||
1390 | 286..287 'a': A<u64, i64> | ||
1391 | 286..291 'a.x()': u64 | ||
1392 | 297..298 'a': A<u64, i64> | ||
1393 | 297..302 'a.y()': i64 | ||
1394 | 308..309 'a': A<u64, i64> | ||
1395 | 308..318 'a.z(1i128)': (u64, i64, i128) | ||
1396 | 312..317 '1i128': i128 | ||
1397 | 324..325 'a': A<u64, i64> | ||
1398 | 324..338 'a.z::<u128>(1)': (u64, i64, u128) | ||
1399 | 336..337 '1': u128 | ||
1400 | "#]], | ||
1401 | ); | ||
1402 | } | ||
1403 | |||
1404 | #[test] | ||
1405 | fn infer_impl_generics_with_autoderef() { | ||
1406 | check_infer( | ||
1407 | r#" | ||
1408 | enum Option<T> { | ||
1409 | Some(T), | ||
1410 | None, | ||
1411 | } | ||
1412 | impl<T> Option<T> { | ||
1413 | fn as_ref(&self) -> Option<&T> {} | ||
1414 | } | ||
1415 | fn test(o: Option<u32>) { | ||
1416 | (&o).as_ref(); | ||
1417 | o.as_ref(); | ||
1418 | } | ||
1419 | "#, | ||
1420 | expect![[r#" | ||
1421 | 77..81 'self': &Option<T> | ||
1422 | 97..99 '{}': () | ||
1423 | 110..111 'o': Option<u32> | ||
1424 | 126..164 '{ ...f(); }': () | ||
1425 | 132..145 '(&o).as_ref()': Option<&u32> | ||
1426 | 133..135 '&o': &Option<u32> | ||
1427 | 134..135 'o': Option<u32> | ||
1428 | 151..152 'o': Option<u32> | ||
1429 | 151..161 'o.as_ref()': Option<&u32> | ||
1430 | "#]], | ||
1431 | ); | ||
1432 | } | ||
1433 | |||
1434 | #[test] | ||
1435 | fn infer_generic_chain() { | ||
1436 | check_infer( | ||
1437 | r#" | ||
1438 | struct A<T> { | ||
1439 | x: T, | ||
1440 | } | ||
1441 | impl<T2> A<T2> { | ||
1442 | fn x(self) -> T2 { | ||
1443 | self.x | ||
1444 | } | ||
1445 | } | ||
1446 | fn id<T>(t: T) -> T { t } | ||
1447 | |||
1448 | fn test() -> i128 { | ||
1449 | let x = 1; | ||
1450 | let y = id(x); | ||
1451 | let a = A { x: id(y) }; | ||
1452 | let z = id(a.x); | ||
1453 | let b = A { x: z }; | ||
1454 | b.x() | ||
1455 | } | ||
1456 | "#, | ||
1457 | expect![[r#" | ||
1458 | 52..56 'self': A<T2> | ||
1459 | 64..86 '{ ... }': T2 | ||
1460 | 74..78 'self': A<T2> | ||
1461 | 74..80 'self.x': T2 | ||
1462 | 98..99 't': T | ||
1463 | 109..114 '{ t }': T | ||
1464 | 111..112 't': T | ||
1465 | 134..254 '{ ....x() }': i128 | ||
1466 | 144..145 'x': i128 | ||
1467 | 148..149 '1': i128 | ||
1468 | 159..160 'y': i128 | ||
1469 | 163..165 'id': fn id<i128>(i128) -> i128 | ||
1470 | 163..168 'id(x)': i128 | ||
1471 | 166..167 'x': i128 | ||
1472 | 178..179 'a': A<i128> | ||
1473 | 182..196 'A { x: id(y) }': A<i128> | ||
1474 | 189..191 'id': fn id<i128>(i128) -> i128 | ||
1475 | 189..194 'id(y)': i128 | ||
1476 | 192..193 'y': i128 | ||
1477 | 206..207 'z': i128 | ||
1478 | 210..212 'id': fn id<i128>(i128) -> i128 | ||
1479 | 210..217 'id(a.x)': i128 | ||
1480 | 213..214 'a': A<i128> | ||
1481 | 213..216 'a.x': i128 | ||
1482 | 227..228 'b': A<i128> | ||
1483 | 231..241 'A { x: z }': A<i128> | ||
1484 | 238..239 'z': i128 | ||
1485 | 247..248 'b': A<i128> | ||
1486 | 247..252 'b.x()': i128 | ||
1487 | "#]], | ||
1488 | ); | ||
1489 | } | ||
1490 | |||
1491 | #[test] | ||
1492 | fn infer_associated_const() { | ||
1493 | check_infer( | ||
1494 | r#" | ||
1495 | struct Struct; | ||
1496 | |||
1497 | impl Struct { | ||
1498 | const FOO: u32 = 1; | ||
1499 | } | ||
1500 | |||
1501 | enum Enum {} | ||
1502 | |||
1503 | impl Enum { | ||
1504 | const BAR: u32 = 2; | ||
1505 | } | ||
1506 | |||
1507 | trait Trait { | ||
1508 | const ID: u32; | ||
1509 | } | ||
1510 | |||
1511 | struct TraitTest; | ||
1512 | |||
1513 | impl Trait for TraitTest { | ||
1514 | const ID: u32 = 5; | ||
1515 | } | ||
1516 | |||
1517 | fn test() { | ||
1518 | let x = Struct::FOO; | ||
1519 | let y = Enum::BAR; | ||
1520 | let z = TraitTest::ID; | ||
1521 | } | ||
1522 | "#, | ||
1523 | expect![[r#" | ||
1524 | 51..52 '1': u32 | ||
1525 | 104..105 '2': u32 | ||
1526 | 212..213 '5': u32 | ||
1527 | 228..306 '{ ...:ID; }': () | ||
1528 | 238..239 'x': u32 | ||
1529 | 242..253 'Struct::FOO': u32 | ||
1530 | 263..264 'y': u32 | ||
1531 | 267..276 'Enum::BAR': u32 | ||
1532 | 286..287 'z': u32 | ||
1533 | 290..303 'TraitTest::ID': u32 | ||
1534 | "#]], | ||
1535 | ); | ||
1536 | } | ||
1537 | |||
1538 | #[test] | ||
1539 | fn infer_type_alias() { | ||
1540 | check_infer( | ||
1541 | r#" | ||
1542 | struct A<X, Y> { x: X, y: Y } | ||
1543 | type Foo = A<u32, i128>; | ||
1544 | type Bar<T> = A<T, u128>; | ||
1545 | type Baz<U, V> = A<V, U>; | ||
1546 | fn test(x: Foo, y: Bar<&str>, z: Baz<i8, u8>) { | ||
1547 | x.x; | ||
1548 | x.y; | ||
1549 | y.x; | ||
1550 | y.y; | ||
1551 | z.x; | ||
1552 | z.y; | ||
1553 | } | ||
1554 | "#, | ||
1555 | expect![[r#" | ||
1556 | 115..116 'x': A<u32, i128> | ||
1557 | 123..124 'y': A<&str, u128> | ||
1558 | 137..138 'z': A<u8, i8> | ||
1559 | 153..210 '{ ...z.y; }': () | ||
1560 | 159..160 'x': A<u32, i128> | ||
1561 | 159..162 'x.x': u32 | ||
1562 | 168..169 'x': A<u32, i128> | ||
1563 | 168..171 'x.y': i128 | ||
1564 | 177..178 'y': A<&str, u128> | ||
1565 | 177..180 'y.x': &str | ||
1566 | 186..187 'y': A<&str, u128> | ||
1567 | 186..189 'y.y': u128 | ||
1568 | 195..196 'z': A<u8, i8> | ||
1569 | 195..198 'z.x': u8 | ||
1570 | 204..205 'z': A<u8, i8> | ||
1571 | 204..207 'z.y': i8 | ||
1572 | "#]], | ||
1573 | ) | ||
1574 | } | ||
1575 | |||
1576 | #[test] | ||
1577 | fn recursive_type_alias() { | ||
1578 | check_infer( | ||
1579 | r#" | ||
1580 | struct A<X> {} | ||
1581 | type Foo = Foo; | ||
1582 | type Bar = A<Bar>; | ||
1583 | fn test(x: Foo) {} | ||
1584 | "#, | ||
1585 | expect![[r#" | ||
1586 | 58..59 'x': {unknown} | ||
1587 | 66..68 '{}': () | ||
1588 | "#]], | ||
1589 | ) | ||
1590 | } | ||
1591 | |||
1592 | #[test] | ||
1593 | fn infer_type_param() { | ||
1594 | check_infer( | ||
1595 | r#" | ||
1596 | fn id<T>(x: T) -> T { | ||
1597 | x | ||
1598 | } | ||
1599 | |||
1600 | fn clone<T>(x: &T) -> T { | ||
1601 | *x | ||
1602 | } | ||
1603 | |||
1604 | fn test() { | ||
1605 | let y = 10u32; | ||
1606 | id(y); | ||
1607 | let x: bool = clone(z); | ||
1608 | id::<i128>(1); | ||
1609 | } | ||
1610 | "#, | ||
1611 | expect![[r#" | ||
1612 | 9..10 'x': T | ||
1613 | 20..29 '{ x }': T | ||
1614 | 26..27 'x': T | ||
1615 | 43..44 'x': &T | ||
1616 | 55..65 '{ *x }': T | ||
1617 | 61..63 '*x': T | ||
1618 | 62..63 'x': &T | ||
1619 | 77..157 '{ ...(1); }': () | ||
1620 | 87..88 'y': u32 | ||
1621 | 91..96 '10u32': u32 | ||
1622 | 102..104 'id': fn id<u32>(u32) -> u32 | ||
1623 | 102..107 'id(y)': u32 | ||
1624 | 105..106 'y': u32 | ||
1625 | 117..118 'x': bool | ||
1626 | 127..132 'clone': fn clone<bool>(&bool) -> bool | ||
1627 | 127..135 'clone(z)': bool | ||
1628 | 133..134 'z': &bool | ||
1629 | 141..151 'id::<i128>': fn id<i128>(i128) -> i128 | ||
1630 | 141..154 'id::<i128>(1)': i128 | ||
1631 | 152..153 '1': i128 | ||
1632 | "#]], | ||
1633 | ); | ||
1634 | } | ||
1635 | |||
1636 | #[test] | ||
1637 | fn infer_const() { | ||
1638 | check_infer( | ||
1639 | r#" | ||
1640 | struct Foo; | ||
1641 | impl Foo { const ASSOC_CONST: u32 = 0; } | ||
1642 | const GLOBAL_CONST: u32 = 101; | ||
1643 | fn test() { | ||
1644 | const LOCAL_CONST: u32 = 99; | ||
1645 | let x = LOCAL_CONST; | ||
1646 | let z = GLOBAL_CONST; | ||
1647 | let id = Foo::ASSOC_CONST; | ||
1648 | } | ||
1649 | "#, | ||
1650 | expect![[r#" | ||
1651 | 48..49 '0': u32 | ||
1652 | 79..82 '101': u32 | ||
1653 | 94..212 '{ ...NST; }': () | ||
1654 | 137..138 'x': u32 | ||
1655 | 141..152 'LOCAL_CONST': u32 | ||
1656 | 162..163 'z': u32 | ||
1657 | 166..178 'GLOBAL_CONST': u32 | ||
1658 | 188..190 'id': u32 | ||
1659 | 193..209 'Foo::A..._CONST': u32 | ||
1660 | 125..127 '99': u32 | ||
1661 | "#]], | ||
1662 | ); | ||
1663 | } | ||
1664 | |||
1665 | #[test] | ||
1666 | fn infer_static() { | ||
1667 | check_infer( | ||
1668 | r#" | ||
1669 | static GLOBAL_STATIC: u32 = 101; | ||
1670 | static mut GLOBAL_STATIC_MUT: u32 = 101; | ||
1671 | fn test() { | ||
1672 | static LOCAL_STATIC: u32 = 99; | ||
1673 | static mut LOCAL_STATIC_MUT: u32 = 99; | ||
1674 | let x = LOCAL_STATIC; | ||
1675 | let y = LOCAL_STATIC_MUT; | ||
1676 | let z = GLOBAL_STATIC; | ||
1677 | let w = GLOBAL_STATIC_MUT; | ||
1678 | } | ||
1679 | "#, | ||
1680 | expect![[r#" | ||
1681 | 28..31 '101': u32 | ||
1682 | 69..72 '101': u32 | ||
1683 | 84..279 '{ ...MUT; }': () | ||
1684 | 172..173 'x': u32 | ||
1685 | 176..188 'LOCAL_STATIC': u32 | ||
1686 | 198..199 'y': u32 | ||
1687 | 202..218 'LOCAL_...IC_MUT': u32 | ||
1688 | 228..229 'z': u32 | ||
1689 | 232..245 'GLOBAL_STATIC': u32 | ||
1690 | 255..256 'w': u32 | ||
1691 | 259..276 'GLOBAL...IC_MUT': u32 | ||
1692 | 117..119 '99': u32 | ||
1693 | 160..162 '99': u32 | ||
1694 | "#]], | ||
1695 | ); | ||
1696 | } | ||
1697 | |||
1698 | #[test] | ||
1699 | fn shadowing_primitive() { | ||
1700 | check_types( | ||
1701 | r#" | ||
1702 | struct i32; | ||
1703 | struct Foo; | ||
1704 | |||
1705 | impl i32 { fn foo(&self) -> Foo { Foo } } | ||
1706 | |||
1707 | fn main() { | ||
1708 | let x: i32 = i32; | ||
1709 | x.foo(); | ||
1710 | //^ Foo | ||
1711 | }"#, | ||
1712 | ); | ||
1713 | } | ||
1714 | |||
1715 | #[test] | ||
1716 | fn not_shadowing_primitive_by_module() { | ||
1717 | check_types( | ||
1718 | r#" | ||
1719 | //- /str.rs | ||
1720 | fn foo() {} | ||
1721 | |||
1722 | //- /main.rs | ||
1723 | mod str; | ||
1724 | fn foo() -> &'static str { "" } | ||
1725 | |||
1726 | fn main() { | ||
1727 | foo(); | ||
1728 | //^ &str | ||
1729 | }"#, | ||
1730 | ); | ||
1731 | } | ||
1732 | |||
1733 | #[test] | ||
1734 | fn not_shadowing_module_by_primitive() { | ||
1735 | check_types( | ||
1736 | r#" | ||
1737 | //- /str.rs | ||
1738 | fn foo() -> u32 {0} | ||
1739 | |||
1740 | //- /main.rs | ||
1741 | mod str; | ||
1742 | fn foo() -> &'static str { "" } | ||
1743 | |||
1744 | fn main() { | ||
1745 | str::foo(); | ||
1746 | //^ u32 | ||
1747 | }"#, | ||
1748 | ); | ||
1749 | } | ||
1750 | |||
1751 | // This test is actually testing the shadowing behavior within ra_hir_def. It | ||
1752 | // lives here because the testing infrastructure in ra_hir_def isn't currently | ||
1753 | // capable of asserting the necessary conditions. | ||
1754 | #[test] | ||
1755 | fn should_be_shadowing_imports() { | ||
1756 | check_types( | ||
1757 | r#" | ||
1758 | mod a { | ||
1759 | pub fn foo() -> i8 {0} | ||
1760 | pub struct foo { a: i8 } | ||
1761 | } | ||
1762 | mod b { pub fn foo () -> u8 {0} } | ||
1763 | mod c { pub struct foo { a: u8 } } | ||
1764 | mod d { | ||
1765 | pub use super::a::*; | ||
1766 | pub use super::c::foo; | ||
1767 | pub use super::b::foo; | ||
1768 | } | ||
1769 | |||
1770 | fn main() { | ||
1771 | d::foo(); | ||
1772 | //^ u8 | ||
1773 | d::foo{a:0}; | ||
1774 | //^ u8 | ||
1775 | }"#, | ||
1776 | ); | ||
1777 | } | ||
1778 | |||
1779 | #[test] | ||
1780 | fn closure_return() { | ||
1781 | check_infer( | ||
1782 | r#" | ||
1783 | fn foo() -> u32 { | ||
1784 | let x = || -> usize { return 1; }; | ||
1785 | } | ||
1786 | "#, | ||
1787 | expect![[r#" | ||
1788 | 16..58 '{ ...; }; }': () | ||
1789 | 26..27 'x': || -> usize | ||
1790 | 30..55 '|| -> ...n 1; }': || -> usize | ||
1791 | 42..55 '{ return 1; }': usize | ||
1792 | 44..52 'return 1': ! | ||
1793 | 51..52 '1': usize | ||
1794 | "#]], | ||
1795 | ); | ||
1796 | } | ||
1797 | |||
1798 | #[test] | ||
1799 | fn closure_return_unit() { | ||
1800 | check_infer( | ||
1801 | r#" | ||
1802 | fn foo() -> u32 { | ||
1803 | let x = || { return; }; | ||
1804 | } | ||
1805 | "#, | ||
1806 | expect![[r#" | ||
1807 | 16..47 '{ ...; }; }': () | ||
1808 | 26..27 'x': || -> () | ||
1809 | 30..44 '|| { return; }': || -> () | ||
1810 | 33..44 '{ return; }': () | ||
1811 | 35..41 'return': ! | ||
1812 | "#]], | ||
1813 | ); | ||
1814 | } | ||
1815 | |||
1816 | #[test] | ||
1817 | fn closure_return_inferred() { | ||
1818 | check_infer( | ||
1819 | r#" | ||
1820 | fn foo() -> u32 { | ||
1821 | let x = || { "test" }; | ||
1822 | } | ||
1823 | "#, | ||
1824 | expect![[r#" | ||
1825 | 16..46 '{ ..." }; }': () | ||
1826 | 26..27 'x': || -> &str | ||
1827 | 30..43 '|| { "test" }': || -> &str | ||
1828 | 33..43 '{ "test" }': &str | ||
1829 | 35..41 '"test"': &str | ||
1830 | "#]], | ||
1831 | ); | ||
1832 | } | ||
1833 | |||
1834 | #[test] | ||
1835 | fn fn_pointer_return() { | ||
1836 | check_infer( | ||
1837 | r#" | ||
1838 | struct Vtable { | ||
1839 | method: fn(), | ||
1840 | } | ||
1841 | |||
1842 | fn main() { | ||
1843 | let vtable = Vtable { method: || {} }; | ||
1844 | let m = vtable.method; | ||
1845 | } | ||
1846 | "#, | ||
1847 | expect![[r#" | ||
1848 | 47..120 '{ ...hod; }': () | ||
1849 | 57..63 'vtable': Vtable | ||
1850 | 66..90 'Vtable...| {} }': Vtable | ||
1851 | 83..88 '|| {}': || -> () | ||
1852 | 86..88 '{}': () | ||
1853 | 100..101 'm': fn() | ||
1854 | 104..110 'vtable': Vtable | ||
1855 | 104..117 'vtable.method': fn() | ||
1856 | "#]], | ||
1857 | ); | ||
1858 | } | ||
1859 | |||
1860 | #[test] | ||
1861 | fn effects_smoke_test() { | ||
1862 | check_infer( | ||
1863 | r#" | ||
1864 | fn main() { | ||
1865 | let x = unsafe { 92 }; | ||
1866 | let y = async { async { () }.await }; | ||
1867 | let z = try { () }; | ||
1868 | let t = 'a: { 92 }; | ||
1869 | } | ||
1870 | "#, | ||
1871 | expect![[r#" | ||
1872 | 10..130 '{ ...2 }; }': () | ||
1873 | 20..21 'x': i32 | ||
1874 | 24..37 'unsafe { 92 }': i32 | ||
1875 | 31..37 '{ 92 }': i32 | ||
1876 | 33..35 '92': i32 | ||
1877 | 47..48 'y': {unknown} | ||
1878 | 57..79 '{ asyn...wait }': {unknown} | ||
1879 | 59..77 'async ....await': {unknown} | ||
1880 | 65..71 '{ () }': () | ||
1881 | 67..69 '()': () | ||
1882 | 89..90 'z': {unknown} | ||
1883 | 93..103 'try { () }': {unknown} | ||
1884 | 97..103 '{ () }': () | ||
1885 | 99..101 '()': () | ||
1886 | 113..114 't': i32 | ||
1887 | 121..127 '{ 92 }': i32 | ||
1888 | 123..125 '92': i32 | ||
1889 | "#]], | ||
1890 | ) | ||
1891 | } | ||
1892 | |||
1893 | #[test] | ||
1894 | fn infer_generic_from_later_assignment() { | ||
1895 | check_infer( | ||
1896 | r#" | ||
1897 | enum Option<T> { Some(T), None } | ||
1898 | use Option::*; | ||
1899 | |||
1900 | fn test() { | ||
1901 | let mut end = None; | ||
1902 | loop { | ||
1903 | end = Some(true); | ||
1904 | } | ||
1905 | } | ||
1906 | "#, | ||
1907 | expect![[r#" | ||
1908 | 59..129 '{ ... } }': () | ||
1909 | 69..76 'mut end': Option<bool> | ||
1910 | 79..83 'None': Option<bool> | ||
1911 | 89..127 'loop {... }': ! | ||
1912 | 94..127 '{ ... }': () | ||
1913 | 104..107 'end': Option<bool> | ||
1914 | 104..120 'end = ...(true)': () | ||
1915 | 110..114 'Some': Some<bool>(bool) -> Option<bool> | ||
1916 | 110..120 'Some(true)': Option<bool> | ||
1917 | 115..119 'true': bool | ||
1918 | "#]], | ||
1919 | ); | ||
1920 | } | ||
1921 | |||
1922 | #[test] | ||
1923 | fn infer_loop_break_with_val() { | ||
1924 | check_infer( | ||
1925 | r#" | ||
1926 | enum Option<T> { Some(T), None } | ||
1927 | use Option::*; | ||
1928 | |||
1929 | fn test() { | ||
1930 | let x = loop { | ||
1931 | if false { | ||
1932 | break None; | ||
1933 | } | ||
1934 | |||
1935 | break Some(true); | ||
1936 | }; | ||
1937 | } | ||
1938 | "#, | ||
1939 | expect![[r#" | ||
1940 | 59..168 '{ ... }; }': () | ||
1941 | 69..70 'x': Option<bool> | ||
1942 | 73..165 'loop {... }': Option<bool> | ||
1943 | 78..165 '{ ... }': () | ||
1944 | 88..132 'if fal... }': () | ||
1945 | 91..96 'false': bool | ||
1946 | 97..132 '{ ... }': () | ||
1947 | 111..121 'break None': ! | ||
1948 | 117..121 'None': Option<bool> | ||
1949 | 142..158 'break ...(true)': ! | ||
1950 | 148..152 'Some': Some<bool>(bool) -> Option<bool> | ||
1951 | 148..158 'Some(true)': Option<bool> | ||
1952 | 153..157 'true': bool | ||
1953 | "#]], | ||
1954 | ); | ||
1955 | } | ||
1956 | |||
1957 | #[test] | ||
1958 | fn infer_loop_break_without_val() { | ||
1959 | check_infer( | ||
1960 | r#" | ||
1961 | enum Option<T> { Some(T), None } | ||
1962 | use Option::*; | ||
1963 | |||
1964 | fn test() { | ||
1965 | let x = loop { | ||
1966 | if false { | ||
1967 | break; | ||
1968 | } | ||
1969 | }; | ||
1970 | } | ||
1971 | "#, | ||
1972 | expect![[r#" | ||
1973 | 59..136 '{ ... }; }': () | ||
1974 | 69..70 'x': () | ||
1975 | 73..133 'loop {... }': () | ||
1976 | 78..133 '{ ... }': () | ||
1977 | 88..127 'if fal... }': () | ||
1978 | 91..96 'false': bool | ||
1979 | 97..127 '{ ... }': () | ||
1980 | 111..116 'break': ! | ||
1981 | "#]], | ||
1982 | ); | ||
1983 | } | ||
1984 | |||
1985 | #[test] | ||
1986 | fn infer_labelled_break_with_val() { | ||
1987 | check_infer( | ||
1988 | r#" | ||
1989 | fn foo() { | ||
1990 | let _x = || 'outer: loop { | ||
1991 | let inner = 'inner: loop { | ||
1992 | let i = Default::default(); | ||
1993 | if (break 'outer i) { | ||
1994 | loop { break 'inner 5i8; }; | ||
1995 | } else if true { | ||
1996 | break 'inner 6; | ||
1997 | } | ||
1998 | break 7; | ||
1999 | }; | ||
2000 | break inner < 8; | ||
2001 | }; | ||
2002 | } | ||
2003 | "#, | ||
2004 | expect![[r#" | ||
2005 | 9..335 '{ ... }; }': () | ||
2006 | 19..21 '_x': || -> bool | ||
2007 | 24..332 '|| 'ou... }': || -> bool | ||
2008 | 27..332 ''outer... }': bool | ||
2009 | 40..332 '{ ... }': () | ||
2010 | 54..59 'inner': i8 | ||
2011 | 62..300 ''inner... }': i8 | ||
2012 | 75..300 '{ ... }': () | ||
2013 | 93..94 'i': bool | ||
2014 | 97..113 'Defaul...efault': {unknown} | ||
2015 | 97..115 'Defaul...ault()': bool | ||
2016 | 129..269 'if (br... }': () | ||
2017 | 133..147 'break 'outer i': ! | ||
2018 | 146..147 'i': bool | ||
2019 | 149..208 '{ ... }': () | ||
2020 | 167..193 'loop {...5i8; }': ! | ||
2021 | 172..193 '{ brea...5i8; }': () | ||
2022 | 174..190 'break ...er 5i8': ! | ||
2023 | 187..190 '5i8': i8 | ||
2024 | 214..269 'if tru... }': () | ||
2025 | 217..221 'true': bool | ||
2026 | 222..269 '{ ... }': () | ||
2027 | 240..254 'break 'inner 6': ! | ||
2028 | 253..254 '6': i8 | ||
2029 | 282..289 'break 7': ! | ||
2030 | 288..289 '7': i8 | ||
2031 | 310..325 'break inner < 8': ! | ||
2032 | 316..321 'inner': i8 | ||
2033 | 316..325 'inner < 8': bool | ||
2034 | 324..325 '8': i8 | ||
2035 | "#]], | ||
2036 | ); | ||
2037 | } | ||
2038 | |||
2039 | #[test] | ||
2040 | fn generic_default() { | ||
2041 | check_infer( | ||
2042 | r#" | ||
2043 | struct Thing<T = ()> { t: T } | ||
2044 | enum OtherThing<T = ()> { | ||
2045 | One { t: T }, | ||
2046 | Two(T), | ||
2047 | } | ||
2048 | |||
2049 | fn test(t1: Thing, t2: OtherThing, t3: Thing<i32>, t4: OtherThing<i32>) { | ||
2050 | t1.t; | ||
2051 | t3.t; | ||
2052 | match t2 { | ||
2053 | OtherThing::One { t } => { t; }, | ||
2054 | OtherThing::Two(t) => { t; }, | ||
2055 | } | ||
2056 | match t4 { | ||
2057 | OtherThing::One { t } => { t; }, | ||
2058 | OtherThing::Two(t) => { t; }, | ||
2059 | } | ||
2060 | } | ||
2061 | "#, | ||
2062 | expect![[r#" | ||
2063 | 97..99 't1': Thing<()> | ||
2064 | 108..110 't2': OtherThing<()> | ||
2065 | 124..126 't3': Thing<i32> | ||
2066 | 140..142 't4': OtherThing<i32> | ||
2067 | 161..384 '{ ... } }': () | ||
2068 | 167..169 't1': Thing<()> | ||
2069 | 167..171 't1.t': () | ||
2070 | 177..179 't3': Thing<i32> | ||
2071 | 177..181 't3.t': i32 | ||
2072 | 187..282 'match ... }': () | ||
2073 | 193..195 't2': OtherThing<()> | ||
2074 | 206..227 'OtherT... { t }': OtherThing<()> | ||
2075 | 224..225 't': () | ||
2076 | 231..237 '{ t; }': () | ||
2077 | 233..234 't': () | ||
2078 | 247..265 'OtherT...Two(t)': OtherThing<()> | ||
2079 | 263..264 't': () | ||
2080 | 269..275 '{ t; }': () | ||
2081 | 271..272 't': () | ||
2082 | 287..382 'match ... }': () | ||
2083 | 293..295 't4': OtherThing<i32> | ||
2084 | 306..327 'OtherT... { t }': OtherThing<i32> | ||
2085 | 324..325 't': i32 | ||
2086 | 331..337 '{ t; }': () | ||
2087 | 333..334 't': i32 | ||
2088 | 347..365 'OtherT...Two(t)': OtherThing<i32> | ||
2089 | 363..364 't': i32 | ||
2090 | 369..375 '{ t; }': () | ||
2091 | 371..372 't': i32 | ||
2092 | "#]], | ||
2093 | ); | ||
2094 | } | ||
2095 | |||
2096 | #[test] | ||
2097 | fn generic_default_in_struct_literal() { | ||
2098 | check_infer( | ||
2099 | r#" | ||
2100 | struct Thing<T = ()> { t: T } | ||
2101 | enum OtherThing<T = ()> { | ||
2102 | One { t: T }, | ||
2103 | Two(T), | ||
2104 | } | ||
2105 | |||
2106 | fn test() { | ||
2107 | let x = Thing { t: loop {} }; | ||
2108 | let y = Thing { t: () }; | ||
2109 | let z = Thing { t: 1i32 }; | ||
2110 | if let Thing { t } = z { | ||
2111 | t; | ||
2112 | } | ||
2113 | |||
2114 | let a = OtherThing::One { t: 1i32 }; | ||
2115 | let b = OtherThing::Two(1i32); | ||
2116 | } | ||
2117 | "#, | ||
2118 | expect![[r#" | ||
2119 | 99..319 '{ ...32); }': () | ||
2120 | 109..110 'x': Thing<!> | ||
2121 | 113..133 'Thing ...p {} }': Thing<!> | ||
2122 | 124..131 'loop {}': ! | ||
2123 | 129..131 '{}': () | ||
2124 | 143..144 'y': Thing<()> | ||
2125 | 147..162 'Thing { t: () }': Thing<()> | ||
2126 | 158..160 '()': () | ||
2127 | 172..173 'z': Thing<i32> | ||
2128 | 176..193 'Thing ...1i32 }': Thing<i32> | ||
2129 | 187..191 '1i32': i32 | ||
2130 | 199..240 'if let... }': () | ||
2131 | 206..217 'Thing { t }': Thing<i32> | ||
2132 | 214..215 't': i32 | ||
2133 | 220..221 'z': Thing<i32> | ||
2134 | 222..240 '{ ... }': () | ||
2135 | 232..233 't': i32 | ||
2136 | 250..251 'a': OtherThing<i32> | ||
2137 | 254..281 'OtherT...1i32 }': OtherThing<i32> | ||
2138 | 275..279 '1i32': i32 | ||
2139 | 291..292 'b': OtherThing<i32> | ||
2140 | 295..310 'OtherThing::Two': Two<i32>(i32) -> OtherThing<i32> | ||
2141 | 295..316 'OtherT...(1i32)': OtherThing<i32> | ||
2142 | 311..315 '1i32': i32 | ||
2143 | "#]], | ||
2144 | ); | ||
2145 | } | ||
2146 | |||
2147 | #[test] | ||
2148 | fn generic_default_depending_on_other_type_arg() { | ||
2149 | // FIXME: the {unknown} is a bug | ||
2150 | check_infer( | ||
2151 | r#" | ||
2152 | struct Thing<T = u128, F = fn() -> T> { t: T } | ||
2153 | |||
2154 | fn test(t1: Thing<u32>, t2: Thing) { | ||
2155 | t1; | ||
2156 | t2; | ||
2157 | Thing::<_> { t: 1u32 }; | ||
2158 | } | ||
2159 | "#, | ||
2160 | expect![[r#" | ||
2161 | 56..58 't1': Thing<u32, fn() -> u32> | ||
2162 | 72..74 't2': Thing<u128, fn() -> u128> | ||
2163 | 83..130 '{ ...2 }; }': () | ||
2164 | 89..91 't1': Thing<u32, fn() -> u32> | ||
2165 | 97..99 't2': Thing<u128, fn() -> u128> | ||
2166 | 105..127 'Thing:...1u32 }': Thing<u32, fn() -> {unknown}> | ||
2167 | 121..125 '1u32': u32 | ||
2168 | "#]], | ||
2169 | ); | ||
2170 | } | ||
2171 | |||
2172 | #[test] | ||
2173 | fn generic_default_depending_on_other_type_arg_forward() { | ||
2174 | // the {unknown} here is intentional, as defaults are not allowed to | ||
2175 | // refer to type parameters coming later | ||
2176 | check_infer( | ||
2177 | r#" | ||
2178 | struct Thing<F = fn() -> T, T = u128> { t: T } | ||
2179 | |||
2180 | fn test(t1: Thing) { | ||
2181 | t1; | ||
2182 | } | ||
2183 | "#, | ||
2184 | expect![[r#" | ||
2185 | 56..58 't1': Thing<fn() -> {unknown}, u128> | ||
2186 | 67..78 '{ t1; }': () | ||
2187 | 73..75 't1': Thing<fn() -> {unknown}, u128> | ||
2188 | "#]], | ||
2189 | ); | ||
2190 | } | ||