@@ -434,35 +434,67 @@ pub(crate) fn find_impl_block_end(impl_def: ast::Impl, buf: &mut String) -> Opti
434
434
Some ( end)
435
435
}
436
436
437
- // Generates the surrounding `impl Type { <code> }` including type and lifetime
438
- // parameters
437
+ /// Generates the surrounding `impl Type { <code> }` including type and lifetime
438
+ /// parameters.
439
439
pub ( crate ) fn generate_impl_text ( adt : & ast:: Adt , code : & str ) -> String {
440
- generate_impl_text_inner ( adt, None , code)
440
+ generate_impl_text_inner ( adt, None , true , code)
441
441
}
442
442
443
- // Generates the surrounding `impl <trait> for Type { <code> }` including type
444
- // 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`.
445
447
pub ( crate ) fn generate_trait_impl_text ( adt : & ast:: Adt , trait_text : & str , code : & str ) -> String {
446
- 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)
447
461
}
448
462
449
- 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 {
450
469
// Ensure lifetime params are before type & const params
451
470
let generic_params = adt. generic_param_list ( ) . map ( |generic_params| {
452
471
let lifetime_params =
453
472
generic_params. lifetime_params ( ) . map ( ast:: GenericParam :: LifetimeParam ) ;
454
- 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
473
+ let ty_or_const_params = generic_params. type_or_const_params ( ) . map ( |param| {
456
474
match param {
457
475
ast:: TypeOrConstParam :: Type ( param) => {
458
476
let param = param. clone_for_update ( ) ;
477
+ // remove defaults since they can't be specified in impls
459
478
param. remove_default ( ) ;
460
- Some ( ast:: GenericParam :: TypeParam ( param) )
479
+ let mut bounds =
480
+ param. type_bound_list ( ) . map_or_else ( Vec :: new, |it| it. bounds ( ) . collect ( ) ) ;
481
+ if let Some ( trait_) = trait_text {
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 {
485
+ bounds. push ( make:: type_bound ( trait_) ) ;
486
+ }
487
+ } ;
488
+ // `{ty_param}: {bounds}`
489
+ let param =
490
+ make:: type_param ( param. name ( ) . unwrap ( ) , make:: type_bound_list ( bounds) ) ;
491
+ ast:: GenericParam :: TypeParam ( param)
461
492
}
462
493
ast:: TypeOrConstParam :: Const ( param) => {
463
494
let param = param. clone_for_update ( ) ;
495
+ // remove defaults since they can't be specified in impls
464
496
param. remove_default ( ) ;
465
- Some ( ast:: GenericParam :: ConstParam ( param) )
497
+ ast:: GenericParam :: ConstParam ( param)
466
498
}
467
499
}
468
500
} ) ;
0 commit comments