Compare commits

...

17 Commits

Author SHA1 Message Date
David Tolnay 89278996c5 Release 1.0.43 2018-04-23 11:23:58 -07:00
David Tolnay ecef937e26 Merge pull request #1234 from serde-rs/newtype
Unpack a layer of NewtypeStruct when content is newtype
2018-04-23 11:23:21 -07:00
David Tolnay bceda5fb18 Unpack a layer of NewtypeStruct when content is newtype 2018-04-23 11:04:42 -07:00
David Tolnay f46a08b04e Merge pull request #1231 from ignatenkobrain/patch-1
derive: bump min version of quote to 0.5.2
2018-04-22 16:48:11 -07:00
Igor Gnatenko f3cb7c7a32 derive: bump min version of quote to 0.5.2
Fixes: https://github.com/serde-rs/serde/issues/1230
2018-04-22 09:22:47 +02:00
David Tolnay af795e2e54 Release 1.0.42 2018-04-21 15:16:10 -07:00
David Tolnay 6aa07fe0d6 Merge pull request #1229 from serde-rs/cold
Mark error construction as cold code
2018-04-21 14:57:11 -07:00
David Tolnay c455720f81 Mark error construction as cold code
This eliminates 12% of the Serde-related code in the Xi release binary
as measured by:

nm -S target/release/xi-core \
    | awk '/serde/{sum += strtonum("0x"$2)} END{print sum}'
2018-04-21 14:41:14 -07:00
David Tolnay b07a208716 Merge pull request #1228 from serde-rs/untagged
Reduce instantiations of Result::map in Deserialize of unit variants
2018-04-21 13:46:36 -07:00
David Tolnay df93fab5fa Reduce instantiations of Result::map in Deserialize of unit variants
This eliminates 110 instantiations of Result::map in Xi and reduces
binary size by 229 kilobytes.
2018-04-21 13:27:17 -07:00
David Tolnay 1a972d2105 Merge pull request #1227 from serde-rs/ser
Improve Serialize of adjacently tagged newtype variants
2018-04-21 12:10:28 -07:00
David Tolnay 6d1807bb4a Improve Serialize of adjacently tagged newtype variants
The existing implementation was unnecessarily complicated.

    struct __AdjacentlyTagged<'__a> {
        data: (&'__a String,),
        phantom: _serde::export::PhantomData<AdjacentlyTagged>,
    }
    impl<'__a> _serde::Serialize for __AdjacentlyTagged<'__a> {
        fn serialize<__S>(
            &self,
            __serializer: __S,
        ) -> _serde::export::Result<__S::Ok, __S::Error>
        where
            __S: _serde::Serializer,
        {
            let (__field0,) = self.data;
            _serde::Serialize::serialize(__field0, __serializer)
        }
    }
    _serde::ser::SerializeStruct::serialize_field(
        &mut __struct,
        "content",
        &__AdjacentlyTagged {
            data: (__field0,),
            phantom: _serde::export::PhantomData::<AdjacentlyTagged>,
        },
    )?;

Instead the new implementation does simply:

    _serde::ser::SerializeStruct::serialize_field(
        &mut __struct,
        "content",
        __field0,
    )?;
