Compare commits

...

49 Commits

Author SHA1 Message Date
David Tolnay 44bf3633af Release 1.0.151 2022-12-16 10:35:12 -08:00
David Tolnay f261184416 Merge pull request #2344 from dtolnay/coreerror
Make StdError identical to core::error::Error on feature="unstable"
2022-12-16 10:22:04 -08:00
David Tolnay df40f80fcf Make StdError identical to core::error::Error on feature="unstable" 2022-12-16 10:11:37 -08:00
David Tolnay e7060ba83d Merge pull request #2342 from atouchet/badges
Update build status badge
2022-12-15 17:54:07 -08:00
Alex Touchet d98f0eea3d Update build status badge 2022-12-15 17:17:05 -08:00
David Tolnay 4f157a8b81 Prevent build.rs rerunning unnecessarily on all source changes 2022-12-12 14:37:41 -08:00
David Tolnay d493649f52 Release 1.0.150 2022-12-11 16:24:46 -08:00
David Tolnay 0e947e6c3b Merge pull request #2338 from serde-rs/atomic
Deduplicate atomic_impl implementations and atomic_impl calls from PR 2337
2022-12-11 16:22:28 -08:00
David Tolnay 9249dab54c Deduplicate atomic_impl macro calls 2022-12-11 16:12:51 -08:00
David Tolnay 7440e56c53 Deduplicate atomic_impl macro implementations 2022-12-11 16:09:26 -08:00
David Tolnay 0d79306285 Update atomic_impl macros to have same input syntax in all cfgs 2022-12-11 16:01:58 -08:00
David Tolnay 37faaf295e Mention target_has_atomic stabilization 2022-12-11 15:56:31 -08:00
David Tolnay 650358fa00 Replace obsolete comment about target_has_atomic support 2022-12-11 15:55:19 -08:00
David Tolnay 6159ead404 Invert use_target_has_atomic cfg
This way, a build system that does not want to run Cargo build scripts
can build serde without any cfgs defined, and get the most modern
feature set.
2022-12-11 15:51:19 -08:00
David Tolnay 692ac99c69 Format PR 2337 with rustfmt 2022-12-11 15:48:30 -08:00
David Tolnay 86161ce15f Adjust spacing in some macro matchers 2022-12-11 15:48:30 -08:00
David Tolnay 5361c790bb Merge pull request #2337 from badboy/use-target_has_atomic-when-available
Use `target_has_atomic` on Rust 1.60+ to enable atomic (de)serialization
2022-12-11 15:42:00 -08:00
Jan-Erik Rediger 126730edc8 Use target_has_atomic on Rust 1.60+ to enable atomic (de)serialization 2022-12-11 13:34:07 +01:00
David Tolnay 3aec2a96a8 Merge pull request #2334 from dtolnay/mapimpl
Reduce trait bounds in HashMap and BTreeMap serialize
2022-12-04 23:27:03 -08:00
David Tolnay 227d039b1e Reduce trait bounds in HashMap and BTreeMap serialize 2022-12-04 23:18:02 -08:00
David Tolnay 0353354d61 Release 1.0.149 2022-12-04 23:11:59 -08:00
David Tolnay 34ae0422f4 Merge pull request #2333 from jonasbb/remove-trait-bounds
Remove some Serialize trait bounds
2022-12-03 09:22:27 -08:00
Jonas Bushart cc128feb4c Remove some Serialize trait bounds
Containers for the most part do not have any trait requirements for
iterating over them. So these bounds are unnecessary when Serializing
only.

