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