Compare commits

...

124 Commits

Author SHA1 Message Date
David Tolnay 3bb4a5a4f6 Release 1.0.134 2022-01-20 22:22:30 -08:00
David Tolnay 6164627bea Merge pull request #2159 from serde-rs/nonzero
Write better Visitor for NonZero integers
2022-01-20 22:22:02 -08:00
David Tolnay 51aaf496d4 Write better Visitor for NonZero integers 2022-01-20 22:15:16 -08:00
David Tolnay bc66aeb0d3 Add tests of deserializing NonZero 2022-01-20 21:55:50 -08:00
David Tolnay 7e7044d457 Ignore clippy in number conversion tests 2022-01-20 21:38:31 -08:00
David Tolnay 5498dc0550 Add tests of num conversion errors 2022-01-20 21:37:16 -08:00
David Tolnay ff04e8be9b Improve coverage of num conversion in test suite 2022-01-20 21:16:50 -08:00
David Tolnay 69240c17c5 Eliminate macro from serialization tests 2022-01-20 20:37:08 -08:00
David Tolnay 237434f19c Accept ?Sized references in assert_ser_tokens 2022-01-20 20:21:04 -08:00
David Tolnay 1833914346 Eliminate macro from deserialization error tests 2022-01-20 19:58:45 -08:00
David Tolnay ab848060f2 Extract tests of deserialization errors to separate file 2022-01-20 19:58:01 -08:00
David Tolnay 7e39623f72 Implement test suite seq macro without tt muncher 2022-01-20 19:40:58 -08:00
David Tolnay 157dc44c51 Clean up test suite's macro formatting 2022-01-20 19:40:32 -08:00
David Tolnay 80d01a3a79 Tweak seq iterators in test suite 2022-01-20 19:40:13 -08:00
David Tolnay 343c060fc1 Adapt seq macro to not derail rustfmt 2022-01-20 19:38:51 -08:00
David Tolnay 21c1ab6c50 Format deserialization tests with rustfmt 2022-01-20 19:24:35 -08:00
David Tolnay 594ab7745d Reimplement deserialization tests without macro 2022-01-20 18:09:48 -08:00
David Tolnay 8cf0ba7fe2 Make serde_test build script buildable with older rustc 2022-01-20 17:59:21 -08:00
David Tolnay 34b52c0b83 Include build script in packaged serde_test crate 2022-01-20 17:52:25 -08:00
David Tolnay ec7ddc93cd Include 128-bit integers in test suite unconditionally 2022-01-20 15:45:07 -08:00
David Tolnay 55a7cedd73 Invert all build.rs cfgs
This allows non-Cargo builds to generally not get involved in cfgs. As
long as one is using a reasonably recent toolchain, no cfgs need to be
set and you'll get a fully-featured build.
2022-01-01 21:09:49 -08:00
David Tolnay 7af97c66b8 Release 1.0.133 2022-01-01 13:16:35 -08:00
David Tolnay 1f57084365 Merge pull request #2148 from serde-rs/deserializecontent
Optimize deserialization of recursive buffered types
2022-01-01 13:16:02 -08:00
David Tolnay 56bd369422 Optimize deserialization of recursive buffered types 2022-01-01 13:01:38 -08:00
David Tolnay ff259ec66b Detect warnings in CI 2022-01-01 11:52:55 -08:00
David Tolnay 6c54aafeb9 Document the atomic ordering in the Serialize impl 2021-12-23 11:44:31 -08:00
David Tolnay 5d41404e67 No need for the SeqCst load in test suite 2021-12-23 11:42:41 -08:00
David Tolnay 1eccb3c350 Resolve unnecessary_to_owned clippy lint in test suite
error: unnecessary use of `to_vec`
       --> test_suite/tests/test_de.rs:251:12
        |
    251 |     .chain(ignorable_tokens.to_vec().into_iter())
        |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `ignorable_tokens.iter().copied()`
        |
        = note: `-D clippy::unnecessary-to-owned` implied by `-D clippy::all`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_to_owned
2021-12-17 18:25:04 -08:00
David Tolnay 77ae1c3bf7 Release 1.0.132 2021-12-16 11:06:42 -08:00
David Tolnay b85e28166c Update path to rustc target spec files 2021-12-16 11:05:58 -08:00
David Tolnay 0508cb50fc Merge pull request #2141 from Avimitin/risc-v
Enable atomic64 on riscv64 arch
2021-12-16 11:05:14 -08:00
Avimitin 84fdc7df69 Enable atomic64 on riscv64 arch
Signed-off-by: Avimitin <avimitin@gmail.com>
2021-12-14 20:30:28 +08:00
David Tolnay ab1ca04b2e Release 1.0.131 2021-12-08 18:47:15 -08:00
David Tolnay fb2fe409c8 Touch up PR 2116 2021-12-08 18:44:41 -08:00
David Tolnay 549fac7235 Merge pull request #2116 from tyranron/fix-unused-results
Fix `unused_results` complaining rustc lint in codegen for adjacently tagged enum
2021-12-08 18:43:31 -08:00
David Tolnay c375d8b19b Merge pull request #2124 from dtolnay/cbor
Change cbor link to new repo
2021-11-26 14:48:40 -08:00
David Tolnay 6cf507f808 Change cbor link to new repo 2021-11-26 14:43:09 -08:00
David Tolnay c3c1641c06 Remove workaround for redundant_field_names Clippy bug 2021-11-04 20:23:25 -07:00
David Tolnay 1fcda0ebdb Enable pedantic lints on test suite in CI 2021-11-04 20:21:48 -07:00
David Tolnay 8f16ac0a94 Move deny(clippy) to command line arguments in the CI job 2021-11-04 20:09:35 -07:00
David Tolnay 737f78c315 Ignore enum_variant_names Clippy lint in test suite
error: all variants have the same prefix: `Serialize`
        --> test_suite/tests/test_macros.rs:1741:5
         |
    1741 | /     enum E {
    1742 | |         #[serde(rename_all = "camelCase")]
    1743 | |         Serialize {
    1744 | |             serialize: bool,
    ...    |
    1756 | |         },
    1757 | |     }
         | |_____^
         |
         = note: `-D clippy::enum-variant-names` implied by `-D clippy::all`
         = help: remove the prefixes and use full paths to the variants instead of glob imports
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names
2021-11-04 20:06:02 -07:00
David Tolnay 4a97386cb9 Clippy if_then_panic lint has been renamed to manual_assert 2021-11-04 19:57:14 -07:00
tyranron 5b32217877 Fix unused_results complaining rustc lint in codegen for adjacently tagged enum 2021-10-29 14:13:26 +03:00
David Tolnay 5b140361a3 Merge pull request #2102 from atouchet/url
Update URL
2021-10-14 16:33:22 -07:00
Alex Touchet 678351eac7 Update URL 2021-10-14 16:27:49 -07:00
David Tolnay 999c261d11 Ui test changes for trybuild 1.0.49 2021-10-08 02:46:15 -04:00
David Tolnay efbe574209 Update ui test files 2021-10-07 00:56:29 -04:00
David Tolnay 33b2677384 Suppress broken semicolon_if_nothing_returned lint
https://github.com/rust-lang/rust-clippy/issues/7768

    error: consider adding a `;` to the last statement for consistent formatting
       --> serde/src/de/impls.rs:849:1
        |
    849 | / seq_impl!(
    850 | |     BinaryHeap<T: Ord>,
    851 | |     seq,
    852 | |     BinaryHeap::clear,
    ...   |
    855 | |     BinaryHeap::push
    856 | | );
        | |__^
        |
    note: the lint level is defined here
       --> serde/src/lib.rs:97:52
        |
    97  | #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
        |                                                    ^^^^^^^^^^^^^^^
        = note: `#[deny(clippy::semicolon_if_nothing_returned)]` implied by `#[deny(clippy::pedantic)]`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
    help: add a `;` here
        |
    849 + seq_impl!(
    850 +     BinaryHeap<T: Ord>,
    851 +     seq,
    852 +     BinaryHeap::clear,
    853 +     BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint())),
    854 +     BinaryHeap::reserve,
      ...

    error: consider adding a `;` to the last statement for consistent formatting
       --> serde/src/de/impls.rs:859:1
        |
    859 | / seq_impl!(
    860 | |     BTreeSet<T: Eq + Ord>,
    861 | |     seq,
    862 | |     BTreeSet::clear,
    ...   |
    865 | |     BTreeSet::insert
    866 | | );
        | |__^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
    help: add a `;` here
        |
    859 + seq_impl!(
    860 +     BTreeSet<T: Eq + Ord>,
    861 +     seq,
    862 +     BTreeSet::clear,
    863 +     BTreeSet::new(),
    864 +     nop_reserve,
      ...

    error: consider adding a `;` to the last statement for consistent formatting
       --> serde/src/de/impls.rs:869:1
        |
    869 | / seq_impl!(
    870 | |     LinkedList<T>,
    871 | |     seq,
    872 | |     LinkedList::clear,
    ...   |
    875 | |     LinkedList::push_back
    876 | | );
        | |__^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
    help: add a `;` here
        |
    869 + seq_impl!(
    870 +     LinkedList<T>,
    871 +     seq,
    872 +     LinkedList::clear,
    873 +     LinkedList::new(),
    874 +     nop_reserve,
      ...

    error: consider adding a `;` to the last statement for consistent formatting
       --> serde/src/de/impls.rs:879:1
        |
    879 | / seq_impl!(
    880 | |     HashSet<T: Eq + Hash, S: BuildHasher + Default>,
    881 | |     seq,
    882 | |     HashSet::clear,
    883 | |     HashSet::with_capacity_and_hasher(size_hint::cautious(seq.size_hint()), S::default()),
    884 | |     HashSet::reserve,
    885 | |     HashSet::insert);
        | |_____________________^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
    help: add a `;` here
        |
    879 + seq_impl!(
    880 +     HashSet<T: Eq + Hash, S: BuildHasher + Default>,
    881 +     seq,
    882 +     HashSet::clear,
    883 +     HashSet::with_capacity_and_hasher(size_hint::cautious(seq.size_hint()), S::default()),
    884 +     HashSet::reserve,
      ...

    error: consider adding a `;` to the last statement for consistent formatting
       --> serde/src/de/impls.rs:888:1
        |
    888 | / seq_impl!(
    889 | |     VecDeque<T>,
    890 | |     seq,
    891 | |     VecDeque::clear,
    ...   |
    894 | |     VecDeque::push_back
    895 | | );
        | |__^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
    help: add a `;` here
        |
    888 + seq_impl!(
    889 +     VecDeque<T>,
    890 +     seq,
    891 +     VecDeque::clear,
    892 +     VecDeque::with_capacity(size_hint::cautious(seq.size_hint())),
    893 +     VecDeque::reserve,
      ...

    error: consider adding a `;` to the last statement for consistent formatting
        --> serde/src/de/impls.rs:1300:1
         |
    1300 | / map_impl!(
    1301 | |     BTreeMap<K: Ord, V>,
    1302 | |     map,
    1303 | |     BTreeMap::new());
         | |_____________________^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
    help: add a `;` here
         |
    1300 + map_impl!(
    1301 +     BTreeMap<K: Ord, V>,
    1302 +     map,
    1303 +     BTreeMap::new());;
         |

    error: consider adding a `;` to the last statement for consistent formatting
        --> serde/src/de/impls.rs:1306:1
         |
    1306 | / map_impl!(
    1307 | |     HashMap<K: Eq + Hash, V, S: BuildHasher + Default>,
    1308 | |     map,
    1309 | |     HashMap::with_capacity_and_hasher(size_hint::cautious(map.size_hint()), S::default()));
         | |___________________________________________________________________________________________^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
    help: add a `;` here
         |
    1306 + map_impl!(
    1307 +     HashMap<K: Eq + Hash, V, S: BuildHasher + Default>,
    1308 +     map,
    1309 +     HashMap::with_capacity_and_hasher(size_hint::cautious(map.size_hint()), S::default()));;
         |
2021-10-04 23:57:05 -04:00
David Tolnay 01ded9f405 Declare minimum Rust version in Cargo metadata 2021-10-02 02:43:22 -04:00
David Tolnay fc827ecec2 Resolve redundant_closure_for_method_calls clippy lints
error: redundant closure
      --> serde_derive/src/bound.rs:53:19
       |
    53 |         .flat_map(|predicates| predicates.to_vec());
       |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `[T]::to_vec`
       |
    note: the lint level is defined here
      --> serde_derive/src/lib.rs:18:22
       |
    18 | #![deny(clippy::all, clippy::pedantic)]
       |                      ^^^^^^^^^^^^^^^^
       = note: `#[deny(clippy::redundant_closure_for_method_calls)]` implied by `#[deny(clippy::pedantic)]`
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_for_method_calls

    error: redundant closure
      --> serde_derive/src/bound.rs:75:19
       |
    75 |         .flat_map(|predicates| predicates.to_vec());
       |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `[T]::to_vec`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_for_method_calls
2021-09-30 00:31:49 -04:00
David Tolnay 5c785eee58 Ignore if_then_panic clippy lint
error: only a `panic!` in `if`-then statement
      --> serde_derive/src/internals/ctxt.rs:58:9
       |
    58 | /         if !thread::panicking() && self.errors.borrow().is_some() {
    59 | |             panic!("forgot to check for errors");
    60 | |         }
       | |_________^ help: try: `assert!(!!thread::panicking() && self.errors.borrow().is_some(), "forgot to check for errors");`
       |
    note: the lint level is defined here
      --> serde_derive/src/lib.rs:18:9
       |
    18 | #![deny(clippy::all, clippy::pedantic)]
       |         ^^^^^^^^^^^
       = note: `#[deny(clippy::if_then_panic)]` implied by `#[deny(clippy::all)]`
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#if_then_panic

    error: only a `panic!` in `if`-then statement
       --> serde_test/src/assert.rs:73:5
        |
    73  | /     if ser.remaining() > 0 {
    74  | |         panic!("{} remaining tokens", ser.remaining());
    75  | |     }
        | |_____^ help: try: `assert!(!ser.remaining() > 0, "{} remaining tokens", ser.remaining());`
        |
    note: the lint level is defined here
       --> serde_test/src/lib.rs:149:44
        |
    149 | #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
        |                                            ^^^^^^
        = note: `#[deny(clippy::if_then_panic)]` implied by `#[deny(clippy::all)]`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#if_then_panic

    error: only a `panic!` in `if`-then statement
       --> serde_test/src/assert.rs:126:5
        |
    126 | /     if ser.remaining() > 0 {
    127 | |         panic!("{} remaining tokens", ser.remaining());
    128 | |     }
        | |_____^ help: try: `assert!(!ser.remaining() > 0, "{} remaining tokens", ser.remaining());`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#if_then_panic

    error: only a `panic!` in `if`-then statement
       --> serde_test/src/assert.rs:166:5
        |
    166 | /     if de.remaining() > 0 {
    167 | |         panic!("{} remaining tokens", de.remaining());
    168 | |     }
        | |_____^ help: try: `assert!(!de.remaining() > 0, "{} remaining tokens", de.remaining());`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#if_then_panic

    error: only a `panic!` in `if`-then statement
       --> serde_test/src/assert.rs:180:5
        |
    180 | /     if de.remaining() > 0 {
    181 | |         panic!("{} remaining tokens", de.remaining());
    182 | |     }
        | |_____^ help: try: `assert!(!de.remaining() > 0, "{} remaining tokens", de.remaining());`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#if_then_panic

    error: only a `panic!` in `if`-then statement
       --> serde_test/src/assert.rs:220:5
        |
    220 | /     if de.remaining() > 0 {
    221 | |         panic!("{} remaining tokens", de.remaining());
    222 | |     }
        | |_____^ help: try: `assert!(!de.remaining() > 0, "{} remaining tokens", de.remaining());`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#if_then_panic

    error: only a `panic!` in `if`-then statement
        --> test_suite/tests/test_de.rs:1349:9
         |
    1349 | /         if de.remaining() > 0 {
    1350 | |             panic!("{} remaining tokens", de.remaining());
    1351 | |         }
         | |_________^ help: try: `assert!(!de.remaining() > 0, "{} remaining tokens", de.remaining());`
         |
         = note: `-D clippy::if-then-panic` implied by `-D clippy::all`
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#if_then_panic
2021-09-30 00:31:49 -04:00
David Tolnay 819db93a3d Format with rustfmt 2021-09-29 2021-09-30 00:31:49 -04:00
David Tolnay a6690ea2fe Update ui test suite to nightly-2021-09-14 2021-09-14 19:13:54 -07:00
David Tolnay 65e1a50749 Release 1.0.130 2021-08-28 11:31:38 -07:00
David Tolnay 87d41b59fd Merge pull request #2081 from dtolnay/accessunsized
Enable unsized Map/SeqAccess types to use the impl for &mut
2021-08-28 11:11:57 -07:00
David Tolnay 3f120fb355 Enable unsized Map/SeqAccess types to use the impl for &mut 2021-08-28 10:59:51 -07:00
David Tolnay 2b92c80cc1 Release 1.0.129 2021-08-23 15:01:24 -07:00
David Tolnay c1c0ede452 Merge pull request #2080 from dtolnay/packeddrop
Support packed remote struct without destructuring
2021-08-23 15:00:50 -07:00
David Tolnay 4a66c5f33d Support packed remote struct without destructuring 2021-08-23 14:38:33 -07:00
David Tolnay 714c8a5586 Add test of packed struct that cannot be destructured
Currently fails:

    error[E0509]: cannot move out of type `RemotePackedNonCopyDef`, which implements the `Drop` trait
       --> test_suite/tests/test_gen.rs:876:10
        |
    876 | #[derive(Deserialize)]
        |          ^^^^^^^^^^^
        |          |
        |          cannot move out of here
        |          data moved here
        |          move occurs because `__v1` has type `std::string::String`, which does not implement the `Copy` trait
        |
        = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)
2021-08-23 14:38:33 -07:00
David Tolnay dc0c0dcba1 Merge pull request #2079 from dtolnay/packedremote
Fix unaligned reference warnings on packed remote def
2021-08-23 14:38:21 -07:00
David Tolnay 54102ee7d0 Avoid generating ref patterns for fields of packed remote struct 2021-08-23 10:18:28 -07:00
David Tolnay 14accf7518 Add test of remote with a packed struct
Currently fails to build:

    error: reference to packed field is unaligned
       --> test_suite/tests/test_gen.rs:858:10
        |
    858 | #[derive(Serialize, Deserialize)]
        |          ^^^^^^^^^
        |
    note: the lint level is defined here
       --> test_suite/tests/test_gen.rs:5:9
        |
    5   | #![deny(warnings)]
        |         ^^^^^^^^
        = note: `#[deny(unaligned_references)]` implied by `#[deny(warnings)]`
        = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
        = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
        = note: this error originates in the derive macro `Serialize` (in Nightly builds, run with -Z macro-backtrace for more info)

    error: reference to packed field is unaligned
       --> test_suite/tests/test_gen.rs:858:21
        |
    858 | #[derive(Serialize, Deserialize)]
        |                     ^^^^^^^^^^^
        |
        = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
        = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
        = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)
2021-08-23 10:18:05 -07:00
David Tolnay 55fdbea20b Merge pull request #2077 from dtolnay/tryfold
Use try_fold in default implementation of collect_seq, collect_map
2021-08-21 14:08:20 -07:00
David Tolnay 75d8902371 Use try_fold in default implementation of collect_seq, collect_map 2021-08-21 14:00:51 -07:00
David Tolnay 9451ea8df1 Format PR 1992 with rustfmt 2021-08-21 12:49:58 -07:00
David Tolnay c1ce03b3dd Merge pull request 1992 from Mingun/unnecessary-deserialize-with 2021-08-21 12:49:39 -07:00
David Tolnay a587eb8953 Release 1.0.128 2021-08-21 10:39:32 -07:00
Oli Scherer 990f7eb6c1 Merge pull request #2076 from Manishearth/emscripten-i128
Enable 128-bit integers on emscripten post Rust 1.40
2021-08-21 19:19:30 +02:00
Manish Goregaokar 082e18f9a1 Rust supports i128/u128 on emscripten post Rust 1.40 2021-08-20 21:57:06 -07:00
David Tolnay f309485787 Ignore buggy collapsible_match clippy lint
https://github.com/rust-lang/rust-clippy/issues/7575
2021-08-16 19:32:10 -07:00
David Tolnay e2f85681fe Release 1.0.127 2021-07-30 20:59:13 -07:00
David Tolnay 8b840c3030 Resolve semicolon_in_expressions_from_macros warning in serde_test
warning: trailing semicolon in macro used in expression position
       --> serde_test/src/ser.rs:44:10
        |
    44  |         );
        |          ^
    ...
    152 |             Some(&Token::BorrowedStr(_)) => assert_next_token!(self, BorrowedStr(v)),
        |                                             ---------------------------------------- in this macro invocation
        |
        = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default
        = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
        = note: this warning originates in the macro `assert_next_token` (in Nightly builds, run with -Z macro-backtrace for more info)

    warning: trailing semicolon in macro used in expression position
       --> serde_test/src/ser.rs:36:76
        |
    36  |         assert_next_token!($ser, stringify!($actual), Token::$actual, true);
        |                                                                            ^
    ...
    386 |             Token::TupleVariantEnd => assert_next_token!(self.ser, TupleVariantEnd),
        |                                       --------------------------------------------- in this macro invocation
        |
        = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
        = note: this warning originates in the macro `assert_next_token` (in Nightly builds, run with -Z macro-backtrace for more info)
2021-07-30 20:58:07 -07:00
David Tolnay 9c39115f82 Ignore buggy nonstandard_macro_braces clippy lint
Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7422

    error: use of irregular braces for `format_args!` macro
       --> test_suite/tests/test_gen.rs:528:25
        |
    528 |     #[derive(Serialize, Deserialize)]
        |                         ^^^^^^^^^^^
        |
        = note: `-D clippy::nonstandard-macro-braces` implied by `-D clippy::all`
    help: consider writing `Deserialize`
       --> test_suite/tests/test_gen.rs:528:25
        |
    528 |     #[derive(Serialize, Deserialize)]
        |                         ^^^^^^^^^^^
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces
        = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)

    error: use of irregular braces for `format_args!` macro
        --> test_suite/tests/test_annotations.rs:1791:43
         |
    1791 |     #[derive(Debug, PartialEq, Serialize, Deserialize)]
         |                                           ^^^^^^^^^^^
         |
         = note: `-D clippy::nonstandard-macro-braces` implied by `-D clippy::all`
    help: consider writing `Deserialize`
        --> test_suite/tests/test_annotations.rs:1791:43
         |
    1791 |     #[derive(Debug, PartialEq, Serialize, Deserialize)]
         |                                           ^^^^^^^^^^^
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces
         = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)
