|
1 | 1 | use proc_macro2::TokenStream;
|
2 |
| -use quote::quote; |
| 2 | +use quote::{quote, quote_spanned}; |
3 | 3 | use syn::parse_quote;
|
| 4 | +use syn::spanned::Spanned; |
4 | 5 |
|
5 | 6 | pub fn type_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
|
6 | 7 | let decoder_ty = quote! { __D };
|
@@ -104,27 +105,30 @@ fn decodable_body(
|
104 | 105 | }
|
105 | 106 |
|
106 | 107 | fn decode_field(field: &syn::Field, index: usize, is_struct: bool) -> proc_macro2::TokenStream {
|
| 108 | + let field_span = field.ident.as_ref().map_or(field.ty.span(), |ident| ident.span()); |
| 109 | + |
107 | 110 | let decode_inner_method = if let syn::Type::Reference(_) = field.ty {
|
108 | 111 | quote! { ::rustc_middle::ty::codec::RefDecodable::decode }
|
109 | 112 | } else {
|
110 | 113 | quote! { ::rustc_serialize::Decodable::decode }
|
111 | 114 | };
|
112 | 115 | let (decode_method, opt_field_name) = if is_struct {
|
113 | 116 | let field_name = field.ident.as_ref().map_or_else(|| index.to_string(), |i| i.to_string());
|
114 |
| - ( |
115 |
| - proc_macro2::Ident::new("read_struct_field", proc_macro2::Span::call_site()), |
116 |
| - quote! { #field_name, }, |
117 |
| - ) |
| 117 | + (proc_macro2::Ident::new("read_struct_field", field_span), quote! { #field_name, }) |
118 | 118 | } else {
|
119 |
| - ( |
120 |
| - proc_macro2::Ident::new("read_enum_variant_arg", proc_macro2::Span::call_site()), |
121 |
| - quote! {}, |
122 |
| - ) |
| 119 | + (proc_macro2::Ident::new("read_enum_variant_arg", field_span), quote! {}) |
| 120 | + }; |
| 121 | + |
| 122 | + let __decoder = quote! { __decoder }; |
| 123 | + // Use the span of the field for the method call, so |
| 124 | + // that backtraces will point to the field. |
| 125 | + let decode_call = quote_spanned! {field_span=> |
| 126 | + ::rustc_serialize::Decoder::#decode_method( |
| 127 | + #__decoder, #opt_field_name #decode_inner_method) |
123 | 128 | };
|
124 | 129 |
|
125 | 130 | quote! {
|
126 |
| - match ::rustc_serialize::Decoder::#decode_method( |
127 |
| - __decoder, #opt_field_name #decode_inner_method) { |
| 131 | + match #decode_call { |
128 | 132 | ::std::result::Result::Ok(__res) => __res,
|
129 | 133 | ::std::result::Result::Err(__err) => return ::std::result::Result::Err(__err),
|
130 | 134 | }
|
|
0 commit comments