1 use proc_macro2::TokenStream;
2 use quote::{quote, quote_spanned};
4 use syn::spanned::Spanned;
6 pub fn type_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
7 let decoder_ty = quote! { __D };
8 if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
9 s.add_impl_generic(parse_quote! { 'tcx });
11 s.add_impl_generic(parse_quote! {#decoder_ty: ::rustc_middle::ty::codec::TyDecoder<'tcx>});
12 s.add_bounds(synstructure::AddBounds::Generics);
14 decodable_body(s, decoder_ty)
17 pub fn meta_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
18 if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
19 s.add_impl_generic(parse_quote! { 'tcx });
21 s.add_impl_generic(parse_quote! { '__a });
22 let decoder_ty = quote! { DecodeContext<'__a, 'tcx> };
23 s.add_bounds(synstructure::AddBounds::Generics);
25 decodable_body(s, decoder_ty)
28 pub fn decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
29 let decoder_ty = quote! { __D };
30 s.add_impl_generic(parse_quote! {#decoder_ty: ::rustc_serialize::Decoder});
31 s.add_bounds(synstructure::AddBounds::Generics);
33 decodable_body(s, decoder_ty)
37 s: synstructure::Structure<'_>,
38 decoder_ty: TokenStream,
39 ) -> proc_macro2::TokenStream {
40 if let syn::Data::Union(_) = s.ast().data {
41 panic!("cannot derive on union")
43 let ty_name = s.ast().ident.to_string();
44 let decode_body = match s.variants() {
45 [vi] => vi.construct(|field, _index| decode_field(field)),
47 let match_inner: TokenStream = variants
51 let construct = vi.construct(|field, _index| decode_field(field));
52 quote! { #idx => { #construct } }
55 let message = format!(
56 "invalid enum variant tag while decoding `{}`, expected 0..{}",
61 ::rustc_serialize::Decoder::read_enum_variant(
63 |__decoder, __variant_idx| {
66 _ => panic!(#message),
74 quote!(::rustc_serialize::Decodable<#decoder_ty>),
76 fn decode(__decoder: &mut #decoder_ty) -> Self {
83 fn decode_field(field: &syn::Field) -> proc_macro2::TokenStream {
84 let field_span = field.ident.as_ref().map_or(field.ty.span(), |ident| ident.span());
86 let decode_inner_method = if let syn::Type::Reference(_) = field.ty {
87 quote! { ::rustc_middle::ty::codec::RefDecodable::decode }
89 quote! { ::rustc_serialize::Decodable::decode }
91 let __decoder = quote! { __decoder };
92 // Use the span of the field for the method call, so
93 // that backtraces will point to the field.
94 quote_spanned! {field_span=> #decode_inner_method(#__decoder) }
97 pub fn type_encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
98 if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
99 s.add_impl_generic(parse_quote! {'tcx});
101 let encoder_ty = quote! { __E };
102 s.add_impl_generic(parse_quote! {#encoder_ty: ::rustc_middle::ty::codec::TyEncoder<'tcx>});
103 s.add_bounds(synstructure::AddBounds::Generics);
105 encodable_body(s, encoder_ty, false)
108 pub fn meta_encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
109 if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
110 s.add_impl_generic(parse_quote! {'tcx});
112 s.add_impl_generic(parse_quote! { '__a });
113 let encoder_ty = quote! { EncodeContext<'__a, 'tcx> };
114 s.add_bounds(synstructure::AddBounds::Generics);
116 encodable_body(s, encoder_ty, true)
119 pub fn encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
120 let encoder_ty = quote! { __E };
121 s.add_impl_generic(parse_quote! { #encoder_ty: ::rustc_serialize::Encoder});
122 s.add_bounds(synstructure::AddBounds::Generics);
124 encodable_body(s, encoder_ty, false)
128 mut s: synstructure::Structure<'_>,
129 encoder_ty: TokenStream,
130 allow_unreachable_code: bool,
131 ) -> proc_macro2::TokenStream {
132 if let syn::Data::Union(_) = s.ast().data {
133 panic!("cannot derive on union")
136 s.bind_with(|binding| {
137 // Handle the lack of a blanket reference impl.
138 if let syn::Type::Reference(_) = binding.ast().ty {
139 synstructure::BindStyle::Move
141 synstructure::BindStyle::Ref
145 let encode_body = match s.variants() {
147 let mut field_idx = 0usize;
148 let encode_inner = s.each_variant(|vi| {
152 let bind_ident = &binding.binding;
153 let field_name = binding
157 .map_or_else(|| field_idx.to_string(), |i| i.to_string());
158 let first = field_idx == 0;
159 let result = quote! {
160 match ::rustc_serialize::Encoder::emit_struct_field(
165 ::rustc_serialize::Encodable::<#encoder_ty>::encode(#bind_ident, __encoder),
167 ::std::result::Result::Ok(()) => (),
168 ::std::result::Result::Err(__err)
169 => return ::std::result::Result::Err(__err),
175 .collect::<TokenStream>()
177 let no_fields = field_idx == 0;
179 ::rustc_serialize::Encoder::emit_struct(__encoder, #no_fields, |__encoder| {
180 ::std::result::Result::Ok(match *self { #encode_inner })
185 let mut variant_idx = 0usize;
186 let encode_inner = s.each_variant(|vi| {
187 let variant_name = vi.ast().ident.to_string();
188 let mut field_idx = 0usize;
190 let encode_fields: TokenStream = vi
194 let bind_ident = &binding.binding;
195 let first = field_idx == 0;
196 let result = quote! {
197 match ::rustc_serialize::Encoder::emit_enum_variant_arg(
201 ::rustc_serialize::Encodable::<#encoder_ty>::encode(#bind_ident, __encoder),
203 ::std::result::Result::Ok(()) => (),
204 ::std::result::Result::Err(__err)
205 => return ::std::result::Result::Err(__err),
213 let result = if field_idx != 0 {
215 ::rustc_serialize::Encoder::emit_enum_variant(
220 |__encoder| { ::std::result::Result::Ok({ #encode_fields }) }
225 ::rustc_serialize::Encoder::emit_fieldless_enum_variant::<#variant_idx>(
235 ::rustc_serialize::Encoder::emit_enum(__encoder, |__encoder| {
244 let lints = if allow_unreachable_code {
245 quote! { #![allow(unreachable_code)] }
251 quote!(::rustc_serialize::Encodable<#encoder_ty>),
255 __encoder: &mut #encoder_ty,
256 ) -> ::std::result::Result<(), <#encoder_ty as ::rustc_serialize::Encoder>::Error> {