2021-07-02 20:58:04 -07:00
David Tolnay 89342af71e Merge pull request #2047 from jsoref/spelling
spelling: implicitly
2021-06-24 22:25:58 -07:00
Josh Soref 3c5e2d11f6 spelling: implicitly
Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
2021-06-25 00:43:23 -04:00
David Tolnay 3805c037a8 Merge pull request #2040 from dtolnay/test
Fix outdated test instructions in CONTRIBUTING.md
2021-06-12 13:43:30 -07:00
David Tolnay 7045fee260 Fix outdated test instructions in CONTRIBUTING.md 2021-06-12 13:38:40 -07:00
David Tolnay 9d81532e41 Merge pull request #2039 from dtolnay/test
Update documented test command for the serde directory
2021-06-12 13:38:34 -07:00
David Tolnay 5e47432ef0 Update documented test command for the serde directory 2021-06-12 13:34:45 -07:00
Mingun e0fc46783d Add test with generic deserialize_with function 2021-06-12 18:47:08 +05:00
Mingun ca772a14f9 Get rid of useless DeserializeWith wrapper 2021-06-12 18:38:03 +05:00
David Tolnay 7b840897a9 Resolve needless_borrow clippy lints
error: this expression borrows a reference (`&syn::Type`) that is immediately dereferenced by the compiler
       --> serde_derive/src/internals/check.rs:399:37
        |
    399 |     if let Type::Path(ty) = ungroup(&field.ty) {
        |                                     ^^^^^^^^^ help: change this to: `field.ty`
        |
    note: the lint level is defined here
       --> serde_derive/src/lib.rs:18:9
        |
    18  | #![deny(clippy::all, clippy::pedantic)]
        |         ^^^^^^^^^^^
        = note: `#[deny(clippy::needless_borrow)]` implied by `#[deny(clippy::all)]`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow

    error: this expression borrows a reference (`&str`) that is immediately dereferenced by the compiler
       --> serde_derive/src/de.rs:478:52
        |
    478 |         &type_path, params, fields, false, cattrs, &expecting,
        |                                                    ^^^^^^^^^^ help: change this to: `expecting`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow

    error: this expression borrows a reference (`&str`) that is immediately dereferenced by the compiler
       --> serde_derive/src/de.rs:564:76
        |
    564 |     let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, &expecting));
        |                                                                            ^^^^^^^^^^ help: change this to: `expecting`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow

    error: this expression borrows a reference (`&str`) that is immediately dereferenced by the compiler
       --> serde_derive/src/de.rs:925:51
        |
    925 |         &type_path, params, fields, true, cattrs, &expecting,
        |                                                   ^^^^^^^^^^ help: change this to: `expecting`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow

    error: this expression borrows a reference (`&str`) that is immediately dereferenced by the compiler
        --> serde_derive/src/de.rs:1066:76
         |
    1066 |     let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, &expecting));
         |                                                                            ^^^^^^^^^^ help: change this to: `expecting`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow

    error: this expression borrows a reference (`&proc_macro2::TokenStream`) that is immediately dereferenced by the compiler
        --> serde_derive/src/de.rs:2288:80
         |
    2288 |         let fallthrough_borrowed_arm = fallthrough_borrowed.as_ref().unwrap_or(&fallthrough_arm);
         |                                                                                ^^^^^^^^^^^^^^^^ help: change this to: `fallthrough_arm`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow

    error: this expression borrows a reference (`&syn::Member`) that is immediately dereferenced by the compiler
        --> serde_derive/src/ser.rs:1102:43
         |
    1102 |                 get_member(params, field, &member)
         |                                           ^^^^^^^ help: change this to: `member`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
2021-06-04 20:58:23 -07:00
David Tolnay 967795414b Resolve semicolon_if_nothing_returned clippy lints
error: consider adding a `;` to the last statement for consistent formatting
       --> serde_derive/src/internals/attr.rs:559:25
        |
    559 |                         serde_path.set(&m.path, path)
        |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add a `;` here: `serde_path.set(&m.path, path);`
        |
    note: the lint level is defined here
       --> serde_derive/src/lib.rs:18:22
        |
    18  | #![deny(clippy::all, clippy::pedantic)]
        |                      ^^^^^^^^^^^^^^^^
        = note: `#[deny(clippy::semicolon_if_nothing_returned)]` implied by `#[deny(clippy::pedantic)]`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned

    error: consider adding a `;` to the last statement for consistent formatting
        --> serde_derive/src/internals/attr.rs:1612:9
         |
    1612 |         cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value()))
         |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add a `;` here: `cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value()));`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned

    error: consider adding a `;` to the last statement for consistent formatting
        --> serde_derive/src/internals/attr.rs:1623:9
         |
    1623 |         cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value()))
         |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add a `;` here: `cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value()));`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned

    error: consider adding a `;` to the last statement for consistent formatting
        --> serde_derive/src/internals/attr.rs:1649:9
         |
    1649 | /         cx.error_spanned_by(
    1650 | |             lit,
    1651 | |             format!("failed to parse type: {} = {:?}", attr_name, string.value()),
    1652 | |         )
         | |_________^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
    help: add a `;` here
         |
    1649 |         cx.error_spanned_by(
    1650 |             lit,
    1651 |             format!("failed to parse type: {} = {:?}", attr_name, string.value()),
    1652 |         );
         |

    error: consider adding a `;` to the last statement for consistent formatting
       --> serde_derive/src/internals/check.rs:260:9
        |
    260 | /         cx.error_spanned_by(
    261 | |             cont.original,
    262 | |             format!("variant field name `{}` conflicts with internal tag", tag),
    263 | |         )
        | |_________^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
    help: add a `;` here
        |
    260 |         cx.error_spanned_by(
    261 |             cont.original,
    262 |             format!("variant field name `{}` conflicts with internal tag", tag),
    263 |         );
        |

    error: consider adding a `;` to the last statement for consistent formatting
        --> serde_derive/src/de.rs:2090:9
         |
    2090 |         flat_fields.extend(aliases.iter().map(|alias| (alias, ident)))
         |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add a `;` here: `flat_fields.extend(aliases.iter().map(|alias| (alias, ident)));`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
2021-06-04 20:55:22 -07:00
David Tolnay 985725f820 Resolve while_let_on_iterator clippy lint
error: this loop could be written as a `for` loop
        --> serde/src/private/de.rs:2835:9
         |
    2835 |         while let Some(item) = self.iter.next() {
         |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for item in &mut self.iter`
         |
    note: the lint level is defined here
        --> serde/src/lib.rs:97:44
         |
    97   | #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
         |                                            ^^^^^^
         = note: `#[deny(clippy::while_let_on_iterator)]` implied by `#[deny(clippy::all)]`
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#while_let_on_iterator

    error: this loop could be written as a `for` loop
        --> serde/src/private/de.rs:2937:9
         |
    2937 |         while let Some(item) = self.iter.next() {
         |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for item in &mut self.iter`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#while_let_on_iterator
2021-05-22 20:29:34 -07:00
David Tolnay 0c303d85d7 Merge pull request #2027 from striezel-stash/fix-typos
fix some typos
2021-05-15 10:14:13 -07:00
Dirk Stolle f68e9e901e fix some typos 2021-05-15 16:18:05 +02:00
David Tolnay 1094e2d334 Update ui test suite to nightly-2021-05-14 2021-05-13 19:16:07 -07:00
David Tolnay d9c338ec4a Release 1.0.126 2021-05-12 10:18:26 -07:00
David Tolnay 699bf3a75d Merge pull request #2026 from hyd-dev/warning
Allow only `unused_extern_crates` instead of the whole `rust_2018_idioms` lint group in `serde_derive`-generated code
2021-05-12 10:16:47 -07:00
hyd-dev dd29825217 Allow only unused_extern_crates instead of the whole rust_2018_idioms lint group in serde_derive-generated code 2021-05-12 18:29:45 +08:00
David Tolnay 6366f17da7 Ignore clone_instead_of_copied pedantic clippy lint
Iterator::copied was introduced in Rust 1.35, whereas serde_test
currently supports a minimum compiler version of 1.13.

    error: used `cloned` where `copied` could be used instead
       --> serde_test/src/de.rs:49:29
        |
    49  |         self.tokens.first().cloned()
        |                             ^^^^^^ help: try: `copied`
        |
    note: the lint level is defined here
       --> serde_test/src/lib.rs:149:52
        |
    149 | #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
        |                                                    ^^^^^^^^^^^^^^^
        = note: `#[deny(clippy::cloned_instead_of_copied)]` implied by `#[deny(clippy::pedantic)]`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#cloned_instead_of_copied
2021-04-24 19:26:19 -07:00
David Tolnay 1120e5af4a Remove suppression of removed clippy lint
warning: lint `clippy::filter_map` has been removed: this lint has been replaced by `manual_filter_map`, a more specific lint
      --> serde_derive/src/lib.rs:42:5
       |
    42 |     clippy::filter_map,
       |     ^^^^^^^^^^^^^^^^^^
       |
       = note: `#[warn(renamed_and_removed_lints)]` on by default

    warning: lint `clippy::filter_map` has been removed: this lint has been replaced by `manual_filter_map`, a more specific lint
      --> serde_derive/src/lib.rs:42:5
       |
    42 |     clippy::filter_map,
       |     ^^^^^^^^^^^^^^^^^^
2021-04-24 19:23:56 -07:00
David Tolnay 1093f7e232 Resolve flat_map_option pedantic clippy lint
error: used `flat_map` where `filter_map` could be used instead
      --> serde_derive/src/bound.rs:52:10
       |
    52 |         .flat_map(|field| from_field(&field.attrs))
       |          ^^^^^^^^ help: try: `filter_map`
       |
    note: the lint level is defined here
      --> serde_derive/src/lib.rs:18:22
       |
    18 | #![deny(clippy::all, clippy::pedantic)]
       |                      ^^^^^^^^^^^^^^^^
       = note: `#[deny(clippy::flat_map_option)]` implied by `#[deny(clippy::pedantic)]`
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#flat_map_option

    error: used `flat_map` where `filter_map` could be used instead
      --> serde_derive/src/bound.rs:74:10
       |
    74 |         .flat_map(|variant| from_variant(&variant.attrs))
       |          ^^^^^^^^ help: try: `filter_map`
       |
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#flat_map_option
2021-04-24 19:23:21 -07:00
David Tolnay 2ea132b8c4 Merge pull request #2018 from dtolnay/nonascii
Remove non_ascii_idents feature gate from test suite
2021-04-19 20:24:51 -07:00
David Tolnay 2ebc771b88 Remove non_ascii_idents feature gate from test suite
error: the feature `non_ascii_idents` has been stable since 1.53.0 and no longer requires an attribute to enable
     --> test_suite/tests/test_gen.rs:6:43
      |
    6 | #![cfg_attr(feature = "unstable", feature(non_ascii_idents))]
      |                                           ^^^^^^^^^^^^^^^^
      |
    note: the lint level is defined here
     --> test_suite/tests/test_gen.rs:5:9
      |
    5 | #![deny(warnings)]
      |         ^^^^^^^^
      = note: `#[deny(stable_features)]` implied by `#[deny(warnings)]`
2021-04-19 19:55:12 -07:00
David Tolnay c17c4eef18 Unify stable and beta CI workflow 2021-04-19 19:54:56 -07:00
David Tolnay 7aa4950504 Release serde_derive_internals 0.26.0 2021-04-09 14:23:13 -07:00
David Tolnay 47015a2727 Merge pull request #2015 from dtolnay/symlink
Build using relative path in repo if Windows lost the symlink
2021-04-09 14:20:55 -07:00
David Tolnay dc4c31eb50 Build using relative path in repo if Windows lost symlink 2021-04-09 14:16:17 -07:00
David Tolnay b53ebef438 Resolve safe_packed_borrows lint renamed to unaligned_references
warning: lint `safe_packed_borrows` has been renamed to `unaligned_references`
        --> test_suite/tests/test_macros.rs:1926:8
         |
    1926 | #[deny(safe_packed_borrows)]
         |        ^^^^^^^^^^^^^^^^^^^ help: use the new name: `unaligned_references`
         |
         = note: `#[warn(renamed_and_removed_lints)]` on by default
2021-04-08 20:08:42 -07:00
David Tolnay 6c3bf7a2fc Ignore poor suggestion from branches_sharing_code lint
https://github.com/rust-lang/rust-clippy/issues/7054

    error: all if blocks contain the same code at the end
        --> serde_derive/src/de.rs:2160:5
         |
    2160 | /         &fallthrough_arm_tokens
    2161 | |     };
         | |_____^
         |
    note: the lint level is defined here
        --> serde_derive/src/lib.rs:18:9
         |
    18   | #![deny(clippy::all, clippy::pedantic)]
         |         ^^^^^^^^^^^
         = note: `#[deny(clippy::branches_sharing_code)]` implied by `#[deny(clippy::all)]`
         = note: The end suggestion probably needs some adjustments to use the expression result correctly
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#branches_sharing_code
    help: consider moving the end statements out like this
         |
    2160 |     }
    2161 |     &fallthrough_arm_tokens;
         |