This relaxation is part of Rust 1.34
2022-12-03 16:03:37 +01:00
David Tolnay 7766103174 Release 1.0.148 2022-11-27 17:58:18 -08:00
David Tolnay 30f7c7110d Merge pull request #2331 from dtolnay/remote
Improve error message on remote derive duplicate generics
2022-11-27 17:57:35 -08:00
David Tolnay 50354c2d0b Improve error message on remote derive duplicate generics 2022-11-27 17:48:48 -08:00
David Tolnay c4f67e679f Add ui test of duplicate generics in remote derive 2022-11-27 17:48:48 -08:00
David Tolnay 0daafe423f Merge pull request #2330 from dtolnay/remote
Fix generated Into conversion involving generic remote derive with getter
2022-11-27 17:48:37 -08:00
David Tolnay 37021910c9 Fix Into conversion involving generic remote derive with getter 2022-11-27 17:18:10 -08:00
David Tolnay 7328b34810 Add test of generic remote derive with getter
Currently fails to compile.

    error[E0107]: missing generics for struct `StructGeneric`
       --> test_suite/tests/test_remote.rs:181:18
        |
    181 | #[serde(remote = "remote::StructGeneric")]
        |                  ^^^^^^^^^^^^^^^^^^^^^^^ expected 1 generic argument
        |
    note: struct defined here, with 1 generic parameter: `T`
       --> test_suite/tests/test_remote.rs:78:16
        |
    78  |     pub struct StructGeneric<T> {
        |                ^^^^^^^^^^^^^ -
    help: add missing generic argument
        |
    181 | #[serde(remote = StructGeneric<T>)]
        |                  ~~~~~~~~~~~~~~~~
2022-11-27 17:17:52 -08:00
David Tolnay fabbd2b097 Merge pull request #2329 from dtolnay/safety
Revert Buf::as_str safety change from PR 2319
2022-11-27 17:05:41 -08:00
David Tolnay 6814f978d7 Revert Buf::as_str safety change from PR 2319 2022-11-27 16:56:31 -08:00
David Tolnay 4ea403c54a Merge pull request #2328 from dtolnay/remote
Handle remote type written without turbofish
2022-11-27 16:41:23 -08:00
David Tolnay f4f6b5af3a Remove unneeded turbofish from remote attr test 2022-11-27 16:32:06 -08:00
David Tolnay 2062a3c16d Handle remote type written without turbofish 2022-11-27 16:32:06 -08:00
David Tolnay 9a53bd9125 Add tests of concrete def of generic remote type 2022-11-27 16:05:56 -08:00
David Tolnay 4873b48b02 Time out workflows after 45 minutes
GitHub's default timeout is 6 hours. Recently some of my GitHub Actions
jobs have started randomly stalling for that long, which is inconvenient
because it ties up a chunk of my runner quota. It apepars to be very
rare for a job to recover after stalling. It's better to time out
quicker and retry on a different runner.
2022-11-25 18:56:19 -08:00
David Tolnay e19844c659 Fix renamed let_underscore_drop lint
warning: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
      --> serde_derive/src/lib.rs:46:5
       |
    46 |     clippy::let_underscore_drop,
       |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
       |
       = note: `#[warn(renamed_and_removed_lints)]` on by default
2022-11-22 19:04:29 -08:00
David Tolnay 93bb9e147c Resolve manual_let_else clippy lints
error: this could be rewritten as `let...else`
        --> test_suite/tests/test_annotations.rs:1247:5
         |
    1247 | /     let f1 = match pieces.next() {
    1248 | |         Some(x) => x,
    1249 | |         None => return Err(de::Error::invalid_length(0, &"2")),
    1250 | |     };
         | |______^ help: consider writing: `let Some(x) = pieces.next() else { return Err(de::Error::invalid_length(0, &"2")) };`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else
         = note: `-D clippy::manual-let-else` implied by `-D clippy::pedantic`

    error: this could be rewritten as `let...else`
        --> test_suite/tests/test_annotations.rs:1251:5
         |
    1251 | /     let f2 = match pieces.next() {
    1252 | |         Some(x) => x,
    1253 | |         None => return Err(de::Error::invalid_length(1, &"2")),
    1254 | |     };
         | |______^ help: consider writing: `let Some(x) = pieces.next() else { return Err(de::Error::invalid_length(1, &"2")) };`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else

    error: this could be rewritten as `let...else`
        --> test_suite/tests/test_annotations.rs:1255:5
         |
    1255 | /     let f2 = match f2.parse() {
    1256 | |         Ok(n) => n,
    1257 | |         Err(_) => {
    1258 | |             return Err(de::Error::invalid_value(
    ...    |
    1262 | |         }
    1263 | |     };
         | |______^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else
    help: consider writing
         |
    1255 ~     let Ok(n) = f2.parse() else {
    1256 +             return Err(de::Error::invalid_value(
    1257 +                 Unexpected::Str(f2),
    1258 +                 &"an 8-bit signed integer",
    1259 +             ));
    1260 +         };
         |
2022-11-22 18:45:27 -08:00
David Tolnay ab230e6e44 Resolve needless_lifetimes clippy lints
error: the following explicit lifetimes could be elided: 'a
       --> serde_derive/src/ser.rs:869:1
        |
    869 | / fn serialize_struct_variant<'a>(
    870 | |     context: StructVariant<'a>,
    871 | |     params: &Parameters,
    872 | |     fields: &[Field],
    873 | |     name: &str,
    874 | | ) -> Fragment {
        | |_____________^
        |
    help: replace with `'_` in generic arguments such as here
       --> serde_derive/src/ser.rs:870:28
        |
    870 |     context: StructVariant<'a>,
        |                            ^^
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes
        = note: `-D clippy::needless-lifetimes` implied by `-D clippy::all`

    error: the following explicit lifetimes could be elided: 'a
       --> serde_derive/src/ser.rs:953:1
        |
    953 | / fn serialize_struct_variant_with_flatten<'a>(
    954 | |     context: StructVariant<'a>,
    955 | |     params: &Parameters,
    956 | |     fields: &[Field],
    957 | |     name: &str,
    958 | | ) -> Fragment {
        | |_____________^
        |
    help: replace with `'_` in generic arguments such as here
       --> serde_derive/src/ser.rs:954:28
        |
    954 |     context: StructVariant<'a>,
        |                            ^^
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes
2022-11-22 18:41:37 -08:00
David Tolnay 51ea34b217 Resolve needless_borrowed_reference clippy lints
error: dereferencing a tuple pattern where every element takes a reference
        --> serde/src/private/de.rs:1813:39
         |
    1813 |         let map = content.iter().map(|&(ref k, ref v)| {
         |                                       ^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrowed_reference
         = note: `-D clippy::needless-borrowed-reference` implied by `-D clippy::all`
    help: try removing the `&` and `ref` parts
         |
    1813 -         let map = content.iter().map(|&(ref k, ref v)| {
    1813 +         let map = content.iter().map(|(k, v)| {
         |

    error: dereferencing a tuple pattern where every element takes a reference
        --> serde/src/private/de.rs:2110:25
         |
    2110 |                     let &(ref variant, ref value) = match iter.next() {
         |                         ^^^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrowed_reference
    help: try removing the `&` and `ref` parts
         |
    2110 -                     let &(ref variant, ref value) = match iter.next() {
    2110 +                     let (variant, value) = match iter.next() {
         |

    error: dereferencing a tuple pattern where every element takes a reference
        --> serde/src/private/de.rs:2257:22
         |
    2257 |                 Some(&Content::Seq(ref v)) => {
         |                      ^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrowed_reference
    help: try removing the `&` and `ref` parts
         |
    2257 -                 Some(&Content::Seq(ref v)) => {
    2257 +                 Some(Content::Seq(v)) => {
         |

    error: dereferencing a tuple pattern where every element takes a reference
        --> serde/src/private/de.rs:2280:22
         |
    2280 |                 Some(&Content::Map(ref v)) => {
         |                      ^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrowed_reference
    help: try removing the `&` and `ref` parts
         |
    2280 -                 Some(&Content::Map(ref v)) => {
    2280 +                 Some(Content::Map(v)) => {
         |

    error: dereferencing a tuple pattern where every element takes a reference
        --> serde/src/private/de.rs:2283:22
         |
    2283 |                 Some(&Content::Seq(ref v)) => {
         |                      ^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrowed_reference
    help: try removing the `&` and `ref` parts
         |
    2283 -                 Some(&Content::Seq(ref v)) => {
    2283 +                 Some(Content::Seq(v)) => {
         |

    error: dereferencing a tuple pattern where every element takes a reference
        --> serde/src/private/de.rs:2406:22
         |
    2406 |                 Some(&(ref key, ref value)) => {
         |                      ^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrowed_reference
    help: try removing the `&` and `ref` parts
         |
    2406 -                 Some(&(ref key, ref value)) => {
    2406 +                 Some((key, value)) => {
         |

    error: dereferencing a tuple pattern where every element takes a reference
       --> serde/src/private/ser.rs:528:25
        |
    528 |                     for &(ref k, ref v) in entries {
        |                         ^^^^^^^^^^^^^^^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrowed_reference
    help: try removing the `&` and `ref` parts
        |
    528 -                     for &(ref k, ref v) in entries {
    528 +                     for (k, v) in entries {
        |
2022-11-22 18:40:34 -08:00
Erick Tryzelaar 1050f6b808 Change comment to // Safety: ...
This changes a comment to be explicit on how it's safe we can avoid
validating UTF-8.
2022-11-09 22:44:24 +00:00
Erick Tryzelaar 15ec95a98d Make Buf::as_str private and unsafe, add safety docs
serde::de::format::Buf is a private type, so this makes it explicit by
declaring the type `pub(super)`. In addition, it marks the function
`Buf::as_str` as unsafe, which lets us document the callsites with
`// Safety: ...` comments to explain why it is safe to use.
2022-11-09 22:40:40 +00:00
David Tolnay 072145e0e9 Update TOML link to a page that covers usage with serde 2022-11-08 17:33:39 -08:00
David Tolnay 92957f17f2 Merge pull request #2317 from TomAFrench/patch-1
Update link to `toml` crate repo
2022-11-08 17:32:56 -08:00
Tom French 667db558b6 chore: update link to toml crate repo 2022-11-09 01:07:53 +00:00
David Tolnay f41509261e Release 1.0.147 2022-10-21 10:04:43 -07:00
David Tolnay 6d009711a2 Merge pull request #2305 from serde-rs/enumaccessdeserializer
Add EnumAccessDeserializer to turn EnumAccess into a Deserializer
2022-10-21 10:04:08 -07:00
David Tolnay 354b48fd40 Add EnumAccessDeserializer to turn EnumAccess into a Deserializer 2022-10-21 09:51:42 -07:00
30 changed files with 470 additions and 209 deletions
+16 -3
View File
@@ -15,6 +15,7 @@ jobs:
test: test:
name: Test suite name: Test suite
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 45
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@nightly - uses: dtolnay/rust-toolchain@nightly
@@ -27,6 +28,7 @@ jobs:
windows: windows:
name: Test suite (windows) name: Test suite (windows)
runs-on: windows-latest runs-on: windows-latest
timeout-minutes: 45
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@nightly - uses: dtolnay/rust-toolchain@nightly
@@ -39,6 +41,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
rust: [stable, beta] rust: [stable, beta]
timeout-minutes: 45
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@master - uses: dtolnay/rust-toolchain@master
@@ -56,6 +59,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu, windows] os: [ubuntu, windows]
timeout-minutes: 45
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@nightly - uses: dtolnay/rust-toolchain@nightly
@@ -74,6 +78,7 @@ jobs:
msrv: msrv:
name: Rust 1.13.0 name: Rust 1.13.0
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 45
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@1.13.0 - uses: dtolnay/rust-toolchain@1.13.0
@@ -95,6 +100,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
rust: [1.19.0, 1.20.0, 1.21.0, 1.25.0, 1.26.0, 1.34.0] rust: [1.19.0, 1.20.0, 1.21.0, 1.25.0, 1.26.0, 1.34.0]
timeout-minutes: 45
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@master - uses: dtolnay/rust-toolchain@master
@@ -110,6 +116,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
rust: [1.27.0, 1.28.0] rust: [1.27.0, 1.28.0]
timeout-minutes: 45
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@master - uses: dtolnay/rust-toolchain@master
@@ -123,6 +130,7 @@ jobs:
derive: derive:
name: Rust 1.31.0 name: Rust 1.31.0
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 45
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@1.31.0 - uses: dtolnay/rust-toolchain@1.31.0
@@ -133,6 +141,7 @@ jobs:
alloc: alloc:
name: Rust 1.36.0 name: Rust 1.36.0
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 45
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@1.36.0 - uses: dtolnay/rust-toolchain@1.36.0
@@ -141,6 +150,7 @@ jobs:
emscripten: emscripten:
name: Emscripten name: Emscripten
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 45
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@nightly - uses: dtolnay/rust-toolchain@nightly
@@ -164,19 +174,21 @@ jobs:
name: Clippy name: Clippy
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.event_name != 'pull_request' if: github.event_name != 'pull_request'
timeout-minutes: 45
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@clippy - uses: dtolnay/rust-toolchain@clippy
- run: cd serde && cargo clippy --features rc,unstable -- -Dclippy::all -Dclippy::pedantic -Aclippy::let_underscore_drop - run: cd serde && cargo clippy --features rc,unstable -- -Dclippy::all -Dclippy::pedantic
- run: cd serde_derive && cargo clippy -- -Dclippy::all -Dclippy::pedantic - run: cd serde_derive && cargo clippy -- -Dclippy::all -Dclippy::pedantic
- run: cd serde_derive_internals && cargo clippy -- -Dclippy::all -Dclippy::pedantic - run: cd serde_derive_internals && cargo clippy -- -Dclippy::all -Dclippy::pedantic
- run: cd serde_test && cargo clippy -- -Dclippy::all -Dclippy::pedantic -Aclippy::let_underscore_drop - run: cd serde_test && cargo clippy -- -Dclippy::all -Dclippy::pedantic
- run: cd test_suite && cargo clippy --tests --features unstable -- -Dclippy::all -Dclippy::pedantic -Aclippy::let_underscore_drop - run: cd test_suite && cargo clippy --tests --features unstable -- -Dclippy::all -Dclippy::pedantic
- run: cd test_suite/no_std && cargo clippy -- -Dclippy::all -Dclippy::pedantic - run: cd test_suite/no_std && cargo clippy -- -Dclippy::all -Dclippy::pedantic
miri: miri:
name: Miri name: Miri
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 45
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@miri - uses: dtolnay/rust-toolchain@miri
@@ -191,6 +203,7 @@ jobs:
name: Outdated name: Outdated
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.event_name != 'pull_request' if: github.event_name != 'pull_request'
timeout-minutes: 45
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: dtolnay/install@cargo-outdated - uses: dtolnay/install@cargo-outdated
+1 -1
View File
@@ -1,6 +1,6 @@
# Serde &emsp; [![Build Status]][actions] [![Latest Version]][crates.io] [![serde: rustc 1.13+]][Rust 1.13] [![serde_derive: rustc 1.31+]][Rust 1.31] # Serde &emsp; [![Build Status]][actions] [![Latest Version]][crates.io] [![serde: rustc 1.13+]][Rust 1.13] [![serde_derive: rustc 1.31+]][Rust 1.31]
[Build Status]: https://img.shields.io/github/workflow/status/serde-rs/serde/CI/master [Build Status]: https://img.shields.io/github/actions/workflow/status/serde-rs/serde/ci.yml?branch=master
[actions]: https://github.com/serde-rs/serde/actions?query=branch%3Amaster [actions]: https://github.com/serde-rs/serde/actions?query=branch%3Amaster
[Latest Version]: https://img.shields.io/crates/v/serde.svg [Latest Version]: https://img.shields.io/crates/v/serde.svg
[crates.io]: https://crates.io/crates/serde [crates.io]: https://crates.io/crates/serde
+2 -2
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde" name = "serde"
version = "1.0.146" # remember to update html_root_url and serde_derive dependency version = "1.0.151" # remember to update html_root_url and serde_derive dependency
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
build = "build.rs" build = "build.rs"
categories = ["encoding", "no-std"] categories = ["encoding", "no-std"]
@@ -15,7 +15,7 @@ repository = "https://github.com/serde-rs/serde"
rust-version = "1.13" rust-version = "1.13"
[dependencies] [dependencies]
serde_derive = { version = "=1.0.146", optional = true, path = "../serde_derive" } serde_derive = { version = "=1.0.151", optional = true, path = "../serde_derive" }
[dev-dependencies] [dev-dependencies]
serde_derive = { version = "1.0", path = "../serde_derive" } serde_derive = { version = "1.0", path = "../serde_derive" }
+22 -16
View File
@@ -6,6 +6,8 @@ use std::str::{self, FromStr};
// opening a GitHub issue if your build environment requires some way to enable // opening a GitHub issue if your build environment requires some way to enable
// these cfgs other than by executing our build script. // these cfgs other than by executing our build script.
fn main() { fn main() {
println!("cargo:rerun-if-changed=build.rs");
let minor = match rustc_minor_version() { let minor = match rustc_minor_version() {
Some(minor) => minor, Some(minor) => minor,
None => return, None => return,
@@ -89,24 +91,28 @@ fn main() {
println!("cargo:rustc-cfg=no_core_try_from"); println!("cargo:rustc-cfg=no_core_try_from");
println!("cargo:rustc-cfg=no_num_nonzero_signed"); println!("cargo:rustc-cfg=no_num_nonzero_signed");
println!("cargo:rustc-cfg=no_systemtime_checked_add"); println!("cargo:rustc-cfg=no_systemtime_checked_add");
println!("cargo:rustc-cfg=no_relaxed_trait_bounds");
} }
// Whitelist of archs that support std::sync::atomic module. Ideally we // Support for #[cfg(target_has_atomic = "...")] stabilized in Rust 1.60.
// would use #[cfg(target_has_atomic = "...")] but it is not stable yet. if minor < 60 {
// Instead this is based on rustc's compiler/rustc_target/src/spec/*.rs. println!("cargo:rustc-cfg=no_target_has_atomic");
let has_atomic64 = target.starts_with("x86_64") // Allowlist of archs that support std::sync::atomic module. This is
|| target.starts_with("i686") // based on rustc's compiler/rustc_target/src/spec/*.rs.
|| target.starts_with("aarch64") let has_atomic64 = target.starts_with("x86_64")
|| target.starts_with("powerpc64") || target.starts_with("i686")
|| target.starts_with("sparc64") || target.starts_with("aarch64")
|| target.starts_with("mips64el") || target.starts_with("powerpc64")
|| target.starts_with("riscv64"); || target.starts_with("sparc64")
let has_atomic32 = has_atomic64 || emscripten; || target.starts_with("mips64el")
if minor < 34 || !has_atomic64 { || target.starts_with("riscv64");
println!("cargo:rustc-cfg=no_std_atomic64"); let has_atomic32 = has_atomic64 || emscripten;
} if minor < 34 || !has_atomic64 {
if minor < 34 || !has_atomic32 { println!("cargo:rustc-cfg=no_std_atomic64");
println!("cargo:rustc-cfg=no_std_atomic"); }
if minor < 34 || !has_atomic32 {
println!("cargo:rustc-cfg=no_std_atomic");
}
} }
} }
+1 -1
View File
@@ -1,7 +1,7 @@
use lib::fmt::{self, Write}; use lib::fmt::{self, Write};
use lib::str; use lib::str;
pub struct Buf<'a> { pub(super) struct Buf<'a> {
bytes: &'a mut [u8], bytes: &'a mut [u8],
offset: usize, offset: usize,
} }
+26 -18
View File
@@ -733,7 +733,7 @@ impl<'de> Deserialize<'de> for CString {
macro_rules! forwarded_impl { macro_rules! forwarded_impl {
( (
$(#[doc = $doc:tt])* $(#[doc = $doc:tt])*
( $($id: ident),* ), $ty: ty, $func: expr ($($id:ident),*), $ty:ty, $func:expr
) => { ) => {
$(#[doc = $doc])* $(#[doc = $doc])*
impl<'de $(, $id : Deserialize<'de>,)*> Deserialize<'de> for $ty { impl<'de $(, $id : Deserialize<'de>,)*> Deserialize<'de> for $ty {
@@ -860,7 +860,7 @@ impl<'de, T: ?Sized> Deserialize<'de> for PhantomData<T> {
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
macro_rules! seq_impl { macro_rules! seq_impl {
( (
$ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >, $ty:ident <T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)*>,
$access:ident, $access:ident,
$clear:expr, $clear:expr,
$with_capacity:expr, $with_capacity:expr,
@@ -1353,7 +1353,7 @@ tuple_impls! {
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
macro_rules! map_impl { macro_rules! map_impl {
( (
$ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >, $ty:ident <K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)*>,
$access:ident, $access:ident,
$with_capacity:expr $with_capacity:expr
) => { ) => {
@@ -1440,15 +1440,15 @@ macro_rules! parse_ip_impl {
#[cfg(feature = "std")] #[cfg(feature = "std")]
macro_rules! variant_identifier { macro_rules! variant_identifier {
( (
$name_kind: ident ( $($variant: ident; $bytes: expr; $index: expr),* ) $name_kind:ident ($($variant:ident; $bytes:expr; $index:expr),*)
$expecting_message: expr, $expecting_message:expr,
$variants_name: ident $variants_name:ident
) => { ) => {
enum $name_kind { enum $name_kind {
$( $variant ),* $($variant),*
} }
static $variants_name: &'static [&'static str] = &[ $( stringify!($variant) ),*]; static $variants_name: &'static [&'static str] = &[$(stringify!($variant)),*];
impl<'de> Deserialize<'de> for $name_kind { impl<'de> Deserialize<'de> for $name_kind {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
@@ -1515,12 +1515,12 @@ macro_rules! variant_identifier {
#[cfg(feature = "std")] #[cfg(feature = "std")]
macro_rules! deserialize_enum { macro_rules! deserialize_enum {
( (
$name: ident $name_kind: ident ( $($variant: ident; $bytes: expr; $index: expr),* ) $name:ident $name_kind:ident ($($variant:ident; $bytes:expr; $index:expr),*)
$expecting_message: expr, $expecting_message:expr,
$deserializer: expr $deserializer:expr
) => { ) => {
variant_identifier!{ variant_identifier! {
$name_kind ( $($variant; $bytes; $index),* ) $name_kind ($($variant; $bytes; $index),*)
$expecting_message, $expecting_message,
VARIANTS VARIANTS
} }
@@ -2662,8 +2662,9 @@ where
#[cfg(all(feature = "std", not(no_std_atomic)))] #[cfg(all(feature = "std", not(no_std_atomic)))]
macro_rules! atomic_impl { macro_rules! atomic_impl {
($($ty:ident)*) => { ($($ty:ident $size:expr)*) => {
$( $(
#[cfg(any(no_target_has_atomic, target_has_atomic = $size))]
impl<'de> Deserialize<'de> for $ty { impl<'de> Deserialize<'de> for $ty {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
@@ -2678,14 +2679,21 @@ macro_rules! atomic_impl {
#[cfg(all(feature = "std", not(no_std_atomic)))] #[cfg(all(feature = "std", not(no_std_atomic)))]
atomic_impl! { atomic_impl! {
AtomicBool AtomicBool "8"
AtomicI8 AtomicI16 AtomicI32 AtomicIsize AtomicI8 "8"
AtomicU8 AtomicU16 AtomicU32 AtomicUsize AtomicI16 "16"
AtomicI32 "32"
AtomicIsize "ptr"
AtomicU8 "8"
AtomicU16 "16"
AtomicU32 "32"
AtomicUsize "ptr"
} }
#[cfg(all(feature = "std", not(no_std_atomic64)))] #[cfg(all(feature = "std", not(no_std_atomic64)))]
atomic_impl! { atomic_impl! {
AtomicI64 AtomicU64 AtomicI64 "64"
AtomicU64 "64"
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
+35
View File
@@ -1510,6 +1510,41 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// A deserializer holding an `EnumAccess`.
#[derive(Clone, Debug)]
pub struct EnumAccessDeserializer<A> {
access: A,
}
impl<A> EnumAccessDeserializer<A> {
/// Construct a new `EnumAccessDeserializer<A>`.
pub fn new(access: A) -> Self {
EnumAccessDeserializer { access: access }
}
}
impl<'de, A> de::Deserializer<'de> for EnumAccessDeserializer<A>
where
A: de::EnumAccess<'de>,
{
type Error = A::Error;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_enum(self.access)
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct enum identifier ignored_any
}
}
////////////////////////////////////////////////////////////////////////////////
mod private { mod private {
use lib::*; use lib::*;
+19 -7
View File
@@ -61,7 +61,7 @@
//! [CBOR]: https://github.com/enarx/ciborium //! [CBOR]: https://github.com/enarx/ciborium
//! [YAML]: https://github.com/dtolnay/serde-yaml //! [YAML]: https://github.com/dtolnay/serde-yaml
//! [MessagePack]: https://github.com/3Hren/msgpack-rust //! [MessagePack]: https://github.com/3Hren/msgpack-rust
//! [TOML]: https://github.com/alexcrichton/toml-rs //! [TOML]: https://docs.rs/toml
//! [Pickle]: https://github.com/birkenfeld/serde-pickle //! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [RON]: https://github.com/ron-rs/ron //! [RON]: https://github.com/ron-rs/ron
//! [BSON]: https://github.com/mongodb/bson-rust //! [BSON]: https://github.com/mongodb/bson-rust
@@ -81,14 +81,14 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Serde types in rustdoc of other crates get linked to here. // Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.146")] #![doc(html_root_url = "https://docs.rs/serde/1.0.151")]
// Support using Serde without the standard library! // Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and // Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue: // discussion of these features please refer to this issue:
// //
// https://github.com/serde-rs/serde/issues/812 // https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(never_type))] #![cfg_attr(feature = "unstable", feature(error_in_core, never_type))]
#![allow(unknown_lints, bare_trait_objects, deprecated)] #![allow(unknown_lints, bare_trait_objects, deprecated)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] #![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
// Ignored clippy and clippy_pedantic lints // Ignored clippy and clippy_pedantic lints
@@ -118,7 +118,6 @@
derive_partial_eq_without_eq, derive_partial_eq_without_eq,
enum_glob_use, enum_glob_use,
explicit_auto_deref, explicit_auto_deref,
let_underscore_drop,
map_err_ignore, map_err_ignore,
new_without_default, new_without_default,
result_unit_err, result_unit_err,
@@ -237,14 +236,27 @@ mod lib {
#[cfg(not(no_range_inclusive))] #[cfg(not(no_range_inclusive))]
pub use self::core::ops::RangeInclusive; pub use self::core::ops::RangeInclusive;
#[cfg(all(feature = "std", not(no_std_atomic)))] #[cfg(all(feature = "std", no_target_has_atomic, not(no_std_atomic)))]
pub use std::sync::atomic::{ pub use std::sync::atomic::{
AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8, AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8,
AtomicUsize, Ordering, AtomicUsize, Ordering,
}; };
#[cfg(all(feature = "std", not(no_std_atomic64)))] #[cfg(all(feature = "std", no_target_has_atomic, not(no_std_atomic64)))]
pub use std::sync::atomic::{AtomicI64, AtomicU64}; pub use std::sync::atomic::{AtomicI64, AtomicU64};
#[cfg(all(feature = "std", not(no_target_has_atomic)))]
pub use std::sync::atomic::Ordering;
#[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "8"))]
pub use std::sync::atomic::{AtomicBool, AtomicI8, AtomicU8};
#[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "16"))]
pub use std::sync::atomic::{AtomicI16, AtomicU16};
#[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "32"))]
pub use std::sync::atomic::{AtomicI32, AtomicU32};
#[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "64"))]
pub use std::sync::atomic::{AtomicI64, AtomicU64};
#[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "ptr"))]
pub use std::sync::atomic::{AtomicIsize, AtomicUsize};
#[cfg(any(feature = "std", not(no_core_duration)))] #[cfg(any(feature = "std", not(no_core_duration)))]
pub use self::core::time::Duration; pub use self::core::time::Duration;
} }
@@ -291,7 +303,7 @@ use self::__private as private;
#[path = "de/seed.rs"] #[path = "de/seed.rs"]
mod seed; mod seed;
#[cfg(not(feature = "std"))] #[cfg(not(any(feature = "std", feature = "unstable")))]
mod std_error; mod std_error;
// Re-export #[derive(Serialize, Deserialize)]. // Re-export #[derive(Serialize, Deserialize)].
+7 -7
View File
@@ -1810,7 +1810,7 @@ mod content {
V: Visitor<'de>, V: Visitor<'de>,
E: de::Error, E: de::Error,
{ {
let map = content.iter().map(|&(ref k, ref v)| { let map = content.iter().map(|(k, v)| {
( (
ContentRefDeserializer::new(k), ContentRefDeserializer::new(k),
ContentRefDeserializer::new(v), ContentRefDeserializer::new(v),
@@ -2107,7 +2107,7 @@ mod content {
let (variant, value) = match *self.content { let (variant, value) = match *self.content {
Content::Map(ref value) => { Content::Map(ref value) => {
let mut iter = value.iter(); let mut iter = value.iter();
let &(ref variant, ref value) = match iter.next() { let (variant, value) = match iter.next() {
Some(v) => v, Some(v) => v,
None => { None => {
return Err(de::Error::invalid_value( return Err(de::Error::invalid_value(
@@ -2254,7 +2254,7 @@ mod content {
V: de::Visitor<'de>, V: de::Visitor<'de>,
{ {
match self.value { match self.value {
Some(&Content::Seq(ref v)) => { Some(Content::Seq(v)) => {
de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor) de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor)
} }
Some(other) => Err(de::Error::invalid_type( Some(other) => Err(de::Error::invalid_type(
@@ -2277,10 +2277,10 @@ mod content {
V: de::Visitor<'de>, V: de::Visitor<'de>,
{ {
match self.value { match self.value {
Some(&Content::Map(ref v)) => { Some(Content::Map(v)) => {
de::Deserializer::deserialize_any(MapRefDeserializer::new(v), visitor) de::Deserializer::deserialize_any(MapRefDeserializer::new(v), visitor)
} }
Some(&Content::Seq(ref v)) => { Some(Content::Seq(v)) => {
de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor) de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor)
} }
Some(other) => Err(de::Error::invalid_type( Some(other) => Err(de::Error::invalid_type(
@@ -2403,7 +2403,7 @@ mod content {
T: de::DeserializeSeed<'de>, T: de::DeserializeSeed<'de>,
{ {
match self.iter.next() { match self.iter.next() {
Some(&(ref key, ref value)) => { Some((key, value)) => {
self.value = Some(value); self.value = Some(value);
seed.deserialize(ContentRefDeserializer::new(key)).map(Some) seed.deserialize(ContentRefDeserializer::new(key)).map(Some)
} }
@@ -2708,7 +2708,7 @@ where
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
macro_rules! forward_to_deserialize_other { macro_rules! forward_to_deserialize_other {
($($func:ident ( $($arg:ty),* ))*) => { ($($func:ident ($($arg:ty),*))*) => {
$( $(
fn $func<V>(self, $(_: $arg,)* _visitor: V) -> Result<V::Value, Self::Error> fn $func<V>(self, $(_: $arg,)* _visitor: V) -> Result<V::Value, Self::Error>
where where
+1 -1
View File
@@ -525,7 +525,7 @@ mod content {
Content::Map(ref entries) => { Content::Map(ref entries) => {
use ser::SerializeMap; use ser::SerializeMap;
let mut map = try!(serializer.serialize_map(Some(entries.len()))); let mut map = try!(serializer.serialize_map(Some(entries.len())));
for &(ref k, ref v) in entries { for (k, v) in entries {
try!(map.serialize_entry(k, v)); try!(map.serialize_entry(k, v));
} }
map.end() map.end()
+58 -12
View File
@@ -182,9 +182,27 @@ where
} }
} }
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(all(any(feature = "std", feature = "alloc"), not(no_relaxed_trait_bounds)))]
macro_rules! seq_impl { macro_rules! seq_impl {
($ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)* >) => { ($ty:ident <T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)*>) => {
impl<T $(, $typaram)*> Serialize for $ty<T $(, $typaram)*>
where
T: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.collect_seq(self)
}
}
}
}
#[cfg(all(any(feature = "std", feature = "alloc"), no_relaxed_trait_bounds))]
macro_rules! seq_impl {
($ty:ident <T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)*>) => {
impl<T $(, $typaram)*> Serialize for $ty<T $(, $typaram)*> impl<T $(, $typaram)*> Serialize for $ty<T $(, $typaram)*>
where where
T: Serialize $(+ $tbound1 $(+ $tbound2)*)*, T: Serialize $(+ $tbound1 $(+ $tbound2)*)*,
@@ -347,9 +365,28 @@ tuple_impls! {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(all(any(feature = "std", feature = "alloc"), not(no_relaxed_trait_bounds)))]
macro_rules! map_impl { macro_rules! map_impl {
($ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)* >) => { ($ty:ident <K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)*>) => {
impl<K, V $(, $typaram)*> Serialize for $ty<K, V $(, $typaram)*>
where
K: Serialize,
V: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.collect_map(self)
}
}
}
}
#[cfg(all(any(feature = "std", feature = "alloc"), no_relaxed_trait_bounds))]
macro_rules! map_impl {
($ty:ident <K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)*>) => {
impl<K, V $(, $typaram)*> Serialize for $ty<K, V $(, $typaram)*> impl<K, V $(, $typaram)*> Serialize for $ty<K, V $(, $typaram)*>
where where
K: Serialize $(+ $kbound1 $(+ $kbound2)*)*, K: Serialize $(+ $kbound1 $(+ $kbound2)*)*,
@@ -465,7 +502,7 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
macro_rules! nonzero_integers { macro_rules! nonzero_integers {
( $( $T: ident, )+ ) => { ($($T:ident,)+) => {
$( $(
#[cfg(not(no_num_nonzero))] #[cfg(not(no_num_nonzero))]
impl Serialize for num::$T { impl Serialize for num::$T {
@@ -736,8 +773,9 @@ impl Serialize for net::Ipv4Addr {
// Skip over delimiters that we initialized buf with // Skip over delimiters that we initialized buf with
written += format_u8(*oct, &mut buf[written + 1..]) + 1; written += format_u8(*oct, &mut buf[written + 1..]) + 1;
} }
// We've only written ASCII bytes to the buffer, so it is valid UTF-8 // Safety: We've only written ASCII bytes to the buffer, so it is valid UTF-8
serializer.serialize_str(unsafe { str::from_utf8_unchecked(&buf[..written]) }) let buf = unsafe { str::from_utf8_unchecked(&buf[..written]) };
serializer.serialize_str(buf)
} else { } else {
self.octets().serialize(serializer) self.octets().serialize(serializer)
} }
@@ -909,8 +947,9 @@ where
#[cfg(all(feature = "std", not(no_std_atomic)))] #[cfg(all(feature = "std", not(no_std_atomic)))]
macro_rules! atomic_impl { macro_rules! atomic_impl {
($($ty:ident)*) => { ($($ty:ident $size:expr)*) => {
$( $(
#[cfg(any(no_target_has_atomic, target_has_atomic = $size))]
impl Serialize for $ty { impl Serialize for $ty {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where where
@@ -926,12 +965,19 @@ macro_rules! atomic_impl {
#[cfg(all(feature = "std", not(no_std_atomic)))] #[cfg(all(feature = "std", not(no_std_atomic)))]
atomic_impl! { atomic_impl! {
AtomicBool AtomicBool "8"
AtomicI8 AtomicI16 AtomicI32 AtomicIsize AtomicI8 "8"
AtomicU8 AtomicU16 AtomicU32 AtomicUsize AtomicI16 "16"
AtomicI32 "32"
AtomicIsize "ptr"
AtomicU8 "8"
AtomicU16 "16"
AtomicU32 "32"
AtomicUsize "ptr"
} }
#[cfg(all(feature = "std", not(no_std_atomic64)))] #[cfg(all(feature = "std", not(no_std_atomic64)))]
atomic_impl! { atomic_impl! {
AtomicI64 AtomicU64 AtomicI64 "64"
AtomicU64 "64"
} }
+4 -1
View File
@@ -115,10 +115,13 @@ mod impossible;
pub use self::impossible::Impossible; pub use self::impossible::Impossible;
#[cfg(all(feature = "unstable", not(feature = "std")))]
#[doc(inline)]
pub use core::error::Error as StdError;
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[doc(no_inline)] #[doc(no_inline)]
pub use std::error::Error as StdError; pub use std::error::Error as StdError;
#[cfg(not(feature = "std"))] #[cfg(not(any(feature = "std", feature = "unstable")))]
#[doc(no_inline)] #[doc(no_inline)]
pub use std_error::Error as StdError; pub use std_error::Error as StdError;
+2 -2
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_derive" name = "serde_derive"
version = "1.0.146" # remember to update html_root_url version = "1.0.151" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
categories = ["no-std"] categories = ["no-std"]
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
@@ -24,7 +24,7 @@ proc-macro = true
[dependencies] [dependencies]
proc-macro2 = "1.0" proc-macro2 = "1.0"
quote = "1.0" quote = "1.0"
syn = "1.0.90" syn = "1.0.104"
[dev-dependencies] [dev-dependencies]
serde = { version = "1.0", path = "../serde" } serde = { version = "1.0", path = "../serde" }
+2
View File
@@ -6,6 +6,8 @@ use std::str;
// opening a GitHub issue if your build environment requires some way to enable // opening a GitHub issue if your build environment requires some way to enable
// these cfgs other than by executing our build script. // these cfgs other than by executing our build script.
fn main() { fn main() {
println!("cargo:rerun-if-changed=build.rs");
let minor = match rustc_minor_version() { let minor = match rustc_minor_version() {
Some(minor) => minor, Some(minor) => minor,
None => return, None => return,
+98 -88
View File
@@ -10,6 +10,7 @@ use fragment::{Expr, Fragment, Match, Stmts};
use internals::ast::{Container, Data, Field, Style, Variant}; use internals::ast::{Container, Data, Field, Style, Variant};
use internals::{attr, replace_receiver, ungroup, Ctxt, Derive}; use internals::{attr, replace_receiver, ungroup, Ctxt, Derive};
use pretend; use pretend;
use this;
use std::collections::BTreeSet; use std::collections::BTreeSet;
use std::ptr; use std::ptr;
@@ -111,9 +112,13 @@ struct Parameters {
local: syn::Ident, local: syn::Ident,
/// Path to the type the impl is for. Either a single `Ident` for local /// Path to the type the impl is for. Either a single `Ident` for local
/// types or `some::remote::Ident` for remote types. Does not include /// types (does not include generic parameters) or `some::remote::Path` for
/// generic parameters. /// remote types.
this: syn::Path, this_type: syn::Path,
/// Same as `this_type` but using `::<T>` for generic parameters for use in
/// expression position.
this_value: syn::Path,
/// Generics including any explicit and inferred bounds for the impl. /// Generics including any explicit and inferred bounds for the impl.
generics: syn::Generics, generics: syn::Generics,
@@ -133,10 +138,8 @@ struct Parameters {
impl Parameters { impl Parameters {
fn new(cont: &Container) -> Self { fn new(cont: &Container) -> Self {
let local = cont.ident.clone(); let local = cont.ident.clone();
let this = match cont.attrs.remote() { let this_type = this::this_type(cont);
Some(remote) => remote.clone(), let this_value = this::this_value(cont);
None => cont.ident.clone().into(),
};
let borrowed = borrowed_lifetimes(cont); let borrowed = borrowed_lifetimes(cont);
let generics = build_generics(cont, &borrowed); let generics = build_generics(cont, &borrowed);
let has_getter = cont.data.has_getter(); let has_getter = cont.data.has_getter();
@@ -144,7 +147,8 @@ impl Parameters {
Parameters { Parameters {
local, local,
this, this_type,
this_value,
generics, generics,
borrowed, borrowed,
has_getter, has_getter,
@@ -155,7 +159,7 @@ impl Parameters {
/// Type name to use in error messages and `&'static str` arguments to /// Type name to use in error messages and `&'static str` arguments to
/// various Deserializer methods. /// various Deserializer methods.
fn type_name(&self) -> String { fn type_name(&self) -> String {
self.this.segments.last().unwrap().ident.to_string() self.this_type.segments.last().unwrap().ident.to_string()
} }
} }
@@ -358,7 +362,7 @@ fn deserialize_transparent(cont: &Container, params: &Parameters) -> Fragment {
Data::Enum(_) => unreachable!(), Data::Enum(_) => unreachable!(),
}; };
let this = &params.this; let this_value = &params.this_value;
let transparent_field = fields.iter().find(|f| f.attrs.transparent()).unwrap(); let transparent_field = fields.iter().find(|f| f.attrs.transparent()).unwrap();
let path = match transparent_field.attrs.deserialize_with() { let path = match transparent_field.attrs.deserialize_with() {
@@ -386,7 +390,7 @@ fn deserialize_transparent(cont: &Container, params: &Parameters) -> Fragment {
quote_block! { quote_block! {
_serde::__private::Result::map( _serde::__private::Result::map(
#path(__deserializer), #path(__deserializer),
|__transparent| #this { #(#assign),* }) |__transparent| #this_value { #(#assign),* })
} }
} }
@@ -407,7 +411,8 @@ fn deserialize_try_from(type_try_from: &syn::Type) -> Fragment {
} }
fn deserialize_unit_struct(params: &Parameters, cattrs: &attr::Container) -> Fragment { fn deserialize_unit_struct(params: &Parameters, cattrs: &attr::Container) -> Fragment {
let this = &params.this; let this_type = &params.this_type;
let this_value = &params.this_value;
let type_name = cattrs.name().deserialize_name(); let type_name = cattrs.name().deserialize_name();
let expecting = format!("unit struct {}", params.type_name()); let expecting = format!("unit struct {}", params.type_name());
@@ -417,7 +422,7 @@ fn deserialize_unit_struct(params: &Parameters, cattrs: &attr::Container) -> Fra
struct __Visitor; struct __Visitor;
impl<'de> _serde::de::Visitor<'de> for __Visitor { impl<'de> _serde::de::Visitor<'de> for __Visitor {
type Value = #this; type Value = #this_type;
fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result { fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(__formatter, #expecting) _serde::__private::Formatter::write_str(__formatter, #expecting)
@@ -428,7 +433,7 @@ fn deserialize_unit_struct(params: &Parameters, cattrs: &attr::Container) -> Fra
where where
__E: _serde::de::Error, __E: _serde::de::Error,
{ {
_serde::__private::Ok(#this) _serde::__private::Ok(#this_value)
} }
} }
@@ -443,7 +448,8 @@ fn deserialize_tuple(
cattrs: &attr::Container, cattrs: &attr::Container,
deserializer: Option<TokenStream>, deserializer: Option<TokenStream>,
) -> Fragment { ) -> Fragment {
let this = &params.this; let this_type = &params.this_type;
let this_value = &params.this_value;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
split_with_de_lifetime(params); split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime(); let delife = params.borrowed.de_lifetime();
@@ -457,7 +463,7 @@ fn deserialize_tuple(
let local = &params.local; let local = &params.local;
quote!(#local) quote!(#local)
} else { } else {
quote!(#this) quote!(#this_value)
}; };
let is_enum = variant_ident.is_some(); let is_enum = variant_ident.is_some();
@@ -485,7 +491,7 @@ fn deserialize_tuple(
let visitor_expr = quote! { let visitor_expr = quote! {
__Visitor { __Visitor {
marker: _serde::__private::PhantomData::<#this #ty_generics>, marker: _serde::__private::PhantomData::<#this_type #ty_generics>,
lifetime: _serde::__private::PhantomData, lifetime: _serde::__private::PhantomData,
} }
}; };
@@ -510,12 +516,12 @@ fn deserialize_tuple(
quote_block! { quote_block! {
struct __Visitor #de_impl_generics #where_clause { struct __Visitor #de_impl_generics #where_clause {
marker: _serde::__private::PhantomData<#this #ty_generics>, marker: _serde::__private::PhantomData<#this_type #ty_generics>,
lifetime: _serde::__private::PhantomData<&#delife ()>, lifetime: _serde::__private::PhantomData<&#delife ()>,
} }
impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause { impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause {
type Value = #this #ty_generics; type Value = #this_type #ty_generics;
fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result { fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(__formatter, #expecting) _serde::__private::Formatter::write_str(__formatter, #expecting)
@@ -544,7 +550,7 @@ fn deserialize_tuple_in_place(
cattrs: &attr::Container, cattrs: &attr::Container,
deserializer: Option<TokenStream>, deserializer: Option<TokenStream>,
) -> Fragment { ) -> Fragment {
let this = &params.this; let this_type = &params.this_type;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
split_with_de_lifetime(params); split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime(); let delife = params.borrowed.de_lifetime();
@@ -600,7 +606,7 @@ fn deserialize_tuple_in_place(
quote_block! { quote_block! {
struct __Visitor #in_place_impl_generics #where_clause { struct __Visitor #in_place_impl_generics #where_clause {
place: &#place_life mut #this #ty_generics, place: &#place_life mut #this_type #ty_generics,
lifetime: _serde::__private::PhantomData<&#delife ()>, lifetime: _serde::__private::PhantomData<&#delife ()>,
} }
@@ -705,9 +711,10 @@ fn deserialize_seq(
}; };
if params.has_getter { if params.has_getter {
let this = &params.this; let this_type = &params.this_type;
let (_, ty_generics, _) = params.generics.split_for_impl();
result = quote! { result = quote! {
_serde::__private::Into::<#this>::into(#result) _serde::__private::Into::<#this_type #ty_generics>::into(#result)
}; };
} }
@@ -801,14 +808,14 @@ fn deserialize_seq_in_place(
} }
}); });
let this = &params.this; let this_type = &params.this_type;
let (_, ty_generics, _) = params.generics.split_for_impl(); let (_, ty_generics, _) = params.generics.split_for_impl();
let let_default = match cattrs.default() { let let_default = match cattrs.default() {
attr::Default::Default => Some(quote!( attr::Default::Default => Some(quote!(
let __default: #this #ty_generics = _serde::__private::Default::default(); let __default: #this_type #ty_generics = _serde::__private::Default::default();
)), )),
attr::Default::Path(path) => Some(quote!( attr::Default::Path(path) => Some(quote!(
let __default: #this #ty_generics = #path(); let __default: #this_type #ty_generics = #path();
)), )),
attr::Default::None => { attr::Default::None => {
// We don't need the default value, to prevent an unused variable warning // We don't need the default value, to prevent an unused variable warning
@@ -849,9 +856,10 @@ fn deserialize_newtype_struct(
let mut result = quote!(#type_path(__field0)); let mut result = quote!(#type_path(__field0));
if params.has_getter { if params.has_getter {
let this = &params.this; let this_type = &params.this_type;
let (_, ty_generics, _) = params.generics.split_for_impl();
result = quote! { result = quote! {
_serde::__private::Into::<#this>::into(#result) _serde::__private::Into::<#this_type #ty_generics>::into(#result)
}; };
} }
@@ -901,7 +909,8 @@ fn deserialize_struct(
) -> Fragment { ) -> Fragment {
let is_enum = variant_ident.is_some(); let is_enum = variant_ident.is_some();
let this = &params.this; let this_type = &params.this_type;
let this_value = &params.this_value;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
split_with_de_lifetime(params); split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime(); let delife = params.borrowed.de_lifetime();
@@ -913,7 +922,7 @@ fn deserialize_struct(
let local = &params.local; let local = &params.local;
quote!(#local) quote!(#local)
} else { } else {
quote!(#this) quote!(#this_value)
}; };
let type_path = match variant_ident { let type_path = match variant_ident {
@@ -941,7 +950,7 @@ fn deserialize_struct(
let visitor_expr = quote! { let visitor_expr = quote! {
__Visitor { __Visitor {
marker: _serde::__private::PhantomData::<#this #ty_generics>, marker: _serde::__private::PhantomData::<#this_type #ty_generics>,
lifetime: _serde::__private::PhantomData, lifetime: _serde::__private::PhantomData,
} }
}; };
@@ -993,7 +1002,7 @@ fn deserialize_struct(
let visitor_seed = if is_enum && cattrs.has_flatten() { let visitor_seed = if is_enum && cattrs.has_flatten() {
Some(quote! { Some(quote! {
impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Visitor #de_ty_generics #where_clause { impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Visitor #de_ty_generics #where_clause {
type Value = #this #ty_generics; type Value = #this_type #ty_generics;
fn deserialize<__D>(self, __deserializer: __D) -> _serde::__private::Result<Self::Value, __D::Error> fn deserialize<__D>(self, __deserializer: __D) -> _serde::__private::Result<Self::Value, __D::Error>
where where
@@ -1011,12 +1020,12 @@ fn deserialize_struct(
#field_visitor #field_visitor
struct __Visitor #de_impl_generics #where_clause { struct __Visitor #de_impl_generics #where_clause {
marker: _serde::__private::PhantomData<#this #ty_generics>, marker: _serde::__private::PhantomData<#this_type #ty_generics>,
lifetime: _serde::__private::PhantomData<&#delife ()>, lifetime: _serde::__private::PhantomData<&#delife ()>,
} }
impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause { impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause {
type Value = #this #ty_generics; type Value = #this_type #ty_generics;
fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result { fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(__formatter, #expecting) _serde::__private::Formatter::write_str(__formatter, #expecting)
@@ -1057,7 +1066,7 @@ fn deserialize_struct_in_place(
return None; return None;
} }
let this = &params.this; let this_type = &params.this_type;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
split_with_de_lifetime(params); split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime(); let delife = params.borrowed.de_lifetime();
@@ -1123,7 +1132,7 @@ fn deserialize_struct_in_place(
#field_visitor #field_visitor
struct __Visitor #in_place_impl_generics #where_clause { struct __Visitor #in_place_impl_generics #where_clause {
place: &#place_life mut #this #ty_generics, place: &#place_life mut #this_type #ty_generics,
lifetime: _serde::__private::PhantomData<&#delife ()>, lifetime: _serde::__private::PhantomData<&#delife ()>,
} }
@@ -1212,7 +1221,7 @@ fn deserialize_externally_tagged_enum(
variants: &[Variant], variants: &[Variant],
cattrs: &attr::Container, cattrs: &attr::Container,
) -> Fragment { ) -> Fragment {
let this = &params.this; let this_type = &params.this_type;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
split_with_de_lifetime(params); split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime(); let delife = params.borrowed.de_lifetime();
@@ -1266,12 +1275,12 @@ fn deserialize_externally_tagged_enum(
#variant_visitor #variant_visitor
struct __Visitor #de_impl_generics #where_clause { struct __Visitor #de_impl_generics #where_clause {
marker: _serde::__private::PhantomData<#this #ty_generics>, marker: _serde::__private::PhantomData<#this_type #ty_generics>,
lifetime: _serde::__private::PhantomData<&#delife ()>, lifetime: _serde::__private::PhantomData<&#delife ()>,
} }
impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause { impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause {
type Value = #this #ty_generics; type Value = #this_type #ty_generics;
fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result { fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(__formatter, #expecting) _serde::__private::Formatter::write_str(__formatter, #expecting)
@@ -1292,7 +1301,7 @@ fn deserialize_externally_tagged_enum(
#type_name, #type_name,
VARIANTS, VARIANTS,
__Visitor { __Visitor {
marker: _serde::__private::PhantomData::<#this #ty_generics>, marker: _serde::__private::PhantomData::<#this_type #ty_generics>,
lifetime: _serde::__private::PhantomData, lifetime: _serde::__private::PhantomData,
}, },
) )
@@ -1354,7 +1363,8 @@ fn deserialize_adjacently_tagged_enum(
tag: &str, tag: &str,
content: &str, content: &str,
) -> Fragment { ) -> Fragment {
let this = &params.this; let this_type = &params.this_type;
let this_value = &params.this_value;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
split_with_de_lifetime(params); split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime(); let delife = params.borrowed.de_lifetime();
@@ -1415,13 +1425,13 @@ fn deserialize_adjacently_tagged_enum(
let arm = match variant.style { let arm = match variant.style {
Style::Unit => quote! { Style::Unit => quote! {
_serde::__private::Ok(#this::#variant_ident) _serde::__private::Ok(#this_value::#variant_ident)
}, },
Style::Newtype if variant.attrs.deserialize_with().is_none() => { Style::Newtype if variant.attrs.deserialize_with().is_none() => {
let span = variant.original.span(); let span = variant.original.span();
let func = quote_spanned!(span=> _serde::__private::de::missing_field); let func = quote_spanned!(span=> _serde::__private::de::missing_field);
quote! { quote! {
#func(#content).map(#this::#variant_ident) #func(#content).map(#this_value::#variant_ident)
} }
} }
_ => { _ => {
@@ -1513,12 +1523,12 @@ fn deserialize_adjacently_tagged_enum(
struct __Seed #de_impl_generics #where_clause { struct __Seed #de_impl_generics #where_clause {
field: __Field, field: __Field,
marker: _serde::__private::PhantomData<#this #ty_generics>, marker: _serde::__private::PhantomData<#this_type #ty_generics>,
lifetime: _serde::__private::PhantomData<&#delife ()>, lifetime: _serde::__private::PhantomData<&#delife ()>,
} }
impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Seed #de_ty_generics #where_clause { impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Seed #de_ty_generics #where_clause {
type Value = #this #ty_generics; type Value = #this_type #ty_generics;
fn deserialize<__D>(self, __deserializer: __D) -> _serde::__private::Result<Self::Value, __D::Error> fn deserialize<__D>(self, __deserializer: __D) -> _serde::__private::Result<Self::Value, __D::Error>
where where
@@ -1531,12 +1541,12 @@ fn deserialize_adjacently_tagged_enum(
} }
struct __Visitor #de_impl_generics #where_clause { struct __Visitor #de_impl_generics #where_clause {
marker: _serde::__private::PhantomData<#this #ty_generics>, marker: _serde::__private::PhantomData<#this_type #ty_generics>,
lifetime: _serde::__private::PhantomData<&#delife ()>, lifetime: _serde::__private::PhantomData<&#delife ()>,
} }
impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause { impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause {
type Value = #this #ty_generics; type Value = #this_type #ty_generics;
fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result { fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(__formatter, #expecting) _serde::__private::Formatter::write_str(__formatter, #expecting)
@@ -1638,7 +1648,7 @@ fn deserialize_adjacently_tagged_enum(
#type_name, #type_name,
FIELDS, FIELDS,
__Visitor { __Visitor {
marker: _serde::__private::PhantomData::<#this #ty_generics>, marker: _serde::__private::PhantomData::<#this_type #ty_generics>,
lifetime: _serde::__private::PhantomData, lifetime: _serde::__private::PhantomData,
}, },
) )
@@ -1707,10 +1717,10 @@ fn deserialize_externally_tagged_variant(
match variant.style { match variant.style {
Style::Unit => { Style::Unit => {
let this = &params.this; let this_value = &params.this_value;
quote_block! { quote_block! {
try!(_serde::de::VariantAccess::unit_variant(__variant)); try!(_serde::de::VariantAccess::unit_variant(__variant));
_serde::__private::Ok(#this::#variant_ident) _serde::__private::Ok(#this_value::#variant_ident)
} }
} }
Style::Newtype => deserialize_externally_tagged_newtype_variant( Style::Newtype => deserialize_externally_tagged_newtype_variant(
@@ -1749,7 +1759,7 @@ fn deserialize_internally_tagged_variant(
match effective_style(variant) { match effective_style(variant) {
Style::Unit => { Style::Unit => {
let this = &params.this; let this_value = &params.this_value;
let type_name = params.type_name(); let type_name = params.type_name();
let variant_name = variant.ident.to_string(); let variant_name = variant.ident.to_string();
let default = variant.fields.get(0).map(|field| { let default = variant.fields.get(0).map(|field| {
@@ -1758,7 +1768,7 @@ fn deserialize_internally_tagged_variant(
}); });
quote_block! { quote_block! {
try!(_serde::Deserializer::deserialize_any(#deserializer, _serde::__private::de::InternallyTaggedUnitVisitor::new(#type_name, #variant_name))); try!(_serde::Deserializer::deserialize_any(#deserializer, _serde::__private::de::InternallyTaggedUnitVisitor::new(#type_name, #variant_name)));
_serde::__private::Ok(#this::#variant_ident #default) _serde::__private::Ok(#this_value::#variant_ident #default)
} }
} }
Style::Newtype => deserialize_untagged_newtype_variant( Style::Newtype => deserialize_untagged_newtype_variant(
@@ -1796,7 +1806,7 @@ fn deserialize_untagged_variant(
match effective_style(variant) { match effective_style(variant) {
Style::Unit => { Style::Unit => {
let this = &params.this; let this_value = &params.this_value;
let type_name = params.type_name(); let type_name = params.type_name();
let variant_name = variant.ident.to_string(); let variant_name = variant.ident.to_string();
let default = variant.fields.get(0).map(|field| { let default = variant.fields.get(0).map(|field| {
@@ -1808,7 +1818,7 @@ fn deserialize_untagged_variant(
#deserializer, #deserializer,
_serde::__private::de::UntaggedUnitVisitor::new(#type_name, #variant_name) _serde::__private::de::UntaggedUnitVisitor::new(#type_name, #variant_name)
) { ) {
_serde::__private::Ok(()) => _serde::__private::Ok(#this::#variant_ident #default), _serde::__private::Ok(()) => _serde::__private::Ok(#this_value::#variant_ident #default),
_serde::__private::Err(__err) => _serde::__private::Err(__err), _serde::__private::Err(__err) => _serde::__private::Err(__err),
} }
} }
@@ -1843,14 +1853,13 @@ fn deserialize_externally_tagged_newtype_variant(
field: &Field, field: &Field,
cattrs: &attr::Container, cattrs: &attr::Container,
) -> Fragment { ) -> Fragment {
let this = &params.this; let this_value = &params.this_value;
if field.attrs.skip_deserializing() { if field.attrs.skip_deserializing() {
let this = &params.this;
let default = Expr(expr_is_missing(field, cattrs)); let default = Expr(expr_is_missing(field, cattrs));
return quote_block! { return quote_block! {
try!(_serde::de::VariantAccess::unit_variant(__variant)); try!(_serde::de::VariantAccess::unit_variant(__variant));
_serde::__private::Ok(#this::#variant_ident(#default)) _serde::__private::Ok(#this_value::#variant_ident(#default))
}; };
} }
@@ -1861,7 +1870,7 @@ fn deserialize_externally_tagged_newtype_variant(
let func = let func =
quote_spanned!(span=> _serde::de::VariantAccess::newtype_variant::<#field_ty>); quote_spanned!(span=> _serde::de::VariantAccess::newtype_variant::<#field_ty>);
quote_expr! { quote_expr! {
_serde::__private::Result::map(#func(__variant), #this::#variant_ident) _serde::__private::Result::map(#func(__variant), #this_value::#variant_ident)
} }
} }
Some(path) => { Some(path) => {
@@ -1870,7 +1879,7 @@ fn deserialize_externally_tagged_newtype_variant(
#wrapper #wrapper
_serde::__private::Result::map( _serde::__private::Result::map(
_serde::de::VariantAccess::newtype_variant::<#wrapper_ty>(__variant), _serde::de::VariantAccess::newtype_variant::<#wrapper_ty>(__variant),
|__wrapper| #this::#variant_ident(__wrapper.value)) |__wrapper| #this_value::#variant_ident(__wrapper.value))
} }
} }
} }
@@ -1882,20 +1891,20 @@ fn deserialize_untagged_newtype_variant(
field: &Field, field: &Field,
deserializer: &TokenStream, deserializer: &TokenStream,
) -> Fragment { ) -> Fragment {
let this = &params.this; let this_value = &params.this_value;
let field_ty = field.ty; let field_ty = field.ty;
match field.attrs.deserialize_with() { match field.attrs.deserialize_with() {
None => { None => {
let span = field.original.span(); let span = field.original.span();
let func = quote_spanned!(span=> <#field_ty as _serde::Deserialize>::deserialize); let func = quote_spanned!(span=> <#field_ty as _serde::Deserialize>::deserialize);
quote_expr! { quote_expr! {
_serde::__private::Result::map(#func(#deserializer), #this::#variant_ident) _serde::__private::Result::map(#func(#deserializer), #this_value::#variant_ident)
} }
} }
Some(path) => { Some(path) => {
quote_block! { quote_block! {
let __value: _serde::__private::Result<#field_ty, _> = #path(#deserializer); let __value: _serde::__private::Result<#field_ty, _> = #path(#deserializer);
_serde::__private::Result::map(__value, #this::#variant_ident) _serde::__private::Result::map(__value, #this_value::#variant_ident)
} }
} }
} }
@@ -1907,7 +1916,7 @@ fn deserialize_generated_identifier(
is_variant: bool, is_variant: bool,
other_idx: Option<usize>, other_idx: Option<usize>,
) -> Fragment { ) -> Fragment {
let this = quote!(__Field); let this_value = quote!(__Field);
let field_idents: &Vec<_> = &fields.iter().map(|(_, ident, _)| ident).collect(); let field_idents: &Vec<_> = &fields.iter().map(|(_, ident, _)| ident).collect();
let (ignore_variant, fallthrough) = if !is_variant && cattrs.has_flatten() { let (ignore_variant, fallthrough) = if !is_variant && cattrs.has_flatten() {
@@ -1927,7 +1936,7 @@ fn deserialize_generated_identifier(
}; };
let visitor_impl = Stmts(deserialize_identifier( let visitor_impl = Stmts(deserialize_identifier(
&this, &this_value,
fields, fields,
is_variant, is_variant,
fallthrough, fallthrough,
@@ -1982,8 +1991,8 @@ fn deserialize_custom_identifier(
attr::Identifier::No => unreachable!(), attr::Identifier::No => unreachable!(),
}; };
let this = &params.this; let this_type = params.this_type.to_token_stream();
let this = quote!(#this); let this_value = params.this_value.to_token_stream();
let (ordinary, fallthrough, fallthrough_borrowed) = if let Some(last) = variants.last() { let (ordinary, fallthrough, fallthrough_borrowed) = if let Some(last) = variants.last() {
let last_ident = &last.ident; let last_ident = &last.ident;
@@ -1992,7 +2001,7 @@ fn deserialize_custom_identifier(
// last variant (checked in `check_identifier`), so all preceding // last variant (checked in `check_identifier`), so all preceding
// are ordinary variants. // are ordinary variants.
let ordinary = &variants[..variants.len() - 1]; let ordinary = &variants[..variants.len() - 1];
let fallthrough = quote!(_serde::__private::Ok(#this::#last_ident)); let fallthrough = quote!(_serde::__private::Ok(#this_value::#last_ident));
(ordinary, Some(fallthrough), None) (ordinary, Some(fallthrough), None)
} else if let Style::Newtype = last.style { } else if let Style::Newtype = last.style {
let ordinary = &variants[..variants.len() - 1]; let ordinary = &variants[..variants.len() - 1];
@@ -2002,7 +2011,7 @@ fn deserialize_custom_identifier(
_serde::Deserialize::deserialize( _serde::Deserialize::deserialize(
_serde::__private::de::IdentifierDeserializer::from(#value) _serde::__private::de::IdentifierDeserializer::from(#value)
), ),
#this::#last_ident) #this_value::#last_ident)
} }
}; };
( (
@@ -2050,7 +2059,7 @@ fn deserialize_custom_identifier(
split_with_de_lifetime(params); split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime(); let delife = params.borrowed.de_lifetime();
let visitor_impl = Stmts(deserialize_identifier( let visitor_impl = Stmts(deserialize_identifier(
&this, &this_value,
&names_idents, &names_idents,
is_variant, is_variant,
fallthrough, fallthrough,
@@ -2063,18 +2072,18 @@ fn deserialize_custom_identifier(
#names_const #names_const
struct __FieldVisitor #de_impl_generics #where_clause { struct __FieldVisitor #de_impl_generics #where_clause {
marker: _serde::__private::PhantomData<#this #ty_generics>, marker: _serde::__private::PhantomData<#this_type #ty_generics>,
lifetime: _serde::__private::PhantomData<&#delife ()>, lifetime: _serde::__private::PhantomData<&#delife ()>,
} }
impl #de_impl_generics _serde::de::Visitor<#delife> for __FieldVisitor #de_ty_generics #where_clause { impl #de_impl_generics _serde::de::Visitor<#delife> for __FieldVisitor #de_ty_generics #where_clause {
type Value = #this #ty_generics; type Value = #this_type #ty_generics;
#visitor_impl #visitor_impl
} }
let __visitor = __FieldVisitor { let __visitor = __FieldVisitor {
marker: _serde::__private::PhantomData::<#this #ty_generics>, marker: _serde::__private::PhantomData::<#this_type #ty_generics>,
lifetime: _serde::__private::PhantomData, lifetime: _serde::__private::PhantomData,
}; };
_serde::Deserializer::deserialize_identifier(__deserializer, __visitor) _serde::Deserializer::deserialize_identifier(__deserializer, __visitor)
@@ -2082,7 +2091,7 @@ fn deserialize_custom_identifier(
} }
fn deserialize_identifier( fn deserialize_identifier(
this: &TokenStream, this_value: &TokenStream,
fields: &[(String, Ident, Vec<String>)], fields: &[(String, Ident, Vec<String>)],
is_variant: bool, is_variant: bool,
fallthrough: Option<TokenStream>, fallthrough: Option<TokenStream>,
@@ -2103,11 +2112,11 @@ fn deserialize_identifier(
let constructors: &Vec<_> = &flat_fields let constructors: &Vec<_> = &flat_fields
.iter() .iter()
.map(|(_, ident)| quote!(#this::#ident)) .map(|(_, ident)| quote!(#this_value::#ident))
.collect(); .collect();
let main_constructors: &Vec<_> = &fields let main_constructors: &Vec<_> = &fields
.iter() .iter()
.map(|(_, ident, _)| quote!(#this::#ident)) .map(|(_, ident, _)| quote!(#this_value::#ident))
.collect(); .collect();
let expecting = expecting.unwrap_or(if is_variant { let expecting = expecting.unwrap_or(if is_variant {
@@ -2621,9 +2630,10 @@ fn deserialize_map(
let mut result = quote!(#struct_path { #(#result),* }); let mut result = quote!(#struct_path { #(#result),* });
if params.has_getter { if params.has_getter {
let this = &params.this; let this_type = &params.this_type;
let (_, ty_generics, _) = params.generics.split_for_impl();
result = quote! { result = quote! {
_serde::__private::Into::<#this>::into(#result) _serde::__private::Into::<#this_type #ty_generics>::into(#result)
}; };
} }
@@ -2803,15 +2813,15 @@ fn deserialize_map_in_place(
} }
}); });
let this = &params.this; let this_type = &params.this_type;
let (_, _, ty_generics, _) = split_with_de_lifetime(params); let (_, _, ty_generics, _) = split_with_de_lifetime(params);
let let_default = match cattrs.default() { let let_default = match cattrs.default() {
attr::Default::Default => Some(quote!( attr::Default::Default => Some(quote!(
let __default: #this #ty_generics = _serde::__private::Default::default(); let __default: #this_type #ty_generics = _serde::__private::Default::default();
)), )),
attr::Default::Path(path) => Some(quote!( attr::Default::Path(path) => Some(quote!(
let __default: #this #ty_generics = #path(); let __default: #this_type #ty_generics = #path();
)), )),
attr::Default::None => { attr::Default::None => {
// We don't need the default value, to prevent an unused variable warning // We don't need the default value, to prevent an unused variable warning
@@ -2844,7 +2854,7 @@ fn wrap_deserialize_with(
value_ty: &TokenStream, value_ty: &TokenStream,
deserialize_with: &syn::ExprPath, deserialize_with: &syn::ExprPath,
) -> (TokenStream, TokenStream) { ) -> (TokenStream, TokenStream) {
let this = &params.this; let this_type = &params.this_type;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
split_with_de_lifetime(params); split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime(); let delife = params.borrowed.de_lifetime();
@@ -2852,7 +2862,7 @@ fn wrap_deserialize_with(
let wrapper = quote! { let wrapper = quote! {
struct __DeserializeWith #de_impl_generics #where_clause { struct __DeserializeWith #de_impl_generics #where_clause {
value: #value_ty, value: #value_ty,
phantom: _serde::__private::PhantomData<#this #ty_generics>, phantom: _serde::__private::PhantomData<#this_type #ty_generics>,
lifetime: _serde::__private::PhantomData<&#delife ()>, lifetime: _serde::__private::PhantomData<&#delife ()>,
} }
@@ -2903,7 +2913,7 @@ fn unwrap_to_variant_closure(
variant: &Variant, variant: &Variant,
with_wrapper: bool, with_wrapper: bool,
) -> TokenStream { ) -> TokenStream {
let this = &params.this; let this_value = &params.this_value;
let variant_ident = &variant.ident; let variant_ident = &variant.ident;
let (arg, wrapper) = if with_wrapper { let (arg, wrapper) = if with_wrapper {
@@ -2924,23 +2934,23 @@ fn unwrap_to_variant_closure(
Style::Struct if variant.fields.len() == 1 => { Style::Struct if variant.fields.len() == 1 => {
let member = &variant.fields[0].member; let member = &variant.fields[0].member;
quote! { quote! {
|#arg| #this::#variant_ident { #member: #wrapper } |#arg| #this_value::#variant_ident { #member: #wrapper }
} }
} }
Style::Struct => { Style::Struct => {
let members = variant.fields.iter().map(|field| &field.member); let members = variant.fields.iter().map(|field| &field.member);
quote! { quote! {
|#arg| #this::#variant_ident { #(#members: #wrapper.#field_access),* } |#arg| #this_value::#variant_ident { #(#members: #wrapper.#field_access),* }
} }
} }
Style::Tuple => quote! { Style::Tuple => quote! {
|#arg| #this::#variant_ident(#(#wrapper.#field_access),*) |#arg| #this_value::#variant_ident(#(#wrapper.#field_access),*)
}, },
Style::Newtype => quote! { Style::Newtype => quote! {
|#arg| #this::#variant_ident(#wrapper) |#arg| #this_value::#variant_ident(#wrapper)
}, },
Style::Unit => quote! { Style::Unit => quote! {
|#arg| #this::#variant_ident |#arg| #this_value::#variant_ident
}, },
} }
} }
+23
View File
@@ -6,6 +6,7 @@ use syn::{Member, Type};
/// Cross-cutting checks that require looking at more than a single attrs /// Cross-cutting checks that require looking at more than a single attrs
/// object. Simpler checks should happen when parsing and building the attrs. /// object. Simpler checks should happen when parsing and building the attrs.
pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) { pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
check_remote_generic(cx, cont);
check_getter(cx, cont); check_getter(cx, cont);
check_flatten(cx, cont); check_flatten(cx, cont);
check_identifier(cx, cont); check_identifier(cx, cont);
@@ -16,6 +17,28 @@ pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
check_from_and_try_from(cx, cont); check_from_and_try_from(cx, cont);
} }
/// Remote derive definition type must have either all of the generics of the
/// remote type:
///
/// #[serde(remote = "Generic")]
/// struct Generic<T> {…}
///
/// or none of them, i.e. defining impls for one concrete instantiation of the
/// remote type only:
///
/// #[serde(remote = "Generic<T>")]
/// struct ConcreteDef {…}
///
fn check_remote_generic(cx: &Ctxt, cont: &Container) {
if let Some(remote) = cont.attrs.remote() {
let local_has_generic = !cont.generics.params.is_empty();
let remote_has_generic = !remote.segments.last().unwrap().arguments.is_none();
if local_has_generic && remote_has_generic {
cx.error_spanned_by(remote, "remove generic parameters from this path");
}
}
}
/// Getters are only allowed inside structs (not enums) with the `remote` /// Getters are only allowed inside structs (not enums) with the `remote`
/// attribute. /// attribute.
fn check_getter(cx: &Ctxt, cont: &Container) { fn check_getter(cx: &Ctxt, cont: &Container) {
+2 -2
View File
@@ -13,7 +13,7 @@
//! //!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html //! [https://serde.rs/derive.html]: https://serde.rs/derive.html
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.146")] #![doc(html_root_url = "https://docs.rs/serde_derive/1.0.151")]
#![allow(unknown_lints, bare_trait_objects)] #![allow(unknown_lints, bare_trait_objects)]
// Ignored clippy lints // Ignored clippy lints
#![allow( #![allow(
@@ -43,7 +43,6 @@
clippy::enum_glob_use, clippy::enum_glob_use,
clippy::indexing_slicing, clippy::indexing_slicing,
clippy::items_after_statements, clippy::items_after_statements,
clippy::let_underscore_drop,
clippy::manual_assert, clippy::manual_assert,
clippy::map_err_ignore, clippy::map_err_ignore,
clippy::match_same_arms, clippy::match_same_arms,
@@ -85,6 +84,7 @@ mod de;
mod dummy; mod dummy;
mod pretend; mod pretend;
mod ser; mod ser;
mod this;
mod try; mod try;
#[proc_macro_derive(Serialize, attributes(serde))] #[proc_macro_derive(Serialize, attributes(serde))]
+32 -30
View File
@@ -8,6 +8,7 @@ use fragment::{Fragment, Match, Stmts};
use internals::ast::{Container, Data, Field, Style, Variant}; use internals::ast::{Container, Data, Field, Style, Variant};
use internals::{attr, replace_receiver, Ctxt, Derive}; use internals::{attr, replace_receiver, Ctxt, Derive};
use pretend; use pretend;
use this;
pub fn expand_derive_serialize( pub fn expand_derive_serialize(
input: &mut syn::DeriveInput, input: &mut syn::DeriveInput,
@@ -82,9 +83,13 @@ struct Parameters {
self_var: Ident, self_var: Ident,
/// Path to the type the impl is for. Either a single `Ident` for local /// Path to the type the impl is for. Either a single `Ident` for local
/// types or `some::remote::Ident` for remote types. Does not include /// types (does not include generic parameters) or `some::remote::Path` for
/// generic parameters. /// remote types.
this: syn::Path, this_type: syn::Path,
/// Same as `this_type` but using `::<T>` for generic parameters for use in
/// expression position.
this_value: syn::Path,
/// Generics including any explicit and inferred bounds for the impl. /// Generics including any explicit and inferred bounds for the impl.
generics: syn::Generics, generics: syn::Generics,
@@ -105,18 +110,15 @@ impl Parameters {
Ident::new("self", Span::call_site()) Ident::new("self", Span::call_site())
}; };
let this = match cont.attrs.remote() { let this_type = this::this_type(cont);
Some(remote) => remote.clone(), let this_value = this::this_value(cont);
None => cont.ident.clone().into(),
};
let is_packed = cont.attrs.is_packed(); let is_packed = cont.attrs.is_packed();
let generics = build_generics(cont); let generics = build_generics(cont);
Parameters { Parameters {
self_var, self_var,
this, this_type,
this_value,
generics, generics,
is_remote, is_remote,
is_packed, is_packed,
@@ -126,7 +128,7 @@ impl Parameters {
/// Type name to use in error messages and `&'static str` arguments to /// Type name to use in error messages and `&'static str` arguments to
/// various Serializer methods. /// various Serializer methods.
fn type_name(&self) -> String { fn type_name(&self) -> String {
self.this.segments.last().unwrap().ident.to_string() self.this_type.segments.last().unwrap().ident.to_string()
} }
} }
@@ -427,7 +429,7 @@ fn serialize_variant(
variant_index: u32, variant_index: u32,
cattrs: &attr::Container, cattrs: &attr::Container,
) -> TokenStream { ) -> TokenStream {
let this = &params.this; let this_value = &params.this_value;
let variant_ident = &variant.ident; let variant_ident = &variant.ident;
if variant.attrs.skip_serializing() { if variant.attrs.skip_serializing() {
@@ -445,32 +447,32 @@ fn serialize_variant(
Style::Struct => quote!({ .. }), Style::Struct => quote!({ .. }),
}; };
quote! { quote! {
#this::#variant_ident #fields_pat => #skipped_err, #this_value::#variant_ident #fields_pat => #skipped_err,
} }
} else { } else {
// variant wasn't skipped // variant wasn't skipped
let case = match variant.style { let case = match variant.style {
Style::Unit => { Style::Unit => {
quote! { quote! {
#this::#variant_ident #this_value::#variant_ident
} }
} }
Style::Newtype => { Style::Newtype => {
quote! { quote! {
#this::#variant_ident(ref __field0) #this_value::#variant_ident(ref __field0)
} }
} }
Style::Tuple => { Style::Tuple => {
let field_names = (0..variant.fields.len()) let field_names = (0..variant.fields.len())
.map(|i| Ident::new(&format!("__field{}", i), Span::call_site())); .map(|i| Ident::new(&format!("__field{}", i), Span::call_site()));
quote! { quote! {
#this::#variant_ident(#(ref #field_names),*) #this_value::#variant_ident(#(ref #field_names),*)
} }
} }
Style::Struct => { Style::Struct => {
let members = variant.fields.iter().map(|f| &f.member); let members = variant.fields.iter().map(|f| &f.member);
quote! { quote! {
#this::#variant_ident { #(ref #members),* } #this_value::#variant_ident { #(ref #members),* }
} }
} }
}; };
@@ -640,7 +642,7 @@ fn serialize_adjacently_tagged_variant(
tag: &str, tag: &str,
content: &str, content: &str,
) -> Fragment { ) -> Fragment {
let this = &params.this; let this_type = &params.this_type;
let type_name = cattrs.name().serialize_name(); let type_name = cattrs.name().serialize_name();
let variant_name = variant.attrs.name().serialize_name(); let variant_name = variant.attrs.name().serialize_name();
@@ -719,7 +721,7 @@ fn serialize_adjacently_tagged_variant(
quote_block! { quote_block! {
struct __AdjacentlyTagged #wrapper_generics #where_clause { struct __AdjacentlyTagged #wrapper_generics #where_clause {
data: (#(&'__a #fields_ty,)*), data: (#(&'__a #fields_ty,)*),
phantom: _serde::__private::PhantomData<#this #ty_generics>, phantom: _serde::__private::PhantomData<#this_type #ty_generics>,
} }
impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause { impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause {
@@ -741,7 +743,7 @@ fn serialize_adjacently_tagged_variant(
try!(_serde::ser::SerializeStruct::serialize_field( try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #content, &__AdjacentlyTagged { &mut __struct, #content, &__AdjacentlyTagged {
data: (#(#fields_ident,)*), data: (#(#fields_ident,)*),
phantom: _serde::__private::PhantomData::<#this #ty_generics>, phantom: _serde::__private::PhantomData::<#this_type #ty_generics>,
})); }));
_serde::ser::SerializeStruct::end(__struct) _serde::ser::SerializeStruct::end(__struct)
} }
@@ -866,8 +868,8 @@ enum StructVariant<'a> {
Untagged, Untagged,
} }
fn serialize_struct_variant<'a>( fn serialize_struct_variant(
context: StructVariant<'a>, context: StructVariant,
params: &Parameters, params: &Parameters,
fields: &[Field], fields: &[Field],
name: &str, name: &str,
@@ -950,8 +952,8 @@ fn serialize_struct_variant<'a>(
} }
} }
fn serialize_struct_variant_with_flatten<'a>( fn serialize_struct_variant_with_flatten(
context: StructVariant<'a>, context: StructVariant,
params: &Parameters, params: &Parameters,
fields: &[Field], fields: &[Field],
name: &str, name: &str,
@@ -971,7 +973,7 @@ fn serialize_struct_variant_with_flatten<'a>(
variant_index, variant_index,
variant_name, variant_name,
} => { } => {
let this = &params.this; let this_type = &params.this_type;
let fields_ty = fields.iter().map(|f| &f.ty); let fields_ty = fields.iter().map(|f| &f.ty);
let members = &fields.iter().map(|f| &f.member).collect::<Vec<_>>(); let members = &fields.iter().map(|f| &f.member).collect::<Vec<_>>();
@@ -982,7 +984,7 @@ fn serialize_struct_variant_with_flatten<'a>(
quote_block! { quote_block! {
struct __EnumFlatten #wrapper_generics #where_clause { struct __EnumFlatten #wrapper_generics #where_clause {
data: (#(&'__a #fields_ty,)*), data: (#(&'__a #fields_ty,)*),
phantom: _serde::__private::PhantomData<#this #ty_generics>, phantom: _serde::__private::PhantomData<#this_type #ty_generics>,
} }
impl #wrapper_impl_generics _serde::Serialize for __EnumFlatten #wrapper_ty_generics #where_clause { impl #wrapper_impl_generics _serde::Serialize for __EnumFlatten #wrapper_ty_generics #where_clause {
@@ -1006,7 +1008,7 @@ fn serialize_struct_variant_with_flatten<'a>(
#variant_name, #variant_name,
&__EnumFlatten { &__EnumFlatten {
data: (#(#members,)*), data: (#(#members,)*),
phantom: _serde::__private::PhantomData::<#this #ty_generics>, phantom: _serde::__private::PhantomData::<#this_type #ty_generics>,
}) })
} }
} }
@@ -1192,7 +1194,7 @@ fn wrap_serialize_with(
field_tys: &[&syn::Type], field_tys: &[&syn::Type],
field_exprs: &[TokenStream], field_exprs: &[TokenStream],
) -> TokenStream { ) -> TokenStream {
let this = &params.this; let this_type = &params.this_type;
let (_, ty_generics, where_clause) = params.generics.split_for_impl(); let (_, ty_generics, where_clause) = params.generics.split_for_impl();
let wrapper_generics = if field_exprs.is_empty() { let wrapper_generics = if field_exprs.is_empty() {
@@ -1212,7 +1214,7 @@ fn wrap_serialize_with(
quote!({ quote!({
struct __SerializeWith #wrapper_impl_generics #where_clause { struct __SerializeWith #wrapper_impl_generics #where_clause {
values: (#(&'__a #field_tys, )*), values: (#(&'__a #field_tys, )*),
phantom: _serde::__private::PhantomData<#this #ty_generics>, phantom: _serde::__private::PhantomData<#this_type #ty_generics>,
} }
impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause { impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause {
@@ -1226,7 +1228,7 @@ fn wrap_serialize_with(
&__SerializeWith { &__SerializeWith {
values: (#(#field_exprs, )*), values: (#(#field_exprs, )*),
phantom: _serde::__private::PhantomData::<#this #ty_generics>, phantom: _serde::__private::PhantomData::<#this_type #ty_generics>,
} }
}) })
} }
+32
View File
@@ -0,0 +1,32 @@
use internals::ast::Container;
use syn::{Path, PathArguments, Token};
pub fn this_type(cont: &Container) -> Path {
if let Some(remote) = cont.attrs.remote() {
let mut this = remote.clone();
for segment in &mut this.segments {
if let PathArguments::AngleBracketed(arguments) = &mut segment.arguments {
arguments.colon2_token = None;
}
}
this
} else {
Path::from(cont.ident.clone())
}
}
pub fn this_value(cont: &Container) -> Path {
if let Some(remote) = cont.attrs.remote() {
let mut this = remote.clone();
for segment in &mut this.segments {
if let PathArguments::AngleBracketed(arguments) = &mut segment.arguments {
if arguments.colon2_token.is_none() {
arguments.colon2_token = Some(Token![::](arguments.lt_token.span));
}
}
}
this
} else {
Path::from(cont.ident.clone())
}
}
+1 -1
View File
@@ -17,7 +17,7 @@ path = "lib.rs"
[dependencies] [dependencies]
proc-macro2 = "1.0" proc-macro2 = "1.0"
quote = "1.0" quote = "1.0"
syn = { version = "1.0.90", default-features = false, features = ["derive", "parsing", "printing", "clone-impls"] } syn = { version = "1.0.104", default-features = false, features = ["derive", "parsing", "printing", "clone-impls"] }
[package.metadata.docs.rs] [package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"] targets = ["x86_64-unknown-linux-gnu"]
+3
View File
@@ -1,6 +1,9 @@
use std::path::Path; use std::path::Path;
fn main() { fn main() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=src/mod.rs");
// Sometimes on Windows the git checkout does not correctly wire up the // Sometimes on Windows the git checkout does not correctly wire up the
// symlink from serde_derive_internals/src to serde_derive/src/internals. // symlink from serde_derive_internals/src to serde_derive/src/internals.
// When this happens we'll just build based on relative paths within the git // When this happens we'll just build based on relative paths within the git
-1
View File
@@ -22,7 +22,6 @@
clippy::doc_markdown, clippy::doc_markdown,
clippy::enum_glob_use, clippy::enum_glob_use,
clippy::items_after_statements, clippy::items_after_statements,
clippy::let_underscore_drop,
clippy::manual_assert, clippy::manual_assert,
clippy::match_same_arms, clippy::match_same_arms,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6984 // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6984
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_test" name = "serde_test"
version = "1.0.146" # remember to update html_root_url version = "1.0.151" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
build = "build.rs" build = "build.rs"
categories = ["development-tools::testing"] categories = ["development-tools::testing"]
+2
View File
@@ -6,6 +6,8 @@ use std::str::{self, FromStr};
// opening a GitHub issue if your build environment requires some way to enable // opening a GitHub issue if your build environment requires some way to enable
// these cfgs other than by executing our build script. // these cfgs other than by executing our build script.
fn main() { fn main() {
println!("cargo:rerun-if-changed=build.rs");
let minor = match rustc_minor_version() { let minor = match rustc_minor_version() {
Some(minor) => minor, Some(minor) => minor,
None => return, None => return,
+1 -1
View File
@@ -144,7 +144,7 @@
//! # } //! # }
//! ``` //! ```
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.146")] #![doc(html_root_url = "https://docs.rs/serde_test/1.0.151")]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] #![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
// Ignored clippy lints // Ignored clippy lints
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp, needless_doctest_main))] #![cfg_attr(feature = "cargo-clippy", allow(float_cmp, needless_doctest_main))]
+2
View File
@@ -19,6 +19,8 @@ fn has_cargo_expand() -> bool {
} }
fn main() { fn main() {
println!("cargo:rerun-if-changed=build.rs");
if cfg!(feature = "expandtest") && has_cargo_expand() { if cfg!(feature = "expandtest") && has_cargo_expand() {
println!("cargo:rustc-cfg=expandtest"); println!("cargo:rustc-cfg=expandtest");
} }
+9 -14
View File
@@ -1244,22 +1244,17 @@ where
{ {
let s = String::deserialize(deserializer)?; let s = String::deserialize(deserializer)?;
let mut pieces = s.split(';'); let mut pieces = s.split(';');
let f1 = match pieces.next() { let Some(f1) = pieces.next() else {
Some(x) => x, return Err(de::Error::invalid_length(0, &"2"));
None => return Err(de::Error::invalid_length(0, &"2")),
}; };
let f2 = match pieces.next() { let Some(f2) = pieces.next() else {
Some(x) => x, return Err(de::Error::invalid_length(1, &"2"));
None => return Err(de::Error::invalid_length(1, &"2")),
}; };
let f2 = match f2.parse() { let Ok(f2) = f2.parse() else {
Ok(n) => n, return Err(de::Error::invalid_value(
Err(_) => { Unexpected::Str(f2),
return Err(de::Error::invalid_value( &"an 8-bit signed integer",
Unexpected::Str(f2), ));
&"an 8-bit signed integer",
));
}
}; };
Ok((f1.into(), f2)) Ok((f1.into(), f2))
} }
+46
View File
@@ -74,6 +74,21 @@ mod remote {
&self.b &self.b
} }
} }
pub struct StructGeneric<T> {
pub value: T,
}
impl<T> StructGeneric<T> {
#[allow(dead_code)]
pub fn get_value(&self) -> &T {
&self.value
}
}
pub enum EnumGeneric<T> {
Variant(T),
}
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@@ -104,6 +119,12 @@ struct Test {
#[serde(with = "StructPubDef")] #[serde(with = "StructPubDef")]
struct_pub: remote::StructPub, struct_pub: remote::StructPub,
#[serde(with = "StructConcrete")]
struct_concrete: remote::StructGeneric<u8>,
#[serde(with = "EnumConcrete")]
enum_concrete: remote::EnumGeneric<u8>,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@@ -157,6 +178,25 @@ struct StructPubDef {
b: remote::Unit, b: remote::Unit,
} }
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::StructGeneric")]
struct StructGenericWithGetterDef<T> {
#[serde(getter = "remote::StructGeneric::get_value")]
value: T,
}
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::StructGeneric<u8>")]
struct StructConcrete {
value: u8,
}
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::EnumGeneric<u8>")]
enum EnumConcrete {
Variant(u8),
}
impl From<PrimitivePrivDef> for remote::PrimitivePriv { impl From<PrimitivePrivDef> for remote::PrimitivePriv {
fn from(def: PrimitivePrivDef) -> Self { fn from(def: PrimitivePrivDef) -> Self {
remote::PrimitivePriv::new(def.0) remote::PrimitivePriv::new(def.0)
@@ -180,3 +220,9 @@ impl From<StructPrivDef> for remote::StructPriv {
remote::StructPriv::new(def.a, def.b) remote::StructPriv::new(def.a, def.b)
} }
} }
impl<T> From<StructGenericWithGetterDef<T>> for remote::StructGeneric<T> {
fn from(def: StructGenericWithGetterDef<T>) -> Self {
remote::StructGeneric { value: def.value }
}
}
@@ -0,0 +1,17 @@
use serde_derive::{Deserialize, Serialize};
mod remote {
pub struct Struct<T, U> {
pub t: T,
pub u: U,
}
}
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::StructGeneric<u8>")]
struct StructDef<U> {
t: u8,
u: U,
}
fn main() {}
@@ -0,0 +1,5 @@
error: remove generic parameters from this path
--> tests/ui/remote/double_generic.rs:11:18
|
11 | #[serde(remote = "remote::StructGeneric<u8>")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^