@@ -2,15 +2,15 @@ use proc_macro::{self, TokenStream};
22use proc_macro2:: Span ;
33use quote:: quote;
44use syn:: {
5- parse_macro_input, Data , DataEnum , DeriveInput , Field , Fields , GenericArgument , Ident , Member , PathArguments ,
6- Type ,
5+ parse_macro_input, parse_quote , Data , DataEnum , DeriveInput , Field , Fields , GenericArgument , Ident , Member ,
6+ PathArguments , Type ,
77} ;
88
99pub ( crate ) fn derive_into_owned ( input : TokenStream ) -> TokenStream {
1010 let DeriveInput {
1111 ident : self_name,
1212 data,
13- generics,
13+ mut generics,
1414 ..
1515 } = parse_macro_input ! ( input) ;
1616
@@ -105,16 +105,61 @@ pub(crate) fn derive_into_owned(input: TokenStream) -> TokenStream {
105105 }
106106 } ;
107107
108- let ( impl_generics , ty_generics , where_clause ) = generics. split_for_impl ( ) ;
108+ let orig_generics = generics. clone ( ) ;
109109
110- let into_owned = if generics. lifetimes ( ) . next ( ) . is_none ( ) {
111- panic ! ( "can't derive IntoOwned on a type without any lifetimes" )
110+ // Add generic bounds for all type parameters.
111+ let mut type_param_names = vec ! [ ] ;
112+
113+ for ty in generics. type_params ( ) {
114+ type_param_names. push ( ty. ident . clone ( ) ) ;
115+ }
116+
117+ for type_param in type_param_names {
118+ generics. make_where_clause ( ) . predicates . push_value ( parse_quote ! {
119+ #type_param: ' static + for <' aa> crate :: traits:: IntoOwned <' aa>
120+ } )
121+ }
122+
123+ let has_lifetime = generics
124+ . params
125+ . first ( )
126+ . map_or ( false , |v| matches ! ( v, syn:: GenericParam :: Lifetime ( ..) ) ) ;
127+
128+ // Prepend `'any` to generics
129+ let any = syn:: GenericParam :: Lifetime ( syn:: LifetimeDef {
130+ attrs : Default :: default ( ) ,
131+ lifetime : syn:: Lifetime {
132+ apostrophe : Span :: call_site ( ) ,
133+ ident : Ident :: new ( "any" , Span :: call_site ( ) ) ,
134+ } ,
135+ colon_token : None ,
136+ bounds : Default :: default ( ) ,
137+ } ) ;
138+ generics. params . insert ( 0 , any. clone ( ) ) ;
139+
140+ let ( impl_generics, _, where_clause) = generics. split_for_impl ( ) ;
141+ let ( _, ty_generics, _) = orig_generics. split_for_impl ( ) ;
142+
143+ let into_owned = if !has_lifetime {
144+ quote ! {
145+ impl #impl_generics crate :: traits:: IntoOwned <' any> for #self_name #ty_generics #where_clause {
146+ type Owned = Self ;
147+
148+ #[ inline]
149+ fn into_owned( self ) -> Self {
150+ self
151+ }
152+ }
153+ }
112154 } else {
113155 let params = generics. type_params ( ) ;
114156 quote ! {
115- impl #impl_generics #self_name #ty_generics #where_clause {
157+ impl #impl_generics crate :: traits:: IntoOwned <' any> for #self_name #ty_generics #where_clause {
158+ type Owned = #self_name<' any, #( #params) , * >;
116159 /// Consumes the value and returns an owned clone.
117- pub fn into_owned<' x>( self ) -> #self_name<' x, #( #params) , * > {
160+ fn into_owned( self ) -> Self :: Owned {
161+ use crate :: traits:: IntoOwned ;
162+
118163 #res
119164 }
120165 }
0 commit comments