2018-04-21 11:41:39 -07:00
David Tolnay b37cf858ce Remove unneeded quote_spanned that uses call_site 2018-04-21 11:33:39 -07:00
David Tolnay 5f8fa33756 Quote's default has changed to call_site 2018-04-21 11:33:38 -07:00
David Tolnay f3f006f411 Merge pull request #1226 from serde-rs/try
More efficient try!() alternative
2018-04-21 11:33:28 -07:00
David Tolnay 607966dcf7 Fix error message type inference in compile-fail/remote/wrong_de.rs 2018-04-21 11:21:13 -07:00
David Tolnay 6a8c39b2aa More efficient try!() alternative 2018-04-21 10:53:13 -07:00
13 changed files with 141 additions and 44 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "serde"
version = "1.0.41" # remember to update html_root_url
version = "1.0.43" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"
+7
View File
@@ -196,6 +196,7 @@ macro_rules! declare_error_trait {
/// For example if we try to deserialize a String out of a JSON file
/// containing an integer, the unexpected type is the integer and the
/// expected type is the string.
#[cold]
fn invalid_type(unexp: Unexpected, exp: &Expected) -> Self {
Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp))
}
@@ -213,6 +214,7 @@ macro_rules! declare_error_trait {
/// For example if we try to deserialize a String out of some binary data
/// that is not valid UTF-8, the unexpected value is the bytes and the
/// expected value is a string.
#[cold]
fn invalid_value(unexp: Unexpected, exp: &Expected) -> Self {
Error::custom(format_args!("invalid value: {}, expected {}", unexp, exp))
}
@@ -226,12 +228,14 @@ macro_rules! declare_error_trait {
/// The `exp` argument provides information about what data was being
/// expected. For example `exp` might say that a tuple of size 6 was
/// expected.
#[cold]
fn invalid_length(len: usize, exp: &Expected) -> Self {
Error::custom(format_args!("invalid length {}, expected {}", len, exp))
}
/// Raised when a `Deserialize` enum type received a variant with an
/// unrecognized name.
#[cold]
fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self {
if expected.is_empty() {
Error::custom(format_args!("unknown variant `{}`, there are no variants",
@@ -245,6 +249,7 @@ macro_rules! declare_error_trait {
/// Raised when a `Deserialize` struct type received a field with an
/// unrecognized name.
#[cold]
fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self {
if expected.is_empty() {
Error::custom(format_args!("unknown field `{}`, there are no fields",
@@ -259,12 +264,14 @@ macro_rules! declare_error_trait {
/// Raised when a `Deserialize` struct type expected to receive a required
/// field with a particular name but that field was not present in the
/// input.
#[cold]
fn missing_field(field: &'static str) -> Self {
Error::custom(format_args!("missing field `{}`", field))
}
/// Raised when a `Deserialize` struct type received more than one of the
/// same field.
#[cold]
fn duplicate_field(field: &'static str) -> Self {
Error::custom(format_args!("duplicate field `{}`", field))
}
+3
View File
@@ -58,6 +58,7 @@ type ErrorImpl = ();
impl de::Error for Error {
#[cfg(any(feature = "std", feature = "alloc"))]
#[cold]
fn custom<T>(msg: T) -> Self
where
T: Display,
@@ -68,6 +69,7 @@ impl de::Error for Error {
}
#[cfg(not(any(feature = "std", feature = "alloc")))]
#[cold]
fn custom<T>(msg: T) -> Self
where
T: Display,
@@ -78,6 +80,7 @@ impl de::Error for Error {
}
impl ser::Error for Error {
#[cold]
fn custom<T>(msg: T) -> Self
where
T: Display,
+1 -1
View File
@@ -79,7 +79,7 @@
////////////////////////////////////////////////////////////////////////////////
// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.41")]
#![doc(html_root_url = "https://docs.rs/serde/1.0.43")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
+13 -2
View File
@@ -277,6 +277,7 @@ mod content {
}
}
#[cold]
fn unexpected(&self) -> Unexpected {
match *self {
Content::Bool(b) => Unexpected::Bool(b),
@@ -1309,7 +1310,12 @@ mod content {
where
V: Visitor<'de>,
{
visitor.visit_newtype_struct(self)
match self.content {
Content::Newtype(v) => {
visitor.visit_newtype_struct(ContentDeserializer::new(*v))
}
_ => visitor.visit_newtype_struct(self),
}
}
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -2000,7 +2006,12 @@ mod content {
where
V: Visitor<'de>,
{
visitor.visit_newtype_struct(self)
match *self.content {
Content::Newtype(ref v) => {
visitor.visit_newtype_struct(ContentRefDeserializer::new(v))
}
_ => visitor.visit_newtype_struct(self),
}
}
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_derive"
version = "1.0.41" # remember to update html_root_url
version = "1.0.43" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
@@ -24,7 +24,7 @@ proc-macro = true
[dependencies]
proc-macro2 = "0.3"
quote = "0.5"
quote = "0.5.2"
serde_derive_internals = { version = "=0.23.1", default-features = false, path = "../serde_derive_internals" }
syn = { version = "0.13", features = ["visit"] }
+22 -20
View File
@@ -16,6 +16,7 @@ use bound;
use fragment::{Expr, Fragment, Match, Stmts};
use internals::ast::{Container, Data, Field, Style, Variant};
use internals::{self, attr};
use try;
use std::collections::BTreeSet;
@@ -36,10 +37,9 @@ pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<Tokens, Str
let impl_block = if let Some(remote) = cont.attrs.remote() {
let vis = &input.vis;
let fun = quote_spanned!(Span::call_site()=> deserialize);
quote! {
impl #de_impl_generics #ident #ty_generics #where_clause {
#vis fn #fun<__D>(__deserializer: __D) -> _serde::export::Result<#remote #ty_generics, __D::Error>
#vis fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<#remote #ty_generics, __D::Error>
where __D: _serde::Deserializer<#delife>
{
#body
@@ -63,10 +63,12 @@ pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<Tokens, Str
}
};
let try_replacement = try::replacement();
let generated = quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = {
extern crate serde as _serde;
#try_replacement
#impl_block
};
};
@@ -583,11 +585,11 @@ fn deserialize_seq(
let mut result = if is_struct {
let names = fields.iter().map(|f| &f.ident);
quote_spanned! {Span::call_site()=>
quote! {
#type_path { #( #names: #vars ),* }
}
} else {
quote_spanned! {Span::call_site()=>
quote! {
#type_path ( #(#vars),* )
}
};
@@ -649,11 +651,10 @@ fn deserialize_seq_in_place(
})
});
let dot = quote_spanned!(Span::call_site()=> .);
if field.attrs.skip_deserializing() {
let default = Expr(expr_is_missing(field, cattrs));
quote! {
self.place #dot #field_name = #default;
self.place.#field_name = #default;
}
} else {
let return_invalid_length = quote! {
@@ -663,7 +664,7 @@ fn deserialize_seq_in_place(
None => {
quote! {
if let _serde::export::None = try!(_serde::de::SeqAccess::next_element_seed(&mut __seq,
_serde::private::de::InPlaceSeed(&mut self.place #dot #field_name)))
_serde::private::de::InPlaceSeed(&mut self.place.#field_name)))
{
#return_invalid_length
}
@@ -676,7 +677,7 @@ fn deserialize_seq_in_place(
#wrapper
match try!(_serde::de::SeqAccess::next_element::<#wrapper_ty>(&mut __seq)) {
_serde::export::Some(__wrap) => {
self.place #dot #field_name = __wrap.value;
self.place.#field_name = __wrap.value;
}
_serde::export::None => {
#return_invalid_length
@@ -732,7 +733,7 @@ fn deserialize_newtype_struct(type_path: &Tokens, params: &Parameters, field: &F
}
};
let mut result = quote_spanned!(Span::call_site()=> #type_path(#value));
let mut result = quote!(#type_path(__field0));
if params.has_getter {
let this = &params.this;
result = quote! {
@@ -745,6 +746,7 @@ fn deserialize_newtype_struct(type_path: &Tokens, params: &Parameters, field: &F
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::export::Result<Self::Value, __E::Error>
where __E: _serde::Deserializer<#delife>
{
let __field0 = #value;
_serde::export::Ok(#result)
}
}
@@ -757,13 +759,12 @@ fn deserialize_newtype_struct_in_place(params: &Parameters, field: &Field) -> To
let delife = params.borrowed.de_lifetime();
let elem = quote_spanned!(Span::call_site()=> .0);
quote! {
#[inline]
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::export::Result<Self::Value, __E::Error>
where __E: _serde::Deserializer<#delife>
{
_serde::Deserialize::deserialize_in_place(__e, &mut self.place #elem)
_serde::Deserialize::deserialize_in_place(__e, &mut self.place.0)
}
}
}
@@ -1625,12 +1626,13 @@ fn deserialize_untagged_variant(
let type_name = params.type_name();
let variant_name = variant.ident.as_ref();
quote_expr! {
_serde::export::Result::map(
_serde::Deserializer::deserialize_any(
#deserializer,
_serde::private::de::UntaggedUnitVisitor::new(#type_name, #variant_name)
),
|()| #this::#variant_ident)
match _serde::Deserializer::deserialize_any(
#deserializer,
_serde::private::de::UntaggedUnitVisitor::new(#type_name, #variant_name)
) {
_serde::export::Ok(()) => _serde::export::Ok(#this::#variant_ident),
_serde::export::Err(__err) => _serde::export::Err(__err),
}
}
}
Style::Newtype => deserialize_untagged_newtype_variant(
@@ -2305,9 +2307,9 @@ fn deserialize_map(
let ident = field.ident.expect("struct contains unnamed fields");
if field.attrs.skip_deserializing() {
let value = Expr(expr_is_missing(field, cattrs));
quote_spanned!(Span::call_site()=> #ident: #value)
quote!(#ident: #value)
} else {
quote_spanned!(Span::call_site()=> #ident: #name)
quote!(#ident: #name)
}
});
@@ -2325,7 +2327,7 @@ fn deserialize_map(
}
};
let mut result = quote_spanned!(Span::call_site()=> #struct_path { #(#result),* });
let mut result = quote!(#struct_path { #(#result),* });
if params.has_getter {
let this = &params.this;
result = quote! {
+2 -9
View File
@@ -22,7 +22,7 @@
//!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.41")]
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.43")]
#![cfg_attr(
feature = "cargo-clippy",
allow(enum_variant_names, redundant_field_names, too_many_arguments, used_underscore_binding)
@@ -43,14 +43,6 @@ extern crate proc_macro2;
use proc_macro::TokenStream;
use syn::DeriveInput;
// Quote's default is def_site but it appears call_site is likely to stabilize
// before def_site. Thus we try to use only call_site.
macro_rules! quote {
($($tt:tt)*) => {
quote_spanned!($crate::proc_macro2::Span::call_site()=> $($tt)*)
}
}
#[macro_use]
mod bound;
#[macro_use]
@@ -58,6 +50,7 @@ mod fragment;
mod de;
mod ser;
mod try;
#[proc_macro_derive(Serialize, attributes(serde))]
pub fn derive_serialize(input: TokenStream) -> TokenStream {
+15 -7
View File
@@ -15,6 +15,7 @@ use bound;
use fragment::{Fragment, Match, Stmts};
use internals::ast::{Container, Data, Field, Style, Variant};
use internals::{attr, Ctxt};
use try;
use std::u32;
@@ -32,10 +33,9 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, Strin
let impl_block = if let Some(remote) = cont.attrs.remote() {
let vis = &input.vis;
let fun = quote_spanned!(Span::call_site()=> serialize);
quote! {
impl #impl_generics #ident #ty_generics #where_clause {
#vis fn #fun<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
#vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer
{
#body
@@ -55,10 +55,12 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, Strin
}
};
let try_replacement = try::replacement();
let generated = quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = {
extern crate serde as _serde;
#try_replacement
#impl_block
};
};
@@ -594,9 +596,15 @@ fn serialize_adjacently_tagged_variant(
field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
}
quote_expr! {
_serde::Serialize::serialize(#field_expr, __serializer)
}
return quote_block! {
let mut __struct = try!(_serde::Serializer::serialize_struct(
__serializer, #type_name, 2));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #content, #field_expr));
_serde::ser::SerializeStruct::end(__struct)
};
}
Style::Tuple => {
serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields)
@@ -1056,9 +1064,9 @@ fn mut_if(is_mut: bool) -> Option<Tokens> {
fn get_member(params: &Parameters, field: &Field, member: &Member) -> Tokens {
let self_var = &params.self_var;
match (params.is_remote, field.attrs.getter()) {
(false, None) => quote_spanned!(Span::call_site()=> &#self_var.#member),
(false, None) => quote!(&#self_var.#member),
(true, None) => {
let inner = quote_spanned!(Span::call_site()=> &#self_var.#member);
let inner = quote!(&#self_var.#member);
let ty = field.ty;
quote!(_serde::private::ser::constrain::<#ty>(#inner))
}
+25
View File
@@ -0,0 +1,25 @@
use quote::Tokens;
use proc_macro2::{Op, Spacing};
// None of our generated code requires the `From::from` error conversion
// performed by the standard library's `try!` macro. With this simplified macro
// we see a significant improvement in type checking and borrow checking time of
// the generated code and a slight improvement in binary size.
pub fn replacement() -> Tokens {
// Cannot pass `$expr` to `quote!` prior to Rust 1.17.0 so interpolate it.
let dollar = Op::new('$', Spacing::Alone);
quote! {
#[allow(unused_macros)]
macro_rules! try {
(#dollar __expr:expr) => {
match #dollar __expr {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
}
}
}
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_test"
version = "1.0.41" # remember to update html_root_url
version = "1.0.43" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Token De/Serializer for testing De/Serialize implementations"
+1 -1
View File
@@ -155,7 +155,7 @@
//! # }
//! ```
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.41")]
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.43")]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp))]
+48
View File
@@ -446,6 +446,54 @@ fn test_generic_newtype_struct() {
);
}
#[test]
fn test_untagged_newtype_struct() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
enum E {
Newtype(GenericNewTypeStruct<u32>),
Null,
}
assert_tokens(
&E::Newtype(GenericNewTypeStruct(5u32)),
&[
Token::NewtypeStruct {
name: "GenericNewTypeStruct",
},
Token::U32(5),
],
);
}
#[test]
fn test_adjacently_tagged_newtype_struct() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "t", content = "c")]
enum E {
Newtype(GenericNewTypeStruct<u32>),
Null,
}
assert_de_tokens(
&E::Newtype(GenericNewTypeStruct(5u32)),
&[
Token::Struct {
name: "E",
len: 2,
},
Token::Str("c"),
Token::NewtypeStruct {
name: "GenericNewTypeStruct",
},
Token::U32(5),
Token::Str("t"),
Token::Str("Newtype"),
Token::StructEnd,
],
);
}
#[test]
fn test_generic_tuple_struct() {
assert_tokens(