]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_macros/src/serialize.rs
bump version to 1.80.1+dfsg1-1~bpo12+pve1
[rustc.git] / compiler / rustc_macros / src / serialize.rs
CommitLineData
3dfed10e 1use proc_macro2::TokenStream;
a2a8927a 2use quote::{quote, quote_spanned};
3dfed10e 3use syn::parse_quote;
a2a8927a 4use syn::spanned::Spanned;
3dfed10e
XL
5
6pub fn type_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
7 let decoder_ty = quote! { __D };
ed00b5ec
FG
8 let bound = if s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
9 quote! { <I = ::rustc_middle::ty::TyCtxt<'tcx>> }
10 } else if s.ast().generics.type_params().any(|ty| ty.ident == "I") {
11 quote! { <I = I> }
12 } else {
13 quote! {}
14 };
15
31ef2f64 16 s.add_impl_generic(parse_quote! { #decoder_ty: ::rustc_type_ir::codec::TyDecoder #bound });
ed00b5ec 17 s.add_bounds(synstructure::AddBounds::Fields);
c620b35d 18 s.underscore_const(true);
3dfed10e
XL
19
20 decodable_body(s, decoder_ty)
21}
22
23pub fn meta_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
24 if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
25 s.add_impl_generic(parse_quote! { 'tcx });
26 }
27 s.add_impl_generic(parse_quote! { '__a });
28 let decoder_ty = quote! { DecodeContext<'__a, 'tcx> };
29 s.add_bounds(synstructure::AddBounds::Generics);
c620b35d 30 s.underscore_const(true);
3dfed10e
XL
31
32 decodable_body(s, decoder_ty)
33}
34
35pub fn decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
c0240ec0 36 let decoder_ty = quote! { __D };
31ef2f64 37 s.add_impl_generic(parse_quote! { #decoder_ty: ::rustc_span::SpanDecoder });
c0240ec0 38 s.add_bounds(synstructure::AddBounds::Generics);
c620b35d 39 s.underscore_const(true);
c0240ec0
FG
40
41 decodable_body(s, decoder_ty)
42}
43
44pub fn decodable_generic_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
3dfed10e 45 let decoder_ty = quote! { __D };
31ef2f64 46 s.add_impl_generic(parse_quote! { #decoder_ty: ::rustc_serialize::Decoder });
3dfed10e 47 s.add_bounds(synstructure::AddBounds::Generics);
c620b35d 48 s.underscore_const(true);
3dfed10e
XL
49
50 decodable_body(s, decoder_ty)
51}
52
53fn decodable_body(
c620b35d 54 mut s: synstructure::Structure<'_>,
3dfed10e
XL
55 decoder_ty: TokenStream,
56) -> proc_macro2::TokenStream {
57 if let syn::Data::Union(_) = s.ast().data {
58 panic!("cannot derive on union")
59 }
60 let ty_name = s.ast().ident.to_string();
61 let decode_body = match s.variants() {
9ffffee4 62 [] => {
add651ee 63 let message = format!("`{ty_name}` has no variants to decode");
9ffffee4
FG
64 quote! {
65 panic!(#message)
66 }
67 }
5e7ed085 68 [vi] => vi.construct(|field, _index| decode_field(field)),
3dfed10e
XL
69 variants => {
70 let match_inner: TokenStream = variants
71 .iter()
72 .enumerate()
73 .map(|(idx, vi)| {
5e7ed085 74 let construct = vi.construct(|field, _index| decode_field(field));
5099ac24 75 quote! { #idx => { #construct } }
3dfed10e
XL
76 })
77 .collect();
3dfed10e 78 let message = format!(
add651ee 79 "invalid enum variant tag while decoding `{}`, expected 0..{}, actual {{}}",
3dfed10e
XL
80 ty_name,
81 variants.len()
82 );
c0240ec0
FG
83 let tag = if variants.len() < u8::MAX as usize {
84 quote! {
85 ::rustc_serialize::Decoder::read_u8(__decoder) as usize
86 }
87 } else {
88 quote! {
89 ::rustc_serialize::Decoder::read_usize(__decoder)
90 }
91 };
3dfed10e 92 quote! {
c0240ec0 93 match #tag {
5e7ed085 94 #match_inner
add651ee 95 n => panic!(#message, n),
5e7ed085 96 }
3dfed10e
XL
97 }
98 }
99 };
c620b35d 100 s.underscore_const(true);
3dfed10e
XL
101
102 s.bound_impl(
103 quote!(::rustc_serialize::Decodable<#decoder_ty>),
104 quote! {
5099ac24 105 fn decode(__decoder: &mut #decoder_ty) -> Self {
3dfed10e
XL
106 #decode_body
107 }
108 },
109 )
110}
111
5e7ed085 112fn decode_field(field: &syn::Field) -> proc_macro2::TokenStream {
a2a8927a
XL
113 let field_span = field.ident.as_ref().map_or(field.ty.span(), |ident| ident.span());
114
3dfed10e
XL
115 let decode_inner_method = if let syn::Type::Reference(_) = field.ty {
116 quote! { ::rustc_middle::ty::codec::RefDecodable::decode }
117 } else {
118 quote! { ::rustc_serialize::Decodable::decode }
119 };
a2a8927a
XL
120 let __decoder = quote! { __decoder };
121 // Use the span of the field for the method call, so
122 // that backtraces will point to the field.
31ef2f64 123 quote_spanned! { field_span=> #decode_inner_method(#__decoder) }
3dfed10e
XL
124}
125
126pub fn type_encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
ed00b5ec
FG
127 let bound = if s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
128 quote! { <I = ::rustc_middle::ty::TyCtxt<'tcx>> }
129 } else if s.ast().generics.type_params().any(|ty| ty.ident == "I") {
130 quote! { <I = I> }
131 } else {
132 quote! {}
133 };
134
3dfed10e 135 let encoder_ty = quote! { __E };
31ef2f64 136 s.add_impl_generic(parse_quote! { #encoder_ty: ::rustc_type_ir::codec::TyEncoder #bound });
ed00b5ec 137 s.add_bounds(synstructure::AddBounds::Fields);
c620b35d 138 s.underscore_const(true);
3dfed10e
XL
139
140 encodable_body(s, encoder_ty, false)
141}
142
143pub fn meta_encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
144 if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
31ef2f64 145 s.add_impl_generic(parse_quote! { 'tcx });
3dfed10e
XL
146 }
147 s.add_impl_generic(parse_quote! { '__a });
148 let encoder_ty = quote! { EncodeContext<'__a, 'tcx> };
149 s.add_bounds(synstructure::AddBounds::Generics);
c620b35d 150 s.underscore_const(true);
3dfed10e
XL
151
152 encodable_body(s, encoder_ty, true)
153}
154
155pub fn encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
c0240ec0 156 let encoder_ty = quote! { __E };
31ef2f64 157 s.add_impl_generic(parse_quote! { #encoder_ty: ::rustc_span::SpanEncoder });
c0240ec0 158 s.add_bounds(synstructure::AddBounds::Generics);
c620b35d 159 s.underscore_const(true);
c0240ec0
FG
160
161 encodable_body(s, encoder_ty, false)
162}
163
164pub fn encodable_generic_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
3dfed10e 165 let encoder_ty = quote! { __E };
31ef2f64 166 s.add_impl_generic(parse_quote! { #encoder_ty: ::rustc_serialize::Encoder });
3dfed10e 167 s.add_bounds(synstructure::AddBounds::Generics);
c620b35d 168 s.underscore_const(true);
3dfed10e
XL
169
170 encodable_body(s, encoder_ty, false)
171}
172
173fn encodable_body(
174 mut s: synstructure::Structure<'_>,
175 encoder_ty: TokenStream,
176 allow_unreachable_code: bool,
177) -> proc_macro2::TokenStream {
178 if let syn::Data::Union(_) = s.ast().data {
179 panic!("cannot derive on union")
180 }
181
c620b35d 182 s.underscore_const(true);
3dfed10e
XL
183 s.bind_with(|binding| {
184 // Handle the lack of a blanket reference impl.
185 if let syn::Type::Reference(_) = binding.ast().ty {
186 synstructure::BindStyle::Move
187 } else {
188 synstructure::BindStyle::Ref
189 }
190 });
191
3dfed10e 192 let encode_body = match s.variants() {
9ffffee4
FG
193 [] => {
194 quote! {
195 match *self {}
196 }
197 }
3dfed10e 198 [_] => {
3dfed10e
XL
199 let encode_inner = s.each_variant(|vi| {
200 vi.bindings()
201 .iter()
202 .map(|binding| {
203 let bind_ident = &binding.binding;
3dfed10e 204 let result = quote! {
923072b8
FG
205 ::rustc_serialize::Encodable::<#encoder_ty>::encode(
206 #bind_ident,
3dfed10e 207 __encoder,
923072b8 208 );
3dfed10e 209 };
3dfed10e
XL
210 result
211 })
212 .collect::<TokenStream>()
213 });
214 quote! {
923072b8 215 match *self { #encode_inner }
3dfed10e
XL
216 }
217 }
218 _ => {
9ffffee4
FG
219 let disc = {
220 let mut variant_idx = 0usize;
221 let encode_inner = s.each_variant(|_| {
222 let result = quote! {
223 #variant_idx
224 };
225 variant_idx += 1;
226 result
227 });
c0240ec0
FG
228 if variant_idx < u8::MAX as usize {
229 quote! {
230 let disc = match *self {
231 #encode_inner
232 };
233 ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
234 }
235 } else {
236 quote! {
237 let disc = match *self {
238 #encode_inner
239 };
240 ::rustc_serialize::Encoder::emit_usize(__encoder, disc);
241 }
9ffffee4
FG
242 }
243 };
244
3dfed10e
XL
245 let mut variant_idx = 0usize;
246 let encode_inner = s.each_variant(|vi| {
3dfed10e
XL
247 let encode_fields: TokenStream = vi
248 .bindings()
249 .iter()
250 .map(|binding| {
251 let bind_ident = &binding.binding;
252 let result = quote! {
923072b8
FG
253 ::rustc_serialize::Encodable::<#encoder_ty>::encode(
254 #bind_ident,
3dfed10e 255 __encoder,
923072b8 256 );
3dfed10e 257 };
3dfed10e
XL
258 result
259 })
260 .collect();
3dfed10e 261 variant_idx += 1;
9ffffee4 262 encode_fields
3dfed10e
XL
263 });
264 quote! {
9ffffee4 265 #disc
923072b8
FG
266 match *self {
267 #encode_inner
268 }
3dfed10e
XL
269 }
270 }
271 };
272
273 let lints = if allow_unreachable_code {
274 quote! { #![allow(unreachable_code)] }
275 } else {
276 quote! {}
277 };
278
279 s.bound_impl(
280 quote!(::rustc_serialize::Encodable<#encoder_ty>),
281 quote! {
282 fn encode(
283 &self,
284 __encoder: &mut #encoder_ty,
923072b8 285 ) {
3dfed10e
XL
286 #lints
287 #encode_body
288 }
289 },
290 )
291}