Fix parsing of qself in paths in attributes

This commit is contained in:
David Tolnay
2018-03-15 10:02:40 -07:00
parent 23c6eb3b40
commit 72ecb9064c
4 changed files with 57 additions and 35 deletions
+3 -3
View File
@@ -2273,7 +2273,7 @@ fn field_i(i: usize) -> Ident {
fn wrap_deserialize_with( fn wrap_deserialize_with(
params: &Parameters, params: &Parameters,
value_ty: &Tokens, value_ty: &Tokens,
deserialize_with: &syn::Path, deserialize_with: &syn::ExprPath,
) -> (Tokens, Tokens) { ) -> (Tokens, Tokens) {
let this = &params.this; let this = &params.this;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
@@ -2308,7 +2308,7 @@ fn wrap_deserialize_with(
fn wrap_deserialize_field_with( fn wrap_deserialize_field_with(
params: &Parameters, params: &Parameters,
field_ty: &syn::Type, field_ty: &syn::Type,
deserialize_with: &syn::Path, deserialize_with: &syn::ExprPath,
) -> (Tokens, Tokens) { ) -> (Tokens, Tokens) {
wrap_deserialize_with(params, &quote!(#field_ty), deserialize_with) wrap_deserialize_with(params, &quote!(#field_ty), deserialize_with)
} }
@@ -2316,7 +2316,7 @@ fn wrap_deserialize_field_with(
fn wrap_deserialize_variant_with( fn wrap_deserialize_variant_with(
params: &Parameters, params: &Parameters,
variant: &Variant, variant: &Variant,
deserialize_with: &syn::Path, deserialize_with: &syn::ExprPath,
) -> (Tokens, Tokens, Tokens) { ) -> (Tokens, Tokens, Tokens) {
let this = &params.this; let this = &params.this;
let variant_ident = &variant.ident; let variant_ident = &variant.ident;
+3 -3
View File
@@ -902,7 +902,7 @@ fn serialize_struct_visitor(
fn wrap_serialize_field_with( fn wrap_serialize_field_with(
params: &Parameters, params: &Parameters,
field_ty: &syn::Type, field_ty: &syn::Type,
serialize_with: &syn::Path, serialize_with: &syn::ExprPath,
field_expr: &Tokens, field_expr: &Tokens,
) -> Tokens { ) -> Tokens {
wrap_serialize_with(params, serialize_with, &[field_ty], &[quote!(#field_expr)]) wrap_serialize_with(params, serialize_with, &[field_ty], &[quote!(#field_expr)])
@@ -910,7 +910,7 @@ fn wrap_serialize_field_with(
fn wrap_serialize_variant_with( fn wrap_serialize_variant_with(
params: &Parameters, params: &Parameters,
serialize_with: &syn::Path, serialize_with: &syn::ExprPath,
variant: &Variant, variant: &Variant,
) -> Tokens { ) -> Tokens {
let field_tys: Vec<_> = variant.fields.iter().map(|field| field.ty).collect(); let field_tys: Vec<_> = variant.fields.iter().map(|field| field.ty).collect();
@@ -935,7 +935,7 @@ fn wrap_serialize_variant_with(
fn wrap_serialize_with( fn wrap_serialize_with(
params: &Parameters, params: &Parameters,
serialize_with: &syn::Path, serialize_with: &syn::ExprPath,
field_tys: &[&syn::Type], field_tys: &[&syn::Type],
field_exprs: &[Tokens], field_exprs: &[Tokens],
) -> Tokens { ) -> Tokens {
+44 -29
View File
@@ -243,7 +243,7 @@ impl Container {
// Parse `#[serde(default = "...")]` // Parse `#[serde(default = "...")]`
Meta(NameValue(ref m)) if m.ident == "default" => { Meta(NameValue(ref m)) if m.ident == "default" => {
if let Ok(path) = parse_lit_into_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
match item.data { match item.data {
syn::Data::Struct(syn::DataStruct { fields: syn::Fields::Named(_), .. }) => { syn::Data::Struct(syn::DataStruct { fields: syn::Fields::Named(_), .. }) => {
default.set(Default::Path(path)); default.set(Default::Path(path));
@@ -510,8 +510,8 @@ pub struct Variant {
skip_deserializing: bool, skip_deserializing: bool,
skip_serializing: bool, skip_serializing: bool,
other: bool, other: bool,
serialize_with: Option<syn::Path>, serialize_with: Option<syn::ExprPath>,
deserialize_with: Option<syn::Path>, deserialize_with: Option<syn::ExprPath>,
borrow: Option<syn::Meta>, borrow: Option<syn::Meta>,
} }
@@ -577,26 +577,26 @@ impl Variant {
// Parse `#[serde(with = "...")]` // Parse `#[serde(with = "...")]`
Meta(NameValue(ref m)) if m.ident == "with" => { Meta(NameValue(ref m)) if m.ident == "with" => {
if let Ok(path) = parse_lit_into_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
let mut ser_path = path.clone(); let mut ser_path = path.clone();
ser_path.segments.push(Ident::new("serialize", Span::call_site()).into()); ser_path.path.segments.push(Ident::new("serialize", Span::call_site()).into());
serialize_with.set(ser_path); serialize_with.set(ser_path);
let mut de_path = path; let mut de_path = path;
de_path.segments.push(Ident::new("deserialize", Span::call_site()).into()); de_path.path.segments.push(Ident::new("deserialize", Span::call_site()).into());
deserialize_with.set(de_path); deserialize_with.set(de_path);
} }
} }
// Parse `#[serde(serialize_with = "...")]` // Parse `#[serde(serialize_with = "...")]`
Meta(NameValue(ref m)) if m.ident == "serialize_with" => { Meta(NameValue(ref m)) if m.ident == "serialize_with" => {
if let Ok(path) = parse_lit_into_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
serialize_with.set(path); serialize_with.set(path);
} }
} }
// Parse `#[serde(deserialize_with = "...")]` // Parse `#[serde(deserialize_with = "...")]`
Meta(NameValue(ref m)) if m.ident == "deserialize_with" => { Meta(NameValue(ref m)) if m.ident == "deserialize_with" => {
if let Ok(path) = parse_lit_into_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
deserialize_with.set(path); deserialize_with.set(path);
} }
} }
@@ -675,11 +675,11 @@ impl Variant {
self.other self.other
} }
pub fn serialize_with(&self) -> Option<&syn::Path> { pub fn serialize_with(&self) -> Option<&syn::ExprPath> {
self.serialize_with.as_ref() self.serialize_with.as_ref()
} }
pub fn deserialize_with(&self) -> Option<&syn::Path> { pub fn deserialize_with(&self) -> Option<&syn::ExprPath> {
self.deserialize_with.as_ref() self.deserialize_with.as_ref()
} }
} }
@@ -691,14 +691,14 @@ pub struct Field {
de_renamed: bool, de_renamed: bool,
skip_serializing: bool, skip_serializing: bool,
skip_deserializing: bool, skip_deserializing: bool,
skip_serializing_if: Option<syn::Path>, skip_serializing_if: Option<syn::ExprPath>,
default: Default, default: Default,
serialize_with: Option<syn::Path>, serialize_with: Option<syn::ExprPath>,
deserialize_with: Option<syn::Path>, deserialize_with: Option<syn::ExprPath>,
ser_bound: Option<Vec<syn::WherePredicate>>, ser_bound: Option<Vec<syn::WherePredicate>>,
de_bound: Option<Vec<syn::WherePredicate>>, de_bound: Option<Vec<syn::WherePredicate>>,
borrowed_lifetimes: BTreeSet<syn::Lifetime>, borrowed_lifetimes: BTreeSet<syn::Lifetime>,
getter: Option<syn::Path>, getter: Option<syn::ExprPath>,
} }
/// Represents the default to use for a field when deserializing. /// Represents the default to use for a field when deserializing.
@@ -708,7 +708,7 @@ pub enum Default {
/// The default is given by `std::default::Default::default()`. /// The default is given by `std::default::Default::default()`.
Default, Default,
/// The default is given by this function. /// The default is given by this function.
Path(syn::Path), Path(syn::ExprPath),
} }
impl Field { impl Field {
@@ -775,7 +775,7 @@ impl Field {
// Parse `#[serde(default = "...")]` // Parse `#[serde(default = "...")]`
Meta(NameValue(ref m)) if m.ident == "default" => { Meta(NameValue(ref m)) if m.ident == "default" => {
if let Ok(path) = parse_lit_into_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
default.set(Default::Path(path)); default.set(Default::Path(path));
} }
} }
@@ -798,33 +798,33 @@ impl Field {
// Parse `#[serde(skip_serializing_if = "...")]` // Parse `#[serde(skip_serializing_if = "...")]`
Meta(NameValue(ref m)) if m.ident == "skip_serializing_if" => { Meta(NameValue(ref m)) if m.ident == "skip_serializing_if" => {
if let Ok(path) = parse_lit_into_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
skip_serializing_if.set(path); skip_serializing_if.set(path);
} }
} }
// Parse `#[serde(serialize_with = "...")]` // Parse `#[serde(serialize_with = "...")]`
Meta(NameValue(ref m)) if m.ident == "serialize_with" => { Meta(NameValue(ref m)) if m.ident == "serialize_with" => {
if let Ok(path) = parse_lit_into_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
serialize_with.set(path); serialize_with.set(path);
} }
} }
// Parse `#[serde(deserialize_with = "...")]` // Parse `#[serde(deserialize_with = "...")]`
Meta(NameValue(ref m)) if m.ident == "deserialize_with" => { Meta(NameValue(ref m)) if m.ident == "deserialize_with" => {
if let Ok(path) = parse_lit_into_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
deserialize_with.set(path); deserialize_with.set(path);
} }
} }
// Parse `#[serde(with = "...")]` // Parse `#[serde(with = "...")]`
Meta(NameValue(ref m)) if m.ident == "with" => { Meta(NameValue(ref m)) if m.ident == "with" => {
if let Ok(path) = parse_lit_into_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
let mut ser_path = path.clone(); let mut ser_path = path.clone();
ser_path.segments.push(Ident::new("serialize", Span::call_site()).into()); ser_path.path.segments.push(Ident::new("serialize", Span::call_site()).into());
serialize_with.set(ser_path); serialize_with.set(ser_path);
let mut de_path = path; let mut de_path = path;
de_path.segments.push(Ident::new("deserialize", Span::call_site()).into()); de_path.path.segments.push(Ident::new("deserialize", Span::call_site()).into());
deserialize_with.set(de_path); deserialize_with.set(de_path);
} }
} }
@@ -873,7 +873,7 @@ impl Field {
// Parse `#[serde(getter = "...")]` // Parse `#[serde(getter = "...")]`
Meta(NameValue(ref m)) if m.ident == "getter" => { Meta(NameValue(ref m)) if m.ident == "getter" => {
if let Ok(path) = parse_lit_into_path(cx, m.ident.as_ref(), &m.lit) { if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
getter.set(path); getter.set(path);
} }
} }
@@ -921,7 +921,12 @@ impl Field {
path.segments.push(Ident::new("private", Span::def_site()).into()); path.segments.push(Ident::new("private", Span::def_site()).into());
path.segments.push(Ident::new("de", Span::def_site()).into()); path.segments.push(Ident::new("de", Span::def_site()).into());
path.segments.push(Ident::new("borrow_cow_str", Span::def_site()).into()); path.segments.push(Ident::new("borrow_cow_str", Span::def_site()).into());
deserialize_with.set_if_none(path); let expr = syn::ExprPath {
attrs: Vec::new(),
qself: None,
path: path,
};
deserialize_with.set_if_none(expr);
} else if is_cow(&field.ty, is_slice_u8) { } else if is_cow(&field.ty, is_slice_u8) {
let mut path = syn::Path { let mut path = syn::Path {
leading_colon: None, leading_colon: None,
@@ -931,7 +936,12 @@ impl Field {
path.segments.push(Ident::new("private", Span::def_site()).into()); path.segments.push(Ident::new("private", Span::def_site()).into());
path.segments.push(Ident::new("de", Span::def_site()).into()); path.segments.push(Ident::new("de", Span::def_site()).into());
path.segments.push(Ident::new("borrow_cow_bytes", Span::def_site()).into()); path.segments.push(Ident::new("borrow_cow_bytes", Span::def_site()).into());
deserialize_with.set_if_none(path); let expr = syn::ExprPath {
attrs: Vec::new(),
qself: None,
path: path,
};
deserialize_with.set_if_none(expr);
} }
} else if is_rptr(&field.ty, is_str) || is_rptr(&field.ty, is_slice_u8) { } else if is_rptr(&field.ty, is_str) || is_rptr(&field.ty, is_slice_u8) {
// Types &str and &[u8] are always implicitly borrowed. No need for // Types &str and &[u8] are always implicitly borrowed. No need for
@@ -984,7 +994,7 @@ impl Field {
self.skip_deserializing self.skip_deserializing
} }
pub fn skip_serializing_if(&self) -> Option<&syn::Path> { pub fn skip_serializing_if(&self) -> Option<&syn::ExprPath> {
self.skip_serializing_if.as_ref() self.skip_serializing_if.as_ref()
} }
@@ -992,11 +1002,11 @@ impl Field {
&self.default &self.default
} }
pub fn serialize_with(&self) -> Option<&syn::Path> { pub fn serialize_with(&self) -> Option<&syn::ExprPath> {
self.serialize_with.as_ref() self.serialize_with.as_ref()
} }
pub fn deserialize_with(&self) -> Option<&syn::Path> { pub fn deserialize_with(&self) -> Option<&syn::ExprPath> {
self.deserialize_with.as_ref() self.deserialize_with.as_ref()
} }
@@ -1012,7 +1022,7 @@ impl Field {
&self.borrowed_lifetimes &self.borrowed_lifetimes
} }
pub fn getter(&self) -> Option<&syn::Path> { pub fn getter(&self) -> Option<&syn::ExprPath> {
self.getter.as_ref() self.getter.as_ref()
} }
} }
@@ -1107,6 +1117,11 @@ fn parse_lit_into_path(cx: &Ctxt, attr_name: &str, lit: &syn::Lit) -> Result<syn
parse_lit_str(string).map_err(|_| cx.error(format!("failed to parse path: {:?}", string.value()))) parse_lit_str(string).map_err(|_| cx.error(format!("failed to parse path: {:?}", string.value())))
} }
fn parse_lit_into_expr_path(cx: &Ctxt, attr_name: &str, lit: &syn::Lit) -> Result<syn::ExprPath, ()> {
let string = try!(get_lit_str(cx, attr_name, attr_name, lit));
parse_lit_str(string).map_err(|_| cx.error(format!("failed to parse path: {:?}", string.value())))
}
fn parse_lit_into_where( fn parse_lit_into_where(
cx: &Ctxt, cx: &Ctxt,
attr_name: &str, attr_name: &str,
+7
View File
@@ -528,6 +528,13 @@ fn test_gen() {
marker: PhantomData<T>, marker: PhantomData<T>,
} }
assert::<TypeMacro<X>>(); assert::<TypeMacro<X>>();
#[derive(Serialize)]
struct BigArray {
#[serde(serialize_with = "<[_]>::serialize")]
array: [u8; 256],
}
assert_ser::<BigArray>();
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////