diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index df16e8ef..2f07d7e0 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -2273,7 +2273,7 @@ fn field_i(i: usize) -> Ident { fn wrap_deserialize_with( params: &Parameters, value_ty: &Tokens, - deserialize_with: &syn::Path, + deserialize_with: &syn::ExprPath, ) -> (Tokens, Tokens) { let this = ¶ms.this; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = @@ -2308,7 +2308,7 @@ fn wrap_deserialize_with( fn wrap_deserialize_field_with( params: &Parameters, field_ty: &syn::Type, - deserialize_with: &syn::Path, + deserialize_with: &syn::ExprPath, ) -> (Tokens, Tokens) { wrap_deserialize_with(params, "e!(#field_ty), deserialize_with) } @@ -2316,7 +2316,7 @@ fn wrap_deserialize_field_with( fn wrap_deserialize_variant_with( params: &Parameters, variant: &Variant, - deserialize_with: &syn::Path, + deserialize_with: &syn::ExprPath, ) -> (Tokens, Tokens, Tokens) { let this = ¶ms.this; let variant_ident = &variant.ident; diff --git a/serde_derive/src/ser.rs b/serde_derive/src/ser.rs index 1f4f70d3..8da9e7c3 100644 --- a/serde_derive/src/ser.rs +++ b/serde_derive/src/ser.rs @@ -902,7 +902,7 @@ fn serialize_struct_visitor( fn wrap_serialize_field_with( params: &Parameters, field_ty: &syn::Type, - serialize_with: &syn::Path, + serialize_with: &syn::ExprPath, field_expr: &Tokens, ) -> Tokens { 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( params: &Parameters, - serialize_with: &syn::Path, + serialize_with: &syn::ExprPath, variant: &Variant, ) -> Tokens { 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( params: &Parameters, - serialize_with: &syn::Path, + serialize_with: &syn::ExprPath, field_tys: &[&syn::Type], field_exprs: &[Tokens], ) -> Tokens { diff --git a/serde_derive_internals/src/attr.rs b/serde_derive_internals/src/attr.rs index 868a8932..7c6e3066 100644 --- a/serde_derive_internals/src/attr.rs +++ b/serde_derive_internals/src/attr.rs @@ -243,7 +243,7 @@ impl Container { // Parse `#[serde(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 { syn::Data::Struct(syn::DataStruct { fields: syn::Fields::Named(_), .. }) => { default.set(Default::Path(path)); @@ -510,8 +510,8 @@ pub struct Variant { skip_deserializing: bool, skip_serializing: bool, other: bool, - serialize_with: Option, - deserialize_with: Option, + serialize_with: Option, + deserialize_with: Option, borrow: Option, } @@ -577,26 +577,26 @@ impl Variant { // Parse `#[serde(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(); - 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); 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); } } // Parse `#[serde(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); } } // Parse `#[serde(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); } } @@ -675,11 +675,11 @@ impl Variant { self.other } - pub fn serialize_with(&self) -> Option<&syn::Path> { + pub fn serialize_with(&self) -> Option<&syn::ExprPath> { 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() } } @@ -691,14 +691,14 @@ pub struct Field { de_renamed: bool, skip_serializing: bool, skip_deserializing: bool, - skip_serializing_if: Option, + skip_serializing_if: Option, default: Default, - serialize_with: Option, - deserialize_with: Option, + serialize_with: Option, + deserialize_with: Option, ser_bound: Option>, de_bound: Option>, borrowed_lifetimes: BTreeSet, - getter: Option, + getter: Option, } /// 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()`. Default, /// The default is given by this function. - Path(syn::Path), + Path(syn::ExprPath), } impl Field { @@ -775,7 +775,7 @@ impl Field { // Parse `#[serde(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)); } } @@ -798,33 +798,33 @@ impl Field { // Parse `#[serde(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); } } // Parse `#[serde(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); } } // Parse `#[serde(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); } } // Parse `#[serde(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(); - 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); 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); } } @@ -873,7 +873,7 @@ impl Field { // Parse `#[serde(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); } } @@ -921,7 +921,12 @@ impl Field { 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("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) { let mut path = syn::Path { leading_colon: None, @@ -931,7 +936,12 @@ impl Field { 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("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) { // Types &str and &[u8] are always implicitly borrowed. No need for @@ -984,7 +994,7 @@ impl Field { 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() } @@ -992,11 +1002,11 @@ impl Field { &self.default } - pub fn serialize_with(&self) -> Option<&syn::Path> { + pub fn serialize_with(&self) -> Option<&syn::ExprPath> { 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() } @@ -1012,7 +1022,7 @@ impl Field { &self.borrowed_lifetimes } - pub fn getter(&self) -> Option<&syn::Path> { + pub fn getter(&self) -> Option<&syn::ExprPath> { self.getter.as_ref() } } @@ -1107,6 +1117,11 @@ fn parse_lit_into_path(cx: &Ctxt, attr_name: &str, lit: &syn::Lit) -> Result Result { + 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( cx: &Ctxt, attr_name: &str, diff --git a/test_suite/tests/test_gen.rs b/test_suite/tests/test_gen.rs index 5f0fd696..7e2f3176 100644 --- a/test_suite/tests/test_gen.rs +++ b/test_suite/tests/test_gen.rs @@ -528,6 +528,13 @@ fn test_gen() { marker: PhantomData, } assert::>(); + + #[derive(Serialize)] + struct BigArray { + #[serde(serialize_with = "<[_]>::serialize")] + array: [u8; 256], + } + assert_ser::(); } //////////////////////////////////////////////////////////////////////////