2021-04-08 20:08:42 -07:00
David Tolnay ce0844b9ec Suppress match_wildcard_for_single_variants clippy false positive
https://github.com/rust-lang/rust-clippy/issues/6984

    error: wildcard matches only a single variant and will also match any future added variants
        --> serde_derive/src/internals/attr.rs:1918:9
         |
    1918 |         _ => {}
         |         ^ help: try this: `syn::Type::__TestExhaustive(_)`
         |
    note: the lint level is defined here
        --> serde_derive/src/lib.rs:18:22
         |
    18   | #![deny(clippy::all, clippy::pedantic)]
         |                      ^^^^^^^^^^^^^^^^
         = note: `#[deny(clippy::match_wildcard_for_single_variants)]` implied by `#[deny(clippy::pedantic)]`
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#match_wildcard_for_single_variants

    error: wildcard matches only a single variant and will also match any future added variants
       --> serde_derive/src/internals/receiver.rs:153:13
        |
    153 |             _ => {}
        |             ^ help: try this: `Type::__TestExhaustive(_)`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#match_wildcard_for_single_variants

    error: wildcard matches only a single variant and will also match any future added variants
       --> serde_derive/src/bound.rs:190:17
        |
    190 |                 _ => {}
        |                 ^ help: try this: `syn::Type::__TestExhaustive(_)`
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#match_wildcard_for_single_variants
2021-03-26 23:30:15 -04:00
David Tolnay e9270e59f0 Release 1.0.125 2021-03-22 16:15:57 -07:00
David Tolnay 72060b779a Extend test_format_u8 to include u8::MAX
This is equivalent to looping 0..=u8::MAX, except that `..=` syntax is
not supported on old rustc and `...` syntax is not supported on new
rustc, so loop it is.
2021-03-22 16:09:33 -07:00
David Tolnay 1bb23ad9d1 Remove format_u8 when not used by Ipv4Addr impl 2021-03-22 16:00:58 -07:00
David Tolnay 9be4c9654a Merge pull request 2001 from saethlin/optimize-ipaddr 2021-03-22 16:00:11 -07:00
Ben Kimock 4114e90bac Fix off-by-one mistake, explain the offset 2021-03-22 18:39:24 -04:00
Ben Kimock 8bb07b0743 skip UTF8 checking and initialize with b'.' 2021-03-22 18:15:50 -04:00
Ben Kimock ba8c1d63c8 use the algorithm from itoa 2021-03-16 17:33:42 -04:00
Ben Kimock 857a805993 Faster Ipv4 serialization prototype 2021-03-16 10:41:13 -04:00
David Tolnay 5a8dcac2ed Release 1.0.124 2021-03-05 19:55:40 -08:00
David Tolnay 697b082e90 Touch up PR 1997 2021-03-05 19:48:40 -08:00
David Tolnay d91075c8d5 Merge pull request #1997 from cyang1/systemtime-panics
Prevent various panics when deserializing malformed SystemTime
2021-03-05 18:35:48 -08:00
Cary Yang 4118cec731 Prevent various panics when deserializing malformed SystemTime 2021-03-05 17:52:51 -08:00
David Tolnay c261015325 Ignore incorrect suggestion from manual_map lint
https://github.com/rust-lang/rust-clippy/issues/6797

    error[E0382]: use of partially moved value: `self`
       --> serde_derive/src/internals/attr.rs:71:24
        |
    71  |         self.value.map(|value| (self.tokens, value))
        |                    ----^^^^^^^----------------------
        |                    |   |        |
        |                    |   |        use occurs due to use in closure
        |                    |   value used here after partial move
        |                    `self.value` partially moved due to this method call
        |
    note: this function takes ownership of the receiver `self`, which moves `self.value`
       --> /home/david/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:485:38
        |
    485 |     pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> {
        |                                      ^^^^
        = note: partial move occurs because `self.value` has type `std::option::Option<T>`, which does not implement the `Copy` trait
2021-02-25 20:53:45 -08:00
David Tolnay 6b5e5a83d0 Ignore let_underscore_drop pedantic clippy lint 2021-02-18 19:31:39 -08:00
David Tolnay bc6b2b1dee Make json5 description capitalization consistent with other links 2021-02-10 23:13:12 -08:00
David Tolnay beb21cb640 Ignore new missing_panics_doc pedantic clippy lint 2021-02-03 20:07:44 -08:00
David Tolnay 7cfebbcd72 Merge pull request #1974 from Mingun/new-internally-tagged-tests
New internally tagged tests
2021-02-02 15:23:10 -08:00
Mingun b60c03ec3f Extend test_internally_tagged_newtype_variant_containing_unit_struct to cover structs and seqs 2021-02-02 09:00:04 +05:00
Mingun 3257851192 Extend test_internally_tagged_struct_variant_containing_unit_variant to cover maps and seqs 2021-02-02 08:59:59 +05:00
David Tolnay 9a84622c56 Merge pull request #1971 from arthurprs/untagged-enum-fix-pr
Allow floats to be deserialized from ints in untagged unions (part 2)
2021-01-26 14:41:56 -08:00
Arthur Silva de8ac1c0be Allow floats to be deserialized from ints in untagged unions 2021-01-26 17:47:20 +01:00
151 changed files with 4965 additions and 2122 deletions
+17 -19
View File
@@ -5,6 +5,9 @@ on:
pull_request: pull_request:
schedule: [cron: "40 1 * * *"] schedule: [cron: "40 1 * * *"]
env:
RUSTFLAGS: -Dwarnings
jobs: jobs:
test: test:
name: Test suite name: Test suite
@@ -23,25 +26,22 @@ jobs:
- run: cd test_suite && cargo test --features unstable -- --skip ui --exact - run: cd test_suite && cargo test --features unstable -- --skip ui --exact
stable: stable:
name: Rust stable name: Rust ${{matrix.rust}}
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
rust: [stable, beta]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: dtolnay/rust-toolchain@stable - uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{matrix.rust}}
- run: cd serde && cargo build --features rc - run: cd serde && cargo build --features rc
- run: cd serde && cargo build --no-default-features - run: cd serde && cargo build --no-default-features
- run: cd serde_test && cargo build - run: cd serde_test && cargo build
- run: cd serde_test && cargo test --features serde/derive,serde/rc - run: cd serde_test && cargo test --features serde/derive,serde/rc
beta:
name: Rust beta
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: dtolnay/rust-toolchain@beta
- run: cd serde && cargo build --features rc
- run: cd test_suite && cargo test
nightly: nightly:
name: Rust nightly ${{matrix.os == 'windows' && '(windows)' || ''}} name: Rust nightly ${{matrix.os == 'windows' && '(windows)' || ''}}
runs-on: ${{matrix.os}}-latest runs-on: ${{matrix.os}}-latest
@@ -156,11 +156,9 @@ jobs:
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: dtolnay/rust-toolchain@clippy - uses: dtolnay/rust-toolchain@clippy
# The need for -Aredundant_field_names here is a Clippy bug. - run: cd serde && cargo clippy --features rc,unstable -- -Dclippy::all -Dclippy::pedantic
# https://github.com/rust-lang/rust-clippy/issues/5356 - run: cd serde_derive && cargo clippy -- -Dclippy::all -Dclippy::pedantic
- run: cd serde && cargo clippy --features rc,unstable -- -D clippy::all -A clippy::redundant_field_names - run: cd serde_derive_internals && cargo clippy -- -Dclippy::all -Dclippy::pedantic
- run: cd serde_derive && cargo clippy -- -D clippy::all - run: cd serde_test && cargo clippy -- -Dclippy::all -Dclippy::pedantic
- run: cd serde_derive_internals && cargo clippy -- -D clippy::all - run: cd test_suite && cargo clippy --tests --features unstable -- -Dclippy::all -Dclippy::pedantic
- run: cd serde_test && cargo clippy -- -D clippy::all -A clippy::redundant_field_names - run: cd test_suite/no_std && cargo clippy -- -Dclippy::all -Dclippy::pedantic
- run: cd test_suite && cargo clippy --tests --features unstable -- -D clippy::all -A clippy::redundant_field_names
- run: cd test_suite/no_std && cargo clippy -- -D clippy::all -A clippy::redundant_field_names
+4 -10
View File
@@ -31,25 +31,19 @@ tests for you.
```sh ```sh
# Test all the example code in Serde documentation # Test all the example code in Serde documentation
cargo test cargo test --features derive
```
##### In the [`test_suite/deps`] directory
```sh
# This is a prerequisite for running the full test suite
cargo clean && cargo update && cargo build
``` ```
##### In the [`test_suite`] directory ##### In the [`test_suite`] directory
```sh ```sh
# Run the full test suite, including tests of unstable functionality # Run the full test suite, including tests of unstable functionality
cargo test --features unstable cargo +nightly test --features unstable
``` ```
Note that this test suite currently only supports running on a nightly compiler.
[`serde`]: https://github.com/serde-rs/serde/tree/master/serde [`serde`]: https://github.com/serde-rs/serde/tree/master/serde
[`test_suite/deps`]: https://github.com/serde-rs/serde/tree/master/test_suite/deps
[`test_suite`]: https://github.com/serde-rs/serde/tree/master/test_suite [`test_suite`]: https://github.com/serde-rs/serde/tree/master/test_suite
## Conduct ## Conduct
+3 -2
View File
@@ -1,7 +1,8 @@
[package] [package]
name = "serde" name = "serde"
version = "1.0.123" # remember to update html_root_url and serde_derive dependency version = "1.0.134" # 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>"]
rust-version = "1.15"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
description = "A generic serialization/deserialization framework" description = "A generic serialization/deserialization framework"
homepage = "https://serde.rs" homepage = "https://serde.rs"
@@ -14,7 +15,7 @@ include = ["build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APAC
build = "build.rs" build = "build.rs"
[dependencies] [dependencies]
serde_derive = { version = "=1.0.123", optional = true, path = "../serde_derive" } serde_derive = { version = "=1.0.134", 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" }
+51 -43
View File
@@ -17,88 +17,96 @@ fn main() {
// std::collections::Bound was stabilized in Rust 1.17 // std::collections::Bound was stabilized in Rust 1.17
// but it was moved to core::ops later in Rust 1.26: // but it was moved to core::ops later in Rust 1.26:
// https://doc.rust-lang.org/core/ops/enum.Bound.html // https://doc.rust-lang.org/core/ops/enum.Bound.html
if minor >= 26 { if minor < 26 {
println!("cargo:rustc-cfg=ops_bound"); println!("cargo:rustc-cfg=no_ops_bound");
} else if minor >= 17 && cfg!(feature = "std") { if minor < 17 {
println!("cargo:rustc-cfg=collections_bound"); println!("cargo:rustc-cfg=no_collections_bound");
}
} }
// core::cmp::Reverse stabilized in Rust 1.19: // core::cmp::Reverse stabilized in Rust 1.19:
// https://doc.rust-lang.org/stable/core/cmp/struct.Reverse.html // https://doc.rust-lang.org/stable/core/cmp/struct.Reverse.html
if minor >= 19 { if minor < 19 {
println!("cargo:rustc-cfg=core_reverse"); println!("cargo:rustc-cfg=no_core_reverse");
} }
// CString::into_boxed_c_str and PathBuf::into_boxed_path stabilized in Rust 1.20: // CString::into_boxed_c_str and PathBuf::into_boxed_path stabilized in Rust 1.20:
// https://doc.rust-lang.org/std/ffi/struct.CString.html#method.into_boxed_c_str // https://doc.rust-lang.org/std/ffi/struct.CString.html#method.into_boxed_c_str
// https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.into_boxed_path // https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.into_boxed_path
if minor >= 20 { if minor < 20 {
println!("cargo:rustc-cfg=de_boxed_c_str"); println!("cargo:rustc-cfg=no_de_boxed_c_str");
println!("cargo:rustc-cfg=de_boxed_path"); println!("cargo:rustc-cfg=no_de_boxed_path");
} }
// From<Box<T>> for Rc<T> / Arc<T> stabilized in Rust 1.21: // From<Box<T>> for Rc<T> / Arc<T> stabilized in Rust 1.21:
// https://doc.rust-lang.org/std/rc/struct.Rc.html#impl-From<Box<T>> // https://doc.rust-lang.org/std/rc/struct.Rc.html#impl-From<Box<T>>
// https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-From<Box<T>> // https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-From<Box<T>>
if minor >= 21 { if minor < 21 {
println!("cargo:rustc-cfg=de_rc_dst"); println!("cargo:rustc-cfg=no_de_rc_dst");
} }
// Duration available in core since Rust 1.25: // Duration available in core since Rust 1.25:
// https://blog.rust-lang.org/2018/03/29/Rust-1.25.html#library-stabilizations // https://blog.rust-lang.org/2018/03/29/Rust-1.25.html#library-stabilizations
if minor >= 25 { if minor < 25 {
println!("cargo:rustc-cfg=core_duration"); println!("cargo:rustc-cfg=no_core_duration");
} }
// 128-bit integers stabilized in Rust 1.26: // 128-bit integers stabilized in Rust 1.26:
// https://blog.rust-lang.org/2018/05/10/Rust-1.26.html // https://blog.rust-lang.org/2018/05/10/Rust-1.26.html
// //
// Disabled on Emscripten targets as Emscripten doesn't // Disabled on Emscripten targets before Rust 1.40 since
// currently support integers larger than 64 bits. // Emscripten did not support 128-bit integers until Rust 1.40
if minor >= 26 && !emscripten { // (https://github.com/rust-lang/rust/pull/65251)
println!("cargo:rustc-cfg=integer128"); if minor < 26 || emscripten && minor < 40 {
println!("cargo:rustc-cfg=no_integer128");
} }
// Inclusive ranges methods stabilized in Rust 1.27: // Inclusive ranges methods stabilized in Rust 1.27:
// https://github.com/rust-lang/rust/pull/50758 // https://github.com/rust-lang/rust/pull/50758
if minor >= 27 { // Also Iterator::try_for_each:
println!("cargo:rustc-cfg=range_inclusive"); // https://blog.rust-lang.org/2018/06/21/Rust-1.27.html#library-stabilizations
if minor < 27 {
println!("cargo:rustc-cfg=no_range_inclusive");
println!("cargo:rustc-cfg=no_iterator_try_fold");
} }
// Non-zero integers stabilized in Rust 1.28: // Non-zero integers stabilized in Rust 1.28:
// https://blog.rust-lang.org/2018/08/02/Rust-1.28.html#library-stabilizations // https://blog.rust-lang.org/2018/08/02/Rust-1.28.html#library-stabilizations
if minor >= 28 { if minor < 28 {
println!("cargo:rustc-cfg=num_nonzero"); println!("cargo:rustc-cfg=no_num_nonzero");
} }
// Current minimum supported version of serde_derive crate is Rust 1.31. // Current minimum supported version of serde_derive crate is Rust 1.31.
if minor >= 31 { if minor < 31 {
println!("cargo:rustc-cfg=serde_derive"); println!("cargo:rustc-cfg=no_serde_derive");
} }
// TryFrom, Atomic types, and non-zero signed integers stabilized in Rust 1.34: // TryFrom, Atomic types, non-zero signed integers, and SystemTime::checked_add
// stabilized in Rust 1.34:
// https://blog.rust-lang.org/2019/04/11/Rust-1.34.0.html#tryfrom-and-tryinto // https://blog.rust-lang.org/2019/04/11/Rust-1.34.0.html#tryfrom-and-tryinto
// https://blog.rust-lang.org/2019/04/11/Rust-1.34.0.html#library-stabilizations // https://blog.rust-lang.org/2019/04/11/Rust-1.34.0.html#library-stabilizations
if minor >= 34 { if minor < 34 {
println!("cargo:rustc-cfg=core_try_from"); println!("cargo:rustc-cfg=no_core_try_from");
println!("cargo:rustc-cfg=num_nonzero_signed"); println!("cargo:rustc-cfg=no_num_nonzero_signed");
println!("cargo:rustc-cfg=no_systemtime_checked_add");
}
// Whitelist of archs that support std::sync::atomic module. Ideally we // Whitelist of archs that support std::sync::atomic module. Ideally we
// would use #[cfg(target_has_atomic = "...")] but it is not stable yet. // would use #[cfg(target_has_atomic = "...")] but it is not stable yet.
// Instead this is based on rustc's src/librustc_target/spec/*.rs. // Instead this is based on rustc's compiler/rustc_target/src/spec/*.rs.
let has_atomic64 = target.starts_with("x86_64") let has_atomic64 = target.starts_with("x86_64")
|| target.starts_with("i686") || target.starts_with("i686")
|| target.starts_with("aarch64") || target.starts_with("aarch64")
|| target.starts_with("powerpc64") || target.starts_with("powerpc64")
|| target.starts_with("sparc64") || target.starts_with("sparc64")
|| target.starts_with("mips64el"); || target.starts_with("mips64el")
let has_atomic32 = has_atomic64 || emscripten; || target.starts_with("riscv64");
if has_atomic64 { let has_atomic32 = has_atomic64 || emscripten;
println!("cargo:rustc-cfg=std_atomic64"); if minor < 34 || !has_atomic64 {
} println!("cargo:rustc-cfg=no_std_atomic64");
if has_atomic32 { }
println!("cargo:rustc-cfg=std_atomic"); if minor < 34 || !has_atomic32 {
} println!("cargo:rustc-cfg=no_std_atomic");
} }
} }
+245 -164
View File
@@ -4,7 +4,7 @@ use de::{
Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, VariantAccess, Visitor, Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, VariantAccess, Visitor,
}; };
#[cfg(any(core_duration, feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc", not(no_core_duration)))]
use de::MapAccess; use de::MapAccess;
use seed::InPlaceSeed; use seed::InPlaceSeed;
@@ -81,8 +81,34 @@ impl<'de> Deserialize<'de> for bool {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
macro_rules! impl_deserialize_num { macro_rules! impl_deserialize_num {
($ty:ident, $deserialize:ident $($methods:tt)*) => { ($primitive:ident, $nonzero:ident $(cfg($($cfg:tt)*))*, $deserialize:ident $($method:ident!($($val:ident : $visit:ident)*);)*) => {
impl<'de> Deserialize<'de> for $ty { impl_deserialize_num!($primitive, $deserialize $($method!($($val : $visit)*);)*);
#[cfg(all(not(no_num_nonzero), $($($cfg)*)*))]
impl<'de> Deserialize<'de> for num::$nonzero {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct NonZeroVisitor;
impl<'de> Visitor<'de> for NonZeroVisitor {
type Value = num::$nonzero;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(concat!("a nonzero ", stringify!($primitive)))
}
$($($method!(nonzero $primitive $val : $visit);)*)*
}
deserializer.$deserialize(NonZeroVisitor)
}
}
};
($primitive:ident, $deserialize:ident $($method:ident!($($val:ident : $visit:ident)*);)*) => {
impl<'de> Deserialize<'de> for $primitive {
#[inline] #[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
@@ -91,13 +117,13 @@ macro_rules! impl_deserialize_num {
struct PrimitiveVisitor; struct PrimitiveVisitor;
impl<'de> Visitor<'de> for PrimitiveVisitor { impl<'de> Visitor<'de> for PrimitiveVisitor {
type Value = $ty; type Value = $primitive;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(stringify!($ty)) formatter.write_str(stringify!($primitive))
} }
$($methods)* $($($method!($val : $visit);)*)*
} }
deserializer.$deserialize(PrimitiveVisitor) deserializer.$deserialize(PrimitiveVisitor)
@@ -116,85 +142,149 @@ macro_rules! num_self {
Ok(v) Ok(v)
} }
}; };
(nonzero $primitive:ident $ty:ident : $visit:ident) => {
fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
where
E: Error,
{
if let Some(nonzero) = Self::Value::new(v) {
Ok(nonzero)
} else {
Err(Error::invalid_value(Unexpected::Unsigned(0), &self))
}
}
};
} }
macro_rules! num_as_self { macro_rules! num_as_self {
($($ty:ident : $visit:ident)*) => { ($ty:ident : $visit:ident) => {
$( #[inline]
#[inline] fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
fn $visit<E>(self, v: $ty) -> Result<Self::Value, E> where
where E: Error,
E: Error, {
{ Ok(v as Self::Value)
Ok(v as Self::Value) }
};
(nonzero $primitive:ident $ty:ident : $visit:ident) => {
fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
where
E: Error,
{
if let Some(nonzero) = Self::Value::new(v as $primitive) {
Ok(nonzero)
} else {
Err(Error::invalid_value(Unexpected::Unsigned(0), &self))
} }
)* }
}; };
} }
macro_rules! int_to_int { macro_rules! int_to_int {
($($ty:ident : $visit:ident)*) => { ($ty:ident : $visit:ident) => {
$( #[inline]
#[inline] fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
fn $visit<E>(self, v: $ty) -> Result<Self::Value, E> where
where E: Error,
E: Error, {
if Self::Value::min_value() as i64 <= v as i64
&& v as i64 <= Self::Value::max_value() as i64
{ {
if Self::Value::min_value() as i64 <= v as i64 && v as i64 <= Self::Value::max_value() as i64 { Ok(v as Self::Value)
Ok(v as Self::Value) } else {
} else { Err(Error::invalid_value(Unexpected::Signed(v as i64), &self))
Err(Error::invalid_value(Unexpected::Signed(v as i64), &self)) }
}
};
(nonzero $primitive:ident $ty:ident : $visit:ident) => {
fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
where
E: Error,
{
if $primitive::min_value() as i64 <= v as i64
&& v as i64 <= $primitive::max_value() as i64
{
if let Some(nonzero) = Self::Value::new(v as $primitive) {
return Ok(nonzero);
} }
} }
)* Err(Error::invalid_value(Unexpected::Signed(v as i64), &self))
}
}; };
} }
macro_rules! int_to_uint { macro_rules! int_to_uint {
($($ty:ident : $visit:ident)*) => { ($ty:ident : $visit:ident) => {
$( #[inline]
#[inline] fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
fn $visit<E>(self, v: $ty) -> Result<Self::Value, E> where
where E: Error,
E: Error, {
{ if 0 <= v && v as u64 <= Self::Value::max_value() as u64 {
if 0 <= v && v as u64 <= Self::Value::max_value() as u64 { Ok(v as Self::Value)
Ok(v as Self::Value) } else {
} else { Err(Error::invalid_value(Unexpected::Signed(v as i64), &self))
Err(Error::invalid_value(Unexpected::Signed(v as i64), &self)) }
}
};
(nonzero $primitive:ident $ty:ident : $visit:ident) => {
fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
where
E: Error,
{
if 0 < v && v as u64 <= $primitive::max_value() as u64 {
if let Some(nonzero) = Self::Value::new(v as $primitive) {
return Ok(nonzero);
} }
} }
)* Err(Error::invalid_value(Unexpected::Signed(v as i64), &self))
}
}; };
} }
macro_rules! uint_to_self { macro_rules! uint_to_self {
($($ty:ident : $visit:ident)*) => { ($ty:ident : $visit:ident) => {
$( #[inline]
#[inline] fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
fn $visit<E>(self, v: $ty) -> Result<Self::Value, E> where
where E: Error,
E: Error, {
{ if v as u64 <= Self::Value::max_value() as u64 {
if v as u64 <= Self::Value::max_value() as u64 { Ok(v as Self::Value)
Ok(v as Self::Value) } else {
} else { Err(Error::invalid_value(Unexpected::Unsigned(v as u64), &self))
Err(Error::invalid_value(Unexpected::Unsigned(v as u64), &self)) }
}
};
(nonzero $primitive:ident $ty:ident : $visit:ident) => {
fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
where
E: Error,
{
if v as u64 <= $primitive::max_value() as u64 {
if let Some(nonzero) = Self::Value::new(v as $primitive) {
return Ok(nonzero);
} }
} }
)* Err(Error::invalid_value(Unexpected::Unsigned(v as u64), &self))
}
}; };
} }
impl_deserialize_num! { impl_deserialize_num! {
i8, deserialize_i8 i8, NonZeroI8 cfg(not(no_num_nonzero_signed)), deserialize_i8
num_self!(i8:visit_i8); num_self!(i8:visit_i8);
int_to_int!(i16:visit_i16 i32:visit_i32 i64:visit_i64); int_to_int!(i16:visit_i16 i32:visit_i32 i64:visit_i64);
uint_to_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); uint_to_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
} }
impl_deserialize_num! { impl_deserialize_num! {
i16, deserialize_i16 i16, NonZeroI16 cfg(not(no_num_nonzero_signed)), deserialize_i16
num_self!(i16:visit_i16); num_self!(i16:visit_i16);
num_as_self!(i8:visit_i8); num_as_self!(i8:visit_i8);
int_to_int!(i32:visit_i32 i64:visit_i64); int_to_int!(i32:visit_i32 i64:visit_i64);
@@ -202,7 +292,7 @@ impl_deserialize_num! {
} }
impl_deserialize_num! { impl_deserialize_num! {
i32, deserialize_i32 i32, NonZeroI32 cfg(not(no_num_nonzero_signed)), deserialize_i32
num_self!(i32:visit_i32); num_self!(i32:visit_i32);
num_as_self!(i8:visit_i8 i16:visit_i16); num_as_self!(i8:visit_i8 i16:visit_i16);
int_to_int!(i64:visit_i64); int_to_int!(i64:visit_i64);
@@ -210,28 +300,28 @@ impl_deserialize_num! {
} }
impl_deserialize_num! { impl_deserialize_num! {
i64, deserialize_i64 i64, NonZeroI64 cfg(not(no_num_nonzero_signed)), deserialize_i64
num_self!(i64:visit_i64); num_self!(i64:visit_i64);
num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32); num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32);
uint_to_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); uint_to_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
} }
impl_deserialize_num! { impl_deserialize_num! {
isize, deserialize_i64 isize, NonZeroIsize cfg(not(no_num_nonzero_signed)), deserialize_i64
num_as_self!(i8:visit_i8 i16:visit_i16); num_as_self!(i8:visit_i8 i16:visit_i16);
int_to_int!(i32:visit_i32 i64:visit_i64); int_to_int!(i32:visit_i32 i64:visit_i64);
uint_to_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); uint_to_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
} }
impl_deserialize_num! { impl_deserialize_num! {
u8, deserialize_u8 u8, NonZeroU8, deserialize_u8
num_self!(u8:visit_u8); num_self!(u8:visit_u8);
int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
uint_to_self!(u16:visit_u16 u32:visit_u32 u64:visit_u64); uint_to_self!(u16:visit_u16 u32:visit_u32 u64:visit_u64);
} }
impl_deserialize_num! { impl_deserialize_num! {
u16, deserialize_u16 u16, NonZeroU16, deserialize_u16
num_self!(u16:visit_u16); num_self!(u16:visit_u16);
num_as_self!(u8:visit_u8); num_as_self!(u8:visit_u8);
int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
@@ -239,7 +329,7 @@ impl_deserialize_num! {
} }
impl_deserialize_num! { impl_deserialize_num! {
u32, deserialize_u32 u32, NonZeroU32, deserialize_u32
num_self!(u32:visit_u32); num_self!(u32:visit_u32);
num_as_self!(u8:visit_u8 u16:visit_u16); num_as_self!(u8:visit_u8 u16:visit_u16);
int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
@@ -247,14 +337,14 @@ impl_deserialize_num! {
} }
impl_deserialize_num! { impl_deserialize_num! {
u64, deserialize_u64 u64, NonZeroU64, deserialize_u64
num_self!(u64:visit_u64); num_self!(u64:visit_u64);
num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32); num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32);
int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
} }
impl_deserialize_num! { impl_deserialize_num! {
usize, deserialize_u64 usize, NonZeroUsize, deserialize_u64
num_as_self!(u8:visit_u8 u16:visit_u16); num_as_self!(u8:visit_u8 u16:visit_u16);
int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
uint_to_self!(u32:visit_u32 u64:visit_u64); uint_to_self!(u32:visit_u32 u64:visit_u64);
@@ -277,42 +367,62 @@ impl_deserialize_num! {
} }
serde_if_integer128! { serde_if_integer128! {
impl_deserialize_num! { macro_rules! num_128 {
i128, deserialize_i128 ($ty:ident : $visit:ident) => {
num_self!(i128:visit_i128); fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); where
num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); E: Error,
{
#[inline] if v as i128 >= Self::Value::min_value() as i128
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E> && v as u128 <= Self::Value::max_value() as u128
where {
E: Error, Ok(v as Self::Value)
{ } else {
if v <= i128::max_value() as u128 { Err(Error::invalid_value(
Ok(v as i128) Unexpected::Other(stringify!($ty)),
} else { &self,
Err(Error::invalid_value(Unexpected::Other("u128"), &self)) ))
}
} }
} };
(nonzero $primitive:ident $ty:ident : $visit:ident) => {
fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
where
E: Error,
{
if v as i128 >= $primitive::min_value() as i128
&& v as u128 <= $primitive::max_value() as u128
{
if let Some(nonzero) = Self::Value::new(v as $primitive) {
Ok(nonzero)
} else {
Err(Error::invalid_value(Unexpected::Unsigned(0), &self))
}
} else {
Err(Error::invalid_value(
Unexpected::Other(stringify!($ty)),
&self,
))
}
}
};
} }
impl_deserialize_num! { impl_deserialize_num! {
u128, deserialize_u128 i128, NonZeroI128 cfg(not(no_num_nonzero_signed)), deserialize_i128
num_self!(i128:visit_i128);
num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
num_128!(u128:visit_u128);
}
impl_deserialize_num! {
u128, NonZeroU128, deserialize_u128
num_self!(u128:visit_u128); num_self!(u128:visit_u128);
num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
num_128!(i128:visit_i128);
#[inline]
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
where
E: Error,
{
if 0 <= v {
Ok(v as u128)
} else {
Err(Error::invalid_value(Unexpected::Other("i128"), &self))
}
}
} }
} }
@@ -637,10 +747,10 @@ macro_rules! forwarded_impl {
} }
} }
#[cfg(all(feature = "std", de_boxed_c_str))] #[cfg(all(feature = "std", not(no_de_boxed_c_str)))]
forwarded_impl!((), Box<CStr>, CString::into_boxed_c_str); forwarded_impl!((), Box<CStr>, CString::into_boxed_c_str);
#[cfg(core_reverse)] #[cfg(not(no_core_reverse))]
forwarded_impl!((T), Reverse<T>, Reverse); forwarded_impl!((T), Reverse<T>, Reverse);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -1604,7 +1714,7 @@ impl<'de> Deserialize<'de> for PathBuf {
} }
} }
#[cfg(all(feature = "std", de_boxed_path))] #[cfg(all(feature = "std", not(no_de_boxed_path)))]
forwarded_impl!((), Box<Path>, PathBuf::into_boxed_path); forwarded_impl!((), Box<Path>, PathBuf::into_boxed_path);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -1685,11 +1795,7 @@ forwarded_impl!((T), Box<[T]>, Vec::into_boxed_slice);
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
forwarded_impl!((), Box<str>, String::into_boxed_str); forwarded_impl!((), Box<str>, String::into_boxed_str);
#[cfg(all( #[cfg(all(no_de_rc_dst, feature = "rc", any(feature = "std", feature = "alloc")))]
not(de_rc_dst),
feature = "rc",
any(feature = "std", feature = "alloc")
))]
forwarded_impl! { forwarded_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde. /// This impl requires the [`"rc"`] Cargo feature of Serde.
/// ///
@@ -1701,11 +1807,7 @@ forwarded_impl! {
(T), Arc<T>, Arc::new (T), Arc<T>, Arc::new
} }
#[cfg(all( #[cfg(all(no_de_rc_dst, feature = "rc", any(feature = "std", feature = "alloc")))]
not(de_rc_dst),
feature = "rc",
any(feature = "std", feature = "alloc")
))]
forwarded_impl! { forwarded_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde. /// This impl requires the [`"rc"`] Cargo feature of Serde.
/// ///
@@ -1772,7 +1874,11 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(all(de_rc_dst, feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg(all(
not(no_de_rc_dst),
feature = "rc",
any(feature = "std", feature = "alloc")
))]
macro_rules! box_forwarded_impl { macro_rules! box_forwarded_impl {
( (
$(#[doc = $doc:tt])* $(#[doc = $doc:tt])*
@@ -1793,7 +1899,11 @@ macro_rules! box_forwarded_impl {
}; };
} }
#[cfg(all(de_rc_dst, feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg(all(
not(no_de_rc_dst),
feature = "rc",
any(feature = "std", feature = "alloc")
))]
box_forwarded_impl! { box_forwarded_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde. /// This impl requires the [`"rc"`] Cargo feature of Serde.
/// ///
@@ -1805,7 +1915,11 @@ box_forwarded_impl! {
Rc Rc
} }
#[cfg(all(de_rc_dst, feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg(all(
not(no_de_rc_dst),
feature = "rc",
any(feature = "std", feature = "alloc")
))]
box_forwarded_impl! { box_forwarded_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde. /// This impl requires the [`"rc"`] Cargo feature of Serde.
/// ///
@@ -1849,7 +1963,7 @@ forwarded_impl!((T), RwLock<T>, RwLock::new);
// secs: u64, // secs: u64,
// nanos: u32, // nanos: u32,
// } // }
#[cfg(any(core_duration, feature = "std"))] #[cfg(any(feature = "std", not(no_core_duration)))]
impl<'de> Deserialize<'de> for Duration { impl<'de> Deserialize<'de> for Duration {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
@@ -2046,6 +2160,17 @@ impl<'de> Deserialize<'de> for SystemTime {
} }
} }
fn check_overflow<E>(secs: u64, nanos: u32) -> Result<(), E>
where
E: Error,
{
static NANOS_PER_SEC: u32 = 1_000_000_000;
match secs.checked_add((nanos / NANOS_PER_SEC) as u64) {
Some(_) => Ok(()),
None => Err(E::custom("overflow deserializing SystemTime epoch offset")),
}
}
struct DurationVisitor; struct DurationVisitor;
impl<'de> Visitor<'de> for DurationVisitor { impl<'de> Visitor<'de> for DurationVisitor {
@@ -2071,6 +2196,7 @@ impl<'de> Deserialize<'de> for SystemTime {
return Err(Error::invalid_length(1, &self)); return Err(Error::invalid_length(1, &self));
} }
}; };
try!(check_overflow(secs, nanos));
Ok(Duration::new(secs, nanos)) Ok(Duration::new(secs, nanos))
} }
@@ -2108,13 +2234,20 @@ impl<'de> Deserialize<'de> for SystemTime {
Some(nanos) => nanos, Some(nanos) => nanos,
None => return Err(<A::Error as Error>::missing_field("nanos_since_epoch")), None => return Err(<A::Error as Error>::missing_field("nanos_since_epoch")),
}; };
try!(check_overflow(secs, nanos));
Ok(Duration::new(secs, nanos)) Ok(Duration::new(secs, nanos))
} }
} }
const FIELDS: &'static [&'static str] = &["secs_since_epoch", "nanos_since_epoch"]; const FIELDS: &'static [&'static str] = &["secs_since_epoch", "nanos_since_epoch"];
let duration = try!(deserializer.deserialize_struct("SystemTime", FIELDS, DurationVisitor)); let duration = try!(deserializer.deserialize_struct("SystemTime", FIELDS, DurationVisitor));
Ok(UNIX_EPOCH + duration) #[cfg(not(no_systemtime_checked_add))]
let ret = UNIX_EPOCH
.checked_add(duration)
.ok_or_else(|| D::Error::custom("overflow deserializing SystemTime"));
#[cfg(no_systemtime_checked_add)]
let ret = Ok(UNIX_EPOCH + duration);
ret
} }
} }
@@ -2148,7 +2281,7 @@ where
} }
} }
#[cfg(range_inclusive)] #[cfg(not(no_range_inclusive))]
impl<'de, Idx> Deserialize<'de> for RangeInclusive<Idx> impl<'de, Idx> Deserialize<'de> for RangeInclusive<Idx>
where where
Idx: Deserialize<'de>, Idx: Deserialize<'de>,
@@ -2300,7 +2433,7 @@ mod range {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(any(ops_bound, collections_bound))] #[cfg(any(not(no_ops_bound), all(feature = "std", not(no_collections_bound))))]
impl<'de, T> Deserialize<'de> for Bound<T> impl<'de, T> Deserialize<'de> for Bound<T>
where where
T: Deserialize<'de>, T: Deserialize<'de>,
@@ -2408,58 +2541,6 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
macro_rules! nonzero_integers {
( $( $T: ident, )+ ) => {
$(
#[cfg(num_nonzero)]
impl<'de> Deserialize<'de> for num::$T {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let value = try!(Deserialize::deserialize(deserializer));
match <num::$T>::new(value) {
Some(nonzero) => Ok(nonzero),
None => Err(Error::custom("expected a non-zero value")),
}
}
}
)+
};
}
nonzero_integers! {
NonZeroU8,
NonZeroU16,
NonZeroU32,
NonZeroU64,
NonZeroUsize,
}
#[cfg(num_nonzero_signed)]
nonzero_integers! {
NonZeroI8,
NonZeroI16,
NonZeroI32,
NonZeroI64,
NonZeroIsize,
}
// Currently 128-bit integers do not work on Emscripten targets so we need an
// additional `#[cfg]`
serde_if_integer128! {
nonzero_integers! {
NonZeroU128,
}
#[cfg(num_nonzero_signed)]
nonzero_integers! {
NonZeroI128,
}
}
////////////////////////////////////////////////////////////////////////////////
impl<'de, T, E> Deserialize<'de> for Result<T, E> impl<'de, T, E> Deserialize<'de> for Result<T, E>
where where
T: Deserialize<'de>, T: Deserialize<'de>,
@@ -2580,7 +2661,7 @@ where
} }
} }
#[cfg(all(feature = "std", std_atomic))] #[cfg(all(feature = "std", not(no_std_atomic)))]
macro_rules! atomic_impl { macro_rules! atomic_impl {
($($ty:ident)*) => { ($($ty:ident)*) => {
$( $(
@@ -2596,14 +2677,14 @@ macro_rules! atomic_impl {
}; };
} }
#[cfg(all(feature = "std", std_atomic))] #[cfg(all(feature = "std", not(no_std_atomic)))]
atomic_impl! { atomic_impl! {
AtomicBool AtomicBool
AtomicI8 AtomicI16 AtomicI32 AtomicIsize AtomicI8 AtomicI16 AtomicI32 AtomicIsize
AtomicU8 AtomicU16 AtomicU32 AtomicUsize AtomicU8 AtomicU16 AtomicU32 AtomicUsize
} }
#[cfg(all(feature = "std", std_atomic64))] #[cfg(all(feature = "std", not(no_std_atomic64)))]
atomic_impl! { atomic_impl! {
AtomicI64 AtomicU64 AtomicI64 AtomicU64
} }
+17 -3
View File
@@ -1007,7 +1007,7 @@ pub trait Deserializer<'de>: Sized {
/// `Deserializer`. /// `Deserializer`.
/// ///
/// If the `Visitor` would benefit from taking ownership of `String` data, /// If the `Visitor` would benefit from taking ownership of `String` data,
/// indiciate this to the `Deserializer` by using `deserialize_string` /// indicate this to the `Deserializer` by using `deserialize_string`
/// instead. /// instead.
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error> fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where where
@@ -1213,6 +1213,20 @@ pub trait Deserializer<'de>: Sized {
fn is_human_readable(&self) -> bool { fn is_human_readable(&self) -> bool {
true true
} }
// Not public API.
#[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))]
#[doc(hidden)]
fn __deserialize_content<V>(
self,
_: ::actually_private::T,
visitor: V,
) -> Result<::private::de::Content<'de>, Self::Error>
where
V: Visitor<'de, Value = ::private::de::Content<'de>>,
{
self.deserialize_any(visitor)
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -1714,7 +1728,7 @@ pub trait SeqAccess<'de> {
} }
} }
impl<'de, 'a, A> SeqAccess<'de> for &'a mut A impl<'de, 'a, A: ?Sized> SeqAccess<'de> for &'a mut A
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
@@ -1867,7 +1881,7 @@ pub trait MapAccess<'de> {
} }
} }
impl<'de, 'a, A> MapAccess<'de> for &'a mut A impl<'de, 'a, A: ?Sized> MapAccess<'de> for &'a mut A
where where
A: MapAccess<'de>, A: MapAccess<'de>,
{ {
+2 -2
View File
@@ -66,7 +66,7 @@
/// ($($tt:tt)*) => {}; /// ($($tt:tt)*) => {};
/// } /// }
/// ``` /// ```
#[cfg(integer128)] #[cfg(not(no_integer128))]
#[macro_export] #[macro_export]
macro_rules! serde_if_integer128 { macro_rules! serde_if_integer128 {
($($tt:tt)*) => { ($($tt:tt)*) => {
@@ -74,7 +74,7 @@ macro_rules! serde_if_integer128 {
}; };
} }
#[cfg(not(integer128))] #[cfg(no_integer128)]
#[macro_export] #[macro_export]
#[doc(hidden)] #[doc(hidden)]
macro_rules! serde_if_integer128 { macro_rules! serde_if_integer128 {
+20 -14
View File
@@ -44,7 +44,7 @@
//! - [BSON], the data storage and network transfer format used by MongoDB. //! - [BSON], the data storage and network transfer format used by MongoDB.
//! - [Avro], a binary format used within Apache Hadoop, with support for schema //! - [Avro], a binary format used within Apache Hadoop, with support for schema
//! definition. //! definition.
//! - [JSON5], A superset of JSON including some productions from ES5. //! - [JSON5], a superset of JSON including some productions from ES5.
//! - [Postcard], a no\_std and embedded-systems friendly compact binary format. //! - [Postcard], a no\_std and embedded-systems friendly compact binary format.
//! - [URL] query strings, in the x-www-form-urlencoded format. //! - [URL] query strings, in the x-www-form-urlencoded format.
//! - [Envy], a way to deserialize environment variables into Rust structs. //! - [Envy], a way to deserialize environment variables into Rust structs.
@@ -60,7 +60,7 @@
//! //!
//! [JSON]: https://github.com/serde-rs/json //! [JSON]: https://github.com/serde-rs/json
//! [Bincode]: https://github.com/servo/bincode //! [Bincode]: https://github.com/servo/bincode
//! [CBOR]: https://github.com/pyfisch/cbor //! [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://github.com/alexcrichton/toml-rs
@@ -73,7 +73,7 @@
//! [URL]: https://docs.rs/serde_qs //! [URL]: https://docs.rs/serde_qs
//! [Envy]: https://github.com/softprops/envy //! [Envy]: https://github.com/softprops/envy
//! [Envy Store]: https://github.com/softprops/envy-store //! [Envy Store]: https://github.com/softprops/envy-store
//! [Cargo]: http://doc.crates.io/manifest.html //! [Cargo]: https://doc.rust-lang.org/cargo/reference/manifest.html
//! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.html //! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.html
//! [S-expressions]: https://github.com/rotty/lexpr-rs //! [S-expressions]: https://github.com/rotty/lexpr-rs
//! [D-Bus]: https://docs.rs/zvariant //! [D-Bus]: https://docs.rs/zvariant
@@ -84,7 +84,7 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// 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.123")] #![doc(html_root_url = "https://docs.rs/serde/1.0.134")]
// 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
@@ -94,13 +94,14 @@
#![cfg_attr(feature = "unstable", feature(never_type))] #![cfg_attr(feature = "unstable", feature(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))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Ignored clippy and clippy_pedantic lints // Ignored clippy and clippy_pedantic lints
#![cfg_attr( #![cfg_attr(
feature = "cargo-clippy", feature = "cargo-clippy",
allow( allow(
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704 // clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
unnested_or_patterns, unnested_or_patterns,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/7768
semicolon_if_nothing_returned,
// not available in our oldest supported compiler // not available in our oldest supported compiler
checked_conversions, checked_conversions,
empty_enum, empty_enum,
@@ -120,6 +121,7 @@
zero_prefixed_literal, zero_prefixed_literal,
// correctly used // correctly used
enum_glob_use, enum_glob_use,
let_underscore_drop,
map_err_ignore, map_err_ignore,
result_unit_err, result_unit_err,
wildcard_imports, wildcard_imports,
@@ -138,7 +140,6 @@
) )
)] )]
// Rustc lints. // Rustc lints.
#![forbid(unsafe_code)]
#![deny(missing_docs, unused_imports)] #![deny(missing_docs, unused_imports)]
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -157,7 +158,7 @@ mod lib {
pub use std::*; pub use std::*;
} }
pub use self::core::{cmp, iter, mem, num, slice, str}; pub use self::core::{cmp, iter, mem, num, ptr, slice, str};
pub use self::core::{f32, f64}; pub use self::core::{f32, f64};
pub use self::core::{i16, i32, i64, i8, isize}; pub use self::core::{i16, i32, i64, i8, isize};
pub use self::core::{u16, u32, u64, u8, usize}; pub use self::core::{u16, u32, u64, u8, usize};
@@ -226,27 +227,27 @@ mod lib {
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::time::{SystemTime, UNIX_EPOCH}; pub use std::time::{SystemTime, UNIX_EPOCH};
#[cfg(all(feature = "std", collections_bound))] #[cfg(all(feature = "std", not(no_collections_bound), no_ops_bound))]
pub use std::collections::Bound; pub use std::collections::Bound;
#[cfg(core_reverse)] #[cfg(not(no_core_reverse))]
pub use self::core::cmp::Reverse; pub use self::core::cmp::Reverse;
#[cfg(ops_bound)] #[cfg(not(no_ops_bound))]
pub use self::core::ops::Bound; pub use self::core::ops::Bound;
#[cfg(range_inclusive)] #[cfg(not(no_range_inclusive))]
pub use self::core::ops::RangeInclusive; pub use self::core::ops::RangeInclusive;
#[cfg(all(feature = "std", std_atomic))] #[cfg(all(feature = "std", 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", std_atomic64))] #[cfg(all(feature = "std", not(no_std_atomic64)))]
pub use std::sync::atomic::{AtomicI64, AtomicU64}; pub use std::sync::atomic::{AtomicI64, AtomicU64};
#[cfg(any(core_duration, feature = "std"))] #[cfg(any(feature = "std", not(no_core_duration)))]
pub use self::core::time::Duration; pub use self::core::time::Duration;
} }
@@ -294,3 +295,8 @@ extern crate serde_derive;
#[cfg(feature = "serde_derive")] #[cfg(feature = "serde_derive")]
#[doc(hidden)] #[doc(hidden)]
pub use serde_derive::*; pub use serde_derive::*;
#[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))]
mod actually_private {
pub struct T;
}
+52 -18
View File
@@ -206,6 +206,7 @@ mod content {
use lib::*; use lib::*;
use __private::size_hint; use __private::size_hint;
use actually_private;
use de::{ use de::{
self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, IgnoredAny, self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, IgnoredAny,
MapAccess, SeqAccess, Unexpected, Visitor, MapAccess, SeqAccess, Unexpected, Visitor,
@@ -215,7 +216,7 @@ mod content {
/// deserializing untagged enums and internally tagged enums. /// deserializing untagged enums and internally tagged enums.
/// ///
/// Not public API. Use serde-value instead. /// Not public API. Use serde-value instead.
#[derive(Debug)] #[derive(Debug, Clone)]
pub enum Content<'de> { pub enum Content<'de> {
Bool(bool), Bool(bool),
@@ -294,7 +295,7 @@ mod content {
// Untagged and internally tagged enums are only supported in // Untagged and internally tagged enums are only supported in
// self-describing formats. // self-describing formats.
let visitor = ContentVisitor { value: PhantomData }; let visitor = ContentVisitor { value: PhantomData };
deserializer.deserialize_any(visitor) deserializer.__deserialize_content(actually_private::T, visitor)
} }
} }
@@ -1287,8 +1288,9 @@ mod content {
// } // }
// //
// We want {"topic":"Info"} to deserialize even though // We want {"topic":"Info"} to deserialize even though
// ordinarily unit structs do not deserialize from empty map. // ordinarily unit structs do not deserialize from empty map/seq.
Content::Map(ref v) if v.is_empty() => visitor.visit_unit(), Content::Map(ref v) if v.is_empty() => visitor.visit_unit(),
Content::Seq(ref v) if v.is_empty() => visitor.visit_unit(),
_ => self.deserialize_any(visitor), _ => self.deserialize_any(visitor),
} }
} }
@@ -1426,6 +1428,18 @@ mod content {
drop(self); drop(self);
visitor.visit_unit() visitor.visit_unit()
} }
fn __deserialize_content<V>(
self,
_: actually_private::T,
visitor: V,
) -> Result<Content<'de>, Self::Error>
where
V: Visitor<'de, Value = Content<'de>>,
{
let _ = visitor;
Ok(self.content)
}
} }
impl<'de, E> ContentDeserializer<'de, E> { impl<'de, E> ContentDeserializer<'de, E> {
@@ -1741,6 +1755,25 @@ mod content {
_ => Err(self.invalid_type(&visitor)), _ => Err(self.invalid_type(&visitor)),
} }
} }
fn deserialize_float<V>(self, visitor: V) -> Result<V::Value, E>
where
V: Visitor<'de>,
{
match *self.content {
Content::F32(v) => visitor.visit_f32(v),
Content::F64(v) => visitor.visit_f64(v),
Content::U8(v) => visitor.visit_u8(v),
Content::U16(v) => visitor.visit_u16(v),
Content::U32(v) => visitor.visit_u32(v),
Content::U64(v) => visitor.visit_u64(v),
Content::I8(v) => visitor.visit_i8(v),
Content::I16(v) => visitor.visit_i16(v),
Content::I32(v) => visitor.visit_i32(v),
Content::I64(v) => visitor.visit_i64(v),
_ => Err(self.invalid_type(&visitor)),
}
}
} }
fn visit_content_seq_ref<'a, 'de, V, E>( fn visit_content_seq_ref<'a, 'de, V, E>(
@@ -1888,25 +1921,14 @@ mod content {
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
match *self.content { self.deserialize_float(visitor)
Content::F32(v) => visitor.visit_f32(v),
Content::F64(v) => visitor.visit_f64(v),
Content::U64(v) => visitor.visit_u64(v),
Content::I64(v) => visitor.visit_i64(v),
_ => Err(self.invalid_type(&visitor)),
}
} }
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error> fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
match *self.content { self.deserialize_float(visitor)
Content::F64(v) => visitor.visit_f64(v),
Content::U64(v) => visitor.visit_u64(v),
Content::I64(v) => visitor.visit_i64(v),
_ => Err(self.invalid_type(&visitor)),
}
} }
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error> fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -2129,6 +2151,18 @@ mod content {
{ {
visitor.visit_unit() visitor.visit_unit()
} }
fn __deserialize_content<V>(
self,
_: actually_private::T,
visitor: V,
) -> Result<Content<'de>, Self::Error>
where
V: Visitor<'de, Value = Content<'de>>,
{
let _ = visitor;
Ok(self.content.clone())
}
} }
impl<'a, 'de, E> ContentRefDeserializer<'a, 'de, E> { impl<'a, 'de, E> ContentRefDeserializer<'a, 'de, E> {
@@ -2823,7 +2857,7 @@ where
where where
T: DeserializeSeed<'de>, T: DeserializeSeed<'de>,
{ {
while let Some(item) = self.iter.next() { for item in &mut self.iter {
// Items in the vector are nulled out when used by a struct. // Items in the vector are nulled out when used by a struct.
if let Some((ref key, ref content)) = *item { if let Some((ref key, ref content)) = *item {
self.pending_content = Some(content); self.pending_content = Some(content);
@@ -2925,7 +2959,7 @@ where
where where
T: DeserializeSeed<'de>, T: DeserializeSeed<'de>,
{ {
while let Some(item) = self.iter.next() { for item in &mut self.iter {
if let Some((ref key, ref content)) = *item { if let Some((ref key, ref content)) = *item {
// Do not take(), instead borrow this entry. The internally tagged // Do not take(), instead borrow this entry. The internally tagged
// enum does its own buffering so we can't tell whether this entry // enum does its own buffering so we can't tell whether this entry
+4 -3
View File
@@ -1,6 +1,6 @@
#[cfg(serde_derive)] #[cfg(not(no_serde_derive))]
pub mod de; pub mod de;
#[cfg(serde_derive)] #[cfg(not(no_serde_derive))]
pub mod ser; pub mod ser;
pub mod size_hint; pub mod size_hint;
@@ -14,6 +14,7 @@ pub use lib::default::Default;
pub use lib::fmt::{self, Formatter}; pub use lib::fmt::{self, Formatter};
pub use lib::marker::PhantomData; pub use lib::marker::PhantomData;
pub use lib::option::Option::{self, None, Some}; pub use lib::option::Option::{self, None, Some};
pub use lib::ptr;
pub use lib::result::Result::{self, Err, Ok}; pub use lib::result::Result::{self, Err, Ok};
pub use self::string::from_utf8_lossy; pub use self::string::from_utf8_lossy;
@@ -21,7 +22,7 @@ pub use self::string::from_utf8_lossy;
#[cfg(any(feature = "alloc", feature = "std"))] #[cfg(any(feature = "alloc", feature = "std"))]
pub use lib::{ToString, Vec}; pub use lib::{ToString, Vec};
#[cfg(core_try_from)] #[cfg(not(no_core_try_from))]
pub use lib::convert::TryFrom; pub use lib::convert::TryFrom;
mod string { mod string {
+65 -11
View File
@@ -239,7 +239,7 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(range_inclusive)] #[cfg(not(no_range_inclusive))]
impl<Idx> Serialize for RangeInclusive<Idx> impl<Idx> Serialize for RangeInclusive<Idx>
where where
Idx: Serialize, Idx: Serialize,
@@ -258,7 +258,7 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(any(ops_bound, collections_bound))] #[cfg(any(not(no_ops_bound), all(feature = "std", not(no_collections_bound))))]
impl<T> Serialize for Bound<T> impl<T> Serialize for Bound<T>
where where
T: Serialize, T: Serialize,
@@ -467,7 +467,7 @@ where
macro_rules! nonzero_integers { macro_rules! nonzero_integers {
( $( $T: ident, )+ ) => { ( $( $T: ident, )+ ) => {
$( $(
#[cfg(num_nonzero)] #[cfg(not(no_num_nonzero))]
impl Serialize for num::$T { impl Serialize for num::$T {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where where
@@ -488,7 +488,7 @@ nonzero_integers! {
NonZeroUsize, NonZeroUsize,
} }
#[cfg(num_nonzero_signed)] #[cfg(not(no_num_nonzero_signed))]
nonzero_integers! { nonzero_integers! {
NonZeroI8, NonZeroI8,
NonZeroI16, NonZeroI16,
@@ -504,7 +504,7 @@ serde_if_integer128! {
NonZeroU128, NonZeroU128,
} }
#[cfg(num_nonzero_signed)] #[cfg(not(no_num_nonzero_signed))]
nonzero_integers! { nonzero_integers! {
NonZeroI128, NonZeroI128,
} }
@@ -591,7 +591,7 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(any(core_duration, feature = "std"))] #[cfg(any(feature = "std", not(no_core_duration)))]
impl Serialize for Duration { impl Serialize for Duration {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where where
@@ -674,6 +674,52 @@ impl Serialize for net::IpAddr {
} }
} }
#[cfg(feature = "std")]
const DEC_DIGITS_LUT: &'static [u8] = b"\
0001020304050607080910111213141516171819\
2021222324252627282930313233343536373839\
4041424344454647484950515253545556575859\
6061626364656667686970717273747576777879\
8081828384858687888990919293949596979899";
#[cfg(feature = "std")]
#[inline]
fn format_u8(mut n: u8, out: &mut [u8]) -> usize {
if n >= 100 {
let d1 = ((n % 100) << 1) as usize;
n /= 100;
out[0] = b'0' + n;
out[1] = DEC_DIGITS_LUT[d1];
out[2] = DEC_DIGITS_LUT[d1 + 1];
3
} else if n >= 10 {
let d1 = (n << 1) as usize;
out[0] = DEC_DIGITS_LUT[d1];
out[1] = DEC_DIGITS_LUT[d1 + 1];
2
} else {
out[0] = b'0' + n;
1
}
}
#[cfg(feature = "std")]
#[test]
fn test_format_u8() {
let mut i = 0u8;
loop {
let mut buf = [0u8; 3];
let written = format_u8(i, &mut buf);
assert_eq!(i.to_string().as_bytes(), &buf[..written]);
match i.checked_add(1) {
Some(next) => i = next,
None => break,
}
}
}
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl Serialize for net::Ipv4Addr { impl Serialize for net::Ipv4Addr {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -683,7 +729,14 @@ impl Serialize for net::Ipv4Addr {
if serializer.is_human_readable() { if serializer.is_human_readable() {
const MAX_LEN: usize = 15; const MAX_LEN: usize = 15;
debug_assert_eq!(MAX_LEN, "101.102.103.104".len()); debug_assert_eq!(MAX_LEN, "101.102.103.104".len());
serialize_display_bounded_length!(self, MAX_LEN, serializer) let mut buf = [b'.'; MAX_LEN];
let mut written = format_u8(self.octets()[0], &mut buf);
for oct in &self.octets()[1..] {
// Skip over delimiters that we initialized buf with
written += format_u8(*oct, &mut buf[written + 1..]) + 1;
}
// 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]) })
} else { } else {
self.octets().serialize(serializer) self.octets().serialize(serializer)
} }
@@ -837,7 +890,7 @@ where
} }
} }
#[cfg(core_reverse)] #[cfg(not(no_core_reverse))]
impl<T> Serialize for Reverse<T> impl<T> Serialize for Reverse<T>
where where
T: Serialize, T: Serialize,
@@ -853,7 +906,7 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(all(feature = "std", std_atomic))] #[cfg(all(feature = "std", not(no_std_atomic)))]
macro_rules! atomic_impl { macro_rules! atomic_impl {
($($ty:ident)*) => { ($($ty:ident)*) => {
$( $(
@@ -862,6 +915,7 @@ macro_rules! atomic_impl {
where where
S: Serializer, S: Serializer,
{ {
// Matches the atomic ordering used in libcore for the Debug impl
self.load(Ordering::SeqCst).serialize(serializer) self.load(Ordering::SeqCst).serialize(serializer)
} }
} }
@@ -869,14 +923,14 @@ macro_rules! atomic_impl {
} }
} }
#[cfg(all(feature = "std", std_atomic))] #[cfg(all(feature = "std", not(no_std_atomic)))]
atomic_impl! { atomic_impl! {
AtomicBool AtomicBool
AtomicI8 AtomicI16 AtomicI32 AtomicIsize AtomicI8 AtomicI16 AtomicI32 AtomicIsize
AtomicU8 AtomicU16 AtomicU32 AtomicUsize AtomicU8 AtomicU16 AtomicU32 AtomicUsize
} }
#[cfg(all(feature = "std", std_atomic64))] #[cfg(all(feature = "std", not(no_std_atomic64)))]
atomic_impl! { atomic_impl! {
AtomicI64 AtomicU64 AtomicI64 AtomicU64
} }
+26 -4
View File
@@ -1279,9 +1279,20 @@ pub trait Serializer: Sized {
{ {
let iter = iter.into_iter(); let iter = iter.into_iter();
let mut serializer = try!(self.serialize_seq(iterator_len_hint(&iter))); let mut serializer = try!(self.serialize_seq(iterator_len_hint(&iter)));
for item in iter {
try!(serializer.serialize_element(&item)); #[cfg(not(no_iterator_try_fold))]
{
let mut iter = iter;
try!(iter.try_for_each(|item| serializer.serialize_element(&item)));
} }
#[cfg(no_iterator_try_fold)]
{
for item in iter {
try!(serializer.serialize_element(&item));
}
}
serializer.end() serializer.end()
} }
@@ -1319,9 +1330,20 @@ pub trait Serializer: Sized {
{ {
let iter = iter.into_iter(); let iter = iter.into_iter();
let mut serializer = try!(self.serialize_map(iterator_len_hint(&iter))); let mut serializer = try!(self.serialize_map(iterator_len_hint(&iter)));
for (key, value) in iter {
try!(serializer.serialize_entry(&key, &value)); #[cfg(not(no_iterator_try_fold))]
{
let mut iter = iter;
try!(iter.try_for_each(|(key, value)| serializer.serialize_entry(&key, &value)));
} }
#[cfg(no_iterator_try_fold)]
{
for (key, value) in iter {
try!(serializer.serialize_entry(&key, &value));
}
}
serializer.end() serializer.end()
} }
+2 -1
View File
@@ -1,7 +1,8 @@
[package] [package]
name = "serde_derive" name = "serde_derive"
version = "1.0.123" # remember to update html_root_url version = "1.0.134" # 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>"]
rust-version = "1.31"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
homepage = "https://serde.rs" homepage = "https://serde.rs"
+6
View File
@@ -16,6 +16,12 @@ fn main() {
if minor >= 37 { if minor >= 37 {
println!("cargo:rustc-cfg=underscore_consts"); println!("cargo:rustc-cfg=underscore_consts");
} }
// The ptr::addr_of! macro stabilized in Rust 1.51:
// https://blog.rust-lang.org/2021/03/25/Rust-1.51.0.html#stabilized-apis
if minor >= 51 {
println!("cargo:rustc-cfg=ptr_addr_of");
}
} }
fn rustc_minor_version() -> Option<u32> { fn rustc_minor_version() -> Option<u32> {
+4 -4
View File
@@ -49,8 +49,8 @@ pub fn with_where_predicates_from_fields(
let predicates = cont let predicates = cont
.data .data
.all_fields() .all_fields()
.flat_map(|field| from_field(&field.attrs)) .filter_map(|field| from_field(&field.attrs))
.flat_map(|predicates| predicates.to_vec()); .flat_map(<[syn::WherePredicate]>::to_vec);
let mut generics = generics.clone(); let mut generics = generics.clone();
generics.make_where_clause().predicates.extend(predicates); generics.make_where_clause().predicates.extend(predicates);
@@ -71,8 +71,8 @@ pub fn with_where_predicates_from_variants(
let predicates = variants let predicates = variants
.iter() .iter()
.flat_map(|variant| from_variant(&variant.attrs)) .filter_map(|variant| from_variant(&variant.attrs))
.flat_map(|predicates| predicates.to_vec()); .flat_map(<[syn::WherePredicate]>::to_vec);
let mut generics = generics.clone(); let mut generics = generics.clone();
generics.make_where_clause().predicates.extend(predicates); generics.make_where_clause().predicates.extend(predicates);
+46 -24
View File
@@ -36,7 +36,7 @@ pub fn expand_derive_deserialize(
let impl_block = if let Some(remote) = cont.attrs.remote() { let impl_block = if let Some(remote) = cont.attrs.remote() {
let vis = &input.vis; let vis = &input.vis;
let used = pretend::pretend_used(&cont); let used = pretend::pretend_used(&cont, params.is_packed);
quote! { quote! {
impl #de_impl_generics #ident #ty_generics #where_clause { impl #de_impl_generics #ident #ty_generics #where_clause {
#vis fn deserialize<__D>(__deserializer: __D) -> #serde::__private::Result<#remote #ty_generics, __D::Error> #vis fn deserialize<__D>(__deserializer: __D) -> #serde::__private::Result<#remote #ty_generics, __D::Error>
@@ -125,6 +125,9 @@ struct Parameters {
/// At least one field has a serde(getter) attribute, implying that the /// At least one field has a serde(getter) attribute, implying that the
/// remote type has a private field. /// remote type has a private field.
has_getter: bool, has_getter: bool,
/// Type has a repr(packed) attribute.
is_packed: bool,
} }
impl Parameters { impl Parameters {
@@ -137,6 +140,7 @@ impl Parameters {
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();
let is_packed = cont.attrs.is_packed();
Parameters { Parameters {
local, local,
@@ -144,6 +148,7 @@ impl Parameters {
generics, generics,
borrowed, borrowed,
has_getter, has_getter,
is_packed,
} }
} }
@@ -475,7 +480,7 @@ fn deserialize_tuple(
}; };
let visit_seq = Stmts(deserialize_seq( let visit_seq = Stmts(deserialize_seq(
&type_path, params, fields, false, cattrs, &expecting, &type_path, params, fields, false, cattrs, expecting,
)); ));
let visitor_expr = quote! { let visitor_expr = quote! {
@@ -561,7 +566,7 @@ fn deserialize_tuple_in_place(
None None
}; };
let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, &expecting)); let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting));
let visitor_expr = quote! { let visitor_expr = quote! {
__Visitor { __Visitor {
@@ -922,7 +927,7 @@ fn deserialize_struct(
let expecting = cattrs.expecting().unwrap_or(&expecting); let expecting = cattrs.expecting().unwrap_or(&expecting);
let visit_seq = Stmts(deserialize_seq( let visit_seq = Stmts(deserialize_seq(
&type_path, params, fields, true, cattrs, &expecting, &type_path, params, fields, true, cattrs, expecting,
)); ));
let (field_visitor, fields_stmt, visit_map) = if cattrs.has_flatten() { let (field_visitor, fields_stmt, visit_map) = if cattrs.has_flatten() {
@@ -1063,7 +1068,7 @@ fn deserialize_struct_in_place(
}; };
let expecting = cattrs.expecting().unwrap_or(&expecting); let expecting = cattrs.expecting().unwrap_or(&expecting);
let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, &expecting)); let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting));
let (field_visitor, fields_stmt, visit_map) = let (field_visitor, fields_stmt, visit_map) =
deserialize_struct_as_struct_in_place_visitor(params, fields, cattrs); deserialize_struct_as_struct_in_place_visitor(params, fields, cattrs);
@@ -1453,7 +1458,7 @@ fn deserialize_adjacently_tagged_enum(
while let _serde::__private::Some(__k) = #next_key { while let _serde::__private::Some(__k) = #next_key {
match __k { match __k {
_serde::__private::de::TagContentOtherField::Other => { _serde::__private::de::TagContentOtherField::Other => {
try!(_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)); let _ = try!(_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map));
continue; continue;
}, },
_serde::__private::de::TagContentOtherField::Tag => { _serde::__private::de::TagContentOtherField::Tag => {
@@ -1728,6 +1733,8 @@ fn deserialize_externally_tagged_variant(
} }
} }
// Generates significant part of the visit_seq and visit_map bodies of visitors
// for the variants of internally tagged enum.
fn deserialize_internally_tagged_variant( fn deserialize_internally_tagged_variant(
params: &Parameters, params: &Parameters,
variant: &Variant, variant: &Variant,
@@ -1779,11 +1786,9 @@ fn deserialize_untagged_variant(
deserializer: TokenStream, deserializer: TokenStream,
) -> Fragment { ) -> Fragment {
if let Some(path) = variant.attrs.deserialize_with() { if let Some(path) = variant.attrs.deserialize_with() {
let (wrapper, wrapper_ty, unwrap_fn) = wrap_deserialize_variant_with(params, variant, path); let unwrap_fn = unwrap_to_variant_closure(params, variant, false);
return quote_block! { return quote_block! {
#wrapper _serde::__private::Result::map(#path(#deserializer), #unwrap_fn)
_serde::__private::Result::map(
<#wrapper_ty as _serde::Deserialize>::deserialize(#deserializer), #unwrap_fn)
}; };
} }
@@ -2087,7 +2092,7 @@ fn deserialize_identifier(
) -> Fragment { ) -> Fragment {
let mut flat_fields = Vec::new(); let mut flat_fields = Vec::new();
for (_, ident, aliases) in fields { for (_, ident, aliases) in fields {
flat_fields.extend(aliases.iter().map(|alias| (alias, ident))) flat_fields.extend(aliases.iter().map(|alias| (alias, ident)));
} }
let field_strs: &Vec<_> = &flat_fields.iter().map(|(name, _)| name).collect(); let field_strs: &Vec<_> = &flat_fields.iter().map(|(name, _)| name).collect();
@@ -2285,7 +2290,7 @@ fn deserialize_identifier(
}; };
let visit_borrowed = if fallthrough_borrowed.is_some() || collect_other_fields { let visit_borrowed = if fallthrough_borrowed.is_some() || collect_other_fields {
let fallthrough_borrowed_arm = fallthrough_borrowed.as_ref().unwrap_or(&fallthrough_arm); let fallthrough_borrowed_arm = fallthrough_borrowed.as_ref().unwrap_or(fallthrough_arm);
Some(quote! { Some(quote! {
fn visit_borrowed_str<__E>(self, __value: &'de str) -> _serde::__private::Result<Self::Value, __E> fn visit_borrowed_str<__E>(self, __value: &'de str) -> _serde::__private::Result<Self::Value, __E>
where where
@@ -2883,44 +2888,61 @@ fn wrap_deserialize_variant_with(
variant: &Variant, variant: &Variant,
deserialize_with: &syn::ExprPath, deserialize_with: &syn::ExprPath,
) -> (TokenStream, TokenStream, TokenStream) { ) -> (TokenStream, TokenStream, TokenStream) {
let this = &params.this;
let variant_ident = &variant.ident;
let field_tys = variant.fields.iter().map(|field| field.ty); let field_tys = variant.fields.iter().map(|field| field.ty);
let (wrapper, wrapper_ty) = let (wrapper, wrapper_ty) =
wrap_deserialize_with(params, &quote!((#(#field_tys),*)), deserialize_with); wrap_deserialize_with(params, &quote!((#(#field_tys),*)), deserialize_with);
let unwrap_fn = unwrap_to_variant_closure(params, variant, true);
(wrapper, wrapper_ty, unwrap_fn)
}
// Generates closure that converts single input parameter to the final value.
fn unwrap_to_variant_closure(
params: &Parameters,
variant: &Variant,
with_wrapper: bool,
) -> TokenStream {
let this = &params.this;
let variant_ident = &variant.ident;
let (arg, wrapper) = if with_wrapper {
(quote! { __wrap }, quote! { __wrap.value })
} else {
let field_tys = variant.fields.iter().map(|field| field.ty);
(quote! { __wrap: (#(#field_tys),*) }, quote! { __wrap })
};
let field_access = (0..variant.fields.len()).map(|n| { let field_access = (0..variant.fields.len()).map(|n| {
Member::Unnamed(Index { Member::Unnamed(Index {
index: n as u32, index: n as u32,
span: Span::call_site(), span: Span::call_site(),
}) })
}); });
let unwrap_fn = match variant.style {
match variant.style {
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! {
|__wrap| #this::#variant_ident { #member: __wrap.value } |#arg| #this::#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! {
|__wrap| #this::#variant_ident { #(#members: __wrap.value.#field_access),* } |#arg| #this::#variant_ident { #(#members: #wrapper.#field_access),* }
} }
} }
Style::Tuple => quote! { Style::Tuple => quote! {
|__wrap| #this::#variant_ident(#(__wrap.value.#field_access),*) |#arg| #this::#variant_ident(#(#wrapper.#field_access),*)
}, },
Style::Newtype => quote! { Style::Newtype => quote! {
|__wrap| #this::#variant_ident(__wrap.value) |#arg| #this::#variant_ident(#wrapper)
}, },
Style::Unit => quote! { Style::Unit => quote! {
|__wrap| #this::#variant_ident |#arg| #this::#variant_ident
}, },
}; }
(wrapper, wrapper_ty, unwrap_fn)
} }
fn expr_is_missing(field: &Field, cattrs: &attr::Container) -> Fragment { fn expr_is_missing(field: &Field, cattrs: &attr::Container) -> Fragment {
+1 -1
View File
@@ -23,7 +23,7 @@ pub fn wrap_in_const(
use #path as _serde; use #path as _serde;
}, },
None => quote! { None => quote! {
#[allow(rust_2018_idioms, clippy::useless_attribute)] #[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde; extern crate serde as _serde;
}, },
}; };
+1 -1
View File
@@ -23,7 +23,7 @@ pub struct Container<'a> {
/// The fields of a struct or enum. /// The fields of a struct or enum.
/// ///
/// Analagous to `syn::Data`. /// Analogous to `syn::Data`.
pub enum Data<'a> { pub enum Data<'a> {
Enum(Vec<Variant<'a>>), Enum(Vec<Variant<'a>>),
Struct(Style, Vec<Field<'a>>), Struct(Style, Vec<Field<'a>>),
+4 -4
View File
@@ -556,7 +556,7 @@ impl Container {
// Parse `#[serde(crate = "foo")]` // Parse `#[serde(crate = "foo")]`
Meta(NameValue(m)) if m.path == CRATE => { Meta(NameValue(m)) if m.path == CRATE => {
if let Ok(path) = parse_lit_into_path(cx, CRATE, &m.lit) { if let Ok(path) = parse_lit_into_path(cx, CRATE, &m.lit) {
serde_path.set(&m.path, path) serde_path.set(&m.path, path);
} }
} }
@@ -1609,7 +1609,7 @@ fn get_lit_str2<'a>(
fn parse_lit_into_path(cx: &Ctxt, attr_name: Symbol, lit: &syn::Lit) -> Result<syn::Path, ()> { fn parse_lit_into_path(cx: &Ctxt, attr_name: Symbol, lit: &syn::Lit) -> Result<syn::Path, ()> {
let string = get_lit_str(cx, attr_name, lit)?; let string = get_lit_str(cx, attr_name, lit)?;
parse_lit_str(string).map_err(|_| { parse_lit_str(string).map_err(|_| {
cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value())) cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value()));
}) })
} }
@@ -1620,7 +1620,7 @@ fn parse_lit_into_expr_path(
) -> Result<syn::ExprPath, ()> { ) -> Result<syn::ExprPath, ()> {
let string = get_lit_str(cx, attr_name, lit)?; let string = get_lit_str(cx, attr_name, lit)?;
parse_lit_str(string).map_err(|_| { parse_lit_str(string).map_err(|_| {
cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value())) cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value()));
}) })
} }
@@ -1649,7 +1649,7 @@ fn parse_lit_into_ty(cx: &Ctxt, attr_name: Symbol, lit: &syn::Lit) -> Result<syn
cx.error_spanned_by( cx.error_spanned_by(
lit, lit,
format!("failed to parse type: {} = {:?}", attr_name, string.value()), format!("failed to parse type: {} = {:?}", attr_name, string.value()),
) );
}) })
} }
+2 -2
View File
@@ -260,7 +260,7 @@ fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
cx.error_spanned_by( cx.error_spanned_by(
cont.original, cont.original,
format!("variant field name `{}` conflicts with internal tag", tag), format!("variant field name `{}` conflicts with internal tag", tag),
) );
}; };
for variant in variants { for variant in variants {
@@ -396,7 +396,7 @@ fn member_message(member: &Member) -> String {
} }
fn allow_transparent(field: &Field, derive: Derive) -> bool { fn allow_transparent(field: &Field, derive: Derive) -> bool {
if let Type::Path(ty) = ungroup(&field.ty) { if let Type::Path(ty) = ungroup(field.ty) {
if let Some(seg) = ty.path.segments.last() { if let Some(seg) = ty.path.segments.last() {
if seg.ident == "PhantomData" { if seg.ident == "PhantomData" {
return false; return false;
+11 -3
View File
@@ -13,13 +13,18 @@
//! //!
//! [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.123")] #![doc(html_root_url = "https://docs.rs/serde_derive/1.0.134")]
#![allow(unknown_lints, bare_trait_objects)] #![allow(unknown_lints, bare_trait_objects)]
#![deny(clippy::all, clippy::pedantic)]
// Ignored clippy lints // Ignored clippy lints
#![allow( #![allow(
// clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054
clippy::branches_sharing_code,
clippy::cognitive_complexity, clippy::cognitive_complexity,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/7575
clippy::collapsible_match,
clippy::enum_variant_names, clippy::enum_variant_names,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797
clippy::manual_map,
clippy::match_like_matches_macro, clippy::match_like_matches_macro,
clippy::needless_pass_by_value, clippy::needless_pass_by_value,
clippy::too_many_arguments, clippy::too_many_arguments,
@@ -35,11 +40,14 @@
clippy::checked_conversions, clippy::checked_conversions,
clippy::doc_markdown, clippy::doc_markdown,
clippy::enum_glob_use, clippy::enum_glob_use,
clippy::filter_map,
clippy::indexing_slicing, clippy::indexing_slicing,
clippy::items_after_statements, clippy::items_after_statements,
clippy::let_underscore_drop,
clippy::manual_assert,
clippy::map_err_ignore, clippy::map_err_ignore,
clippy::match_same_arms, clippy::match_same_arms,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6984
clippy::match_wildcard_for_single_variants,
clippy::module_name_repetitions, clippy::module_name_repetitions,
clippy::must_use_candidate, clippy::must_use_candidate,
clippy::option_if_let_else, clippy::option_if_let_else,
+103 -42
View File
@@ -1,7 +1,7 @@
use proc_macro2::{Span, TokenStream}; use proc_macro2::TokenStream;
use syn::Ident; use quote::format_ident;
use internals::ast::{Container, Data, Field, Style}; use internals::ast::{Container, Data, Field, Style, Variant};
// Suppress dead_code warnings that would otherwise appear when using a remote // Suppress dead_code warnings that would otherwise appear when using a remote
// derive. Other than this pretend code, a struct annotated with remote derive // derive. Other than this pretend code, a struct annotated with remote derive
@@ -20,8 +20,8 @@ use internals::ast::{Container, Data, Field, Style};
// 8 | enum EnumDef { V } // 8 | enum EnumDef { V }
// | ^ // | ^
// //
pub fn pretend_used(cont: &Container) -> TokenStream { pub fn pretend_used(cont: &Container, is_packed: bool) -> TokenStream {
let pretend_fields = pretend_fields_used(cont); let pretend_fields = pretend_fields_used(cont, is_packed);
let pretend_variants = pretend_variants_used(cont); let pretend_variants = pretend_variants_used(cont);
quote! { quote! {
@@ -32,49 +32,117 @@ pub fn pretend_used(cont: &Container) -> TokenStream {
// For structs with named fields, expands to: // For structs with named fields, expands to:
// //
// match None::<&T> {
// Some(T { a: __v0, b: __v1 }) => {}
// _ => {}
// }
//
// For packed structs on sufficiently new rustc, expands to:
//
// match None::<&T> {
// Some(__v @ T { a: _, b: _ }) => {
// let _ = addr_of!(__v.a);
// let _ = addr_of!(__v.b);
// }
// _ => {}
// }
//
// For packed structs on older rustc, we assume Sized and !Drop, and expand to:
//
// match None::<T> { // match None::<T> {
// Some(T { a: ref __v0, b: ref __v1 }) => {} // Some(T { a: __v0, b: __v1 }) => {}
// _ => {} // _ => {}
// } // }
// //
// For enums, expands to the following but only including struct variants: // For enums, expands to the following but only including struct variants:
// //
// match None::<T> { // match None::<&T> {
// Some(T::A { a: ref __v0 }) => {} // Some(T::A { a: __v0 }) => {}
// Some(T::B { b: ref __v0 }) => {} // Some(T::B { b: __v0 }) => {}
// _ => {} // _ => {}
// } // }
// //
// The `ref` is important in case the user has written a Drop impl on their fn pretend_fields_used(cont: &Container, is_packed: bool) -> TokenStream {
// type. Rust does not allow destructuring a struct or enum that has a Drop match &cont.data {
// impl. Data::Enum(variants) => pretend_fields_used_enum(cont, variants),
fn pretend_fields_used(cont: &Container) -> TokenStream { Data::Struct(Style::Struct, fields) => {
if is_packed {
pretend_fields_used_struct_packed(cont, fields)
} else {
pretend_fields_used_struct(cont, fields)
}
}
Data::Struct(_, _) => quote!(),
}
}
fn pretend_fields_used_struct(cont: &Container, fields: &[Field]) -> TokenStream {
let type_ident = &cont.ident; let type_ident = &cont.ident;
let (_, ty_generics, _) = cont.generics.split_for_impl(); let (_, ty_generics, _) = cont.generics.split_for_impl();
let patterns = match &cont.data { let members = fields.iter().map(|field| &field.member);
Data::Enum(variants) => variants let placeholders = (0usize..).map(|i| format_ident!("__v{}", i));
.iter()
.filter_map(|variant| match variant.style {
Style::Struct => {
let variant_ident = &variant.ident;
let pat = struct_pattern(&variant.fields);
Some(quote!(#type_ident::#variant_ident #pat))
}
_ => None,
})
.collect::<Vec<_>>(),
Data::Struct(Style::Struct, fields) => {
let pat = struct_pattern(fields);
vec![quote!(#type_ident #pat)]
}
Data::Struct(_, _) => {
return quote!();
}
};
quote! { quote! {
match _serde::__private::None::<#type_ident #ty_generics> { match _serde::__private::None::<&#type_ident #ty_generics> {
_serde::__private::Some(#type_ident { #(#members: #placeholders),* }) => {}
_ => {}
}
}
}
fn pretend_fields_used_struct_packed(cont: &Container, fields: &[Field]) -> TokenStream {
let type_ident = &cont.ident;
let (_, ty_generics, _) = cont.generics.split_for_impl();
let members = fields.iter().map(|field| &field.member).collect::<Vec<_>>();
#[cfg(ptr_addr_of)]
{
quote! {
match _serde::__private::None::<&#type_ident #ty_generics> {
_serde::__private::Some(__v @ #type_ident { #(#members: _),* }) => {
#(
let _ = _serde::__private::ptr::addr_of!(__v.#members);
)*
}
_ => {}
}
}
}
#[cfg(not(ptr_addr_of))]
{
let placeholders = (0usize..).map(|i| format_ident!("__v{}", i));
quote! {
match _serde::__private::None::<#type_ident #ty_generics> {
_serde::__private::Some(#type_ident { #(#members: #placeholders),* }) => {}
_ => {}
}
}
}
}
fn pretend_fields_used_enum(cont: &Container, variants: &[Variant]) -> TokenStream {
let type_ident = &cont.ident;
let (_, ty_generics, _) = cont.generics.split_for_impl();
let patterns = variants
.iter()
.filter_map(|variant| match variant.style {
Style::Struct => {
let variant_ident = &variant.ident;
let members = variant.fields.iter().map(|field| &field.member);
let placeholders = (0usize..).map(|i| format_ident!("__v{}", i));
Some(quote!(#type_ident::#variant_ident { #(#members: #placeholders),* }))
}
_ => None,
})
.collect::<Vec<_>>();
quote! {
match _serde::__private::None::<&#type_ident #ty_generics> {
#( #(
_serde::__private::Some(#patterns) => {} _serde::__private::Some(#patterns) => {}
)* )*
@@ -107,7 +175,7 @@ fn pretend_variants_used(cont: &Container) -> TokenStream {
let cases = variants.iter().map(|variant| { let cases = variants.iter().map(|variant| {
let variant_ident = &variant.ident; let variant_ident = &variant.ident;
let placeholders = &(0..variant.fields.len()) let placeholders = &(0..variant.fields.len())
.map(|i| Ident::new(&format!("__v{}", i), Span::call_site())) .map(|i| format_ident!("__v{}", i))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let pat = match variant.style { let pat = match variant.style {
@@ -131,10 +199,3 @@ fn pretend_variants_used(cont: &Container) -> TokenStream {
quote!(#(#cases)*) quote!(#(#cases)*)
} }
fn struct_pattern(fields: &[Field]) -> TokenStream {
let members = fields.iter().map(|field| &field.member);
let placeholders =
(0..fields.len()).map(|i| Ident::new(&format!("__v{}", i), Span::call_site()));
quote!({ #(#members: ref #placeholders),* })
}
+2 -2
View File
@@ -30,7 +30,7 @@ pub fn expand_derive_serialize(
let impl_block = if let Some(remote) = cont.attrs.remote() { let impl_block = if let Some(remote) = cont.attrs.remote() {
let vis = &input.vis; let vis = &input.vis;
let used = pretend::pretend_used(&cont); let used = pretend::pretend_used(&cont, params.is_packed);
quote! { quote! {
impl #impl_generics #ident #ty_generics #where_clause { impl #impl_generics #ident #ty_generics #where_clause {
#vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> #serde::__private::Result<__S::Ok, __S::Error> #vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> #serde::__private::Result<__S::Ok, __S::Error>
@@ -1099,7 +1099,7 @@ fn serialize_struct_visitor(
let mut field_expr = if is_enum { let mut field_expr = if is_enum {
quote!(#member) quote!(#member)
} else { } else {
get_member(params, field, &member) get_member(params, field, member)
}; };
let key_expr = field.attrs.name().serialize_name(); let key_expr = field.attrs.name().serialize_name();
+2 -1
View File
@@ -1,7 +1,8 @@
[package] [package]
name = "serde_derive_internals" name = "serde_derive_internals"
version = "0.25.0" # remember to update html_root_url version = "0.26.0" # 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>"]
rust-version = "1.31"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
description = "AST representation used by Serde derive macros. Unstable." description = "AST representation used by Serde derive macros. Unstable."
homepage = "https://serde.rs" homepage = "https://serde.rs"
+12
View File
@@ -0,0 +1,12 @@
use std::path::Path;
fn main() {
// Sometimes on Windows the git checkout does not correctly wire up the
// 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
// repo.
let mod_behind_symlink = Path::new("src/mod.rs");
if !mod_behind_symlink.exists() {
println!("cargo:rustc-cfg=serde_build_from_git");
}
}
+12 -3
View File
@@ -1,9 +1,13 @@
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.25.0")] #![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.26.0")]
#![allow(unknown_lints, bare_trait_objects)] #![allow(unknown_lints, bare_trait_objects)]
#![deny(clippy::all, clippy::pedantic)]
// Ignored clippy lints // Ignored clippy lints
#![allow( #![allow(
clippy::cognitive_complexity, clippy::cognitive_complexity,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/7575
clippy::collapsible_match,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797
clippy::manual_map,
clippy::missing_panics_doc,
clippy::redundant_field_names, clippy::redundant_field_names,
clippy::result_unit_err, clippy::result_unit_err,
clippy::should_implement_trait, clippy::should_implement_trait,
@@ -17,7 +21,11 @@
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::match_same_arms, clippy::match_same_arms,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6984
clippy::match_wildcard_for_single_variants,
clippy::missing_errors_doc, clippy::missing_errors_doc,
clippy::module_name_repetitions, clippy::module_name_repetitions,
clippy::must_use_candidate, clippy::must_use_candidate,
@@ -34,7 +42,8 @@ extern crate syn;
extern crate proc_macro2; extern crate proc_macro2;
extern crate quote; extern crate quote;
#[path = "src/mod.rs"] #[cfg_attr(serde_build_from_git, path = "../serde_derive/src/internals/mod.rs")]
#[cfg_attr(not(serde_build_from_git), path = "src/mod.rs")]
mod internals; mod internals;
pub use internals::*; pub use internals::*;
+4 -2
View File
@@ -1,7 +1,8 @@
[package] [package]
name = "serde_test" name = "serde_test"
version = "1.0.123" # remember to update html_root_url version = "1.0.134" # 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>"]
rust-version = "1.15"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
description = "Token De/Serializer for testing De/Serialize implementations" description = "Token De/Serializer for testing De/Serialize implementations"
homepage = "https://serde.rs" homepage = "https://serde.rs"
@@ -9,7 +10,8 @@ repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde_test/" documentation = "https://docs.serde.rs/serde_test/"
keywords = ["serde", "serialization"] keywords = ["serde", "serialization"]
readme = "crates-io.md" readme = "crates-io.md"
include = ["src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] include = ["build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
build = "build.rs"
[dependencies] [dependencies]
serde = { version = "1.0.60", path = "../serde" } serde = { version = "1.0.60", path = "../serde" }
+23 -5
View File
@@ -1,6 +1,6 @@
use std::env; use std::env;
use std::process::Command; use std::process::Command;
use std::str; use std::str::{self, FromStr};
// The rustc-cfg strings below are *not* public API. Please let us know by // The rustc-cfg strings below are *not* public API. Please let us know by
// opening a GitHub issue if your build environment requires some way to enable // opening a GitHub issue if your build environment requires some way to enable
@@ -19,12 +19,30 @@ fn main() {
} }
fn rustc_minor_version() -> Option<u32> { fn rustc_minor_version() -> Option<u32> {
let rustc = env::var_os("RUSTC")?; let rustc = match env::var_os("RUSTC") {
let output = Command::new(rustc).arg("--version").output().ok()?; Some(rustc) => rustc,
let version = str::from_utf8(&output.stdout).ok()?; None => return None,
};
let output = match Command::new(rustc).arg("--version").output() {
Ok(output) => output,
Err(_) => return None,
};
let version = match str::from_utf8(&output.stdout) {
Ok(version) => version,
Err(_) => return None,
};
let mut pieces = version.split('.'); let mut pieces = version.split('.');
if pieces.next() != Some("rustc 1") { if pieces.next() != Some("rustc 1") {
return None; return None;
} }
pieces.next()?.parse().ok()
let next = match pieces.next() {
Some(next) => next,
None => return None,
};
u32::from_str(next).ok()
} }
+2 -2
View File
@@ -60,7 +60,7 @@ where
/// ]); /// ]);
/// ``` /// ```
#[cfg_attr(track_caller, track_caller)] #[cfg_attr(track_caller, track_caller)]
pub fn assert_ser_tokens<T>(value: &T, tokens: &[Token]) pub fn assert_ser_tokens<T: ?Sized>(value: &T, tokens: &[Token])
where where
T: Serialize, T: Serialize,
{ {
@@ -113,7 +113,7 @@ where
/// } /// }
/// ``` /// ```
#[cfg_attr(track_caller, track_caller)] #[cfg_attr(track_caller, track_caller)]
pub fn assert_ser_tokens_error<T>(value: &T, tokens: &[Token], error: &str) pub fn assert_ser_tokens_error<T: ?Sized>(value: &T, tokens: &[Token], error: &str)
where where
T: Serialize, T: Serialize,
{ {
+4 -2
View File
@@ -144,17 +144,19 @@
//! # } //! # }
//! ``` //! ```
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.123")] #![doc(html_root_url = "https://docs.rs/serde_test/1.0.134")]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] #![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// 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))]
// Ignored clippy_pedantic lints // Ignored clippy_pedantic lints
#![cfg_attr( #![cfg_attr(
feature = "cargo-clippy", feature = "cargo-clippy",
allow( allow(
cloned_instead_of_copied,
empty_line_after_outer_attr, empty_line_after_outer_attr,
manual_assert,
missing_docs_in_private_items, missing_docs_in_private_items,
missing_panics_doc,
module_name_repetitions, module_name_repetitions,
must_use_candidate, must_use_candidate,
redundant_field_names, redundant_field_names,
+6 -6
View File
@@ -32,18 +32,18 @@ impl<'a> Serializer<'a> {
} }
macro_rules! assert_next_token { macro_rules! assert_next_token {
($ser:expr, $actual:ident) => { ($ser:expr, $actual:ident) => {{
assert_next_token!($ser, stringify!($actual), Token::$actual, true); assert_next_token!($ser, stringify!($actual), Token::$actual, true);
}; }};
($ser:expr, $actual:ident($v:expr)) => { ($ser:expr, $actual:ident($v:expr)) => {{
assert_next_token!( assert_next_token!(
$ser, $ser,
format_args!(concat!(stringify!($actual), "({:?})"), $v), format_args!(concat!(stringify!($actual), "({:?})"), $v),
Token::$actual(v), Token::$actual(v),
v == $v v == $v
); );
}; }};
($ser:expr, $actual:ident { $($k:ident),* }) => { ($ser:expr, $actual:ident { $($k:ident),* }) => {{
let compare = ($($k,)*); let compare = ($($k,)*);
let field_format = || { let field_format = || {
use std::fmt::Write; use std::fmt::Write;
@@ -59,7 +59,7 @@ macro_rules! assert_next_token {
Token::$actual { $($k),* }, Token::$actual { $($k),* },
($($k,)*) == compare ($($k,)*) == compare
); );
}; }};
($ser:expr, $actual:expr, $pat:pat, $guard:expr) => { ($ser:expr, $actual:expr, $pat:pat, $guard:expr) => {
match $ser.next_token() { match $ser.next_token() {
Some($pat) if $guard => {} Some($pat) if $guard => {}
+1 -1
View File
@@ -23,4 +23,4 @@ rustversion = "1.0"
serde = { path = "../serde", features = ["rc", "derive"] } serde = { path = "../serde", features = ["rc", "derive"] }
serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] } serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] }
serde_test = { path = "../serde_test" } serde_test = { path = "../serde_test" }
trybuild = { version = "1.0.19", features = ["diff"] } trybuild = { version = "1.0.49", features = ["diff"] }
+2 -2
View File
@@ -10,7 +10,7 @@ enum DeEnum<B, C, D> {
#[doc(hidden)] #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = { const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)] #[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde; extern crate serde as _serde;
#[automatically_derived] #[automatically_derived]
impl<B, C, D> _serde::Serialize for DeEnum<B, C, D> impl<B, C, D> _serde::Serialize for DeEnum<B, C, D>
@@ -265,7 +265,7 @@ const _: () = {
#[doc(hidden)] #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = { const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)] #[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde; extern crate serde as _serde;
#[automatically_derived] #[automatically_derived]
impl<'de, B, C, D> _serde::Deserialize<'de> for DeEnum<B, C, D> impl<'de, B, C, D> _serde::Deserialize<'de> for DeEnum<B, C, D>
@@ -11,7 +11,7 @@ struct DefaultTyParam<T: AssociatedType<X = i32> = i32> {
#[doc(hidden)] #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = { const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)] #[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde; extern crate serde as _serde;
#[automatically_derived] #[automatically_derived]
impl<T: AssociatedType<X = i32>> _serde::Serialize for DefaultTyParam<T> { impl<T: AssociatedType<X = i32>> _serde::Serialize for DefaultTyParam<T> {
@@ -49,7 +49,7 @@ const _: () = {
#[doc(hidden)] #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = { const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)] #[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde; extern crate serde as _serde;
#[automatically_derived] #[automatically_derived]
impl<'de, T: AssociatedType<X = i32>> _serde::Deserialize<'de> for DefaultTyParam<T> { impl<'de, T: AssociatedType<X = i32>> _serde::Deserialize<'de> for DefaultTyParam<T> {
@@ -8,7 +8,7 @@ pub enum GenericEnum<T, U> {
#[doc(hidden)] #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = { const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)] #[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde; extern crate serde as _serde;
#[automatically_derived] #[automatically_derived]
impl<T, U> _serde::Serialize for GenericEnum<T, U> impl<T, U> _serde::Serialize for GenericEnum<T, U>
@@ -114,7 +114,7 @@ const _: () = {
#[doc(hidden)] #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = { const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)] #[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde; extern crate serde as _serde;
#[automatically_derived] #[automatically_derived]
impl<'de, T, U> _serde::Deserialize<'de> for GenericEnum<T, U> impl<'de, T, U> _serde::Deserialize<'de> for GenericEnum<T, U>
@@ -5,7 +5,7 @@ pub struct GenericStruct<T> {
#[doc(hidden)] #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = { const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)] #[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde; extern crate serde as _serde;
#[automatically_derived] #[automatically_derived]
impl<T> _serde::Serialize for GenericStruct<T> impl<T> _serde::Serialize for GenericStruct<T>
@@ -42,7 +42,7 @@ const _: () = {
#[doc(hidden)] #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = { const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)] #[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde; extern crate serde as _serde;
#[automatically_derived] #[automatically_derived]
impl<'de, T> _serde::Deserialize<'de> for GenericStruct<T> impl<'de, T> _serde::Deserialize<'de> for GenericStruct<T>
@@ -410,7 +410,7 @@ pub struct GenericNewTypeStruct<T>(T);
#[doc(hidden)] #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = { const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)] #[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde; extern crate serde as _serde;
#[automatically_derived] #[automatically_derived]
impl<T> _serde::Serialize for GenericNewTypeStruct<T> impl<T> _serde::Serialize for GenericNewTypeStruct<T>
@@ -435,7 +435,7 @@ const _: () = {
#[doc(hidden)] #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = { const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)] #[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde; extern crate serde as _serde;
#[automatically_derived] #[automatically_derived]
impl<'de, T> _serde::Deserialize<'de> for GenericNewTypeStruct<T> impl<'de, T> _serde::Deserialize<'de> for GenericNewTypeStruct<T>
@@ -3,7 +3,7 @@ pub struct GenericTupleStruct<T, U>(T, U);
#[doc(hidden)] #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = { const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)] #[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde; extern crate serde as _serde;
#[automatically_derived] #[automatically_derived]
impl<'de, T, U> _serde::Deserialize<'de> for GenericTupleStruct<T, U> impl<'de, T, U> _serde::Deserialize<'de> for GenericTupleStruct<T, U>
@@ -8,7 +8,7 @@ enum Lifetimes<'a> {
#[doc(hidden)] #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = { const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)] #[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde; extern crate serde as _serde;
#[automatically_derived] #[automatically_derived]
impl<'a> _serde::Serialize for Lifetimes<'a> { impl<'a> _serde::Serialize for Lifetimes<'a> {
@@ -95,7 +95,7 @@ const _: () = {
#[doc(hidden)] #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = { const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)] #[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde; extern crate serde as _serde;
#[automatically_derived] #[automatically_derived]
impl<'de, 'a> _serde::Deserialize<'de> for Lifetimes<'a> { impl<'de, 'a> _serde::Deserialize<'de> for Lifetimes<'a> {
@@ -7,7 +7,7 @@ struct SerNamedMap<'a, 'b, A: 'a, B: 'b, C> {
#[doc(hidden)] #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = { const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)] #[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde; extern crate serde as _serde;
#[automatically_derived] #[automatically_derived]
impl<'a, 'b, A: 'a, B: 'b, C> _serde::Serialize for SerNamedMap<'a, 'b, A, B, C> impl<'a, 'b, A: 'a, B: 'b, C> _serde::Serialize for SerNamedMap<'a, 'b, A, B, C>
@@ -63,7 +63,7 @@ struct DeNamedMap<A, B, C> {
#[doc(hidden)] #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = { const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)] #[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde; extern crate serde as _serde;
#[automatically_derived] #[automatically_derived]
impl<'de, A, B, C> _serde::Deserialize<'de> for DeNamedMap<A, B, C> impl<'de, A, B, C> _serde::Deserialize<'de> for DeNamedMap<A, B, C>
@@ -3,7 +3,7 @@ struct SerNamedTuple<'a, 'b, A: 'a, B: 'b, C>(&'a A, &'b mut B, C);
#[doc(hidden)] #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = { const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)] #[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde; extern crate serde as _serde;
#[automatically_derived] #[automatically_derived]
impl<'a, 'b, A: 'a, B: 'b, C> _serde::Serialize for SerNamedTuple<'a, 'b, A, B, C> impl<'a, 'b, A: 'a, B: 'b, C> _serde::Serialize for SerNamedTuple<'a, 'b, A, B, C>
@@ -55,7 +55,7 @@ struct DeNamedTuple<A, B, C>(A, B, C);
#[doc(hidden)] #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = { const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)] #[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde; extern crate serde as _serde;
#[automatically_derived] #[automatically_derived]
impl<'de, A, B, C> _serde::Deserialize<'de> for DeNamedTuple<A, B, C> impl<'de, A, B, C> _serde::Deserialize<'de> for DeNamedTuple<A, B, C>
@@ -3,7 +3,7 @@ struct NamedUnit;
#[doc(hidden)] #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = { const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)] #[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde; extern crate serde as _serde;
#[automatically_derived] #[automatically_derived]
impl _serde::Serialize for NamedUnit { impl _serde::Serialize for NamedUnit {
@@ -21,7 +21,7 @@ const _: () = {
#[doc(hidden)] #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = { const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)] #[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde; extern crate serde as _serde;
#[automatically_derived] #[automatically_derived]
impl<'de> _serde::Deserialize<'de> for NamedUnit { impl<'de> _serde::Deserialize<'de> for NamedUnit {
+1 -1
View File
@@ -13,7 +13,7 @@ where
#[doc(hidden)] #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = { const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)] #[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde; extern crate serde as _serde;
#[automatically_derived] #[automatically_derived]
impl<'a, B: 'a, C: 'a, D> _serde::Serialize for SerEnum<'a, B, C, D> impl<'a, B: 'a, C: 'a, D> _serde::Serialize for SerEnum<'a, B, C, D>
+2 -2
View File
@@ -3,7 +3,7 @@ enum Void {}
#[doc(hidden)] #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = { const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)] #[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde; extern crate serde as _serde;
#[automatically_derived] #[automatically_derived]
impl _serde::Serialize for Void { impl _serde::Serialize for Void {
@@ -21,7 +21,7 @@ const _: () = {
#[doc(hidden)] #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = { const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)] #[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde; extern crate serde as _serde;
#[automatically_derived] #[automatically_derived]
impl<'de> _serde::Deserialize<'de> for Void { impl<'de> _serde::Deserialize<'de> for Void {
+50 -66
View File
@@ -1,93 +1,77 @@
use serde_test::Token;
use std::iter;
macro_rules! btreeset { macro_rules! btreeset {
() => { () => {
BTreeSet::new() BTreeSet::new()
}; };
($($value:expr),+) => { ($($value:expr),+) => {{
{ let mut set = BTreeSet::new();
let mut set = BTreeSet::new(); $(set.insert($value);)+
$(set.insert($value);)+ set
set }};
}
}
} }
macro_rules! btreemap { macro_rules! btreemap {
() => { () => {
BTreeMap::new() BTreeMap::new()
}; };
($($key:expr => $value:expr),+) => { ($($key:expr => $value:expr),+) => {{
{ let mut map = BTreeMap::new();
let mut map = BTreeMap::new(); $(map.insert($key, $value);)+
$(map.insert($key, $value);)+ map
map }};
}
}
} }
macro_rules! hashset { macro_rules! hashset {
() => { () => {
HashSet::new() HashSet::new()
}; };
($($value:expr),+) => { ($($value:expr),+) => {{
{ let mut set = HashSet::new();
let mut set = HashSet::new(); $(set.insert($value);)+
$(set.insert($value);)+ set
set }};
} ($hasher:ident @ $($value:expr),+) => {{
}; use std::hash::BuildHasherDefault;
($hasher:ident @ $($value:expr),+) => { let mut set = HashSet::with_hasher(BuildHasherDefault::<$hasher>::default());
{ $(set.insert($value);)+
use std::hash::BuildHasherDefault; set
let mut set = HashSet::with_hasher(BuildHasherDefault::<$hasher>::default()); }};
$(set.insert($value);)+
set
}
}
} }
macro_rules! hashmap { macro_rules! hashmap {
() => { () => {
HashMap::new() HashMap::new()
}; };
($($key:expr => $value:expr),+) => { ($($key:expr => $value:expr),+) => {{
{ let mut map = HashMap::new();
let mut map = HashMap::new(); $(map.insert($key, $value);)+
$(map.insert($key, $value);)+ map
map }};
} ($hasher:ident @ $($key:expr => $value:expr),+) => {{
}; use std::hash::BuildHasherDefault;
($hasher:ident @ $($key:expr => $value:expr),+) => { let mut map = HashMap::with_hasher(BuildHasherDefault::<$hasher>::default());
{ $(map.insert($key, $value);)+
use std::hash::BuildHasherDefault; map
let mut map = HashMap::with_hasher(BuildHasherDefault::<$hasher>::default()); }};
$(map.insert($key, $value);)+ }
map
} pub trait SingleTokenIntoIterator {
fn into_iter(self) -> iter::Once<Token>;
}
impl SingleTokenIntoIterator for Token {
fn into_iter(self) -> iter::Once<Token> {
iter::once(self)
} }
} }
macro_rules! seq_impl {
(seq $first:expr,) => {
seq_impl!(seq $first)
};
($first:expr,) => {
seq_impl!($first)
};
(seq $first:expr) => {
$first.into_iter()
};
($first:expr) => {
Some($first).into_iter()
};
(seq $first:expr , $( $elem: tt)*) => {
$first.into_iter().chain(seq!( $($elem)* ))
};
($first:expr , $($elem: tt)*) => {
Some($first).into_iter().chain(seq!( $($elem)* ))
}
}
macro_rules! seq { macro_rules! seq {
($($tt: tt)*) => { ($($elem:expr),* $(,)?) => {{
seq_impl!($($tt)*).collect::<Vec<_>>() use crate::macros::SingleTokenIntoIterator;
}; let mut vec = Vec::new();
$(<Vec<Token> as Extend<Token>>::extend(&mut vec, $elem.into_iter());)*
vec
}};
} }
+3
View File
@@ -1,6 +1,9 @@
#![allow( #![allow(
clippy::cast_lossless, clippy::cast_lossless,
clippy::from_over_into, clippy::from_over_into,
// Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7422
clippy::nonstandard_macro_braces,
clippy::too_many_lines,
clippy::trivially_copy_pass_by_ref clippy::trivially_copy_pass_by_ref
)] )]
+2
View File
@@ -1,3 +1,5 @@
#![allow(clippy::items_after_statements, clippy::used_underscore_binding)]
use serde::{Deserialize, Deserializer}; use serde::{Deserialize, Deserializer};
use serde_test::{assert_de_tokens, assert_de_tokens_error, Token}; use serde_test::{assert_de_tokens, assert_de_tokens_error, Token};
+1747 -1083
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+69 -3
View File
@@ -3,11 +3,17 @@
// types involved. // types involved.
#![deny(warnings)] #![deny(warnings)]
#![cfg_attr(feature = "unstable", feature(non_ascii_idents))]
#![allow( #![allow(
unknown_lints, unknown_lints,
mixed_script_confusables, mixed_script_confusables,
clippy::items_after_statements,
clippy::missing_errors_doc,
clippy::missing_panics_doc,
clippy::must_use_candidate,
// Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7422
clippy::nonstandard_macro_braces,
clippy::ptr_arg, clippy::ptr_arg,
clippy::too_many_lines,
clippy::trivially_copy_pass_by_ref clippy::trivially_copy_pass_by_ref
)] )]
@@ -267,7 +273,6 @@ fn test_gen() {
} }
assert::<EmptyEnumVariant>(); assert::<EmptyEnumVariant>();
#[cfg(feature = "unstable")]
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
struct NonAsciiIdents { struct NonAsciiIdents {
σ: f64, σ: f64,
@@ -643,7 +648,7 @@ fn test_gen() {
assert::<SkippedVariant<X>>(); assert::<SkippedVariant<X>>();
#[derive(Deserialize)] #[derive(Deserialize)]
struct ImpliciltyBorrowedOption<'a> { struct ImplicitlyBorrowedOption<'a> {
option: std::option::Option<&'a str>, option: std::option::Option<&'a str>,
} }
@@ -823,3 +828,64 @@ where
{ {
vec.first().serialize(serializer) vec.first().serialize(serializer)
} }
//////////////////////////////////////////////////////////////////////////
#[derive(Debug, PartialEq, Deserialize)]
#[serde(tag = "tag")]
enum InternallyTagged {
#[serde(deserialize_with = "deserialize_generic")]
Unit,
#[serde(deserialize_with = "deserialize_generic")]
Newtype(i32),
#[serde(deserialize_with = "deserialize_generic")]
Struct { f1: String, f2: u8 },
}
fn deserialize_generic<'de, T, D>(deserializer: D) -> StdResult<T, D::Error>
where
T: Deserialize<'de>,
D: Deserializer<'de>,
{
T::deserialize(deserializer)
}
//////////////////////////////////////////////////////////////////////////
#[repr(packed)]
pub struct RemotePacked {
pub a: u16,
pub b: u32,
}
#[derive(Serialize)]
#[repr(packed)]
#[serde(remote = "RemotePacked")]
pub struct RemotePackedDef {
a: u16,
b: u32,
}
impl Drop for RemotePackedDef {
fn drop(&mut self) {}
}
#[repr(packed)]
pub struct RemotePackedNonCopy {
pub a: u16,
pub b: String,
}
#[derive(Deserialize)]
#[repr(packed)]
#[serde(remote = "RemotePackedNonCopy")]
pub struct RemotePackedNonCopyDef {
a: u16,
b: String,
}
impl Drop for RemotePackedNonCopyDef {
fn drop(&mut self) {}
}
+50 -2
View File
@@ -1,5 +1,9 @@
#![deny(trivial_numeric_casts)] #![deny(trivial_numeric_casts)]
#![allow(clippy::redundant_field_names)] #![allow(
clippy::enum_variant_names,
clippy::redundant_field_names,
clippy::too_many_lines
)]
mod bytes; mod bytes;
@@ -994,6 +998,28 @@ fn test_internally_tagged_struct_variant_containing_unit_variant() {
Token::StructEnd, Token::StructEnd,
], ],
); );
assert_de_tokens(
&Message::Log { level: Level::Info },
&[
Token::Map { len: Some(2) },
Token::Str("action"),
Token::Str("Log"),
Token::Str("level"),
Token::BorrowedStr("Info"),
Token::MapEnd,
],
);
assert_de_tokens(
&Message::Log { level: Level::Info },
&[
Token::Seq { len: Some(2) },
Token::Str("Log"),
Token::BorrowedStr("Info"),
Token::SeqEnd,
],
);
} }
#[test] #[test]
@@ -1877,9 +1903,31 @@ fn test_internally_tagged_newtype_variant_containing_unit_struct() {
Token::MapEnd, Token::MapEnd,
], ],
); );
assert_de_tokens(
&Message::Info(Info),
&[
Token::Struct {
name: "Message",
len: 1,
},
Token::Str("topic"),
Token::Str("Info"),
Token::StructEnd,
],
);
assert_de_tokens(
&Message::Info(Info),
&[
Token::Seq { len: Some(1) },
Token::Str("Info"),
Token::SeqEnd,
],
);
} }
#[deny(safe_packed_borrows)] #[deny(unaligned_references)]
#[test] #[test]
fn test_packed_struct_can_derive_serialize() { fn test_packed_struct_can_derive_serialize() {
#[derive(Copy, Clone, Serialize)] #[derive(Copy, Clone, Serialize)]
+10 -8
View File
@@ -11,10 +11,12 @@ fn ip_addr_roundtrip() {
assert_tokens( assert_tokens(
&net::IpAddr::from(*b"1234").compact(), &net::IpAddr::from(*b"1234").compact(),
&seq![ &seq![
Token::NewtypeVariant { name: "IpAddr", variant: "V4" }, Token::NewtypeVariant {
name: "IpAddr",
variant: "V4"
},
Token::Tuple { len: 4 }, Token::Tuple { len: 4 },
seq b"1234".iter().map(|&b| Token::U8(b)), b"1234".iter().copied().map(Token::U8),
Token::TupleEnd, Token::TupleEnd,
], ],
); );
@@ -25,14 +27,14 @@ fn socket_addr_roundtrip() {
assert_tokens( assert_tokens(
&net::SocketAddr::from((*b"1234567890123456", 1234)).compact(), &net::SocketAddr::from((*b"1234567890123456", 1234)).compact(),
&seq![ &seq![
Token::NewtypeVariant { name: "SocketAddr", variant: "V6" }, Token::NewtypeVariant {
name: "SocketAddr",
variant: "V6"
},
Token::Tuple { len: 2 }, Token::Tuple { len: 2 },
Token::Tuple { len: 16 }, Token::Tuple { len: 16 },
seq b"1234567890123456".iter().map(|&b| Token::U8(b)), b"1234567890123456".iter().copied().map(Token::U8),
Token::TupleEnd, Token::TupleEnd,
Token::U16(1234), Token::U16(1234),
Token::TupleEnd, Token::TupleEnd,
], ],
+2
View File
@@ -1,3 +1,5 @@
#![allow(clippy::used_underscore_binding)]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[test] #[test]
File diff suppressed because it is too large Load Diff
+2
View File
@@ -1,3 +1,5 @@
#![allow(clippy::type_repetition_in_bounds)]
#[test] #[test]
fn test_gen_custom_serde() { fn test_gen_custom_serde() {
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
+2 -1
View File
@@ -1,3 +1,5 @@
#![allow(clippy::similar_names)]
use serde::de::value::{self, MapAccessDeserializer}; use serde::de::value::{self, MapAccessDeserializer};
use serde::de::{IntoDeserializer, MapAccess, Visitor}; use serde::de::{IntoDeserializer, MapAccess, Visitor};
use serde::{Deserialize, Deserializer}; use serde::{Deserialize, Deserializer};
@@ -17,7 +19,6 @@ fn test_u32_to_enum() {
assert_eq!(E::B, e); assert_eq!(E::B, e);
} }
#[cfg(not(any(target_arch = "asmjs", target_arch = "wasm32")))]
#[test] #[test]
fn test_integer128() { fn test_integer128() {
let de_u128 = IntoDeserializer::<value::Error>::into_deserializer(1u128); let de_u128 = IntoDeserializer::<value::Error>::into_deserializer(1u128);
@@ -1,5 +1,5 @@
error: failed to parse borrowed lifetimes: "zzz" error: failed to parse borrowed lifetimes: "zzz"
--> $DIR/bad_lifetimes.rs:5:22 --> tests/ui/borrow/bad_lifetimes.rs:5:22
| |
5 | #[serde(borrow = "zzz")] 5 | #[serde(borrow = "zzz")]
| ^^^^^ | ^^^^^
@@ -1,5 +1,5 @@
error: duplicate borrowed lifetime `'a` error: duplicate borrowed lifetime `'a`
--> $DIR/duplicate_lifetime.rs:5:22 --> tests/ui/borrow/duplicate_lifetime.rs:5:22
| |
5 | #[serde(borrow = "'a + 'a")] 5 | #[serde(borrow = "'a + 'a")]
| ^^^^^^^^^ | ^^^^^^^^^
@@ -1,5 +1,5 @@
error: duplicate serde attribute `borrow` error: duplicate serde attribute `borrow`
--> $DIR/duplicate_variant.rs:8:13 --> tests/ui/borrow/duplicate_variant.rs:8:13
| |
8 | #[serde(borrow)] 8 | #[serde(borrow)]
| ^^^^^^ | ^^^^^^
@@ -1,5 +1,5 @@
error: at least one lifetime must be borrowed error: at least one lifetime must be borrowed
--> $DIR/empty_lifetimes.rs:5:22 --> tests/ui/borrow/empty_lifetimes.rs:5:22
| |
5 | #[serde(borrow = "")] 5 | #[serde(borrow = "")]
| ^^ | ^^
@@ -1,5 +1,5 @@
error: field `s` has no lifetimes to borrow error: field `s` has no lifetimes to borrow
--> $DIR/no_lifetimes.rs:5:5 --> tests/ui/borrow/no_lifetimes.rs:5:5
| |
5 | / #[serde(borrow)] 5 | / #[serde(borrow)]
6 | | s: String, 6 | | s: String,
@@ -1,5 +1,5 @@
error: #[serde(borrow)] may only be used on newtype variants error: #[serde(borrow)] may only be used on newtype variants
--> $DIR/struct_variant.rs:8:5 --> tests/ui/borrow/struct_variant.rs:8:5
| |
8 | / #[serde(borrow)] 8 | / #[serde(borrow)]
9 | | S { s: Str<'a> }, 9 | | S { s: Str<'a> },
@@ -1,5 +1,5 @@
error: field `s` does not have lifetime 'b error: field `s` does not have lifetime 'b
--> $DIR/wrong_lifetime.rs:5:5 --> tests/ui/borrow/wrong_lifetime.rs:5:5
| |
5 | / #[serde(borrow = "'b")] 5 | / #[serde(borrow = "'b")]
6 | | s: &'a str, 6 | | s: &'a str,
@@ -1,5 +1,5 @@
error: enum tags `conflict` for type and content conflict with each other error: enum tags `conflict` for type and content conflict with each other
--> $DIR/adjacent-tag.rs:4:1 --> tests/ui/conflict/adjacent-tag.rs:4:1
| |
4 | / #[serde(tag = "conflict", content = "conflict")] 4 | / #[serde(tag = "conflict", content = "conflict")]
5 | | enum E { 5 | | enum E {
@@ -1,5 +1,5 @@
error: #[serde(flatten)] cannot be used on newtype structs error: #[serde(flatten)] cannot be used on newtype structs
--> $DIR/flatten-newtype-struct.rs:6:12 --> tests/ui/conflict/flatten-newtype-struct.rs:6:12
| |
6 | struct Foo(#[serde(flatten)] HashMap<String, String>); 6 | struct Foo(#[serde(flatten)] HashMap<String, String>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1,5 +1,5 @@
error: #[serde(flatten)] cannot be used on tuple structs error: #[serde(flatten)] cannot be used on tuple structs
--> $DIR/flatten-tuple-struct.rs:6:17 --> tests/ui/conflict/flatten-tuple-struct.rs:6:17
| |
6 | struct Foo(u32, #[serde(flatten)] HashMap<String, String>); 6 | struct Foo(u32, #[serde(flatten)] HashMap<String, String>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1,5 +1,5 @@
error: #[serde(from = "...")] and #[serde(try_from = "...")] conflict with each other error: #[serde(from = "...")] and #[serde(try_from = "...")] conflict with each other
--> $DIR/from-try-from.rs:4:1 --> tests/ui/conflict/from-try-from.rs:4:1
| |
4 | / #[serde(from = "u64", try_from = "u64")] 4 | / #[serde(from = "u64", try_from = "u64")]
5 | | struct S { 5 | | struct S {
@@ -1,5 +1,5 @@
error: variant field name `conflict` conflicts with internal tag error: variant field name `conflict` conflicts with internal tag
--> $DIR/internal-tag-alias.rs:4:1 --> tests/ui/conflict/internal-tag-alias.rs:4:1
| |
4 | / #[serde(tag = "conflict")] 4 | / #[serde(tag = "conflict")]
5 | | enum E { 5 | | enum E {
@@ -1,5 +1,5 @@
error: variant field name `conflict` conflicts with internal tag error: variant field name `conflict` conflicts with internal tag
--> $DIR/internal-tag.rs:4:1 --> tests/ui/conflict/internal-tag.rs:4:1
| |
4 | / #[serde(tag = "conflict")] 4 | / #[serde(tag = "conflict")]
5 | | enum E { 5 | | enum E {
@@ -1,5 +1,5 @@
error: #[serde(default)] can only be used on structs with named fields error: #[serde(default)] can only be used on structs with named fields
--> $DIR/enum.rs:5:1 --> tests/ui/default-attribute/enum.rs:5:1
| |
5 | enum E { 5 | enum E {
| ^^^^ | ^^^^
@@ -1,5 +1,5 @@
error: #[serde(default = "...")] can only be used on structs with named fields error: #[serde(default = "...")] can only be used on structs with named fields
--> $DIR/enum_path.rs:5:1 --> tests/ui/default-attribute/enum_path.rs:5:1
| |
5 | enum E { 5 | enum E {
| ^^^^ | ^^^^
@@ -1,5 +1,5 @@
error: #[serde(default)] can only be used on structs with named fields error: #[serde(default)] can only be used on structs with named fields
--> $DIR/nameless_struct_fields.rs:5:9 --> tests/ui/default-attribute/nameless_struct_fields.rs:5:9
| |
5 | struct T(u8, u8); 5 | struct T(u8, u8);
| ^^^^^^^^ | ^^^^^^^^
@@ -1,5 +1,5 @@
error: #[serde(default = "...")] can only be used on structs with named fields error: #[serde(default = "...")] can only be used on structs with named fields
--> $DIR/nameless_struct_fields_path.rs:5:9 --> tests/ui/default-attribute/nameless_struct_fields_path.rs:5:9
| |
5 | struct T(u8, u8); 5 | struct T(u8, u8);
| ^^^^^^^^ | ^^^^^^^^
@@ -1,5 +1,5 @@
error: unknown serde field attribute `serialize` error: unknown serde field attribute `serialize`
--> $DIR/rename-and-ser.rs:5:27 --> tests/ui/duplicate-attribute/rename-and-ser.rs:5:27
| |
5 | #[serde(rename = "x", serialize = "y")] 5 | #[serde(rename = "x", serialize = "y")]
| ^^^^^^^^^ | ^^^^^^^^^
@@ -1,5 +1,5 @@
error: duplicate serde attribute `rename` error: duplicate serde attribute `rename`
--> $DIR/rename-ser-rename-ser.rs:5:38 --> tests/ui/duplicate-attribute/rename-ser-rename-ser.rs:5:38
| |
5 | #[serde(rename(serialize = "x"), rename(serialize = "y"))] 5 | #[serde(rename(serialize = "x"), rename(serialize = "y"))]
| ^^^^^^ | ^^^^^^
@@ -1,5 +1,5 @@
error: duplicate serde attribute `rename` error: duplicate serde attribute `rename`
--> $DIR/rename-ser-rename.rs:6:13 --> tests/ui/duplicate-attribute/rename-ser-rename.rs:6:13
| |
6 | #[serde(rename = "y")] 6 | #[serde(rename = "y")]
| ^^^^^^ | ^^^^^^
@@ -1,5 +1,5 @@
error: duplicate serde attribute `rename` error: duplicate serde attribute `rename`
--> $DIR/rename-ser-ser.rs:5:37 --> tests/ui/duplicate-attribute/rename-ser-ser.rs:5:37
| |
5 | #[serde(rename(serialize = "x", serialize = "y"))] 5 | #[serde(rename(serialize = "x", serialize = "y"))]
| ^^^^^^^^^ | ^^^^^^^^^
@@ -1,5 +1,5 @@
error: duplicate serde attribute `rename` error: duplicate serde attribute `rename`
--> $DIR/two-rename-ser.rs:6:13 --> tests/ui/duplicate-attribute/two-rename-ser.rs:6:13
| |
6 | #[serde(rename(serialize = "y"))] 6 | #[serde(rename(serialize = "y"))]
| ^^^^^^ | ^^^^^^
@@ -1,5 +1,5 @@
error: duplicate serde attribute `serialize_with` error: duplicate serde attribute `serialize_with`
--> $DIR/with-and-serialize-with.rs:5:25 --> tests/ui/duplicate-attribute/with-and-serialize-with.rs:5:25
| |
5 | #[serde(with = "w", serialize_with = "s")] 5 | #[serde(with = "w", serialize_with = "s")]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
@@ -1,5 +1,5 @@
error: #[serde(tag = "...", content = "...")] must be used together error: #[serde(tag = "...", content = "...")] must be used together
--> $DIR/content-no-tag.rs:4:9 --> tests/ui/enum-representation/content-no-tag.rs:4:9
| |
4 | #[serde(content = "c")] 4 | #[serde(content = "c")]
| ^^^^^^^ | ^^^^^^^
@@ -1,5 +1,5 @@
error: #[serde(tag = "...")] cannot be used with tuple variants error: #[serde(tag = "...")] cannot be used with tuple variants
--> $DIR/internal-tuple-variant.rs:6:5 --> tests/ui/enum-representation/internal-tuple-variant.rs:6:5
| |
6 | Tuple(u8, u8), 6 | Tuple(u8, u8),
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
@@ -1,17 +1,17 @@
error: untagged enum cannot have #[serde(tag = "...", content = "...")] error: untagged enum cannot have #[serde(tag = "...", content = "...")]
--> $DIR/untagged-and-adjacent.rs:4:9 --> tests/ui/enum-representation/untagged-and-adjacent.rs:4:9
| |
4 | #[serde(untagged)] 4 | #[serde(untagged)]
| ^^^^^^^^ | ^^^^^^^^
error: untagged enum cannot have #[serde(tag = "...", content = "...")] error: untagged enum cannot have #[serde(tag = "...", content = "...")]
--> $DIR/untagged-and-adjacent.rs:5:9 --> tests/ui/enum-representation/untagged-and-adjacent.rs:5:9
| |
5 | #[serde(tag = "t", content = "c")] 5 | #[serde(tag = "t", content = "c")]
| ^^^ | ^^^
error: untagged enum cannot have #[serde(tag = "...", content = "...")] error: untagged enum cannot have #[serde(tag = "...", content = "...")]
--> $DIR/untagged-and-adjacent.rs:5:20 --> tests/ui/enum-representation/untagged-and-adjacent.rs:5:20
| |
5 | #[serde(tag = "t", content = "c")] 5 | #[serde(tag = "t", content = "c")]
| ^^^^^^^ | ^^^^^^^
@@ -1,11 +1,11 @@
error: untagged enum cannot have #[serde(content = "...")] error: untagged enum cannot have #[serde(content = "...")]
--> $DIR/untagged-and-content.rs:4:9 --> tests/ui/enum-representation/untagged-and-content.rs:4:9
| |
4 | #[serde(untagged)] 4 | #[serde(untagged)]
| ^^^^^^^^ | ^^^^^^^^
error: untagged enum cannot have #[serde(content = "...")] error: untagged enum cannot have #[serde(content = "...")]
--> $DIR/untagged-and-content.rs:5:9 --> tests/ui/enum-representation/untagged-and-content.rs:5:9
| |
5 | #[serde(content = "c")] 5 | #[serde(content = "c")]
| ^^^^^^^ | ^^^^^^^
@@ -1,11 +1,11 @@
error: enum cannot be both untagged and internally tagged error: enum cannot be both untagged and internally tagged
--> $DIR/untagged-and-internal.rs:4:9 --> tests/ui/enum-representation/untagged-and-internal.rs:4:9
| |
4 | #[serde(untagged)] 4 | #[serde(untagged)]
| ^^^^^^^^ | ^^^^^^^^
error: enum cannot be both untagged and internally tagged error: enum cannot be both untagged and internally tagged
--> $DIR/untagged-and-internal.rs:5:9 --> tests/ui/enum-representation/untagged-and-internal.rs:5:9
| |
5 | #[serde(tag = "type")] 5 | #[serde(tag = "type")]
| ^^^ | ^^^
@@ -1,5 +1,5 @@
error: #[serde(untagged)] can only be used on enums error: #[serde(untagged)] can only be used on enums
--> $DIR/untagged-struct.rs:5:1 --> tests/ui/enum-representation/untagged-struct.rs:5:1
| |
5 | struct S; 5 | struct S;
| ^^^^^^ | ^^^^^^
@@ -1,5 +1,5 @@
error: expected serde rename attribute to be a string: `rename = "..."` error: expected serde rename attribute to be a string: `rename = "..."`
--> $DIR/boolean.rs:5:22 --> tests/ui/expected-string/boolean.rs:5:22
| |
5 | #[serde(rename = true)] 5 | #[serde(rename = true)]
| ^^^^ | ^^^^
@@ -1,5 +1,5 @@
error: expected serde rename attribute to be a string: `rename = "..."` error: expected serde rename attribute to be a string: `rename = "..."`
--> $DIR/byte_character.rs:5:22 --> tests/ui/expected-string/byte_character.rs:5:22
| |
5 | #[serde(rename = b'a')] 5 | #[serde(rename = b'a')]
| ^^^^ | ^^^^
@@ -1,5 +1,5 @@
error: expected serde rename attribute to be a string: `rename = "..."` error: expected serde rename attribute to be a string: `rename = "..."`
--> $DIR/byte_string.rs:5:22 --> tests/ui/expected-string/byte_string.rs:5:22
| |
5 | #[serde(rename = b"byte string")] 5 | #[serde(rename = b"byte string")]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
@@ -1,5 +1,5 @@
error: expected serde rename attribute to be a string: `rename = "..."` error: expected serde rename attribute to be a string: `rename = "..."`
--> $DIR/character.rs:5:22 --> tests/ui/expected-string/character.rs:5:22
| |
5 | #[serde(rename = 'a')] 5 | #[serde(rename = 'a')]
| ^^^ | ^^^
@@ -1,5 +1,5 @@
error: expected serde rename attribute to be a string: `rename = "..."` error: expected serde rename attribute to be a string: `rename = "..."`
--> $DIR/float.rs:5:22 --> tests/ui/expected-string/float.rs:5:22
| |
5 | #[serde(rename = 3.14)] 5 | #[serde(rename = 3.14)]
| ^^^^ | ^^^^
@@ -1,5 +1,5 @@
error: expected serde rename attribute to be a string: `rename = "..."` error: expected serde rename attribute to be a string: `rename = "..."`
--> $DIR/integer.rs:5:22 --> tests/ui/expected-string/integer.rs:5:22
| |
5 | #[serde(rename = 100)] 5 | #[serde(rename = 100)]
| ^^^ | ^^^
+2 -2
View File
@@ -1,11 +1,11 @@
error: #[serde(field_identifier)] and #[serde(variant_identifier)] cannot both be set error: #[serde(field_identifier)] and #[serde(variant_identifier)] cannot both be set
--> $DIR/both.rs:4:9 --> tests/ui/identifier/both.rs:4:9
| |
4 | #[serde(field_identifier, variant_identifier)] 4 | #[serde(field_identifier, variant_identifier)]
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
error: #[serde(field_identifier)] and #[serde(variant_identifier)] cannot both be set error: #[serde(field_identifier)] and #[serde(variant_identifier)] cannot both be set
--> $DIR/both.rs:4:27 --> tests/ui/identifier/both.rs:4:27
| |
4 | #[serde(field_identifier, variant_identifier)] 4 | #[serde(field_identifier, variant_identifier)]
| ^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^
@@ -1,5 +1,5 @@
error: #[serde(field_identifier)] can only be used on an enum error: #[serde(field_identifier)] can only be used on an enum
--> $DIR/field_struct.rs:5:1 --> tests/ui/identifier/field_struct.rs:5:1
| |
5 | struct S; 5 | struct S;
| ^^^^^^ | ^^^^^^
@@ -1,5 +1,5 @@
error: #[serde(field_identifier)] may only contain unit variants error: #[serde(field_identifier)] may only contain unit variants
--> $DIR/field_tuple.rs:7:5 --> tests/ui/identifier/field_tuple.rs:7:5
| |
7 | B(u8, u8), 7 | B(u8, u8),
| ^^^^^^^^^ | ^^^^^^^^^
@@ -1,5 +1,5 @@
error: `Other` must be the last variant error: `Other` must be the last variant
--> $DIR/newtype_not_last.rs:7:5 --> tests/ui/identifier/newtype_not_last.rs:7:5
| |
7 | Other(String), 7 | Other(String),
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
@@ -1,5 +1,5 @@
error: #[serde(other)] must be on a unit variant error: #[serde(other)] must be on a unit variant
--> $DIR/not_unit.rs:7:5 --> tests/ui/identifier/not_unit.rs:7:5
| |
7 | / #[serde(other)] 7 | / #[serde(other)]
8 | | Other(u8, u8), 8 | | Other(u8, u8),
@@ -1,5 +1,5 @@
error: #[serde(other)] must be on the last variant error: #[serde(other)] must be on the last variant
--> $DIR/other_not_last.rs:7:5 --> tests/ui/identifier/other_not_last.rs:7:5
| |
7 | / #[serde(other)] 7 | / #[serde(other)]
8 | | Other, 8 | | Other,
@@ -1,5 +1,5 @@
error: #[serde(other)] cannot appear on untagged enum error: #[serde(other)] cannot appear on untagged enum
--> $DIR/other_untagged.rs:6:5 --> tests/ui/identifier/other_untagged.rs:6:5
| |
6 | / #[serde(other)] 6 | / #[serde(other)]
7 | | Other, 7 | | Other,
@@ -1,5 +1,5 @@
error: #[serde(other)] may not be used on a variant identifier error: #[serde(other)] may not be used on a variant identifier
--> $DIR/other_variant.rs:6:5 --> tests/ui/identifier/other_variant.rs:6:5
| |
6 | / #[serde(other)] 6 | / #[serde(other)]
7 | | Other, 7 | | Other,
@@ -1,5 +1,5 @@
error: #[serde(variant_identifier)] can only be used on an enum error: #[serde(variant_identifier)] can only be used on an enum
--> $DIR/variant_struct.rs:5:1 --> tests/ui/identifier/variant_struct.rs:5:1
| |
5 | struct S; 5 | struct S;
| ^^^^^^ | ^^^^^^
@@ -1,5 +1,5 @@
error: #[serde(variant_identifier)] may only contain unit variants error: #[serde(variant_identifier)] may only contain unit variants
--> $DIR/variant_tuple.rs:7:5 --> tests/ui/identifier/variant_tuple.rs:7:5
| |
7 | B(u8, u8), 7 | B(u8, u8),
| ^^^^^^^^^ | ^^^^^^^^^

Some files were not shown because too many files have changed in this diff Show More