@@ -470,6 +470,7 @@ pub(crate) fn find_impl_block_end(impl_def: ast::Impl, buf: &mut String) -> Opti
470470
471471/// Generates the surrounding `impl Type { <code> }` including type and lifetime
472472/// parameters.
473+ // FIXME: migrate remaining uses to `generate_impl`
473474pub ( crate ) fn generate_impl_text ( adt : & ast:: Adt , code : & str ) -> String {
474475 generate_impl_text_inner ( adt, None , true , code)
475476}
@@ -478,6 +479,7 @@ pub(crate) fn generate_impl_text(adt: &ast::Adt, code: &str) -> String {
478479/// and lifetime parameters, with `<trait>` appended to `impl`'s generic parameters' bounds.
479480///
480481/// This is useful for traits like `PartialEq`, since `impl<T> PartialEq for U<T>` often requires `T: PartialEq`.
482+ // FIXME: migrate remaining uses to `generate_trait_impl`
481483pub ( crate ) fn generate_trait_impl_text ( adt : & ast:: Adt , trait_text : & str , code : & str ) -> String {
482484 generate_impl_text_inner ( adt, Some ( trait_text) , true , code)
483485}
@@ -486,6 +488,7 @@ pub(crate) fn generate_trait_impl_text(adt: &ast::Adt, trait_text: &str, code: &
486488/// and lifetime parameters, with `impl`'s generic parameters' bounds kept as-is.
487489///
488490/// This is useful for traits like `From<T>`, since `impl<T> From<T> for U<T>` doesn't require `T: From<T>`.
491+ // FIXME: migrate remaining uses to `generate_trait_impl_intransitive`
489492pub ( crate ) fn generate_trait_impl_text_intransitive (
490493 adt : & ast:: Adt ,
491494 trait_text : & str ,
@@ -516,7 +519,7 @@ fn generate_impl_text_inner(
516519 // Add the current trait to `bounds` if the trait is transitive,
517520 // meaning `impl<T> Trait for U<T>` requires `T: Trait`.
518521 if trait_is_transitive {
519- bounds. push ( make:: type_bound ( trait_) ) ;
522+ bounds. push ( make:: type_bound_text ( trait_) ) ;
520523 }
521524 } ;
522525 // `{ty_param}: {bounds}`
@@ -574,6 +577,101 @@ fn generate_impl_text_inner(
574577 buf
575578}
576579
580+ /// Generates the corresponding `impl Type {}` including type and lifetime
581+ /// parameters.
582+ pub ( crate ) fn generate_impl ( adt : & ast:: Adt ) -> ast:: Impl {
583+ generate_impl_inner ( adt, None , true )
584+ }
585+
586+ /// Generates the corresponding `impl <trait> for Type {}` including type
587+ /// and lifetime parameters, with `<trait>` appended to `impl`'s generic parameters' bounds.
588+ ///
589+ /// This is useful for traits like `PartialEq`, since `impl<T> PartialEq for U<T>` often requires `T: PartialEq`.
590+ pub ( crate ) fn generate_trait_impl ( adt : & ast:: Adt , trait_ : ast:: Type ) -> ast:: Impl {
591+ generate_impl_inner ( adt, Some ( trait_) , true )
592+ }
593+
594+ /// Generates the corresponding `impl <trait> for Type {}` including type
595+ /// and lifetime parameters, with `impl`'s generic parameters' bounds kept as-is.
596+ ///
597+ /// This is useful for traits like `From<T>`, since `impl<T> From<T> for U<T>` doesn't require `T: From<T>`.
598+ pub ( crate ) fn generate_trait_impl_intransitive ( adt : & ast:: Adt , trait_ : ast:: Type ) -> ast:: Impl {
599+ generate_impl_inner ( adt, Some ( trait_) , false )
600+ }
601+
602+ fn generate_impl_inner (
603+ adt : & ast:: Adt ,
604+ trait_ : Option < ast:: Type > ,
605+ trait_is_transitive : bool ,
606+ ) -> ast:: Impl {
607+ // Ensure lifetime params are before type & const params
608+ let generic_params = adt. generic_param_list ( ) . map ( |generic_params| {
609+ let lifetime_params =
610+ generic_params. lifetime_params ( ) . map ( ast:: GenericParam :: LifetimeParam ) ;
611+ let ty_or_const_params = generic_params. type_or_const_params ( ) . map ( |param| {
612+ match param {
613+ ast:: TypeOrConstParam :: Type ( param) => {
614+ let param = param. clone_for_update ( ) ;
615+ // remove defaults since they can't be specified in impls
616+ param. remove_default ( ) ;
617+ let mut bounds =
618+ param. type_bound_list ( ) . map_or_else ( Vec :: new, |it| it. bounds ( ) . collect ( ) ) ;
619+ if let Some ( trait_) = & trait_ {
620+ // Add the current trait to `bounds` if the trait is transitive,
621+ // meaning `impl<T> Trait for U<T>` requires `T: Trait`.
622+ if trait_is_transitive {
623+ bounds. push ( make:: type_bound ( trait_. clone ( ) ) ) ;
624+ }
625+ } ;
626+ // `{ty_param}: {bounds}`
627+ let param =
628+ make:: type_param ( param. name ( ) . unwrap ( ) , make:: type_bound_list ( bounds) ) ;
629+ ast:: GenericParam :: TypeParam ( param)
630+ }
631+ ast:: TypeOrConstParam :: Const ( param) => {
632+ let param = param. clone_for_update ( ) ;
633+ // remove defaults since they can't be specified in impls
634+ param. remove_default ( ) ;
635+ ast:: GenericParam :: ConstParam ( param)
636+ }
637+ }
638+ } ) ;
639+
640+ make:: generic_param_list ( itertools:: chain ( lifetime_params, ty_or_const_params) )
641+ } ) ;
642+ let generic_args =
643+ generic_params. as_ref ( ) . map ( |params| params. to_generic_args ( ) . clone_for_update ( ) ) ;
644+ let ty = make:: ty_path ( make:: ext:: ident_path ( & adt. name ( ) . unwrap ( ) . text ( ) ) ) ;
645+
646+ let impl_ = match trait_ {
647+ Some ( trait_) => make:: impl_trait (
648+ false ,
649+ None ,
650+ None ,
651+ generic_params,
652+ generic_args,
653+ false ,
654+ trait_,
655+ ty,
656+ None ,
657+ adt. where_clause ( ) ,
658+ None ,
659+ ) ,
660+ None => make:: impl_ ( generic_params, generic_args, ty, adt. where_clause ( ) , None ) ,
661+ }
662+ . clone_for_update ( ) ;
663+
664+ // Copy any cfg attrs from the original adt
665+ let cfg_attrs = adt
666+ . attrs ( )
667+ . filter ( |attr| attr. as_simple_call ( ) . map ( |( name, _arg) | name == "cfg" ) . unwrap_or ( false ) ) ;
668+ for attr in cfg_attrs {
669+ impl_. add_attr ( attr. clone_for_update ( ) ) ;
670+ }
671+
672+ impl_
673+ }
674+
577675pub ( crate ) fn add_method_to_adt (
578676 builder : & mut SourceChangeBuilder ,
579677 adt : & ast:: Adt ,
0 commit comments