]> git.proxmox.com Git - rustc.git/blob - src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs
New upstream version 1.64.0+dfsg1
[rustc.git] / src / tools / rust-analyzer / crates / ide-assists / src / handlers / add_missing_impl_members.rs
1 use hir::HasSource;
2 use ide_db::{
3 syntax_helpers::insert_whitespace_into_node::insert_ws_into, traits::resolve_target_trait,
4 };
5 use syntax::ast::{self, make, AstNode};
6
7 use crate::{
8 assist_context::{AssistContext, Assists},
9 utils::{
10 add_trait_assoc_items_to_impl, filter_assoc_items, gen_trait_fn_body, render_snippet,
11 Cursor, DefaultMethods,
12 },
13 AssistId, AssistKind,
14 };
15
16 // Assist: add_impl_missing_members
17 //
18 // Adds scaffold for required impl members.
19 //
20 // ```
21 // trait Trait<T> {
22 // type X;
23 // fn foo(&self) -> T;
24 // fn bar(&self) {}
25 // }
26 //
27 // impl Trait<u32> for () {$0
28 //
29 // }
30 // ```
31 // ->
32 // ```
33 // trait Trait<T> {
34 // type X;
35 // fn foo(&self) -> T;
36 // fn bar(&self) {}
37 // }
38 //
39 // impl Trait<u32> for () {
40 // $0type X;
41 //
42 // fn foo(&self) -> u32 {
43 // todo!()
44 // }
45 // }
46 // ```
47 pub(crate) fn add_missing_impl_members(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
48 add_missing_impl_members_inner(
49 acc,
50 ctx,
51 DefaultMethods::No,
52 "add_impl_missing_members",
53 "Implement missing members",
54 )
55 }
56
57 // Assist: add_impl_default_members
58 //
59 // Adds scaffold for overriding default impl members.
60 //
61 // ```
62 // trait Trait {
63 // type X;
64 // fn foo(&self);
65 // fn bar(&self) {}
66 // }
67 //
68 // impl Trait for () {
69 // type X = ();
70 // fn foo(&self) {}$0
71 // }
72 // ```
73 // ->
74 // ```
75 // trait Trait {
76 // type X;
77 // fn foo(&self);
78 // fn bar(&self) {}
79 // }
80 //
81 // impl Trait for () {
82 // type X = ();
83 // fn foo(&self) {}
84 //
85 // $0fn bar(&self) {}
86 // }
87 // ```
88 pub(crate) fn add_missing_default_members(
89 acc: &mut Assists,
90 ctx: &AssistContext<'_>,
91 ) -> Option<()> {
92 add_missing_impl_members_inner(
93 acc,
94 ctx,
95 DefaultMethods::Only,
96 "add_impl_default_members",
97 "Implement default members",
98 )
99 }
100
101 fn add_missing_impl_members_inner(
102 acc: &mut Assists,
103 ctx: &AssistContext<'_>,
104 mode: DefaultMethods,
105 assist_id: &'static str,
106 label: &'static str,
107 ) -> Option<()> {
108 let _p = profile::span("add_missing_impl_members_inner");
109 let impl_def = ctx.find_node_at_offset::<ast::Impl>()?;
110 let target_scope = ctx.sema.scope(impl_def.syntax())?;
111 let trait_ = resolve_target_trait(&ctx.sema, &impl_def)?;
112
113 let missing_items = filter_assoc_items(
114 &ctx.sema,
115 &ide_db::traits::get_missing_assoc_items(&ctx.sema, &impl_def),
116 mode,
117 );
118
119 if missing_items.is_empty() {
120 return None;
121 }
122
123 let target = impl_def.syntax().text_range();
124 acc.add(AssistId(assist_id, AssistKind::QuickFix), label, target, |builder| {
125 let missing_items = missing_items
126 .into_iter()
127 .map(|it| {
128 if ctx.sema.hir_file_for(it.syntax()).is_macro() {
129 if let Some(it) = ast::AssocItem::cast(insert_ws_into(it.syntax().clone())) {
130 return it;
131 }
132 }
133 it.clone_for_update()
134 })
135 .collect();
136 let (new_impl_def, first_new_item) = add_trait_assoc_items_to_impl(
137 &ctx.sema,
138 missing_items,
139 trait_,
140 impl_def.clone(),
141 target_scope,
142 );
143 match ctx.config.snippet_cap {
144 None => builder.replace(target, new_impl_def.to_string()),
145 Some(cap) => {
146 let mut cursor = Cursor::Before(first_new_item.syntax());
147 let placeholder;
148 if let DefaultMethods::No = mode {
149 if let ast::AssocItem::Fn(func) = &first_new_item {
150 if try_gen_trait_body(ctx, func, &trait_, &impl_def).is_none() {
151 if let Some(m) =
152 func.syntax().descendants().find_map(ast::MacroCall::cast)
153 {
154 if m.syntax().text() == "todo!()" {
155 placeholder = m;
156 cursor = Cursor::Replace(placeholder.syntax());
157 }
158 }
159 }
160 }
161 }
162 builder.replace_snippet(
163 cap,
164 target,
165 render_snippet(cap, new_impl_def.syntax(), cursor),
166 )
167 }
168 };
169 })
170 }
171
172 fn try_gen_trait_body(
173 ctx: &AssistContext<'_>,
174 func: &ast::Fn,
175 trait_: &hir::Trait,
176 impl_def: &ast::Impl,
177 ) -> Option<()> {
178 let trait_path = make::ext::ident_path(&trait_.name(ctx.db()).to_string());
179 let hir_ty = ctx.sema.resolve_type(&impl_def.self_ty()?)?;
180 let adt = hir_ty.as_adt()?.source(ctx.db())?;
181 gen_trait_fn_body(func, &trait_path, &adt.value)
182 }
183
184 #[cfg(test)]
185 mod tests {
186 use crate::tests::{check_assist, check_assist_not_applicable};
187
188 use super::*;
189
190 #[test]
191 fn test_add_missing_impl_members() {
192 check_assist(
193 add_missing_impl_members,
194 r#"
195 trait Foo {
196 type Output;
197
198 const CONST: usize = 42;
199
200 fn foo(&self);
201 fn bar(&self);
202 fn baz(&self);
203 }
204
205 struct S;
206
207 impl Foo for S {
208 fn bar(&self) {}
209 $0
210 }"#,
211 r#"
212 trait Foo {
213 type Output;
214
215 const CONST: usize = 42;
216
217 fn foo(&self);
218 fn bar(&self);
219 fn baz(&self);
220 }
221
222 struct S;
223
224 impl Foo for S {
225 fn bar(&self) {}
226
227 $0type Output;
228
229 const CONST: usize = 42;
230
231 fn foo(&self) {
232 todo!()
233 }
234
235 fn baz(&self) {
236 todo!()
237 }
238
239 }"#,
240 );
241 }
242
243 #[test]
244 fn test_copied_overriden_members() {
245 check_assist(
246 add_missing_impl_members,
247 r#"
248 trait Foo {
249 fn foo(&self);
250 fn bar(&self) -> bool { true }
251 fn baz(&self) -> u32 { 42 }
252 }
253
254 struct S;
255
256 impl Foo for S {
257 fn bar(&self) {}
258 $0
259 }"#,
260 r#"
261 trait Foo {
262 fn foo(&self);
263 fn bar(&self) -> bool { true }
264 fn baz(&self) -> u32 { 42 }
265 }
266
267 struct S;
268
269 impl Foo for S {
270 fn bar(&self) {}
271
272 fn foo(&self) {
273 ${0:todo!()}
274 }
275
276 }"#,
277 );
278 }
279
280 #[test]
281 fn test_empty_impl_def() {
282 check_assist(
283 add_missing_impl_members,
284 r#"
285 trait Foo { fn foo(&self); }
286 struct S;
287 impl Foo for S { $0 }"#,
288 r#"
289 trait Foo { fn foo(&self); }
290 struct S;
291 impl Foo for S {
292 fn foo(&self) {
293 ${0:todo!()}
294 }
295 }"#,
296 );
297 }
298
299 #[test]
300 fn test_impl_def_without_braces() {
301 check_assist(
302 add_missing_impl_members,
303 r#"
304 trait Foo { fn foo(&self); }
305 struct S;
306 impl Foo for S$0"#,
307 r#"
308 trait Foo { fn foo(&self); }
309 struct S;
310 impl Foo for S {
311 fn foo(&self) {
312 ${0:todo!()}
313 }
314 }"#,
315 );
316 }
317
318 #[test]
319 fn fill_in_type_params_1() {
320 check_assist(
321 add_missing_impl_members,
322 r#"
323 trait Foo<T> { fn foo(&self, t: T) -> &T; }
324 struct S;
325 impl Foo<u32> for S { $0 }"#,
326 r#"
327 trait Foo<T> { fn foo(&self, t: T) -> &T; }
328 struct S;
329 impl Foo<u32> for S {
330 fn foo(&self, t: u32) -> &u32 {
331 ${0:todo!()}
332 }
333 }"#,
334 );
335 }
336
337 #[test]
338 fn fill_in_type_params_2() {
339 check_assist(
340 add_missing_impl_members,
341 r#"
342 trait Foo<T> { fn foo(&self, t: T) -> &T; }
343 struct S;
344 impl<U> Foo<U> for S { $0 }"#,
345 r#"
346 trait Foo<T> { fn foo(&self, t: T) -> &T; }
347 struct S;
348 impl<U> Foo<U> for S {
349 fn foo(&self, t: U) -> &U {
350 ${0:todo!()}
351 }
352 }"#,
353 );
354 }
355
356 #[test]
357 fn test_cursor_after_empty_impl_def() {
358 check_assist(
359 add_missing_impl_members,
360 r#"
361 trait Foo { fn foo(&self); }
362 struct S;
363 impl Foo for S {}$0"#,
364 r#"
365 trait Foo { fn foo(&self); }
366 struct S;
367 impl Foo for S {
368 fn foo(&self) {
369 ${0:todo!()}
370 }
371 }"#,
372 )
373 }
374
375 #[test]
376 fn test_qualify_path_1() {
377 check_assist(
378 add_missing_impl_members,
379 r#"
380 mod foo {
381 pub struct Bar;
382 trait Foo { fn foo(&self, bar: Bar); }
383 }
384 struct S;
385 impl foo::Foo for S { $0 }"#,
386 r#"
387 mod foo {
388 pub struct Bar;
389 trait Foo { fn foo(&self, bar: Bar); }
390 }
391 struct S;
392 impl foo::Foo for S {
393 fn foo(&self, bar: foo::Bar) {
394 ${0:todo!()}
395 }
396 }"#,
397 );
398 }
399
400 #[test]
401 fn test_qualify_path_2() {
402 check_assist(
403 add_missing_impl_members,
404 r#"
405 mod foo {
406 pub mod bar {
407 pub struct Bar;
408 pub trait Foo { fn foo(&self, bar: Bar); }
409 }
410 }
411
412 use foo::bar;
413
414 struct S;
415 impl bar::Foo for S { $0 }"#,
416 r#"
417 mod foo {
418 pub mod bar {
419 pub struct Bar;
420 pub trait Foo { fn foo(&self, bar: Bar); }
421 }
422 }
423
424 use foo::bar;
425
426 struct S;
427 impl bar::Foo for S {
428 fn foo(&self, bar: bar::Bar) {
429 ${0:todo!()}
430 }
431 }"#,
432 );
433 }
434
435 #[test]
436 fn test_qualify_path_generic() {
437 check_assist(
438 add_missing_impl_members,
439 r#"
440 mod foo {
441 pub struct Bar<T>;
442 trait Foo { fn foo(&self, bar: Bar<u32>); }
443 }
444 struct S;
445 impl foo::Foo for S { $0 }"#,
446 r#"
447 mod foo {
448 pub struct Bar<T>;
449 trait Foo { fn foo(&self, bar: Bar<u32>); }
450 }
451 struct S;
452 impl foo::Foo for S {
453 fn foo(&self, bar: foo::Bar<u32>) {
454 ${0:todo!()}
455 }
456 }"#,
457 );
458 }
459
460 #[test]
461 fn test_qualify_path_and_substitute_param() {
462 check_assist(
463 add_missing_impl_members,
464 r#"
465 mod foo {
466 pub struct Bar<T>;
467 trait Foo<T> { fn foo(&self, bar: Bar<T>); }
468 }
469 struct S;
470 impl foo::Foo<u32> for S { $0 }"#,
471 r#"
472 mod foo {
473 pub struct Bar<T>;
474 trait Foo<T> { fn foo(&self, bar: Bar<T>); }
475 }
476 struct S;
477 impl foo::Foo<u32> for S {
478 fn foo(&self, bar: foo::Bar<u32>) {
479 ${0:todo!()}
480 }
481 }"#,
482 );
483 }
484
485 #[test]
486 fn test_substitute_param_no_qualify() {
487 // when substituting params, the substituted param should not be qualified!
488 check_assist(
489 add_missing_impl_members,
490 r#"
491 mod foo {
492 trait Foo<T> { fn foo(&self, bar: T); }
493 pub struct Param;
494 }
495 struct Param;
496 struct S;
497 impl foo::Foo<Param> for S { $0 }"#,
498 r#"
499 mod foo {
500 trait Foo<T> { fn foo(&self, bar: T); }
501 pub struct Param;
502 }
503 struct Param;
504 struct S;
505 impl foo::Foo<Param> for S {
506 fn foo(&self, bar: Param) {
507 ${0:todo!()}
508 }
509 }"#,
510 );
511 }
512
513 #[test]
514 fn test_qualify_path_associated_item() {
515 check_assist(
516 add_missing_impl_members,
517 r#"
518 mod foo {
519 pub struct Bar<T>;
520 impl Bar<T> { type Assoc = u32; }
521 trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); }
522 }
523 struct S;
524 impl foo::Foo for S { $0 }"#,
525 r#"
526 mod foo {
527 pub struct Bar<T>;
528 impl Bar<T> { type Assoc = u32; }
529 trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); }
530 }
531 struct S;
532 impl foo::Foo for S {
533 fn foo(&self, bar: foo::Bar<u32>::Assoc) {
534 ${0:todo!()}
535 }
536 }"#,
537 );
538 }
539
540 #[test]
541 fn test_qualify_path_nested() {
542 check_assist(
543 add_missing_impl_members,
544 r#"
545 mod foo {
546 pub struct Bar<T>;
547 pub struct Baz;
548 trait Foo { fn foo(&self, bar: Bar<Baz>); }
549 }
550 struct S;
551 impl foo::Foo for S { $0 }"#,
552 r#"
553 mod foo {
554 pub struct Bar<T>;
555 pub struct Baz;
556 trait Foo { fn foo(&self, bar: Bar<Baz>); }
557 }
558 struct S;
559 impl foo::Foo for S {
560 fn foo(&self, bar: foo::Bar<foo::Baz>) {
561 ${0:todo!()}
562 }
563 }"#,
564 );
565 }
566
567 #[test]
568 fn test_qualify_path_fn_trait_notation() {
569 check_assist(
570 add_missing_impl_members,
571 r#"
572 mod foo {
573 pub trait Fn<Args> { type Output; }
574 trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); }
575 }
576 struct S;
577 impl foo::Foo for S { $0 }"#,
578 r#"
579 mod foo {
580 pub trait Fn<Args> { type Output; }
581 trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); }
582 }
583 struct S;
584 impl foo::Foo for S {
585 fn foo(&self, bar: dyn Fn(u32) -> i32) {
586 ${0:todo!()}
587 }
588 }"#,
589 );
590 }
591
592 #[test]
593 fn test_empty_trait() {
594 check_assist_not_applicable(
595 add_missing_impl_members,
596 r#"
597 trait Foo;
598 struct S;
599 impl Foo for S { $0 }"#,
600 )
601 }
602
603 #[test]
604 fn test_ignore_unnamed_trait_members_and_default_methods() {
605 check_assist_not_applicable(
606 add_missing_impl_members,
607 r#"
608 trait Foo {
609 fn (arg: u32);
610 fn valid(some: u32) -> bool { false }
611 }
612 struct S;
613 impl Foo for S { $0 }"#,
614 )
615 }
616
617 #[test]
618 fn test_with_docstring_and_attrs() {
619 check_assist(
620 add_missing_impl_members,
621 r#"
622 #[doc(alias = "test alias")]
623 trait Foo {
624 /// doc string
625 type Output;
626
627 #[must_use]
628 fn foo(&self);
629 }
630 struct S;
631 impl Foo for S {}$0"#,
632 r#"
633 #[doc(alias = "test alias")]
634 trait Foo {
635 /// doc string
636 type Output;
637
638 #[must_use]
639 fn foo(&self);
640 }
641 struct S;
642 impl Foo for S {
643 $0type Output;
644
645 fn foo(&self) {
646 todo!()
647 }
648 }"#,
649 )
650 }
651
652 #[test]
653 fn test_default_methods() {
654 check_assist(
655 add_missing_default_members,
656 r#"
657 trait Foo {
658 type Output;
659
660 const CONST: usize = 42;
661
662 fn valid(some: u32) -> bool { false }
663 fn foo(some: u32) -> bool;
664 }
665 struct S;
666 impl Foo for S { $0 }"#,
667 r#"
668 trait Foo {
669 type Output;
670
671 const CONST: usize = 42;
672
673 fn valid(some: u32) -> bool { false }
674 fn foo(some: u32) -> bool;
675 }
676 struct S;
677 impl Foo for S {
678 $0fn valid(some: u32) -> bool { false }
679 }"#,
680 )
681 }
682
683 #[test]
684 fn test_generic_single_default_parameter() {
685 check_assist(
686 add_missing_impl_members,
687 r#"
688 trait Foo<T = Self> {
689 fn bar(&self, other: &T);
690 }
691
692 struct S;
693 impl Foo for S { $0 }"#,
694 r#"
695 trait Foo<T = Self> {
696 fn bar(&self, other: &T);
697 }
698
699 struct S;
700 impl Foo for S {
701 fn bar(&self, other: &Self) {
702 ${0:todo!()}
703 }
704 }"#,
705 )
706 }
707
708 #[test]
709 fn test_generic_default_parameter_is_second() {
710 check_assist(
711 add_missing_impl_members,
712 r#"
713 trait Foo<T1, T2 = Self> {
714 fn bar(&self, this: &T1, that: &T2);
715 }
716
717 struct S<T>;
718 impl Foo<T> for S<T> { $0 }"#,
719 r#"
720 trait Foo<T1, T2 = Self> {
721 fn bar(&self, this: &T1, that: &T2);
722 }
723
724 struct S<T>;
725 impl Foo<T> for S<T> {
726 fn bar(&self, this: &T, that: &Self) {
727 ${0:todo!()}
728 }
729 }"#,
730 )
731 }
732
733 #[test]
734 fn test_assoc_type_bounds_are_removed() {
735 check_assist(
736 add_missing_impl_members,
737 r#"
738 trait Tr {
739 type Ty: Copy + 'static;
740 }
741
742 impl Tr for ()$0 {
743 }"#,
744 r#"
745 trait Tr {
746 type Ty: Copy + 'static;
747 }
748
749 impl Tr for () {
750 $0type Ty;
751 }"#,
752 )
753 }
754
755 #[test]
756 fn test_whitespace_fixup_preserves_bad_tokens() {
757 check_assist(
758 add_missing_impl_members,
759 r#"
760 trait Tr {
761 fn foo();
762 }
763
764 impl Tr for ()$0 {
765 +++
766 }"#,
767 r#"
768 trait Tr {
769 fn foo();
770 }
771
772 impl Tr for () {
773 fn foo() {
774 ${0:todo!()}
775 }
776 +++
777 }"#,
778 )
779 }
780
781 #[test]
782 fn test_whitespace_fixup_preserves_comments() {
783 check_assist(
784 add_missing_impl_members,
785 r#"
786 trait Tr {
787 fn foo();
788 }
789
790 impl Tr for ()$0 {
791 // very important
792 }"#,
793 r#"
794 trait Tr {
795 fn foo();
796 }
797
798 impl Tr for () {
799 fn foo() {
800 ${0:todo!()}
801 }
802 // very important
803 }"#,
804 )
805 }
806
807 #[test]
808 fn weird_path() {
809 check_assist(
810 add_missing_impl_members,
811 r#"
812 trait Test {
813 fn foo(&self, x: crate)
814 }
815 impl Test for () {
816 $0
817 }
818 "#,
819 r#"
820 trait Test {
821 fn foo(&self, x: crate)
822 }
823 impl Test for () {
824 fn foo(&self, x: crate) {
825 ${0:todo!()}
826 }
827 }
828 "#,
829 )
830 }
831
832 #[test]
833 fn missing_generic_type() {
834 check_assist(
835 add_missing_impl_members,
836 r#"
837 trait Foo<BAR> {
838 fn foo(&self, bar: BAR);
839 }
840 impl Foo for () {
841 $0
842 }
843 "#,
844 r#"
845 trait Foo<BAR> {
846 fn foo(&self, bar: BAR);
847 }
848 impl Foo for () {
849 fn foo(&self, bar: BAR) {
850 ${0:todo!()}
851 }
852 }
853 "#,
854 )
855 }
856
857 #[test]
858 fn does_not_requalify_self_as_crate() {
859 check_assist(
860 add_missing_default_members,
861 r"
862 struct Wrapper<T>(T);
863
864 trait T {
865 fn f(self) -> Wrapper<Self> {
866 Wrapper(self)
867 }
868 }
869
870 impl T for () {
871 $0
872 }
873 ",
874 r"
875 struct Wrapper<T>(T);
876
877 trait T {
878 fn f(self) -> Wrapper<Self> {
879 Wrapper(self)
880 }
881 }
882
883 impl T for () {
884 $0fn f(self) -> Wrapper<Self> {
885 Wrapper(self)
886 }
887 }
888 ",
889 );
890 }
891
892 #[test]
893 fn test_default_body_generation() {
894 check_assist(
895 add_missing_impl_members,
896 r#"
897 //- minicore: default
898 struct Foo(usize);
899
900 impl Default for Foo {
901 $0
902 }
903 "#,
904 r#"
905 struct Foo(usize);
906
907 impl Default for Foo {
908 $0fn default() -> Self {
909 Self(Default::default())
910 }
911 }
912 "#,
913 )
914 }
915
916 #[test]
917 fn test_from_macro() {
918 check_assist(
919 add_missing_default_members,
920 r#"
921 macro_rules! foo {
922 () => {
923 trait FooB {
924 fn foo<'lt>(&'lt self) {}
925 }
926 }
927 }
928 foo!();
929 struct Foo(usize);
930
931 impl FooB for Foo {
932 $0
933 }
934 "#,
935 r#"
936 macro_rules! foo {
937 () => {
938 trait FooB {
939 fn foo<'lt>(&'lt self) {}
940 }
941 }
942 }
943 foo!();
944 struct Foo(usize);
945
946 impl FooB for Foo {
947 $0fn foo< 'lt>(& 'lt self){}
948 }
949 "#,
950 )
951 }
952
953 #[test]
954 fn test_assoc_type_when_trait_with_same_name_in_scope() {
955 check_assist(
956 add_missing_impl_members,
957 r#"
958 pub trait Foo {}
959
960 pub trait Types {
961 type Foo;
962 }
963
964 pub trait Behavior<T: Types> {
965 fn reproduce(&self, foo: T::Foo);
966 }
967
968 pub struct Impl;
969
970 impl<T: Types> Behavior<T> for Impl { $0 }"#,
971 r#"
972 pub trait Foo {}
973
974 pub trait Types {
975 type Foo;
976 }
977
978 pub trait Behavior<T: Types> {
979 fn reproduce(&self, foo: T::Foo);
980 }
981
982 pub struct Impl;
983
984 impl<T: Types> Behavior<T> for Impl {
985 fn reproduce(&self, foo: <T as Types>::Foo) {
986 ${0:todo!()}
987 }
988 }"#,
989 );
990 }
991
992 #[test]
993 fn test_assoc_type_on_concrete_type() {
994 check_assist(
995 add_missing_impl_members,
996 r#"
997 pub trait Types {
998 type Foo;
999 }
1000
1001 impl Types for u32 {
1002 type Foo = bool;
1003 }
1004
1005 pub trait Behavior<T: Types> {
1006 fn reproduce(&self, foo: T::Foo);
1007 }
1008
1009 pub struct Impl;
1010
1011 impl Behavior<u32> for Impl { $0 }"#,
1012 r#"
1013 pub trait Types {
1014 type Foo;
1015 }
1016
1017 impl Types for u32 {
1018 type Foo = bool;
1019 }
1020
1021 pub trait Behavior<T: Types> {
1022 fn reproduce(&self, foo: T::Foo);
1023 }
1024
1025 pub struct Impl;
1026
1027 impl Behavior<u32> for Impl {
1028 fn reproduce(&self, foo: <u32 as Types>::Foo) {
1029 ${0:todo!()}
1030 }
1031 }"#,
1032 );
1033 }
1034
1035 #[test]
1036 fn test_assoc_type_on_concrete_type_qualified() {
1037 check_assist(
1038 add_missing_impl_members,
1039 r#"
1040 pub trait Types {
1041 type Foo;
1042 }
1043
1044 impl Types for std::string::String {
1045 type Foo = bool;
1046 }
1047
1048 pub trait Behavior<T: Types> {
1049 fn reproduce(&self, foo: T::Foo);
1050 }
1051
1052 pub struct Impl;
1053
1054 impl Behavior<std::string::String> for Impl { $0 }"#,
1055 r#"
1056 pub trait Types {
1057 type Foo;
1058 }
1059
1060 impl Types for std::string::String {
1061 type Foo = bool;
1062 }
1063
1064 pub trait Behavior<T: Types> {
1065 fn reproduce(&self, foo: T::Foo);
1066 }
1067
1068 pub struct Impl;
1069
1070 impl Behavior<std::string::String> for Impl {
1071 fn reproduce(&self, foo: <std::string::String as Types>::Foo) {
1072 ${0:todo!()}
1073 }
1074 }"#,
1075 );
1076 }
1077
1078 #[test]
1079 fn test_assoc_type_on_concrete_type_multi_option_ambiguous() {
1080 check_assist(
1081 add_missing_impl_members,
1082 r#"
1083 pub trait Types {
1084 type Foo;
1085 }
1086
1087 pub trait Types2 {
1088 type Foo;
1089 }
1090
1091 impl Types for u32 {
1092 type Foo = bool;
1093 }
1094
1095 impl Types2 for u32 {
1096 type Foo = String;
1097 }
1098
1099 pub trait Behavior<T: Types + Types2> {
1100 fn reproduce(&self, foo: <T as Types2>::Foo);
1101 }
1102
1103 pub struct Impl;
1104
1105 impl Behavior<u32> for Impl { $0 }"#,
1106 r#"
1107 pub trait Types {
1108 type Foo;
1109 }
1110
1111 pub trait Types2 {
1112 type Foo;
1113 }
1114
1115 impl Types for u32 {
1116 type Foo = bool;
1117 }
1118
1119 impl Types2 for u32 {
1120 type Foo = String;
1121 }
1122
1123 pub trait Behavior<T: Types + Types2> {
1124 fn reproduce(&self, foo: <T as Types2>::Foo);
1125 }
1126
1127 pub struct Impl;
1128
1129 impl Behavior<u32> for Impl {
1130 fn reproduce(&self, foo: <u32 as Types2>::Foo) {
1131 ${0:todo!()}
1132 }
1133 }"#,
1134 );
1135 }
1136
1137 #[test]
1138 fn test_assoc_type_on_concrete_type_multi_option() {
1139 check_assist(
1140 add_missing_impl_members,
1141 r#"
1142 pub trait Types {
1143 type Foo;
1144 }
1145
1146 pub trait Types2 {
1147 type Bar;
1148 }
1149
1150 impl Types for u32 {
1151 type Foo = bool;
1152 }
1153
1154 impl Types2 for u32 {
1155 type Bar = String;
1156 }
1157
1158 pub trait Behavior<T: Types + Types2> {
1159 fn reproduce(&self, foo: T::Bar);
1160 }
1161
1162 pub struct Impl;
1163
1164 impl Behavior<u32> for Impl { $0 }"#,
1165 r#"
1166 pub trait Types {
1167 type Foo;
1168 }
1169
1170 pub trait Types2 {
1171 type Bar;
1172 }
1173
1174 impl Types for u32 {
1175 type Foo = bool;
1176 }
1177
1178 impl Types2 for u32 {
1179 type Bar = String;
1180 }
1181
1182 pub trait Behavior<T: Types + Types2> {
1183 fn reproduce(&self, foo: T::Bar);
1184 }
1185
1186 pub struct Impl;
1187
1188 impl Behavior<u32> for Impl {
1189 fn reproduce(&self, foo: <u32 as Types2>::Bar) {
1190 ${0:todo!()}
1191 }
1192 }"#,
1193 );
1194 }
1195
1196 #[test]
1197 fn test_assoc_type_on_concrete_type_multi_option_foreign() {
1198 check_assist(
1199 add_missing_impl_members,
1200 r#"
1201 mod bar {
1202 pub trait Types2 {
1203 type Bar;
1204 }
1205 }
1206
1207 pub trait Types {
1208 type Foo;
1209 }
1210
1211 impl Types for u32 {
1212 type Foo = bool;
1213 }
1214
1215 impl bar::Types2 for u32 {
1216 type Bar = String;
1217 }
1218
1219 pub trait Behavior<T: Types + bar::Types2> {
1220 fn reproduce(&self, foo: T::Bar);
1221 }
1222
1223 pub struct Impl;
1224
1225 impl Behavior<u32> for Impl { $0 }"#,
1226 r#"
1227 mod bar {
1228 pub trait Types2 {
1229 type Bar;
1230 }
1231 }
1232
1233 pub trait Types {
1234 type Foo;
1235 }
1236
1237 impl Types for u32 {
1238 type Foo = bool;
1239 }
1240
1241 impl bar::Types2 for u32 {
1242 type Bar = String;
1243 }
1244
1245 pub trait Behavior<T: Types + bar::Types2> {
1246 fn reproduce(&self, foo: T::Bar);
1247 }
1248
1249 pub struct Impl;
1250
1251 impl Behavior<u32> for Impl {
1252 fn reproduce(&self, foo: <u32 as bar::Types2>::Bar) {
1253 ${0:todo!()}
1254 }
1255 }"#,
1256 );
1257 }
1258
1259 #[test]
1260 fn test_transform_path_in_path_expr() {
1261 check_assist(
1262 add_missing_default_members,
1263 r#"
1264 pub trait Const {
1265 const FOO: u32;
1266 }
1267
1268 pub trait Trait<T: Const> {
1269 fn foo() -> bool {
1270 match T::FOO {
1271 0 => true,
1272 _ => false,
1273 }
1274 }
1275 }
1276
1277 impl Const for u32 {
1278 const FOO: u32 = 1;
1279 }
1280
1281 struct Impl;
1282
1283 impl Trait<u32> for Impl { $0 }"#,
1284 r#"
1285 pub trait Const {
1286 const FOO: u32;
1287 }
1288
1289 pub trait Trait<T: Const> {
1290 fn foo() -> bool {
1291 match T::FOO {
1292 0 => true,
1293 _ => false,
1294 }
1295 }
1296 }
1297
1298 impl Const for u32 {
1299 const FOO: u32 = 1;
1300 }
1301
1302 struct Impl;
1303
1304 impl Trait<u32> for Impl {
1305 $0fn foo() -> bool {
1306 match <u32 as Const>::FOO {
1307 0 => true,
1308 _ => false,
1309 }
1310 }
1311 }"#,
1312 );
1313 }
1314
1315 #[test]
1316 fn test_default_partial_eq() {
1317 check_assist(
1318 add_missing_default_members,
1319 r#"
1320 //- minicore: eq
1321 struct SomeStruct {
1322 data: usize,
1323 field: (usize, usize),
1324 }
1325 impl PartialEq for SomeStruct {$0}
1326 "#,
1327 r#"
1328 struct SomeStruct {
1329 data: usize,
1330 field: (usize, usize),
1331 }
1332 impl PartialEq for SomeStruct {
1333 $0fn ne(&self, other: &Self) -> bool {
1334 !self.eq(other)
1335 }
1336 }
1337 "#,
1338 );
1339 }
1340 }