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