Skip to content

Commit fd09f34

Browse files
authored
Rollup merge of rust-lang#92011 - Aaron1011:decode-span, r=michaelwoerister
Use field span in `rustc_macros` when emitting decode call This will cause backtraces to point to the location of the field in the struct/enum, rather than the derive macro. This makes it clear which field was being decoded when the backtrace was captured (which is especially useful if there are multiple fields with the same type).
2 parents 57a4f4a + 44fdb98 commit fd09f34

File tree

1 file changed

+15
-11
lines changed

1 file changed

+15
-11
lines changed

compiler/rustc_macros/src/serialize.rs

+15-11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use proc_macro2::TokenStream;
2-
use quote::quote;
2+
use quote::{quote, quote_spanned};
33
use syn::parse_quote;
4+
use syn::spanned::Spanned;
45

56
pub fn type_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
67
let decoder_ty = quote! { __D };
@@ -104,27 +105,30 @@ fn decodable_body(
104105
}
105106

106107
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+
107110
let decode_inner_method = if let syn::Type::Reference(_) = field.ty {
108111
quote! { ::rustc_middle::ty::codec::RefDecodable::decode }
109112
} else {
110113
quote! { ::rustc_serialize::Decodable::decode }
111114
};
112115
let (decode_method, opt_field_name) = if is_struct {
113116
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, })
118118
} 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)
123128
};
124129

125130
quote! {
126-
match ::rustc_serialize::Decoder::#decode_method(
127-
__decoder, #opt_field_name #decode_inner_method) {
131+
match #decode_call {
128132
::std::result::Result::Ok(__res) => __res,
129133
::std::result::Result::Err(__err) => return ::std::result::Result::Err(__err),
130134
}

0 commit comments

Comments
 (0)