]> git.proxmox.com Git - rustc.git/blame - vendor/serde_derive/src/pretend.rs
New upstream version 1.59.0+dfsg1
[rustc.git] / vendor / serde_derive / src / pretend.rs
CommitLineData
c295e0f8
XL
1use proc_macro2::TokenStream;
2use quote::format_ident;
8faf50e0 3
c295e0f8 4use internals::ast::{Container, Data, Field, Style, Variant};
8faf50e0
XL
5
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.
10//
11// warning: field is never used: `i`
12// --> src/main.rs:4:20
13// |
14// 4 | struct StructDef { i: i32 }
15// | ^^^^^^
16//
17// warning: variant is never constructed: `V`
18// --> src/main.rs:8:16
19// |
20// 8 | enum EnumDef { V }
21// | ^
22//
c295e0f8
XL
23pub fn pretend_used(cont: &Container, is_packed: bool) -> TokenStream {
24 let pretend_fields = pretend_fields_used(cont, is_packed);
8faf50e0
XL
25 let pretend_variants = pretend_variants_used(cont);
26
27 quote! {
28 #pretend_fields
29 #pretend_variants
30 }
31}
32
33// For structs with named fields, expands to:
34//
c295e0f8
XL
35// match None::<&T> {
36// Some(T { a: __v0, b: __v1 }) => {}
37// _ => {}
38// }
39//
40// For packed structs on sufficiently new rustc, expands to:
41//
42// match None::<&T> {
43// Some(__v @ T { a: _, b: _ }) => {
44// let _ = addr_of!(__v.a);
45// let _ = addr_of!(__v.b);
46// }
47// _ => {}
48// }
49//
50// For packed structs on older rustc, we assume Sized and !Drop, and expand to:
51//
8faf50e0 52// match None::<T> {
c295e0f8 53// Some(T { a: __v0, b: __v1 }) => {}
8faf50e0
XL
54// _ => {}
55// }
56//
57// For enums, expands to the following but only including struct variants:
58//
c295e0f8
XL
59// match None::<&T> {
60// Some(T::A { a: __v0 }) => {}
61// Some(T::B { b: __v0 }) => {}
8faf50e0
XL
62// _ => {}
63// }
64//
c295e0f8
XL
65fn pretend_fields_used(cont: &Container, is_packed: bool) -> TokenStream {
66 match &cont.data {
67 Data::Enum(variants) => pretend_fields_used_enum(cont, variants),
a2a8927a
XL
68 Data::Struct(Style::Struct, fields) => {
69 if is_packed {
70 pretend_fields_used_struct_packed(cont, fields)
71 } else {
72 pretend_fields_used_struct(cont, fields)
73 }
74 }
c295e0f8
XL
75 Data::Struct(_, _) => quote!(),
76 }
77}
78
79fn pretend_fields_used_struct(cont: &Container, fields: &[Field]) -> TokenStream {
8faf50e0
XL
80 let type_ident = &cont.ident;
81 let (_, ty_generics, _) = cont.generics.split_for_impl();
82
c295e0f8
XL
83 let members = fields.iter().map(|field| &field.member);
84 let placeholders = (0usize..).map(|i| format_ident!("__v{}", i));
85
86 quote! {
87 match _serde::__private::None::<&#type_ident #ty_generics> {
88 _serde::__private::Some(#type_ident { #(#members: #placeholders),* }) => {}
89 _ => {}
90 }
91 }
92}
93
94fn pretend_fields_used_struct_packed(cont: &Container, fields: &[Field]) -> TokenStream {
95 let type_ident = &cont.ident;
96 let (_, ty_generics, _) = cont.generics.split_for_impl();
97
98 let members = fields.iter().map(|field| &field.member).collect::<Vec<_>>();
99
100 #[cfg(ptr_addr_of)]
101 {
102 quote! {
103 match _serde::__private::None::<&#type_ident #ty_generics> {
104 _serde::__private::Some(__v @ #type_ident { #(#members: _),* }) => {
105 #(
106 let _ = _serde::__private::ptr::addr_of!(__v.#members);
107 )*
8faf50e0 108 }
c295e0f8
XL
109 _ => {}
110 }
8faf50e0 111 }
c295e0f8
XL
112 }
113
114 #[cfg(not(ptr_addr_of))]
115 {
116 let placeholders = (0usize..).map(|i| format_ident!("__v{}", i));
117
118 quote! {
119 match _serde::__private::None::<#type_ident #ty_generics> {
120 _serde::__private::Some(#type_ident { #(#members: #placeholders),* }) => {}
121 _ => {}
122 }
8faf50e0 123 }
c295e0f8
XL
124 }
125}
126
127fn pretend_fields_used_enum(cont: &Container, variants: &[Variant]) -> TokenStream {
128 let type_ident = &cont.ident;
129 let (_, ty_generics, _) = cont.generics.split_for_impl();
130
131 let patterns = variants
132 .iter()
133 .filter_map(|variant| match variant.style {
134 Style::Struct => {
135 let variant_ident = &variant.ident;
136 let members = variant.fields.iter().map(|field| &field.member);
137 let placeholders = (0usize..).map(|i| format_ident!("__v{}", i));
138 Some(quote!(#type_ident::#variant_ident { #(#members: #placeholders),* }))
139 }
140 _ => None,
141 })
142 .collect::<Vec<_>>();
8faf50e0
XL
143
144 quote! {
c295e0f8 145 match _serde::__private::None::<&#type_ident #ty_generics> {
8faf50e0 146 #(
5869c6ff 147 _serde::__private::Some(#patterns) => {}
8faf50e0
XL
148 )*
149 _ => {}
150 }
151 }
152}
153
154// Expands to one of these per enum variant:
155//
156// match None {
157// Some((__v0, __v1,)) => {
158// let _ = E::V { a: __v0, b: __v1 };
159// }
160// _ => {}
161// }
162//
163fn pretend_variants_used(cont: &Container) -> TokenStream {
f9f354fc
XL
164 let variants = match &cont.data {
165 Data::Enum(variants) => variants,
8faf50e0
XL
166 Data::Struct(_, _) => {
167 return quote!();
168 }
169 };
170
171 let type_ident = &cont.ident;
172 let (_, ty_generics, _) = cont.generics.split_for_impl();
173 let turbofish = ty_generics.as_turbofish();
174
175 let cases = variants.iter().map(|variant| {
176 let variant_ident = &variant.ident;
177 let placeholders = &(0..variant.fields.len())
c295e0f8 178 .map(|i| format_ident!("__v{}", i))
8faf50e0
XL
179 .collect::<Vec<_>>();
180
181 let pat = match variant.style {
182 Style::Struct => {
183 let members = variant.fields.iter().map(|field| &field.member);
184 quote!({ #(#members: #placeholders),* })
185 }
186 Style::Tuple | Style::Newtype => quote!(( #(#placeholders),* )),
187 Style::Unit => quote!(),
188 };
189
190 quote! {
5869c6ff
XL
191 match _serde::__private::None {
192 _serde::__private::Some((#(#placeholders,)*)) => {
8faf50e0
XL
193 let _ = #type_ident::#variant_ident #turbofish #pat;
194 }
195 _ => {}
196 }
197 }
198 });
199
200 quote!(#(#cases)*)
201}