aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-10 06:58:06 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-10 06:58:06 +0000
commitfe550d782c1dcc87676c5590ef684b329e22d0fa (patch)
tree91380375cadc4e0835f7e031ac39e9a33dce2c13
parent92ed66199eb5b1ef475b309262864e86071a3773 (diff)
parent6e1d8718fc5e3dbc97a6b030204ef46f4e0289dd (diff)
downloadserde_derive-android13-mainline-cellbroadcast-release.tar.gz
Change-Id: Id11e2ec824bf0cd37f49ddf3cc9af20e5f86abc7
-rw-r--r--.cargo_vcs_info.json7
-rw-r--r--Android.bp16
-rw-r--r--Cargo.toml12
-rw-r--r--Cargo.toml.orig3
-rw-r--r--METADATA10
-rw-r--r--README.md23
-rw-r--r--TEST_MAPPING109
-rw-r--r--build.rs6
-rw-r--r--cargo2android.json4
-rw-r--r--crates-io.md23
-rw-r--r--src/bound.rs8
-rw-r--r--src/de.rs70
-rw-r--r--src/dummy.rs2
-rw-r--r--src/internals/ast.rs2
-rw-r--r--src/internals/attr.rs8
-rw-r--r--src/internals/check.rs4
-rw-r--r--src/lib.rs14
-rw-r--r--src/pretend.rs139
-rw-r--r--src/ser.rs4
19 files changed, 337 insertions, 127 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 71f38ef..7239a8b 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
{
"git": {
- "sha1": "3d6c4149b177e9cadfb948ebc6d1e55b33861792"
- }
-}
+ "sha1": "02bd79a0bada78dd88d050f6478806f001f41fb0"
+ },
+ "path_in_vcs": "serde_derive"
+} \ No newline at end of file
diff --git a/Android.bp b/Android.bp
index 89739c0..d7a8421 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,4 +1,5 @@
-// This file is generated by cargo2android.py --run --device --dependencies.
+// This file is generated by cargo2android.py --config cargo2android.json.
+// Do not modify this file as changes will be overridden on upgrade.
package {
default_applicable_licenses: ["external_rust_crates_serde_derive_license"],
@@ -39,11 +40,14 @@ license {
rust_proc_macro {
name: "libserde_derive",
crate_name: "serde_derive",
+ cargo_env_compat: true,
+ cargo_pkg_version: "1.0.136",
srcs: ["src/lib.rs"],
edition: "2015",
features: ["default"],
- flags: [
- "--cfg underscore_consts",
+ cfgs: [
+ "ptr_addr_of",
+ "underscore_consts",
],
rustlibs: [
"libproc_macro2",
@@ -51,9 +55,3 @@ rust_proc_macro {
"libsyn",
],
}
-
-// dependent_library ["feature_list"]
-// proc-macro2-1.0.24 "default,proc-macro"
-// quote-1.0.8 "default,proc-macro"
-// syn-1.0.60 "clone-impls,default,derive,parsing,printing,proc-macro,quote"
-// unicode-xid-0.2.1 "default"
diff --git a/Cargo.toml b/Cargo.toml
index 389d48c..6fac8e3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,16 +3,16 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
[package]
+rust-version = "1.31"
name = "serde_derive"
-version = "1.0.123"
+version = "1.0.136"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
include = ["build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 24e2f6b..47fda7f 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,7 +1,8 @@
[package]
name = "serde_derive"
-version = "1.0.123" # remember to update html_root_url
+version = "1.0.136" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
+rust-version = "1.31"
license = "MIT OR Apache-2.0"
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
homepage = "https://serde.rs"
diff --git a/METADATA b/METADATA
index aea0a1a..5954db1 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/serde_derive/serde_derive-1.0.123.crate"
+ value: "https://static.crates.io/crates/serde_derive/serde_derive-1.0.136.crate"
}
- version: "1.0.123"
+ version: "1.0.136"
license_type: NOTICE
last_upgrade_date {
- year: 2021
- month: 2
- day: 9
+ year: 2022
+ month: 3
+ day: 1
}
}
diff --git a/README.md b/README.md
index 14b0098..79409a3 100644
--- a/README.md
+++ b/README.md
@@ -77,17 +77,20 @@ fn main() {
Serde is one of the most widely used Rust libraries so any place that Rustaceans
congregate will be able to help you out. For chat, consider trying the
-[#general] or [#beginners] channels of the unofficial community Discord, the
-[#rust-usage] channel of the official Rust Project Discord, or the
-[#general][zulip] stream in Zulip. For asynchronous, consider the [\[rust\] tag
-on StackOverflow][stackoverflow], the [/r/rust] subreddit which has a pinned
-weekly easy questions post, or the Rust [Discourse forum][discourse]. It's
-acceptable to file a support issue in this repo but they tend not to get as many
-eyes as any of the above and may get closed without a response after some time.
-
-[#general]: https://discord.com/channels/273534239310479360/274215136414400513
-[#beginners]: https://discord.com/channels/273534239310479360/273541522815713281
+[#rust-questions] or [#rust-beginners] channels of the unofficial community
+Discord (invite: <https://discord.gg/rust-lang-community>), the [#rust-usage] or
+[#beginners] channels of the official Rust Project Discord (invite:
+<https://discord.gg/rust-lang>), or the [#general][zulip] stream in Zulip. For
+asynchronous, consider the [\[rust\] tag on StackOverflow][stackoverflow], the
+[/r/rust] subreddit which has a pinned weekly easy questions post, or the Rust
+[Discourse forum][discourse]. It's acceptable to file a support issue in this
+repo but they tend not to get as many eyes as any of the above and may get
+closed without a response after some time.
+
+[#rust-questions]: https://discord.com/channels/273534239310479360/274215136414400513
+[#rust-beginners]: https://discord.com/channels/273534239310479360/273541522815713281
[#rust-usage]: https://discord.com/channels/442252698964721669/443150878111694848
+[#beginners]: https://discord.com/channels/442252698964721669/448238009733742612
[zulip]: https://rust-lang.zulipchat.com/#narrow/stream/122651-general
[stackoverflow]: https://stackoverflow.com/questions/tagged/rust
[/r/rust]: https://www.reddit.com/r/rust
diff --git a/TEST_MAPPING b/TEST_MAPPING
index f4547bb..b424c9c 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -1,14 +1,117 @@
// Generated by update_crate_tests.py for tests that depend on this crate.
{
+ "imports": [
+ {
+ "path": "external/rust/crates/base64"
+ },
+ {
+ "path": "external/rust/crates/bitflags"
+ },
+ {
+ "path": "external/rust/crates/bytes"
+ },
+ {
+ "path": "external/rust/crates/either"
+ },
+ {
+ "path": "external/rust/crates/rand_chacha"
+ },
+ {
+ "path": "external/rust/crates/serde"
+ },
+ {
+ "path": "external/rust/crates/serde-xml-rs"
+ },
+ {
+ "path": "external/rust/crates/serde_cbor"
+ },
+ {
+ "path": "external/rust/crates/slab"
+ },
+ {
+ "path": "external/rust/crates/tinytemplate"
+ },
+ {
+ "path": "external/rust/crates/tinyvec"
+ },
+ {
+ "path": "external/rust/crates/unicode-bidi"
+ },
+ {
+ "path": "external/rust/crates/unicode-xid"
+ },
+ {
+ "path": "external/rust/crates/url"
+ }
+ ],
"presubmit": [
{
- "name": "url_device_test_src_lib"
+ "name": "ZipFuseTest"
+ },
+ {
+ "name": "apkdmverity.test"
+ },
+ {
+ "name": "authfs_device_test_src_lib"
+ },
+ {
+ "name": "diced_test"
+ },
+ {
+ "name": "diced_vendor_test"
+ },
+ {
+ "name": "keystore2_test"
+ },
+ {
+ "name": "keystore2_test_utils_test"
+ },
+ {
+ "name": "legacykeystore_test"
+ },
+ {
+ "name": "libcert_request_validator_tests"
+ },
+ {
+ "name": "microdroid_manager_test"
+ },
+ {
+ "name": "virtualizationservice_device_test"
+ }
+ ],
+ "presubmit-rust": [
+ {
+ "name": "ZipFuseTest"
+ },
+ {
+ "name": "apkdmverity.test"
+ },
+ {
+ "name": "authfs_device_test_src_lib"
+ },
+ {
+ "name": "diced_test"
+ },
+ {
+ "name": "diced_vendor_test"
+ },
+ {
+ "name": "keystore2_test"
+ },
+ {
+ "name": "keystore2_test_utils_test"
+ },
+ {
+ "name": "legacykeystore_test"
+ },
+ {
+ "name": "libcert_request_validator_tests"
},
{
- "name": "unicode-bidi_device_test_src_lib"
+ "name": "microdroid_manager_test"
},
{
- "name": "serde_test_device_test_src_lib"
+ "name": "virtualizationservice_device_test"
}
]
}
diff --git a/build.rs b/build.rs
index 6e1b7b6..d0c827a 100644
--- a/build.rs
+++ b/build.rs
@@ -16,6 +16,12 @@ fn main() {
if minor >= 37 {
println!("cargo:rustc-cfg=underscore_consts");
}
+
+ // The ptr::addr_of! macro stabilized in Rust 1.51:
+ // https://blog.rust-lang.org/2021/03/25/Rust-1.51.0.html#stabilized-apis
+ if minor >= 51 {
+ println!("cargo:rustc-cfg=ptr_addr_of");
+ }
}
fn rustc_minor_version() -> Option<u32> {
diff --git a/cargo2android.json b/cargo2android.json
new file mode 100644
index 0000000..bf78496
--- /dev/null
+++ b/cargo2android.json
@@ -0,0 +1,4 @@
+{
+ "device": true,
+ "run": true
+} \ No newline at end of file
diff --git a/crates-io.md b/crates-io.md
index 0775761..b57bc5f 100644
--- a/crates-io.md
+++ b/crates-io.md
@@ -45,17 +45,20 @@ fn main() {
Serde is one of the most widely used Rust libraries so any place that Rustaceans
congregate will be able to help you out. For chat, consider trying the
-[#general] or [#beginners] channels of the unofficial community Discord, the
-[#rust-usage] channel of the official Rust Project Discord, or the
-[#general][zulip] stream in Zulip. For asynchronous, consider the [\[rust\] tag
-on StackOverflow][stackoverflow], the [/r/rust] subreddit which has a pinned
-weekly easy questions post, or the Rust [Discourse forum][discourse]. It's
-acceptable to file a support issue in this repo but they tend not to get as many
-eyes as any of the above and may get closed without a response after some time.
-
-[#general]: https://discord.com/channels/273534239310479360/274215136414400513
-[#beginners]: https://discord.com/channels/273534239310479360/273541522815713281
+[#rust-questions] or [#rust-beginners] channels of the unofficial community
+Discord (invite: <https://discord.gg/rust-lang-community>, the [#rust-usage] or
+[#beginners] channels of the official Rust Project Discord (invite:
+<https://discord.gg/rust-lang>), or the [#general][zulip] stream in Zulip. For
+asynchronous, consider the [\[rust\] tag on StackOverflow][stackoverflow], the
+[/r/rust] subreddit which has a pinned weekly easy questions post, or the Rust
+[Discourse forum][discourse]. It's acceptable to file a support issue in this
+repo but they tend not to get as many eyes as any of the above and may get
+closed without a response after some time.
+
+[#rust-questions]: https://discord.com/channels/273534239310479360/274215136414400513
+[#rust-beginners]: https://discord.com/channels/273534239310479360/273541522815713281
[#rust-usage]: https://discord.com/channels/442252698964721669/443150878111694848
+[#beginners]: https://discord.com/channels/442252698964721669/448238009733742612
[zulip]: https://rust-lang.zulipchat.com/#narrow/stream/122651-general
[stackoverflow]: https://stackoverflow.com/questions/tagged/rust
[/r/rust]: https://www.reddit.com/r/rust
diff --git a/src/bound.rs b/src/bound.rs
index 0949dfc..abca467 100644
--- a/src/bound.rs
+++ b/src/bound.rs
@@ -49,8 +49,8 @@ pub fn with_where_predicates_from_fields(
let predicates = cont
.data
.all_fields()
- .flat_map(|field| from_field(&field.attrs))
- .flat_map(|predicates| predicates.to_vec());
+ .filter_map(|field| from_field(&field.attrs))
+ .flat_map(<[syn::WherePredicate]>::to_vec);
let mut generics = generics.clone();
generics.make_where_clause().predicates.extend(predicates);
@@ -71,8 +71,8 @@ pub fn with_where_predicates_from_variants(
let predicates = variants
.iter()
- .flat_map(|variant| from_variant(&variant.attrs))
- .flat_map(|predicates| predicates.to_vec());
+ .filter_map(|variant| from_variant(&variant.attrs))
+ .flat_map(<[syn::WherePredicate]>::to_vec);
let mut generics = generics.clone();
generics.make_where_clause().predicates.extend(predicates);
diff --git a/src/de.rs b/src/de.rs
index 3daa9d1..ff7bc42 100644
--- a/src/de.rs
+++ b/src/de.rs
@@ -36,7 +36,7 @@ pub fn expand_derive_deserialize(
let impl_block = if let Some(remote) = cont.attrs.remote() {
let vis = &input.vis;
- let used = pretend::pretend_used(&cont);
+ let used = pretend::pretend_used(&cont, params.is_packed);
quote! {
impl #de_impl_generics #ident #ty_generics #where_clause {
#vis fn deserialize<__D>(__deserializer: __D) -> #serde::__private::Result<#remote #ty_generics, __D::Error>
@@ -125,6 +125,9 @@ struct Parameters {
/// At least one field has a serde(getter) attribute, implying that the
/// remote type has a private field.
has_getter: bool,
+
+ /// Type has a repr(packed) attribute.
+ is_packed: bool,
}
impl Parameters {
@@ -137,6 +140,7 @@ impl Parameters {
let borrowed = borrowed_lifetimes(cont);
let generics = build_generics(cont, &borrowed);
let has_getter = cont.data.has_getter();
+ let is_packed = cont.attrs.is_packed();
Parameters {
local,
@@ -144,6 +148,7 @@ impl Parameters {
generics,
borrowed,
has_getter,
+ is_packed,
}
}
@@ -475,7 +480,7 @@ fn deserialize_tuple(
};
let visit_seq = Stmts(deserialize_seq(
- &type_path, params, fields, false, cattrs, &expecting,
+ &type_path, params, fields, false, cattrs, expecting,
));
let visitor_expr = quote! {
@@ -561,7 +566,7 @@ fn deserialize_tuple_in_place(
None
};
- let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, &expecting));
+ let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting));
let visitor_expr = quote! {
__Visitor {
@@ -922,7 +927,7 @@ fn deserialize_struct(
let expecting = cattrs.expecting().unwrap_or(&expecting);
let visit_seq = Stmts(deserialize_seq(
- &type_path, params, fields, true, cattrs, &expecting,
+ &type_path, params, fields, true, cattrs, expecting,
));
let (field_visitor, fields_stmt, visit_map) = if cattrs.has_flatten() {
@@ -1063,7 +1068,7 @@ fn deserialize_struct_in_place(
};
let expecting = cattrs.expecting().unwrap_or(&expecting);
- let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, &expecting));
+ let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting));
let (field_visitor, fields_stmt, visit_map) =
deserialize_struct_as_struct_in_place_visitor(params, fields, cattrs);
@@ -1453,7 +1458,7 @@ fn deserialize_adjacently_tagged_enum(
while let _serde::__private::Some(__k) = #next_key {
match __k {
_serde::__private::de::TagContentOtherField::Other => {
- try!(_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map));
+ let _ = try!(_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map));
continue;
},
_serde::__private::de::TagContentOtherField::Tag => {
@@ -1728,6 +1733,8 @@ fn deserialize_externally_tagged_variant(
}
}
+// Generates significant part of the visit_seq and visit_map bodies of visitors
+// for the variants of internally tagged enum.
fn deserialize_internally_tagged_variant(
params: &Parameters,
variant: &Variant,
@@ -1779,11 +1786,9 @@ fn deserialize_untagged_variant(
deserializer: TokenStream,
) -> Fragment {
if let Some(path) = variant.attrs.deserialize_with() {
- let (wrapper, wrapper_ty, unwrap_fn) = wrap_deserialize_variant_with(params, variant, path);
+ let unwrap_fn = unwrap_to_variant_closure(params, variant, false);
return quote_block! {
- #wrapper
- _serde::__private::Result::map(
- <#wrapper_ty as _serde::Deserialize>::deserialize(#deserializer), #unwrap_fn)
+ _serde::__private::Result::map(#path(#deserializer), #unwrap_fn)
};
}
@@ -2087,7 +2092,7 @@ fn deserialize_identifier(
) -> Fragment {
let mut flat_fields = Vec::new();
for (_, ident, aliases) in fields {
- flat_fields.extend(aliases.iter().map(|alias| (alias, ident)))
+ flat_fields.extend(aliases.iter().map(|alias| (alias, ident)));
}
let field_strs: &Vec<_> = &flat_fields.iter().map(|(name, _)| name).collect();
@@ -2285,7 +2290,7 @@ fn deserialize_identifier(
};
let visit_borrowed = if fallthrough_borrowed.is_some() || collect_other_fields {
- let fallthrough_borrowed_arm = fallthrough_borrowed.as_ref().unwrap_or(&fallthrough_arm);
+ let fallthrough_borrowed_arm = fallthrough_borrowed.as_ref().unwrap_or(fallthrough_arm);
Some(quote! {
fn visit_borrowed_str<__E>(self, __value: &'de str) -> _serde::__private::Result<Self::Value, __E>
where
@@ -2883,44 +2888,61 @@ fn wrap_deserialize_variant_with(
variant: &Variant,
deserialize_with: &syn::ExprPath,
) -> (TokenStream, TokenStream, TokenStream) {
- let this = &params.this;
- let variant_ident = &variant.ident;
-
let field_tys = variant.fields.iter().map(|field| field.ty);
let (wrapper, wrapper_ty) =
wrap_deserialize_with(params, &quote!((#(#field_tys),*)), deserialize_with);
+ let unwrap_fn = unwrap_to_variant_closure(params, variant, true);
+
+ (wrapper, wrapper_ty, unwrap_fn)
+}
+
+// Generates closure that converts single input parameter to the final value.
+fn unwrap_to_variant_closure(
+ params: &Parameters,
+ variant: &Variant,
+ with_wrapper: bool,
+) -> TokenStream {
+ let this = &params.this;
+ let variant_ident = &variant.ident;
+
+ let (arg, wrapper) = if with_wrapper {
+ (quote! { __wrap }, quote! { __wrap.value })
+ } else {
+ let field_tys = variant.fields.iter().map(|field| field.ty);
+ (quote! { __wrap: (#(#field_tys),*) }, quote! { __wrap })
+ };
+
let field_access = (0..variant.fields.len()).map(|n| {
Member::Unnamed(Index {
index: n as u32,
span: Span::call_site(),
})
});
- let unwrap_fn = match variant.style {
+
+ match variant.style {
Style::Struct if variant.fields.len() == 1 => {
let member = &variant.fields[0].member;
quote! {
- |__wrap| #this::#variant_ident { #member: __wrap.value }
+ |#arg| #this::#variant_ident { #member: #wrapper }
}
}
Style::Struct => {
let members = variant.fields.iter().map(|field| &field.member);
quote! {
- |__wrap| #this::#variant_ident { #(#members: __wrap.value.#field_access),* }
+ |#arg| #this::#variant_ident { #(#members: #wrapper.#field_access),* }
}
}
Style::Tuple => quote! {
- |__wrap| #this::#variant_ident(#(__wrap.value.#field_access),*)
+ |#arg| #this::#variant_ident(#(#wrapper.#field_access),*)
},
Style::Newtype => quote! {
- |__wrap| #this::#variant_ident(__wrap.value)
+ |#arg| #this::#variant_ident(#wrapper)
},
Style::Unit => quote! {
- |__wrap| #this::#variant_ident
+ |#arg| #this::#variant_ident
},
- };
-
- (wrapper, wrapper_ty, unwrap_fn)
+ }
}
fn expr_is_missing(field: &Field, cattrs: &attr::Container) -> Fragment {
diff --git a/src/dummy.rs b/src/dummy.rs
index 9a4e5f0..29de260 100644
--- a/src/dummy.rs
+++ b/src/dummy.rs
@@ -23,7 +23,7 @@ pub fn wrap_in_const(
use #path as _serde;
},
None => quote! {
- #[allow(rust_2018_idioms, clippy::useless_attribute)]
+ #[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde;
},
};
diff --git a/src/internals/ast.rs b/src/internals/ast.rs
index 1afdaee..2a6950b 100644
--- a/src/internals/ast.rs
+++ b/src/internals/ast.rs
@@ -23,7 +23,7 @@ pub struct Container<'a> {
/// The fields of a struct or enum.
///
-/// Analagous to `syn::Data`.
+/// Analogous to `syn::Data`.
pub enum Data<'a> {
Enum(Vec<Variant<'a>>),
Struct(Style, Vec<Field<'a>>),
diff --git a/src/internals/attr.rs b/src/internals/attr.rs
index dcc4bf8..13f5525 100644
--- a/src/internals/attr.rs
+++ b/src/internals/attr.rs
@@ -556,7 +556,7 @@ impl Container {
// Parse `#[serde(crate = "foo")]`
Meta(NameValue(m)) if m.path == CRATE => {
if let Ok(path) = parse_lit_into_path(cx, CRATE, &m.lit) {
- serde_path.set(&m.path, path)
+ serde_path.set(&m.path, path);
}
}
@@ -1609,7 +1609,7 @@ fn get_lit_str2<'a>(
fn parse_lit_into_path(cx: &Ctxt, attr_name: Symbol, lit: &syn::Lit) -> Result<syn::Path, ()> {
let string = get_lit_str(cx, attr_name, lit)?;
parse_lit_str(string).map_err(|_| {
- cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value()))
+ cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value()));
})
}
@@ -1620,7 +1620,7 @@ fn parse_lit_into_expr_path(
) -> Result<syn::ExprPath, ()> {
let string = get_lit_str(cx, attr_name, lit)?;
parse_lit_str(string).map_err(|_| {
- cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value()))
+ cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value()));
})
}
@@ -1649,7 +1649,7 @@ fn parse_lit_into_ty(cx: &Ctxt, attr_name: Symbol, lit: &syn::Lit) -> Result<syn
cx.error_spanned_by(
lit,
format!("failed to parse type: {} = {:?}", attr_name, string.value()),
- )
+ );
})
}
diff --git a/src/internals/check.rs b/src/internals/check.rs
index 30ede1c..0e2484a 100644
--- a/src/internals/check.rs
+++ b/src/internals/check.rs
@@ -260,7 +260,7 @@ fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
cx.error_spanned_by(
cont.original,
format!("variant field name `{}` conflicts with internal tag", tag),
- )
+ );
};
for variant in variants {
@@ -396,7 +396,7 @@ fn member_message(member: &Member) -> String {
}
fn allow_transparent(field: &Field, derive: Derive) -> bool {
- if let Type::Path(ty) = ungroup(&field.ty) {
+ if let Type::Path(ty) = ungroup(field.ty) {
if let Some(seg) = ty.path.segments.last() {
if seg.ident == "PhantomData" {
return false;
diff --git a/src/lib.rs b/src/lib.rs
index f4a93ae..8079bb6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -13,13 +13,18 @@
//!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
-#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.123")]
+#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.136")]
#![allow(unknown_lints, bare_trait_objects)]
-#![deny(clippy::all, clippy::pedantic)]
// Ignored clippy lints
#![allow(
+ // clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054
+ clippy::branches_sharing_code,
clippy::cognitive_complexity,
+ // clippy bug: https://github.com/rust-lang/rust-clippy/issues/7575
+ clippy::collapsible_match,
clippy::enum_variant_names,
+ // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797
+ clippy::manual_map,
clippy::match_like_matches_macro,
clippy::needless_pass_by_value,
clippy::too_many_arguments,
@@ -35,11 +40,14 @@
clippy::checked_conversions,
clippy::doc_markdown,
clippy::enum_glob_use,
- clippy::filter_map,
clippy::indexing_slicing,
clippy::items_after_statements,
+ clippy::let_underscore_drop,
+ clippy::manual_assert,
clippy::map_err_ignore,
clippy::match_same_arms,
+ // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6984
+ clippy::match_wildcard_for_single_variants,
clippy::module_name_repetitions,
clippy::must_use_candidate,
clippy::option_if_let_else,
diff --git a/src/pretend.rs b/src/pretend.rs
index 955ce3d..3af6a66 100644
--- a/src/pretend.rs
+++ b/src/pretend.rs
@@ -1,7 +1,7 @@
-use proc_macro2::{Span, TokenStream};
-use syn::Ident;
+use proc_macro2::TokenStream;
+use quote::format_ident;
-use internals::ast::{Container, Data, Field, Style};
+use internals::ast::{Container, Data, Field, Style, Variant};
// Suppress dead_code warnings that would otherwise appear when using a remote
// derive. Other than this pretend code, a struct annotated with remote derive
@@ -20,8 +20,8 @@ use internals::ast::{Container, Data, Field, Style};
// 8 | enum EnumDef { V }
// | ^
//
-pub fn pretend_used(cont: &Container) -> TokenStream {
- let pretend_fields = pretend_fields_used(cont);
+pub fn pretend_used(cont: &Container, is_packed: bool) -> TokenStream {
+ let pretend_fields = pretend_fields_used(cont, is_packed);
let pretend_variants = pretend_variants_used(cont);
quote! {
@@ -32,49 +32,117 @@ pub fn pretend_used(cont: &Container) -> TokenStream {
// For structs with named fields, expands to:
//
+// match None::<&T> {
+// Some(T { a: __v0, b: __v1 }) => {}
+// _ => {}
+// }
+//
+// For packed structs on sufficiently new rustc, expands to:
+//
+// match None::<&T> {
+// Some(__v @ T { a: _, b: _ }) => {
+// let _ = addr_of!(__v.a);
+// let _ = addr_of!(__v.b);
+// }
+// _ => {}
+// }
+//
+// For packed structs on older rustc, we assume Sized and !Drop, and expand to:
+//
// match None::<T> {
-// Some(T { a: ref __v0, b: ref __v1 }) => {}
+// Some(T { a: __v0, b: __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 }) => {}
+// match None::<&T> {
+// Some(T::A { a: __v0 }) => {}
+// Some(T::B { b: __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) -> TokenStream {
+fn pretend_fields_used(cont: &Container, is_packed: bool) -> TokenStream {
+ match &cont.data {
+ Data::Enum(variants) => pretend_fields_used_enum(cont, variants),
+ Data::Struct(Style::Struct, fields) => {
+ if is_packed {
+ pretend_fields_used_struct_packed(cont, fields)
+ } else {
+ pretend_fields_used_struct(cont, fields)
+ }
+ }
+ Data::Struct(_, _) => quote!(),
+ }
+}
+
+fn pretend_fields_used_struct(cont: &Container, fields: &[Field]) -> TokenStream {
+ let type_ident = &cont.ident;
+ let (_, ty_generics, _) = cont.generics.split_for_impl();
+
+ let members = fields.iter().map(|field| &field.member);
+ let placeholders = (0usize..).map(|i| format_ident!("__v{}", i));
+
+ quote! {
+ match _serde::__private::None::<&#type_ident #ty_generics> {
+ _serde::__private::Some(#type_ident { #(#members: #placeholders),* }) => {}
+ _ => {}
+ }
+ }
+}
+
+fn pretend_fields_used_struct_packed(cont: &Container, fields: &[Field]) -> TokenStream {
let type_ident = &cont.ident;
let (_, ty_generics, _) = cont.generics.split_for_impl();
- let patterns = match &cont.data {
- Data::Enum(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))
+ let members = fields.iter().map(|field| &field.member).collect::<Vec<_>>();
+
+ #[cfg(ptr_addr_of)]
+ {
+ quote! {
+ match _serde::__private::None::<&#type_ident #ty_generics> {
+ _serde::__private::Some(__v @ #type_ident { #(#members: _),* }) => {
+ #(
+ let _ = _serde::__private::ptr::addr_of!(__v.#members);
+ )*
}
- _ => None,
- })
- .collect::<Vec<_>>(),
- Data::Struct(Style::Struct, fields) => {
- let pat = struct_pattern(fields);
- vec![quote!(#type_ident #pat)]
+ _ => {}
+ }
}
- Data::Struct(_, _) => {
- return quote!();
+ }
+
+ #[cfg(not(ptr_addr_of))]
+ {
+ let placeholders = (0usize..).map(|i| format_ident!("__v{}", i));
+
+ quote! {
+ match _serde::__private::None::<#type_ident #ty_generics> {
+ _serde::__private::Some(#type_ident { #(#members: #placeholders),* }) => {}
+ _ => {}
+ }
}
- };
+ }
+}
+
+fn pretend_fields_used_enum(cont: &Container, variants: &[Variant]) -> TokenStream {
+ let type_ident = &cont.ident;
+ let (_, ty_generics, _) = cont.generics.split_for_impl();
+
+ let patterns = variants
+ .iter()
+ .filter_map(|variant| match variant.style {
+ Style::Struct => {
+ let variant_ident = &variant.ident;
+ let members = variant.fields.iter().map(|field| &field.member);
+ let placeholders = (0usize..).map(|i| format_ident!("__v{}", i));
+ Some(quote!(#type_ident::#variant_ident { #(#members: #placeholders),* }))
+ }
+ _ => None,
+ })
+ .collect::<Vec<_>>();
quote! {
- match _serde::__private::None::<#type_ident #ty_generics> {
+ match _serde::__private::None::<&#type_ident #ty_generics> {
#(
_serde::__private::Some(#patterns) => {}
)*
@@ -107,7 +175,7 @@ fn pretend_variants_used(cont: &Container) -> TokenStream {
let cases = variants.iter().map(|variant| {
let variant_ident = &variant.ident;
let placeholders = &(0..variant.fields.len())
- .map(|i| Ident::new(&format!("__v{}", i), Span::call_site()))
+ .map(|i| format_ident!("__v{}", i))
.collect::<Vec<_>>();
let pat = match variant.style {
@@ -131,10 +199,3 @@ fn pretend_variants_used(cont: &Container) -> TokenStream {
quote!(#(#cases)*)
}
-
-fn struct_pattern(fields: &[Field]) -> TokenStream {
- let members = fields.iter().map(|field| &field.member);
- let placeholders =
- (0..fields.len()).map(|i| Ident::new(&format!("__v{}", i), Span::call_site()));
- quote!({ #(#members: ref #placeholders),* })
-}
diff --git a/src/ser.rs b/src/ser.rs
index c663c3b..529a20d 100644
--- a/src/ser.rs
+++ b/src/ser.rs
@@ -30,7 +30,7 @@ pub fn expand_derive_serialize(
let impl_block = if let Some(remote) = cont.attrs.remote() {
let vis = &input.vis;
- let used = pretend::pretend_used(&cont);
+ let used = pretend::pretend_used(&cont, params.is_packed);
quote! {
impl #impl_generics #ident #ty_generics #where_clause {
#vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> #serde::__private::Result<__S::Ok, __S::Error>
@@ -1099,7 +1099,7 @@ fn serialize_struct_visitor(
let mut field_expr = if is_enum {
quote!(#member)
} else {
- get_member(params, field, &member)
+ get_member(params, field, member)
};
let key_expr = field.attrs.name().serialize_name();