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