@@ -5,7 +5,6 @@ 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 ;
98use stdx:: format_to;
109use syntax:: {
1110 ast:: {
@@ -435,52 +434,67 @@ pub(crate) fn find_impl_block_end(impl_def: ast::Impl, buf: &mut String) -> Opti
435434 Some ( end)
436435}
437436
438- // Generates the surrounding `impl Type { <code> }` including type and lifetime
439- // parameters
437+ /// Generates the surrounding `impl Type { <code> }` including type and lifetime
438+ /// parameters.
440439pub ( crate ) fn generate_impl_text ( adt : & ast:: Adt , code : & str ) -> String {
441- generate_impl_text_inner ( adt, None , code)
440+ generate_impl_text_inner ( adt, None , true , code)
442441}
443442
444- // Generates the surrounding `impl <trait> for Type { <code> }` including type
445- // and lifetime parameters
443+ /// Generates the surrounding `impl <trait> for Type { <code> }` including type
444+ /// and lifetime parameters, with `<trait>` appended to `impl`'s generic parameters' bounds.
445+ ///
446+ /// This is useful for traits like `PartialEq`, since `impl<T> PartialEq for U<T>` often requires `T: PartialEq`.
446447pub ( crate ) fn generate_trait_impl_text ( adt : & ast:: Adt , trait_text : & str , code : & str ) -> String {
447- generate_impl_text_inner ( adt, Some ( trait_text) , code)
448+ generate_impl_text_inner ( adt, Some ( trait_text) , true , code)
449+ }
450+
451+ /// Generates the surrounding `impl <trait> for Type { <code> }` including type
452+ /// and lifetime parameters, with `impl`'s generic parameters' bounds kept as-is.
453+ ///
454+ /// This is useful for traits like `From<T>`, since `impl<T> From<T> for U<T>` doesn't require `T: From<T>`.
455+ pub ( crate ) fn generate_trait_impl_text_intransitive (
456+ adt : & ast:: Adt ,
457+ trait_text : & str ,
458+ code : & str ,
459+ ) -> String {
460+ generate_impl_text_inner ( adt, Some ( trait_text) , false , code)
448461}
449462
450- fn generate_impl_text_inner ( adt : & ast:: Adt , trait_text : Option < & str > , code : & str ) -> String {
463+ fn generate_impl_text_inner (
464+ adt : & ast:: Adt ,
465+ trait_text : Option < & str > ,
466+ trait_is_transitive : bool ,
467+ code : & str ,
468+ ) -> String {
451469 // Ensure lifetime params are before type & const params
452470 let generic_params = adt. generic_param_list ( ) . map ( |generic_params| {
453471 let lifetime_params =
454472 generic_params. lifetime_params ( ) . map ( ast:: GenericParam :: LifetimeParam ) ;
455- let ty_or_const_params = generic_params. type_or_const_params ( ) . filter_map ( |param| {
473+ let ty_or_const_params = generic_params. type_or_const_params ( ) . map ( |param| {
456474 match param {
457475 ast:: TypeOrConstParam :: Type ( param) => {
458476 let param = param. clone_for_update ( ) ;
459477 // remove defaults since they can't be specified in impls
460478 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}`
479+ let mut bounds =
480+ param. type_bound_list ( ) . map_or_else ( Vec :: new, |it| it. bounds ( ) . collect ( ) ) ;
465481 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- {
482+ // Add the current trait to `bounds` if the trait is transitive,
483+ // meaning `impl<T> Trait for U<T>` requires `T: Trait`.
484+ if trait_is_transitive {
472485 bounds. push ( make:: type_bound ( trait_) ) ;
473486 }
474487 } ;
488+ // `{ty_param}: {bounds}`
475489 let param =
476490 make:: type_param ( param. name ( ) . unwrap ( ) , make:: type_bound_list ( bounds) ) ;
477- Some ( ast:: GenericParam :: TypeParam ( param) )
491+ ast:: GenericParam :: TypeParam ( param)
478492 }
479493 ast:: TypeOrConstParam :: Const ( param) => {
480494 let param = param. clone_for_update ( ) ;
481495 // remove defaults since they can't be specified in impls
482496 param. remove_default ( ) ;
483- Some ( ast:: GenericParam :: ConstParam ( param) )
497+ ast:: GenericParam :: ConstParam ( param)
484498 }
485499 }
486500 } ) ;
0 commit comments