Compare commits

...

48 Commits

Author SHA1 Message Date
David Tolnay 930401b0dd Release 1.0.217 2024-12-27 12:41:22 -08:00
Mingun cb6eaea151 Fix roundtrip inconsistency:
- deserialization of flatten unit variant is possible
- serialization of such variant gives Err("can only flatten structs and maps (got an enum)")
2024-12-27 08:21:07 +00:00
David Tolnay b6f339ca36 Resolve repr_packed_without_abi clippy lint in tests
warning: item uses `packed` representation without ABI-qualification
       --> test_suite/tests/test_gen.rs:774:5
        |
    772 |       #[repr(packed)]
        |              ------ `packed` representation set here
    773 |       #[allow(dead_code)]
    774 | /     struct Packed {
    775 | |         x: u8,
    776 | |         y: u16,
    777 | |     }
        | |_____^
        |
        = warning: unqualified `#[repr(packed)]` defaults to `#[repr(Rust, packed)]`, which has no stable ABI
        = help: qualify the desired ABI explicity via `#[repr(C, packed)]` or `#[repr(Rust, packed)]`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#repr_packed_without_abi
    note: the lint level is defined here
       --> test_suite/tests/test_gen.rs:5:9
        |
    5   | #![deny(warnings)]
        |         ^^^^^^^^
        = note: `#[warn(clippy::repr_packed_without_abi)]` implied by `#[warn(warnings)]`

    warning: item uses `packed` representation without ABI-qualification
       --> test_suite/tests/test_gen.rs:919:1
        |
    918 |   #[repr(packed)]
        |          ------ `packed` representation set here
    919 | / pub struct RemotePacked {
    920 | |     pub a: u16,
    921 | |     pub b: u32,
    922 | | }
        | |_^
        |
        = warning: unqualified `#[repr(packed)]` defaults to `#[repr(Rust, packed)]`, which has no stable ABI
        = help: qualify the desired ABI explicity via `#[repr(C, packed)]` or `#[repr(Rust, packed)]`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#repr_packed_without_abi

    warning: item uses `packed` representation without ABI-qualification
       --> test_suite/tests/test_gen.rs:927:1
        |
    925 |   #[repr(packed)]
        |          ------ `packed` representation set here
    926 |   #[serde(remote = "RemotePacked")]
    927 | / pub struct RemotePackedDef {
    928 | |     a: u16,
    929 | |     b: u32,
    930 | | }
        | |_^
        |
        = warning: unqualified `#[repr(packed)]` defaults to `#[repr(Rust, packed)]`, which has no stable ABI
        = help: qualify the desired ABI explicity via `#[repr(C, packed)]` or `#[repr(Rust, packed)]`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#repr_packed_without_abi

    warning: item uses `packed` representation without ABI-qualification
       --> test_suite/tests/test_gen.rs:937:1
        |
    936 |   #[repr(packed)]
        |          ------ `packed` representation set here
    937 | / pub struct RemotePackedNonCopy {
    938 | |     pub a: u16,
    939 | |     pub b: String,
    940 | | }
        | |_^
        |
        = warning: unqualified `#[repr(packed)]` defaults to `#[repr(Rust, packed)]`, which has no stable ABI
        = help: qualify the desired ABI explicity via `#[repr(C, packed)]` or `#[repr(Rust, packed)]`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#repr_packed_without_abi

    warning: item uses `packed` representation without ABI-qualification
       --> test_suite/tests/test_gen.rs:945:1
        |
    943 |   #[repr(packed)]
        |          ------ `packed` representation set here
    944 |   #[serde(remote = "RemotePackedNonCopy")]
    945 | / pub struct RemotePackedNonCopyDef {
    946 | |     a: u16,
    947 | |     b: String,
    948 | | }
        | |_^
        |
        = warning: unqualified `#[repr(packed)]` defaults to `#[repr(Rust, packed)]`, which has no stable ABI
        = help: qualify the desired ABI explicity via `#[repr(C, packed)]` or `#[repr(Rust, packed)]`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#repr_packed_without_abi
2024-12-26 18:33:33 -08:00
David Tolnay 2a5caea1a8 Merge pull request #2872 from dtolnay/ehpersonality
Drop #[lang = "eh_personality"] from no-std test
2024-12-20 04:33:24 -08:00
David Tolnay b9f93f99aa Add no-std CI on stable compiler 2024-12-20 04:30:14 -08:00
David Tolnay eb5cd476ba Drop #[lang = "eh_personality"] from no-std test 2024-12-20 04:28:35 -08:00
David Tolnay 8478a3b7dd Merge pull request #2871 from dtolnay/nostdstart
Replace #[start] with extern fn main
2024-12-20 04:28:27 -08:00
David Tolnay dbb909136e Replace #[start] with extern fn main 2024-12-20 04:20:26 -08:00
David Tolnay ad8dd4148b Release 1.0.216 2024-12-10 18:05:39 -08:00
David Tolnay f91d2ed9ae Merge pull request #2868 from dtolnay/automaticallyderived
Mark all generated trait impls as #[automatically_derived]
2024-12-10 18:04:42 -08:00
David Tolnay 9497463718 Mark all generated trait impls as #[automatically_derived] 2024-12-10 17:57:05 -08:00
Oli Scherer 46e9ecfcdd Merge pull request #2866 from tdittr/mark-visitors-as-generated
Mark generated `impl de::Visitor` blocks as `#[automatically_derived]`
2024-12-09 11:58:24 +01:00
Tamme Dittrich e9c399c822 Mark generated impl de::Visitor blocks as #[automatically_derived]
This hides the generated visitors and field visitors from code
coverage.
2024-12-05 17:26:13 +01:00
David Tolnay b9dbfcb4ac Switch out fnv in favor of foldhash in test 2024-11-16 12:24:05 -08:00
David Tolnay c270e27a4d Use BuildHasher instead of Hasher in collection macros 2024-11-16 12:23:34 -08:00
David Tolnay 0307f604ea Resolve question_mark clippy lint in build script
warning: this `match` expression can be replaced with `?`
       --> serde/build.rs:111:17
        |
    111 |       let rustc = match env::var_os("RUSTC") {
        |  _________________^
    112 | |         Some(rustc) => rustc,
    113 | |         None => return None,
    114 | |     };
        | |_____^ help: try instead: `env::var_os("RUSTC")?`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#question_mark
        = note: `-W clippy::question-mark` implied by `-W clippy::all`
        = help: to override `-W clippy::all` add `#[allow(clippy::question_mark)]`

    warning: this `match` expression can be replaced with `?`
       --> serde/build.rs:131:16
        |
    131 |       let next = match pieces.next() {
        |  ________________^
    132 | |         Some(next) => next,
    133 | |         None => return None,
    134 | |     };
        | |_____^ help: try instead: `pieces.next()?`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#question_mark
