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