@@ -5,6 +5,7 @@ use std::ops;
55pub ( crate ) use gen_trait_fn_body:: gen_trait_fn_body;
66use hir:: { db:: HirDatabase , HirDisplay , Semantics } ;
77use ide_db:: { famous_defs:: FamousDefs , path_transform:: PathTransform , RootDatabase , SnippetCap } ;
8+ use itertools:: Itertools ;
89use stdx:: format_to;
910use syntax:: {
1011 ast:: {
@@ -452,15 +453,32 @@ fn generate_impl_text_inner(adt: &ast::Adt, trait_text: Option<&str>, code: &str
452453 let lifetime_params =
453454 generic_params. lifetime_params ( ) . map ( ast:: GenericParam :: LifetimeParam ) ;
454455 let ty_or_const_params = generic_params. type_or_const_params ( ) . filter_map ( |param| {
455- // remove defaults since they can't be specified in impls
456456 match param {
457457 ast:: TypeOrConstParam :: Type ( param) => {
458458 let param = param. clone_for_update ( ) ;
459+ // remove defaults since they can't be specified in impls
459460 param. remove_default ( ) ;
461+ let mut bounds = param
462+ . type_bound_list ( )
463+ . map_or_else ( Vec :: new, |it| it. bounds ( ) . collect_vec ( ) ) ;
464+ // `{ty_param}: {trait_text}`
465+ if let Some ( trait_) = trait_text {
466+ // Defense against the following cases:
467+ // - The trait is undetermined, e.g. `$0`.
468+ // - The trait is a `From`, e.g. `From<T>`.
469+ if !trait_. starts_with ( '$' )
470+ && !matches ! ( trait_. split_once( '<' ) , Some ( ( left, _right) ) if left. trim( ) == "From" )
471+ {
472+ bounds. push ( make:: type_bound ( trait_) ) ;
473+ }
474+ } ;
475+ let param =
476+ make:: type_param ( param. name ( ) . unwrap ( ) , make:: type_bound_list ( bounds) ) ;
460477 Some ( ast:: GenericParam :: TypeParam ( param) )
461478 }
462479 ast:: TypeOrConstParam :: Const ( param) => {
463480 let param = param. clone_for_update ( ) ;
481+ // remove defaults since they can't be specified in impls
464482 param. remove_default ( ) ;
465483 Some ( ast:: GenericParam :: ConstParam ( param) )
466484 }
0 commit comments