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