@@ -150,49 +150,48 @@ impl<'a> Expansion<'a> {
150
150
( & convs. ref_mut , true , true ) ,
151
151
]
152
152
. into_iter ( )
153
- . filter_map ( |( out_tys, ref_, mut_) | {
154
- out_tys. as_ref ( ) . map ( |out_tys| {
155
- let lf = ref_. then ( || {
156
- syn:: Lifetime :: new ( "'__derive_more_into" , Span :: call_site ( ) )
157
- } ) ;
158
- let r = ref_. then ( token:: And :: default) ;
159
- let m = mut_. then ( token:: Mut :: default) ;
160
-
161
- let gens = if let Some ( lf) = lf. clone ( ) {
162
- let mut gens = input_generics. clone ( ) ;
163
- gens. params . push ( syn:: LifetimeParam :: new ( lf) . into ( ) ) ;
164
- Cow :: Owned ( gens)
165
- } else {
166
- Cow :: Borrowed ( input_generics)
167
- } ;
168
- let ( impl_gens, _, where_clause) = gens. split_for_impl ( ) ;
169
- let ( _, ty_gens, _) = input_generics. split_for_impl ( ) ;
170
-
171
- if out_tys. is_empty ( ) {
172
- Either :: Left ( iter:: once ( & fields_tuple) )
173
- } else {
174
- Either :: Right ( out_tys. iter ( ) )
175
- } . map ( |out_ty| {
176
- let tys: Vec < _ > = fields_tys. validate_type ( out_ty) ?. collect ( ) ;
177
-
178
- Ok ( quote ! {
179
- #[ automatically_derived]
180
- impl #impl_gens :: core:: convert:: From <#r #lf #m #input_ident #ty_gens>
181
- for ( #( #r #lf #m #tys ) , * ) #where_clause
182
- {
183
- #[ inline]
184
- fn from( value: #r #lf #m #input_ident #ty_gens) -> Self {
185
- ( #(
186
- <#r #m #tys as :: core:: convert:: From <_>>:: from(
187
- #r #m value. #fields_idents
188
- )
189
- ) , * )
190
- }
153
+ . filter ( |( conv, _, _) | conv. consider_fields_ty || !conv. tys . is_empty ( ) )
154
+ . map ( |( conv, ref_, mut_) | {
155
+ let lf = ref_. then ( || syn:: Lifetime :: new ( "'__derive_more_into" , Span :: call_site ( ) ) ) ;
156
+ let r = ref_. then ( token:: And :: default) ;
157
+ let m = mut_. then ( token:: Mut :: default) ;
158
+
159
+ let gens = if let Some ( lf) = lf. clone ( ) {
160
+ let mut gens = input_generics. clone ( ) ;
161
+ gens. params . push ( syn:: LifetimeParam :: new ( lf) . into ( ) ) ;
162
+ Cow :: Owned ( gens)
163
+ } else {
164
+ Cow :: Borrowed ( input_generics)
165
+ } ;
166
+ let ( impl_gens, _, where_clause) = gens. split_for_impl ( ) ;
167
+ let ( _, ty_gens, _) = input_generics. split_for_impl ( ) ;
168
+
169
+ if conv. consider_fields_ty {
170
+ Either :: Left ( iter:: once ( & fields_tuple) )
171
+ } else {
172
+ Either :: Right ( iter:: empty ( ) )
173
+ }
174
+ . chain ( & conv. tys )
175
+ . map ( |out_ty| {
176
+ let tys: Vec < _ > = fields_tys. validate_type ( out_ty) ?. collect ( ) ;
177
+
178
+ Ok ( quote ! {
179
+ #[ automatically_derived]
180
+ impl #impl_gens :: core:: convert:: From <#r #lf #m #input_ident #ty_gens>
181
+ for ( #( #r #lf #m #tys ) , * ) #where_clause
182
+ {
183
+ #[ inline]
184
+ fn from( value: #r #lf #m #input_ident #ty_gens) -> Self {
185
+ ( #(
186
+ <#r #m #tys as :: core:: convert:: From <_>>:: from(
187
+ #r #m value. #fields_idents
188
+ )
189
+ ) , * )
191
190
}
192
- } )
191
+ }
193
192
} )
194
- . collect :: < syn:: Result < TokenStream > > ( )
195
193
} )
194
+ . collect :: < syn:: Result < TokenStream > > ( )
196
195
} )
197
196
. collect ( )
198
197
}
@@ -289,64 +288,75 @@ impl attr::ParseMultiple for FieldAttribute {
289
288
}
290
289
}
291
290
291
+ /// [`Into`] conversions specified by a [`ConversionsAttribute`].
292
+ #[ derive( Clone , Debug , Default ) ]
293
+ struct Conversions {
294
+ /// Indicator whether these [`Conversions`] should contain a conversion into fields type.
295
+ consider_fields_ty : bool ,
296
+
297
+ /// [`syn::Type`]s explicitly specified in a [`ConversionsAttribute`].
298
+ tys : Punctuated < syn:: Type , token:: Comma > ,
299
+ }
300
+
292
301
/// Representation of an [`Into`] derive macro attribute describing specified [`Into`] conversions.
293
302
///
294
303
/// ```rust,ignore
295
304
/// #[into(<types>)]
296
305
/// #[into(owned(<types>), ref(<types>), ref_mut(<types>))]
297
306
/// ```
298
- ///
299
- /// For each field:
300
- /// - [`None`] represents no conversions.
301
- /// - Empty [`Punctuated`] represents a conversion into the field type.
302
307
#[ derive( Clone , Debug ) ]
303
308
struct ConversionsAttribute {
304
309
/// [`Type`]s wrapped into `owned(...)` or simply `#[into(...)]`.
305
- owned : Option < Punctuated < syn :: Type , token :: Comma > > ,
310
+ owned : Conversions ,
306
311
307
312
/// [`Type`]s wrapped into `ref(...)`.
308
- r#ref : Option < Punctuated < syn :: Type , token :: Comma > > ,
313
+ r#ref : Conversions ,
309
314
310
315
/// [`Type`]s wrapped into `ref_mut(...)`.
311
- ref_mut : Option < Punctuated < syn :: Type , token :: Comma > > ,
316
+ ref_mut : Conversions ,
312
317
}
313
318
314
319
impl Default for ConversionsAttribute {
315
320
fn default ( ) -> Self {
316
321
Self {
317
- owned : Some ( Punctuated :: new ( ) ) ,
318
- r#ref : None ,
319
- ref_mut : None ,
322
+ owned : Conversions {
323
+ consider_fields_ty : true ,
324
+ tys : Punctuated :: new ( ) ,
325
+ } ,
326
+ r#ref : Conversions :: default ( ) ,
327
+ ref_mut : Conversions :: default ( ) ,
320
328
}
321
329
}
322
330
}
323
331
324
332
impl Parse for ConversionsAttribute {
325
333
fn parse ( input : ParseStream < ' _ > ) -> syn:: Result < Self > {
326
334
let mut out = Self {
327
- owned : None ,
328
- r#ref : None ,
329
- ref_mut : None ,
335
+ owned : Conversions :: default ( ) ,
336
+ r#ref : Conversions :: default ( ) ,
337
+ ref_mut : Conversions :: default ( ) ,
330
338
} ;
331
339
332
- let parse_inner = |ahead, types : & mut Option < _ > | {
340
+ let parse_inner = |ahead, convs : & mut Conversions | {
333
341
input. advance_to ( & ahead) ;
334
342
335
- let types = types. get_or_insert_with ( Punctuated :: new) ;
336
343
if input. peek ( token:: Paren ) {
337
344
let inner;
338
345
syn:: parenthesized!( inner in input) ;
339
346
340
- types . extend (
347
+ convs . tys . extend (
341
348
inner
342
349
. parse_terminated ( syn:: Type :: parse, token:: Comma ) ?
343
350
. into_pairs ( ) ,
344
351
) ;
352
+ } else {
353
+ convs. consider_fields_ty = true ;
345
354
}
355
+
346
356
if input. peek ( token:: Comma ) {
347
357
let comma = input. parse :: < token:: Comma > ( ) ?;
348
- if !types . empty_or_trailing ( ) {
349
- types . push_punct ( comma) ;
358
+ if !convs . tys . empty_or_trailing ( ) {
359
+ convs . tys . push_punct ( comma) ;
350
360
}
351
361
}
352
362
@@ -379,12 +389,10 @@ impl Parse for ConversionsAttribute {
379
389
_ => {
380
390
let ty = input. parse :: < syn:: Type > ( ) ?;
381
391
let _ = top_level_type. get_or_insert_with ( || ty. clone ( ) ) ;
382
- out. owned . get_or_insert_with ( Punctuated :: new ) . push_value ( ty) ;
392
+ out. owned . tys . push_value ( ty) ;
383
393
384
394
if input. peek ( token:: Comma ) {
385
- out. owned
386
- . get_or_insert_with ( Punctuated :: new)
387
- . push_punct ( input. parse :: < token:: Comma > ( ) ?)
395
+ out. owned . tys . push_punct ( input. parse :: < token:: Comma > ( ) ?)
388
396
}
389
397
}
390
398
}
@@ -411,14 +419,6 @@ impl attr::ParseMultiple for ConversionsAttribute {
411
419
new : Spanning < Self > ,
412
420
_: & syn:: Ident ,
413
421
) -> syn:: Result < Spanning < Self > > {
414
- let merge = |out : & mut Option < _ > , tys| match ( out. as_mut ( ) , tys) {
415
- ( None , Some ( tys) ) => {
416
- * out = Some :: < Punctuated < _ , _ > > ( tys) ;
417
- }
418
- ( Some ( out) , Some ( tys) ) => out. extend ( tys) ,
419
- ( Some ( _) , None ) | ( None , None ) => { }
420
- } ;
421
-
422
422
let Spanning {
423
423
span : prev_span,
424
424
item : mut prev,
@@ -428,9 +428,12 @@ impl attr::ParseMultiple for ConversionsAttribute {
428
428
item : new,
429
429
} = new;
430
430
431
- merge ( & mut prev. owned , new. owned ) ;
432
- merge ( & mut prev. r#ref , new. r#ref ) ;
433
- merge ( & mut prev. ref_mut , new. ref_mut ) ;
431
+ prev. owned . tys . extend ( new. owned . tys ) ;
432
+ prev. owned . consider_fields_ty |= new. owned . consider_fields_ty ;
433
+ prev. r#ref . tys . extend ( new. r#ref . tys ) ;
434
+ prev. r#ref . consider_fields_ty |= new. r#ref . consider_fields_ty ;
435
+ prev. ref_mut . tys . extend ( new. ref_mut . tys ) ;
436
+ prev. ref_mut . consider_fields_ty |= new. ref_mut . consider_fields_ty ;
434
437
435
438
Ok ( Spanning :: new (
436
439
prev,
0 commit comments