1 use proc_macro2
::{Span, TokenStream}
;
4 use internals
::ast
::{Container, Data, Field, Style}
;
6 // Suppress dead_code warnings that would otherwise appear when using a remote
7 // derive. Other than this pretend code, a struct annotated with remote derive
8 // never has its fields referenced and an enum annotated with remote derive
9 // never has its variants constructed.
11 // warning: field is never used: `i`
12 // --> src/main.rs:4:20
14 // 4 | struct StructDef { i: i32 }
17 // warning: variant is never constructed: `V`
18 // --> src/main.rs:8:16
20 // 8 | enum EnumDef { V }
23 pub fn pretend_used(cont
: &Container
) -> TokenStream
{
24 let pretend_fields
= pretend_fields_used(cont
);
25 let pretend_variants
= pretend_variants_used(cont
);
33 // For structs with named fields, expands to:
36 // Some(T { a: ref __v0, b: ref __v1 }) => {}
40 // For enums, expands to the following but only including struct variants:
43 // Some(T::A { a: ref __v0 }) => {}
44 // Some(T::B { b: ref __v0 }) => {}
48 // The `ref` is important in case the user has written a Drop impl on their
49 // type. Rust does not allow destructuring a struct or enum that has a Drop
51 fn pretend_fields_used(cont
: &Container
) -> TokenStream
{
52 let type_ident
= &cont
.ident
;
53 let (_
, ty_generics
, _
) = cont
.generics
.split_for_impl();
55 let patterns
= match &cont
.data
{
56 Data
::Enum(variants
) => variants
58 .filter_map(|variant
| match variant
.style
{
60 let variant_ident
= &variant
.ident
;
61 let pat
= struct_pattern(&variant
.fields
);
62 Some(quote
!(#type_ident::#variant_ident #pat))
67 Data
::Struct(Style
::Struct
, fields
) => {
68 let pat
= struct_pattern(fields
);
69 vec
![quote
!(#type_ident #pat)]
71 Data
::Struct(_
, _
) => {
77 match _serde
::export
::None
::<#type_ident #ty_generics> {
79 _serde
::export
::Some(#patterns) => {}
86 // Expands to one of these per enum variant:
89 // Some((__v0, __v1,)) => {
90 // let _ = E::V { a: __v0, b: __v1 };
95 fn pretend_variants_used(cont
: &Container
) -> TokenStream
{
96 let variants
= match &cont
.data
{
97 Data
::Enum(variants
) => variants
,
98 Data
::Struct(_
, _
) => {
103 let type_ident
= &cont
.ident
;
104 let (_
, ty_generics
, _
) = cont
.generics
.split_for_impl();
105 let turbofish
= ty_generics
.as_turbofish();
107 let cases
= variants
.iter().map(|variant
| {
108 let variant_ident
= &variant
.ident
;
109 let placeholders
= &(0..variant
.fields
.len())
110 .map(|i
| Ident
::new(&format
!("__v{}", i
), Span
::call_site()))
111 .collect
::<Vec
<_
>>();
113 let pat
= match variant
.style
{
115 let members
= variant
.fields
.iter().map(|field
| &field
.member
);
116 quote
!({ #(#members: #placeholders),* }
)
118 Style
::Tuple
| Style
::Newtype
=> quote
!(( #(#placeholders),* )),
119 Style
::Unit
=> quote
!(),
123 match _serde
::export
::None
{
124 _serde
::export
::Some((#(#placeholders,)*)) => {
125 let _
= #type_ident::#variant_ident #turbofish #pat;
135 fn struct_pattern(fields
: &[Field
]) -> TokenStream
{
136 let members
= fields
.iter().map(|field
| &field
.member
);
138 (0..fields
.len()).map(|i
| Ident
::new(&format
!("__v{}", i
), Span
::call_site()));
139 quote
!({ #(#members: ref #placeholders),* }
)