Skip to main content

ide_assists/handlers/
generate_delegate_trait.rs

1use std::ops::Not;
2
3use crate::{
4    assist_context::{AssistContext, Assists},
5    utils::convert_param_list_to_arg_list,
6};
7use either::Either;
8use hir::{HasVisibility, db::HirDatabase};
9use ide_db::{
10    FxHashMap, FxHashSet,
11    assists::{AssistId, GroupLabel},
12    path_transform::PathTransform,
13    syntax_helpers::suggest_name,
14};
15use itertools::Itertools;
16use syntax::{
17    AstNode, Edition, SmolStr, SyntaxElement, SyntaxKind, ToSmolStr,
18    ast::{
19        self, AssocItem, GenericArgList, GenericParamList, HasAttrs, HasGenericArgs,
20        HasGenericParams, HasName, HasTypeBounds, HasVisibility as astHasVisibility, Path,
21        WherePred,
22        edit::{self, AstNodeEdit},
23        syntax_factory::SyntaxFactory,
24    },
25    syntax_editor::SyntaxEditor,
26};
27
28// Assist: generate_delegate_trait
29//
30// Generate delegate trait implementation for `StructField`s.
31//
32// ```
33// trait SomeTrait {
34//     type T;
35//     fn fn_(arg: u32) -> u32;
36//     fn method_(&mut self) -> bool;
37// }
38// struct A;
39// impl SomeTrait for A {
40//     type T = u32;
41//
42//     fn fn_(arg: u32) -> u32 {
43//         42
44//     }
45//
46//     fn method_(&mut self) -> bool {
47//         false
48//     }
49// }
50// struct B {
51//     a$0: A,
52// }
53// ```
54// ->
55// ```
56// trait SomeTrait {
57//     type T;
58//     fn fn_(arg: u32) -> u32;
59//     fn method_(&mut self) -> bool;
60// }
61// struct A;
62// impl SomeTrait for A {
63//     type T = u32;
64//
65//     fn fn_(arg: u32) -> u32 {
66//         42
67//     }
68//
69//     fn method_(&mut self) -> bool {
70//         false
71//     }
72// }
73// struct B {
74//     a: A,
75// }
76//
77// impl SomeTrait for B {
78//     type T = <A as SomeTrait>::T;
79//
80//     fn fn_(arg: u32) -> u32 {
81//         <A as SomeTrait>::fn_(arg)
82//     }
83//
84//     fn method_(&mut self) -> bool {
85//         <A as SomeTrait>::method_(&mut self.a)
86//     }
87// }
88// ```
89pub(crate) fn generate_delegate_trait(
90    acc: &mut Assists,
91    ctx: &AssistContext<'_, '_>,
92) -> Option<()> {
93    if !ctx.config.code_action_grouping {
94        return None;
95    }
96
97    let strukt = Struct::new(ctx.find_node_at_offset::<ast::Struct>()?)?;
98
99    let field: Field = match ctx.find_node_at_offset::<ast::RecordField>() {
100        Some(field) => Field::new(ctx, Either::Left(field))?,
101        None => {
102            let field = ctx.find_node_at_offset::<ast::TupleField>()?;
103            let field_list = ctx.find_node_at_offset::<ast::TupleFieldList>()?;
104            Field::new(ctx, either::Right((field, field_list)))?
105        }
106    };
107
108    strukt.delegate(field, acc, ctx);
109    Some(())
110}
111
112/// A utility object that represents a struct's field.
113#[derive(Debug)]
114struct Field {
115    name: String,
116    ty: ast::Type,
117    range: syntax::TextRange,
118    impls: Vec<Delegee>,
119    edition: Edition,
120}
121
122impl Field {
123    pub(crate) fn new(
124        ctx: &AssistContext<'_, '_>,
125        f: Either<ast::RecordField, (ast::TupleField, ast::TupleFieldList)>,
126    ) -> Option<Field> {
127        let db = ctx.sema.db;
128
129        let module = ctx.sema.file_to_module_def(ctx.vfs_file_id())?;
130        let edition = module.krate(ctx.db()).edition(ctx.db());
131
132        let (name, range, ty) = match f {
133            Either::Left(f) => {
134                let name = f.name()?.to_string();
135                (name, f.syntax().text_range(), f.ty()?)
136            }
137            Either::Right((f, l)) => {
138                let name = l.fields().position(|it| it == f)?.to_string();
139                (name, f.syntax().text_range(), f.ty()?)
140            }
141        };
142
143        let hir_ty = ctx.sema.resolve_type(&ty)?;
144        let type_impls = hir::Impl::all_for_type(db, hir_ty.clone());
145        let mut impls = Vec::with_capacity(type_impls.len());
146
147        if let Some(tp) = hir_ty.as_type_param(db) {
148            for tb in tp.trait_bounds(db) {
149                impls.push(Delegee::Bound(tb));
150            }
151        };
152
153        for imp in type_impls {
154            if let Some(tr) = imp.trait_(db).filter(|tr| tr.is_visible_from(db, module)) {
155                impls.push(Delegee::Impls(tr, imp))
156            }
157        }
158
159        Some(Field { name, ty, range, impls, edition })
160    }
161}
162
163/// A field that we want to delegate can offer the enclosing struct
164/// trait to implement in two ways. The first way is when the field
165/// actually implements the trait and the second way is when the field
166/// has a bound type parameter. We handle these cases in different ways
167/// hence the enum.
168#[derive(Debug)]
169enum Delegee {
170    Bound(hir::Trait),
171    Impls(hir::Trait, hir::Impl),
172}
173
174impl Delegee {
175    fn trait_(&self) -> &hir::Trait {
176        match self {
177            Delegee::Bound(it) | Delegee::Impls(it, _) => it,
178        }
179    }
180
181    fn signature(&self, db: &dyn HirDatabase, edition: Edition) -> String {
182        let mut s = String::new();
183        let it = self.trait_();
184
185        for m in it.module(db).path_to_root(db).iter().rev() {
186            if let Some(name) = m.name(db) {
187                s.push_str(&format!("{}::", name.display_no_db(edition).to_smolstr()));
188            }
189        }
190
191        s.push_str(&it.name(db).display_no_db(edition).to_smolstr());
192        s
193    }
194}
195
196/// A utility struct that is used for the enclosing struct.
197struct Struct {
198    strukt: ast::Struct,
199    name: ast::Name,
200}
201
202impl Struct {
203    pub(crate) fn new(s: ast::Struct) -> Option<Self> {
204        let name = s.name()?;
205        Some(Struct { name, strukt: s })
206    }
207
208    pub(crate) fn delegate(&self, field: Field, acc: &mut Assists, ctx: &AssistContext<'_, '_>) {
209        let db = ctx.db();
210
211        for (index, delegee) in field.impls.iter().enumerate() {
212            let trait_ = delegee.trait_();
213
214            // Skip trait that has `Self` type, which cannot be delegated
215            //
216            // See [`test_self_ty`]
217            if has_self_type(*trait_, ctx) {
218                continue;
219            }
220
221            // FIXME :  We can omit already implemented impl_traits
222            // But we don't know what the &[hir::Type] argument should look like.
223            // if self.hir_ty.impls_trait(db, trait_, &[]) {
224            //     continue;
225            // }
226            let signature = delegee.signature(db, field.edition);
227
228            let Some(delegate) =
229                generate_impl(ctx, self, &field.ty, &field.name, delegee, field.edition)
230            else {
231                continue;
232            };
233
234            acc.add_group(
235                &GroupLabel(format!("Generate delegate trait impls for field `{}`", field.name)),
236                AssistId(
237                    "generate_delegate_trait",
238                    ide_db::assists::AssistKind::Generate,
239                    Some(index),
240                ),
241                format!("Generate delegate trait impl `{}` for `{}`", signature, field.name),
242                field.range,
243                |builder| {
244                    builder.insert(
245                        self.strukt.syntax().text_range().end(),
246                        format!("\n\n{}", delegate.syntax()),
247                    );
248                },
249            );
250        }
251    }
252}
253
254fn generate_impl(
255    ctx: &AssistContext<'_, '_>,
256    strukt: &Struct,
257    field_ty: &ast::Type,
258    field_name: &str,
259    delegee: &Delegee,
260    edition: Edition,
261) -> Option<ast::Impl> {
262    let make = SyntaxFactory::without_mappings();
263    let db = ctx.db();
264    let ast_strukt = &strukt.strukt;
265    let strukt_ty = make.ty_path(make.ident_path(&strukt.name.to_string())).into();
266    let strukt_params = ast_strukt.generic_param_list();
267
268    match delegee {
269        Delegee::Bound(delegee) => {
270            let bound_def = ctx.sema.source(delegee.to_owned())?.value;
271            let bound_params = bound_def.generic_param_list();
272
273            let delegate = make.impl_trait(
274                None,
275                delegee.is_unsafe(db),
276                bound_params.clone(),
277                bound_params.map(|params| params.to_generic_args(&make)),
278                strukt_params.clone(),
279                strukt_params.map(|params| params.to_generic_args(&make)),
280                delegee.is_auto(db),
281                make.ty(&delegee.name(db).display_no_db(edition).to_smolstr()),
282                strukt_ty,
283                bound_def.where_clause(),
284                ast_strukt.where_clause(),
285                None,
286            );
287
288            // Goto link : https://doc.rust-lang.org/reference/paths.html#qualified-paths
289            let qualified_path_type =
290                make.path_from_text(&format!("<{} as {}>", field_ty, delegate.trait_()?));
291
292            // Collect assoc items
293            let assoc_items: Option<Vec<ast::AssocItem>> = bound_def.assoc_item_list().map(|ai| {
294                ai.assoc_items()
295                    .filter(|item| matches!(item, AssocItem::MacroCall(_)).not())
296                    .filter_map(|item| {
297                        process_assoc_item(item, qualified_path_type.clone(), field_name)
298                    })
299                    .collect()
300            });
301
302            let delegate = finalize_delegate(&make, &delegate, assoc_items, false)?;
303
304            let target_scope = ctx.sema.scope(strukt.strukt.syntax())?;
305            let source_scope = ctx.sema.scope(bound_def.syntax())?;
306            let transform = PathTransform::generic_transformation(&target_scope, &source_scope);
307            ast::Impl::cast(transform.apply(delegate.syntax()))
308        }
309        Delegee::Impls(trait_, old_impl) => {
310            let old_impl = ctx.sema.source(old_impl.to_owned())?.value;
311            let old_impl_params = old_impl.generic_param_list();
312
313            // 1) Resolve conflicts between generic parameters in old_impl and
314            // those in strukt.
315            //
316            // These generics parameters will also be used in `field_ty` and
317            // `where_clauses`, so we should substitute arguments in them as well.
318            let strukt_params = resolve_name_conflicts(strukt_params, &old_impl_params);
319            let (field_ty, ty_where_clause) = match &strukt_params {
320                Some(strukt_params) => {
321                    let args = strukt_params.to_generic_args(&make);
322                    let field_ty = rename_strukt_args(ctx, ast_strukt, field_ty, &args)?;
323                    let where_clause = ast_strukt
324                        .where_clause()
325                        .and_then(|wc| rename_strukt_args(ctx, ast_strukt, &wc, &args));
326                    (field_ty, where_clause)
327                }
328                None => (field_ty.clone(), None),
329            };
330
331            // 2) Handle instantiated generics in `field_ty`.
332
333            // 2.1) Some generics used in `self_ty` may be instantiated, so they
334            // are no longer generics, we should remove and instantiate those
335            // generics in advance.
336
337            // `old_trait_args` contains names of generic args for trait in `old_impl`
338            let old_impl_trait_args = old_impl
339                .trait_()?
340                .generic_arg_list()
341                .map(|l| l.generic_args().map(|arg| arg.to_string()))
342                .map_or_else(FxHashSet::default, |it| it.collect());
343
344            let trait_gen_params = remove_instantiated_params(
345                &old_impl.self_ty()?,
346                old_impl_params.clone(),
347                &old_impl_trait_args,
348            );
349
350            // 2.2) Generate generic args applied on impl.
351            let (transform_args, trait_gen_params) = generate_args_for_impl(
352                &make,
353                old_impl_params,
354                &old_impl.self_ty()?,
355                &field_ty,
356                trait_gen_params,
357                &old_impl_trait_args,
358            );
359
360            // 2.3) Instantiate generics with `transform_impl`, this step also
361            // remove unused params.
362            let trait_gen_args =
363                old_impl.trait_()?.generic_arg_list().and_then(|mut trait_args| {
364                    let trait_args = &mut trait_args;
365                    if let Some(new_args) = transform_impl(
366                        ctx,
367                        ast_strukt,
368                        &old_impl,
369                        &transform_args,
370                        trait_args.clone(),
371                    ) {
372                        *trait_args = new_args.clone();
373                        Some(new_args)
374                    } else {
375                        None
376                    }
377                });
378
379            let type_gen_args = strukt_params.clone().map(|params| params.to_generic_args(&make));
380            let path_type = make.ty(&trait_.name(db).display_no_db(edition).to_smolstr());
381            let path_type = transform_impl(ctx, ast_strukt, &old_impl, &transform_args, path_type)?;
382            // 3) Generate delegate trait impl
383            let delegate = make.impl_trait(
384                None,
385                trait_.is_unsafe(db),
386                trait_gen_params,
387                trait_gen_args,
388                strukt_params,
389                type_gen_args,
390                trait_.is_auto(db),
391                path_type,
392                strukt_ty,
393                old_impl.where_clause(),
394                ty_where_clause,
395                None,
396            );
397            // Goto link : https://doc.rust-lang.org/reference/paths.html#qualified-paths
398            let qualified_path_type =
399                make.path_from_text(&format!("<{} as {}>", field_ty, delegate.trait_()?));
400
401            // 4) Transform associated items in delegate trait impl
402            let assoc_items: Option<Vec<ast::AssocItem>> = old_impl.assoc_item_list().map(|ail| {
403                ail.assoc_items()
404                    .filter(|item| matches!(item, AssocItem::MacroCall(_)).not())
405                    .filter_map(|item| {
406                        let item =
407                            transform_impl(ctx, ast_strukt, &old_impl, &transform_args, item)?;
408                        process_assoc_item(item, qualified_path_type.clone(), field_name)
409                    })
410                    .collect()
411            });
412
413            finalize_delegate(&make, &delegate, assoc_items, true)
414        }
415    }
416}
417
418fn transform_impl<N: ast::AstNode>(
419    ctx: &AssistContext<'_, '_>,
420    strukt: &ast::Struct,
421    old_impl: &ast::Impl,
422    args: &Option<GenericArgList>,
423    syntax: N,
424) -> Option<N> {
425    let source_scope = ctx.sema.scope(old_impl.self_ty()?.syntax())?;
426    let target_scope = ctx.sema.scope(strukt.syntax())?;
427    let hir_old_impl = ctx.sema.to_impl_def(old_impl)?;
428
429    let transform = args.as_ref().map_or_else(
430        || PathTransform::generic_transformation(&target_scope, &source_scope),
431        |args| {
432            PathTransform::impl_transformation(
433                &target_scope,
434                &source_scope,
435                hir_old_impl,
436                args.clone(),
437            )
438        },
439    );
440
441    N::cast(transform.apply(syntax.syntax()))
442}
443
444/// Extracts the name from a generic parameter.
445fn generic_param_name(param: &ast::GenericParam) -> Option<String> {
446    match param {
447        ast::GenericParam::TypeParam(t) => t.name().map(|n| n.to_string()),
448        ast::GenericParam::ConstParam(c) => c.name().map(|n| n.to_string()),
449        ast::GenericParam::LifetimeParam(l) => l.lifetime().map(|lt| lt.to_string()),
450    }
451}
452
453/// Filters generic params, keeping only those whose names are not in `names_to_remove`.
454fn filter_generic_params(
455    gpl: ast::GenericParamList,
456    names_to_remove: &FxHashSet<String>,
457) -> Option<ast::GenericParamList> {
458    let remaining_params: Vec<_> = gpl
459        .generic_params()
460        .filter(|param| {
461            generic_param_name(param).is_none_or(|name| !names_to_remove.contains(&name))
462        })
463        .collect();
464
465    if remaining_params.is_empty() {
466        None
467    } else {
468        let make = SyntaxFactory::without_mappings();
469        Some(make.generic_param_list(remaining_params))
470    }
471}
472
473fn remove_instantiated_params(
474    self_ty: &ast::Type,
475    old_impl_params: Option<GenericParamList>,
476    old_trait_args: &FxHashSet<String>,
477) -> Option<GenericParamList> {
478    match self_ty {
479        ast::Type::PathType(path_type) => {
480            old_impl_params.and_then(|gpl| {
481                // Collect generic args that should be removed (instantiated params)
482                let args_to_remove: FxHashSet<String> = path_type
483                    .path()?
484                    .segments()
485                    .filter_map(|seg| seg.generic_arg_list())
486                    .flat_map(|it| it.generic_args())
487                    // However, if the param is also used in the trait arguments,
488                    // it shouldn't be removed now, which will be instantiated in
489                    // later `path_transform`
490                    .filter(|arg| !old_trait_args.contains(&arg.to_string()))
491                    .map(|arg| arg.to_string())
492                    .collect();
493
494                filter_generic_params(gpl, &args_to_remove)
495            })
496        }
497        _ => old_impl_params,
498    }
499}
500
501fn remove_useless_where_clauses(editor: &SyntaxEditor, delegate: &ast::Impl) {
502    let Some(wc) = delegate.where_clause() else {
503        return;
504    };
505    let (Some(trait_ty), Some(self_ty)) = (delegate.trait_(), delegate.self_ty()) else {
506        return;
507    };
508
509    let live_generics = [&trait_ty, &self_ty]
510        .into_iter()
511        .flat_map(|ty| ty.generic_arg_list())
512        .flat_map(|gal| gal.generic_args())
513        .map(|x| x.to_string())
514        .collect::<FxHashSet<_>>();
515
516    // Keep where-clauses that have generics after substitution, and remove the
517    // rest.
518    let has_no_live_generics = |pred: &WherePred| {
519        pred.syntax()
520            .descendants_with_tokens()
521            .filter_map(|e| e.into_token())
522            .any(|e| e.kind() == SyntaxKind::IDENT && live_generics.contains(&e.to_string()))
523            .not()
524    };
525
526    let predicates_to_remove: Vec<_> = wc.predicates().filter(has_no_live_generics).collect();
527    let remaining_predicates = wc.predicates().count() - predicates_to_remove.len();
528
529    if remaining_predicates == 0 {
530        // Remove the entire where clause
531        editor.delete(wc.syntax().clone());
532    } else {
533        // Remove only the useless predicates
534        for pred in predicates_to_remove {
535            // Also remove the comma before or after the predicate
536            if let Some(previous) = pred.syntax().prev_sibling() {
537                // Remove from after previous sibling to predicate (inclusive)
538                if let Some(start) = previous.next_sibling_or_token() {
539                    let end: SyntaxElement = pred.syntax().clone().into();
540                    editor.delete_all(start..=end);
541                }
542            } else if let Some(next) = pred.syntax().next_sibling() {
543                // Remove from predicate to before next sibling (exclusive)
544                if let Some(end) = next.prev_sibling_or_token() {
545                    let start: SyntaxElement = pred.syntax().clone().into();
546                    editor.delete_all(start..=end);
547                }
548            } else {
549                editor.delete(pred.syntax().clone());
550            }
551        }
552    }
553}
554
555/// Finalize the delegate impl by:
556/// 1. Replacing the assoc_item_list with new items (if any)
557/// 2. Removing useless where clauses
558fn finalize_delegate(
559    make: &SyntaxFactory,
560    delegate: &ast::Impl,
561    assoc_items: Option<Vec<ast::AssocItem>>,
562    remove_where_clauses: bool,
563) -> Option<ast::Impl> {
564    let has_items = assoc_items.as_ref().is_some_and(|items| !items.is_empty());
565
566    if !has_items && !remove_where_clauses {
567        return Some(delegate.clone());
568    }
569
570    let (editor, delegate) = SyntaxEditor::with_ast_node(delegate);
571
572    // 1. Replace assoc_item_list if we have new items
573    if let Some(items) = assoc_items
574        && !items.is_empty()
575    {
576        let new_assoc_item_list = make.assoc_item_list(items);
577        if let Some(old_list) = delegate.assoc_item_list() {
578            editor.replace(old_list.syntax(), new_assoc_item_list.syntax());
579        }
580    }
581
582    // 2. Remove useless where clauses
583    if remove_where_clauses {
584        remove_useless_where_clauses(&editor, &delegate);
585    }
586
587    ast::Impl::cast(editor.finish().new_root().clone())
588}
589
590// Generate generic args that should be apply to current impl.
591//
592// For example, say we have implementation `impl<A, B, C> Trait for B<A>`,
593// and `b: B<T>` in struct `S<T>`. Then the `A` should be instantiated to `T`.
594// While the last two generic args `B` and `C` doesn't change, it remains
595// `<B, C>`. So we apply `<T, B, C>` as generic arguments to impl.
596fn generate_args_for_impl(
597    make: &SyntaxFactory,
598    old_impl_gpl: Option<GenericParamList>,
599    self_ty: &ast::Type,
600    field_ty: &ast::Type,
601    trait_params: Option<GenericParamList>,
602    old_trait_args: &FxHashSet<String>,
603) -> (Option<ast::GenericArgList>, Option<GenericParamList>) {
604    let Some(old_impl_args) = old_impl_gpl.map(|gpl| gpl.to_generic_args(make).generic_args())
605    else {
606        return (None, trait_params);
607    };
608
609    // Create pairs of the args of `self_ty` and corresponding `field_ty` to
610    // form the substitution list
611    let mut arg_substs = FxHashMap::default();
612
613    if let field_ty @ ast::Type::PathType(_) = field_ty {
614        let field_args = field_ty.generic_arg_list().map(|gal| gal.generic_args());
615        let self_ty_args = self_ty.generic_arg_list().map(|gal| gal.generic_args());
616        if let (Some(field_args), Some(self_ty_args)) = (field_args, self_ty_args) {
617            self_ty_args.zip(field_args).for_each(|(self_ty_arg, field_arg)| {
618                arg_substs.entry(self_ty_arg.to_string()).or_insert(field_arg);
619            })
620        }
621    }
622
623    let mut params_to_remove = FxHashSet::default();
624
625    let args = old_impl_args
626        .map(|old_arg| {
627            arg_substs.get(&old_arg.to_string()).map_or_else(
628                || old_arg.clone(),
629                |replace_with| {
630                    // The old_arg will be replaced, so it becomes redundant
631                    if trait_params.is_some() && old_trait_args.contains(&old_arg.to_string()) {
632                        params_to_remove.insert(old_arg.to_string());
633                    }
634                    replace_with.clone()
635                },
636            )
637        })
638        .collect_vec();
639
640    let make = SyntaxFactory::without_mappings();
641    let result = args.is_empty().not().then(|| make.generic_arg_list(args, false));
642    let trait_params = trait_params.and_then(|gpl| filter_generic_params(gpl, &params_to_remove));
643    (result, trait_params)
644}
645
646fn rename_strukt_args<N>(
647    ctx: &AssistContext<'_, '_>,
648    strukt: &ast::Struct,
649    item: &N,
650    args: &GenericArgList,
651) -> Option<N>
652where
653    N: ast::AstNode,
654{
655    let hir_strukt = ctx.sema.to_struct_def(strukt)?;
656    let hir_adt = hir::Adt::from(hir_strukt);
657    let scope = ctx.sema.scope(item.syntax())?;
658
659    let transform = PathTransform::adt_transformation(&scope, &scope, hir_adt, args.clone());
660    N::cast(transform.apply(item.syntax()))
661}
662
663fn has_self_type(trait_: hir::Trait, ctx: &AssistContext<'_, '_>) -> bool {
664    ctx.sema
665        .source(trait_)
666        .and_then(|src| {
667            src.value
668                .syntax()
669                .descendants_with_tokens()
670                .filter_map(|e| e.into_token())
671                .find(|e| e.kind() == SyntaxKind::SELF_TYPE_KW)
672        })
673        .is_some()
674}
675
676fn resolve_name_conflicts(
677    strukt_params: Option<ast::GenericParamList>,
678    old_impl_params: &Option<ast::GenericParamList>,
679) -> Option<ast::GenericParamList> {
680    let make = SyntaxFactory::without_mappings();
681    match (strukt_params, old_impl_params) {
682        (Some(old_strukt_params), Some(old_impl_params)) => {
683            let mut new_params: Vec<ast::GenericParam> = Vec::new();
684
685            for old_strukt_param in old_strukt_params.generic_params() {
686                // Get old name from `strukt`
687                let name = SmolStr::from(generic_param_name(&old_strukt_param)?);
688
689                // The new name cannot be conflicted with generics in trait, and the renamed names.
690                let param_list_to_names = |param_list: &GenericParamList| {
691                    param_list.generic_params().flat_map(|param| match param {
692                        ast::GenericParam::TypeParam(t) => t.name().map(|name| name.to_string()),
693                        p => Some(p.to_string()),
694                    })
695                };
696                let new_params_list = make.generic_param_list(new_params.clone());
697                let existing_names = param_list_to_names(old_impl_params)
698                    .chain(param_list_to_names(&new_params_list))
699                    .collect_vec();
700                let mut name_generator = suggest_name::NameGenerator::new_with_names(
701                    existing_names.iter().map(|s| s.as_str()),
702                );
703                let name = name_generator.suggest_name(&name);
704                match old_strukt_param {
705                    ast::GenericParam::ConstParam(c) => {
706                        if let Some(const_ty) = c.ty() {
707                            let const_param = make.const_param(make.name(&name), const_ty);
708                            new_params.push(ast::GenericParam::ConstParam(const_param));
709                        }
710                    }
711                    p @ ast::GenericParam::LifetimeParam(_) => {
712                        new_params.push(p);
713                    }
714                    ast::GenericParam::TypeParam(t) => {
715                        let type_bounds = t.type_bound_list();
716                        let type_param = make.type_param(make.name(&name), type_bounds);
717                        new_params.push(ast::GenericParam::TypeParam(type_param));
718                    }
719                }
720            }
721            Some(make.generic_param_list(new_params))
722        }
723        (Some(old_strukt_gpl), None) => Some(old_strukt_gpl),
724        _ => None,
725    }
726}
727
728fn process_assoc_item(
729    item: syntax::ast::AssocItem,
730    qual_path_ty: ast::Path,
731    base_name: &str,
732) -> Option<ast::AssocItem> {
733    match item {
734        AssocItem::Const(c) => const_assoc_item(c, qual_path_ty),
735        AssocItem::Fn(f) => func_assoc_item(f, qual_path_ty, base_name),
736        AssocItem::MacroCall(_) => {
737            // FIXME : Handle MacroCall case.
738            // macro_assoc_item(mac, qual_path_ty)
739            None
740        }
741        AssocItem::TypeAlias(ta) => ty_assoc_item(ta, qual_path_ty),
742    }
743}
744
745fn const_assoc_item(item: syntax::ast::Const, qual_path_ty: ast::Path) -> Option<AssocItem> {
746    let make = SyntaxFactory::without_mappings();
747    let path_expr_segment = make.path_from_text(item.name()?.to_string().as_str());
748
749    // We want rhs of the const assignment to be a qualified path
750    // The general case for const assignment can be found [here](`https://doc.rust-lang.org/reference/items/constant-items.html`)
751    // The qualified will have the following generic syntax :
752    // <Base as Trait<GenArgs>>::ConstName;
753    // FIXME : We can't rely on `make::path_qualified` for now but it would be nice to replace the following with it.
754    // make::path_qualified(qual_path_ty, path_expr_segment.as_single_segment().unwrap());
755    let qualified_path = make.path_from_text(&format!("{qual_path_ty}::{path_expr_segment}"));
756    let inner = make.item_const(
757        item.attrs(),
758        item.visibility(),
759        item.name()?,
760        item.ty()?,
761        make.expr_path(qualified_path),
762    );
763
764    Some(AssocItem::Const(inner))
765}
766
767fn func_assoc_item(
768    item: syntax::ast::Fn,
769    qual_path_ty: Path,
770    base_name: &str,
771) -> Option<AssocItem> {
772    let make = SyntaxFactory::without_mappings();
773    let path_expr_segment = make.path_from_text(item.name()?.to_string().as_str());
774    let qualified_path = make.path_from_text(&format!("{qual_path_ty}::{path_expr_segment}"));
775
776    let call = match item.param_list() {
777        // Methods and funcs should be handled separately.
778        // We ask if the func has a `self` param.
779        Some(l) => match l.self_param() {
780            Some(slf) => {
781                let self_kw = make.expr_path(make.path_from_text("self"));
782                let self_kw = make.expr_field(self_kw, base_name).into();
783
784                let tail_expr_self = match slf.kind() {
785                    ast::SelfParamKind::Owned => self_kw,
786                    ast::SelfParamKind::Ref => make.expr_ref(self_kw, false),
787                    ast::SelfParamKind::MutRef => make.expr_ref(self_kw, true),
788                };
789
790                // Build argument list with self expression prepended
791                let other_args = convert_param_list_to_arg_list(l, &make);
792                let all_args: Vec<ast::Expr> =
793                    std::iter::once(tail_expr_self).chain(other_args.args()).collect();
794                let args = make.arg_list(all_args);
795
796                make.expr_call(make.expr_path(qualified_path), args).into()
797            }
798            None => make
799                .expr_call(make.expr_path(qualified_path), convert_param_list_to_arg_list(l, &make))
800                .into(),
801        },
802        None => make
803            .expr_call(
804                make.expr_path(qualified_path),
805                convert_param_list_to_arg_list(make.param_list(None, Vec::new()), &make),
806            )
807            .into(),
808    };
809
810    let body = make.block_expr(vec![], Some(call));
811    let func = make.fn_(
812        item.attrs(),
813        item.visibility(),
814        item.name()?,
815        item.generic_param_list(),
816        item.where_clause(),
817        item.param_list()?,
818        body,
819        item.ret_type(),
820        item.async_token().is_some(),
821        item.const_token().is_some(),
822        item.unsafe_token().is_some(),
823        item.gen_token().is_some(),
824    );
825
826    Some(AssocItem::Fn(func.indent(edit::IndentLevel(1))))
827}
828
829fn ty_assoc_item(item: syntax::ast::TypeAlias, qual_path_ty: Path) -> Option<AssocItem> {
830    let make = SyntaxFactory::without_mappings();
831    let path_expr_segment = make.path_from_text(item.name()?.to_string().as_str());
832    let qualified_path = make.path_from_text(&format!("{qual_path_ty}::{path_expr_segment}"));
833    let ty = make.ty_path(qualified_path).into();
834    let ident = item.name()?.to_string();
835
836    let alias = make
837        .ty_alias(
838            item.attrs(),
839            ident.as_str(),
840            item.generic_param_list(),
841            None,
842            item.where_clause(),
843            Some((ty, None)),
844        )
845        .indent(edit::IndentLevel(1));
846
847    Some(AssocItem::TypeAlias(alias))
848}
849
850#[cfg(test)]
851mod test {
852
853    use super::*;
854    use crate::tests::{
855        check_assist, check_assist_not_applicable, check_assist_not_applicable_no_grouping,
856    };
857
858    #[test]
859    fn test_tuple_struct_basic() {
860        check_assist(
861            generate_delegate_trait,
862            r#"
863struct Base;
864struct S(B$0ase);
865trait Trait {}
866impl Trait for Base {}
867"#,
868            r#"
869struct Base;
870struct S(Base);
871
872impl Trait for S {}
873trait Trait {}
874impl Trait for Base {}
875"#,
876        );
877    }
878
879    #[test]
880    fn test_self_ty() {
881        // trait with `Self` type cannot be delegated
882        //
883        // See the function `fn f() -> Self`.
884        // It should be `fn f() -> Base` in `Base`, and `fn f() -> S` in `S`
885        check_assist_not_applicable(
886            generate_delegate_trait,
887            r#"
888struct Base(());
889struct S(B$0ase);
890trait Trait {
891    fn f() -> Self;
892}
893impl Trait for Base {
894    fn f() -> Base {
895        Base(())
896    }
897}
898"#,
899        );
900    }
901
902    #[test]
903    fn test_struct_struct_basic() {
904        check_assist(
905            generate_delegate_trait,
906            r#"
907struct Base;
908struct S {
909    ba$0se : Base
910}
911trait Trait {}
912impl Trait for Base {}
913"#,
914            r#"
915struct Base;
916struct S {
917    base : Base
918}
919
920impl Trait for S {}
921trait Trait {}
922impl Trait for Base {}
923"#,
924        )
925    }
926
927    // Structs need to be by def populated with fields
928    // However user can invoke this assist while still editing
929    // We therefore assert its non-applicability
930    #[test]
931    fn test_yet_empty_struct() {
932        check_assist_not_applicable(
933            generate_delegate_trait,
934            r#"
935struct Base;
936struct S {
937    $0
938}
939
940impl Trait for S {}
941trait Trait {}
942impl Trait for Base {}
943"#,
944        )
945    }
946
947    #[test]
948    fn test_yet_unspecified_field_type() {
949        check_assist_not_applicable(
950            generate_delegate_trait,
951            r#"
952struct Base;
953struct S {
954    ab$0c
955}
956
957impl Trait for S {}
958trait Trait {}
959impl Trait for Base {}
960"#,
961        );
962    }
963
964    #[test]
965    fn test_unsafe_trait() {
966        check_assist(
967            generate_delegate_trait,
968            r#"
969struct Base;
970struct S {
971    ba$0se : Base
972}
973unsafe trait Trait {}
974unsafe impl Trait for Base {}
975"#,
976            r#"
977struct Base;
978struct S {
979    base : Base
980}
981
982unsafe impl Trait for S {}
983unsafe trait Trait {}
984unsafe impl Trait for Base {}
985"#,
986        );
987    }
988
989    #[test]
990    fn test_unsafe_trait_with_unsafe_fn() {
991        check_assist(
992            generate_delegate_trait,
993            r#"
994struct Base;
995struct S {
996    ba$0se: Base,
997}
998
999unsafe trait Trait {
1000    unsafe fn a_func();
1001    unsafe fn a_method(&self);
1002}
1003unsafe impl Trait for Base {
1004    unsafe fn a_func() {}
1005    unsafe fn a_method(&self) {}
1006}
1007"#,
1008            r#"
1009struct Base;
1010struct S {
1011    base: Base,
1012}
1013
1014unsafe impl Trait for S {
1015    unsafe fn a_func() {
1016        <Base as Trait>::a_func()
1017    }
1018
1019    unsafe fn a_method(&self) {
1020        <Base as Trait>::a_method(&self.base)
1021    }
1022}
1023
1024unsafe trait Trait {
1025    unsafe fn a_func();
1026    unsafe fn a_method(&self);
1027}
1028unsafe impl Trait for Base {
1029    unsafe fn a_func() {}
1030    unsafe fn a_method(&self) {}
1031}
1032"#,
1033        );
1034    }
1035
1036    #[test]
1037    fn test_struct_with_where_clause() {
1038        check_assist(
1039            generate_delegate_trait,
1040            r#"
1041trait AnotherTrait {}
1042struct S<T>
1043where
1044    T: AnotherTrait,
1045{
1046    b$0 : T,
1047}"#,
1048            r#"
1049trait AnotherTrait {}
1050struct S<T>
1051where
1052    T: AnotherTrait,
1053{
1054    b : T,
1055}
1056
1057impl<T> AnotherTrait for S<T>
1058where
1059    T: AnotherTrait,
1060{
1061}"#,
1062        );
1063    }
1064
1065    #[test]
1066    fn test_fields_with_generics() {
1067        check_assist(
1068            generate_delegate_trait,
1069            r#"
1070struct B<T> {
1071    a: T
1072}
1073
1074trait Trait<T> {
1075    fn f(&self, a: T) -> T;
1076}
1077
1078impl<T1, T2> Trait<T1> for B<T2> {
1079    fn f(&self, a: T1) -> T1 { a }
1080}
1081
1082struct A {}
1083struct S {
1084    b :$0 B<A>,
1085}
1086"#,
1087            r#"
1088struct B<T> {
1089    a: T
1090}
1091
1092trait Trait<T> {
1093    fn f(&self, a: T) -> T;
1094}
1095
1096impl<T1, T2> Trait<T1> for B<T2> {
1097    fn f(&self, a: T1) -> T1 { a }
1098}
1099
1100struct A {}
1101struct S {
1102    b : B<A>,
1103}
1104
1105impl<T1> Trait<T1> for S {
1106    fn f(&self, a: T1) -> T1 {
1107        <B<A> as Trait<T1>>::f(&self.b, a)
1108    }
1109}
1110"#,
1111        );
1112    }
1113
1114    #[test]
1115    fn test_generics_with_conflict_names() {
1116        check_assist(
1117            generate_delegate_trait,
1118            r#"
1119struct B<T> {
1120    a: T
1121}
1122
1123trait Trait<T> {
1124    fn f(&self, a: T) -> T;
1125}
1126
1127impl<T, T0> Trait<T> for B<T0> {
1128    fn f(&self, a: T) -> T { a }
1129}
1130
1131struct S<T> {
1132    b : $0B<T>,
1133}
1134"#,
1135            r#"
1136struct B<T> {
1137    a: T
1138}
1139
1140trait Trait<T> {
1141    fn f(&self, a: T) -> T;
1142}
1143
1144impl<T, T0> Trait<T> for B<T0> {
1145    fn f(&self, a: T) -> T { a }
1146}
1147
1148struct S<T> {
1149    b : B<T>,
1150}
1151
1152impl<T, T1> Trait<T> for S<T1> {
1153    fn f(&self, a: T) -> T {
1154        <B<T1> as Trait<T>>::f(&self.b, a)
1155    }
1156}
1157"#,
1158        );
1159    }
1160
1161    #[test]
1162    fn test_lifetime_with_conflict_names() {
1163        check_assist(
1164            generate_delegate_trait,
1165            r#"
1166struct B<'a, T> {
1167    a: &'a T
1168}
1169
1170trait Trait<T> {
1171    fn f(&self, a: T) -> T;
1172}
1173
1174impl<'a, T, T0> Trait<T> for B<'a, T0> {
1175    fn f(&self, a: T) -> T { a }
1176}
1177
1178struct S<'a, T> {
1179    b : $0B<'a, T>,
1180}
1181"#,
1182            r#"
1183struct B<'a, T> {
1184    a: &'a T
1185}
1186
1187trait Trait<T> {
1188    fn f(&self, a: T) -> T;
1189}
1190
1191impl<'a, T, T0> Trait<T> for B<'a, T0> {
1192    fn f(&self, a: T) -> T { a }
1193}
1194
1195struct S<'a, T> {
1196    b : B<'a, T>,
1197}
1198
1199impl<'a, T, T1> Trait<T> for S<'a, T1> {
1200    fn f(&self, a: T) -> T {
1201        <B<'a, T1> as Trait<T>>::f(&self.b, a)
1202    }
1203}
1204"#,
1205        );
1206    }
1207
1208    #[test]
1209    fn test_multiple_generics() {
1210        check_assist(
1211            generate_delegate_trait,
1212            r#"
1213struct B<T1, T2> {
1214    a: T1,
1215    b: T2
1216}
1217
1218trait Trait<T> {
1219    fn f(&self, a: T) -> T;
1220}
1221
1222impl<T, T0> Trait<T> for B<T, T0> {
1223    fn f(&self, a: T) -> T { a }
1224}
1225
1226struct S<T> {
1227    b :$0 B<i32, T>,
1228}
1229"#,
1230            r#"
1231struct B<T1, T2> {
1232    a: T1,
1233    b: T2
1234}
1235
1236trait Trait<T> {
1237    fn f(&self, a: T) -> T;
1238}
1239
1240impl<T, T0> Trait<T> for B<T, T0> {
1241    fn f(&self, a: T) -> T { a }
1242}
1243
1244struct S<T> {
1245    b : B<i32, T>,
1246}
1247
1248impl<T1> Trait<i32> for S<T1> {
1249    fn f(&self, a: i32) -> i32 {
1250        <B<i32, T1> as Trait<i32>>::f(&self.b, a)
1251    }
1252}
1253"#,
1254        );
1255    }
1256
1257    #[test]
1258    fn test_generics_multiplex() {
1259        check_assist(
1260            generate_delegate_trait,
1261            r#"
1262struct B<T> {
1263    a: T
1264}
1265
1266trait Trait<T> {
1267    fn f(&self, a: T) -> T;
1268}
1269
1270impl<T> Trait<T> for B<T> {
1271    fn f(&self, a: T) -> T { a }
1272}
1273
1274struct S<T> {
1275    b : $0B<T>,
1276}
1277"#,
1278            r#"
1279struct B<T> {
1280    a: T
1281}
1282
1283trait Trait<T> {
1284    fn f(&self, a: T) -> T;
1285}
1286
1287impl<T> Trait<T> for B<T> {
1288    fn f(&self, a: T) -> T { a }
1289}
1290
1291struct S<T> {
1292    b : B<T>,
1293}
1294
1295impl<T1> Trait<T1> for S<T1> {
1296    fn f(&self, a: T1) -> T1 {
1297        <B<T1> as Trait<T1>>::f(&self.b, a)
1298    }
1299}
1300"#,
1301        );
1302    }
1303
1304    #[test]
1305    fn test_complex_without_where() {
1306        check_assist(
1307            generate_delegate_trait,
1308            r#"
1309trait Trait<'a, T, const C: usize> {
1310    type AssocType;
1311    const AssocConst: usize;
1312    fn assoc_fn(p: ());
1313    fn assoc_method(&self, p: ());
1314}
1315
1316struct Base;
1317struct S {
1318    field$0: Base
1319}
1320
1321impl<'a, T, const C: usize> Trait<'a, T, C> for Base {
1322    type AssocType = ();
1323    const AssocConst: usize = 0;
1324    fn assoc_fn(p: ()) {}
1325    fn assoc_method(&self, p: ()) {}
1326}
1327"#,
1328            r#"
1329trait Trait<'a, T, const C: usize> {
1330    type AssocType;
1331    const AssocConst: usize;
1332    fn assoc_fn(p: ());
1333    fn assoc_method(&self, p: ());
1334}
1335
1336struct Base;
1337struct S {
1338    field: Base
1339}
1340
1341impl<'a, T, const C: usize> Trait<'a, T, C> for S {
1342    type AssocType = <Base as Trait<'a, T, C>>::AssocType;
1343
1344    const AssocConst: usize = <Base as Trait<'a, T, C>>::AssocConst;
1345
1346    fn assoc_fn(p: ()) {
1347        <Base as Trait<'a, T, C>>::assoc_fn(p)
1348    }
1349
1350    fn assoc_method(&self, p: ()) {
1351        <Base as Trait<'a, T, C>>::assoc_method(&self.field, p)
1352    }
1353}
1354
1355impl<'a, T, const C: usize> Trait<'a, T, C> for Base {
1356    type AssocType = ();
1357    const AssocConst: usize = 0;
1358    fn assoc_fn(p: ()) {}
1359    fn assoc_method(&self, p: ()) {}
1360}
1361"#,
1362        );
1363    }
1364
1365    #[test]
1366    fn test_complex_two() {
1367        check_assist(
1368            generate_delegate_trait,
1369            r"
1370trait AnotherTrait {}
1371
1372trait Trait<'a, T, const C: usize> {
1373    type AssocType;
1374    const AssocConst: usize;
1375    fn assoc_fn(p: ());
1376    fn assoc_method(&self, p: ());
1377}
1378
1379struct Base;
1380struct S {
1381    fi$0eld: Base,
1382}
1383
1384impl<'b, C, const D: usize> Trait<'b, C, D> for Base
1385where
1386    C: AnotherTrait,
1387{
1388    type AssocType = ();
1389    const AssocConst: usize = 0;
1390    fn assoc_fn(p: ()) {}
1391    fn assoc_method(&self, p: ()) {}
1392}",
1393            r#"
1394trait AnotherTrait {}
1395
1396trait Trait<'a, T, const C: usize> {
1397    type AssocType;
1398    const AssocConst: usize;
1399    fn assoc_fn(p: ());
1400    fn assoc_method(&self, p: ());
1401}
1402
1403struct Base;
1404struct S {
1405    field: Base,
1406}
1407
1408impl<'b, C, const D: usize> Trait<'b, C, D> for S
1409where
1410    C: AnotherTrait,
1411{
1412    type AssocType = <Base as Trait<'b, C, D>>::AssocType;
1413
1414    const AssocConst: usize = <Base as Trait<'b, C, D>>::AssocConst;
1415
1416    fn assoc_fn(p: ()) {
1417        <Base as Trait<'b, C, D>>::assoc_fn(p)
1418    }
1419
1420    fn assoc_method(&self, p: ()) {
1421        <Base as Trait<'b, C, D>>::assoc_method(&self.field, p)
1422    }
1423}
1424
1425impl<'b, C, const D: usize> Trait<'b, C, D> for Base
1426where
1427    C: AnotherTrait,
1428{
1429    type AssocType = ();
1430    const AssocConst: usize = 0;
1431    fn assoc_fn(p: ()) {}
1432    fn assoc_method(&self, p: ()) {}
1433}"#,
1434        )
1435    }
1436
1437    #[test]
1438    fn test_complex_three() {
1439        check_assist(
1440            generate_delegate_trait,
1441            r#"
1442trait AnotherTrait {}
1443trait YetAnotherTrait {}
1444
1445struct StructImplsAll();
1446impl AnotherTrait for StructImplsAll {}
1447impl YetAnotherTrait for StructImplsAll {}
1448
1449trait Trait<'a, T, const C: usize> {
1450    type A;
1451    const ASSOC_CONST: usize = C;
1452    fn assoc_fn(p: ());
1453    fn assoc_method(&self, p: ());
1454}
1455
1456struct Base;
1457struct S {
1458    fi$0eld: Base,
1459}
1460
1461impl<'b, A: AnotherTrait + YetAnotherTrait, const B: usize> Trait<'b, A, B> for Base
1462where
1463    A: AnotherTrait,
1464{
1465    type A = i32;
1466
1467    const ASSOC_CONST: usize = B;
1468
1469    fn assoc_fn(p: ()) {}
1470
1471    fn assoc_method(&self, p: ()) {}
1472}
1473"#,
1474            r#"
1475trait AnotherTrait {}
1476trait YetAnotherTrait {}
1477
1478struct StructImplsAll();
1479impl AnotherTrait for StructImplsAll {}
1480impl YetAnotherTrait for StructImplsAll {}
1481
1482trait Trait<'a, T, const C: usize> {
1483    type A;
1484    const ASSOC_CONST: usize = C;
1485    fn assoc_fn(p: ());
1486    fn assoc_method(&self, p: ());
1487}
1488
1489struct Base;
1490struct S {
1491    field: Base,
1492}
1493
1494impl<'b, A: AnotherTrait + YetAnotherTrait, const B: usize> Trait<'b, A, B> for S
1495where
1496    A: AnotherTrait,
1497{
1498    type A = <Base as Trait<'b, A, B>>::A;
1499
1500    const ASSOC_CONST: usize = <Base as Trait<'b, A, B>>::ASSOC_CONST;
1501
1502    fn assoc_fn(p: ()) {
1503        <Base as Trait<'b, A, B>>::assoc_fn(p)
1504    }
1505
1506    fn assoc_method(&self, p: ()) {
1507        <Base as Trait<'b, A, B>>::assoc_method(&self.field, p)
1508    }
1509}
1510
1511impl<'b, A: AnotherTrait + YetAnotherTrait, const B: usize> Trait<'b, A, B> for Base
1512where
1513    A: AnotherTrait,
1514{
1515    type A = i32;
1516
1517    const ASSOC_CONST: usize = B;
1518
1519    fn assoc_fn(p: ()) {}
1520
1521    fn assoc_method(&self, p: ()) {}
1522}
1523"#,
1524        )
1525    }
1526
1527    #[test]
1528    fn test_type_bound() {
1529        check_assist(
1530            generate_delegate_trait,
1531            r#"
1532trait AnotherTrait {}
1533struct S<T>
1534where
1535    T: AnotherTrait,
1536{
1537    b$0: T,
1538}"#,
1539            r#"
1540trait AnotherTrait {}
1541struct S<T>
1542where
1543    T: AnotherTrait,
1544{
1545    b: T,
1546}
1547
1548impl<T> AnotherTrait for S<T>
1549where
1550    T: AnotherTrait,
1551{
1552}"#,
1553        );
1554    }
1555
1556    #[test]
1557    fn test_type_bound_with_generics_1() {
1558        check_assist(
1559            generate_delegate_trait,
1560            r#"
1561trait AnotherTrait {}
1562struct B<T, T1>
1563where
1564    T1: AnotherTrait
1565{
1566    a: T,
1567    b: T1
1568}
1569
1570trait Trait<T> {
1571    fn f(&self, a: T) -> T;
1572}
1573
1574impl<T, T0, T1: AnotherTrait> Trait<T> for B<T0, T1> {
1575    fn f(&self, a: T) -> T { a }
1576}
1577
1578struct S<T, T1>
1579where
1580    T1: AnotherTrait
1581{
1582    b : $0B<T, T1>,
1583}"#,
1584            r#"
1585trait AnotherTrait {}
1586struct B<T, T1>
1587where
1588    T1: AnotherTrait
1589{
1590    a: T,
1591    b: T1
1592}
1593
1594trait Trait<T> {
1595    fn f(&self, a: T) -> T;
1596}
1597
1598impl<T, T0, T1: AnotherTrait> Trait<T> for B<T0, T1> {
1599    fn f(&self, a: T) -> T { a }
1600}
1601
1602struct S<T, T1>
1603where
1604    T1: AnotherTrait
1605{
1606    b : B<T, T1>,
1607}
1608
1609impl<T, T2, T3> Trait<T> for S<T2, T3>
1610where
1611    T3: AnotherTrait
1612{
1613    fn f(&self, a: T) -> T {
1614        <B<T2, T3> as Trait<T>>::f(&self.b, a)
1615    }
1616}"#,
1617        );
1618    }
1619
1620    #[test]
1621    fn test_type_bound_with_generics_2() {
1622        check_assist(
1623            generate_delegate_trait,
1624            r#"
1625trait AnotherTrait {}
1626struct B<T1>
1627where
1628    T1: AnotherTrait
1629{
1630    b: T1
1631}
1632
1633trait Trait<T1> {
1634    fn f(&self, a: T1) -> T1;
1635}
1636
1637impl<T, T1: AnotherTrait> Trait<T> for B<T1> {
1638    fn f(&self, a: T) -> T { a }
1639}
1640
1641struct S<T>
1642where
1643    T: AnotherTrait
1644{
1645    b : $0B<T>,
1646}"#,
1647            r#"
1648trait AnotherTrait {}
1649struct B<T1>
1650where
1651    T1: AnotherTrait
1652{
1653    b: T1
1654}
1655
1656trait Trait<T1> {
1657    fn f(&self, a: T1) -> T1;
1658}
1659
1660impl<T, T1: AnotherTrait> Trait<T> for B<T1> {
1661    fn f(&self, a: T) -> T { a }
1662}
1663
1664struct S<T>
1665where
1666    T: AnotherTrait
1667{
1668    b : B<T>,
1669}
1670
1671impl<T, T2> Trait<T> for S<T2>
1672where
1673    T2: AnotherTrait
1674{
1675    fn f(&self, a: T) -> T {
1676        <B<T2> as Trait<T>>::f(&self.b, a)
1677    }
1678}"#,
1679        );
1680    }
1681
1682    #[test]
1683    fn test_docstring_example() {
1684        check_assist(
1685            generate_delegate_trait,
1686            r#"
1687trait SomeTrait {
1688    type T;
1689    fn fn_(arg: u32) -> u32;
1690    fn method_(&mut self) -> bool;
1691}
1692struct A;
1693impl SomeTrait for A {
1694    type T = u32;
1695    fn fn_(arg: u32) -> u32 {
1696        42
1697    }
1698    fn method_(&mut self) -> bool {
1699        false
1700    }
1701}
1702struct B {
1703    a$0: A,
1704}
1705"#,
1706            r#"
1707trait SomeTrait {
1708    type T;
1709    fn fn_(arg: u32) -> u32;
1710    fn method_(&mut self) -> bool;
1711}
1712struct A;
1713impl SomeTrait for A {
1714    type T = u32;
1715    fn fn_(arg: u32) -> u32 {
1716        42
1717    }
1718    fn method_(&mut self) -> bool {
1719        false
1720    }
1721}
1722struct B {
1723    a: A,
1724}
1725
1726impl SomeTrait for B {
1727    type T = <A as SomeTrait>::T;
1728
1729    fn fn_(arg: u32) -> u32 {
1730        <A as SomeTrait>::fn_(arg)
1731    }
1732
1733    fn method_(&mut self) -> bool {
1734        <A as SomeTrait>::method_(&mut self.a)
1735    }
1736}
1737"#,
1738        );
1739    }
1740
1741    #[test]
1742    fn import_from_other_mod() {
1743        check_assist(
1744            generate_delegate_trait,
1745            r#"
1746mod some_module {
1747    pub trait SomeTrait {
1748        type T;
1749        fn fn_(arg: u32) -> u32;
1750        fn method_(&mut self) -> bool;
1751    }
1752    pub struct A;
1753    impl SomeTrait for A {
1754        type T = u32;
1755
1756        fn fn_(arg: u32) -> u32 {
1757            42
1758        }
1759
1760        fn method_(&mut self) -> bool {
1761            false
1762        }
1763    }
1764}
1765
1766struct B {
1767    a$0: some_module::A,
1768}"#,
1769            r#"
1770mod some_module {
1771    pub trait SomeTrait {
1772        type T;
1773        fn fn_(arg: u32) -> u32;
1774        fn method_(&mut self) -> bool;
1775    }
1776    pub struct A;
1777    impl SomeTrait for A {
1778        type T = u32;
1779
1780        fn fn_(arg: u32) -> u32 {
1781            42
1782        }
1783
1784        fn method_(&mut self) -> bool {
1785            false
1786        }
1787    }
1788}
1789
1790struct B {
1791    a: some_module::A,
1792}
1793
1794impl some_module::SomeTrait for B {
1795    type T = <some_module::A as some_module::SomeTrait>::T;
1796
1797    fn fn_(arg: u32) -> u32 {
1798        <some_module::A as some_module::SomeTrait>::fn_(arg)
1799    }
1800
1801    fn method_(&mut self) -> bool {
1802        <some_module::A as some_module::SomeTrait>::method_(&mut self.a)
1803    }
1804}"#,
1805        )
1806    }
1807
1808    #[test]
1809    fn test_fn_with_attrs() {
1810        check_assist(
1811            generate_delegate_trait,
1812            r#"
1813struct A;
1814
1815trait T {
1816    #[cfg(test)]
1817    fn f(&self, a: u32);
1818    #[cfg(not(test))]
1819    fn f(&self, a: bool);
1820}
1821
1822impl T for A {
1823    #[cfg(test)]
1824    fn f(&self, a: u32) {}
1825    #[cfg(not(test))]
1826    fn f(&self, a: bool) {}
1827}
1828
1829struct B {
1830    a$0: A,
1831}
1832"#,
1833            r#"
1834struct A;
1835
1836trait T {
1837    #[cfg(test)]
1838    fn f(&self, a: u32);
1839    #[cfg(not(test))]
1840    fn f(&self, a: bool);
1841}
1842
1843impl T for A {
1844    #[cfg(test)]
1845    fn f(&self, a: u32) {}
1846    #[cfg(not(test))]
1847    fn f(&self, a: bool) {}
1848}
1849
1850struct B {
1851    a: A,
1852}
1853
1854impl T for B {
1855    #[cfg(test)]
1856    fn f(&self, a: u32) {
1857        <A as T>::f(&self.a, a)
1858    }
1859
1860    #[cfg(not(test))]
1861    fn f(&self, a: bool) {
1862        <A as T>::f(&self.a, a)
1863    }
1864}
1865"#,
1866        );
1867    }
1868
1869    #[test]
1870    fn test_ty_alias_attrs() {
1871        check_assist(
1872            generate_delegate_trait,
1873            r#"
1874struct A;
1875
1876trait T {
1877    #[cfg(test)]
1878    type t;
1879    #[cfg(not(test))]
1880    type t;
1881}
1882
1883impl T for A {
1884    #[cfg(test)]
1885    type t = u32;
1886    #[cfg(not(test))]
1887    type t = bool;
1888}
1889
1890struct B {
1891    a$0: A,
1892}
1893"#,
1894            r#"
1895struct A;
1896
1897trait T {
1898    #[cfg(test)]
1899    type t;
1900    #[cfg(not(test))]
1901    type t;
1902}
1903
1904impl T for A {
1905    #[cfg(test)]
1906    type t = u32;
1907    #[cfg(not(test))]
1908    type t = bool;
1909}
1910
1911struct B {
1912    a: A,
1913}
1914
1915impl T for B {
1916    #[cfg(test)]
1917    type t = <A as T>::t;
1918
1919    #[cfg(not(test))]
1920    type t = <A as T>::t;
1921}
1922"#,
1923        );
1924    }
1925
1926    #[test]
1927    fn assoc_items_attributes_mutably_cloned() {
1928        check_assist(
1929            generate_delegate_trait,
1930            r#"
1931pub struct A;
1932pub trait C<D> {
1933    #[allow(clippy::dead_code)]
1934    fn a_funk(&self) -> &D;
1935}
1936
1937pub struct B<T: C<A>> {
1938    has_dr$0ain: T,
1939}
1940"#,
1941            r#"
1942pub struct A;
1943pub trait C<D> {
1944    #[allow(clippy::dead_code)]
1945    fn a_funk(&self) -> &D;
1946}
1947
1948pub struct B<T: C<A>> {
1949    has_drain: T,
1950}
1951
1952impl<D, T: C<A>> C<D> for B<T> {
1953    #[allow(clippy::dead_code)]
1954    fn a_funk(&self) -> &D {
1955        <T as C<D>>::a_funk(&self.has_drain)
1956    }
1957}
1958"#,
1959        )
1960    }
1961
1962    #[test]
1963    fn delegate_trait_skipped_when_no_grouping() {
1964        check_assist_not_applicable_no_grouping(
1965            generate_delegate_trait,
1966            r#"
1967trait SomeTrait {
1968    type T;
1969    fn fn_(arg: u32) -> u32;
1970    fn method_(&mut self) -> bool;
1971}
1972struct A;
1973impl SomeTrait for A {
1974    type T = u32;
1975
1976    fn fn_(arg: u32) -> u32 {
1977        42
1978    }
1979
1980    fn method_(&mut self) -> bool {
1981        false
1982    }
1983}
1984struct B {
1985    a$0 : A,
1986}
1987"#,
1988        );
1989    }
1990}