mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 00:34:06 +00:00
Rollup merge of #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).
This commit is contained in:
commit
fd09f342f3
@ -1,6 +1,7 @@
|
|||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::quote;
|
use quote::{quote, quote_spanned};
|
||||||
use syn::parse_quote;
|
use syn::parse_quote;
|
||||||
|
use syn::spanned::Spanned;
|
||||||
|
|
||||||
pub fn type_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
|
pub fn type_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
|
||||||
let decoder_ty = quote! { __D };
|
let decoder_ty = quote! { __D };
|
||||||
@ -104,6 +105,8 @@ fn decodable_body(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn decode_field(field: &syn::Field, index: usize, is_struct: bool) -> proc_macro2::TokenStream {
|
fn decode_field(field: &syn::Field, index: usize, is_struct: bool) -> proc_macro2::TokenStream {
|
||||||
|
let field_span = field.ident.as_ref().map_or(field.ty.span(), |ident| ident.span());
|
||||||
|
|
||||||
let decode_inner_method = if let syn::Type::Reference(_) = field.ty {
|
let decode_inner_method = if let syn::Type::Reference(_) = field.ty {
|
||||||
quote! { ::rustc_middle::ty::codec::RefDecodable::decode }
|
quote! { ::rustc_middle::ty::codec::RefDecodable::decode }
|
||||||
} else {
|
} else {
|
||||||
@ -111,20 +114,21 @@ fn decode_field(field: &syn::Field, index: usize, is_struct: bool) -> proc_macro
|
|||||||
};
|
};
|
||||||
let (decode_method, opt_field_name) = if is_struct {
|
let (decode_method, opt_field_name) = if is_struct {
|
||||||
let field_name = field.ident.as_ref().map_or_else(|| index.to_string(), |i| i.to_string());
|
let field_name = field.ident.as_ref().map_or_else(|| index.to_string(), |i| i.to_string());
|
||||||
(
|
(proc_macro2::Ident::new("read_struct_field", field_span), quote! { #field_name, })
|
||||||
proc_macro2::Ident::new("read_struct_field", proc_macro2::Span::call_site()),
|
|
||||||
quote! { #field_name, },
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
(
|
(proc_macro2::Ident::new("read_enum_variant_arg", field_span), quote! {})
|
||||||
proc_macro2::Ident::new("read_enum_variant_arg", proc_macro2::Span::call_site()),
|
};
|
||||||
quote! {},
|
|
||||||
)
|
let __decoder = quote! { __decoder };
|
||||||
|
// Use the span of the field for the method call, so
|
||||||
|
// that backtraces will point to the field.
|
||||||
|
let decode_call = quote_spanned! {field_span=>
|
||||||
|
::rustc_serialize::Decoder::#decode_method(
|
||||||
|
#__decoder, #opt_field_name #decode_inner_method)
|
||||||
};
|
};
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
match ::rustc_serialize::Decoder::#decode_method(
|
match #decode_call {
|
||||||
__decoder, #opt_field_name #decode_inner_method) {
|
|
||||||
::std::result::Result::Ok(__res) => __res,
|
::std::result::Result::Ok(__res) => __res,
|
||||||
::std::result::Result::Err(__err) => return ::std::result::Result::Err(__err),
|
::std::result::Result::Err(__err) => return ::std::result::Result::Err(__err),
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user