@@ -470,6 +470,7 @@ pub(crate) fn find_impl_block_end(impl_def: ast::Impl, buf: &mut String) -> Opti
470
470
471
471
/// Generates the surrounding `impl Type { <code> }` including type and lifetime
472
472
/// parameters.
473
+ // FIXME: migrate remaining uses to `generate_impl`
473
474
pub ( crate ) fn generate_impl_text ( adt : & ast:: Adt , code : & str ) -> String {
474
475
generate_impl_text_inner ( adt, None , true , code)
475
476
}
@@ -478,6 +479,7 @@ pub(crate) fn generate_impl_text(adt: &ast::Adt, code: &str) -> String {
478
479
/// and lifetime parameters, with `<trait>` appended to `impl`'s generic parameters' bounds.
479
480
///
480
481
/// 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`
481
483
pub ( crate ) fn generate_trait_impl_text ( adt : & ast:: Adt , trait_text : & str , code : & str ) -> String {
482
484
generate_impl_text_inner ( adt, Some ( trait_text) , true , code)
483
485
}
@@ -486,6 +488,7 @@ pub(crate) fn generate_trait_impl_text(adt: &ast::Adt, trait_text: &str, code: &
486
488
/// and lifetime parameters, with `impl`'s generic parameters' bounds kept as-is.
487
489
///
488
490
/// 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`
489
492
pub ( crate ) fn generate_trait_impl_text_intransitive (
490
493
adt : & ast:: Adt ,
491
494
trait_text : & str ,
@@ -516,7 +519,7 @@ fn generate_impl_text_inner(
516
519
// Add the current trait to `bounds` if the trait is transitive,
517
520
// meaning `impl<T> Trait for U<T>` requires `T: Trait`.
518
521
if trait_is_transitive {
519
- bounds. push ( make:: type_bound ( trait_) ) ;
522
+ bounds. push ( make:: type_bound_text ( trait_) ) ;
520
523
}
521
524
} ;
522
525
// `{ty_param}: {bounds}`
@@ -574,6 +577,101 @@ fn generate_impl_text_inner(
574
577
buf
575
578
}
576
579
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
+
577
675
pub ( crate ) fn add_method_to_adt (
578
676
builder : & mut SourceChangeBuilder ,
579
677
adt : & ast:: Adt ,
0 commit comments