2024-11-15 18:57:00 -08:00
David Tolnay 8939af48fe Release 1.0.215 2024-11-11 13:03:35 -08:00
David Tolnay fa5d58cd00 Use ui test syntax that does not interfere with rustfmt 2024-11-10 23:50:37 -08:00
David Tolnay 1a3cf4b3c1 Update PR 2562 ui tests 2024-11-10 23:46:31 -08:00
David Tolnay 7d96352e96 Merge pull request #2857 from dtolnay/collide
Revert the colliding aliases hard error (PRs #2562 & #2853)
2024-11-10 23:37:01 -08:00
David Tolnay 111ecc5d8c Update ui tests for warning on colliding aliases 2024-11-10 23:31:55 -08:00
David Tolnay edd6fe954b Revert "Add checks for conflicts for aliases"
This reverts commit 5f9fffa53e.
2024-11-10 23:31:55 -08:00
David Tolnay a20e9249c5 Revert "pacify clippy"
This reverts commit 951ca5ace0.
2024-11-10 23:31:55 -08:00
David Tolnay b1353a99cd Merge pull request #2856 from dtolnay/dename
Produce a separate warning for every colliding name
2024-11-10 23:31:44 -08:00
David Tolnay c59e876bb3 Produce a separate warning for every colliding name 2024-11-10 23:23:09 -08:00
David Tolnay 7f1e697c0d Merge pull request #2855 from dtolnay/namespan
Produce unreachable_patterns warning when deserialization names collide
2024-11-10 23:21:46 -08:00
David Tolnay 373edcd055 Keep track of a span for alias strings 2024-11-10 23:08:40 -08:00
David Tolnay f0b5c4f857 Move MultiName to a new module 2024-11-10 22:32:49 -08:00
David Tolnay 3035d4fa34 Rename Name -> MultiName 2024-11-10 22:32:49 -08:00
David Tolnay 60ac737439 Prevent upload-artifact step from causing CI failure
This step has been failing way more than reasonable across my various repos.

    With the provided path, there will be 1 file uploaded
    Artifact name is valid!
    Root directory input is valid!
    Attempt 1 of 5 failed with error: Request timeout: /twirp/github.actions.results.api.v1.ArtifactService/CreateArtifact. Retrying request in 3000 ms...
    Attempt 2 of 5 failed with error: Request timeout: /twirp/github.actions.results.api.v1.ArtifactService/CreateArtifact. Retrying request in 6029 ms...
    Attempt 3 of 5 failed with error: Request timeout: /twirp/github.actions.results.api.v1.ArtifactService/CreateArtifact. Retrying request in 8270 ms...
    Attempt 4 of 5 failed with error: Request timeout: /twirp/github.actions.results.api.v1.ArtifactService/CreateArtifact. Retrying request in 12577 ms...
    Error: Failed to CreateArtifact: Failed to make request after 5 attempts: Request timeout: /twirp/github.actions.results.api.v1.ArtifactService/CreateArtifact
2024-11-08 21:45:52 -05:00
Oli Scherer a95b0d301e Merge pull request #2853 from serde-rs/oli-obk-patch-1
pacify clippy
2024-11-01 15:25:08 +01:00
Oli Scherer 951ca5ace0 pacify clippy 2024-11-01 15:20:51 +01:00
Oli Scherer adf05a5bf6 Merge pull request #2562 from Mingun/alias-check
Add checks for conflicts for aliases
2024-11-01 15:14:15 +01:00
David Tolnay 418062165f Release 1.0.214 2024-10-28 09:41:44 -07:00
David Tolnay 210373b3b6 Merge pull request #2568 from Mingun/into_deserializer-for-deserializers
Implement `IntoDeserializer` for all `Deserializer`s in `serde::de::value` module
2024-10-28 09:40:57 -07:00
Mingun 5f9fffa53e Add checks for conflicts for aliases
- Check that alias is not the same as name of other field (it still can be the name of owning field/variant)
- Check that aliases are unique, i. e. two different fields does not use the same alias
2024-10-25 19:18:31 +05:00
Mingun 9cda015733 Implement IntoDeserializer for all Deserializers in serde::de::value module
Unfortunately, blanket implementation IntoDeserializer for Deserializer is impossible
right now because this would be a breaking change. External crates may have this
such implementation (and serde_json actually have it for Value)
2024-10-25 19:17:50 +05:00
David Tolnay 58a8d22931 Release 1.0.213 2024-10-22 11:14:58 -07:00
David Tolnay ef0ed22593 Merge pull request #2847 from dtolnay/newtypewith
Hygiene for macro-generated newtype struct deserialization with `with` attr
2024-10-22 11:14:18 -07:00
David Tolnay 79925ac394 Ignore dead_code warning in regression test
warning: field `0` is never read
      --> test_suite/tests/regression/issue2846.rs:8:45
       |
    8  |         pub struct S(#[serde(with = $with)] i32);
       |                    - field in this struct   ^^^
    ...
    12 | declare_in_macro!("with");
       | ------------------------- in this macro invocation
       |
       = help: consider removing this field
       = note: `#[warn(dead_code)]` on by default
       = note: this warning originates in the macro `declare_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
2024-10-22 11:10:52 -07:00
David Tolnay b60e4092ec Hygiene for macro-generated newtype struct deserialization with 'with' attr 2024-10-22 11:10:40 -07:00
David Tolnay fdc36e5c06 Add regression test for issue 2846
error[E0425]: cannot find value `__e` in this scope
      --> test_suite/tests/regression/issue2846.rs:12:19
       |
    12 | declare_in_macro!("with");
       |                   ^^^^^^ not found in this scope
2024-10-22 11:08:22 -07:00
David Tolnay 49e11ce1ba Ignore trivially_copy_pass_by_ref pedantic clippy lint in test
warning: this argument (4 byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
      --> test_suite/tests/regression/issue2844.rs:18:28
       |
    18 |     pub fn serialize<S>(_: &i32, _: S) -> Result<S::Ok, S::Error>
       |                            ^^^^ help: consider passing by value instead: `i32`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref
       = note: `-W clippy::trivially-copy-pass-by-ref` implied by `-W clippy::pedantic`
       = help: to override `-W clippy::pedantic` add `#[allow(clippy::trivially_copy_pass_by_ref)]`
2024-10-22 09:56:12 -07:00
David Tolnay 7ae1b5f8f3 Release 1.0.212 2024-10-22 09:41:55 -07:00
David Tolnay 1ac054b34a Merge pull request #2845 from dtolnay/withlocal
Fix hygiene of macro-generated local variable accesses in serde(with) wrappers
2024-10-22 09:41:27 -07:00
David Tolnay 1e36ef551d Fix hygiene of macro-generated local variable accesses in serde(with) wrappers 2024-10-22 09:38:06 -07:00
David Tolnay 0058c7226e Add regression test for issue 2844
error[E0424]: expected value, found module `self`
      --> test_suite/tests/regression/issue2844.rs:13:19
       |
    5  |         #[derive(Serialize, Deserialize)]
       |                  --------- this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters
    ...
    13 | declare_in_macro!("with");
       |                   ^^^^^^ `self` value is a keyword only available in methods with a `self` parameter

    error[E0425]: cannot find value `__s` in this scope
      --> test_suite/tests/regression/issue2844.rs:13:19
       |
    13 | declare_in_macro!("with");
       |                   ^^^^^^ not found in this scope

    error[E0425]: cannot find value `__deserializer` in this scope
      --> test_suite/tests/regression/issue2844.rs:13:19
       |
    13 | declare_in_macro!("with");
       |                   ^^^^^^ not found in this scope
2024-10-22 09:37:58 -07:00
David Tolnay 29d4f3e887 Format regression tests with rustfmt 2024-10-22 09:28:10 -07:00
30 changed files with 782 additions and 170 deletions
+2
View File
@@ -26,6 +26,7 @@ jobs:
with:
name: Cargo.lock
path: Cargo.lock
continue-on-error: true
windows:
name: Test suite (windows)
@@ -51,6 +52,7 @@ jobs:
toolchain: ${{matrix.rust}}
- run: cd serde && cargo build --features rc
- run: cd serde && cargo build --no-default-features
- run: cd test_suite/no_std && cargo build
nightly:
name: Rust nightly ${{matrix.os == 'windows' && '(windows)' || ''}}
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "serde"
version = "1.0.211"
version = "1.0.217"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
build = "build.rs"
categories = ["encoding", "no-std", "no-std::no-alloc"]
@@ -37,7 +37,7 @@ rustdoc-args = ["--generate-link-to-definition"]
# is compatible with exactly one serde release because the generated code
# involves nonpublic APIs which are not bound by semver.
[target.'cfg(any())'.dependencies]
serde_derive = { version = "=1.0.211", path = "../serde_derive" }
serde_derive = { version = "=1.0.217", path = "../serde_derive" }
### FEATURES #################################################################
+5 -23
View File
@@ -1,6 +1,6 @@
use std::env;
use std::process::Command;
use std::str::{self, FromStr};
use std::str;
// The rustc-cfg strings below are *not* public API. Please let us know by
// opening a GitHub issue if your build environment requires some way to enable
@@ -108,30 +108,12 @@ fn main() {
}
fn rustc_minor_version() -> Option<u32> {
let rustc = match env::var_os("RUSTC") {
Some(rustc) => rustc,
None => return None,
};
let output = match Command::new(rustc).arg("--version").output() {
Ok(output) => output,
Err(_) => return None,
};
let version = match str::from_utf8(&output.stdout) {
Ok(version) => version,
Err(_) => return None,
};
let rustc = env::var_os("RUSTC")?;
let output = Command::new(rustc).arg("--version").output().ok()?;
let version = str::from_utf8(&output.stdout).ok()?;
let mut pieces = version.split('.');
if pieces.next() != Some("rustc 1") {
return None;
}
let next = match pieces.next() {
Some(next) => next,
None => return None,
};
u32::from_str(next).ok()
pieces.next()?.parse().ok()
}
+174
View File
@@ -175,6 +175,17 @@ where
}
}
impl<'de, E> IntoDeserializer<'de, E> for UnitDeserializer<E>
where
E: de::Error,
{
type Deserializer = Self;
fn into_deserializer(self) -> Self {
self
}
}
impl<E> Debug for UnitDeserializer<E> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.debug_struct("UnitDeserializer").finish()
@@ -225,6 +236,18 @@ where
}
}
#[cfg(feature = "unstable")]
impl<'de, E> IntoDeserializer<'de, E> for NeverDeserializer<E>
where
E: de::Error,
{
type Deserializer = Self;
fn into_deserializer(self) -> Self {
self
}
}
////////////////////////////////////////////////////////////////////////////////
macro_rules! primitive_deserializer {
@@ -279,6 +302,17 @@ macro_rules! primitive_deserializer {
}
}
impl<'de, E> IntoDeserializer<'de, E> for $name<E>
where
E: de::Error,
{
type Deserializer = Self;
fn into_deserializer(self) -> Self {
self
}
}
impl<E> Debug for $name<E> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter
@@ -369,6 +403,17 @@ where
}
}
impl<'de, E> IntoDeserializer<'de, E> for U32Deserializer<E>
where
E: de::Error,
{
type Deserializer = Self;
fn into_deserializer(self) -> Self {
self
}
}
impl<'de, E> de::EnumAccess<'de> for U32Deserializer<E>
where
E: de::Error,
@@ -458,6 +503,17 @@ where
}
}
impl<'de, 'a, E> IntoDeserializer<'de, E> for StrDeserializer<'a, E>
where
E: de::Error,
{
type Deserializer = Self;
fn into_deserializer(self) -> Self {
self
}
}
impl<'de, 'a, E> de::EnumAccess<'de> for StrDeserializer<'a, E>
where
E: de::Error,
@@ -537,6 +593,17 @@ where
}
}
impl<'de, E> IntoDeserializer<'de, E> for BorrowedStrDeserializer<'de, E>
where
E: de::Error,
{
type Deserializer = Self;
fn into_deserializer(self) -> Self {
self
}
}
impl<'de, E> de::EnumAccess<'de> for BorrowedStrDeserializer<'de, E>
where
E: de::Error,
@@ -640,6 +707,18 @@ where
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, E> IntoDeserializer<'de, E> for StringDeserializer<E>
where
E: de::Error,
{
type Deserializer = Self;
fn into_deserializer(self) -> Self {
self
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, E> de::EnumAccess<'de> for StringDeserializer<E>
where
@@ -748,6 +827,18 @@ where
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, 'a, E> IntoDeserializer<'de, E> for CowStrDeserializer<'a, E>
where
E: de::Error,
{
type Deserializer = Self;
fn into_deserializer(self) -> Self {
self
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, 'a, E> de::EnumAccess<'de> for CowStrDeserializer<'a, E>
where
@@ -825,6 +916,17 @@ where
}
}
impl<'de, 'a, E> IntoDeserializer<'de, E> for BytesDeserializer<'a, E>
where
E: de::Error,
{
type Deserializer = Self;
fn into_deserializer(self) -> Self {
self
}
}
impl<'a, E> Debug for BytesDeserializer<'a, E> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter
@@ -873,6 +975,17 @@ where
}
}
impl<'de, E> IntoDeserializer<'de, E> for BorrowedBytesDeserializer<'de, E>
where
E: de::Error,
{
type Deserializer = Self;
fn into_deserializer(self) -> Self {
self
}
}
impl<'de, E> Debug for BorrowedBytesDeserializer<'de, E> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter
@@ -952,6 +1065,19 @@ where
}
}
impl<'de, I, T, E> IntoDeserializer<'de, E> for SeqDeserializer<I, E>
where
I: Iterator<Item = T>,
T: IntoDeserializer<'de, E>,
E: de::Error,
{
type Deserializer = Self;
fn into_deserializer(self) -> Self {
self
}
}
impl<'de, I, T, E> de::SeqAccess<'de> for SeqDeserializer<I, E>
where
I: Iterator<Item = T>,
@@ -1083,6 +1209,17 @@ where
}
}
impl<'de, A> IntoDeserializer<'de, A::Error> for SeqAccessDeserializer<A>
where
A: de::SeqAccess<'de>,
{
type Deserializer = Self;
fn into_deserializer(self) -> Self {
self
}
}
////////////////////////////////////////////////////////////////////////////////
/// A deserializer that iterates over a map.
@@ -1197,6 +1334,21 @@ where
}
}
impl<'de, I, E> IntoDeserializer<'de, E> for MapDeserializer<'de, I, E>
where
I: Iterator,
I::Item: private::Pair,
First<I::Item>: IntoDeserializer<'de, E>,
Second<I::Item>: IntoDeserializer<'de, E>,
E: de::Error,
{
type Deserializer = Self;
fn into_deserializer(self) -> Self {
self
}
}
impl<'de, I, E> de::MapAccess<'de> for MapDeserializer<'de, I, E>
where
I: Iterator,
@@ -1498,6 +1650,17 @@ where
}
}
impl<'de, A> IntoDeserializer<'de, A::Error> for MapAccessDeserializer<A>
where
A: de::MapAccess<'de>,
{
type Deserializer = Self;
fn into_deserializer(self) -> Self {
self
}
}
impl<'de, A> de::EnumAccess<'de> for MapAccessDeserializer<A>
where
A: de::MapAccess<'de>,
@@ -1551,6 +1714,17 @@ where
}
}
impl<'de, A> IntoDeserializer<'de, A::Error> for EnumAccessDeserializer<A>
where
A: de::EnumAccess<'de>,
{
type Deserializer = Self;
fn into_deserializer(self) -> Self {
self
}
}
////////////////////////////////////////////////////////////////////////////////
mod private {
+1 -1
View File
@@ -95,7 +95,7 @@
////////////////////////////////////////////////////////////////////////////////
// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.211")]
#![doc(html_root_url = "https://docs.rs/serde/1.0.217")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Show which crate feature enables conditionally compiled APIs in documentation.
+4 -2
View File
@@ -54,6 +54,7 @@ enum Unsupported {
Sequence,
Tuple,
TupleStruct,
#[cfg(not(any(feature = "std", feature = "alloc")))]
Enum,
}
@@ -70,6 +71,7 @@ impl Display for Unsupported {
Unsupported::Sequence => formatter.write_str("a sequence"),
Unsupported::Tuple => formatter.write_str("a tuple"),
Unsupported::TupleStruct => formatter.write_str("a tuple struct"),
#[cfg(not(any(feature = "std", feature = "alloc")))]
Unsupported::Enum => formatter.write_str("an enum"),
}
}
@@ -1095,9 +1097,9 @@ where
self,
_: &'static str,
_: u32,
_: &'static str,
variant: &'static str,
) -> Result<Self::Ok, Self::Error> {
Err(Self::bad_type(Unsupported::Enum))
self.0.serialize_entry(variant, &())
}
fn serialize_newtype_struct<T>(
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_derive"
version = "1.0.211"
version = "1.0.217"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
categories = ["no-std", "no-std::no-alloc"]
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
+38 -13
View File
@@ -1,5 +1,6 @@
use crate::fragment::{Expr, Fragment, Match, Stmts};
use crate::internals::ast::{Container, Data, Field, Style, Variant};
use crate::internals::name::Name;
use crate::internals::{attr, replace_receiver, ungroup, Ctxt, Derive};
use crate::{bound, dummy, pretend, this};
use proc_macro2::{Literal, Span, TokenStream};
@@ -32,6 +33,7 @@ pub fn expand_derive_deserialize(input: &mut syn::DeriveInput) -> syn::Result<To
let vis = &input.vis;
let used = pretend::pretend_used(&cont, params.is_packed);
quote! {
#[automatically_derived]
impl #de_impl_generics #ident #ty_generics #where_clause {
#vis fn deserialize<__D>(__deserializer: __D) -> #serde::__private::Result<#remote #ty_generics, __D::Error>
where
@@ -423,6 +425,7 @@ fn deserialize_unit_struct(params: &Parameters, cattrs: &attr::Container) -> Fra
lifetime: _serde::__private::PhantomData<&#delife ()>,
}
#[automatically_derived]
impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause {
type Value = #this_type #ty_generics;
@@ -558,6 +561,7 @@ fn deserialize_tuple(
lifetime: _serde::__private::PhantomData<&#delife ()>,
}
#[automatically_derived]
impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause {
type Value = #this_type #ty_generics;
@@ -657,6 +661,7 @@ fn deserialize_tuple_in_place(
lifetime: _serde::__private::PhantomData<&#delife ()>,
}
#[automatically_derived]
impl #in_place_impl_generics _serde::de::Visitor<#delife> for __Visitor #in_place_ty_generics #where_clause {
type Value = ();
@@ -875,13 +880,14 @@ fn deserialize_newtype_struct(
) -> TokenStream {
let delife = params.borrowed.de_lifetime();
let field_ty = field.ty;
let deserializer_var = quote!(__e);
let value = match field.attrs.deserialize_with() {
None => {
let span = field.original.span();
let func = quote_spanned!(span=> <#field_ty as _serde::Deserialize>::deserialize);
quote! {
#func(__e)?
#func(#deserializer_var)?
}
}
Some(path) => {
@@ -890,7 +896,7 @@ fn deserialize_newtype_struct(
// on the #[serde(with = "...")]
// ^^^^^
quote_spanned! {path.span()=>
#path(__e)?
#path(#deserializer_var)?
}
}
};
@@ -906,7 +912,7 @@ fn deserialize_newtype_struct(
quote! {
#[inline]
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::__private::Result<Self::Value, __E::Error>
fn visit_newtype_struct<__E>(self, #deserializer_var: __E) -> _serde::__private::Result<Self::Value, __E::Error>
where
__E: _serde::Deserializer<#delife>,
{
@@ -1018,6 +1024,7 @@ fn deserialize_struct(
let visitor_seed = match form {
StructForm::ExternallyTagged(..) if has_flatten => Some(quote! {
#[automatically_derived]
impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Visitor #de_ty_generics #where_clause {
type Value = #this_type #ty_generics;
@@ -1082,6 +1089,7 @@ fn deserialize_struct(
lifetime: _serde::__private::PhantomData<&#delife ()>,
}
#[automatically_derived]
impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause {
type Value = #this_type #ty_generics;
@@ -1163,6 +1171,7 @@ fn deserialize_struct_in_place(
lifetime: _serde::__private::PhantomData<&#delife ()>,
}
#[automatically_derived]
impl #in_place_impl_generics _serde::de::Visitor<#delife> for __Visitor #in_place_ty_generics #where_clause {
type Value = ();
@@ -1336,6 +1345,7 @@ fn deserialize_externally_tagged_enum(
lifetime: _serde::__private::PhantomData<&#delife ()>,
}
#[automatically_derived]
impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause {
type Value = #this_type #ty_generics;
@@ -1597,6 +1607,7 @@ fn deserialize_adjacently_tagged_enum(
lifetime: _serde::__private::PhantomData<&#delife ()>,
}
#[automatically_derived]
impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Seed #de_ty_generics #where_clause {
type Value = #this_type #ty_generics;
@@ -1616,6 +1627,7 @@ fn deserialize_adjacently_tagged_enum(
lifetime: _serde::__private::PhantomData<&#delife ()>,
}
#[automatically_derived]
impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause {
type Value = #this_type #ty_generics;
@@ -2001,7 +2013,7 @@ fn deserialize_untagged_newtype_variant(
struct FieldWithAliases<'a> {
ident: Ident,
aliases: &'a BTreeSet<String>,
aliases: &'a BTreeSet<Name>,
}
fn deserialize_generated_identifier(
@@ -2044,12 +2056,14 @@ fn deserialize_generated_identifier(
#[doc(hidden)]
struct __FieldVisitor;
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field #lifetime;
#visitor_impl
}
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for __Field #lifetime {
#[inline]
fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result<Self, __D::Error>
@@ -2188,6 +2202,7 @@ fn deserialize_custom_identifier(
lifetime: _serde::__private::PhantomData<&#delife ()>,
}
#[automatically_derived]
impl #de_impl_generics _serde::de::Visitor<#delife> for __FieldVisitor #de_ty_generics #where_clause {
type Value = #this_type #ty_generics;
@@ -2215,7 +2230,11 @@ fn deserialize_identifier(
let ident = &field.ident;
let aliases = field.aliases;
// `aliases` also contains a main name
quote!(#(#aliases)|* => _serde::__private::Ok(#this_value::#ident))
quote! {
#(
#aliases => _serde::__private::Ok(#this_value::#ident),
)*
}
});
let bytes_mapping = deserialized_fields.iter().map(|field| {
let ident = &field.ident;
@@ -2223,8 +2242,12 @@ fn deserialize_identifier(
let aliases = field
.aliases
.iter()
.map(|alias| Literal::byte_string(alias.as_bytes()));
quote!(#(#aliases)|* => _serde::__private::Ok(#this_value::#ident))
.map(|alias| Literal::byte_string(alias.value.as_bytes()));
quote! {
#(
#aliases => _serde::__private::Ok(#this_value::#ident),
)*
}
});
let expecting = expecting.unwrap_or(if is_variant {
@@ -2422,7 +2445,7 @@ fn deserialize_identifier(
__E: _serde::de::Error,
{
match __value {
#(#str_mapping,)*
#(#str_mapping)*
_ => {
#value_as_borrowed_str_content
#fallthrough_borrowed_arm
@@ -2435,7 +2458,7 @@ fn deserialize_identifier(
__E: _serde::de::Error,
{
match __value {
#(#bytes_mapping,)*
#(#bytes_mapping)*
_ => {
#bytes_to_str
#value_as_borrowed_bytes_content
@@ -2460,7 +2483,7 @@ fn deserialize_identifier(
__E: _serde::de::Error,
{
match __value {
#(#str_mapping,)*
#(#str_mapping)*
_ => {
#value_as_str_content
#fallthrough_arm
@@ -2473,7 +2496,7 @@ fn deserialize_identifier(
__E: _serde::de::Error,
{
match __value {
#(#bytes_mapping,)*
#(#bytes_mapping)*
_ => {
#bytes_to_str
#value_as_bytes_content
@@ -2882,13 +2905,14 @@ fn wrap_deserialize_with(
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime();
let deserializer_var = quote!(__deserializer);
// If #deserialize_with returns wrong type, error will be reported here (^^^^^).
// We attach span of the path to the function so it will be reported
// on the #[serde(with = "...")]
// ^^^^^
let value = quote_spanned! {deserialize_with.span()=>
#deserialize_with(__deserializer)?
#deserialize_with(#deserializer_var)?
};
let wrapper = quote! {
#[doc(hidden)]
@@ -2898,8 +2922,9 @@ fn wrap_deserialize_with(
lifetime: _serde::__private::PhantomData<&#delife ()>,
}
#[automatically_derived]
impl #de_impl_generics _serde::Deserialize<#delife> for __DeserializeWith #de_ty_generics #where_clause {
fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result<Self, __D::Error>
fn deserialize<__D>(#deserializer_var: __D) -> _serde::__private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<#delife>,
{
+48 -84
View File
@@ -1,3 +1,4 @@
use crate::internals::name::{MultiName, Name};
use crate::internals::symbol::*;
use crate::internals::{ungroup, Ctxt};
use proc_macro2::{Spacing, Span, TokenStream, TokenTree};
@@ -21,7 +22,7 @@ use syn::{parse_quote, token, Ident, Lifetime, Token};
pub use crate::internals::case::RenameRule;
struct Attr<'c, T> {
pub(crate) struct Attr<'c, T> {
cx: &'c Ctxt,
name: Symbol,
tokens: TokenStream,
@@ -62,7 +63,7 @@ impl<'c, T> Attr<'c, T> {
}
}
fn get(self) -> Option<T> {
pub(crate) fn get(self) -> Option<T> {
self.value
}
@@ -90,7 +91,7 @@ impl<'c> BoolAttr<'c> {
}
}
struct VecAttr<'c, T> {
pub(crate) struct VecAttr<'c, T> {
cx: &'c Ctxt,
name: Symbol,
first_dup_tokens: TokenStream,
@@ -125,63 +126,13 @@ impl<'c, T> VecAttr<'c, T> {
}
}
fn get(self) -> Vec<T> {
pub(crate) fn get(self) -> Vec<T> {
self.values
}
}
pub struct Name {
serialize: String,
serialize_renamed: bool,
deserialize: String,
deserialize_renamed: bool,
deserialize_aliases: BTreeSet<String>,
}
fn unraw(ident: &Ident) -> String {
ident.to_string().trim_start_matches("r#").to_owned()
}
impl Name {
fn from_attrs(
source_name: String,
ser_name: Attr<String>,
de_name: Attr<String>,
de_aliases: Option<VecAttr<String>>,
) -> Name {
let mut alias_set = BTreeSet::new();
if let Some(de_aliases) = de_aliases {
for alias_name in de_aliases.get() {
alias_set.insert(alias_name);
}
}
let ser_name = ser_name.get();
let ser_renamed = ser_name.is_some();
let de_name = de_name.get();
let de_renamed = de_name.is_some();
Name {
serialize: ser_name.unwrap_or_else(|| source_name.clone()),
serialize_renamed: ser_renamed,
deserialize: de_name.unwrap_or(source_name),
deserialize_renamed: de_renamed,
deserialize_aliases: alias_set,
}
}
/// Return the container name for the container when serializing.
pub fn serialize_name(&self) -> &str {
&self.serialize
}
/// Return the container name for the container when deserializing.
pub fn deserialize_name(&self) -> &str {
&self.deserialize
}
fn deserialize_aliases(&self) -> &BTreeSet<String> {
&self.deserialize_aliases
}
fn unraw(ident: &Ident) -> Ident {
Ident::new(ident.to_string().trim_start_matches("r#"), ident.span())
}
#[derive(Copy, Clone)]
@@ -203,7 +154,7 @@ impl RenameAllRules {
/// Represents struct or enum attribute information.
pub struct Container {
name: Name,
name: MultiName,
transparent: bool,
deny_unknown_fields: bool,
default: Default,
@@ -327,8 +278,8 @@ impl Container {
// #[serde(rename = "foo")]
// #[serde(rename(serialize = "foo", deserialize = "bar"))]
let (ser, de) = get_renames(cx, RENAME, &meta)?;
ser_name.set_opt(&meta.path, ser.as_ref().map(syn::LitStr::value));
de_name.set_opt(&meta.path, de.as_ref().map(syn::LitStr::value));
ser_name.set_opt(&meta.path, ser.as_ref().map(Name::from));
de_name.set_opt(&meta.path, de.as_ref().map(Name::from));
} else if meta.path == RENAME_ALL {
// #[serde(rename_all = "foo")]
// #[serde(rename_all(serialize = "foo", deserialize = "bar"))]
@@ -567,7 +518,7 @@ impl Container {
}
Container {
name: Name::from_attrs(unraw(&item.ident), ser_name, de_name, None),
name: MultiName::from_attrs(Name::from(&unraw(&item.ident)), ser_name, de_name, None),
transparent: transparent.get(),
deny_unknown_fields: deny_unknown_fields.get(),
default: default.get().unwrap_or(Default::None),
@@ -594,7 +545,7 @@ impl Container {
}
}
pub fn name(&self) -> &Name {
pub fn name(&self) -> &MultiName {
&self.name
}
@@ -781,7 +732,7 @@ fn decide_identifier(
/// Represents variant attribute information
pub struct Variant {
name: Name,
name: MultiName,
rename_all_rules: RenameAllRules,
ser_bound: Option<Vec<syn::WherePredicate>>,
de_bound: Option<Vec<syn::WherePredicate>>,
@@ -832,15 +783,15 @@ impl Variant {
// #[serde(rename = "foo")]
// #[serde(rename(serialize = "foo", deserialize = "bar"))]
let (ser, de) = get_multiple_renames(cx, &meta)?;
ser_name.set_opt(&meta.path, ser.as_ref().map(syn::LitStr::value));
ser_name.set_opt(&meta.path, ser.as_ref().map(Name::from));
for de_value in de {
de_name.set_if_none(de_value.value());
de_aliases.insert(&meta.path, de_value.value());
de_name.set_if_none(Name::from(&de_value));
de_aliases.insert(&meta.path, Name::from(&de_value));
}
} else if meta.path == ALIAS {
// #[serde(alias = "foo")]
if let Some(s) = get_lit_str(cx, ALIAS, &meta)? {
de_aliases.insert(&meta.path, s.value());
de_aliases.insert(&meta.path, Name::from(&s));
}
} else if meta.path == RENAME_ALL {
// #[serde(rename_all = "foo")]
@@ -947,7 +898,12 @@ impl Variant {
}
Variant {
name: Name::from_attrs(unraw(&variant.ident), ser_name, de_name, Some(de_aliases)),
name: MultiName::from_attrs(
Name::from(&unraw(&variant.ident)),
ser_name,
de_name,
Some(de_aliases),
),
rename_all_rules: RenameAllRules {
serialize: rename_all_ser_rule.get().unwrap_or(RenameRule::None),
deserialize: rename_all_de_rule.get().unwrap_or(RenameRule::None),
@@ -964,20 +920,23 @@ impl Variant {
}
}
pub fn name(&self) -> &Name {
pub fn name(&self) -> &MultiName {
&self.name
}
pub fn aliases(&self) -> &BTreeSet<String> {
pub fn aliases(&self) -> &BTreeSet<Name> {
self.name.deserialize_aliases()
}
pub fn rename_by_rules(&mut self, rules: RenameAllRules) {
if !self.name.serialize_renamed {
self.name.serialize = rules.serialize.apply_to_variant(&self.name.serialize);
self.name.serialize.value =
rules.serialize.apply_to_variant(&self.name.serialize.value);
}
if !self.name.deserialize_renamed {
self.name.deserialize = rules.deserialize.apply_to_variant(&self.name.deserialize);
self.name.deserialize.value = rules
.deserialize
.apply_to_variant(&self.name.deserialize.value);
}
self.name
.deserialize_aliases
@@ -1023,7 +982,7 @@ impl Variant {
/// Represents field attribute information
pub struct Field {
name: Name,
name: MultiName,
skip_serializing: bool,
skip_deserializing: bool,
skip_serializing_if: Option<syn::ExprPath>,
@@ -1082,8 +1041,11 @@ impl Field {
let mut flatten = BoolAttr::none(cx, FLATTEN);
let ident = match &field.ident {
Some(ident) => unraw(ident),
None => index.to_string(),
Some(ident) => Name::from(&unraw(ident)),
None => Name {
value: index.to_string(),
span: Span::call_site(),
},
};
if let Some(borrow_attribute) = attrs.and_then(|variant| variant.borrow.as_ref()) {
@@ -1119,15 +1081,15 @@ impl Field {
// #[serde(rename = "foo")]
// #[serde(rename(serialize = "foo", deserialize = "bar"))]
let (ser, de) = get_multiple_renames(cx, &meta)?;
ser_name.set_opt(&meta.path, ser.as_ref().map(syn::LitStr::value));
ser_name.set_opt(&meta.path, ser.as_ref().map(Name::from));
for de_value in de {
de_name.set_if_none(de_value.value());
de_aliases.insert(&meta.path, de_value.value());
de_name.set_if_none(Name::from(&de_value));
de_aliases.insert(&meta.path, Name::from(&de_value));
}
} else if meta.path == ALIAS {
// #[serde(alias = "foo")]
if let Some(s) = get_lit_str(cx, ALIAS, &meta)? {
de_aliases.insert(&meta.path, s.value());
de_aliases.insert(&meta.path, Name::from(&s));
}
} else if meta.path == DEFAULT {
if meta.input.peek(Token![=]) {
@@ -1290,7 +1252,7 @@ impl Field {
}
Field {
name: Name::from_attrs(ident, ser_name, de_name, Some(de_aliases)),
name: MultiName::from_attrs(ident, ser_name, de_name, Some(de_aliases)),
skip_serializing: skip_serializing.get(),
skip_deserializing: skip_deserializing.get(),
skip_serializing_if: skip_serializing_if.get(),
@@ -1306,20 +1268,22 @@ impl Field {
}
}
pub fn name(&self) -> &Name {
pub fn name(&self) -> &MultiName {
&self.name
}
pub fn aliases(&self) -> &BTreeSet<String> {
pub fn aliases(&self) -> &BTreeSet<Name> {
self.name.deserialize_aliases()
}
pub fn rename_by_rules(&mut self, rules: RenameAllRules) {
if !self.name.serialize_renamed {
self.name.serialize = rules.serialize.apply_to_field(&self.name.serialize);
self.name.serialize.value = rules.serialize.apply_to_field(&self.name.serialize.value);
}
if !self.name.deserialize_renamed {
self.name.deserialize = rules.deserialize.apply_to_field(&self.name.deserialize);
self.name.deserialize.value = rules
.deserialize
.apply_to_field(&self.name.deserialize.value);
}
self.name
.deserialize_aliases
@@ -1769,7 +1733,7 @@ fn is_primitive_path(path: &syn::Path, primitive: &str) -> bool {
// attribute on the field so there must be at least one borrowable lifetime.
fn borrowable_lifetimes(
cx: &Ctxt,
name: &str,
name: &Name,
field: &syn::Field,
) -> Result<BTreeSet<syn::Lifetime>, ()> {
let mut lifetimes = BTreeSet::new();
+2 -2
View File
@@ -329,13 +329,13 @@ fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
let name = field.attrs.name();
let ser_name = name.serialize_name();
if check_ser && ser_name == tag {
if check_ser && ser_name.value == tag {
diagnose_conflict();
return;
}
for de_name in field.attrs.aliases() {
if check_de && de_name == tag {
if check_de && de_name.value == tag {
diagnose_conflict();
return;
}
+1
View File
@@ -1,5 +1,6 @@
pub mod ast;
pub mod attr;
pub mod name;
mod case;
mod check;
+113
View File
@@ -0,0 +1,113 @@
use crate::internals::attr::{Attr, VecAttr};
use proc_macro2::{Ident, Span, TokenStream};
use quote::ToTokens;
use std::cmp::Ordering;
use std::collections::BTreeSet;
use std::fmt::{self, Display};
use syn::LitStr;
pub struct MultiName {
pub(crate) serialize: Name,
pub(crate) serialize_renamed: bool,
pub(crate) deserialize: Name,
pub(crate) deserialize_renamed: bool,
pub(crate) deserialize_aliases: BTreeSet<Name>,
}
impl MultiName {
pub(crate) fn from_attrs(
source_name: Name,
ser_name: Attr<Name>,
de_name: Attr<Name>,
de_aliases: Option<VecAttr<Name>>,
) -> Self {
let mut alias_set = BTreeSet::new();
if let Some(de_aliases) = de_aliases {
for alias_name in de_aliases.get() {
alias_set.insert(alias_name);
}
}
let ser_name = ser_name.get();
let ser_renamed = ser_name.is_some();
let de_name = de_name.get();
let de_renamed = de_name.is_some();
MultiName {
serialize: ser_name.unwrap_or_else(|| source_name.clone()),
serialize_renamed: ser_renamed,
deserialize: de_name.unwrap_or(source_name),
deserialize_renamed: de_renamed,
deserialize_aliases: alias_set,
}
}
/// Return the container name for the container when serializing.
pub fn serialize_name(&self) -> &Name {
&self.serialize
}
/// Return the container name for the container when deserializing.
pub fn deserialize_name(&self) -> &Name {
&self.deserialize
}
pub(crate) fn deserialize_aliases(&self) -> &BTreeSet<Name> {
&self.deserialize_aliases
}
}
#[derive(Clone)]
pub struct Name {
pub value: String,
pub span: Span,
}
impl ToTokens for Name {
fn to_tokens(&self, tokens: &mut TokenStream) {
LitStr::new(&self.value, self.span).to_tokens(tokens);
}
}
impl Ord for Name {
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(&self.value, &other.value)
}
}
impl PartialOrd for Name {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(Ord::cmp(self, other))
}
}
impl Eq for Name {}
impl PartialEq for Name {
fn eq(&self, other: &Self) -> bool {
self.value == other.value
}
}
impl From<&Ident> for Name {
fn from(ident: &Ident) -> Self {
Name {
value: ident.to_string(),
span: ident.span(),
}
}
}
impl From<&LitStr> for Name {
fn from(lit: &LitStr) -> Self {
Name {
value: lit.value(),
span: lit.span(),
}
}
}
impl Display for Name {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&self.value, formatter)
}
}
+1 -1
View File
@@ -13,7 +13,7 @@
//!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.211")]
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.217")]
#![cfg_attr(not(check_cfg), allow(unexpected_cfgs))]
// Ignored clippy lints
#![allow(
+16 -8
View File
@@ -1,5 +1,6 @@
use crate::fragment::{Fragment, Match, Stmts};
use crate::internals::ast::{Container, Data, Field, Style, Variant};
use crate::internals::name::Name;
use crate::internals::{attr, replace_receiver, Ctxt, Derive};
use crate::{bound, dummy, pretend, this};
use proc_macro2::{Span, TokenStream};
@@ -28,6 +29,7 @@ pub fn expand_derive_serialize(input: &mut syn::DeriveInput) -> syn::Result<Toke
let vis = &input.vis;
let used = pretend::pretend_used(&cont, params.is_packed);
quote! {
#[automatically_derived]
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>
where
@@ -732,6 +734,7 @@ fn serialize_adjacently_tagged_variant(
phantom: _serde::__private::PhantomData<#this_type #ty_generics>,
}
#[automatically_derived]
impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause {
fn serialize<__S>(&self, __serializer: __S) -> _serde::__private::Result<__S::Ok, __S::Error>
where
@@ -798,9 +801,9 @@ fn serialize_untagged_variant(
enum TupleVariant<'a> {
ExternallyTagged {
type_name: &'a str,
type_name: &'a Name,
variant_index: u32,
variant_name: &'a str,
variant_name: &'a Name,
},
Untagged,
}
@@ -867,11 +870,11 @@ fn serialize_tuple_variant(
enum StructVariant<'a> {
ExternallyTagged {
variant_index: u32,
variant_name: &'a str,
variant_name: &'a Name,
},
InternallyTagged {
tag: &'a str,
variant_name: &'a str,
variant_name: &'a Name,
},
Untagged,
}
@@ -880,7 +883,7 @@ fn serialize_struct_variant(
context: StructVariant,
params: &Parameters,
fields: &[Field],
name: &str,
name: &Name,
) -> Fragment {
if fields.iter().any(|field| field.attrs.flatten()) {
return serialize_struct_variant_with_flatten(context, params, fields, name);
@@ -964,7 +967,7 @@ fn serialize_struct_variant_with_flatten(
context: StructVariant,
params: &Parameters,
fields: &[Field],
name: &str,
name: &Name,
) -> Fragment {
let struct_trait = StructTrait::SerializeMap;
let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait);
@@ -996,6 +999,7 @@ fn serialize_struct_variant_with_flatten(
phantom: _serde::__private::PhantomData<#this_type #ty_generics>,
}
#[automatically_derived]
impl #wrapper_impl_generics _serde::Serialize for __EnumFlatten #wrapper_ty_generics #where_clause {
fn serialize<__S>(&self, __serializer: __S) -> _serde::__private::Result<__S::Ok, __S::Error>
where
@@ -1220,12 +1224,15 @@ fn wrap_serialize_with(
})
});
let self_var = quote!(self);
let serializer_var = quote!(__s);
// If #serialize_with returns wrong type, error will be reported on here.
// We attach span of the path to this piece so error will be reported
// on the #[serde(with = "...")]
// ^^^^^
let wrapper_serialize = quote_spanned! {serialize_with.span()=>
#serialize_with(#(self.values.#field_access, )* __s)
#serialize_with(#(#self_var.values.#field_access, )* #serializer_var)
};
quote!({
@@ -1235,8 +1242,9 @@ fn wrap_serialize_with(
phantom: _serde::__private::PhantomData<#this_type #ty_generics>,
}
#[automatically_derived]
impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause {
fn serialize<__S>(&self, __s: __S) -> _serde::__private::Result<__S::Ok, __S::Error>
fn serialize<__S>(&#self_var, #serializer_var: __S) -> _serde::__private::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
+1 -1
View File
@@ -13,7 +13,7 @@ serde = { path = "../serde" }
[dev-dependencies]
automod = "1.0.1"
fnv = "1.0"
foldhash = "0.1"
rustversion = "1.0"
serde = { path = "../serde", features = ["rc"] }
serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] }
+6
View File
@@ -10,4 +10,10 @@ libc = { version = "0.2", default-features = false }
serde = { path = "../../serde", default-features = false }
serde_derive = { path = "../../serde_derive" }
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"
[workspace]
+5 -8
View File
@@ -1,16 +1,13 @@
#![allow(internal_features)]
#![feature(lang_items, start)]
#![no_std]
#![no_main]
#[start]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
use core::ffi::c_int;
#[no_mangle]
extern "C" fn main(_argc: c_int, _argv: *const *const u8) -> c_int {
0
}
#[lang = "eh_personality"]
#[no_mangle]
pub extern "C" fn rust_eh_personality() {}
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
unsafe {
+4 -6
View File
@@ -34,9 +34,8 @@ macro_rules! hashset {
$(set.insert($value);)+
set
}};
($hasher:ident @ $($value:expr),+) => {{
use std::hash::BuildHasherDefault;
let mut set = HashSet::with_hasher(BuildHasherDefault::<$hasher>::default());
($hasher:ty; $($value:expr),+) => {{
let mut set = HashSet::<_, $hasher>::default();
$(set.insert($value);)+
set
}};
@@ -51,9 +50,8 @@ macro_rules! hashmap {
$(map.insert($key, $value);)+
map
}};
($hasher:ident @ $($key:expr => $value:expr),+) => {{
use std::hash::BuildHasherDefault;
let mut map = HashMap::with_hasher(BuildHasherDefault::<$hasher>::default());
($hasher:ty; $($key:expr => $value:expr),+) => {{
let mut map = HashMap::<_, _, $hasher>::default();
$(map.insert($key, $value);)+
map
}};
+12 -5
View File
@@ -1,4 +1,4 @@
use serde_derive::{Serialize, Deserialize};
use serde_derive::{Deserialize, Serialize};
use serde_test::{assert_tokens, Token};
#[derive(Serialize, Deserialize, Debug, PartialEq)]
@@ -18,11 +18,15 @@ fn simple_variant() {
assert_tokens(
&Enum::Simple { a: 42 },
&[
Token::StructVariant { name: "Enum", variant: "Simple", len: 1 },
Token::StructVariant {
name: "Enum",
variant: "Simple",
len: 1,
},
Token::Str("a"),
Token::I32(42),
Token::StructVariantEnd,
]
],
);
}
@@ -31,11 +35,14 @@ fn flatten_variant() {
assert_tokens(
&Enum::Flatten { flatten: (), a: 42 },
&[
Token::NewtypeVariant { name: "Enum", variant: "Flatten" },
Token::NewtypeVariant {
name: "Enum",
variant: "Flatten",
},
Token::Map { len: None },
Token::Str("a"),
Token::I32(42),
Token::MapEnd,
]
],
);
}
+33
View File
@@ -0,0 +1,33 @@
#![allow(clippy::trivially_copy_pass_by_ref)]
use serde_derive::{Deserialize, Serialize};
macro_rules! declare_in_macro {
($with:literal) => {
#[derive(Serialize, Deserialize)]
pub struct S {
#[serde(with = $with)]
f: i32,
}
};
}
declare_in_macro!("with");
mod with {
use serde::{Deserializer, Serializer};
pub fn serialize<S>(_: &i32, _: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
unimplemented!()
}
pub fn deserialize<'de, D>(_: D) -> Result<i32, D::Error>
where
D: Deserializer<'de>,
{
unimplemented!()
}
}
+27
View File
@@ -0,0 +1,27 @@
#![allow(clippy::trivially_copy_pass_by_ref)]
use serde_derive::Deserialize;
macro_rules! declare_in_macro {
($with:literal) => {
#[derive(Deserialize)]
pub struct S(
#[serde(with = $with)]
#[allow(dead_code)]
i32,
);
};
}
declare_in_macro!("with");
mod with {
use serde::Deserializer;
pub fn deserialize<'de, D>(_: D) -> Result<i32, D::Error>
where
D: Deserializer<'de>,
{
unimplemented!()
}
}
+35
View File
@@ -2655,11 +2655,46 @@ mod flatten {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
enum Enum {
Unit,
Newtype(HashMap<String, String>),
Tuple(u32, u32),
Struct { index: u32, value: u32 },
}
#[test]
fn unit() {
let value = Flatten {
data: Enum::Unit,
extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]),
};
assert_tokens(
&value,
&[
Token::Map { len: None },
// data
Token::Str("Unit"), // variant
Token::Unit,
// extra
Token::Str("extra_key"),
Token::Str("extra value"),
Token::MapEnd,
],
);
assert_de_tokens(
&value,
&[
Token::Map { len: None },
// extra
Token::Str("extra_key"),
Token::Str("extra value"),
// data
Token::Str("Unit"), // variant
Token::Unit,
Token::MapEnd,
],
);
}
#[test]
fn newtype() {
assert_tokens(
+2 -3
View File
@@ -10,7 +10,6 @@
)]
#![cfg_attr(feature = "unstable", feature(never_type))]
use fnv::FnvHasher;
use serde::de::value::{F32Deserializer, F64Deserializer};
use serde::de::{Deserialize, DeserializeOwned, Deserializer, IntoDeserializer};
use serde_derive::Deserialize;
@@ -1040,7 +1039,7 @@ fn test_hashset() {
],
);
test(
hashset![FnvHasher @ 1, 2, 3],
hashset![foldhash::fast::FixedState; 1, 2, 3],
&[
Token::Seq { len: Some(3) },
Token::I32(1),
@@ -1275,7 +1274,7 @@ fn test_hashmap() {
],
);
test(
hashmap![FnvHasher @ 1 => 2, 3 => 4],
hashmap![foldhash::fast::FixedState; 1 => 2, 3 => 4],
&[
Token::Map { len: Some(2) },
Token::I32(1),
+5 -5
View File
@@ -769,7 +769,7 @@ fn test_gen() {
}
#[derive(Serialize)]
#[repr(packed)]
#[repr(C, packed)]
#[allow(dead_code)]
struct Packed {
x: u8,
@@ -915,14 +915,14 @@ where
//////////////////////////////////////////////////////////////////////////
#[repr(packed)]
#[repr(C, packed)]
pub struct RemotePacked {
pub a: u16,
pub b: u32,
}
#[derive(Serialize)]
#[repr(packed)]
#[repr(C, packed)]
#[serde(remote = "RemotePacked")]
pub struct RemotePackedDef {
a: u16,
@@ -933,14 +933,14 @@ impl Drop for RemotePackedDef {
fn drop(&mut self) {}
}
#[repr(packed)]
#[repr(C, packed)]
pub struct RemotePackedNonCopy {
pub a: u16,
pub b: String,
}
#[derive(Deserialize)]
#[repr(packed)]
#[repr(C, packed)]
#[serde(remote = "RemotePackedNonCopy")]
pub struct RemotePackedNonCopyDef {
a: u16,
+2 -3
View File
@@ -1,7 +1,6 @@
#![allow(clippy::derive_partial_eq_without_eq, clippy::unreadable_literal)]
#![cfg_attr(feature = "unstable", feature(never_type))]
use fnv::FnvHasher;
use serde_derive::Serialize;
use serde_test::{assert_ser_tokens, assert_ser_tokens_error, Configure, Token};
use std::cell::RefCell;
@@ -220,7 +219,7 @@ fn test_hashset() {
&[Token::Seq { len: Some(1) }, Token::I32(1), Token::SeqEnd],
);
assert_ser_tokens(
&hashset![FnvHasher @ 1],
&hashset![foldhash::fast::FixedState; 1],
&[Token::Seq { len: Some(1) }, Token::I32(1), Token::SeqEnd],
);
}
@@ -300,7 +299,7 @@ fn test_hashmap() {
],
);
assert_ser_tokens(
&hashmap![FnvHasher @ 1 => 2],
&hashmap![foldhash::fast::FixedState; 1 => 2],
&[
Token::Map { len: Some(1) },
Token::I32(1),
@@ -0,0 +1,75 @@
#![allow(non_camel_case_types)]
use serde_derive::Deserialize;
#[derive(Deserialize)]
enum E {
S1 {
#[serde(alias = "a", alias = "b", alias = "c")]
a: (),
// Warning on "c" and "b"
#[serde(alias = "c")]
b: (),
#[serde(skip_deserializing)]
c: (),
},
S2 {
#[serde(alias = "b", alias = "c")]
a: (),
// Warning on "c"
#[serde(rename = "c")]
b: (),
},
#[serde(rename_all = "UPPERCASE")]
S3 {
#[serde(alias = "B", alias = "c")]
a: (),
// Warning on "b" because this collides with the "B" above after
// applying rename rules
b: (),
},
}
#[derive(Deserialize)]
enum E1 {
#[serde(alias = "a", alias = "b", alias = "c")]
a,
// Warning on "c" and "b"
#[serde(alias = "c")]
b,
#[serde(skip_deserializing)]
c,
}
#[derive(Deserialize)]
enum E2 {
#[serde(alias = "b", alias = "c")]
a,
// Warning on "c"
#[serde(rename = "c")]
b,
}
#[derive(Deserialize)]
#[serde(rename_all = "UPPERCASE")]
enum E3 {
#[serde(alias = "B", alias = "c")]
a,
// Warning on "b" because this collides with the "B" above after applying
// rename rules
b,
}
fn main() {
__FAIL__;
}
@@ -0,0 +1,79 @@
error[E0425]: cannot find value `__FAIL__` in this scope
--> tests/ui/conflict/alias-enum.rs:74:5
|
74 | __FAIL__;
| ^^^^^^^^ not found in this scope
warning: unreachable pattern
--> tests/ui/conflict/alias-enum.rs:13:9
|
8 | #[serde(alias = "a", alias = "b", alias = "c")]
| --- matches all the relevant values
...
13 | b: (),
| ^ no value can reach this
|
= note: `#[warn(unreachable_patterns)]` on by default
warning: unreachable pattern
--> tests/ui/conflict/alias-enum.rs:12:25
|
8 | #[serde(alias = "a", alias = "b", alias = "c")]
| --- matches all the relevant values
...
12 | #[serde(alias = "c")]
| ^^^ no value can reach this
warning: unreachable pattern
--> tests/ui/conflict/alias-enum.rs:24:26
|
20 | #[serde(alias = "b", alias = "c")]
| --- matches all the relevant values
...
24 | #[serde(rename = "c")]
| ^^^ no value can reach this
warning: unreachable pattern
--> tests/ui/conflict/alias-enum.rs:35:9
|
30 | #[serde(alias = "B", alias = "c")]
| --- matches all the relevant values
...
35 | b: (),
| ^ no value can reach this
warning: unreachable pattern
--> tests/ui/conflict/alias-enum.rs:46:5
|
41 | #[serde(alias = "a", alias = "b", alias = "c")]
| --- matches all the relevant values
...
46 | b,
| ^ no value can reach this
warning: unreachable pattern
--> tests/ui/conflict/alias-enum.rs:45:21
|
41 | #[serde(alias = "a", alias = "b", alias = "c")]
| --- matches all the relevant values
...
45 | #[serde(alias = "c")]
| ^^^ no value can reach this
warning: unreachable pattern
--> tests/ui/conflict/alias-enum.rs:58:22
|
54 | #[serde(alias = "b", alias = "c")]
| --- matches all the relevant values
...
58 | #[serde(rename = "c")]
| ^^^ no value can reach this
warning: unreachable pattern
--> tests/ui/conflict/alias-enum.rs:70:5
|
65 | #[serde(alias = "B", alias = "c")]
| --- matches all the relevant values
...
70 | b,
| ^ no value can reach this
+39
View File
@@ -0,0 +1,39 @@
use serde_derive::Deserialize;
#[derive(Deserialize)]
struct S1 {
#[serde(alias = "a", alias = "b", alias = "c")]
a: (),
// Warning on "c" and "b"
#[serde(alias = "c")]
b: (),
#[serde(skip_deserializing)]
c: (),
}
#[derive(Deserialize)]
struct S2 {
#[serde(alias = "b", alias = "c")]
a: (),
// Warning on "c"
#[serde(rename = "c")]
b: (),
}
#[derive(Deserialize)]
#[serde(rename_all = "UPPERCASE")]
struct S3 {
#[serde(alias = "B", alias = "c")]
a: (),
// Warning on "b" because this collides with the "B" above after applying
// rename rules
b: (),
}
fn main() {
__FAIL__;
}
+43
View File
@@ -0,0 +1,43 @@
error[E0425]: cannot find value `__FAIL__` in this scope
--> tests/ui/conflict/alias.rs:38:5
|
38 | __FAIL__;
| ^^^^^^^^ not found in this scope
warning: unreachable pattern
--> tests/ui/conflict/alias.rs:10:5
|
5 | #[serde(alias = "a", alias = "b", alias = "c")]
| --- matches all the relevant values
...
10 | b: (),
| ^ no value can reach this
|
= note: `#[warn(unreachable_patterns)]` on by default
warning: unreachable pattern
--> tests/ui/conflict/alias.rs:9:21
|
5 | #[serde(alias = "a", alias = "b", alias = "c")]
| --- matches all the relevant values
...
9 | #[serde(alias = "c")]
| ^^^ no value can reach this
warning: unreachable pattern
--> tests/ui/conflict/alias.rs:22:22
|
18 | #[serde(alias = "b", alias = "c")]
| --- matches all the relevant values
...
22 | #[serde(rename = "c")]
| ^^^ no value can reach this
warning: unreachable pattern
--> tests/ui/conflict/alias.rs:34:5
|
29 | #[serde(alias = "B", alias = "c")]
| --- matches all the relevant values
...
34 | b: (),
| ^ no value can reach this
@@ -19,8 +19,10 @@ note: required by a bound in `w::serialize`
error[E0061]: this function takes 1 argument but 2 arguments were supplied
--> tests/ui/with/incorrect_type.rs:15:25
|
14 | #[derive(Serialize, Deserialize)]
| --------- unexpected argument #2 of type `__S`
15 | struct W(#[serde(with = "w")] u8, u8);
| ^^^ unexpected argument #2 of type `__S`
| ^^^
|
note: function defined here
--> tests/ui/with/incorrect_type.rs:9:12
@@ -68,8 +70,10 @@ note: required by a bound in `w::serialize`
error[E0061]: this function takes 1 argument but 2 arguments were supplied
--> tests/ui/with/incorrect_type.rs:18:35
|
17 | #[derive(Serialize, Deserialize)]
| --------- unexpected argument #2 of type `__S`
18 | struct S(#[serde(serialize_with = "w::serialize")] u8, u8);
| ^^^^^^^^^^^^^^ unexpected argument #2 of type `__S`
| ^^^^^^^^^^^^^^
|
note: function defined here
--> tests/ui/with/incorrect_type.rs:9:12