Compare commits

...

5 Commits

Author SHA1 Message Date
David Tolnay 3f0d3453d8 Release 1.0.45 2018-05-02 15:18:17 -07:00
David Tolnay b27a27ce22 Merge pull request #1241 from serde-rs/pretend
Pretend remote derives are not dead code
2018-05-02 15:17:19 -07:00
David Tolnay 80c0600657 Merge pull request #1243 from serde-rs/ci
Add a CI build on 1.15.0
2018-05-02 15:17:10 -07:00
David Tolnay 77f9e63661 Add a CI build on 1.15.0 2018-05-02 14:29:51 -07:00
David Tolnay b78f434086 Pretend remote derives are not dead code 2018-05-02 14:23:59 -07:00
13 changed files with 165 additions and 10 deletions
+1
View File
@@ -5,6 +5,7 @@ cache: cargo
# run builds for all the trains (and more)
rust:
- 1.13.0
- 1.15.0
- stable
- beta
- nightly
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "serde"
version = "1.0.44" # remember to update html_root_url
version = "1.0.45" # 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"
+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.44")]
#![doc(html_root_url = "https://docs.rs/serde/1.0.45")]
// 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
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_derive"
version = "1.0.44" # remember to update html_root_url
version = "1.0.45" # 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)]"
+3
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 pretend;
use try;
use std::collections::BTreeSet;
@@ -37,11 +38,13 @@ 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 used = pretend::pretend_used(&cont);
quote! {
impl #de_impl_generics #ident #ty_generics #where_clause {
#vis fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<#remote #ty_generics, __D::Error>
where __D: _serde::Deserializer<#delife>
{
#used
#body
}
}
+2 -1
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.44")]
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.45")]
#![cfg_attr(
feature = "cargo-clippy",
allow(enum_variant_names, redundant_field_names, too_many_arguments, used_underscore_binding)
@@ -49,6 +49,7 @@ mod bound;
mod fragment;
mod de;
mod pretend;
mod ser;
mod try;
+145
View File
@@ -0,0 +1,145 @@
use proc_macro2::Span;
use quote::Tokens;
use syn::Ident;
use internals::ast::{Container, Data, Field, Style};
// Suppress dead_code warnings that would otherwise appear when using a remote
// derive. Other than this pretend code, a struct annotated with remote derive
// never has its fields referenced and an enum annotated with remote derive
// never has its variants constructed.
//
// warning: field is never used: `i`
// --> src/main.rs:4:20
// |
// 4 | struct StructDef { i: i32 }
// | ^^^^^^
//
// warning: variant is never constructed: `V`
// --> src/main.rs:8:16
// |
// 8 | enum EnumDef { V }
// | ^
//
pub fn pretend_used(cont: &Container) -> Tokens {
let pretend_fields = pretend_fields_used(cont);
let pretend_variants = pretend_variants_used(cont);
quote! {
#pretend_fields
#pretend_variants
}
}
// For structs with named fields, expands to:
//
// match None::<T> {
// Some(T { a: ref __v0, b: ref __v1 }) => {}
// _ => {}
// }
//
// For enums, expands to the following but only including struct variants:
//
// match None::<T> {
// Some(T::A { a: ref __v0 }) => {}
// Some(T::B { b: ref __v0 }) => {}
// _ => {}
// }
//
// The `ref` is important in case the user has written a Drop impl on their
// type. Rust does not allow destructuring a struct or enum that has a Drop
// impl.
fn pretend_fields_used(cont: &Container) -> Tokens {
let type_ident = cont.ident;
let (_, ty_generics, _) = cont.generics.split_for_impl();
let patterns = match cont.data {
Data::Enum(ref variants) => {
variants.iter()
.filter_map(|variant| match variant.style {
Style::Struct => {
let variant_ident = variant.ident;
let pat = struct_pattern(&variant.fields);
Some(quote!(#type_ident::#variant_ident #pat))
}
_ => None,
})
.collect::<Vec<_>>()
}
Data::Struct(Style::Struct, ref fields) => {
let pat = struct_pattern(fields);
vec![quote!(#type_ident #pat)]
}
Data::Struct(_, _) => {
return quote!();
}
};
quote! {
match _serde::export::None::<#type_ident #ty_generics> {
#(
_serde::export::Some(#patterns) => {}
)*
_ => {}
}
}
}
// Expands to one of these per enum variant:
//
// match None {
// Some((__v0, __v1,)) => {
// let _ = E::V { a: __v0, b: __v1 };
// }
// _ => {}
// }
//
fn pretend_variants_used(cont: &Container) -> Tokens {
let variants = match cont.data {
Data::Enum(ref variants) => variants,
Data::Struct(_, _) => {
return quote!();
}
};
let type_ident = cont.ident;
let (_, ty_generics, _) = cont.generics.split_for_impl();
let turbofish = ty_generics.as_turbofish();
let cases = variants.iter()
.map(|variant| {
let variant_ident = variant.ident;
let ref placeholders = (0..variant.fields.len())
.map(|i| Ident::new(&format!("__v{}", i), Span::call_site()))
.collect::<Vec<_>>();
let pat = match variant.style {
Style::Struct => {
let names = variant.fields.iter().map(|field| field.ident);
quote!({ #(#names: #placeholders),* })
}
Style::Tuple | Style::Newtype => {
quote!(( #(#placeholders),* ))
}
Style::Unit => quote!(),
};
quote! {
match _serde::export::None {
_serde::export::Some((#(#placeholders,)*)) => {
let _ = #type_ident::#variant_ident #turbofish #pat;
}
_ => {}
}
}
});
quote!(#(#cases)*)
}
fn struct_pattern(fields: &[Field]) -> Tokens {
let names = fields.iter().map(|field| field.ident);
let placeholders = (0..fields.len())
.map(|i| Ident::new(&format!("__v{}", i), Span::call_site()));
quote!({ #(#names: ref #placeholders),* })
}
+3
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 pretend;
use try;
use std::u32;
@@ -33,11 +34,13 @@ 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 used = pretend::pretend_used(&cont);
quote! {
impl #impl_generics #ident #ty_generics #where_clause {
#vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer
{
#used
#body
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_test"
version = "1.0.44" # remember to update html_root_url
version = "1.0.45" # 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.44")]
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.45")]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp))]
-2
View File
@@ -333,9 +333,7 @@ fn test_gen() {
#[derive(Serialize, Deserialize)]
#[serde(untagged, remote = "Or")]
enum OrDef<A, B> {
#[allow(dead_code)]
A(A),
#[allow(dead_code)]
B(B),
}
-2
View File
@@ -160,10 +160,8 @@ struct StructPrivDef {
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::StructPub")]
struct StructPubDef {
#[allow(dead_code)]
a: u8,
#[allow(dead_code)]
#[serde(with = "UnitDef")]
b: remote::Unit,
}
+6
View File
@@ -87,4 +87,10 @@ else
channel build --no-default-features
cd "$DIR/serde_test"
channel build
CHANNEL=1.15.0
cd "$DIR"
cargo clean
cd "$DIR/serde_derive"
channel build
fi