]>
Commit | Line | Data |
---|---|---|
064997fb FG |
1 | use cov_mark::check; |
2 | use expect_test::expect; | |
3 | ||
4 | use super::{check, check_infer, check_infer_with_mismatches, check_no_mismatches, check_types}; | |
5 | ||
6 | #[test] | |
7 | fn infer_await() { | |
8 | check_types( | |
9 | r#" | |
10 | //- minicore: future | |
11 | struct IntFuture; | |
12 | ||
13 | impl core::future::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 | ); | |
24 | } | |
25 | ||
26 | #[test] | |
27 | fn infer_async() { | |
28 | check_types( | |
29 | r#" | |
30 | //- minicore: future | |
31 | async fn foo() -> u64 { 128 } | |
32 | ||
33 | fn test() { | |
34 | let r = foo(); | |
35 | let v = r.await; | |
36 | v; | |
37 | } //^ u64 | |
38 | "#, | |
39 | ); | |
40 | } | |
41 | ||
42 | #[test] | |
43 | fn infer_desugar_async() { | |
44 | check_types( | |
45 | r#" | |
46 | //- minicore: future, sized | |
47 | async fn foo() -> u64 { 128 } | |
48 | ||
49 | fn test() { | |
50 | let r = foo(); | |
51 | r; | |
52 | } //^ impl Future<Output = u64> | |
53 | "#, | |
54 | ); | |
55 | } | |
56 | ||
57 | #[test] | |
58 | fn infer_async_block() { | |
59 | check_types( | |
60 | r#" | |
61 | //- minicore: future, option | |
62 | async fn test() { | |
63 | let a = async { 42 }; | |
64 | a; | |
65 | // ^ impl Future<Output = i32> | |
66 | let x = a.await; | |
67 | x; | |
68 | // ^ i32 | |
69 | let b = async {}.await; | |
70 | b; | |
71 | // ^ () | |
72 | let c = async { | |
73 | let y = None; | |
74 | y | |
75 | // ^ Option<u64> | |
76 | }; | |
77 | let _: Option<u64> = c.await; | |
78 | c; | |
79 | // ^ impl Future<Output = Option<u64>> | |
80 | } | |
81 | "#, | |
82 | ); | |
83 | } | |
84 | ||
85 | #[test] | |
86 | fn auto_sized_async_block() { | |
87 | check_no_mismatches( | |
88 | r#" | |
89 | //- minicore: future, sized | |
90 | ||
91 | use core::future::Future; | |
92 | struct MyFut<Fut>(Fut); | |
93 | ||
94 | impl<Fut> Future for MyFut<Fut> | |
95 | where Fut: Future | |
96 | { | |
97 | type Output = Fut::Output; | |
98 | } | |
99 | async fn reproduction() -> usize { | |
100 | let f = async {999usize}; | |
101 | MyFut(f).await | |
102 | } | |
103 | "#, | |
104 | ); | |
105 | check_no_mismatches( | |
106 | r#" | |
107 | //- minicore: future | |
108 | //#11815 | |
109 | #[lang = "sized"] | |
110 | pub trait Sized {} | |
111 | ||
112 | #[lang = "unsize"] | |
113 | pub trait Unsize<T: ?Sized> {} | |
114 | ||
115 | #[lang = "coerce_unsized"] | |
116 | pub trait CoerceUnsized<T> {} | |
117 | ||
118 | pub unsafe trait Allocator {} | |
119 | ||
120 | pub struct Global; | |
121 | unsafe impl Allocator for Global {} | |
122 | ||
123 | #[lang = "owned_box"] | |
124 | #[fundamental] | |
125 | pub struct Box<T: ?Sized, A: Allocator = Global>; | |
126 | ||
127 | impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Box<U, A>> for Box<T, A> {} | |
128 | ||
129 | fn send() -> Box<dyn Future<Output = ()> + Send + 'static>{ | |
130 | box async move {} | |
131 | } | |
132 | ||
133 | fn not_send() -> Box<dyn Future<Output = ()> + 'static> { | |
134 | box async move {} | |
135 | } | |
136 | "#, | |
137 | ); | |
138 | } | |
139 | ||
f2b60f7d FG |
140 | #[test] |
141 | fn into_future_trait() { | |
142 | check_types( | |
143 | r#" | |
144 | //- minicore: future | |
145 | struct Futurable; | |
146 | impl core::future::IntoFuture for Futurable { | |
147 | type Output = u64; | |
148 | type IntoFuture = IntFuture; | |
149 | } | |
150 | ||
151 | struct IntFuture; | |
152 | impl core::future::Future for IntFuture { | |
153 | type Output = u64; | |
154 | } | |
155 | ||
156 | fn test() { | |
157 | let r = Futurable; | |
158 | let v = r.await; | |
159 | v; | |
160 | } //^ u64 | |
161 | "#, | |
162 | ); | |
163 | } | |
164 | ||
064997fb FG |
165 | #[test] |
166 | fn infer_try() { | |
167 | check_types( | |
168 | r#" | |
169 | //- /main.rs crate:main deps:core | |
170 | fn test() { | |
171 | let r: Result<i32, u64> = Result::Ok(1); | |
172 | let v = r?; | |
173 | v; | |
174 | } //^ i32 | |
175 | ||
176 | //- /core.rs crate:core | |
177 | pub mod ops { | |
178 | pub trait Try { | |
179 | type Ok; | |
180 | type Error; | |
181 | } | |
182 | } | |
183 | ||
184 | pub mod result { | |
185 | pub enum Result<O, E> { | |
186 | Ok(O), | |
187 | Err(E) | |
188 | } | |
189 | ||
190 | impl<O, E> crate::ops::Try for Result<O, E> { | |
191 | type Ok = O; | |
192 | type Error = E; | |
193 | } | |
194 | } | |
195 | ||
196 | pub mod prelude { | |
197 | pub mod rust_2018 { | |
198 | pub use crate::{result::*, ops::*}; | |
199 | } | |
200 | } | |
201 | "#, | |
202 | ); | |
203 | } | |
204 | ||
205 | #[test] | |
206 | fn infer_try_trait_v2() { | |
207 | check_types( | |
208 | r#" | |
209 | //- /main.rs crate:main deps:core | |
210 | fn test() { | |
211 | let r: Result<i32, u64> = Result::Ok(1); | |
212 | let v = r?; | |
213 | v; | |
214 | } //^ i32 | |
215 | ||
216 | //- /core.rs crate:core | |
217 | mod ops { | |
218 | mod try_trait { | |
219 | pub trait Try: FromResidual { | |
220 | type Output; | |
221 | type Residual; | |
222 | } | |
223 | pub trait FromResidual<R = <Self as Try>::Residual> {} | |
224 | } | |
225 | ||
226 | pub use self::try_trait::FromResidual; | |
227 | pub use self::try_trait::Try; | |
228 | } | |
229 | ||
230 | mod convert { | |
231 | pub trait From<T> {} | |
232 | impl<T> From<T> for T {} | |
233 | } | |
234 | ||
235 | pub mod result { | |
236 | use crate::convert::From; | |
237 | use crate::ops::{Try, FromResidual}; | |
238 | ||
239 | pub enum Infallible {} | |
240 | pub enum Result<O, E> { | |
241 | Ok(O), | |
242 | Err(E) | |
243 | } | |
244 | ||
245 | impl<O, E> Try for Result<O, E> { | |
246 | type Output = O; | |
247 | type Error = Result<Infallible, E>; | |
248 | } | |
249 | ||
250 | impl<T, E, F: From<E>> FromResidual<Result<Infallible, E>> for Result<T, F> {} | |
251 | } | |
252 | ||
253 | pub mod prelude { | |
254 | pub mod rust_2018 { | |
255 | pub use crate::result::*; | |
256 | } | |
257 | } | |
258 | "#, | |
259 | ); | |
260 | } | |
261 | ||
262 | #[test] | |
263 | fn infer_for_loop() { | |
264 | check_types( | |
265 | r#" | |
266 | //- /main.rs crate:main deps:core,alloc | |
267 | #![no_std] | |
268 | use alloc::collections::Vec; | |
269 | ||
270 | fn test() { | |
271 | let v = Vec::new(); | |
272 | v.push("foo"); | |
273 | for x in v { | |
274 | x; | |
275 | } //^ &str | |
276 | } | |
277 | ||
278 | //- /core.rs crate:core | |
279 | pub mod iter { | |
280 | pub trait IntoIterator { | |
281 | type Item; | |
2b03887a FG |
282 | type IntoIter: Iterator<Item = Self::Item>; |
283 | } | |
284 | pub trait Iterator { | |
285 | type Item; | |
064997fb FG |
286 | } |
287 | } | |
288 | pub mod prelude { | |
289 | pub mod rust_2018 { | |
290 | pub use crate::iter::*; | |
291 | } | |
292 | } | |
293 | ||
294 | //- /alloc.rs crate:alloc deps:core | |
295 | #![no_std] | |
296 | pub mod collections { | |
297 | pub struct Vec<T> {} | |
298 | impl<T> Vec<T> { | |
299 | pub fn new() -> Self { Vec {} } | |
300 | pub fn push(&mut self, t: T) { } | |
301 | } | |
302 | ||
303 | impl<T> IntoIterator for Vec<T> { | |
2b03887a FG |
304 | type Item = T; |
305 | type IntoIter = IntoIter<T>; | |
306 | } | |
307 | ||
308 | struct IntoIter<T> {} | |
309 | impl<T> Iterator for IntoIter<T> { | |
310 | type Item = T; | |
064997fb FG |
311 | } |
312 | } | |
313 | "#, | |
314 | ); | |
315 | } | |
316 | ||
317 | #[test] | |
318 | fn infer_ops_neg() { | |
319 | check_types( | |
320 | r#" | |
321 | //- /main.rs crate:main deps:std | |
322 | struct Bar; | |
323 | struct Foo; | |
324 | ||
325 | impl std::ops::Neg for Bar { | |
326 | type Output = Foo; | |
327 | } | |
328 | ||
329 | fn test() { | |
330 | let a = Bar; | |
331 | let b = -a; | |
332 | b; | |
333 | } //^ Foo | |
334 | ||
335 | //- /std.rs crate:std | |
336 | #[prelude_import] use ops::*; | |
337 | mod ops { | |
338 | #[lang = "neg"] | |
339 | pub trait Neg { | |
340 | type Output; | |
341 | } | |
342 | } | |
343 | "#, | |
344 | ); | |
345 | } | |
346 | ||
347 | #[test] | |
348 | fn infer_ops_not() { | |
349 | check_types( | |
350 | r#" | |
351 | //- /main.rs crate:main deps:std | |
352 | struct Bar; | |
353 | struct Foo; | |
354 | ||
355 | impl std::ops::Not for Bar { | |
356 | type Output = Foo; | |
357 | } | |
358 | ||
359 | fn test() { | |
360 | let a = Bar; | |
361 | let b = !a; | |
362 | b; | |
363 | } //^ Foo | |
364 | ||
365 | //- /std.rs crate:std | |
366 | #[prelude_import] use ops::*; | |
367 | mod ops { | |
368 | #[lang = "not"] | |
369 | pub trait Not { | |
370 | type Output; | |
371 | } | |
372 | } | |
373 | "#, | |
374 | ); | |
375 | } | |
376 | ||
377 | #[test] | |
378 | fn infer_from_bound_1() { | |
379 | check_types( | |
380 | r#" | |
381 | trait Trait<T> {} | |
382 | struct S<T>(T); | |
383 | impl<U> Trait<U> for S<U> {} | |
384 | fn foo<T: Trait<u32>>(t: T) {} | |
385 | fn test() { | |
386 | let s = S(unknown); | |
387 | // ^^^^^^^ u32 | |
388 | foo(s); | |
389 | }"#, | |
390 | ); | |
391 | } | |
392 | ||
393 | #[test] | |
394 | fn infer_from_bound_2() { | |
395 | check_types( | |
396 | r#" | |
397 | trait Trait<T> {} | |
398 | struct S<T>(T); | |
399 | impl<U> Trait<U> for S<U> {} | |
400 | fn foo<U, T: Trait<U>>(t: T) -> U { loop {} } | |
401 | fn test() { | |
402 | let s = S(unknown); | |
403 | // ^^^^^^^ u32 | |
404 | let x: u32 = foo(s); | |
405 | }"#, | |
406 | ); | |
407 | } | |
408 | ||
409 | #[test] | |
410 | fn trait_default_method_self_bound_implements_trait() { | |
411 | cov_mark::check!(trait_self_implements_self); | |
412 | check( | |
413 | r#" | |
414 | trait Trait { | |
415 | fn foo(&self) -> i64; | |
416 | fn bar(&self) -> () { | |
417 | self.foo(); | |
418 | // ^^^^^^^^^^ type: i64 | |
419 | } | |
420 | }"#, | |
421 | ); | |
422 | } | |
423 | ||
424 | #[test] | |
425 | fn trait_default_method_self_bound_implements_super_trait() { | |
426 | check( | |
427 | r#" | |
428 | trait SuperTrait { | |
429 | fn foo(&self) -> i64; | |
430 | } | |
431 | trait Trait: SuperTrait { | |
432 | fn bar(&self) -> () { | |
433 | self.foo(); | |
434 | // ^^^^^^^^^^ type: i64 | |
435 | } | |
436 | }"#, | |
437 | ); | |
438 | } | |
439 | ||
440 | #[test] | |
441 | fn infer_project_associated_type() { | |
442 | check_types( | |
443 | r#" | |
444 | trait Iterable { | |
445 | type Item; | |
446 | } | |
447 | struct S; | |
448 | impl Iterable for S { type Item = u32; } | |
449 | fn test<T: Iterable>() { | |
450 | let x: <S as Iterable>::Item = 1; | |
451 | // ^ u32 | |
452 | let y: <T as Iterable>::Item = u; | |
453 | // ^ Iterable::Item<T> | |
454 | let z: T::Item = u; | |
455 | // ^ Iterable::Item<T> | |
456 | let a: <T>::Item = u; | |
457 | // ^ Iterable::Item<T> | |
458 | }"#, | |
459 | ); | |
460 | } | |
461 | ||
462 | #[test] | |
463 | fn infer_return_associated_type() { | |
464 | check_types( | |
465 | r#" | |
466 | trait Iterable { | |
467 | type Item; | |
468 | } | |
469 | struct S; | |
470 | impl Iterable for S { type Item = u32; } | |
471 | fn foo1<T: Iterable>(t: T) -> T::Item { loop {} } | |
472 | fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item { loop {} } | |
473 | fn foo3<T: Iterable>(t: T) -> <T>::Item { loop {} } | |
474 | fn test() { | |
475 | foo1(S); | |
476 | // ^^^^^^^ u32 | |
477 | foo2(S); | |
478 | // ^^^^^^^ u32 | |
479 | foo3(S); | |
480 | // ^^^^^^^ u32 | |
481 | }"#, | |
482 | ); | |
483 | } | |
484 | ||
485 | #[test] | |
486 | fn associated_type_shorthand_from_method_bound() { | |
487 | check_types( | |
488 | r#" | |
489 | trait Iterable { | |
490 | type Item; | |
491 | } | |
492 | struct S<T>; | |
493 | impl<T> S<T> { | |
494 | fn foo(self) -> T::Item where T: Iterable { loop {} } | |
495 | } | |
496 | fn test<T: Iterable>() { | |
497 | let s: S<T>; | |
498 | s.foo(); | |
499 | // ^^^^^^^ Iterable::Item<T> | |
500 | }"#, | |
501 | ); | |
502 | } | |
503 | ||
504 | #[test] | |
505 | fn associated_type_shorthand_from_self_issue_12484() { | |
506 | check_types( | |
507 | r#" | |
508 | trait Bar { | |
509 | type A; | |
510 | } | |
511 | trait Foo { | |
512 | type A; | |
513 | fn test(a: Self::A, _: impl Bar) { | |
514 | a; | |
515 | //^ Foo::A<Self> | |
516 | } | |
517 | }"#, | |
518 | ); | |
519 | } | |
520 | ||
521 | #[test] | |
522 | fn infer_associated_type_bound() { | |
523 | check_types( | |
524 | r#" | |
525 | trait Iterable { | |
526 | type Item; | |
527 | } | |
528 | fn test<T: Iterable<Item=u32>>() { | |
529 | let y: T::Item = unknown; | |
530 | // ^^^^^^^ u32 | |
531 | }"#, | |
532 | ); | |
533 | } | |
534 | ||
535 | #[test] | |
536 | fn infer_const_body() { | |
537 | // FIXME make check_types work with other bodies | |
538 | check_infer( | |
539 | r#" | |
540 | const A: u32 = 1 + 1; | |
541 | static B: u64 = { let x = 1; x }; | |
542 | "#, | |
543 | expect![[r#" | |
544 | 15..16 '1': u32 | |
545 | 15..20 '1 + 1': u32 | |
546 | 19..20 '1': u32 | |
547 | 38..54 '{ let ...1; x }': u64 | |
548 | 44..45 'x': u64 | |
549 | 48..49 '1': u64 | |
550 | 51..52 'x': u64 | |
551 | "#]], | |
552 | ); | |
553 | } | |
554 | ||
555 | #[test] | |
556 | fn tuple_struct_fields() { | |
557 | check_infer( | |
558 | r#" | |
559 | struct S(i32, u64); | |
560 | fn test() -> u64 { | |
561 | let a = S(4, 6); | |
562 | let b = a.0; | |
563 | a.1 | |
564 | }"#, | |
565 | expect![[r#" | |
566 | 37..86 '{ ... a.1 }': u64 | |
567 | 47..48 'a': S | |
568 | 51..52 'S': S(i32, u64) -> S | |
569 | 51..58 'S(4, 6)': S | |
570 | 53..54 '4': i32 | |
571 | 56..57 '6': u64 | |
572 | 68..69 'b': i32 | |
573 | 72..73 'a': S | |
574 | 72..75 'a.0': i32 | |
575 | 81..82 'a': S | |
576 | 81..84 'a.1': u64 | |
577 | "#]], | |
578 | ); | |
579 | } | |
580 | ||
581 | #[test] | |
582 | fn tuple_struct_with_fn() { | |
583 | check_infer( | |
584 | r#" | |
585 | struct S(fn(u32) -> u64); | |
586 | fn test() -> u64 { | |
587 | let a = S(|i| 2*i); | |
588 | let b = a.0(4); | |
589 | a.0(2) | |
590 | }"#, | |
591 | expect![[r#" | |
592 | 43..101 '{ ...0(2) }': u64 | |
593 | 53..54 'a': S | |
594 | 57..58 'S': S(fn(u32) -> u64) -> S | |
595 | 57..67 'S(|i| 2*i)': S | |
596 | 59..66 '|i| 2*i': |u32| -> u64 | |
597 | 60..61 'i': u32 | |
598 | 63..64 '2': u32 | |
599 | 63..66 '2*i': u32 | |
600 | 65..66 'i': u32 | |
601 | 77..78 'b': u64 | |
602 | 81..82 'a': S | |
603 | 81..84 'a.0': fn(u32) -> u64 | |
604 | 81..87 'a.0(4)': u64 | |
605 | 85..86 '4': u32 | |
606 | 93..94 'a': S | |
607 | 93..96 'a.0': fn(u32) -> u64 | |
608 | 93..99 'a.0(2)': u64 | |
609 | 97..98 '2': u32 | |
610 | "#]], | |
611 | ); | |
612 | } | |
613 | ||
614 | #[test] | |
615 | fn indexing_arrays() { | |
616 | check_infer( | |
617 | "fn main() { &mut [9][2]; }", | |
618 | expect![[r#" | |
619 | 10..26 '{ &mut...[2]; }': () | |
620 | 12..23 '&mut [9][2]': &mut {unknown} | |
621 | 17..20 '[9]': [i32; 1] | |
622 | 17..23 '[9][2]': {unknown} | |
623 | 18..19 '9': i32 | |
624 | 21..22 '2': i32 | |
625 | "#]], | |
626 | ) | |
627 | } | |
628 | ||
629 | #[test] | |
630 | fn infer_ops_index() { | |
631 | check_types( | |
632 | r#" | |
633 | //- minicore: index | |
634 | struct Bar; | |
635 | struct Foo; | |
636 | ||
637 | impl core::ops::Index<u32> for Bar { | |
638 | type Output = Foo; | |
639 | } | |
640 | ||
641 | fn test() { | |
642 | let a = Bar; | |
643 | let b = a[1u32]; | |
644 | b; | |
645 | } //^ Foo | |
646 | "#, | |
647 | ); | |
648 | } | |
649 | ||
650 | #[test] | |
651 | fn infer_ops_index_field() { | |
652 | check_types( | |
653 | r#" | |
654 | //- minicore: index | |
655 | struct Bar; | |
656 | struct Foo { | |
657 | field: u32; | |
658 | } | |
659 | ||
660 | impl core::ops::Index<u32> for Bar { | |
661 | type Output = Foo; | |
662 | } | |
663 | ||
664 | fn test() { | |
665 | let a = Bar; | |
666 | let b = a[1u32].field; | |
667 | b; | |
668 | } //^ u32 | |
669 | "#, | |
670 | ); | |
671 | } | |
672 | ||
673 | #[test] | |
674 | fn infer_ops_index_field_autoderef() { | |
675 | check_types( | |
676 | r#" | |
677 | //- minicore: index | |
678 | struct Bar; | |
679 | struct Foo { | |
680 | field: u32; | |
681 | } | |
682 | ||
683 | impl core::ops::Index<u32> for Bar { | |
684 | type Output = Foo; | |
685 | } | |
686 | ||
687 | fn test() { | |
688 | let a = Bar; | |
689 | let b = (&a[1u32]).field; | |
690 | b; | |
691 | } //^ u32 | |
692 | "#, | |
693 | ); | |
694 | } | |
695 | ||
696 | #[test] | |
697 | fn infer_ops_index_int() { | |
698 | check_types( | |
699 | r#" | |
700 | //- minicore: index | |
701 | struct Bar; | |
702 | struct Foo; | |
703 | ||
704 | impl core::ops::Index<u32> for Bar { | |
705 | type Output = Foo; | |
706 | } | |
707 | ||
708 | struct Range; | |
709 | impl core::ops::Index<Range> for Bar { | |
710 | type Output = Bar; | |
711 | } | |
712 | ||
713 | fn test() { | |
714 | let a = Bar; | |
715 | let b = a[1]; | |
716 | b; | |
717 | //^ Foo | |
718 | } | |
719 | "#, | |
720 | ); | |
721 | } | |
722 | ||
723 | #[test] | |
724 | fn infer_ops_index_autoderef() { | |
725 | check_types( | |
726 | r#" | |
727 | //- minicore: index, slice | |
728 | fn test() { | |
729 | let a = &[1u32, 2, 3]; | |
730 | let b = a[1]; | |
731 | b; | |
732 | } //^ u32 | |
733 | "#, | |
734 | ); | |
735 | } | |
736 | ||
737 | #[test] | |
738 | fn deref_trait() { | |
739 | check_types( | |
740 | r#" | |
741 | //- minicore: deref | |
742 | struct Arc<T: ?Sized>; | |
743 | impl<T: ?Sized> core::ops::Deref for Arc<T> { | |
744 | type Target = T; | |
745 | } | |
746 | ||
747 | struct S; | |
748 | impl S { | |
749 | fn foo(&self) -> u128 { 0 } | |
750 | } | |
751 | ||
752 | fn test(s: Arc<S>) { | |
753 | (*s, s.foo()); | |
754 | } //^^^^^^^^^^^^^ (S, u128) | |
755 | "#, | |
756 | ); | |
757 | } | |
758 | ||
759 | #[test] | |
760 | fn deref_trait_with_inference_var() { | |
761 | check_types( | |
762 | r#" | |
763 | //- minicore: deref | |
764 | struct Arc<T: ?Sized>; | |
765 | fn new_arc<T: ?Sized>() -> Arc<T> { Arc } | |
766 | impl<T: ?Sized> core::ops::Deref for Arc<T> { | |
767 | type Target = T; | |
768 | } | |
769 | ||
770 | struct S; | |
771 | fn foo(a: Arc<S>) {} | |
772 | ||
773 | fn test() { | |
774 | let a = new_arc(); | |
775 | let b = *a; | |
776 | //^^ S | |
777 | foo(a); | |
778 | } | |
779 | "#, | |
780 | ); | |
781 | } | |
782 | ||
783 | #[test] | |
784 | fn deref_trait_infinite_recursion() { | |
785 | check_types( | |
786 | r#" | |
787 | //- minicore: deref | |
788 | struct S; | |
789 | ||
790 | impl core::ops::Deref for S { | |
791 | type Target = S; | |
792 | } | |
793 | ||
794 | fn test(s: S) { | |
795 | s.foo(); | |
796 | } //^^^^^^^ {unknown} | |
797 | "#, | |
798 | ); | |
799 | } | |
800 | ||
801 | #[test] | |
802 | fn deref_trait_with_question_mark_size() { | |
803 | check_types( | |
804 | r#" | |
805 | //- minicore: deref | |
806 | struct Arc<T: ?Sized>; | |
807 | impl<T: ?Sized> core::ops::Deref for Arc<T> { | |
808 | type Target = T; | |
809 | } | |
810 | ||
811 | struct S; | |
812 | impl S { | |
813 | fn foo(&self) -> u128 { 0 } | |
814 | } | |
815 | ||
816 | fn test(s: Arc<S>) { | |
817 | (*s, s.foo()); | |
818 | } //^^^^^^^^^^^^^ (S, u128) | |
819 | "#, | |
820 | ); | |
821 | } | |
822 | ||
823 | #[test] | |
824 | fn deref_trait_with_implicit_sized_requirement_on_inference_var() { | |
825 | check_types( | |
826 | r#" | |
827 | //- minicore: deref | |
828 | struct Foo<T>; | |
829 | impl<T> core::ops::Deref for Foo<T> { | |
830 | type Target = (); | |
831 | } | |
832 | fn test() { | |
833 | let foo = Foo; | |
834 | *foo; | |
835 | //^^^^ () | |
836 | let _: Foo<u8> = foo; | |
837 | } | |
838 | "#, | |
839 | ) | |
840 | } | |
841 | ||
842 | #[test] | |
843 | fn obligation_from_function_clause() { | |
844 | check_types( | |
845 | r#" | |
846 | struct S; | |
847 | ||
848 | trait Trait<T> {} | |
849 | impl Trait<u32> for S {} | |
850 | ||
851 | fn foo<T: Trait<U>, U>(t: T) -> U { loop {} } | |
852 | ||
853 | fn test(s: S) { | |
854 | foo(s); | |
855 | } //^^^^^^ u32 | |
856 | "#, | |
857 | ); | |
858 | } | |
859 | ||
860 | #[test] | |
861 | fn obligation_from_method_clause() { | |
862 | check_types( | |
863 | r#" | |
864 | //- /main.rs | |
865 | struct S; | |
866 | ||
867 | trait Trait<T> {} | |
868 | impl Trait<isize> for S {} | |
869 | ||
870 | struct O; | |
871 | impl O { | |
872 | fn foo<T: Trait<U>, U>(&self, t: T) -> U { loop {} } | |
873 | } | |
874 | ||
875 | fn test() { | |
876 | O.foo(S); | |
877 | } //^^^^^^^^ isize | |
878 | "#, | |
879 | ); | |
880 | } | |
881 | ||
882 | #[test] | |
883 | fn obligation_from_self_method_clause() { | |
884 | check_types( | |
885 | r#" | |
886 | struct S; | |
887 | ||
888 | trait Trait<T> {} | |
889 | impl Trait<i64> for S {} | |
890 | ||
891 | impl S { | |
892 | fn foo<U>(&self) -> U where Self: Trait<U> { loop {} } | |
893 | } | |
894 | ||
895 | fn test() { | |
896 | S.foo(); | |
897 | } //^^^^^^^ i64 | |
898 | "#, | |
899 | ); | |
900 | } | |
901 | ||
902 | #[test] | |
903 | fn obligation_from_impl_clause() { | |
904 | check_types( | |
905 | r#" | |
906 | struct S; | |
907 | ||
908 | trait Trait<T> {} | |
909 | impl Trait<&str> for S {} | |
910 | ||
911 | struct O<T>; | |
912 | impl<U, T: Trait<U>> O<T> { | |
913 | fn foo(&self) -> U { loop {} } | |
914 | } | |
915 | ||
916 | fn test(o: O<S>) { | |
917 | o.foo(); | |
918 | } //^^^^^^^ &str | |
919 | "#, | |
920 | ); | |
921 | } | |
922 | ||
923 | #[test] | |
924 | fn generic_param_env_1() { | |
925 | check_types( | |
926 | r#" | |
927 | trait Clone {} | |
928 | trait Trait { fn foo(self) -> u128; } | |
929 | struct S; | |
930 | impl Clone for S {} | |
931 | impl<T> Trait for T where T: Clone {} | |
932 | fn test<T: Clone>(t: T) { t.foo(); } | |
933 | //^^^^^^^ u128 | |
934 | "#, | |
935 | ); | |
936 | } | |
937 | ||
938 | #[test] | |
939 | fn generic_param_env_1_not_met() { | |
940 | check_types( | |
941 | r#" | |
942 | //- /main.rs | |
943 | trait Clone {} | |
944 | trait Trait { fn foo(self) -> u128; } | |
945 | struct S; | |
946 | impl Clone for S {} | |
947 | impl<T> Trait for T where T: Clone {} | |
948 | fn test<T>(t: T) { t.foo(); } | |
949 | //^^^^^^^ {unknown} | |
950 | "#, | |
951 | ); | |
952 | } | |
953 | ||
954 | #[test] | |
955 | fn generic_param_env_2() { | |
956 | check_types( | |
957 | r#" | |
958 | trait Trait { fn foo(self) -> u128; } | |
959 | struct S; | |
960 | impl Trait for S {} | |
961 | fn test<T: Trait>(t: T) { t.foo(); } | |
962 | //^^^^^^^ u128 | |
963 | "#, | |
964 | ); | |
965 | } | |
966 | ||
967 | #[test] | |
968 | fn generic_param_env_2_not_met() { | |
969 | check_types( | |
970 | r#" | |
971 | trait Trait { fn foo(self) -> u128; } | |
972 | struct S; | |
973 | impl Trait for S {} | |
974 | fn test<T>(t: T) { t.foo(); } | |
975 | //^^^^^^^ {unknown} | |
976 | "#, | |
977 | ); | |
978 | } | |
979 | ||
980 | #[test] | |
981 | fn generic_param_env_deref() { | |
982 | check_types( | |
983 | r#" | |
984 | //- minicore: deref | |
985 | trait Trait {} | |
986 | impl<T> core::ops::Deref for T where T: Trait { | |
987 | type Target = i128; | |
988 | } | |
989 | fn test<T: Trait>(t: T) { *t; } | |
990 | //^^ i128 | |
991 | "#, | |
992 | ); | |
993 | } | |
994 | ||
995 | #[test] | |
996 | fn associated_type_placeholder() { | |
997 | // 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]. | |
998 | check_types( | |
999 | r#" | |
1000 | pub trait ApplyL { | |
1001 | type Out; | |
1002 | } | |
1003 | ||
1004 | pub struct RefMutL<T>; | |
1005 | ||
1006 | impl<T> ApplyL for RefMutL<T> { | |
1007 | type Out = <T as ApplyL>::Out; | |
1008 | } | |
1009 | ||
1010 | fn test<T: ApplyL>() { | |
1011 | let y: <RefMutL<T> as ApplyL>::Out = no_matter; | |
1012 | y; | |
1013 | } //^ ApplyL::Out<T> | |
1014 | "#, | |
1015 | ); | |
1016 | } | |
1017 | ||
1018 | #[test] | |
1019 | fn associated_type_placeholder_2() { | |
1020 | check_types( | |
1021 | r#" | |
1022 | pub trait ApplyL { | |
1023 | type Out; | |
1024 | } | |
1025 | fn foo<T: ApplyL>(t: T) -> <T as ApplyL>::Out; | |
1026 | ||
1027 | fn test<T: ApplyL>(t: T) { | |
1028 | let y = foo(t); | |
1029 | y; | |
1030 | } //^ ApplyL::Out<T> | |
1031 | "#, | |
1032 | ); | |
1033 | } | |
1034 | ||
1035 | #[test] | |
1036 | fn argument_impl_trait() { | |
1037 | check_infer_with_mismatches( | |
1038 | r#" | |
1039 | //- minicore: sized | |
1040 | trait Trait<T> { | |
1041 | fn foo(&self) -> T; | |
1042 | fn foo2(&self) -> i64; | |
1043 | } | |
1044 | fn bar(x: impl Trait<u16>) {} | |
1045 | struct S<T>(T); | |
1046 | impl<T> Trait<T> for S<T> {} | |
1047 | ||
1048 | fn test(x: impl Trait<u64>, y: &impl Trait<u32>) { | |
1049 | x; | |
1050 | y; | |
1051 | let z = S(1); | |
1052 | bar(z); | |
1053 | x.foo(); | |
1054 | y.foo(); | |
1055 | z.foo(); | |
1056 | x.foo2(); | |
1057 | y.foo2(); | |
1058 | z.foo2(); | |
1059 | }"#, | |
1060 | expect![[r#" | |
1061 | 29..33 'self': &Self | |
1062 | 54..58 'self': &Self | |
1063 | 77..78 'x': impl Trait<u16> | |
1064 | 97..99 '{}': () | |
1065 | 154..155 'x': impl Trait<u64> | |
1066 | 174..175 'y': &impl Trait<u32> | |
1067 | 195..323 '{ ...2(); }': () | |
1068 | 201..202 'x': impl Trait<u64> | |
1069 | 208..209 'y': &impl Trait<u32> | |
1070 | 219..220 'z': S<u16> | |
1071 | 223..224 'S': S<u16>(u16) -> S<u16> | |
1072 | 223..227 'S(1)': S<u16> | |
1073 | 225..226 '1': u16 | |
1074 | 233..236 'bar': fn bar(S<u16>) | |
1075 | 233..239 'bar(z)': () | |
1076 | 237..238 'z': S<u16> | |
1077 | 245..246 'x': impl Trait<u64> | |
1078 | 245..252 'x.foo()': u64 | |
1079 | 258..259 'y': &impl Trait<u32> | |
1080 | 258..265 'y.foo()': u32 | |
1081 | 271..272 'z': S<u16> | |
1082 | 271..278 'z.foo()': u16 | |
1083 | 284..285 'x': impl Trait<u64> | |
1084 | 284..292 'x.foo2()': i64 | |
1085 | 298..299 'y': &impl Trait<u32> | |
1086 | 298..306 'y.foo2()': i64 | |
1087 | 312..313 'z': S<u16> | |
1088 | 312..320 'z.foo2()': i64 | |
1089 | "#]], | |
1090 | ); | |
1091 | } | |
1092 | ||
1093 | #[test] | |
1094 | fn argument_impl_trait_type_args_1() { | |
1095 | check_infer_with_mismatches( | |
1096 | r#" | |
1097 | //- minicore: sized | |
1098 | trait Trait {} | |
1099 | trait Foo { | |
1100 | // this function has an implicit Self param, an explicit type param, | |
1101 | // and an implicit impl Trait param! | |
1102 | fn bar<T>(x: impl Trait) -> T { loop {} } | |
1103 | } | |
1104 | fn foo<T>(x: impl Trait) -> T { loop {} } | |
1105 | struct S; | |
1106 | impl Trait for S {} | |
1107 | struct F; | |
1108 | impl Foo for F {} | |
1109 | ||
1110 | fn test() { | |
1111 | Foo::bar(S); | |
1112 | <F as Foo>::bar(S); | |
1113 | F::bar(S); | |
1114 | Foo::bar::<u32>(S); | |
1115 | <F as Foo>::bar::<u32>(S); | |
1116 | ||
1117 | foo(S); | |
1118 | foo::<u32>(S); | |
1119 | foo::<u32, i32>(S); // we should ignore the extraneous i32 | |
1120 | }"#, | |
1121 | expect![[r#" | |
1122 | 155..156 'x': impl Trait | |
1123 | 175..186 '{ loop {} }': T | |
1124 | 177..184 'loop {}': ! | |
1125 | 182..184 '{}': () | |
1126 | 199..200 'x': impl Trait | |
1127 | 219..230 '{ loop {} }': T | |
1128 | 221..228 'loop {}': ! | |
1129 | 226..228 '{}': () | |
1130 | 300..509 '{ ... i32 }': () | |
1131 | 306..314 'Foo::bar': fn bar<{unknown}, {unknown}>(S) -> {unknown} | |
1132 | 306..317 'Foo::bar(S)': {unknown} | |
1133 | 315..316 'S': S | |
1134 | 323..338 '<F as Foo>::bar': fn bar<F, {unknown}>(S) -> {unknown} | |
1135 | 323..341 '<F as ...bar(S)': {unknown} | |
1136 | 339..340 'S': S | |
1137 | 347..353 'F::bar': fn bar<F, {unknown}>(S) -> {unknown} | |
1138 | 347..356 'F::bar(S)': {unknown} | |
1139 | 354..355 'S': S | |
1140 | 362..377 'Foo::bar::<u32>': fn bar<{unknown}, u32>(S) -> u32 | |
1141 | 362..380 'Foo::b...32>(S)': u32 | |
1142 | 378..379 'S': S | |
1143 | 386..408 '<F as ...:<u32>': fn bar<F, u32>(S) -> u32 | |
1144 | 386..411 '<F as ...32>(S)': u32 | |
1145 | 409..410 'S': S | |
1146 | 418..421 'foo': fn foo<{unknown}>(S) -> {unknown} | |
1147 | 418..424 'foo(S)': {unknown} | |
1148 | 422..423 'S': S | |
1149 | 430..440 'foo::<u32>': fn foo<u32>(S) -> u32 | |
1150 | 430..443 'foo::<u32>(S)': u32 | |
1151 | 441..442 'S': S | |
1152 | 449..464 'foo::<u32, i32>': fn foo<u32>(S) -> u32 | |
1153 | 449..467 'foo::<...32>(S)': u32 | |
1154 | 465..466 'S': S | |
1155 | "#]], | |
1156 | ); | |
1157 | } | |
1158 | ||
1159 | #[test] | |
1160 | fn argument_impl_trait_type_args_2() { | |
1161 | check_infer_with_mismatches( | |
1162 | r#" | |
1163 | //- minicore: sized | |
1164 | trait Trait {} | |
1165 | struct S; | |
1166 | impl Trait for S {} | |
1167 | struct F<T>; | |
1168 | impl<T> F<T> { | |
1169 | fn foo<U>(self, x: impl Trait) -> (T, U) { loop {} } | |
1170 | } | |
1171 | ||
1172 | fn test() { | |
1173 | F.foo(S); | |
1174 | F::<u32>.foo(S); | |
1175 | F::<u32>.foo::<i32>(S); | |
1176 | F::<u32>.foo::<i32, u32>(S); // extraneous argument should be ignored | |
1177 | }"#, | |
1178 | expect![[r#" | |
1179 | 87..91 'self': F<T> | |
1180 | 93..94 'x': impl Trait | |
1181 | 118..129 '{ loop {} }': (T, U) | |
1182 | 120..127 'loop {}': ! | |
1183 | 125..127 '{}': () | |
1184 | 143..283 '{ ...ored }': () | |
1185 | 149..150 'F': F<{unknown}> | |
1186 | 149..157 'F.foo(S)': ({unknown}, {unknown}) | |
1187 | 155..156 'S': S | |
1188 | 163..171 'F::<u32>': F<u32> | |
1189 | 163..178 'F::<u32>.foo(S)': (u32, {unknown}) | |
1190 | 176..177 'S': S | |
1191 | 184..192 'F::<u32>': F<u32> | |
1192 | 184..206 'F::<u3...32>(S)': (u32, i32) | |
1193 | 204..205 'S': S | |
1194 | 212..220 'F::<u32>': F<u32> | |
1195 | 212..239 'F::<u3...32>(S)': (u32, i32) | |
1196 | 237..238 'S': S | |
1197 | "#]], | |
1198 | ); | |
1199 | } | |
1200 | ||
1201 | #[test] | |
1202 | fn argument_impl_trait_to_fn_pointer() { | |
1203 | check_infer_with_mismatches( | |
1204 | r#" | |
1205 | //- minicore: sized | |
1206 | trait Trait {} | |
1207 | fn foo(x: impl Trait) { loop {} } | |
1208 | struct S; | |
1209 | impl Trait for S {} | |
1210 | ||
1211 | fn test() { | |
1212 | let f: fn(S) -> () = foo; | |
1213 | }"#, | |
1214 | expect![[r#" | |
1215 | 22..23 'x': impl Trait | |
1216 | 37..48 '{ loop {} }': () | |
1217 | 39..46 'loop {}': ! | |
1218 | 44..46 '{}': () | |
1219 | 90..123 '{ ...foo; }': () | |
1220 | 100..101 'f': fn(S) | |
1221 | 117..120 'foo': fn foo(S) | |
1222 | "#]], | |
1223 | ); | |
1224 | } | |
1225 | ||
1226 | #[test] | |
1227 | fn impl_trait() { | |
1228 | check_infer( | |
1229 | r#" | |
1230 | //- minicore: sized | |
1231 | trait Trait<T> { | |
1232 | fn foo(&self) -> T; | |
1233 | fn foo2(&self) -> i64; | |
1234 | } | |
1235 | fn bar() -> impl Trait<u64> {} | |
1236 | ||
1237 | fn test(x: impl Trait<u64>, y: &impl Trait<u64>) { | |
1238 | x; | |
1239 | y; | |
1240 | let z = bar(); | |
1241 | x.foo(); | |
1242 | y.foo(); | |
1243 | z.foo(); | |
1244 | x.foo2(); | |
1245 | y.foo2(); | |
1246 | z.foo2(); | |
1247 | }"#, | |
1248 | expect![[r#" | |
1249 | 29..33 'self': &Self | |
1250 | 54..58 'self': &Self | |
1251 | 98..100 '{}': () | |
1252 | 110..111 'x': impl Trait<u64> | |
1253 | 130..131 'y': &impl Trait<u64> | |
1254 | 151..268 '{ ...2(); }': () | |
1255 | 157..158 'x': impl Trait<u64> | |
1256 | 164..165 'y': &impl Trait<u64> | |
1257 | 175..176 'z': impl Trait<u64> | |
1258 | 179..182 'bar': fn bar() -> impl Trait<u64> | |
1259 | 179..184 'bar()': impl Trait<u64> | |
1260 | 190..191 'x': impl Trait<u64> | |
1261 | 190..197 'x.foo()': u64 | |
1262 | 203..204 'y': &impl Trait<u64> | |
1263 | 203..210 'y.foo()': u64 | |
1264 | 216..217 'z': impl Trait<u64> | |
1265 | 216..223 'z.foo()': u64 | |
1266 | 229..230 'x': impl Trait<u64> | |
1267 | 229..237 'x.foo2()': i64 | |
1268 | 243..244 'y': &impl Trait<u64> | |
1269 | 243..251 'y.foo2()': i64 | |
1270 | 257..258 'z': impl Trait<u64> | |
1271 | 257..265 'z.foo2()': i64 | |
1272 | "#]], | |
1273 | ); | |
1274 | } | |
1275 | ||
1276 | #[test] | |
1277 | fn simple_return_pos_impl_trait() { | |
1278 | cov_mark::check!(lower_rpit); | |
1279 | check_infer( | |
1280 | r#" | |
1281 | //- minicore: sized | |
1282 | trait Trait<T> { | |
1283 | fn foo(&self) -> T; | |
1284 | } | |
1285 | fn bar() -> impl Trait<u64> { loop {} } | |
1286 | ||
1287 | fn test() { | |
1288 | let a = bar(); | |
1289 | a.foo(); | |
1290 | }"#, | |
1291 | expect![[r#" | |
1292 | 29..33 'self': &Self | |
1293 | 71..82 '{ loop {} }': ! | |
1294 | 73..80 'loop {}': ! | |
1295 | 78..80 '{}': () | |
1296 | 94..129 '{ ...o(); }': () | |
1297 | 104..105 'a': impl Trait<u64> | |
1298 | 108..111 'bar': fn bar() -> impl Trait<u64> | |
1299 | 108..113 'bar()': impl Trait<u64> | |
1300 | 119..120 'a': impl Trait<u64> | |
1301 | 119..126 'a.foo()': u64 | |
1302 | "#]], | |
1303 | ); | |
1304 | } | |
1305 | ||
1306 | #[test] | |
1307 | fn more_return_pos_impl_trait() { | |
1308 | check_infer( | |
1309 | r#" | |
1310 | //- minicore: sized | |
1311 | trait Iterator { | |
1312 | type Item; | |
1313 | fn next(&mut self) -> Self::Item; | |
1314 | } | |
1315 | trait Trait<T> { | |
1316 | fn foo(&self) -> T; | |
1317 | } | |
1318 | fn bar() -> (impl Iterator<Item = impl Trait<u32>>, impl Trait<u64>) { loop {} } | |
1319 | fn baz<T>(t: T) -> (impl Iterator<Item = impl Trait<T>>, impl Trait<T>) { loop {} } | |
1320 | ||
1321 | fn test() { | |
1322 | let (a, b) = bar(); | |
1323 | a.next().foo(); | |
1324 | b.foo(); | |
1325 | let (c, d) = baz(1u128); | |
1326 | c.next().foo(); | |
1327 | d.foo(); | |
1328 | }"#, | |
1329 | expect![[r#" | |
1330 | 49..53 'self': &mut Self | |
1331 | 101..105 'self': &Self | |
1332 | 184..195 '{ loop {} }': ({unknown}, {unknown}) | |
1333 | 186..193 'loop {}': ! | |
1334 | 191..193 '{}': () | |
1335 | 206..207 't': T | |
1336 | 268..279 '{ loop {} }': ({unknown}, {unknown}) | |
1337 | 270..277 'loop {}': ! | |
1338 | 275..277 '{}': () | |
1339 | 291..413 '{ ...o(); }': () | |
1340 | 301..307 '(a, b)': (impl Iterator<Item = impl Trait<u32>>, impl Trait<u64>) | |
1341 | 302..303 'a': impl Iterator<Item = impl Trait<u32>> | |
1342 | 305..306 'b': impl Trait<u64> | |
1343 | 310..313 'bar': fn bar() -> (impl Iterator<Item = impl Trait<u32>>, impl Trait<u64>) | |
1344 | 310..315 'bar()': (impl Iterator<Item = impl Trait<u32>>, impl Trait<u64>) | |
1345 | 321..322 'a': impl Iterator<Item = impl Trait<u32>> | |
1346 | 321..329 'a.next()': impl Trait<u32> | |
1347 | 321..335 'a.next().foo()': u32 | |
1348 | 341..342 'b': impl Trait<u64> | |
1349 | 341..348 'b.foo()': u64 | |
1350 | 358..364 '(c, d)': (impl Iterator<Item = impl Trait<u128>>, impl Trait<u128>) | |
1351 | 359..360 'c': impl Iterator<Item = impl Trait<u128>> | |
1352 | 362..363 'd': impl Trait<u128> | |
1353 | 367..370 'baz': fn baz<u128>(u128) -> (impl Iterator<Item = impl Trait<u128>>, impl Trait<u128>) | |
1354 | 367..377 'baz(1u128)': (impl Iterator<Item = impl Trait<u128>>, impl Trait<u128>) | |
1355 | 371..376 '1u128': u128 | |
1356 | 383..384 'c': impl Iterator<Item = impl Trait<u128>> | |
1357 | 383..391 'c.next()': impl Trait<u128> | |
1358 | 383..397 'c.next().foo()': u128 | |
1359 | 403..404 'd': impl Trait<u128> | |
1360 | 403..410 'd.foo()': u128 | |
1361 | "#]], | |
1362 | ); | |
1363 | } | |
1364 | ||
1365 | #[test] | |
1366 | fn infer_from_return_pos_impl_trait() { | |
1367 | check_infer_with_mismatches( | |
1368 | r#" | |
1369 | //- minicore: fn, sized | |
1370 | trait Trait<T> {} | |
1371 | struct Bar<T>(T); | |
1372 | impl<T> Trait<T> for Bar<T> {} | |
1373 | fn foo<const C: u8, T>() -> (impl FnOnce(&str, T), impl Trait<u8>) { | |
1374 | (|input, t| {}, Bar(C)) | |
1375 | } | |
1376 | "#, | |
1377 | expect![[r#" | |
1378 | 134..165 '{ ...(C)) }': (|&str, T| -> (), Bar<u8>) | |
1379 | 140..163 '(|inpu...ar(C))': (|&str, T| -> (), Bar<u8>) | |
1380 | 141..154 '|input, t| {}': |&str, T| -> () | |
1381 | 142..147 'input': &str | |
1382 | 149..150 't': T | |
1383 | 152..154 '{}': () | |
1384 | 156..159 'Bar': Bar<u8>(u8) -> Bar<u8> | |
1385 | 156..162 'Bar(C)': Bar<u8> | |
1386 | 160..161 'C': u8 | |
1387 | "#]], | |
1388 | ); | |
1389 | } | |
1390 | ||
f25598a0 FG |
1391 | #[test] |
1392 | fn return_pos_impl_trait_in_projection() { | |
1393 | // Note that the unused type param `X` is significant; see #13307. | |
1394 | check_no_mismatches( | |
1395 | r#" | |
1396 | //- minicore: sized | |
1397 | trait Future { type Output; } | |
1398 | impl Future for () { type Output = i32; } | |
1399 | type Foo<F> = (<F as Future>::Output, F); | |
1400 | fn foo<X>() -> Foo<impl Future<Output = ()>> { | |
1401 | (0, ()) | |
1402 | } | |
1403 | "#, | |
1404 | ) | |
1405 | } | |
1406 | ||
064997fb FG |
1407 | #[test] |
1408 | fn dyn_trait() { | |
1409 | check_infer( | |
1410 | r#" | |
1411 | //- minicore: sized | |
1412 | trait Trait<T> { | |
1413 | fn foo(&self) -> T; | |
1414 | fn foo2(&self) -> i64; | |
1415 | } | |
1416 | fn bar() -> dyn Trait<u64> {} | |
1417 | ||
1418 | fn test(x: dyn Trait<u64>, y: &dyn Trait<u64>) { | |
1419 | x; | |
1420 | y; | |
1421 | let z = bar(); | |
1422 | x.foo(); | |
1423 | y.foo(); | |
1424 | z.foo(); | |
1425 | x.foo2(); | |
1426 | y.foo2(); | |
1427 | z.foo2(); | |
1428 | }"#, | |
1429 | expect![[r#" | |
1430 | 29..33 'self': &Self | |
1431 | 54..58 'self': &Self | |
1432 | 97..99 '{}': dyn Trait<u64> | |
1433 | 109..110 'x': dyn Trait<u64> | |
1434 | 128..129 'y': &dyn Trait<u64> | |
1435 | 148..265 '{ ...2(); }': () | |
1436 | 154..155 'x': dyn Trait<u64> | |
1437 | 161..162 'y': &dyn Trait<u64> | |
1438 | 172..173 'z': dyn Trait<u64> | |
1439 | 176..179 'bar': fn bar() -> dyn Trait<u64> | |
1440 | 176..181 'bar()': dyn Trait<u64> | |
1441 | 187..188 'x': dyn Trait<u64> | |
1442 | 187..194 'x.foo()': u64 | |
1443 | 200..201 'y': &dyn Trait<u64> | |
1444 | 200..207 'y.foo()': u64 | |
1445 | 213..214 'z': dyn Trait<u64> | |
1446 | 213..220 'z.foo()': u64 | |
1447 | 226..227 'x': dyn Trait<u64> | |
1448 | 226..234 'x.foo2()': i64 | |
1449 | 240..241 'y': &dyn Trait<u64> | |
1450 | 240..248 'y.foo2()': i64 | |
1451 | 254..255 'z': dyn Trait<u64> | |
1452 | 254..262 'z.foo2()': i64 | |
1453 | "#]], | |
1454 | ); | |
1455 | } | |
1456 | ||
1457 | #[test] | |
1458 | fn dyn_trait_in_impl() { | |
1459 | check_infer( | |
1460 | r#" | |
1461 | //- minicore: sized | |
1462 | trait Trait<T, U> { | |
1463 | fn foo(&self) -> (T, U); | |
1464 | } | |
1465 | struct S<T, U> {} | |
1466 | impl<T, U> S<T, U> { | |
1467 | fn bar(&self) -> &dyn Trait<T, U> { loop {} } | |
1468 | } | |
1469 | trait Trait2<T, U> { | |
1470 | fn baz(&self) -> (T, U); | |
1471 | } | |
1472 | impl<T, U> Trait2<T, U> for dyn Trait<T, U> { } | |
1473 | ||
1474 | fn test(s: S<u32, i32>) { | |
1475 | s.bar().baz(); | |
1476 | }"#, | |
1477 | expect![[r#" | |
1478 | 32..36 'self': &Self | |
1479 | 102..106 'self': &S<T, U> | |
1480 | 128..139 '{ loop {} }': &dyn Trait<T, U> | |
1481 | 130..137 'loop {}': ! | |
1482 | 135..137 '{}': () | |
1483 | 175..179 'self': &Self | |
1484 | 251..252 's': S<u32, i32> | |
1485 | 267..289 '{ ...z(); }': () | |
1486 | 273..274 's': S<u32, i32> | |
1487 | 273..280 's.bar()': &dyn Trait<u32, i32> | |
1488 | 273..286 's.bar().baz()': (u32, i32) | |
1489 | "#]], | |
1490 | ); | |
1491 | } | |
1492 | ||
1493 | #[test] | |
1494 | fn dyn_trait_bare() { | |
1495 | check_infer( | |
1496 | r#" | |
1497 | //- minicore: sized | |
1498 | trait Trait { | |
1499 | fn foo(&self) -> u64; | |
1500 | } | |
1501 | fn bar() -> Trait {} | |
1502 | ||
1503 | fn test(x: Trait, y: &Trait) -> u64 { | |
1504 | x; | |
1505 | y; | |
1506 | let z = bar(); | |
1507 | x.foo(); | |
1508 | y.foo(); | |
1509 | z.foo(); | |
1510 | }"#, | |
1511 | expect![[r#" | |
1512 | 26..30 'self': &Self | |
1513 | 60..62 '{}': dyn Trait | |
1514 | 72..73 'x': dyn Trait | |
1515 | 82..83 'y': &dyn Trait | |
1516 | 100..175 '{ ...o(); }': u64 | |
1517 | 106..107 'x': dyn Trait | |
1518 | 113..114 'y': &dyn Trait | |
1519 | 124..125 'z': dyn Trait | |
1520 | 128..131 'bar': fn bar() -> dyn Trait | |
1521 | 128..133 'bar()': dyn Trait | |
1522 | 139..140 'x': dyn Trait | |
1523 | 139..146 'x.foo()': u64 | |
1524 | 152..153 'y': &dyn Trait | |
1525 | 152..159 'y.foo()': u64 | |
1526 | 165..166 'z': dyn Trait | |
1527 | 165..172 'z.foo()': u64 | |
1528 | "#]], | |
1529 | ); | |
f2b60f7d FG |
1530 | |
1531 | check_infer_with_mismatches( | |
1532 | r#" | |
1533 | //- minicore: fn, coerce_unsized | |
1534 | struct S; | |
1535 | impl S { | |
1536 | fn foo(&self) {} | |
1537 | } | |
1538 | fn f(_: &Fn(S)) {} | |
1539 | fn main() { | |
1540 | f(&|number| number.foo()); | |
1541 | } | |
1542 | "#, | |
1543 | expect![[r#" | |
1544 | 31..35 'self': &S | |
1545 | 37..39 '{}': () | |
1546 | 47..48 '_': &dyn Fn(S) | |
1547 | 58..60 '{}': () | |
1548 | 71..105 '{ ...()); }': () | |
1549 | 77..78 'f': fn f(&dyn Fn(S)) | |
1550 | 77..102 'f(&|nu...foo())': () | |
1551 | 79..101 '&|numb....foo()': &|S| -> () | |
1552 | 80..101 '|numbe....foo()': |S| -> () | |
1553 | 81..87 'number': S | |
1554 | 89..95 'number': S | |
1555 | 89..101 'number.foo()': () | |
1556 | "#]], | |
1557 | ) | |
064997fb FG |
1558 | } |
1559 | ||
1560 | #[test] | |
1561 | fn weird_bounds() { | |
1562 | check_infer( | |
1563 | r#" | |
1564 | //- minicore: sized | |
1565 | trait Trait {} | |
1566 | fn test( | |
1567 | a: impl Trait + 'lifetime, | |
1568 | b: impl 'lifetime, | |
1569 | c: impl (Trait), | |
1570 | d: impl ('lifetime), | |
1571 | e: impl ?Sized, | |
1572 | f: impl Trait + ?Sized | |
1573 | ) {} | |
1574 | "#, | |
1575 | expect![[r#" | |
1576 | 28..29 'a': impl Trait | |
1577 | 59..60 'b': impl Sized | |
1578 | 82..83 'c': impl Trait | |
1579 | 103..104 'd': impl Sized | |
1580 | 128..129 'e': impl ?Sized | |
1581 | 148..149 'f': impl Trait + ?Sized | |
1582 | 173..175 '{}': () | |
1583 | "#]], | |
1584 | ); | |
1585 | } | |
1586 | ||
1587 | #[test] | |
1588 | fn error_bound_chalk() { | |
1589 | check_types( | |
1590 | r#" | |
1591 | trait Trait { | |
1592 | fn foo(&self) -> u32 { 0 } | |
1593 | } | |
1594 | ||
1595 | fn test(x: (impl Trait + UnknownTrait)) { | |
1596 | x.foo(); | |
1597 | } //^^^^^^^ u32 | |
1598 | "#, | |
1599 | ); | |
1600 | } | |
1601 | ||
1602 | #[test] | |
1603 | fn assoc_type_bindings() { | |
1604 | check_infer( | |
1605 | r#" | |
1606 | //- minicore: sized | |
1607 | trait Trait { | |
1608 | type Type; | |
1609 | } | |
1610 | ||
1611 | fn get<T: Trait>(t: T) -> <T as Trait>::Type {} | |
1612 | fn get2<U, T: Trait<Type = U>>(t: T) -> U {} | |
1613 | fn set<T: Trait<Type = u64>>(t: T) -> T {t} | |
1614 | ||
1615 | struct S<T>; | |
1616 | impl<T> Trait for S<T> { type Type = T; } | |
1617 | ||
1618 | fn test<T: Trait<Type = u32>>(x: T, y: impl Trait<Type = i64>) { | |
1619 | get(x); | |
1620 | get2(x); | |
1621 | get(y); | |
1622 | get2(y); | |
1623 | get(set(S)); | |
1624 | get2(set(S)); | |
1625 | get2(S::<str>); | |
1626 | }"#, | |
1627 | expect![[r#" | |
1628 | 49..50 't': T | |
1629 | 77..79 '{}': Trait::Type<T> | |
1630 | 111..112 't': T | |
1631 | 122..124 '{}': U | |
1632 | 154..155 't': T | |
1633 | 165..168 '{t}': T | |
1634 | 166..167 't': T | |
1635 | 256..257 'x': T | |
1636 | 262..263 'y': impl Trait<Type = i64> | |
1637 | 289..397 '{ ...r>); }': () | |
1638 | 295..298 'get': fn get<T>(T) -> <T as Trait>::Type | |
1639 | 295..301 'get(x)': u32 | |
1640 | 299..300 'x': T | |
1641 | 307..311 'get2': fn get2<u32, T>(T) -> u32 | |
1642 | 307..314 'get2(x)': u32 | |
1643 | 312..313 'x': T | |
1644 | 320..323 'get': fn get<impl Trait<Type = i64>>(impl Trait<Type = i64>) -> <impl Trait<Type = i64> as Trait>::Type | |
1645 | 320..326 'get(y)': i64 | |
1646 | 324..325 'y': impl Trait<Type = i64> | |
1647 | 332..336 'get2': fn get2<i64, impl Trait<Type = i64>>(impl Trait<Type = i64>) -> i64 | |
1648 | 332..339 'get2(y)': i64 | |
1649 | 337..338 'y': impl Trait<Type = i64> | |
1650 | 345..348 'get': fn get<S<u64>>(S<u64>) -> <S<u64> as Trait>::Type | |
1651 | 345..356 'get(set(S))': u64 | |
1652 | 349..352 'set': fn set<S<u64>>(S<u64>) -> S<u64> | |
1653 | 349..355 'set(S)': S<u64> | |
1654 | 353..354 'S': S<u64> | |
1655 | 362..366 'get2': fn get2<u64, S<u64>>(S<u64>) -> u64 | |
1656 | 362..374 'get2(set(S))': u64 | |
1657 | 367..370 'set': fn set<S<u64>>(S<u64>) -> S<u64> | |
1658 | 367..373 'set(S)': S<u64> | |
1659 | 371..372 'S': S<u64> | |
1660 | 380..384 'get2': fn get2<str, S<str>>(S<str>) -> str | |
1661 | 380..394 'get2(S::<str>)': str | |
1662 | 385..393 'S::<str>': S<str> | |
1663 | "#]], | |
1664 | ); | |
1665 | } | |
1666 | ||
1667 | #[test] | |
1668 | fn impl_trait_assoc_binding_projection_bug() { | |
1669 | check_types( | |
1670 | r#" | |
1671 | //- minicore: iterator | |
1672 | pub trait Language { | |
1673 | type Kind; | |
1674 | } | |
1675 | pub enum RustLanguage {} | |
1676 | impl Language for RustLanguage { | |
1677 | type Kind = SyntaxKind; | |
1678 | } | |
1679 | struct SyntaxNode<L> {} | |
1680 | fn foo() -> impl Iterator<Item = SyntaxNode<RustLanguage>> {} | |
1681 | ||
1682 | trait Clone { | |
1683 | fn clone(&self) -> Self; | |
1684 | } | |
1685 | ||
1686 | fn api_walkthrough() { | |
1687 | for node in foo() { | |
1688 | node.clone(); | |
1689 | } //^^^^^^^^^^^^ {unknown} | |
1690 | } | |
1691 | "#, | |
1692 | ); | |
1693 | } | |
1694 | ||
1695 | #[test] | |
1696 | fn projection_eq_within_chalk() { | |
1697 | check_infer( | |
1698 | r#" | |
1699 | trait Trait1 { | |
1700 | type Type; | |
1701 | } | |
1702 | trait Trait2<T> { | |
1703 | fn foo(self) -> T; | |
1704 | } | |
1705 | impl<T, U> Trait2<T> for U where U: Trait1<Type = T> {} | |
1706 | ||
1707 | fn test<T: Trait1<Type = u32>>(x: T) { | |
1708 | x.foo(); | |
1709 | }"#, | |
1710 | expect![[r#" | |
1711 | 61..65 'self': Self | |
1712 | 163..164 'x': T | |
1713 | 169..185 '{ ...o(); }': () | |
1714 | 175..176 'x': T | |
1715 | 175..182 'x.foo()': u32 | |
1716 | "#]], | |
1717 | ); | |
1718 | } | |
1719 | ||
1720 | #[test] | |
1721 | fn where_clause_trait_in_scope_for_method_resolution() { | |
1722 | check_types( | |
1723 | r#" | |
1724 | mod foo { | |
487cf647 | 1725 | pub trait Trait { |
064997fb FG |
1726 | fn foo(&self) -> u32 { 0 } |
1727 | } | |
1728 | } | |
1729 | ||
1730 | fn test<T: foo::Trait>(x: T) { | |
1731 | x.foo(); | |
1732 | } //^^^^^^^ u32 | |
1733 | "#, | |
1734 | ); | |
1735 | } | |
1736 | ||
1737 | #[test] | |
1738 | fn super_trait_method_resolution() { | |
1739 | check_infer( | |
1740 | r#" | |
1741 | mod foo { | |
487cf647 | 1742 | pub trait SuperTrait { |
064997fb FG |
1743 | fn foo(&self) -> u32 {} |
1744 | } | |
1745 | } | |
1746 | trait Trait1: foo::SuperTrait {} | |
1747 | trait Trait2 where Self: foo::SuperTrait {} | |
1748 | ||
1749 | fn test<T: Trait1, U: Trait2>(x: T, y: U) { | |
1750 | x.foo(); | |
1751 | y.foo(); | |
1752 | }"#, | |
1753 | expect![[r#" | |
487cf647 FG |
1754 | 53..57 'self': &Self |
1755 | 66..68 '{}': u32 | |
1756 | 185..186 'x': T | |
1757 | 191..192 'y': U | |
1758 | 197..226 '{ ...o(); }': () | |
1759 | 203..204 'x': T | |
1760 | 203..210 'x.foo()': u32 | |
1761 | 216..217 'y': U | |
1762 | 216..223 'y.foo()': u32 | |
064997fb FG |
1763 | "#]], |
1764 | ); | |
1765 | } | |
1766 | ||
1767 | #[test] | |
1768 | fn super_trait_impl_trait_method_resolution() { | |
1769 | check_infer( | |
1770 | r#" | |
1771 | //- minicore: sized | |
1772 | mod foo { | |
487cf647 | 1773 | pub trait SuperTrait { |
064997fb FG |
1774 | fn foo(&self) -> u32 {} |
1775 | } | |
1776 | } | |
1777 | trait Trait1: foo::SuperTrait {} | |
1778 | ||
1779 | fn test(x: &impl Trait1) { | |
1780 | x.foo(); | |
1781 | }"#, | |
1782 | expect![[r#" | |
487cf647 FG |
1783 | 53..57 'self': &Self |
1784 | 66..68 '{}': u32 | |
1785 | 119..120 'x': &impl Trait1 | |
1786 | 136..152 '{ ...o(); }': () | |
1787 | 142..143 'x': &impl Trait1 | |
1788 | 142..149 'x.foo()': u32 | |
064997fb FG |
1789 | "#]], |
1790 | ); | |
1791 | } | |
1792 | ||
1793 | #[test] | |
1794 | fn super_trait_cycle() { | |
1795 | // This just needs to not crash | |
1796 | check_infer( | |
1797 | r#" | |
1798 | trait A: B {} | |
1799 | trait B: A {} | |
1800 | ||
1801 | fn test<T: A>(x: T) { | |
1802 | x.foo(); | |
1803 | } | |
1804 | "#, | |
1805 | expect![[r#" | |
1806 | 43..44 'x': T | |
1807 | 49..65 '{ ...o(); }': () | |
1808 | 55..56 'x': T | |
1809 | 55..62 'x.foo()': {unknown} | |
1810 | "#]], | |
1811 | ); | |
1812 | } | |
1813 | ||
1814 | #[test] | |
1815 | fn super_trait_assoc_type_bounds() { | |
1816 | check_infer( | |
1817 | r#" | |
1818 | trait SuperTrait { type Type; } | |
1819 | trait Trait where Self: SuperTrait {} | |
1820 | ||
1821 | fn get2<U, T: Trait<Type = U>>(t: T) -> U {} | |
1822 | fn set<T: Trait<Type = u64>>(t: T) -> T {t} | |
1823 | ||
1824 | struct S<T>; | |
1825 | impl<T> SuperTrait for S<T> { type Type = T; } | |
1826 | impl<T> Trait for S<T> {} | |
1827 | ||
1828 | fn test() { | |
1829 | get2(set(S)); | |
1830 | }"#, | |
1831 | expect![[r#" | |
1832 | 102..103 't': T | |
1833 | 113..115 '{}': U | |
1834 | 145..146 't': T | |
1835 | 156..159 '{t}': T | |
1836 | 157..158 't': T | |
1837 | 258..279 '{ ...S)); }': () | |
1838 | 264..268 'get2': fn get2<u64, S<u64>>(S<u64>) -> u64 | |
1839 | 264..276 'get2(set(S))': u64 | |
1840 | 269..272 'set': fn set<S<u64>>(S<u64>) -> S<u64> | |
1841 | 269..275 'set(S)': S<u64> | |
1842 | 273..274 'S': S<u64> | |
1843 | "#]], | |
1844 | ); | |
1845 | } | |
1846 | ||
1847 | #[test] | |
1848 | fn fn_trait() { | |
1849 | check_infer_with_mismatches( | |
1850 | r#" | |
1851 | trait FnOnce<Args> { | |
1852 | type Output; | |
1853 | ||
1854 | fn call_once(self, args: Args) -> <Self as FnOnce<Args>>::Output; | |
1855 | } | |
1856 | ||
1857 | fn test<F: FnOnce(u32, u64) -> u128>(f: F) { | |
1858 | f.call_once((1, 2)); | |
1859 | }"#, | |
1860 | expect![[r#" | |
1861 | 56..60 'self': Self | |
1862 | 62..66 'args': Args | |
1863 | 149..150 'f': F | |
1864 | 155..183 '{ ...2)); }': () | |
1865 | 161..162 'f': F | |
1866 | 161..180 'f.call...1, 2))': u128 | |
1867 | 173..179 '(1, 2)': (u32, u64) | |
1868 | 174..175 '1': u32 | |
1869 | 177..178 '2': u64 | |
1870 | "#]], | |
1871 | ); | |
1872 | } | |
1873 | ||
1874 | #[test] | |
1875 | fn fn_ptr_and_item() { | |
1876 | check_infer_with_mismatches( | |
1877 | r#" | |
1878 | #[lang="fn_once"] | |
1879 | trait FnOnce<Args> { | |
1880 | type Output; | |
1881 | ||
1882 | fn call_once(self, args: Args) -> Self::Output; | |
1883 | } | |
1884 | ||
1885 | trait Foo<T> { | |
1886 | fn foo(&self) -> T; | |
1887 | } | |
1888 | ||
1889 | struct Bar<T>(T); | |
1890 | ||
1891 | impl<A1, R, F: FnOnce(A1) -> R> Foo<(A1, R)> for Bar<F> { | |
1892 | fn foo(&self) -> (A1, R) { loop {} } | |
1893 | } | |
1894 | ||
1895 | enum Opt<T> { None, Some(T) } | |
1896 | impl<T> Opt<T> { | |
1897 | fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Opt<U> { loop {} } | |
1898 | } | |
1899 | ||
1900 | fn test() { | |
1901 | let bar: Bar<fn(u8) -> u32>; | |
1902 | bar.foo(); | |
1903 | ||
1904 | let opt: Opt<u8>; | |
1905 | let f: fn(u8) -> u32; | |
1906 | opt.map(f); | |
1907 | }"#, | |
1908 | expect![[r#" | |
1909 | 74..78 'self': Self | |
1910 | 80..84 'args': Args | |
1911 | 139..143 'self': &Self | |
1912 | 243..247 'self': &Bar<F> | |
1913 | 260..271 '{ loop {} }': (A1, R) | |
1914 | 262..269 'loop {}': ! | |
1915 | 267..269 '{}': () | |
1916 | 355..359 'self': Opt<T> | |
1917 | 361..362 'f': F | |
1918 | 377..388 '{ loop {} }': Opt<U> | |
1919 | 379..386 'loop {}': ! | |
1920 | 384..386 '{}': () | |
1921 | 402..518 '{ ...(f); }': () | |
1922 | 412..415 'bar': Bar<fn(u8) -> u32> | |
1923 | 441..444 'bar': Bar<fn(u8) -> u32> | |
1924 | 441..450 'bar.foo()': (u8, u32) | |
1925 | 461..464 'opt': Opt<u8> | |
1926 | 483..484 'f': fn(u8) -> u32 | |
1927 | 505..508 'opt': Opt<u8> | |
1928 | 505..515 'opt.map(f)': Opt<u32> | |
1929 | 513..514 'f': fn(u8) -> u32 | |
1930 | "#]], | |
1931 | ); | |
1932 | } | |
1933 | ||
1934 | #[test] | |
1935 | fn fn_trait_deref_with_ty_default() { | |
1936 | check_infer( | |
1937 | r#" | |
1938 | //- minicore: deref, fn | |
1939 | struct Foo; | |
1940 | ||
1941 | impl Foo { | |
1942 | fn foo(&self) -> usize {} | |
1943 | } | |
1944 | ||
1945 | struct Lazy<T, F = fn() -> T>(F); | |
1946 | ||
1947 | impl<T, F> Lazy<T, F> { | |
1948 | pub fn new(f: F) -> Lazy<T, F> {} | |
1949 | } | |
1950 | ||
1951 | impl<T, F: FnOnce() -> T> core::ops::Deref for Lazy<T, F> { | |
1952 | type Target = T; | |
1953 | } | |
1954 | ||
1955 | fn test() { | |
1956 | let lazy1: Lazy<Foo, _> = Lazy::new(|| Foo); | |
1957 | let r1 = lazy1.foo(); | |
1958 | ||
1959 | fn make_foo_fn() -> Foo {} | |
1960 | let make_foo_fn_ptr: fn() -> Foo = make_foo_fn; | |
1961 | let lazy2: Lazy<Foo, _> = Lazy::new(make_foo_fn_ptr); | |
1962 | let r2 = lazy2.foo(); | |
1963 | }"#, | |
1964 | expect![[r#" | |
1965 | 36..40 'self': &Foo | |
1966 | 51..53 '{}': usize | |
1967 | 131..132 'f': F | |
1968 | 151..153 '{}': Lazy<T, F> | |
1969 | 251..497 '{ ...o(); }': () | |
1970 | 261..266 'lazy1': Lazy<Foo, || -> Foo> | |
1971 | 283..292 'Lazy::new': fn new<Foo, || -> Foo>(|| -> Foo) -> Lazy<Foo, || -> Foo> | |
1972 | 283..300 'Lazy::...| Foo)': Lazy<Foo, || -> Foo> | |
1973 | 293..299 '|| Foo': || -> Foo | |
1974 | 296..299 'Foo': Foo | |
1975 | 310..312 'r1': usize | |
1976 | 315..320 'lazy1': Lazy<Foo, || -> Foo> | |
1977 | 315..326 'lazy1.foo()': usize | |
1978 | 368..383 'make_foo_fn_ptr': fn() -> Foo | |
1979 | 399..410 'make_foo_fn': fn make_foo_fn() -> Foo | |
1980 | 420..425 'lazy2': Lazy<Foo, fn() -> Foo> | |
1981 | 442..451 'Lazy::new': fn new<Foo, fn() -> Foo>(fn() -> Foo) -> Lazy<Foo, fn() -> Foo> | |
1982 | 442..468 'Lazy::...n_ptr)': Lazy<Foo, fn() -> Foo> | |
1983 | 452..467 'make_foo_fn_ptr': fn() -> Foo | |
1984 | 478..480 'r2': usize | |
1985 | 483..488 'lazy2': Lazy<Foo, fn() -> Foo> | |
1986 | 483..494 'lazy2.foo()': usize | |
1987 | 357..359 '{}': Foo | |
1988 | "#]], | |
1989 | ); | |
1990 | } | |
1991 | ||
1992 | #[test] | |
1993 | fn closure_1() { | |
1994 | check_infer_with_mismatches( | |
1995 | r#" | |
1996 | //- minicore: fn | |
1997 | enum Option<T> { Some(T), None } | |
1998 | impl<T> Option<T> { | |
1999 | fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> { loop {} } | |
2000 | } | |
2001 | ||
2002 | fn test() { | |
2003 | let x = Option::Some(1u32); | |
2004 | x.map(|v| v + 1); | |
2005 | x.map(|_v| 1u64); | |
2006 | let y: Option<i64> = x.map(|_v| 1); | |
2007 | }"#, | |
2008 | expect![[r#" | |
2009 | 86..90 'self': Option<T> | |
2010 | 92..93 'f': F | |
2011 | 111..122 '{ loop {} }': Option<U> | |
2012 | 113..120 'loop {}': ! | |
2013 | 118..120 '{}': () | |
2014 | 136..255 '{ ... 1); }': () | |
2015 | 146..147 'x': Option<u32> | |
2016 | 150..162 'Option::Some': Some<u32>(u32) -> Option<u32> | |
2017 | 150..168 'Option...(1u32)': Option<u32> | |
2018 | 163..167 '1u32': u32 | |
2019 | 174..175 'x': Option<u32> | |
2020 | 174..190 'x.map(...v + 1)': Option<u32> | |
2021 | 180..189 '|v| v + 1': |u32| -> u32 | |
2022 | 181..182 'v': u32 | |
2023 | 184..185 'v': u32 | |
2024 | 184..189 'v + 1': u32 | |
2025 | 188..189 '1': u32 | |
2026 | 196..197 'x': Option<u32> | |
2027 | 196..212 'x.map(... 1u64)': Option<u64> | |
2028 | 202..211 '|_v| 1u64': |u32| -> u64 | |
2029 | 203..205 '_v': u32 | |
2030 | 207..211 '1u64': u64 | |
2031 | 222..223 'y': Option<i64> | |
2032 | 239..240 'x': Option<u32> | |
2033 | 239..252 'x.map(|_v| 1)': Option<i64> | |
2034 | 245..251 '|_v| 1': |u32| -> i64 | |
2035 | 246..248 '_v': u32 | |
2036 | 250..251 '1': i64 | |
2037 | "#]], | |
2038 | ); | |
2039 | } | |
2040 | ||
2041 | #[test] | |
2042 | fn closure_2() { | |
2043 | check_types( | |
2044 | r#" | |
2045 | //- minicore: add, fn | |
2046 | ||
2047 | impl core::ops::Add for u64 { | |
2048 | type Output = Self; | |
2049 | fn add(self, rhs: u64) -> Self::Output {0} | |
2050 | } | |
2051 | ||
2052 | impl core::ops::Add for u128 { | |
2053 | type Output = Self; | |
2054 | fn add(self, rhs: u128) -> Self::Output {0} | |
2055 | } | |
2056 | ||
2057 | fn test<F: FnOnce(u32) -> u64>(f: F) { | |
2058 | f(1); | |
2059 | // ^ u32 | |
2060 | //^^^^ u64 | |
2061 | let g = |v| v + 1; | |
2062 | //^^^^^ u64 | |
2063 | //^^^^^^^^^ |u64| -> u64 | |
2064 | g(1u64); | |
2065 | //^^^^^^^ u64 | |
2066 | let h = |v| 1u128 + v; | |
2067 | //^^^^^^^^^^^^^ |u128| -> u128 | |
2068 | }"#, | |
2069 | ); | |
2070 | } | |
2071 | ||
2072 | #[test] | |
2073 | fn closure_as_argument_inference_order() { | |
2074 | check_infer_with_mismatches( | |
2075 | r#" | |
2076 | //- minicore: fn | |
2077 | fn foo1<T, U, F: FnOnce(T) -> U>(x: T, f: F) -> U { loop {} } | |
2078 | fn foo2<T, U, F: FnOnce(T) -> U>(f: F, x: T) -> U { loop {} } | |
2079 | ||
2080 | struct S; | |
2081 | impl S { | |
2082 | fn method(self) -> u64; | |
2083 | ||
2084 | fn foo1<T, U, F: FnOnce(T) -> U>(self, x: T, f: F) -> U { loop {} } | |
2085 | fn foo2<T, U, F: FnOnce(T) -> U>(self, f: F, x: T) -> U { loop {} } | |
2086 | } | |
2087 | ||
2088 | fn test() { | |
2089 | let x1 = foo1(S, |s| s.method()); | |
2090 | let x2 = foo2(|s| s.method(), S); | |
2091 | let x3 = S.foo1(S, |s| s.method()); | |
2092 | let x4 = S.foo2(|s| s.method(), S); | |
2093 | }"#, | |
2094 | expect![[r#" | |
2095 | 33..34 'x': T | |
2096 | 39..40 'f': F | |
2097 | 50..61 '{ loop {} }': U | |
2098 | 52..59 'loop {}': ! | |
2099 | 57..59 '{}': () | |
2100 | 95..96 'f': F | |
2101 | 101..102 'x': T | |
2102 | 112..123 '{ loop {} }': U | |
2103 | 114..121 'loop {}': ! | |
2104 | 119..121 '{}': () | |
2105 | 158..162 'self': S | |
2106 | 210..214 'self': S | |
2107 | 216..217 'x': T | |
2108 | 222..223 'f': F | |
2109 | 233..244 '{ loop {} }': U | |
2110 | 235..242 'loop {}': ! | |
2111 | 240..242 '{}': () | |
2112 | 282..286 'self': S | |
2113 | 288..289 'f': F | |
2114 | 294..295 'x': T | |
2115 | 305..316 '{ loop {} }': U | |
2116 | 307..314 'loop {}': ! | |
2117 | 312..314 '{}': () | |
2118 | 330..489 '{ ... S); }': () | |
2119 | 340..342 'x1': u64 | |
2120 | 345..349 'foo1': fn foo1<S, u64, |S| -> u64>(S, |S| -> u64) -> u64 | |
2121 | 345..368 'foo1(S...hod())': u64 | |
2122 | 350..351 'S': S | |
2123 | 353..367 '|s| s.method()': |S| -> u64 | |
2124 | 354..355 's': S | |
2125 | 357..358 's': S | |
2126 | 357..367 's.method()': u64 | |
2127 | 378..380 'x2': u64 | |
2128 | 383..387 'foo2': fn foo2<S, u64, |S| -> u64>(|S| -> u64, S) -> u64 | |
2129 | 383..406 'foo2(|...(), S)': u64 | |
2130 | 388..402 '|s| s.method()': |S| -> u64 | |
2131 | 389..390 's': S | |
2132 | 392..393 's': S | |
2133 | 392..402 's.method()': u64 | |
2134 | 404..405 'S': S | |
2135 | 416..418 'x3': u64 | |
2136 | 421..422 'S': S | |
2137 | 421..446 'S.foo1...hod())': u64 | |
2138 | 428..429 'S': S | |
2139 | 431..445 '|s| s.method()': |S| -> u64 | |
2140 | 432..433 's': S | |
2141 | 435..436 's': S | |
2142 | 435..445 's.method()': u64 | |
2143 | 456..458 'x4': u64 | |
2144 | 461..462 'S': S | |
2145 | 461..486 'S.foo2...(), S)': u64 | |
2146 | 468..482 '|s| s.method()': |S| -> u64 | |
2147 | 469..470 's': S | |
2148 | 472..473 's': S | |
2149 | 472..482 's.method()': u64 | |
2150 | 484..485 'S': S | |
2151 | "#]], | |
2152 | ); | |
2153 | } | |
2154 | ||
2155 | #[test] | |
2156 | fn fn_item_fn_trait() { | |
2157 | check_types( | |
2158 | r#" | |
2159 | //- minicore: fn | |
2160 | struct S; | |
2161 | ||
2162 | fn foo() -> S { S } | |
2163 | ||
2164 | fn takes_closure<U, F: FnOnce() -> U>(f: F) -> U { f() } | |
2165 | ||
2166 | fn test() { | |
2167 | takes_closure(foo); | |
2168 | } //^^^^^^^^^^^^^^^^^^ S | |
2169 | "#, | |
2170 | ); | |
2171 | } | |
2172 | ||
2173 | #[test] | |
2174 | fn unselected_projection_in_trait_env_1() { | |
2175 | check_types( | |
2176 | r#" | |
2177 | //- /main.rs | |
2178 | trait Trait { | |
2179 | type Item; | |
2180 | } | |
2181 | ||
2182 | trait Trait2 { | |
2183 | fn foo(&self) -> u32; | |
2184 | } | |
2185 | ||
2186 | fn test<T: Trait>() where T::Item: Trait2 { | |
2187 | let x: T::Item = no_matter; | |
2188 | x.foo(); | |
2189 | } //^^^^^^^ u32 | |
2190 | "#, | |
2191 | ); | |
2192 | } | |
2193 | ||
2194 | #[test] | |
2195 | fn unselected_projection_in_trait_env_2() { | |
2196 | check_types( | |
2197 | r#" | |
2198 | trait Trait<T> { | |
2199 | type Item; | |
2200 | } | |
2201 | ||
2202 | trait Trait2 { | |
2203 | fn foo(&self) -> u32; | |
2204 | } | |
2205 | ||
2206 | fn test<T, U>() where T::Item: Trait2, T: Trait<U::Item>, U: Trait<()> { | |
2207 | let x: T::Item = no_matter; | |
2208 | x.foo(); | |
2209 | } //^^^^^^^ u32 | |
2210 | "#, | |
2211 | ); | |
2212 | } | |
2213 | ||
2214 | #[test] | |
2215 | fn unselected_projection_on_impl_self() { | |
2216 | check_infer( | |
2217 | r#" | |
2218 | //- /main.rs | |
2219 | trait Trait { | |
2220 | type Item; | |
2221 | ||
2222 | fn f(&self, x: Self::Item); | |
2223 | } | |
2224 | ||
2225 | struct S; | |
2226 | ||
2227 | impl Trait for S { | |
2228 | type Item = u32; | |
2229 | fn f(&self, x: Self::Item) { let y = x; } | |
2230 | } | |
2231 | ||
2232 | struct S2; | |
2233 | ||
2234 | impl Trait for S2 { | |
2235 | type Item = i32; | |
2236 | fn f(&self, x: <Self>::Item) { let y = x; } | |
2237 | }"#, | |
2238 | expect![[r#" | |
2239 | 40..44 'self': &Self | |
2240 | 46..47 'x': Trait::Item<Self> | |
2241 | 126..130 'self': &S | |
2242 | 132..133 'x': u32 | |
2243 | 147..161 '{ let y = x; }': () | |
2244 | 153..154 'y': u32 | |
2245 | 157..158 'x': u32 | |
2246 | 228..232 'self': &S2 | |
2247 | 234..235 'x': i32 | |
2248 | 251..265 '{ let y = x; }': () | |
2249 | 257..258 'y': i32 | |
2250 | 261..262 'x': i32 | |
2251 | "#]], | |
2252 | ); | |
2253 | } | |
2254 | ||
2255 | #[test] | |
2256 | fn unselected_projection_on_trait_self() { | |
2257 | check_types( | |
2258 | r#" | |
2259 | trait Trait { | |
2260 | type Item; | |
2261 | ||
2262 | fn f(&self) -> Self::Item { loop {} } | |
2263 | } | |
2264 | ||
2265 | struct S; | |
2266 | impl Trait for S { | |
2267 | type Item = u32; | |
2268 | } | |
2269 | ||
2270 | fn test() { | |
2271 | S.f(); | |
2272 | } //^^^^^ u32 | |
2273 | "#, | |
2274 | ); | |
2275 | } | |
2276 | ||
2277 | #[test] | |
2278 | fn unselected_projection_chalk_fold() { | |
2279 | check_types( | |
2280 | r#" | |
2281 | trait Interner {} | |
2282 | trait Fold<I: Interner, TI = I> { | |
2283 | type Result; | |
2284 | } | |
2285 | ||
2286 | struct Ty<I: Interner> {} | |
2287 | impl<I: Interner, TI: Interner> Fold<I, TI> for Ty<I> { | |
2288 | type Result = Ty<TI>; | |
2289 | } | |
2290 | ||
2291 | fn fold<I: Interner, T>(interner: &I, t: T) -> T::Result | |
2292 | where | |
2293 | T: Fold<I, I>, | |
2294 | { | |
2295 | loop {} | |
2296 | } | |
2297 | ||
2298 | fn foo<I: Interner>(interner: &I, t: Ty<I>) { | |
2299 | fold(interner, t); | |
2300 | } //^^^^^^^^^^^^^^^^^ Ty<I> | |
2301 | "#, | |
2302 | ); | |
2303 | } | |
2304 | ||
2305 | #[test] | |
2306 | fn trait_impl_self_ty() { | |
2307 | check_types( | |
2308 | r#" | |
2309 | trait Trait<T> { | |
2310 | fn foo(&self); | |
2311 | } | |
2312 | ||
2313 | struct S; | |
2314 | ||
2315 | impl Trait<Self> for S {} | |
2316 | ||
2317 | fn test() { | |
2318 | S.foo(); | |
2319 | } //^^^^^^^ () | |
2320 | "#, | |
2321 | ); | |
2322 | } | |
2323 | ||
2324 | #[test] | |
2325 | fn trait_impl_self_ty_cycle() { | |
2326 | check_types( | |
2327 | r#" | |
2328 | trait Trait { | |
2329 | fn foo(&self); | |
2330 | } | |
2331 | ||
2332 | struct S<T>; | |
2333 | ||
2334 | impl Trait for S<Self> {} | |
2335 | ||
2336 | fn test() { | |
2337 | S.foo(); | |
2338 | } //^^^^^^^ {unknown} | |
2339 | "#, | |
2340 | ); | |
2341 | } | |
2342 | ||
2343 | #[test] | |
2344 | fn unselected_projection_in_trait_env_cycle_1() { | |
2345 | // This is not a cycle, because the `T: Trait2<T::Item>` bound depends only on the `T: Trait` | |
2346 | // bound, not on itself (since only `Trait` can define `Item`). | |
2347 | check_types( | |
2348 | r#" | |
2349 | trait Trait { | |
2350 | type Item; | |
2351 | } | |
2352 | ||
2353 | trait Trait2<T> {} | |
2354 | ||
2355 | fn test<T: Trait>() where T: Trait2<T::Item> { | |
2356 | let x: T::Item = no_matter; | |
2357 | } //^^^^^^^^^ Trait::Item<T> | |
2358 | "#, | |
2359 | ); | |
2360 | } | |
2361 | ||
2362 | #[test] | |
2363 | fn unselected_projection_in_trait_env_cycle_2() { | |
2364 | // this is a legitimate cycle | |
2365 | check_types( | |
2366 | r#" | |
2367 | //- /main.rs | |
2368 | trait Trait<T> { | |
2369 | type Item; | |
2370 | } | |
2371 | ||
2372 | fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> { | |
2373 | let x: T::Item = no_matter; | |
2374 | } //^^^^^^^^^ {unknown} | |
2375 | "#, | |
2376 | ); | |
2377 | } | |
2378 | ||
2379 | #[test] | |
2380 | fn unselected_projection_in_trait_env_cycle_3() { | |
2381 | // this is a cycle for rustc; we currently accept it | |
2382 | check_types( | |
2383 | r#" | |
2384 | //- /main.rs | |
2385 | trait Trait { | |
2386 | type Item; | |
2387 | type OtherItem; | |
2388 | } | |
2389 | ||
2390 | fn test<T>() where T: Trait<OtherItem = T::Item> { | |
2391 | let x: T::Item = no_matter; | |
2392 | } //^^^^^^^^^ Trait::Item<T> | |
2393 | "#, | |
2394 | ); | |
2395 | } | |
2396 | ||
2397 | #[test] | |
2398 | fn unselected_projection_in_trait_env_no_cycle() { | |
2399 | // this is not a cycle | |
2400 | check_types( | |
2401 | r#" | |
2402 | //- /main.rs | |
2403 | trait Index { | |
2404 | type Output; | |
2405 | } | |
2406 | ||
2407 | type Key<S: UnificationStoreBase> = <S as UnificationStoreBase>::Key; | |
2408 | ||
2409 | pub trait UnificationStoreBase: Index<Output = Key<Self>> { | |
2410 | type Key; | |
2411 | ||
2412 | fn len(&self) -> usize; | |
2413 | } | |
2414 | ||
2415 | pub trait UnificationStoreMut: UnificationStoreBase { | |
2416 | fn push(&mut self, value: Self::Key); | |
2417 | } | |
2418 | ||
2419 | fn test<T>(t: T) where T: UnificationStoreMut { | |
2420 | let x; | |
2421 | t.push(x); | |
2422 | let y: Key<T>; | |
2423 | (x, y); | |
2424 | } //^^^^^^ (UnificationStoreBase::Key<T>, UnificationStoreBase::Key<T>) | |
2425 | "#, | |
2426 | ); | |
2427 | } | |
2428 | ||
2429 | #[test] | |
2430 | fn inline_assoc_type_bounds_1() { | |
2431 | check_types( | |
2432 | r#" | |
2433 | trait Iterator { | |
2434 | type Item; | |
2435 | } | |
2436 | trait OtherTrait<T> { | |
2437 | fn foo(&self) -> T; | |
2438 | } | |
2439 | ||
2440 | // workaround for Chalk assoc type normalization problems | |
2441 | pub struct S<T>; | |
2442 | impl<T: Iterator> Iterator for S<T> { | |
2443 | type Item = <T as Iterator>::Item; | |
2444 | } | |
2445 | ||
2446 | fn test<I: Iterator<Item: OtherTrait<u32>>>() { | |
2447 | let x: <S<I> as Iterator>::Item; | |
2448 | x.foo(); | |
2449 | } //^^^^^^^ u32 | |
2450 | "#, | |
2451 | ); | |
2452 | } | |
2453 | ||
2454 | #[test] | |
2455 | fn inline_assoc_type_bounds_2() { | |
2456 | check_types( | |
2457 | r#" | |
2458 | trait Iterator { | |
2459 | type Item; | |
2460 | } | |
2461 | ||
2462 | fn test<I: Iterator<Item: Iterator<Item = u32>>>() { | |
2463 | let x: <<I as Iterator>::Item as Iterator>::Item; | |
2464 | x; | |
2465 | } //^ u32 | |
2466 | "#, | |
2467 | ); | |
2468 | } | |
2469 | ||
2470 | #[test] | |
2471 | fn proc_macro_server_types() { | |
2472 | check_infer( | |
2473 | r#" | |
2474 | macro_rules! with_api { | |
2475 | ($S:ident, $self:ident, $m:ident) => { | |
2476 | $m! { | |
2477 | TokenStream { | |
2478 | fn new() -> $S::TokenStream; | |
2479 | }, | |
2480 | Group { | |
2481 | }, | |
2482 | } | |
2483 | }; | |
2484 | } | |
2485 | macro_rules! associated_item { | |
2486 | (type TokenStream) => | |
2487 | (type TokenStream: 'static;); | |
2488 | (type Group) => | |
2489 | (type Group: 'static;); | |
2490 | ($($item:tt)*) => ($($item)*;) | |
2491 | } | |
2492 | macro_rules! declare_server_traits { | |
2493 | ($($name:ident { | |
2494 | $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?;)* | |
2495 | }),* $(,)?) => { | |
2496 | pub trait Types { | |
2497 | $(associated_item!(type $name);)* | |
2498 | } | |
2499 | ||
2500 | $(pub trait $name: Types { | |
2501 | $(associated_item!(fn $method($($arg: $arg_ty),*) $(-> $ret_ty)?);)* | |
2502 | })* | |
2503 | ||
2504 | pub trait Server: Types $(+ $name)* {} | |
2505 | impl<S: Types $(+ $name)*> Server for S {} | |
2506 | } | |
2507 | } | |
2508 | ||
2509 | with_api!(Self, self_, declare_server_traits); | |
2510 | struct G {} | |
2511 | struct T {} | |
2512 | struct RustAnalyzer; | |
2513 | impl Types for RustAnalyzer { | |
2514 | type TokenStream = T; | |
2515 | type Group = G; | |
2516 | } | |
2517 | ||
2518 | fn make<T>() -> T { loop {} } | |
2519 | impl TokenStream for RustAnalyzer { | |
2520 | fn new() -> Self::TokenStream { | |
2521 | let group: Self::Group = make(); | |
2522 | make() | |
2523 | } | |
2524 | }"#, | |
2525 | expect![[r#" | |
2526 | 1075..1086 '{ loop {} }': T | |
2527 | 1077..1084 'loop {}': ! | |
2528 | 1082..1084 '{}': () | |
2529 | 1157..1220 '{ ... }': T | |
2530 | 1171..1176 'group': G | |
2531 | 1192..1196 'make': fn make<G>() -> G | |
2532 | 1192..1198 'make()': G | |
2533 | 1208..1212 'make': fn make<T>() -> T | |
2534 | 1208..1214 'make()': T | |
2535 | "#]], | |
2536 | ); | |
2537 | } | |
2538 | ||
2539 | #[test] | |
2540 | fn unify_impl_trait() { | |
2541 | check_infer_with_mismatches( | |
2542 | r#" | |
2543 | //- minicore: sized | |
2544 | trait Trait<T> {} | |
2545 | ||
2546 | fn foo(x: impl Trait<u32>) { loop {} } | |
2547 | fn bar<T>(x: impl Trait<T>) -> T { loop {} } | |
2548 | ||
2549 | struct S<T>(T); | |
2550 | impl<T> Trait<T> for S<T> {} | |
2551 | ||
2552 | fn default<T>() -> T { loop {} } | |
2553 | ||
2554 | fn test() -> impl Trait<i32> { | |
2555 | let s1 = S(default()); | |
2556 | foo(s1); | |
2557 | let x: i32 = bar(S(default())); | |
2558 | S(default()) | |
2559 | }"#, | |
2560 | expect![[r#" | |
2561 | 26..27 'x': impl Trait<u32> | |
2562 | 46..57 '{ loop {} }': () | |
2563 | 48..55 'loop {}': ! | |
2564 | 53..55 '{}': () | |
2565 | 68..69 'x': impl Trait<T> | |
2566 | 91..102 '{ loop {} }': T | |
2567 | 93..100 'loop {}': ! | |
2568 | 98..100 '{}': () | |
2569 | 171..182 '{ loop {} }': T | |
2570 | 173..180 'loop {}': ! | |
2571 | 178..180 '{}': () | |
2572 | 213..309 '{ ...t()) }': S<i32> | |
2573 | 223..225 's1': S<u32> | |
2574 | 228..229 'S': S<u32>(u32) -> S<u32> | |
2575 | 228..240 'S(default())': S<u32> | |
2576 | 230..237 'default': fn default<u32>() -> u32 | |
2577 | 230..239 'default()': u32 | |
2578 | 246..249 'foo': fn foo(S<u32>) | |
2579 | 246..253 'foo(s1)': () | |
2580 | 250..252 's1': S<u32> | |
2581 | 263..264 'x': i32 | |
2582 | 272..275 'bar': fn bar<i32>(S<i32>) -> i32 | |
2583 | 272..289 'bar(S(...lt()))': i32 | |
2584 | 276..277 'S': S<i32>(i32) -> S<i32> | |
2585 | 276..288 'S(default())': S<i32> | |
2586 | 278..285 'default': fn default<i32>() -> i32 | |
2587 | 278..287 'default()': i32 | |
2588 | 295..296 'S': S<i32>(i32) -> S<i32> | |
2589 | 295..307 'S(default())': S<i32> | |
2590 | 297..304 'default': fn default<i32>() -> i32 | |
2591 | 297..306 'default()': i32 | |
2592 | "#]], | |
2593 | ); | |
2594 | } | |
2595 | ||
2596 | #[test] | |
2597 | fn assoc_types_from_bounds() { | |
2598 | check_infer( | |
2599 | r#" | |
2600 | //- minicore: fn | |
2601 | trait T { | |
2602 | type O; | |
2603 | } | |
2604 | ||
2605 | impl T for () { | |
2606 | type O = (); | |
2607 | } | |
2608 | ||
2609 | fn f<X, F>(_v: F) | |
2610 | where | |
2611 | X: T, | |
2612 | F: FnOnce(&X::O), | |
2613 | { } | |
2614 | ||
2615 | fn main() { | |
2616 | f::<(), _>(|z| { z; }); | |
2617 | }"#, | |
2618 | expect![[r#" | |
2619 | 72..74 '_v': F | |
2620 | 117..120 '{ }': () | |
2621 | 132..163 '{ ... }); }': () | |
2622 | 138..148 'f::<(), _>': fn f<(), |&()| -> ()>(|&()| -> ()) | |
2623 | 138..160 'f::<()... z; })': () | |
2624 | 149..159 '|z| { z; }': |&()| -> () | |
2625 | 150..151 'z': &() | |
2626 | 153..159 '{ z; }': () | |
2627 | 155..156 'z': &() | |
2628 | "#]], | |
2629 | ); | |
2630 | } | |
2631 | ||
2632 | #[test] | |
2633 | fn associated_type_bound() { | |
2634 | check_types( | |
2635 | r#" | |
2636 | pub trait Trait { | |
2637 | type Item: OtherTrait<u32>; | |
2638 | } | |
2639 | pub trait OtherTrait<T> { | |
2640 | fn foo(&self) -> T; | |
2641 | } | |
2642 | ||
2643 | // this is just a workaround for chalk#234 | |
2644 | pub struct S<T>; | |
2645 | impl<T: Trait> Trait for S<T> { | |
2646 | type Item = <T as Trait>::Item; | |
2647 | } | |
2648 | ||
2649 | fn test<T: Trait>() { | |
2650 | let y: <S<T> as Trait>::Item = no_matter; | |
2651 | y.foo(); | |
2652 | } //^^^^^^^ u32 | |
2653 | "#, | |
2654 | ); | |
2655 | } | |
2656 | ||
2657 | #[test] | |
2658 | fn dyn_trait_through_chalk() { | |
2659 | check_types( | |
2660 | r#" | |
2661 | //- minicore: deref | |
2662 | struct Box<T: ?Sized> {} | |
2663 | impl<T: ?Sized> core::ops::Deref for Box<T> { | |
2664 | type Target = T; | |
2665 | } | |
2666 | trait Trait { | |
2667 | fn foo(&self); | |
2668 | } | |
2669 | ||
2670 | fn test(x: Box<dyn Trait>) { | |
2671 | x.foo(); | |
2672 | } //^^^^^^^ () | |
2673 | "#, | |
2674 | ); | |
2675 | } | |
2676 | ||
2677 | #[test] | |
2678 | fn string_to_owned() { | |
2679 | check_types( | |
2680 | r#" | |
2681 | struct String {} | |
2682 | pub trait ToOwned { | |
2683 | type Owned; | |
2684 | fn to_owned(&self) -> Self::Owned; | |
2685 | } | |
2686 | impl ToOwned for str { | |
2687 | type Owned = String; | |
2688 | } | |
2689 | fn test() { | |
2690 | "foo".to_owned(); | |
2691 | } //^^^^^^^^^^^^^^^^ String | |
2692 | "#, | |
2693 | ); | |
2694 | } | |
2695 | ||
2696 | #[test] | |
2697 | fn iterator_chain() { | |
2698 | check_infer_with_mismatches( | |
2699 | r#" | |
2700 | //- minicore: fn, option | |
2701 | pub trait Iterator { | |
2702 | type Item; | |
2703 | ||
2704 | fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> | |
2705 | where | |
2706 | F: FnMut(Self::Item) -> Option<B>, | |
2707 | { loop {} } | |
2708 | ||
2709 | fn for_each<F>(self, f: F) | |
2710 | where | |
2711 | F: FnMut(Self::Item), | |
2712 | { loop {} } | |
2713 | } | |
2714 | ||
2715 | pub trait IntoIterator { | |
2716 | type Item; | |
2717 | type IntoIter: Iterator<Item = Self::Item>; | |
2718 | fn into_iter(self) -> Self::IntoIter; | |
2719 | } | |
2720 | ||
2721 | pub struct FilterMap<I, F> { } | |
2722 | impl<B, I: Iterator, F> Iterator for FilterMap<I, F> | |
2723 | where | |
2724 | F: FnMut(I::Item) -> Option<B>, | |
2725 | { | |
2726 | type Item = B; | |
2727 | } | |
2728 | ||
2729 | #[stable(feature = "rust1", since = "1.0.0")] | |
2730 | impl<I: Iterator> IntoIterator for I { | |
2731 | type Item = I::Item; | |
2732 | type IntoIter = I; | |
2733 | ||
2734 | fn into_iter(self) -> I { | |
2735 | self | |
2736 | } | |
2737 | } | |
2738 | ||
2739 | struct Vec<T> {} | |
2740 | impl<T> Vec<T> { | |
2741 | fn new() -> Self { loop {} } | |
2742 | } | |
2743 | ||
2744 | impl<T> IntoIterator for Vec<T> { | |
2745 | type Item = T; | |
2746 | type IntoIter = IntoIter<T>; | |
2747 | } | |
2748 | ||
2749 | pub struct IntoIter<T> { } | |
2750 | impl<T> Iterator for IntoIter<T> { | |
2751 | type Item = T; | |
2752 | } | |
2753 | ||
2754 | fn main() { | |
2755 | Vec::<i32>::new().into_iter() | |
2756 | .filter_map(|x| if x > 0 { Some(x as u32) } else { None }) | |
2757 | .for_each(|y| { y; }); | |
2758 | }"#, | |
2759 | expect![[r#" | |
2760 | 61..65 'self': Self | |
2761 | 67..68 'f': F | |
2762 | 152..163 '{ loop {} }': FilterMap<Self, F> | |
2763 | 154..161 'loop {}': ! | |
2764 | 159..161 '{}': () | |
2765 | 184..188 'self': Self | |
2766 | 190..191 'f': F | |
2767 | 240..251 '{ loop {} }': () | |
2768 | 242..249 'loop {}': ! | |
2769 | 247..249 '{}': () | |
2770 | 360..364 'self': Self | |
2771 | 689..693 'self': I | |
2772 | 700..720 '{ ... }': I | |
2773 | 710..714 'self': I | |
2774 | 779..790 '{ loop {} }': Vec<T> | |
2775 | 781..788 'loop {}': ! | |
2776 | 786..788 '{}': () | |
2777 | 977..1104 '{ ... }); }': () | |
2778 | 983..998 'Vec::<i32>::new': fn new<i32>() -> Vec<i32> | |
2779 | 983..1000 'Vec::<...:new()': Vec<i32> | |
2780 | 983..1012 'Vec::<...iter()': IntoIter<i32> | |
2781 | 983..1075 'Vec::<...one })': FilterMap<IntoIter<i32>, |i32| -> Option<u32>> | |
2782 | 983..1101 'Vec::<... y; })': () | |
2783 | 1029..1074 '|x| if...None }': |i32| -> Option<u32> | |
2784 | 1030..1031 'x': i32 | |
2785 | 1033..1074 'if x >...None }': Option<u32> | |
2786 | 1036..1037 'x': i32 | |
2787 | 1036..1041 'x > 0': bool | |
2788 | 1040..1041 '0': i32 | |
2789 | 1042..1060 '{ Some...u32) }': Option<u32> | |
2790 | 1044..1048 'Some': Some<u32>(u32) -> Option<u32> | |
2791 | 1044..1058 'Some(x as u32)': Option<u32> | |
2792 | 1049..1050 'x': i32 | |
2793 | 1049..1057 'x as u32': u32 | |
2794 | 1066..1074 '{ None }': Option<u32> | |
2795 | 1068..1072 'None': Option<u32> | |
2796 | 1090..1100 '|y| { y; }': |u32| -> () | |
2797 | 1091..1092 'y': u32 | |
2798 | 1094..1100 '{ y; }': () | |
2799 | 1096..1097 'y': u32 | |
2800 | "#]], | |
2801 | ); | |
2802 | } | |
2803 | ||
2804 | #[test] | |
2805 | fn nested_assoc() { | |
2806 | check_types( | |
2807 | r#" | |
2808 | struct Bar; | |
2809 | struct Foo; | |
2810 | ||
2811 | trait A { | |
2812 | type OutputA; | |
2813 | } | |
2814 | ||
2815 | impl A for Bar { | |
2816 | type OutputA = Foo; | |
2817 | } | |
2818 | ||
2819 | trait B { | |
2820 | type Output; | |
2821 | fn foo() -> Self::Output; | |
2822 | } | |
2823 | ||
2824 | impl<T:A> B for T { | |
2825 | type Output = T::OutputA; | |
2826 | fn foo() -> Self::Output { loop {} } | |
2827 | } | |
2828 | ||
2829 | fn main() { | |
2830 | Bar::foo(); | |
2831 | } //^^^^^^^^^^ Foo | |
2832 | "#, | |
2833 | ); | |
2834 | } | |
2835 | ||
2836 | #[test] | |
2837 | fn trait_object_no_coercion() { | |
2838 | check_infer_with_mismatches( | |
2839 | r#" | |
2840 | trait Foo {} | |
2841 | ||
2842 | fn foo(x: &dyn Foo) {} | |
2843 | ||
2844 | fn test(x: &dyn Foo) { | |
2845 | foo(x); | |
2846 | }"#, | |
2847 | expect![[r#" | |
2848 | 21..22 'x': &dyn Foo | |
2849 | 34..36 '{}': () | |
2850 | 46..47 'x': &dyn Foo | |
2851 | 59..74 '{ foo(x); }': () | |
2852 | 65..68 'foo': fn foo(&dyn Foo) | |
2853 | 65..71 'foo(x)': () | |
2854 | 69..70 'x': &dyn Foo | |
2855 | "#]], | |
2856 | ); | |
2857 | } | |
2858 | ||
2859 | #[test] | |
2860 | fn builtin_copy() { | |
2861 | check_infer_with_mismatches( | |
2862 | r#" | |
2863 | //- minicore: copy | |
2864 | struct IsCopy; | |
2865 | impl Copy for IsCopy {} | |
2866 | struct NotCopy; | |
2867 | ||
2868 | trait Test { fn test(&self) -> bool; } | |
2869 | impl<T: Copy> Test for T {} | |
2870 | ||
2871 | fn test() { | |
2872 | IsCopy.test(); | |
2873 | NotCopy.test(); | |
2874 | (IsCopy, IsCopy).test(); | |
2875 | (IsCopy, NotCopy).test(); | |
2876 | }"#, | |
2877 | expect![[r#" | |
2878 | 78..82 'self': &Self | |
2879 | 134..235 '{ ...t(); }': () | |
2880 | 140..146 'IsCopy': IsCopy | |
2881 | 140..153 'IsCopy.test()': bool | |
2882 | 159..166 'NotCopy': NotCopy | |
2883 | 159..173 'NotCopy.test()': {unknown} | |
2884 | 179..195 '(IsCop...sCopy)': (IsCopy, IsCopy) | |
2885 | 179..202 '(IsCop...test()': bool | |
2886 | 180..186 'IsCopy': IsCopy | |
2887 | 188..194 'IsCopy': IsCopy | |
2888 | 208..225 '(IsCop...tCopy)': (IsCopy, NotCopy) | |
2889 | 208..232 '(IsCop...test()': {unknown} | |
2890 | 209..215 'IsCopy': IsCopy | |
2891 | 217..224 'NotCopy': NotCopy | |
2892 | "#]], | |
2893 | ); | |
2894 | } | |
2895 | ||
2896 | #[test] | |
2897 | fn builtin_fn_def_copy() { | |
2898 | check_infer_with_mismatches( | |
2899 | r#" | |
2900 | //- minicore: copy | |
2901 | fn foo() {} | |
2902 | fn bar<T: Copy>(T) -> T {} | |
2903 | struct Struct(usize); | |
2904 | enum Enum { Variant(usize) } | |
2905 | ||
2906 | trait Test { fn test(&self) -> bool; } | |
2907 | impl<T: Copy> Test for T {} | |
2908 | ||
2909 | fn test() { | |
2910 | foo.test(); | |
2911 | bar.test(); | |
2912 | Struct.test(); | |
2913 | Enum::Variant.test(); | |
2914 | }"#, | |
2915 | expect![[r#" | |
2916 | 9..11 '{}': () | |
2917 | 28..29 'T': {unknown} | |
2918 | 36..38 '{}': T | |
2919 | 36..38: expected T, got () | |
2920 | 113..117 'self': &Self | |
2921 | 169..249 '{ ...t(); }': () | |
2922 | 175..178 'foo': fn foo() | |
2923 | 175..185 'foo.test()': bool | |
2924 | 191..194 'bar': fn bar<{unknown}>({unknown}) -> {unknown} | |
2925 | 191..201 'bar.test()': bool | |
2926 | 207..213 'Struct': Struct(usize) -> Struct | |
2927 | 207..220 'Struct.test()': bool | |
2928 | 226..239 'Enum::Variant': Variant(usize) -> Enum | |
2929 | 226..246 'Enum::...test()': bool | |
2930 | "#]], | |
2931 | ); | |
2932 | } | |
2933 | ||
2934 | #[test] | |
2935 | fn builtin_fn_ptr_copy() { | |
2936 | check_infer_with_mismatches( | |
2937 | r#" | |
2938 | //- minicore: copy | |
2939 | trait Test { fn test(&self) -> bool; } | |
2940 | impl<T: Copy> Test for T {} | |
2941 | ||
2942 | fn test(f1: fn(), f2: fn(usize) -> u8, f3: fn(u8, u8) -> &u8) { | |
2943 | f1.test(); | |
2944 | f2.test(); | |
2945 | f3.test(); | |
2946 | }"#, | |
2947 | expect![[r#" | |
2948 | 22..26 'self': &Self | |
2949 | 76..78 'f1': fn() | |
2950 | 86..88 'f2': fn(usize) -> u8 | |
2951 | 107..109 'f3': fn(u8, u8) -> &u8 | |
2952 | 130..178 '{ ...t(); }': () | |
2953 | 136..138 'f1': fn() | |
2954 | 136..145 'f1.test()': bool | |
2955 | 151..153 'f2': fn(usize) -> u8 | |
2956 | 151..160 'f2.test()': bool | |
2957 | 166..168 'f3': fn(u8, u8) -> &u8 | |
2958 | 166..175 'f3.test()': bool | |
2959 | "#]], | |
2960 | ); | |
2961 | } | |
2962 | ||
2963 | #[test] | |
2964 | fn builtin_sized() { | |
2965 | check_infer_with_mismatches( | |
2966 | r#" | |
2967 | //- minicore: sized | |
2968 | trait Test { fn test(&self) -> bool; } | |
2969 | impl<T: Sized> Test for T {} | |
2970 | ||
2971 | fn test() { | |
2972 | 1u8.test(); | |
2973 | (*"foo").test(); // not Sized | |
2974 | (1u8, 1u8).test(); | |
2975 | (1u8, *"foo").test(); // not Sized | |
2976 | }"#, | |
2977 | expect![[r#" | |
2978 | 22..26 'self': &Self | |
2979 | 79..194 '{ ...ized }': () | |
2980 | 85..88 '1u8': u8 | |
2981 | 85..95 '1u8.test()': bool | |
2982 | 101..116 '(*"foo").test()': {unknown} | |
2983 | 102..108 '*"foo"': str | |
2984 | 103..108 '"foo"': &str | |
2985 | 135..145 '(1u8, 1u8)': (u8, u8) | |
2986 | 135..152 '(1u8, ...test()': bool | |
2987 | 136..139 '1u8': u8 | |
2988 | 141..144 '1u8': u8 | |
2989 | 158..171 '(1u8, *"foo")': (u8, str) | |
2990 | 158..178 '(1u8, ...test()': {unknown} | |
2991 | 159..162 '1u8': u8 | |
2992 | 164..170 '*"foo"': str | |
2993 | 165..170 '"foo"': &str | |
2994 | "#]], | |
2995 | ); | |
2996 | } | |
2997 | ||
2998 | #[test] | |
2999 | fn integer_range_iterate() { | |
3000 | check_types( | |
3001 | r#" | |
3002 | //- /main.rs crate:main deps:core | |
3003 | fn test() { | |
3004 | for x in 0..100 { x; } | |
3005 | } //^ i32 | |
3006 | ||
3007 | //- /core.rs crate:core | |
3008 | pub mod ops { | |
3009 | pub struct Range<Idx> { | |
3010 | pub start: Idx, | |
3011 | pub end: Idx, | |
3012 | } | |
3013 | } | |
3014 | ||
3015 | pub mod iter { | |
3016 | pub trait Iterator { | |
3017 | type Item; | |
3018 | } | |
3019 | ||
3020 | pub trait IntoIterator { | |
3021 | type Item; | |
3022 | type IntoIter: Iterator<Item = Self::Item>; | |
3023 | } | |
3024 | ||
3025 | impl<T> IntoIterator for T where T: Iterator { | |
3026 | type Item = <T as Iterator>::Item; | |
3027 | type IntoIter = Self; | |
3028 | } | |
3029 | } | |
3030 | ||
3031 | trait Step {} | |
3032 | impl Step for i32 {} | |
3033 | impl Step for i64 {} | |
3034 | ||
3035 | impl<A: Step> iter::Iterator for ops::Range<A> { | |
3036 | type Item = A; | |
3037 | } | |
3038 | "#, | |
3039 | ); | |
3040 | } | |
3041 | ||
3042 | #[test] | |
3043 | fn infer_closure_arg() { | |
3044 | check_infer( | |
3045 | r#" | |
3046 | //- /lib.rs | |
3047 | ||
3048 | enum Option<T> { | |
3049 | None, | |
3050 | Some(T) | |
3051 | } | |
3052 | ||
3053 | fn foo() { | |
3054 | let s = Option::None; | |
3055 | let f = |x: Option<i32>| {}; | |
3056 | (&f)(s) | |
3057 | }"#, | |
3058 | expect![[r#" | |
3059 | 52..126 '{ ...)(s) }': () | |
3060 | 62..63 's': Option<i32> | |
3061 | 66..78 'Option::None': Option<i32> | |
3062 | 88..89 'f': |Option<i32>| -> () | |
3063 | 92..111 '|x: Op...2>| {}': |Option<i32>| -> () | |
3064 | 93..94 'x': Option<i32> | |
3065 | 109..111 '{}': () | |
3066 | 117..124 '(&f)(s)': () | |
3067 | 118..120 '&f': &|Option<i32>| -> () | |
3068 | 119..120 'f': |Option<i32>| -> () | |
3069 | 122..123 's': Option<i32> | |
3070 | "#]], | |
3071 | ); | |
3072 | } | |
3073 | ||
3074 | #[test] | |
3075 | fn dyn_fn_param_informs_call_site_closure_signature() { | |
3076 | cov_mark::check!(dyn_fn_param_informs_call_site_closure_signature); | |
3077 | check_types( | |
3078 | r#" | |
3079 | //- minicore: fn, coerce_unsized | |
3080 | struct S; | |
3081 | impl S { | |
3082 | fn inherent(&self) -> u8 { 0 } | |
3083 | } | |
3084 | fn take_dyn_fn(f: &dyn Fn(S)) {} | |
3085 | ||
3086 | fn f() { | |
3087 | take_dyn_fn(&|x| { x.inherent(); }); | |
3088 | //^^^^^^^^^^^^ u8 | |
3089 | } | |
3090 | "#, | |
3091 | ); | |
3092 | } | |
3093 | ||
3094 | #[test] | |
3095 | fn infer_fn_trait_arg() { | |
3096 | check_infer_with_mismatches( | |
3097 | r#" | |
3098 | //- minicore: fn, option | |
3099 | fn foo<F, T>(f: F) -> T | |
3100 | where | |
3101 | F: Fn(Option<i32>) -> T, | |
3102 | { | |
3103 | let s = None; | |
3104 | f(s) | |
3105 | } | |
3106 | "#, | |
3107 | expect![[r#" | |
3108 | 13..14 'f': F | |
3109 | 59..89 '{ ...f(s) }': T | |
3110 | 69..70 's': Option<i32> | |
3111 | 73..77 'None': Option<i32> | |
3112 | 83..84 'f': F | |
3113 | 83..87 'f(s)': T | |
3114 | 85..86 's': Option<i32> | |
3115 | "#]], | |
3116 | ); | |
3117 | } | |
3118 | ||
3119 | #[test] | |
3120 | fn infer_box_fn_arg() { | |
3121 | // The type mismatch is because we don't define Unsize and CoerceUnsized | |
3122 | check_infer_with_mismatches( | |
3123 | r#" | |
3124 | //- minicore: fn, deref, option | |
3125 | #[lang = "owned_box"] | |
3126 | pub struct Box<T: ?Sized> { | |
3127 | inner: *mut T, | |
3128 | } | |
3129 | ||
3130 | impl<T: ?Sized> core::ops::Deref for Box<T> { | |
3131 | type Target = T; | |
3132 | ||
3133 | fn deref(&self) -> &T { | |
3134 | &self.inner | |
3135 | } | |
3136 | } | |
3137 | ||
3138 | fn foo() { | |
3139 | let s = None; | |
3140 | let f: Box<dyn FnOnce(&Option<i32>)> = box (|ps| {}); | |
3141 | f(&s); | |
3142 | }"#, | |
3143 | expect![[r#" | |
3144 | 154..158 'self': &Box<T> | |
3145 | 166..193 '{ ... }': &T | |
3146 | 176..187 '&self.inner': &*mut T | |
3147 | 177..181 'self': &Box<T> | |
3148 | 177..187 'self.inner': *mut T | |
3149 | 206..296 '{ ...&s); }': () | |
3150 | 216..217 's': Option<i32> | |
3151 | 220..224 'None': Option<i32> | |
3152 | 234..235 'f': Box<dyn FnOnce(&Option<i32>)> | |
3153 | 269..282 'box (|ps| {})': Box<|&Option<i32>| -> ()> | |
3154 | 274..281 '|ps| {}': |&Option<i32>| -> () | |
3155 | 275..277 'ps': &Option<i32> | |
3156 | 279..281 '{}': () | |
3157 | 288..289 'f': Box<dyn FnOnce(&Option<i32>)> | |
3158 | 288..293 'f(&s)': () | |
3159 | 290..292 '&s': &Option<i32> | |
3160 | 291..292 's': Option<i32> | |
3161 | 269..282: expected Box<dyn FnOnce(&Option<i32>)>, got Box<|&Option<i32>| -> ()> | |
3162 | "#]], | |
3163 | ); | |
3164 | } | |
3165 | ||
3166 | #[test] | |
3167 | fn infer_dyn_fn_output() { | |
3168 | check_types( | |
3169 | r#" | |
3170 | //- minicore: fn | |
3171 | fn foo() { | |
3172 | let f: &dyn Fn() -> i32; | |
3173 | f(); | |
3174 | //^^^ i32 | |
3175 | }"#, | |
3176 | ); | |
3177 | } | |
3178 | ||
3179 | #[test] | |
3180 | fn infer_dyn_fn_once_output() { | |
3181 | check_types( | |
3182 | r#" | |
3183 | //- minicore: fn | |
3184 | fn foo() { | |
3185 | let f: dyn FnOnce() -> i32; | |
3186 | f(); | |
3187 | //^^^ i32 | |
3188 | }"#, | |
3189 | ); | |
3190 | } | |
3191 | ||
3192 | #[test] | |
3193 | fn variable_kinds_1() { | |
3194 | check_types( | |
3195 | r#" | |
3196 | trait Trait<T> { fn get(self, t: T) -> T; } | |
3197 | struct S; | |
3198 | impl Trait<u128> for S {} | |
3199 | impl Trait<f32> for S {} | |
3200 | fn test() { | |
3201 | S.get(1); | |
3202 | //^^^^^^^^ u128 | |
3203 | S.get(1.); | |
3204 | //^^^^^^^^^ f32 | |
3205 | } | |
3206 | "#, | |
3207 | ); | |
3208 | } | |
3209 | ||
3210 | #[test] | |
3211 | fn variable_kinds_2() { | |
3212 | check_types( | |
3213 | r#" | |
3214 | trait Trait { fn get(self) -> Self; } | |
3215 | impl Trait for u128 {} | |
3216 | impl Trait for f32 {} | |
3217 | fn test() { | |
3218 | 1.get(); | |
3219 | //^^^^^^^ u128 | |
3220 | (1.).get(); | |
3221 | //^^^^^^^^^^ f32 | |
3222 | } | |
3223 | "#, | |
3224 | ); | |
3225 | } | |
3226 | ||
3227 | #[test] | |
3228 | fn underscore_import() { | |
3229 | check_types( | |
3230 | r#" | |
3231 | mod tr { | |
3232 | pub trait Tr { | |
3233 | fn method(&self) -> u8 { 0 } | |
3234 | } | |
3235 | } | |
3236 | ||
3237 | struct Tr; | |
3238 | impl crate::tr::Tr for Tr {} | |
3239 | ||
3240 | use crate::tr::Tr as _; | |
3241 | fn test() { | |
3242 | Tr.method(); | |
3243 | //^^^^^^^^^^^ u8 | |
3244 | } | |
3245 | "#, | |
3246 | ); | |
3247 | } | |
3248 | ||
3249 | #[test] | |
3250 | fn inner_use() { | |
3251 | check_types( | |
3252 | r#" | |
3253 | mod m { | |
3254 | pub trait Tr { | |
3255 | fn method(&self) -> u8 { 0 } | |
3256 | } | |
3257 | ||
3258 | impl Tr for () {} | |
3259 | } | |
3260 | ||
3261 | fn f() { | |
3262 | use m::Tr; | |
3263 | ||
3264 | ().method(); | |
3265 | //^^^^^^^^^^^ u8 | |
3266 | } | |
3267 | "#, | |
3268 | ); | |
3269 | } | |
3270 | ||
3271 | #[test] | |
3272 | fn trait_in_scope_with_inner_item() { | |
3273 | check_infer( | |
3274 | r#" | |
3275 | mod m { | |
3276 | pub trait Tr { | |
3277 | fn method(&self) -> u8 { 0 } | |
3278 | } | |
3279 | ||
3280 | impl Tr for () {} | |
3281 | } | |
3282 | ||
3283 | use m::Tr; | |
3284 | ||
3285 | fn f() { | |
3286 | fn inner() { | |
3287 | ().method(); | |
3288 | //^^^^^^^^^^^ u8 | |
3289 | } | |
3290 | }"#, | |
3291 | expect![[r#" | |
3292 | 46..50 'self': &Self | |
3293 | 58..63 '{ 0 }': u8 | |
3294 | 60..61 '0': u8 | |
3295 | 115..185 '{ ... } }': () | |
3296 | 132..183 '{ ... }': () | |
3297 | 142..144 '()': () | |
3298 | 142..153 '().method()': u8 | |
3299 | "#]], | |
3300 | ); | |
3301 | } | |
3302 | ||
3303 | #[test] | |
3304 | fn inner_use_in_block() { | |
3305 | check_types( | |
3306 | r#" | |
3307 | mod m { | |
3308 | pub trait Tr { | |
3309 | fn method(&self) -> u8 { 0 } | |
3310 | } | |
3311 | ||
3312 | impl Tr for () {} | |
3313 | } | |
3314 | ||
3315 | fn f() { | |
3316 | { | |
3317 | use m::Tr; | |
3318 | ||
3319 | ().method(); | |
3320 | //^^^^^^^^^^^ u8 | |
3321 | } | |
3322 | ||
3323 | { | |
3324 | ().method(); | |
3325 | //^^^^^^^^^^^ {unknown} | |
3326 | } | |
3327 | ||
3328 | ().method(); | |
3329 | //^^^^^^^^^^^ {unknown} | |
3330 | } | |
3331 | "#, | |
3332 | ); | |
3333 | } | |
3334 | ||
3335 | #[test] | |
3336 | fn nested_inner_function_calling_self() { | |
3337 | check_infer( | |
3338 | r#" | |
3339 | struct S; | |
3340 | fn f() { | |
3341 | fn inner() -> S { | |
3342 | let s = inner(); | |
3343 | } | |
3344 | }"#, | |
3345 | expect![[r#" | |
3346 | 17..73 '{ ... } }': () | |
3347 | 39..71 '{ ... }': S | |
3348 | 53..54 's': S | |
3349 | 57..62 'inner': fn inner() -> S | |
3350 | 57..64 'inner()': S | |
3351 | "#]], | |
3352 | ) | |
3353 | } | |
3354 | ||
3355 | #[test] | |
3356 | fn infer_default_trait_type_parameter() { | |
3357 | check_infer( | |
3358 | r#" | |
3359 | struct A; | |
3360 | ||
3361 | trait Op<RHS=Self> { | |
3362 | type Output; | |
3363 | ||
3364 | fn do_op(self, rhs: RHS) -> Self::Output; | |
3365 | } | |
3366 | ||
3367 | impl Op for A { | |
3368 | type Output = bool; | |
3369 | ||
3370 | fn do_op(self, rhs: Self) -> Self::Output { | |
3371 | true | |
3372 | } | |
3373 | } | |
3374 | ||
3375 | fn test() { | |
3376 | let x = A; | |
3377 | let y = A; | |
3378 | let r = x.do_op(y); | |
3379 | }"#, | |
3380 | expect![[r#" | |
3381 | 63..67 'self': Self | |
3382 | 69..72 'rhs': RHS | |
3383 | 153..157 'self': A | |
3384 | 159..162 'rhs': A | |
3385 | 186..206 '{ ... }': bool | |
3386 | 196..200 'true': bool | |
3387 | 220..277 '{ ...(y); }': () | |
3388 | 230..231 'x': A | |
3389 | 234..235 'A': A | |
3390 | 245..246 'y': A | |
3391 | 249..250 'A': A | |
3392 | 260..261 'r': bool | |
3393 | 264..265 'x': A | |
3394 | 264..274 'x.do_op(y)': bool | |
3395 | 272..273 'y': A | |
3396 | "#]], | |
3397 | ) | |
3398 | } | |
3399 | ||
3400 | #[test] | |
3401 | fn qualified_path_as_qualified_trait() { | |
3402 | check_infer( | |
3403 | r#" | |
3404 | mod foo { | |
3405 | ||
3406 | pub trait Foo { | |
3407 | type Target; | |
3408 | } | |
3409 | pub trait Bar { | |
3410 | type Output; | |
3411 | fn boo() -> Self::Output { | |
3412 | loop {} | |
3413 | } | |
3414 | } | |
3415 | } | |
3416 | ||
3417 | struct F; | |
3418 | impl foo::Foo for F { | |
3419 | type Target = (); | |
3420 | } | |
3421 | impl foo::Bar for F { | |
3422 | type Output = <F as foo::Foo>::Target; | |
3423 | } | |
3424 | ||
3425 | fn foo() { | |
3426 | use foo::Bar; | |
3427 | let x = <F as Bar>::boo(); | |
3428 | }"#, | |
3429 | expect![[r#" | |
3430 | 132..163 '{ ... }': Bar::Output<Self> | |
3431 | 146..153 'loop {}': ! | |
3432 | 151..153 '{}': () | |
3433 | 306..358 '{ ...o(); }': () | |
3434 | 334..335 'x': () | |
3435 | 338..353 '<F as Bar>::boo': fn boo<F>() -> <F as Bar>::Output | |
3436 | 338..355 '<F as ...:boo()': () | |
3437 | "#]], | |
3438 | ); | |
3439 | } | |
3440 | ||
3441 | #[test] | |
3442 | fn renamed_extern_crate_in_block() { | |
3443 | check_types( | |
3444 | r#" | |
3445 | //- /lib.rs crate:lib deps:serde | |
3446 | use serde::Deserialize; | |
3447 | ||
3448 | struct Foo {} | |
3449 | ||
3450 | const _ : () = { | |
3451 | extern crate serde as _serde; | |
3452 | impl _serde::Deserialize for Foo { | |
3453 | fn deserialize() -> u8 { 0 } | |
3454 | } | |
3455 | }; | |
3456 | ||
3457 | fn foo() { | |
3458 | Foo::deserialize(); | |
3459 | //^^^^^^^^^^^^^^^^^^ u8 | |
3460 | } | |
3461 | ||
3462 | //- /serde.rs crate:serde | |
3463 | ||
3464 | pub trait Deserialize { | |
3465 | fn deserialize() -> u8; | |
3466 | }"#, | |
3467 | ); | |
3468 | } | |
3469 | ||
3470 | #[test] | |
3471 | fn bin_op_with_rhs_is_self_for_assoc_bound() { | |
3472 | check_no_mismatches( | |
3473 | r#"//- minicore: eq | |
3474 | fn repro<T>(t: T) -> bool | |
3475 | where | |
3476 | T: Request, | |
3477 | T::Output: Convertable, | |
3478 | { | |
3479 | let a = execute(&t).convert(); | |
3480 | let b = execute(&t).convert(); | |
3481 | a.eq(&b); | |
3482 | let a = execute(&t).convert2(); | |
3483 | let b = execute(&t).convert2(); | |
3484 | a.eq(&b) | |
3485 | } | |
3486 | fn execute<T>(t: &T) -> T::Output | |
3487 | where | |
3488 | T: Request, | |
3489 | { | |
3490 | <T as Request>::output() | |
3491 | } | |
3492 | trait Convertable { | |
3493 | type TraitSelf: PartialEq<Self::TraitSelf>; | |
3494 | type AssocAsDefaultSelf: PartialEq; | |
3495 | fn convert(self) -> Self::AssocAsDefaultSelf; | |
3496 | fn convert2(self) -> Self::TraitSelf; | |
3497 | } | |
3498 | trait Request { | |
3499 | type Output; | |
3500 | fn output() -> Self::Output; | |
3501 | } | |
3502 | "#, | |
3503 | ); | |
3504 | } | |
3505 | ||
3506 | #[test] | |
3507 | fn bin_op_adt_with_rhs_primitive() { | |
3508 | check_infer_with_mismatches( | |
3509 | r#" | |
3510 | #[lang = "add"] | |
3511 | pub trait Add<Rhs = Self> { | |
3512 | type Output; | |
3513 | fn add(self, rhs: Rhs) -> Self::Output; | |
3514 | } | |
3515 | ||
3516 | struct Wrapper(u32); | |
3517 | impl Add<u32> for Wrapper { | |
3518 | type Output = Self; | |
3519 | fn add(self, rhs: u32) -> Wrapper { | |
3520 | Wrapper(rhs) | |
3521 | } | |
3522 | } | |
3523 | fn main(){ | |
3524 | let wrapped = Wrapper(10); | |
3525 | let num: u32 = 2; | |
3526 | let res = wrapped + num; | |
3527 | ||
3528 | }"#, | |
3529 | expect![[r#" | |
3530 | 72..76 'self': Self | |
3531 | 78..81 'rhs': Rhs | |
3532 | 192..196 'self': Wrapper | |
3533 | 198..201 'rhs': u32 | |
3534 | 219..247 '{ ... }': Wrapper | |
3535 | 229..236 'Wrapper': Wrapper(u32) -> Wrapper | |
3536 | 229..241 'Wrapper(rhs)': Wrapper | |
3537 | 237..240 'rhs': u32 | |
3538 | 259..345 '{ ...um; }': () | |
3539 | 269..276 'wrapped': Wrapper | |
3540 | 279..286 'Wrapper': Wrapper(u32) -> Wrapper | |
3541 | 279..290 'Wrapper(10)': Wrapper | |
3542 | 287..289 '10': u32 | |
3543 | 300..303 'num': u32 | |
3544 | 311..312 '2': u32 | |
3545 | 322..325 'res': Wrapper | |
3546 | 328..335 'wrapped': Wrapper | |
3547 | 328..341 'wrapped + num': Wrapper | |
3548 | 338..341 'num': u32 | |
3549 | "#]], | |
3550 | ) | |
3551 | } | |
3552 | ||
3553 | #[test] | |
3554 | fn array_length() { | |
3555 | check_infer( | |
3556 | r#" | |
3557 | trait T { | |
3558 | type Output; | |
3559 | fn do_thing(&self) -> Self::Output; | |
3560 | } | |
3561 | ||
3562 | impl T for [u8; 4] { | |
3563 | type Output = usize; | |
3564 | fn do_thing(&self) -> Self::Output { | |
3565 | 2 | |
3566 | } | |
3567 | } | |
3568 | ||
3569 | impl T for [u8; 2] { | |
3570 | type Output = u8; | |
3571 | fn do_thing(&self) -> Self::Output { | |
3572 | 2 | |
3573 | } | |
3574 | } | |
3575 | ||
3576 | fn main() { | |
3577 | let v = [0u8; 2]; | |
3578 | let v2 = v.do_thing(); | |
3579 | let v3 = [0u8; 4]; | |
3580 | let v4 = v3.do_thing(); | |
3581 | } | |
3582 | "#, | |
3583 | expect![[r#" | |
3584 | 44..48 'self': &Self | |
3585 | 133..137 'self': &[u8; 4] | |
3586 | 155..172 '{ ... }': usize | |
3587 | 165..166 '2': usize | |
3588 | 236..240 'self': &[u8; 2] | |
3589 | 258..275 '{ ... }': u8 | |
3590 | 268..269 '2': u8 | |
3591 | 289..392 '{ ...g(); }': () | |
3592 | 299..300 'v': [u8; 2] | |
3593 | 303..311 '[0u8; 2]': [u8; 2] | |
3594 | 304..307 '0u8': u8 | |
3595 | 309..310 '2': usize | |
3596 | 321..323 'v2': u8 | |
3597 | 326..327 'v': [u8; 2] | |
3598 | 326..338 'v.do_thing()': u8 | |
3599 | 348..350 'v3': [u8; 4] | |
3600 | 353..361 '[0u8; 4]': [u8; 4] | |
3601 | 354..357 '0u8': u8 | |
3602 | 359..360 '4': usize | |
3603 | 371..373 'v4': usize | |
3604 | 376..378 'v3': [u8; 4] | |
3605 | 376..389 'v3.do_thing()': usize | |
3606 | "#]], | |
3607 | ) | |
3608 | } | |
3609 | ||
3610 | #[test] | |
3611 | fn const_generics() { | |
3612 | check_infer( | |
3613 | r#" | |
3614 | trait T { | |
3615 | type Output; | |
3616 | fn do_thing(&self) -> Self::Output; | |
3617 | } | |
3618 | ||
3619 | impl<const L: usize> T for [u8; L] { | |
3620 | type Output = [u8; L]; | |
3621 | fn do_thing(&self) -> Self::Output { | |
3622 | *self | |
3623 | } | |
3624 | } | |
3625 | ||
3626 | fn main() { | |
3627 | let v = [0u8; 2]; | |
3628 | let v2 = v.do_thing(); | |
3629 | } | |
3630 | "#, | |
3631 | expect![[r#" | |
3632 | 44..48 'self': &Self | |
3633 | 151..155 'self': &[u8; L] | |
3634 | 173..194 '{ ... }': [u8; L] | |
3635 | 183..188 '*self': [u8; L] | |
3636 | 184..188 'self': &[u8; L] | |
3637 | 208..260 '{ ...g(); }': () | |
3638 | 218..219 'v': [u8; 2] | |
3639 | 222..230 '[0u8; 2]': [u8; 2] | |
3640 | 223..226 '0u8': u8 | |
3641 | 228..229 '2': usize | |
3642 | 240..242 'v2': [u8; 2] | |
3643 | 245..246 'v': [u8; 2] | |
3644 | 245..257 'v.do_thing()': [u8; 2] | |
3645 | "#]], | |
3646 | ) | |
3647 | } | |
3648 | ||
3649 | #[test] | |
3650 | fn fn_returning_unit() { | |
3651 | check_infer_with_mismatches( | |
3652 | r#" | |
3653 | //- minicore: fn | |
3654 | fn test<F: FnOnce()>(f: F) { | |
3655 | let _: () = f(); | |
3656 | }"#, | |
3657 | expect![[r#" | |
3658 | 21..22 'f': F | |
3659 | 27..51 '{ ...f(); }': () | |
3660 | 37..38 '_': () | |
3661 | 45..46 'f': F | |
3662 | 45..48 'f()': () | |
3663 | "#]], | |
3664 | ); | |
3665 | } | |
3666 | ||
3667 | #[test] | |
3668 | fn trait_in_scope_of_trait_impl() { | |
3669 | check_infer( | |
3670 | r#" | |
3671 | mod foo { | |
3672 | pub trait Foo { | |
3673 | fn foo(self); | |
3674 | fn bar(self) -> usize { 0 } | |
3675 | } | |
3676 | } | |
3677 | impl foo::Foo for u32 { | |
3678 | fn foo(self) { | |
3679 | let _x = self.bar(); | |
3680 | } | |
3681 | } | |
3682 | "#, | |
3683 | expect![[r#" | |
3684 | 45..49 'self': Self | |
3685 | 67..71 'self': Self | |
3686 | 82..87 '{ 0 }': usize | |
3687 | 84..85 '0': usize | |
3688 | 131..135 'self': u32 | |
3689 | 137..173 '{ ... }': () | |
3690 | 151..153 '_x': usize | |
3691 | 156..160 'self': u32 | |
3692 | 156..166 'self.bar()': usize | |
3693 | "#]], | |
3694 | ); | |
3695 | } | |
3696 | ||
3697 | #[test] | |
3698 | fn infer_async_ret_type() { | |
3699 | check_types( | |
3700 | r#" | |
3701 | //- minicore: future, result | |
3702 | struct Fooey; | |
3703 | ||
3704 | impl Fooey { | |
3705 | fn collect<B: Convert>(self) -> B { | |
3706 | B::new() | |
3707 | } | |
3708 | } | |
3709 | ||
3710 | trait Convert { | |
3711 | fn new() -> Self; | |
3712 | } | |
3713 | impl Convert for u32 { | |
3714 | fn new() -> Self { 0 } | |
3715 | } | |
3716 | ||
3717 | async fn get_accounts() -> Result<u32, ()> { | |
3718 | let ret = Fooey.collect(); | |
3719 | // ^^^^^^^^^^^^^^^ u32 | |
3720 | Ok(ret) | |
3721 | } | |
3722 | "#, | |
3723 | ); | |
3724 | } | |
3725 | ||
3726 | #[test] | |
3727 | fn local_impl_1() { | |
3728 | check!(block_local_impls); | |
3729 | check_types( | |
3730 | r#" | |
3731 | trait Trait<T> { | |
3732 | fn foo(&self) -> T; | |
3733 | } | |
3734 | ||
3735 | fn test() { | |
3736 | struct S; | |
3737 | impl Trait<u32> for S { | |
3738 | fn foo(&self) -> u32 { 0 } | |
3739 | } | |
3740 | ||
3741 | S.foo(); | |
3742 | // ^^^^^^^ u32 | |
3743 | } | |
3744 | "#, | |
3745 | ); | |
3746 | } | |
3747 | ||
3748 | #[test] | |
3749 | fn local_impl_2() { | |
3750 | check!(block_local_impls); | |
3751 | check_types( | |
3752 | r#" | |
3753 | struct S; | |
3754 | ||
3755 | fn test() { | |
3756 | trait Trait<T> { | |
3757 | fn foo(&self) -> T; | |
3758 | } | |
3759 | impl Trait<u32> for S { | |
3760 | fn foo(&self) -> u32 { 0 } | |
3761 | } | |
3762 | ||
3763 | S.foo(); | |
3764 | // ^^^^^^^ u32 | |
3765 | } | |
3766 | "#, | |
3767 | ); | |
3768 | } | |
3769 | ||
3770 | #[test] | |
3771 | fn local_impl_3() { | |
3772 | check!(block_local_impls); | |
3773 | check_types( | |
3774 | r#" | |
3775 | trait Trait<T> { | |
3776 | fn foo(&self) -> T; | |
3777 | } | |
3778 | ||
3779 | fn test() { | |
3780 | struct S1; | |
3781 | { | |
3782 | struct S2; | |
3783 | ||
3784 | impl Trait<S1> for S2 { | |
3785 | fn foo(&self) -> S1 { S1 } | |
3786 | } | |
3787 | ||
3788 | S2.foo(); | |
3789 | // ^^^^^^^^ S1 | |
3790 | } | |
3791 | } | |
3792 | "#, | |
3793 | ); | |
3794 | } | |
3795 | ||
3796 | #[test] | |
3797 | fn associated_type_sized_bounds() { | |
3798 | check_infer( | |
3799 | r#" | |
3800 | //- minicore: sized | |
3801 | struct Yes; | |
3802 | trait IsSized { const IS_SIZED: Yes; } | |
3803 | impl<T: Sized> IsSized for T { const IS_SIZED: Yes = Yes; } | |
3804 | ||
3805 | trait Foo { | |
3806 | type Explicit: Sized; | |
3807 | type Implicit; | |
3808 | type Relaxed: ?Sized; | |
3809 | } | |
3810 | fn f<F: Foo>() { | |
3811 | F::Explicit::IS_SIZED; | |
3812 | F::Implicit::IS_SIZED; | |
3813 | F::Relaxed::IS_SIZED; | |
3814 | } | |
3815 | "#, | |
3816 | expect![[r#" | |
3817 | 104..107 'Yes': Yes | |
3818 | 212..295 '{ ...ZED; }': () | |
3819 | 218..239 'F::Exp..._SIZED': Yes | |
3820 | 245..266 'F::Imp..._SIZED': Yes | |
3821 | 272..292 'F::Rel..._SIZED': {unknown} | |
3822 | "#]], | |
3823 | ); | |
3824 | } | |
3825 | ||
3826 | #[test] | |
3827 | fn dyn_map() { | |
3828 | check_types( | |
3829 | r#" | |
3830 | pub struct Key<K, V, P = (K, V)> {} | |
3831 | ||
3832 | pub trait Policy { | |
3833 | type K; | |
3834 | type V; | |
3835 | } | |
3836 | ||
3837 | impl<K, V> Policy for (K, V) { | |
3838 | type K = K; | |
3839 | type V = V; | |
3840 | } | |
3841 | ||
3842 | pub struct KeyMap<KEY> {} | |
3843 | ||
3844 | impl<P: Policy> KeyMap<Key<P::K, P::V, P>> { | |
3845 | pub fn get(&self, key: &P::K) -> P::V { | |
3846 | loop {} | |
3847 | } | |
3848 | } | |
3849 | ||
3850 | struct Fn {} | |
3851 | struct FunctionId {} | |
3852 | ||
3853 | fn test() { | |
3854 | let key_map: &KeyMap<Key<Fn, FunctionId>> = loop {}; | |
3855 | let key; | |
3856 | let result = key_map.get(key); | |
3857 | //^^^^^^ FunctionId | |
3858 | } | |
3859 | "#, | |
3860 | ) | |
3861 | } | |
f2b60f7d FG |
3862 | |
3863 | #[test] | |
3864 | fn dyn_multiple_auto_traits_in_different_order() { | |
3865 | check_no_mismatches( | |
3866 | r#" | |
3867 | auto trait Send {} | |
3868 | auto trait Sync {} | |
3869 | ||
3870 | fn f(t: &(dyn Sync + Send)) {} | |
3871 | fn g(t: &(dyn Send + Sync)) { | |
3872 | f(t); | |
3873 | } | |
3874 | "#, | |
3875 | ); | |
3876 | ||
3877 | check_no_mismatches( | |
3878 | r#" | |
3879 | auto trait Send {} | |
3880 | auto trait Sync {} | |
3881 | trait T {} | |
3882 | ||
3883 | fn f(t: &(dyn T + Send + Sync)) {} | |
3884 | fn g(t: &(dyn Sync + T + Send)) { | |
3885 | f(t); | |
3886 | } | |
3887 | "#, | |
3888 | ); | |
3889 | ||
3890 | check_infer_with_mismatches( | |
3891 | r#" | |
3892 | auto trait Send {} | |
3893 | auto trait Sync {} | |
3894 | trait T1 {} | |
3895 | trait T2 {} | |
3896 | ||
3897 | fn f(t: &(dyn T1 + T2 + Send + Sync)) {} | |
3898 | fn g(t: &(dyn Sync + T2 + T1 + Send)) { | |
3899 | f(t); | |
3900 | } | |
3901 | "#, | |
3902 | expect![[r#" | |
3903 | 68..69 't': &{unknown} | |
3904 | 101..103 '{}': () | |
3905 | 109..110 't': &{unknown} | |
3906 | 142..155 '{ f(t); }': () | |
3907 | 148..149 'f': fn f(&{unknown}) | |
3908 | 148..152 'f(t)': () | |
3909 | 150..151 't': &{unknown} | |
3910 | "#]], | |
3911 | ); | |
3912 | ||
3913 | check_no_mismatches( | |
3914 | r#" | |
3915 | auto trait Send {} | |
3916 | auto trait Sync {} | |
3917 | trait T { | |
3918 | type Proj: Send + Sync; | |
3919 | } | |
3920 | ||
3921 | fn f(t: &(dyn T<Proj = ()> + Send + Sync)) {} | |
3922 | fn g(t: &(dyn Sync + T<Proj = ()> + Send)) { | |
3923 | f(t); | |
3924 | } | |
3925 | "#, | |
3926 | ); | |
3927 | } | |
3928 | ||
3929 | #[test] | |
3930 | fn dyn_multiple_projection_bounds() { | |
3931 | check_no_mismatches( | |
3932 | r#" | |
3933 | trait Trait { | |
3934 | type T; | |
3935 | type U; | |
3936 | } | |
3937 | ||
3938 | fn f(t: &dyn Trait<T = (), U = ()>) {} | |
3939 | fn g(t: &dyn Trait<U = (), T = ()>) { | |
3940 | f(t); | |
3941 | } | |
3942 | "#, | |
3943 | ); | |
3944 | ||
3945 | check_types( | |
3946 | r#" | |
3947 | trait Trait { | |
3948 | type T; | |
3949 | } | |
3950 | ||
3951 | fn f(t: &dyn Trait<T = (), T = ()>) {} | |
3952 | //^&{unknown} | |
3953 | "#, | |
3954 | ); | |
3955 | } | |
3956 | ||
3957 | #[test] | |
3958 | fn dyn_duplicate_auto_trait() { | |
3959 | check_no_mismatches( | |
3960 | r#" | |
3961 | auto trait Send {} | |
3962 | ||
3963 | fn f(t: &(dyn Send + Send)) {} | |
3964 | fn g(t: &(dyn Send)) { | |
3965 | f(t); | |
3966 | } | |
3967 | "#, | |
3968 | ); | |
3969 | ||
3970 | check_no_mismatches( | |
3971 | r#" | |
3972 | auto trait Send {} | |
3973 | trait T {} | |
3974 | ||
3975 | fn f(t: &(dyn T + Send + Send)) {} | |
3976 | fn g(t: &(dyn T + Send)) { | |
3977 | f(t); | |
3978 | } | |
3979 | "#, | |
3980 | ); | |
3981 | } | |
487cf647 FG |
3982 | |
3983 | #[test] | |
3984 | fn gats_in_path() { | |
3985 | check_types( | |
3986 | r#" | |
3987 | //- minicore: deref | |
3988 | use core::ops::Deref; | |
3989 | trait PointerFamily { | |
3990 | type Pointer<T>: Deref<Target = T>; | |
3991 | } | |
3992 | ||
3993 | fn f<P: PointerFamily>(p: P::Pointer<i32>) { | |
3994 | let a = *p; | |
3995 | //^ i32 | |
3996 | } | |
3997 | fn g<P: PointerFamily>(p: <P as PointerFamily>::Pointer<i32>) { | |
3998 | let a = *p; | |
3999 | //^ i32 | |
4000 | } | |
4001 | "#, | |
4002 | ); | |
4003 | } | |
4004 | ||
4005 | #[test] | |
4006 | fn gats_with_impl_trait() { | |
4007 | // FIXME: the last function (`fn i()`) is not valid Rust as of this writing because you cannot | |
4008 | // specify the same associated type multiple times even if their arguments are different (c.f. | |
4009 | // `fn h()`, which is valid). Reconsider how to treat these invalid types. | |
4010 | check_types( | |
4011 | r#" | |
4012 | //- minicore: deref | |
4013 | use core::ops::Deref; | |
4014 | ||
4015 | trait Trait { | |
4016 | type Assoc<T>: Deref<Target = T>; | |
4017 | fn get<U>(&self) -> Self::Assoc<U>; | |
4018 | } | |
4019 | ||
4020 | fn f<T>(v: impl Trait) { | |
4021 | let a = v.get::<i32>().deref(); | |
4022 | //^ &i32 | |
4023 | let a = v.get::<T>().deref(); | |
4024 | //^ &T | |
4025 | } | |
4026 | fn g<'a, T: 'a>(v: impl Trait<Assoc<T> = &'a T>) { | |
4027 | let a = v.get::<T>(); | |
4028 | //^ &T | |
4029 | let a = v.get::<()>(); | |
4030 | //^ Trait::Assoc<(), impl Trait<Assoc<T> = &T>> | |
4031 | } | |
4032 | fn h<'a>(v: impl Trait<Assoc<i32> = &'a i32> + Trait<Assoc<i64> = &'a i64>) { | |
4033 | let a = v.get::<i32>(); | |
4034 | //^ &i32 | |
4035 | let a = v.get::<i64>(); | |
4036 | //^ &i64 | |
4037 | } | |
4038 | fn i<'a>(v: impl Trait<Assoc<i32> = &'a i32, Assoc<i64> = &'a i64>) { | |
4039 | let a = v.get::<i32>(); | |
4040 | //^ &i32 | |
4041 | let a = v.get::<i64>(); | |
4042 | //^ &i64 | |
4043 | } | |
4044 | "#, | |
4045 | ); | |
4046 | } | |
4047 | ||
4048 | #[test] | |
4049 | fn gats_with_dyn() { | |
4050 | // This test is here to keep track of how we infer things despite traits with GATs being not | |
4051 | // object-safe currently. | |
4052 | // FIXME: reconsider how to treat these invalid types. | |
4053 | check_infer_with_mismatches( | |
4054 | r#" | |
4055 | //- minicore: deref | |
4056 | use core::ops::Deref; | |
4057 | ||
4058 | trait Trait { | |
4059 | type Assoc<T>: Deref<Target = T>; | |
4060 | fn get<U>(&self) -> Self::Assoc<U>; | |
4061 | } | |
4062 | ||
4063 | fn f<'a>(v: &dyn Trait<Assoc<i32> = &'a i32>) { | |
4064 | v.get::<i32>().deref(); | |
4065 | } | |
4066 | "#, | |
4067 | expect![[r#" | |
4068 | 90..94 'self': &Self | |
4069 | 127..128 'v': &(dyn Trait<Assoc<i32> = &i32>) | |
4070 | 164..195 '{ ...f(); }': () | |
4071 | 170..171 'v': &(dyn Trait<Assoc<i32> = &i32>) | |
4072 | 170..184 'v.get::<i32>()': &i32 | |
4073 | 170..192 'v.get:...eref()': &i32 | |
4074 | "#]], | |
4075 | ); | |
4076 | } | |
4077 | ||
4078 | #[test] | |
4079 | fn gats_in_associated_type_binding() { | |
4080 | check_types( | |
4081 | r#" | |
4082 | trait Trait { | |
4083 | type Assoc<T>; | |
4084 | fn get<U>(&self) -> Self::Assoc<U>; | |
4085 | } | |
4086 | ||
4087 | fn f<T>(t: T) | |
4088 | where | |
4089 | T: Trait<Assoc<i32> = u32>, | |
4090 | T: Trait<Assoc<isize> = usize>, | |
4091 | { | |
4092 | let a = t.get::<i32>(); | |
4093 | //^ u32 | |
4094 | let a = t.get::<isize>(); | |
4095 | //^ usize | |
4096 | let a = t.get::<()>(); | |
4097 | //^ Trait::Assoc<(), T> | |
4098 | } | |
4099 | ||
4100 | "#, | |
4101 | ); | |
4102 | } | |
f25598a0 FG |
4103 | |
4104 | #[test] | |
4105 | fn bin_op_with_scalar_fallback() { | |
4106 | // Extra impls are significant so that chalk doesn't give us definite guidances. | |
4107 | check_types( | |
4108 | r#" | |
4109 | //- minicore: add | |
4110 | use core::ops::Add; | |
4111 | ||
4112 | struct Vec2<T>(T, T); | |
4113 | ||
4114 | impl Add for Vec2<i32> { | |
4115 | type Output = Self; | |
4116 | fn add(self, rhs: Self) -> Self::Output { loop {} } | |
4117 | } | |
4118 | impl Add for Vec2<u32> { | |
4119 | type Output = Self; | |
4120 | fn add(self, rhs: Self) -> Self::Output { loop {} } | |
4121 | } | |
4122 | impl Add for Vec2<f32> { | |
4123 | type Output = Self; | |
4124 | fn add(self, rhs: Self) -> Self::Output { loop {} } | |
4125 | } | |
4126 | impl Add for Vec2<f64> { | |
4127 | type Output = Self; | |
4128 | fn add(self, rhs: Self) -> Self::Output { loop {} } | |
4129 | } | |
4130 | ||
4131 | fn test() { | |
4132 | let a = Vec2(1, 2); | |
4133 | let b = Vec2(3, 4); | |
4134 | let c = a + b; | |
4135 | //^ Vec2<i32> | |
4136 | let a = Vec2(1., 2.); | |
4137 | let b = Vec2(3., 4.); | |
4138 | let c = a + b; | |
4139 | //^ Vec2<f64> | |
4140 | } | |
4141 | "#, | |
4142 | ); | |
4143 | } | |
4144 | ||
4145 | #[test] | |
4146 | fn trait_method_with_scalar_fallback() { | |
4147 | check_types( | |
4148 | r#" | |
4149 | trait Trait { | |
4150 | type Output; | |
4151 | fn foo(&self) -> Self::Output; | |
4152 | } | |
4153 | impl<T> Trait for T { | |
4154 | type Output = T; | |
4155 | fn foo(&self) -> Self::Output { loop {} } | |
4156 | } | |
4157 | fn test() { | |
4158 | let a = 42; | |
4159 | let b = a.foo(); | |
4160 | //^ i32 | |
4161 | let a = 3.14; | |
4162 | let b = a.foo(); | |
4163 | //^ f64 | |
4164 | } | |
4165 | "#, | |
4166 | ); | |
4167 | } |