1use hir::HasSource;
2use syntax::{
3 Edition,
4 ast::{self, AstNode, syntax_factory::SyntaxFactory},
5 syntax_editor::{Position, SyntaxEditor},
6};
7
8use crate::{
9 AssistId,
10 assist_context::{AssistContext, Assists},
11 utils::{
12 DefaultMethods, IgnoreAssocItems, add_trait_assoc_items_to_impl, filter_assoc_items,
13 gen_trait_fn_body,
14 },
15};
16
17pub(crate) fn add_missing_impl_members(
49 acc: &mut Assists,
50 ctx: &AssistContext<'_, '_>,
51) -> Option<()> {
52 add_missing_impl_members_inner(
53 acc,
54 ctx,
55 DefaultMethods::No,
56 IgnoreAssocItems::DocHiddenAttrPresent,
57 "add_impl_missing_members",
58 "Implement missing members",
59 )
60}
61
62pub(crate) fn add_missing_default_members(
94 acc: &mut Assists,
95 ctx: &AssistContext<'_, '_>,
96) -> Option<()> {
97 add_missing_impl_members_inner(
98 acc,
99 ctx,
100 DefaultMethods::Only,
101 IgnoreAssocItems::DocHiddenAttrPresent,
102 "add_impl_default_members",
103 "Implement default members",
104 )
105}
106
107fn add_missing_impl_members_inner(
108 acc: &mut Assists,
109 ctx: &AssistContext<'_, '_>,
110 mode: DefaultMethods,
111 ignore_items: IgnoreAssocItems,
112 assist_id: &'static str,
113 label: &'static str,
114) -> Option<()> {
115 let _p = tracing::info_span!("add_missing_impl_members_inner").entered();
116 let impl_def = ctx.find_node_at_offset::<ast::Impl>()?;
117 let impl_ = ctx.sema.to_def(&impl_def)?;
118
119 if ctx.token_at_offset().all(|t| {
120 t.parent_ancestors()
121 .take_while(|node| node != impl_def.syntax())
122 .any(|s| ast::BlockExpr::can_cast(s.kind()) || ast::ParamList::can_cast(s.kind()))
123 }) {
124 return None;
125 }
126
127 let target_scope = ctx.sema.scope(impl_def.syntax())?;
128 let trait_ref = impl_.trait_ref(ctx.db())?;
129 let trait_ = trait_ref.trait_();
130
131 let mut ign_item = ignore_items;
132
133 if let IgnoreAssocItems::DocHiddenAttrPresent = ignore_items {
134 let db = ctx.db();
136 if trait_.module(db).krate(db).origin(db).is_local() {
137 ign_item = IgnoreAssocItems::No;
138 }
139 }
140
141 let missing_items = filter_assoc_items(
142 &ctx.sema,
143 &ide_db::traits::get_missing_assoc_items(&ctx.sema, &impl_def),
144 mode,
145 ign_item,
146 );
147
148 if missing_items.is_empty() {
149 return None;
150 }
151
152 let target = impl_def.syntax().text_range();
153 acc.add(AssistId::quick_fix(assist_id), label, target, |edit| {
154 let editor = edit.make_editor(impl_def.syntax());
155 let make = editor.make();
156 let new_item = add_trait_assoc_items_to_impl(
157 make,
158 &ctx.sema,
159 ctx.config,
160 &missing_items,
161 trait_,
162 &impl_def,
163 &target_scope,
164 );
165
166 let Some((first_new_item, other_items)) = new_item.split_first() else {
167 return;
168 };
169
170 let mut first_new_item = if let DefaultMethods::No = mode
171 && let ast::AssocItem::Fn(func) = &first_new_item
172 && let Some(body) = try_gen_trait_body(
173 make,
174 ctx,
175 func,
176 trait_ref,
177 &impl_def,
178 target_scope.krate().edition(ctx.sema.db),
179 )
180 && let Some(func_body) = func.body()
181 {
182 let (func_editor, _) = SyntaxEditor::new(first_new_item.syntax().clone());
183 func_editor.replace(func_body.syntax(), body.syntax());
184 ast::AssocItem::cast(func_editor.finish().new_root().clone())
185 } else {
186 Some(first_new_item.clone())
187 };
188
189 let new_assoc_items = first_new_item
190 .clone()
191 .into_iter()
192 .chain(other_items.iter().cloned())
193 .collect::<Vec<_>>();
194
195 if let Some(assoc_item_list) = impl_def.assoc_item_list() {
196 assoc_item_list.add_items(&editor, new_assoc_items);
197 } else {
198 let assoc_item_list = make.assoc_item_list(new_assoc_items);
199 editor.insert_all(
200 Position::after(impl_def.syntax()),
201 vec![make.whitespace(" ").into(), assoc_item_list.syntax().clone().into()],
202 );
203 first_new_item = assoc_item_list.assoc_items().next();
204 }
205
206 if let Some(cap) = ctx.config.snippet_cap {
207 let mut placeholder = None;
208 if let DefaultMethods::No = mode
209 && let Some(ast::AssocItem::Fn(func)) = &first_new_item
210 && let Some(m) = func.syntax().descendants().find_map(ast::MacroCall::cast)
211 && m.syntax().text() == "todo!()"
212 {
213 placeholder = Some(m);
214 }
215
216 if let Some(macro_call) = placeholder {
217 let placeholder = edit.make_placeholder_snippet(cap);
218 editor.add_annotation(macro_call.syntax(), placeholder);
219 } else if let Some(first_new_item) = first_new_item {
220 let tabstop = edit.make_tabstop_before(cap);
221 editor.add_annotation(first_new_item.syntax(), tabstop);
222 };
223 };
224 edit.add_file_edits(ctx.vfs_file_id(), editor);
225 })
226}
227
228fn try_gen_trait_body(
229 make: &SyntaxFactory,
230 ctx: &AssistContext<'_, '_>,
231 func: &ast::Fn,
232 trait_ref: hir::TraitRef<'_>,
233 impl_def: &ast::Impl,
234 edition: Edition,
235) -> Option<ast::BlockExpr> {
236 let trait_path =
237 make.ident_path(&trait_ref.trait_().name(ctx.db()).display(ctx.db(), edition).to_string());
238 let hir_ty = ctx.sema.resolve_type(&impl_def.self_ty()?)?;
239 let adt = hir_ty.as_adt()?.source(ctx.db())?;
240 gen_trait_fn_body(make, func, &trait_path, &adt.value, Some(trait_ref))
241}
242
243#[cfg(test)]
244mod tests {
245 use crate::tests::{check_assist, check_assist_not_applicable};
246
247 use super::*;
248
249 #[test]
250 fn test_add_missing_impl_members() {
251 check_assist(
252 add_missing_impl_members,
253 r#"
254trait Foo {
255 type Output;
256
257 const CONST: usize = 42;
258 const CONST_2: i32;
259
260 fn foo(&self);
261 fn bar(&self);
262 fn baz(&self);
263}
264
265struct S;
266
267impl Foo for S {
268 fn bar(&self) {}
269$0
270}"#,
271 r#"
272trait Foo {
273 type Output;
274
275 const CONST: usize = 42;
276 const CONST_2: i32;
277
278 fn foo(&self);
279 fn bar(&self);
280 fn baz(&self);
281}
282
283struct S;
284
285impl Foo for S {
286 fn bar(&self) {}
287
288 $0type Output;
289
290 const CONST_2: i32;
291
292 fn foo(&self) {
293 todo!()
294 }
295
296 fn baz(&self) {
297 todo!()
298 }
299
300}"#,
301 );
302 }
303
304 #[test]
305 fn test_copied_overridden_members() {
306 check_assist(
307 add_missing_impl_members,
308 r#"
309trait Foo {
310 fn foo(&self);
311 fn bar(&self) -> bool { true }
312 fn baz(&self) -> u32 { 42 }
313}
314
315struct S;
316
317impl Foo for S {
318 fn bar(&self) {}
319$0
320}"#,
321 r#"
322trait Foo {
323 fn foo(&self);
324 fn bar(&self) -> bool { true }
325 fn baz(&self) -> u32 { 42 }
326}
327
328struct S;
329
330impl Foo for S {
331 fn bar(&self) {}
332
333 fn foo(&self) {
334 ${0:todo!()}
335 }
336
337}"#,
338 );
339 }
340
341 #[test]
342 fn test_empty_impl_def() {
343 check_assist(
344 add_missing_impl_members,
345 r#"
346trait Foo { fn foo(&self); }
347struct S;
348impl Foo for S { $0 }"#,
349 r#"
350trait Foo { fn foo(&self); }
351struct S;
352impl Foo for S {
353 fn foo(&self) {
354 ${0:todo!()}
355 }
356}"#,
357 );
358 }
359
360 #[test]
361 fn test_impl_def_without_braces_macro() {
362 check_assist(
363 add_missing_impl_members,
364 r#"
365trait Foo { fn foo(&self); }
366struct S;
367impl Foo for S$0"#,
368 r#"
369trait Foo { fn foo(&self); }
370struct S;
371impl Foo for S {
372 fn foo(&self) {
373 ${0:todo!()}
374 }
375}"#,
376 );
377 }
378
379 #[test]
380 fn test_impl_def_without_braces_tabstop_first_item() {
381 check_assist(
382 add_missing_impl_members,
383 r#"
384trait Foo {
385 type Output;
386 fn foo(&self);
387}
388struct S;
389impl Foo for S { $0 }"#,
390 r#"
391trait Foo {
392 type Output;
393 fn foo(&self);
394}
395struct S;
396impl Foo for S {
397 $0type Output;
398
399 fn foo(&self) {
400 todo!()
401 }
402}"#,
403 );
404 }
405
406 #[test]
407 fn fill_in_type_params_1() {
408 check_assist(
409 add_missing_impl_members,
410 r#"
411trait Foo<T> { fn foo(&self, t: T) -> &T; }
412struct S;
413impl Foo<u32> for S { $0 }"#,
414 r#"
415trait Foo<T> { fn foo(&self, t: T) -> &T; }
416struct S;
417impl Foo<u32> for S {
418 fn foo(&self, t: u32) -> &u32 {
419 ${0:todo!()}
420 }
421}"#,
422 );
423 }
424
425 #[test]
426 fn fill_in_type_params_2() {
427 check_assist(
428 add_missing_impl_members,
429 r#"
430trait Foo<T> { fn foo(&self, t: T) -> &T; }
431struct S;
432impl<U> Foo<U> for S { $0 }"#,
433 r#"
434trait Foo<T> { fn foo(&self, t: T) -> &T; }
435struct S;
436impl<U> Foo<U> for S {
437 fn foo(&self, t: U) -> &U {
438 ${0:todo!()}
439 }
440}"#,
441 );
442 }
443
444 #[test]
445 fn test_lifetime_substitution() {
446 check_assist(
447 add_missing_impl_members,
448 r#"
449pub trait Trait<'a, 'b, A, B, C> {
450 fn foo(&self, one: &'a A, another: &'b B) -> &'a C;
451}
452
453impl<'x, 'y, T, V, U> Trait<'x, 'y, T, V, U> for () {$0}"#,
454 r#"
455pub trait Trait<'a, 'b, A, B, C> {
456 fn foo(&self, one: &'a A, another: &'b B) -> &'a C;
457}
458
459impl<'x, 'y, T, V, U> Trait<'x, 'y, T, V, U> for () {
460 fn foo(&self, one: &'x T, another: &'y V) -> &'x U {
461 ${0:todo!()}
462 }
463}"#,
464 );
465 }
466
467 #[test]
468 fn test_lifetime_substitution_with_body() {
469 check_assist(
470 add_missing_default_members,
471 r#"
472pub trait Trait<'a, 'b, A, B, C: Default> {
473 fn foo(&self, _one: &'a A, _another: &'b B) -> (C, &'a i32) {
474 let value: &'a i32 = &0;
475 (C::default(), value)
476 }
477}
478
479impl<'x, 'y, T, V, U: Default> Trait<'x, 'y, T, V, U> for () {$0}"#,
480 r#"
481pub trait Trait<'a, 'b, A, B, C: Default> {
482 fn foo(&self, _one: &'a A, _another: &'b B) -> (C, &'a i32) {
483 let value: &'a i32 = &0;
484 (C::default(), value)
485 }
486}
487
488impl<'x, 'y, T, V, U: Default> Trait<'x, 'y, T, V, U> for () {
489 $0fn foo(&self, _one: &'x T, _another: &'y V) -> (U, &'x i32) {
490 let value: &'x i32 = &0;
491 (<U>::default(), value)
492 }
493}"#,
494 );
495 }
496
497 #[test]
498 fn test_const_substitution() {
499 check_assist(
500 add_missing_default_members,
501 r#"
502struct Bar<const N: usize> {
503 bar: [i32, N]
504}
505
506trait Foo<const N: usize, T> {
507 fn get_n_sq(&self, arg: &T) -> usize { N * N }
508 fn get_array(&self, arg: Bar<N>) -> [i32; N] { [1; N] }
509}
510
511struct S<T> {
512 wrapped: T
513}
514
515impl<const X: usize, Y, Z> Foo<X, Z> for S<Y> {
516 $0
517}"#,
518 r#"
519struct Bar<const N: usize> {
520 bar: [i32, N]
521}
522
523trait Foo<const N: usize, T> {
524 fn get_n_sq(&self, arg: &T) -> usize { N * N }
525 fn get_array(&self, arg: Bar<N>) -> [i32; N] { [1; N] }
526}
527
528struct S<T> {
529 wrapped: T
530}
531
532impl<const X: usize, Y, Z> Foo<X, Z> for S<Y> {
533 $0fn get_n_sq(&self, arg: &Z) -> usize { X * X }
534
535 fn get_array(&self, arg: Bar<X>) -> [i32; X] { [1; X] }
536}"#,
537 )
538 }
539
540 #[test]
541 fn test_const_substitution_2() {
542 check_assist(
543 add_missing_default_members,
544 r#"
545trait Foo<const N: usize, const M: usize, T> {
546 fn get_sum(&self, arg: &T) -> usize { N + M }
547}
548
549impl<X> Foo<42, {20 + 22}, X> for () {
550 $0
551}"#,
552 r#"
553trait Foo<const N: usize, const M: usize, T> {
554 fn get_sum(&self, arg: &T) -> usize { N + M }
555}
556
557impl<X> Foo<42, {20 + 22}, X> for () {
558 $0fn get_sum(&self, arg: &X) -> usize { 42 + {20 + 22} }
559}"#,
560 )
561 }
562
563 #[test]
564 fn test_const_substitution_with_defaults() {
565 check_assist(
566 add_missing_default_members,
567 r#"
568trait Foo<T, const N: usize = 42, const M: bool = false, const P: char = 'a'> {
569 fn get_n(&self) -> usize { N }
570 fn get_m(&self) -> bool { M }
571 fn get_p(&self) -> char { P }
572 fn get_array(&self, arg: &T) -> [bool; N] { [M; N] }
573}
574
575impl<X> Foo<X> for () {
576 $0
577}"#,
578 r#"
579trait Foo<T, const N: usize = 42, const M: bool = false, const P: char = 'a'> {
580 fn get_n(&self) -> usize { N }
581 fn get_m(&self) -> bool { M }
582 fn get_p(&self) -> char { P }
583 fn get_array(&self, arg: &T) -> [bool; N] { [M; N] }
584}
585
586impl<X> Foo<X> for () {
587 $0fn get_n(&self) -> usize { 42 }
588
589 fn get_m(&self) -> bool { false }
590
591 fn get_p(&self) -> char { 'a' }
592
593 fn get_array(&self, arg: &X) -> [bool; 42] { [false; 42] }
594}"#,
595 );
596 }
597
598 #[test]
599 fn test_const_substitution_with_defaults_2() {
600 check_assist(
601 add_missing_impl_members,
602 r#"
603mod m {
604 pub const LEN: usize = 42;
605 pub trait Foo<const M: usize = LEN, const N: usize = M, T = [bool; N]> {
606 fn get_t(&self) -> T;
607 }
608}
609
610impl m::Foo for () {
611 $0
612}"#,
613 r#"
614mod m {
615 pub const LEN: usize = 42;
616 pub trait Foo<const M: usize = LEN, const N: usize = M, T = [bool; N]> {
617 fn get_t(&self) -> T;
618 }
619}
620
621impl m::Foo for () {
622 fn get_t(&self) -> [bool; m::LEN] {
623 ${0:todo!()}
624 }
625}"#,
626 )
627 }
628
629 #[test]
630 fn test_const_substitution_with_defaults_3() {
631 check_assist(
632 add_missing_default_members,
633 r#"
634mod m {
635 pub const VAL: usize = 0;
636
637 pub trait Foo<const N: usize = {40 + 2}, const M: usize = {VAL + 1}> {
638 fn get_n(&self) -> usize { N }
639 fn get_m(&self) -> usize { M }
640 }
641}
642
643impl m::Foo for () {
644 $0
645}"#,
646 r#"
647mod m {
648 pub const VAL: usize = 0;
649
650 pub trait Foo<const N: usize = {40 + 2}, const M: usize = {VAL + 1}> {
651 fn get_n(&self) -> usize { N }
652 fn get_m(&self) -> usize { M }
653 }
654}
655
656impl m::Foo for () {
657 $0fn get_n(&self) -> usize { N }
658
659 fn get_m(&self) -> usize { M }
660}"#,
661 )
662 }
663
664 #[test]
665 fn test_cursor_after_empty_impl_def() {
666 check_assist(
667 add_missing_impl_members,
668 r#"
669trait Foo { fn foo(&self); }
670struct S;
671impl Foo for S {}$0"#,
672 r#"
673trait Foo { fn foo(&self); }
674struct S;
675impl Foo for S {
676 fn foo(&self) {
677 ${0:todo!()}
678 }
679}"#,
680 )
681 }
682
683 #[test]
684 fn test_qualify_path_1() {
685 check_assist(
686 add_missing_impl_members,
687 r#"
688mod foo {
689 pub struct Bar;
690 pub trait Foo { fn foo(&self, bar: Bar); }
691}
692struct S;
693impl foo::Foo for S { $0 }"#,
694 r#"
695mod foo {
696 pub struct Bar;
697 pub trait Foo { fn foo(&self, bar: Bar); }
698}
699struct S;
700impl foo::Foo for S {
701 fn foo(&self, bar: foo::Bar) {
702 ${0:todo!()}
703 }
704}"#,
705 );
706 }
707
708 #[test]
709 fn test_qualify_path_2() {
710 check_assist(
711 add_missing_impl_members,
712 r#"
713mod foo {
714 pub mod bar {
715 pub struct Bar;
716 pub trait Foo { fn foo(&self, bar: Bar); }
717 }
718}
719
720use foo::bar;
721
722struct S;
723impl bar::Foo for S { $0 }"#,
724 r#"
725mod foo {
726 pub mod bar {
727 pub struct Bar;
728 pub trait Foo { fn foo(&self, bar: Bar); }
729 }
730}
731
732use foo::bar;
733
734struct S;
735impl bar::Foo for S {
736 fn foo(&self, bar: bar::Bar) {
737 ${0:todo!()}
738 }
739}"#,
740 );
741 }
742
743 #[test]
744 fn test_qualify_path_generic() {
745 check_assist(
746 add_missing_impl_members,
747 r#"
748mod foo {
749 pub struct Bar<T>;
750 pub trait Foo { fn foo(&self, bar: Bar<u32>); }
751}
752struct S;
753impl foo::Foo for S { $0 }"#,
754 r#"
755mod foo {
756 pub struct Bar<T>;
757 pub trait Foo { fn foo(&self, bar: Bar<u32>); }
758}
759struct S;
760impl foo::Foo for S {
761 fn foo(&self, bar: foo::Bar<u32>) {
762 ${0:todo!()}
763 }
764}"#,
765 );
766 }
767
768 #[test]
769 fn test_qualify_path_and_substitute_param() {
770 check_assist(
771 add_missing_impl_members,
772 r#"
773mod foo {
774 pub struct Bar<T>;
775 pub trait Foo<T> { fn foo(&self, bar: Bar<T>); }
776}
777struct S;
778impl foo::Foo<u32> for S { $0 }"#,
779 r#"
780mod foo {
781 pub struct Bar<T>;
782 pub trait Foo<T> { fn foo(&self, bar: Bar<T>); }
783}
784struct S;
785impl foo::Foo<u32> for S {
786 fn foo(&self, bar: foo::Bar<u32>) {
787 ${0:todo!()}
788 }
789}"#,
790 );
791 }
792
793 #[test]
794 fn test_substitute_param_no_qualify() {
795 check_assist(
797 add_missing_impl_members,
798 r#"
799mod foo {
800 pub trait Foo<T> { fn foo(&self, bar: T); }
801 pub struct Param;
802}
803struct Param;
804struct S;
805impl foo::Foo<Param> for S { $0 }"#,
806 r#"
807mod foo {
808 pub trait Foo<T> { fn foo(&self, bar: T); }
809 pub struct Param;
810}
811struct Param;
812struct S;
813impl foo::Foo<Param> for S {
814 fn foo(&self, bar: Param) {
815 ${0:todo!()}
816 }
817}"#,
818 );
819 }
820
821 #[test]
822 fn test_qualify_path_associated_item() {
823 check_assist(
824 add_missing_impl_members,
825 r#"
826mod foo {
827 pub struct Bar<T>;
828 impl Bar<T> { type Assoc = u32; }
829 pub trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); }
830}
831struct S;
832impl foo::Foo for S { $0 }"#,
833 r#"
834mod foo {
835 pub struct Bar<T>;
836 impl Bar<T> { type Assoc = u32; }
837 pub trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); }
838}
839struct S;
840impl foo::Foo for S {
841 fn foo(&self, bar: foo::Bar<u32>::Assoc) {
842 ${0:todo!()}
843 }
844}"#,
845 );
846 }
847
848 #[test]
849 fn test_qualify_path_nested() {
850 check_assist(
851 add_missing_impl_members,
852 r#"
853mod foo {
854 pub struct Bar<T>;
855 pub struct Baz;
856 pub trait Foo { fn foo(&self, bar: Bar<Baz>); }
857}
858struct S;
859impl foo::Foo for S { $0 }"#,
860 r#"
861mod foo {
862 pub struct Bar<T>;
863 pub struct Baz;
864 pub trait Foo { fn foo(&self, bar: Bar<Baz>); }
865}
866struct S;
867impl foo::Foo for S {
868 fn foo(&self, bar: foo::Bar<foo::Baz>) {
869 ${0:todo!()}
870 }
871}"#,
872 );
873 }
874
875 #[test]
876 fn test_qualify_path_fn_trait_notation() {
877 check_assist(
878 add_missing_impl_members,
879 r#"
880mod foo {
881 pub trait Fn<Args> { type Output; }
882 pub trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); }
883}
884struct S;
885impl foo::Foo for S { $0 }"#,
886 r#"
887mod foo {
888 pub trait Fn<Args> { type Output; }
889 pub trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); }
890}
891struct S;
892impl foo::Foo for S {
893 fn foo(&self, bar: dyn Fn(u32) -> i32) {
894 ${0:todo!()}
895 }
896}"#,
897 );
898 }
899
900 #[test]
901 fn test_empty_trait() {
902 check_assist_not_applicable(
903 add_missing_impl_members,
904 r#"
905trait Foo;
906struct S;
907impl Foo for S { $0 }"#,
908 )
909 }
910
911 #[test]
912 fn test_ignore_unnamed_trait_members_and_default_methods() {
913 check_assist_not_applicable(
914 add_missing_impl_members,
915 r#"
916trait Foo {
917 fn (arg: u32);
918 fn valid(some: u32) -> bool { false }
919}
920struct S;
921impl Foo for S { $0 }"#,
922 )
923 }
924
925 #[test]
926 fn test_with_docstring_and_attrs() {
927 check_assist(
928 add_missing_impl_members,
929 r#"
930#[doc(alias = "test alias")]
931trait Foo {
932 /// doc string
933 type Output;
934
935 #[must_use]
936 fn foo(&self);
937}
938struct S;
939impl Foo for S {}$0"#,
940 r#"
941#[doc(alias = "test alias")]
942trait Foo {
943 /// doc string
944 type Output;
945
946 #[must_use]
947 fn foo(&self);
948}
949struct S;
950impl Foo for S {
951 $0type Output;
952
953 fn foo(&self) {
954 todo!()
955 }
956}"#,
957 )
958 }
959
960 #[test]
961 fn test_default_methods() {
962 check_assist(
963 add_missing_default_members,
964 r#"
965trait Foo {
966 type Output;
967
968 const CONST: usize = 42;
969 const CONST_2: i32;
970
971 fn valid(some: u32) -> bool { false }
972 fn foo(some: u32) -> bool;
973}
974struct S;
975impl Foo for S { $0 }"#,
976 r#"
977trait Foo {
978 type Output;
979
980 const CONST: usize = 42;
981 const CONST_2: i32;
982
983 fn valid(some: u32) -> bool { false }
984 fn foo(some: u32) -> bool;
985}
986struct S;
987impl Foo for S {
988 $0const CONST: usize = 42;
989
990 fn valid(some: u32) -> bool { false }
991}"#,
992 )
993 }
994
995 #[test]
996 fn test_generic_single_default_parameter() {
997 check_assist(
998 add_missing_impl_members,
999 r#"
1000trait Foo<T = Self> {
1001 fn bar(&self, other: &T);
1002}
1003
1004struct S;
1005impl Foo for S { $0 }"#,
1006 r#"
1007trait Foo<T = Self> {
1008 fn bar(&self, other: &T);
1009}
1010
1011struct S;
1012impl Foo for S {
1013 fn bar(&self, other: &Self) {
1014 ${0:todo!()}
1015 }
1016}"#,
1017 )
1018 }
1019
1020 #[test]
1021 fn test_generic_default_parameter_is_second() {
1022 check_assist(
1023 add_missing_impl_members,
1024 r#"
1025trait Foo<T1, T2 = Self> {
1026 fn bar(&self, this: &T1, that: &T2);
1027}
1028
1029struct S<T>;
1030impl Foo<T> for S<T> { $0 }"#,
1031 r#"
1032trait Foo<T1, T2 = Self> {
1033 fn bar(&self, this: &T1, that: &T2);
1034}
1035
1036struct S<T>;
1037impl Foo<T> for S<T> {
1038 fn bar(&self, this: &T, that: &Self) {
1039 ${0:todo!()}
1040 }
1041}"#,
1042 )
1043 }
1044
1045 #[test]
1046 fn test_qualify_generic_default_parameter() {
1047 check_assist(
1048 add_missing_impl_members,
1049 r#"
1050mod m {
1051 pub struct S;
1052 pub trait Foo<T = S> {
1053 fn bar(&self, other: &T);
1054 }
1055}
1056
1057struct S;
1058impl m::Foo for S { $0 }"#,
1059 r#"
1060mod m {
1061 pub struct S;
1062 pub trait Foo<T = S> {
1063 fn bar(&self, other: &T);
1064 }
1065}
1066
1067struct S;
1068impl m::Foo for S {
1069 fn bar(&self, other: &m::S) {
1070 ${0:todo!()}
1071 }
1072}"#,
1073 )
1074 }
1075
1076 #[test]
1077 fn test_qualify_generic_default_parameter_2() {
1078 check_assist(
1079 add_missing_impl_members,
1080 r#"
1081mod m {
1082 pub struct Wrapper<T, V> {
1083 one: T,
1084 another: V
1085 };
1086 pub struct S;
1087 pub trait Foo<T = Wrapper<S, bool>> {
1088 fn bar(&self, other: &T);
1089 }
1090}
1091
1092struct S;
1093impl m::Foo for S { $0 }"#,
1094 r#"
1095mod m {
1096 pub struct Wrapper<T, V> {
1097 one: T,
1098 another: V
1099 };
1100 pub struct S;
1101 pub trait Foo<T = Wrapper<S, bool>> {
1102 fn bar(&self, other: &T);
1103 }
1104}
1105
1106struct S;
1107impl m::Foo for S {
1108 fn bar(&self, other: &m::Wrapper<m::S, bool>) {
1109 ${0:todo!()}
1110 }
1111}"#,
1112 );
1113 }
1114
1115 #[test]
1116 fn test_qualify_generic_default_parameter_3() {
1117 check_assist(
1118 add_missing_impl_members,
1119 r#"
1120mod m {
1121 pub struct Wrapper<T, V> {
1122 one: T,
1123 another: V
1124 };
1125 pub struct S;
1126 pub trait Foo<T = S, V = Wrapper<T, S>> {
1127 fn bar(&self, other: &V);
1128 }
1129}
1130
1131struct S;
1132impl m::Foo for S { $0 }"#,
1133 r#"
1134mod m {
1135 pub struct Wrapper<T, V> {
1136 one: T,
1137 another: V
1138 };
1139 pub struct S;
1140 pub trait Foo<T = S, V = Wrapper<T, S>> {
1141 fn bar(&self, other: &V);
1142 }
1143}
1144
1145struct S;
1146impl m::Foo for S {
1147 fn bar(&self, other: &m::Wrapper<m::S, m::S>) {
1148 ${0:todo!()}
1149 }
1150}"#,
1151 );
1152 }
1153
1154 #[test]
1155 fn test_assoc_type_bounds_are_removed() {
1156 check_assist(
1157 add_missing_impl_members,
1158 r#"
1159trait Tr {
1160 type Ty: Copy + 'static;
1161}
1162
1163impl Tr for ()$0 {
1164}"#,
1165 r#"
1166trait Tr {
1167 type Ty: Copy + 'static;
1168}
1169
1170impl Tr for () {
1171 $0type Ty;
1172}"#,
1173 )
1174 }
1175
1176 #[test]
1177 fn test_whitespace_fixup_preserves_bad_tokens() {
1178 check_assist(
1179 add_missing_impl_members,
1180 r#"
1181trait Tr {
1182 fn foo();
1183}
1184
1185impl Tr for ()$0 {
1186 +++
1187}"#,
1188 r#"
1189trait Tr {
1190 fn foo();
1191}
1192
1193impl Tr for () {
1194 fn foo() {
1195 ${0:todo!()}
1196 }
1197 +++
1198}"#,
1199 )
1200 }
1201
1202 #[test]
1203 fn test_whitespace_fixup_preserves_comments() {
1204 check_assist(
1205 add_missing_impl_members,
1206 r#"
1207trait Tr {
1208 fn foo();
1209}
1210
1211impl Tr for ()$0 {
1212 // very important
1213}"#,
1214 r#"
1215trait Tr {
1216 fn foo();
1217}
1218
1219impl Tr for () {
1220 fn foo() {
1221 ${0:todo!()}
1222 }
1223 // very important
1224}"#,
1225 )
1226 }
1227
1228 #[test]
1229 fn weird_path() {
1230 check_assist(
1231 add_missing_impl_members,
1232 r#"
1233trait Test {
1234 fn foo(&self, x: crate)
1235}
1236impl Test for () {
1237 $0
1238}
1239"#,
1240 r#"
1241trait Test {
1242 fn foo(&self, x: crate)
1243}
1244impl Test for () {
1245 fn foo(&self, x: crate) {
1246 ${0:todo!()}
1247 }
1248}
1249"#,
1250 )
1251 }
1252
1253 #[test]
1254 fn missing_generic_type() {
1255 check_assist(
1256 add_missing_impl_members,
1257 r#"
1258trait Foo<BAR> {
1259 fn foo(&self, bar: BAR);
1260}
1261impl Foo for () {
1262 $0
1263}
1264"#,
1265 r#"
1266trait Foo<BAR> {
1267 fn foo(&self, bar: BAR);
1268}
1269impl Foo for () {
1270 fn foo(&self, bar: BAR) {
1271 ${0:todo!()}
1272 }
1273}
1274"#,
1275 )
1276 }
1277
1278 #[test]
1279 fn does_not_requalify_self_as_crate() {
1280 check_assist(
1281 add_missing_default_members,
1282 r"
1283struct Wrapper<T>(T);
1284
1285trait T {
1286 fn f(self) -> Wrapper<Self> {
1287 Wrapper(self)
1288 }
1289}
1290
1291impl T for () {
1292 $0
1293}
1294",
1295 r"
1296struct Wrapper<T>(T);
1297
1298trait T {
1299 fn f(self) -> Wrapper<Self> {
1300 Wrapper(self)
1301 }
1302}
1303
1304impl T for () {
1305 $0fn f(self) -> Wrapper<Self> {
1306 Wrapper(self)
1307 }
1308}
1309",
1310 );
1311 }
1312
1313 #[test]
1314 fn test_default_body_generation() {
1315 check_assist(
1316 add_missing_impl_members,
1317 r#"
1318//- minicore: default
1319struct Foo(usize);
1320
1321impl Default for Foo {
1322 $0
1323}
1324"#,
1325 r#"
1326struct Foo(usize);
1327
1328impl Default for Foo {
1329 $0fn default() -> Self {
1330 Self(Default::default())
1331 }
1332}
1333"#,
1334 )
1335 }
1336
1337 #[test]
1338 fn test_from_macro() {
1339 check_assist(
1340 add_missing_default_members,
1341 r#"
1342macro_rules! foo {
1343 () => {
1344 trait FooB {
1345 fn foo<'lt>(&'lt self) {}
1346 }
1347 }
1348}
1349foo!();
1350struct Foo(usize);
1351
1352impl FooB for Foo {
1353 $0
1354}
1355"#,
1356 r#"
1357macro_rules! foo {
1358 () => {
1359 trait FooB {
1360 fn foo<'lt>(&'lt self) {}
1361 }
1362 }
1363}
1364foo!();
1365struct Foo(usize);
1366
1367impl FooB for Foo {
1368 $0fn foo<'lt>(&'lt self){}
1369}
1370"#,
1371 )
1372 }
1373
1374 #[test]
1375 fn test_assoc_type_when_trait_with_same_name_in_scope() {
1376 check_assist(
1377 add_missing_impl_members,
1378 r#"
1379pub trait Foo {}
1380
1381pub trait Types {
1382 type Foo;
1383}
1384
1385pub trait Behavior<T: Types> {
1386 fn reproduce(&self, foo: T::Foo);
1387}
1388
1389pub struct Impl;
1390
1391impl<T: Types> Behavior<T> for Impl { $0 }"#,
1392 r#"
1393pub trait Foo {}
1394
1395pub trait Types {
1396 type Foo;
1397}
1398
1399pub trait Behavior<T: Types> {
1400 fn reproduce(&self, foo: T::Foo);
1401}
1402
1403pub struct Impl;
1404
1405impl<T: Types> Behavior<T> for Impl {
1406 fn reproduce(&self, foo: <T as Types>::Foo) {
1407 ${0:todo!()}
1408 }
1409}"#,
1410 );
1411 }
1412
1413 #[test]
1414 fn test_assoc_type_on_concrete_type() {
1415 check_assist(
1416 add_missing_impl_members,
1417 r#"
1418pub trait Types {
1419 type Foo;
1420}
1421
1422impl Types for u32 {
1423 type Foo = bool;
1424}
1425
1426pub trait Behavior<T: Types> {
1427 fn reproduce(&self, foo: T::Foo);
1428}
1429
1430pub struct Impl;
1431
1432impl Behavior<u32> for Impl { $0 }"#,
1433 r#"
1434pub trait Types {
1435 type Foo;
1436}
1437
1438impl Types for u32 {
1439 type Foo = bool;
1440}
1441
1442pub trait Behavior<T: Types> {
1443 fn reproduce(&self, foo: T::Foo);
1444}
1445
1446pub struct Impl;
1447
1448impl Behavior<u32> for Impl {
1449 fn reproduce(&self, foo: <u32 as Types>::Foo) {
1450 ${0:todo!()}
1451 }
1452}"#,
1453 );
1454 }
1455
1456 #[test]
1457 fn test_assoc_type_on_concrete_type_qualified() {
1458 check_assist(
1459 add_missing_impl_members,
1460 r#"
1461pub trait Types {
1462 type Foo;
1463}
1464
1465impl Types for std::string::String {
1466 type Foo = bool;
1467}
1468
1469pub trait Behavior<T: Types> {
1470 fn reproduce(&self, foo: T::Foo);
1471}
1472
1473pub struct Impl;
1474
1475impl Behavior<std::string::String> for Impl { $0 }"#,
1476 r#"
1477pub trait Types {
1478 type Foo;
1479}
1480
1481impl Types for std::string::String {
1482 type Foo = bool;
1483}
1484
1485pub trait Behavior<T: Types> {
1486 fn reproduce(&self, foo: T::Foo);
1487}
1488
1489pub struct Impl;
1490
1491impl Behavior<std::string::String> for Impl {
1492 fn reproduce(&self, foo: <std::string::String as Types>::Foo) {
1493 ${0:todo!()}
1494 }
1495}"#,
1496 );
1497 }
1498
1499 #[test]
1500 fn test_assoc_type_on_concrete_type_multi_option_ambiguous() {
1501 check_assist(
1502 add_missing_impl_members,
1503 r#"
1504pub trait Types {
1505 type Foo;
1506}
1507
1508pub trait Types2 {
1509 type Foo;
1510}
1511
1512impl Types for u32 {
1513 type Foo = bool;
1514}
1515
1516impl Types2 for u32 {
1517 type Foo = String;
1518}
1519
1520pub trait Behavior<T: Types + Types2> {
1521 fn reproduce(&self, foo: <T as Types2>::Foo);
1522}
1523
1524pub struct Impl;
1525
1526impl Behavior<u32> for Impl { $0 }"#,
1527 r#"
1528pub trait Types {
1529 type Foo;
1530}
1531
1532pub trait Types2 {
1533 type Foo;
1534}
1535
1536impl Types for u32 {
1537 type Foo = bool;
1538}
1539
1540impl Types2 for u32 {
1541 type Foo = String;
1542}
1543
1544pub trait Behavior<T: Types + Types2> {
1545 fn reproduce(&self, foo: <T as Types2>::Foo);
1546}
1547
1548pub struct Impl;
1549
1550impl Behavior<u32> for Impl {
1551 fn reproduce(&self, foo: <u32 as Types2>::Foo) {
1552 ${0:todo!()}
1553 }
1554}"#,
1555 );
1556 }
1557
1558 #[test]
1559 fn test_assoc_type_on_concrete_type_multi_option() {
1560 check_assist(
1561 add_missing_impl_members,
1562 r#"
1563pub trait Types {
1564 type Foo;
1565}
1566
1567pub trait Types2 {
1568 type Bar;
1569}
1570
1571impl Types for u32 {
1572 type Foo = bool;
1573}
1574
1575impl Types2 for u32 {
1576 type Bar = String;
1577}
1578
1579pub trait Behavior<T: Types + Types2> {
1580 fn reproduce(&self, foo: T::Bar);
1581}
1582
1583pub struct Impl;
1584
1585impl Behavior<u32> for Impl { $0 }"#,
1586 r#"
1587pub trait Types {
1588 type Foo;
1589}
1590
1591pub trait Types2 {
1592 type Bar;
1593}
1594
1595impl Types for u32 {
1596 type Foo = bool;
1597}
1598
1599impl Types2 for u32 {
1600 type Bar = String;
1601}
1602
1603pub trait Behavior<T: Types + Types2> {
1604 fn reproduce(&self, foo: T::Bar);
1605}
1606
1607pub struct Impl;
1608
1609impl Behavior<u32> for Impl {
1610 fn reproduce(&self, foo: <u32 as Types2>::Bar) {
1611 ${0:todo!()}
1612 }
1613}"#,
1614 );
1615 }
1616
1617 #[test]
1618 fn test_assoc_type_on_concrete_type_multi_option_foreign() {
1619 check_assist(
1620 add_missing_impl_members,
1621 r#"
1622mod bar {
1623 pub trait Types2 {
1624 type Bar;
1625 }
1626}
1627
1628pub trait Types {
1629 type Foo;
1630}
1631
1632impl Types for u32 {
1633 type Foo = bool;
1634}
1635
1636impl bar::Types2 for u32 {
1637 type Bar = String;
1638}
1639
1640pub trait Behavior<T: Types + bar::Types2> {
1641 fn reproduce(&self, foo: T::Bar);
1642}
1643
1644pub struct Impl;
1645
1646impl Behavior<u32> for Impl { $0 }"#,
1647 r#"
1648mod bar {
1649 pub trait Types2 {
1650 type Bar;
1651 }
1652}
1653
1654pub trait Types {
1655 type Foo;
1656}
1657
1658impl Types for u32 {
1659 type Foo = bool;
1660}
1661
1662impl bar::Types2 for u32 {
1663 type Bar = String;
1664}
1665
1666pub trait Behavior<T: Types + bar::Types2> {
1667 fn reproduce(&self, foo: T::Bar);
1668}
1669
1670pub struct Impl;
1671
1672impl Behavior<u32> for Impl {
1673 fn reproduce(&self, foo: <u32 as bar::Types2>::Bar) {
1674 ${0:todo!()}
1675 }
1676}"#,
1677 );
1678 }
1679
1680 #[test]
1681 fn test_transform_path_in_path_expr() {
1682 check_assist(
1683 add_missing_default_members,
1684 r#"
1685pub trait Const {
1686 const FOO: u32;
1687}
1688
1689pub trait Trait<T: Const> {
1690 fn foo() -> bool {
1691 match T::FOO {
1692 0 => true,
1693 _ => false,
1694 }
1695 }
1696}
1697
1698impl Const for u32 {
1699 const FOO: u32 = 1;
1700}
1701
1702struct Impl;
1703
1704impl Trait<u32> for Impl { $0 }"#,
1705 r#"
1706pub trait Const {
1707 const FOO: u32;
1708}
1709
1710pub trait Trait<T: Const> {
1711 fn foo() -> bool {
1712 match T::FOO {
1713 0 => true,
1714 _ => false,
1715 }
1716 }
1717}
1718
1719impl Const for u32 {
1720 const FOO: u32 = 1;
1721}
1722
1723struct Impl;
1724
1725impl Trait<u32> for Impl {
1726 $0fn foo() -> bool {
1727 match <u32 as Const>::FOO {
1728 0 => true,
1729 _ => false,
1730 }
1731 }
1732}"#,
1733 );
1734 }
1735
1736 #[test]
1737 fn test_default_partial_eq() {
1738 check_assist(
1739 add_missing_default_members,
1740 r#"
1741//- minicore: eq
1742struct SomeStruct {
1743 data: usize,
1744 field: (usize, usize),
1745}
1746impl PartialEq for SomeStruct {$0}
1747"#,
1748 r#"
1749struct SomeStruct {
1750 data: usize,
1751 field: (usize, usize),
1752}
1753impl PartialEq for SomeStruct {
1754 $0fn ne(&self, other: &Self) -> bool {
1755 !self.eq(other)
1756 }
1757}
1758"#,
1759 );
1760 }
1761
1762 #[test]
1763 fn test_partial_eq_body_when_types_semantically_match() {
1764 check_assist(
1765 add_missing_impl_members,
1766 r#"
1767//- minicore: eq
1768struct S<T, U>(T, U);
1769type Alias<T> = S<T, T>;
1770impl<T> PartialEq<Alias<T>> for S<T, T> {$0}
1771"#,
1772 r#"
1773struct S<T, U>(T, U);
1774type Alias<T> = S<T, T>;
1775impl<T> PartialEq<Alias<T>> for S<T, T> {
1776 $0fn eq(&self, other: &Alias<T>) -> bool {
1777 self.0 == other.0 && self.1 == other.1
1778 }
1779}
1780"#,
1781 );
1782 }
1783
1784 #[test]
1785 fn test_partial_eq_body_when_types_dont_match() {
1786 check_assist(
1787 add_missing_impl_members,
1788 r#"
1789//- minicore: eq
1790struct S<T, U>(T, U);
1791type Alias<T> = S<T, T>;
1792impl<T> PartialEq<Alias<T>> for S<T, i32> {$0}
1793"#,
1794 r#"
1795struct S<T, U>(T, U);
1796type Alias<T> = S<T, T>;
1797impl<T> PartialEq<Alias<T>> for S<T, i32> {
1798 fn eq(&self, other: &Alias<T>) -> bool {
1799 ${0:todo!()}
1800 }
1801}
1802"#,
1803 );
1804 }
1805
1806 #[test]
1807 fn test_ignore_function_body() {
1808 check_assist_not_applicable(
1809 add_missing_default_members,
1810 r#"
1811trait Trait {
1812 type X;
1813 fn foo(&self);
1814 fn bar(&self) {}
1815}
1816
1817impl Trait for () {
1818 type X = u8;
1819 fn foo(&self) {$0
1820 let x = 5;
1821 }
1822}"#,
1823 )
1824 }
1825
1826 #[test]
1827 fn test_ignore_param_list() {
1828 check_assist_not_applicable(
1829 add_missing_impl_members,
1830 r#"
1831trait Trait {
1832 type X;
1833 fn foo(&self);
1834 fn bar(&self);
1835}
1836
1837impl Trait for () {
1838 type X = u8;
1839 fn foo(&self$0) {
1840 let x = 5;
1841 }
1842}"#,
1843 )
1844 }
1845
1846 #[test]
1847 fn test_ignore_scope_inside_function() {
1848 check_assist_not_applicable(
1849 add_missing_impl_members,
1850 r#"
1851trait Trait {
1852 type X;
1853 fn foo(&self);
1854 fn bar(&self);
1855}
1856
1857impl Trait for () {
1858 type X = u8;
1859 fn foo(&self) {
1860 let x = async {$0 5 };
1861 }
1862}"#,
1863 )
1864 }
1865
1866 #[test]
1867 fn test_apply_outside_function() {
1868 check_assist(
1869 add_missing_default_members,
1870 r#"
1871trait Trait {
1872 type X;
1873 fn foo(&self);
1874 fn bar(&self) {}
1875}
1876
1877impl Trait for () {
1878 type X = u8;
1879 fn foo(&self)$0 {}
1880}"#,
1881 r#"
1882trait Trait {
1883 type X;
1884 fn foo(&self);
1885 fn bar(&self) {}
1886}
1887
1888impl Trait for () {
1889 type X = u8;
1890 fn foo(&self) {}
1891
1892 $0fn bar(&self) {}
1893}"#,
1894 )
1895 }
1896
1897 #[test]
1898 fn test_works_inside_function() {
1899 check_assist(
1900 add_missing_impl_members,
1901 r#"
1902trait Tr {
1903 fn method();
1904}
1905fn main() {
1906 struct S;
1907 impl Tr for S {
1908 $0
1909 }
1910}
1911"#,
1912 r#"
1913trait Tr {
1914 fn method();
1915}
1916fn main() {
1917 struct S;
1918 impl Tr for S {
1919 fn method() {
1920 ${0:todo!()}
1921 }
1922 }
1923}
1924"#,
1925 );
1926 }
1927
1928 #[test]
1929 fn test_add_missing_preserves_indentation() {
1930 check_assist(
1932 add_missing_impl_members,
1933 r#"
1934mod m {
1935 pub trait Foo {
1936 const CONST_MULTILINE: (
1937 i32,
1938 i32
1939 );
1940
1941 fn foo(&self);
1942 }
1943}
1944struct S;
1945impl m::Foo for S { $0 }"#,
1946 r#"
1947mod m {
1948 pub trait Foo {
1949 const CONST_MULTILINE: (
1950 i32,
1951 i32
1952 );
1953
1954 fn foo(&self);
1955 }
1956}
1957struct S;
1958impl m::Foo for S {
1959 $0const CONST_MULTILINE: (
1960 i32,
1961 i32
1962 );
1963
1964 fn foo(&self) {
1965 todo!()
1966 }
1967}"#,
1968 );
1969 check_assist(
1971 add_missing_impl_members,
1972 r#"
1973mod m {
1974 trait Foo {
1975 type Output;
1976
1977 const CONST: usize = 42;
1978 const CONST_2: i32;
1979 const CONST_MULTILINE: (
1980 i32,
1981 i32
1982 );
1983
1984 fn foo(&self);
1985 fn bar(&self);
1986 fn baz(&self);
1987 }
1988
1989 struct S;
1990
1991 impl Foo for S {
1992 fn bar(&self) {}
1993$0
1994 }
1995}"#,
1996 r#"
1997mod m {
1998 trait Foo {
1999 type Output;
2000
2001 const CONST: usize = 42;
2002 const CONST_2: i32;
2003 const CONST_MULTILINE: (
2004 i32,
2005 i32
2006 );
2007
2008 fn foo(&self);
2009 fn bar(&self);
2010 fn baz(&self);
2011 }
2012
2013 struct S;
2014
2015 impl Foo for S {
2016 fn bar(&self) {}
2017
2018 $0type Output;
2019
2020 const CONST_2: i32;
2021
2022 const CONST_MULTILINE: (
2023 i32,
2024 i32
2025 );
2026
2027 fn foo(&self) {
2028 todo!()
2029 }
2030
2031 fn baz(&self) {
2032 todo!()
2033 }
2034
2035 }
2036}"#,
2037 );
2038 }
2039
2040 #[test]
2041 fn test_add_default_preserves_indentation() {
2042 check_assist(
2043 add_missing_default_members,
2044 r#"
2045mod m {
2046 pub trait Foo {
2047 type Output;
2048
2049 const CONST: usize = 42;
2050 const CONST_2: i32;
2051 const CONST_MULTILINE: = (
2052 i32,
2053 i32,
2054 ) = (3, 14);
2055
2056 fn valid(some: u32) -> bool { false }
2057 fn foo(some: u32) -> bool;
2058 }
2059}
2060struct S;
2061impl m::Foo for S { $0 }"#,
2062 r#"
2063mod m {
2064 pub trait Foo {
2065 type Output;
2066
2067 const CONST: usize = 42;
2068 const CONST_2: i32;
2069 const CONST_MULTILINE: = (
2070 i32,
2071 i32,
2072 ) = (3, 14);
2073
2074 fn valid(some: u32) -> bool { false }
2075 fn foo(some: u32) -> bool;
2076 }
2077}
2078struct S;
2079impl m::Foo for S {
2080 $0const CONST: usize = 42;
2081
2082 const CONST_MULTILINE: = (
2083 i32,
2084 i32,
2085 ) = (3, 14);
2086
2087 fn valid(some: u32) -> bool { false }
2088}"#,
2089 )
2090 }
2091
2092 #[test]
2093 fn nested_macro_should_not_cause_crash() {
2094 check_assist(
2095 add_missing_impl_members,
2096 r#"
2097macro_rules! ty { () => { i32 } }
2098trait SomeTrait { type Output; }
2099impl SomeTrait for i32 { type Output = i64; }
2100macro_rules! define_method {
2101 () => {
2102 fn method(&mut self, params: <ty!() as SomeTrait>::Output);
2103 };
2104}
2105trait AnotherTrait { define_method!(); }
2106impl $0AnotherTrait for () {
2107}
2108"#,
2109 r#"
2110macro_rules! ty { () => { i32 } }
2111trait SomeTrait { type Output; }
2112impl SomeTrait for i32 { type Output = i64; }
2113macro_rules! define_method {
2114 () => {
2115 fn method(&mut self, params: <ty!() as SomeTrait>::Output);
2116 };
2117}
2118trait AnotherTrait { define_method!(); }
2119impl AnotherTrait for () {
2120 $0fn method(&mut self,params: <ty!()as SomeTrait>::Output) {
2121 todo!()
2122 }
2123}
2124"#,
2125 );
2126 }
2127
2128 #[test]
2130 fn paths_in_nested_macro_should_get_transformed() {
2131 check_assist(
2132 add_missing_impl_members,
2133 r#"
2134macro_rules! ty { ($me:ty) => { $me } }
2135trait SomeTrait { type Output; }
2136impl SomeTrait for i32 { type Output = i64; }
2137macro_rules! define_method {
2138 ($t:ty) => {
2139 fn method(&mut self, params: <ty!($t) as SomeTrait>::Output);
2140 };
2141}
2142trait AnotherTrait<T: SomeTrait> { define_method!(T); }
2143impl $0AnotherTrait<i32> for () {
2144}
2145"#,
2146 r#"
2147macro_rules! ty { ($me:ty) => { $me } }
2148trait SomeTrait { type Output; }
2149impl SomeTrait for i32 { type Output = i64; }
2150macro_rules! define_method {
2151 ($t:ty) => {
2152 fn method(&mut self, params: <ty!($t) as SomeTrait>::Output);
2153 };
2154}
2155trait AnotherTrait<T: SomeTrait> { define_method!(T); }
2156impl AnotherTrait<i32> for () {
2157 $0fn method(&mut self,params: <ty!(T)as SomeTrait>::Output) {
2158 todo!()
2159 }
2160}
2161"#,
2162 );
2163 }
2164
2165 #[test]
2166 fn doc_hidden_default_impls_ignored() {
2167 check_assist(
2169 add_missing_default_members,
2170 r#"
2171struct Foo;
2172trait Trait {
2173 #[doc(hidden)]
2174 fn func_with_default_impl() -> u32 {
2175 42
2176 }
2177 fn another_default_impl() -> u32 {
2178 43
2179 }
2180}
2181impl Tra$0it for Foo {}"#,
2182 r#"
2183struct Foo;
2184trait Trait {
2185 #[doc(hidden)]
2186 fn func_with_default_impl() -> u32 {
2187 42
2188 }
2189 fn another_default_impl() -> u32 {
2190 43
2191 }
2192}
2193impl Trait for Foo {
2194 $0fn func_with_default_impl() -> u32 {
2195 42
2196 }
2197
2198 fn another_default_impl() -> u32 {
2199 43
2200 }
2201}"#,
2202 )
2203 }
2204
2205 #[test]
2206 fn doc_hidden_default_impls_lang_crates() {
2207 check_assist_not_applicable(
2209 add_missing_default_members,
2210 r#"
2211//- minicore: eq
2212use core::cmp::Eq;
2213struct Foo;
2214impl E$0q for Foo { /* $0 */ }
2215"#,
2216 )
2217 }
2218
2219 #[test]
2220 fn doc_hidden_default_impls_lib_crates() {
2221 check_assist(
2222 add_missing_default_members,
2223 r#"
2224 //- /main.rs crate:a deps:b
2225 struct B;
2226 impl b::Exte$0rnTrait for B {}
2227 //- /lib.rs crate:b new_source_root:library
2228 pub trait ExternTrait {
2229 #[doc(hidden)]
2230 fn hidden_default() -> Option<()> {
2231 todo!()
2232 }
2233
2234 fn unhidden_default() -> Option<()> {
2235 todo!()
2236 }
2237
2238 fn unhidden_nondefault() -> Option<()>;
2239 }
2240 "#,
2241 r#"
2242 struct B;
2243 impl b::ExternTrait for B {
2244 $0fn unhidden_default() -> Option<()> {
2245 todo!()
2246 }
2247 }
2248 "#,
2249 )
2250 }
2251
2252 #[test]
2253 fn doc_hidden_default_impls_local_crates() {
2254 check_assist(
2255 add_missing_default_members,
2256 r#"
2257trait LocalTrait {
2258 #[doc(hidden)]
2259 fn no_skip_default() -> Option<()> {
2260 todo!()
2261 }
2262 fn no_skip_default_2() -> Option<()> {
2263 todo!()
2264 }
2265}
2266
2267struct B;
2268impl Loc$0alTrait for B {}
2269 "#,
2270 r#"
2271trait LocalTrait {
2272 #[doc(hidden)]
2273 fn no_skip_default() -> Option<()> {
2274 todo!()
2275 }
2276 fn no_skip_default_2() -> Option<()> {
2277 todo!()
2278 }
2279}
2280
2281struct B;
2282impl LocalTrait for B {
2283 $0fn no_skip_default() -> Option<()> {
2284 todo!()
2285 }
2286
2287 fn no_skip_default_2() -> Option<()> {
2288 todo!()
2289 }
2290}
2291 "#,
2292 )
2293 }
2294
2295 #[test]
2296 fn doc_hidden_default_impls_workspace_crates() {
2297 check_assist(
2298 add_missing_default_members,
2299 r#"
2300//- /lib.rs crate:b new_source_root:local
2301trait LocalTrait {
2302 #[doc(hidden)]
2303 fn no_skip_default() -> Option<()> {
2304 todo!()
2305 }
2306 fn no_skip_default_2() -> Option<()> {
2307 todo!()
2308 }
2309}
2310
2311//- /main.rs crate:a deps:b
2312struct B;
2313impl b::Loc$0alTrait for B {}
2314 "#,
2315 r#"
2316struct B;
2317impl b::LocalTrait for B {
2318 $0fn no_skip_default() -> Option<()> {
2319 todo!()
2320 }
2321
2322 fn no_skip_default_2() -> Option<()> {
2323 todo!()
2324 }
2325}
2326 "#,
2327 )
2328 }
2329
2330 #[test]
2331 fn doc_hidden_nondefault_member() {
2332 check_assist(
2333 add_missing_impl_members,
2334 r#"
2335//- /lib.rs crate:b new_source_root:local
2336trait LocalTrait {
2337 #[doc(hidden)]
2338 fn no_skip_non_default() -> Option<()>;
2339
2340 #[doc(hidden)]
2341 fn skip_default() -> Option<()> {
2342 todo!()
2343 }
2344}
2345
2346//- /main.rs crate:a deps:b
2347struct B;
2348impl b::Loc$0alTrait for B {}
2349 "#,
2350 r#"
2351struct B;
2352impl b::LocalTrait for B {
2353 fn no_skip_non_default() -> Option<()> {
2354 ${0:todo!()}
2355 }
2356}
2357 "#,
2358 )
2359 }
2360
2361 #[test]
2362 fn impl_with_type_param_with_former_param_as_default() {
2363 check_assist(
2364 add_missing_impl_members,
2365 r#"
2366pub trait Test<'a, T, U = T> {
2367 fn test(item: &'a T) -> U;
2368}
2369impl<'a> Test<'a, i32> for bool {
2370 $0
2371}
2372"#,
2373 r#"
2374pub trait Test<'a, T, U = T> {
2375 fn test(item: &'a T) -> U;
2376}
2377impl<'a> Test<'a, i32> for bool {
2378 fn test(item: &'a i32) -> i32 {
2379 ${0:todo!()}
2380 }
2381}
2382"#,
2383 );
2384 }
2385
2386 #[test]
2387 fn issue_17321() {
2388 check_assist(
2389 add_missing_impl_members,
2390 r#"
2391fn main() {}
2392
2393mod other_file_1 {
2394 pub const SOME_CONSTANT: usize = 8;
2395}
2396
2397mod other_file_2 {
2398 use crate::other_file_1::SOME_CONSTANT;
2399
2400 pub trait Trait {
2401 type Iter: Iterator<Item = [u8; SOME_CONSTANT]>;
2402 }
2403}
2404
2405pub struct MyStruct;
2406
2407impl other_file_2::Trait for MyStruct$0 {}"#,
2408 r#"
2409fn main() {}
2410
2411mod other_file_1 {
2412 pub const SOME_CONSTANT: usize = 8;
2413}
2414
2415mod other_file_2 {
2416 use crate::other_file_1::SOME_CONSTANT;
2417
2418 pub trait Trait {
2419 type Iter: Iterator<Item = [u8; SOME_CONSTANT]>;
2420 }
2421}
2422
2423pub struct MyStruct;
2424
2425impl other_file_2::Trait for MyStruct {
2426 $0type Iter;
2427}"#,
2428 );
2429 }
2430
2431 #[test]
2432 fn test_qualify_ident_pat_in_default_members() {
2433 check_assist(
2434 add_missing_default_members,
2435 r#"
2436//- /lib.rs crate:b new_source_root:library
2437pub enum State {
2438 Active,
2439 Inactive,
2440}
2441
2442use State::*;
2443
2444pub trait Checker {
2445 fn check(&self) -> State;
2446
2447 fn is_active(&self) -> bool {
2448 match self.check() {
2449 Active => true,
2450 Inactive => false,
2451 }
2452 }
2453}
2454//- /main.rs crate:a deps:b
2455struct MyChecker;
2456
2457impl b::Checker for MyChecker {
2458 fn check(&self) -> b::State {
2459 todo!();
2460 }$0
2461}"#,
2462 r#"
2463struct MyChecker;
2464
2465impl b::Checker for MyChecker {
2466 fn check(&self) -> b::State {
2467 todo!();
2468 }
2469
2470 $0fn is_active(&self) -> bool {
2471 match self.check() {
2472 b::State::Active => true,
2473 b::State::Inactive => false,
2474 }
2475 }
2476}"#,
2477 );
2478 }
2479
2480 #[test]
2481 fn test_parameter_names_matching_macros_not_qualified() {
2482 check_assist(
2484 add_missing_impl_members,
2485 r#"
2486//- /lib.rs crate:dep
2487#[macro_export]
2488macro_rules! my_macro {
2489 () => {}
2490}
2491
2492pub trait Foo {
2493 fn foo(&self, my_macro: usize);
2494}
2495
2496//- /main.rs crate:main deps:dep
2497struct Bar;
2498
2499impl dep::Foo for Bar {$0}
2500"#,
2501 r#"
2502struct Bar;
2503
2504impl dep::Foo for Bar {
2505 fn foo(&self, my_macro: usize) {
2506 ${0:todo!()}
2507 }
2508}
2509"#,
2510 );
2511 }
2512
2513 #[test]
2514 fn regression_test_for_when_impl_for_unit() {
2515 check_assist(
2516 add_missing_impl_members,
2517 r#"
2518trait Test {
2519 fn f<B>()
2520 where
2521 B: IntoIterator,
2522 <B as IntoIterator>::Item: Copy;
2523}
2524impl Test for () {
2525 $0
2526}
2527"#,
2528 r#"
2529trait Test {
2530 fn f<B>()
2531 where
2532 B: IntoIterator,
2533 <B as IntoIterator>::Item: Copy;
2534}
2535impl Test for () {
2536 fn f<B>()
2537 where
2538 B: IntoIterator,
2539 <B as IntoIterator>::Item: Copy {
2540 ${0:todo!()}
2541 }
2542}
2543"#,
2544 );
2545 }
2546
2547 #[test]
2548 fn test_param_name_not_qualified() {
2549 check_assist(
2550 add_missing_impl_members,
2551 r#"
2552mod ptr {
2553 pub struct NonNull<T>(T);
2554}
2555mod alloc {
2556 use super::ptr::NonNull;
2557 pub trait Allocator {
2558 unsafe fn deallocate(&self, ptr: NonNull<u8>);
2559 }
2560}
2561
2562struct System;
2563
2564unsafe impl alloc::Allocator for System {
2565 $0
2566}
2567"#,
2568 r#"
2569mod ptr {
2570 pub struct NonNull<T>(T);
2571}
2572mod alloc {
2573 use super::ptr::NonNull;
2574 pub trait Allocator {
2575 unsafe fn deallocate(&self, ptr: NonNull<u8>);
2576 }
2577}
2578
2579struct System;
2580
2581unsafe impl alloc::Allocator for System {
2582 unsafe fn deallocate(&self, ptr: ptr::NonNull<u8>) {
2583 ${0:todo!()}
2584 }
2585}
2586"#,
2587 );
2588 }
2589
2590 #[test]
2591 fn test_param_name_shadows_module() {
2592 check_assist(
2593 add_missing_impl_members,
2594 r#"
2595mod m { }
2596use m as p;
2597
2598pub trait Allocator {
2599 fn deallocate(&self, p: u8);
2600}
2601
2602struct System;
2603
2604impl Allocator for System {
2605 $0
2606}
2607"#,
2608 r#"
2609mod m { }
2610use m as p;
2611
2612pub trait Allocator {
2613 fn deallocate(&self, p: u8);
2614}
2615
2616struct System;
2617
2618impl Allocator for System {
2619 fn deallocate(&self, p: u8) {
2620 ${0:todo!()}
2621 }
2622}
2623"#,
2624 );
2625 }
2626
2627 #[test]
2628 fn does_not_include_defaulted_assoc_types() {
2629 check_assist_not_applicable(
2630 add_missing_impl_members,
2631 r#"
2632trait Trait {
2633 type NotRequired = ();
2634}
2635
2636struct Struct;
2637
2638impl Trait for Struct {
2639 $0
2640}
2641 "#,
2642 );
2643 }
2644}