From 84d1c5385ddefb1bb89feff596f5810d9293168b Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 7 Aug 2023 02:53:24 +0500 Subject: [PATCH 001/258] Use correct tokens in test to represent an enum variant Unit variant of externally tagged enum cannot be deserialized from the string token by itself. It is ContentDeserializer + serde_test::Deserializer that makes this possible, because serde_test::Deserializer produces Content::Str() from Token::BorrowedStr() and ContentDeserializer produces unit variant from Content::Str(). The following tokens all produces Content::String(variant): - Token::String(variant) - Token::Str(variant) - Token::UnitVariant { variant, .. } Token::BorrowedStr(variant) produces Content::Str(variant) that was the real purpose to use it in test in #933. This actually makes this test testing `Content` rather than type itself. Correct way to represent enum one of: - [xxxVariant { .. }] - [Enum { .. }, xxxVariant { variant, .. }] - [Enum { .. }, String(variant), ] - [Enum { .. }, Str(variant), ] - [Enum { .. }, BorrowedStr(variant), ] --- serde/src/private/de.rs | 7 +++++++ test_suite/tests/test_macros.rs | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index 883e6909c..c402d2c66 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -313,6 +313,8 @@ mod content { } } + /// Used to capture data in [`Content`] from other deserializers. + /// Cannot capture externally tagged enums, `i128` and `u128`. struct ContentVisitor<'de> { value: PhantomData>, } @@ -528,6 +530,8 @@ mod content { Content(Content<'de>), } + /// Serves as a seed for deserializing a key of internally tagged enum. + /// Cannot capture externally tagged enums, `i128` and `u128`. struct TagOrContentVisitor<'de> { name: &'static str, value: PhantomData>, @@ -814,6 +818,9 @@ mod content { /// Used by generated code to deserialize an internally tagged enum. /// + /// Captures map or sequence from the original deserializer and searches + /// a tag in it (in case of sequence, tag is the first element of sequence). + /// /// Not public API. pub struct TaggedContentVisitor { tag_name: &'static str, diff --git a/test_suite/tests/test_macros.rs b/test_suite/tests/test_macros.rs index 2b7d189fd..b9e543015 100644 --- a/test_suite/tests/test_macros.rs +++ b/test_suite/tests/test_macros.rs @@ -997,7 +997,9 @@ fn test_internally_tagged_struct_variant_containing_unit_variant() { Token::Str("action"), Token::Str("Log"), Token::Str("level"), + Token::Enum { name: "Level" }, Token::BorrowedStr("Info"), + Token::Unit, Token::StructEnd, ], ); @@ -1009,7 +1011,9 @@ fn test_internally_tagged_struct_variant_containing_unit_variant() { Token::Str("action"), Token::Str("Log"), Token::Str("level"), + Token::Enum { name: "Level" }, Token::BorrowedStr("Info"), + Token::Unit, Token::MapEnd, ], ); @@ -1019,7 +1023,9 @@ fn test_internally_tagged_struct_variant_containing_unit_variant() { &[ Token::Seq { len: Some(2) }, Token::Str("Log"), + Token::Enum { name: "Level" }, Token::BorrowedStr("Info"), + Token::Unit, Token::SeqEnd, ], ); From 6a097eca9334577001cdde8f5b4ec4d054fddd27 Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 7 Aug 2023 20:33:12 +0500 Subject: [PATCH 002/258] Add canary test to ensure that we use adequate enum representation --- test_suite/tests/test_macros.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test_suite/tests/test_macros.rs b/test_suite/tests/test_macros.rs index b9e543015..0aee66946 100644 --- a/test_suite/tests/test_macros.rs +++ b/test_suite/tests/test_macros.rs @@ -987,6 +987,18 @@ fn test_internally_tagged_struct_variant_containing_unit_variant() { Log { level: Level }, } + // Canary test that ensures that we use adequate enum representation that + // is possible to deserialize regardless of possible buffering in internally + // tagged enum implementation + assert_de_tokens( + &Level::Info, + &[ + Token::Enum { name: "Level" }, + Token::BorrowedStr("Info"), + Token::Unit, + ], + ); + assert_de_tokens( &Message::Log { level: Level::Info }, &[ From 5d1403461c5da80e2e0f0ed59e920e74d9ee2262 Mon Sep 17 00:00:00 2001 From: "Adam H. Leventhal" Date: Wed, 6 Sep 2023 15:31:16 -0700 Subject: [PATCH 003/258] add failing test --- test_suite/tests/test_annotations.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test_suite/tests/test_annotations.rs b/test_suite/tests/test_annotations.rs index fa314cbca..f4801002f 100644 --- a/test_suite/tests/test_annotations.rs +++ b/test_suite/tests/test_annotations.rs @@ -2380,6 +2380,30 @@ fn test_partially_untagged_enum_desugared() { ); } +#[test] +fn test_partially_untagged_simple_enum() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[serde(tag = "tag")] + enum Data { + A, + #[serde(untagged)] + Var(u32), + } + + let data = Data::A; + assert_tokens( + &data, + &[ + Token::Map { len: None }, + Token::Str("t"), + Token::Str("A"), + Token::Str("b"), + Token::I32(0), + Token::MapEnd, + ], + ); +} + #[test] fn test_flatten_option() { #[derive(Serialize, Deserialize, PartialEq, Debug)] From 09993a904a7d2346955899feaa8b43668a3fb667 Mon Sep 17 00:00:00 2001 From: "Adam H. Leventhal" Date: Wed, 6 Sep 2023 15:25:05 -0700 Subject: [PATCH 004/258] Fix for "cannot infer type" from Deserialize derive macro with simple variants and untagged variants --- serde_derive/src/de.rs | 10 +++++++++- test_suite/tests/test_annotations.rs | 5 +++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index ee8a23766..4c39b7ca1 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -1737,7 +1737,6 @@ fn deserialize_untagged_enum_after( quote!(__deserializer), )) }); - let attempts = first_attempt.into_iter().chain(attempts); // TODO this message could be better by saving the errors from the failed // attempts. The heuristic used by TOML was to count the number of fields // processed before an error, and use the error that happened after the @@ -1750,10 +1749,19 @@ fn deserialize_untagged_enum_after( ); let fallthrough_msg = cattrs.expecting().unwrap_or(&fallthrough_msg); + // This may be infallible so we need to provide the error type. + let first_attempt = first_attempt.map(|expr| { + quote! { + if let _serde::__private::Result::<_, __D::Error>::Ok(__ok) = #expr { + return _serde::__private::Ok(__ok); + } + } + }); quote_block! { let __content = <_serde::__private::de::Content as _serde::Deserialize>::deserialize(__deserializer)?; let __deserializer = _serde::__private::de::ContentRefDeserializer::<__D::Error>::new(&__content); + #first_attempt #( if let _serde::__private::Ok(__ok) = #attempts { return _serde::__private::Ok(__ok); diff --git a/test_suite/tests/test_annotations.rs b/test_suite/tests/test_annotations.rs index f4801002f..eeb3ec0d4 100644 --- a/test_suite/tests/test_annotations.rs +++ b/test_suite/tests/test_annotations.rs @@ -2383,7 +2383,7 @@ fn test_partially_untagged_enum_desugared() { #[test] fn test_partially_untagged_simple_enum() { #[derive(Serialize, Deserialize, PartialEq, Debug)] - #[serde(tag = "tag")] + #[serde(tag = "t")] enum Data { A, #[serde(untagged)] @@ -2391,7 +2391,8 @@ fn test_partially_untagged_simple_enum() { } let data = Data::A; - assert_tokens( + + assert_de_tokens( &data, &[ Token::Map { len: None }, From 8da2058e2a18f7a986c758129c4c199ad4353ad3 Mon Sep 17 00:00:00 2001 From: "Adam H. Leventhal" Date: Thu, 7 Sep 2023 17:19:27 -0700 Subject: [PATCH 005/258] fix deserialization of untagged variants within internally or adjacently tagged enums --- serde_derive/src/de.rs | 8 ++++-- test_suite/tests/test_annotations.rs | 40 +++++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index 4c39b7ca1..c6b2cfff2 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -1749,10 +1749,14 @@ fn deserialize_untagged_enum_after( ); let fallthrough_msg = cattrs.expecting().unwrap_or(&fallthrough_msg); - // This may be infallible so we need to provide the error type. + // Ignore any error associated with non-untagged deserialization so that we + // can fall through to the untagged variants. This may be infallible so we + // need to provide the error type. let first_attempt = first_attempt.map(|expr| { quote! { - if let _serde::__private::Result::<_, __D::Error>::Ok(__ok) = #expr { + if let _serde::__private::Result::<_, __D::Error>::Ok(__ok) = (|| { + #expr + })() { return _serde::__private::Ok(__ok); } } diff --git a/test_suite/tests/test_annotations.rs b/test_suite/tests/test_annotations.rs index eeb3ec0d4..9c4eabbb9 100644 --- a/test_suite/tests/test_annotations.rs +++ b/test_suite/tests/test_annotations.rs @@ -2381,11 +2381,12 @@ fn test_partially_untagged_enum_desugared() { } #[test] -fn test_partially_untagged_simple_enum() { +fn test_partially_untagged_tagged_enum() { #[derive(Serialize, Deserialize, PartialEq, Debug)] #[serde(tag = "t")] enum Data { A, + B, #[serde(untagged)] Var(u32), } @@ -2398,11 +2399,44 @@ fn test_partially_untagged_simple_enum() { Token::Map { len: None }, Token::Str("t"), Token::Str("A"), - Token::Str("b"), - Token::I32(0), Token::MapEnd, ], ); + + let data = Data::Var(42); + + assert_de_tokens(&data, &[Token::U32(42)]); + + // TODO test error output + + #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[serde(tag = "t", content = "c")] + enum Data2 { + A(u32), + B, + #[serde(untagged)] + Var(u32), + } + + let data = Data2::A(7); + + assert_de_tokens( + &data, + &[ + Token::Map { len: None }, + Token::Str("t"), + Token::Str("A"), + Token::Str("c"), + Token::U32(7), + Token::MapEnd, + ], + ); + + let data = Data2::Var(42); + + assert_de_tokens(&data, &[Token::U32(42)]); + + // TODO test error output } #[test] From 94fbc3d38838398a8971cb4e4d617b8d42685b0c Mon Sep 17 00:00:00 2001 From: "Adam H. Leventhal" Date: Thu, 7 Sep 2023 22:17:22 -0700 Subject: [PATCH 006/258] fix clippy --- test_suite/tests/test_annotations.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/test_suite/tests/test_annotations.rs b/test_suite/tests/test_annotations.rs index 9c4eabbb9..90e0a153a 100644 --- a/test_suite/tests/test_annotations.rs +++ b/test_suite/tests/test_annotations.rs @@ -2381,7 +2381,7 @@ fn test_partially_untagged_enum_desugared() { } #[test] -fn test_partially_untagged_tagged_enum() { +fn test_partially_untagged_internally_tagged_enum() { #[derive(Serialize, Deserialize, PartialEq, Debug)] #[serde(tag = "t")] enum Data { @@ -2408,17 +2408,20 @@ fn test_partially_untagged_tagged_enum() { assert_de_tokens(&data, &[Token::U32(42)]); // TODO test error output +} +#[test] +fn test_partially_untagged_adjacently_tagged_enum() { #[derive(Serialize, Deserialize, PartialEq, Debug)] #[serde(tag = "t", content = "c")] - enum Data2 { + enum Data { A(u32), B, #[serde(untagged)] Var(u32), } - let data = Data2::A(7); + let data = Data::A(7); assert_de_tokens( &data, @@ -2432,7 +2435,7 @@ fn test_partially_untagged_tagged_enum() { ], ); - let data = Data2::Var(42); + let data = Data::Var(42); assert_de_tokens(&data, &[Token::U32(42)]); From 1af23f1f2d51ce2bb80f9d54c7ccb68ee0c672a0 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 24 Sep 2023 10:53:44 -0700 Subject: [PATCH 007/258] Test docs.rs documentation build in CI --- .github/workflows/ci.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e924dfa4c..dd49909b2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -118,6 +118,20 @@ jobs: - run: cargo generate-lockfile -Z minimal-versions - run: cargo check --locked --workspace + doc: + name: Documentation + runs-on: ubuntu-latest + timeout-minutes: 45 + env: + RUSTDOCFLAGS: -Dwarnings + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + - uses: dtolnay/install@cargo-docs-rs + - run: cargo docs-rs -p serde + - run: cargo docs-rs -p serde_derive + - run: cargo docs-rs -p serde_derive_internals + clippy: name: Clippy runs-on: ubuntu-latest From 1774794b191c7e14b178aee8a18dcfd34dd002a8 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 26 Sep 2023 19:05:12 -0700 Subject: [PATCH 008/258] Resolve needless_raw_string_hashes clippy lint in test warning: unnecessary hashes around raw string literal --> test_suite/tests/test_annotations.rs:2722:9 | 2722 | r#"invalid type: unit value, expected variant identifier"#, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string_hashes = note: `-W clippy::needless-raw-string-hashes` implied by `-W clippy::all` = help: to override `-W clippy::all` add `#[allow(clippy::needless_raw_string_hashes)]` help: remove all the hashes around the literal | 2722 - r#"invalid type: unit value, expected variant identifier"#, 2722 + r"invalid type: unit value, expected variant identifier", | warning: unnecessary hashes around raw string literal --> test_suite/tests/test_annotations.rs:2743:9 | 2743 | r#"invalid type: unit value, expected variant identifier"#, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string_hashes help: remove all the hashes around the literal | 2743 - r#"invalid type: unit value, expected variant identifier"#, 2743 + r"invalid type: unit value, expected variant identifier", | warning: unnecessary hashes around raw string literal --> test_suite/tests/test_annotations.rs:2769:9 | 2769 | r#"invalid type: unit value, expected variant of enum Enum"#, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string_hashes help: remove all the hashes around the literal | 2769 - r#"invalid type: unit value, expected variant of enum Enum"#, 2769 + r"invalid type: unit value, expected variant of enum Enum", | warning: unnecessary hashes around raw string literal --> test_suite/tests/test_annotations.rs:2782:63 | 2782 | assert_de_tokens_error::(&[Token::Str("Untagged")], r#"something strange..."#); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string_hashes help: remove all the hashes around the literal | 2782 - assert_de_tokens_error::(&[Token::Str("Untagged")], r#"something strange..."#); 2782 + assert_de_tokens_error::(&[Token::Str("Untagged")], r"something strange..."); | warning: unnecessary hashes around raw string literal --> test_suite/tests/test_annotations.rs:2803:9 | 2803 | r#"invalid type: unit value, expected something strange..."#, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string_hashes help: remove all the hashes around the literal | 2803 - r#"invalid type: unit value, expected something strange..."#, 2803 + r"invalid type: unit value, expected something strange...", | warning: unnecessary hashes around raw string literal --> test_suite/tests/test_annotations.rs:2812:9 | 2812 | r#"invalid type: map, expected something strange..."#, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string_hashes help: remove all the hashes around the literal | 2812 - r#"invalid type: map, expected something strange..."#, 2812 + r"invalid type: map, expected something strange...", | warning: unnecessary hashes around raw string literal --> test_suite/tests/test_annotations.rs:2817:9 | 2817 | r#"invalid type: unit value, expected something strange..."#, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string_hashes help: remove all the hashes around the literal | 2817 - r#"invalid type: unit value, expected something strange..."#, 2817 + r"invalid type: unit value, expected something strange...", | warning: unnecessary hashes around raw string literal --> test_suite/tests/test_annotations.rs:2828:9 | 2828 | r#"invalid type: map, expected something strange..."#, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string_hashes help: remove all the hashes around the literal | 2828 - r#"invalid type: map, expected something strange..."#, 2828 + r"invalid type: map, expected something strange...", | --- test_suite/tests/test_annotations.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test_suite/tests/test_annotations.rs b/test_suite/tests/test_annotations.rs index fa314cbca..17ff486bd 100644 --- a/test_suite/tests/test_annotations.rs +++ b/test_suite/tests/test_annotations.rs @@ -2719,7 +2719,7 @@ fn test_expecting_message_externally_tagged_enum() { // Check that #[serde(expecting = "...")] doesn't affect variant identifier error message assert_de_tokens_error::( &[Token::Enum { name: "Enum" }, Token::Unit], - r#"invalid type: unit value, expected variant identifier"#, + r"invalid type: unit value, expected variant identifier", ); } @@ -2740,7 +2740,7 @@ fn test_expecting_message_internally_tagged_enum() { // Check that #[serde(expecting = "...")] doesn't affect variant identifier error message assert_de_tokens_error::( &[Token::Map { len: None }, Token::Str("tag"), Token::Unit], - r#"invalid type: unit value, expected variant identifier"#, + r"invalid type: unit value, expected variant identifier", ); } @@ -2766,7 +2766,7 @@ fn test_expecting_message_adjacently_tagged_enum() { // Check that #[serde(expecting = "...")] doesn't affect variant identifier error message assert_de_tokens_error::( &[Token::Map { len: None }, Token::Str("tag"), Token::Unit], - r#"invalid type: unit value, expected variant of enum Enum"#, + r"invalid type: unit value, expected variant of enum Enum", ); } @@ -2779,7 +2779,7 @@ fn test_expecting_message_untagged_tagged_enum() { Untagged, } - assert_de_tokens_error::(&[Token::Str("Untagged")], r#"something strange..."#); + assert_de_tokens_error::(&[Token::Str("Untagged")], r"something strange..."); } #[test] @@ -2800,7 +2800,7 @@ fn test_expecting_message_identifier_enum() { assert_de_tokens_error::( &[Token::Unit], - r#"invalid type: unit value, expected something strange..."#, + r"invalid type: unit value, expected something strange...", ); assert_de_tokens_error::( @@ -2809,12 +2809,12 @@ fn test_expecting_message_identifier_enum() { Token::Str("Unknown"), Token::None, ], - r#"invalid type: map, expected something strange..."#, + r"invalid type: map, expected something strange...", ); assert_de_tokens_error::( &[Token::Unit], - r#"invalid type: unit value, expected something strange..."#, + r"invalid type: unit value, expected something strange...", ); assert_de_tokens_error::( @@ -2825,7 +2825,7 @@ fn test_expecting_message_identifier_enum() { Token::Str("Unknown"), Token::None, ], - r#"invalid type: map, expected something strange..."#, + r"invalid type: map, expected something strange...", ); } From 8c4aad3a59515f7b779f764d5e16d6bae297ab7f Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 26 Sep 2023 19:09:30 -0700 Subject: [PATCH 009/258] Clean up unneeded raw strings in test --- test_suite/tests/test_annotations.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test_suite/tests/test_annotations.rs b/test_suite/tests/test_annotations.rs index 17ff486bd..d83d4daf3 100644 --- a/test_suite/tests/test_annotations.rs +++ b/test_suite/tests/test_annotations.rs @@ -2719,7 +2719,7 @@ fn test_expecting_message_externally_tagged_enum() { // Check that #[serde(expecting = "...")] doesn't affect variant identifier error message assert_de_tokens_error::( &[Token::Enum { name: "Enum" }, Token::Unit], - r"invalid type: unit value, expected variant identifier", + "invalid type: unit value, expected variant identifier", ); } @@ -2740,7 +2740,7 @@ fn test_expecting_message_internally_tagged_enum() { // Check that #[serde(expecting = "...")] doesn't affect variant identifier error message assert_de_tokens_error::( &[Token::Map { len: None }, Token::Str("tag"), Token::Unit], - r"invalid type: unit value, expected variant identifier", + "invalid type: unit value, expected variant identifier", ); } @@ -2766,7 +2766,7 @@ fn test_expecting_message_adjacently_tagged_enum() { // Check that #[serde(expecting = "...")] doesn't affect variant identifier error message assert_de_tokens_error::( &[Token::Map { len: None }, Token::Str("tag"), Token::Unit], - r"invalid type: unit value, expected variant of enum Enum", + "invalid type: unit value, expected variant of enum Enum", ); } @@ -2779,7 +2779,7 @@ fn test_expecting_message_untagged_tagged_enum() { Untagged, } - assert_de_tokens_error::(&[Token::Str("Untagged")], r"something strange..."); + assert_de_tokens_error::(&[Token::Str("Untagged")], "something strange..."); } #[test] @@ -2800,7 +2800,7 @@ fn test_expecting_message_identifier_enum() { assert_de_tokens_error::( &[Token::Unit], - r"invalid type: unit value, expected something strange...", + "invalid type: unit value, expected something strange...", ); assert_de_tokens_error::( @@ -2809,12 +2809,12 @@ fn test_expecting_message_identifier_enum() { Token::Str("Unknown"), Token::None, ], - r"invalid type: map, expected something strange...", + "invalid type: map, expected something strange...", ); assert_de_tokens_error::( &[Token::Unit], - r"invalid type: unit value, expected something strange...", + "invalid type: unit value, expected something strange...", ); assert_de_tokens_error::( @@ -2825,7 +2825,7 @@ fn test_expecting_message_identifier_enum() { Token::Str("Unknown"), Token::None, ], - r"invalid type: map, expected something strange...", + "invalid type: map, expected something strange...", ); } From 37a32857a2667756936888a1da81ada9242d26a9 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 5 Oct 2023 23:24:34 -0400 Subject: [PATCH 010/258] Update ui test suite to nightly-2023-10-06 --- test_suite/tests/ui/remote/unknown_field.stderr | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test_suite/tests/ui/remote/unknown_field.stderr b/test_suite/tests/ui/remote/unknown_field.stderr index 152ffb60c..98b8478c2 100644 --- a/test_suite/tests/ui/remote/unknown_field.stderr +++ b/test_suite/tests/ui/remote/unknown_field.stderr @@ -2,10 +2,12 @@ error[E0609]: no field `b` on type `&remote::S` --> tests/ui/remote/unknown_field.rs:12:5 | 12 | b: u8, - | ^ help: a field with a similar name exists: `a` + | ^ unknown field error[E0560]: struct `remote::S` has no field named `b` --> tests/ui/remote/unknown_field.rs:12:5 | 12 | b: u8, - | ^ help: a field with a similar name exists: `a` + | ^ `remote::S` does not have this field + | + = note: all struct fields are already assigned From 1cbea892cf5b786d606b1ef5f6733cc2e39bbbc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Marcos=20P=2E=20Bezerra?= Date: Mon, 9 Oct 2023 22:59:56 -0300 Subject: [PATCH 011/258] Add CSV to the formats list --- serde/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/serde/src/lib.rs b/serde/src/lib.rs index f7d445749..4b8255e26 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -63,6 +63,7 @@ //! and from DynamoDB. //! - [Hjson], a syntax extension to JSON designed around human reading and //! editing. *(deserialization only)* +//! - [CSV], Comma-separated values is a tabular text file format. //! //! [JSON]: https://github.com/serde-rs/json //! [Postcard]: https://github.com/jamesmunns/postcard @@ -89,6 +90,7 @@ //! [DynamoDB Items]: https://docs.rs/serde_dynamo //! [rusoto_dynamodb]: https://docs.rs/rusoto_dynamodb //! [Hjson]: https://github.com/Canop/deser-hjson +//! [CSV]: https://docs.rs/csv //////////////////////////////////////////////////////////////////////////////// From b908487476633a397685a5a5f5265d4e0a4cd3a4 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 12 Oct 2023 19:18:37 -0700 Subject: [PATCH 012/258] Remove double nesting of first_attempt `expr` is of type serde_derive::fragment::Expr, which can be interpolated directly in any expression position. It does not need to be nested in another set of braces. --- serde_derive/src/de.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index c6b2cfff2..9942770ae 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -1754,18 +1754,18 @@ fn deserialize_untagged_enum_after( // need to provide the error type. let first_attempt = first_attempt.map(|expr| { quote! { - if let _serde::__private::Result::<_, __D::Error>::Ok(__ok) = (|| { - #expr - })() { + if let _serde::__private::Result::<_, __D::Error>::Ok(__ok) = (|| #expr)() { return _serde::__private::Ok(__ok); } } }); + quote_block! { let __content = <_serde::__private::de::Content as _serde::Deserialize>::deserialize(__deserializer)?; let __deserializer = _serde::__private::de::ContentRefDeserializer::<__D::Error>::new(&__content); #first_attempt + #( if let _serde::__private::Ok(__ok) = #attempts { return _serde::__private::Ok(__ok); From e94fc65f01e60d91c6dd9bafc0601c4ae4a77739 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 12 Oct 2023 19:20:43 -0700 Subject: [PATCH 013/258] Release 1.0.189 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 5ecd948e9..b1d5059f8 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.188" # remember to update html_root_url and serde_derive dependency +version = "1.0.189" # remember to update html_root_url and serde_derive dependency authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.188", path = "../serde_derive" } +serde_derive = { version = "=1.0.189", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 4b8255e26..2d93a4232 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.188")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.189")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Unstable functionality only if the user asks for it. For tracking and diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 2f3520b78..f2f9e9bcf 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.188" # remember to update html_root_url +version = "1.0.189" # remember to update html_root_url authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index d094242f3..27a106bfe 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.188")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.189")] // Ignored clippy lints #![allow( // clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054 From 9cdf33202977df68289a42b1ba30885b6b2abe44 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 17 Oct 2023 21:05:31 -0700 Subject: [PATCH 014/258] Remove 'remember to update' reminder from Cargo.toml --- serde/Cargo.toml | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive_internals/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index b1d5059f8..c4a644f24 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.189" # remember to update html_root_url and serde_derive dependency +version = "1.0.189" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index f2f9e9bcf..648158fec 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.189" # remember to update html_root_url +version = "1.0.189" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive_internals/Cargo.toml b/serde_derive_internals/Cargo.toml index 4c57a3c3d..c99267370 100644 --- a/serde_derive_internals/Cargo.toml +++ b/serde_derive_internals/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive_internals" -version = "0.29.0" # remember to update html_root_url +version = "0.29.0" authors = ["Erick Tryzelaar ", "David Tolnay "] description = "AST representation used by Serde derive macros. Unstable." documentation = "https://docs.rs/serde_derive_internals" From 8de84b7ca32afd5037326025ed8fcfd06ed9db5f Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 21 Oct 2023 22:00:59 -0700 Subject: [PATCH 015/258] Resolve get_first clippy lint warning: accessing first element with `variant.fields.get(0)` --> serde_derive/src/de.rs:1843:27 | 1843 | let default = variant.fields.get(0).map(|field| { | ^^^^^^^^^^^^^^^^^^^^^ help: try: `variant.fields.first()` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#get_first = note: `-W clippy::get-first` implied by `-W clippy::all` = help: to override `-W clippy::all` add `#[allow(clippy::get_first)]` warning: accessing first element with `variant.fields.get(0)` --> serde_derive/src/de.rs:1888:27 | 1888 | let default = variant.fields.get(0).map(|field| { | ^^^^^^^^^^^^^^^^^^^^^ help: try: `variant.fields.first()` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#get_first --- serde_derive/src/de.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index 9942770ae..e3b737c61 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -1840,7 +1840,7 @@ fn deserialize_internally_tagged_variant( let this_value = ¶ms.this_value; let type_name = params.type_name(); let variant_name = variant.ident.to_string(); - let default = variant.fields.get(0).map(|field| { + let default = variant.fields.first().map(|field| { let default = Expr(expr_is_missing(field, cattrs)); quote!((#default)) }); @@ -1885,7 +1885,7 @@ fn deserialize_untagged_variant( let this_value = ¶ms.this_value; let type_name = params.type_name(); let variant_name = variant.ident.to_string(); - let default = variant.fields.get(0).map(|field| { + let default = variant.fields.first().map(|field| { let default = Expr(expr_is_missing(field, cattrs)); quote!((#default)) }); From bb4135cae830e27135c5ba0a3f23512634dfd7c6 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 24 Oct 2023 22:32:19 -0700 Subject: [PATCH 016/258] Fix unused imports warning: unused imports: `cmp`, `mem`, `slice` --> serde/src/lib.rs:171:26 | 171 | pub use self::core::{cmp, iter, mem, num, ptr, slice, str}; | ^^^ ^^^ ^^^^^ | = note: `#[warn(unused_imports)]` on by default --- serde/src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 2d93a4232..f513a2911 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -168,11 +168,14 @@ mod lib { pub use std::*; } - pub use self::core::{cmp, iter, mem, num, ptr, slice, str}; pub use self::core::{f32, f64}; pub use self::core::{i16, i32, i64, i8, isize}; + pub use self::core::{iter, num, ptr, str}; pub use self::core::{u16, u32, u64, u8, usize}; + #[cfg(any(feature = "std", feature = "alloc"))] + pub use self::core::{cmp, mem, slice}; + pub use self::core::cell::{Cell, RefCell}; pub use self::core::clone::{self, Clone}; pub use self::core::cmp::Reverse; From a091a07aa2a70ce45e7c61146b4387630239eae8 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 25 Oct 2023 19:42:00 -0700 Subject: [PATCH 017/258] Add float NaN tests --- test_suite/tests/test_de.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test_suite/tests/test_de.rs b/test_suite/tests/test_de.rs index 33dc7351b..b7d82ecff 100644 --- a/test_suite/tests/test_de.rs +++ b/test_suite/tests/test_de.rs @@ -11,6 +11,7 @@ #![cfg_attr(feature = "unstable", feature(never_type))] use fnv::FnvHasher; +use serde::de::value::{F32Deserializer, F64Deserializer}; use serde::de::{Deserialize, DeserializeOwned, Deserializer, IntoDeserializer}; use serde_derive::Deserialize; use serde_test::{assert_de_tokens, Configure, Token}; @@ -832,6 +833,26 @@ fn test_f64() { test(1.11, &[Token::F64(1.11)]); } +#[test] +fn test_nan() { + let f32_deserializer = F32Deserializer::::new; + let f64_deserializer = F64Deserializer::::new; + + let pos_f32_nan = f32_deserializer(f32::NAN.copysign(1.0)); + let pos_f64_nan = f64_deserializer(f64::NAN.copysign(1.0)); + assert!(f32::deserialize(pos_f32_nan).unwrap().is_sign_positive()); + assert!(f32::deserialize(pos_f64_nan).unwrap().is_sign_positive()); + assert!(f64::deserialize(pos_f32_nan).unwrap().is_sign_positive()); + assert!(f64::deserialize(pos_f64_nan).unwrap().is_sign_positive()); + + let neg_f32_nan = f32_deserializer(f32::NAN.copysign(-1.0)); + let neg_f64_nan = f64_deserializer(f64::NAN.copysign(-1.0)); + assert!(f32::deserialize(neg_f32_nan).unwrap().is_sign_negative()); + assert!(f32::deserialize(neg_f64_nan).unwrap().is_sign_negative()); + assert!(f64::deserialize(neg_f32_nan).unwrap().is_sign_negative()); + assert!(f64::deserialize(neg_f64_nan).unwrap().is_sign_negative()); +} + #[test] fn test_char() { test('a', &[Token::Char('a')]); From d2fcc346b9f8f8a61d05474b4e95198788c05ed0 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 25 Oct 2023 19:37:47 -0700 Subject: [PATCH 018/258] Ensure f32 deserialized from f64 and vice versa preserve NaN sign --- serde/build.rs | 6 ++++++ serde/src/de/impls.rs | 26 ++++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/serde/build.rs b/serde/build.rs index 2b10c5893..fe5486a7a 100644 --- a/serde/build.rs +++ b/serde/build.rs @@ -27,6 +27,12 @@ fn main() { println!("cargo:rustc-cfg=no_relaxed_trait_bounds"); } + // f32::copysign and f64::copysign stabilized in Rust 1.35. + // https://blog.rust-lang.org/2019/05/23/Rust-1.35.0.html#copy-the-sign-of-a-floating-point-number-onto-another + if minor < 35 { + println!("cargo:rustc-cfg=no_float_copysign"); + } + // Current minimum supported version of serde_derive crate is Rust 1.56. if minor < 56 { println!("cargo:rustc-cfg=no_serde_derive"); diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index fbee1554b..9b8755bd7 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -180,6 +180,28 @@ macro_rules! num_as_self { }; } +macro_rules! num_as_copysign_self { + ($ty:ident : $visit:ident) => { + #[inline] + fn $visit(self, v: $ty) -> Result + where + E: Error, + { + #[cfg(no_float_copysign)] + { + Ok(v as Self::Value) + } + + #[cfg(not(no_float_copysign))] + { + // Preserve sign of NaN. The `as` produces a nondeterministic sign. + let sign = if v.is_sign_positive() { 1.0 } else { -1.0 }; + Ok((v as Self::Value).copysign(sign)) + } + } + }; +} + macro_rules! int_to_int { ($ty:ident : $visit:ident) => { #[inline] @@ -351,7 +373,7 @@ impl_deserialize_num! { impl_deserialize_num! { f32, deserialize_f32 num_self!(f32:visit_f32); - num_as_self!(f64:visit_f64); + num_as_copysign_self!(f64:visit_f64); 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); } @@ -359,7 +381,7 @@ impl_deserialize_num! { impl_deserialize_num! { f64, deserialize_f64 num_self!(f64:visit_f64); - num_as_self!(f32:visit_f32); + num_as_copysign_self!(f32:visit_f32); 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); } From 6ba9c12ff6309114fd22d56a9f4acf32284352f4 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 25 Oct 2023 19:55:12 -0700 Subject: [PATCH 019/258] Float copysign does not exist in libcore yet --- serde/src/de/impls.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 9b8755bd7..b7e4c549d 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -187,12 +187,12 @@ macro_rules! num_as_copysign_self { where E: Error, { - #[cfg(no_float_copysign)] + #[cfg(any(no_float_copysign, not(feature = "std")))] { Ok(v as Self::Value) } - #[cfg(not(no_float_copysign))] + #[cfg(all(not(no_float_copysign), feature = "std"))] { // Preserve sign of NaN. The `as` produces a nondeterministic sign. let sign = if v.is_sign_positive() { 1.0 } else { -1.0 }; From edb1a586d83ceaf4a61980ce890bc77a02e00787 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 25 Oct 2023 20:05:13 -0700 Subject: [PATCH 020/258] Release 1.0.190 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index c4a644f24..b1a6d3e9b 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.189" +version = "1.0.190" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.189", path = "../serde_derive" } +serde_derive = { version = "=1.0.190", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index f513a2911..8c6a4affc 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.189")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.190")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Unstable functionality only if the user asks for it. For tracking and diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 648158fec..e70d177a9 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.189" +version = "1.0.190" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index 27a106bfe..7d653ff0c 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.189")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.190")] // Ignored clippy lints #![allow( // clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054 From 589549d7e62051160e0ed7382e1dcc4b924c38c9 Mon Sep 17 00:00:00 2001 From: Robsdedude Date: Mon, 6 Nov 2023 12:11:02 +0100 Subject: [PATCH 021/258] Allow internal tag field in untagged variant --- serde_derive/src/internals/check.rs | 3 + test_suite/tests/test_macros.rs | 94 +++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/serde_derive/src/internals/check.rs b/serde_derive/src/internals/check.rs index b01a8ca4d..52b0f379f 100644 --- a/serde_derive/src/internals/check.rs +++ b/serde_derive/src/internals/check.rs @@ -318,6 +318,9 @@ fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) { for variant in variants { match variant.style { Style::Struct => { + if variant.attrs.untagged() { + continue; + } for field in &variant.fields { let check_ser = !(field.attrs.skip_serializing() || variant.attrs.skip_serializing()); diff --git a/test_suite/tests/test_macros.rs b/test_suite/tests/test_macros.rs index 2b7d189fd..02c36c413 100644 --- a/test_suite/tests/test_macros.rs +++ b/test_suite/tests/test_macros.rs @@ -814,6 +814,100 @@ fn test_internally_tagged_enum() { ); } +#[test] +fn test_internally_tagged_enum_with_untagged_variant() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(tag = "kind")] + enum InternallyTagged { + Tagged { + a: u8, + }, + #[serde(untagged)] + Untagged { + kind: String, + b: u8, + }, + } + + assert_de_tokens( + &InternallyTagged::Tagged { a: 1 }, + &[ + Token::Map { len: Some(2) }, + Token::Str("kind"), + Token::Str("Tagged"), + Token::Str("a"), + Token::U8(1), + Token::MapEnd, + ], + ); + + assert_tokens( + &InternallyTagged::Tagged { a: 1 }, + &[ + Token::Struct { + name: "InternallyTagged", + len: 2, + }, + Token::Str("kind"), + Token::Str("Tagged"), + Token::Str("a"), + Token::U8(1), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &InternallyTagged::Untagged { + kind: "Foo".to_owned(), + b: 2, + }, + &[ + Token::Map { len: Some(2) }, + Token::Str("kind"), + Token::Str("Foo"), + Token::Str("b"), + Token::U8(2), + Token::MapEnd, + ], + ); + + assert_tokens( + &InternallyTagged::Untagged { + kind: "Foo".to_owned(), + b: 2, + }, + &[ + Token::Struct { + name: "InternallyTagged", + len: 2, + }, + Token::Str("kind"), + Token::Str("Foo"), + Token::Str("b"), + Token::U8(2), + Token::StructEnd, + ], + ); + + assert_tokens( + &InternallyTagged::Untagged { + kind: "Tagged".to_owned(), + b: 2, + }, + &[ + Token::Struct { + name: "InternallyTagged", + len: 2, + }, + Token::Str("kind"), + Token::Str("Tagged"), + Token::Str("b"), + Token::U8(2), + Token::StructEnd, + ], + ); +} + #[test] fn test_internally_tagged_bytes() { #[derive(Debug, PartialEq, Deserialize)] From 0726b2c4799fb31705aa8c488209dd865a8fe851 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 6 Nov 2023 08:06:23 -0800 Subject: [PATCH 022/258] Enable feature(doc_cfg) during docs.rs documentation build --- serde/Cargo.toml | 2 +- serde/src/lib.rs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index b1a6d3e9b..bb7b60b17 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -29,7 +29,7 @@ features = ["derive", "rc"] [package.metadata.docs.rs] features = ["derive"] targets = ["x86_64-unknown-linux-gnu"] -rustdoc-args = ["--generate-link-to-definition"] +rustdoc-args = ["--cfg", "doc_cfg", "--generate-link-to-definition"] # This cfg cannot be enabled, but it still forces Cargo to keep serde_derive's # version in lockstep with serde's, even if someone depends on the two crates diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 8c6a4affc..214fd5bdb 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -98,6 +98,8 @@ #![doc(html_root_url = "https://docs.rs/serde/1.0.190")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] +// Show which crate feature enables conditionally compiled APIs in documentation. +#![cfg_attr(doc_cfg, feature(doc_cfg))] // Unstable functionality only if the user asks for it. For tracking and // discussion of these features please refer to this issue: // From ce8fef7e0b917cc5150b3c753fd444c2a5f2acc6 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 6 Nov 2023 08:06:40 -0800 Subject: [PATCH 023/258] Show that derives are specific to feature="derive" in documentation --- serde/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 214fd5bdb..8408bbb2e 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -326,6 +326,7 @@ extern crate serde_derive; /// Derive macro available if serde is built with `features = ["derive"]`. #[cfg(feature = "serde_derive")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))] pub use serde_derive::{Deserialize, Serialize}; #[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))] From 215c2b71ef387e193860b57ee2868f3a2367afaa Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 6 Nov 2023 08:30:21 -0800 Subject: [PATCH 024/258] Relocate cfg attrs into forwarded_impl macro This will allow adding #[doc(cfg(feature = "..."))] attributes to the impl in an upcoming commit. --- serde/src/de/impls.rs | 69 +++++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 25 deletions(-) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index b7e4c549d..514443260 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -750,10 +750,10 @@ impl<'de> Deserialize<'de> for CString { macro_rules! forwarded_impl { ( - $(#[doc = $doc:tt])* + $(#[$attr:meta])* ($($id:ident),*), $ty:ty, $func:expr ) => { - $(#[doc = $doc])* + $(#[$attr])* impl<'de $(, $id : Deserialize<'de>,)*> Deserialize<'de> for $ty { fn deserialize(deserializer: D) -> Result where @@ -765,10 +765,14 @@ macro_rules! forwarded_impl { } } -#[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))] -forwarded_impl!((), Box, CString::into_boxed_c_str); +forwarded_impl! { + #[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))] + (), Box, CString::into_boxed_c_str +} -forwarded_impl!((T), Reverse, Reverse); +forwarded_impl! { + (T), Reverse, Reverse +} //////////////////////////////////////////////////////////////////////////////// @@ -1728,8 +1732,10 @@ impl<'de> Deserialize<'de> for PathBuf { } } -#[cfg(feature = "std")] -forwarded_impl!((), Box, PathBuf::into_boxed_path); +forwarded_impl! { + #[cfg(feature = "std")] + (), Box, PathBuf::into_boxed_path +} //////////////////////////////////////////////////////////////////////////////// @@ -1800,17 +1806,25 @@ impl<'de> Deserialize<'de> for OsString { //////////////////////////////////////////////////////////////////////////////// -#[cfg(any(feature = "std", feature = "alloc"))] -forwarded_impl!((T), Box, Box::new); +forwarded_impl! { + #[cfg(any(feature = "std", feature = "alloc"))] + (T), Box, Box::new +} -#[cfg(any(feature = "std", feature = "alloc"))] -forwarded_impl!((T), Box<[T]>, Vec::into_boxed_slice); +forwarded_impl! { + #[cfg(any(feature = "std", feature = "alloc"))] + (T), Box<[T]>, Vec::into_boxed_slice +} -#[cfg(any(feature = "std", feature = "alloc"))] -forwarded_impl!((), Box, String::into_boxed_str); +forwarded_impl! { + #[cfg(any(feature = "std", feature = "alloc"))] + (), Box, String::into_boxed_str +} -#[cfg(all(feature = "std", any(unix, windows)))] -forwarded_impl!((), Box, OsString::into_boxed_os_str); +forwarded_impl! { + #[cfg(all(feature = "std", any(unix, windows)))] + (), Box, OsString::into_boxed_os_str +} #[cfg(any(feature = "std", feature = "alloc"))] impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T> @@ -1867,13 +1881,12 @@ where //////////////////////////////////////////////////////////////////////////////// -#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] macro_rules! box_forwarded_impl { ( - $(#[doc = $doc:tt])* + $(#[$attr:meta])* $t:ident ) => { - $(#[doc = $doc])* + $(#[$attr])* impl<'de, T: ?Sized> Deserialize<'de> for $t where Box: Deserialize<'de>, @@ -1888,7 +1901,6 @@ macro_rules! box_forwarded_impl { }; } -#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] box_forwarded_impl! { /// This impl requires the [`"rc"`] Cargo feature of Serde. /// @@ -1897,10 +1909,10 @@ box_forwarded_impl! { /// will end up with a strong count of 1. /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc + #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] Rc } -#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] box_forwarded_impl! { /// This impl requires the [`"rc"`] Cargo feature of Serde. /// @@ -1909,6 +1921,7 @@ box_forwarded_impl! { /// will end up with a strong count of 1. /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc + #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] Arc } @@ -1926,13 +1939,19 @@ where } } -forwarded_impl!((T), RefCell, RefCell::new); +forwarded_impl! { + (T), RefCell, RefCell::new +} -#[cfg(feature = "std")] -forwarded_impl!((T), Mutex, Mutex::new); +forwarded_impl! { + #[cfg(feature = "std")] + (T), Mutex, Mutex::new +} -#[cfg(feature = "std")] -forwarded_impl!((T), RwLock, RwLock::new); +forwarded_impl! { + #[cfg(feature = "std")] + (T), RwLock, RwLock::new +} //////////////////////////////////////////////////////////////////////////////// From 3f339de36ae3e72fa4b2d683c12d3c37ec19537d Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 6 Nov 2023 08:39:31 -0800 Subject: [PATCH 025/258] Relocate cfg attrs into seq_impl and map_impl --- serde/src/de/impls.rs | 34 ++++++++++-------- serde/src/ser/impls.rs | 80 +++++++++++++++++++++++++++++------------- 2 files changed, 76 insertions(+), 38 deletions(-) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 514443260..ebdcfd58d 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -878,9 +878,9 @@ impl<'de, T: ?Sized> Deserialize<'de> for PhantomData { //////////////////////////////////////////////////////////////////////////////// -#[cfg(any(feature = "std", feature = "alloc"))] macro_rules! seq_impl { ( + $(#[$attr:meta])* $ty:ident , $access:ident, $clear:expr, @@ -888,6 +888,7 @@ macro_rules! seq_impl { $reserve:expr, $insert:expr ) => { + $(#[$attr])* impl<'de, T $(, $typaram)*> Deserialize<'de> for $ty where T: Deserialize<'de> $(+ $tbound1 $(+ $tbound2)*)*, @@ -975,8 +976,8 @@ macro_rules! seq_impl { #[cfg(any(feature = "std", feature = "alloc"))] fn nop_reserve(_seq: T, _n: usize) {} -#[cfg(any(feature = "std", feature = "alloc"))] seq_impl!( + #[cfg(any(feature = "std", feature = "alloc"))] BinaryHeap, seq, BinaryHeap::clear, @@ -985,8 +986,8 @@ seq_impl!( BinaryHeap::push ); -#[cfg(any(feature = "std", feature = "alloc"))] seq_impl!( + #[cfg(any(feature = "std", feature = "alloc"))] BTreeSet, seq, BTreeSet::clear, @@ -995,8 +996,8 @@ seq_impl!( BTreeSet::insert ); -#[cfg(any(feature = "std", feature = "alloc"))] seq_impl!( + #[cfg(any(feature = "std", feature = "alloc"))] LinkedList, seq, LinkedList::clear, @@ -1005,8 +1006,8 @@ seq_impl!( LinkedList::push_back ); -#[cfg(feature = "std")] seq_impl!( + #[cfg(feature = "std")] HashSet, seq, HashSet::clear, @@ -1015,8 +1016,8 @@ seq_impl!( HashSet::insert ); -#[cfg(any(feature = "std", feature = "alloc"))] seq_impl!( + #[cfg(any(feature = "std", feature = "alloc"))] VecDeque, seq, VecDeque::clear, @@ -1373,13 +1374,14 @@ tuple_impls! { //////////////////////////////////////////////////////////////////////////////// -#[cfg(any(feature = "std", feature = "alloc"))] macro_rules! map_impl { ( + $(#[$attr:meta])* $ty:ident , $access:ident, - $with_capacity:expr + $with_capacity:expr, ) => { + $(#[$attr])* impl<'de, K, V $(, $typaram)*> Deserialize<'de> for $ty where K: Deserialize<'de> $(+ $kbound1 $(+ $kbound2)*)*, @@ -1428,15 +1430,19 @@ macro_rules! map_impl { } } -#[cfg(any(feature = "std", feature = "alloc"))] -map_impl!(BTreeMap, map, BTreeMap::new()); +map_impl! { + #[cfg(any(feature = "std", feature = "alloc"))] + BTreeMap, + map, + BTreeMap::new(), +} -#[cfg(feature = "std")] -map_impl!( +map_impl! { + #[cfg(feature = "std")] HashMap, map, - HashMap::with_capacity_and_hasher(size_hint::cautious::<(K, V)>(map.size_hint()), S::default()) -); + HashMap::with_capacity_and_hasher(size_hint::cautious::<(K, V)>(map.size_hint()), S::default()), +} //////////////////////////////////////////////////////////////////////////////// diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index 39acba315..75f84b248 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -179,9 +179,13 @@ where } } -#[cfg(all(any(feature = "std", feature = "alloc"), not(no_relaxed_trait_bounds)))] +#[cfg(not(no_relaxed_trait_bounds))] macro_rules! seq_impl { - ($ty:ident ) => { + ( + $(#[$attr:meta])* + $ty:ident + ) => { + $(#[$attr])* impl Serialize for $ty where T: Serialize, @@ -197,9 +201,13 @@ macro_rules! seq_impl { } } -#[cfg(all(any(feature = "std", feature = "alloc"), no_relaxed_trait_bounds))] +#[cfg(no_relaxed_trait_bounds)] macro_rules! seq_impl { - ($ty:ident ) => { + ( + $(#[$attr:meta])* + $ty:ident + ) => { + $(#[$attr])* impl Serialize for $ty where T: Serialize $(+ $tbound1 $(+ $tbound2)*)*, @@ -216,23 +224,35 @@ macro_rules! seq_impl { } } -#[cfg(any(feature = "std", feature = "alloc"))] -seq_impl!(BinaryHeap); +seq_impl! { + #[cfg(any(feature = "std", feature = "alloc"))] + BinaryHeap +} -#[cfg(any(feature = "std", feature = "alloc"))] -seq_impl!(BTreeSet); +seq_impl! { + #[cfg(any(feature = "std", feature = "alloc"))] + BTreeSet +} -#[cfg(feature = "std")] -seq_impl!(HashSet); +seq_impl! { + #[cfg(feature = "std")] + HashSet +} -#[cfg(any(feature = "std", feature = "alloc"))] -seq_impl!(LinkedList); +seq_impl! { + #[cfg(any(feature = "std", feature = "alloc"))] + LinkedList +} -#[cfg(any(feature = "std", feature = "alloc"))] -seq_impl!(Vec); +seq_impl! { + #[cfg(any(feature = "std", feature = "alloc"))] + Vec +} -#[cfg(any(feature = "std", feature = "alloc"))] -seq_impl!(VecDeque); +seq_impl! { + #[cfg(any(feature = "std", feature = "alloc"))] + VecDeque +} //////////////////////////////////////////////////////////////////////////////// @@ -394,9 +414,13 @@ tuple_impls! { //////////////////////////////////////////////////////////////////////////////// -#[cfg(all(any(feature = "std", feature = "alloc"), not(no_relaxed_trait_bounds)))] +#[cfg(not(no_relaxed_trait_bounds))] macro_rules! map_impl { - ($ty:ident ) => { + ( + $(#[$attr:meta])* + $ty:ident + ) => { + $(#[$attr])* impl Serialize for $ty where K: Serialize, @@ -413,9 +437,13 @@ macro_rules! map_impl { } } -#[cfg(all(any(feature = "std", feature = "alloc"), no_relaxed_trait_bounds))] +#[cfg(no_relaxed_trait_bounds)] macro_rules! map_impl { - ($ty:ident ) => { + ( + $(#[$attr:meta])* + $ty:ident + ) => { + $(#[$attr])* impl Serialize for $ty where K: Serialize $(+ $kbound1 $(+ $kbound2)*)*, @@ -433,11 +461,15 @@ macro_rules! map_impl { } } -#[cfg(any(feature = "std", feature = "alloc"))] -map_impl!(BTreeMap); +map_impl! { + #[cfg(any(feature = "std", feature = "alloc"))] + BTreeMap +} -#[cfg(feature = "std")] -map_impl!(HashMap); +map_impl! { + #[cfg(feature = "std")] + HashMap +} //////////////////////////////////////////////////////////////////////////////// From 64f949b37b5b6cd1c02f71ab13d8beae53150b5d Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 6 Nov 2023 08:41:40 -0800 Subject: [PATCH 026/258] Relocate cfg attrs into parse_ip_impl and parse_socket_impl --- serde/src/de/impls.rs | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index ebdcfd58d..f4c313ef2 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -1446,9 +1446,12 @@ map_impl! { //////////////////////////////////////////////////////////////////////////////// -#[cfg(feature = "std")] macro_rules! parse_ip_impl { - ($expecting:tt $ty:ty; $size:tt) => { + ( + $(#[$attr:meta])* + $ty:ty, $expecting:expr, $size:tt + ) => { + $(#[$attr])* impl<'de> Deserialize<'de> for $ty { fn deserialize(deserializer: D) -> Result where @@ -1595,15 +1598,23 @@ impl<'de> Deserialize<'de> for net::IpAddr { } } -#[cfg(feature = "std")] -parse_ip_impl!("IPv4 address" net::Ipv4Addr; 4); +parse_ip_impl! { + #[cfg(feature = "std")] + net::Ipv4Addr, "IPv4 address", 4 +} -#[cfg(feature = "std")] -parse_ip_impl!("IPv6 address" net::Ipv6Addr; 16); +parse_ip_impl! { + #[cfg(feature = "std")] + net::Ipv6Addr, "IPv6 address", 16 +} -#[cfg(feature = "std")] macro_rules! parse_socket_impl { - ($expecting:tt $ty:ty, $new:expr) => { + ( + $(#[$attr:meta])* + $ty:ty, $expecting:tt, + $new:expr, + ) => { + $(#[$attr])* impl<'de> Deserialize<'de> for $ty { fn deserialize(deserializer: D) -> Result where @@ -1638,11 +1649,17 @@ impl<'de> Deserialize<'de> for net::SocketAddr { } } -#[cfg(feature = "std")] -parse_socket_impl!("IPv4 socket address" net::SocketAddrV4, |(ip, port)| net::SocketAddrV4::new(ip, port)); +parse_socket_impl! { + #[cfg(feature = "std")] + net::SocketAddrV4, "IPv4 socket address", + |(ip, port)| net::SocketAddrV4::new(ip, port), +} -#[cfg(feature = "std")] -parse_socket_impl!("IPv6 socket address" net::SocketAddrV6, |(ip, port)| net::SocketAddrV6::new(ip, port, 0, 0)); +parse_socket_impl! { + #[cfg(feature = "std")] + net::SocketAddrV6, "IPv6 socket address", + |(ip, port)| net::SocketAddrV6::new(ip, port, 0, 0), +} //////////////////////////////////////////////////////////////////////////////// From 05c2509d07ae52a15db3675aa6e942620d988c3a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 6 Nov 2023 11:13:28 -0800 Subject: [PATCH 027/258] Relocate cfg attrs into deref_impl --- serde/src/ser/impls.rs | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index 75f84b248..fdf3994d7 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -475,10 +475,10 @@ map_impl! { macro_rules! deref_impl { ( - $(#[doc = $doc:tt])* + $(#[$attr:meta])* <$($desc:tt)+ ) => { - $(#[doc = $doc])* + $(#[$attr])* impl <$($desc)+ { #[inline] fn serialize(&self, serializer: S) -> Result @@ -491,13 +491,19 @@ macro_rules! deref_impl { }; } -deref_impl!(<'a, T: ?Sized> Serialize for &'a T where T: Serialize); -deref_impl!(<'a, T: ?Sized> Serialize for &'a mut T where T: Serialize); +deref_impl! { + <'a, T: ?Sized> Serialize for &'a T where T: Serialize +} -#[cfg(any(feature = "std", feature = "alloc"))] -deref_impl!( Serialize for Box where T: Serialize); +deref_impl! { + <'a, T: ?Sized> Serialize for &'a mut T where T: Serialize +} + +deref_impl! { + #[cfg(any(feature = "std", feature = "alloc"))] + Serialize for Box where T: Serialize +} -#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] deref_impl! { /// This impl requires the [`"rc"`] Cargo feature of Serde. /// @@ -507,10 +513,10 @@ deref_impl! { /// repeated data. /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc + #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] Serialize for Rc where T: Serialize } -#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] deref_impl! { /// This impl requires the [`"rc"`] Cargo feature of Serde. /// @@ -520,11 +526,14 @@ deref_impl! { /// repeated data. /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc + #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] Serialize for Arc where T: Serialize } -#[cfg(any(feature = "std", feature = "alloc"))] -deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned); +deref_impl! { + #[cfg(any(feature = "std", feature = "alloc"))] + <'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned +} //////////////////////////////////////////////////////////////////////////////// From 9dacfbbd69d7911910eb641ed3deb6ce723059f0 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 6 Nov 2023 08:29:16 -0800 Subject: [PATCH 028/258] Fill in more doc(cfg) attributes --- serde/src/de/impls.rs | 41 +++++++++++++++++++++++++++++++++++++++++ serde/src/de/mod.rs | 2 ++ serde/src/de/value.rs | 12 ++++++++++++ serde/src/ser/impls.rs | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index f4c313ef2..1f05c5333 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -39,6 +39,7 @@ impl<'de> Deserialize<'de> for () { } #[cfg(feature = "unstable")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "unstable")))] impl<'de> Deserialize<'de> for ! { fn deserialize(_deserializer: D) -> Result where @@ -596,6 +597,7 @@ impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> { } #[cfg(any(feature = "std", feature = "alloc"))] +#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de> Deserialize<'de> for String { fn deserialize(deserializer: D) -> Result where @@ -739,6 +741,7 @@ impl<'de> Visitor<'de> for CStringVisitor { } #[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))] +#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de> Deserialize<'de> for CString { fn deserialize(deserializer: D) -> Result where @@ -767,6 +770,7 @@ macro_rules! forwarded_impl { forwarded_impl! { #[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] (), Box, CString::into_boxed_c_str } @@ -978,6 +982,7 @@ fn nop_reserve(_seq: T, _n: usize) {} seq_impl!( #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] BinaryHeap, seq, BinaryHeap::clear, @@ -988,6 +993,7 @@ seq_impl!( seq_impl!( #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] BTreeSet, seq, BTreeSet::clear, @@ -998,6 +1004,7 @@ seq_impl!( seq_impl!( #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] LinkedList, seq, LinkedList::clear, @@ -1008,6 +1015,7 @@ seq_impl!( seq_impl!( #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] HashSet, seq, HashSet::clear, @@ -1018,6 +1026,7 @@ seq_impl!( seq_impl!( #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] VecDeque, seq, VecDeque::clear, @@ -1029,6 +1038,7 @@ seq_impl!( //////////////////////////////////////////////////////////////////////////////// #[cfg(any(feature = "std", feature = "alloc"))] +#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, T> Deserialize<'de> for Vec where T: Deserialize<'de>, @@ -1432,6 +1442,7 @@ macro_rules! map_impl { map_impl! { #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] BTreeMap, map, BTreeMap::new(), @@ -1439,6 +1450,7 @@ map_impl! { map_impl! { #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] HashMap, map, HashMap::with_capacity_and_hasher(size_hint::cautious::<(K, V)>(map.size_hint()), S::default()), @@ -1580,6 +1592,7 @@ macro_rules! deserialize_enum { } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl<'de> Deserialize<'de> for net::IpAddr { fn deserialize(deserializer: D) -> Result where @@ -1600,11 +1613,13 @@ impl<'de> Deserialize<'de> for net::IpAddr { parse_ip_impl! { #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] net::Ipv4Addr, "IPv4 address", 4 } parse_ip_impl! { #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] net::Ipv6Addr, "IPv6 address", 16 } @@ -1631,6 +1646,7 @@ macro_rules! parse_socket_impl { } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl<'de> Deserialize<'de> for net::SocketAddr { fn deserialize(deserializer: D) -> Result where @@ -1651,12 +1667,14 @@ impl<'de> Deserialize<'de> for net::SocketAddr { parse_socket_impl! { #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] net::SocketAddrV4, "IPv4 socket address", |(ip, port)| net::SocketAddrV4::new(ip, port), } parse_socket_impl! { #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] net::SocketAddrV6, "IPv6 socket address", |(ip, port)| net::SocketAddrV6::new(ip, port, 0, 0), } @@ -1692,6 +1710,7 @@ impl<'a> Visitor<'a> for PathVisitor { } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl<'de: 'a, 'a> Deserialize<'de> for &'a Path { fn deserialize(deserializer: D) -> Result where @@ -1746,6 +1765,7 @@ impl<'de> Visitor<'de> for PathBufVisitor { } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl<'de> Deserialize<'de> for PathBuf { fn deserialize(deserializer: D) -> Result where @@ -1757,6 +1777,7 @@ impl<'de> Deserialize<'de> for PathBuf { forwarded_impl! { #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] (), Box, PathBuf::into_boxed_path } @@ -1818,6 +1839,7 @@ impl<'de> Visitor<'de> for OsStringVisitor { } #[cfg(all(feature = "std", any(unix, windows)))] +#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", any(unix, windows)))))] impl<'de> Deserialize<'de> for OsString { fn deserialize(deserializer: D) -> Result where @@ -1831,25 +1853,30 @@ impl<'de> Deserialize<'de> for OsString { forwarded_impl! { #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] (T), Box, Box::new } forwarded_impl! { #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] (T), Box<[T]>, Vec::into_boxed_slice } forwarded_impl! { #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] (), Box, String::into_boxed_str } forwarded_impl! { #[cfg(all(feature = "std", any(unix, windows)))] + #[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", any(unix, windows)))))] (), Box, OsString::into_boxed_os_str } #[cfg(any(feature = "std", feature = "alloc"))] +#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T> where T: ToOwned, @@ -1871,6 +1898,10 @@ where /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] +#[cfg_attr( + doc_cfg, + doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))) +)] impl<'de, T: ?Sized> Deserialize<'de> for RcWeak where T: Deserialize<'de>, @@ -1889,6 +1920,10 @@ where /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] +#[cfg_attr( + doc_cfg, + doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))) +)] impl<'de, T: ?Sized> Deserialize<'de> for ArcWeak where T: Deserialize<'de>, @@ -1933,6 +1968,7 @@ box_forwarded_impl! { /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] + #[cfg_attr(doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))] Rc } @@ -1945,6 +1981,7 @@ box_forwarded_impl! { /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] + #[cfg_attr(doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))] Arc } @@ -1968,11 +2005,13 @@ forwarded_impl! { forwarded_impl! { #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] (T), Mutex, Mutex::new } forwarded_impl! { #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] (T), RwLock, RwLock::new } @@ -2127,6 +2166,7 @@ impl<'de> Deserialize<'de> for Duration { //////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl<'de> Deserialize<'de> for SystemTime { fn deserialize(deserializer: D) -> Result where @@ -2962,6 +3002,7 @@ macro_rules! atomic_impl { ($($ty:ident $size:expr)*) => { $( #[cfg(any(no_target_has_atomic, target_has_atomic = $size))] + #[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", target_has_atomic = $size))))] impl<'de> Deserialize<'de> for $ty { fn deserialize(deserializer: D) -> Result where diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index afbc23af6..c22ed070b 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -1525,6 +1525,7 @@ pub trait Visitor<'de>: Sized { /// `String`. #[inline] #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] fn visit_string(self, v: String) -> Result where E: Error, @@ -1583,6 +1584,7 @@ pub trait Visitor<'de>: Sized { /// The default implementation forwards to `visit_bytes` and then drops the /// `Vec`. #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] fn visit_byte_buf(self, v: Vec) -> Result where E: Error, diff --git a/serde/src/de/value.rs b/serde/src/de/value.rs index 1234b8103..b229ebab7 100644 --- a/serde/src/de/value.rs +++ b/serde/src/de/value.rs @@ -112,6 +112,7 @@ impl Debug for Error { } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl error::Error for Error { fn description(&self) -> &str { &self.err @@ -184,12 +185,14 @@ impl Debug for UnitDeserializer { /// A deserializer that cannot be instantiated. #[cfg(feature = "unstable")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "unstable")))] pub struct NeverDeserializer { never: !, marker: PhantomData, } #[cfg(feature = "unstable")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "unstable")))] impl<'de, E> IntoDeserializer<'de, E> for ! where E: de::Error, @@ -562,6 +565,7 @@ impl<'de, E> Debug for BorrowedStrDeserializer<'de, E> { /// A deserializer holding a `String`. #[cfg(any(feature = "std", feature = "alloc"))] +#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] pub struct StringDeserializer { value: String, marker: PhantomData, @@ -578,6 +582,7 @@ impl Clone for StringDeserializer { } #[cfg(any(feature = "std", feature = "alloc"))] +#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, E> IntoDeserializer<'de, E> for String where E: de::Error, @@ -665,6 +670,7 @@ impl Debug for StringDeserializer { /// A deserializer holding a `Cow`. #[cfg(any(feature = "std", feature = "alloc"))] +#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] pub struct CowStrDeserializer<'a, E> { value: Cow<'a, str>, marker: PhantomData, @@ -681,6 +687,7 @@ impl<'a, E> Clone for CowStrDeserializer<'a, E> { } #[cfg(any(feature = "std", feature = "alloc"))] +#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, 'a, E> IntoDeserializer<'de, E> for Cow<'a, str> where E: de::Error, @@ -999,6 +1006,7 @@ where //////////////////////////////////////////////////////////////////////////////// #[cfg(any(feature = "std", feature = "alloc"))] +#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, T, E> IntoDeserializer<'de, E> for Vec where T: IntoDeserializer<'de, E>, @@ -1012,6 +1020,7 @@ where } #[cfg(any(feature = "std", feature = "alloc"))] +#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, T, E> IntoDeserializer<'de, E> for BTreeSet where T: IntoDeserializer<'de, E> + Eq + Ord, @@ -1025,6 +1034,7 @@ where } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl<'de, T, S, E> IntoDeserializer<'de, E> for HashSet where T: IntoDeserializer<'de, E> + Eq + Hash, @@ -1411,6 +1421,7 @@ impl Expected for ExpectedInMap { //////////////////////////////////////////////////////////////////////////////// #[cfg(any(feature = "std", feature = "alloc"))] +#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, K, V, E> IntoDeserializer<'de, E> for BTreeMap where K: IntoDeserializer<'de, E> + Eq + Ord, @@ -1425,6 +1436,7 @@ where } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl<'de, K, V, S, E> IntoDeserializer<'de, E> for HashMap where K: IntoDeserializer<'de, E> + Eq + Hash, diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index fdf3994d7..8c70634af 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -48,6 +48,7 @@ impl Serialize for str { } #[cfg(any(feature = "std", feature = "alloc"))] +#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] impl Serialize for String { #[inline] fn serialize(&self, serializer: S) -> Result @@ -70,6 +71,7 @@ impl<'a> Serialize for fmt::Arguments<'a> { //////////////////////////////////////////////////////////////////////////////// #[cfg(any(feature = "std", not(no_core_cstr)))] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl Serialize for CStr { #[inline] fn serialize(&self, serializer: S) -> Result @@ -81,6 +83,7 @@ impl Serialize for CStr { } #[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))] +#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] impl Serialize for CString { #[inline] fn serialize(&self, serializer: S) -> Result @@ -226,31 +229,37 @@ macro_rules! seq_impl { seq_impl! { #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] BinaryHeap } seq_impl! { #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] BTreeSet } seq_impl! { #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] HashSet } seq_impl! { #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] LinkedList } seq_impl! { #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] Vec } seq_impl! { #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] VecDeque } @@ -359,6 +368,7 @@ impl Serialize for () { } #[cfg(feature = "unstable")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "unstable")))] impl Serialize for ! { fn serialize(&self, _serializer: S) -> Result where @@ -463,11 +473,13 @@ macro_rules! map_impl { map_impl! { #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] BTreeMap } map_impl! { #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] HashMap } @@ -501,6 +513,7 @@ deref_impl! { deref_impl! { #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] Serialize for Box where T: Serialize } @@ -514,6 +527,7 @@ deref_impl! { /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] + #[cfg_attr(doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))] Serialize for Rc where T: Serialize } @@ -527,11 +541,13 @@ deref_impl! { /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] + #[cfg_attr(doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))] Serialize for Arc where T: Serialize } deref_impl! { #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] <'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned } @@ -541,6 +557,10 @@ deref_impl! { /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] +#[cfg_attr( + doc_cfg, + doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))) +)] impl Serialize for RcWeak where T: Serialize, @@ -557,6 +577,10 @@ where /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] +#[cfg_attr( + doc_cfg, + doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))) +)] impl Serialize for ArcWeak where T: Serialize, @@ -633,6 +657,7 @@ where } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl Serialize for Mutex where T: Serialize, @@ -649,6 +674,7 @@ where } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl Serialize for RwLock where T: Serialize, @@ -702,6 +728,7 @@ impl Serialize for Duration { //////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl Serialize for SystemTime { fn serialize(&self, serializer: S) -> Result where @@ -746,6 +773,7 @@ macro_rules! serialize_display_bounded_length { } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl Serialize for net::IpAddr { fn serialize(&self, serializer: S) -> Result where @@ -816,6 +844,7 @@ fn test_format_u8() { } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl Serialize for net::Ipv4Addr { fn serialize(&self, serializer: S) -> Result where @@ -840,6 +869,7 @@ impl Serialize for net::Ipv4Addr { } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl Serialize for net::Ipv6Addr { fn serialize(&self, serializer: S) -> Result where @@ -856,6 +886,7 @@ impl Serialize for net::Ipv6Addr { } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl Serialize for net::SocketAddr { fn serialize(&self, serializer: S) -> Result where @@ -880,6 +911,7 @@ impl Serialize for net::SocketAddr { } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl Serialize for net::SocketAddrV4 { fn serialize(&self, serializer: S) -> Result where @@ -896,6 +928,7 @@ impl Serialize for net::SocketAddrV4 { } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl Serialize for net::SocketAddrV6 { fn serialize(&self, serializer: S) -> Result where @@ -917,6 +950,7 @@ impl Serialize for net::SocketAddrV6 { //////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl Serialize for Path { fn serialize(&self, serializer: S) -> Result where @@ -930,6 +964,7 @@ impl Serialize for Path { } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl Serialize for PathBuf { fn serialize(&self, serializer: S) -> Result where @@ -940,6 +975,7 @@ impl Serialize for PathBuf { } #[cfg(all(feature = "std", any(unix, windows)))] +#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", any(unix, windows)))))] impl Serialize for OsStr { #[cfg(unix)] fn serialize(&self, serializer: S) -> Result @@ -962,6 +998,7 @@ impl Serialize for OsStr { } #[cfg(all(feature = "std", any(unix, windows)))] +#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", any(unix, windows)))))] impl Serialize for OsString { fn serialize(&self, serializer: S) -> Result where @@ -1006,6 +1043,7 @@ macro_rules! atomic_impl { ($($ty:ident $size:expr)*) => { $( #[cfg(any(no_target_has_atomic, target_has_atomic = $size))] + #[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", target_has_atomic = $size))))] impl Serialize for $ty { fn serialize(&self, serializer: S) -> Result where From c8bc97c81be0251670e3f3f279dc45820ad87784 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 6 Nov 2023 11:22:25 -0800 Subject: [PATCH 029/258] Document "rc" and "unstable" features on docs.rs --- serde/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index bb7b60b17..14603e70d 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -27,7 +27,7 @@ doc-scrape-examples = false features = ["derive", "rc"] [package.metadata.docs.rs] -features = ["derive"] +features = ["derive", "rc", "unstable"] targets = ["x86_64-unknown-linux-gnu"] rustdoc-args = ["--cfg", "doc_cfg", "--generate-link-to-definition"] From 59892e7b58f95dace1fbf57bfa3072dc655b598e Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 6 Nov 2023 11:30:27 -0800 Subject: [PATCH 030/258] Release 1.0.191 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 14603e70d..684068cc8 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.190" +version = "1.0.191" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--cfg", "doc_cfg", "--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.190", path = "../serde_derive" } +serde_derive = { version = "=1.0.191", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 8408bbb2e..5845b6515 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.190")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.191")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index e70d177a9..c86aeb7df 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.190" +version = "1.0.191" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index 7d653ff0c..a00a12ea7 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.190")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.191")] // Ignored clippy lints #![allow( // clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054 From 4676abdc9e6bbbddfb33a00ce8d7e81e92f01120 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 6 Nov 2023 18:49:17 -0800 Subject: [PATCH 031/258] Release 1.0.192 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 684068cc8..345312951 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.191" +version = "1.0.192" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--cfg", "doc_cfg", "--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.191", path = "../serde_derive" } +serde_derive = { version = "=1.0.192", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 5845b6515..f41bc44fd 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.191")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.192")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index c86aeb7df..74240e0a8 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.191" +version = "1.0.192" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index a00a12ea7..f4eeba4fc 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.191")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.192")] // Ignored clippy lints #![allow( // clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054 From 2083f43a287cac8302009fda5bbe41518dd83209 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 18 Nov 2023 18:13:57 -0800 Subject: [PATCH 032/258] Update ui test suite to nightly-2023-11-19 --- test_suite/tests/ui/remote/unknown_field.stderr | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test_suite/tests/ui/remote/unknown_field.stderr b/test_suite/tests/ui/remote/unknown_field.stderr index 98b8478c2..f7efacdef 100644 --- a/test_suite/tests/ui/remote/unknown_field.stderr +++ b/test_suite/tests/ui/remote/unknown_field.stderr @@ -3,6 +3,11 @@ error[E0609]: no field `b` on type `&remote::S` | 12 | b: u8, | ^ unknown field + | +help: a field with a similar name exists + | +12 | a: u8, + | ~ error[E0560]: struct `remote::S` has no field named `b` --> tests/ui/remote/unknown_field.rs:12:5 From c91c33436d7aaef7472ebc18b734ddc9b5bd11fa Mon Sep 17 00:00:00 2001 From: Emil Bonne Kristiansen Date: Tue, 21 Nov 2023 02:13:18 +0100 Subject: [PATCH 033/258] Fix Range{From,To} deserialize mixup --- serde/src/de/impls.rs | 72 +++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 1f05c5333..6675f6206 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -2509,7 +2509,7 @@ where where D: Deserializer<'de>, { - let start = tri!(deserializer.deserialize_struct( + let end = tri!(deserializer.deserialize_struct( "RangeFrom", range_from::FIELDS, range_from::RangeFromVisitor { @@ -2517,7 +2517,7 @@ where phantom: PhantomData, }, )); - Ok(start..) + Ok(end..) } } @@ -2526,14 +2526,14 @@ mod range_from { use crate::de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor}; - pub const FIELDS: &[&str] = &["end"]; + pub const FIELDS: &[&str] = &["start"]; // If this were outside of the serde crate, it would just use: // // #[derive(Deserialize)] // #[serde(field_identifier, rename_all = "lowercase")] enum Field { - End, + Start, } impl<'de> Deserialize<'de> for Field { @@ -2547,7 +2547,7 @@ mod range_from { type Value = Field; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("`end`") + formatter.write_str("`start`") } fn visit_str(self, value: &str) -> Result @@ -2555,7 +2555,7 @@ mod range_from { E: Error, { match value { - "end" => Ok(Field::End), + "start" => Ok(Field::Start), _ => Err(Error::unknown_field(value, FIELDS)), } } @@ -2565,7 +2565,7 @@ mod range_from { E: Error, { match value { - b"end" => Ok(Field::End), + b"start" => Ok(Field::Start), _ => { let value = crate::__private::from_utf8_lossy(value); Err(Error::unknown_field(&*value, FIELDS)) @@ -2597,35 +2597,35 @@ mod range_from { where A: SeqAccess<'de>, { - let end: Idx = match tri!(seq.next_element()) { + let start: Idx = match tri!(seq.next_element()) { Some(value) => value, None => { return Err(Error::invalid_length(0, &self)); } }; - Ok(end) + Ok(start) } fn visit_map(self, mut map: A) -> Result where A: MapAccess<'de>, { - let mut end: Option = None; + let mut start: Option = None; while let Some(key) = tri!(map.next_key()) { match key { - Field::End => { - if end.is_some() { - return Err(::duplicate_field("end")); + Field::Start => { + if start.is_some() { + return Err(::duplicate_field("start")); } - end = Some(tri!(map.next_value())); + start = Some(tri!(map.next_value())); } } } - let end = match end { - Some(end) => end, - None => return Err(::missing_field("end")), + let start = match start { + Some(start) => start, + None => return Err(::missing_field("start")), }; - Ok(end) + Ok(start) } } } @@ -2647,7 +2647,7 @@ where where D: Deserializer<'de>, { - let end = tri!(deserializer.deserialize_struct( + let start = tri!(deserializer.deserialize_struct( "RangeTo", range_to::FIELDS, range_to::RangeToVisitor { @@ -2655,7 +2655,7 @@ where phantom: PhantomData, }, )); - Ok(..end) + Ok(..start) } } @@ -2664,14 +2664,14 @@ mod range_to { use crate::de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor}; - pub const FIELDS: &[&str] = &["start"]; + pub const FIELDS: &[&str] = &["end"]; // If this were outside of the serde crate, it would just use: // // #[derive(Deserialize)] // #[serde(field_identifier, rename_all = "lowercase")] enum Field { - Start, + End, } impl<'de> Deserialize<'de> for Field { @@ -2685,7 +2685,7 @@ mod range_to { type Value = Field; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("`start`") + formatter.write_str("`end`") } fn visit_str(self, value: &str) -> Result @@ -2693,7 +2693,7 @@ mod range_to { E: Error, { match value { - "start" => Ok(Field::Start), + "end" => Ok(Field::End), _ => Err(Error::unknown_field(value, FIELDS)), } } @@ -2703,7 +2703,7 @@ mod range_to { E: Error, { match value { - b"start" => Ok(Field::Start), + b"end" => Ok(Field::End), _ => { let value = crate::__private::from_utf8_lossy(value); Err(Error::unknown_field(&*value, FIELDS)) @@ -2735,35 +2735,35 @@ mod range_to { where A: SeqAccess<'de>, { - let start: Idx = match tri!(seq.next_element()) { + let end: Idx = match tri!(seq.next_element()) { Some(value) => value, None => { return Err(Error::invalid_length(0, &self)); } }; - Ok(start) + Ok(end) } fn visit_map(self, mut map: A) -> Result where A: MapAccess<'de>, { - let mut start: Option = None; + let mut end: Option = None; while let Some(key) = tri!(map.next_key()) { match key { - Field::Start => { - if start.is_some() { - return Err(::duplicate_field("start")); + Field::End => { + if end.is_some() { + return Err(::duplicate_field("end")); } - start = Some(tri!(map.next_value())); + end = Some(tri!(map.next_value())); } } } - let start = match start { - Some(start) => start, - None => return Err(::missing_field("start")), + let end = match end { + Some(end) => end, + None => return Err(::missing_field("end")), }; - Ok(start) + Ok(end) } } } From 8c4af412969086bc8f54fdc2a079d373632e0a03 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 20 Nov 2023 17:21:28 -0800 Subject: [PATCH 034/258] Fix more RangeFrom / RangeEnd mixups --- serde/src/de/impls.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 6675f6206..413c997af 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -2509,7 +2509,7 @@ where where D: Deserializer<'de>, { - let end = tri!(deserializer.deserialize_struct( + let start = tri!(deserializer.deserialize_struct( "RangeFrom", range_from::FIELDS, range_from::RangeFromVisitor { @@ -2517,7 +2517,7 @@ where phantom: PhantomData, }, )); - Ok(end..) + Ok(start..) } } @@ -2637,7 +2637,7 @@ mod range_from { // #[derive(Deserialize)] // #[serde(deny_unknown_fields)] // struct RangeTo { -// start: Idx, +// end: Idx, // } impl<'de, Idx> Deserialize<'de> for RangeTo where @@ -2647,7 +2647,7 @@ where where D: Deserializer<'de>, { - let start = tri!(deserializer.deserialize_struct( + let end = tri!(deserializer.deserialize_struct( "RangeTo", range_to::FIELDS, range_to::RangeToVisitor { @@ -2655,7 +2655,7 @@ where phantom: PhantomData, }, )); - Ok(..start) + Ok(..end) } } From 65d75b8fe3105f00ab2e01537d568d4587167582 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 20 Nov 2023 17:25:48 -0800 Subject: [PATCH 035/258] Add RangeFrom and RangeTo tests --- test_suite/tests/test_de.rs | 40 ++++++++++++++++++++++++++++++++++++ test_suite/tests/test_ser.rs | 32 +++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/test_suite/tests/test_de.rs b/test_suite/tests/test_de.rs index b7d82ecff..3ca0fde36 100644 --- a/test_suite/tests/test_de.rs +++ b/test_suite/tests/test_de.rs @@ -1898,6 +1898,46 @@ fn test_range_inclusive() { ); } +#[test] +fn test_range_from() { + test( + 1u32.., + &[ + Token::Struct { + name: "RangeFrom", + len: 1, + }, + Token::Str("start"), + Token::U32(1), + Token::StructEnd, + ], + ); + test( + 1u32.., + &[Token::Seq { len: Some(1) }, Token::U32(1), Token::SeqEnd], + ); +} + +#[test] +fn test_range_to() { + test( + ..2u32, + &[ + Token::Struct { + name: "RangeTo", + len: 1, + }, + Token::Str("end"), + Token::U32(2), + Token::StructEnd, + ], + ); + test( + ..2u32, + &[Token::Seq { len: Some(1) }, Token::U32(2), Token::SeqEnd], + ); +} + #[test] fn test_bound() { test( diff --git a/test_suite/tests/test_ser.rs b/test_suite/tests/test_ser.rs index 81fc9ea74..71ec3bc57 100644 --- a/test_suite/tests/test_ser.rs +++ b/test_suite/tests/test_ser.rs @@ -500,6 +500,38 @@ fn test_range_inclusive() { ); } +#[test] +fn test_range_from() { + assert_ser_tokens( + &(1u32..), + &[ + Token::Struct { + name: "RangeFrom", + len: 1, + }, + Token::Str("start"), + Token::U32(1), + Token::StructEnd, + ], + ); +} + +#[test] +fn test_range_to() { + assert_ser_tokens( + &(..2u32), + &[ + Token::Struct { + name: "RangeTo", + len: 1, + }, + Token::Str("end"), + Token::U32(2), + Token::StructEnd, + ], + ); +} + #[test] fn test_bound() { assert_ser_tokens( From 44613c7d0190dbb5ecd2d5ec19c636f45b7488cc Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 20 Nov 2023 17:34:20 -0800 Subject: [PATCH 036/258] Release 1.0.193 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 345312951..395e08025 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.192" +version = "1.0.193" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--cfg", "doc_cfg", "--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.192", path = "../serde_derive" } +serde_derive = { version = "=1.0.193", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index f41bc44fd..b9fbefed4 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.192")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.193")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 74240e0a8..c21aabc6a 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.192" +version = "1.0.193" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index f4eeba4fc..dba48d4eb 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.192")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.193")] // Ignored clippy lints #![allow( // clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054 From a0e68698e33fa928f1d9f208d68b17df9f8bb568 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 2 Dec 2023 18:25:33 -0800 Subject: [PATCH 037/258] Work around doc_link_with_quotes pedantic clippy lint warning: possible intra-doc link using quotes instead of backticks --> serde/src/de/mod.rs:67:41 | 67 | //! - Rc\ *(if* features = ["rc"] *is enabled)* | ^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_with_quotes = note: `-W clippy::doc-link-with-quotes` implied by `-W clippy::pedantic` = help: to override `-W clippy::pedantic` add `#[allow(clippy::doc_link_with_quotes)]` warning: possible intra-doc link using quotes instead of backticks --> serde/src/de/mod.rs:68:42 | 68 | //! - Arc\ *(if* features = ["rc"] *is enabled)* | ^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_with_quotes warning: possible intra-doc link using quotes instead of backticks --> serde/src/ser/mod.rs:64:41 | 64 | //! - Rc\ *(if* features = ["rc"] *is enabled)* | ^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_with_quotes warning: possible intra-doc link using quotes instead of backticks --> serde/src/ser/mod.rs:65:42 | 65 | //! - Arc\ *(if* features = ["rc"] *is enabled)* | ^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_with_quotes --- serde/src/de/mod.rs | 4 ++-- serde/src/ser/mod.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index c22ed070b..c9919d92b 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -64,8 +64,8 @@ //! - RefCell\ //! - Mutex\ //! - RwLock\ -//! - Rc\ *(if* features = ["rc"] *is enabled)* -//! - Arc\ *(if* features = ["rc"] *is enabled)* +//! - Rc\ *(if* features = \["rc"\] *is enabled)* +//! - Arc\ *(if* features = \["rc"\] *is enabled)* //! - **Collection types**: //! - BTreeMap\ //! - BTreeSet\ diff --git a/serde/src/ser/mod.rs b/serde/src/ser/mod.rs index f1820c20a..75c45140e 100644 --- a/serde/src/ser/mod.rs +++ b/serde/src/ser/mod.rs @@ -61,8 +61,8 @@ //! - RefCell\ //! - Mutex\ //! - RwLock\ -//! - Rc\ *(if* features = ["rc"] *is enabled)* -//! - Arc\ *(if* features = ["rc"] *is enabled)* +//! - Rc\ *(if* features = \["rc"\] *is enabled)* +//! - Arc\ *(if* features = \["rc"\] *is enabled)* //! - **Collection types**: //! - BTreeMap\ //! - BTreeSet\ From 3d6a789562579fb7ea783e0d7f35530914d8baca Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 30 Dec 2023 14:46:51 -0800 Subject: [PATCH 038/258] Remove option_if_let_else clippy suppression --- serde/src/lib.rs | 1 - serde_derive/src/lib.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/serde/src/lib.rs b/serde/src/lib.rs index b9fbefed4..957dc9071 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -122,7 +122,6 @@ // things are often more readable this way clippy::cast_lossless, clippy::module_name_repetitions, - clippy::option_if_let_else, clippy::single_match_else, clippy::type_complexity, clippy::use_self, diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index dba48d4eb..70adb0674 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -50,7 +50,6 @@ clippy::match_wildcard_for_single_variants, clippy::module_name_repetitions, clippy::must_use_candidate, - clippy::option_if_let_else, clippy::similar_names, clippy::single_match_else, clippy::struct_excessive_bools, From a9a6ee9d7f2e3a3306ad7c7a8f21dcf369c6acb7 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 1 Jan 2024 23:03:34 -0800 Subject: [PATCH 039/258] Pull in proc-macro2 sccache fix --- serde_derive/Cargo.toml | 6 +++--- serde_derive_internals/Cargo.toml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index c21aabc6a..d2ff6982d 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -21,9 +21,9 @@ name = "serde_derive" proc-macro = true [dependencies] -proc-macro2 = "1.0" -quote = "1.0" -syn = "2.0.28" +proc-macro2 = "1.0.74" +quote = "1.0.35" +syn = "2.0.46" [dev-dependencies] serde = { version = "1", path = "../serde" } diff --git a/serde_derive_internals/Cargo.toml b/serde_derive_internals/Cargo.toml index c99267370..181cd4c88 100644 --- a/serde_derive_internals/Cargo.toml +++ b/serde_derive_internals/Cargo.toml @@ -15,9 +15,9 @@ rust-version = "1.56" path = "lib.rs" [dependencies] -proc-macro2 = "1.0" -quote = "1.0" -syn = { version = "2.0.28", default-features = false, features = ["clone-impls", "derive", "parsing", "printing"] } +proc-macro2 = "1.0.74" +quote = "1.0.35" +syn = { version = "2.0.46", default-features = false, features = ["clone-impls", "derive", "parsing", "printing"] } [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] From d2d977a6c6dcff237ae956336d18b0c900c61aad Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 1 Jan 2024 23:07:27 -0800 Subject: [PATCH 040/258] Release 1.0.194 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 395e08025..2f279934a 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.193" +version = "1.0.194" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--cfg", "doc_cfg", "--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.193", path = "../serde_derive" } +serde_derive = { version = "=1.0.194", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 957dc9071..a8522dd5c 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.193")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.194")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index d2ff6982d..2bb6256b3 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.193" +version = "1.0.194" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index 70adb0674..200ce8475 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.193")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.194")] // Ignored clippy lints #![allow( // clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054 From 7c65a9dc0eab2d4d829b258a7b3549351bbe8dcd Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 3 Jan 2024 18:35:30 -0800 Subject: [PATCH 041/258] Pick up changes to non_exhaustive_omitted_patterns lint warning: the lint level must be set on the whole match --> serde_derive/src/internals/attr.rs:1855:9 | 1854 | #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] | ------------------------------- remove this attribute 1855 | _ => {} | ^ | = help: it no longer has any effect to set the lint level on an individual match arm help: set the lint level on the whole match | 1796 + #[deny(non_exhaustive_omitted_patterns)] 1797 | match ty { | warning: the lint level must be set on the whole match --> serde_derive/src/internals/receiver.rs:151:13 | 150 | #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] | ------------------------------- remove this attribute 151 | _ => {} | ^ | = help: it no longer has any effect to set the lint level on an individual match arm help: set the lint level on the whole match | 109 + #[deny(non_exhaustive_omitted_patterns)] 110 | match ty { | warning: the lint level must be set on the whole match --> serde_derive/src/internals/receiver.rs:188:25 | 187 | #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] | ------------------------------- remove this attribute 188 | _ => {} | ^ | = help: it no longer has any effect to set the lint level on an individual match arm help: set the lint level on the whole match | 180 + #[deny(non_exhaustive_omitted_patterns)] 181 | match arg { | warning: the lint level must be set on the whole match --> serde_derive/src/internals/receiver.rs:213:13 | 212 | #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] | ------------------------------- remove this attribute 213 | _ => {} | ^ | = help: it no longer has any effect to set the lint level on an individual match arm help: set the lint level on the whole match | 209 + #[deny(non_exhaustive_omitted_patterns)] 210 | match bound { | warning: the lint level must be set on the whole match --> serde_derive/src/internals/receiver.rs:239:21 | 238 | #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] | ------------------------------- remove this attribute 239 | _ => {} | ^ | = help: it no longer has any effect to set the lint level on an individual match arm help: set the lint level on the whole match | 230 + #[deny(non_exhaustive_omitted_patterns)] 231 | match predicate { | warning: the lint level must be set on the whole match --> serde_derive/src/bound.rs:185:17 | 184 | #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] | ------------------------------- remove this attribute 185 | _ => {} | ^ | = help: it no longer has any effect to set the lint level on an individual match arm help: set the lint level on the whole match | 146 + #[deny(non_exhaustive_omitted_patterns)] 147 | match ty { | warning: the lint level must be set on the whole match --> serde_derive/src/bound.rs:209:29 | 207 | ... deny(non_exhaustive_omitted_patterns) | ------------------------------- remove this attribute 208 | ... )] 209 | ... _ => {} | ^ | = help: it no longer has any effect to set the lint level on an individual match arm help: set the lint level on the whole match | 198 + #[deny(non_exhaustive_omitted_patterns)] 199 | match arg { | warning: the lint level must be set on the whole match --> serde_derive/src/bound.rs:234:17 | 233 | #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] | ------------------------------- remove this attribute 234 | _ => {} | ^ | = help: it no longer has any effect to set the lint level on an individual match arm help: set the lint level on the whole match | 230 + #[deny(non_exhaustive_omitted_patterns)] 231 | match bound { | --- serde_derive/src/bound.rs | 9 +++------ serde_derive/src/internals/attr.rs | 2 +- serde_derive/src/internals/receiver.rs | 8 ++++---- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/serde_derive/src/bound.rs b/serde_derive/src/bound.rs index dd51e6898..fe8ccfff5 100644 --- a/serde_derive/src/bound.rs +++ b/serde_derive/src/bound.rs @@ -144,6 +144,7 @@ pub fn with_bound( fn visit_type(&mut self, ty: &'ast syn::Type) { match ty { + #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] syn::Type::Array(ty) => self.visit_type(&ty.elem), syn::Type::BareFn(ty) => { for arg in &ty.inputs { @@ -181,7 +182,6 @@ pub fn with_bound( syn::Type::Infer(_) | syn::Type::Never(_) | syn::Type::Verbatim(_) => {} - #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] _ => {} } } @@ -196,16 +196,13 @@ pub fn with_bound( syn::PathArguments::AngleBracketed(arguments) => { for arg in &arguments.args { match arg { + #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] syn::GenericArgument::Type(arg) => self.visit_type(arg), syn::GenericArgument::AssocType(arg) => self.visit_type(&arg.ty), syn::GenericArgument::Lifetime(_) | syn::GenericArgument::Const(_) | syn::GenericArgument::AssocConst(_) | syn::GenericArgument::Constraint(_) => {} - #[cfg_attr( - all(test, exhaustive), - deny(non_exhaustive_omitted_patterns) - )] _ => {} } } @@ -228,9 +225,9 @@ pub fn with_bound( fn visit_type_param_bound(&mut self, bound: &'ast syn::TypeParamBound) { match bound { + #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] syn::TypeParamBound::Trait(bound) => self.visit_path(&bound.path), syn::TypeParamBound::Lifetime(_) | syn::TypeParamBound::Verbatim(_) => {} - #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] _ => {} } } diff --git a/serde_derive/src/internals/attr.rs b/serde_derive/src/internals/attr.rs index 58d18b403..bb9de328a 100644 --- a/serde_derive/src/internals/attr.rs +++ b/serde_derive/src/internals/attr.rs @@ -1794,6 +1794,7 @@ fn borrowable_lifetimes( fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet) { match ty { + #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] syn::Type::Slice(ty) => { collect_lifetimes(&ty.elem, out); } @@ -1854,7 +1855,6 @@ fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet) { | syn::Type::Infer(_) | syn::Type::Verbatim(_) => {} - #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] _ => {} } } diff --git a/serde_derive/src/internals/receiver.rs b/serde_derive/src/internals/receiver.rs index 6273dfece..fa2a77d24 100644 --- a/serde_derive/src/internals/receiver.rs +++ b/serde_derive/src/internals/receiver.rs @@ -107,6 +107,7 @@ impl ReplaceReceiver<'_> { fn visit_type_mut_impl(&mut self, ty: &mut Type) { match ty { + #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] Type::Array(ty) => { self.visit_type_mut(&mut ty.elem); self.visit_expr_mut(&mut ty.len); @@ -147,7 +148,6 @@ impl ReplaceReceiver<'_> { Type::Infer(_) | Type::Never(_) | Type::Verbatim(_) => {} - #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] _ => {} } } @@ -178,13 +178,13 @@ impl ReplaceReceiver<'_> { PathArguments::AngleBracketed(arguments) => { for arg in &mut arguments.args { match arg { + #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] GenericArgument::Type(arg) => self.visit_type_mut(arg), GenericArgument::AssocType(arg) => self.visit_type_mut(&mut arg.ty), GenericArgument::Lifetime(_) | GenericArgument::Const(_) | GenericArgument::AssocConst(_) | GenericArgument::Constraint(_) => {} - #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] _ => {} } } @@ -207,9 +207,9 @@ impl ReplaceReceiver<'_> { fn visit_type_param_bound_mut(&mut self, bound: &mut TypeParamBound) { match bound { + #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] TypeParamBound::Trait(bound) => self.visit_path_mut(&mut bound.path), TypeParamBound::Lifetime(_) | TypeParamBound::Verbatim(_) => {} - #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] _ => {} } } @@ -228,6 +228,7 @@ impl ReplaceReceiver<'_> { if let Some(where_clause) = &mut generics.where_clause { for predicate in &mut where_clause.predicates { match predicate { + #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] WherePredicate::Type(predicate) => { self.visit_type_mut(&mut predicate.bounded_ty); for bound in &mut predicate.bounds { @@ -235,7 +236,6 @@ impl ReplaceReceiver<'_> { } } WherePredicate::Lifetime(_) => {} - #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] _ => {} } } From 8bc71def551df190e6817d3311e5c76f751f53e6 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 3 Jan 2024 18:38:37 -0800 Subject: [PATCH 042/258] Fill in omitted patterns for GenericArguments match error: some variants are not matched explicitly --> serde_derive/src/internals/attr.rs:1823:31 | 1823 | match arg { | ^^^ patterns `&GenericArgument::Const(_)`, `&GenericArgument::AssocConst(_)` and `&GenericArgument::Constraint(_)` not covered | = help: ensure that all variants are matched explicitly by adding the suggested match arms = note: the matched value is of type `&GenericArgument` and the `non_exhaustive_omitted_patterns` attribute was found note: the lint level is defined here --> serde_derive/src/internals/attr.rs:1797:49 | 1797 | #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --- serde_derive/src/internals/attr.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/serde_derive/src/internals/attr.rs b/serde_derive/src/internals/attr.rs index 0b25c7c0d..58d18b403 100644 --- a/serde_derive/src/internals/attr.rs +++ b/serde_derive/src/internals/attr.rs @@ -1829,7 +1829,10 @@ fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet) { syn::GenericArgument::AssocType(binding) => { collect_lifetimes(&binding.ty, out); } - _ => {} + syn::GenericArgument::Const(_) + | syn::GenericArgument::AssocConst(_) + | syn::GenericArgument::Constraint(_) + | _ => {} } } } From d883c94cc9fe72d0512dc7f4def7191a401595c9 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 5 Jan 2024 18:06:04 -0800 Subject: [PATCH 043/258] Work around dead_code warning in tests error: field `0` is never read --> test_suite/tests/test_gen.rs:690:33 | 690 | Single(#[serde(borrow)] RelObject<'a>), | ------ ^^^^^^^^^^^^^ | | | field in this variant | help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field | 690 | Single(#[serde(borrow)] ()), | ~~ error: field `0` is never read --> test_suite/tests/test_gen.rs:691:31 | 691 | Many(#[serde(borrow)] Vec>), | ---- ^^^^^^^^^^^^^^^^^^ | | | field in this variant | help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field | 691 | Many(#[serde(borrow)] ()), | ~~ --- test_suite/tests/test_gen.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_suite/tests/test_gen.rs b/test_suite/tests/test_gen.rs index 9a7c99e79..97b0a96e9 100644 --- a/test_suite/tests/test_gen.rs +++ b/test_suite/tests/test_gen.rs @@ -686,7 +686,7 @@ fn test_gen() { #[derive(Deserialize)] #[serde(untagged)] - enum UntaggedWithBorrow<'a> { + pub enum UntaggedWithBorrow<'a> { Single(#[serde(borrow)] RelObject<'a>), Many(#[serde(borrow)] Vec>), } From 6f1a8c3115c8d2502178c25d610fbaee2e82c46b Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 5 Jan 2024 18:12:20 -0800 Subject: [PATCH 044/258] Add FIXME to fix dead_code warning when using serde(remote) warning: field `0` is never read --> test_suite/tests/test_remote.rs:143:24 | 143 | struct PrimitivePubDef(u8); | --------------- ^^ | | | field in this struct | = note: `#[warn(dead_code)]` on by default help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field | 143 | struct PrimitivePubDef(()); | ~~ warning: field `0` is never read --> test_suite/tests/test_remote.rs:162:20 | 162 | struct TuplePubDef(u8, #[serde(with = "UnitDef")] remote::Unit); | ----------- ^^ | | | field in this struct | help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field | 162 | struct TuplePubDef((), #[serde(with = "UnitDef")] remote::Unit); | ~~ warning: field `0` is never read --> test_suite/tests/test_remote.rs:200:13 | 200 | Variant(u8), | ------- ^^ | | | field in this variant | help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field | 200 | Variant(()), | ~~ error: field `0` is never read --> test_suite/tests/test_gen.rs:390:23 | 390 | struct StrDef<'a>(&'a str); | ------ ^^^^^^^ | | | field in this struct | note: the lint level is defined here --> test_suite/tests/test_gen.rs:5:9 | 5 | #![deny(warnings)] | ^^^^^^^^ = note: `#[deny(dead_code)]` implied by `#[deny(warnings)]` help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field | 390 | struct StrDef<'a>(()); | ~~ --- test_suite/tests/test_gen.rs | 1 + test_suite/tests/test_remote.rs | 3 +++ 2 files changed, 4 insertions(+) diff --git a/test_suite/tests/test_gen.rs b/test_suite/tests/test_gen.rs index 97b0a96e9..eca197cd3 100644 --- a/test_suite/tests/test_gen.rs +++ b/test_suite/tests/test_gen.rs @@ -387,6 +387,7 @@ fn test_gen() { #[derive(Serialize, Deserialize)] #[serde(remote = "Str")] + #[allow(dead_code)] // FIXME struct StrDef<'a>(&'a str); #[derive(Serialize, Deserialize)] diff --git a/test_suite/tests/test_remote.rs b/test_suite/tests/test_remote.rs index c1f152eb8..0c0827c9f 100644 --- a/test_suite/tests/test_remote.rs +++ b/test_suite/tests/test_remote.rs @@ -140,6 +140,7 @@ struct PrimitivePrivDef(#[serde(getter = "remote::PrimitivePriv::get")] u8); #[derive(Serialize, Deserialize)] #[serde(remote = "remote::PrimitivePub")] +#[allow(dead_code)] // FIXME struct PrimitivePubDef(u8); #[derive(Serialize, Deserialize)] @@ -159,6 +160,7 @@ struct TuplePrivDef( #[derive(Serialize, Deserialize)] #[serde(remote = "remote::TuplePub")] +#[allow(dead_code)] // FIXME struct TuplePubDef(u8, #[serde(with = "UnitDef")] remote::Unit); #[derive(Serialize, Deserialize)] @@ -196,6 +198,7 @@ struct StructConcrete { #[derive(Serialize, Deserialize)] #[serde(remote = "remote::EnumGeneric")] +#[allow(dead_code)] // FIXME enum EnumConcrete { Variant(u8), } From 6502b3131697eff6420786ad71f87f29cfff3a13 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 5 Jan 2024 18:24:43 -0800 Subject: [PATCH 045/258] Fix new dead_code warning in tuple struct and tuple variant remote defs --- serde_derive/src/pretend.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/serde_derive/src/pretend.rs b/serde_derive/src/pretend.rs index 04868753b..2c9e77936 100644 --- a/serde_derive/src/pretend.rs +++ b/serde_derive/src/pretend.rs @@ -64,14 +64,14 @@ pub fn pretend_used(cont: &Container, is_packed: bool) -> TokenStream { fn pretend_fields_used(cont: &Container, is_packed: bool) -> TokenStream { match &cont.data { Data::Enum(variants) => pretend_fields_used_enum(cont, variants), - Data::Struct(Style::Struct, fields) => { + Data::Struct(Style::Struct | Style::Tuple | Style::Newtype, fields) => { if is_packed { pretend_fields_used_struct_packed(cont, fields) } else { pretend_fields_used_struct(cont, fields) } } - Data::Struct(_, _) => quote!(), + Data::Struct(Style::Unit, _) => quote!(), } } @@ -115,13 +115,13 @@ fn pretend_fields_used_enum(cont: &Container, variants: &[Variant]) -> TokenStre let patterns = variants .iter() .filter_map(|variant| match variant.style { - Style::Struct => { + Style::Struct | Style::Tuple | Style::Newtype => { 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, + Style::Unit => None, }) .collect::>(); From 38d9e0b2091e9b6150486c2c37367819b86bcc39 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 5 Jan 2024 18:19:12 -0800 Subject: [PATCH 046/258] Revert "Add FIXME to fix dead_code warning when using serde(remote)" --- test_suite/tests/test_gen.rs | 1 - test_suite/tests/test_remote.rs | 3 --- 2 files changed, 4 deletions(-) diff --git a/test_suite/tests/test_gen.rs b/test_suite/tests/test_gen.rs index eca197cd3..97b0a96e9 100644 --- a/test_suite/tests/test_gen.rs +++ b/test_suite/tests/test_gen.rs @@ -387,7 +387,6 @@ fn test_gen() { #[derive(Serialize, Deserialize)] #[serde(remote = "Str")] - #[allow(dead_code)] // FIXME struct StrDef<'a>(&'a str); #[derive(Serialize, Deserialize)] diff --git a/test_suite/tests/test_remote.rs b/test_suite/tests/test_remote.rs index 0c0827c9f..c1f152eb8 100644 --- a/test_suite/tests/test_remote.rs +++ b/test_suite/tests/test_remote.rs @@ -140,7 +140,6 @@ struct PrimitivePrivDef(#[serde(getter = "remote::PrimitivePriv::get")] u8); #[derive(Serialize, Deserialize)] #[serde(remote = "remote::PrimitivePub")] -#[allow(dead_code)] // FIXME struct PrimitivePubDef(u8); #[derive(Serialize, Deserialize)] @@ -160,7 +159,6 @@ struct TuplePrivDef( #[derive(Serialize, Deserialize)] #[serde(remote = "remote::TuplePub")] -#[allow(dead_code)] // FIXME struct TuplePubDef(u8, #[serde(with = "UnitDef")] remote::Unit); #[derive(Serialize, Deserialize)] @@ -198,7 +196,6 @@ struct StructConcrete { #[derive(Serialize, Deserialize)] #[serde(remote = "remote::EnumGeneric")] -#[allow(dead_code)] // FIXME enum EnumConcrete { Variant(u8), } From 03eec42c3313b36da416be1486e9ecac345784d5 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 5 Jan 2024 18:33:24 -0800 Subject: [PATCH 047/258] Release 1.0.195 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 2f279934a..c2b46f7d0 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.194" +version = "1.0.195" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--cfg", "doc_cfg", "--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.194", path = "../serde_derive" } +serde_derive = { version = "=1.0.195", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index a8522dd5c..b0756af6d 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.194")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.195")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 2bb6256b3..b58142a1b 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.194" +version = "1.0.195" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index 200ce8475..8c4a6cacc 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.194")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.195")] // Ignored clippy lints #![allow( // clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054 From 0024f74f34fbbdc44a7b22457faebe36c5cbe7f8 Mon Sep 17 00:00:00 2001 From: Sky Date: Mon, 8 Jan 2024 22:22:03 -0500 Subject: [PATCH 048/258] Use shields.io's MSRV badges --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 477fd3647..31292944a 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -# Serde   [![Build Status]][actions] [![Latest Version]][crates.io] [![serde: rustc 1.31+]][Rust 1.31] [![serde_derive: rustc 1.56+]][Rust 1.56] +# Serde   [![Build Status]][actions] [![Latest Version]][crates.io] [![serde msrv]][Rust 1.31] [![serde_derive msrv]][Rust 1.56] [Build Status]: https://img.shields.io/github/actions/workflow/status/serde-rs/serde/ci.yml?branch=master [actions]: https://github.com/serde-rs/serde/actions?query=branch%3Amaster [Latest Version]: https://img.shields.io/crates/v/serde.svg [crates.io]: https://crates.io/crates/serde -[serde: rustc 1.31+]: https://img.shields.io/badge/serde-rustc_1.31+-lightgray.svg -[serde_derive: rustc 1.56+]: https://img.shields.io/badge/serde_derive-rustc_1.56+-lightgray.svg +[serde msrv]: https://img.shields.io/crates/msrv/serde.svg?label=serde%20msrv&color=lightgray +[serde_derive msrv]: https://img.shields.io/crates/msrv/serde_derive.svg?label=serde_derive%20msrv&color=lightgray [Rust 1.31]: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html [Rust 1.56]: https://blog.rust-lang.org/2021/10/21/Rust-1.56.0.html From dd619630a337139424725697ccd9a9f7596a2d3a Mon Sep 17 00:00:00 2001 From: Rodolfo P A <6721075+rodoufu@users.noreply.github.com> Date: Tue, 23 Jan 2024 12:53:29 +0000 Subject: [PATCH 049/258] Adding workspace dependencies --- Cargo.toml | 5 +++++ serde_derive/Cargo.toml | 6 +++--- serde_derive_internals/Cargo.toml | 6 +++--- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 727dc484f..521e1f206 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,3 +8,8 @@ members = [ [patch.crates-io] serde = { path = "serde" } + +[workspace.dependencies] +syn = "2.0.46" +quote = "1.0.35" +proc-macro2 = "1.0.74" diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index b58142a1b..701456c57 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -21,9 +21,9 @@ name = "serde_derive" proc-macro = true [dependencies] -proc-macro2 = "1.0.74" -quote = "1.0.35" -syn = "2.0.46" +proc-macro2 = { workspace = true } +quote = { workspace = true } +syn = { workspace = true } [dev-dependencies] serde = { version = "1", path = "../serde" } diff --git a/serde_derive_internals/Cargo.toml b/serde_derive_internals/Cargo.toml index 181cd4c88..91ee26133 100644 --- a/serde_derive_internals/Cargo.toml +++ b/serde_derive_internals/Cargo.toml @@ -15,9 +15,9 @@ rust-version = "1.56" path = "lib.rs" [dependencies] -proc-macro2 = "1.0.74" -quote = "1.0.35" -syn = { version = "2.0.46", default-features = false, features = ["clone-impls", "derive", "parsing", "printing"] } +proc-macro2 = { workspace = true } +quote = { workspace = true } +syn = { workspace = true, default-features = false, features = ["clone-impls", "derive", "parsing", "printing"] } [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] From aecb4083bde754155752f5d7d442b64eb7dc636f Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 23 Jan 2024 10:08:00 -0800 Subject: [PATCH 050/258] Sort workspace dependencies --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 521e1f206..877467be7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,6 @@ members = [ serde = { path = "serde" } [workspace.dependencies] -syn = "2.0.46" -quote = "1.0.35" proc-macro2 = "1.0.74" +quote = "1.0.35" +syn = "2.0.46" From 29d9f693996d199748136d5561a971ed68626724 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 26 Jan 2024 13:33:14 -0800 Subject: [PATCH 051/258] Fix workspace.dependencies default-features future compat warning warning: serde_derive_internals/Cargo.toml: `default-features` is ignored for syn, since `default-features` was not specified for `workspace.dependencies.syn`, this could become a hard error in the future --- Cargo.toml | 6 +++--- serde_derive/Cargo.toml | 6 +++--- serde_derive_internals/Cargo.toml | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 877467be7..ac94fb08c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,6 @@ members = [ serde = { path = "serde" } [workspace.dependencies] -proc-macro2 = "1.0.74" -quote = "1.0.35" -syn = "2.0.46" +proc-macro2 = { version = "1.0.74", default-features = false } +quote = { version = "1.0.35", default-features = false } +syn = { version = "2.0.46", default-features = false } diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 701456c57..8e50c9eab 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -21,9 +21,9 @@ name = "serde_derive" proc-macro = true [dependencies] -proc-macro2 = { workspace = true } -quote = { workspace = true } -syn = { workspace = true } +proc-macro2 = { workspace = true, features = ["proc-macro"] } +quote = { workspace = true, features = ["proc-macro"] } +syn = { workspace = true, features = ["clone-impls", "derive", "parsing", "printing", "proc-macro"] } [dev-dependencies] serde = { version = "1", path = "../serde" } diff --git a/serde_derive_internals/Cargo.toml b/serde_derive_internals/Cargo.toml index 91ee26133..6ce277974 100644 --- a/serde_derive_internals/Cargo.toml +++ b/serde_derive_internals/Cargo.toml @@ -17,7 +17,7 @@ path = "lib.rs" [dependencies] proc-macro2 = { workspace = true } quote = { workspace = true } -syn = { workspace = true, default-features = false, features = ["clone-impls", "derive", "parsing", "printing"] } +syn = { workspace = true, features = ["clone-impls", "derive", "parsing", "printing"] } [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] From bef110b92a171ac568a47339f5bd97938a8c9da2 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 26 Jan 2024 13:28:54 -0800 Subject: [PATCH 052/258] Format Unexpected::Float with decimal point --- serde/src/de/mod.rs | 35 ++++++++++++++++++++++++++++++- serde/src/lib.rs | 2 +- test_suite/tests/test_de_error.rs | 2 +- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index c9919d92b..6efeaaeec 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -402,7 +402,7 @@ impl<'a> fmt::Display for Unexpected<'a> { Bool(b) => write!(formatter, "boolean `{}`", b), Unsigned(i) => write!(formatter, "integer `{}`", i), Signed(i) => write!(formatter, "integer `{}`", i), - Float(f) => write!(formatter, "floating point `{}`", f), + Float(f) => write!(formatter, "floating point `{}`", WithDecimalPoint(f)), Char(c) => write!(formatter, "character `{}`", c), Str(s) => write!(formatter, "string {:?}", s), Bytes(_) => write!(formatter, "byte array"), @@ -2290,3 +2290,36 @@ impl Display for OneOf { } } } + +struct WithDecimalPoint(f64); + +impl Display for WithDecimalPoint { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + struct LookForDecimalPoint<'f, 'a> { + formatter: &'f mut fmt::Formatter<'a>, + has_decimal_point: bool, + } + + impl<'f, 'a> fmt::Write for LookForDecimalPoint<'f, 'a> { + fn write_str(&mut self, fragment: &str) -> fmt::Result { + self.has_decimal_point |= fragment.contains('.'); + self.formatter.write_str(fragment) + } + + fn write_char(&mut self, ch: char) -> fmt::Result { + self.has_decimal_point |= ch == '.'; + self.formatter.write_char(ch) + } + } + + let mut writer = LookForDecimalPoint { + formatter, + has_decimal_point: false, + }; + tri!(write!(writer, "{}", self.0)); + if !writer.has_decimal_point { + tri!(formatter.write_str(".0")); + } + Ok(()) + } +} diff --git a/serde/src/lib.rs b/serde/src/lib.rs index b0756af6d..1a17a25ae 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -182,7 +182,7 @@ mod lib { pub use self::core::cmp::Reverse; pub use self::core::convert::{self, From, Into}; pub use self::core::default::{self, Default}; - pub use self::core::fmt::{self, Debug, Display}; + pub use self::core::fmt::{self, Debug, Display, Write as FmtWrite}; pub use self::core::marker::{self, PhantomData}; pub use self::core::num::Wrapping; pub use self::core::ops::{Bound, Range, RangeFrom, RangeInclusive, RangeTo}; diff --git a/test_suite/tests/test_de_error.rs b/test_suite/tests/test_de_error.rs index d4449fdd8..d1ea2b910 100644 --- a/test_suite/tests/test_de_error.rs +++ b/test_suite/tests/test_de_error.rs @@ -1434,7 +1434,7 @@ fn test_number_from_string() { fn test_integer_from_float() { assert_de_tokens_error::( &[Token::F32(0.0)], - "invalid type: floating point `0`, expected isize", + "invalid type: floating point `0.0`, expected isize", ); } From ede9762a583c3cc3b87c10a53551828fad339525 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 26 Jan 2024 14:00:35 -0800 Subject: [PATCH 053/258] Release 1.0.196 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index c2b46f7d0..41967fefe 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.195" +version = "1.0.196" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--cfg", "doc_cfg", "--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.195", path = "../serde_derive" } +serde_derive = { version = "=1.0.196", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 1a17a25ae..5eb44311d 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.195")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.196")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 8e50c9eab..1bfecd808 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.195" +version = "1.0.196" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index 8c4a6cacc..db21f54b3 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.195")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.196")] // Ignored clippy lints #![allow( // clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054 From 846f865de2e94408e0edc6a2c6863c063cd234be Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 7 Feb 2024 22:15:14 -0800 Subject: [PATCH 054/258] Ignore dead_code warnings in test warning: trait `AssertNotSerdeSerialize` is never used --> test_suite/tests/test_serde_path.rs:39:7 | 39 | trait AssertNotSerdeSerialize {} | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(dead_code)]` on by default warning: trait `AssertNotSerdeDeserialize` is never used --> test_suite/tests/test_serde_path.rs:43:7 | 43 | trait AssertNotSerdeDeserialize<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: method `serialize` is never used --> test_suite/tests/test_serde_path.rs:31:12 | 30 | pub trait Serialize { | --------- method in this trait 31 | fn serialize(&self, serializer: S) -> Result; | ^^^^^^^^^ warning: associated function `deserialize` is never used --> test_suite/tests/test_serde_path.rs:35:12 | 34 | pub trait Deserialize<'a>: Sized { | ----------- associated function in this trait 35 | fn deserialize>(deserializer: D) -> Result; | ^^^^^^^^^^^ --- test_suite/tests/test_serde_path.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test_suite/tests/test_serde_path.rs b/test_suite/tests/test_serde_path.rs index a87e49d91..127b557ec 100644 --- a/test_suite/tests/test_serde_path.rs +++ b/test_suite/tests/test_serde_path.rs @@ -27,19 +27,21 @@ mod fake_serde { { } + #[allow(dead_code)] pub trait Serialize { fn serialize(&self, serializer: S) -> Result; } + #[allow(dead_code)] pub trait Deserialize<'a>: Sized { fn deserialize>(deserializer: D) -> Result; } } -trait AssertNotSerdeSerialize {} +pub trait AssertNotSerdeSerialize {} impl AssertNotSerdeSerialize for T {} -trait AssertNotSerdeDeserialize<'a> {} +pub trait AssertNotSerdeDeserialize<'a> {} impl<'a, T: serde::Deserialize<'a>> AssertNotSerdeDeserialize<'a> for T {} From 9e680620b595724a6abfb8e785155d02482f911a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 9 Feb 2024 18:55:51 -0800 Subject: [PATCH 055/258] Ignore incompatible_msrv clippy lint for conditionally compiled code warning: current MSRV (Minimum Supported Rust Version) is `1.31.0` but this item is stable since `1.35.0` --> serde/src/de/impls.rs:200:39 | 200 | Ok((v as Self::Value).copysign(sign)) | ^^^^^^^^^^^^^^ ... 374 | / impl_deserialize_num! { 375 | | f32, deserialize_f32 376 | | num_self!(f32:visit_f32); 377 | | num_as_copysign_self!(f64:visit_f64); 378 | | num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); 379 | | num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); 380 | | } | |_- in this macro invocation | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#incompatible_msrv = note: `-W clippy::incompatible-msrv` implied by `-W clippy::all` = help: to override `-W clippy::all` add `#[allow(clippy::incompatible_msrv)]` = note: this warning originates in the macro `num_as_copysign_self` which comes from the expansion of the macro `impl_deserialize_num` (in Nightly builds, run with -Z macro-backtrace for more info) warning: current MSRV (Minimum Supported Rust Version) is `1.31.0` but this item is stable since `1.35.0` --> serde/src/de/impls.rs:200:39 | 200 | Ok((v as Self::Value).copysign(sign)) | ^^^^^^^^^^^^^^ ... 382 | / impl_deserialize_num! { 383 | | f64, deserialize_f64 384 | | num_self!(f64:visit_f64); 385 | | num_as_copysign_self!(f32:visit_f32); 386 | | num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); 387 | | num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); 388 | | } | |_- in this macro invocation | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#incompatible_msrv = note: this warning originates in the macro `num_as_copysign_self` which comes from the expansion of the macro `impl_deserialize_num` (in Nightly builds, run with -Z macro-backtrace for more info) warning: current MSRV (Minimum Supported Rust Version) is `1.31.0` but this item is stable since `1.34.0` --> serde/src/de/impls.rs:2308:14 | 2308 | .checked_add(duration) | ^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#incompatible_msrv warning: current MSRV (Minimum Supported Rust Version) is `1.31.0` but this item is stable since `1.34.0` --> serde/src/ser/impls.rs:606:26 | 606 | self.get().serialize(serializer) | ^^^^^ ... 623 | / nonzero_integers! { 624 | | NonZeroI8, 625 | | NonZeroI16, 626 | | NonZeroI32, ... | 629 | | NonZeroIsize, 630 | | } | |_- in this macro invocation | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#incompatible_msrv = note: this warning originates in the macro `nonzero_integers` (in Nightly builds, run with -Z macro-backtrace for more info) warning: current MSRV (Minimum Supported Rust Version) is `1.31.0` but this item is stable since `1.34.0` --> serde/src/ser/impls.rs:1053:26 | 1053 | self.load(Ordering::Relaxed).serialize(serializer) | ^^^^^^^^^^^^^^^^^^^^^^^ ... 1061 | / atomic_impl! { 1062 | | AtomicBool "8" 1063 | | AtomicI8 "8" 1064 | | AtomicI16 "16" ... | 1070 | | AtomicUsize "ptr" 1071 | | } | |_- in this macro invocation | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#incompatible_msrv = note: this warning originates in the macro `atomic_impl` (in Nightly builds, run with -Z macro-backtrace for more info) warning: current MSRV (Minimum Supported Rust Version) is `1.31.0` but this item is stable since `1.34.0` --> serde/src/ser/impls.rs:1053:26 | 1053 | self.load(Ordering::Relaxed).serialize(serializer) | ^^^^^^^^^^^^^^^^^^^^^^^ ... 1074 | / atomic_impl! { 1075 | | AtomicI64 "64" 1076 | | AtomicU64 "64" 1077 | | } | |_- in this macro invocation | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#incompatible_msrv = note: this warning originates in the macro `atomic_impl` (in Nightly builds, run with -Z macro-backtrace for more info) --- serde/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 5eb44311d..6d66d8e1c 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -130,6 +130,7 @@ clippy::derive_partial_eq_without_eq, clippy::enum_glob_use, clippy::explicit_auto_deref, + clippy::incompatible_msrv, clippy::let_underscore_untyped, clippy::map_err_ignore, clippy::new_without_default, From c42ebb8839fbd92dbda6729e8363c8d683f26306 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 11 Feb 2024 20:00:23 -0800 Subject: [PATCH 056/258] Update ui test suite to nightly-2024-02-12 --- test_suite/tests/ui/remote/wrong_de.stderr | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test_suite/tests/ui/remote/wrong_de.stderr b/test_suite/tests/ui/remote/wrong_de.stderr index 314f2b395..be7b78783 100644 --- a/test_suite/tests/ui/remote/wrong_de.stderr +++ b/test_suite/tests/ui/remote/wrong_de.stderr @@ -12,7 +12,3 @@ note: tuple struct defined here 4 | pub struct S(pub u16); | ^ = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info) -help: you can convert a `u8` to a `u16` - | -7 | #[derive(Deserialize.into())] - | +++++++ From b8fafefd8588f84af54329945fab701ec414281d Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Mon, 12 Feb 2024 16:06:43 -0500 Subject: [PATCH 057/258] A few minor `write_str` optimizations and inlining Apparently `write!` generates more code than `write_str` when used with a simple string, so optimizing it. --- serde/src/de/mod.rs | 26 +++++++++++++------------- serde/src/de/value.rs | 4 ++-- test_suite/tests/test_value.rs | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index 6efeaaeec..1924fe3d8 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -405,17 +405,17 @@ impl<'a> fmt::Display for Unexpected<'a> { Float(f) => write!(formatter, "floating point `{}`", WithDecimalPoint(f)), Char(c) => write!(formatter, "character `{}`", c), Str(s) => write!(formatter, "string {:?}", s), - Bytes(_) => write!(formatter, "byte array"), - Unit => write!(formatter, "unit value"), - Option => write!(formatter, "Option value"), - NewtypeStruct => write!(formatter, "newtype struct"), - Seq => write!(formatter, "sequence"), - Map => write!(formatter, "map"), - Enum => write!(formatter, "enum"), - UnitVariant => write!(formatter, "unit variant"), - NewtypeVariant => write!(formatter, "newtype variant"), - TupleVariant => write!(formatter, "tuple variant"), - StructVariant => write!(formatter, "struct variant"), + Bytes(_) => formatter.write_str("byte array"), + Unit => formatter.write_str("unit value"), + Option => formatter.write_str("Option value"), + NewtypeStruct => formatter.write_str("newtype struct"), + Seq => formatter.write_str("sequence"), + Map => formatter.write_str("map"), + Enum => formatter.write_str("enum"), + UnitVariant => formatter.write_str("unit variant"), + NewtypeVariant => formatter.write_str("newtype variant"), + TupleVariant => formatter.write_str("tuple variant"), + StructVariant => formatter.write_str("struct variant"), Other(other) => formatter.write_str(other), } } @@ -2278,10 +2278,10 @@ impl Display for OneOf { 1 => write!(formatter, "`{}`", self.names[0]), 2 => write!(formatter, "`{}` or `{}`", self.names[0], self.names[1]), _ => { - tri!(write!(formatter, "one of ")); + tri!(formatter.write_str("one of ")); for (i, alt) in self.names.iter().enumerate() { if i > 0 { - tri!(write!(formatter, ", ")); + tri!(formatter.write_str(", ")); } tri!(write!(formatter, "`{}`", alt)); } diff --git a/serde/src/de/value.rs b/serde/src/de/value.rs index b229ebab7..3bc0c71c5 100644 --- a/serde/src/de/value.rs +++ b/serde/src/de/value.rs @@ -983,7 +983,7 @@ struct ExpectedInSeq(usize); impl Expected for ExpectedInSeq { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { if self.0 == 1 { - write!(formatter, "1 element in sequence") + formatter.write_str("1 element in sequence") } else { write!(formatter, "{} elements in sequence", self.0) } @@ -1411,7 +1411,7 @@ struct ExpectedInMap(usize); impl Expected for ExpectedInMap { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { if self.0 == 1 { - write!(formatter, "1 element in map") + formatter.write_str("1 element in map") } else { write!(formatter, "{} elements in map", self.0) } diff --git a/test_suite/tests/test_value.rs b/test_suite/tests/test_value.rs index 15d25401a..3a1922c0f 100644 --- a/test_suite/tests/test_value.rs +++ b/test_suite/tests/test_value.rs @@ -63,7 +63,7 @@ fn test_map_access_to_enum() { type Value = Potential; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "a map") + formatter.write_str("a map") } fn visit_map(self, map: A) -> Result From f5d8ae423aa195d3423029ff5a618266cc8ff9a5 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 19 Feb 2024 16:10:06 -0800 Subject: [PATCH 058/258] Resolve prelude redundant import warnings warning: the item `Into` is imported redundantly --> serde/src/lib.rs:184:47 | 184 | pub use self::core::convert::{self, From, Into}; | ^^^^ | ::: nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/prelude/mod.rs:115:13 | 115 | pub use super::v1::*; | --------- the item `Into` is already defined here | = note: `#[warn(unused_imports)]` on by default --- serde/src/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 6d66d8e1c..307e8c7b7 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -179,16 +179,16 @@ mod lib { pub use self::core::{cmp, mem, slice}; pub use self::core::cell::{Cell, RefCell}; - pub use self::core::clone::{self, Clone}; + pub use self::core::clone; pub use self::core::cmp::Reverse; - pub use self::core::convert::{self, From, Into}; - pub use self::core::default::{self, Default}; + pub use self::core::convert; + pub use self::core::default; pub use self::core::fmt::{self, Debug, Display, Write as FmtWrite}; pub use self::core::marker::{self, PhantomData}; pub use self::core::num::Wrapping; pub use self::core::ops::{Bound, Range, RangeFrom, RangeInclusive, RangeTo}; - pub use self::core::option::{self, Option}; - pub use self::core::result::{self, Result}; + pub use self::core::option; + pub use self::core::result; pub use self::core::time::Duration; #[cfg(all(feature = "alloc", not(feature = "std")))] From 5fa711d75d91173aafc6019e03cf8af6ac9ba7b2 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 19 Feb 2024 16:22:07 -0800 Subject: [PATCH 059/258] Release 1.0.197 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 41967fefe..73732672f 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.196" +version = "1.0.197" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--cfg", "doc_cfg", "--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.196", path = "../serde_derive" } +serde_derive = { version = "=1.0.197", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 307e8c7b7..5cf44c1c1 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.196")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.197")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 1bfecd808..cd3c4b798 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.196" +version = "1.0.197" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index db21f54b3..b91f17b1a 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.196")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.197")] // Ignored clippy lints #![allow( // clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054 From c9cab490f7a3c1038fb5d5bc93d87737228300f8 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 27 Feb 2024 22:37:04 -0800 Subject: [PATCH 060/258] Resolve multiple_bound_locations clippy lint warning: bound is defined in more than one place --> serde/src/ser/fmt.rs:77:33 | 77 | fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> fmt::Result | ^ 78 | where 79 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations = note: `-W clippy::multiple-bound-locations` implied by `-W clippy::all` = help: to override `-W clippy::all` add `#[allow(clippy::multiple_bound_locations)]` warning: bound is defined in more than one place --> serde/src/ser/fmt.rs:92:23 | 92 | fn serialize_some(self, _value: &T) -> fmt::Result | ^ 93 | where 94 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/ser/fmt.rs:103:34 | 103 | fn serialize_newtype_variant( | ^ ... 111 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/ser/fmt.rs:164:20 | 164 | fn collect_str(self, value: &T) -> fmt::Result | ^ 165 | where 166 | T: Display, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/ser/impossible.rs:75:26 | 75 | fn serialize_element(&mut self, value: &T) -> Result<(), Error> | ^ 76 | where 77 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/ser/impossible.rs:95:26 | 95 | fn serialize_element(&mut self, value: &T) -> Result<(), Error> | ^ 96 | where 97 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/ser/impossible.rs:115:24 | 115 | fn serialize_field(&mut self, value: &T) -> Result<(), Error> | ^ 116 | where 117 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/ser/impossible.rs:135:24 | 135 | fn serialize_field(&mut self, value: &T) -> Result<(), Error> | ^ 136 | where 137 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/ser/impossible.rs:155:22 | 155 | fn serialize_key(&mut self, key: &T) -> Result<(), Error> | ^ 156 | where 157 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/ser/impossible.rs:163:24 | 163 | fn serialize_value(&mut self, value: &T) -> Result<(), Error> | ^ 164 | where 165 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/ser/impossible.rs:183:24 | 183 | fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Error> | ^ 184 | where 185 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/ser/impossible.rs:204:24 | 204 | fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Error> | ^ 205 | where 206 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/ser/mod.rs:799:23 | 799 | fn serialize_some(self, value: &T) -> Result | ^ 800 | where 801 | T: Serialize; | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/ser/mod.rs:894:33 | 894 | fn serialize_newtype_struct( | ^ ... 900 | T: Serialize; | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/ser/mod.rs:928:34 | 928 | fn serialize_newtype_variant( | ^ ... 936 | T: Serialize; | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/ser/mod.rs:1349:20 | 1349 | fn collect_str(self, value: &T) -> Result | ^ 1350 | where 1351 | T: Display, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/ser/mod.rs:1496:26 | 1496 | fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> | ^ 1497 | where 1498 | T: Serialize; | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/ser/mod.rs:1596:26 | 1596 | fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> | ^ 1597 | where 1598 | T: Serialize; | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/ser/mod.rs:1641:24 | 1641 | fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> | ^ 1642 | where 1643 | T: Serialize; | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/ser/mod.rs:1699:24 | 1699 | fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> | ^ 1700 | where 1701 | T: Serialize; | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/ser/mod.rs:1770:22 | 1770 | fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> | ^ 1771 | where 1772 | T: Serialize; | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/ser/mod.rs:1780:24 | 1780 | fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> | ^ 1781 | where 1782 | T: Serialize; | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/ser/mod.rs:1801:24 | 1801 | fn serialize_entry( | ^ ... 1807 | K: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/ser/mod.rs:1801:35 | 1801 | fn serialize_entry( | ^ ... 1808 | V: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/ser/mod.rs:1859:24 | 1859 | fn serialize_field( | ^ ... 1865 | T: Serialize; | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/ser/mod.rs:1925:24 | 1925 | fn serialize_field( | ^ ... 1931 | T: Serialize; | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:177:23 | 177 | fn serialize_some(self, _: &T) -> Result | ^ 178 | where 179 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:208:33 | 208 | fn serialize_newtype_struct( | ^ ... 214 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:219:34 | 219 | fn serialize_newtype_variant( | ^ ... 227 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:367:28 | 367 | fn serialize_field(&mut self, value: &T) -> Result<(), M::Error> | ^ 368 | where 369 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:407:28 | 407 | fn serialize_field( | ^ ... 413 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:638:27 | 638 | fn serialize_some(self, value: &T) -> Result | ^ 639 | where 640 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:662:37 | 662 | fn serialize_newtype_struct( | ^ ... 668 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:676:38 | 676 | fn serialize_newtype_variant( | ^ ... 684 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:785:30 | 785 | fn serialize_element(&mut self, value: &T) -> Result<(), E> | ^ 786 | where 787 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:811:30 | 811 | fn serialize_element(&mut self, value: &T) -> Result<(), E> | ^ 812 | where 813 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:838:28 | 838 | fn serialize_field(&mut self, value: &T) -> Result<(), E> | ^ 839 | where 840 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:867:28 | 867 | fn serialize_field(&mut self, value: &T) -> Result<(), E> | ^ 868 | where 869 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:899:26 | 899 | fn serialize_key(&mut self, key: &T) -> Result<(), E> | ^ 900 | where 901 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:908:28 | 908 | fn serialize_value(&mut self, value: &T) -> Result<(), E> | ^ 909 | where 910 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:925:28 | 925 | fn serialize_entry(&mut self, key: &K, value: &V) -> Result<(), E> | ^ 926 | where 927 | K: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:925:39 | 925 | fn serialize_entry(&mut self, key: &K, value: &V) -> Result<(), E> | ^ ... 928 | V: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:950:28 | 950 | fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), E> | ^ 951 | where 952 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:979:28 | 979 | fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), E> | ^ 980 | where 981 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:1091:23 | 1091 | fn serialize_some(self, value: &T) -> Result | ^ 1092 | where 1093 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:1115:33 | 1115 | fn serialize_newtype_struct( | ^ ... 1121 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:1126:34 | 1126 | fn serialize_newtype_variant( | ^ ... 1134 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:1205:22 | 1205 | fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> | ^ 1206 | where 1207 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:1212:24 | 1212 | fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> | ^ 1213 | where 1214 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:1219:24 | 1219 | fn serialize_entry( | ^ ... 1225 | K: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:1219:35 | 1219 | fn serialize_entry( | ^ ... 1226 | V: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:1247:24 | 1247 | fn serialize_field( | ^ ... 1253 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:1292:24 | 1292 | fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> | ^ 1293 | where 1294 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations warning: bound is defined in more than one place --> serde/src/private/ser.rs:1338:24 | 1338 | fn serialize_field( | ^ ... 1344 | T: Serialize, | ^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations --- serde/src/de/impls.rs | 17 +++-- serde/src/de/mod.rs | 8 +-- serde/src/private/doc.rs | 5 +- serde/src/private/ser.rs | 132 +++++++++++++++--------------------- serde/src/ser/fmt.rs | 16 ++--- serde/src/ser/impls.rs | 37 +++++----- serde/src/ser/impossible.rs | 32 ++++----- serde/src/ser/mod.rs | 70 ++++++++----------- 8 files changed, 149 insertions(+), 168 deletions(-) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 413c997af..c866c90e5 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -852,7 +852,10 @@ struct PhantomDataVisitor { marker: PhantomData, } -impl<'de, T: ?Sized> Visitor<'de> for PhantomDataVisitor { +impl<'de, T> Visitor<'de> for PhantomDataVisitor +where + T: ?Sized, +{ type Value = PhantomData; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { @@ -868,7 +871,10 @@ impl<'de, T: ?Sized> Visitor<'de> for PhantomDataVisitor { } } -impl<'de, T: ?Sized> Deserialize<'de> for PhantomData { +impl<'de, T> Deserialize<'de> for PhantomData +where + T: ?Sized, +{ fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, @@ -1877,9 +1883,9 @@ forwarded_impl! { #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] -impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T> +impl<'de, 'a, T> Deserialize<'de> for Cow<'a, T> where - T: ToOwned, + T: ?Sized + ToOwned, T::Owned: Deserialize<'de>, { #[inline] @@ -1945,8 +1951,9 @@ macro_rules! box_forwarded_impl { $t:ident ) => { $(#[$attr])* - impl<'de, T: ?Sized> Deserialize<'de> for $t + impl<'de, T> Deserialize<'de> for $t where + T: ?Sized, Box: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index 1924fe3d8..4c5a5f9b7 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -1735,9 +1735,9 @@ pub trait SeqAccess<'de> { } } -impl<'de, 'a, A: ?Sized> SeqAccess<'de> for &'a mut A +impl<'de, 'a, A> SeqAccess<'de> for &'a mut A where - A: SeqAccess<'de>, + A: ?Sized + SeqAccess<'de>, { type Error = A::Error; @@ -1888,9 +1888,9 @@ pub trait MapAccess<'de> { } } -impl<'de, 'a, A: ?Sized> MapAccess<'de> for &'a mut A +impl<'de, 'a, A> MapAccess<'de> for &'a mut A where - A: MapAccess<'de>, + A: ?Sized + MapAccess<'de>, { type Error = A::Error; diff --git a/serde/src/private/doc.rs b/serde/src/private/doc.rs index 1b18fe6b4..1f17c8db5 100644 --- a/serde/src/private/doc.rs +++ b/serde/src/private/doc.rs @@ -56,7 +56,10 @@ macro_rules! __serialize_unimplemented { #[macro_export] macro_rules! __serialize_unimplemented_method { ($func:ident $(<$t:ident>)* ($($arg:ty),*) -> $ret:ident) => { - fn $func $(<$t: ?Sized + $crate::Serialize>)* (self $(, _: $arg)*) -> $crate::__private::Result { + fn $func $(<$t>)* (self $(, _: $arg)*) -> $crate::__private::Result + where + $($t: ?Sized + $crate::Serialize,)* + { unimplemented!() } }; diff --git a/serde/src/private/ser.rs b/serde/src/private/ser.rs index 50bcb251e..40cc6cbdb 100644 --- a/serde/src/private/ser.rs +++ b/serde/src/private/ser.rs @@ -174,9 +174,9 @@ where Err(self.bad_type(Unsupported::Optional)) } - fn serialize_some(self, _: &T) -> Result + fn serialize_some(self, _: &T) -> Result where - T: Serialize, + T: ?Sized + Serialize, { Err(self.bad_type(Unsupported::Optional)) } @@ -205,18 +205,18 @@ where map.end() } - fn serialize_newtype_struct( + fn serialize_newtype_struct( self, _: &'static str, value: &T, ) -> Result where - T: Serialize, + T: ?Sized + Serialize, { value.serialize(self) } - fn serialize_newtype_variant( + fn serialize_newtype_variant( self, _: &'static str, _: u32, @@ -224,7 +224,7 @@ where inner_value: &T, ) -> Result where - T: Serialize, + T: ?Sized + Serialize, { let mut map = tri!(self.delegate.serialize_map(Some(2))); tri!(map.serialize_entry(self.tag, self.variant_name)); @@ -327,9 +327,9 @@ where } #[cfg(not(any(feature = "std", feature = "alloc")))] - fn collect_str(self, _: &T) -> Result + fn collect_str(self, _: &T) -> Result where - T: Display, + T: ?Sized + Display, { Err(self.bad_type(Unsupported::String)) } @@ -364,9 +364,9 @@ mod content { type Ok = M::Ok; type Error = M::Error; - fn serialize_field(&mut self, value: &T) -> Result<(), M::Error> + fn serialize_field(&mut self, value: &T) -> Result<(), M::Error> where - T: Serialize, + T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push(value); @@ -404,13 +404,9 @@ mod content { type Ok = M::Ok; type Error = M::Error; - fn serialize_field( - &mut self, - key: &'static str, - value: &T, - ) -> Result<(), M::Error> + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), M::Error> where - T: Serialize, + T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push((key, value)); @@ -635,9 +631,9 @@ mod content { Ok(Content::None) } - fn serialize_some(self, value: &T) -> Result + fn serialize_some(self, value: &T) -> Result where - T: Serialize, + T: ?Sized + Serialize, { Ok(Content::Some(Box::new(tri!(value.serialize(self))))) } @@ -659,13 +655,9 @@ mod content { Ok(Content::UnitVariant(name, variant_index, variant)) } - fn serialize_newtype_struct( - self, - name: &'static str, - value: &T, - ) -> Result + fn serialize_newtype_struct(self, name: &'static str, value: &T) -> Result where - T: Serialize, + T: ?Sized + Serialize, { Ok(Content::NewtypeStruct( name, @@ -673,7 +665,7 @@ mod content { )) } - fn serialize_newtype_variant( + fn serialize_newtype_variant( self, name: &'static str, variant_index: u32, @@ -681,7 +673,7 @@ mod content { value: &T, ) -> Result where - T: Serialize, + T: ?Sized + Serialize, { Ok(Content::NewtypeVariant( name, @@ -782,9 +774,9 @@ mod content { type Ok = Content; type Error = E; - fn serialize_element(&mut self, value: &T) -> Result<(), E> + fn serialize_element(&mut self, value: &T) -> Result<(), E> where - T: Serialize, + T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.elements.push(value); @@ -808,9 +800,9 @@ mod content { type Ok = Content; type Error = E; - fn serialize_element(&mut self, value: &T) -> Result<(), E> + fn serialize_element(&mut self, value: &T) -> Result<(), E> where - T: Serialize, + T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.elements.push(value); @@ -835,9 +827,9 @@ mod content { type Ok = Content; type Error = E; - fn serialize_field(&mut self, value: &T) -> Result<(), E> + fn serialize_field(&mut self, value: &T) -> Result<(), E> where - T: Serialize, + T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push(value); @@ -864,9 +856,9 @@ mod content { type Ok = Content; type Error = E; - fn serialize_field(&mut self, value: &T) -> Result<(), E> + fn serialize_field(&mut self, value: &T) -> Result<(), E> where - T: Serialize, + T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push(value); @@ -896,18 +888,18 @@ mod content { type Ok = Content; type Error = E; - fn serialize_key(&mut self, key: &T) -> Result<(), E> + fn serialize_key(&mut self, key: &T) -> Result<(), E> where - T: Serialize, + T: ?Sized + Serialize, { let key = tri!(key.serialize(ContentSerializer::::new())); self.key = Some(key); Ok(()) } - fn serialize_value(&mut self, value: &T) -> Result<(), E> + fn serialize_value(&mut self, value: &T) -> Result<(), E> where - T: Serialize, + T: ?Sized + Serialize, { let key = self .key @@ -922,10 +914,10 @@ mod content { Ok(Content::Map(self.entries)) } - fn serialize_entry(&mut self, key: &K, value: &V) -> Result<(), E> + fn serialize_entry(&mut self, key: &K, value: &V) -> Result<(), E> where - K: Serialize, - V: Serialize, + K: ?Sized + Serialize, + V: ?Sized + Serialize, { let key = tri!(key.serialize(ContentSerializer::::new())); let value = tri!(value.serialize(ContentSerializer::::new())); @@ -947,9 +939,9 @@ mod content { type Ok = Content; type Error = E; - fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), E> + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), E> where - T: Serialize, + T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push((key, value)); @@ -976,9 +968,9 @@ mod content { type Ok = Content; type Error = E; - fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), E> + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), E> where - T: Serialize, + T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push((key, value)); @@ -1088,9 +1080,9 @@ where Ok(()) } - fn serialize_some(self, value: &T) -> Result + fn serialize_some(self, value: &T) -> Result where - T: Serialize, + T: ?Sized + Serialize, { value.serialize(self) } @@ -1112,18 +1104,18 @@ where Err(Self::bad_type(Unsupported::Enum)) } - fn serialize_newtype_struct( + fn serialize_newtype_struct( self, _: &'static str, value: &T, ) -> Result where - T: Serialize, + T: ?Sized + Serialize, { value.serialize(self) } - fn serialize_newtype_variant( + fn serialize_newtype_variant( self, _: &'static str, _: u32, @@ -1131,7 +1123,7 @@ where value: &T, ) -> Result where - T: Serialize, + T: ?Sized + Serialize, { tri!(self.0.serialize_key(variant)); self.0.serialize_value(value) @@ -1202,28 +1194,24 @@ where type Ok = (); type Error = M::Error; - fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> + fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> where - T: Serialize, + T: ?Sized + Serialize, { self.0.serialize_key(key) } - fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> + fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> where - T: Serialize, + T: ?Sized + Serialize, { self.0.serialize_value(value) } - fn serialize_entry( - &mut self, - key: &K, - value: &V, - ) -> Result<(), Self::Error> + fn serialize_entry(&mut self, key: &K, value: &V) -> Result<(), Self::Error> where - K: Serialize, - V: Serialize, + K: ?Sized + Serialize, + V: ?Sized + Serialize, { self.0.serialize_entry(key, value) } @@ -1244,13 +1232,9 @@ where type Ok = (); type Error = M::Error; - fn serialize_field( - &mut self, - key: &'static str, - value: &T, - ) -> Result<(), Self::Error> + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> where - T: Serialize, + T: ?Sized + Serialize, { self.0.serialize_entry(key, value) } @@ -1289,9 +1273,9 @@ where type Ok = (); type Error = M::Error; - fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> + fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> where - T: Serialize, + T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push(value); @@ -1335,13 +1319,9 @@ where type Ok = (); type Error = M::Error; - fn serialize_field( - &mut self, - key: &'static str, - value: &T, - ) -> Result<(), Self::Error> + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> where - T: Serialize, + T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push((key, value)); diff --git a/serde/src/ser/fmt.rs b/serde/src/ser/fmt.rs index 0650ab6f1..04684aded 100644 --- a/serde/src/ser/fmt.rs +++ b/serde/src/ser/fmt.rs @@ -74,9 +74,9 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> { Display::fmt(variant, self) } - fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> fmt::Result + fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> fmt::Result where - T: Serialize, + T: ?Sized + Serialize, { Serialize::serialize(value, self) } @@ -89,9 +89,9 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> { Err(fmt::Error) } - fn serialize_some(self, _value: &T) -> fmt::Result + fn serialize_some(self, _value: &T) -> fmt::Result where - T: Serialize, + T: ?Sized + Serialize, { Err(fmt::Error) } @@ -100,7 +100,7 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> { Err(fmt::Error) } - fn serialize_newtype_variant( + fn serialize_newtype_variant( self, _name: &'static str, _variant_index: u32, @@ -108,7 +108,7 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> { _value: &T, ) -> fmt::Result where - T: Serialize, + T: ?Sized + Serialize, { Err(fmt::Error) } @@ -161,9 +161,9 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> { Err(fmt::Error) } - fn collect_str(self, value: &T) -> fmt::Result + fn collect_str(self, value: &T) -> fmt::Result where - T: Display, + T: ?Sized + Display, { Display::fmt(value, self) } diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index 8c70634af..7aa11621c 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -114,7 +114,10 @@ where //////////////////////////////////////////////////////////////////////////////// -impl Serialize for PhantomData { +impl Serialize for PhantomData +where + T: ?Sized, +{ #[inline] fn serialize(&self, serializer: S) -> Result where @@ -504,17 +507,17 @@ macro_rules! deref_impl { } deref_impl! { - <'a, T: ?Sized> Serialize for &'a T where T: Serialize + <'a, T> Serialize for &'a T where T: ?Sized + Serialize } deref_impl! { - <'a, T: ?Sized> Serialize for &'a mut T where T: Serialize + <'a, T> Serialize for &'a mut T where T: ?Sized + Serialize } deref_impl! { #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] - Serialize for Box where T: Serialize + Serialize for Box where T: ?Sized + Serialize } deref_impl! { @@ -528,7 +531,7 @@ deref_impl! { /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg_attr(doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))] - Serialize for Rc where T: Serialize + Serialize for Rc where T: ?Sized + Serialize } deref_impl! { @@ -542,13 +545,13 @@ deref_impl! { /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg_attr(doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))] - Serialize for Arc where T: Serialize + Serialize for Arc where T: ?Sized + Serialize } deref_impl! { #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] - <'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned + <'a, T> Serialize for Cow<'a, T> where T: ?Sized + Serialize + ToOwned } //////////////////////////////////////////////////////////////////////////////// @@ -561,9 +564,9 @@ deref_impl! { doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))) )] -impl Serialize for RcWeak +impl Serialize for RcWeak where - T: Serialize, + T: ?Sized + Serialize, { fn serialize(&self, serializer: S) -> Result where @@ -581,9 +584,9 @@ where doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))) )] -impl Serialize for ArcWeak +impl Serialize for ArcWeak where - T: Serialize, + T: ?Sized + Serialize, { fn serialize(&self, serializer: S) -> Result where @@ -641,9 +644,9 @@ where } } -impl Serialize for RefCell +impl Serialize for RefCell where - T: Serialize, + T: ?Sized + Serialize, { fn serialize(&self, serializer: S) -> Result where @@ -658,9 +661,9 @@ where #[cfg(feature = "std")] #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] -impl Serialize for Mutex +impl Serialize for Mutex where - T: Serialize, + T: ?Sized + Serialize, { fn serialize(&self, serializer: S) -> Result where @@ -675,9 +678,9 @@ where #[cfg(feature = "std")] #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] -impl Serialize for RwLock +impl Serialize for RwLock where - T: Serialize, + T: ?Sized + Serialize, { fn serialize(&self, serializer: S) -> Result where diff --git a/serde/src/ser/impossible.rs b/serde/src/ser/impossible.rs index 479be9407..6432d5775 100644 --- a/serde/src/ser/impossible.rs +++ b/serde/src/ser/impossible.rs @@ -72,9 +72,9 @@ where type Ok = Ok; type Error = Error; - fn serialize_element(&mut self, value: &T) -> Result<(), Error> + fn serialize_element(&mut self, value: &T) -> Result<(), Error> where - T: Serialize, + T: ?Sized + Serialize, { let _ = value; match self.void {} @@ -92,9 +92,9 @@ where type Ok = Ok; type Error = Error; - fn serialize_element(&mut self, value: &T) -> Result<(), Error> + fn serialize_element(&mut self, value: &T) -> Result<(), Error> where - T: Serialize, + T: ?Sized + Serialize, { let _ = value; match self.void {} @@ -112,9 +112,9 @@ where type Ok = Ok; type Error = Error; - fn serialize_field(&mut self, value: &T) -> Result<(), Error> + fn serialize_field(&mut self, value: &T) -> Result<(), Error> where - T: Serialize, + T: ?Sized + Serialize, { let _ = value; match self.void {} @@ -132,9 +132,9 @@ where type Ok = Ok; type Error = Error; - fn serialize_field(&mut self, value: &T) -> Result<(), Error> + fn serialize_field(&mut self, value: &T) -> Result<(), Error> where - T: Serialize, + T: ?Sized + Serialize, { let _ = value; match self.void {} @@ -152,17 +152,17 @@ where type Ok = Ok; type Error = Error; - fn serialize_key(&mut self, key: &T) -> Result<(), Error> + fn serialize_key(&mut self, key: &T) -> Result<(), Error> where - T: Serialize, + T: ?Sized + Serialize, { let _ = key; match self.void {} } - fn serialize_value(&mut self, value: &T) -> Result<(), Error> + fn serialize_value(&mut self, value: &T) -> Result<(), Error> where - T: Serialize, + T: ?Sized + Serialize, { let _ = value; match self.void {} @@ -180,9 +180,9 @@ where type Ok = Ok; type Error = Error; - fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Error> + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Error> where - T: Serialize, + T: ?Sized + Serialize, { let _ = key; let _ = value; @@ -201,9 +201,9 @@ where type Ok = Ok; type Error = Error; - fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Error> + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Error> where - T: Serialize, + T: ?Sized + Serialize, { let _ = key; let _ = value; diff --git a/serde/src/ser/mod.rs b/serde/src/ser/mod.rs index 75c45140e..715d7e6cd 100644 --- a/serde/src/ser/mod.rs +++ b/serde/src/ser/mod.rs @@ -796,9 +796,9 @@ pub trait Serializer: Sized { /// ``` /// /// [`Some(T)`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.Some - fn serialize_some(self, value: &T) -> Result + fn serialize_some(self, value: &T) -> Result where - T: Serialize; + T: ?Sized + Serialize; /// Serialize a `()` value. /// @@ -891,13 +891,13 @@ pub trait Serializer: Sized { /// } /// } /// ``` - fn serialize_newtype_struct( + fn serialize_newtype_struct( self, name: &'static str, value: &T, ) -> Result where - T: Serialize; + T: ?Sized + Serialize; /// Serialize a newtype variant like `E::N` in `enum E { N(u8) }`. /// @@ -925,7 +925,7 @@ pub trait Serializer: Sized { /// } /// } /// ``` - fn serialize_newtype_variant( + fn serialize_newtype_variant( self, name: &'static str, variant_index: u32, @@ -933,7 +933,7 @@ pub trait Serializer: Sized { value: &T, ) -> Result where - T: Serialize; + T: ?Sized + Serialize; /// Begin to serialize a variably sized sequence. This call must be /// followed by zero or more calls to `serialize_element`, then a call to @@ -1346,9 +1346,9 @@ pub trait Serializer: Sized { /// [`String`]: https://doc.rust-lang.org/std/string/struct.String.html /// [`serialize_str`]: #tymethod.serialize_str #[cfg(any(feature = "std", feature = "alloc"))] - fn collect_str(self, value: &T) -> Result + fn collect_str(self, value: &T) -> Result where - T: Display, + T: ?Sized + Display, { self.serialize_str(&value.to_string()) } @@ -1379,9 +1379,9 @@ pub trait Serializer: Sized { /// } /// ``` #[cfg(not(any(feature = "std", feature = "alloc")))] - fn collect_str(self, value: &T) -> Result + fn collect_str(self, value: &T) -> Result where - T: Display; + T: ?Sized + Display; /// Determine whether `Serialize` implementations should serialize in /// human-readable form. @@ -1493,9 +1493,9 @@ pub trait SerializeSeq { type Error: Error; /// Serialize a sequence element. - fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> + fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> where - T: Serialize; + T: ?Sized + Serialize; /// Finish serializing a sequence. fn end(self) -> Result; @@ -1593,9 +1593,9 @@ pub trait SerializeTuple { type Error: Error; /// Serialize a tuple element. - fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> + fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> where - T: Serialize; + T: ?Sized + Serialize; /// Finish serializing a tuple. fn end(self) -> Result; @@ -1638,9 +1638,9 @@ pub trait SerializeTupleStruct { type Error: Error; /// Serialize a tuple struct field. - fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> + fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> where - T: Serialize; + T: ?Sized + Serialize; /// Finish serializing a tuple struct. fn end(self) -> Result; @@ -1696,9 +1696,9 @@ pub trait SerializeTupleVariant { type Error: Error; /// Serialize a tuple variant field. - fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> + fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> where - T: Serialize; + T: ?Sized + Serialize; /// Finish serializing a tuple variant. fn end(self) -> Result; @@ -1767,9 +1767,9 @@ pub trait SerializeMap { /// `serialize_entry` instead as it may be implemented more efficiently in /// some formats compared to a pair of calls to `serialize_key` and /// `serialize_value`. - fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> + fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> where - T: Serialize; + T: ?Sized + Serialize; /// Serialize a map value. /// @@ -1777,9 +1777,9 @@ pub trait SerializeMap { /// /// Calling `serialize_value` before `serialize_key` is incorrect and is /// allowed to panic or produce bogus results. - fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> + fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> where - T: Serialize; + T: ?Sized + Serialize; /// Serialize a map entry consisting of a key and a value. /// @@ -1798,14 +1798,10 @@ pub trait SerializeMap { /// [`Serialize`]: ../trait.Serialize.html /// [`serialize_key`]: #tymethod.serialize_key /// [`serialize_value`]: #tymethod.serialize_value - fn serialize_entry( - &mut self, - key: &K, - value: &V, - ) -> Result<(), Self::Error> + fn serialize_entry(&mut self, key: &K, value: &V) -> Result<(), Self::Error> where - K: Serialize, - V: Serialize, + K: ?Sized + Serialize, + V: ?Sized + Serialize, { tri!(self.serialize_key(key)); self.serialize_value(value) @@ -1856,13 +1852,9 @@ pub trait SerializeStruct { type Error: Error; /// Serialize a struct field. - fn serialize_field( - &mut self, - key: &'static str, - value: &T, - ) -> Result<(), Self::Error> + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> where - T: Serialize; + T: ?Sized + Serialize; /// Indicate that a struct field has been skipped. #[inline] @@ -1922,13 +1914,9 @@ pub trait SerializeStructVariant { type Error: Error; /// Serialize a struct variant field. - fn serialize_field( - &mut self, - key: &'static str, - value: &T, - ) -> Result<(), Self::Error> + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> where - T: Serialize; + T: ?Sized + Serialize; /// Indicate that a struct variant field has been skipped. #[inline] From 89139e2c11c9e975753ebe82745071acb47ecb03 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 27 Feb 2024 22:52:18 -0800 Subject: [PATCH 061/258] Remove ineffective ?Sized bound on weak rc Deserialize impls These impls have both `T: ?Sized` and `T: Deserialize<'de>`. But `Deserialize<'de>: Sized`. --- serde/src/de/impls.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index c866c90e5..d89f1872b 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -1908,7 +1908,7 @@ where doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))) )] -impl<'de, T: ?Sized> Deserialize<'de> for RcWeak +impl<'de, T> Deserialize<'de> for RcWeak where T: Deserialize<'de>, { @@ -1930,7 +1930,7 @@ where doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))) )] -impl<'de, T: ?Sized> Deserialize<'de> for ArcWeak +impl<'de, T> Deserialize<'de> for ArcWeak where T: Deserialize<'de>, { From 76449488caeaa5b376912f53715e3b22bb2274b7 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 11 Mar 2024 20:10:02 -0700 Subject: [PATCH 062/258] Ignore new dead_code warnings in test Since nightly-2024-03-12. warning: struct `PackedC` is never constructed --> test_suite/tests/test_macros.rs:2237:12 | 2237 | struct PackedC { | ^^^^^^^ | = note: `#[warn(dead_code)]` on by default warning: struct `CPacked` is never constructed --> test_suite/tests/test_macros.rs:2243:12 | 2243 | struct CPacked { | ^^^^^^^ warning: struct `CPacked2` is never constructed --> test_suite/tests/test_macros.rs:2249:12 | 2249 | struct CPacked2 { | ^^^^^^^^ warning: struct `Packed2C` is never constructed --> test_suite/tests/test_macros.rs:2255:12 | 2255 | struct Packed2C { | ^^^^^^^^ error: struct `Packed` is never constructed --> test_suite/tests/test_gen.rs:733:12 | 733 | struct Packed { | ^^^^^^ | note: the lint level is defined here --> test_suite/tests/test_gen.rs:5:9 | 5 | #![deny(warnings)] | ^^^^^^^^ = note: `#[deny(dead_code)]` implied by `#[deny(warnings)]` error: struct `Struct` is never constructed --> test_suite/tests/test_gen.rs:764:12 | 764 | struct Struct { | ^^^^^^ error: function `vec_first_element` is never used --> test_suite/tests/test_gen.rs:846:4 | 846 | fn vec_first_element(vec: &[T], serializer: S) -> StdResult | ^^^^^^^^^^^^^^^^^ --- test_suite/tests/test_gen.rs | 2 ++ test_suite/tests/test_macros.rs | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/test_suite/tests/test_gen.rs b/test_suite/tests/test_gen.rs index 97b0a96e9..055fae60c 100644 --- a/test_suite/tests/test_gen.rs +++ b/test_suite/tests/test_gen.rs @@ -730,6 +730,7 @@ fn test_gen() { #[derive(Serialize)] #[repr(packed)] + #[allow(dead_code)] struct Packed { x: u8, y: u16, @@ -761,6 +762,7 @@ fn test_gen() { } #[derive(Serialize)] + #[allow(dead_code)] struct Struct { #[serde(serialize_with = "vec_first_element")] vec: Vec, diff --git a/test_suite/tests/test_macros.rs b/test_suite/tests/test_macros.rs index 0d6472df6..7bd7a94e7 100644 --- a/test_suite/tests/test_macros.rs +++ b/test_suite/tests/test_macros.rs @@ -2234,24 +2234,28 @@ fn test_internally_tagged_newtype_variant_containing_unit_struct() { fn test_packed_struct_can_derive_serialize() { #[derive(Copy, Clone, Serialize)] #[repr(packed, C)] + #[allow(dead_code)] struct PackedC { t: f32, } #[derive(Copy, Clone, Serialize)] #[repr(C, packed)] + #[allow(dead_code)] struct CPacked { t: f32, } #[derive(Copy, Clone, Serialize)] #[repr(C, packed(2))] + #[allow(dead_code)] struct CPacked2 { t: f32, } #[derive(Copy, Clone, Serialize)] #[repr(packed(2), C)] + #[allow(dead_code)] struct Packed2C { t: f32, } From 3f43fca90dfff4a8728765867cea85865843c337 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 11 Mar 2024 20:17:37 -0700 Subject: [PATCH 063/258] Fix warning on no edition set in serde_derive New warning since nightly-2024-03-03: warning: serde_derive/Cargo.toml: no edition set: defaulting to the 2015 edition while 2018 is compatible with `rust-version` warning: serde_derive_internals/Cargo.toml: no edition set: defaulting to the 2015 edition while 2018 is compatible with `rust-version` --- serde_derive/Cargo.toml | 1 + serde_derive_internals/Cargo.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index cd3c4b798..8d91a74d7 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -5,6 +5,7 @@ authors = ["Erick Tryzelaar ", "David Tolnay ", "David Tolnay "] description = "AST representation used by Serde derive macros. Unstable." documentation = "https://docs.rs/serde_derive_internals" +edition = "2015" exclude = ["build.rs"] homepage = "https://serde.rs" keywords = ["serde", "serialization"] From eae7c2d684cd2c20fca5c039ced25f6bb1d13e30 Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Sat, 16 Mar 2024 14:40:28 +0100 Subject: [PATCH 064/258] Document that `len` does not include skipped struct fields --- serde/src/ser/mod.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/serde/src/ser/mod.rs b/serde/src/ser/mod.rs index 715d7e6cd..74b5e0769 100644 --- a/serde/src/ser/mod.rs +++ b/serde/src/ser/mod.rs @@ -1170,7 +1170,8 @@ pub trait Serializer: Sized { /// then a call to `end`. /// /// The `name` is the name of the struct and the `len` is the number of - /// data fields that will be serialized. + /// data fields that will be serialized. `len` does not include fields + /// which are skipped with [`SerializeStruct::skip_field`]. /// /// ```edition2021 /// use serde::ser::{Serialize, SerializeStruct, Serializer}; @@ -1207,6 +1208,8 @@ pub trait Serializer: Sized { /// The `name` is the name of the enum, the `variant_index` is the index of /// this variant within the enum, the `variant` is the name of the variant, /// and the `len` is the number of data fields that will be serialized. + /// `len` does not include fields which are skipped with + /// [`SerializeStructVariant::skip_field`]. /// /// ```edition2021 /// use serde::ser::{Serialize, SerializeStructVariant, Serializer}; @@ -1857,6 +1860,8 @@ pub trait SerializeStruct { T: ?Sized + Serialize; /// Indicate that a struct field has been skipped. + /// + /// The default implementation does nothing. #[inline] fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> { let _ = key; @@ -1919,6 +1924,8 @@ pub trait SerializeStructVariant { T: ?Sized + Serialize; /// Indicate that a struct variant field has been skipped. + /// + /// The default implementation does nothing. #[inline] fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> { let _ = key; From 364cd8d8f76697d2e0bc91132c34a5446a934708 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 23 Mar 2024 20:23:13 -0700 Subject: [PATCH 065/258] Ignore dead code lint in tests New in nightly-2024-03-24 from https://github.com/rust-lang/rust/pull/119552. warning: fields `nested` and `string` are never read --> test_suite/tests/regression/issue2371.rs:10:9 | 8 | Flatten { | ------- fields in this variant 9 | #[serde(flatten)] 10 | nested: Nested, | ^^^^^^ 11 | string: &'static str, | ^^^^^^ | = note: `#[warn(dead_code)]` on by default warning: fields `nested` and `string` are never read --> test_suite/tests/regression/issue2371.rs:20:9 | 18 | Flatten { | ------- fields in this variant 19 | #[serde(flatten)] 20 | nested: Nested, | ^^^^^^ 21 | string: &'static str, | ^^^^^^ warning: fields `nested` and `string` are never read --> test_suite/tests/regression/issue2371.rs:30:9 | 28 | Flatten { | ------- fields in this variant 29 | #[serde(flatten)] 30 | nested: Nested, | ^^^^^^ 31 | string: &'static str, | ^^^^^^ warning: fields `nested` and `string` are never read --> test_suite/tests/regression/issue2371.rs:40:9 | 38 | Flatten { | ------- fields in this variant 39 | #[serde(flatten)] 40 | nested: Nested, | ^^^^^^ 41 | string: &'static str, | ^^^^^^ warning: field `0` is never read --> test_suite/tests/test_gen.rs:690:33 | 690 | Single(#[serde(borrow)] RelObject<'a>), | ------ ^^^^^^^^^^^^^ | | | field in this variant | = note: `#[warn(dead_code)]` on by default help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field | 690 | Single(#[serde(borrow)] ()), | ~~ warning: field `0` is never read --> test_suite/tests/test_gen.rs:691:31 | 691 | Many(#[serde(borrow)] Vec>), | ---- ^^^^^^^^^^^^^^^^^^ | | | field in this variant | help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field | 691 | Many(#[serde(borrow)] ()), | ~~ --- test_suite/tests/regression/issue2371.rs | 8 ++++++++ test_suite/tests/test_gen.rs | 12 ++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/test_suite/tests/regression/issue2371.rs b/test_suite/tests/regression/issue2371.rs index e4832af38..7668af1db 100644 --- a/test_suite/tests/regression/issue2371.rs +++ b/test_suite/tests/regression/issue2371.rs @@ -7,7 +7,9 @@ pub struct Nested; pub enum ExternallyTagged { Flatten { #[serde(flatten)] + #[allow(dead_code)] nested: Nested, + #[allow(dead_code)] string: &'static str, }, } @@ -17,7 +19,9 @@ pub enum ExternallyTagged { pub enum InternallyTagged { Flatten { #[serde(flatten)] + #[allow(dead_code)] nested: Nested, + #[allow(dead_code)] string: &'static str, }, } @@ -27,7 +31,9 @@ pub enum InternallyTagged { pub enum AdjacentlyTagged { Flatten { #[serde(flatten)] + #[allow(dead_code)] nested: Nested, + #[allow(dead_code)] string: &'static str, }, } @@ -37,7 +43,9 @@ pub enum AdjacentlyTagged { pub enum UntaggedWorkaround { Flatten { #[serde(flatten)] + #[allow(dead_code)] nested: Nested, + #[allow(dead_code)] string: &'static str, }, } diff --git a/test_suite/tests/test_gen.rs b/test_suite/tests/test_gen.rs index 055fae60c..4aaf06a8b 100644 --- a/test_suite/tests/test_gen.rs +++ b/test_suite/tests/test_gen.rs @@ -687,8 +687,16 @@ fn test_gen() { #[derive(Deserialize)] #[serde(untagged)] pub enum UntaggedWithBorrow<'a> { - Single(#[serde(borrow)] RelObject<'a>), - Many(#[serde(borrow)] Vec>), + Single( + #[serde(borrow)] + #[allow(dead_code)] + RelObject<'a>, + ), + Many( + #[serde(borrow)] + #[allow(dead_code)] + Vec>, + ), } #[derive(Deserialize)] From 3bfab6ef7fc80ad73eb598687c836609c14f6f8b Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 24 Mar 2024 19:50:50 -0700 Subject: [PATCH 066/258] Temporarily disable miri on doctests --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dd49909b2..74cdb7dc7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -154,7 +154,7 @@ jobs: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@miri - run: cargo miri setup - - run: cd serde && cargo miri test --features derive,rc,unstable + - run: cd serde && cargo miri test --features derive,rc,unstable --all-targets # exclude doctests https://github.com/rust-lang/miri/issues/3404 env: MIRIFLAGS: -Zmiri-strict-provenance - run: cd test_suite && cargo miri test --features unstable From 74d06708ddff495161187ea490c4616291216346 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 25 Mar 2024 22:24:55 -0700 Subject: [PATCH 067/258] Explicitly install a Rust toolchain for cargo-outdated job Debugging a recent cargo-outdated bug, it would have been nice not to wonder whether a rustc version change in GitHub's runner image was a contributing factor. --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 74cdb7dc7..efb475011 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -168,5 +168,6 @@ jobs: timeout-minutes: 45 steps: - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable - uses: dtolnay/install@cargo-outdated - run: cargo outdated --workspace --exit-code 1 From 5b24f88e73caa9c607527b5b4696fc34263cd238 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 5 Apr 2024 19:18:03 -0700 Subject: [PATCH 068/258] Resolve legacy_numeric_constants clippy lints warning: usage of a legacy numeric method --> serde_derive/src/ser.rs:292:51 | 292 | assert!(fields.len() as u64 <= u64::from(u32::max_value())); | ^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#legacy_numeric_constants = note: `#[warn(clippy::legacy_numeric_constants)]` on by default help: use the associated constant instead | 292 | assert!(fields.len() as u64 <= u64::from(u32::MAX)); | ~~~ warning: usage of a legacy numeric method --> serde_derive/src/ser.rs:400:53 | 400 | assert!(variants.len() as u64 <= u64::from(u32::max_value())); | ^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#legacy_numeric_constants help: use the associated constant instead | 400 | assert!(variants.len() as u64 <= u64::from(u32::MAX)); | ~~~ warning: usage of a legacy numeric method --> test_suite/tests/test_de_error.rs:1462:29 | 1462 | Token::U64(u64::max_value()), | ^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#legacy_numeric_constants = note: `-W clippy::legacy-numeric-constants` implied by `-W clippy::all` = help: to override `-W clippy::all` add `#[allow(clippy::legacy_numeric_constants)]` help: use the associated constant instead | 1462 | Token::U64(u64::MAX), | ~~~ warning: usage of a legacy numeric method --> test_suite/tests/test_de_error.rs:1479:29 | 1479 | Token::U64(u64::max_value()), | ^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#legacy_numeric_constants help: use the associated constant instead | 1479 | Token::U64(u64::MAX), | ~~~ warning: usage of a legacy numeric method --> test_suite/tests/test_de_error.rs:1493:29 | 1493 | Token::U64(u64::max_value()), | ^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#legacy_numeric_constants help: use the associated constant instead | 1493 | Token::U64(u64::MAX), | ~~~ warning: usage of a legacy numeric method --> test_suite/tests/test_de_error.rs:1510:29 | 1510 | Token::U64(u64::max_value()), | ^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#legacy_numeric_constants help: use the associated constant instead | 1510 | Token::U64(u64::MAX), | ~~~ --- serde_derive/src/ser.rs | 4 ++-- test_suite/tests/test_de_error.rs | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/serde_derive/src/ser.rs b/serde_derive/src/ser.rs index 3be51ee52..7d89d2212 100644 --- a/serde_derive/src/ser.rs +++ b/serde_derive/src/ser.rs @@ -289,7 +289,7 @@ fn serialize_tuple_struct( } fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment { - assert!(fields.len() as u64 <= u64::from(u32::max_value())); + assert!(fields.len() as u64 <= u64::from(u32::MAX)); if cattrs.has_flatten() { serialize_struct_as_map(params, fields, cattrs) @@ -397,7 +397,7 @@ fn serialize_struct_as_map( } fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment { - assert!(variants.len() as u64 <= u64::from(u32::max_value())); + assert!(variants.len() as u64 <= u64::from(u32::MAX)); let self_var = ¶ms.self_var; diff --git a/test_suite/tests/test_de_error.rs b/test_suite/tests/test_de_error.rs index d1ea2b910..cf4bec86b 100644 --- a/test_suite/tests/test_de_error.rs +++ b/test_suite/tests/test_de_error.rs @@ -1459,7 +1459,7 @@ fn test_duration_overflow_seq() { assert_de_tokens_error::( &[ Token::Seq { len: Some(2) }, - Token::U64(u64::max_value()), + Token::U64(u64::MAX), Token::U32(1_000_000_000), Token::SeqEnd, ], @@ -1476,7 +1476,7 @@ fn test_duration_overflow_struct() { len: 2, }, Token::Str("secs"), - Token::U64(u64::max_value()), + Token::U64(u64::MAX), Token::Str("nanos"), Token::U32(1_000_000_000), Token::StructEnd, @@ -1490,7 +1490,7 @@ fn test_systemtime_overflow_seq() { assert_de_tokens_error::( &[ Token::Seq { len: Some(2) }, - Token::U64(u64::max_value()), + Token::U64(u64::MAX), Token::U32(1_000_000_000), Token::SeqEnd, ], @@ -1507,7 +1507,7 @@ fn test_systemtime_overflow_struct() { len: 2, }, Token::Str("secs_since_epoch"), - Token::U64(u64::max_value()), + Token::U64(u64::MAX), Token::Str("nanos_since_epoch"), Token::U32(1_000_000_000), Token::StructEnd, @@ -1522,7 +1522,7 @@ fn test_systemtime_overflow() { assert_de_tokens_error::( &[ Token::Seq { len: Some(2) }, - Token::U64(u64::max_value()), + Token::U64(u64::MAX), Token::U32(0), Token::SeqEnd, ], From 3d1b19ed906cb1c8cf4e2b4a45eea8f810115db1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Bethune?= Date: Mon, 4 Mar 2024 18:56:15 +0100 Subject: [PATCH 069/258] Implement Ser+De for `Saturating` The serialization implementation is heavily inspired by the existing trait implentation for `std::num::Wrapping`. The deserializing implementation maps input values that lie outside of the numerical range of the output type to the `MIN` or `MAX` value of the output type, depending on the sign of the input value. This behaviour follows to the `Saturating` semantics of the output type. fix #2708 --- serde/build.rs | 6 ++++ serde/src/de/impls.rs | 67 ++++++++++++++++++++++++++++++++++++ serde/src/lib.rs | 3 ++ serde/src/ser/impls.rs | 14 ++++++++ test_suite/tests/test_de.rs | 39 ++++++++++++++++++++- test_suite/tests/test_ser.rs | 7 +++- 6 files changed, 134 insertions(+), 2 deletions(-) diff --git a/serde/build.rs b/serde/build.rs index fe5486a7a..0074df63f 100644 --- a/serde/build.rs +++ b/serde/build.rs @@ -64,6 +64,12 @@ fn main() { if minor < 64 { println!("cargo:rustc-cfg=no_core_cstr"); } + + // Support for core::num::Saturating and std::num::Saturating stabilized in Rust 1.74 + // https://blog.rust-lang.org/2023/11/16/Rust-1.74.0.html#stabilized-apis + if minor < 74 { + println!("cargo:rustc-cfg=no_core_num_saturating"); + } } fn rustc_minor_version() -> Option { diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index d89f1872b..9ccb3ce69 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -387,6 +387,73 @@ impl_deserialize_num! { num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); } +#[cfg(not(no_core_num_saturating))] +macro_rules! visit_saturating { + ($primitive:ident, $ty:ident : $visit:ident) => { + #[inline] + fn $visit(self, v: $ty) -> Result, E> + where + E: Error, + { + let out: $primitive = core::convert::TryFrom::<$ty>::try_from(v).unwrap_or_else(|_| { + #[allow(unused_comparisons)] + if v < 0 { + // never true for unsigned values + $primitive::MIN + } else { + $primitive::MAX + } + }); + Ok(Saturating(out)) + } + }; +} + +macro_rules! impl_deserialize_saturating_num { + ($primitive:ident, $deserialize:ident ) => { + #[cfg(not(no_core_num_saturating))] + impl<'de> Deserialize<'de> for Saturating<$primitive> { + #[inline] + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct SaturatingVisitor; + + impl<'de> Visitor<'de> for SaturatingVisitor { + type Value = Saturating<$primitive>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("An integer with support for saturating semantics") + } + + visit_saturating!($primitive, u8:visit_u8); + visit_saturating!($primitive, u16:visit_u16); + visit_saturating!($primitive, u32:visit_u32); + visit_saturating!($primitive, u64:visit_u64); + visit_saturating!($primitive, i8:visit_i8); + visit_saturating!($primitive, i16:visit_i16); + visit_saturating!($primitive, i32:visit_i32); + visit_saturating!($primitive, i64:visit_i64); + } + + deserializer.$deserialize(SaturatingVisitor) + } + } + }; +} + +impl_deserialize_saturating_num!(u8, deserialize_u8); +impl_deserialize_saturating_num!(u16, deserialize_u16); +impl_deserialize_saturating_num!(u32, deserialize_u32); +impl_deserialize_saturating_num!(u64, deserialize_u64); +impl_deserialize_saturating_num!(usize, deserialize_u64); +impl_deserialize_saturating_num!(i8, deserialize_i8); +impl_deserialize_saturating_num!(i16, deserialize_i16); +impl_deserialize_saturating_num!(i32, deserialize_i32); +impl_deserialize_saturating_num!(i64, deserialize_i64); +impl_deserialize_saturating_num!(isize, deserialize_i64); + macro_rules! num_128 { ($ty:ident : $visit:ident) => { fn $visit(self, v: $ty) -> Result diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 5cf44c1c1..dc6d392bd 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -274,6 +274,9 @@ mod lib { pub use std::sync::atomic::{AtomicI64, AtomicU64}; #[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "ptr"))] pub use std::sync::atomic::{AtomicIsize, AtomicUsize}; + + #[cfg(not(no_core_num_saturating))] + pub use self::core::num::Saturating; } // None of this crate's error handling needs the `From::from` error conversion diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index 7aa11621c..ffc4c70f9 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -1026,6 +1026,20 @@ where } } +#[cfg(not(no_core_num_saturating))] +impl Serialize for Saturating +where + T: Serialize, +{ + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.0.serialize(serializer) + } +} + impl Serialize for Reverse where T: Serialize, diff --git a/test_suite/tests/test_de.rs b/test_suite/tests/test_de.rs index 3ca0fde36..8a7310cd2 100644 --- a/test_suite/tests/test_de.rs +++ b/test_suite/tests/test_de.rs @@ -23,7 +23,7 @@ use std::iter; use std::net; use std::num::{ NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128, - NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, Wrapping, + NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, Saturating, Wrapping, }; use std::ops::Bound; use std::path::{Path, PathBuf}; @@ -2065,6 +2065,43 @@ fn test_wrapping() { test(Wrapping(1usize), &[Token::U64(1)]); } +#[test] +fn test_saturating() { + test(Saturating(1usize), &[Token::U32(1)]); + test(Saturating(1usize), &[Token::U64(1)]); + test(Saturating(0u8), &[Token::I8(0)]); + test(Saturating(0u16), &[Token::I16(0)]); + + // saturate input values at the minimum or maximum value + test(Saturating(u8::MAX), &[Token::U16(u16::MAX)]); + test(Saturating(u8::MAX), &[Token::U16(u8::MAX as u16 + 1)]); + test(Saturating(u16::MAX), &[Token::U32(u32::MAX)]); + test(Saturating(u32::MAX), &[Token::U64(u64::MAX)]); + test(Saturating(u8::MIN), &[Token::I8(i8::MIN)]); + test(Saturating(u16::MIN), &[Token::I16(i16::MIN)]); + test(Saturating(u32::MIN), &[Token::I32(i32::MIN)]); + test(Saturating(i8::MIN), &[Token::I16(i16::MIN)]); + test(Saturating(i16::MIN), &[Token::I32(i32::MIN)]); + test(Saturating(i32::MIN), &[Token::I64(i64::MIN)]); + + test(Saturating(u8::MIN), &[Token::I8(-1)]); + test(Saturating(u16::MIN), &[Token::I16(-1)]); + + #[cfg(target_pointer_width = "64")] + { + test(Saturating(usize::MIN), &[Token::U64(u64::MIN)]); + test(Saturating(usize::MAX), &[Token::U64(u64::MAX)]); + test(Saturating(isize::MIN), &[Token::I64(i64::MIN)]); + test(Saturating(isize::MAX), &[Token::I64(i64::MAX)]); + test(Saturating(0usize), &[Token::I64(i64::MIN)]); + + test( + Saturating(9_223_372_036_854_775_807usize), + &[Token::I64(i64::MAX)], + ); + } +} + #[test] fn test_rc_dst() { test(Rc::::from("s"), &[Token::Str("s")]); diff --git a/test_suite/tests/test_ser.rs b/test_suite/tests/test_ser.rs index 71ec3bc57..b60d03ab2 100644 --- a/test_suite/tests/test_ser.rs +++ b/test_suite/tests/test_ser.rs @@ -8,7 +8,7 @@ use std::cell::RefCell; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::ffi::CString; use std::net; -use std::num::Wrapping; +use std::num::{Saturating, Wrapping}; use std::ops::Bound; use std::path::{Path, PathBuf}; use std::rc::{Rc, Weak as RcWeak}; @@ -624,6 +624,11 @@ fn test_wrapping() { assert_ser_tokens(&Wrapping(1usize), &[Token::U64(1)]); } +#[test] +fn test_saturating() { + assert_ser_tokens(&Saturating(1usize), &[Token::U64(1)]); +} + #[test] fn test_rc_dst() { assert_ser_tokens(&Rc::::from("s"), &[Token::Str("s")]); From 6e38afff498d592af4ccac4cb669a86fc789207f Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 8 Apr 2024 11:58:08 -0700 Subject: [PATCH 070/258] Revert "Temporarily disable miri on doctests" This reverts commit 3bfab6ef7fc80ad73eb598687c836609c14f6f8b. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index efb475011..8487ba65d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -154,7 +154,7 @@ jobs: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@miri - run: cargo miri setup - - run: cd serde && cargo miri test --features derive,rc,unstable --all-targets # exclude doctests https://github.com/rust-lang/miri/issues/3404 + - run: cd serde && cargo miri test --features derive,rc,unstable env: MIRIFLAGS: -Zmiri-strict-provenance - run: cd test_suite && cargo miri test --features unstable From c13b3f7e68d4c71bbe1ea825b36148eadf7de603 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 16 Apr 2024 13:31:27 -0700 Subject: [PATCH 071/258] Format PR 2709 --- serde/src/de/impls.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 9ccb3ce69..6a1dbd3ad 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -410,7 +410,7 @@ macro_rules! visit_saturating { } macro_rules! impl_deserialize_saturating_num { - ($primitive:ident, $deserialize:ident ) => { + ($primitive:ident, $deserialize:ident) => { #[cfg(not(no_core_num_saturating))] impl<'de> Deserialize<'de> for Saturating<$primitive> { #[inline] @@ -424,7 +424,7 @@ macro_rules! impl_deserialize_saturating_num { type Value = Saturating<$primitive>; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("An integer with support for saturating semantics") + formatter.write_str("integer with support for saturating semantics") } visit_saturating!($primitive, u8:visit_u8); From 01cd696fd17f586aab428b1bbd11d533124a3425 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 16 Apr 2024 13:49:36 -0700 Subject: [PATCH 072/258] Integrate Saturating deserialization into impl_deserialize_num macro --- serde/src/de/impls.rs | 165 +++++++++++++++++++++++++----------------- 1 file changed, 98 insertions(+), 67 deletions(-) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 6a1dbd3ad..140878aec 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -104,6 +104,28 @@ macro_rules! impl_deserialize_num { deserializer.$deserialize(NonZeroVisitor) } } + + #[cfg(not(no_core_num_saturating))] + impl<'de> Deserialize<'de> for Saturating<$primitive> { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct SaturatingVisitor; + + impl<'de> Visitor<'de> for SaturatingVisitor { + type Value = Saturating<$primitive>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("integer with support for saturating semantics") + } + + $($($method!(saturating $primitive $val : $visit);)*)* + } + + deserializer.$deserialize(SaturatingVisitor) + } + } }; ($primitive:ident, $deserialize:ident $($method:ident!($($val:ident : $visit:ident)*);)*) => { @@ -154,6 +176,15 @@ macro_rules! num_self { } } }; + + (saturating $primitive:ident $ty:ident : $visit:ident) => { + fn $visit(self, v: $ty) -> Result + where + E: Error, + { + Ok(Saturating(v)) + } + }; } macro_rules! num_as_self { @@ -179,6 +210,15 @@ macro_rules! num_as_self { } } }; + + (saturating $primitive:ident $ty:ident : $visit:ident) => { + fn $visit(self, v: $ty) -> Result + where + E: Error, + { + Ok(Saturating(v as $primitive)) + } + }; } macro_rules! num_as_copysign_self { @@ -235,6 +275,21 @@ macro_rules! int_to_int { Err(Error::invalid_value(Unexpected::Signed(v as i64), &self)) } }; + + (saturating $primitive:ident $ty:ident : $visit:ident) => { + fn $visit(self, v: $ty) -> Result + where + E: Error, + { + if (v as i64) < $primitive::MIN as i64 { + Ok(Saturating($primitive::MIN)) + } else if ($primitive::MAX as i64) < v as i64 { + Ok(Saturating($primitive::MAX)) + } else { + Ok(Saturating(v as $primitive)) + } + } + }; } macro_rules! int_to_uint { @@ -265,6 +320,21 @@ macro_rules! int_to_uint { Err(Error::invalid_value(Unexpected::Signed(v as i64), &self)) } }; + + (saturating $primitive:ident $ty:ident : $visit:ident) => { + fn $visit(self, v: $ty) -> Result + where + E: Error, + { + if v < 0 { + Ok(Saturating(0)) + } else if ($primitive::MAX as u64) < v as u64 { + Ok(Saturating($primitive::MAX)) + } else { + Ok(Saturating(v as $primitive)) + } + } + }; } macro_rules! uint_to_self { @@ -295,6 +365,19 @@ macro_rules! uint_to_self { Err(Error::invalid_value(Unexpected::Unsigned(v as u64), &self)) } }; + + (saturating $primitive:ident $ty:ident : $visit:ident) => { + fn $visit(self, v: $ty) -> Result + where + E: Error, + { + if v as u64 <= $primitive::MAX as u64 { + Ok(Saturating(v as $primitive)) + } else { + Ok(Saturating($primitive::MAX)) + } + } + }; } impl_deserialize_num! { @@ -387,73 +470,6 @@ impl_deserialize_num! { num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); } -#[cfg(not(no_core_num_saturating))] -macro_rules! visit_saturating { - ($primitive:ident, $ty:ident : $visit:ident) => { - #[inline] - fn $visit(self, v: $ty) -> Result, E> - where - E: Error, - { - let out: $primitive = core::convert::TryFrom::<$ty>::try_from(v).unwrap_or_else(|_| { - #[allow(unused_comparisons)] - if v < 0 { - // never true for unsigned values - $primitive::MIN - } else { - $primitive::MAX - } - }); - Ok(Saturating(out)) - } - }; -} - -macro_rules! impl_deserialize_saturating_num { - ($primitive:ident, $deserialize:ident) => { - #[cfg(not(no_core_num_saturating))] - impl<'de> Deserialize<'de> for Saturating<$primitive> { - #[inline] - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - struct SaturatingVisitor; - - impl<'de> Visitor<'de> for SaturatingVisitor { - type Value = Saturating<$primitive>; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("integer with support for saturating semantics") - } - - visit_saturating!($primitive, u8:visit_u8); - visit_saturating!($primitive, u16:visit_u16); - visit_saturating!($primitive, u32:visit_u32); - visit_saturating!($primitive, u64:visit_u64); - visit_saturating!($primitive, i8:visit_i8); - visit_saturating!($primitive, i16:visit_i16); - visit_saturating!($primitive, i32:visit_i32); - visit_saturating!($primitive, i64:visit_i64); - } - - deserializer.$deserialize(SaturatingVisitor) - } - } - }; -} - -impl_deserialize_saturating_num!(u8, deserialize_u8); -impl_deserialize_saturating_num!(u16, deserialize_u16); -impl_deserialize_saturating_num!(u32, deserialize_u32); -impl_deserialize_saturating_num!(u64, deserialize_u64); -impl_deserialize_saturating_num!(usize, deserialize_u64); -impl_deserialize_saturating_num!(i8, deserialize_i8); -impl_deserialize_saturating_num!(i16, deserialize_i16); -impl_deserialize_saturating_num!(i32, deserialize_i32); -impl_deserialize_saturating_num!(i64, deserialize_i64); -impl_deserialize_saturating_num!(isize, deserialize_i64); - macro_rules! num_128 { ($ty:ident : $visit:ident) => { fn $visit(self, v: $ty) -> Result @@ -494,6 +510,21 @@ macro_rules! num_128 { } } }; + + (saturating $primitive:ident $ty:ident : $visit:ident) => { + fn $visit(self, v: $ty) -> Result + where + E: Error, + { + if (v as i128) < $primitive::MIN as i128 { + Ok(Saturating($primitive::MIN)) + } else if ($primitive::MAX as u128) < v as u128 { + Ok(Saturating($primitive::MAX)) + } else { + Ok(Saturating(v as $primitive)) + } + } + }; } impl_deserialize_num! { From c4fb92333593ac875ca7b615398f9de9d703ba8f Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 16 Apr 2024 14:18:01 -0700 Subject: [PATCH 073/258] Release 1.0.198 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 73732672f..239d0272f 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.197" +version = "1.0.198" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--cfg", "doc_cfg", "--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.197", path = "../serde_derive" } +serde_derive = { version = "=1.0.198", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index dc6d392bd..fefbf8fda 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.197")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.198")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 8d91a74d7..94b38d940 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.197" +version = "1.0.198" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index b91f17b1a..70b16e995 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.197")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.198")] // Ignored clippy lints #![allow( // clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054 From f6623a36548cfce02f880a33c6d2f420934c95c5 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 19 Apr 2024 20:57:34 -0700 Subject: [PATCH 074/258] Ignore cast_precision_loss pedantic clippy lint warning: casting `i32` to `f32` causes a loss of precision (`i32` is 32 bits wide, but `f32`'s mantissa is only 23 bits wide) --> serde/src/de/impls.rs:197:16 | 197 | Ok(v as Self::Value) | ^^^^^^^^^^^^^^^^ ... 457 | / impl_deserialize_num! { 458 | | f32, deserialize_f32 459 | | num_self!(f32:visit_f32); 460 | | num_as_copysign_self!(f64:visit_f64); 461 | | num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); 462 | | num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); 463 | | } | |_- in this macro invocation | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#cast_precision_loss = note: `-W clippy::cast-precision-loss` implied by `-W clippy::pedantic` = help: to override `-W clippy::pedantic` add `#[allow(clippy::cast_precision_loss)]` = note: this warning originates in the macro `num_as_self` which comes from the expansion of the macro `impl_deserialize_num` (in Nightly builds, run with -Z macro-backtrace for more info) warning: casting `i64` to `f32` causes a loss of precision (`i64` is 64 bits wide, but `f32`'s mantissa is only 23 bits wide) --> serde/src/de/impls.rs:197:16 | 197 | Ok(v as Self::Value) | ^^^^^^^^^^^^^^^^ ... 457 | / impl_deserialize_num! { 458 | | f32, deserialize_f32 459 | | num_self!(f32:visit_f32); 460 | | num_as_copysign_self!(f64:visit_f64); 461 | | num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); 462 | | num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); 463 | | } | |_- in this macro invocation | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#cast_precision_loss = note: this warning originates in the macro `num_as_self` which comes from the expansion of the macro `impl_deserialize_num` (in Nightly builds, run with -Z macro-backtrace for more info) warning: casting `u32` to `f32` causes a loss of precision (`u32` is 32 bits wide, but `f32`'s mantissa is only 23 bits wide) --> serde/src/de/impls.rs:197:16 | 197 | Ok(v as Self::Value) | ^^^^^^^^^^^^^^^^ ... 457 | / impl_deserialize_num! { 458 | | f32, deserialize_f32 459 | | num_self!(f32:visit_f32); 460 | | num_as_copysign_self!(f64:visit_f64); 461 | | num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); 462 | | num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); 463 | | } | |_- in this macro invocation | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#cast_precision_loss = note: this warning originates in the macro `num_as_self` which comes from the expansion of the macro `impl_deserialize_num` (in Nightly builds, run with -Z macro-backtrace for more info) warning: casting `u64` to `f32` causes a loss of precision (`u64` is 64 bits wide, but `f32`'s mantissa is only 23 bits wide) --> serde/src/de/impls.rs:197:16 | 197 | Ok(v as Self::Value) | ^^^^^^^^^^^^^^^^ ... 457 | / impl_deserialize_num! { 458 | | f32, deserialize_f32 459 | | num_self!(f32:visit_f32); 460 | | num_as_copysign_self!(f64:visit_f64); 461 | | num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); 462 | | num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); 463 | | } | |_- in this macro invocation | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#cast_precision_loss = note: this warning originates in the macro `num_as_self` which comes from the expansion of the macro `impl_deserialize_num` (in Nightly builds, run with -Z macro-backtrace for more info) warning: casting `i64` to `f64` causes a loss of precision (`i64` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide) --> serde/src/de/impls.rs:197:16 | 197 | Ok(v as Self::Value) | ^^^^^^^^^^^^^^^^ ... 465 | / impl_deserialize_num! { 466 | | f64, deserialize_f64 467 | | num_self!(f64:visit_f64); 468 | | num_as_copysign_self!(f32:visit_f32); 469 | | num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); 470 | | num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); 471 | | } | |_- in this macro invocation | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#cast_precision_loss = note: this warning originates in the macro `num_as_self` which comes from the expansion of the macro `impl_deserialize_num` (in Nightly builds, run with -Z macro-backtrace for more info) warning: casting `u64` to `f64` causes a loss of precision (`u64` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide) --> serde/src/de/impls.rs:197:16 | 197 | Ok(v as Self::Value) | ^^^^^^^^^^^^^^^^ ... 465 | / impl_deserialize_num! { 466 | | f64, deserialize_f64 467 | | num_self!(f64:visit_f64); 468 | | num_as_copysign_self!(f32:visit_f32); 469 | | num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); 470 | | num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); 471 | | } | |_- in this macro invocation | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#cast_precision_loss = note: this warning originates in the macro `num_as_self` which comes from the expansion of the macro `impl_deserialize_num` (in Nightly builds, run with -Z macro-backtrace for more info) --- serde/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/serde/src/lib.rs b/serde/src/lib.rs index fefbf8fda..f92210620 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -118,6 +118,7 @@ // integer and float ser/de requires these sorts of casts clippy::cast_possible_truncation, clippy::cast_possible_wrap, + clippy::cast_precision_loss, clippy::cast_sign_loss, // things are often more readable this way clippy::cast_lossless, From 8fe7539bb2b46001f70751f1db60e1a7144f8f3d Mon Sep 17 00:00:00 2001 From: Aatif Syed Date: Fri, 26 Apr 2024 13:04:00 +0200 Subject: [PATCH 075/258] fix: ambiguous associated type in forward_to_deserialize_any! --- serde/src/macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serde/src/macros.rs b/serde/src/macros.rs index a8fd85a37..9646cb375 100644 --- a/serde/src/macros.rs +++ b/serde/src/macros.rs @@ -123,7 +123,7 @@ macro_rules! forward_to_deserialize_any { macro_rules! forward_to_deserialize_any_method { ($func:ident<$l:tt, $v:ident>($($arg:ident : $ty:ty),*)) => { #[inline] - fn $func<$v>(self, $($arg: $ty,)* visitor: $v) -> $crate::__private::Result<$v::Value, Self::Error> + fn $func<$v>(self, $($arg: $ty,)* visitor: $v) -> $crate::__private::Result<$v::Value, >::Error> where $v: $crate::de::Visitor<$l>, { From 147702871760a38d2e97e0cd15d568559876aeda Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 26 Apr 2024 21:22:11 -0700 Subject: [PATCH 076/258] Release 1.0.199 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 239d0272f..3a844eed3 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.198" +version = "1.0.199" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--cfg", "doc_cfg", "--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.198", path = "../serde_derive" } +serde_derive = { version = "=1.0.199", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index f92210620..3da33efde 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.198")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.199")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 94b38d940..772aa429d 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.198" +version = "1.0.199" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index 70b16e995..a6cee61bc 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.198")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.199")] // Ignored clippy lints #![allow( // clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054 From 6ca499b2dd3d520903095b202770eba2720ba9b5 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Wed, 1 May 2024 08:20:59 -0400 Subject: [PATCH 077/258] Only format Unexpected::Float with decimal point if it is finite bef110b92a1 changed the display for unexpected floats to always append a ".0" if there was no decimal point found in the formatting of the float. However, this should only be relevant for finite (i.e., not NaN or inf) values. The change introduced a test failure in the ordered-float crate due to this: ---- impl_serde::test_fail_on_nan stdout ---- thread 'impl_serde::test_fail_on_nan' panicked at 'assertion failed: `(left == right)` left: `Error { msg: "invalid value: floating point `NaN.0`, expected float (but not NaN)" }`, right: `"invalid value: floating point `NaN`, expected float (but not NaN)"`', src/lib.rs:1554:9 stack backtrace: 0: rust_begin_unwind at /usr/src/rustc-1.70.0/library/std/src/panicking.rs:578:5 1: core::panicking::panic_fmt at /usr/src/rustc-1.70.0/library/core/src/panicking.rs:67:14 2: core::panicking::assert_failed_inner 3: core::panicking::assert_failed at /usr/src/rustc-1.70.0/library/core/src/panicking.rs:228:5 4: serde_test::assert::assert_de_tokens_error at /usr/share/cargo/registry/serde_test-1.0.171/src/assert.rs:228:19 5: ordered_float::impl_serde::test_fail_on_nan at ./src/lib.rs:1554:9 6: ordered_float::impl_serde::test_fail_on_nan::{{closure}} at ./src/lib.rs:1553:27 7: core::ops::function::FnOnce::call_once at /usr/src/rustc-1.70.0/library/core/src/ops/function.rs:250:5 8: core::ops::function::FnOnce::call_once at /usr/src/rustc-1.70.0/library/core/src/ops/function.rs:250:5 note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. --- serde/src/de/mod.rs | 18 +++++++++++------- test_suite/tests/test_de_error.rs | 8 ++++++++ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index 4c5a5f9b7..47d5ab8b0 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -2312,13 +2312,17 @@ impl Display for WithDecimalPoint { } } - let mut writer = LookForDecimalPoint { - formatter, - has_decimal_point: false, - }; - tri!(write!(writer, "{}", self.0)); - if !writer.has_decimal_point { - tri!(formatter.write_str(".0")); + if self.0.is_finite() { + let mut writer = LookForDecimalPoint { + formatter, + has_decimal_point: false, + }; + tri!(write!(writer, "{}", self.0)); + if !writer.has_decimal_point { + tri!(formatter.write_str(".0")); + } + } else { + tri!(write!(formatter, "{}", self.0)); } Ok(()) } diff --git a/test_suite/tests/test_de_error.rs b/test_suite/tests/test_de_error.rs index cf4bec86b..75c7e3030 100644 --- a/test_suite/tests/test_de_error.rs +++ b/test_suite/tests/test_de_error.rs @@ -1438,6 +1438,14 @@ fn test_integer_from_float() { ); } +#[test] +fn test_nan_no_decimal_point() { + assert_de_tokens_error::( + &[Token::F32(f32::NAN)], + "invalid type: floating point `NaN`, expected isize", + ); +} + #[test] fn test_unit_struct_from_seq() { assert_de_tokens_error::( From cc865ac5236c094275b10bff4fa41e561b3e359f Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 1 May 2024 08:58:52 -0700 Subject: [PATCH 078/258] Release 1.0.200 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 3a844eed3..a38c1d81d 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.199" +version = "1.0.200" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--cfg", "doc_cfg", "--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.199", path = "../serde_derive" } +serde_derive = { version = "=1.0.200", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 3da33efde..4bf3fc6a6 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.199")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.200")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 772aa429d..f42fbe547 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.199" +version = "1.0.200" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index a6cee61bc..393f8074b 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.199")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.200")] // Ignored clippy lints #![allow( // clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054 From 20306f493a4c943459e7492caf4dbcfca717790d Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 7 May 2024 16:53:53 -0700 Subject: [PATCH 079/258] Fix cfg on test_systemtime_overflow --- test_suite/tests/test_de_error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_suite/tests/test_de_error.rs b/test_suite/tests/test_de_error.rs index 75c7e3030..06508cbc8 100644 --- a/test_suite/tests/test_de_error.rs +++ b/test_suite/tests/test_de_error.rs @@ -1524,7 +1524,7 @@ fn test_systemtime_overflow_struct() { ); } -#[cfg(systemtime_checked_add)] +#[cfg(not(no_systemtime_checked_add))] #[test] fn test_systemtime_overflow() { assert_de_tokens_error::( From 220ca0ca9dddba8cc19d19968af7988ca3fc7d7c Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 4 May 2024 19:59:44 -0700 Subject: [PATCH 080/258] Resolve unexpected_cfgs warning warning: unexpected `cfg` condition name: `serde_build_from_git` --> serde_derive_internals/lib.rs:45:12 | 45 | #[cfg_attr(serde_build_from_git, path = "../serde_derive/src/internals/mod.rs")] | ^^^^^^^^^^^^^^^^^^^^ | = help: expected names are: `clippy`, `debug_assertions`, `doc`, `docsrs`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows` = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(serde_build_from_git)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition name: `serde_build_from_git` --> serde_derive_internals/lib.rs:46:16 | 46 | #[cfg_attr(not(serde_build_from_git), path = "src/mod.rs")] | ^^^^^^^^^^^^^^^^^^^^ | = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(serde_build_from_git)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `deserialize_in_place` --> serde_derive_internals/src/attr.rs:276:11 | 276 | #[cfg(feature = "deserialize_in_place")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the condition | = note: no expected values for `feature` = help: consider adding `deserialize_in_place` as a feature in `Cargo.toml` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `exhaustive` --> serde_derive_internals/src/attr.rs:1797:31 | 1797 | #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] | ^^^^^^^^^^ | = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `exhaustive` --> serde_derive_internals/src/receiver.rs:110:35 | 110 | #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] | ^^^^^^^^^^ | = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `exhaustive` --> serde_derive_internals/src/receiver.rs:181:47 | 181 | #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] | ^^^^^^^^^^ | = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `exhaustive` --> serde_derive_internals/src/receiver.rs:210:35 | 210 | #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] | ^^^^^^^^^^ | = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `exhaustive` --> serde_derive_internals/src/receiver.rs:231:43 | 231 | #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] | ^^^^^^^^^^ | = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `exhaustive` --> serde_derive/src/lib.rs:62:23 | 62 | #![cfg_attr(all(test, exhaustive), feature(non_exhaustive_omitted_patterns_lint))] | ^^^^^^^^^^ | = help: expected names are: `clippy`, `debug_assertions`, `doc`, `docsrs`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows` = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition name: `exhaustive` --> serde_derive/src/internals/attr.rs:1797:31 | 1797 | #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] | ^^^^^^^^^^ | = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `exhaustive` --> serde_derive/src/internals/receiver.rs:110:35 | 110 | #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] | ^^^^^^^^^^ | = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `exhaustive` --> serde_derive/src/internals/receiver.rs:181:47 | 181 | #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] | ^^^^^^^^^^ | = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `exhaustive` --> serde_derive/src/internals/receiver.rs:210:35 | 210 | #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] | ^^^^^^^^^^ | = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `exhaustive` --> serde_derive/src/internals/receiver.rs:231:43 | 231 | #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] | ^^^^^^^^^^ | = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `exhaustive` --> serde_derive/src/bound.rs:147:39 | 147 | #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] | ^^^^^^^^^^ | = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `exhaustive` --> serde_derive/src/bound.rs:199:51 | 199 | ... #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] | ^^^^^^^^^^ | = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `exhaustive` --> serde_derive/src/bound.rs:228:39 | 228 | #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] | ^^^^^^^^^^ | = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(exhaustive)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `systemtime_checked_add` --> test_suite/tests/test_de_error.rs:1527:7 | 1527 | #[cfg(systemtime_checked_add)] | ^^^^^^^^^^^^^^^^^^^^^^ | = help: expected names are: `clippy`, `debug_assertions`, `doc`, `docsrs`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows` = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(systemtime_checked_add)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default --- serde/build.rs | 15 +++++++++++++++ serde_derive/Cargo.toml | 1 + serde_derive/build.rs | 7 +++++++ serde_derive/src/lib.rs | 1 + serde_derive_internals/build.rs | 8 ++++++++ serde_derive_internals/lib.rs | 1 + test_suite/tests/test_de_error.rs | 1 - 7 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 serde_derive/build.rs diff --git a/serde/build.rs b/serde/build.rs index 0074df63f..097e5f98f 100644 --- a/serde/build.rs +++ b/serde/build.rs @@ -13,6 +13,21 @@ fn main() { None => return, }; + if minor >= 77 { + println!("cargo:rustc-check-cfg=cfg(doc_cfg)"); + println!("cargo:rustc-check-cfg=cfg(no_core_cstr)"); + println!("cargo:rustc-check-cfg=cfg(no_core_num_saturating)"); + println!("cargo:rustc-check-cfg=cfg(no_core_try_from)"); + println!("cargo:rustc-check-cfg=cfg(no_float_copysign)"); + println!("cargo:rustc-check-cfg=cfg(no_num_nonzero_signed)"); + println!("cargo:rustc-check-cfg=cfg(no_relaxed_trait_bounds)"); + println!("cargo:rustc-check-cfg=cfg(no_serde_derive)"); + println!("cargo:rustc-check-cfg=cfg(no_std_atomic)"); + println!("cargo:rustc-check-cfg=cfg(no_std_atomic64)"); + println!("cargo:rustc-check-cfg=cfg(no_systemtime_checked_add)"); + println!("cargo:rustc-check-cfg=cfg(no_target_has_atomic)"); + } + let target = env::var("TARGET").unwrap(); let emscripten = target == "asmjs-unknown-emscripten" || target == "wasm32-unknown-emscripten"; diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index f42fbe547..7b85edb8d 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -6,6 +6,7 @@ categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" documentation = "https://serde.rs/derive.html" edition = "2015" +exclude = ["build.rs"] homepage = "https://serde.rs" keywords = ["serde", "serialization", "no_std", "derive"] license = "MIT OR Apache-2.0" diff --git a/serde_derive/build.rs b/serde_derive/build.rs new file mode 100644 index 000000000..ecd2acf40 --- /dev/null +++ b/serde_derive/build.rs @@ -0,0 +1,7 @@ +fn main() { + // Warning: build.rs is not published to crates.io. + + println!("cargo:rustc-cfg=check_cfg"); + println!("cargo:rustc-check-cfg=cfg(check_cfg)"); + println!("cargo:rustc-check-cfg=cfg(exhaustive)"); +} diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index 393f8074b..cdc3c2b90 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -14,6 +14,7 @@ //! [https://serde.rs/derive.html]: https://serde.rs/derive.html #![doc(html_root_url = "https://docs.rs/serde_derive/1.0.200")] +#![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] // Ignored clippy lints #![allow( // clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054 diff --git a/serde_derive_internals/build.rs b/serde_derive_internals/build.rs index 25b5ef313..b2bbb3a56 100644 --- a/serde_derive_internals/build.rs +++ b/serde_derive_internals/build.rs @@ -1,9 +1,17 @@ use std::path::Path; fn main() { + // Warning: build.rs is not published to crates.io. + println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-changed=src/mod.rs"); + println!("cargo:rustc-cfg=check_cfg"); + println!("cargo:rustc-check-cfg=cfg(check_cfg)"); + println!("cargo:rustc-check-cfg=cfg(exhaustive)"); + println!("cargo:rustc-check-cfg=cfg(serde_build_from_git)"); + println!("cargo:rustc-check-cfg=cfg(feature, values(\"deserialize_in_place\"))"); + // 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 diff --git a/serde_derive_internals/lib.rs b/serde_derive_internals/lib.rs index 1053b009a..b3d55baac 100644 --- a/serde_derive_internals/lib.rs +++ b/serde_derive_internals/lib.rs @@ -1,4 +1,5 @@ #![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.29.0")] +#![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] // Ignored clippy lints #![allow( clippy::cognitive_complexity, diff --git a/test_suite/tests/test_de_error.rs b/test_suite/tests/test_de_error.rs index 06508cbc8..cae5eddab 100644 --- a/test_suite/tests/test_de_error.rs +++ b/test_suite/tests/test_de_error.rs @@ -1524,7 +1524,6 @@ fn test_systemtime_overflow_struct() { ); } -#[cfg(not(no_systemtime_checked_add))] #[test] fn test_systemtime_overflow() { assert_de_tokens_error::( From b4f1bc16ffe9650750695db59bcb786033a929be Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 7 May 2024 17:02:11 -0700 Subject: [PATCH 081/258] Release 1.0.201 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index a38c1d81d..3df903b7d 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.200" +version = "1.0.201" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--cfg", "doc_cfg", "--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.200", path = "../serde_derive" } +serde_derive = { version = "=1.0.201", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 4bf3fc6a6..75904e787 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.200")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.201")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 7b85edb8d..3fc93d99b 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.200" +version = "1.0.201" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index cdc3c2b90..c1155ef91 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.200")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.201")] #![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] // Ignored clippy lints #![allow( From 3202a6858a2802b5aba2fa5cf3ec8f203408db74 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 8 May 2024 21:59:41 -0700 Subject: [PATCH 082/258] Skip rerunning build script on library code changes --- serde_derive/build.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/serde_derive/build.rs b/serde_derive/build.rs index ecd2acf40..ebaa409a4 100644 --- a/serde_derive/build.rs +++ b/serde_derive/build.rs @@ -1,6 +1,7 @@ fn main() { // Warning: build.rs is not published to crates.io. + println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rustc-cfg=check_cfg"); println!("cargo:rustc-check-cfg=cfg(check_cfg)"); println!("cargo:rustc-check-cfg=cfg(exhaustive)"); From 48cc2a63279d4ea44a88d566b0667f65c9ea79f4 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 14 May 2024 23:02:27 -0700 Subject: [PATCH 083/258] Replace use of a syn From impl The From impls may be going away in the next version of syn. --- serde_derive/src/internals/receiver.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serde_derive/src/internals/receiver.rs b/serde_derive/src/internals/receiver.rs index fa2a77d24..852e857b8 100644 --- a/serde_derive/src/internals/receiver.rs +++ b/serde_derive/src/internals/receiver.rs @@ -84,7 +84,7 @@ impl ReplaceReceiver<'_> { self.visit_type_mut_impl(ty); return; }; - *ty = self.self_ty(span).into(); + *ty = Type::Path(self.self_ty(span)); } // `Self::Assoc` -> `::Assoc` From f6ab0bc56f3df6d03974d233ffce352b0725ae09 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 15 May 2024 00:30:55 -0700 Subject: [PATCH 084/258] Provide public access to RenameAllRules in serde_derive_internals --- serde_derive/src/internals/attr.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/serde_derive/src/internals/attr.rs b/serde_derive/src/internals/attr.rs index bb9de328a..0cfb23bf1 100644 --- a/serde_derive/src/internals/attr.rs +++ b/serde_derive/src/internals/attr.rs @@ -185,8 +185,8 @@ impl Name { #[derive(Copy, Clone)] pub struct RenameAllRules { - serialize: RenameRule, - deserialize: RenameRule, + pub serialize: RenameRule, + pub deserialize: RenameRule, } impl RenameAllRules { From 87f635e54d5359fa0eb94b1ef0a684ee3d24cb85 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 15 May 2024 00:35:14 -0700 Subject: [PATCH 085/258] Release serde_derive_internals 0.29.1 --- serde_derive_internals/Cargo.toml | 2 +- serde_derive_internals/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/serde_derive_internals/Cargo.toml b/serde_derive_internals/Cargo.toml index 095a7439c..bf99c1399 100644 --- a/serde_derive_internals/Cargo.toml +++ b/serde_derive_internals/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive_internals" -version = "0.29.0" +version = "0.29.1" authors = ["Erick Tryzelaar ", "David Tolnay "] description = "AST representation used by Serde derive macros. Unstable." documentation = "https://docs.rs/serde_derive_internals" diff --git a/serde_derive_internals/lib.rs b/serde_derive_internals/lib.rs index b3d55baac..6edb07ee0 100644 --- a/serde_derive_internals/lib.rs +++ b/serde_derive_internals/lib.rs @@ -1,4 +1,4 @@ -#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.29.0")] +#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.29.1")] #![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] // Ignored clippy lints #![allow( From 9e32a40b1c745d1d67d451cc983fab5751d394a5 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 15 May 2024 00:42:49 -0700 Subject: [PATCH 086/258] Release 1.0.202 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 3df903b7d..1dea49bc4 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.201" +version = "1.0.202" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--cfg", "doc_cfg", "--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.201", path = "../serde_derive" } +serde_derive = { version = "=1.0.202", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 75904e787..308895da1 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.201")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.202")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 3fc93d99b..a2b479268 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.201" +version = "1.0.202" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index c1155ef91..2146989a5 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.201")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.202")] #![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] // Ignored clippy lints #![allow( From a8f14840ab3ff58f533cd27d0f91955d57f12a65 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 18 May 2024 21:16:37 -0700 Subject: [PATCH 087/258] Rely on docs.rs to define --cfg=docsrs by default --- serde/Cargo.toml | 2 +- serde/build.rs | 1 - serde/src/de/impls.rs | 70 +++++++++++++++++++++--------------------- serde/src/de/mod.rs | 4 +-- serde/src/de/value.rs | 24 +++++++-------- serde/src/lib.rs | 4 +-- serde/src/ser/impls.rs | 64 +++++++++++++++++++------------------- 7 files changed, 84 insertions(+), 85 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 1dea49bc4..3a7ce5e79 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -29,7 +29,7 @@ features = ["derive", "rc"] [package.metadata.docs.rs] features = ["derive", "rc", "unstable"] targets = ["x86_64-unknown-linux-gnu"] -rustdoc-args = ["--cfg", "doc_cfg", "--generate-link-to-definition"] +rustdoc-args = ["--generate-link-to-definition"] # This cfg cannot be enabled, but it still forces Cargo to keep serde_derive's # version in lockstep with serde's, even if someone depends on the two crates diff --git a/serde/build.rs b/serde/build.rs index 097e5f98f..46ca435d5 100644 --- a/serde/build.rs +++ b/serde/build.rs @@ -14,7 +14,6 @@ fn main() { }; if minor >= 77 { - println!("cargo:rustc-check-cfg=cfg(doc_cfg)"); println!("cargo:rustc-check-cfg=cfg(no_core_cstr)"); println!("cargo:rustc-check-cfg=cfg(no_core_num_saturating)"); println!("cargo:rustc-check-cfg=cfg(no_core_try_from)"); diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 140878aec..f26b20d46 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -39,7 +39,7 @@ impl<'de> Deserialize<'de> for () { } #[cfg(feature = "unstable")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "unstable")))] +#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))] impl<'de> Deserialize<'de> for ! { fn deserialize(_deserializer: D) -> Result where @@ -695,7 +695,7 @@ impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> { } #[cfg(any(feature = "std", feature = "alloc"))] -#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de> Deserialize<'de> for String { fn deserialize(deserializer: D) -> Result where @@ -839,7 +839,7 @@ impl<'de> Visitor<'de> for CStringVisitor { } #[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))] -#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de> Deserialize<'de> for CString { fn deserialize(deserializer: D) -> Result where @@ -868,7 +868,7 @@ macro_rules! forwarded_impl { forwarded_impl! { #[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))] - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] (), Box, CString::into_boxed_c_str } @@ -1086,7 +1086,7 @@ fn nop_reserve(_seq: T, _n: usize) {} seq_impl!( #[cfg(any(feature = "std", feature = "alloc"))] - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] BinaryHeap, seq, BinaryHeap::clear, @@ -1097,7 +1097,7 @@ seq_impl!( seq_impl!( #[cfg(any(feature = "std", feature = "alloc"))] - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] BTreeSet, seq, BTreeSet::clear, @@ -1108,7 +1108,7 @@ seq_impl!( seq_impl!( #[cfg(any(feature = "std", feature = "alloc"))] - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] LinkedList, seq, LinkedList::clear, @@ -1119,7 +1119,7 @@ seq_impl!( seq_impl!( #[cfg(feature = "std")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] HashSet, seq, HashSet::clear, @@ -1130,7 +1130,7 @@ seq_impl!( seq_impl!( #[cfg(any(feature = "std", feature = "alloc"))] - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] VecDeque, seq, VecDeque::clear, @@ -1142,7 +1142,7 @@ seq_impl!( //////////////////////////////////////////////////////////////////////////////// #[cfg(any(feature = "std", feature = "alloc"))] -#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, T> Deserialize<'de> for Vec where T: Deserialize<'de>, @@ -1546,7 +1546,7 @@ macro_rules! map_impl { map_impl! { #[cfg(any(feature = "std", feature = "alloc"))] - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] BTreeMap, map, BTreeMap::new(), @@ -1554,7 +1554,7 @@ map_impl! { map_impl! { #[cfg(feature = "std")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] HashMap, map, HashMap::with_capacity_and_hasher(size_hint::cautious::<(K, V)>(map.size_hint()), S::default()), @@ -1696,7 +1696,7 @@ macro_rules! deserialize_enum { } #[cfg(feature = "std")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl<'de> Deserialize<'de> for net::IpAddr { fn deserialize(deserializer: D) -> Result where @@ -1717,13 +1717,13 @@ impl<'de> Deserialize<'de> for net::IpAddr { parse_ip_impl! { #[cfg(feature = "std")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] net::Ipv4Addr, "IPv4 address", 4 } parse_ip_impl! { #[cfg(feature = "std")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] net::Ipv6Addr, "IPv6 address", 16 } @@ -1750,7 +1750,7 @@ macro_rules! parse_socket_impl { } #[cfg(feature = "std")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl<'de> Deserialize<'de> for net::SocketAddr { fn deserialize(deserializer: D) -> Result where @@ -1771,14 +1771,14 @@ impl<'de> Deserialize<'de> for net::SocketAddr { parse_socket_impl! { #[cfg(feature = "std")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] net::SocketAddrV4, "IPv4 socket address", |(ip, port)| net::SocketAddrV4::new(ip, port), } parse_socket_impl! { #[cfg(feature = "std")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] net::SocketAddrV6, "IPv6 socket address", |(ip, port)| net::SocketAddrV6::new(ip, port, 0, 0), } @@ -1814,7 +1814,7 @@ impl<'a> Visitor<'a> for PathVisitor { } #[cfg(feature = "std")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl<'de: 'a, 'a> Deserialize<'de> for &'a Path { fn deserialize(deserializer: D) -> Result where @@ -1869,7 +1869,7 @@ impl<'de> Visitor<'de> for PathBufVisitor { } #[cfg(feature = "std")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl<'de> Deserialize<'de> for PathBuf { fn deserialize(deserializer: D) -> Result where @@ -1881,7 +1881,7 @@ impl<'de> Deserialize<'de> for PathBuf { forwarded_impl! { #[cfg(feature = "std")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] (), Box, PathBuf::into_boxed_path } @@ -1943,7 +1943,7 @@ impl<'de> Visitor<'de> for OsStringVisitor { } #[cfg(all(feature = "std", any(unix, windows)))] -#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", any(unix, windows)))))] +#[cfg_attr(docsrs, doc(cfg(all(feature = "std", any(unix, windows)))))] impl<'de> Deserialize<'de> for OsString { fn deserialize(deserializer: D) -> Result where @@ -1957,30 +1957,30 @@ impl<'de> Deserialize<'de> for OsString { forwarded_impl! { #[cfg(any(feature = "std", feature = "alloc"))] - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] (T), Box, Box::new } forwarded_impl! { #[cfg(any(feature = "std", feature = "alloc"))] - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] (T), Box<[T]>, Vec::into_boxed_slice } forwarded_impl! { #[cfg(any(feature = "std", feature = "alloc"))] - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] (), Box, String::into_boxed_str } forwarded_impl! { #[cfg(all(feature = "std", any(unix, windows)))] - #[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", any(unix, windows)))))] + #[cfg_attr(docsrs, doc(cfg(all(feature = "std", any(unix, windows)))))] (), Box, OsString::into_boxed_os_str } #[cfg(any(feature = "std", feature = "alloc"))] -#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, 'a, T> Deserialize<'de> for Cow<'a, T> where T: ?Sized + ToOwned, @@ -2003,7 +2003,7 @@ where /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg_attr( - doc_cfg, + docsrs, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))) )] impl<'de, T> Deserialize<'de> for RcWeak @@ -2025,7 +2025,7 @@ where /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg_attr( - doc_cfg, + docsrs, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))) )] impl<'de, T> Deserialize<'de> for ArcWeak @@ -2073,7 +2073,7 @@ box_forwarded_impl! { /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] - #[cfg_attr(doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))] + #[cfg_attr(docsrs, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))] Rc } @@ -2086,7 +2086,7 @@ box_forwarded_impl! { /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] - #[cfg_attr(doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))] + #[cfg_attr(docsrs, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))] Arc } @@ -2110,13 +2110,13 @@ forwarded_impl! { forwarded_impl! { #[cfg(feature = "std")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] (T), Mutex, Mutex::new } forwarded_impl! { #[cfg(feature = "std")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] (T), RwLock, RwLock::new } @@ -2271,7 +2271,7 @@ impl<'de> Deserialize<'de> for Duration { //////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "std")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl<'de> Deserialize<'de> for SystemTime { fn deserialize(deserializer: D) -> Result where @@ -3107,7 +3107,7 @@ macro_rules! atomic_impl { ($($ty:ident $size:expr)*) => { $( #[cfg(any(no_target_has_atomic, target_has_atomic = $size))] - #[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", target_has_atomic = $size))))] + #[cfg_attr(docsrs, doc(cfg(all(feature = "std", target_has_atomic = $size))))] impl<'de> Deserialize<'de> for $ty { fn deserialize(deserializer: D) -> Result where diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index 47d5ab8b0..602054a18 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -1525,7 +1525,7 @@ pub trait Visitor<'de>: Sized { /// `String`. #[inline] #[cfg(any(feature = "std", feature = "alloc"))] - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] fn visit_string(self, v: String) -> Result where E: Error, @@ -1584,7 +1584,7 @@ pub trait Visitor<'de>: Sized { /// The default implementation forwards to `visit_bytes` and then drops the /// `Vec`. #[cfg(any(feature = "std", feature = "alloc"))] - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] fn visit_byte_buf(self, v: Vec) -> Result where E: Error, diff --git a/serde/src/de/value.rs b/serde/src/de/value.rs index 3bc0c71c5..1ec947786 100644 --- a/serde/src/de/value.rs +++ b/serde/src/de/value.rs @@ -112,7 +112,7 @@ impl Debug for Error { } #[cfg(feature = "std")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl error::Error for Error { fn description(&self) -> &str { &self.err @@ -185,14 +185,14 @@ impl Debug for UnitDeserializer { /// A deserializer that cannot be instantiated. #[cfg(feature = "unstable")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "unstable")))] +#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))] pub struct NeverDeserializer { never: !, marker: PhantomData, } #[cfg(feature = "unstable")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "unstable")))] +#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))] impl<'de, E> IntoDeserializer<'de, E> for ! where E: de::Error, @@ -565,7 +565,7 @@ impl<'de, E> Debug for BorrowedStrDeserializer<'de, E> { /// A deserializer holding a `String`. #[cfg(any(feature = "std", feature = "alloc"))] -#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] pub struct StringDeserializer { value: String, marker: PhantomData, @@ -582,7 +582,7 @@ impl Clone for StringDeserializer { } #[cfg(any(feature = "std", feature = "alloc"))] -#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, E> IntoDeserializer<'de, E> for String where E: de::Error, @@ -670,7 +670,7 @@ impl Debug for StringDeserializer { /// A deserializer holding a `Cow`. #[cfg(any(feature = "std", feature = "alloc"))] -#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] pub struct CowStrDeserializer<'a, E> { value: Cow<'a, str>, marker: PhantomData, @@ -687,7 +687,7 @@ impl<'a, E> Clone for CowStrDeserializer<'a, E> { } #[cfg(any(feature = "std", feature = "alloc"))] -#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, 'a, E> IntoDeserializer<'de, E> for Cow<'a, str> where E: de::Error, @@ -1006,7 +1006,7 @@ where //////////////////////////////////////////////////////////////////////////////// #[cfg(any(feature = "std", feature = "alloc"))] -#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, T, E> IntoDeserializer<'de, E> for Vec where T: IntoDeserializer<'de, E>, @@ -1020,7 +1020,7 @@ where } #[cfg(any(feature = "std", feature = "alloc"))] -#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, T, E> IntoDeserializer<'de, E> for BTreeSet where T: IntoDeserializer<'de, E> + Eq + Ord, @@ -1034,7 +1034,7 @@ where } #[cfg(feature = "std")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl<'de, T, S, E> IntoDeserializer<'de, E> for HashSet where T: IntoDeserializer<'de, E> + Eq + Hash, @@ -1421,7 +1421,7 @@ impl Expected for ExpectedInMap { //////////////////////////////////////////////////////////////////////////////// #[cfg(any(feature = "std", feature = "alloc"))] -#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, K, V, E> IntoDeserializer<'de, E> for BTreeMap where K: IntoDeserializer<'de, E> + Eq + Ord, @@ -1436,7 +1436,7 @@ where } #[cfg(feature = "std")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl<'de, K, V, S, E> IntoDeserializer<'de, E> for HashMap where K: IntoDeserializer<'de, E> + Eq + Hash, diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 308895da1..3185d340e 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -99,7 +99,7 @@ // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. -#![cfg_attr(doc_cfg, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_cfg))] // Unstable functionality only if the user asks for it. For tracking and // discussion of these features please refer to this issue: // @@ -330,7 +330,7 @@ extern crate serde_derive; /// Derive macro available if serde is built with `features = ["derive"]`. #[cfg(feature = "serde_derive")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))] +#[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub use serde_derive::{Deserialize, Serialize}; #[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))] diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index ffc4c70f9..70711afd4 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -48,7 +48,7 @@ impl Serialize for str { } #[cfg(any(feature = "std", feature = "alloc"))] -#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] impl Serialize for String { #[inline] fn serialize(&self, serializer: S) -> Result @@ -71,7 +71,7 @@ impl<'a> Serialize for fmt::Arguments<'a> { //////////////////////////////////////////////////////////////////////////////// #[cfg(any(feature = "std", not(no_core_cstr)))] -#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl Serialize for CStr { #[inline] fn serialize(&self, serializer: S) -> Result @@ -83,7 +83,7 @@ impl Serialize for CStr { } #[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))] -#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] impl Serialize for CString { #[inline] fn serialize(&self, serializer: S) -> Result @@ -232,37 +232,37 @@ macro_rules! seq_impl { seq_impl! { #[cfg(any(feature = "std", feature = "alloc"))] - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] BinaryHeap } seq_impl! { #[cfg(any(feature = "std", feature = "alloc"))] - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] BTreeSet } seq_impl! { #[cfg(feature = "std")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] HashSet } seq_impl! { #[cfg(any(feature = "std", feature = "alloc"))] - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] LinkedList } seq_impl! { #[cfg(any(feature = "std", feature = "alloc"))] - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] Vec } seq_impl! { #[cfg(any(feature = "std", feature = "alloc"))] - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] VecDeque } @@ -371,7 +371,7 @@ impl Serialize for () { } #[cfg(feature = "unstable")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "unstable")))] +#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))] impl Serialize for ! { fn serialize(&self, _serializer: S) -> Result where @@ -476,13 +476,13 @@ macro_rules! map_impl { map_impl! { #[cfg(any(feature = "std", feature = "alloc"))] - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] BTreeMap } map_impl! { #[cfg(feature = "std")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] HashMap } @@ -516,7 +516,7 @@ deref_impl! { deref_impl! { #[cfg(any(feature = "std", feature = "alloc"))] - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] Serialize for Box where T: ?Sized + Serialize } @@ -530,7 +530,7 @@ deref_impl! { /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] - #[cfg_attr(doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))] + #[cfg_attr(docsrs, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))] Serialize for Rc where T: ?Sized + Serialize } @@ -544,13 +544,13 @@ deref_impl! { /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] - #[cfg_attr(doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))] + #[cfg_attr(docsrs, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))] Serialize for Arc where T: ?Sized + Serialize } deref_impl! { #[cfg(any(feature = "std", feature = "alloc"))] - #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] <'a, T> Serialize for Cow<'a, T> where T: ?Sized + Serialize + ToOwned } @@ -561,7 +561,7 @@ deref_impl! { /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg_attr( - doc_cfg, + docsrs, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))) )] impl Serialize for RcWeak @@ -581,7 +581,7 @@ where /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg_attr( - doc_cfg, + docsrs, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))) )] impl Serialize for ArcWeak @@ -660,7 +660,7 @@ where } #[cfg(feature = "std")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl Serialize for Mutex where T: ?Sized + Serialize, @@ -677,7 +677,7 @@ where } #[cfg(feature = "std")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl Serialize for RwLock where T: ?Sized + Serialize, @@ -731,7 +731,7 @@ impl Serialize for Duration { //////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "std")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl Serialize for SystemTime { fn serialize(&self, serializer: S) -> Result where @@ -776,7 +776,7 @@ macro_rules! serialize_display_bounded_length { } #[cfg(feature = "std")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl Serialize for net::IpAddr { fn serialize(&self, serializer: S) -> Result where @@ -847,7 +847,7 @@ fn test_format_u8() { } #[cfg(feature = "std")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl Serialize for net::Ipv4Addr { fn serialize(&self, serializer: S) -> Result where @@ -872,7 +872,7 @@ impl Serialize for net::Ipv4Addr { } #[cfg(feature = "std")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl Serialize for net::Ipv6Addr { fn serialize(&self, serializer: S) -> Result where @@ -889,7 +889,7 @@ impl Serialize for net::Ipv6Addr { } #[cfg(feature = "std")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl Serialize for net::SocketAddr { fn serialize(&self, serializer: S) -> Result where @@ -914,7 +914,7 @@ impl Serialize for net::SocketAddr { } #[cfg(feature = "std")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl Serialize for net::SocketAddrV4 { fn serialize(&self, serializer: S) -> Result where @@ -931,7 +931,7 @@ impl Serialize for net::SocketAddrV4 { } #[cfg(feature = "std")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl Serialize for net::SocketAddrV6 { fn serialize(&self, serializer: S) -> Result where @@ -953,7 +953,7 @@ impl Serialize for net::SocketAddrV6 { //////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "std")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl Serialize for Path { fn serialize(&self, serializer: S) -> Result where @@ -967,7 +967,7 @@ impl Serialize for Path { } #[cfg(feature = "std")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl Serialize for PathBuf { fn serialize(&self, serializer: S) -> Result where @@ -978,7 +978,7 @@ impl Serialize for PathBuf { } #[cfg(all(feature = "std", any(unix, windows)))] -#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", any(unix, windows)))))] +#[cfg_attr(docsrs, doc(cfg(all(feature = "std", any(unix, windows)))))] impl Serialize for OsStr { #[cfg(unix)] fn serialize(&self, serializer: S) -> Result @@ -1001,7 +1001,7 @@ impl Serialize for OsStr { } #[cfg(all(feature = "std", any(unix, windows)))] -#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", any(unix, windows)))))] +#[cfg_attr(docsrs, doc(cfg(all(feature = "std", any(unix, windows)))))] impl Serialize for OsString { fn serialize(&self, serializer: S) -> Result where @@ -1060,7 +1060,7 @@ macro_rules! atomic_impl { ($($ty:ident $size:expr)*) => { $( #[cfg(any(no_target_has_atomic, target_has_atomic = $size))] - #[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", target_has_atomic = $size))))] + #[cfg_attr(docsrs, doc(cfg(all(feature = "std", target_has_atomic = $size))))] impl Serialize for $ty { fn serialize(&self, serializer: S) -> Result where From 5d3c563d469ef36ce5a01f1612f53883fee20db5 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 25 May 2024 10:02:21 -0700 Subject: [PATCH 088/258] Document tuple impls as fake variadic --- serde/src/de/impls.rs | 31 ++++++++++++++++++++++++++----- serde/src/lib.rs | 3 ++- serde/src/ser/impls.rs | 26 ++++++++++++++++++++++---- 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index f26b20d46..4f71a20e5 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -1393,7 +1393,19 @@ array_impls! { macro_rules! tuple_impls { ($($len:tt => ($($n:tt $name:ident)+))+) => { $( - impl<'de, $($name: Deserialize<'de>),+> Deserialize<'de> for ($($name,)+) { + #[cfg_attr(docsrs, doc(hidden))] + impl<'de, $($name),+> Deserialize<'de> for ($($name,)+) + where + $($name: Deserialize<'de>,)+ + { + tuple_impl_body!($len => ($($n $name)+)); + } + )+ + }; +} + +macro_rules! tuple_impl_body { + ($len:tt => ($($n:tt $name:ident)+)) => { #[inline] fn deserialize(deserializer: D) -> Result where @@ -1462,13 +1474,22 @@ macro_rules! tuple_impls { deserializer.deserialize_tuple($len, TupleInPlaceVisitor(place)) } - } - )+ - } + }; +} + +#[cfg_attr(docsrs, doc(fake_variadic))] +#[cfg_attr( + docsrs, + doc = "This trait is implemented for tuples up to 16 items long." +)] +impl<'de, T> Deserialize<'de> for (T,) +where + T: Deserialize<'de>, +{ + tuple_impl_body!(1 => (0 T)); } tuple_impls! { - 1 => (0 T0) 2 => (0 T0 1 T1) 3 => (0 T0 1 T1 2 T2) 4 => (0 T0 1 T1 2 T2 3 T3) diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 3185d340e..d2eeca162 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -99,7 +99,8 @@ // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_cfg, rustdoc_internals))] +#![cfg_attr(docsrs, allow(internal_features))] // Unstable functionality only if the user asks for it. For tracking and // discussion of these features please refer to this issue: // diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index 70711afd4..c3a6215ad 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -386,10 +386,19 @@ impl Serialize for ! { macro_rules! tuple_impls { ($($len:expr => ($($n:tt $name:ident)+))+) => { $( + #[cfg_attr(docsrs, doc(hidden))] impl<$($name),+> Serialize for ($($name,)+) where $($name: Serialize,)+ { + tuple_impl_body!($len => ($($n)+)); + } + )+ + }; +} + +macro_rules! tuple_impl_body { + ($len:expr => ($($n:tt)+)) => { #[inline] fn serialize(&self, serializer: S) -> Result where @@ -401,13 +410,22 @@ macro_rules! tuple_impls { )+ tuple.end() } - } - )+ - } + }; +} + +#[cfg_attr(docsrs, doc(fake_variadic))] +#[cfg_attr( + docsrs, + doc = "This trait is implemented for tuples up to 16 items long." +)] +impl Serialize for (T,) +where + T: Serialize, +{ + tuple_impl_body!(1 => (0)); } tuple_impls! { - 1 => (0 T0) 2 => (0 T0 1 T1) 3 => (0 T0 1 T1 2 T2) 4 => (0 T0 1 T1 2 T2 3 T3) From b7b97dda7333baf6474517e3646754be54e3796b Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 25 May 2024 10:11:45 -0700 Subject: [PATCH 089/258] Unindent implementation inside tuple_impl_body macro --- serde/src/de/impls.rs | 104 ++++++++++++++++++++--------------------- serde/src/ser/impls.rs | 22 ++++----- 2 files changed, 63 insertions(+), 63 deletions(-) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 4f71a20e5..02591d982 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -1406,74 +1406,74 @@ macro_rules! tuple_impls { macro_rules! tuple_impl_body { ($len:tt => ($($n:tt $name:ident)+)) => { + #[inline] + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct TupleVisitor<$($name,)+> { + marker: PhantomData<($($name,)+)>, + } + + impl<'de, $($name: Deserialize<'de>),+> Visitor<'de> for TupleVisitor<$($name,)+> { + type Value = ($($name,)+); + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str(concat!("a tuple of size ", $len)) + } + #[inline] - fn deserialize(deserializer: D) -> Result + #[allow(non_snake_case)] + fn visit_seq(self, mut seq: A) -> Result where - D: Deserializer<'de>, + A: SeqAccess<'de>, { - struct TupleVisitor<$($name,)+> { - marker: PhantomData<($($name,)+)>, - } + $( + let $name = match tri!(seq.next_element()) { + Some(value) => value, + None => return Err(Error::invalid_length($n, &self)), + }; + )+ - impl<'de, $($name: Deserialize<'de>),+> Visitor<'de> for TupleVisitor<$($name,)+> { - type Value = ($($name,)+); + Ok(($($name,)+)) + } + } - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str(concat!("a tuple of size ", $len)) - } + deserializer.deserialize_tuple($len, TupleVisitor { marker: PhantomData }) + } - #[inline] - #[allow(non_snake_case)] - fn visit_seq(self, mut seq: A) -> Result - where - A: SeqAccess<'de>, - { - $( - let $name = match tri!(seq.next_element()) { - Some(value) => value, - None => return Err(Error::invalid_length($n, &self)), - }; - )+ + #[inline] + fn deserialize_in_place(deserializer: D, place: &mut Self) -> Result<(), D::Error> + where + D: Deserializer<'de>, + { + struct TupleInPlaceVisitor<'a, $($name: 'a,)+>(&'a mut ($($name,)+)); - Ok(($($name,)+)) - } - } + impl<'a, 'de, $($name: Deserialize<'de>),+> Visitor<'de> for TupleInPlaceVisitor<'a, $($name,)+> { + type Value = (); - deserializer.deserialize_tuple($len, TupleVisitor { marker: PhantomData }) + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str(concat!("a tuple of size ", $len)) } #[inline] - fn deserialize_in_place(deserializer: D, place: &mut Self) -> Result<(), D::Error> + #[allow(non_snake_case)] + fn visit_seq(self, mut seq: A) -> Result where - D: Deserializer<'de>, + A: SeqAccess<'de>, { - struct TupleInPlaceVisitor<'a, $($name: 'a,)+>(&'a mut ($($name,)+)); - - impl<'a, 'de, $($name: Deserialize<'de>),+> Visitor<'de> for TupleInPlaceVisitor<'a, $($name,)+> { - type Value = (); - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str(concat!("a tuple of size ", $len)) - } - - #[inline] - #[allow(non_snake_case)] - fn visit_seq(self, mut seq: A) -> Result - where - A: SeqAccess<'de>, - { - $( - if tri!(seq.next_element_seed(InPlaceSeed(&mut (self.0).$n))).is_none() { - return Err(Error::invalid_length($n, &self)); - } - )+ - - Ok(()) + $( + if tri!(seq.next_element_seed(InPlaceSeed(&mut (self.0).$n))).is_none() { + return Err(Error::invalid_length($n, &self)); } - } + )+ - deserializer.deserialize_tuple($len, TupleInPlaceVisitor(place)) + Ok(()) } + } + + deserializer.deserialize_tuple($len, TupleInPlaceVisitor(place)) + } }; } diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index c3a6215ad..557b6aa12 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -399,17 +399,17 @@ macro_rules! tuple_impls { macro_rules! tuple_impl_body { ($len:expr => ($($n:tt)+)) => { - #[inline] - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - let mut tuple = tri!(serializer.serialize_tuple($len)); - $( - tri!(tuple.serialize_element(&self.$n)); - )+ - tuple.end() - } + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut tuple = tri!(serializer.serialize_tuple($len)); + $( + tri!(tuple.serialize_element(&self.$n)); + )+ + tuple.end() + } }; } From d5bc546ca53be0b31984a06a8ad587cbea4ca5ce Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 25 May 2024 10:43:27 -0700 Subject: [PATCH 090/258] Release 1.0.203 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 3a7ce5e79..3d9832268 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.202" +version = "1.0.203" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.202", path = "../serde_derive" } +serde_derive = { version = "=1.0.203", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index d2eeca162..1d9e6bc12 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.202")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.203")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index a2b479268..f006f716a 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.202" +version = "1.0.203" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index 2146989a5..019cbff62 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.202")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.203")] #![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] // Ignored clippy lints #![allow( From 7aafa263146f9140b18879c114a69fe96b2ebffc Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 1 Jun 2024 22:13:43 -0700 Subject: [PATCH 091/258] Fill in ignore reasons in all #[ignore] attributes --- test_suite/tests/compiletest.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test_suite/tests/compiletest.rs b/test_suite/tests/compiletest.rs index 621660b08..8ab6342f2 100644 --- a/test_suite/tests/compiletest.rs +++ b/test_suite/tests/compiletest.rs @@ -1,6 +1,6 @@ -#[cfg_attr(target_os = "emscripten", ignore)] -#[rustversion::attr(not(nightly), ignore)] -#[cfg_attr(miri, ignore)] +#[cfg_attr(target_os = "emscripten", ignore = "disabled on Emscripten")] +#[rustversion::attr(not(nightly), ignore = "requires nightly")] +#[cfg_attr(miri, ignore = "incompatible with miri")] #[allow(unused_attributes)] #[test] fn ui() { From fee0b82a40123e7a7234a43a3fc762c413be8bb3 Mon Sep 17 00:00:00 2001 From: Bastiaan Marinus van de Weerd Date: Thu, 6 Jun 2024 23:19:04 -0400 Subject: [PATCH 092/258] Fix missing close paren in crates-io.md --- crates-io.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates-io.md b/crates-io.md index 187100358..b49a5483b 100644 --- a/crates-io.md +++ b/crates-io.md @@ -46,8 +46,8 @@ fn main() { Serde is one of the most widely used Rust libraries so any place that Rustaceans congregate will be able to help you out. For chat, consider trying the [#rust-questions] or [#rust-beginners] channels of the unofficial community -Discord (invite: , the [#rust-usage] or -[#beginners] channels of the official Rust Project Discord (invite: +Discord (invite: ), the [#rust-usage] +or [#beginners] channels of the official Rust Project Discord (invite: ), or the [#general][zulip] stream in Zulip. For asynchronous, consider the [\[rust\] tag on StackOverflow][stackoverflow], the [/r/rust] subreddit which has a pinned weekly easy questions post, or the Rust From 9e6158e9e6be4a9e599643a12539f2e9d9ab4506 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 10 Jun 2024 09:45:45 -0700 Subject: [PATCH 093/258] Nightly no longer requires error_in_core feature warning: the feature `error_in_core` has been stable since 1.81.0-nightly and no longer requires an attribute to enable --> serde/src/lib.rs:108:43 | 108 | #![cfg_attr(feature = "unstable", feature(error_in_core, never_type))] | ^^^^^^^^^^^^^ | = note: `#[warn(stable_features)]` on by default --- serde/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 1d9e6bc12..43ae06763 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -105,7 +105,7 @@ // discussion of these features please refer to this issue: // // https://github.com/serde-rs/serde/issues/812 -#![cfg_attr(feature = "unstable", feature(error_in_core, never_type))] +#![cfg_attr(feature = "unstable", feature(never_type))] #![allow(unknown_lints, bare_trait_objects, deprecated)] // Ignored clippy and clippy_pedantic lints #![allow( From f3dfd2a2375d9caf15a18ec657dde51a32caf6ed Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 26 Jun 2024 19:41:19 -0700 Subject: [PATCH 094/258] Suppress dead code warning in test of unit struct remote derive error: struct `RemoteSelf` is never constructed --> test_suite/tests/test_gen.rs:425:12 | 425 | struct RemoteSelf; | ^^^^^^^^^^ | note: the lint level is defined here --> test_suite/tests/test_gen.rs:5:9 | 5 | #![deny(warnings)] | ^^^^^^^^ = note: `#[deny(dead_code)]` implied by `#[deny(warnings)]` --- test_suite/tests/test_gen.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/test_suite/tests/test_gen.rs b/test_suite/tests/test_gen.rs index 4aaf06a8b..d7ae9190f 100644 --- a/test_suite/tests/test_gen.rs +++ b/test_suite/tests/test_gen.rs @@ -422,6 +422,7 @@ fn test_gen() { #[derive(Serialize, Deserialize)] #[serde(remote = "Self")] + #[allow(dead_code)] struct RemoteSelf; #[derive(Serialize, Deserialize)] From 694fe0595358aa0857120a99041d99975b1a8a70 Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Tue, 2 Jul 2024 16:39:06 +0200 Subject: [PATCH 095/258] Use the `#[diagnostic::on_unimplemented]` attribute when possible This change enables the `#[diagnostic::on_unimplemented]` attribute for the `Serialize` and `Deserialize` trait to point the user to the relevant derives and point out that they might want to check crates features for external types by adding the relevant hints an note. --- serde/build.rs | 7 +++++++ serde/src/de/mod.rs | 7 +++++++ serde/src/ser/mod.rs | 7 +++++++ 3 files changed, 21 insertions(+) diff --git a/serde/build.rs b/serde/build.rs index 46ca435d5..261ed52ab 100644 --- a/serde/build.rs +++ b/serde/build.rs @@ -25,6 +25,7 @@ fn main() { println!("cargo:rustc-check-cfg=cfg(no_std_atomic64)"); println!("cargo:rustc-check-cfg=cfg(no_systemtime_checked_add)"); println!("cargo:rustc-check-cfg=cfg(no_target_has_atomic)"); + println!("cargo:rustc-check-cfg=cfg(no_diagnostic_namespace)"); } let target = env::var("TARGET").unwrap(); @@ -84,6 +85,12 @@ fn main() { if minor < 74 { println!("cargo:rustc-cfg=no_core_num_saturating"); } + + // Support for the `#[diagnostic]` tool attribute namespace + // https://blog.rust-lang.org/2024/05/02/Rust-1.78.0.html#diagnostic-attributes + if minor < 78 { + println!("cargo:rustc-cfg=no_diagnostic_namespace"); + } } fn rustc_minor_version() -> Option { diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index 602054a18..d6b9f5ab4 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -532,6 +532,13 @@ impl<'a> Display for Expected + 'a { /// deserializer lifetimes] for a more detailed explanation of these lifetimes. /// /// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html +#[cfg_attr( + not(no_diagnostic_namespace), + diagnostic::on_unimplemented( + note = "for local types consider adding `#[derive(serde::Deserialize)]` to your `{Self}` type", + note = "for types from other crates check whether the crate offers a `serde` feature flag", + ) +)] pub trait Deserialize<'de>: Sized { /// Deserialize this value from the given Serde deserializer. /// diff --git a/serde/src/ser/mod.rs b/serde/src/ser/mod.rs index 74b5e0769..30a648093 100644 --- a/serde/src/ser/mod.rs +++ b/serde/src/ser/mod.rs @@ -215,6 +215,13 @@ declare_error_trait!(Error: Sized + Debug + Display); /// [`linked-hash-map`]: https://crates.io/crates/linked-hash-map /// [`serde_derive`]: https://crates.io/crates/serde_derive /// [derive section of the manual]: https://serde.rs/derive.html +#[cfg_attr( + not(no_diagnostic_namespace), + diagnostic::on_unimplemented( + note = "for local types consider adding `#[derive(serde::Serialize)]` to your `{Self}` type", + note = "for types from other crates check whether the crate offers a `serde` feature flag", + ) +)] pub trait Serialize { /// Serialize this value into the given Serde serializer. /// From b0d7917f88978eda264f8fbac13b46ece35f5348 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 6 Jul 2024 13:13:04 -0700 Subject: [PATCH 096/258] Pull in trybuild 'following types implement trait' fix --- test_suite/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_suite/Cargo.toml b/test_suite/Cargo.toml index b7686baf2..07e62656a 100644 --- a/test_suite/Cargo.toml +++ b/test_suite/Cargo.toml @@ -18,4 +18,4 @@ rustversion = "1.0" serde = { path = "../serde", features = ["rc"] } serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] } serde_test = "1.0.176" -trybuild = { version = "1.0.66", features = ["diff"] } +trybuild = { version = "1.0.97", features = ["diff"] } From 595019e979ebed5452b550bf901abcab2cf4e945 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 6 Jul 2024 13:25:54 -0700 Subject: [PATCH 097/258] Cut test_suite from workspace members in old toolchain CI jobs The test suite's dependencies cannot be resolved by an old toolchain. error: failed to select a version for the requirement `toml = "^0.8"` candidate versions found which didn't match: 0.5.11, 0.5.10, 0.5.9, ... location searched: crates.io index required by package `trybuild v1.0.97` ... which satisfies dependency `trybuild = "^1.0.97"` of package `serde_test_suite v0.0.0` --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8487ba65d..8c32b678b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -84,6 +84,7 @@ jobs: - uses: dtolnay/rust-toolchain@master with: toolchain: ${{matrix.rust}} + - run: sed -i '/"test_suite"/d' Cargo.toml - run: cd serde && cargo build --features rc - run: cd serde && cargo build --no-default-features - run: cd serde && cargo build @@ -95,6 +96,7 @@ jobs: steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@1.56.0 + - run: sed -i '/"test_suite"/d' Cargo.toml - run: cd serde && cargo check --no-default-features - run: cd serde && cargo check - run: cd serde_derive && cargo check @@ -106,6 +108,7 @@ jobs: steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@1.36.0 + - run: sed -i '/"test_suite"/d' Cargo.toml - run: cd serde && cargo build --no-default-features --features alloc minimal: From 91aa40e749620f31bf7db01c772e672f023136b5 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 6 Jul 2024 10:25:56 -0700 Subject: [PATCH 098/258] Add ui test of unsatisfied serde trait bound --- test_suite/tests/ui/on_unimplemented.rs | 23 ++++++++++ test_suite/tests/ui/on_unimplemented.stderr | 51 +++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 test_suite/tests/ui/on_unimplemented.rs create mode 100644 test_suite/tests/ui/on_unimplemented.stderr diff --git a/test_suite/tests/ui/on_unimplemented.rs b/test_suite/tests/ui/on_unimplemented.rs new file mode 100644 index 000000000..fab56751b --- /dev/null +++ b/test_suite/tests/ui/on_unimplemented.rs @@ -0,0 +1,23 @@ +use serde::de::Deserialize; +use serde::ser::Serialize; + +fn to_string(_: &T) -> String +where + T: Serialize, +{ + unimplemented!() +} + +fn from_str<'de, T>(_: &'de str) -> T +where + T: Deserialize<'de>, +{ + unimplemented!() +} + +struct MyStruct; + +fn main() { + to_string(&MyStruct); + let _: MyStruct = from_str(""); +} diff --git a/test_suite/tests/ui/on_unimplemented.stderr b/test_suite/tests/ui/on_unimplemented.stderr new file mode 100644 index 000000000..3575f4a60 --- /dev/null +++ b/test_suite/tests/ui/on_unimplemented.stderr @@ -0,0 +1,51 @@ +error[E0277]: the trait bound `MyStruct: Serialize` is not satisfied + --> tests/ui/on_unimplemented.rs:21:15 + | +21 | to_string(&MyStruct); + | --------- ^^^^^^^^^ the trait `Serialize` is not implemented for `MyStruct` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `Serialize`: + &'a T + &'a mut T + () + (T,) + (T0, T1) + (T0, T1, T2) + (T0, T1, T2, T3) + (T0, T1, T2, T3, T4) + and $N others +note: required by a bound in `to_string` + --> tests/ui/on_unimplemented.rs:6:8 + | +4 | fn to_string(_: &T) -> String + | --------- required by a bound in this function +5 | where +6 | T: Serialize, + | ^^^^^^^^^ required by this bound in `to_string` + +error[E0277]: the trait bound `MyStruct: Deserialize<'_>` is not satisfied + --> tests/ui/on_unimplemented.rs:22:23 + | +22 | let _: MyStruct = from_str(""); + | ^^^^^^^^^^^^ the trait `Deserialize<'_>` is not implemented for `MyStruct` + | + = help: the following other types implement trait `Deserialize<'de>`: + &'a Path + &'a [u8] + &'a str + () + (T,) + (T0, T1) + (T0, T1, T2) + (T0, T1, T2, T3) + and $N others +note: required by a bound in `from_str` + --> tests/ui/on_unimplemented.rs:13:8 + | +11 | fn from_str<'de, T>(_: &'de str) -> T + | -------- required by a bound in this function +12 | where +13 | T: Deserialize<'de>, + | ^^^^^^^^^^^^^^^^ required by this bound in `from_str` From 1179158defc5351467cbd2c340b7e1498391bce4 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 6 Jul 2024 13:17:21 -0700 Subject: [PATCH 099/258] Update ui test with diagnostic::on_unimplemented from PR 2767 --- test_suite/tests/ui/on_unimplemented.stderr | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test_suite/tests/ui/on_unimplemented.stderr b/test_suite/tests/ui/on_unimplemented.stderr index 3575f4a60..1b0318190 100644 --- a/test_suite/tests/ui/on_unimplemented.stderr +++ b/test_suite/tests/ui/on_unimplemented.stderr @@ -6,6 +6,8 @@ error[E0277]: the trait bound `MyStruct: Serialize` is not satisfied | | | required by a bound introduced by this call | + = note: for local types consider adding `#[derive(serde::Serialize)]` to your `MyStruct` type + = note: for types from other crates check whether the crate offers a `serde` feature flag = help: the following other types implement trait `Serialize`: &'a T &'a mut T @@ -31,6 +33,8 @@ error[E0277]: the trait bound `MyStruct: Deserialize<'_>` is not satisfied 22 | let _: MyStruct = from_str(""); | ^^^^^^^^^^^^ the trait `Deserialize<'_>` is not implemented for `MyStruct` | + = note: for local types consider adding `#[derive(serde::Deserialize)]` to your `MyStruct` type + = note: for types from other crates check whether the crate offers a `serde` feature flag = help: the following other types implement trait `Deserialize<'de>`: &'a Path &'a [u8] From 58c307f9cc28a19d73a0e2869f6addf9a8a329f9 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 6 Jul 2024 10:30:46 -0700 Subject: [PATCH 100/258] Alphabetize list of rustc-check-cfg --- serde/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serde/build.rs b/serde/build.rs index 261ed52ab..c32872b95 100644 --- a/serde/build.rs +++ b/serde/build.rs @@ -17,6 +17,7 @@ fn main() { println!("cargo:rustc-check-cfg=cfg(no_core_cstr)"); println!("cargo:rustc-check-cfg=cfg(no_core_num_saturating)"); println!("cargo:rustc-check-cfg=cfg(no_core_try_from)"); + println!("cargo:rustc-check-cfg=cfg(no_diagnostic_namespace)"); println!("cargo:rustc-check-cfg=cfg(no_float_copysign)"); println!("cargo:rustc-check-cfg=cfg(no_num_nonzero_signed)"); println!("cargo:rustc-check-cfg=cfg(no_relaxed_trait_bounds)"); @@ -25,7 +26,6 @@ fn main() { println!("cargo:rustc-check-cfg=cfg(no_std_atomic64)"); println!("cargo:rustc-check-cfg=cfg(no_systemtime_checked_add)"); println!("cargo:rustc-check-cfg=cfg(no_target_has_atomic)"); - println!("cargo:rustc-check-cfg=cfg(no_diagnostic_namespace)"); } let target = env::var("TARGET").unwrap(); From 18dcae0a77632fb4767a420c550cb41991f750b8 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 6 Jul 2024 13:38:01 -0700 Subject: [PATCH 101/258] Release 1.0.204 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 3d9832268..b51397218 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.203" +version = "1.0.204" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.203", path = "../serde_derive" } +serde_derive = { version = "=1.0.204", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 43ae06763..6a0569460 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.203")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.204")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index f006f716a..91509f599 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.203" +version = "1.0.204" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index 019cbff62..6ad174dc6 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.203")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.204")] #![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] // Ignored clippy lints #![allow( From 28a092261b1b47726c4c16fd00aa7de8df19785f Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 6 Jul 2024 19:17:26 -0700 Subject: [PATCH 102/258] Work around test suite dead code warnings in nightly-2024-07-07 warning: struct `Cows` is never constructed --> test_suite/tests/test_borrow.rs:165:12 | 165 | struct Cows<'a, 'b> { | ^^^^ warning: struct `Wrap` is never constructed --> test_suite/tests/test_borrow.rs:181:12 | 181 | struct Wrap<'a, 'b> { | ^^^^ warning: struct `StructSkipDefaultGeneric` is never constructed --> test_suite/tests/test_de.rs:96:8 | 96 | struct StructSkipDefaultGeneric { | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: struct `NonAsciiIdents` is never constructed --> test_suite/tests/test_gen.rs:290:12 | 290 | struct NonAsciiIdents { | ^^^^^^^^^^^^^^ | note: the lint level is defined here --> test_suite/tests/test_gen.rs:5:9 | 5 | #![deny(warnings)] | ^^^^^^^^ = note: `#[warn(dead_code)]` implied by `#[warn(warnings)]` warning: struct `EmptyBraced` is never constructed --> test_suite/tests/test_gen.rs:295:12 | 295 | struct EmptyBraced {} | ^^^^^^^^^^^ warning: struct `EmptyBracedDenyUnknown` is never constructed --> test_suite/tests/test_gen.rs:299:12 | 299 | struct EmptyBracedDenyUnknown {} | ^^^^^^^^^^^^^^^^^^^^^^ warning: struct `BracedSkipAll` is never constructed --> test_suite/tests/test_gen.rs:302:12 | 302 | struct BracedSkipAll { | ^^^^^^^^^^^^^ warning: struct `BracedSkipAllDenyUnknown` is never constructed --> test_suite/tests/test_gen.rs:309:12 | 309 | struct BracedSkipAllDenyUnknown { | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: struct `EmptyTuple` is never constructed --> test_suite/tests/test_gen.rs:315:12 | 315 | struct EmptyTuple(); | ^^^^^^^^^^ warning: struct `EmptyTupleDenyUnknown` is never constructed --> test_suite/tests/test_gen.rs:319:12 | 319 | struct EmptyTupleDenyUnknown(); | ^^^^^^^^^^^^^^^^^^^^^ warning: struct `TupleSkipAll` is never constructed --> test_suite/tests/test_gen.rs:322:12 | 322 | struct TupleSkipAll(#[serde(skip_deserializing)] u8); | ^^^^^^^^^^^^ warning: struct `TupleSkipAllDenyUnknown` is never constructed --> test_suite/tests/test_gen.rs:326:12 | 326 | struct TupleSkipAllDenyUnknown(#[serde(skip_deserializing)] u8); | ^^^^^^^^^^^^^^^^^^^^^^^ warning: enum `EmptyEnum` is never used --> test_suite/tests/test_gen.rs:329:10 | 329 | enum EmptyEnum {} | ^^^^^^^^^ warning: enum `EmptyEnumDenyUnknown` is never used --> test_suite/tests/test_gen.rs:333:10 | 333 | enum EmptyEnumDenyUnknown {} | ^^^^^^^^^^^^^^^^^^^^ warning: enum `EnumSkipAll` is never used --> test_suite/tests/test_gen.rs:336:10 | 336 | enum EnumSkipAll { | ^^^^^^^^^^^ warning: enum `EmptyVariants` is never used --> test_suite/tests/test_gen.rs:343:10 | 343 | enum EmptyVariants { | ^^^^^^^^^^^^^ warning: enum `EmptyVariantsDenyUnknown` is never used --> test_suite/tests/test_gen.rs:355:10 | 355 | enum EmptyVariantsDenyUnknown { | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: struct `UnitDenyUnknown` is never constructed --> test_suite/tests/test_gen.rs:367:12 | 367 | struct UnitDenyUnknown; | ^^^^^^^^^^^^^^^ warning: struct `EmptyArray` is never constructed --> test_suite/tests/test_gen.rs:370:12 | 370 | struct EmptyArray { | ^^^^^^^^^^ warning: enum `Or` is never used --> test_suite/tests/test_gen.rs:374:10 | 374 | enum Or { | ^^ warning: enum `OrDef` is never used --> test_suite/tests/test_gen.rs:381:10 | 381 | enum OrDef { | ^^^^^ warning: struct `Str` is never constructed --> test_suite/tests/test_gen.rs:386:12 | 386 | struct Str<'a>(&'a str); | ^^^ warning: struct `StrDef` is never constructed --> test_suite/tests/test_gen.rs:390:12 | 390 | struct StrDef<'a>(&'a str); | ^^^^^^ warning: struct `Remote` is never constructed --> test_suite/tests/test_gen.rs:393:12 | 393 | struct Remote<'a> { | ^^^^^^ warning: enum `BorrowVariant` is never used --> test_suite/tests/test_gen.rs:401:10 | 401 | enum BorrowVariant<'a> { | ^^^^^^^^^^^^^ warning: struct `RemoteVisibility` is never constructed --> test_suite/tests/test_gen.rs:418:12 | 418 | struct RemoteVisibility { | ^^^^^^^^^^^^^^^^ warning: struct `FlattenDenyUnknown` is never constructed --> test_suite/tests/test_gen.rs:551:12 | 551 | struct FlattenDenyUnknown { | ^^^^^^^^^^^^^^^^^^ warning: struct `StaticStrStruct` is never constructed --> test_suite/tests/test_gen.rs:557:12 | 557 | struct StaticStrStruct<'a> { | ^^^^^^^^^^^^^^^ warning: struct `StaticStrTupleStruct` is never constructed --> test_suite/tests/test_gen.rs:563:12 | 563 | struct StaticStrTupleStruct<'a>(&'a str, &'static str); | ^^^^^^^^^^^^^^^^^^^^ warning: struct `StaticStrNewtypeStruct` is never constructed --> test_suite/tests/test_gen.rs:566:12 | 566 | struct StaticStrNewtypeStruct(&'static str); | ^^^^^^^^^^^^^^^^^^^^^^ warning: enum `StaticStrEnum` is never used --> test_suite/tests/test_gen.rs:569:10 | 569 | enum StaticStrEnum<'a> { | ^^^^^^^^^^^^^ warning: enum `AdjacentlyTaggedVoid` is never used --> test_suite/tests/test_gen.rs:652:10 | 652 | enum AdjacentlyTaggedVoid {} | ^^^^^^^^^^^^^^^^^^^^ warning: struct `ImplicitlyBorrowedOption` is never constructed --> test_suite/tests/test_gen.rs:665:12 | 665 | struct ImplicitlyBorrowedOption<'a> { | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: enum `UntaggedNewtypeVariantWith` is never used --> test_suite/tests/test_gen.rs:672:10 | 672 | enum UntaggedNewtypeVariantWith { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: struct `TransparentWith` is never constructed --> test_suite/tests/test_gen.rs:682:12 | 682 | struct TransparentWith { | ^^^^^^^^^^^^^^^ warning: struct `FlattenSkipSerializing` is never constructed --> test_suite/tests/test_gen.rs:712:12 | 712 | struct FlattenSkipSerializing { | ^^^^^^^^^^^^^^^^^^^^^^ warning: struct `FlattenSkipSerializingIf` is never constructed --> test_suite/tests/test_gen.rs:719:12 | 719 | struct FlattenSkipSerializingIf { | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: struct `FlattenSkipDeserializing` is never constructed --> test_suite/tests/test_gen.rs:725:12 | 725 | struct FlattenSkipDeserializing { | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: enum `Message` is never used --> test_suite/tests/test_gen.rs:732:10 | 732 | enum Message { | ^^^^^^^ warning: struct `MacroRules` is never constructed --> test_suite/tests/test_gen.rs:751:20 | 751 | struct MacroRules<'a> { | ^^^^^^^^^^ ... 758 | deriving!(&'a str); | ------------------ in this macro invocation | = note: this warning originates in the macro `deriving` (in Nightly builds, run with -Z macro-backtrace for more info) warning: struct `BorrowLifetimeInsideMacro` is never constructed --> test_suite/tests/test_gen.rs:767:12 | 767 | struct BorrowLifetimeInsideMacro<'a> { | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: struct `GenericUnitStruct` is never constructed --> test_suite/tests/test_gen.rs:782:12 | 782 | struct GenericUnitStruct; | ^^^^^^^^^^^^^^^^^ warning: enum `InternallyTagged` is never used --> test_suite/tests/test_gen.rs:869:6 | 869 | enum InternallyTagged { | ^^^^^^^^^^^^^^^^ warning: function `deserialize_generic` is never used --> test_suite/tests/test_gen.rs:880:4 | 880 | fn deserialize_generic<'de, T, D>(deserializer: D) -> StdResult | ^^^^^^^^^^^^^^^^^^^ warning: struct `Restricted` is never constructed --> test_suite/tests/test_gen.rs:643:20 | 643 | struct Restricted { | ^^^^^^^^^^ warning: struct `Test` is never constructed --> test_suite/tests/test_remote.rs:95:8 | 95 | struct Test { | ^^^^ warning: struct `UnitDef` is never constructed --> test_suite/tests/test_remote.rs:135:8 | 135 | struct UnitDef; | ^^^^^^^ warning: struct `PrimitivePubDef` is never constructed --> test_suite/tests/test_remote.rs:143:8 | 143 | struct PrimitivePubDef(u8); | ^^^^^^^^^^^^^^^ warning: struct `NewtypePubDef` is never constructed --> test_suite/tests/test_remote.rs:151:8 | 151 | struct NewtypePubDef(#[serde(with = "UnitDef")] remote::Unit); | ^^^^^^^^^^^^^ warning: struct `TuplePubDef` is never constructed --> test_suite/tests/test_remote.rs:162:8 | 162 | struct TuplePubDef(u8, #[serde(with = "UnitDef")] remote::Unit); | ^^^^^^^^^^^ warning: struct `StructPubDef` is never constructed --> test_suite/tests/test_remote.rs:177:8 | 177 | struct StructPubDef { | ^^^^^^^^^^^^ warning: struct `StructConcrete` is never constructed --> test_suite/tests/test_remote.rs:193:8 | 193 | struct StructConcrete { | ^^^^^^^^^^^^^^ warning: enum `EnumConcrete` is never used --> test_suite/tests/test_remote.rs:199:6 | 199 | enum EnumConcrete { | ^^^^^^^^^^^^ warning: enum `ErrorKind` is never used --> test_suite/tests/test_remote.rs:204:6 | 204 | enum ErrorKind { | ^^^^^^^^^ warning: enum `ErrorKindDef` is never used --> test_suite/tests/test_remote.rs:214:6 | 214 | enum ErrorKindDef { | ^^^^^^^^^^^^ warning: struct `PrimitivePub` is never constructed --> test_suite/tests/test_remote.rs:10:16 | 10 | pub struct PrimitivePub(pub u8); | ^^^^^^^^^^^^ warning: struct `NewtypePub` is never constructed --> test_suite/tests/test_remote.rs:14:16 | 14 | pub struct NewtypePub(pub Unit); | ^^^^^^^^^^ warning: struct `TuplePub` is never constructed --> test_suite/tests/test_remote.rs:18:16 | 18 | pub struct TuplePub(pub u8, pub Unit); | ^^^^^^^^ warning: struct `StructPub` is never constructed --> test_suite/tests/test_remote.rs:25:16 | 25 | pub struct StructPub { | ^^^^^^^^^ warning: enum `EnumGeneric` is never used --> test_suite/tests/test_remote.rs:89:14 | 89 | pub enum EnumGeneric { | ^^^^^^^^^^^ warning: struct `Tuple` is never constructed --> test_suite/tests/test_self.rs:44:12 | 44 | struct Tuple( | ^^^^^ warning: associated items `ASSOC` and `assoc` are never used --> test_suite/tests/test_self.rs:52:15 | 51 | impl Tuple { | ---------- associated items in this implementation 52 | const ASSOC: usize = 1; | ^^^^^ 53 | const fn assoc() -> usize { | ^^^^^ warning: enum `Enum` is never used --> test_suite/tests/test_self.rs:63:10 | 63 | enum Enum { | ^^^^ warning: associated items `ASSOC` and `assoc` are never used --> test_suite/tests/test_self.rs:79:15 | 78 | impl Enum { | --------- associated items in this implementation 79 | const ASSOC: usize = 1; | ^^^^^ 80 | const fn assoc() -> usize { | ^^^^^ warning: struct `Unit` is never constructed --> test_suite/no_std/src/main.rs:26:8 | 26 | struct Unit; | ^^^^ warning: struct `Newtype` is never constructed --> test_suite/no_std/src/main.rs:29:8 | 29 | struct Newtype(u8); | ^^^^^^^ warning: struct `Tuple` is never constructed --> test_suite/no_std/src/main.rs:32:8 | 32 | struct Tuple(u8, u8); | ^^^^^ warning: struct `Struct` is never constructed --> test_suite/no_std/src/main.rs:35:8 | 35 | struct Struct { | ^^^^^^ warning: enum `Enum` is never used --> test_suite/no_std/src/main.rs:40:6 | 40 | enum Enum { | ^^^^ --- test_suite/no_std/src/main.rs | 10 ++-- test_suite/tests/test_borrow.rs | 4 +- test_suite/tests/test_de.rs | 2 +- test_suite/tests/test_gen.rs | 94 +++++++++++++++------------------ test_suite/tests/test_remote.rs | 15 ++++++ test_suite/tests/test_self.rs | 4 +- 6 files changed, 69 insertions(+), 60 deletions(-) diff --git a/test_suite/no_std/src/main.rs b/test_suite/no_std/src/main.rs index 57b3f3151..f8ef34b44 100644 --- a/test_suite/no_std/src/main.rs +++ b/test_suite/no_std/src/main.rs @@ -23,21 +23,21 @@ fn panic(_info: &core::panic::PanicInfo) -> ! { use serde_derive::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] -struct Unit; +pub struct Unit; #[derive(Serialize, Deserialize)] -struct Newtype(u8); +pub struct Newtype(u8); #[derive(Serialize, Deserialize)] -struct Tuple(u8, u8); +pub struct Tuple(u8, u8); #[derive(Serialize, Deserialize)] -struct Struct { +pub struct Struct { f: u8, } #[derive(Serialize, Deserialize)] -enum Enum { +pub enum Enum { Unit, Newtype(u8), Tuple(u8, u8), diff --git a/test_suite/tests/test_borrow.rs b/test_suite/tests/test_borrow.rs index f749ec323..a9eee4550 100644 --- a/test_suite/tests/test_borrow.rs +++ b/test_suite/tests/test_borrow.rs @@ -162,7 +162,7 @@ fn test_cow() { #[test] fn test_lifetimes() { #[derive(Deserialize)] - struct Cows<'a, 'b> { + pub struct Cows<'a, 'b> { _copied: Cow<'a, str>, #[serde(borrow)] @@ -178,7 +178,7 @@ fn test_lifetimes() { } #[derive(Deserialize)] - struct Wrap<'a, 'b> { + pub struct Wrap<'a, 'b> { #[serde(borrow = "'b")] _cows: Cows<'a, 'b>, } diff --git a/test_suite/tests/test_de.rs b/test_suite/tests/test_de.rs index 8a7310cd2..31e726d4b 100644 --- a/test_suite/tests/test_de.rs +++ b/test_suite/tests/test_de.rs @@ -93,7 +93,7 @@ struct StructSkipDefault { #[derive(PartialEq, Debug, Deserialize)] #[serde(default)] -struct StructSkipDefaultGeneric { +pub struct StructSkipDefaultGeneric { #[serde(skip_deserializing)] t: T, } diff --git a/test_suite/tests/test_gen.rs b/test_suite/tests/test_gen.rs index d7ae9190f..f8d577bb8 100644 --- a/test_suite/tests/test_gen.rs +++ b/test_suite/tests/test_gen.rs @@ -287,60 +287,60 @@ fn test_gen() { assert::(); #[derive(Serialize, Deserialize)] - struct NonAsciiIdents { + pub struct NonAsciiIdents { σ: f64, } #[derive(Serialize, Deserialize)] - struct EmptyBraced {} + pub struct EmptyBraced {} #[derive(Serialize, Deserialize)] #[serde(deny_unknown_fields)] - struct EmptyBracedDenyUnknown {} + pub struct EmptyBracedDenyUnknown {} #[derive(Serialize, Deserialize)] - struct BracedSkipAll { + pub struct BracedSkipAll { #[serde(skip_deserializing)] f: u8, } #[derive(Serialize, Deserialize)] #[serde(deny_unknown_fields)] - struct BracedSkipAllDenyUnknown { + pub struct BracedSkipAllDenyUnknown { #[serde(skip_deserializing)] f: u8, } #[derive(Serialize, Deserialize)] - struct EmptyTuple(); + pub struct EmptyTuple(); #[derive(Serialize, Deserialize)] #[serde(deny_unknown_fields)] - struct EmptyTupleDenyUnknown(); + pub struct EmptyTupleDenyUnknown(); #[derive(Serialize, Deserialize)] - struct TupleSkipAll(#[serde(skip_deserializing)] u8); + pub struct TupleSkipAll(#[serde(skip_deserializing)] u8); #[derive(Serialize, Deserialize)] #[serde(deny_unknown_fields)] - struct TupleSkipAllDenyUnknown(#[serde(skip_deserializing)] u8); + pub struct TupleSkipAllDenyUnknown(#[serde(skip_deserializing)] u8); #[derive(Serialize, Deserialize)] - enum EmptyEnum {} + pub enum EmptyEnum {} #[derive(Serialize, Deserialize)] #[serde(deny_unknown_fields)] - enum EmptyEnumDenyUnknown {} + pub enum EmptyEnumDenyUnknown {} #[derive(Serialize, Deserialize)] - enum EnumSkipAll { + pub enum EnumSkipAll { #[serde(skip_deserializing)] #[allow(dead_code)] Variant, } #[derive(Serialize, Deserialize)] - enum EmptyVariants { + pub enum EmptyVariants { Braced {}, Tuple(), BracedSkip { @@ -352,7 +352,7 @@ fn test_gen() { #[derive(Serialize, Deserialize)] #[serde(deny_unknown_fields)] - enum EmptyVariantsDenyUnknown { + pub enum EmptyVariantsDenyUnknown { Braced {}, Tuple(), BracedSkip { @@ -364,21 +364,21 @@ fn test_gen() { #[derive(Serialize, Deserialize)] #[serde(deny_unknown_fields)] - struct UnitDenyUnknown; + pub struct UnitDenyUnknown; #[derive(Serialize, Deserialize)] - struct EmptyArray { + pub struct EmptyArray { empty: [X; 0], } - enum Or { + pub enum Or { A(A), B(B), } #[derive(Serialize, Deserialize)] #[serde(untagged, remote = "Or")] - enum OrDef { + pub enum OrDef { A(A), B(B), } @@ -390,7 +390,7 @@ fn test_gen() { struct StrDef<'a>(&'a str); #[derive(Serialize, Deserialize)] - struct Remote<'a> { + pub struct Remote<'a> { #[serde(with = "OrDef")] or: Or, #[serde(borrow, with = "StrDef")] @@ -398,7 +398,7 @@ fn test_gen() { } #[derive(Serialize, Deserialize)] - enum BorrowVariant<'a> { + pub enum BorrowVariant<'a> { #[serde(borrow, with = "StrDef")] S(Str<'a>), } @@ -415,15 +415,14 @@ fn test_gen() { // This would not work if SDef::serialize / deserialize are private. #[derive(Serialize, Deserialize)] - struct RemoteVisibility { + pub struct RemoteVisibility { #[serde(with = "vis::SDef")] s: vis::S, } #[derive(Serialize, Deserialize)] #[serde(remote = "Self")] - #[allow(dead_code)] - struct RemoteSelf; + pub struct RemoteSelf; #[derive(Serialize, Deserialize)] enum ExternallyTaggedVariantWith { @@ -548,25 +547,25 @@ fn test_gen() { #[derive(Serialize, Deserialize)] #[serde(deny_unknown_fields)] - struct FlattenDenyUnknown { + pub struct FlattenDenyUnknown { #[serde(flatten)] t: T, } #[derive(Serialize, Deserialize)] - struct StaticStrStruct<'a> { + pub struct StaticStrStruct<'a> { a: &'a str, b: &'static str, } #[derive(Serialize, Deserialize)] - struct StaticStrTupleStruct<'a>(&'a str, &'static str); + pub struct StaticStrTupleStruct<'a>(&'a str, &'static str); #[derive(Serialize, Deserialize)] - struct StaticStrNewtypeStruct(&'static str); + pub struct StaticStrNewtypeStruct(&'static str); #[derive(Serialize, Deserialize)] - enum StaticStrEnum<'a> { + pub enum StaticStrEnum<'a> { Struct { a: &'a str, b: &'static str }, Tuple(&'a str, &'static str), Newtype(&'static str), @@ -640,6 +639,7 @@ fn test_gen() { use serde_derive::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] + #[allow(dead_code)] struct Restricted { pub(super) a: usize, pub(in super::inner) b: usize, @@ -649,7 +649,7 @@ fn test_gen() { #[derive(Deserialize)] #[serde(tag = "t", content = "c")] - enum AdjacentlyTaggedVoid {} + pub enum AdjacentlyTaggedVoid {} #[derive(Serialize, Deserialize)] enum SkippedVariant { @@ -662,14 +662,13 @@ fn test_gen() { assert::>(); #[derive(Deserialize)] - struct ImplicitlyBorrowedOption<'a> { - #[allow(dead_code)] + pub struct ImplicitlyBorrowedOption<'a> { option: std::option::Option<&'a str>, } #[derive(Serialize, Deserialize)] #[serde(untagged)] - enum UntaggedNewtypeVariantWith { + pub enum UntaggedNewtypeVariantWith { Newtype( #[serde(serialize_with = "ser_x")] #[serde(deserialize_with = "de_x")] @@ -679,7 +678,7 @@ fn test_gen() { #[derive(Serialize, Deserialize)] #[serde(transparent)] - struct TransparentWith { + pub struct TransparentWith { #[serde(serialize_with = "ser_x")] #[serde(deserialize_with = "de_x")] x: X, @@ -701,35 +700,33 @@ fn test_gen() { } #[derive(Deserialize)] - struct RelObject<'a> { - #[allow(dead_code)] + pub struct RelObject<'a> { ty: &'a str, - #[allow(dead_code)] id: String, } #[derive(Serialize, Deserialize)] - struct FlattenSkipSerializing { + pub struct FlattenSkipSerializing { #[serde(flatten, skip_serializing)] #[allow(dead_code)] flat: T, } #[derive(Serialize, Deserialize)] - struct FlattenSkipSerializingIf { + pub struct FlattenSkipSerializingIf { #[serde(flatten, skip_serializing_if = "StdOption::is_none")] flat: StdOption, } #[derive(Serialize, Deserialize)] - struct FlattenSkipDeserializing { + pub struct FlattenSkipDeserializing { #[serde(flatten, skip_deserializing)] flat: T, } // https://github.com/serde-rs/serde/issues/1804 #[derive(Serialize, Deserialize)] - enum Message { + pub enum Message { #[serde(skip)] #[allow(dead_code)] String(String), @@ -748,8 +745,7 @@ fn test_gen() { macro_rules! deriving { ($field:ty) => { #[derive(Deserialize)] - struct MacroRules<'a> { - #[allow(dead_code)] + pub struct MacroRules<'a> { field: $field, } }; @@ -764,22 +760,20 @@ fn test_gen() { } #[derive(Deserialize)] - struct BorrowLifetimeInsideMacro<'a> { + pub struct BorrowLifetimeInsideMacro<'a> { #[serde(borrow = "'a")] - #[allow(dead_code)] - f: mac!(Cow<'a, str>), + pub f: mac!(Cow<'a, str>), } #[derive(Serialize)] - #[allow(dead_code)] - struct Struct { + pub struct Struct { #[serde(serialize_with = "vec_first_element")] - vec: Vec, + pub vec: Vec, } #[derive(Deserialize)] #[serde(bound(deserialize = "[&'de str; N]: Copy"))] - struct GenericUnitStruct; + pub struct GenericUnitStruct; } ////////////////////////////////////////////////////////////////////////// @@ -866,7 +860,7 @@ where #[derive(Debug, PartialEq, Deserialize)] #[serde(tag = "tag")] -enum InternallyTagged { +pub enum InternallyTagged { #[serde(deserialize_with = "deserialize_generic")] Unit, diff --git a/test_suite/tests/test_remote.rs b/test_suite/tests/test_remote.rs index c1f152eb8..d550af427 100644 --- a/test_suite/tests/test_remote.rs +++ b/test_suite/tests/test_remote.rs @@ -7,14 +7,17 @@ mod remote { pub struct PrimitivePriv(u8); + #[allow(dead_code)] pub struct PrimitivePub(pub u8); pub struct NewtypePriv(Unit); + #[allow(dead_code)] pub struct NewtypePub(pub Unit); pub struct TuplePriv(u8, Unit); + #[allow(dead_code)] pub struct TuplePub(pub u8, pub Unit); pub struct StructPriv { @@ -22,6 +25,7 @@ mod remote { b: Unit, } + #[allow(dead_code)] pub struct StructPub { pub a: u8, pub b: Unit, @@ -86,12 +90,14 @@ mod remote { } } + #[allow(dead_code)] pub enum EnumGeneric { Variant(T), } } #[derive(Serialize, Deserialize)] +#[allow(dead_code)] struct Test { #[serde(with = "UnitDef")] unit: remote::Unit, @@ -132,6 +138,7 @@ struct Test { #[derive(Serialize, Deserialize)] #[serde(remote = "remote::Unit")] +#[allow(dead_code)] struct UnitDef; #[derive(Serialize, Deserialize)] @@ -140,6 +147,7 @@ struct PrimitivePrivDef(#[serde(getter = "remote::PrimitivePriv::get")] u8); #[derive(Serialize, Deserialize)] #[serde(remote = "remote::PrimitivePub")] +#[allow(dead_code)] struct PrimitivePubDef(u8); #[derive(Serialize, Deserialize)] @@ -148,6 +156,7 @@ struct NewtypePrivDef(#[serde(getter = "remote::NewtypePriv::get", with = "UnitD #[derive(Serialize, Deserialize)] #[serde(remote = "remote::NewtypePub")] +#[allow(dead_code)] struct NewtypePubDef(#[serde(with = "UnitDef")] remote::Unit); #[derive(Serialize, Deserialize)] @@ -159,6 +168,7 @@ struct TuplePrivDef( #[derive(Serialize, Deserialize)] #[serde(remote = "remote::TuplePub")] +#[allow(dead_code)] struct TuplePubDef(u8, #[serde(with = "UnitDef")] remote::Unit); #[derive(Serialize, Deserialize)] @@ -174,6 +184,7 @@ struct StructPrivDef { #[derive(Serialize, Deserialize)] #[serde(remote = "remote::StructPub")] +#[allow(dead_code)] struct StructPubDef { a: u8, @@ -190,17 +201,20 @@ struct StructGenericWithGetterDef { #[derive(Serialize, Deserialize)] #[serde(remote = "remote::StructGeneric")] +#[allow(dead_code)] struct StructConcrete { value: u8, } #[derive(Serialize, Deserialize)] #[serde(remote = "remote::EnumGeneric")] +#[allow(dead_code)] enum EnumConcrete { Variant(u8), } #[derive(Debug)] +#[allow(dead_code)] enum ErrorKind { NotFound, PermissionDenied, @@ -211,6 +225,7 @@ enum ErrorKind { #[derive(Serialize, Deserialize)] #[serde(remote = "ErrorKind")] #[non_exhaustive] +#[allow(dead_code)] enum ErrorKindDef { NotFound, PermissionDenied, diff --git a/test_suite/tests/test_self.rs b/test_suite/tests/test_self.rs index 516bdeaec..2813c4854 100644 --- a/test_suite/tests/test_self.rs +++ b/test_suite/tests/test_self.rs @@ -41,7 +41,7 @@ fn test_self() { } #[derive(Deserialize, Serialize)] - struct Tuple( + pub struct Tuple( Box, Box<::Assoc>, [(); Self::ASSOC], @@ -60,7 +60,7 @@ fn test_self() { } #[derive(Deserialize, Serialize)] - enum Enum { + pub enum Enum { Struct { _f1: Box, _f2: Box<::Assoc>, From 21c7fd1bd5164e77071c817f85206475964070de Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 7 Aug 2023 14:42:54 +0500 Subject: [PATCH 103/258] Add tests of #[serde(default)] attribute for units and unions --- test_suite/tests/ui/default-attribute/union.rs | 9 +++++++++ test_suite/tests/ui/default-attribute/union.stderr | 14 ++++++++++++++ .../tests/ui/default-attribute/union_path.rs | 9 +++++++++ .../tests/ui/default-attribute/union_path.stderr | 14 ++++++++++++++ test_suite/tests/ui/default-attribute/unit.rs | 7 +++++++ test_suite/tests/ui/default-attribute/unit.stderr | 7 +++++++ test_suite/tests/ui/default-attribute/unit_path.rs | 7 +++++++ .../tests/ui/default-attribute/unit_path.stderr | 5 +++++ 8 files changed, 72 insertions(+) create mode 100644 test_suite/tests/ui/default-attribute/union.rs create mode 100644 test_suite/tests/ui/default-attribute/union.stderr create mode 100644 test_suite/tests/ui/default-attribute/union_path.rs create mode 100644 test_suite/tests/ui/default-attribute/union_path.stderr create mode 100644 test_suite/tests/ui/default-attribute/unit.rs create mode 100644 test_suite/tests/ui/default-attribute/unit.stderr create mode 100644 test_suite/tests/ui/default-attribute/unit_path.rs create mode 100644 test_suite/tests/ui/default-attribute/unit_path.stderr diff --git a/test_suite/tests/ui/default-attribute/union.rs b/test_suite/tests/ui/default-attribute/union.rs new file mode 100644 index 000000000..296512ff0 --- /dev/null +++ b/test_suite/tests/ui/default-attribute/union.rs @@ -0,0 +1,9 @@ +use serde_derive::Deserialize; + +#[derive(Deserialize)] +#[serde(default)] +union Union { + f: u8, +} + +fn main() {} diff --git a/test_suite/tests/ui/default-attribute/union.stderr b/test_suite/tests/ui/default-attribute/union.stderr new file mode 100644 index 000000000..d0268ce34 --- /dev/null +++ b/test_suite/tests/ui/default-attribute/union.stderr @@ -0,0 +1,14 @@ +error: #[serde(default)] can only be used on structs + --> tests/ui/default-attribute/union.rs:4:9 + | +4 | #[serde(default)] + | ^^^^^^^ + +error: Serde does not support derive for unions + --> tests/ui/default-attribute/union.rs:4:1 + | +4 | / #[serde(default)] +5 | | union Union { +6 | | f: u8, +7 | | } + | |_^ diff --git a/test_suite/tests/ui/default-attribute/union_path.rs b/test_suite/tests/ui/default-attribute/union_path.rs new file mode 100644 index 000000000..e57f4d1a0 --- /dev/null +++ b/test_suite/tests/ui/default-attribute/union_path.rs @@ -0,0 +1,9 @@ +use serde_derive::Deserialize; + +#[derive(Deserialize)] +#[serde(default = "default_u")] +union Union { + f: u8, +} + +fn main() {} diff --git a/test_suite/tests/ui/default-attribute/union_path.stderr b/test_suite/tests/ui/default-attribute/union_path.stderr new file mode 100644 index 000000000..08e89ee18 --- /dev/null +++ b/test_suite/tests/ui/default-attribute/union_path.stderr @@ -0,0 +1,14 @@ +error: #[serde(default = "...")] can only be used on structs + --> tests/ui/default-attribute/union_path.rs:4:9 + | +4 | #[serde(default = "default_u")] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: Serde does not support derive for unions + --> tests/ui/default-attribute/union_path.rs:4:1 + | +4 | / #[serde(default = "default_u")] +5 | | union Union { +6 | | f: u8, +7 | | } + | |_^ diff --git a/test_suite/tests/ui/default-attribute/unit.rs b/test_suite/tests/ui/default-attribute/unit.rs new file mode 100644 index 000000000..c0500545f --- /dev/null +++ b/test_suite/tests/ui/default-attribute/unit.rs @@ -0,0 +1,7 @@ +use serde_derive::Deserialize; + +#[derive(Deserialize)] +#[serde(default)] +struct Unit; + +fn main() {} diff --git a/test_suite/tests/ui/default-attribute/unit.stderr b/test_suite/tests/ui/default-attribute/unit.stderr new file mode 100644 index 000000000..c99c3bb17 --- /dev/null +++ b/test_suite/tests/ui/default-attribute/unit.stderr @@ -0,0 +1,7 @@ +error: #[serde(default)] can only be used on structs that have fields + --> tests/ui/default-attribute/unit.rs:3:10 + | +3 | #[derive(Deserialize)] + | ^^^^^^^^^^^ + | + = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/test_suite/tests/ui/default-attribute/unit_path.rs b/test_suite/tests/ui/default-attribute/unit_path.rs new file mode 100644 index 000000000..25705fad5 --- /dev/null +++ b/test_suite/tests/ui/default-attribute/unit_path.rs @@ -0,0 +1,7 @@ +use serde_derive::Deserialize; + +#[derive(Deserialize)] +#[serde(default = "default_u")] +struct Unit; + +fn main() {} diff --git a/test_suite/tests/ui/default-attribute/unit_path.stderr b/test_suite/tests/ui/default-attribute/unit_path.stderr new file mode 100644 index 000000000..430136120 --- /dev/null +++ b/test_suite/tests/ui/default-attribute/unit_path.stderr @@ -0,0 +1,5 @@ +error: #[serde(default = "...")] can only be used on structs that have fields + --> tests/ui/default-attribute/unit_path.rs:4:9 + | +4 | #[serde(default = "default_u")] + | ^^^^^^^^^^^^^^^^^^^^^ From bc5af506bd068aa0d9b201832fab7c64652b9b13 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 3 Aug 2024 14:49:38 +0500 Subject: [PATCH 104/258] Use serialize_entry instead of serialize_key + serialize_value when serialize flatten newtype enum variant Serializers that reimplements serialize_entry will get benefits from that --- serde/src/private/ser.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/serde/src/private/ser.rs b/serde/src/private/ser.rs index 40cc6cbdb..9570629e9 100644 --- a/serde/src/private/ser.rs +++ b/serde/src/private/ser.rs @@ -1125,8 +1125,7 @@ where where T: ?Sized + Serialize, { - tri!(self.0.serialize_key(variant)); - self.0.serialize_value(value) + self.0.serialize_entry(variant, value) } fn serialize_seq(self, _: Option) -> Result { From 291ec50d98dc4bb0b309d13b9cbdcd5a2baf4765 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 22 Jul 2023 22:33:09 +0500 Subject: [PATCH 105/258] Add tests that ensures that error reported for a path for `with` and `default` attributes --- .../incorrect_type_enum_adjacently_tagged.rs | 22 +++++ ...correct_type_enum_adjacently_tagged.stderr | 35 +++++++ .../incorrect_type_enum_externally_tagged.rs | 21 ++++ ...correct_type_enum_externally_tagged.stderr | 35 +++++++ .../incorrect_type_enum_internally_tagged.rs | 19 ++++ ...correct_type_enum_internally_tagged.stderr | 23 +++++ .../incorrect_type_enum_untagged.rs | 22 +++++ .../incorrect_type_enum_untagged.stderr | 35 +++++++ .../incorrect_type_newtype.rs | 8 ++ .../incorrect_type_newtype.stderr | 37 +++++++ .../incorrect_type_struct.rs | 14 +++ .../incorrect_type_struct.stderr | 58 +++++++++++ .../default-attribute/incorrect_type_tuple.rs | 11 +++ .../incorrect_type_tuple.stderr | 37 +++++++ test_suite/tests/ui/with/incorrect_type.rs | 23 +++++ .../tests/ui/with/incorrect_type.stderr | 97 +++++++++++++++++++ 16 files changed, 497 insertions(+) create mode 100644 test_suite/tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs create mode 100644 test_suite/tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.stderr create mode 100644 test_suite/tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs create mode 100644 test_suite/tests/ui/default-attribute/incorrect_type_enum_externally_tagged.stderr create mode 100644 test_suite/tests/ui/default-attribute/incorrect_type_enum_internally_tagged.rs create mode 100644 test_suite/tests/ui/default-attribute/incorrect_type_enum_internally_tagged.stderr create mode 100644 test_suite/tests/ui/default-attribute/incorrect_type_enum_untagged.rs create mode 100644 test_suite/tests/ui/default-attribute/incorrect_type_enum_untagged.stderr create mode 100644 test_suite/tests/ui/default-attribute/incorrect_type_newtype.rs create mode 100644 test_suite/tests/ui/default-attribute/incorrect_type_newtype.stderr create mode 100644 test_suite/tests/ui/default-attribute/incorrect_type_struct.rs create mode 100644 test_suite/tests/ui/default-attribute/incorrect_type_struct.stderr create mode 100644 test_suite/tests/ui/default-attribute/incorrect_type_tuple.rs create mode 100644 test_suite/tests/ui/default-attribute/incorrect_type_tuple.stderr create mode 100644 test_suite/tests/ui/with/incorrect_type.rs create mode 100644 test_suite/tests/ui/with/incorrect_type.stderr diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs b/test_suite/tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs new file mode 100644 index 000000000..63a88fed6 --- /dev/null +++ b/test_suite/tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs @@ -0,0 +1,22 @@ +//! Ensures that error message points to the path in attribute +use serde_derive::Deserialize; + +#[derive(Deserialize)] +#[serde(tag = "tag", content = "content")] +enum Enum { + // Newtype variants does not use the provided path, so it is forbidden here + // Newtype(#[serde(default = "main")] u8), + Tuple( + u8, + #[serde(default = "main")] i8, + ), + Struct { + #[serde(default = "main")] + f1: u8, + f2: u8, + #[serde(default = "main")] + f3: i8, + }, +} + +fn main() {} diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.stderr b/test_suite/tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.stderr new file mode 100644 index 000000000..eefe58500 --- /dev/null +++ b/test_suite/tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.stderr @@ -0,0 +1,35 @@ +error[E0308]: `match` arms have incompatible types + --> tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs:11:27 + | +4 | #[derive(Deserialize)] + | ----------- + | | + | this is found to be of type `i8` + | `match` arms have incompatible types +... +11 | #[serde(default = "main")] i8, + | ^^^^^^ expected `i8`, found `()` + +error[E0308]: `match` arms have incompatible types + --> tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs:14:27 + | +4 | #[derive(Deserialize)] + | ----------- + | | + | this is found to be of type `u8` + | `match` arms have incompatible types +... +14 | #[serde(default = "main")] + | ^^^^^^ expected `u8`, found `()` + +error[E0308]: `match` arms have incompatible types + --> tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs:17:27 + | +4 | #[derive(Deserialize)] + | ----------- + | | + | this is found to be of type `i8` + | `match` arms have incompatible types +... +17 | #[serde(default = "main")] + | ^^^^^^ expected `i8`, found `()` diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs b/test_suite/tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs new file mode 100644 index 000000000..ae6144d8b --- /dev/null +++ b/test_suite/tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs @@ -0,0 +1,21 @@ +//! Ensures that error message points to the path in attribute +use serde_derive::Deserialize; + +#[derive(Deserialize)] +enum Enum { + // Newtype variants does not use the provided path, so it is forbidden here + // Newtype(#[serde(default = "main")] u8), + Tuple( + u8, + #[serde(default = "main")] i8, + ), + Struct { + #[serde(default = "main")] + f1: u8, + f2: u8, + #[serde(default = "main")] + f3: i8, + }, +} + +fn main() {} diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_enum_externally_tagged.stderr b/test_suite/tests/ui/default-attribute/incorrect_type_enum_externally_tagged.stderr new file mode 100644 index 000000000..dd6f8b0d6 --- /dev/null +++ b/test_suite/tests/ui/default-attribute/incorrect_type_enum_externally_tagged.stderr @@ -0,0 +1,35 @@ +error[E0308]: `match` arms have incompatible types + --> tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs:10:27 + | +4 | #[derive(Deserialize)] + | ----------- + | | + | this is found to be of type `i8` + | `match` arms have incompatible types +... +10 | #[serde(default = "main")] i8, + | ^^^^^^ expected `i8`, found `()` + +error[E0308]: `match` arms have incompatible types + --> tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs:13:27 + | +4 | #[derive(Deserialize)] + | ----------- + | | + | this is found to be of type `u8` + | `match` arms have incompatible types +... +13 | #[serde(default = "main")] + | ^^^^^^ expected `u8`, found `()` + +error[E0308]: `match` arms have incompatible types + --> tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs:16:27 + | +4 | #[derive(Deserialize)] + | ----------- + | | + | this is found to be of type `i8` + | `match` arms have incompatible types +... +16 | #[serde(default = "main")] + | ^^^^^^ expected `i8`, found `()` diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_enum_internally_tagged.rs b/test_suite/tests/ui/default-attribute/incorrect_type_enum_internally_tagged.rs new file mode 100644 index 000000000..d50264155 --- /dev/null +++ b/test_suite/tests/ui/default-attribute/incorrect_type_enum_internally_tagged.rs @@ -0,0 +1,19 @@ +//! Ensures that error message points to the path in attribute +use serde_derive::Deserialize; + +#[derive(Deserialize)] +#[serde(tag = "tag")] +enum Enum { + // Newtype variants does not use the provided path, so it is forbidden here + // Newtype(#[serde(default = "main")] u8), + // Tuple variants does not supported in internally tagged enums + Struct { + #[serde(default = "main")] + f1: u8, + f2: u8, + #[serde(default = "main")] + f3: i8, + }, +} + +fn main() {} diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_enum_internally_tagged.stderr b/test_suite/tests/ui/default-attribute/incorrect_type_enum_internally_tagged.stderr new file mode 100644 index 000000000..752806b64 --- /dev/null +++ b/test_suite/tests/ui/default-attribute/incorrect_type_enum_internally_tagged.stderr @@ -0,0 +1,23 @@ +error[E0308]: `match` arms have incompatible types + --> tests/ui/default-attribute/incorrect_type_enum_internally_tagged.rs:11:27 + | +4 | #[derive(Deserialize)] + | ----------- + | | + | this is found to be of type `u8` + | `match` arms have incompatible types +... +11 | #[serde(default = "main")] + | ^^^^^^ expected `u8`, found `()` + +error[E0308]: `match` arms have incompatible types + --> tests/ui/default-attribute/incorrect_type_enum_internally_tagged.rs:14:27 + | +4 | #[derive(Deserialize)] + | ----------- + | | + | this is found to be of type `i8` + | `match` arms have incompatible types +... +14 | #[serde(default = "main")] + | ^^^^^^ expected `i8`, found `()` diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_enum_untagged.rs b/test_suite/tests/ui/default-attribute/incorrect_type_enum_untagged.rs new file mode 100644 index 000000000..8fa6c04e9 --- /dev/null +++ b/test_suite/tests/ui/default-attribute/incorrect_type_enum_untagged.rs @@ -0,0 +1,22 @@ +//! Ensures that error message points to the path in attribute +use serde_derive::Deserialize; + +#[derive(Deserialize)] +#[serde(untagged)] +enum Enum { + // Newtype variants does not use the provided path, so it is forbidden here + // Newtype(#[serde(default = "main")] u8), + Tuple( + u8, + #[serde(default = "main")] i8, + ), + Struct { + #[serde(default = "main")] + f1: u8, + f2: u8, + #[serde(default = "main")] + f3: i8, + }, +} + +fn main() {} diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_enum_untagged.stderr b/test_suite/tests/ui/default-attribute/incorrect_type_enum_untagged.stderr new file mode 100644 index 000000000..9ffa6bb4e --- /dev/null +++ b/test_suite/tests/ui/default-attribute/incorrect_type_enum_untagged.stderr @@ -0,0 +1,35 @@ +error[E0308]: `match` arms have incompatible types + --> tests/ui/default-attribute/incorrect_type_enum_untagged.rs:11:27 + | +4 | #[derive(Deserialize)] + | ----------- + | | + | this is found to be of type `i8` + | `match` arms have incompatible types +... +11 | #[serde(default = "main")] i8, + | ^^^^^^ expected `i8`, found `()` + +error[E0308]: `match` arms have incompatible types + --> tests/ui/default-attribute/incorrect_type_enum_untagged.rs:14:27 + | +4 | #[derive(Deserialize)] + | ----------- + | | + | this is found to be of type `u8` + | `match` arms have incompatible types +... +14 | #[serde(default = "main")] + | ^^^^^^ expected `u8`, found `()` + +error[E0308]: `match` arms have incompatible types + --> tests/ui/default-attribute/incorrect_type_enum_untagged.rs:17:27 + | +4 | #[derive(Deserialize)] + | ----------- + | | + | this is found to be of type `i8` + | `match` arms have incompatible types +... +17 | #[serde(default = "main")] + | ^^^^^^ expected `i8`, found `()` diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_newtype.rs b/test_suite/tests/ui/default-attribute/incorrect_type_newtype.rs new file mode 100644 index 000000000..7db2a3d4b --- /dev/null +++ b/test_suite/tests/ui/default-attribute/incorrect_type_newtype.rs @@ -0,0 +1,8 @@ +//! Ensures that error message points to the path in attribute +use serde_derive::Deserialize; + +#[derive(Deserialize)] +#[serde(default = "main")] +struct Newtype(#[serde(default = "main")] u8); + +fn main() {} diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_newtype.stderr b/test_suite/tests/ui/default-attribute/incorrect_type_newtype.stderr new file mode 100644 index 000000000..b8910514e --- /dev/null +++ b/test_suite/tests/ui/default-attribute/incorrect_type_newtype.stderr @@ -0,0 +1,37 @@ +error[E0308]: mismatched types + --> tests/ui/default-attribute/incorrect_type_newtype.rs:5:19 + | +5 | #[serde(default = "main")] + | ^^^^^^ + | | + | expected `Newtype`, found `()` + | expected due to this + +error[E0308]: `match` arms have incompatible types + --> tests/ui/default-attribute/incorrect_type_newtype.rs:6:34 + | +4 | #[derive(Deserialize)] + | ----------- + | | + | this is found to be of type `u8` + | `match` arms have incompatible types +5 | #[serde(default = "main")] +6 | struct Newtype(#[serde(default = "main")] u8); + | ^^^^^^ expected `u8`, found `()` + +error[E0308]: mismatched types + --> tests/ui/default-attribute/incorrect_type_newtype.rs:5:19 + | +5 | #[serde(default = "main")] + | ^^^^^^ expected `Newtype`, found `()` +6 | struct Newtype(#[serde(default = "main")] u8); + | ------- expected due to this + +error[E0308]: mismatched types + --> tests/ui/default-attribute/incorrect_type_newtype.rs:6:34 + | +4 | #[derive(Deserialize)] + | ----------- expected due to the type of this binding +5 | #[serde(default = "main")] +6 | struct Newtype(#[serde(default = "main")] u8); + | ^^^^^^ expected `u8`, found `()` diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_struct.rs b/test_suite/tests/ui/default-attribute/incorrect_type_struct.rs new file mode 100644 index 000000000..52d5af9aa --- /dev/null +++ b/test_suite/tests/ui/default-attribute/incorrect_type_struct.rs @@ -0,0 +1,14 @@ +//! Ensures that error message points to the path in attribute +use serde_derive::Deserialize; + +#[derive(Deserialize)] +#[serde(default = "main")] +struct Struct { + #[serde(default = "main")] + f1: u8, + f2: u8, + #[serde(default = "main")] + f3: i8, +} + +fn main() {} diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_struct.stderr b/test_suite/tests/ui/default-attribute/incorrect_type_struct.stderr new file mode 100644 index 000000000..5663c3200 --- /dev/null +++ b/test_suite/tests/ui/default-attribute/incorrect_type_struct.stderr @@ -0,0 +1,58 @@ +error[E0308]: mismatched types + --> tests/ui/default-attribute/incorrect_type_struct.rs:5:19 + | +5 | #[serde(default = "main")] + | ^^^^^^ + | | + | expected `Struct`, found `()` + | expected due to this + +error[E0308]: `match` arms have incompatible types + --> tests/ui/default-attribute/incorrect_type_struct.rs:7:23 + | +4 | #[derive(Deserialize)] + | ----------- + | | + | this is found to be of type `u8` + | `match` arms have incompatible types +... +7 | #[serde(default = "main")] + | ^^^^^^ expected `u8`, found `()` + +error[E0308]: `match` arms have incompatible types + --> tests/ui/default-attribute/incorrect_type_struct.rs:10:23 + | +4 | #[derive(Deserialize)] + | ----------- + | | + | this is found to be of type `i8` + | `match` arms have incompatible types +... +10 | #[serde(default = "main")] + | ^^^^^^ expected `i8`, found `()` + +error[E0308]: mismatched types + --> tests/ui/default-attribute/incorrect_type_struct.rs:5:19 + | +5 | #[serde(default = "main")] + | ^^^^^^ expected `Struct`, found `()` +6 | struct Struct { + | ------ expected due to this + +error[E0308]: mismatched types + --> tests/ui/default-attribute/incorrect_type_struct.rs:7:23 + | +4 | #[derive(Deserialize)] + | ----------- expected due to the type of this binding +... +7 | #[serde(default = "main")] + | ^^^^^^ expected `u8`, found `()` + +error[E0308]: mismatched types + --> tests/ui/default-attribute/incorrect_type_struct.rs:10:23 + | +4 | #[derive(Deserialize)] + | ----------- expected due to the type of this binding +... +10 | #[serde(default = "main")] + | ^^^^^^ expected `i8`, found `()` diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_tuple.rs b/test_suite/tests/ui/default-attribute/incorrect_type_tuple.rs new file mode 100644 index 000000000..b5f0c5c9e --- /dev/null +++ b/test_suite/tests/ui/default-attribute/incorrect_type_tuple.rs @@ -0,0 +1,11 @@ +//! Ensures that error message points to the path in attribute +use serde_derive::Deserialize; + +#[derive(Deserialize)] +#[serde(default = "main")] +struct Tuple( + u8, + #[serde(default = "main")] i8, +); + +fn main() {} diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_tuple.stderr b/test_suite/tests/ui/default-attribute/incorrect_type_tuple.stderr new file mode 100644 index 000000000..e473e6ff6 --- /dev/null +++ b/test_suite/tests/ui/default-attribute/incorrect_type_tuple.stderr @@ -0,0 +1,37 @@ +error[E0308]: mismatched types + --> tests/ui/default-attribute/incorrect_type_tuple.rs:5:19 + | +5 | #[serde(default = "main")] + | ^^^^^^ + | | + | expected `Tuple`, found `()` + | expected due to this + +error[E0308]: `match` arms have incompatible types + --> tests/ui/default-attribute/incorrect_type_tuple.rs:8:23 + | +4 | #[derive(Deserialize)] + | ----------- + | | + | this is found to be of type `i8` + | `match` arms have incompatible types +... +8 | #[serde(default = "main")] i8, + | ^^^^^^ expected `i8`, found `()` + +error[E0308]: mismatched types + --> tests/ui/default-attribute/incorrect_type_tuple.rs:5:19 + | +5 | #[serde(default = "main")] + | ^^^^^^ expected `Tuple`, found `()` +6 | struct Tuple( + | ----- expected due to this + +error[E0308]: mismatched types + --> tests/ui/default-attribute/incorrect_type_tuple.rs:8:23 + | +4 | #[derive(Deserialize)] + | ----------- expected due to the type of this binding +... +8 | #[serde(default = "main")] i8, + | ^^^^^^ expected `i8`, found `()` diff --git a/test_suite/tests/ui/with/incorrect_type.rs b/test_suite/tests/ui/with/incorrect_type.rs new file mode 100644 index 000000000..c1502bb45 --- /dev/null +++ b/test_suite/tests/ui/with/incorrect_type.rs @@ -0,0 +1,23 @@ +use serde_derive::{Deserialize, Serialize}; + +mod w { + use serde::{Deserializer, Serializer}; + + pub fn deserialize<'de, D: Deserializer<'de>>(_: D) -> Result<(), D::Error> { + unimplemented!() + } + pub fn serialize(_: S) -> Result { + unimplemented!() + } +} + +#[derive(Serialize, Deserialize)] +struct W(#[serde(with = "w")] u8, u8); + +#[derive(Serialize, Deserialize)] +struct S(#[serde(serialize_with = "w::serialize")] u8, u8); + +#[derive(Serialize, Deserialize)] +struct D(#[serde(deserialize_with = "w::deserialize")] u8, u8); + +fn main() {} diff --git a/test_suite/tests/ui/with/incorrect_type.stderr b/test_suite/tests/ui/with/incorrect_type.stderr new file mode 100644 index 000000000..9981948b5 --- /dev/null +++ b/test_suite/tests/ui/with/incorrect_type.stderr @@ -0,0 +1,97 @@ +error[E0277]: the trait bound `&u8: Serializer` is not satisfied + --> tests/ui/with/incorrect_type.rs:14:10 + | +14 | #[derive(Serialize, Deserialize)] + | ^^^^^^^^^ the trait `Serializer` is not implemented for `&u8` +15 | struct W(#[serde(with = "w")] u8, u8); + | --- required by a bound introduced by this call + | + = help: the following other types implement trait `Serializer`: + &'a mut Formatter<'b> + FlatMapSerializer<'a, M> + _::_serde::__private::ser::content::ContentSerializer +note: required by a bound in `w::serialize` + --> tests/ui/with/incorrect_type.rs:9:28 + | +9 | pub fn serialize(_: S) -> Result { + | ^^^^^^^^^^ required by this bound in `serialize` + +error[E0061]: this function takes 1 argument but 2 arguments were supplied + --> tests/ui/with/incorrect_type.rs:15:25 + | +15 | struct W(#[serde(with = "w")] u8, u8); + | ^^^ unexpected argument #2 of type `__S` + | +note: function defined here + --> tests/ui/with/incorrect_type.rs:9:12 + | +9 | pub fn serialize(_: S) -> Result { + | ^^^^^^^^^ ---- + +error[E0277]: the trait bound `&u8: Serializer` is not satisfied + --> tests/ui/with/incorrect_type.rs:15:25 + | +15 | struct W(#[serde(with = "w")] u8, u8); + | ^^^ the trait `Serializer` is not implemented for `&u8` + | + = help: the following other types implement trait `Serializer`: + &'a mut Formatter<'b> + FlatMapSerializer<'a, M> + _::_serde::__private::ser::content::ContentSerializer + +error[E0308]: `?` operator has incompatible types + --> tests/ui/with/incorrect_type.rs:15:25 + | +15 | struct W(#[serde(with = "w")] u8, u8); + | ^^^ expected `u8`, found `()` + | + = note: `?` operator cannot convert from `()` to `u8` + +error[E0277]: the trait bound `&u8: Serializer` is not satisfied + --> tests/ui/with/incorrect_type.rs:17:10 + | +17 | #[derive(Serialize, Deserialize)] + | ^^^^^^^^^ the trait `Serializer` is not implemented for `&u8` +18 | struct S(#[serde(serialize_with = "w::serialize")] u8, u8); + | -------------- required by a bound introduced by this call + | + = help: the following other types implement trait `Serializer`: + &'a mut Formatter<'b> + FlatMapSerializer<'a, M> + _::_serde::__private::ser::content::ContentSerializer +note: required by a bound in `w::serialize` + --> tests/ui/with/incorrect_type.rs:9:28 + | +9 | pub fn serialize(_: S) -> Result { + | ^^^^^^^^^^ required by this bound in `serialize` + +error[E0061]: this function takes 1 argument but 2 arguments were supplied + --> tests/ui/with/incorrect_type.rs:18:35 + | +18 | struct S(#[serde(serialize_with = "w::serialize")] u8, u8); + | ^^^^^^^^^^^^^^ unexpected argument #2 of type `__S` + | +note: function defined here + --> tests/ui/with/incorrect_type.rs:9:12 + | +9 | pub fn serialize(_: S) -> Result { + | ^^^^^^^^^ ---- + +error[E0277]: the trait bound `&u8: Serializer` is not satisfied + --> tests/ui/with/incorrect_type.rs:18:35 + | +18 | struct S(#[serde(serialize_with = "w::serialize")] u8, u8); + | ^^^^^^^^^^^^^^ the trait `Serializer` is not implemented for `&u8` + | + = help: the following other types implement trait `Serializer`: + &'a mut Formatter<'b> + FlatMapSerializer<'a, M> + _::_serde::__private::ser::content::ContentSerializer + +error[E0308]: `?` operator has incompatible types + --> tests/ui/with/incorrect_type.rs:21:37 + | +21 | struct D(#[serde(deserialize_with = "w::deserialize")] u8, u8); + | ^^^^^^^^^^^^^^^^ expected `u8`, found `()` + | + = note: `?` operator cannot convert from `()` to `u8` From 74b538b8eca6d1be9e2b318f7c17e25981f917ed Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 22 Jul 2023 19:44:59 +0500 Subject: [PATCH 106/258] Produce error about mismatched types of #[serde(with = "...")] and #[serde(default = "...")] attributes on the attribute itself --- serde_derive/src/de.rs | 55 +++++++++++++++++++++++++----- serde_derive/src/internals/attr.rs | 9 ++--- serde_derive/src/ser.rs | 8 ++++- 3 files changed, 59 insertions(+), 13 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index e3b737c61..30f553749 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -371,7 +371,11 @@ fn deserialize_transparent(cont: &Container, params: &Parameters) -> Fragment { } else { let value = match field.attrs.default() { attr::Default::Default => quote!(_serde::__private::Default::default()), - attr::Default::Path(path) => quote!(#path()), + // If #path returns wrong type, error will be reported here (^^^^^). + // We attach span of the path to the function so it will be reported + // on the #[serde(default = "...")] + // ^^^^^ + attr::Default::Path(path) => quote_spanned!(path.span()=> #path()), attr::Default::None => quote!(_serde::__private::PhantomData), }; quote!(#member: #value) @@ -751,7 +755,11 @@ fn deserialize_seq( attr::Default::Default => Some(quote!( let __default: Self::Value = _serde::__private::Default::default(); )), - attr::Default::Path(path) => Some(quote!( + // If #path returns wrong type, error will be reported here (^^^^^). + // We attach span of the path to the function so it will be reported + // on the #[serde(default = "...")] + // ^^^^^ + attr::Default::Path(path) => Some(quote_spanned!(path.span()=> let __default: Self::Value = #path(); )), attr::Default::None => { @@ -833,7 +841,11 @@ fn deserialize_seq_in_place( attr::Default::Default => Some(quote!( let __default: #this_type #ty_generics = _serde::__private::Default::default(); )), - attr::Default::Path(path) => Some(quote!( + // If #path returns wrong type, error will be reported here (^^^^^). + // We attach span of the path to the function so it will be reported + // on the #[serde(default = "...")] + // ^^^^^ + attr::Default::Path(path) => Some(quote_spanned!(path.span()=> let __default: #this_type #ty_generics = #path(); )), attr::Default::None => { @@ -867,7 +879,11 @@ fn deserialize_newtype_struct( } } Some(path) => { - quote! { + // If #path returns wrong type, error will be reported here (^^^^^). + // We attach span of the path to the function so it will be reported + // on the #[serde(with = "...")] + // ^^^^^ + quote_spanned! {path.span()=> #path(__e)? } } @@ -2634,7 +2650,11 @@ fn deserialize_map( attr::Default::Default => Some(quote!( let __default: Self::Value = _serde::__private::Default::default(); )), - attr::Default::Path(path) => Some(quote!( + // If #path returns wrong type, error will be reported here (^^^^^). + // We attach span of the path to the function so it will be reported + // on the #[serde(default = "...")] + // ^^^^^ + attr::Default::Path(path) => Some(quote_spanned!(path.span()=> let __default: Self::Value = #path(); )), attr::Default::None => { @@ -2801,7 +2821,11 @@ fn deserialize_map_in_place( attr::Default::Default => Some(quote!( let __default: #this_type #ty_generics = _serde::__private::Default::default(); )), - attr::Default::Path(path) => Some(quote!( + // If #path returns wrong type, error will be reported here (^^^^^). + // We attach span of the path to the function so it will be reported + // on the #[serde(default = "...")] + // ^^^^^ + attr::Default::Path(path) => Some(quote_spanned!(path.span()=> let __default: #this_type #ty_generics = #path(); )), attr::Default::None => { @@ -2840,6 +2864,13 @@ fn wrap_deserialize_with( split_with_de_lifetime(params); let delife = params.borrowed.de_lifetime(); + // If #deserialize_with returns wrong type, error will be reported here (^^^^^). + // We attach span of the path to the function so it will be reported + // on the #[serde(with = "...")] + // ^^^^^ + let value = quote_spanned! {deserialize_with.span()=> + #deserialize_with(__deserializer)? + }; let wrapper = quote! { #[doc(hidden)] struct __DeserializeWith #de_impl_generics #where_clause { @@ -2854,7 +2885,7 @@ fn wrap_deserialize_with( __D: _serde::Deserializer<#delife>, { _serde::__private::Ok(__DeserializeWith { - value: #deserialize_with(__deserializer)?, + value: #value, phantom: _serde::__private::PhantomData, lifetime: _serde::__private::PhantomData, }) @@ -2945,7 +2976,11 @@ fn expr_is_missing(field: &Field, cattrs: &attr::Container) -> Fragment { return quote_expr!(#func()); } attr::Default::Path(path) => { - return quote_expr!(#path()); + // If #path returns wrong type, error will be reported here (^^^^^). + // We attach span of the path to the function so it will be reported + // on the #[serde(default = "...")] + // ^^^^^ + return Fragment::Expr(quote_spanned!(path.span()=> #path())); } attr::Default::None => { /* below */ } } @@ -2988,6 +3023,10 @@ fn expr_is_missing_seq( return quote_spanned!(span=> #assign_to _serde::__private::Default::default()); } attr::Default::Path(path) => { + // If #path returns wrong type, error will be reported here (^^^^^). + // We attach span of the path to the function so it will be reported + // on the #[serde(default = "...")] + // ^^^^^ return quote_spanned!(path.span()=> #assign_to #path()); } attr::Default::None => { /* below */ } diff --git a/serde_derive/src/internals/attr.rs b/serde_derive/src/internals/attr.rs index 0cfb23bf1..07c9fe9a3 100644 --- a/serde_derive/src/internals/attr.rs +++ b/serde_derive/src/internals/attr.rs @@ -8,6 +8,7 @@ use std::iter::FromIterator; use syn::meta::ParseNestedMeta; use syn::parse::ParseStream; use syn::punctuated::Punctuated; +use syn::spanned::Spanned; use syn::{parse_quote, token, Ident, Lifetime, Token}; // This module handles parsing of `#[serde(...)]` attributes. The entrypoints @@ -898,13 +899,13 @@ impl Variant { ser_path .path .segments - .push(Ident::new("serialize", Span::call_site()).into()); + .push(Ident::new("serialize", ser_path.span()).into()); serialize_with.set(&meta.path, ser_path); let mut de_path = path; de_path .path .segments - .push(Ident::new("deserialize", Span::call_site()).into()); + .push(Ident::new("deserialize", de_path.span()).into()); deserialize_with.set(&meta.path, de_path); } } else if meta.path == SERIALIZE_WITH { @@ -1180,13 +1181,13 @@ impl Field { ser_path .path .segments - .push(Ident::new("serialize", Span::call_site()).into()); + .push(Ident::new("serialize", ser_path.span()).into()); serialize_with.set(&meta.path, ser_path); let mut de_path = path; de_path .path .segments - .push(Ident::new("deserialize", Span::call_site()).into()); + .push(Ident::new("deserialize", de_path.span()).into()); deserialize_with.set(&meta.path, de_path); } } else if meta.path == BOUND { diff --git a/serde_derive/src/ser.rs b/serde_derive/src/ser.rs index 7d89d2212..7d10c287e 100644 --- a/serde_derive/src/ser.rs +++ b/serde_derive/src/ser.rs @@ -1229,9 +1229,15 @@ fn wrap_serialize_with( }) }); - quote!({ + // If #serialize_with returns wrong type, error will be reported on here. + // We attach span of the path to this piece so error will be reported + // on the #[serde(with = "...")] + // ^^^^^ + quote_spanned!(serialize_with.span()=> { #[doc(hidden)] struct __SerializeWith #wrapper_impl_generics #where_clause { + // If #field_tys is empty, `values` does not used + #[allow(dead_code)] values: (#(&'__a #field_tys, )*), phantom: _serde::__private::PhantomData<#this_type #ty_generics>, } From 8764353fe2f52000e40db29dd42e312dfcae918e Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 7 Aug 2024 18:16:48 -0700 Subject: [PATCH 107/258] Enable collection_is_never_read nursury lint in test error: collection is never read --> test_suite/tests/test_gen.rs:722:25 | 722 | #[derive(Serialize, Deserialize)] | ^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collection_is_never_read note: the lint level is defined here --> test_suite/tests/test_gen.rs:22:9 | 22 | #![deny(clippy::collection_is_never_read)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info) --- test_suite/tests/test_gen.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/test_suite/tests/test_gen.rs b/test_suite/tests/test_gen.rs index f8d577bb8..0459691bb 100644 --- a/test_suite/tests/test_gen.rs +++ b/test_suite/tests/test_gen.rs @@ -19,6 +19,7 @@ clippy::trivially_copy_pass_by_ref, clippy::type_repetition_in_bounds )] +#![deny(clippy::collection_is_never_read)] use serde::de::{Deserialize, DeserializeOwned, Deserializer}; use serde::ser::{Serialize, Serializer}; From c3df3372a18a7c0964b55bd495e52d666680a9c4 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 7 Aug 2024 18:17:50 -0700 Subject: [PATCH 108/258] Add test of flatten in enum error: collection is never read --> test_suite/tests/test_gen.rs:728:25 | 728 | #[derive(Serialize, Deserialize)] | ^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collection_is_never_read = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info) --- test_suite/tests/test_gen.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test_suite/tests/test_gen.rs b/test_suite/tests/test_gen.rs index 0459691bb..0119584c3 100644 --- a/test_suite/tests/test_gen.rs +++ b/test_suite/tests/test_gen.rs @@ -725,6 +725,19 @@ fn test_gen() { flat: T, } + #[derive(Serialize, Deserialize)] + #[serde(untagged)] + pub enum Inner { + Builder { + s: T, + #[serde(flatten)] + o: T, + }, + Default { + s: T, + }, + } + // https://github.com/serde-rs/serde/issues/1804 #[derive(Serialize, Deserialize)] pub enum Message { From d64a97ba1e099fc8033c9eea6fec14e1a71c0303 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 7 Aug 2024 18:19:46 -0700 Subject: [PATCH 109/258] Ignore confusable_idents warning in test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit error: found both `σ` and `o` as identifiers, which look alike --> test_suite/tests/test_gen.rs:734:13 | 292 | σ: f64, | - other identifier used here ... 734 | o: T, | ^ this identifier can be confused with `σ` | note: the lint level is defined here --> test_suite/tests/test_gen.rs:5:9 | 5 | #![deny(warnings)] | ^^^^^^^^ = note: `#[deny(confusable_idents)]` implied by `#[deny(warnings)]` --- test_suite/tests/test_gen.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/test_suite/tests/test_gen.rs b/test_suite/tests/test_gen.rs index 0119584c3..3dacf00ab 100644 --- a/test_suite/tests/test_gen.rs +++ b/test_suite/tests/test_gen.rs @@ -4,6 +4,7 @@ #![deny(warnings)] #![allow( + confusable_idents, unknown_lints, mixed_script_confusables, clippy::derive_partial_eq_without_eq, From 32958dec3bf3886961166ec651194d6f0243a497 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 7 Aug 2024 18:43:47 -0700 Subject: [PATCH 110/258] Skip collecting unmatched fields in variants that do not use flatten --- serde_derive/src/de.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index e3b737c61..c5861d9bc 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -2480,7 +2480,10 @@ fn deserialize_map( }); // Collect contents for flatten fields into a buffer - let let_collect = if cattrs.has_flatten() { + let has_flatten = fields + .iter() + .any(|field| field.attrs.flatten() && !field.attrs.skip_deserializing()); + let let_collect = if has_flatten { Some(quote! { let mut __collect = _serde::__private::Vec::<_serde::__private::Option<( _serde::__private::de::Content, @@ -2532,7 +2535,7 @@ fn deserialize_map( }); // Visit ignored values to consume them - let ignored_arm = if cattrs.has_flatten() { + let ignored_arm = if has_flatten { Some(quote! { __Field::__other(__name) => { __collect.push(_serde::__private::Some(( @@ -2602,7 +2605,7 @@ fn deserialize_map( } }); - let collected_deny_unknown_fields = if cattrs.has_flatten() && cattrs.deny_unknown_fields() { + let collected_deny_unknown_fields = if has_flatten && cattrs.deny_unknown_fields() { Some(quote! { if let _serde::__private::Some(_serde::__private::Some((__key, _))) = __collect.into_iter().filter(_serde::__private::Option::is_some).next() From 9b868ef831c95f50dd4bde51a7eb52e3b9ee265a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 7 Aug 2024 18:53:21 -0700 Subject: [PATCH 111/258] Release 1.0.205 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index b51397218..458971705 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.204" +version = "1.0.205" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.204", path = "../serde_derive" } +serde_derive = { version = "=1.0.205", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 6a0569460..f7ae62822 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.204")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.205")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 91509f599..ab66b05be 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.204" +version = "1.0.205" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index 6ad174dc6..6560fe1ad 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.204")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.205")] #![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] // Ignored clippy lints #![allow( From 24614e44bff5466057e46c55394bac3ae20142c4 Mon Sep 17 00:00:00 2001 From: Mingun Date: Fri, 11 Aug 2023 02:50:46 +0500 Subject: [PATCH 112/258] Add regression test for issue #2565 failures (1): regression::issue2565::simple_variant --- test_suite/tests/regression/issue2565.rs | 41 ++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 test_suite/tests/regression/issue2565.rs diff --git a/test_suite/tests/regression/issue2565.rs b/test_suite/tests/regression/issue2565.rs new file mode 100644 index 000000000..65cbb0a31 --- /dev/null +++ b/test_suite/tests/regression/issue2565.rs @@ -0,0 +1,41 @@ +use serde_derive::{Serialize, Deserialize}; +use serde_test::{assert_tokens, Token}; + +#[derive(Serialize, Deserialize, Debug, PartialEq)] +enum Enum { + Simple { + a: i32, + }, + Flatten { + #[serde(flatten)] + flatten: (), + a: i32, + }, +} + +#[test] +fn simple_variant() { + assert_tokens( + &Enum::Simple { a: 42 }, + &[ + Token::StructVariant { name: "Enum", variant: "Simple", len: 1 }, + Token::Str("a"), + Token::I32(42), + Token::StructVariantEnd, + ] + ); +} + +#[test] +fn flatten_variant() { + assert_tokens( + &Enum::Flatten { flatten: (), a: 42 }, + &[ + Token::NewtypeVariant { name: "Enum", variant: "Flatten" }, + Token::Map { len: None }, + Token::Str("a"), + Token::I32(42), + Token::MapEnd, + ] + ); +} From c3ac7b675a38a73170879992976acb0009834ac0 Mon Sep 17 00:00:00 2001 From: Mingun Date: Wed, 5 Oct 2022 22:35:28 +0500 Subject: [PATCH 113/258] Add regression test for issue #1904 Currently panics in derive: error: proc-macro derive panicked --> test_suite\tests\test_annotations.rs:2386:25 | 2386 | #[derive(Serialize, Deserialize, PartialEq, Debug)] | ^^^^^^^^^^^ | = help: message: assertion failed: !cattrs.has_flatten() error: proc-macro derive panicked --> test_suite\tests\regression\issue1904.rs:57:10 | 57 | #[derive(Deserialize)] | ^^^^^^^^^^^ | = help: message: assertion failed: !cattrs.has_flatten() error: proc-macro derive panicked --> test_suite\tests\regression\issue1904.rs:47:10 | 47 | #[derive(Deserialize)] | ^^^^^^^^^^^ | = help: message: assertion failed: !cattrs.has_flatten() error: proc-macro derive panicked --> test_suite\tests\regression\issue1904.rs:37:10 | 37 | #[derive(Deserialize)] | ^^^^^^^^^^^ | = help: message: assertion failed: !cattrs.has_flatten() error: proc-macro derive panicked --> test_suite\tests\regression\issue1904.rs:27:10 | 27 | #[derive(Deserialize)] | ^^^^^^^^^^^ | = help: message: assertion failed: !cattrs.has_flatten() error: proc-macro derive panicked --> test_suite\tests\regression\issue1904.rs:16:10 | 16 | #[derive(Deserialize)] | ^^^^^^^^^^^ | = help: message: assertion failed: !cattrs.has_flatten() error: proc-macro derive panicked --> test_suite\tests\regression\issue1904.rs:7:10 | 7 | #[derive(Deserialize)] | ^^^^^^^^^^^ | = help: message: assertion failed: !cattrs.has_flatten() --- test_suite/tests/regression/issue1904.rs | 65 ++++++++++++++++++++++++ test_suite/tests/test_annotations.rs | 50 ++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 test_suite/tests/regression/issue1904.rs diff --git a/test_suite/tests/regression/issue1904.rs b/test_suite/tests/regression/issue1904.rs new file mode 100644 index 000000000..99736c078 --- /dev/null +++ b/test_suite/tests/regression/issue1904.rs @@ -0,0 +1,65 @@ +#![allow(dead_code)] // we do not read enum fields +use serde_derive::Deserialize; + +#[derive(Deserialize)] +pub struct Nested; + +#[derive(Deserialize)] +pub enum ExternallyTagged1 { + Tuple(f64, String), + Flatten { + #[serde(flatten)] + nested: Nested, + }, +} + +#[derive(Deserialize)] +pub enum ExternallyTagged2 { + Flatten { + #[serde(flatten)] + nested: Nested, + }, + Tuple(f64, String), +} + +// Internally tagged enums cannot contain tuple variants so not tested here + +#[derive(Deserialize)] +#[serde(tag = "tag", content = "content")] +pub enum AdjacentlyTagged1 { + Tuple(f64, String), + Flatten { + #[serde(flatten)] + nested: Nested, + }, +} + +#[derive(Deserialize)] +#[serde(tag = "tag", content = "content")] +pub enum AdjacentlyTagged2 { + Flatten { + #[serde(flatten)] + nested: Nested, + }, + Tuple(f64, String), +} + +#[derive(Deserialize)] +#[serde(untagged)] +pub enum Untagged1 { + Tuple(f64, String), + Flatten { + #[serde(flatten)] + nested: Nested, + }, +} + +#[derive(Deserialize)] +#[serde(untagged)] +pub enum Untagged2 { + Flatten { + #[serde(flatten)] + nested: Nested, + }, + Tuple(f64, String), +} diff --git a/test_suite/tests/test_annotations.rs b/test_suite/tests/test_annotations.rs index 566f7d43f..1488c8364 100644 --- a/test_suite/tests/test_annotations.rs +++ b/test_suite/tests/test_annotations.rs @@ -2380,6 +2380,56 @@ fn test_partially_untagged_enum_desugared() { ); } +/// Regression test for https://github.com/serde-rs/serde/issues/1904 +#[test] +fn test_enum_tuple_and_struct_with_flatten() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + enum Outer { + Tuple(f64, i32), + Flatten { + #[serde(flatten)] + nested: Nested, + }, + } + + #[derive(Serialize, Deserialize, PartialEq, Debug)] + struct Nested { + a: i32, + b: i32, + } + + assert_tokens( + &Outer::Tuple(1.2, 3), + &[ + Token::TupleVariant { + name: "Outer", + variant: "Tuple", + len: 2, + }, + Token::F64(1.2), + Token::I32(3), + Token::TupleVariantEnd, + ], + ); + assert_tokens( + &Outer::Flatten { + nested: Nested { a: 1, b: 2 }, + }, + &[ + Token::NewtypeVariant { + name: "Outer", + variant: "Flatten", + }, + Token::Map { len: None }, + Token::Str("a"), + Token::I32(1), + Token::Str("b"), + Token::I32(2), + Token::MapEnd, + ], + ); +} + #[test] fn test_partially_untagged_internally_tagged_enum() { #[derive(Serialize, Deserialize, PartialEq, Debug)] From b4ec2595c9dd8e380227043eba42ff85beb780c2 Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 24 Jul 2023 00:57:47 +0500 Subject: [PATCH 114/258] Correctly process flatten fields in enum variants - Fix incorrect deserialization of variants that doesn't contain flatten field when other contains - Fix a panic when deriving `Deserialize` for an enum with tuple and struct with flatten field Fixes (2): regression::issue2565::simple_variant regression::issue1904 (compilation) --- serde_derive/src/de.rs | 90 ++++++++++++++++++++---------- serde_derive/src/internals/ast.rs | 1 + serde_derive/src/internals/attr.rs | 37 ++++++++++++ 3 files changed, 97 insertions(+), 31 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index c5861d9bc..ef85385f6 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -281,11 +281,21 @@ fn deserialize_body(cont: &Container, params: &Parameters) -> Fragment { } else if let attr::Identifier::No = cont.attrs.identifier() { match &cont.data { Data::Enum(variants) => deserialize_enum(params, variants, &cont.attrs), - Data::Struct(Style::Struct, fields) => { - deserialize_struct(params, fields, &cont.attrs, StructForm::Struct) - } + Data::Struct(Style::Struct, fields) => deserialize_struct( + params, + fields, + &cont.attrs, + cont.attrs.has_flatten(), + StructForm::Struct, + ), Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => { - deserialize_tuple(params, fields, &cont.attrs, TupleForm::Tuple) + deserialize_tuple( + params, + fields, + &cont.attrs, + cont.attrs.has_flatten(), + TupleForm::Tuple, + ) } Data::Struct(Style::Unit, _) => deserialize_unit_struct(params, &cont.attrs), } @@ -459,9 +469,13 @@ fn deserialize_tuple( params: &Parameters, fields: &[Field], cattrs: &attr::Container, + has_flatten: bool, form: TupleForm, ) -> Fragment { - assert!(!cattrs.has_flatten()); + assert!( + !has_flatten, + "tuples and tuple variants cannot have flatten fields" + ); let field_count = fields .iter() @@ -579,7 +593,10 @@ fn deserialize_tuple_in_place( fields: &[Field], cattrs: &attr::Container, ) -> Fragment { - assert!(!cattrs.has_flatten()); + assert!( + !cattrs.has_flatten(), + "tuples and tuple variants cannot have flatten fields" + ); let field_count = fields .iter() @@ -910,6 +927,7 @@ fn deserialize_struct( params: &Parameters, fields: &[Field], cattrs: &attr::Container, + has_flatten: bool, form: StructForm, ) -> Fragment { let this_type = ¶ms.this_type; @@ -958,13 +976,13 @@ fn deserialize_struct( ) }) .collect(); - let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs); + let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs, has_flatten); // untagged struct variants do not get a visit_seq method. The same applies to // structs that only have a map representation. let visit_seq = match form { StructForm::Untagged(..) => None, - _ if cattrs.has_flatten() => None, + _ if has_flatten => None, _ => { let mut_seq = if field_names_idents.is_empty() { quote!(_) @@ -987,10 +1005,16 @@ fn deserialize_struct( }) } }; - let visit_map = Stmts(deserialize_map(&type_path, params, fields, cattrs)); + let visit_map = Stmts(deserialize_map( + &type_path, + params, + fields, + cattrs, + has_flatten, + )); let visitor_seed = match form { - StructForm::ExternallyTagged(..) if cattrs.has_flatten() => Some(quote! { + StructForm::ExternallyTagged(..) if has_flatten => Some(quote! { impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Visitor #de_ty_generics #where_clause { type Value = #this_type #ty_generics; @@ -1005,7 +1029,7 @@ fn deserialize_struct( _ => None, }; - let fields_stmt = if cattrs.has_flatten() { + let fields_stmt = if has_flatten { None } else { let field_names = field_names_idents @@ -1025,7 +1049,7 @@ fn deserialize_struct( } }; let dispatch = match form { - StructForm::Struct if cattrs.has_flatten() => quote! { + StructForm::Struct if has_flatten => quote! { _serde::Deserializer::deserialize_map(__deserializer, #visitor_expr) }, StructForm::Struct => { @@ -1034,7 +1058,7 @@ fn deserialize_struct( _serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, #visitor_expr) } } - StructForm::ExternallyTagged(_) if cattrs.has_flatten() => quote! { + StructForm::ExternallyTagged(_) if has_flatten => quote! { _serde::de::VariantAccess::newtype_variant_seed(__variant, #visitor_expr) }, StructForm::ExternallyTagged(_) => quote! { @@ -1116,7 +1140,7 @@ fn deserialize_struct_in_place( }) .collect(); - let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs); + let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs, false); let mut_seq = if field_names_idents.is_empty() { quote!(_) @@ -1210,10 +1234,7 @@ fn deserialize_homogeneous_enum( } } -fn prepare_enum_variant_enum( - variants: &[Variant], - cattrs: &attr::Container, -) -> (TokenStream, Stmts) { +fn prepare_enum_variant_enum(variants: &[Variant]) -> (TokenStream, Stmts) { let mut deserialized_variants = variants .iter() .enumerate() @@ -1247,7 +1268,7 @@ fn prepare_enum_variant_enum( let variant_visitor = Stmts(deserialize_generated_identifier( &variant_names_idents, - cattrs, + false, // variant identifiers does not depend on the presence of flatten fields true, None, fallthrough, @@ -1270,7 +1291,7 @@ fn deserialize_externally_tagged_enum( let expecting = format!("enum {}", params.type_name()); let expecting = cattrs.expecting().unwrap_or(&expecting); - let (variants_stmt, variant_visitor) = prepare_enum_variant_enum(variants, cattrs); + let (variants_stmt, variant_visitor) = prepare_enum_variant_enum(variants); // Match arms to extract a variant from a string let variant_arms = variants @@ -1355,7 +1376,7 @@ fn deserialize_internally_tagged_enum( cattrs: &attr::Container, tag: &str, ) -> Fragment { - let (variants_stmt, variant_visitor) = prepare_enum_variant_enum(variants, cattrs); + let (variants_stmt, variant_visitor) = prepare_enum_variant_enum(variants); // Match arms to extract a variant from a string let variant_arms = variants @@ -1409,7 +1430,7 @@ fn deserialize_adjacently_tagged_enum( split_with_de_lifetime(params); let delife = params.borrowed.de_lifetime(); - let (variants_stmt, variant_visitor) = prepare_enum_variant_enum(variants, cattrs); + let (variants_stmt, variant_visitor) = prepare_enum_variant_enum(variants); let variant_arms: &Vec<_> = &variants .iter() @@ -1810,12 +1831,14 @@ fn deserialize_externally_tagged_variant( params, &variant.fields, cattrs, + variant.attrs.has_flatten(), TupleForm::ExternallyTagged(variant_ident), ), Style::Struct => deserialize_struct( params, &variant.fields, cattrs, + variant.attrs.has_flatten(), StructForm::ExternallyTagged(variant_ident), ), } @@ -1859,6 +1882,7 @@ fn deserialize_internally_tagged_variant( params, &variant.fields, cattrs, + variant.attrs.has_flatten(), StructForm::InternallyTagged(variant_ident, deserializer), ), Style::Tuple => unreachable!("checked in serde_derive_internals"), @@ -1909,12 +1933,14 @@ fn deserialize_untagged_variant( params, &variant.fields, cattrs, + variant.attrs.has_flatten(), TupleForm::Untagged(variant_ident, deserializer), ), Style::Struct => deserialize_struct( params, &variant.fields, cattrs, + variant.attrs.has_flatten(), StructForm::Untagged(variant_ident, deserializer), ), } @@ -1985,7 +2011,7 @@ fn deserialize_untagged_newtype_variant( fn deserialize_generated_identifier( fields: &[(&str, Ident, &BTreeSet)], - cattrs: &attr::Container, + has_flatten: bool, is_variant: bool, ignore_variant: Option, fallthrough: Option, @@ -1999,11 +2025,11 @@ fn deserialize_generated_identifier( is_variant, fallthrough, None, - !is_variant && cattrs.has_flatten(), + !is_variant && has_flatten, None, )); - let lifetime = if !is_variant && cattrs.has_flatten() { + let lifetime = if !is_variant && has_flatten { Some(quote!(<'de>)) } else { None @@ -2043,8 +2069,9 @@ fn deserialize_generated_identifier( fn deserialize_field_identifier( fields: &[(&str, Ident, &BTreeSet)], cattrs: &attr::Container, + has_flatten: bool, ) -> Stmts { - let (ignore_variant, fallthrough) = if cattrs.has_flatten() { + let (ignore_variant, fallthrough) = if has_flatten { let ignore_variant = quote!(__other(_serde::__private::de::Content<'de>),); let fallthrough = quote!(_serde::__private::Ok(__Field::__other(__value))); (Some(ignore_variant), Some(fallthrough)) @@ -2058,7 +2085,7 @@ fn deserialize_field_identifier( Stmts(deserialize_generated_identifier( fields, - cattrs, + has_flatten, false, ignore_variant, fallthrough, @@ -2460,6 +2487,7 @@ fn deserialize_map( params: &Parameters, fields: &[Field], cattrs: &attr::Container, + has_flatten: bool, ) -> Fragment { // Create the field names for the fields. let fields_names: Vec<_> = fields @@ -2480,9 +2508,6 @@ fn deserialize_map( }); // Collect contents for flatten fields into a buffer - let has_flatten = fields - .iter() - .any(|field| field.attrs.flatten() && !field.attrs.skip_deserializing()); let let_collect = if has_flatten { Some(quote! { let mut __collect = _serde::__private::Vec::<_serde::__private::Option<( @@ -2681,7 +2706,10 @@ fn deserialize_map_in_place( fields: &[Field], cattrs: &attr::Container, ) -> Fragment { - assert!(!cattrs.has_flatten()); + assert!( + !cattrs.has_flatten(), + "inplace deserialization of maps doesn't support flatten fields" + ); // Create the field names for the fields. let fields_names: Vec<_> = fields diff --git a/serde_derive/src/internals/ast.rs b/serde_derive/src/internals/ast.rs index a28d3ae7e..4ec709952 100644 --- a/serde_derive/src/internals/ast.rs +++ b/serde_derive/src/internals/ast.rs @@ -85,6 +85,7 @@ impl<'a> Container<'a> { for field in &mut variant.fields { if field.attrs.flatten() { has_flatten = true; + variant.attrs.mark_has_flatten(); } field.attrs.rename_by_rules( variant diff --git a/serde_derive/src/internals/attr.rs b/serde_derive/src/internals/attr.rs index 0cfb23bf1..5064d079a 100644 --- a/serde_derive/src/internals/attr.rs +++ b/serde_derive/src/internals/attr.rs @@ -216,6 +216,22 @@ pub struct Container { type_into: Option, remote: Option, identifier: Identifier, + /// `true` if container is a `struct` and it has a field with `#[serde(flatten)]` + /// attribute or it is an `enum` with a struct variant which has a field with + /// `#[serde(flatten)]` attribute. Examples: + /// + /// ```ignore + /// struct Container { + /// #[serde(flatten)] + /// some_field: (), + /// } + /// enum Container { + /// Variant { + /// #[serde(flatten)] + /// some_field: (), + /// }, + /// } + /// ``` has_flatten: bool, serde_path: Option, is_packed: bool, @@ -794,6 +810,18 @@ pub struct Variant { rename_all_rules: RenameAllRules, ser_bound: Option>, de_bound: Option>, + /// `true` if variant is a struct variant which contains a field with `#[serde(flatten)]` + /// attribute. Examples: + /// + /// ```ignore + /// enum Enum { + /// Variant { + /// #[serde(flatten)] + /// some_field: (), + /// }, + /// } + /// ``` + has_flatten: bool, skip_deserializing: bool, skip_serializing: bool, other: bool, @@ -963,6 +991,7 @@ impl Variant { }, ser_bound: ser_bound.get(), de_bound: de_bound.get(), + has_flatten: false, skip_deserializing: skip_deserializing.get(), skip_serializing: skip_serializing.get(), other: other.get(), @@ -1005,6 +1034,14 @@ impl Variant { self.de_bound.as_ref().map(|vec| &vec[..]) } + pub fn has_flatten(&self) -> bool { + self.has_flatten + } + + pub fn mark_has_flatten(&mut self) { + self.has_flatten = true; + } + pub fn skip_deserializing(&self) -> bool { self.skip_deserializing } From 2afe5b4ef9d0e89587ec564eadbc7583fd1f0673 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 10 Aug 2024 21:29:39 +0500 Subject: [PATCH 115/258] Add regression test for issue #2792 --- test_suite/tests/regression/issue2792.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 test_suite/tests/regression/issue2792.rs diff --git a/test_suite/tests/regression/issue2792.rs b/test_suite/tests/regression/issue2792.rs new file mode 100644 index 000000000..13c0b7103 --- /dev/null +++ b/test_suite/tests/regression/issue2792.rs @@ -0,0 +1,16 @@ +#![allow(dead_code)] // we do not read enum fields +use serde_derive::Deserialize; + +#[derive(Deserialize)] +#[serde(deny_unknown_fields)] +pub enum A { + B { + c: String, + }, + D { + #[serde(flatten)] + e: E, + }, +} +#[derive(Deserialize)] +pub struct E {} From 536221b1f93a5dcf97352c7d1e3b93a5a56bf747 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 10 Aug 2024 23:58:58 -0700 Subject: [PATCH 116/258] Temporarily ignore collection_is_never_read on FlattenSkipDeserializing error: collection is never read --> test_suite/tests/test_gen.rs:723:25 | 723 | #[derive(Serialize, Deserialize)] | ^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collection_is_never_read note: the lint level is defined here --> test_suite/tests/test_gen.rs:23:9 | 23 | #![deny(clippy::collection_is_never_read)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info) --- test_suite/tests/test_gen.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/test_suite/tests/test_gen.rs b/test_suite/tests/test_gen.rs index 3dacf00ab..2f43b20ba 100644 --- a/test_suite/tests/test_gen.rs +++ b/test_suite/tests/test_gen.rs @@ -720,11 +720,14 @@ fn test_gen() { flat: StdOption, } - #[derive(Serialize, Deserialize)] - pub struct FlattenSkipDeserializing { - #[serde(flatten, skip_deserializing)] - flat: T, - } + #[allow(clippy::collection_is_never_read)] // FIXME + const _: () = { + #[derive(Serialize, Deserialize)] + pub struct FlattenSkipDeserializing { + #[serde(flatten, skip_deserializing)] + flat: T, + } + }; #[derive(Serialize, Deserialize)] #[serde(untagged)] From e52b7b380f88e0112c9f84e6258bdd34ad132352 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 10 Aug 2024 23:34:36 -0700 Subject: [PATCH 117/258] Touch up PR 2567 --- serde_derive/src/de.rs | 4 ++-- serde_derive/src/internals/attr.rs | 10 +++++----- test_suite/tests/regression/issue1904.rs | 1 + test_suite/tests/regression/issue2792.rs | 2 ++ 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index ef85385f6..b87ababf0 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -1268,7 +1268,7 @@ fn prepare_enum_variant_enum(variants: &[Variant]) -> (TokenStream, Stmts) { let variant_visitor = Stmts(deserialize_generated_identifier( &variant_names_idents, - false, // variant identifiers does not depend on the presence of flatten fields + false, // variant identifiers do not depend on the presence of flatten fields true, None, fallthrough, @@ -2708,7 +2708,7 @@ fn deserialize_map_in_place( ) -> Fragment { assert!( !cattrs.has_flatten(), - "inplace deserialization of maps doesn't support flatten fields" + "inplace deserialization of maps does not support flatten fields" ); // Create the field names for the fields. diff --git a/serde_derive/src/internals/attr.rs b/serde_derive/src/internals/attr.rs index 5064d079a..ba3a2d8d8 100644 --- a/serde_derive/src/internals/attr.rs +++ b/serde_derive/src/internals/attr.rs @@ -216,9 +216,9 @@ pub struct Container { type_into: Option, remote: Option, identifier: Identifier, - /// `true` if container is a `struct` and it has a field with `#[serde(flatten)]` - /// attribute or it is an `enum` with a struct variant which has a field with - /// `#[serde(flatten)]` attribute. Examples: + /// True if container is a struct and has a field with `#[serde(flatten)]`, + /// or is an enum with a struct variant which has a field with + /// `#[serde(flatten)]`. /// /// ```ignore /// struct Container { @@ -810,8 +810,8 @@ pub struct Variant { rename_all_rules: RenameAllRules, ser_bound: Option>, de_bound: Option>, - /// `true` if variant is a struct variant which contains a field with `#[serde(flatten)]` - /// attribute. Examples: + /// True if variant is a struct variant which contains a field with + /// `#[serde(flatten)]`. /// /// ```ignore /// enum Enum { diff --git a/test_suite/tests/regression/issue1904.rs b/test_suite/tests/regression/issue1904.rs index 99736c078..b1d5c7314 100644 --- a/test_suite/tests/regression/issue1904.rs +++ b/test_suite/tests/regression/issue1904.rs @@ -1,4 +1,5 @@ #![allow(dead_code)] // we do not read enum fields + use serde_derive::Deserialize; #[derive(Deserialize)] diff --git a/test_suite/tests/regression/issue2792.rs b/test_suite/tests/regression/issue2792.rs index 13c0b7103..a8c1604ca 100644 --- a/test_suite/tests/regression/issue2792.rs +++ b/test_suite/tests/regression/issue2792.rs @@ -1,4 +1,5 @@ #![allow(dead_code)] // we do not read enum fields + use serde_derive::Deserialize; #[derive(Deserialize)] @@ -12,5 +13,6 @@ pub enum A { e: E, }, } + #[derive(Deserialize)] pub struct E {} From 5ba1796a7e639839d4e18c3ae23b9bb32b0700b5 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 11 Aug 2024 00:08:11 -0700 Subject: [PATCH 118/258] Resolve doc_markdown pedantic lint on regression test function warning: you should put bare URLs between `<`/`>` or make a proper Markdown link --> test_suite/tests/test_annotations.rs:2383:25 | 2383 | /// Regression test for https://github.com/serde-rs/serde/issues/1904 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown = note: `-W clippy::doc-markdown` implied by `-W clippy::pedantic` = help: to override `-W clippy::pedantic` add `#[allow(clippy::doc_markdown)]` --- test_suite/tests/test_annotations.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_suite/tests/test_annotations.rs b/test_suite/tests/test_annotations.rs index 1488c8364..1174be6d2 100644 --- a/test_suite/tests/test_annotations.rs +++ b/test_suite/tests/test_annotations.rs @@ -2380,7 +2380,7 @@ fn test_partially_untagged_enum_desugared() { ); } -/// Regression test for https://github.com/serde-rs/serde/issues/1904 +// Regression test for https://github.com/serde-rs/serde/issues/1904 #[test] fn test_enum_tuple_and_struct_with_flatten() { #[derive(Serialize, Deserialize, PartialEq, Debug)] From 85c73ef8dea8966d88a03876e6f0dc9359e68cc9 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 11 Aug 2024 00:06:36 -0700 Subject: [PATCH 119/258] Release 1.0.206 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 458971705..0511992d0 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.205" +version = "1.0.206" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.205", path = "../serde_derive" } +serde_derive = { version = "=1.0.206", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index f7ae62822..7e740d174 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.205")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.206")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index ab66b05be..ed636c5ef 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.205" +version = "1.0.206" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index 6560fe1ad..c3d64d0a3 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.205")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.206")] #![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] // Ignored clippy lints #![allow( From 0647a7c1feafebacea6de4cb69f0aee9b2ba2919 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sun, 11 Aug 2024 18:16:19 +0500 Subject: [PATCH 120/258] Fix creating and filling a collections that was not read --- serde_derive/src/de.rs | 18 +++++++----------- test_suite/tests/test_gen.rs | 32 ++++++++++++++++++++++++-------- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index b87ababf0..1ccecb26c 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -281,13 +281,9 @@ fn deserialize_body(cont: &Container, params: &Parameters) -> Fragment { } else if let attr::Identifier::No = cont.attrs.identifier() { match &cont.data { Data::Enum(variants) => deserialize_enum(params, variants, &cont.attrs), - Data::Struct(Style::Struct, fields) => deserialize_struct( - params, - fields, - &cont.attrs, - cont.attrs.has_flatten(), - StructForm::Struct, - ), + Data::Struct(Style::Struct, fields) => { + deserialize_struct(params, fields, &cont.attrs, StructForm::Struct) + } Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => { deserialize_tuple( params, @@ -927,7 +923,6 @@ fn deserialize_struct( params: &Parameters, fields: &[Field], cattrs: &attr::Container, - has_flatten: bool, form: StructForm, ) -> Fragment { let this_type = ¶ms.this_type; @@ -976,6 +971,10 @@ fn deserialize_struct( ) }) .collect(); + + let has_flatten = fields + .iter() + .any(|field| field.attrs.flatten() && !field.attrs.skip_deserializing()); let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs, has_flatten); // untagged struct variants do not get a visit_seq method. The same applies to @@ -1838,7 +1837,6 @@ fn deserialize_externally_tagged_variant( params, &variant.fields, cattrs, - variant.attrs.has_flatten(), StructForm::ExternallyTagged(variant_ident), ), } @@ -1882,7 +1880,6 @@ fn deserialize_internally_tagged_variant( params, &variant.fields, cattrs, - variant.attrs.has_flatten(), StructForm::InternallyTagged(variant_ident, deserializer), ), Style::Tuple => unreachable!("checked in serde_derive_internals"), @@ -1940,7 +1937,6 @@ fn deserialize_untagged_variant( params, &variant.fields, cattrs, - variant.attrs.has_flatten(), StructForm::Untagged(variant_ident, deserializer), ), } diff --git a/test_suite/tests/test_gen.rs b/test_suite/tests/test_gen.rs index 2f43b20ba..ed9dc725e 100644 --- a/test_suite/tests/test_gen.rs +++ b/test_suite/tests/test_gen.rs @@ -547,6 +547,12 @@ fn test_gen() { } assert::(); + #[derive(Serialize, Deserialize)] + pub struct Flatten { + #[serde(flatten)] + t: T, + } + #[derive(Serialize, Deserialize)] #[serde(deny_unknown_fields)] pub struct FlattenDenyUnknown { @@ -554,6 +560,19 @@ fn test_gen() { t: T, } + #[derive(Serialize, Deserialize)] + pub struct SkipDeserializing { + #[serde(skip_deserializing)] + flat: T, + } + + #[derive(Serialize, Deserialize)] + #[serde(deny_unknown_fields)] + pub struct SkipDeserializingDenyUnknown { + #[serde(skip_deserializing)] + flat: T, + } + #[derive(Serialize, Deserialize)] pub struct StaticStrStruct<'a> { a: &'a str, @@ -720,14 +739,11 @@ fn test_gen() { flat: StdOption, } - #[allow(clippy::collection_is_never_read)] // FIXME - const _: () = { - #[derive(Serialize, Deserialize)] - pub struct FlattenSkipDeserializing { - #[serde(flatten, skip_deserializing)] - flat: T, - } - }; + #[derive(Serialize, Deserialize)] + pub struct FlattenSkipDeserializing { + #[serde(flatten, skip_deserializing)] + flat: T, + } #[derive(Serialize, Deserialize)] #[serde(untagged)] From fd5b5e9aa561e29d9312ecef2019ec670b4bc334 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sun, 11 Aug 2024 18:46:31 +0500 Subject: [PATCH 121/258] Correctly calculate `has_flatten` attribute in all cases for deserialization Consequence: `FlattenSkipDeserializing[DenyUnknown]` - does not collect data in Field, because do not read them anyway - gets `deserialize_in_place` method - gets ability to deserialize from sequence (visit_seq method) - uses `deserialize_struct` instead of `deserialize_map` --- serde_derive/src/de.rs | 30 +++++++++++++----------------- serde_derive/src/internals/ast.rs | 1 - serde_derive/src/internals/attr.rs | 21 --------------------- 3 files changed, 13 insertions(+), 39 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index 1ccecb26c..be1666e7b 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -285,13 +285,7 @@ fn deserialize_body(cont: &Container, params: &Parameters) -> Fragment { deserialize_struct(params, fields, &cont.attrs, StructForm::Struct) } Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => { - deserialize_tuple( - params, - fields, - &cont.attrs, - cont.attrs.has_flatten(), - TupleForm::Tuple, - ) + deserialize_tuple(params, fields, &cont.attrs, TupleForm::Tuple) } Data::Struct(Style::Unit, _) => deserialize_unit_struct(params, &cont.attrs), } @@ -465,11 +459,10 @@ fn deserialize_tuple( params: &Parameters, fields: &[Field], cattrs: &attr::Container, - has_flatten: bool, form: TupleForm, ) -> Fragment { assert!( - !has_flatten, + !has_flatten(fields), "tuples and tuple variants cannot have flatten fields" ); @@ -590,7 +583,7 @@ fn deserialize_tuple_in_place( cattrs: &attr::Container, ) -> Fragment { assert!( - !cattrs.has_flatten(), + !has_flatten(fields), "tuples and tuple variants cannot have flatten fields" ); @@ -972,9 +965,7 @@ fn deserialize_struct( }) .collect(); - let has_flatten = fields - .iter() - .any(|field| field.attrs.flatten() && !field.attrs.skip_deserializing()); + let has_flatten = has_flatten(fields); let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs, has_flatten); // untagged struct variants do not get a visit_seq method. The same applies to @@ -1114,7 +1105,7 @@ fn deserialize_struct_in_place( ) -> Option { // for now we do not support in_place deserialization for structs that // are represented as map. - if cattrs.has_flatten() { + if has_flatten(fields) { return None; } @@ -1830,7 +1821,6 @@ fn deserialize_externally_tagged_variant( params, &variant.fields, cattrs, - variant.attrs.has_flatten(), TupleForm::ExternallyTagged(variant_ident), ), Style::Struct => deserialize_struct( @@ -1930,7 +1920,6 @@ fn deserialize_untagged_variant( params, &variant.fields, cattrs, - variant.attrs.has_flatten(), TupleForm::Untagged(variant_ident, deserializer), ), Style::Struct => deserialize_struct( @@ -2703,7 +2692,7 @@ fn deserialize_map_in_place( cattrs: &attr::Container, ) -> Fragment { assert!( - !cattrs.has_flatten(), + !has_flatten(fields), "inplace deserialization of maps does not support flatten fields" ); @@ -3038,6 +3027,13 @@ fn effective_style(variant: &Variant) -> Style { } } +/// True if there are fields that is not skipped and has a `#[serde(flatten)]` attribute. +fn has_flatten(fields: &[Field]) -> bool { + fields + .iter() + .any(|field| field.attrs.flatten() && !field.attrs.skip_deserializing()) +} + struct DeImplGenerics<'a>(&'a Parameters); #[cfg(feature = "deserialize_in_place")] struct InPlaceImplGenerics<'a>(&'a Parameters); diff --git a/serde_derive/src/internals/ast.rs b/serde_derive/src/internals/ast.rs index 4ec709952..a28d3ae7e 100644 --- a/serde_derive/src/internals/ast.rs +++ b/serde_derive/src/internals/ast.rs @@ -85,7 +85,6 @@ impl<'a> Container<'a> { for field in &mut variant.fields { if field.attrs.flatten() { has_flatten = true; - variant.attrs.mark_has_flatten(); } field.attrs.rename_by_rules( variant diff --git a/serde_derive/src/internals/attr.rs b/serde_derive/src/internals/attr.rs index ba3a2d8d8..28ed54267 100644 --- a/serde_derive/src/internals/attr.rs +++ b/serde_derive/src/internals/attr.rs @@ -810,18 +810,6 @@ pub struct Variant { rename_all_rules: RenameAllRules, ser_bound: Option>, de_bound: Option>, - /// True if variant is a struct variant which contains a field with - /// `#[serde(flatten)]`. - /// - /// ```ignore - /// enum Enum { - /// Variant { - /// #[serde(flatten)] - /// some_field: (), - /// }, - /// } - /// ``` - has_flatten: bool, skip_deserializing: bool, skip_serializing: bool, other: bool, @@ -991,7 +979,6 @@ impl Variant { }, ser_bound: ser_bound.get(), de_bound: de_bound.get(), - has_flatten: false, skip_deserializing: skip_deserializing.get(), skip_serializing: skip_serializing.get(), other: other.get(), @@ -1034,14 +1021,6 @@ impl Variant { self.de_bound.as_ref().map(|vec| &vec[..]) } - pub fn has_flatten(&self) -> bool { - self.has_flatten - } - - pub fn mark_has_flatten(&mut self) { - self.has_flatten = true; - } - pub fn skip_deserializing(&self) -> bool { self.skip_deserializing } From 005cb84593e73cb3ba263232cc5f09b77859ec5b Mon Sep 17 00:00:00 2001 From: Mingun Date: Sun, 11 Aug 2024 20:00:02 +0500 Subject: [PATCH 122/258] Fail with an understandable message is number of fields for serialization is too many --- serde_derive/src/ser.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/serde_derive/src/ser.rs b/serde_derive/src/ser.rs index 7d89d2212..a0291aff7 100644 --- a/serde_derive/src/ser.rs +++ b/serde_derive/src/ser.rs @@ -289,7 +289,13 @@ fn serialize_tuple_struct( } fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment { - assert!(fields.len() as u64 <= u64::from(u32::MAX)); + assert!( + fields.len() as u64 <= u64::from(u32::MAX), + "too many fields in {}: {}, maximum supported count is {}", + cattrs.name().serialize_name(), + fields.len(), + u32::MAX + ); if cattrs.has_flatten() { serialize_struct_as_map(params, fields, cattrs) From 547d843ccaa1349b074991f5ceeda722cf245824 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sun, 11 Aug 2024 19:22:47 +0500 Subject: [PATCH 123/258] Remove dead code - serialize_struct_as_map always called when cattrs.has_flatten()==true --- serde_derive/src/ser.rs | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/serde_derive/src/ser.rs b/serde_derive/src/ser.rs index a0291aff7..f745bf675 100644 --- a/serde_derive/src/ser.rs +++ b/serde_derive/src/ser.rs @@ -376,26 +376,8 @@ fn serialize_struct_as_map( let let_mut = mut_if(serialized_fields.peek().is_some() || tag_field_exists); - let len = if cattrs.has_flatten() { - quote!(_serde::__private::None) - } else { - let len = serialized_fields - .map(|field| match field.attrs.skip_serializing_if() { - None => quote!(1), - Some(path) => { - let field_expr = get_member(params, field, &field.member); - quote!(if #path(#field_expr) { 0 } else { 1 }) - } - }) - .fold( - quote!(#tag_field_exists as usize), - |sum, expr| quote!(#sum + #expr), - ); - quote!(_serde::__private::Some(#len)) - }; - quote_block! { - let #let_mut __serde_state = _serde::Serializer::serialize_map(__serializer, #len)?; + let #let_mut __serde_state = _serde::Serializer::serialize_map(__serializer, _serde::__private::None)?; #tag_field #(#serialize_fields)* _serde::ser::SerializeMap::end(__serde_state) From 77a6a9d4e193c82439aa0c35dfdbbb34fafdf38e Mon Sep 17 00:00:00 2001 From: Mingun Date: Sun, 11 Aug 2024 19:56:27 +0500 Subject: [PATCH 124/258] Take into account only not skipped flatten fields when choose serialization form Consequence: `FlattenSkipSerializing` - uses `serialize_struct` instead of `serialize_map` --- serde_derive/src/internals/ast.rs | 13 +------------ serde_derive/src/internals/attr.rs | 26 -------------------------- serde_derive/src/ser.rs | 5 ++++- 3 files changed, 5 insertions(+), 39 deletions(-) diff --git a/serde_derive/src/internals/ast.rs b/serde_derive/src/internals/ast.rs index a28d3ae7e..3293823a7 100644 --- a/serde_derive/src/internals/ast.rs +++ b/serde_derive/src/internals/ast.rs @@ -63,7 +63,7 @@ impl<'a> Container<'a> { item: &'a syn::DeriveInput, derive: Derive, ) -> Option> { - let mut attrs = attr::Container::from_ast(cx, item); + let attrs = attr::Container::from_ast(cx, item); let mut data = match &item.data { syn::Data::Enum(data) => Data::Enum(enum_from_ast(cx, &data.variants, attrs.default())), @@ -77,15 +77,11 @@ impl<'a> Container<'a> { } }; - let mut has_flatten = false; match &mut data { Data::Enum(variants) => { for variant in variants { variant.attrs.rename_by_rules(attrs.rename_all_rules()); for field in &mut variant.fields { - if field.attrs.flatten() { - has_flatten = true; - } field.attrs.rename_by_rules( variant .attrs @@ -97,18 +93,11 @@ impl<'a> Container<'a> { } Data::Struct(_, fields) => { for field in fields { - if field.attrs.flatten() { - has_flatten = true; - } field.attrs.rename_by_rules(attrs.rename_all_rules()); } } } - if has_flatten { - attrs.mark_has_flatten(); - } - let mut item = Container { ident: item.ident.clone(), attrs, diff --git a/serde_derive/src/internals/attr.rs b/serde_derive/src/internals/attr.rs index 28ed54267..ac5f5d9a5 100644 --- a/serde_derive/src/internals/attr.rs +++ b/serde_derive/src/internals/attr.rs @@ -216,23 +216,6 @@ pub struct Container { type_into: Option, remote: Option, identifier: Identifier, - /// True if container is a struct and has a field with `#[serde(flatten)]`, - /// or is an enum with a struct variant which has a field with - /// `#[serde(flatten)]`. - /// - /// ```ignore - /// struct Container { - /// #[serde(flatten)] - /// some_field: (), - /// } - /// enum Container { - /// Variant { - /// #[serde(flatten)] - /// some_field: (), - /// }, - /// } - /// ``` - has_flatten: bool, serde_path: Option, is_packed: bool, /// Error message generated when type can't be deserialized @@ -603,7 +586,6 @@ impl Container { type_into: type_into.get(), remote: remote.get(), identifier: decide_identifier(cx, item, field_identifier, variant_identifier), - has_flatten: false, serde_path: serde_path.get(), is_packed, expecting: expecting.get(), @@ -671,14 +653,6 @@ impl Container { self.identifier } - pub fn has_flatten(&self) -> bool { - self.has_flatten - } - - pub fn mark_has_flatten(&mut self) { - self.has_flatten = true; - } - pub fn custom_serde_path(&self) -> Option<&syn::Path> { self.serde_path.as_ref() } diff --git a/serde_derive/src/ser.rs b/serde_derive/src/ser.rs index f745bf675..4f5e000d4 100644 --- a/serde_derive/src/ser.rs +++ b/serde_derive/src/ser.rs @@ -297,7 +297,10 @@ fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Contai u32::MAX ); - if cattrs.has_flatten() { + let has_non_skipped_flatten = fields + .iter() + .any(|field| field.attrs.flatten() && !field.attrs.skip_serializing()); + if has_non_skipped_flatten { serialize_struct_as_map(params, fields, cattrs) } else { serialize_struct_as_struct(params, fields, cattrs) From 9c954264f47f65f91f387e7deccb73568fc67d0f Mon Sep 17 00:00:00 2001 From: Mingun Date: Fri, 11 Aug 2023 01:09:44 +0500 Subject: [PATCH 125/258] Include variant aliases in error messages --- serde_derive/src/de.rs | 2 +- test_suite/tests/test_annotations.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index b87ababf0..eb415be73 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -1259,7 +1259,7 @@ fn prepare_enum_variant_enum(variants: &[Variant]) -> (TokenStream, Stmts) { }); let variants_stmt = { - let variant_names = variant_names_idents.iter().map(|(name, _, _)| name); + let variant_names = variant_names_idents.iter().flat_map(|&(_, _, aliases)| aliases); quote! { #[doc(hidden)] const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ]; diff --git a/test_suite/tests/test_annotations.rs b/test_suite/tests/test_annotations.rs index 1174be6d2..5aa20c16e 100644 --- a/test_suite/tests/test_annotations.rs +++ b/test_suite/tests/test_annotations.rs @@ -782,7 +782,7 @@ fn test_unknown_field_rename_enum() { variant: "SailorMoon", len: 3, }], - "unknown variant `SailorMoon`, expected `sailor_moon`", + "unknown variant `SailorMoon`, expected `sailor_moon` or `usagi_tsukino`", ); assert_de_tokens_error::( From 8b769fcc2025f1d4941bc9d322f45a6f9e966f82 Mon Sep 17 00:00:00 2001 From: Mingun Date: Fri, 11 Aug 2023 01:19:48 +0500 Subject: [PATCH 126/258] Remove unused component from tuple --- serde_derive/src/de.rs | 62 ++++++++++++------------------------------ 1 file changed, 18 insertions(+), 44 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index eb415be73..087b955a8 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -968,13 +968,7 @@ fn deserialize_struct( // Skip fields that shouldn't be deserialized or that were flattened, // so they don't appear in the storage in their literal form .filter(|&(_, field)| !field.attrs.skip_deserializing() && !field.attrs.flatten()) - .map(|(i, field)| { - ( - field.attrs.name().deserialize_name(), - field_i(i), - field.attrs.aliases(), - ) - }) + .map(|(i, field)| (field_i(i), field.attrs.aliases())) .collect(); let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs, has_flatten); @@ -1032,9 +1026,7 @@ fn deserialize_struct( let fields_stmt = if has_flatten { None } else { - let field_names = field_names_idents - .iter() - .flat_map(|&(_, _, aliases)| aliases); + let field_names = field_names_idents.iter().flat_map(|&(_, aliases)| aliases); Some(quote! { #[doc(hidden)] @@ -1131,13 +1123,7 @@ fn deserialize_struct_in_place( .iter() .enumerate() .filter(|&(_, field)| !field.attrs.skip_deserializing()) - .map(|(i, field)| { - ( - field.attrs.name().deserialize_name(), - field_i(i), - field.attrs.aliases(), - ) - }) + .map(|(i, field)| (field_i(i), field.attrs.aliases())) .collect(); let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs, false); @@ -1149,9 +1135,7 @@ fn deserialize_struct_in_place( }; let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting)); let visit_map = Stmts(deserialize_map_in_place(params, fields, cattrs)); - let field_names = field_names_idents - .iter() - .flat_map(|&(_, _, aliases)| aliases); + let field_names = field_names_idents.iter().flat_map(|&(_, aliases)| aliases); let type_name = cattrs.name().deserialize_name(); let in_place_impl_generics = de_impl_generics.in_place(); @@ -1242,24 +1226,20 @@ fn prepare_enum_variant_enum(variants: &[Variant]) -> (TokenStream, Stmts) { let variant_names_idents: Vec<_> = deserialized_variants .clone() - .map(|(i, variant)| { - ( - variant.attrs.name().deserialize_name(), - field_i(i), - variant.attrs.aliases(), - ) - }) + .map(|(i, variant)| (field_i(i), variant.attrs.aliases())) .collect(); let fallthrough = deserialized_variants .position(|(_, variant)| variant.attrs.other()) .map(|other_idx| { - let ignore_variant = variant_names_idents[other_idx].1.clone(); + let ignore_variant = variant_names_idents[other_idx].0.clone(); quote!(_serde::__private::Ok(__Field::#ignore_variant)) }); let variants_stmt = { - let variant_names = variant_names_idents.iter().flat_map(|&(_, _, aliases)| aliases); + let variant_names = variant_names_idents + .iter() + .flat_map(|&(_, aliases)| aliases); quote! { #[doc(hidden)] const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ]; @@ -2010,14 +1990,14 @@ fn deserialize_untagged_newtype_variant( } fn deserialize_generated_identifier( - fields: &[(&str, Ident, &BTreeSet)], + fields: &[(Ident, &BTreeSet)], has_flatten: bool, is_variant: bool, ignore_variant: Option, fallthrough: Option, ) -> Fragment { let this_value = quote!(__Field); - let field_idents: &Vec<_> = &fields.iter().map(|(_, ident, _)| ident).collect(); + let field_idents: &Vec<_> = &fields.iter().map(|(ident, _)| ident).collect(); let visitor_impl = Stmts(deserialize_identifier( &this_value, @@ -2067,7 +2047,7 @@ fn deserialize_generated_identifier( /// Generates enum and its `Deserialize` implementation that represents each /// non-skipped field of the struct fn deserialize_field_identifier( - fields: &[(&str, Ident, &BTreeSet)], + fields: &[(Ident, &BTreeSet)], cattrs: &attr::Container, has_flatten: bool, ) -> Stmts { @@ -2144,16 +2124,10 @@ fn deserialize_custom_identifier( let names_idents: Vec<_> = ordinary .iter() - .map(|variant| { - ( - variant.attrs.name().deserialize_name(), - variant.ident.clone(), - variant.attrs.aliases(), - ) - }) + .map(|variant| (variant.ident.clone(), variant.attrs.aliases())) .collect(); - let names = names_idents.iter().flat_map(|&(_, _, aliases)| aliases); + let names = names_idents.iter().flat_map(|&(_, aliases)| aliases); let names_const = if fallthrough.is_some() { None @@ -2209,18 +2183,18 @@ fn deserialize_custom_identifier( fn deserialize_identifier( this_value: &TokenStream, - fields: &[(&str, Ident, &BTreeSet)], + fields: &[(Ident, &BTreeSet)], is_variant: bool, fallthrough: Option, fallthrough_borrowed: Option, collect_other_fields: bool, expecting: Option<&str>, ) -> Fragment { - let str_mapping = fields.iter().map(|(_, ident, aliases)| { + let str_mapping = fields.iter().map(|(ident, aliases)| { // `aliases` also contains a main name quote!(#(#aliases)|* => _serde::__private::Ok(#this_value::#ident)) }); - let bytes_mapping = fields.iter().map(|(_, ident, aliases)| { + let bytes_mapping = fields.iter().map(|(ident, aliases)| { // `aliases` also contains a main name let aliases = aliases .iter() @@ -2375,7 +2349,7 @@ fn deserialize_identifier( } } } else { - let u64_mapping = fields.iter().enumerate().map(|(i, (_, ident, _))| { + let u64_mapping = fields.iter().enumerate().map(|(i, (ident, _))| { let i = i as u64; quote!(#i => _serde::__private::Ok(#this_value::#ident)) }); From f61d452814d6c7bf32d139e747d18c21592d702a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 12 Aug 2024 13:00:04 -0700 Subject: [PATCH 127/258] Touch up PR 2795 --- serde_derive/src/de.rs | 3 ++- serde_derive/src/ser.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index be1666e7b..996e97e86 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -3027,7 +3027,8 @@ fn effective_style(variant: &Variant) -> Style { } } -/// True if there are fields that is not skipped and has a `#[serde(flatten)]` attribute. +/// True if there is any field with a `#[serde(flatten)]` attribute, other than +/// fields which are skipped. fn has_flatten(fields: &[Field]) -> bool { fields .iter() diff --git a/serde_derive/src/ser.rs b/serde_derive/src/ser.rs index 4f5e000d4..35f8ca4bd 100644 --- a/serde_derive/src/ser.rs +++ b/serde_derive/src/ser.rs @@ -294,7 +294,7 @@ fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Contai "too many fields in {}: {}, maximum supported count is {}", cattrs.name().serialize_name(), fields.len(), - u32::MAX + u32::MAX, ); let has_non_skipped_flatten = fields From 1b4da41f970555e111f471633205bbcb4dadbc63 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 12 Aug 2024 13:06:46 -0700 Subject: [PATCH 128/258] Release 1.0.207 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 0511992d0..a2f227eb7 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.206" +version = "1.0.207" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.206", path = "../serde_derive" } +serde_derive = { version = "=1.0.207", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 7e740d174..c65826d08 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.206")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.207")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index ed636c5ef..17648eb88 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.206" +version = "1.0.207" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index c3d64d0a3..372b424c2 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.206")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.207")] #![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] // Ignored clippy lints #![allow( From 4036ff88edc2ee85f288e8c9bc6d9a0f393cf96e Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Thu, 15 Aug 2024 15:50:40 +0200 Subject: [PATCH 129/258] Support (de-)serializing flattened unit struct Fixes #2801. --- serde/src/private/de.rs | 12 +++++++++++- serde/src/private/ser.rs | 6 +----- test_suite/tests/test_annotations.rs | 26 ++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index c402d2c66..c146539ee 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -2710,6 +2710,17 @@ where visitor.visit_unit() } + fn deserialize_unit_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + visitor.visit_unit() + } + fn deserialize_ignored_any(self, visitor: V) -> Result where V: Visitor<'de>, @@ -2734,7 +2745,6 @@ where deserialize_string() deserialize_bytes() deserialize_byte_buf() - deserialize_unit_struct(&'static str) deserialize_seq() deserialize_tuple(usize) deserialize_tuple_struct(&'static str, usize) diff --git a/serde/src/private/ser.rs b/serde/src/private/ser.rs index 9570629e9..ebfeba97e 100644 --- a/serde/src/private/ser.rs +++ b/serde/src/private/ser.rs @@ -51,8 +51,6 @@ enum Unsupported { String, ByteArray, Optional, - #[cfg(any(feature = "std", feature = "alloc"))] - UnitStruct, Sequence, Tuple, TupleStruct, @@ -69,8 +67,6 @@ impl Display for Unsupported { Unsupported::String => formatter.write_str("a string"), Unsupported::ByteArray => formatter.write_str("a byte array"), Unsupported::Optional => formatter.write_str("an optional"), - #[cfg(any(feature = "std", feature = "alloc"))] - Unsupported::UnitStruct => formatter.write_str("unit struct"), Unsupported::Sequence => formatter.write_str("a sequence"), Unsupported::Tuple => formatter.write_str("a tuple"), Unsupported::TupleStruct => formatter.write_str("a tuple struct"), @@ -1092,7 +1088,7 @@ where } fn serialize_unit_struct(self, _: &'static str) -> Result { - Err(Self::bad_type(Unsupported::UnitStruct)) + Ok(()) } fn serialize_unit_variant( diff --git a/test_suite/tests/test_annotations.rs b/test_suite/tests/test_annotations.rs index 1174be6d2..63cb3dd1b 100644 --- a/test_suite/tests/test_annotations.rs +++ b/test_suite/tests/test_annotations.rs @@ -1815,6 +1815,32 @@ fn test_flatten_unit() { ); } +#[test] +fn test_flatten_unit_struct() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct Response { + #[serde(flatten)] + data: T, + status: usize, + } + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct Unit; + + assert_tokens( + &Response { + data: Unit, + status: 0, + }, + &[ + Token::Map { len: None }, + Token::Str("status"), + Token::U64(0), + Token::MapEnd, + ], + ); +} + #[test] fn test_flatten_unsupported_type() { #[derive(Debug, PartialEq, Serialize, Deserialize)] From 026e91a68cdb00ed89bae5f566852ecbd7525315 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 15 Aug 2024 08:41:27 -0700 Subject: [PATCH 130/258] Release 1.0.208 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index a2f227eb7..e2c3bf976 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.207" +version = "1.0.208" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.207", path = "../serde_derive" } +serde_derive = { version = "=1.0.208", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index c65826d08..5317d93c7 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.207")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.208")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 17648eb88..1ba754b0e 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.207" +version = "1.0.208" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index 372b424c2..45fa33653 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.207")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.208")] #![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] // Ignored clippy lints #![allow( From 477eb7b70ea11bfc377ff2bb89c435dc2e661796 Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Thu, 15 Aug 2024 18:28:49 +0200 Subject: [PATCH 131/258] Group flatten tests --- test_suite/tests/test_annotations.rs | 1648 +++++++++++++------------- 1 file changed, 826 insertions(+), 822 deletions(-) diff --git a/test_suite/tests/test_annotations.rs b/test_suite/tests/test_annotations.rs index 63cb3dd1b..6864bf960 100644 --- a/test_suite/tests/test_annotations.rs +++ b/test_suite/tests/test_annotations.rs @@ -1607,426 +1607,6 @@ fn test_collect_other() { ); } -#[test] -fn test_unknown_field_in_flatten() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(deny_unknown_fields)] - struct Outer { - dummy: String, - #[serde(flatten)] - inner: Inner, - } - - #[derive(Debug, PartialEq, Serialize, Deserialize)] - struct Inner { - foo: HashMap, - } - - assert_de_tokens_error::( - &[ - Token::Struct { - name: "Outer", - len: 1, - }, - Token::Str("dummy"), - Token::Str("23"), - Token::Str("foo"), - Token::Map { len: None }, - Token::Str("a"), - Token::U32(1), - Token::Str("b"), - Token::U32(2), - Token::MapEnd, - Token::Str("bar"), - Token::U32(23), - Token::StructEnd, - ], - "unknown field `bar`", - ); -} - -#[test] -fn test_complex_flatten() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - struct Outer { - y: u32, - #[serde(flatten)] - first: First, - #[serde(flatten)] - second: Second, - z: u32, - } - - #[derive(Debug, PartialEq, Serialize, Deserialize)] - struct First { - a: u32, - b: bool, - c: Vec, - d: String, - e: Option, - } - - #[derive(Debug, PartialEq, Serialize, Deserialize)] - struct Second { - f: u32, - } - - assert_de_tokens( - &Outer { - y: 0, - first: First { - a: 1, - b: true, - c: vec!["a".into(), "b".into()], - d: "c".into(), - e: Some(2), - }, - second: Second { f: 3 }, - z: 4, - }, - &[ - Token::Map { len: None }, - Token::Str("y"), - Token::U32(0), - Token::Str("a"), - Token::U32(1), - Token::Str("b"), - Token::Bool(true), - Token::Str("c"), - Token::Seq { len: Some(2) }, - Token::Str("a"), - Token::Str("b"), - Token::SeqEnd, - Token::Str("d"), - Token::Str("c"), - Token::Str("e"), - Token::U64(2), - Token::Str("f"), - Token::U32(3), - Token::Str("z"), - Token::U32(4), - Token::MapEnd, - ], - ); - - assert_ser_tokens( - &Outer { - y: 0, - first: First { - a: 1, - b: true, - c: vec!["a".into(), "b".into()], - d: "c".into(), - e: Some(2), - }, - second: Second { f: 3 }, - z: 4, - }, - &[ - Token::Map { len: None }, - Token::Str("y"), - Token::U32(0), - Token::Str("a"), - Token::U32(1), - Token::Str("b"), - Token::Bool(true), - Token::Str("c"), - Token::Seq { len: Some(2) }, - Token::Str("a"), - Token::Str("b"), - Token::SeqEnd, - Token::Str("d"), - Token::Str("c"), - Token::Str("e"), - Token::Some, - Token::U64(2), - Token::Str("f"), - Token::U32(3), - Token::Str("z"), - Token::U32(4), - Token::MapEnd, - ], - ); -} - -#[test] -fn test_flatten_map_twice() { - #[derive(Debug, PartialEq, Deserialize)] - struct Outer { - #[serde(flatten)] - first: BTreeMap, - #[serde(flatten)] - between: Inner, - #[serde(flatten)] - second: BTreeMap, - } - - #[derive(Debug, PartialEq, Deserialize)] - struct Inner { - y: String, - } - - assert_de_tokens( - &Outer { - first: { - let mut first = BTreeMap::new(); - first.insert("x".to_owned(), "X".to_owned()); - first.insert("y".to_owned(), "Y".to_owned()); - first - }, - between: Inner { y: "Y".to_owned() }, - second: { - let mut second = BTreeMap::new(); - second.insert("x".to_owned(), "X".to_owned()); - second - }, - }, - &[ - Token::Map { len: None }, - Token::Str("x"), - Token::Str("X"), - Token::Str("y"), - Token::Str("Y"), - Token::MapEnd, - ], - ); -} - -#[test] -fn test_flatten_unit() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - struct Response { - #[serde(flatten)] - data: T, - status: usize, - } - - assert_tokens( - &Response { - data: (), - status: 0, - }, - &[ - Token::Map { len: None }, - Token::Str("status"), - Token::U64(0), - Token::MapEnd, - ], - ); -} - -#[test] -fn test_flatten_unit_struct() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - struct Response { - #[serde(flatten)] - data: T, - status: usize, - } - - #[derive(Debug, PartialEq, Serialize, Deserialize)] - struct Unit; - - assert_tokens( - &Response { - data: Unit, - status: 0, - }, - &[ - Token::Map { len: None }, - Token::Str("status"), - Token::U64(0), - Token::MapEnd, - ], - ); -} - -#[test] -fn test_flatten_unsupported_type() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - struct Outer { - outer: String, - #[serde(flatten)] - inner: String, - } - - assert_ser_tokens_error( - &Outer { - outer: "foo".into(), - inner: "bar".into(), - }, - &[ - Token::Map { len: None }, - Token::Str("outer"), - Token::Str("foo"), - ], - "can only flatten structs and maps (got a string)", - ); - assert_de_tokens_error::( - &[ - Token::Map { len: None }, - Token::Str("outer"), - Token::Str("foo"), - Token::Str("a"), - Token::Str("b"), - Token::MapEnd, - ], - "can only flatten structs and maps", - ); -} - -#[test] -fn test_non_string_keys() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - struct TestStruct { - name: String, - age: u32, - #[serde(flatten)] - mapping: HashMap, - } - - let mut mapping = HashMap::new(); - mapping.insert(0, 42); - assert_tokens( - &TestStruct { - name: "peter".into(), - age: 3, - mapping, - }, - &[ - Token::Map { len: None }, - Token::Str("name"), - Token::Str("peter"), - Token::Str("age"), - Token::U32(3), - Token::U32(0), - Token::U32(42), - Token::MapEnd, - ], - ); -} - -#[test] -fn test_lifetime_propagation_for_flatten() { - #[derive(Deserialize, Serialize, Debug, PartialEq)] - struct A { - #[serde(flatten)] - t: T, - } - - #[derive(Deserialize, Serialize, Debug, PartialEq)] - struct B<'a> { - #[serde(flatten, borrow)] - t: HashMap<&'a str, u32>, - } - - #[derive(Deserialize, Serialize, Debug, PartialEq)] - struct C<'a> { - #[serde(flatten, borrow)] - t: HashMap<&'a [u8], u32>, - } - - let mut owned_map = HashMap::new(); - owned_map.insert("x".to_string(), 42u32); - assert_tokens( - &A { t: owned_map }, - &[ - Token::Map { len: None }, - Token::Str("x"), - Token::U32(42), - Token::MapEnd, - ], - ); - - let mut borrowed_map = HashMap::new(); - borrowed_map.insert("x", 42u32); - assert_ser_tokens( - &B { - t: borrowed_map.clone(), - }, - &[ - Token::Map { len: None }, - Token::BorrowedStr("x"), - Token::U32(42), - Token::MapEnd, - ], - ); - - assert_de_tokens( - &B { t: borrowed_map }, - &[ - Token::Map { len: None }, - Token::BorrowedStr("x"), - Token::U32(42), - Token::MapEnd, - ], - ); - - let mut borrowed_map = HashMap::new(); - borrowed_map.insert(&b"x"[..], 42u32); - assert_ser_tokens( - &C { - t: borrowed_map.clone(), - }, - &[ - Token::Map { len: None }, - Token::Seq { len: Some(1) }, - Token::U8(120), - Token::SeqEnd, - Token::U32(42), - Token::MapEnd, - ], - ); - - assert_de_tokens( - &C { t: borrowed_map }, - &[ - Token::Map { len: None }, - Token::BorrowedBytes(b"x"), - Token::U32(42), - Token::MapEnd, - ], - ); -} - -#[test] -fn test_externally_tagged_enum_containing_flatten() { - #[derive(Serialize, Deserialize, PartialEq, Debug)] - enum Data { - A { - a: i32, - #[serde(flatten)] - flat: Flat, - }, - } - - #[derive(Serialize, Deserialize, PartialEq, Debug)] - struct Flat { - b: i32, - } - - let data = Data::A { - a: 0, - flat: Flat { b: 0 }, - }; - - assert_tokens( - &data, - &[ - Token::NewtypeVariant { - name: "Data", - variant: "A", - }, - Token::Map { len: None }, - Token::Str("a"), - Token::I32(0), - Token::Str("b"), - Token::I32(0), - Token::MapEnd, - ], - ); -} - #[test] fn test_internally_tagged_enum_with_skipped_conflict() { #[derive(Serialize, Deserialize, PartialEq, Debug)] @@ -2060,43 +1640,6 @@ fn test_internally_tagged_enum_with_skipped_conflict() { ); } -#[test] -fn test_internally_tagged_enum_containing_flatten() { - #[derive(Serialize, Deserialize, PartialEq, Debug)] - #[serde(tag = "t")] - enum Data { - A { - a: i32, - #[serde(flatten)] - flat: Flat, - }, - } - - #[derive(Serialize, Deserialize, PartialEq, Debug)] - struct Flat { - b: i32, - } - - let data = Data::A { - a: 0, - flat: Flat { b: 0 }, - }; - - assert_tokens( - &data, - &[ - Token::Map { len: None }, - Token::Str("t"), - Token::Str("A"), - Token::Str("a"), - Token::I32(0), - Token::Str("b"), - Token::I32(0), - Token::MapEnd, - ], - ); -} - #[test] fn test_internally_tagged_enum_new_type_with_unit() { #[derive(Serialize, Deserialize, PartialEq, Debug)] @@ -2169,87 +1712,6 @@ fn test_adjacently_tagged_enum_bytes() { ); } -#[test] -fn test_adjacently_tagged_enum_containing_flatten() { - #[derive(Serialize, Deserialize, PartialEq, Debug)] - #[serde(tag = "t", content = "c")] - enum Data { - A { - a: i32, - #[serde(flatten)] - flat: Flat, - }, - } - - #[derive(Serialize, Deserialize, PartialEq, Debug)] - struct Flat { - b: i32, - } - - let data = Data::A { - a: 0, - flat: Flat { b: 0 }, - }; - - assert_tokens( - &data, - &[ - Token::Struct { - name: "Data", - len: 2, - }, - Token::Str("t"), - Token::UnitVariant { - name: "Data", - variant: "A", - }, - Token::Str("c"), - Token::Map { len: None }, - Token::Str("a"), - Token::I32(0), - Token::Str("b"), - Token::I32(0), - Token::MapEnd, - Token::StructEnd, - ], - ); -} - -#[test] -fn test_untagged_enum_containing_flatten() { - #[derive(Serialize, Deserialize, PartialEq, Debug)] - #[serde(untagged)] - enum Data { - A { - a: i32, - #[serde(flatten)] - flat: Flat, - }, - } - - #[derive(Serialize, Deserialize, PartialEq, Debug)] - struct Flat { - b: i32, - } - - let data = Data::A { - a: 0, - flat: Flat { b: 0 }, - }; - - assert_tokens( - &data, - &[ - Token::Map { len: None }, - Token::Str("a"), - Token::I32(0), - Token::Str("b"), - Token::I32(0), - Token::MapEnd, - ], - ); -} - #[test] fn test_partially_untagged_enum() { #[derive(Serialize, Deserialize, PartialEq, Debug)] @@ -2406,56 +1868,6 @@ fn test_partially_untagged_enum_desugared() { ); } -// Regression test for https://github.com/serde-rs/serde/issues/1904 -#[test] -fn test_enum_tuple_and_struct_with_flatten() { - #[derive(Serialize, Deserialize, PartialEq, Debug)] - enum Outer { - Tuple(f64, i32), - Flatten { - #[serde(flatten)] - nested: Nested, - }, - } - - #[derive(Serialize, Deserialize, PartialEq, Debug)] - struct Nested { - a: i32, - b: i32, - } - - assert_tokens( - &Outer::Tuple(1.2, 3), - &[ - Token::TupleVariant { - name: "Outer", - variant: "Tuple", - len: 2, - }, - Token::F64(1.2), - Token::I32(3), - Token::TupleVariantEnd, - ], - ); - assert_tokens( - &Outer::Flatten { - nested: Nested { a: 1, b: 2 }, - }, - &[ - Token::NewtypeVariant { - name: "Outer", - variant: "Flatten", - }, - Token::Map { len: None }, - Token::Str("a"), - Token::I32(1), - Token::Str("b"), - Token::I32(2), - Token::MapEnd, - ], - ); -} - #[test] fn test_partially_untagged_internally_tagged_enum() { #[derive(Serialize, Deserialize, PartialEq, Debug)] @@ -2493,124 +1905,29 @@ fn test_partially_untagged_adjacently_tagged_enum() { enum Data { A(u32), B, - #[serde(untagged)] - Var(u32), - } - - let data = Data::A(7); - - assert_de_tokens( - &data, - &[ - Token::Map { len: None }, - Token::Str("t"), - Token::Str("A"), - Token::Str("c"), - Token::U32(7), - Token::MapEnd, - ], - ); - - let data = Data::Var(42); - - assert_de_tokens(&data, &[Token::U32(42)]); - - // TODO test error output -} - -#[test] -fn test_flatten_option() { - #[derive(Serialize, Deserialize, PartialEq, Debug)] - struct Outer { - #[serde(flatten)] - inner1: Option, - #[serde(flatten)] - inner2: Option, - } - - #[derive(Serialize, Deserialize, PartialEq, Debug)] - struct Inner1 { - inner1: i32, - } - - #[derive(Serialize, Deserialize, PartialEq, Debug)] - struct Inner2 { - inner2: i32, - } - - assert_tokens( - &Outer { - inner1: Some(Inner1 { inner1: 1 }), - inner2: Some(Inner2 { inner2: 2 }), - }, - &[ - Token::Map { len: None }, - Token::Str("inner1"), - Token::I32(1), - Token::Str("inner2"), - Token::I32(2), - Token::MapEnd, - ], - ); - - assert_tokens( - &Outer { - inner1: Some(Inner1 { inner1: 1 }), - inner2: None, - }, - &[ - Token::Map { len: None }, - Token::Str("inner1"), - Token::I32(1), - Token::MapEnd, - ], - ); - - assert_tokens( - &Outer { - inner1: None, - inner2: Some(Inner2 { inner2: 2 }), - }, - &[ - Token::Map { len: None }, - Token::Str("inner2"), - Token::I32(2), - Token::MapEnd, - ], - ); - - assert_tokens( - &Outer { - inner1: None, - inner2: None, - }, - &[Token::Map { len: None }, Token::MapEnd], - ); -} - -#[test] -fn test_flatten_ignored_any() { - #[derive(Deserialize, PartialEq, Debug)] - struct Outer { - #[serde(flatten)] - inner: IgnoredAny, + #[serde(untagged)] + Var(u32), } - assert_de_tokens( - &Outer { inner: IgnoredAny }, - &[Token::Map { len: None }, Token::MapEnd], - ); + let data = Data::A(7); assert_de_tokens( - &Outer { inner: IgnoredAny }, + &data, &[ - Token::Struct { - name: "DoNotMatter", - len: 0, - }, - Token::StructEnd, + Token::Map { len: None }, + Token::Str("t"), + Token::Str("A"), + Token::Str("c"), + Token::U32(7), + Token::MapEnd, ], ); + + let data = Data::Var(42); + + assert_de_tokens(&data, &[Token::U32(42)]); + + // TODO test error output } #[test] @@ -2674,129 +1991,6 @@ fn test_internally_tagged_unit_enum_with_unknown_fields() { ); } -#[test] -fn test_flatten_any_after_flatten_struct() { - #[derive(PartialEq, Debug)] - struct Any; - - impl<'de> Deserialize<'de> for Any { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - struct AnyVisitor; - - impl<'de> Visitor<'de> for AnyVisitor { - type Value = Any; - - fn expecting(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { - unimplemented!() - } - - fn visit_map(self, mut map: M) -> Result - where - M: MapAccess<'de>, - { - while let Some((Any, Any)) = map.next_entry()? {} - Ok(Any) - } - } - - deserializer.deserialize_any(AnyVisitor) - } - } - - #[derive(Deserialize, PartialEq, Debug)] - struct Outer { - #[serde(flatten)] - inner: Inner, - #[serde(flatten)] - extra: Any, - } - - #[derive(Deserialize, PartialEq, Debug)] - struct Inner { - inner: i32, - } - - let s = Outer { - inner: Inner { inner: 0 }, - extra: Any, - }; - - assert_de_tokens( - &s, - &[ - Token::Map { len: None }, - Token::Str("inner"), - Token::I32(0), - Token::MapEnd, - ], - ); -} - -#[test] -fn test_alias_in_flatten_context() { - #[derive(Debug, PartialEq, Deserialize)] - struct Outer { - #[serde(flatten)] - a: AliasStruct, - b: i32, - } - - assert_de_tokens( - &Outer { - a: AliasStruct { - a1: 1, - a2: 2, - a4: 4, - }, - b: 7, - }, - &[ - Token::Struct { - name: "Outer", - len: 4, - }, - Token::Str("a1"), - Token::I32(1), - Token::Str("a2"), - Token::I32(2), - Token::Str("a5"), - Token::I32(4), - Token::Str("b"), - Token::I32(7), - Token::StructEnd, - ], - ); - - assert_de_tokens( - &Outer { - a: AliasStruct { - a1: 1, - a2: 2, - a4: 4, - }, - b: 7, - }, - &[ - Token::Struct { - name: "Outer", - len: 4, - }, - Token::Str("a1"), - Token::I32(1), - Token::Str("a2"), - Token::I32(2), - Token::Str("a6"), - Token::I32(4), - Token::Str("b"), - Token::I32(7), - Token::StructEnd, - ], - ); -} - #[test] fn test_expecting_message() { #[derive(Deserialize, PartialEq, Debug)] @@ -2970,6 +2164,660 @@ fn test_expecting_message_identifier_enum() { mod flatten { use super::*; + #[test] + fn complex() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct Outer { + y: u32, + #[serde(flatten)] + first: First, + #[serde(flatten)] + second: Second, + z: u32, + } + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct First { + a: u32, + b: bool, + c: Vec, + d: String, + e: Option, + } + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct Second { + f: u32, + } + + assert_de_tokens( + &Outer { + y: 0, + first: First { + a: 1, + b: true, + c: vec!["a".into(), "b".into()], + d: "c".into(), + e: Some(2), + }, + second: Second { f: 3 }, + z: 4, + }, + &[ + Token::Map { len: None }, + Token::Str("y"), + Token::U32(0), + Token::Str("a"), + Token::U32(1), + Token::Str("b"), + Token::Bool(true), + Token::Str("c"), + Token::Seq { len: Some(2) }, + Token::Str("a"), + Token::Str("b"), + Token::SeqEnd, + Token::Str("d"), + Token::Str("c"), + Token::Str("e"), + Token::U64(2), + Token::Str("f"), + Token::U32(3), + Token::Str("z"), + Token::U32(4), + Token::MapEnd, + ], + ); + + assert_ser_tokens( + &Outer { + y: 0, + first: First { + a: 1, + b: true, + c: vec!["a".into(), "b".into()], + d: "c".into(), + e: Some(2), + }, + second: Second { f: 3 }, + z: 4, + }, + &[ + Token::Map { len: None }, + Token::Str("y"), + Token::U32(0), + Token::Str("a"), + Token::U32(1), + Token::Str("b"), + Token::Bool(true), + Token::Str("c"), + Token::Seq { len: Some(2) }, + Token::Str("a"), + Token::Str("b"), + Token::SeqEnd, + Token::Str("d"), + Token::Str("c"), + Token::Str("e"), + Token::Some, + Token::U64(2), + Token::Str("f"), + Token::U32(3), + Token::Str("z"), + Token::U32(4), + Token::MapEnd, + ], + ); + } + + #[test] + fn map_twice() { + #[derive(Debug, PartialEq, Deserialize)] + struct Outer { + #[serde(flatten)] + first: BTreeMap, + #[serde(flatten)] + between: Inner, + #[serde(flatten)] + second: BTreeMap, + } + + #[derive(Debug, PartialEq, Deserialize)] + struct Inner { + y: String, + } + + assert_de_tokens( + &Outer { + first: { + let mut first = BTreeMap::new(); + first.insert("x".to_owned(), "X".to_owned()); + first.insert("y".to_owned(), "Y".to_owned()); + first + }, + between: Inner { y: "Y".to_owned() }, + second: { + let mut second = BTreeMap::new(); + second.insert("x".to_owned(), "X".to_owned()); + second + }, + }, + &[ + Token::Map { len: None }, + Token::Str("x"), + Token::Str("X"), + Token::Str("y"), + Token::Str("Y"), + Token::MapEnd, + ], + ); + } + + #[test] + fn unsupported_type() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct Outer { + outer: String, + #[serde(flatten)] + inner: String, + } + + assert_ser_tokens_error( + &Outer { + outer: "foo".into(), + inner: "bar".into(), + }, + &[ + Token::Map { len: None }, + Token::Str("outer"), + Token::Str("foo"), + ], + "can only flatten structs and maps (got a string)", + ); + assert_de_tokens_error::( + &[ + Token::Map { len: None }, + Token::Str("outer"), + Token::Str("foo"), + Token::Str("a"), + Token::Str("b"), + Token::MapEnd, + ], + "can only flatten structs and maps", + ); + } + + #[test] + fn unknown_field() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(deny_unknown_fields)] + struct Outer { + dummy: String, + #[serde(flatten)] + inner: Inner, + } + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct Inner { + foo: HashMap, + } + + assert_de_tokens_error::( + &[ + Token::Struct { + name: "Outer", + len: 1, + }, + Token::Str("dummy"), + Token::Str("23"), + Token::Str("foo"), + Token::Map { len: None }, + Token::Str("a"), + Token::U32(1), + Token::Str("b"), + Token::U32(2), + Token::MapEnd, + Token::Str("bar"), + Token::U32(23), + Token::StructEnd, + ], + "unknown field `bar`", + ); + } + + #[test] + fn non_string_keys() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct TestStruct { + name: String, + age: u32, + #[serde(flatten)] + mapping: HashMap, + } + + let mut mapping = HashMap::new(); + mapping.insert(0, 42); + assert_tokens( + &TestStruct { + name: "peter".into(), + age: 3, + mapping, + }, + &[ + Token::Map { len: None }, + Token::Str("name"), + Token::Str("peter"), + Token::Str("age"), + Token::U32(3), + Token::U32(0), + Token::U32(42), + Token::MapEnd, + ], + ); + } + + #[test] + fn lifetime_propagation() { + #[derive(Deserialize, Serialize, Debug, PartialEq)] + struct A { + #[serde(flatten)] + t: T, + } + + #[derive(Deserialize, Serialize, Debug, PartialEq)] + struct B<'a> { + #[serde(flatten, borrow)] + t: HashMap<&'a str, u32>, + } + + #[derive(Deserialize, Serialize, Debug, PartialEq)] + struct C<'a> { + #[serde(flatten, borrow)] + t: HashMap<&'a [u8], u32>, + } + + let mut owned_map = HashMap::new(); + owned_map.insert("x".to_string(), 42u32); + assert_tokens( + &A { t: owned_map }, + &[ + Token::Map { len: None }, + Token::Str("x"), + Token::U32(42), + Token::MapEnd, + ], + ); + + let mut borrowed_map = HashMap::new(); + borrowed_map.insert("x", 42u32); + assert_ser_tokens( + &B { + t: borrowed_map.clone(), + }, + &[ + Token::Map { len: None }, + Token::BorrowedStr("x"), + Token::U32(42), + Token::MapEnd, + ], + ); + + assert_de_tokens( + &B { t: borrowed_map }, + &[ + Token::Map { len: None }, + Token::BorrowedStr("x"), + Token::U32(42), + Token::MapEnd, + ], + ); + + let mut borrowed_map = HashMap::new(); + borrowed_map.insert(&b"x"[..], 42u32); + assert_ser_tokens( + &C { + t: borrowed_map.clone(), + }, + &[ + Token::Map { len: None }, + Token::Seq { len: Some(1) }, + Token::U8(120), + Token::SeqEnd, + Token::U32(42), + Token::MapEnd, + ], + ); + + assert_de_tokens( + &C { t: borrowed_map }, + &[ + Token::Map { len: None }, + Token::BorrowedBytes(b"x"), + Token::U32(42), + Token::MapEnd, + ], + ); + } + + // Regression test for https://github.com/serde-rs/serde/issues/1904 + #[test] + fn enum_tuple_and_struct() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + enum Outer { + Tuple(f64, i32), + Flatten { + #[serde(flatten)] + nested: Nested, + }, + } + + #[derive(Serialize, Deserialize, PartialEq, Debug)] + struct Nested { + a: i32, + b: i32, + } + + assert_tokens( + &Outer::Tuple(1.2, 3), + &[ + Token::TupleVariant { + name: "Outer", + variant: "Tuple", + len: 2, + }, + Token::F64(1.2), + Token::I32(3), + Token::TupleVariantEnd, + ], + ); + assert_tokens( + &Outer::Flatten { + nested: Nested { a: 1, b: 2 }, + }, + &[ + Token::NewtypeVariant { + name: "Outer", + variant: "Flatten", + }, + Token::Map { len: None }, + Token::Str("a"), + Token::I32(1), + Token::Str("b"), + Token::I32(2), + Token::MapEnd, + ], + ); + } + + #[test] + fn option() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + struct Outer { + #[serde(flatten)] + inner1: Option, + #[serde(flatten)] + inner2: Option, + } + + #[derive(Serialize, Deserialize, PartialEq, Debug)] + struct Inner1 { + inner1: i32, + } + + #[derive(Serialize, Deserialize, PartialEq, Debug)] + struct Inner2 { + inner2: i32, + } + + assert_tokens( + &Outer { + inner1: Some(Inner1 { inner1: 1 }), + inner2: Some(Inner2 { inner2: 2 }), + }, + &[ + Token::Map { len: None }, + Token::Str("inner1"), + Token::I32(1), + Token::Str("inner2"), + Token::I32(2), + Token::MapEnd, + ], + ); + + assert_tokens( + &Outer { + inner1: Some(Inner1 { inner1: 1 }), + inner2: None, + }, + &[ + Token::Map { len: None }, + Token::Str("inner1"), + Token::I32(1), + Token::MapEnd, + ], + ); + + assert_tokens( + &Outer { + inner1: None, + inner2: Some(Inner2 { inner2: 2 }), + }, + &[ + Token::Map { len: None }, + Token::Str("inner2"), + Token::I32(2), + Token::MapEnd, + ], + ); + + assert_tokens( + &Outer { + inner1: None, + inner2: None, + }, + &[Token::Map { len: None }, Token::MapEnd], + ); + } + + #[test] + fn ignored_any() { + #[derive(Deserialize, PartialEq, Debug)] + struct Outer { + #[serde(flatten)] + inner: IgnoredAny, + } + + assert_de_tokens( + &Outer { inner: IgnoredAny }, + &[Token::Map { len: None }, Token::MapEnd], + ); + + assert_de_tokens( + &Outer { inner: IgnoredAny }, + &[ + Token::Struct { + name: "DoNotMatter", + len: 0, + }, + Token::StructEnd, + ], + ); + } + + #[test] + fn flatten_any_after_flatten_struct() { + #[derive(PartialEq, Debug)] + struct Any; + + impl<'de> Deserialize<'de> for Any { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct AnyVisitor; + + impl<'de> Visitor<'de> for AnyVisitor { + type Value = Any; + + fn expecting(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { + unimplemented!() + } + + fn visit_map(self, mut map: M) -> Result + where + M: MapAccess<'de>, + { + while let Some((Any, Any)) = map.next_entry()? {} + Ok(Any) + } + } + + deserializer.deserialize_any(AnyVisitor) + } + } + + #[derive(Deserialize, PartialEq, Debug)] + struct Outer { + #[serde(flatten)] + inner: Inner, + #[serde(flatten)] + extra: Any, + } + + #[derive(Deserialize, PartialEq, Debug)] + struct Inner { + inner: i32, + } + + let s = Outer { + inner: Inner { inner: 0 }, + extra: Any, + }; + + assert_de_tokens( + &s, + &[ + Token::Map { len: None }, + Token::Str("inner"), + Token::I32(0), + Token::MapEnd, + ], + ); + } + + #[test] + fn alias() { + #[derive(Debug, PartialEq, Deserialize)] + struct Outer { + #[serde(flatten)] + a: AliasStruct, + b: i32, + } + + assert_de_tokens( + &Outer { + a: AliasStruct { + a1: 1, + a2: 2, + a4: 4, + }, + b: 7, + }, + &[ + Token::Struct { + name: "Outer", + len: 4, + }, + Token::Str("a1"), + Token::I32(1), + Token::Str("a2"), + Token::I32(2), + Token::Str("a5"), + Token::I32(4), + Token::Str("b"), + Token::I32(7), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &Outer { + a: AliasStruct { + a1: 1, + a2: 2, + a4: 4, + }, + b: 7, + }, + &[ + Token::Struct { + name: "Outer", + len: 4, + }, + Token::Str("a1"), + Token::I32(1), + Token::Str("a2"), + Token::I32(2), + Token::Str("a6"), + Token::I32(4), + Token::Str("b"), + Token::I32(7), + Token::StructEnd, + ], + ); + } + + mod unit { + use super::*; + + #[test] + fn unit() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct Response { + #[serde(flatten)] + data: T, + status: usize, + } + + assert_tokens( + &Response { + data: (), + status: 0, + }, + &[ + Token::Map { len: None }, + Token::Str("status"), + Token::U64(0), + Token::MapEnd, + ], + ); + } + + #[test] + fn unit_struct() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct Response { + #[serde(flatten)] + data: T, + status: usize, + } + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct Unit; + + assert_tokens( + &Response { + data: Unit, + status: 0, + }, + &[ + Token::Map { len: None }, + Token::Str("status"), + Token::U64(0), + Token::MapEnd, + ], + ); + } + } + mod enum_ { use super::*; @@ -2977,6 +2825,44 @@ mod flatten { use super::*; use std::iter::FromIterator; + #[test] + fn straightforward() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + enum Data { + A { + a: i32, + #[serde(flatten)] + flat: Flat, + }, + } + + #[derive(Serialize, Deserialize, PartialEq, Debug)] + struct Flat { + b: i32, + } + + let data = Data::A { + a: 0, + flat: Flat { b: 0 }, + }; + + assert_tokens( + &data, + &[ + Token::NewtypeVariant { + name: "Data", + variant: "A", + }, + Token::Map { len: None }, + Token::Str("a"), + Token::I32(0), + Token::Str("b"), + Token::I32(0), + Token::MapEnd, + ], + ); + } + #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Flatten { #[serde(flatten)] @@ -3101,6 +2987,52 @@ mod flatten { mod adjacently_tagged { use super::*; + #[test] + fn straightforward() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[serde(tag = "t", content = "c")] + enum Data { + A { + a: i32, + #[serde(flatten)] + flat: Flat, + }, + } + + #[derive(Serialize, Deserialize, PartialEq, Debug)] + struct Flat { + b: i32, + } + + let data = Data::A { + a: 0, + flat: Flat { b: 0 }, + }; + + assert_tokens( + &data, + &[ + Token::Struct { + name: "Data", + len: 2, + }, + Token::Str("t"), + Token::UnitVariant { + name: "Data", + variant: "A", + }, + Token::Str("c"), + Token::Map { len: None }, + Token::Str("a"), + Token::I32(0), + Token::Str("b"), + Token::I32(0), + Token::MapEnd, + Token::StructEnd, + ], + ); + } + #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Flatten { outer: u32, @@ -3191,6 +3123,43 @@ mod flatten { mod internally_tagged { use super::*; + #[test] + fn straightforward() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[serde(tag = "t")] + enum Data { + A { + a: i32, + #[serde(flatten)] + flat: Flat, + }, + } + + #[derive(Serialize, Deserialize, PartialEq, Debug)] + struct Flat { + b: i32, + } + + let data = Data::A { + a: 0, + flat: Flat { b: 0 }, + }; + + assert_tokens( + &data, + &[ + Token::Map { len: None }, + Token::Str("t"), + Token::Str("A"), + Token::Str("a"), + Token::I32(0), + Token::Str("b"), + Token::I32(0), + Token::MapEnd, + ], + ); + } + #[test] fn structs() { #[derive(Debug, PartialEq, Serialize, Deserialize)] @@ -3279,6 +3248,41 @@ mod flatten { mod untagged { use super::*; + #[test] + fn straightforward() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[serde(untagged)] + enum Data { + A { + a: i32, + #[serde(flatten)] + flat: Flat, + }, + } + + #[derive(Serialize, Deserialize, PartialEq, Debug)] + struct Flat { + b: i32, + } + + let data = Data::A { + a: 0, + flat: Flat { b: 0 }, + }; + + assert_tokens( + &data, + &[ + Token::Map { len: None }, + Token::Str("a"), + Token::I32(0), + Token::Str("b"), + Token::I32(0), + Token::MapEnd, + ], + ); + } + #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Flatten { #[serde(flatten)] From aa0654332d26ea3d217eabc78ce6956735999bb0 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 22 Apr 2023 20:36:41 +0500 Subject: [PATCH 132/258] Convert test_internally_tagged_enum into module (review this commit with "ignore whitespace changes" option on) --- test_suite/tests/test_macros.rs | 239 +++++++++++++++++--------------- 1 file changed, 129 insertions(+), 110 deletions(-) diff --git a/test_suite/tests/test_macros.rs b/test_suite/tests/test_macros.rs index 7bd7a94e7..4291841a4 100644 --- a/test_suite/tests/test_macros.rs +++ b/test_suite/tests/test_macros.rs @@ -679,8 +679,9 @@ fn test_untagged_enum() { ); } -#[test] -fn test_internally_tagged_enum() { +mod internally_tagged_enum { + use super::*; + #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Newtype(BTreeMap); @@ -699,119 +700,137 @@ fn test_internally_tagged_enum() { E(Struct), } - assert_tokens( - &InternallyTagged::A { a: 1 }, - &[ - Token::Struct { - name: "InternallyTagged", - len: 2, - }, - Token::Str("type"), - Token::Str("A"), - Token::Str("a"), - Token::U8(1), - Token::StructEnd, - ], - ); - - assert_de_tokens( - &InternallyTagged::A { a: 1 }, - &[ - Token::Seq { len: Some(2) }, - Token::Str("A"), - Token::U8(1), - Token::SeqEnd, - ], - ); - - assert_tokens( - &InternallyTagged::B, - &[ - Token::Struct { - name: "InternallyTagged", - len: 1, - }, - Token::Str("type"), - Token::Str("B"), - Token::StructEnd, - ], - ); - - assert_de_tokens( - &InternallyTagged::B, - &[Token::Seq { len: Some(1) }, Token::Str("B"), Token::SeqEnd], - ); - - assert_tokens( - &InternallyTagged::C(BTreeMap::new()), - &[ - Token::Map { len: Some(1) }, - Token::Str("type"), - Token::Str("C"), - Token::MapEnd, - ], - ); - - assert_de_tokens_error::( - &[ - Token::Seq { len: Some(2) }, - Token::Str("C"), - Token::Map { len: Some(0) }, - Token::MapEnd, - Token::SeqEnd, - ], - "invalid type: sequence, expected a map", - ); + #[test] + fn struct_() { + assert_tokens( + &InternallyTagged::A { a: 1 }, + &[ + Token::Struct { + name: "InternallyTagged", + len: 2, + }, + Token::Str("type"), + Token::Str("A"), + Token::Str("a"), + Token::U8(1), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &InternallyTagged::A { a: 1 }, + &[ + Token::Seq { len: Some(2) }, + Token::Str("A"), + Token::U8(1), + Token::SeqEnd, + ], + ); + } - assert_tokens( - &InternallyTagged::D(Newtype(BTreeMap::new())), - &[ - Token::Map { len: Some(1) }, - Token::Str("type"), - Token::Str("D"), - Token::MapEnd, - ], - ); + #[test] + fn unit() { + assert_tokens( + &InternallyTagged::B, + &[ + Token::Struct { + name: "InternallyTagged", + len: 1, + }, + Token::Str("type"), + Token::Str("B"), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &InternallyTagged::B, + &[Token::Seq { len: Some(1) }, Token::Str("B"), Token::SeqEnd], + ); + } - assert_tokens( - &InternallyTagged::E(Struct { f: 6 }), - &[ - Token::Struct { - name: "Struct", - len: 2, - }, - Token::Str("type"), - Token::Str("E"), - Token::Str("f"), - Token::U8(6), - Token::StructEnd, - ], - ); + #[test] + fn newtype_map() { + assert_tokens( + &InternallyTagged::C(BTreeMap::new()), + &[ + Token::Map { len: Some(1) }, + Token::Str("type"), + Token::Str("C"), + Token::MapEnd, + ], + ); + + assert_de_tokens_error::( + &[ + Token::Seq { len: Some(2) }, + Token::Str("C"), + Token::Map { len: Some(0) }, + Token::MapEnd, + Token::SeqEnd, + ], + "invalid type: sequence, expected a map", + ); + } - assert_de_tokens( - &InternallyTagged::E(Struct { f: 6 }), - &[ - Token::Seq { len: Some(2) }, - Token::Str("E"), - Token::U8(6), - Token::SeqEnd, - ], - ); + #[test] + fn newtype_newtype() { + assert_tokens( + &InternallyTagged::D(Newtype(BTreeMap::new())), + &[ + Token::Map { len: Some(1) }, + Token::Str("type"), + Token::Str("D"), + Token::MapEnd, + ], + ); + } - assert_de_tokens_error::( - &[Token::Map { len: Some(0) }, Token::MapEnd], - "missing field `type`", - ); + #[test] + fn newtype_struct() { + assert_tokens( + &InternallyTagged::E(Struct { f: 6 }), + &[ + Token::Struct { + name: "Struct", + len: 2, + }, + Token::Str("type"), + Token::Str("E"), + Token::Str("f"), + Token::U8(6), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &InternallyTagged::E(Struct { f: 6 }), + &[ + Token::Seq { len: Some(2) }, + Token::Str("E"), + Token::U8(6), + Token::SeqEnd, + ], + ); + } - assert_de_tokens_error::( - &[ - Token::Map { len: Some(1) }, - Token::Str("type"), - Token::Str("Z"), - Token::MapEnd, - ], - "unknown variant `Z`, expected one of `A`, `B`, `C`, `D`, `E`", - ); + #[test] + fn wrong_tag() { + assert_de_tokens_error::( + &[Token::Map { len: Some(0) }, Token::MapEnd], + "missing field `type`", + ); + + assert_de_tokens_error::( + &[ + Token::Map { len: Some(1) }, + Token::Str("type"), + Token::Str("Z"), + Token::MapEnd, + ], + "unknown variant `Z`, expected one of `A`, `B`, `C`, `D`, `E`", + ); + } } #[test] From 99f905403b83013d998855224c4235007cbb96af Mon Sep 17 00:00:00 2001 From: Mingun Date: Thu, 27 Jul 2023 23:42:58 +0500 Subject: [PATCH 133/258] Move all internally tagged enum tests of `test_macros` into a dedicated module Moved: - test_internally_tagged_enum_with_untagged_variant => untagged_variant - test_internally_tagged_bytes => string_and_bytes mod - test_internally_tagged_struct_variant_containing_unit_variant => struct_variant_containing_unit_variant - test_internally_tagged_borrow => borrow - test_enum_in_internally_tagged_enum => newtype_variant_containing_externally_tagged_enum - test_internally_tagged_newtype_variant_containing_unit_struct => newtype_variant_containing_unit_struct (review this commit with "ignore whitespace changes" option on) --- test_suite/tests/test_macros.rs | 934 ++++++++++++++++---------------- 1 file changed, 475 insertions(+), 459 deletions(-) diff --git a/test_suite/tests/test_macros.rs b/test_suite/tests/test_macros.rs index 4291841a4..84f2f4441 100644 --- a/test_suite/tests/test_macros.rs +++ b/test_suite/tests/test_macros.rs @@ -831,350 +831,510 @@ mod internally_tagged_enum { "unknown variant `Z`, expected one of `A`, `B`, `C`, `D`, `E`", ); } -} - -#[test] -fn test_internally_tagged_enum_with_untagged_variant() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "kind")] - enum InternallyTagged { - Tagged { - a: u8, - }, - #[serde(untagged)] - Untagged { - kind: String, - b: u8, - }, - } - - assert_de_tokens( - &InternallyTagged::Tagged { a: 1 }, - &[ - Token::Map { len: Some(2) }, - Token::Str("kind"), - Token::Str("Tagged"), - Token::Str("a"), - Token::U8(1), - Token::MapEnd, - ], - ); - assert_tokens( - &InternallyTagged::Tagged { a: 1 }, - &[ - Token::Struct { - name: "InternallyTagged", - len: 2, + #[test] + fn untagged_variant() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(tag = "kind")] + enum InternallyTagged { + Tagged { + a: u8, }, - Token::Str("kind"), - Token::Str("Tagged"), - Token::Str("a"), - Token::U8(1), - Token::StructEnd, - ], - ); - - assert_de_tokens( - &InternallyTagged::Untagged { - kind: "Foo".to_owned(), - b: 2, - }, - &[ - Token::Map { len: Some(2) }, - Token::Str("kind"), - Token::Str("Foo"), - Token::Str("b"), - Token::U8(2), - Token::MapEnd, - ], - ); - - assert_tokens( - &InternallyTagged::Untagged { - kind: "Foo".to_owned(), - b: 2, - }, - &[ - Token::Struct { - name: "InternallyTagged", - len: 2, + #[serde(untagged)] + Untagged { + kind: String, + b: u8, }, - Token::Str("kind"), - Token::Str("Foo"), - Token::Str("b"), - Token::U8(2), - Token::StructEnd, - ], - ); + } - assert_tokens( - &InternallyTagged::Untagged { - kind: "Tagged".to_owned(), - b: 2, - }, - &[ - Token::Struct { - name: "InternallyTagged", - len: 2, - }, - Token::Str("kind"), - Token::Str("Tagged"), - Token::Str("b"), - Token::U8(2), - Token::StructEnd, - ], - ); -} + assert_de_tokens( + &InternallyTagged::Tagged { a: 1 }, + &[ + Token::Map { len: Some(2) }, + Token::Str("kind"), + Token::Str("Tagged"), + Token::Str("a"), + Token::U8(1), + Token::MapEnd, + ], + ); -#[test] -fn test_internally_tagged_bytes() { - #[derive(Debug, PartialEq, Deserialize)] - #[serde(tag = "type")] - enum InternallyTagged { - String { - string: String, - }, - Bytes { - #[serde(with = "bytes")] - bytes: Vec, - }, - } + assert_tokens( + &InternallyTagged::Tagged { a: 1 }, + &[ + Token::Struct { + name: "InternallyTagged", + len: 2, + }, + Token::Str("kind"), + Token::Str("Tagged"), + Token::Str("a"), + Token::U8(1), + Token::StructEnd, + ], + ); - assert_de_tokens( - &InternallyTagged::String { - string: "\0".to_owned(), - }, - &[ - Token::Struct { - name: "String", - len: 2, + assert_de_tokens( + &InternallyTagged::Untagged { + kind: "Foo".to_owned(), + b: 2, }, - Token::Str("type"), - Token::Str("String"), - Token::Str("string"), - Token::Str("\0"), - Token::StructEnd, - ], - ); + &[ + Token::Map { len: Some(2) }, + Token::Str("kind"), + Token::Str("Foo"), + Token::Str("b"), + Token::U8(2), + Token::MapEnd, + ], + ); - assert_de_tokens( - &InternallyTagged::String { - string: "\0".to_owned(), - }, - &[ - Token::Struct { - name: "String", - len: 2, + assert_tokens( + &InternallyTagged::Untagged { + kind: "Foo".to_owned(), + b: 2, }, - Token::Str("type"), - Token::Str("String"), - Token::Str("string"), - Token::String("\0"), - Token::StructEnd, - ], - ); + &[ + Token::Struct { + name: "InternallyTagged", + len: 2, + }, + Token::Str("kind"), + Token::Str("Foo"), + Token::Str("b"), + Token::U8(2), + Token::StructEnd, + ], + ); - assert_de_tokens( - &InternallyTagged::String { - string: "\0".to_owned(), - }, - &[ - Token::Struct { - name: "String", - len: 2, + assert_tokens( + &InternallyTagged::Untagged { + kind: "Tagged".to_owned(), + b: 2, }, - Token::Str("type"), - Token::Str("String"), - Token::Str("string"), - Token::Bytes(b"\0"), - Token::StructEnd, - ], - ); + &[ + Token::Struct { + name: "InternallyTagged", + len: 2, + }, + Token::Str("kind"), + Token::Str("Tagged"), + Token::Str("b"), + Token::U8(2), + Token::StructEnd, + ], + ); + } - assert_de_tokens( - &InternallyTagged::String { - string: "\0".to_owned(), - }, - &[ - Token::Struct { - name: "String", - len: 2, - }, - Token::Str("type"), - Token::Str("String"), - Token::Str("string"), - Token::ByteBuf(b"\0"), - Token::StructEnd, - ], - ); + mod string_and_bytes { + use super::*; - assert_de_tokens( - &InternallyTagged::Bytes { bytes: vec![0] }, - &[ - Token::Struct { - name: "Bytes", - len: 2, + #[derive(Debug, PartialEq, Deserialize)] + #[serde(tag = "type")] + enum InternallyTagged { + String { + string: String, }, - Token::Str("type"), - Token::Str("Bytes"), - Token::Str("bytes"), - Token::Str("\0"), - Token::StructEnd, - ], - ); - - assert_de_tokens( - &InternallyTagged::Bytes { bytes: vec![0] }, - &[ - Token::Struct { - name: "Bytes", - len: 2, + Bytes { + #[serde(with = "bytes")] + bytes: Vec, }, - Token::Str("type"), - Token::Str("Bytes"), - Token::Str("bytes"), - Token::String("\0"), - Token::StructEnd, - ], - ); + } - assert_de_tokens( - &InternallyTagged::Bytes { bytes: vec![0] }, - &[ - Token::Struct { - name: "Bytes", - len: 2, - }, - Token::Str("type"), - Token::Str("Bytes"), - Token::Str("bytes"), - Token::Bytes(b"\0"), - Token::StructEnd, - ], - ); + #[test] + fn string_from_string() { + assert_de_tokens( + &InternallyTagged::String { + string: "\0".to_owned(), + }, + &[ + Token::Struct { + name: "String", + len: 2, + }, + Token::Str("type"), + Token::Str("String"), + Token::Str("string"), + Token::Str("\0"), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &InternallyTagged::String { + string: "\0".to_owned(), + }, + &[ + Token::Struct { + name: "String", + len: 2, + }, + Token::Str("type"), + Token::Str("String"), + Token::Str("string"), + Token::String("\0"), + Token::StructEnd, + ], + ); + } + + #[test] + fn string_from_bytes() { + assert_de_tokens( + &InternallyTagged::String { + string: "\0".to_owned(), + }, + &[ + Token::Struct { + name: "String", + len: 2, + }, + Token::Str("type"), + Token::Str("String"), + Token::Str("string"), + Token::Bytes(b"\0"), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &InternallyTagged::String { + string: "\0".to_owned(), + }, + &[ + Token::Struct { + name: "String", + len: 2, + }, + Token::Str("type"), + Token::Str("String"), + Token::Str("string"), + Token::ByteBuf(b"\0"), + Token::StructEnd, + ], + ); + } + + #[test] + fn bytes_from_string() { + assert_de_tokens( + &InternallyTagged::Bytes { bytes: vec![0] }, + &[ + Token::Struct { + name: "Bytes", + len: 2, + }, + Token::Str("type"), + Token::Str("Bytes"), + Token::Str("bytes"), + Token::Str("\0"), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &InternallyTagged::Bytes { bytes: vec![0] }, + &[ + Token::Struct { + name: "Bytes", + len: 2, + }, + Token::Str("type"), + Token::Str("Bytes"), + Token::Str("bytes"), + Token::String("\0"), + Token::StructEnd, + ], + ); + } + + #[test] + fn bytes_from_bytes() { + assert_de_tokens( + &InternallyTagged::Bytes { bytes: vec![0] }, + &[ + Token::Struct { + name: "Bytes", + len: 2, + }, + Token::Str("type"), + Token::Str("Bytes"), + Token::Str("bytes"), + Token::Bytes(b"\0"), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &InternallyTagged::Bytes { bytes: vec![0] }, + &[ + Token::Struct { + name: "Bytes", + len: 2, + }, + Token::Str("type"), + Token::Str("Bytes"), + Token::Str("bytes"), + Token::ByteBuf(b"\0"), + Token::StructEnd, + ], + ); + } + + #[test] + fn bytes_from_seq() { + assert_de_tokens( + &InternallyTagged::Bytes { bytes: vec![0] }, + &[ + Token::Struct { + name: "Bytes", + len: 2, + }, + Token::Str("type"), + Token::Str("Bytes"), + Token::Str("bytes"), + Token::Seq { len: Some(1) }, + Token::U8(0), + Token::SeqEnd, + Token::StructEnd, + ], + ); + } + } - assert_de_tokens( - &InternallyTagged::Bytes { bytes: vec![0] }, - &[ - Token::Struct { - name: "Bytes", - len: 2, - }, - Token::Str("type"), - Token::Str("Bytes"), - Token::Str("bytes"), - Token::ByteBuf(b"\0"), - Token::StructEnd, - ], - ); + #[test] + fn struct_variant_containing_unit_variant() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + pub enum Level { + Info, + } + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(tag = "action")] + pub enum Message { + Log { level: Level }, + } - assert_de_tokens( - &InternallyTagged::Bytes { bytes: vec![0] }, - &[ - Token::Struct { - name: "Bytes", - len: 2, - }, - Token::Str("type"), - Token::Str("Bytes"), - Token::Str("bytes"), - Token::Seq { len: Some(1) }, - Token::U8(0), - Token::SeqEnd, - Token::StructEnd, - ], - ); -} + assert_de_tokens( + &Level::Info, + &[ + Token::Enum { name: "Level" }, + Token::BorrowedStr("Info"), + Token::Unit, + ], + ); -#[test] -fn test_internally_tagged_struct_variant_containing_unit_variant() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - pub enum Level { - Info, + assert_de_tokens( + &Message::Log { level: Level::Info }, + &[ + Token::Struct { + name: "Message", + len: 2, + }, + Token::Str("action"), + Token::Str("Log"), + Token::Str("level"), + Token::Enum { name: "Level" }, + Token::BorrowedStr("Info"), + Token::Unit, + 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::Enum { name: "Level" }, + Token::BorrowedStr("Info"), + Token::Unit, + Token::MapEnd, + ], + ); + + assert_de_tokens( + &Message::Log { level: Level::Info }, + &[ + Token::Seq { len: Some(2) }, + Token::Str("Log"), + Token::Enum { name: "Level" }, + Token::BorrowedStr("Info"), + Token::Unit, + Token::SeqEnd, + ], + ); } - #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "action")] - pub enum Message { - Log { level: Level }, + #[test] + fn borrow() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(tag = "type")] + enum Input<'a> { + Package { name: &'a str }, + } + + assert_tokens( + &Input::Package { name: "borrowed" }, + &[ + Token::Struct { + name: "Input", + len: 2, + }, + Token::BorrowedStr("type"), + Token::BorrowedStr("Package"), + Token::BorrowedStr("name"), + Token::BorrowedStr("borrowed"), + Token::StructEnd, + ], + ); } - assert_de_tokens( - &Level::Info, - &[ - Token::Enum { name: "Level" }, - Token::BorrowedStr("Info"), - Token::Unit, - ], - ); + #[test] + fn newtype_variant_containing_externally_tagged_enum() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(tag = "type")] + enum Outer { + Inner(Inner), + } + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + enum Inner { + Unit, + Newtype(u8), + Tuple(u8, u8), + Struct { f: u8 }, + } - assert_de_tokens( - &Message::Log { level: Level::Info }, - &[ - Token::Struct { - name: "Message", - len: 2, - }, - Token::Str("action"), - Token::Str("Log"), - Token::Str("level"), - Token::Enum { name: "Level" }, - Token::BorrowedStr("Info"), - Token::Unit, - Token::StructEnd, - ], - ); + assert_tokens( + &Outer::Inner(Inner::Unit), + &[ + Token::Map { len: Some(2) }, + Token::Str("type"), + Token::Str("Inner"), + Token::Str("Unit"), + Token::Unit, + Token::MapEnd, + ], + ); - assert_de_tokens( - &Message::Log { level: Level::Info }, - &[ - Token::Map { len: Some(2) }, - Token::Str("action"), - Token::Str("Log"), - Token::Str("level"), - Token::Enum { name: "Level" }, - Token::BorrowedStr("Info"), - Token::Unit, - Token::MapEnd, - ], - ); + assert_tokens( + &Outer::Inner(Inner::Newtype(1)), + &[ + Token::Map { len: Some(2) }, + Token::Str("type"), + Token::Str("Inner"), + Token::Str("Newtype"), + Token::U8(1), + Token::MapEnd, + ], + ); - assert_de_tokens( - &Message::Log { level: Level::Info }, - &[ - Token::Seq { len: Some(2) }, - Token::Str("Log"), - Token::Enum { name: "Level" }, - Token::BorrowedStr("Info"), - Token::Unit, - Token::SeqEnd, - ], - ); -} + // Reaches crate::private::de::content::VariantDeserializer::tuple_variant + // Content::Seq case + // via ContentDeserializer::deserialize_enum + assert_tokens( + &Outer::Inner(Inner::Tuple(1, 1)), + &[ + Token::Map { len: Some(2) }, + Token::Str("type"), + Token::Str("Inner"), + Token::Str("Tuple"), + Token::TupleStruct { + name: "Tuple", + len: 2, + }, + Token::U8(1), + Token::U8(1), + Token::TupleStructEnd, + Token::MapEnd, + ], + ); -#[test] -fn test_internally_tagged_borrow() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "type")] - pub enum Input<'a> { - Package { name: &'a str }, + // Reaches crate::private::de::content::VariantDeserializer::struct_variant + // Content::Map case + // via ContentDeserializer::deserialize_enum + assert_tokens( + &Outer::Inner(Inner::Struct { f: 1 }), + &[ + Token::Map { len: Some(2) }, + Token::Str("type"), + Token::Str("Inner"), + Token::Str("Struct"), + Token::Struct { + name: "Struct", + len: 1, + }, + Token::Str("f"), + Token::U8(1), + Token::StructEnd, + Token::MapEnd, + ], + ); + + // Reaches crate::private::de::content::VariantDeserializer::struct_variant + // Content::Seq case + // via ContentDeserializer::deserialize_enum + assert_de_tokens( + &Outer::Inner(Inner::Struct { f: 1 }), + &[ + Token::Map { len: Some(2) }, + Token::Str("type"), + Token::Str("Inner"), + Token::Str("Struct"), + Token::Seq { len: Some(1) }, + Token::U8(1), // f + Token::SeqEnd, + Token::MapEnd, + ], + ); } - assert_tokens( - &Input::Package { name: "borrowed" }, - &[ - Token::Struct { - name: "Input", - len: 2, - }, - Token::BorrowedStr("type"), - Token::BorrowedStr("Package"), - Token::BorrowedStr("name"), - Token::BorrowedStr("borrowed"), - Token::StructEnd, - ], - ); + #[test] + fn newtype_variant_containing_unit_struct() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct Info; + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(tag = "topic")] + enum Message { + Info(Info), + } + + assert_tokens( + &Message::Info(Info), + &[ + Token::Map { len: Some(1) }, + Token::Str("topic"), + Token::Str("Info"), + 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, + ], + ); + } } #[test] @@ -1571,106 +1731,6 @@ fn test_adjacently_tagged_enum_deny_unknown_fields() { ); } -#[test] -fn test_enum_in_internally_tagged_enum() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "type")] - enum Outer { - Inner(Inner), - } - - #[derive(Debug, PartialEq, Serialize, Deserialize)] - enum Inner { - Unit, - Newtype(u8), - Tuple(u8, u8), - Struct { f: u8 }, - } - - assert_tokens( - &Outer::Inner(Inner::Unit), - &[ - Token::Map { len: Some(2) }, - Token::Str("type"), - Token::Str("Inner"), - Token::Str("Unit"), - Token::Unit, - Token::MapEnd, - ], - ); - - assert_tokens( - &Outer::Inner(Inner::Newtype(1)), - &[ - Token::Map { len: Some(2) }, - Token::Str("type"), - Token::Str("Inner"), - Token::Str("Newtype"), - Token::U8(1), - Token::MapEnd, - ], - ); - - // Reaches crate::private::de::content::VariantDeserializer::tuple_variant - // Content::Seq case - // via ContentDeserializer::deserialize_enum - assert_tokens( - &Outer::Inner(Inner::Tuple(1, 1)), - &[ - Token::Map { len: Some(2) }, - Token::Str("type"), - Token::Str("Inner"), - Token::Str("Tuple"), - Token::TupleStruct { - name: "Tuple", - len: 2, - }, - Token::U8(1), - Token::U8(1), - Token::TupleStructEnd, - Token::MapEnd, - ], - ); - - // Reaches crate::private::de::content::VariantDeserializer::struct_variant - // Content::Map case - // via ContentDeserializer::deserialize_enum - assert_tokens( - &Outer::Inner(Inner::Struct { f: 1 }), - &[ - Token::Map { len: Some(2) }, - Token::Str("type"), - Token::Str("Inner"), - Token::Str("Struct"), - Token::Struct { - name: "Struct", - len: 1, - }, - Token::Str("f"), - Token::U8(1), - Token::StructEnd, - Token::MapEnd, - ], - ); - - // Reaches crate::private::de::content::VariantDeserializer::struct_variant - // Content::Seq case - // via ContentDeserializer::deserialize_enum - assert_de_tokens( - &Outer::Inner(Inner::Struct { f: 1 }), - &[ - Token::Map { len: Some(2) }, - Token::Str("type"), - Token::Str("Inner"), - Token::Str("Struct"), - Token::Seq { len: Some(1) }, - Token::U8(1), // f - Token::SeqEnd, - Token::MapEnd, - ], - ); -} - #[test] fn test_internally_tagged_struct() { #[derive(Debug, PartialEq, Serialize, Deserialize)] @@ -2205,50 +2265,6 @@ fn test_untagged_newtype_variant_containing_unit_struct_not_map() { ); } -#[test] -fn test_internally_tagged_newtype_variant_containing_unit_struct() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - struct Info; - - #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "topic")] - enum Message { - Info(Info), - } - - assert_tokens( - &Message::Info(Info), - &[ - Token::Map { len: Some(1) }, - Token::Str("topic"), - Token::Str("Info"), - 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, - ], - ); -} - #[test] fn test_packed_struct_can_derive_serialize() { #[derive(Copy, Clone, Serialize)] From da0ed4021df00153e86343ea0db710685f99eb28 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 22 Apr 2023 20:51:00 +0500 Subject: [PATCH 134/258] Give meaningful names to enum variants --- test_suite/tests/test_macros.rs | 50 ++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/test_suite/tests/test_macros.rs b/test_suite/tests/test_macros.rs index 84f2f4441..64f0875d2 100644 --- a/test_suite/tests/test_macros.rs +++ b/test_suite/tests/test_macros.rs @@ -693,24 +693,24 @@ mod internally_tagged_enum { #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "type")] enum InternallyTagged { - A { a: u8 }, - B, - C(BTreeMap), - D(Newtype), - E(Struct), + Struct { a: u8 }, + Unit, + NewtypeMap(BTreeMap), + NewtypeNewtype(Newtype), + NewtypeStruct(Struct), } #[test] fn struct_() { assert_tokens( - &InternallyTagged::A { a: 1 }, + &InternallyTagged::Struct { a: 1 }, &[ Token::Struct { name: "InternallyTagged", len: 2, }, Token::Str("type"), - Token::Str("A"), + Token::Str("Struct"), Token::Str("a"), Token::U8(1), Token::StructEnd, @@ -718,10 +718,10 @@ mod internally_tagged_enum { ); assert_de_tokens( - &InternallyTagged::A { a: 1 }, + &InternallyTagged::Struct { a: 1 }, &[ Token::Seq { len: Some(2) }, - Token::Str("A"), + Token::Str("Struct"), Token::U8(1), Token::SeqEnd, ], @@ -731,32 +731,36 @@ mod internally_tagged_enum { #[test] fn unit() { assert_tokens( - &InternallyTagged::B, + &InternallyTagged::Unit, &[ Token::Struct { name: "InternallyTagged", len: 1, }, Token::Str("type"), - Token::Str("B"), + Token::Str("Unit"), Token::StructEnd, ], ); assert_de_tokens( - &InternallyTagged::B, - &[Token::Seq { len: Some(1) }, Token::Str("B"), Token::SeqEnd], + &InternallyTagged::Unit, + &[ + Token::Seq { len: Some(1) }, + Token::Str("Unit"), + Token::SeqEnd, + ], ); } #[test] fn newtype_map() { assert_tokens( - &InternallyTagged::C(BTreeMap::new()), + &InternallyTagged::NewtypeMap(BTreeMap::new()), &[ Token::Map { len: Some(1) }, Token::Str("type"), - Token::Str("C"), + Token::Str("NewtypeMap"), Token::MapEnd, ], ); @@ -764,7 +768,7 @@ mod internally_tagged_enum { assert_de_tokens_error::( &[ Token::Seq { len: Some(2) }, - Token::Str("C"), + Token::Str("NewtypeMap"), Token::Map { len: Some(0) }, Token::MapEnd, Token::SeqEnd, @@ -776,11 +780,11 @@ mod internally_tagged_enum { #[test] fn newtype_newtype() { assert_tokens( - &InternallyTagged::D(Newtype(BTreeMap::new())), + &InternallyTagged::NewtypeNewtype(Newtype(BTreeMap::new())), &[ Token::Map { len: Some(1) }, Token::Str("type"), - Token::Str("D"), + Token::Str("NewtypeNewtype"), Token::MapEnd, ], ); @@ -789,14 +793,14 @@ mod internally_tagged_enum { #[test] fn newtype_struct() { assert_tokens( - &InternallyTagged::E(Struct { f: 6 }), + &InternallyTagged::NewtypeStruct(Struct { f: 6 }), &[ Token::Struct { name: "Struct", len: 2, }, Token::Str("type"), - Token::Str("E"), + Token::Str("NewtypeStruct"), Token::Str("f"), Token::U8(6), Token::StructEnd, @@ -804,10 +808,10 @@ mod internally_tagged_enum { ); assert_de_tokens( - &InternallyTagged::E(Struct { f: 6 }), + &InternallyTagged::NewtypeStruct(Struct { f: 6 }), &[ Token::Seq { len: Some(2) }, - Token::Str("E"), + Token::Str("NewtypeStruct"), Token::U8(6), Token::SeqEnd, ], @@ -828,7 +832,7 @@ mod internally_tagged_enum { Token::Str("Z"), Token::MapEnd, ], - "unknown variant `Z`, expected one of `A`, `B`, `C`, `D`, `E`", + "unknown variant `Z`, expected one of `Struct`, `Unit`, `NewtypeMap`, `NewtypeNewtype`, `NewtypeStruct`", ); } From 8c60f5aea7238bf21a6dc82aa497e8c49db0a0cc Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 22 Apr 2023 20:54:00 +0500 Subject: [PATCH 135/258] Reorder enum variants and tests to canonical order (Unit, Newtype, Tuple, Struct) --- test_suite/tests/test_macros.rs | 86 ++++++++++++++++----------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/test_suite/tests/test_macros.rs b/test_suite/tests/test_macros.rs index 64f0875d2..9404c3835 100644 --- a/test_suite/tests/test_macros.rs +++ b/test_suite/tests/test_macros.rs @@ -693,62 +693,47 @@ mod internally_tagged_enum { #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "type")] enum InternallyTagged { - Struct { a: u8 }, Unit, - NewtypeMap(BTreeMap), NewtypeNewtype(Newtype), + NewtypeMap(BTreeMap), NewtypeStruct(Struct), + Struct { a: u8 }, } #[test] - fn struct_() { + fn unit() { assert_tokens( - &InternallyTagged::Struct { a: 1 }, + &InternallyTagged::Unit, &[ Token::Struct { name: "InternallyTagged", - len: 2, + len: 1, }, Token::Str("type"), - Token::Str("Struct"), - Token::Str("a"), - Token::U8(1), + Token::Str("Unit"), Token::StructEnd, ], ); assert_de_tokens( - &InternallyTagged::Struct { a: 1 }, + &InternallyTagged::Unit, &[ - Token::Seq { len: Some(2) }, - Token::Str("Struct"), - Token::U8(1), + Token::Seq { len: Some(1) }, + Token::Str("Unit"), Token::SeqEnd, ], ); } #[test] - fn unit() { + fn newtype_newtype() { assert_tokens( - &InternallyTagged::Unit, + &InternallyTagged::NewtypeNewtype(Newtype(BTreeMap::new())), &[ - Token::Struct { - name: "InternallyTagged", - len: 1, - }, + Token::Map { len: Some(1) }, Token::Str("type"), - Token::Str("Unit"), - Token::StructEnd, - ], - ); - - assert_de_tokens( - &InternallyTagged::Unit, - &[ - Token::Seq { len: Some(1) }, - Token::Str("Unit"), - Token::SeqEnd, + Token::Str("NewtypeNewtype"), + Token::MapEnd, ], ); } @@ -777,19 +762,6 @@ mod internally_tagged_enum { ); } - #[test] - fn newtype_newtype() { - assert_tokens( - &InternallyTagged::NewtypeNewtype(Newtype(BTreeMap::new())), - &[ - Token::Map { len: Some(1) }, - Token::Str("type"), - Token::Str("NewtypeNewtype"), - Token::MapEnd, - ], - ); - } - #[test] fn newtype_struct() { assert_tokens( @@ -818,6 +790,34 @@ mod internally_tagged_enum { ); } + #[test] + fn struct_() { + assert_tokens( + &InternallyTagged::Struct { a: 1 }, + &[ + Token::Struct { + name: "InternallyTagged", + len: 2, + }, + Token::Str("type"), + Token::Str("Struct"), + Token::Str("a"), + Token::U8(1), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &InternallyTagged::Struct { a: 1 }, + &[ + Token::Seq { len: Some(2) }, + Token::Str("Struct"), + Token::U8(1), + Token::SeqEnd, + ], + ); + } + #[test] fn wrong_tag() { assert_de_tokens_error::( @@ -832,7 +832,7 @@ mod internally_tagged_enum { Token::Str("Z"), Token::MapEnd, ], - "unknown variant `Z`, expected one of `Struct`, `Unit`, `NewtypeMap`, `NewtypeNewtype`, `NewtypeStruct`", + "unknown variant `Z`, expected one of `Unit`, `NewtypeNewtype`, `NewtypeMap`, `NewtypeStruct`, `Struct`", ); } From 0939214c514086169e9bd3b8fc09b60ff3315e51 Mon Sep 17 00:00:00 2001 From: Mingun Date: Fri, 28 Jul 2023 00:30:15 +0500 Subject: [PATCH 136/258] Move internally tagged enum tests into a dedicated file Ctrl+X, Ctrl+V --- .../tests/test_enum_internally_tagged.rs | 671 ++++++++++++++++++ test_suite/tests/test_macros.rs | 662 ----------------- 2 files changed, 671 insertions(+), 662 deletions(-) create mode 100644 test_suite/tests/test_enum_internally_tagged.rs diff --git a/test_suite/tests/test_enum_internally_tagged.rs b/test_suite/tests/test_enum_internally_tagged.rs new file mode 100644 index 000000000..8c573a9e3 --- /dev/null +++ b/test_suite/tests/test_enum_internally_tagged.rs @@ -0,0 +1,671 @@ +#![deny(trivial_numeric_casts)] +#![allow( + clippy::derive_partial_eq_without_eq, + clippy::enum_variant_names, + clippy::redundant_field_names, + clippy::too_many_lines +)] + +mod bytes; + +use serde_derive::{Deserialize, Serialize}; +use serde_test::{assert_de_tokens, assert_de_tokens_error, assert_tokens, Token}; +use std::collections::BTreeMap; + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +struct Newtype(BTreeMap); + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +struct Struct { + f: u8, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(tag = "type")] +enum InternallyTagged { + Unit, + NewtypeNewtype(Newtype), + NewtypeMap(BTreeMap), + NewtypeStruct(Struct), + Struct { a: u8 }, +} + +#[test] +fn unit() { + assert_tokens( + &InternallyTagged::Unit, + &[ + Token::Struct { + name: "InternallyTagged", + len: 1, + }, + Token::Str("type"), + Token::Str("Unit"), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &InternallyTagged::Unit, + &[ + Token::Seq { len: Some(1) }, + Token::Str("Unit"), + Token::SeqEnd, + ], + ); +} + +#[test] +fn newtype_newtype() { + assert_tokens( + &InternallyTagged::NewtypeNewtype(Newtype(BTreeMap::new())), + &[ + Token::Map { len: Some(1) }, + Token::Str("type"), + Token::Str("NewtypeNewtype"), + Token::MapEnd, + ], + ); +} + +#[test] +fn newtype_map() { + assert_tokens( + &InternallyTagged::NewtypeMap(BTreeMap::new()), + &[ + Token::Map { len: Some(1) }, + Token::Str("type"), + Token::Str("NewtypeMap"), + Token::MapEnd, + ], + ); + + assert_de_tokens_error::( + &[ + Token::Seq { len: Some(2) }, + Token::Str("NewtypeMap"), + Token::Map { len: Some(0) }, + Token::MapEnd, + Token::SeqEnd, + ], + "invalid type: sequence, expected a map", + ); +} + +#[test] +fn newtype_struct() { + assert_tokens( + &InternallyTagged::NewtypeStruct(Struct { f: 6 }), + &[ + Token::Struct { + name: "Struct", + len: 2, + }, + Token::Str("type"), + Token::Str("NewtypeStruct"), + Token::Str("f"), + Token::U8(6), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &InternallyTagged::NewtypeStruct(Struct { f: 6 }), + &[ + Token::Seq { len: Some(2) }, + Token::Str("NewtypeStruct"), + Token::U8(6), + Token::SeqEnd, + ], + ); +} + +#[test] +fn struct_() { + assert_tokens( + &InternallyTagged::Struct { a: 1 }, + &[ + Token::Struct { + name: "InternallyTagged", + len: 2, + }, + Token::Str("type"), + Token::Str("Struct"), + Token::Str("a"), + Token::U8(1), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &InternallyTagged::Struct { a: 1 }, + &[ + Token::Seq { len: Some(2) }, + Token::Str("Struct"), + Token::U8(1), + Token::SeqEnd, + ], + ); +} + +#[test] +fn wrong_tag() { + assert_de_tokens_error::( + &[Token::Map { len: Some(0) }, Token::MapEnd], + "missing field `type`", + ); + + assert_de_tokens_error::( + &[ + Token::Map { len: Some(1) }, + Token::Str("type"), + Token::Str("Z"), + Token::MapEnd, + ], + "unknown variant `Z`, expected one of `Unit`, `NewtypeNewtype`, `NewtypeMap`, `NewtypeStruct`, `Struct`", + ); +} + +#[test] +fn untagged_variant() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(tag = "kind")] + enum InternallyTagged { + Tagged { + a: u8, + }, + #[serde(untagged)] + Untagged { + kind: String, + b: u8, + }, + } + + assert_de_tokens( + &InternallyTagged::Tagged { a: 1 }, + &[ + Token::Map { len: Some(2) }, + Token::Str("kind"), + Token::Str("Tagged"), + Token::Str("a"), + Token::U8(1), + Token::MapEnd, + ], + ); + + assert_tokens( + &InternallyTagged::Tagged { a: 1 }, + &[ + Token::Struct { + name: "InternallyTagged", + len: 2, + }, + Token::Str("kind"), + Token::Str("Tagged"), + Token::Str("a"), + Token::U8(1), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &InternallyTagged::Untagged { + kind: "Foo".to_owned(), + b: 2, + }, + &[ + Token::Map { len: Some(2) }, + Token::Str("kind"), + Token::Str("Foo"), + Token::Str("b"), + Token::U8(2), + Token::MapEnd, + ], + ); + + assert_tokens( + &InternallyTagged::Untagged { + kind: "Foo".to_owned(), + b: 2, + }, + &[ + Token::Struct { + name: "InternallyTagged", + len: 2, + }, + Token::Str("kind"), + Token::Str("Foo"), + Token::Str("b"), + Token::U8(2), + Token::StructEnd, + ], + ); + + assert_tokens( + &InternallyTagged::Untagged { + kind: "Tagged".to_owned(), + b: 2, + }, + &[ + Token::Struct { + name: "InternallyTagged", + len: 2, + }, + Token::Str("kind"), + Token::Str("Tagged"), + Token::Str("b"), + Token::U8(2), + Token::StructEnd, + ], + ); +} + +mod string_and_bytes { + use super::*; + + #[derive(Debug, PartialEq, Deserialize)] + #[serde(tag = "type")] + enum InternallyTagged { + String { + string: String, + }, + Bytes { + #[serde(with = "bytes")] + bytes: Vec, + }, + } + + #[test] + fn string_from_string() { + assert_de_tokens( + &InternallyTagged::String { + string: "\0".to_owned(), + }, + &[ + Token::Struct { + name: "String", + len: 2, + }, + Token::Str("type"), + Token::Str("String"), + Token::Str("string"), + Token::Str("\0"), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &InternallyTagged::String { + string: "\0".to_owned(), + }, + &[ + Token::Struct { + name: "String", + len: 2, + }, + Token::Str("type"), + Token::Str("String"), + Token::Str("string"), + Token::String("\0"), + Token::StructEnd, + ], + ); + } + + #[test] + fn string_from_bytes() { + assert_de_tokens( + &InternallyTagged::String { + string: "\0".to_owned(), + }, + &[ + Token::Struct { + name: "String", + len: 2, + }, + Token::Str("type"), + Token::Str("String"), + Token::Str("string"), + Token::Bytes(b"\0"), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &InternallyTagged::String { + string: "\0".to_owned(), + }, + &[ + Token::Struct { + name: "String", + len: 2, + }, + Token::Str("type"), + Token::Str("String"), + Token::Str("string"), + Token::ByteBuf(b"\0"), + Token::StructEnd, + ], + ); + } + + #[test] + fn bytes_from_string() { + assert_de_tokens( + &InternallyTagged::Bytes { bytes: vec![0] }, + &[ + Token::Struct { + name: "Bytes", + len: 2, + }, + Token::Str("type"), + Token::Str("Bytes"), + Token::Str("bytes"), + Token::Str("\0"), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &InternallyTagged::Bytes { bytes: vec![0] }, + &[ + Token::Struct { + name: "Bytes", + len: 2, + }, + Token::Str("type"), + Token::Str("Bytes"), + Token::Str("bytes"), + Token::String("\0"), + Token::StructEnd, + ], + ); + } + + #[test] + fn bytes_from_bytes() { + assert_de_tokens( + &InternallyTagged::Bytes { bytes: vec![0] }, + &[ + Token::Struct { + name: "Bytes", + len: 2, + }, + Token::Str("type"), + Token::Str("Bytes"), + Token::Str("bytes"), + Token::Bytes(b"\0"), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &InternallyTagged::Bytes { bytes: vec![0] }, + &[ + Token::Struct { + name: "Bytes", + len: 2, + }, + Token::Str("type"), + Token::Str("Bytes"), + Token::Str("bytes"), + Token::ByteBuf(b"\0"), + Token::StructEnd, + ], + ); + } + + #[test] + fn bytes_from_seq() { + assert_de_tokens( + &InternallyTagged::Bytes { bytes: vec![0] }, + &[ + Token::Struct { + name: "Bytes", + len: 2, + }, + Token::Str("type"), + Token::Str("Bytes"), + Token::Str("bytes"), + Token::Seq { len: Some(1) }, + Token::U8(0), + Token::SeqEnd, + Token::StructEnd, + ], + ); + } +} + +#[test] +fn struct_variant_containing_unit_variant() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + pub enum Level { + Info, + } + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(tag = "action")] + pub enum Message { + Log { level: Level }, + } + + assert_de_tokens( + &Level::Info, + &[ + Token::Enum { name: "Level" }, + Token::BorrowedStr("Info"), + Token::Unit, + ], + ); + + assert_de_tokens( + &Message::Log { level: Level::Info }, + &[ + Token::Struct { + name: "Message", + len: 2, + }, + Token::Str("action"), + Token::Str("Log"), + Token::Str("level"), + Token::Enum { name: "Level" }, + Token::BorrowedStr("Info"), + Token::Unit, + 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::Enum { name: "Level" }, + Token::BorrowedStr("Info"), + Token::Unit, + Token::MapEnd, + ], + ); + + assert_de_tokens( + &Message::Log { level: Level::Info }, + &[ + Token::Seq { len: Some(2) }, + Token::Str("Log"), + Token::Enum { name: "Level" }, + Token::BorrowedStr("Info"), + Token::Unit, + Token::SeqEnd, + ], + ); +} + +#[test] +fn borrow() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(tag = "type")] + enum Input<'a> { + Package { name: &'a str }, + } + + assert_tokens( + &Input::Package { name: "borrowed" }, + &[ + Token::Struct { + name: "Input", + len: 2, + }, + Token::BorrowedStr("type"), + Token::BorrowedStr("Package"), + Token::BorrowedStr("name"), + Token::BorrowedStr("borrowed"), + Token::StructEnd, + ], + ); +} + +#[test] +fn newtype_variant_containing_externally_tagged_enum() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(tag = "type")] + enum Outer { + Inner(Inner), + } + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + enum Inner { + Unit, + Newtype(u8), + Tuple(u8, u8), + Struct { f: u8 }, + } + + assert_tokens( + &Outer::Inner(Inner::Unit), + &[ + Token::Map { len: Some(2) }, + Token::Str("type"), + Token::Str("Inner"), + Token::Str("Unit"), + Token::Unit, + Token::MapEnd, + ], + ); + + assert_tokens( + &Outer::Inner(Inner::Newtype(1)), + &[ + Token::Map { len: Some(2) }, + Token::Str("type"), + Token::Str("Inner"), + Token::Str("Newtype"), + Token::U8(1), + Token::MapEnd, + ], + ); + + // Reaches crate::private::de::content::VariantDeserializer::tuple_variant + // Content::Seq case + // via ContentDeserializer::deserialize_enum + assert_tokens( + &Outer::Inner(Inner::Tuple(1, 1)), + &[ + Token::Map { len: Some(2) }, + Token::Str("type"), + Token::Str("Inner"), + Token::Str("Tuple"), + Token::TupleStruct { + name: "Tuple", + len: 2, + }, + Token::U8(1), + Token::U8(1), + Token::TupleStructEnd, + Token::MapEnd, + ], + ); + + // Reaches crate::private::de::content::VariantDeserializer::struct_variant + // Content::Map case + // via ContentDeserializer::deserialize_enum + assert_tokens( + &Outer::Inner(Inner::Struct { f: 1 }), + &[ + Token::Map { len: Some(2) }, + Token::Str("type"), + Token::Str("Inner"), + Token::Str("Struct"), + Token::Struct { + name: "Struct", + len: 1, + }, + Token::Str("f"), + Token::U8(1), + Token::StructEnd, + Token::MapEnd, + ], + ); + + // Reaches crate::private::de::content::VariantDeserializer::struct_variant + // Content::Seq case + // via ContentDeserializer::deserialize_enum + assert_de_tokens( + &Outer::Inner(Inner::Struct { f: 1 }), + &[ + Token::Map { len: Some(2) }, + Token::Str("type"), + Token::Str("Inner"), + Token::Str("Struct"), + Token::Seq { len: Some(1) }, + Token::U8(1), // f + Token::SeqEnd, + Token::MapEnd, + ], + ); +} + +#[test] +fn newtype_variant_containing_unit_struct() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct Info; + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(tag = "topic")] + enum Message { + Info(Info), + } + + assert_tokens( + &Message::Info(Info), + &[ + Token::Map { len: Some(1) }, + Token::Str("topic"), + Token::Str("Info"), + 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, + ], + ); +} \ No newline at end of file diff --git a/test_suite/tests/test_macros.rs b/test_suite/tests/test_macros.rs index 9404c3835..72137ddd0 100644 --- a/test_suite/tests/test_macros.rs +++ b/test_suite/tests/test_macros.rs @@ -679,668 +679,6 @@ fn test_untagged_enum() { ); } -mod internally_tagged_enum { - use super::*; - - #[derive(Debug, PartialEq, Serialize, Deserialize)] - struct Newtype(BTreeMap); - - #[derive(Debug, PartialEq, Serialize, Deserialize)] - struct Struct { - f: u8, - } - - #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "type")] - enum InternallyTagged { - Unit, - NewtypeNewtype(Newtype), - NewtypeMap(BTreeMap), - NewtypeStruct(Struct), - Struct { a: u8 }, - } - - #[test] - fn unit() { - assert_tokens( - &InternallyTagged::Unit, - &[ - Token::Struct { - name: "InternallyTagged", - len: 1, - }, - Token::Str("type"), - Token::Str("Unit"), - Token::StructEnd, - ], - ); - - assert_de_tokens( - &InternallyTagged::Unit, - &[ - Token::Seq { len: Some(1) }, - Token::Str("Unit"), - Token::SeqEnd, - ], - ); - } - - #[test] - fn newtype_newtype() { - assert_tokens( - &InternallyTagged::NewtypeNewtype(Newtype(BTreeMap::new())), - &[ - Token::Map { len: Some(1) }, - Token::Str("type"), - Token::Str("NewtypeNewtype"), - Token::MapEnd, - ], - ); - } - - #[test] - fn newtype_map() { - assert_tokens( - &InternallyTagged::NewtypeMap(BTreeMap::new()), - &[ - Token::Map { len: Some(1) }, - Token::Str("type"), - Token::Str("NewtypeMap"), - Token::MapEnd, - ], - ); - - assert_de_tokens_error::( - &[ - Token::Seq { len: Some(2) }, - Token::Str("NewtypeMap"), - Token::Map { len: Some(0) }, - Token::MapEnd, - Token::SeqEnd, - ], - "invalid type: sequence, expected a map", - ); - } - - #[test] - fn newtype_struct() { - assert_tokens( - &InternallyTagged::NewtypeStruct(Struct { f: 6 }), - &[ - Token::Struct { - name: "Struct", - len: 2, - }, - Token::Str("type"), - Token::Str("NewtypeStruct"), - Token::Str("f"), - Token::U8(6), - Token::StructEnd, - ], - ); - - assert_de_tokens( - &InternallyTagged::NewtypeStruct(Struct { f: 6 }), - &[ - Token::Seq { len: Some(2) }, - Token::Str("NewtypeStruct"), - Token::U8(6), - Token::SeqEnd, - ], - ); - } - - #[test] - fn struct_() { - assert_tokens( - &InternallyTagged::Struct { a: 1 }, - &[ - Token::Struct { - name: "InternallyTagged", - len: 2, - }, - Token::Str("type"), - Token::Str("Struct"), - Token::Str("a"), - Token::U8(1), - Token::StructEnd, - ], - ); - - assert_de_tokens( - &InternallyTagged::Struct { a: 1 }, - &[ - Token::Seq { len: Some(2) }, - Token::Str("Struct"), - Token::U8(1), - Token::SeqEnd, - ], - ); - } - - #[test] - fn wrong_tag() { - assert_de_tokens_error::( - &[Token::Map { len: Some(0) }, Token::MapEnd], - "missing field `type`", - ); - - assert_de_tokens_error::( - &[ - Token::Map { len: Some(1) }, - Token::Str("type"), - Token::Str("Z"), - Token::MapEnd, - ], - "unknown variant `Z`, expected one of `Unit`, `NewtypeNewtype`, `NewtypeMap`, `NewtypeStruct`, `Struct`", - ); - } - - #[test] - fn untagged_variant() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "kind")] - enum InternallyTagged { - Tagged { - a: u8, - }, - #[serde(untagged)] - Untagged { - kind: String, - b: u8, - }, - } - - assert_de_tokens( - &InternallyTagged::Tagged { a: 1 }, - &[ - Token::Map { len: Some(2) }, - Token::Str("kind"), - Token::Str("Tagged"), - Token::Str("a"), - Token::U8(1), - Token::MapEnd, - ], - ); - - assert_tokens( - &InternallyTagged::Tagged { a: 1 }, - &[ - Token::Struct { - name: "InternallyTagged", - len: 2, - }, - Token::Str("kind"), - Token::Str("Tagged"), - Token::Str("a"), - Token::U8(1), - Token::StructEnd, - ], - ); - - assert_de_tokens( - &InternallyTagged::Untagged { - kind: "Foo".to_owned(), - b: 2, - }, - &[ - Token::Map { len: Some(2) }, - Token::Str("kind"), - Token::Str("Foo"), - Token::Str("b"), - Token::U8(2), - Token::MapEnd, - ], - ); - - assert_tokens( - &InternallyTagged::Untagged { - kind: "Foo".to_owned(), - b: 2, - }, - &[ - Token::Struct { - name: "InternallyTagged", - len: 2, - }, - Token::Str("kind"), - Token::Str("Foo"), - Token::Str("b"), - Token::U8(2), - Token::StructEnd, - ], - ); - - assert_tokens( - &InternallyTagged::Untagged { - kind: "Tagged".to_owned(), - b: 2, - }, - &[ - Token::Struct { - name: "InternallyTagged", - len: 2, - }, - Token::Str("kind"), - Token::Str("Tagged"), - Token::Str("b"), - Token::U8(2), - Token::StructEnd, - ], - ); - } - - mod string_and_bytes { - use super::*; - - #[derive(Debug, PartialEq, Deserialize)] - #[serde(tag = "type")] - enum InternallyTagged { - String { - string: String, - }, - Bytes { - #[serde(with = "bytes")] - bytes: Vec, - }, - } - - #[test] - fn string_from_string() { - assert_de_tokens( - &InternallyTagged::String { - string: "\0".to_owned(), - }, - &[ - Token::Struct { - name: "String", - len: 2, - }, - Token::Str("type"), - Token::Str("String"), - Token::Str("string"), - Token::Str("\0"), - Token::StructEnd, - ], - ); - - assert_de_tokens( - &InternallyTagged::String { - string: "\0".to_owned(), - }, - &[ - Token::Struct { - name: "String", - len: 2, - }, - Token::Str("type"), - Token::Str("String"), - Token::Str("string"), - Token::String("\0"), - Token::StructEnd, - ], - ); - } - - #[test] - fn string_from_bytes() { - assert_de_tokens( - &InternallyTagged::String { - string: "\0".to_owned(), - }, - &[ - Token::Struct { - name: "String", - len: 2, - }, - Token::Str("type"), - Token::Str("String"), - Token::Str("string"), - Token::Bytes(b"\0"), - Token::StructEnd, - ], - ); - - assert_de_tokens( - &InternallyTagged::String { - string: "\0".to_owned(), - }, - &[ - Token::Struct { - name: "String", - len: 2, - }, - Token::Str("type"), - Token::Str("String"), - Token::Str("string"), - Token::ByteBuf(b"\0"), - Token::StructEnd, - ], - ); - } - - #[test] - fn bytes_from_string() { - assert_de_tokens( - &InternallyTagged::Bytes { bytes: vec![0] }, - &[ - Token::Struct { - name: "Bytes", - len: 2, - }, - Token::Str("type"), - Token::Str("Bytes"), - Token::Str("bytes"), - Token::Str("\0"), - Token::StructEnd, - ], - ); - - assert_de_tokens( - &InternallyTagged::Bytes { bytes: vec![0] }, - &[ - Token::Struct { - name: "Bytes", - len: 2, - }, - Token::Str("type"), - Token::Str("Bytes"), - Token::Str("bytes"), - Token::String("\0"), - Token::StructEnd, - ], - ); - } - - #[test] - fn bytes_from_bytes() { - assert_de_tokens( - &InternallyTagged::Bytes { bytes: vec![0] }, - &[ - Token::Struct { - name: "Bytes", - len: 2, - }, - Token::Str("type"), - Token::Str("Bytes"), - Token::Str("bytes"), - Token::Bytes(b"\0"), - Token::StructEnd, - ], - ); - - assert_de_tokens( - &InternallyTagged::Bytes { bytes: vec![0] }, - &[ - Token::Struct { - name: "Bytes", - len: 2, - }, - Token::Str("type"), - Token::Str("Bytes"), - Token::Str("bytes"), - Token::ByteBuf(b"\0"), - Token::StructEnd, - ], - ); - } - - #[test] - fn bytes_from_seq() { - assert_de_tokens( - &InternallyTagged::Bytes { bytes: vec![0] }, - &[ - Token::Struct { - name: "Bytes", - len: 2, - }, - Token::Str("type"), - Token::Str("Bytes"), - Token::Str("bytes"), - Token::Seq { len: Some(1) }, - Token::U8(0), - Token::SeqEnd, - Token::StructEnd, - ], - ); - } - } - - #[test] - fn struct_variant_containing_unit_variant() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - pub enum Level { - Info, - } - - #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "action")] - pub enum Message { - Log { level: Level }, - } - - assert_de_tokens( - &Level::Info, - &[ - Token::Enum { name: "Level" }, - Token::BorrowedStr("Info"), - Token::Unit, - ], - ); - - assert_de_tokens( - &Message::Log { level: Level::Info }, - &[ - Token::Struct { - name: "Message", - len: 2, - }, - Token::Str("action"), - Token::Str("Log"), - Token::Str("level"), - Token::Enum { name: "Level" }, - Token::BorrowedStr("Info"), - Token::Unit, - 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::Enum { name: "Level" }, - Token::BorrowedStr("Info"), - Token::Unit, - Token::MapEnd, - ], - ); - - assert_de_tokens( - &Message::Log { level: Level::Info }, - &[ - Token::Seq { len: Some(2) }, - Token::Str("Log"), - Token::Enum { name: "Level" }, - Token::BorrowedStr("Info"), - Token::Unit, - Token::SeqEnd, - ], - ); - } - - #[test] - fn borrow() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "type")] - enum Input<'a> { - Package { name: &'a str }, - } - - assert_tokens( - &Input::Package { name: "borrowed" }, - &[ - Token::Struct { - name: "Input", - len: 2, - }, - Token::BorrowedStr("type"), - Token::BorrowedStr("Package"), - Token::BorrowedStr("name"), - Token::BorrowedStr("borrowed"), - Token::StructEnd, - ], - ); - } - - #[test] - fn newtype_variant_containing_externally_tagged_enum() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "type")] - enum Outer { - Inner(Inner), - } - - #[derive(Debug, PartialEq, Serialize, Deserialize)] - enum Inner { - Unit, - Newtype(u8), - Tuple(u8, u8), - Struct { f: u8 }, - } - - assert_tokens( - &Outer::Inner(Inner::Unit), - &[ - Token::Map { len: Some(2) }, - Token::Str("type"), - Token::Str("Inner"), - Token::Str("Unit"), - Token::Unit, - Token::MapEnd, - ], - ); - - assert_tokens( - &Outer::Inner(Inner::Newtype(1)), - &[ - Token::Map { len: Some(2) }, - Token::Str("type"), - Token::Str("Inner"), - Token::Str("Newtype"), - Token::U8(1), - Token::MapEnd, - ], - ); - - // Reaches crate::private::de::content::VariantDeserializer::tuple_variant - // Content::Seq case - // via ContentDeserializer::deserialize_enum - assert_tokens( - &Outer::Inner(Inner::Tuple(1, 1)), - &[ - Token::Map { len: Some(2) }, - Token::Str("type"), - Token::Str("Inner"), - Token::Str("Tuple"), - Token::TupleStruct { - name: "Tuple", - len: 2, - }, - Token::U8(1), - Token::U8(1), - Token::TupleStructEnd, - Token::MapEnd, - ], - ); - - // Reaches crate::private::de::content::VariantDeserializer::struct_variant - // Content::Map case - // via ContentDeserializer::deserialize_enum - assert_tokens( - &Outer::Inner(Inner::Struct { f: 1 }), - &[ - Token::Map { len: Some(2) }, - Token::Str("type"), - Token::Str("Inner"), - Token::Str("Struct"), - Token::Struct { - name: "Struct", - len: 1, - }, - Token::Str("f"), - Token::U8(1), - Token::StructEnd, - Token::MapEnd, - ], - ); - - // Reaches crate::private::de::content::VariantDeserializer::struct_variant - // Content::Seq case - // via ContentDeserializer::deserialize_enum - assert_de_tokens( - &Outer::Inner(Inner::Struct { f: 1 }), - &[ - Token::Map { len: Some(2) }, - Token::Str("type"), - Token::Str("Inner"), - Token::Str("Struct"), - Token::Seq { len: Some(1) }, - Token::U8(1), // f - Token::SeqEnd, - Token::MapEnd, - ], - ); - } - - #[test] - fn newtype_variant_containing_unit_struct() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - struct Info; - - #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "topic")] - enum Message { - Info(Info), - } - - assert_tokens( - &Message::Info(Info), - &[ - Token::Map { len: Some(1) }, - Token::Str("topic"), - Token::Str("Info"), - 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, - ], - ); - } -} - #[test] fn test_adjacently_tagged_enum() { #[derive(Debug, PartialEq, Serialize, Deserialize)] From 2cbfd37072a5af4774a77c8d3f7661dd3c1af194 Mon Sep 17 00:00:00 2001 From: Mingun Date: Fri, 28 Jul 2023 00:46:02 +0500 Subject: [PATCH 137/258] Move all other internally tagged enum tests into a dedicated file Moved all except flattened tests: - test_internally_tagged_enum_with_skipped_conflict => with_skipped_conflict - test_internally_tagged_enum_new_type_with_unit => newtype_variant_containing_unit - test_internally_tagged_unit_enum_with_unknown_fields => unit_variant_with_unknown_fields - test_expecting_message_internally_tagged_enum => expecting_message - flatten::enum_::internally_tagged::straightforward => containing_flatten --- test_suite/tests/test_annotations.rs | 133 ----------------- .../tests/test_enum_internally_tagged.rs | 135 +++++++++++++++++- 2 files changed, 134 insertions(+), 134 deletions(-) diff --git a/test_suite/tests/test_annotations.rs b/test_suite/tests/test_annotations.rs index 6864bf960..9aa328725 100644 --- a/test_suite/tests/test_annotations.rs +++ b/test_suite/tests/test_annotations.rs @@ -1607,58 +1607,6 @@ fn test_collect_other() { ); } -#[test] -fn test_internally_tagged_enum_with_skipped_conflict() { - #[derive(Serialize, Deserialize, PartialEq, Debug)] - #[serde(tag = "t")] - enum Data { - A, - #[serde(skip)] - #[allow(dead_code)] - B { - t: String, - }, - C { - #[serde(default, skip)] - t: String, - }, - } - - let data = Data::C { t: String::new() }; - - assert_tokens( - &data, - &[ - Token::Struct { - name: "Data", - len: 1, - }, - Token::Str("t"), - Token::Str("C"), - Token::StructEnd, - ], - ); -} - -#[test] -fn test_internally_tagged_enum_new_type_with_unit() { - #[derive(Serialize, Deserialize, PartialEq, Debug)] - #[serde(tag = "t")] - enum Data { - A(()), - } - - assert_tokens( - &Data::A(()), - &[ - Token::Map { len: Some(1) }, - Token::Str("t"), - Token::Str("A"), - Token::MapEnd, - ], - ); -} - #[test] fn test_adjacently_tagged_enum_bytes() { #[derive(Serialize, Deserialize, PartialEq, Debug)] @@ -1968,29 +1916,6 @@ fn test_transparent_tuple_struct() { assert_tokens(&Transparent(false, 1, false, PhantomData), &[Token::U32(1)]); } -#[test] -fn test_internally_tagged_unit_enum_with_unknown_fields() { - #[derive(Deserialize, PartialEq, Debug)] - #[serde(tag = "t")] - enum Data { - A, - } - - let data = Data::A; - - assert_de_tokens( - &data, - &[ - Token::Map { len: None }, - Token::Str("t"), - Token::Str("A"), - Token::Str("b"), - Token::I32(0), - Token::MapEnd, - ], - ); -} - #[test] fn test_expecting_message() { #[derive(Deserialize, PartialEq, Debug)] @@ -2055,27 +1980,6 @@ fn test_expecting_message_externally_tagged_enum() { ); } -#[test] -fn test_expecting_message_internally_tagged_enum() { - #[derive(Deserialize)] - #[serde(tag = "tag")] - #[serde(expecting = "something strange...")] - enum Enum { - InternallyTagged, - } - - assert_de_tokens_error::( - &[Token::Str("InternallyTagged")], - r#"invalid type: string "InternallyTagged", expected something strange..."#, - ); - - // Check that #[serde(expecting = "...")] doesn't affect variant identifier error message - assert_de_tokens_error::( - &[Token::Map { len: None }, Token::Str("tag"), Token::Unit], - "invalid type: unit value, expected variant identifier", - ); -} - #[test] fn test_expecting_message_adjacently_tagged_enum() { #[derive(Deserialize)] @@ -3123,43 +3027,6 @@ mod flatten { mod internally_tagged { use super::*; - #[test] - fn straightforward() { - #[derive(Serialize, Deserialize, PartialEq, Debug)] - #[serde(tag = "t")] - enum Data { - A { - a: i32, - #[serde(flatten)] - flat: Flat, - }, - } - - #[derive(Serialize, Deserialize, PartialEq, Debug)] - struct Flat { - b: i32, - } - - let data = Data::A { - a: 0, - flat: Flat { b: 0 }, - }; - - assert_tokens( - &data, - &[ - Token::Map { len: None }, - Token::Str("t"), - Token::Str("A"), - Token::Str("a"), - Token::I32(0), - Token::Str("b"), - Token::I32(0), - Token::MapEnd, - ], - ); - } - #[test] fn structs() { #[derive(Debug, PartialEq, Serialize, Deserialize)] diff --git a/test_suite/tests/test_enum_internally_tagged.rs b/test_suite/tests/test_enum_internally_tagged.rs index 8c573a9e3..0a0220280 100644 --- a/test_suite/tests/test_enum_internally_tagged.rs +++ b/test_suite/tests/test_enum_internally_tagged.rs @@ -668,4 +668,137 @@ fn newtype_variant_containing_unit_struct() { Token::SeqEnd, ], ); -} \ No newline at end of file +} + +#[test] +fn with_skipped_conflict() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[serde(tag = "t")] + enum Data { + A, + #[serde(skip)] + #[allow(dead_code)] + B { + t: String, + }, + C { + #[serde(default, skip)] + t: String, + }, + } + + let data = Data::C { t: String::new() }; + + assert_tokens( + &data, + &[ + Token::Struct { + name: "Data", + len: 1, + }, + Token::Str("t"), + Token::Str("C"), + Token::StructEnd, + ], + ); +} + +#[test] +fn containing_flatten() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[serde(tag = "t")] + enum Data { + A { + a: i32, + #[serde(flatten)] + flat: Flat, + }, + } + + #[derive(Serialize, Deserialize, PartialEq, Debug)] + struct Flat { + b: i32, + } + + let data = Data::A { + a: 0, + flat: Flat { b: 0 }, + }; + + assert_tokens( + &data, + &[ + Token::Map { len: None }, + Token::Str("t"), + Token::Str("A"), + Token::Str("a"), + Token::I32(0), + Token::Str("b"), + Token::I32(0), + Token::MapEnd, + ], + ); +} + +#[test] +fn newtype_variant_containing_unit() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[serde(tag = "t")] + enum Data { + A(()), + } + + assert_tokens( + &Data::A(()), + &[ + Token::Map { len: Some(1) }, + Token::Str("t"), + Token::Str("A"), + Token::MapEnd, + ], + ); +} + +#[test] +fn unit_variant_with_unknown_fields() { + #[derive(Deserialize, PartialEq, Debug)] + #[serde(tag = "t")] + enum Data { + A, + } + + let data = Data::A; + + assert_de_tokens( + &data, + &[ + Token::Map { len: None }, + Token::Str("t"), + Token::Str("A"), + Token::Str("b"), + Token::I32(0), + Token::MapEnd, + ], + ); +} + +#[test] +fn expecting_message() { + #[derive(Deserialize)] + #[serde(tag = "tag")] + #[serde(expecting = "something strange...")] + enum Enum { + InternallyTagged, + } + + assert_de_tokens_error::( + &[Token::Str("InternallyTagged")], + r#"invalid type: string "InternallyTagged", expected something strange..."#, + ); + + // Check that #[serde(expecting = "...")] doesn't affect variant identifier error message + assert_de_tokens_error::( + &[Token::Map { len: None }, Token::Str("tag"), Token::Unit], + "invalid type: unit value, expected variant identifier", + ); +} From 9128201c78ae7674ae6c0c5876b7842c0d0c3664 Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 7 Aug 2023 21:12:23 +0500 Subject: [PATCH 138/258] Use the same order of derives --- test_suite/tests/test_enum_internally_tagged.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test_suite/tests/test_enum_internally_tagged.rs b/test_suite/tests/test_enum_internally_tagged.rs index 0a0220280..751a80c93 100644 --- a/test_suite/tests/test_enum_internally_tagged.rs +++ b/test_suite/tests/test_enum_internally_tagged.rs @@ -672,7 +672,7 @@ fn newtype_variant_containing_unit_struct() { #[test] fn with_skipped_conflict() { - #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "t")] enum Data { A, @@ -705,7 +705,7 @@ fn with_skipped_conflict() { #[test] fn containing_flatten() { - #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "t")] enum Data { A { @@ -715,7 +715,7 @@ fn containing_flatten() { }, } - #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Flat { b: i32, } @@ -742,7 +742,7 @@ fn containing_flatten() { #[test] fn newtype_variant_containing_unit() { - #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "t")] enum Data { A(()), @@ -761,7 +761,7 @@ fn newtype_variant_containing_unit() { #[test] fn unit_variant_with_unknown_fields() { - #[derive(Deserialize, PartialEq, Debug)] + #[derive(Debug, PartialEq, Deserialize)] #[serde(tag = "t")] enum Data { A, From eb59c776ca5c14312a03ce8fc70ce8a071f27cad Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 7 Aug 2023 21:15:21 +0500 Subject: [PATCH 139/258] Use name "tag" to refer to tag field --- .../tests/test_enum_internally_tagged.rs | 100 +++++++++--------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/test_suite/tests/test_enum_internally_tagged.rs b/test_suite/tests/test_enum_internally_tagged.rs index 751a80c93..63b2c4374 100644 --- a/test_suite/tests/test_enum_internally_tagged.rs +++ b/test_suite/tests/test_enum_internally_tagged.rs @@ -21,7 +21,7 @@ struct Struct { } #[derive(Debug, PartialEq, Serialize, Deserialize)] -#[serde(tag = "type")] +#[serde(tag = "tag")] enum InternallyTagged { Unit, NewtypeNewtype(Newtype), @@ -39,7 +39,7 @@ fn unit() { name: "InternallyTagged", len: 1, }, - Token::Str("type"), + Token::Str("tag"), Token::Str("Unit"), Token::StructEnd, ], @@ -61,7 +61,7 @@ fn newtype_newtype() { &InternallyTagged::NewtypeNewtype(Newtype(BTreeMap::new())), &[ Token::Map { len: Some(1) }, - Token::Str("type"), + Token::Str("tag"), Token::Str("NewtypeNewtype"), Token::MapEnd, ], @@ -74,7 +74,7 @@ fn newtype_map() { &InternallyTagged::NewtypeMap(BTreeMap::new()), &[ Token::Map { len: Some(1) }, - Token::Str("type"), + Token::Str("tag"), Token::Str("NewtypeMap"), Token::MapEnd, ], @@ -101,7 +101,7 @@ fn newtype_struct() { name: "Struct", len: 2, }, - Token::Str("type"), + Token::Str("tag"), Token::Str("NewtypeStruct"), Token::Str("f"), Token::U8(6), @@ -129,7 +129,7 @@ fn struct_() { name: "InternallyTagged", len: 2, }, - Token::Str("type"), + Token::Str("tag"), Token::Str("Struct"), Token::Str("a"), Token::U8(1), @@ -152,13 +152,13 @@ fn struct_() { fn wrong_tag() { assert_de_tokens_error::( &[Token::Map { len: Some(0) }, Token::MapEnd], - "missing field `type`", + "missing field `tag`", ); assert_de_tokens_error::( &[ Token::Map { len: Some(1) }, - Token::Str("type"), + Token::Str("tag"), Token::Str("Z"), Token::MapEnd, ], @@ -169,14 +169,14 @@ fn wrong_tag() { #[test] fn untagged_variant() { #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "kind")] + #[serde(tag = "tag")] enum InternallyTagged { Tagged { a: u8, }, #[serde(untagged)] Untagged { - kind: String, + tag: String, b: u8, }, } @@ -185,7 +185,7 @@ fn untagged_variant() { &InternallyTagged::Tagged { a: 1 }, &[ Token::Map { len: Some(2) }, - Token::Str("kind"), + Token::Str("tag"), Token::Str("Tagged"), Token::Str("a"), Token::U8(1), @@ -200,7 +200,7 @@ fn untagged_variant() { name: "InternallyTagged", len: 2, }, - Token::Str("kind"), + Token::Str("tag"), Token::Str("Tagged"), Token::Str("a"), Token::U8(1), @@ -210,12 +210,12 @@ fn untagged_variant() { assert_de_tokens( &InternallyTagged::Untagged { - kind: "Foo".to_owned(), + tag: "Foo".to_owned(), b: 2, }, &[ Token::Map { len: Some(2) }, - Token::Str("kind"), + Token::Str("tag"), Token::Str("Foo"), Token::Str("b"), Token::U8(2), @@ -225,7 +225,7 @@ fn untagged_variant() { assert_tokens( &InternallyTagged::Untagged { - kind: "Foo".to_owned(), + tag: "Foo".to_owned(), b: 2, }, &[ @@ -233,7 +233,7 @@ fn untagged_variant() { name: "InternallyTagged", len: 2, }, - Token::Str("kind"), + Token::Str("tag"), Token::Str("Foo"), Token::Str("b"), Token::U8(2), @@ -243,7 +243,7 @@ fn untagged_variant() { assert_tokens( &InternallyTagged::Untagged { - kind: "Tagged".to_owned(), + tag: "Tagged".to_owned(), b: 2, }, &[ @@ -251,7 +251,7 @@ fn untagged_variant() { name: "InternallyTagged", len: 2, }, - Token::Str("kind"), + Token::Str("tag"), Token::Str("Tagged"), Token::Str("b"), Token::U8(2), @@ -264,7 +264,7 @@ mod string_and_bytes { use super::*; #[derive(Debug, PartialEq, Deserialize)] - #[serde(tag = "type")] + #[serde(tag = "tag")] enum InternallyTagged { String { string: String, @@ -286,7 +286,7 @@ mod string_and_bytes { name: "String", len: 2, }, - Token::Str("type"), + Token::Str("tag"), Token::Str("String"), Token::Str("string"), Token::Str("\0"), @@ -303,7 +303,7 @@ mod string_and_bytes { name: "String", len: 2, }, - Token::Str("type"), + Token::Str("tag"), Token::Str("String"), Token::Str("string"), Token::String("\0"), @@ -323,7 +323,7 @@ mod string_and_bytes { name: "String", len: 2, }, - Token::Str("type"), + Token::Str("tag"), Token::Str("String"), Token::Str("string"), Token::Bytes(b"\0"), @@ -340,7 +340,7 @@ mod string_and_bytes { name: "String", len: 2, }, - Token::Str("type"), + Token::Str("tag"), Token::Str("String"), Token::Str("string"), Token::ByteBuf(b"\0"), @@ -358,7 +358,7 @@ mod string_and_bytes { name: "Bytes", len: 2, }, - Token::Str("type"), + Token::Str("tag"), Token::Str("Bytes"), Token::Str("bytes"), Token::Str("\0"), @@ -373,7 +373,7 @@ mod string_and_bytes { name: "Bytes", len: 2, }, - Token::Str("type"), + Token::Str("tag"), Token::Str("Bytes"), Token::Str("bytes"), Token::String("\0"), @@ -391,7 +391,7 @@ mod string_and_bytes { name: "Bytes", len: 2, }, - Token::Str("type"), + Token::Str("tag"), Token::Str("Bytes"), Token::Str("bytes"), Token::Bytes(b"\0"), @@ -406,7 +406,7 @@ mod string_and_bytes { name: "Bytes", len: 2, }, - Token::Str("type"), + Token::Str("tag"), Token::Str("Bytes"), Token::Str("bytes"), Token::ByteBuf(b"\0"), @@ -424,7 +424,7 @@ mod string_and_bytes { name: "Bytes", len: 2, }, - Token::Str("type"), + Token::Str("tag"), Token::Str("Bytes"), Token::Str("bytes"), Token::Seq { len: Some(1) }, @@ -444,7 +444,7 @@ fn struct_variant_containing_unit_variant() { } #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "action")] + #[serde(tag = "tag")] pub enum Message { Log { level: Level }, } @@ -465,7 +465,7 @@ fn struct_variant_containing_unit_variant() { name: "Message", len: 2, }, - Token::Str("action"), + Token::Str("tag"), Token::Str("Log"), Token::Str("level"), Token::Enum { name: "Level" }, @@ -479,7 +479,7 @@ fn struct_variant_containing_unit_variant() { &Message::Log { level: Level::Info }, &[ Token::Map { len: Some(2) }, - Token::Str("action"), + Token::Str("tag"), Token::Str("Log"), Token::Str("level"), Token::Enum { name: "Level" }, @@ -505,7 +505,7 @@ fn struct_variant_containing_unit_variant() { #[test] fn borrow() { #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "type")] + #[serde(tag = "tag")] enum Input<'a> { Package { name: &'a str }, } @@ -517,7 +517,7 @@ fn borrow() { name: "Input", len: 2, }, - Token::BorrowedStr("type"), + Token::BorrowedStr("tag"), Token::BorrowedStr("Package"), Token::BorrowedStr("name"), Token::BorrowedStr("borrowed"), @@ -529,7 +529,7 @@ fn borrow() { #[test] fn newtype_variant_containing_externally_tagged_enum() { #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "type")] + #[serde(tag = "tag")] enum Outer { Inner(Inner), } @@ -546,7 +546,7 @@ fn newtype_variant_containing_externally_tagged_enum() { &Outer::Inner(Inner::Unit), &[ Token::Map { len: Some(2) }, - Token::Str("type"), + Token::Str("tag"), Token::Str("Inner"), Token::Str("Unit"), Token::Unit, @@ -558,7 +558,7 @@ fn newtype_variant_containing_externally_tagged_enum() { &Outer::Inner(Inner::Newtype(1)), &[ Token::Map { len: Some(2) }, - Token::Str("type"), + Token::Str("tag"), Token::Str("Inner"), Token::Str("Newtype"), Token::U8(1), @@ -573,7 +573,7 @@ fn newtype_variant_containing_externally_tagged_enum() { &Outer::Inner(Inner::Tuple(1, 1)), &[ Token::Map { len: Some(2) }, - Token::Str("type"), + Token::Str("tag"), Token::Str("Inner"), Token::Str("Tuple"), Token::TupleStruct { @@ -594,7 +594,7 @@ fn newtype_variant_containing_externally_tagged_enum() { &Outer::Inner(Inner::Struct { f: 1 }), &[ Token::Map { len: Some(2) }, - Token::Str("type"), + Token::Str("tag"), Token::Str("Inner"), Token::Str("Struct"), Token::Struct { @@ -615,7 +615,7 @@ fn newtype_variant_containing_externally_tagged_enum() { &Outer::Inner(Inner::Struct { f: 1 }), &[ Token::Map { len: Some(2) }, - Token::Str("type"), + Token::Str("tag"), Token::Str("Inner"), Token::Str("Struct"), Token::Seq { len: Some(1) }, @@ -632,7 +632,7 @@ fn newtype_variant_containing_unit_struct() { struct Info; #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "topic")] + #[serde(tag = "tag")] enum Message { Info(Info), } @@ -641,7 +641,7 @@ fn newtype_variant_containing_unit_struct() { &Message::Info(Info), &[ Token::Map { len: Some(1) }, - Token::Str("topic"), + Token::Str("tag"), Token::Str("Info"), Token::MapEnd, ], @@ -654,7 +654,7 @@ fn newtype_variant_containing_unit_struct() { name: "Message", len: 1, }, - Token::Str("topic"), + Token::Str("tag"), Token::Str("Info"), Token::StructEnd, ], @@ -673,7 +673,7 @@ fn newtype_variant_containing_unit_struct() { #[test] fn with_skipped_conflict() { #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "t")] + #[serde(tag = "tag")] enum Data { A, #[serde(skip)] @@ -696,7 +696,7 @@ fn with_skipped_conflict() { name: "Data", len: 1, }, - Token::Str("t"), + Token::Str("tag"), Token::Str("C"), Token::StructEnd, ], @@ -706,7 +706,7 @@ fn with_skipped_conflict() { #[test] fn containing_flatten() { #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "t")] + #[serde(tag = "tag")] enum Data { A { a: i32, @@ -729,7 +729,7 @@ fn containing_flatten() { &data, &[ Token::Map { len: None }, - Token::Str("t"), + Token::Str("tag"), Token::Str("A"), Token::Str("a"), Token::I32(0), @@ -743,7 +743,7 @@ fn containing_flatten() { #[test] fn newtype_variant_containing_unit() { #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "t")] + #[serde(tag = "tag")] enum Data { A(()), } @@ -752,7 +752,7 @@ fn newtype_variant_containing_unit() { &Data::A(()), &[ Token::Map { len: Some(1) }, - Token::Str("t"), + Token::Str("tag"), Token::Str("A"), Token::MapEnd, ], @@ -762,7 +762,7 @@ fn newtype_variant_containing_unit() { #[test] fn unit_variant_with_unknown_fields() { #[derive(Debug, PartialEq, Deserialize)] - #[serde(tag = "t")] + #[serde(tag = "tag")] enum Data { A, } @@ -773,7 +773,7 @@ fn unit_variant_with_unknown_fields() { &data, &[ Token::Map { len: None }, - Token::Str("t"), + Token::Str("tag"), Token::Str("A"), Token::Str("b"), Token::I32(0), From f97160f715f743145ba61a4fb45db587651d3fe8 Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 7 Aug 2023 21:42:47 +0500 Subject: [PATCH 140/258] Reuse type in unit_variant_with_unknown_fields and add test for sequence --- .../tests/test_enum_internally_tagged.rs | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/test_suite/tests/test_enum_internally_tagged.rs b/test_suite/tests/test_enum_internally_tagged.rs index 63b2c4374..b7ff46152 100644 --- a/test_suite/tests/test_enum_internally_tagged.rs +++ b/test_suite/tests/test_enum_internally_tagged.rs @@ -761,25 +761,30 @@ fn newtype_variant_containing_unit() { #[test] fn unit_variant_with_unknown_fields() { - #[derive(Debug, PartialEq, Deserialize)] - #[serde(tag = "tag")] - enum Data { - A, - } - - let data = Data::A; + let value = InternallyTagged::Unit; assert_de_tokens( - &data, + &value, &[ Token::Map { len: None }, Token::Str("tag"), - Token::Str("A"), + Token::Str("Unit"), Token::Str("b"), Token::I32(0), Token::MapEnd, ], ); + + // Unknown elements are not allowed in sequences + assert_de_tokens_error::( + &[ + Token::Seq { len: None }, + Token::Str("Unit"), + Token::I32(0), + Token::SeqEnd, + ], + "invalid length 1, expected 0 elements in sequence", + ); } #[test] From 2d75ef6b30c21022f457d673b2ed5a715c153515 Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 7 Aug 2023 21:47:55 +0500 Subject: [PATCH 141/258] Reuse type in newtype_variant_containing_unit --- .../tests/test_enum_internally_tagged.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/test_suite/tests/test_enum_internally_tagged.rs b/test_suite/tests/test_enum_internally_tagged.rs index b7ff46152..646b14543 100644 --- a/test_suite/tests/test_enum_internally_tagged.rs +++ b/test_suite/tests/test_enum_internally_tagged.rs @@ -24,6 +24,7 @@ struct Struct { #[serde(tag = "tag")] enum InternallyTagged { Unit, + NewtypeUnit(()), NewtypeNewtype(Newtype), NewtypeMap(BTreeMap), NewtypeStruct(Struct), @@ -162,7 +163,13 @@ fn wrong_tag() { Token::Str("Z"), Token::MapEnd, ], - "unknown variant `Z`, expected one of `Unit`, `NewtypeNewtype`, `NewtypeMap`, `NewtypeStruct`, `Struct`", + "unknown variant `Z`, expected one of \ + `Unit`, \ + `NewtypeUnit`, \ + `NewtypeNewtype`, \ + `NewtypeMap`, \ + `NewtypeStruct`, \ + `Struct`", ); } @@ -742,18 +749,14 @@ fn containing_flatten() { #[test] fn newtype_variant_containing_unit() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "tag")] - enum Data { - A(()), - } + let value = InternallyTagged::NewtypeUnit(()); assert_tokens( - &Data::A(()), + &value, &[ Token::Map { len: Some(1) }, Token::Str("tag"), - Token::Str("A"), + Token::Str("NewtypeUnit"), Token::MapEnd, ], ); From 93bda5f1dc7b3f6618f1eecbd62cff3c4790e5c3 Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 7 Aug 2023 21:35:02 +0500 Subject: [PATCH 142/258] Rename unit struct to a generic name: Info->Unit --- test_suite/tests/test_enum_internally_tagged.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test_suite/tests/test_enum_internally_tagged.rs b/test_suite/tests/test_enum_internally_tagged.rs index 646b14543..cdf0d4e55 100644 --- a/test_suite/tests/test_enum_internally_tagged.rs +++ b/test_suite/tests/test_enum_internally_tagged.rs @@ -636,16 +636,16 @@ fn newtype_variant_containing_externally_tagged_enum() { #[test] fn newtype_variant_containing_unit_struct() { #[derive(Debug, PartialEq, Serialize, Deserialize)] - struct Info; + struct Unit; #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "tag")] enum Message { - Info(Info), + Info(Unit), } assert_tokens( - &Message::Info(Info), + &Message::Info(Unit), &[ Token::Map { len: Some(1) }, Token::Str("tag"), @@ -655,7 +655,7 @@ fn newtype_variant_containing_unit_struct() { ); assert_de_tokens( - &Message::Info(Info), + &Message::Info(Unit), &[ Token::Struct { name: "Message", @@ -668,7 +668,7 @@ fn newtype_variant_containing_unit_struct() { ); assert_de_tokens( - &Message::Info(Info), + &Message::Info(Unit), &[ Token::Seq { len: Some(1) }, Token::Str("Info"), From 48de0c51b0e64cbc538ecf469554d36126803bc0 Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 7 Aug 2023 21:36:16 +0500 Subject: [PATCH 143/258] Share unit struct Unit between all tests --- test_suite/tests/test_enum_internally_tagged.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test_suite/tests/test_enum_internally_tagged.rs b/test_suite/tests/test_enum_internally_tagged.rs index cdf0d4e55..55069a5f3 100644 --- a/test_suite/tests/test_enum_internally_tagged.rs +++ b/test_suite/tests/test_enum_internally_tagged.rs @@ -12,6 +12,9 @@ use serde_derive::{Deserialize, Serialize}; use serde_test::{assert_de_tokens, assert_de_tokens_error, assert_tokens, Token}; use std::collections::BTreeMap; +#[derive(Debug, PartialEq, Serialize, Deserialize)] +struct Unit; + #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Newtype(BTreeMap); @@ -635,9 +638,6 @@ fn newtype_variant_containing_externally_tagged_enum() { #[test] fn newtype_variant_containing_unit_struct() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - struct Unit; - #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "tag")] enum Message { From d3492d8d36af377ac4d07637b82a95862ca26c68 Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 7 Aug 2023 21:53:32 +0500 Subject: [PATCH 144/258] Reuse type in newtype_variant_containing_unit_struct --- .../tests/test_enum_internally_tagged.rs | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/test_suite/tests/test_enum_internally_tagged.rs b/test_suite/tests/test_enum_internally_tagged.rs index 55069a5f3..b7568b9aa 100644 --- a/test_suite/tests/test_enum_internally_tagged.rs +++ b/test_suite/tests/test_enum_internally_tagged.rs @@ -28,6 +28,7 @@ struct Struct { enum InternallyTagged { Unit, NewtypeUnit(()), + NewtypeUnitStruct(Unit), NewtypeNewtype(Newtype), NewtypeMap(BTreeMap), NewtypeStruct(Struct), @@ -169,6 +170,7 @@ fn wrong_tag() { "unknown variant `Z`, expected one of \ `Unit`, \ `NewtypeUnit`, \ + `NewtypeUnitStruct`, \ `NewtypeNewtype`, \ `NewtypeMap`, \ `NewtypeStruct`, \ @@ -638,40 +640,36 @@ fn newtype_variant_containing_externally_tagged_enum() { #[test] fn newtype_variant_containing_unit_struct() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "tag")] - enum Message { - Info(Unit), - } + let value = InternallyTagged::NewtypeUnitStruct(Unit); assert_tokens( - &Message::Info(Unit), + &value, &[ Token::Map { len: Some(1) }, Token::Str("tag"), - Token::Str("Info"), + Token::Str("NewtypeUnitStruct"), Token::MapEnd, ], ); assert_de_tokens( - &Message::Info(Unit), + &value, &[ Token::Struct { - name: "Message", + name: "InternallyTagged", len: 1, }, Token::Str("tag"), - Token::Str("Info"), + Token::Str("NewtypeUnitStruct"), Token::StructEnd, ], ); assert_de_tokens( - &Message::Info(Unit), + &value, &[ Token::Seq { len: Some(1) }, - Token::Str("Info"), + Token::Str("NewtypeUnitStruct"), // tag Token::SeqEnd, ], ); From e999600f8f705b5969a71abe85e008c6b18f2370 Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 7 Aug 2023 21:20:28 +0500 Subject: [PATCH 145/258] Rename externally tagged enum Inner to Enum --- test_suite/tests/test_enum_internally_tagged.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test_suite/tests/test_enum_internally_tagged.rs b/test_suite/tests/test_enum_internally_tagged.rs index b7568b9aa..cf39ebe3e 100644 --- a/test_suite/tests/test_enum_internally_tagged.rs +++ b/test_suite/tests/test_enum_internally_tagged.rs @@ -543,11 +543,11 @@ fn newtype_variant_containing_externally_tagged_enum() { #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "tag")] enum Outer { - Inner(Inner), + Inner(Enum), } #[derive(Debug, PartialEq, Serialize, Deserialize)] - enum Inner { + enum Enum { Unit, Newtype(u8), Tuple(u8, u8), @@ -555,7 +555,7 @@ fn newtype_variant_containing_externally_tagged_enum() { } assert_tokens( - &Outer::Inner(Inner::Unit), + &Outer::Inner(Enum::Unit), &[ Token::Map { len: Some(2) }, Token::Str("tag"), @@ -567,7 +567,7 @@ fn newtype_variant_containing_externally_tagged_enum() { ); assert_tokens( - &Outer::Inner(Inner::Newtype(1)), + &Outer::Inner(Enum::Newtype(1)), &[ Token::Map { len: Some(2) }, Token::Str("tag"), @@ -582,7 +582,7 @@ fn newtype_variant_containing_externally_tagged_enum() { // Content::Seq case // via ContentDeserializer::deserialize_enum assert_tokens( - &Outer::Inner(Inner::Tuple(1, 1)), + &Outer::Inner(Enum::Tuple(1, 1)), &[ Token::Map { len: Some(2) }, Token::Str("tag"), @@ -603,7 +603,7 @@ fn newtype_variant_containing_externally_tagged_enum() { // Content::Map case // via ContentDeserializer::deserialize_enum assert_tokens( - &Outer::Inner(Inner::Struct { f: 1 }), + &Outer::Inner(Enum::Struct { f: 1 }), &[ Token::Map { len: Some(2) }, Token::Str("tag"), @@ -624,7 +624,7 @@ fn newtype_variant_containing_externally_tagged_enum() { // Content::Seq case // via ContentDeserializer::deserialize_enum assert_de_tokens( - &Outer::Inner(Inner::Struct { f: 1 }), + &Outer::Inner(Enum::Struct { f: 1 }), &[ Token::Map { len: Some(2) }, Token::Str("tag"), From 28a775db22e66c85c2b1410e23e212a4f345b63c Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 7 Aug 2023 21:30:37 +0500 Subject: [PATCH 146/258] Share externally tagged enum Enum between all tests and reuse in struct_variant_containing_unit_variant --- .../tests/test_enum_internally_tagged.rs | 51 +++++++++---------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/test_suite/tests/test_enum_internally_tagged.rs b/test_suite/tests/test_enum_internally_tagged.rs index cf39ebe3e..e7beae0b3 100644 --- a/test_suite/tests/test_enum_internally_tagged.rs +++ b/test_suite/tests/test_enum_internally_tagged.rs @@ -23,6 +23,14 @@ struct Struct { f: u8, } +#[derive(Debug, PartialEq, Serialize, Deserialize)] +enum Enum { + Unit, + Newtype(u8), + Tuple(u8, u8), + Struct { f: u8 }, +} + #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "tag")] enum InternallyTagged { @@ -450,28 +458,25 @@ mod string_and_bytes { #[test] fn struct_variant_containing_unit_variant() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - pub enum Level { - Info, - } - #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "tag")] - pub enum Message { - Log { level: Level }, + enum Message { + Log { level: Enum }, } assert_de_tokens( - &Level::Info, + &Enum::Unit, &[ - Token::Enum { name: "Level" }, - Token::BorrowedStr("Info"), + Token::Enum { name: "Enum" }, + Token::BorrowedStr("Unit"), Token::Unit, ], ); + let value = Message::Log { level: Enum::Unit }; + assert_de_tokens( - &Message::Log { level: Level::Info }, + &value, &[ Token::Struct { name: "Message", @@ -480,34 +485,34 @@ fn struct_variant_containing_unit_variant() { Token::Str("tag"), Token::Str("Log"), Token::Str("level"), - Token::Enum { name: "Level" }, - Token::BorrowedStr("Info"), + Token::Enum { name: "Enum" }, + Token::BorrowedStr("Unit"), Token::Unit, Token::StructEnd, ], ); assert_de_tokens( - &Message::Log { level: Level::Info }, + &value, &[ Token::Map { len: Some(2) }, Token::Str("tag"), Token::Str("Log"), Token::Str("level"), - Token::Enum { name: "Level" }, - Token::BorrowedStr("Info"), + Token::Enum { name: "Enum" }, + Token::BorrowedStr("Unit"), Token::Unit, Token::MapEnd, ], ); assert_de_tokens( - &Message::Log { level: Level::Info }, + &value, &[ Token::Seq { len: Some(2) }, Token::Str("Log"), - Token::Enum { name: "Level" }, - Token::BorrowedStr("Info"), + Token::Enum { name: "Enum" }, + Token::BorrowedStr("Unit"), Token::Unit, Token::SeqEnd, ], @@ -546,14 +551,6 @@ fn newtype_variant_containing_externally_tagged_enum() { Inner(Enum), } - #[derive(Debug, PartialEq, Serialize, Deserialize)] - enum Enum { - Unit, - Newtype(u8), - Tuple(u8, u8), - Struct { f: u8 }, - } - assert_tokens( &Outer::Inner(Enum::Unit), &[ From 41b9c33c2bb8dfa8731cfe8318290719cc5404be Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 7 Aug 2023 21:58:50 +0500 Subject: [PATCH 147/258] Reuse type in newtype_variant_containing_externally_tagged_enum --- .../tests/test_enum_internally_tagged.rs | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/test_suite/tests/test_enum_internally_tagged.rs b/test_suite/tests/test_enum_internally_tagged.rs index e7beae0b3..904985d30 100644 --- a/test_suite/tests/test_enum_internally_tagged.rs +++ b/test_suite/tests/test_enum_internally_tagged.rs @@ -40,6 +40,7 @@ enum InternallyTagged { NewtypeNewtype(Newtype), NewtypeMap(BTreeMap), NewtypeStruct(Struct), + NewtypeEnum(Enum), Struct { a: u8 }, } @@ -182,6 +183,7 @@ fn wrong_tag() { `NewtypeNewtype`, \ `NewtypeMap`, \ `NewtypeStruct`, \ + `NewtypeEnum`, \ `Struct`", ); } @@ -545,18 +547,12 @@ fn borrow() { #[test] fn newtype_variant_containing_externally_tagged_enum() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "tag")] - enum Outer { - Inner(Enum), - } - assert_tokens( - &Outer::Inner(Enum::Unit), + &InternallyTagged::NewtypeEnum(Enum::Unit), &[ Token::Map { len: Some(2) }, Token::Str("tag"), - Token::Str("Inner"), + Token::Str("NewtypeEnum"), Token::Str("Unit"), Token::Unit, Token::MapEnd, @@ -564,11 +560,11 @@ fn newtype_variant_containing_externally_tagged_enum() { ); assert_tokens( - &Outer::Inner(Enum::Newtype(1)), + &InternallyTagged::NewtypeEnum(Enum::Newtype(1)), &[ Token::Map { len: Some(2) }, Token::Str("tag"), - Token::Str("Inner"), + Token::Str("NewtypeEnum"), Token::Str("Newtype"), Token::U8(1), Token::MapEnd, @@ -579,11 +575,11 @@ fn newtype_variant_containing_externally_tagged_enum() { // Content::Seq case // via ContentDeserializer::deserialize_enum assert_tokens( - &Outer::Inner(Enum::Tuple(1, 1)), + &InternallyTagged::NewtypeEnum(Enum::Tuple(1, 1)), &[ Token::Map { len: Some(2) }, Token::Str("tag"), - Token::Str("Inner"), + Token::Str("NewtypeEnum"), Token::Str("Tuple"), Token::TupleStruct { name: "Tuple", @@ -600,11 +596,11 @@ fn newtype_variant_containing_externally_tagged_enum() { // Content::Map case // via ContentDeserializer::deserialize_enum assert_tokens( - &Outer::Inner(Enum::Struct { f: 1 }), + &InternallyTagged::NewtypeEnum(Enum::Struct { f: 1 }), &[ Token::Map { len: Some(2) }, Token::Str("tag"), - Token::Str("Inner"), + Token::Str("NewtypeEnum"), Token::Str("Struct"), Token::Struct { name: "Struct", @@ -621,11 +617,11 @@ fn newtype_variant_containing_externally_tagged_enum() { // Content::Seq case // via ContentDeserializer::deserialize_enum assert_de_tokens( - &Outer::Inner(Enum::Struct { f: 1 }), + &InternallyTagged::NewtypeEnum(Enum::Struct { f: 1 }), &[ Token::Map { len: Some(2) }, Token::Str("tag"), - Token::Str("Inner"), + Token::Str("NewtypeEnum"), Token::Str("Struct"), Token::Seq { len: Some(1) }, Token::U8(1), // f From 7c0e6bd18f28eb15c622f7d3bb08a119ffe26929 Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 7 Aug 2023 22:55:35 +0500 Subject: [PATCH 148/258] Reuse type in struct_variant_containing_unit_variant --- .../tests/test_enum_internally_tagged.rs | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/test_suite/tests/test_enum_internally_tagged.rs b/test_suite/tests/test_enum_internally_tagged.rs index 904985d30..900a9b337 100644 --- a/test_suite/tests/test_enum_internally_tagged.rs +++ b/test_suite/tests/test_enum_internally_tagged.rs @@ -42,6 +42,7 @@ enum InternallyTagged { NewtypeStruct(Struct), NewtypeEnum(Enum), Struct { a: u8 }, + StructEnum { enum_: Enum }, } #[test] @@ -184,7 +185,8 @@ fn wrong_tag() { `NewtypeMap`, \ `NewtypeStruct`, \ `NewtypeEnum`, \ - `Struct`", + `Struct`, \ + `StructEnum`", ); } @@ -460,12 +462,6 @@ mod string_and_bytes { #[test] fn struct_variant_containing_unit_variant() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "tag")] - enum Message { - Log { level: Enum }, - } - assert_de_tokens( &Enum::Unit, &[ @@ -475,18 +471,18 @@ fn struct_variant_containing_unit_variant() { ], ); - let value = Message::Log { level: Enum::Unit }; + let value = InternallyTagged::StructEnum { enum_: Enum::Unit }; assert_de_tokens( &value, &[ Token::Struct { - name: "Message", + name: "InternallyTagged", len: 2, }, Token::Str("tag"), - Token::Str("Log"), - Token::Str("level"), + Token::Str("StructEnum"), + Token::Str("enum_"), Token::Enum { name: "Enum" }, Token::BorrowedStr("Unit"), Token::Unit, @@ -499,8 +495,8 @@ fn struct_variant_containing_unit_variant() { &[ Token::Map { len: Some(2) }, Token::Str("tag"), - Token::Str("Log"), - Token::Str("level"), + Token::Str("StructEnum"), + Token::Str("enum_"), Token::Enum { name: "Enum" }, Token::BorrowedStr("Unit"), Token::Unit, @@ -512,8 +508,8 @@ fn struct_variant_containing_unit_variant() { &value, &[ Token::Seq { len: Some(2) }, - Token::Str("Log"), - Token::Enum { name: "Enum" }, + Token::Str("StructEnum"), // tag + Token::Enum { name: "Enum" }, // enum_ Token::BorrowedStr("Unit"), Token::Unit, Token::SeqEnd, From 8bfe0d0ac04e01b9fd3658c5707c62da651d3770 Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 7 Aug 2023 22:51:46 +0500 Subject: [PATCH 149/258] Move and rename tests: - newtype_variant_containing_unit -> newtype_unit - newtype_variant_containing_unit_struct -> newtype_unit_struct - newtype_variant_containing_externally_tagged_enum -> newtype_enum - struct_variant_containing_unit_variant -> struct_enum --- .../tests/test_enum_internally_tagged.rs | 390 +++++++++--------- 1 file changed, 195 insertions(+), 195 deletions(-) diff --git a/test_suite/tests/test_enum_internally_tagged.rs b/test_suite/tests/test_enum_internally_tagged.rs index 900a9b337..916076052 100644 --- a/test_suite/tests/test_enum_internally_tagged.rs +++ b/test_suite/tests/test_enum_internally_tagged.rs @@ -70,6 +70,58 @@ fn unit() { ); } +#[test] +fn newtype_unit() { + let value = InternallyTagged::NewtypeUnit(()); + + assert_tokens( + &value, + &[ + Token::Map { len: Some(1) }, + Token::Str("tag"), + Token::Str("NewtypeUnit"), + Token::MapEnd, + ], + ); +} + +#[test] +fn newtype_unit_struct() { + let value = InternallyTagged::NewtypeUnitStruct(Unit); + + assert_tokens( + &value, + &[ + Token::Map { len: Some(1) }, + Token::Str("tag"), + Token::Str("NewtypeUnitStruct"), + Token::MapEnd, + ], + ); + + assert_de_tokens( + &value, + &[ + Token::Struct { + name: "InternallyTagged", + len: 1, + }, + Token::Str("tag"), + Token::Str("NewtypeUnitStruct"), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &value, + &[ + Token::Seq { len: Some(1) }, + Token::Str("NewtypeUnitStruct"), // tag + Token::SeqEnd, + ], + ); +} + #[test] fn newtype_newtype() { assert_tokens( @@ -135,6 +187,92 @@ fn newtype_struct() { ); } +#[test] +fn newtype_enum() { + assert_tokens( + &InternallyTagged::NewtypeEnum(Enum::Unit), + &[ + Token::Map { len: Some(2) }, + Token::Str("tag"), + Token::Str("NewtypeEnum"), + Token::Str("Unit"), + Token::Unit, + Token::MapEnd, + ], + ); + + assert_tokens( + &InternallyTagged::NewtypeEnum(Enum::Newtype(1)), + &[ + Token::Map { len: Some(2) }, + Token::Str("tag"), + Token::Str("NewtypeEnum"), + Token::Str("Newtype"), + Token::U8(1), + Token::MapEnd, + ], + ); + + // Reaches crate::private::de::content::VariantDeserializer::tuple_variant + // Content::Seq case + // via ContentDeserializer::deserialize_enum + assert_tokens( + &InternallyTagged::NewtypeEnum(Enum::Tuple(1, 1)), + &[ + Token::Map { len: Some(2) }, + Token::Str("tag"), + Token::Str("NewtypeEnum"), + Token::Str("Tuple"), + Token::TupleStruct { + name: "Tuple", + len: 2, + }, + Token::U8(1), + Token::U8(1), + Token::TupleStructEnd, + Token::MapEnd, + ], + ); + + // Reaches crate::private::de::content::VariantDeserializer::struct_variant + // Content::Map case + // via ContentDeserializer::deserialize_enum + assert_tokens( + &InternallyTagged::NewtypeEnum(Enum::Struct { f: 1 }), + &[ + Token::Map { len: Some(2) }, + Token::Str("tag"), + Token::Str("NewtypeEnum"), + Token::Str("Struct"), + Token::Struct { + name: "Struct", + len: 1, + }, + Token::Str("f"), + Token::U8(1), + Token::StructEnd, + Token::MapEnd, + ], + ); + + // Reaches crate::private::de::content::VariantDeserializer::struct_variant + // Content::Seq case + // via ContentDeserializer::deserialize_enum + assert_de_tokens( + &InternallyTagged::NewtypeEnum(Enum::Struct { f: 1 }), + &[ + Token::Map { len: Some(2) }, + Token::Str("tag"), + Token::Str("NewtypeEnum"), + Token::Str("Struct"), + Token::Seq { len: Some(1) }, + Token::U8(1), // f + Token::SeqEnd, + Token::MapEnd, + ], + ); +} + #[test] fn struct_() { assert_tokens( @@ -163,6 +301,63 @@ fn struct_() { ); } +#[test] +fn struct_enum() { + assert_de_tokens( + &Enum::Unit, + &[ + Token::Enum { name: "Enum" }, + Token::BorrowedStr("Unit"), + Token::Unit, + ], + ); + + let value = InternallyTagged::StructEnum { enum_: Enum::Unit }; + + assert_de_tokens( + &value, + &[ + Token::Struct { + name: "InternallyTagged", + len: 2, + }, + Token::Str("tag"), + Token::Str("StructEnum"), + Token::Str("enum_"), + Token::Enum { name: "Enum" }, + Token::BorrowedStr("Unit"), + Token::Unit, + Token::StructEnd, + ], + ); + + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::Str("tag"), + Token::Str("StructEnum"), + Token::Str("enum_"), + Token::Enum { name: "Enum" }, + Token::BorrowedStr("Unit"), + Token::Unit, + Token::MapEnd, + ], + ); + + assert_de_tokens( + &value, + &[ + Token::Seq { len: Some(2) }, + Token::Str("StructEnum"), // tag + Token::Enum { name: "Enum" }, // enum_ + Token::BorrowedStr("Unit"), + Token::Unit, + Token::SeqEnd, + ], + ); +} + #[test] fn wrong_tag() { assert_de_tokens_error::( @@ -460,63 +655,6 @@ mod string_and_bytes { } } -#[test] -fn struct_variant_containing_unit_variant() { - assert_de_tokens( - &Enum::Unit, - &[ - Token::Enum { name: "Enum" }, - Token::BorrowedStr("Unit"), - Token::Unit, - ], - ); - - let value = InternallyTagged::StructEnum { enum_: Enum::Unit }; - - assert_de_tokens( - &value, - &[ - Token::Struct { - name: "InternallyTagged", - len: 2, - }, - Token::Str("tag"), - Token::Str("StructEnum"), - Token::Str("enum_"), - Token::Enum { name: "Enum" }, - Token::BorrowedStr("Unit"), - Token::Unit, - Token::StructEnd, - ], - ); - - assert_de_tokens( - &value, - &[ - Token::Map { len: Some(2) }, - Token::Str("tag"), - Token::Str("StructEnum"), - Token::Str("enum_"), - Token::Enum { name: "Enum" }, - Token::BorrowedStr("Unit"), - Token::Unit, - Token::MapEnd, - ], - ); - - assert_de_tokens( - &value, - &[ - Token::Seq { len: Some(2) }, - Token::Str("StructEnum"), // tag - Token::Enum { name: "Enum" }, // enum_ - Token::BorrowedStr("Unit"), - Token::Unit, - Token::SeqEnd, - ], - ); -} - #[test] fn borrow() { #[derive(Debug, PartialEq, Serialize, Deserialize)] @@ -541,129 +679,6 @@ fn borrow() { ); } -#[test] -fn newtype_variant_containing_externally_tagged_enum() { - assert_tokens( - &InternallyTagged::NewtypeEnum(Enum::Unit), - &[ - Token::Map { len: Some(2) }, - Token::Str("tag"), - Token::Str("NewtypeEnum"), - Token::Str("Unit"), - Token::Unit, - Token::MapEnd, - ], - ); - - assert_tokens( - &InternallyTagged::NewtypeEnum(Enum::Newtype(1)), - &[ - Token::Map { len: Some(2) }, - Token::Str("tag"), - Token::Str("NewtypeEnum"), - Token::Str("Newtype"), - Token::U8(1), - Token::MapEnd, - ], - ); - - // Reaches crate::private::de::content::VariantDeserializer::tuple_variant - // Content::Seq case - // via ContentDeserializer::deserialize_enum - assert_tokens( - &InternallyTagged::NewtypeEnum(Enum::Tuple(1, 1)), - &[ - Token::Map { len: Some(2) }, - Token::Str("tag"), - Token::Str("NewtypeEnum"), - Token::Str("Tuple"), - Token::TupleStruct { - name: "Tuple", - len: 2, - }, - Token::U8(1), - Token::U8(1), - Token::TupleStructEnd, - Token::MapEnd, - ], - ); - - // Reaches crate::private::de::content::VariantDeserializer::struct_variant - // Content::Map case - // via ContentDeserializer::deserialize_enum - assert_tokens( - &InternallyTagged::NewtypeEnum(Enum::Struct { f: 1 }), - &[ - Token::Map { len: Some(2) }, - Token::Str("tag"), - Token::Str("NewtypeEnum"), - Token::Str("Struct"), - Token::Struct { - name: "Struct", - len: 1, - }, - Token::Str("f"), - Token::U8(1), - Token::StructEnd, - Token::MapEnd, - ], - ); - - // Reaches crate::private::de::content::VariantDeserializer::struct_variant - // Content::Seq case - // via ContentDeserializer::deserialize_enum - assert_de_tokens( - &InternallyTagged::NewtypeEnum(Enum::Struct { f: 1 }), - &[ - Token::Map { len: Some(2) }, - Token::Str("tag"), - Token::Str("NewtypeEnum"), - Token::Str("Struct"), - Token::Seq { len: Some(1) }, - Token::U8(1), // f - Token::SeqEnd, - Token::MapEnd, - ], - ); -} - -#[test] -fn newtype_variant_containing_unit_struct() { - let value = InternallyTagged::NewtypeUnitStruct(Unit); - - assert_tokens( - &value, - &[ - Token::Map { len: Some(1) }, - Token::Str("tag"), - Token::Str("NewtypeUnitStruct"), - Token::MapEnd, - ], - ); - - assert_de_tokens( - &value, - &[ - Token::Struct { - name: "InternallyTagged", - len: 1, - }, - Token::Str("tag"), - Token::Str("NewtypeUnitStruct"), - Token::StructEnd, - ], - ); - - assert_de_tokens( - &value, - &[ - Token::Seq { len: Some(1) }, - Token::Str("NewtypeUnitStruct"), // tag - Token::SeqEnd, - ], - ); -} - #[test] fn with_skipped_conflict() { #[derive(Debug, PartialEq, Serialize, Deserialize)] @@ -734,21 +749,6 @@ fn containing_flatten() { ); } -#[test] -fn newtype_variant_containing_unit() { - let value = InternallyTagged::NewtypeUnit(()); - - assert_tokens( - &value, - &[ - Token::Map { len: Some(1) }, - Token::Str("tag"), - Token::Str("NewtypeUnit"), - Token::MapEnd, - ], - ); -} - #[test] fn unit_variant_with_unknown_fields() { let value = InternallyTagged::Unit; From 4987fd15f7bf26c5c7809fd772a218e8782a6d59 Mon Sep 17 00:00:00 2001 From: Mingun Date: Tue, 8 Aug 2023 00:54:36 +0500 Subject: [PATCH 150/258] Convert newtype_enum and struct_enum tests into modules Separate testing each variant kind of enum (unit, newtype, tuple, struct) results in more specific information if that checks fail (review this commit with "ignore whitespace changes" option on) --- .../tests/test_enum_internally_tagged.rs | 279 ++++++++++-------- 1 file changed, 148 insertions(+), 131 deletions(-) diff --git a/test_suite/tests/test_enum_internally_tagged.rs b/test_suite/tests/test_enum_internally_tagged.rs index 916076052..38c8dc61a 100644 --- a/test_suite/tests/test_enum_internally_tagged.rs +++ b/test_suite/tests/test_enum_internally_tagged.rs @@ -187,90 +187,103 @@ fn newtype_struct() { ); } -#[test] -fn newtype_enum() { - assert_tokens( - &InternallyTagged::NewtypeEnum(Enum::Unit), - &[ - Token::Map { len: Some(2) }, - Token::Str("tag"), - Token::Str("NewtypeEnum"), - Token::Str("Unit"), - Token::Unit, - Token::MapEnd, - ], - ); +mod newtype_enum { + use super::*; - assert_tokens( - &InternallyTagged::NewtypeEnum(Enum::Newtype(1)), - &[ - Token::Map { len: Some(2) }, - Token::Str("tag"), - Token::Str("NewtypeEnum"), - Token::Str("Newtype"), - Token::U8(1), - Token::MapEnd, - ], - ); + #[test] + fn unit() { + assert_tokens( + &InternallyTagged::NewtypeEnum(Enum::Unit), + &[ + Token::Map { len: Some(2) }, + Token::Str("tag"), + Token::Str("NewtypeEnum"), + Token::Str("Unit"), + Token::Unit, + Token::MapEnd, + ], + ); + } - // Reaches crate::private::de::content::VariantDeserializer::tuple_variant - // Content::Seq case - // via ContentDeserializer::deserialize_enum - assert_tokens( - &InternallyTagged::NewtypeEnum(Enum::Tuple(1, 1)), - &[ - Token::Map { len: Some(2) }, - Token::Str("tag"), - Token::Str("NewtypeEnum"), - Token::Str("Tuple"), - Token::TupleStruct { - name: "Tuple", - len: 2, - }, - Token::U8(1), - Token::U8(1), - Token::TupleStructEnd, - Token::MapEnd, - ], - ); + #[test] + fn newtype() { + assert_tokens( + &InternallyTagged::NewtypeEnum(Enum::Newtype(1)), + &[ + Token::Map { len: Some(2) }, + Token::Str("tag"), + Token::Str("NewtypeEnum"), + Token::Str("Newtype"), + Token::U8(1), + Token::MapEnd, + ], + ); + } - // Reaches crate::private::de::content::VariantDeserializer::struct_variant - // Content::Map case - // via ContentDeserializer::deserialize_enum - assert_tokens( - &InternallyTagged::NewtypeEnum(Enum::Struct { f: 1 }), - &[ - Token::Map { len: Some(2) }, - Token::Str("tag"), - Token::Str("NewtypeEnum"), - Token::Str("Struct"), - Token::Struct { - name: "Struct", - len: 1, - }, - Token::Str("f"), - Token::U8(1), - Token::StructEnd, - Token::MapEnd, - ], - ); + #[test] + fn tuple() { + // Reaches crate::private::de::content::VariantDeserializer::tuple_variant + // Content::Seq case + // via ContentDeserializer::deserialize_enum + assert_tokens( + &InternallyTagged::NewtypeEnum(Enum::Tuple(1, 1)), + &[ + Token::Map { len: Some(2) }, + Token::Str("tag"), + Token::Str("NewtypeEnum"), + Token::Str("Tuple"), + Token::TupleStruct { + name: "Tuple", + len: 2, + }, + Token::U8(1), + Token::U8(1), + Token::TupleStructEnd, + Token::MapEnd, + ], + ); + } - // Reaches crate::private::de::content::VariantDeserializer::struct_variant - // Content::Seq case - // via ContentDeserializer::deserialize_enum - assert_de_tokens( - &InternallyTagged::NewtypeEnum(Enum::Struct { f: 1 }), - &[ - Token::Map { len: Some(2) }, - Token::Str("tag"), - Token::Str("NewtypeEnum"), - Token::Str("Struct"), - Token::Seq { len: Some(1) }, - Token::U8(1), // f - Token::SeqEnd, - Token::MapEnd, - ], - ); + #[test] + fn struct_() { + // Reaches crate::private::de::content::VariantDeserializer::struct_variant + // Content::Map case + // via ContentDeserializer::deserialize_enum + assert_tokens( + &InternallyTagged::NewtypeEnum(Enum::Struct { f: 1 }), + &[ + Token::Map { len: Some(2) }, + Token::Str("tag"), + Token::Str("NewtypeEnum"), + Token::Str("Struct"), + Token::Struct { + name: "Struct", + len: 1, + }, + Token::Str("f"), + Token::U8(1), + Token::StructEnd, + Token::MapEnd, + ], + ); + + // Reaches crate::private::de::content::VariantDeserializer::struct_variant + // Content::Seq case + // via ContentDeserializer::deserialize_enum + assert_de_tokens( + &InternallyTagged::NewtypeEnum(Enum::Struct { f: 1 }), + &[ + Token::Map { len: Some(2) }, + Token::Str("tag"), + Token::Str("NewtypeEnum"), + Token::Str("Struct"), + Token::Seq { len: Some(1) }, + Token::U8(1), // f + Token::SeqEnd, + Token::MapEnd, + ], + ); + } } #[test] @@ -301,61 +314,65 @@ fn struct_() { ); } -#[test] -fn struct_enum() { - assert_de_tokens( - &Enum::Unit, - &[ - Token::Enum { name: "Enum" }, - Token::BorrowedStr("Unit"), - Token::Unit, - ], - ); +mod struct_enum { + use super::*; - let value = InternallyTagged::StructEnum { enum_: Enum::Unit }; + #[test] + fn unit() { + assert_de_tokens( + &Enum::Unit, + &[ + Token::Enum { name: "Enum" }, + Token::BorrowedStr("Unit"), + Token::Unit, + ], + ); - assert_de_tokens( - &value, - &[ - Token::Struct { - name: "InternallyTagged", - len: 2, - }, - Token::Str("tag"), - Token::Str("StructEnum"), - Token::Str("enum_"), - Token::Enum { name: "Enum" }, - Token::BorrowedStr("Unit"), - Token::Unit, - Token::StructEnd, - ], - ); + let value = InternallyTagged::StructEnum { enum_: Enum::Unit }; - assert_de_tokens( - &value, - &[ - Token::Map { len: Some(2) }, - Token::Str("tag"), - Token::Str("StructEnum"), - Token::Str("enum_"), - Token::Enum { name: "Enum" }, - Token::BorrowedStr("Unit"), - Token::Unit, - Token::MapEnd, - ], - ); + assert_de_tokens( + &value, + &[ + Token::Struct { + name: "InternallyTagged", + len: 2, + }, + Token::Str("tag"), + Token::Str("StructEnum"), + Token::Str("enum_"), + Token::Enum { name: "Enum" }, + Token::BorrowedStr("Unit"), + Token::Unit, + Token::StructEnd, + ], + ); - assert_de_tokens( - &value, - &[ - Token::Seq { len: Some(2) }, - Token::Str("StructEnum"), // tag - Token::Enum { name: "Enum" }, // enum_ - Token::BorrowedStr("Unit"), - Token::Unit, - Token::SeqEnd, - ], - ); + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::Str("tag"), + Token::Str("StructEnum"), + Token::Str("enum_"), + Token::Enum { name: "Enum" }, + Token::BorrowedStr("Unit"), + Token::Unit, + Token::MapEnd, + ], + ); + + assert_de_tokens( + &value, + &[ + Token::Seq { len: Some(2) }, + Token::Str("StructEnum"), // tag + Token::Enum { name: "Enum" }, // enum_ + Token::BorrowedStr("Unit"), + Token::Unit, + Token::SeqEnd, + ], + ); + } } #[test] From 47954502af93d856aca1fb92d8fecb931e469ff1 Mon Sep 17 00:00:00 2001 From: Mingun Date: Tue, 8 Aug 2023 01:20:15 +0500 Subject: [PATCH 151/258] Add tests with borrowed strings for the tag field name and tag value --- .../tests/test_enum_internally_tagged.rs | 268 ++++++++++++++++-- 1 file changed, 252 insertions(+), 16 deletions(-) diff --git a/test_suite/tests/test_enum_internally_tagged.rs b/test_suite/tests/test_enum_internally_tagged.rs index 38c8dc61a..4c8002564 100644 --- a/test_suite/tests/test_enum_internally_tagged.rs +++ b/test_suite/tests/test_enum_internally_tagged.rs @@ -59,12 +59,32 @@ fn unit() { Token::StructEnd, ], ); + assert_de_tokens( + &InternallyTagged::Unit, + &[ + Token::Struct { + name: "InternallyTagged", + len: 1, + }, + Token::BorrowedStr("tag"), + Token::BorrowedStr("Unit"), + Token::StructEnd, + ], + ); assert_de_tokens( &InternallyTagged::Unit, &[ Token::Seq { len: Some(1) }, - Token::Str("Unit"), + Token::Str("Unit"), // tag + Token::SeqEnd, + ], + ); + assert_de_tokens( + &InternallyTagged::Unit, + &[ + Token::Seq { len: Some(1) }, + Token::BorrowedStr("Unit"), // tag Token::SeqEnd, ], ); @@ -83,6 +103,15 @@ fn newtype_unit() { Token::MapEnd, ], ); + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(1) }, + Token::BorrowedStr("tag"), + Token::BorrowedStr("NewtypeUnit"), + Token::MapEnd, + ], + ); } #[test] @@ -98,6 +127,15 @@ fn newtype_unit_struct() { Token::MapEnd, ], ); + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(1) }, + Token::BorrowedStr("tag"), + Token::BorrowedStr("NewtypeUnitStruct"), + Token::MapEnd, + ], + ); assert_de_tokens( &value, @@ -111,6 +149,18 @@ fn newtype_unit_struct() { Token::StructEnd, ], ); + assert_de_tokens( + &value, + &[ + Token::Struct { + name: "InternallyTagged", + len: 1, + }, + Token::BorrowedStr("tag"), + Token::BorrowedStr("NewtypeUnitStruct"), + Token::StructEnd, + ], + ); assert_de_tokens( &value, @@ -120,6 +170,14 @@ fn newtype_unit_struct() { Token::SeqEnd, ], ); + assert_de_tokens( + &value, + &[ + Token::Seq { len: Some(1) }, + Token::BorrowedStr("NewtypeUnitStruct"), // tag + Token::SeqEnd, + ], + ); } #[test] @@ -137,8 +195,10 @@ fn newtype_newtype() { #[test] fn newtype_map() { + let value = InternallyTagged::NewtypeMap(BTreeMap::new()); + assert_tokens( - &InternallyTagged::NewtypeMap(BTreeMap::new()), + &value, &[ Token::Map { len: Some(1) }, Token::Str("tag"), @@ -146,11 +206,20 @@ fn newtype_map() { Token::MapEnd, ], ); + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(1) }, + Token::BorrowedStr("tag"), + Token::BorrowedStr("NewtypeMap"), + Token::MapEnd, + ], + ); assert_de_tokens_error::( &[ Token::Seq { len: Some(2) }, - Token::Str("NewtypeMap"), + Token::Str("NewtypeMap"), // tag Token::Map { len: Some(0) }, Token::MapEnd, Token::SeqEnd, @@ -161,8 +230,10 @@ fn newtype_map() { #[test] fn newtype_struct() { + let value = InternallyTagged::NewtypeStruct(Struct { f: 6 }); + assert_tokens( - &InternallyTagged::NewtypeStruct(Struct { f: 6 }), + &value, &[ Token::Struct { name: "Struct", @@ -175,12 +246,35 @@ fn newtype_struct() { Token::StructEnd, ], ); + assert_de_tokens( + &value, + &[ + Token::Struct { + name: "Struct", + len: 2, + }, + Token::BorrowedStr("tag"), + Token::BorrowedStr("NewtypeStruct"), + Token::BorrowedStr("f"), + Token::U8(6), + Token::StructEnd, + ], + ); assert_de_tokens( - &InternallyTagged::NewtypeStruct(Struct { f: 6 }), + &value, + &[ + Token::Seq { len: Some(2) }, + Token::Str("NewtypeStruct"), // tag + Token::U8(6), + Token::SeqEnd, + ], + ); + assert_de_tokens( + &value, &[ Token::Seq { len: Some(2) }, - Token::Str("NewtypeStruct"), + Token::BorrowedStr("NewtypeStruct"), // tag Token::U8(6), Token::SeqEnd, ], @@ -192,8 +286,10 @@ mod newtype_enum { #[test] fn unit() { + let value = InternallyTagged::NewtypeEnum(Enum::Unit); + assert_tokens( - &InternallyTagged::NewtypeEnum(Enum::Unit), + &value, &[ Token::Map { len: Some(2) }, Token::Str("tag"), @@ -203,12 +299,25 @@ mod newtype_enum { Token::MapEnd, ], ); + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::BorrowedStr("tag"), + Token::BorrowedStr("NewtypeEnum"), + Token::BorrowedStr("Unit"), + Token::Unit, + Token::MapEnd, + ], + ); } #[test] fn newtype() { + let value = InternallyTagged::NewtypeEnum(Enum::Newtype(1)); + assert_tokens( - &InternallyTagged::NewtypeEnum(Enum::Newtype(1)), + &value, &[ Token::Map { len: Some(2) }, Token::Str("tag"), @@ -218,15 +327,28 @@ mod newtype_enum { Token::MapEnd, ], ); + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::BorrowedStr("tag"), + Token::BorrowedStr("NewtypeEnum"), + Token::BorrowedStr("Newtype"), + Token::U8(1), + Token::MapEnd, + ], + ); } #[test] fn tuple() { + let value = InternallyTagged::NewtypeEnum(Enum::Tuple(1, 1)); + // Reaches crate::private::de::content::VariantDeserializer::tuple_variant // Content::Seq case // via ContentDeserializer::deserialize_enum assert_tokens( - &InternallyTagged::NewtypeEnum(Enum::Tuple(1, 1)), + &value, &[ Token::Map { len: Some(2) }, Token::Str("tag"), @@ -242,15 +364,34 @@ mod newtype_enum { Token::MapEnd, ], ); + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::BorrowedStr("tag"), + Token::BorrowedStr("NewtypeEnum"), + Token::BorrowedStr("Tuple"), + Token::TupleStruct { + name: "Tuple", + len: 2, + }, + Token::U8(1), + Token::U8(1), + Token::TupleStructEnd, + Token::MapEnd, + ], + ); } #[test] fn struct_() { + let value = InternallyTagged::NewtypeEnum(Enum::Struct { f: 1 }); + // Reaches crate::private::de::content::VariantDeserializer::struct_variant // Content::Map case // via ContentDeserializer::deserialize_enum assert_tokens( - &InternallyTagged::NewtypeEnum(Enum::Struct { f: 1 }), + &value, &[ Token::Map { len: Some(2) }, Token::Str("tag"), @@ -266,12 +407,29 @@ mod newtype_enum { Token::MapEnd, ], ); + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::BorrowedStr("tag"), + Token::BorrowedStr("NewtypeEnum"), + Token::BorrowedStr("Struct"), + Token::Struct { + name: "Struct", + len: 1, + }, + Token::BorrowedStr("f"), + Token::U8(1), + Token::StructEnd, + Token::MapEnd, + ], + ); // Reaches crate::private::de::content::VariantDeserializer::struct_variant // Content::Seq case // via ContentDeserializer::deserialize_enum assert_de_tokens( - &InternallyTagged::NewtypeEnum(Enum::Struct { f: 1 }), + &value, &[ Token::Map { len: Some(2) }, Token::Str("tag"), @@ -283,13 +441,28 @@ mod newtype_enum { Token::MapEnd, ], ); + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::BorrowedStr("tag"), + Token::BorrowedStr("NewtypeEnum"), + Token::BorrowedStr("Struct"), + Token::Seq { len: Some(1) }, + Token::U8(1), // f + Token::SeqEnd, + Token::MapEnd, + ], + ); } } #[test] fn struct_() { + let value = InternallyTagged::Struct { a: 1 }; + assert_tokens( - &InternallyTagged::Struct { a: 1 }, + &value, &[ Token::Struct { name: "InternallyTagged", @@ -302,12 +475,35 @@ fn struct_() { Token::StructEnd, ], ); + assert_de_tokens( + &value, + &[ + Token::Struct { + name: "InternallyTagged", + len: 2, + }, + Token::BorrowedStr("tag"), + Token::BorrowedStr("Struct"), + Token::BorrowedStr("a"), + Token::U8(1), + Token::StructEnd, + ], + ); assert_de_tokens( - &InternallyTagged::Struct { a: 1 }, + &value, &[ Token::Seq { len: Some(2) }, - Token::Str("Struct"), + Token::Str("Struct"), // tag + Token::U8(1), + Token::SeqEnd, + ], + ); + assert_de_tokens( + &value, + &[ + Token::Seq { len: Some(2) }, + Token::BorrowedStr("Struct"), // tag Token::U8(1), Token::SeqEnd, ], @@ -330,7 +526,7 @@ mod struct_enum { let value = InternallyTagged::StructEnum { enum_: Enum::Unit }; - assert_de_tokens( + assert_tokens( &value, &[ Token::Struct { @@ -341,6 +537,22 @@ mod struct_enum { Token::Str("StructEnum"), Token::Str("enum_"), Token::Enum { name: "Enum" }, + Token::Str("Unit"), + Token::Unit, + Token::StructEnd, + ], + ); + assert_de_tokens( + &value, + &[ + Token::Struct { + name: "InternallyTagged", + len: 2, + }, + Token::BorrowedStr("tag"), + Token::BorrowedStr("StructEnum"), + Token::BorrowedStr("enum_"), + Token::Enum { name: "Enum" }, Token::BorrowedStr("Unit"), Token::Unit, Token::StructEnd, @@ -355,6 +567,19 @@ mod struct_enum { Token::Str("StructEnum"), Token::Str("enum_"), Token::Enum { name: "Enum" }, + Token::Str("Unit"), + Token::Unit, + Token::MapEnd, + ], + ); + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::BorrowedStr("tag"), + Token::BorrowedStr("StructEnum"), + Token::BorrowedStr("enum_"), + Token::Enum { name: "Enum" }, Token::BorrowedStr("Unit"), Token::Unit, Token::MapEnd, @@ -367,6 +592,17 @@ mod struct_enum { Token::Seq { len: Some(2) }, Token::Str("StructEnum"), // tag Token::Enum { name: "Enum" }, // enum_ + Token::Str("Unit"), + Token::Unit, + Token::SeqEnd, + ], + ); + assert_de_tokens( + &value, + &[ + Token::Seq { len: Some(2) }, + Token::BorrowedStr("StructEnum"), // tag + Token::Enum { name: "Enum" }, // enum_ Token::BorrowedStr("Unit"), Token::Unit, Token::SeqEnd, @@ -786,7 +1022,7 @@ fn unit_variant_with_unknown_fields() { assert_de_tokens_error::( &[ Token::Seq { len: None }, - Token::Str("Unit"), + Token::Str("Unit"), // tag Token::I32(0), Token::SeqEnd, ], From 71ed1f2f127ef3847f35ecbe0cd8e2b5e7b42be1 Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 3 Oct 2022 23:07:12 +0500 Subject: [PATCH 152/258] Add tests for special and general cases for internally tagged enums Special case is the tag field first (so the enum variant are known after reading the first entry from map). General case is the tag field not the first (so we need to buffer entries until we found an entry with tag) --- .../tests/test_enum_internally_tagged.rs | 396 +++++++++++++++++- 1 file changed, 389 insertions(+), 7 deletions(-) diff --git a/test_suite/tests/test_enum_internally_tagged.rs b/test_suite/tests/test_enum_internally_tagged.rs index 4c8002564..9527da581 100644 --- a/test_suite/tests/test_enum_internally_tagged.rs +++ b/test_suite/tests/test_enum_internally_tagged.rs @@ -11,6 +11,7 @@ mod bytes; use serde_derive::{Deserialize, Serialize}; use serde_test::{assert_de_tokens, assert_de_tokens_error, assert_tokens, Token}; use std::collections::BTreeMap; +use std::iter::FromIterator; #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Unit; @@ -197,6 +198,7 @@ fn newtype_newtype() { fn newtype_map() { let value = InternallyTagged::NewtypeMap(BTreeMap::new()); + // Special case: empty map assert_tokens( &value, &[ @@ -216,6 +218,59 @@ fn newtype_map() { ], ); + let value = InternallyTagged::NewtypeMap(BTreeMap::from_iter([( + "field".to_string(), + "value".to_string(), + )])); + + // Special case: tag field ("tag") is the first field + assert_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::Str("tag"), + Token::Str("NewtypeMap"), + Token::Str("field"), + Token::Str("value"), + Token::MapEnd, + ], + ); + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::BorrowedStr("tag"), + Token::BorrowedStr("NewtypeMap"), + Token::BorrowedStr("field"), + Token::BorrowedStr("value"), + Token::MapEnd, + ], + ); + + // General case: tag field ("tag") is not the first field + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::Str("field"), + Token::Str("value"), + Token::Str("tag"), + Token::Str("NewtypeMap"), + Token::MapEnd, + ], + ); + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::BorrowedStr("field"), + Token::BorrowedStr("value"), + Token::BorrowedStr("tag"), + Token::BorrowedStr("NewtypeMap"), + Token::MapEnd, + ], + ); + assert_de_tokens_error::( &[ Token::Seq { len: Some(2) }, @@ -232,6 +287,7 @@ fn newtype_map() { fn newtype_struct() { let value = InternallyTagged::NewtypeStruct(Struct { f: 6 }); + // Special case: tag field ("tag") is the first field assert_tokens( &value, &[ @@ -261,6 +317,36 @@ fn newtype_struct() { ], ); + // General case: tag field ("tag") is not the first field + assert_de_tokens( + &value, + &[ + Token::Struct { + name: "Struct", + len: 2, + }, + Token::Str("f"), + Token::U8(6), + Token::Str("tag"), + Token::Str("NewtypeStruct"), + Token::StructEnd, + ], + ); + assert_de_tokens( + &value, + &[ + Token::Struct { + name: "Struct", + len: 2, + }, + Token::BorrowedStr("f"), + Token::U8(6), + Token::BorrowedStr("tag"), + Token::BorrowedStr("NewtypeStruct"), + Token::StructEnd, + ], + ); + assert_de_tokens( &value, &[ @@ -288,6 +374,7 @@ mod newtype_enum { fn unit() { let value = InternallyTagged::NewtypeEnum(Enum::Unit); + // Special case: tag field ("tag") is the first field assert_tokens( &value, &[ @@ -310,12 +397,37 @@ mod newtype_enum { Token::MapEnd, ], ); + + // General case: tag field ("tag") is not the first field + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::Str("Unit"), + Token::Unit, + Token::Str("tag"), + Token::Str("NewtypeEnum"), + Token::MapEnd, + ], + ); + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::BorrowedStr("Unit"), + Token::Unit, + Token::BorrowedStr("tag"), + Token::BorrowedStr("NewtypeEnum"), + Token::MapEnd, + ], + ); } #[test] fn newtype() { let value = InternallyTagged::NewtypeEnum(Enum::Newtype(1)); + // Special case: tag field ("tag") is the first field assert_tokens( &value, &[ @@ -338,15 +450,37 @@ mod newtype_enum { Token::MapEnd, ], ); + + // General case: tag field ("tag") is not the first field + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::Str("Newtype"), + Token::U8(1), + Token::Str("tag"), + Token::Str("NewtypeEnum"), + Token::MapEnd, + ], + ); + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::BorrowedStr("Newtype"), + Token::U8(1), + Token::BorrowedStr("tag"), + Token::BorrowedStr("NewtypeEnum"), + Token::MapEnd, + ], + ); } #[test] fn tuple() { let value = InternallyTagged::NewtypeEnum(Enum::Tuple(1, 1)); - // Reaches crate::private::de::content::VariantDeserializer::tuple_variant - // Content::Seq case - // via ContentDeserializer::deserialize_enum + // Special case: tag field ("tag") is the first field assert_tokens( &value, &[ @@ -381,15 +515,52 @@ mod newtype_enum { Token::MapEnd, ], ); + + // Special case: tag field ("tag") is not the first field + // Reaches crate::private::de::content::VariantDeserializer::tuple_variant + // Content::Seq case + // via ContentDeserializer::deserialize_enum + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::Str("Tuple"), + Token::TupleStruct { + name: "Tuple", + len: 2, + }, + Token::U8(1), + Token::U8(1), + Token::TupleStructEnd, + Token::Str("tag"), + Token::Str("NewtypeEnum"), + Token::MapEnd, + ], + ); + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::BorrowedStr("Tuple"), + Token::TupleStruct { + name: "Tuple", + len: 2, + }, + Token::U8(1), + Token::U8(1), + Token::TupleStructEnd, + Token::BorrowedStr("tag"), + Token::BorrowedStr("NewtypeEnum"), + Token::MapEnd, + ], + ); } #[test] fn struct_() { let value = InternallyTagged::NewtypeEnum(Enum::Struct { f: 1 }); - // Reaches crate::private::de::content::VariantDeserializer::struct_variant - // Content::Map case - // via ContentDeserializer::deserialize_enum + // Special case: tag field ("tag") is the first field assert_tokens( &value, &[ @@ -425,9 +596,46 @@ mod newtype_enum { ], ); + // General case: tag field ("tag") is not the first field // Reaches crate::private::de::content::VariantDeserializer::struct_variant - // Content::Seq case + // Content::Map case // via ContentDeserializer::deserialize_enum + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::Str("Struct"), + Token::Struct { + name: "Struct", + len: 1, + }, + Token::Str("f"), + Token::U8(1), + Token::StructEnd, + Token::Str("tag"), + Token::Str("NewtypeEnum"), + Token::MapEnd, + ], + ); + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::BorrowedStr("Struct"), + Token::Struct { + name: "Struct", + len: 1, + }, + Token::BorrowedStr("f"), + Token::U8(1), + Token::StructEnd, + Token::BorrowedStr("tag"), + Token::BorrowedStr("NewtypeEnum"), + Token::MapEnd, + ], + ); + + // Special case: tag field ("tag") is the first field assert_de_tokens( &value, &[ @@ -454,6 +662,37 @@ mod newtype_enum { Token::MapEnd, ], ); + + // General case: tag field ("tag") is not the first field + // Reaches crate::private::de::content::VariantDeserializer::struct_variant + // Content::Seq case + // via ContentDeserializer::deserialize_enum + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::Str("Struct"), + Token::Seq { len: Some(1) }, + Token::U8(1), // f + Token::SeqEnd, + Token::Str("tag"), + Token::Str("NewtypeEnum"), + Token::MapEnd, + ], + ); + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::BorrowedStr("Struct"), + Token::Seq { len: Some(1) }, + Token::U8(1), // f + Token::SeqEnd, + Token::BorrowedStr("tag"), + Token::BorrowedStr("NewtypeEnum"), + Token::MapEnd, + ], + ); } } @@ -461,6 +700,7 @@ mod newtype_enum { fn struct_() { let value = InternallyTagged::Struct { a: 1 }; + // Special case: tag field ("tag") is the first field assert_tokens( &value, &[ @@ -490,6 +730,84 @@ fn struct_() { ], ); + // General case: tag field ("tag") is not the first field + assert_de_tokens( + &value, + &[ + Token::Struct { + name: "InternallyTagged", + len: 2, + }, + Token::Str("a"), + Token::U8(1), + Token::Str("tag"), + Token::Str("Struct"), + Token::StructEnd, + ], + ); + assert_de_tokens( + &value, + &[ + Token::Struct { + name: "InternallyTagged", + len: 2, + }, + Token::BorrowedStr("a"), + Token::U8(1), + Token::BorrowedStr("tag"), + Token::BorrowedStr("Struct"), + Token::StructEnd, + ], + ); + + // Special case: tag field ("tag") is the first field + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::Str("tag"), + Token::Str("Struct"), + Token::Str("a"), + Token::U8(1), + Token::MapEnd, + ], + ); + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::BorrowedStr("tag"), + Token::BorrowedStr("Struct"), + Token::BorrowedStr("a"), + Token::U8(1), + Token::MapEnd, + ], + ); + + // General case: tag field ("tag") is not the first field + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::Str("a"), + Token::U8(1), + Token::Str("tag"), + Token::Str("Struct"), + Token::MapEnd, + ], + ); + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::BorrowedStr("a"), + Token::U8(1), + Token::BorrowedStr("tag"), + Token::BorrowedStr("Struct"), + Token::MapEnd, + ], + ); + assert_de_tokens( &value, &[ @@ -526,6 +844,7 @@ mod struct_enum { let value = InternallyTagged::StructEnum { enum_: Enum::Unit }; + // Special case: tag field ("tag") is the first field assert_tokens( &value, &[ @@ -559,6 +878,41 @@ mod struct_enum { ], ); + // General case: tag field ("tag") is not the first field + assert_de_tokens( + &value, + &[ + Token::Struct { + name: "InternallyTagged", + len: 2, + }, + Token::Str("enum_"), + Token::Enum { name: "Enum" }, + Token::Str("Unit"), + Token::Unit, + Token::Str("tag"), + Token::Str("StructEnum"), + Token::StructEnd, + ], + ); + assert_de_tokens( + &value, + &[ + Token::Struct { + name: "InternallyTagged", + len: 2, + }, + Token::BorrowedStr("enum_"), + Token::Enum { name: "Enum" }, + Token::BorrowedStr("Unit"), + Token::Unit, + Token::BorrowedStr("tag"), + Token::BorrowedStr("StructEnum"), + Token::StructEnd, + ], + ); + + // Special case: tag field ("tag") is the first field assert_de_tokens( &value, &[ @@ -586,6 +940,34 @@ mod struct_enum { ], ); + // General case: tag field ("tag") is not the first field + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::Str("enum_"), + Token::Enum { name: "Enum" }, + Token::Str("Unit"), + Token::Unit, + Token::Str("tag"), + Token::Str("StructEnum"), + Token::MapEnd, + ], + ); + assert_de_tokens( + &value, + &[ + Token::Map { len: Some(2) }, + Token::BorrowedStr("enum_"), + Token::Enum { name: "Enum" }, + Token::BorrowedStr("Unit"), + Token::Unit, + Token::BorrowedStr("tag"), + Token::BorrowedStr("StructEnum"), + Token::MapEnd, + ], + ); + assert_de_tokens( &value, &[ From 2adb0e99b024aab039a9fc6fdd384e84c8ae8297 Mon Sep 17 00:00:00 2001 From: Mingun Date: Tue, 8 Aug 2023 01:56:51 +0500 Subject: [PATCH 153/258] Add additional checks for unit and newtype_unit tests - check that unit variant can be deserialized from a map - check that newtype variant with unit can be deserialized from a struct --- .../tests/test_enum_internally_tagged.rs | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/test_suite/tests/test_enum_internally_tagged.rs b/test_suite/tests/test_enum_internally_tagged.rs index 9527da581..b4d428c4d 100644 --- a/test_suite/tests/test_enum_internally_tagged.rs +++ b/test_suite/tests/test_enum_internally_tagged.rs @@ -73,6 +73,25 @@ fn unit() { ], ); + assert_de_tokens( + &InternallyTagged::Unit, + &[ + Token::Map { len: Some(1) }, + Token::Str("tag"), + Token::Str("Unit"), + Token::MapEnd, + ], + ); + assert_de_tokens( + &InternallyTagged::Unit, + &[ + Token::Map { len: Some(1) }, + Token::BorrowedStr("tag"), + Token::BorrowedStr("Unit"), + Token::MapEnd, + ], + ); + assert_de_tokens( &InternallyTagged::Unit, &[ @@ -113,6 +132,31 @@ fn newtype_unit() { Token::MapEnd, ], ); + + assert_de_tokens( + &value, + &[ + Token::Struct { + name: "InternallyTagged", + len: 1, + }, + Token::Str("tag"), + Token::Str("NewtypeUnit"), + Token::StructEnd, + ], + ); + assert_de_tokens( + &value, + &[ + Token::Struct { + name: "InternallyTagged", + len: 1, + }, + Token::BorrowedStr("tag"), + Token::BorrowedStr("NewtypeUnit"), + Token::StructEnd, + ], + ); } #[test] From 5e37ade519df3ad1c82d18b12d7b2216e549678e Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 14 Aug 2023 01:46:37 +0500 Subject: [PATCH 154/258] Move all adjacently tagged enum tests (except flatten) into a dedicated module Moved and renamed: From test_annotatons - test_adjacently_tagged_enum_bytes => bytes - flatten::enum_::adjacently_tagged::straitforward=> struct_with_flatten - test_expecting_message_adjacently_tagged_enum => expecting_message - test_partially_untagged_adjacently_tagged_enum => partially_untagged From test_macros - test_adjacently_tagged_newtype_struct => newtype_with_newtype - test_adjacently_tagged_enum - test_adjacently_tagged_enum_deny_unknown_fields => deny_unknown_fields --- test_suite/tests/test_annotations.rs | 157 ----- .../tests/test_enum_adjacently_tagged.rs | 594 ++++++++++++++++++ test_suite/tests/test_macros.rs | 422 ------------- 3 files changed, 594 insertions(+), 579 deletions(-) create mode 100644 test_suite/tests/test_enum_adjacently_tagged.rs diff --git a/test_suite/tests/test_annotations.rs b/test_suite/tests/test_annotations.rs index 9aa328725..9d03280d2 100644 --- a/test_suite/tests/test_annotations.rs +++ b/test_suite/tests/test_annotations.rs @@ -1607,59 +1607,6 @@ fn test_collect_other() { ); } -#[test] -fn test_adjacently_tagged_enum_bytes() { - #[derive(Serialize, Deserialize, PartialEq, Debug)] - #[serde(tag = "t", content = "c")] - enum Data { - A { a: i32 }, - } - - let data = Data::A { a: 0 }; - - assert_tokens( - &data, - &[ - Token::Struct { - name: "Data", - len: 2, - }, - Token::Str("t"), - Token::UnitVariant { - name: "Data", - variant: "A", - }, - Token::Str("c"), - Token::Struct { name: "A", len: 1 }, - Token::Str("a"), - Token::I32(0), - Token::StructEnd, - Token::StructEnd, - ], - ); - - assert_de_tokens( - &data, - &[ - Token::Struct { - name: "Data", - len: 2, - }, - Token::Bytes(b"t"), - Token::UnitVariant { - name: "Data", - variant: "A", - }, - Token::Bytes(b"c"), - Token::Struct { name: "A", len: 1 }, - Token::Str("a"), - Token::I32(0), - Token::StructEnd, - Token::StructEnd, - ], - ); -} - #[test] fn test_partially_untagged_enum() { #[derive(Serialize, Deserialize, PartialEq, Debug)] @@ -1846,38 +1793,6 @@ fn test_partially_untagged_internally_tagged_enum() { // TODO test error output } -#[test] -fn test_partially_untagged_adjacently_tagged_enum() { - #[derive(Serialize, Deserialize, PartialEq, Debug)] - #[serde(tag = "t", content = "c")] - enum Data { - A(u32), - B, - #[serde(untagged)] - Var(u32), - } - - let data = Data::A(7); - - assert_de_tokens( - &data, - &[ - Token::Map { len: None }, - Token::Str("t"), - Token::Str("A"), - Token::Str("c"), - Token::U32(7), - Token::MapEnd, - ], - ); - - let data = Data::Var(42); - - assert_de_tokens(&data, &[Token::U32(42)]); - - // TODO test error output -} - #[test] fn test_transparent_struct() { #[derive(Serialize, Deserialize, PartialEq, Debug)] @@ -1980,32 +1895,6 @@ fn test_expecting_message_externally_tagged_enum() { ); } -#[test] -fn test_expecting_message_adjacently_tagged_enum() { - #[derive(Deserialize)] - #[serde(tag = "tag", content = "content")] - #[serde(expecting = "something strange...")] - enum Enum { - AdjacentlyTagged, - } - - assert_de_tokens_error::( - &[Token::Str("AdjacentlyTagged")], - r#"invalid type: string "AdjacentlyTagged", expected something strange..."#, - ); - - assert_de_tokens_error::( - &[Token::Map { len: None }, Token::Unit], - r#"invalid type: unit value, expected "tag", "content", or other ignored fields"#, - ); - - // Check that #[serde(expecting = "...")] doesn't affect variant identifier error message - assert_de_tokens_error::( - &[Token::Map { len: None }, Token::Str("tag"), Token::Unit], - "invalid type: unit value, expected variant of enum Enum", - ); -} - #[test] fn test_expecting_message_untagged_tagged_enum() { #[derive(Deserialize)] @@ -2891,52 +2780,6 @@ mod flatten { mod adjacently_tagged { use super::*; - #[test] - fn straightforward() { - #[derive(Serialize, Deserialize, PartialEq, Debug)] - #[serde(tag = "t", content = "c")] - enum Data { - A { - a: i32, - #[serde(flatten)] - flat: Flat, - }, - } - - #[derive(Serialize, Deserialize, PartialEq, Debug)] - struct Flat { - b: i32, - } - - let data = Data::A { - a: 0, - flat: Flat { b: 0 }, - }; - - assert_tokens( - &data, - &[ - Token::Struct { - name: "Data", - len: 2, - }, - Token::Str("t"), - Token::UnitVariant { - name: "Data", - variant: "A", - }, - Token::Str("c"), - Token::Map { len: None }, - Token::Str("a"), - Token::I32(0), - Token::Str("b"), - Token::I32(0), - Token::MapEnd, - Token::StructEnd, - ], - ); - } - #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Flatten { outer: u32, diff --git a/test_suite/tests/test_enum_adjacently_tagged.rs b/test_suite/tests/test_enum_adjacently_tagged.rs new file mode 100644 index 000000000..e50d2e0a2 --- /dev/null +++ b/test_suite/tests/test_enum_adjacently_tagged.rs @@ -0,0 +1,594 @@ +#![deny(trivial_numeric_casts)] +#![allow( + clippy::derive_partial_eq_without_eq, + clippy::enum_variant_names, + clippy::redundant_field_names, + clippy::too_many_lines +)] + +use serde_derive::{Deserialize, Serialize}; +use serde_test::{ + assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_tokens, Token, +}; + +#[test] +fn test_adjacently_tagged_enum() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(tag = "t", content = "c")] + enum AdjacentlyTagged { + Unit, + Newtype(T), + Tuple(u8, u8), + Struct { f: u8 }, + } + + // unit with no content + assert_ser_tokens( + &AdjacentlyTagged::Unit::, + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 1, + }, + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, + Token::StructEnd, + ], + ); + + // unit with no content + assert_de_tokens( + &AdjacentlyTagged::Unit::, + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, + Token::StructEnd, + ], + ); + + // unit with tag first + assert_de_tokens( + &AdjacentlyTagged::Unit::, + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, + Token::Str("c"), + Token::Unit, + Token::StructEnd, + ], + ); + + // unit with content first + assert_de_tokens( + &AdjacentlyTagged::Unit::, + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Str("c"), + Token::Unit, + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, + Token::StructEnd, + ], + ); + + // unit with excess content (f, g, h) + assert_de_tokens( + &AdjacentlyTagged::Unit::, + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Str("f"), + Token::Unit, + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, + Token::Str("g"), + Token::Unit, + Token::Str("c"), + Token::Unit, + Token::Str("h"), + Token::Unit, + Token::StructEnd, + ], + ); + + // newtype with tag first + assert_tokens( + &AdjacentlyTagged::Newtype::(1), + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Newtype", + }, + Token::Str("c"), + Token::U8(1), + Token::StructEnd, + ], + ); + + // newtype with content first + assert_de_tokens( + &AdjacentlyTagged::Newtype::(1), + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Str("c"), + Token::U8(1), + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Newtype", + }, + Token::StructEnd, + ], + ); + + // optional newtype with no content field + assert_de_tokens( + &AdjacentlyTagged::Newtype::>(None), + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 1, + }, + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Newtype", + }, + Token::StructEnd, + ], + ); + + // tuple with tag first + assert_tokens( + &AdjacentlyTagged::Tuple::(1, 1), + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Tuple", + }, + Token::Str("c"), + Token::Tuple { len: 2 }, + Token::U8(1), + Token::U8(1), + Token::TupleEnd, + Token::StructEnd, + ], + ); + + // tuple with content first + assert_de_tokens( + &AdjacentlyTagged::Tuple::(1, 1), + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Str("c"), + Token::Tuple { len: 2 }, + Token::U8(1), + Token::U8(1), + Token::TupleEnd, + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Tuple", + }, + Token::StructEnd, + ], + ); + + // struct with tag first + assert_tokens( + &AdjacentlyTagged::Struct:: { f: 1 }, + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Struct", + }, + Token::Str("c"), + Token::Struct { + name: "Struct", + len: 1, + }, + Token::Str("f"), + Token::U8(1), + Token::StructEnd, + Token::StructEnd, + ], + ); + + // struct with content first + assert_de_tokens( + &AdjacentlyTagged::Struct:: { f: 1 }, + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Str("c"), + Token::Struct { + name: "Struct", + len: 1, + }, + Token::Str("f"), + Token::U8(1), + Token::StructEnd, + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Struct", + }, + Token::StructEnd, + ], + ); + + // integer field keys + assert_de_tokens( + &AdjacentlyTagged::Newtype::(1), + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::U64(1), // content field + Token::U8(1), + Token::U64(0), // tag field + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Newtype", + }, + Token::StructEnd, + ], + ); + + // byte-array field keys + assert_de_tokens( + &AdjacentlyTagged::Newtype::(1), + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Bytes(b"c"), + Token::U8(1), + Token::Bytes(b"t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Newtype", + }, + Token::StructEnd, + ], + ); +} + +#[test] +fn bytes() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[serde(tag = "t", content = "c")] + enum Data { + A { a: i32 }, + } + + let data = Data::A { a: 0 }; + + assert_tokens( + &data, + &[ + Token::Struct { + name: "Data", + len: 2, + }, + Token::Str("t"), + Token::UnitVariant { + name: "Data", + variant: "A", + }, + Token::Str("c"), + Token::Struct { name: "A", len: 1 }, + Token::Str("a"), + Token::I32(0), + Token::StructEnd, + Token::StructEnd, + ], + ); + + assert_de_tokens( + &data, + &[ + Token::Struct { + name: "Data", + len: 2, + }, + Token::Bytes(b"t"), + Token::UnitVariant { + name: "Data", + variant: "A", + }, + Token::Bytes(b"c"), + Token::Struct { name: "A", len: 1 }, + Token::Str("a"), + Token::I32(0), + Token::StructEnd, + Token::StructEnd, + ], + ); +} + +#[test] +fn struct_with_flatten() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[serde(tag = "t", content = "c")] + enum Data { + A { + a: i32, + #[serde(flatten)] + flat: Flat, + }, + } + + #[derive(Serialize, Deserialize, PartialEq, Debug)] + struct Flat { + b: i32, + } + + let data = Data::A { + a: 0, + flat: Flat { b: 0 }, + }; + + assert_tokens( + &data, + &[ + Token::Struct { + name: "Data", + len: 2, + }, + Token::Str("t"), + Token::UnitVariant { + name: "Data", + variant: "A", + }, + Token::Str("c"), + Token::Map { len: None }, + Token::Str("a"), + Token::I32(0), + Token::Str("b"), + Token::I32(0), + Token::MapEnd, + Token::StructEnd, + ], + ); +} + +#[test] +fn expecting_message() { + #[derive(Deserialize)] + #[serde(tag = "tag", content = "content")] + #[serde(expecting = "something strange...")] + enum Enum { + AdjacentlyTagged, + } + + assert_de_tokens_error::( + &[Token::Str("AdjacentlyTagged")], + r#"invalid type: string "AdjacentlyTagged", expected something strange..."#, + ); + + assert_de_tokens_error::( + &[Token::Map { len: None }, Token::Unit], + r#"invalid type: unit value, expected "tag", "content", or other ignored fields"#, + ); + + // Check that #[serde(expecting = "...")] doesn't affect variant identifier error message + assert_de_tokens_error::( + &[Token::Map { len: None }, Token::Str("tag"), Token::Unit], + "invalid type: unit value, expected variant of enum Enum", + ); +} + +#[test] +fn partially_untagged() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[serde(tag = "t", content = "c")] + enum Data { + A(u32), + B, + #[serde(untagged)] + Var(u32), + } + + let data = Data::A(7); + + assert_de_tokens( + &data, + &[ + Token::Map { len: None }, + Token::Str("t"), + Token::Str("A"), + Token::Str("c"), + Token::U32(7), + Token::MapEnd, + ], + ); + + let data = Data::Var(42); + + assert_de_tokens(&data, &[Token::U32(42)]); + + // TODO test error output +} + +#[test] +fn newtype_with_newtype() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct GenericNewTypeStruct(T); + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(tag = "t", content = "c")] + enum E { + Newtype(GenericNewTypeStruct), + Null, + } + + assert_de_tokens( + &E::Newtype(GenericNewTypeStruct(5u32)), + &[ + Token::Struct { name: "E", len: 2 }, + Token::Str("c"), + Token::NewtypeStruct { + name: "GenericNewTypeStruct", + }, + Token::U32(5), + Token::Str("t"), + Token::UnitVariant { + name: "E", + variant: "Newtype", + }, + Token::StructEnd, + ], + ); +} + +#[test] +fn deny_unknown_fields() { + #[derive(Debug, PartialEq, Deserialize)] + #[serde(tag = "t", content = "c", deny_unknown_fields)] + enum AdjacentlyTagged { + Unit, + } + + assert_de_tokens( + &AdjacentlyTagged::Unit, + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, + Token::Str("c"), + Token::Unit, + Token::StructEnd, + ], + ); + + assert_de_tokens_error::( + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, + Token::Str("c"), + Token::Unit, + Token::Str("h"), + ], + r#"invalid value: string "h", expected "t" or "c""#, + ); + + assert_de_tokens_error::( + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Str("h"), + ], + r#"invalid value: string "h", expected "t" or "c""#, + ); + + assert_de_tokens_error::( + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Str("c"), + Token::Unit, + Token::Str("h"), + ], + r#"invalid value: string "h", expected "t" or "c""#, + ); + + assert_de_tokens_error::( + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::U64(0), // tag field + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, + Token::U64(3), + ], + r#"invalid value: integer `3`, expected "t" or "c""#, + ); + + assert_de_tokens_error::( + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Bytes(b"c"), + Token::Unit, + Token::Bytes(b"h"), + ], + r#"invalid value: byte array, expected "t" or "c""#, + ); +} diff --git a/test_suite/tests/test_macros.rs b/test_suite/tests/test_macros.rs index 72137ddd0..aaab95816 100644 --- a/test_suite/tests/test_macros.rs +++ b/test_suite/tests/test_macros.rs @@ -453,34 +453,6 @@ fn test_untagged_newtype_struct() { ); } -#[test] -fn test_adjacently_tagged_newtype_struct() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "t", content = "c")] - enum E { - Newtype(GenericNewTypeStruct), - Null, - } - - assert_de_tokens( - &E::Newtype(GenericNewTypeStruct(5u32)), - &[ - Token::Struct { name: "E", len: 2 }, - Token::Str("c"), - Token::NewtypeStruct { - name: "GenericNewTypeStruct", - }, - Token::U32(5), - Token::Str("t"), - Token::UnitVariant { - name: "E", - variant: "Newtype", - }, - Token::StructEnd, - ], - ); -} - #[test] fn test_generic_tuple_struct() { assert_tokens( @@ -679,400 +651,6 @@ fn test_untagged_enum() { ); } -#[test] -fn test_adjacently_tagged_enum() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "t", content = "c")] - enum AdjacentlyTagged { - Unit, - Newtype(T), - Tuple(u8, u8), - Struct { f: u8 }, - } - - // unit with no content - assert_ser_tokens( - &AdjacentlyTagged::Unit::, - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 1, - }, - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Unit", - }, - Token::StructEnd, - ], - ); - - // unit with no content - assert_de_tokens( - &AdjacentlyTagged::Unit::, - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Unit", - }, - Token::StructEnd, - ], - ); - - // unit with tag first - assert_de_tokens( - &AdjacentlyTagged::Unit::, - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Unit", - }, - Token::Str("c"), - Token::Unit, - Token::StructEnd, - ], - ); - - // unit with content first - assert_de_tokens( - &AdjacentlyTagged::Unit::, - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Str("c"), - Token::Unit, - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Unit", - }, - Token::StructEnd, - ], - ); - - // unit with excess content (f, g, h) - assert_de_tokens( - &AdjacentlyTagged::Unit::, - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Str("f"), - Token::Unit, - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Unit", - }, - Token::Str("g"), - Token::Unit, - Token::Str("c"), - Token::Unit, - Token::Str("h"), - Token::Unit, - Token::StructEnd, - ], - ); - - // newtype with tag first - assert_tokens( - &AdjacentlyTagged::Newtype::(1), - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Newtype", - }, - Token::Str("c"), - Token::U8(1), - Token::StructEnd, - ], - ); - - // newtype with content first - assert_de_tokens( - &AdjacentlyTagged::Newtype::(1), - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Str("c"), - Token::U8(1), - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Newtype", - }, - Token::StructEnd, - ], - ); - - // optional newtype with no content field - assert_de_tokens( - &AdjacentlyTagged::Newtype::>(None), - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 1, - }, - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Newtype", - }, - Token::StructEnd, - ], - ); - - // tuple with tag first - assert_tokens( - &AdjacentlyTagged::Tuple::(1, 1), - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Tuple", - }, - Token::Str("c"), - Token::Tuple { len: 2 }, - Token::U8(1), - Token::U8(1), - Token::TupleEnd, - Token::StructEnd, - ], - ); - - // tuple with content first - assert_de_tokens( - &AdjacentlyTagged::Tuple::(1, 1), - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Str("c"), - Token::Tuple { len: 2 }, - Token::U8(1), - Token::U8(1), - Token::TupleEnd, - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Tuple", - }, - Token::StructEnd, - ], - ); - - // struct with tag first - assert_tokens( - &AdjacentlyTagged::Struct:: { f: 1 }, - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Struct", - }, - Token::Str("c"), - Token::Struct { - name: "Struct", - len: 1, - }, - Token::Str("f"), - Token::U8(1), - Token::StructEnd, - Token::StructEnd, - ], - ); - - // struct with content first - assert_de_tokens( - &AdjacentlyTagged::Struct:: { f: 1 }, - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Str("c"), - Token::Struct { - name: "Struct", - len: 1, - }, - Token::Str("f"), - Token::U8(1), - Token::StructEnd, - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Struct", - }, - Token::StructEnd, - ], - ); - - // integer field keys - assert_de_tokens( - &AdjacentlyTagged::Newtype::(1), - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::U64(1), // content field - Token::U8(1), - Token::U64(0), // tag field - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Newtype", - }, - Token::StructEnd, - ], - ); - - // byte-array field keys - assert_de_tokens( - &AdjacentlyTagged::Newtype::(1), - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Bytes(b"c"), - Token::U8(1), - Token::Bytes(b"t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Newtype", - }, - Token::StructEnd, - ], - ); -} - -#[test] -fn test_adjacently_tagged_enum_deny_unknown_fields() { - #[derive(Debug, PartialEq, Deserialize)] - #[serde(tag = "t", content = "c", deny_unknown_fields)] - enum AdjacentlyTagged { - Unit, - } - - assert_de_tokens( - &AdjacentlyTagged::Unit, - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Unit", - }, - Token::Str("c"), - Token::Unit, - Token::StructEnd, - ], - ); - - assert_de_tokens_error::( - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Unit", - }, - Token::Str("c"), - Token::Unit, - Token::Str("h"), - ], - r#"invalid value: string "h", expected "t" or "c""#, - ); - - assert_de_tokens_error::( - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Str("h"), - ], - r#"invalid value: string "h", expected "t" or "c""#, - ); - - assert_de_tokens_error::( - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Str("c"), - Token::Unit, - Token::Str("h"), - ], - r#"invalid value: string "h", expected "t" or "c""#, - ); - - assert_de_tokens_error::( - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::U64(0), // tag field - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Unit", - }, - Token::U64(3), - ], - r#"invalid value: integer `3`, expected "t" or "c""#, - ); - - assert_de_tokens_error::( - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Bytes(b"c"), - Token::Unit, - Token::Bytes(b"h"), - ], - r#"invalid value: byte array, expected "t" or "c""#, - ); -} - #[test] fn test_internally_tagged_struct() { #[derive(Debug, PartialEq, Serialize, Deserialize)] From 5a359e10f4a5e1a7230e58c2fd4b09d63b5664a9 Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 14 Aug 2023 01:57:15 +0500 Subject: [PATCH 155/258] Group Newtype variant checks in test_adjacently_tagged_enum together --- .../tests/test_enum_adjacently_tagged.rs | 76 +++++++++---------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/test_suite/tests/test_enum_adjacently_tagged.rs b/test_suite/tests/test_enum_adjacently_tagged.rs index e50d2e0a2..a7968336b 100644 --- a/test_suite/tests/test_enum_adjacently_tagged.rs +++ b/test_suite/tests/test_enum_adjacently_tagged.rs @@ -174,6 +174,44 @@ fn test_adjacently_tagged_enum() { ], ); + // integer field keys + assert_de_tokens( + &AdjacentlyTagged::Newtype::(1), + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::U64(1), // content field + Token::U8(1), + Token::U64(0), // tag field + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Newtype", + }, + Token::StructEnd, + ], + ); + + // byte-array field keys + assert_de_tokens( + &AdjacentlyTagged::Newtype::(1), + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Bytes(b"c"), + Token::U8(1), + Token::Bytes(b"t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Newtype", + }, + Token::StructEnd, + ], + ); + // tuple with tag first assert_tokens( &AdjacentlyTagged::Tuple::(1, 1), @@ -267,44 +305,6 @@ fn test_adjacently_tagged_enum() { Token::StructEnd, ], ); - - // integer field keys - assert_de_tokens( - &AdjacentlyTagged::Newtype::(1), - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::U64(1), // content field - Token::U8(1), - Token::U64(0), // tag field - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Newtype", - }, - Token::StructEnd, - ], - ); - - // byte-array field keys - assert_de_tokens( - &AdjacentlyTagged::Newtype::(1), - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Bytes(b"c"), - Token::U8(1), - Token::Bytes(b"t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Newtype", - }, - Token::StructEnd, - ], - ); } #[test] From bee74707154049eb823732043c0e422b7b04a742 Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 14 Aug 2023 02:19:31 +0500 Subject: [PATCH 156/258] Split test test_adjacently_tagged_enum into four tests for each variant (review this commit with "ignore whitespace changes" option on) --- .../tests/test_enum_adjacently_tagged.rs | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/test_suite/tests/test_enum_adjacently_tagged.rs b/test_suite/tests/test_enum_adjacently_tagged.rs index a7968336b..d60817cca 100644 --- a/test_suite/tests/test_enum_adjacently_tagged.rs +++ b/test_suite/tests/test_enum_adjacently_tagged.rs @@ -11,17 +11,17 @@ use serde_test::{ assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_tokens, Token, }; -#[test] -fn test_adjacently_tagged_enum() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "t", content = "c")] - enum AdjacentlyTagged { - Unit, - Newtype(T), - Tuple(u8, u8), - Struct { f: u8 }, - } +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(tag = "t", content = "c")] +enum AdjacentlyTagged { + Unit, + Newtype(T), + Tuple(u8, u8), + Struct { f: u8 }, +} +#[test] +fn unit() { // unit with no content assert_ser_tokens( &AdjacentlyTagged::Unit::, @@ -118,7 +118,10 @@ fn test_adjacently_tagged_enum() { Token::StructEnd, ], ); +} +#[test] +fn newtype() { // newtype with tag first assert_tokens( &AdjacentlyTagged::Newtype::(1), @@ -211,7 +214,10 @@ fn test_adjacently_tagged_enum() { Token::StructEnd, ], ); +} +#[test] +fn tuple() { // tuple with tag first assert_tokens( &AdjacentlyTagged::Tuple::(1, 1), @@ -255,7 +261,10 @@ fn test_adjacently_tagged_enum() { Token::StructEnd, ], ); +} +#[test] +fn struct_() { // struct with tag first assert_tokens( &AdjacentlyTagged::Struct:: { f: 1 }, From 59628d171272d8dd2de0508a177b0980cbf38694 Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 14 Aug 2023 02:48:56 +0500 Subject: [PATCH 157/258] Create only one value for all checks --- .../tests/test_enum_adjacently_tagged.rs | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/test_suite/tests/test_enum_adjacently_tagged.rs b/test_suite/tests/test_enum_adjacently_tagged.rs index d60817cca..4b2db7a27 100644 --- a/test_suite/tests/test_enum_adjacently_tagged.rs +++ b/test_suite/tests/test_enum_adjacently_tagged.rs @@ -122,9 +122,11 @@ fn unit() { #[test] fn newtype() { + let value = AdjacentlyTagged::Newtype::(1); + // newtype with tag first assert_tokens( - &AdjacentlyTagged::Newtype::(1), + &value, &[ Token::Struct { name: "AdjacentlyTagged", @@ -143,7 +145,7 @@ fn newtype() { // newtype with content first assert_de_tokens( - &AdjacentlyTagged::Newtype::(1), + &value, &[ Token::Struct { name: "AdjacentlyTagged", @@ -179,7 +181,7 @@ fn newtype() { // integer field keys assert_de_tokens( - &AdjacentlyTagged::Newtype::(1), + &value, &[ Token::Struct { name: "AdjacentlyTagged", @@ -198,7 +200,7 @@ fn newtype() { // byte-array field keys assert_de_tokens( - &AdjacentlyTagged::Newtype::(1), + &value, &[ Token::Struct { name: "AdjacentlyTagged", @@ -218,9 +220,11 @@ fn newtype() { #[test] fn tuple() { + let value = AdjacentlyTagged::Tuple::(1, 1); + // tuple with tag first assert_tokens( - &AdjacentlyTagged::Tuple::(1, 1), + &value, &[ Token::Struct { name: "AdjacentlyTagged", @@ -242,7 +246,7 @@ fn tuple() { // tuple with content first assert_de_tokens( - &AdjacentlyTagged::Tuple::(1, 1), + &value, &[ Token::Struct { name: "AdjacentlyTagged", @@ -265,9 +269,11 @@ fn tuple() { #[test] fn struct_() { + let value = AdjacentlyTagged::Struct:: { f: 1 }; + // struct with tag first assert_tokens( - &AdjacentlyTagged::Struct:: { f: 1 }, + &value, &[ Token::Struct { name: "AdjacentlyTagged", @@ -292,7 +298,7 @@ fn struct_() { // struct with content first assert_de_tokens( - &AdjacentlyTagged::Struct:: { f: 1 }, + &value, &[ Token::Struct { name: "AdjacentlyTagged", From 36b9a859c447244aa6ae4fd73dfe0d01f840e9e1 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sun, 11 Aug 2024 23:03:26 +0500 Subject: [PATCH 158/258] Test deserialization of the serialized unit format for adjacently tagged enum --- test_suite/tests/test_enum_adjacently_tagged.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/test_suite/tests/test_enum_adjacently_tagged.rs b/test_suite/tests/test_enum_adjacently_tagged.rs index 4b2db7a27..9836e4b02 100644 --- a/test_suite/tests/test_enum_adjacently_tagged.rs +++ b/test_suite/tests/test_enum_adjacently_tagged.rs @@ -7,9 +7,7 @@ )] use serde_derive::{Deserialize, Serialize}; -use serde_test::{ - assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_tokens, Token, -}; +use serde_test::{assert_de_tokens, assert_de_tokens_error, assert_tokens, Token}; #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "t", content = "c")] @@ -23,7 +21,7 @@ enum AdjacentlyTagged { #[test] fn unit() { // unit with no content - assert_ser_tokens( + assert_tokens( &AdjacentlyTagged::Unit::, &[ Token::Struct { @@ -39,7 +37,7 @@ fn unit() { ], ); - // unit with no content + // unit with no content and incorrect hint for number of elements assert_de_tokens( &AdjacentlyTagged::Unit::, &[ From 9d0f811221bbb7b9ec520278f036ed93ba5a3647 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sun, 11 Aug 2024 23:08:25 +0500 Subject: [PATCH 159/258] Remove unnecessary generic --- test_suite/tests/test_enum_adjacently_tagged.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test_suite/tests/test_enum_adjacently_tagged.rs b/test_suite/tests/test_enum_adjacently_tagged.rs index 9836e4b02..eccdc3356 100644 --- a/test_suite/tests/test_enum_adjacently_tagged.rs +++ b/test_suite/tests/test_enum_adjacently_tagged.rs @@ -480,22 +480,22 @@ fn partially_untagged() { #[test] fn newtype_with_newtype() { #[derive(Debug, PartialEq, Serialize, Deserialize)] - struct GenericNewTypeStruct(T); + struct NewtypeStruct(u32); #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "t", content = "c")] enum E { - Newtype(GenericNewTypeStruct), + Newtype(NewtypeStruct), Null, } assert_de_tokens( - &E::Newtype(GenericNewTypeStruct(5u32)), + &E::Newtype(NewtypeStruct(5)), &[ Token::Struct { name: "E", len: 2 }, Token::Str("c"), Token::NewtypeStruct { - name: "GenericNewTypeStruct", + name: "NewtypeStruct", }, Token::U32(5), Token::Str("t"), From 5445f1741b1269f81b67403ad8b602f214ae7452 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sun, 11 Aug 2024 23:10:12 +0500 Subject: [PATCH 160/258] Reuse AdjacentlyTagged enum in newtype_with_newtype test --- test_suite/tests/test_enum_adjacently_tagged.rs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/test_suite/tests/test_enum_adjacently_tagged.rs b/test_suite/tests/test_enum_adjacently_tagged.rs index eccdc3356..f3be60d34 100644 --- a/test_suite/tests/test_enum_adjacently_tagged.rs +++ b/test_suite/tests/test_enum_adjacently_tagged.rs @@ -482,17 +482,13 @@ fn newtype_with_newtype() { #[derive(Debug, PartialEq, Serialize, Deserialize)] struct NewtypeStruct(u32); - #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(tag = "t", content = "c")] - enum E { - Newtype(NewtypeStruct), - Null, - } - assert_de_tokens( - &E::Newtype(NewtypeStruct(5)), + &AdjacentlyTagged::Newtype(NewtypeStruct(5)), &[ - Token::Struct { name: "E", len: 2 }, + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, Token::Str("c"), Token::NewtypeStruct { name: "NewtypeStruct", @@ -500,7 +496,7 @@ fn newtype_with_newtype() { Token::U32(5), Token::Str("t"), Token::UnitVariant { - name: "E", + name: "AdjacentlyTagged", variant: "Newtype", }, Token::StructEnd, From df07751e6fad8d5ceeaa9f41e73fb6371de86ee6 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sun, 11 Aug 2024 23:11:31 +0500 Subject: [PATCH 161/258] Group newtype and newtype_with_newtype tests --- .../tests/test_enum_adjacently_tagged.rs | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/test_suite/tests/test_enum_adjacently_tagged.rs b/test_suite/tests/test_enum_adjacently_tagged.rs index f3be60d34..ecb35d591 100644 --- a/test_suite/tests/test_enum_adjacently_tagged.rs +++ b/test_suite/tests/test_enum_adjacently_tagged.rs @@ -216,6 +216,33 @@ fn newtype() { ); } +#[test] +fn newtype_with_newtype() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct NewtypeStruct(u32); + + assert_de_tokens( + &AdjacentlyTagged::Newtype(NewtypeStruct(5)), + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Str("c"), + Token::NewtypeStruct { + name: "NewtypeStruct", + }, + Token::U32(5), + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Newtype", + }, + Token::StructEnd, + ], + ); +} + #[test] fn tuple() { let value = AdjacentlyTagged::Tuple::(1, 1); @@ -477,33 +504,6 @@ fn partially_untagged() { // TODO test error output } -#[test] -fn newtype_with_newtype() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - struct NewtypeStruct(u32); - - assert_de_tokens( - &AdjacentlyTagged::Newtype(NewtypeStruct(5)), - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Str("c"), - Token::NewtypeStruct { - name: "NewtypeStruct", - }, - Token::U32(5), - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Newtype", - }, - Token::StructEnd, - ], - ); -} - #[test] fn deny_unknown_fields() { #[derive(Debug, PartialEq, Deserialize)] From 42e63ff942311f2e15e9e8ae4c7f903934c53e6d Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 14 Aug 2023 02:59:20 +0500 Subject: [PATCH 162/258] Reuse AdjacentlyTagged enum in `bytes` test Change 0i32 to 1u8 so the test can be merged with the previous in the next commit --- .../tests/test_enum_adjacently_tagged.rs | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/test_suite/tests/test_enum_adjacently_tagged.rs b/test_suite/tests/test_enum_adjacently_tagged.rs index ecb35d591..9894f9622 100644 --- a/test_suite/tests/test_enum_adjacently_tagged.rs +++ b/test_suite/tests/test_enum_adjacently_tagged.rs @@ -349,51 +349,51 @@ fn struct_() { #[test] fn bytes() { - #[derive(Serialize, Deserialize, PartialEq, Debug)] - #[serde(tag = "t", content = "c")] - enum Data { - A { a: i32 }, - } - - let data = Data::A { a: 0 }; + let value = AdjacentlyTagged::Struct:: { f: 1 }; assert_tokens( - &data, + &value, &[ Token::Struct { - name: "Data", + name: "AdjacentlyTagged", len: 2, }, Token::Str("t"), Token::UnitVariant { - name: "Data", - variant: "A", + name: "AdjacentlyTagged", + variant: "Struct", }, Token::Str("c"), - Token::Struct { name: "A", len: 1 }, - Token::Str("a"), - Token::I32(0), + Token::Struct { + name: "Struct", + len: 1, + }, + Token::Str("f"), + Token::U8(1), Token::StructEnd, Token::StructEnd, ], ); assert_de_tokens( - &data, + &value, &[ Token::Struct { - name: "Data", + name: "AdjacentlyTagged", len: 2, }, Token::Bytes(b"t"), Token::UnitVariant { - name: "Data", - variant: "A", + name: "AdjacentlyTagged", + variant: "Struct", }, Token::Bytes(b"c"), - Token::Struct { name: "A", len: 1 }, - Token::Str("a"), - Token::I32(0), + Token::Struct { + name: "Struct", + len: 1, + }, + Token::Str("f"), + Token::U8(1), Token::StructEnd, Token::StructEnd, ], From 3dc6829303556d4bfdbc63d1315c81dc2456f57c Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 14 Aug 2023 03:05:50 +0500 Subject: [PATCH 163/258] Integrate `bytes` test into `struct_` test `newtype` test also integrates test with `Bytes` tag, so be like Removed the first assert_tokens because it is the same as the first assert in the merged method --- .../tests/test_enum_adjacently_tagged.rs | 30 +------------------ 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/test_suite/tests/test_enum_adjacently_tagged.rs b/test_suite/tests/test_enum_adjacently_tagged.rs index 9894f9622..55be6ca6a 100644 --- a/test_suite/tests/test_enum_adjacently_tagged.rs +++ b/test_suite/tests/test_enum_adjacently_tagged.rs @@ -345,36 +345,8 @@ fn struct_() { Token::StructEnd, ], ); -} - -#[test] -fn bytes() { - let value = AdjacentlyTagged::Struct:: { f: 1 }; - - assert_tokens( - &value, - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Struct", - }, - Token::Str("c"), - Token::Struct { - name: "Struct", - len: 1, - }, - Token::Str("f"), - Token::U8(1), - Token::StructEnd, - Token::StructEnd, - ], - ); + // byte-array field keys assert_de_tokens( &value, &[ From a7f0bab078ea5226c244069f43738c5e896483c2 Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 12 Aug 2024 00:49:58 +0500 Subject: [PATCH 164/258] Document fields in internal structs used to deserialize adjacently tagged enums --- serde/src/private/de.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index c146539ee..6c81b720b 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -904,7 +904,9 @@ mod content { /// Not public API. pub struct TagOrContentFieldVisitor { + /// Name of the tag field of the adjacently tagged enum pub tag: &'static str, + /// Name of the content field of the adjacently tagged enum pub content: &'static str, } @@ -979,7 +981,9 @@ mod content { /// Not public API. pub struct TagContentOtherFieldVisitor { + /// Name of the tag field of the adjacently tagged enum pub tag: &'static str, + /// Name of the content field of the adjacently tagged enum pub content: &'static str, } From 29dc6c33674f48e4010cc72cee8ab8d0118d5c50 Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 12 Aug 2024 00:45:29 +0500 Subject: [PATCH 165/258] Unit: add tests for deserialization from sequence (review this commit with "ignore whitespace changes" option on) --- .../tests/test_enum_adjacently_tagged.rs | 237 +++++++++++------- 1 file changed, 141 insertions(+), 96 deletions(-) diff --git a/test_suite/tests/test_enum_adjacently_tagged.rs b/test_suite/tests/test_enum_adjacently_tagged.rs index 55be6ca6a..ee397855f 100644 --- a/test_suite/tests/test_enum_adjacently_tagged.rs +++ b/test_suite/tests/test_enum_adjacently_tagged.rs @@ -18,104 +18,149 @@ enum AdjacentlyTagged { Struct { f: u8 }, } -#[test] -fn unit() { - // unit with no content - assert_tokens( - &AdjacentlyTagged::Unit::, - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 1, - }, - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Unit", - }, - Token::StructEnd, - ], - ); - - // unit with no content and incorrect hint for number of elements - assert_de_tokens( - &AdjacentlyTagged::Unit::, - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Unit", - }, - Token::StructEnd, - ], - ); - - // unit with tag first - assert_de_tokens( - &AdjacentlyTagged::Unit::, - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Unit", - }, - Token::Str("c"), - Token::Unit, - Token::StructEnd, - ], - ); +mod unit { + use super::*; + + #[test] + fn map_str_tag_only() { + // Map: tag only + assert_tokens( + &AdjacentlyTagged::Unit::, + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 1, + }, + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, + Token::StructEnd, + ], + ); + + // Map: tag only and incorrect hint for number of elements + assert_de_tokens( + &AdjacentlyTagged::Unit::, + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, + Token::StructEnd, + ], + ); + } - // unit with content first - assert_de_tokens( - &AdjacentlyTagged::Unit::, - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Str("c"), - Token::Unit, - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Unit", - }, - Token::StructEnd, - ], - ); + #[test] + fn map_str_tag_content() { + // Map: tag + content + assert_de_tokens( + &AdjacentlyTagged::Unit::, + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, + Token::Str("c"), + Token::Unit, + Token::StructEnd, + ], + ); + // Map: content + tag + assert_de_tokens( + &AdjacentlyTagged::Unit::, + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Str("c"), + Token::Unit, + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, + Token::StructEnd, + ], + ); + + // Map: tag + content + excess fields (f, g, h) + assert_de_tokens( + &AdjacentlyTagged::Unit::, + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Str("f"), + Token::Unit, + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, + Token::Str("g"), + Token::Unit, + Token::Str("c"), + Token::Unit, + Token::Str("h"), + Token::Unit, + Token::StructEnd, + ], + ); + } - // unit with excess content (f, g, h) - assert_de_tokens( - &AdjacentlyTagged::Unit::, - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Str("f"), - Token::Unit, - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Unit", - }, - Token::Str("g"), - Token::Unit, - Token::Str("c"), - Token::Unit, - Token::Str("h"), - Token::Unit, - Token::StructEnd, - ], - ); + #[test] + fn seq_tag_content() { + // Seq: tag and content + assert_de_tokens( + &AdjacentlyTagged::Unit::, + &[ + Token::Seq { len: Some(2) }, + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, + Token::Unit, + Token::SeqEnd, + ], + ); + + // Seq: tag (as string) and content + assert_de_tokens( + &AdjacentlyTagged::Unit::, + &[ + Token::Seq { len: None }, + Token::Str("Unit"), // tag + Token::Unit, // content + Token::SeqEnd, + ], + ); + + // Seq: tag (as borrowed string) and content + assert_de_tokens( + &AdjacentlyTagged::Unit::, + &[ + Token::Seq { len: None }, + Token::BorrowedStr("Unit"), // tag + Token::Unit, // content + Token::SeqEnd, + ], + ); + } } #[test] From a02da49b87cb7d416cb672c55d61c6a9177630b0 Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 12 Aug 2024 01:06:51 +0500 Subject: [PATCH 166/258] Unit: add tests for deserialization from integer tag and content fields --- .../tests/test_enum_adjacently_tagged.rs | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/test_suite/tests/test_enum_adjacently_tagged.rs b/test_suite/tests/test_enum_adjacently_tagged.rs index ee397855f..6c2520234 100644 --- a/test_suite/tests/test_enum_adjacently_tagged.rs +++ b/test_suite/tests/test_enum_adjacently_tagged.rs @@ -58,6 +58,26 @@ mod unit { ); } + #[test] + fn map_int_tag_only() { + // Map: tag (as number) only + assert_de_tokens( + &AdjacentlyTagged::Unit::, + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 1, + }, + Token::U16(0), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, + Token::StructEnd, + ], + ); + } + #[test] fn map_str_tag_content() { // Map: tag + content @@ -123,6 +143,47 @@ mod unit { ); } + #[test] + fn map_int_tag_content() { + // Map: tag (as number) + content (as number) + assert_de_tokens( + &AdjacentlyTagged::Unit::, + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::U8(0), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, + Token::U8(1), + Token::Unit, + Token::StructEnd, + ], + ); + + // Map: content (as number) + tag (as number) + assert_de_tokens( + &AdjacentlyTagged::Unit::, + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::U64(1), + Token::Unit, + Token::U64(0), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, + Token::StructEnd, + ], + ); + } + #[test] fn seq_tag_content() { // Seq: tag and content From 6bfe1c435ad8f946f8269b9a39af79507a897cdd Mon Sep 17 00:00:00 2001 From: Mingun Date: Fri, 16 Aug 2024 22:35:54 +0500 Subject: [PATCH 167/258] Unit: add tests for deserialization from bytes tag and content fields --- .../tests/test_enum_adjacently_tagged.rs | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/test_suite/tests/test_enum_adjacently_tagged.rs b/test_suite/tests/test_enum_adjacently_tagged.rs index 6c2520234..8546c9a41 100644 --- a/test_suite/tests/test_enum_adjacently_tagged.rs +++ b/test_suite/tests/test_enum_adjacently_tagged.rs @@ -78,6 +78,43 @@ mod unit { ); } + #[test] + fn map_bytes_tag_only() { + // Map: tag only + assert_de_tokens( + &AdjacentlyTagged::Unit::, + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 1, + }, + Token::Bytes(b"t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, + Token::StructEnd, + ], + ); + + // Map: tag only + assert_de_tokens( + &AdjacentlyTagged::Unit::, + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 1, + }, + Token::BorrowedBytes(b"t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, + Token::StructEnd, + ], + ); + } + #[test] fn map_str_tag_content() { // Map: tag + content @@ -184,6 +221,47 @@ mod unit { ); } + #[test] + fn map_bytes_tag_content() { + // Map: tag + content + assert_de_tokens( + &AdjacentlyTagged::Unit::, + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::BorrowedBytes(b"t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, + Token::BorrowedBytes(b"c"), + Token::Unit, + Token::StructEnd, + ], + ); + + // Map: content + tag + assert_de_tokens( + &AdjacentlyTagged::Unit::, + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Bytes(b"c"), + Token::Unit, + Token::Bytes(b"t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, + Token::StructEnd, + ], + ); + } + #[test] fn seq_tag_content() { // Seq: tag and content From d5a9c11b5c9a72aca31a4fa5898c54945b26f325 Mon Sep 17 00:00:00 2001 From: Mingun Date: Fri, 16 Aug 2024 22:46:41 +0500 Subject: [PATCH 168/258] No need to test integer and byte array field names, they already tested for Unit case There is no difference what variant is deserialized so we can test only one kind of variant --- .../tests/test_enum_adjacently_tagged.rs | 63 ------------------- 1 file changed, 63 deletions(-) diff --git a/test_suite/tests/test_enum_adjacently_tagged.rs b/test_suite/tests/test_enum_adjacently_tagged.rs index 8546c9a41..6c8489eb9 100644 --- a/test_suite/tests/test_enum_adjacently_tagged.rs +++ b/test_suite/tests/test_enum_adjacently_tagged.rs @@ -360,44 +360,6 @@ fn newtype() { Token::StructEnd, ], ); - - // integer field keys - assert_de_tokens( - &value, - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::U64(1), // content field - Token::U8(1), - Token::U64(0), // tag field - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Newtype", - }, - Token::StructEnd, - ], - ); - - // byte-array field keys - assert_de_tokens( - &value, - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Bytes(b"c"), - Token::U8(1), - Token::Bytes(b"t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Newtype", - }, - Token::StructEnd, - ], - ); } #[test] @@ -529,31 +491,6 @@ fn struct_() { Token::StructEnd, ], ); - - // byte-array field keys - assert_de_tokens( - &value, - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Bytes(b"t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Struct", - }, - Token::Bytes(b"c"), - Token::Struct { - name: "Struct", - len: 1, - }, - Token::Str("f"), - Token::U8(1), - Token::StructEnd, - Token::StructEnd, - ], - ); } #[test] From b0d651be402838a7640c8f1751f5553af456730a Mon Sep 17 00:00:00 2001 From: Mingun Date: Fri, 16 Aug 2024 22:10:26 +0500 Subject: [PATCH 169/258] Newtype: add tests for deserialization from sequence (review this commit with "ignore whitespace changes" option on) --- .../tests/test_enum_adjacently_tagged.rs | 158 ++++++++++++------ 1 file changed, 103 insertions(+), 55 deletions(-) diff --git a/test_suite/tests/test_enum_adjacently_tagged.rs b/test_suite/tests/test_enum_adjacently_tagged.rs index 6c8489eb9..b1437bbe9 100644 --- a/test_suite/tests/test_enum_adjacently_tagged.rs +++ b/test_suite/tests/test_enum_adjacently_tagged.rs @@ -302,64 +302,112 @@ mod unit { } } -#[test] -fn newtype() { - let value = AdjacentlyTagged::Newtype::(1); +mod newtype { + use super::*; - // newtype with tag first - assert_tokens( - &value, - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Newtype", - }, - Token::Str("c"), - Token::U8(1), - Token::StructEnd, - ], - ); + #[test] + fn map_tag_content() { + let value = AdjacentlyTagged::Newtype::(1); - // newtype with content first - assert_de_tokens( - &value, - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Str("c"), - Token::U8(1), - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Newtype", - }, - Token::StructEnd, - ], - ); + // Map: tag + content + assert_tokens( + &value, + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Newtype", + }, + Token::Str("c"), + Token::U8(1), + Token::StructEnd, + ], + ); - // optional newtype with no content field - assert_de_tokens( - &AdjacentlyTagged::Newtype::>(None), - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 1, - }, - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Newtype", - }, - Token::StructEnd, - ], - ); + // Map: content + tag + assert_de_tokens( + &value, + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Str("c"), + Token::U8(1), + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Newtype", + }, + Token::StructEnd, + ], + ); + } + + #[test] + fn map_tag_only() { + // optional newtype with no content field + assert_de_tokens( + &AdjacentlyTagged::Newtype::>(None), + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 1, + }, + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Newtype", + }, + Token::StructEnd, + ], + ); + } + + #[test] + fn seq() { + let value = AdjacentlyTagged::Newtype::(1); + + // Seq: tag and content + assert_de_tokens( + &value, + &[ + Token::Seq { len: Some(2) }, + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Newtype", + }, + Token::U8(1), + Token::SeqEnd, + ], + ); + + // Seq: tag (as string) and content + assert_de_tokens( + &value, + &[ + Token::Seq { len: None }, + Token::Str("Newtype"), // tag + Token::U8(1), // content + Token::SeqEnd, + ], + ); + + // Seq: tag (as borrowed string) and content + assert_de_tokens( + &value, + &[ + Token::Seq { len: None }, + Token::BorrowedStr("Newtype"), // tag + Token::U8(1), // content + Token::SeqEnd, + ], + ); + } } #[test] From a94d8750fb91d9773553b03e544cf98547a9c8bf Mon Sep 17 00:00:00 2001 From: Mingun Date: Fri, 16 Aug 2024 22:12:33 +0500 Subject: [PATCH 170/258] Newtype: move up the test with tag only --- .../tests/test_enum_adjacently_tagged.rs | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/test_suite/tests/test_enum_adjacently_tagged.rs b/test_suite/tests/test_enum_adjacently_tagged.rs index b1437bbe9..d21ac73c1 100644 --- a/test_suite/tests/test_enum_adjacently_tagged.rs +++ b/test_suite/tests/test_enum_adjacently_tagged.rs @@ -306,58 +306,58 @@ mod newtype { use super::*; #[test] - fn map_tag_content() { - let value = AdjacentlyTagged::Newtype::(1); - - // Map: tag + content - assert_tokens( - &value, + fn map_tag_only() { + // optional newtype with no content field + assert_de_tokens( + &AdjacentlyTagged::Newtype::>(None), &[ Token::Struct { name: "AdjacentlyTagged", - len: 2, + len: 1, }, Token::Str("t"), Token::UnitVariant { name: "AdjacentlyTagged", variant: "Newtype", }, - Token::Str("c"), - Token::U8(1), Token::StructEnd, ], ); + } - // Map: content + tag - assert_de_tokens( + #[test] + fn map_tag_content() { + let value = AdjacentlyTagged::Newtype::(1); + + // Map: tag + content + assert_tokens( &value, &[ Token::Struct { name: "AdjacentlyTagged", len: 2, }, - Token::Str("c"), - Token::U8(1), Token::Str("t"), Token::UnitVariant { name: "AdjacentlyTagged", variant: "Newtype", }, + Token::Str("c"), + Token::U8(1), Token::StructEnd, ], ); - } - #[test] - fn map_tag_only() { - // optional newtype with no content field + // Map: content + tag assert_de_tokens( - &AdjacentlyTagged::Newtype::>(None), + &value, &[ Token::Struct { name: "AdjacentlyTagged", - len: 1, + len: 2, }, + Token::Str("c"), + Token::U8(1), Token::Str("t"), Token::UnitVariant { name: "AdjacentlyTagged", From c383e4f9535e4ffdbda36d5c5c2a01bc0518237a Mon Sep 17 00:00:00 2001 From: Mingun Date: Fri, 16 Aug 2024 22:18:20 +0500 Subject: [PATCH 171/258] Tuple: add tests for deserialization from sequence (review this commit with "ignore whitespace changes" option on) --- .../tests/test_enum_adjacently_tagged.rs | 116 +++++++++++------- 1 file changed, 71 insertions(+), 45 deletions(-) diff --git a/test_suite/tests/test_enum_adjacently_tagged.rs b/test_suite/tests/test_enum_adjacently_tagged.rs index d21ac73c1..5584f662b 100644 --- a/test_suite/tests/test_enum_adjacently_tagged.rs +++ b/test_suite/tests/test_enum_adjacently_tagged.rs @@ -437,53 +437,79 @@ fn newtype_with_newtype() { ); } -#[test] -fn tuple() { - let value = AdjacentlyTagged::Tuple::(1, 1); +mod tuple { + use super::*; - // tuple with tag first - assert_tokens( - &value, - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Tuple", - }, - Token::Str("c"), - Token::Tuple { len: 2 }, - Token::U8(1), - Token::U8(1), - Token::TupleEnd, - Token::StructEnd, - ], - ); + #[test] + fn map() { + let value = AdjacentlyTagged::Tuple::(1, 1); - // tuple with content first - assert_de_tokens( - &value, - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Str("c"), - Token::Tuple { len: 2 }, - Token::U8(1), - Token::U8(1), - Token::TupleEnd, - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Tuple", - }, - Token::StructEnd, - ], - ); + // Map: tag + content + assert_tokens( + &value, + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Tuple", + }, + Token::Str("c"), + Token::Tuple { len: 2 }, + Token::U8(1), + Token::U8(1), + Token::TupleEnd, + Token::StructEnd, + ], + ); + + // Map: content + tag + assert_de_tokens( + &value, + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Str("c"), + Token::Tuple { len: 2 }, + Token::U8(1), + Token::U8(1), + Token::TupleEnd, + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Tuple", + }, + Token::StructEnd, + ], + ); + } + + #[test] + fn seq() { + let value = AdjacentlyTagged::Tuple::(1, 1); + + // Seq: tag + content + assert_de_tokens( + &value, + &[ + Token::Seq { len: Some(2) }, + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Tuple", + }, + Token::Tuple { len: 2 }, + Token::U8(1), + Token::U8(1), + Token::TupleEnd, + Token::SeqEnd, + ], + ); + } } #[test] From 9f72ce695e3d7e58a16d4909217f0f1a8d63373e Mon Sep 17 00:00:00 2001 From: Mingun Date: Fri, 16 Aug 2024 22:22:26 +0500 Subject: [PATCH 172/258] Struct: add tests for deserialization from sequence (review this commit with "ignore whitespace changes" option on) --- .../tests/test_enum_adjacently_tagged.rs | 131 +++++++++++------- 1 file changed, 80 insertions(+), 51 deletions(-) diff --git a/test_suite/tests/test_enum_adjacently_tagged.rs b/test_suite/tests/test_enum_adjacently_tagged.rs index 5584f662b..0bcdbc39e 100644 --- a/test_suite/tests/test_enum_adjacently_tagged.rs +++ b/test_suite/tests/test_enum_adjacently_tagged.rs @@ -512,59 +512,88 @@ mod tuple { } } -#[test] -fn struct_() { - let value = AdjacentlyTagged::Struct:: { f: 1 }; +mod struct_ { + use super::*; - // struct with tag first - assert_tokens( - &value, - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Struct", - }, - Token::Str("c"), - Token::Struct { - name: "Struct", - len: 1, - }, - Token::Str("f"), - Token::U8(1), - Token::StructEnd, - Token::StructEnd, - ], - ); + #[test] + fn map() { + let value = AdjacentlyTagged::Struct:: { f: 1 }; - // struct with content first - assert_de_tokens( - &value, - &[ - Token::Struct { - name: "AdjacentlyTagged", - len: 2, - }, - Token::Str("c"), - Token::Struct { - name: "Struct", - len: 1, - }, - Token::Str("f"), - Token::U8(1), - Token::StructEnd, - Token::Str("t"), - Token::UnitVariant { - name: "AdjacentlyTagged", - variant: "Struct", - }, - Token::StructEnd, - ], - ); + // Map: tag + content + assert_tokens( + &value, + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Struct", + }, + Token::Str("c"), + Token::Struct { + name: "Struct", + len: 1, + }, + Token::Str("f"), + Token::U8(1), + Token::StructEnd, + Token::StructEnd, + ], + ); + + // Map: content + tag + assert_de_tokens( + &value, + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Str("c"), + Token::Struct { + name: "Struct", + len: 1, + }, + Token::Str("f"), + Token::U8(1), + Token::StructEnd, + Token::Str("t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Struct", + }, + Token::StructEnd, + ], + ); + } + + #[test] + fn seq() { + let value = AdjacentlyTagged::Struct:: { f: 1 }; + + // Seq: tag + content + assert_de_tokens( + &value, + &[ + Token::Seq { len: Some(2) }, + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Struct", + }, + Token::Struct { + name: "Struct", + len: 1, + }, + Token::Str("f"), + Token::U8(1), + Token::StructEnd, + Token::SeqEnd, + ], + ); + } } #[test] From 98fb7d94aa3d5ba7055a07494ab561da7868a9cc Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 17 Aug 2024 01:32:20 +0500 Subject: [PATCH 173/258] Move all untagged enum tests (except flatten) into a dedicated module Moved and renamed: From test_annotations - test_expecting_message_untagged_tagged_enum => expecting_message - flatten::enum_::untagged::straitforward => contains_flatten From test_macros - test_untagged_newtype_struct => newtype_struct - test_untagged_enum => complex - test_untagged_enum_with_flattened_integer_key => contains_flatten_with_integer_key - test_enum_in_untagged_enum => newtype_enum - test_untagged_bytes => string_and_bytes - test_untagged_newtype_variant_containing_unit_struct_not_map => newtype_unit_and_empty_map --- test_suite/tests/test_annotations.rs | 47 --- test_suite/tests/test_enum_untagged.rs | 409 +++++++++++++++++++++++++ test_suite/tests/test_macros.rs | 353 +-------------------- 3 files changed, 410 insertions(+), 399 deletions(-) create mode 100644 test_suite/tests/test_enum_untagged.rs diff --git a/test_suite/tests/test_annotations.rs b/test_suite/tests/test_annotations.rs index 9d03280d2..b26ec8722 100644 --- a/test_suite/tests/test_annotations.rs +++ b/test_suite/tests/test_annotations.rs @@ -1895,18 +1895,6 @@ fn test_expecting_message_externally_tagged_enum() { ); } -#[test] -fn test_expecting_message_untagged_tagged_enum() { - #[derive(Deserialize)] - #[serde(untagged)] - #[serde(expecting = "something strange...")] - enum Enum { - Untagged, - } - - assert_de_tokens_error::(&[Token::Str("Untagged")], "something strange..."); -} - #[test] fn test_expecting_message_identifier_enum() { #[derive(Deserialize)] @@ -2958,41 +2946,6 @@ mod flatten { mod untagged { use super::*; - #[test] - fn straightforward() { - #[derive(Serialize, Deserialize, PartialEq, Debug)] - #[serde(untagged)] - enum Data { - A { - a: i32, - #[serde(flatten)] - flat: Flat, - }, - } - - #[derive(Serialize, Deserialize, PartialEq, Debug)] - struct Flat { - b: i32, - } - - let data = Data::A { - a: 0, - flat: Flat { b: 0 }, - }; - - assert_tokens( - &data, - &[ - Token::Map { len: None }, - Token::Str("a"), - Token::I32(0), - Token::Str("b"), - Token::I32(0), - Token::MapEnd, - ], - ); - } - #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Flatten { #[serde(flatten)] diff --git a/test_suite/tests/test_enum_untagged.rs b/test_suite/tests/test_enum_untagged.rs new file mode 100644 index 000000000..1c7ce542c --- /dev/null +++ b/test_suite/tests/test_enum_untagged.rs @@ -0,0 +1,409 @@ +#![deny(trivial_numeric_casts)] +#![allow( + clippy::derive_partial_eq_without_eq, + clippy::enum_variant_names, + clippy::redundant_field_names, + clippy::too_many_lines +)] + +mod bytes; + +use serde_derive::{Deserialize, Serialize}; +use serde_test::{assert_de_tokens, assert_de_tokens_error, assert_tokens, Token}; +use std::collections::BTreeMap; + +#[test] +fn complex() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(untagged)] + enum Untagged { + A { a: u8 }, + B { b: u8 }, + C, + D(u8), + E(String), + F(u8, u8), + } + + assert_tokens( + &Untagged::A { a: 1 }, + &[ + Token::Struct { + name: "Untagged", + len: 1, + }, + Token::Str("a"), + Token::U8(1), + Token::StructEnd, + ], + ); + + assert_tokens( + &Untagged::B { b: 2 }, + &[ + Token::Struct { + name: "Untagged", + len: 1, + }, + Token::Str("b"), + Token::U8(2), + Token::StructEnd, + ], + ); + + // Serializes to unit, deserializes from either depending on format's + // preference. + assert_tokens(&Untagged::C, &[Token::Unit]); + assert_de_tokens(&Untagged::C, &[Token::None]); + + assert_tokens(&Untagged::D(4), &[Token::U8(4)]); + assert_tokens(&Untagged::E("e".to_owned()), &[Token::Str("e")]); + + assert_tokens( + &Untagged::F(1, 2), + &[ + Token::Tuple { len: 2 }, + Token::U8(1), + Token::U8(2), + Token::TupleEnd, + ], + ); + + assert_de_tokens_error::( + &[Token::Tuple { len: 1 }, Token::U8(1), Token::TupleEnd], + "data did not match any variant of untagged enum Untagged", + ); + + assert_de_tokens_error::( + &[ + Token::Tuple { len: 3 }, + Token::U8(1), + Token::U8(2), + Token::U8(3), + Token::TupleEnd, + ], + "data did not match any variant of untagged enum Untagged", + ); +} + +#[test] +fn newtype_unit_and_empty_map() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct Unit; + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(untagged)] + enum Message { + Unit(Unit), + Map(BTreeMap), + } + + assert_tokens( + &Message::Map(BTreeMap::new()), + &[Token::Map { len: Some(0) }, Token::MapEnd], + ); +} + +#[test] +fn newtype_struct() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct GenericNewTypeStruct(T); + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(untagged)] + enum E { + Newtype(GenericNewTypeStruct), + Null, + } + + assert_tokens( + &E::Newtype(GenericNewTypeStruct(5u32)), + &[ + Token::NewtypeStruct { + name: "GenericNewTypeStruct", + }, + Token::U32(5), + ], + ); +} + +#[test] +fn newtype_enum() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(untagged)] + enum Outer { + Inner(Inner), + } + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + enum Inner { + Unit, + Newtype(u8), + Tuple(u8, u8), + Struct { f: u8 }, + } + + assert_tokens( + &Outer::Inner(Inner::Unit), + &[Token::UnitVariant { + name: "Inner", + variant: "Unit", + }], + ); + + assert_tokens( + &Outer::Inner(Inner::Newtype(1)), + &[ + Token::NewtypeVariant { + name: "Inner", + variant: "Newtype", + }, + Token::U8(1), + ], + ); + + assert_tokens( + &Outer::Inner(Inner::Tuple(1, 1)), + &[ + Token::TupleVariant { + name: "Inner", + variant: "Tuple", + len: 2, + }, + Token::U8(1), + Token::U8(1), + Token::TupleVariantEnd, + ], + ); + + assert_tokens( + &Outer::Inner(Inner::Struct { f: 1 }), + &[ + Token::StructVariant { + name: "Inner", + variant: "Struct", + len: 1, + }, + Token::Str("f"), + Token::U8(1), + Token::StructVariantEnd, + ], + ); +} + +#[test] +fn string_and_bytes() { + #[derive(Debug, PartialEq, Deserialize)] + #[serde(untagged)] + enum Untagged { + String { + string: String, + }, + Bytes { + #[serde(with = "bytes")] + bytes: Vec, + }, + } + + assert_de_tokens( + &Untagged::String { + string: "\0".to_owned(), + }, + &[ + Token::Struct { + name: "Untagged", + len: 1, + }, + Token::Str("string"), + Token::Str("\0"), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &Untagged::String { + string: "\0".to_owned(), + }, + &[ + Token::Struct { + name: "Untagged", + len: 1, + }, + Token::Str("string"), + Token::String("\0"), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &Untagged::String { + string: "\0".to_owned(), + }, + &[ + Token::Struct { + name: "Untagged", + len: 1, + }, + Token::Str("string"), + Token::Bytes(b"\0"), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &Untagged::String { + string: "\0".to_owned(), + }, + &[ + Token::Struct { + name: "Untagged", + len: 1, + }, + Token::Str("string"), + Token::ByteBuf(b"\0"), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &Untagged::Bytes { bytes: vec![0] }, + &[ + Token::Struct { + name: "Untagged", + len: 1, + }, + Token::Str("bytes"), + Token::Str("\0"), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &Untagged::Bytes { bytes: vec![0] }, + &[ + Token::Struct { + name: "Untagged", + len: 1, + }, + Token::Str("bytes"), + Token::String("\0"), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &Untagged::Bytes { bytes: vec![0] }, + &[ + Token::Struct { + name: "Untagged", + len: 1, + }, + Token::Str("bytes"), + Token::Bytes(b"\0"), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &Untagged::Bytes { bytes: vec![0] }, + &[ + Token::Struct { + name: "Untagged", + len: 1, + }, + Token::Str("bytes"), + Token::ByteBuf(b"\0"), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &Untagged::Bytes { bytes: vec![0] }, + &[ + Token::Struct { + name: "Untagged", + len: 1, + }, + Token::Str("bytes"), + Token::Seq { len: Some(1) }, + Token::U8(0), + Token::SeqEnd, + Token::StructEnd, + ], + ); +} + +#[test] +fn contains_flatten() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[serde(untagged)] + enum Data { + A { + a: i32, + #[serde(flatten)] + flat: Flat, + }, + } + + #[derive(Serialize, Deserialize, PartialEq, Debug)] + struct Flat { + b: i32, + } + + let data = Data::A { + a: 0, + flat: Flat { b: 0 }, + }; + + assert_tokens( + &data, + &[ + Token::Map { len: None }, + Token::Str("a"), + Token::I32(0), + Token::Str("b"), + Token::I32(0), + Token::MapEnd, + ], + ); +} + +#[test] +fn contains_flatten_with_integer_key() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(untagged)] + pub enum Untagged { + Variant { + #[serde(flatten)] + map: BTreeMap, + }, + } + + assert_tokens( + &Untagged::Variant { + map: { + let mut map = BTreeMap::new(); + map.insert(100, "BTreeMap".to_owned()); + map + }, + }, + &[ + Token::Map { len: None }, + Token::U64(100), + Token::Str("BTreeMap"), + Token::MapEnd, + ], + ); +} + +#[test] +fn expecting_message() { + #[derive(Deserialize)] + #[serde(untagged)] + #[serde(expecting = "something strange...")] + enum Enum { + Untagged, + } + + assert_de_tokens_error::(&[Token::Str("Untagged")], "something strange..."); +} diff --git a/test_suite/tests/test_macros.rs b/test_suite/tests/test_macros.rs index aaab95816..6b2fc4c5d 100644 --- a/test_suite/tests/test_macros.rs +++ b/test_suite/tests/test_macros.rs @@ -6,13 +6,8 @@ clippy::too_many_lines )] -mod bytes; - use serde_derive::{Deserialize, Serialize}; -use serde_test::{ - assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_tokens, Token, -}; -use std::collections::BTreeMap; +use serde_test::{assert_de_tokens, assert_ser_tokens, assert_tokens, Token}; use std::marker::PhantomData; // That tests that the derived Serialize implementation doesn't trigger @@ -433,26 +428,6 @@ fn test_generic_newtype_struct() { ); } -#[test] -fn test_untagged_newtype_struct() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(untagged)] - enum E { - Newtype(GenericNewTypeStruct), - Null, - } - - assert_tokens( - &E::Newtype(GenericNewTypeStruct(5u32)), - &[ - Token::NewtypeStruct { - name: "GenericNewTypeStruct", - }, - Token::U32(5), - ], - ); -} - #[test] fn test_generic_tuple_struct() { assert_tokens( @@ -577,80 +552,6 @@ fn test_enum_state_field() { ); } -#[test] -fn test_untagged_enum() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(untagged)] - enum Untagged { - A { a: u8 }, - B { b: u8 }, - C, - D(u8), - E(String), - F(u8, u8), - } - - assert_tokens( - &Untagged::A { a: 1 }, - &[ - Token::Struct { - name: "Untagged", - len: 1, - }, - Token::Str("a"), - Token::U8(1), - Token::StructEnd, - ], - ); - - assert_tokens( - &Untagged::B { b: 2 }, - &[ - Token::Struct { - name: "Untagged", - len: 1, - }, - Token::Str("b"), - Token::U8(2), - Token::StructEnd, - ], - ); - - // Serializes to unit, deserializes from either depending on format's - // preference. - assert_tokens(&Untagged::C, &[Token::Unit]); - assert_de_tokens(&Untagged::C, &[Token::None]); - - assert_tokens(&Untagged::D(4), &[Token::U8(4)]); - assert_tokens(&Untagged::E("e".to_owned()), &[Token::Str("e")]); - - assert_tokens( - &Untagged::F(1, 2), - &[ - Token::Tuple { len: 2 }, - Token::U8(1), - Token::U8(2), - Token::TupleEnd, - ], - ); - - assert_de_tokens_error::( - &[Token::Tuple { len: 1 }, Token::U8(1), Token::TupleEnd], - "data did not match any variant of untagged enum Untagged", - ); - - assert_de_tokens_error::( - &[ - Token::Tuple { len: 3 }, - Token::U8(1), - Token::U8(2), - Token::U8(3), - Token::TupleEnd, - ], - "data did not match any variant of untagged enum Untagged", - ); -} - #[test] fn test_internally_tagged_struct() { #[derive(Debug, PartialEq, Serialize, Deserialize)] @@ -750,240 +651,6 @@ fn test_internally_tagged_struct_with_flattened_field() { ); } -#[test] -fn test_untagged_enum_with_flattened_integer_key() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(untagged)] - pub enum Untagged { - Variant { - #[serde(flatten)] - map: BTreeMap, - }, - } - - assert_tokens( - &Untagged::Variant { - map: { - let mut map = BTreeMap::new(); - map.insert(100, "BTreeMap".to_owned()); - map - }, - }, - &[ - Token::Map { len: None }, - Token::U64(100), - Token::Str("BTreeMap"), - Token::MapEnd, - ], - ); -} - -#[test] -fn test_enum_in_untagged_enum() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(untagged)] - enum Outer { - Inner(Inner), - } - - #[derive(Debug, PartialEq, Serialize, Deserialize)] - enum Inner { - Unit, - Newtype(u8), - Tuple(u8, u8), - Struct { f: u8 }, - } - - assert_tokens( - &Outer::Inner(Inner::Unit), - &[Token::UnitVariant { - name: "Inner", - variant: "Unit", - }], - ); - - assert_tokens( - &Outer::Inner(Inner::Newtype(1)), - &[ - Token::NewtypeVariant { - name: "Inner", - variant: "Newtype", - }, - Token::U8(1), - ], - ); - - assert_tokens( - &Outer::Inner(Inner::Tuple(1, 1)), - &[ - Token::TupleVariant { - name: "Inner", - variant: "Tuple", - len: 2, - }, - Token::U8(1), - Token::U8(1), - Token::TupleVariantEnd, - ], - ); - - assert_tokens( - &Outer::Inner(Inner::Struct { f: 1 }), - &[ - Token::StructVariant { - name: "Inner", - variant: "Struct", - len: 1, - }, - Token::Str("f"), - Token::U8(1), - Token::StructVariantEnd, - ], - ); -} - -#[test] -fn test_untagged_bytes() { - #[derive(Debug, PartialEq, Deserialize)] - #[serde(untagged)] - enum Untagged { - String { - string: String, - }, - Bytes { - #[serde(with = "bytes")] - bytes: Vec, - }, - } - - assert_de_tokens( - &Untagged::String { - string: "\0".to_owned(), - }, - &[ - Token::Struct { - name: "Untagged", - len: 1, - }, - Token::Str("string"), - Token::Str("\0"), - Token::StructEnd, - ], - ); - - assert_de_tokens( - &Untagged::String { - string: "\0".to_owned(), - }, - &[ - Token::Struct { - name: "Untagged", - len: 1, - }, - Token::Str("string"), - Token::String("\0"), - Token::StructEnd, - ], - ); - - assert_de_tokens( - &Untagged::String { - string: "\0".to_owned(), - }, - &[ - Token::Struct { - name: "Untagged", - len: 1, - }, - Token::Str("string"), - Token::Bytes(b"\0"), - Token::StructEnd, - ], - ); - - assert_de_tokens( - &Untagged::String { - string: "\0".to_owned(), - }, - &[ - Token::Struct { - name: "Untagged", - len: 1, - }, - Token::Str("string"), - Token::ByteBuf(b"\0"), - Token::StructEnd, - ], - ); - - assert_de_tokens( - &Untagged::Bytes { bytes: vec![0] }, - &[ - Token::Struct { - name: "Untagged", - len: 1, - }, - Token::Str("bytes"), - Token::Str("\0"), - Token::StructEnd, - ], - ); - - assert_de_tokens( - &Untagged::Bytes { bytes: vec![0] }, - &[ - Token::Struct { - name: "Untagged", - len: 1, - }, - Token::Str("bytes"), - Token::String("\0"), - Token::StructEnd, - ], - ); - - assert_de_tokens( - &Untagged::Bytes { bytes: vec![0] }, - &[ - Token::Struct { - name: "Untagged", - len: 1, - }, - Token::Str("bytes"), - Token::Bytes(b"\0"), - Token::StructEnd, - ], - ); - - assert_de_tokens( - &Untagged::Bytes { bytes: vec![0] }, - &[ - Token::Struct { - name: "Untagged", - len: 1, - }, - Token::Str("bytes"), - Token::ByteBuf(b"\0"), - Token::StructEnd, - ], - ); - - assert_de_tokens( - &Untagged::Bytes { bytes: vec![0] }, - &[ - Token::Struct { - name: "Untagged", - len: 1, - }, - Token::Str("bytes"), - Token::Seq { len: Some(1) }, - Token::U8(0), - Token::SeqEnd, - Token::StructEnd, - ], - ); -} - #[test] fn test_rename_all() { #[derive(Serialize, Deserialize, Debug, PartialEq)] @@ -1167,24 +834,6 @@ fn test_rename_all_fields() { ); } -#[test] -fn test_untagged_newtype_variant_containing_unit_struct_not_map() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - struct Unit; - - #[derive(Debug, PartialEq, Serialize, Deserialize)] - #[serde(untagged)] - enum Message { - Unit(Unit), - Map(BTreeMap), - } - - assert_tokens( - &Message::Map(BTreeMap::new()), - &[Token::Map { len: Some(0) }, Token::MapEnd], - ); -} - #[test] fn test_packed_struct_can_derive_serialize() { #[derive(Copy, Clone, Serialize)] From 8514f4119aa1833bbd7a73231fedcbfeb5970e78 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 17 Aug 2024 12:48:27 +0500 Subject: [PATCH 174/258] Remove unnecessary generics --- test_suite/tests/test_enum_untagged.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test_suite/tests/test_enum_untagged.rs b/test_suite/tests/test_enum_untagged.rs index 1c7ce542c..d06002ce8 100644 --- a/test_suite/tests/test_enum_untagged.rs +++ b/test_suite/tests/test_enum_untagged.rs @@ -107,20 +107,20 @@ fn newtype_unit_and_empty_map() { #[test] fn newtype_struct() { #[derive(Debug, PartialEq, Serialize, Deserialize)] - struct GenericNewTypeStruct(T); + struct NewtypeStruct(u32); #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(untagged)] enum E { - Newtype(GenericNewTypeStruct), + Newtype(NewtypeStruct), Null, } assert_tokens( - &E::Newtype(GenericNewTypeStruct(5u32)), + &E::Newtype(NewtypeStruct(5)), &[ Token::NewtypeStruct { - name: "GenericNewTypeStruct", + name: "NewtypeStruct", }, Token::U32(5), ], From 2dddc7796d436b2bfa0d1016d252250a3f7c4d18 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 17 Aug 2024 11:58:28 +0500 Subject: [PATCH 175/258] Cover ContentRefDeserializer::deserialize_option --- serde/src/private/de.rs | 7 +++ test_suite/tests/test_enum_untagged.rs | 74 ++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index 6c81b720b..5b5d9b6a1 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -1898,10 +1898,17 @@ mod content { where V: Visitor<'de>, { + // Covered by tests/test_enum_untagged.rs + // with_optional_field::* match *self.content { Content::None => visitor.visit_none(), Content::Some(ref v) => visitor.visit_some(ContentRefDeserializer::new(v)), Content::Unit => visitor.visit_unit(), + // This case is necessary for formats which does not store marker of optionality of value, + // for example, JSON. When `deserialize_any` is requested from such formats, they will + // report value without using `Visitor::visit_some`, because they do not known in which + // contexts this value will be used. + // RON is example of format which preserve markers. _ => visitor.visit_some(self), } } diff --git a/test_suite/tests/test_enum_untagged.rs b/test_suite/tests/test_enum_untagged.rs index d06002ce8..60c62bac6 100644 --- a/test_suite/tests/test_enum_untagged.rs +++ b/test_suite/tests/test_enum_untagged.rs @@ -191,6 +191,80 @@ fn newtype_enum() { ); } +// Reaches crate::private::de::content::ContentRefDeserializer::deserialize_option +mod with_optional_field { + use super::*; + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(untagged)] + enum Enum { + Struct { optional: Option }, + Null, + } + + #[test] + fn some() { + assert_tokens( + &Enum::Struct { optional: Some(42) }, + &[ + Token::Struct { + name: "Enum", + len: 1, + }, + Token::Str("optional"), + Token::Some, + Token::U32(42), + Token::StructEnd, + ], + ); + } + + #[test] + fn some_without_marker() { + assert_de_tokens( + &Enum::Struct { optional: Some(42) }, + &[ + Token::Struct { + name: "Enum", + len: 1, + }, + Token::Str("optional"), + Token::U32(42), + Token::StructEnd, + ], + ); + } + + #[test] + fn none() { + assert_tokens( + &Enum::Struct { optional: None }, + &[ + Token::Struct { + name: "Enum", + len: 1, + }, + Token::Str("optional"), + Token::None, + Token::StructEnd, + ], + ); + } + + #[test] + fn unit() { + assert_de_tokens( + &Enum::Struct { optional: None }, + &[ + Token::Map { len: None }, + Token::Str("optional"), + Token::Unit, + Token::MapEnd, + ], + ); + } +} + #[test] fn string_and_bytes() { #[derive(Debug, PartialEq, Deserialize)] From 171c6da57af712cfcf01c6c124b14cabfca364ba Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 17 Aug 2024 11:31:50 +0500 Subject: [PATCH 176/258] Complete coverage of ContentRefDeserializer::deserialize_newtype_struct --- serde/src/private/de.rs | 7 +++++++ test_suite/tests/test_enum_untagged.rs | 9 ++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index 5b5d9b6a1..846647e0c 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -1938,10 +1938,17 @@ mod content { where V: Visitor<'de>, { + // Covered by tests/test_enum_untagged.rs + // newtype_struct match *self.content { Content::Newtype(ref v) => { visitor.visit_newtype_struct(ContentRefDeserializer::new(v)) } + // This case is necessary for formats which does not store marker of a newtype, + // for example, JSON. When `deserialize_any` is requested from such formats, they will + // report value without using `Visitor::visit_newtype_struct`, because they do not + // known in which contexts this value will be used. + // RON is example of format which preserve markers. _ => visitor.visit_newtype_struct(self), } } diff --git a/test_suite/tests/test_enum_untagged.rs b/test_suite/tests/test_enum_untagged.rs index 60c62bac6..9079eeb60 100644 --- a/test_suite/tests/test_enum_untagged.rs +++ b/test_suite/tests/test_enum_untagged.rs @@ -104,6 +104,7 @@ fn newtype_unit_and_empty_map() { ); } +// Reaches crate::private::de::content::ContentRefDeserializer::deserialize_newtype_struct #[test] fn newtype_struct() { #[derive(Debug, PartialEq, Serialize, Deserialize)] @@ -116,8 +117,11 @@ fn newtype_struct() { Null, } + let value = E::Newtype(NewtypeStruct(5)); + + // Content::Newtype case assert_tokens( - &E::Newtype(NewtypeStruct(5)), + &value, &[ Token::NewtypeStruct { name: "NewtypeStruct", @@ -125,6 +129,9 @@ fn newtype_struct() { Token::U32(5), ], ); + + // _ case + assert_de_tokens(&value, &[Token::U32(5)]); } #[test] From 0093f74cfee5ee3239514a7aad5fb44843eddcdd Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 17 Aug 2024 14:53:41 +0500 Subject: [PATCH 177/258] Split test newtype_enum into four tests for each variant (review this commit with "ignore whitespace changes" option on) --- serde/src/private/de.rs | 16 ++++ test_suite/tests/test_enum_untagged.rs | 110 ++++++++++++++----------- 2 files changed, 80 insertions(+), 46 deletions(-) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index 846647e0c..864f93b02 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -2153,6 +2153,10 @@ mod content { fn unit_variant(self) -> Result<(), E> { match self.value { Some(value) => de::Deserialize::deserialize(ContentRefDeserializer::new(value)), + // Covered by tests/test_annotations.rs + // test_partially_untagged_adjacently_tagged_enum + // Covered by tests/test_enum_untagged.rs + // newtype_enum::unit None => Ok(()), } } @@ -2162,6 +2166,11 @@ mod content { T: de::DeserializeSeed<'de>, { match self.value { + // Covered by tests/test_annotations.rs + // test_partially_untagged_enum_desugared + // test_partially_untagged_enum_generic + // Covered by tests/test_enum_untagged.rs + // newtype_enum::newtype Some(value) => seed.deserialize(ContentRefDeserializer::new(value)), None => Err(de::Error::invalid_type( de::Unexpected::UnitVariant, @@ -2175,6 +2184,11 @@ mod content { V: de::Visitor<'de>, { match self.value { + // Covered by tests/test_annotations.rs + // test_partially_untagged_enum + // test_partially_untagged_enum_desugared + // Covered by tests/test_enum_untagged.rs + // newtype_enum::tuple2 Some(Content::Seq(v)) => { de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor) } @@ -2198,6 +2212,8 @@ mod content { V: de::Visitor<'de>, { match self.value { + // Covered by tests/test_enum_untagged.rs + // newtype_enum::struct_from_map Some(Content::Map(v)) => { de::Deserializer::deserialize_any(MapRefDeserializer::new(v), visitor) } diff --git a/test_suite/tests/test_enum_untagged.rs b/test_suite/tests/test_enum_untagged.rs index 9079eeb60..8c212a970 100644 --- a/test_suite/tests/test_enum_untagged.rs +++ b/test_suite/tests/test_enum_untagged.rs @@ -134,8 +134,9 @@ fn newtype_struct() { assert_de_tokens(&value, &[Token::U32(5)]); } -#[test] -fn newtype_enum() { +mod newtype_enum { + use super::*; + #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(untagged)] enum Outer { @@ -146,56 +147,73 @@ fn newtype_enum() { enum Inner { Unit, Newtype(u8), - Tuple(u8, u8), + Tuple2(u8, u8), Struct { f: u8 }, } - assert_tokens( - &Outer::Inner(Inner::Unit), - &[Token::UnitVariant { - name: "Inner", - variant: "Unit", - }], - ); - - assert_tokens( - &Outer::Inner(Inner::Newtype(1)), - &[ - Token::NewtypeVariant { + // Reaches crate::private::de::content::VariantRefDeserializer::unit_variant + #[test] + fn unit() { + assert_tokens( + &Outer::Inner(Inner::Unit), + &[Token::UnitVariant { name: "Inner", - variant: "Newtype", - }, - Token::U8(1), - ], - ); + variant: "Unit", + }], + ); + } - assert_tokens( - &Outer::Inner(Inner::Tuple(1, 1)), - &[ - Token::TupleVariant { - name: "Inner", - variant: "Tuple", - len: 2, - }, - Token::U8(1), - Token::U8(1), - Token::TupleVariantEnd, - ], - ); + // Reaches crate::private::de::content::VariantRefDeserializer::newtype_variant_seed + #[test] + fn newtype() { + assert_tokens( + &Outer::Inner(Inner::Newtype(1)), + &[ + Token::NewtypeVariant { + name: "Inner", + variant: "Newtype", + }, + Token::U8(1), + ], + ); + } - assert_tokens( - &Outer::Inner(Inner::Struct { f: 1 }), - &[ - Token::StructVariant { - name: "Inner", - variant: "Struct", - len: 1, - }, - Token::Str("f"), - Token::U8(1), - Token::StructVariantEnd, - ], - ); + // Reaches crate::private::de::content::VariantRefDeserializer::tuple_variant + #[test] + fn tuple2() { + assert_tokens( + &Outer::Inner(Inner::Tuple2(1, 1)), + &[ + Token::TupleVariant { + name: "Inner", + variant: "Tuple2", + len: 2, + }, + Token::U8(1), + Token::U8(1), + Token::TupleVariantEnd, + ], + ); + } + + // Reaches crate::private::de::content::VariantRefDeserializer::struct_variant + // Content::Map case + #[test] + fn struct_from_map() { + assert_tokens( + &Outer::Inner(Inner::Struct { f: 1 }), + &[ + Token::StructVariant { + name: "Inner", + variant: "Struct", + len: 1, + }, + Token::Str("f"), + Token::U8(1), + Token::StructVariantEnd, + ], + ); + } } // Reaches crate::private::de::content::ContentRefDeserializer::deserialize_option From 6588b0ad3777f7ad930d68ab4b9ec5b9c25398e0 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 17 Aug 2024 15:26:59 +0500 Subject: [PATCH 178/258] Cover Content::Seq case in VariantRefDeserializer::struct_variant --- serde/src/private/de.rs | 2 ++ test_suite/tests/test_enum_untagged.rs | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index 864f93b02..0c6f4d3a0 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -2217,6 +2217,8 @@ mod content { Some(Content::Map(v)) => { de::Deserializer::deserialize_any(MapRefDeserializer::new(v), visitor) } + // Covered by tests/test_enum_untagged.rs + // newtype_enum::struct_from_seq Some(Content::Seq(v)) => { de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor) } diff --git a/test_suite/tests/test_enum_untagged.rs b/test_suite/tests/test_enum_untagged.rs index 8c212a970..01ecae9c1 100644 --- a/test_suite/tests/test_enum_untagged.rs +++ b/test_suite/tests/test_enum_untagged.rs @@ -214,6 +214,25 @@ mod newtype_enum { ], ); } + + // Reaches crate::private::de::content::VariantRefDeserializer::struct_variant + // Content::Seq case + #[test] + fn struct_from_seq() { + assert_de_tokens( + &Outer::Inner(Inner::Struct { f: 1 }), + &[ + Token::Map { len: Some(1) }, + // tag + Token::Str("Struct"), + // content + Token::Seq { len: Some(1) }, + Token::U8(1), + Token::SeqEnd, + Token::MapEnd, + ], + ); + } } // Reaches crate::private::de::content::ContentRefDeserializer::deserialize_option From 4c5fec1363d363f995375426f72db11c28f357c1 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 17 Aug 2024 16:05:34 +0500 Subject: [PATCH 179/258] Test special cases that reaches SeqRefDeserializer::deserialize_any len==0 condition failures (2): newtype_enum::empty_struct_from_seq newtype_enum::tuple0 --- serde/src/private/de.rs | 2 + test_suite/tests/test_enum_untagged.rs | 56 ++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index 0c6f4d3a0..cb34f1c31 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -2188,6 +2188,7 @@ mod content { // test_partially_untagged_enum // test_partially_untagged_enum_desugared // Covered by tests/test_enum_untagged.rs + // newtype_enum::tuple0 // newtype_enum::tuple2 Some(Content::Seq(v)) => { de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor) @@ -2219,6 +2220,7 @@ mod content { } // Covered by tests/test_enum_untagged.rs // newtype_enum::struct_from_seq + // newtype_enum::empty_struct_from_seq Some(Content::Seq(v)) => { de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor) } diff --git a/test_suite/tests/test_enum_untagged.rs b/test_suite/tests/test_enum_untagged.rs index 01ecae9c1..48f50c9c2 100644 --- a/test_suite/tests/test_enum_untagged.rs +++ b/test_suite/tests/test_enum_untagged.rs @@ -147,8 +147,10 @@ mod newtype_enum { enum Inner { Unit, Newtype(u8), + Tuple0(), Tuple2(u8, u8), Struct { f: u8 }, + EmptyStruct {}, } // Reaches crate::private::de::content::VariantRefDeserializer::unit_variant @@ -178,6 +180,22 @@ mod newtype_enum { ); } + // Reaches crate::private::de::content::VariantRefDeserializer::tuple_variant + #[test] + fn tuple0() { + assert_tokens( + &Outer::Inner(Inner::Tuple0()), + &[ + Token::TupleVariant { + name: "Inner", + variant: "Tuple0", + len: 0, + }, + Token::TupleVariantEnd, + ], + ); + } + // Reaches crate::private::de::content::VariantRefDeserializer::tuple_variant #[test] fn tuple2() { @@ -233,6 +251,44 @@ mod newtype_enum { ], ); } + + // Reaches crate::private::de::content::VariantRefDeserializer::struct_variant + // Content::Map case + // Special case - empty map + #[test] + fn empty_struct_from_map() { + assert_de_tokens( + &Outer::Inner(Inner::EmptyStruct {}), + &[ + Token::Map { len: Some(1) }, + // tag + Token::Str("EmptyStruct"), + // content + Token::Map { len: Some(0) }, + Token::MapEnd, + Token::MapEnd, + ], + ); + } + + // Reaches crate::private::de::content::VariantRefDeserializer::struct_variant + // Content::Seq case + // Special case - empty seq + #[test] + fn empty_struct_from_seq() { + assert_de_tokens( + &Outer::Inner(Inner::EmptyStruct {}), + &[ + Token::Map { len: Some(1) }, + // tag + Token::Str("EmptyStruct"), + // content + Token::Seq { len: Some(0) }, + Token::SeqEnd, + Token::MapEnd, + ], + ); + } } // Reaches crate::private::de::content::ContentRefDeserializer::deserialize_option From da7fc795ee654252effa232a62a5a1e6d4f551ee Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 17 Aug 2024 16:32:36 +0500 Subject: [PATCH 180/258] Fix deserialization of empty struct variant in untagged enums SeqRefDeserializer::deserialize_any has a special condition for empty sequence, which emits visit_unit. That condition assumes that type would be able to deserialized from unit, but: 1) struct variants was never able to deserialize from it (they expect only visit_map or visit_seq) 2) tuple variants even with zero fields expect visit_seq only. The suggestion to accept visit_unit instead was rejected in #2520 Fixes (2): newtype_enum::tuple0 newtype_enum::empty_struct_from_seq --- serde/src/private/de.rs | 83 +---------------------------------------- 1 file changed, 2 insertions(+), 81 deletions(-) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index cb34f1c31..be2b119d2 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -2190,9 +2190,7 @@ mod content { // Covered by tests/test_enum_untagged.rs // newtype_enum::tuple0 // newtype_enum::tuple2 - Some(Content::Seq(v)) => { - de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor) - } + Some(Content::Seq(v)) => visit_content_seq_ref(v, visitor), Some(other) => Err(de::Error::invalid_type( other.unexpected(), &"tuple variant", @@ -2221,9 +2219,7 @@ mod content { // Covered by tests/test_enum_untagged.rs // newtype_enum::struct_from_seq // newtype_enum::empty_struct_from_seq - Some(Content::Seq(v)) => { - de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor) - } + Some(Content::Seq(v)) => visit_content_seq_ref(v, visitor), Some(other) => Err(de::Error::invalid_type( other.unexpected(), &"struct variant", @@ -2236,81 +2232,6 @@ mod content { } } - struct SeqRefDeserializer<'a, 'de: 'a, E> - where - E: de::Error, - { - iter: <&'a [Content<'de>] as IntoIterator>::IntoIter, - err: PhantomData, - } - - impl<'a, 'de, E> SeqRefDeserializer<'a, 'de, E> - where - E: de::Error, - { - fn new(slice: &'a [Content<'de>]) -> Self { - SeqRefDeserializer { - iter: slice.iter(), - err: PhantomData, - } - } - } - - impl<'de, 'a, E> de::Deserializer<'de> for SeqRefDeserializer<'a, 'de, E> - where - E: de::Error, - { - type Error = E; - - #[inline] - fn deserialize_any(mut self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - let len = self.iter.len(); - if len == 0 { - visitor.visit_unit() - } else { - let ret = tri!(visitor.visit_seq(&mut self)); - let remaining = self.iter.len(); - if remaining == 0 { - Ok(ret) - } else { - Err(de::Error::invalid_length(len, &"fewer elements in array")) - } - } - } - - forward_to_deserialize_any! { - bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string - bytes byte_buf option unit unit_struct newtype_struct seq tuple - tuple_struct map struct enum identifier ignored_any - } - } - - impl<'de, 'a, E> de::SeqAccess<'de> for SeqRefDeserializer<'a, 'de, E> - where - E: de::Error, - { - type Error = E; - - fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> - where - T: de::DeserializeSeed<'de>, - { - match self.iter.next() { - Some(value) => seed - .deserialize(ContentRefDeserializer::new(value)) - .map(Some), - None => Ok(None), - } - } - - fn size_hint(&self) -> Option { - size_hint::from_bounds(&self.iter) - } - } - struct MapRefDeserializer<'a, 'de: 'a, E> where E: de::Error, From 7bde100237875d4f435de5ad90074b0479c37486 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 17 Aug 2024 17:09:53 +0500 Subject: [PATCH 181/258] Replace MapRefDeserializer with value::MapDeserializer Although they are slightly different, this difference is irrelevant: - MapDeserializer has a specialization for deserialize_seq and deserialize_tuple, but only MapRefDeserializer::deserialize_any is used by the code which is almost the same - MapDeserializer checks that map was consumed after visit_map, but MapRefDeserializer does not. Actually, each derived implementation consumes map and each manual implementation also should consume it Also, MapDeserializer already used when value deserialized from ContentRefDeserializer directly and MapRefDeserializer was only used to deserialize Struct variants of enums. There are no reasons why the behavior should be different in those two cases --- serde/src/private/de.rs | 81 +---------------------------------------- 1 file changed, 1 insertion(+), 80 deletions(-) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index be2b119d2..2682136cb 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -2213,9 +2213,7 @@ mod content { match self.value { // Covered by tests/test_enum_untagged.rs // newtype_enum::struct_from_map - Some(Content::Map(v)) => { - de::Deserializer::deserialize_any(MapRefDeserializer::new(v), visitor) - } + Some(Content::Map(v)) => visit_content_map_ref(v, visitor), // Covered by tests/test_enum_untagged.rs // newtype_enum::struct_from_seq // newtype_enum::empty_struct_from_seq @@ -2232,83 +2230,6 @@ mod content { } } - struct MapRefDeserializer<'a, 'de: 'a, E> - where - E: de::Error, - { - iter: <&'a [(Content<'de>, Content<'de>)] as IntoIterator>::IntoIter, - value: Option<&'a Content<'de>>, - err: PhantomData, - } - - impl<'a, 'de, E> MapRefDeserializer<'a, 'de, E> - where - E: de::Error, - { - fn new(map: &'a [(Content<'de>, Content<'de>)]) -> Self { - MapRefDeserializer { - iter: map.iter(), - value: None, - err: PhantomData, - } - } - } - - impl<'de, 'a, E> de::MapAccess<'de> for MapRefDeserializer<'a, 'de, E> - where - E: de::Error, - { - type Error = E; - - fn next_key_seed(&mut self, seed: T) -> Result, Self::Error> - where - T: de::DeserializeSeed<'de>, - { - match self.iter.next() { - Some((key, value)) => { - self.value = Some(value); - seed.deserialize(ContentRefDeserializer::new(key)).map(Some) - } - None => Ok(None), - } - } - - fn next_value_seed(&mut self, seed: T) -> Result - where - T: de::DeserializeSeed<'de>, - { - match self.value.take() { - Some(value) => seed.deserialize(ContentRefDeserializer::new(value)), - None => Err(de::Error::custom("value is missing")), - } - } - - fn size_hint(&self) -> Option { - size_hint::from_bounds(&self.iter) - } - } - - impl<'de, 'a, E> de::Deserializer<'de> for MapRefDeserializer<'a, 'de, E> - where - E: de::Error, - { - type Error = E; - - #[inline] - fn deserialize_any(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - visitor.visit_map(self) - } - - forward_to_deserialize_any! { - bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string - bytes byte_buf option unit unit_struct newtype_struct seq tuple - tuple_struct map struct enum identifier ignored_any - } - } - impl<'de, E> de::IntoDeserializer<'de, E> for ContentDeserializer<'de, E> where E: de::Error, From 87a2fb0f1a2774ea5bb20c0ed988b9ba57fc8166 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 23 Aug 2024 19:33:54 -0700 Subject: [PATCH 182/258] Wrap comments from PR 2805 to 80 columns --- serde/src/private/de.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index 2682136cb..484db2a1e 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -1904,10 +1904,11 @@ mod content { Content::None => visitor.visit_none(), Content::Some(ref v) => visitor.visit_some(ContentRefDeserializer::new(v)), Content::Unit => visitor.visit_unit(), - // This case is necessary for formats which does not store marker of optionality of value, - // for example, JSON. When `deserialize_any` is requested from such formats, they will - // report value without using `Visitor::visit_some`, because they do not known in which - // contexts this value will be used. + // This case is necessary for formats which does not store + // marker of optionality of value, for example, JSON. When + // `deserialize_any` is requested from such formats, they will + // report value without using `Visitor::visit_some`, because + // they do not known in which contexts this value will be used. // RON is example of format which preserve markers. _ => visitor.visit_some(self), } @@ -1944,11 +1945,12 @@ mod content { Content::Newtype(ref v) => { visitor.visit_newtype_struct(ContentRefDeserializer::new(v)) } - // This case is necessary for formats which does not store marker of a newtype, - // for example, JSON. When `deserialize_any` is requested from such formats, they will - // report value without using `Visitor::visit_newtype_struct`, because they do not - // known in which contexts this value will be used. - // RON is example of format which preserve markers. + // This case is necessary for formats which does not store + // marker of a newtype, for example, JSON. When + // `deserialize_any` is requested from such formats, they will + // report value without using `Visitor::visit_newtype_struct`, + // because they do not known in which contexts this value will + // be used. RON is example of format which preserve markers. _ => visitor.visit_newtype_struct(self), } } From b84e6ca4f5fef69b3de985c586a07b1246f3eb9a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 23 Aug 2024 19:42:10 -0700 Subject: [PATCH 183/258] Improve wording of PR 2805 comments --- serde/src/private/de.rs | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index 484db2a1e..f0eca71ff 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -1904,12 +1904,13 @@ mod content { Content::None => visitor.visit_none(), Content::Some(ref v) => visitor.visit_some(ContentRefDeserializer::new(v)), Content::Unit => visitor.visit_unit(), - // This case is necessary for formats which does not store - // marker of optionality of value, for example, JSON. When - // `deserialize_any` is requested from such formats, they will - // report value without using `Visitor::visit_some`, because - // they do not known in which contexts this value will be used. - // RON is example of format which preserve markers. + // This case is to support data formats which do not encode an + // indication whether a value is optional. An example of such a + // format is JSON, and a counterexample is RON. When requesting + // `deserialize_any` in JSON, the data format never performs + // `Visitor::visit_some` but we still must be able to + // deserialize the resulting Content into data structures with + // optional fields. _ => visitor.visit_some(self), } } @@ -1945,12 +1946,15 @@ mod content { Content::Newtype(ref v) => { visitor.visit_newtype_struct(ContentRefDeserializer::new(v)) } - // This case is necessary for formats which does not store - // marker of a newtype, for example, JSON. When - // `deserialize_any` is requested from such formats, they will - // report value without using `Visitor::visit_newtype_struct`, - // because they do not known in which contexts this value will - // be used. RON is example of format which preserve markers. + // This case is to support data formats that encode newtype + // structs and their underlying data the same, with no + // indication whether a newtype wrapper was present. For example + // JSON does this, while RON does not. In RON a newtype's name + // is included in the serialized representation and it knows to + // call `Visitor::visit_newtype_struct` from `deserialize_any`. + // JSON's `deserialize_any` never calls `visit_newtype_struct` + // but in this code we still must be able to deserialize the + // resulting Content into newtypes. _ => visitor.visit_newtype_struct(self), } } From 30752ac4ffdaa284606eda34055ad185e28c5499 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 23 Aug 2024 20:29:05 -0700 Subject: [PATCH 184/258] Release 1.0.209 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index e2c3bf976..7f3a9ccc8 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.208" +version = "1.0.209" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.208", path = "../serde_derive" } +serde_derive = { version = "=1.0.209", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 5317d93c7..e9fc96cba 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.208")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.209")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 1ba754b0e..4476a5e68 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.208" +version = "1.0.209" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index 45fa33653..48104ed32 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.208")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.209")] #![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] // Ignored clippy lints #![allow( From 3aca38d2d3c9b5dba9bcb25be2e16bde6678dbf6 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 25 Aug 2024 12:12:25 -0700 Subject: [PATCH 185/258] Upload CI Cargo.lock for reproducing failures --- .github/workflows/ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8c32b678b..81a861a55 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,6 +21,11 @@ jobs: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@nightly - run: cd test_suite && cargo test --features unstable + - uses: actions/upload-artifact@v4 + if: always() + with: + name: Cargo.lock + path: Cargo.lock windows: name: Test suite (windows) From f2899a9e064b225d903307db25719324c3db0510 Mon Sep 17 00:00:00 2001 From: Mathias Date: Thu, 5 Sep 2024 10:38:00 +0200 Subject: [PATCH 186/258] Implement serialize/deserialize for core::net instead of std::net if running rust version newer than 1.77, where core::net was stabilized --- serde/build.rs | 7 +++++ serde/src/de/impls.rs | 34 ++++++++++----------- serde/src/lib.rs | 7 ++++- serde/src/ser/impls.rs | 69 +++++++++++++++++++++++++++++------------- 4 files changed, 78 insertions(+), 39 deletions(-) diff --git a/serde/build.rs b/serde/build.rs index c32872b95..604511587 100644 --- a/serde/build.rs +++ b/serde/build.rs @@ -15,6 +15,7 @@ fn main() { if minor >= 77 { println!("cargo:rustc-check-cfg=cfg(no_core_cstr)"); + println!("cargo:rustc-check-cfg=cfg(no_core_net)"); println!("cargo:rustc-check-cfg=cfg(no_core_num_saturating)"); println!("cargo:rustc-check-cfg=cfg(no_core_try_from)"); println!("cargo:rustc-check-cfg=cfg(no_diagnostic_namespace)"); @@ -86,6 +87,12 @@ fn main() { println!("cargo:rustc-cfg=no_core_num_saturating"); } + // Support for core::net stabilized in Rust 1.77. + // https://blog.rust-lang.org/2024/03/21/Rust-1.77.0.html + if minor < 77 { + println!("cargo:rustc-cfg=no_core_net"); + } + // Support for the `#[diagnostic]` tool attribute namespace // https://blog.rust-lang.org/2024/05/02/Rust-1.78.0.html#diagnostic-attributes if minor < 78 { diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 02591d982..c85aa30d0 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -1604,7 +1604,7 @@ macro_rules! parse_ip_impl { }; } -#[cfg(feature = "std")] +#[cfg(any(feature = "std", not(no_core_net)))] macro_rules! variant_identifier { ( $name_kind:ident ($($variant:ident; $bytes:expr; $index:expr),*) @@ -1679,7 +1679,7 @@ macro_rules! variant_identifier { } } -#[cfg(feature = "std")] +#[cfg(any(feature = "std", not(no_core_net)))] macro_rules! deserialize_enum { ( $name:ident $name_kind:ident ($($variant:ident; $bytes:expr; $index:expr),*) @@ -1716,8 +1716,8 @@ macro_rules! deserialize_enum { } } -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +#[cfg(any(feature = "std", not(no_core_net)))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] impl<'de> Deserialize<'de> for net::IpAddr { fn deserialize(deserializer: D) -> Result where @@ -1737,14 +1737,14 @@ impl<'de> Deserialize<'de> for net::IpAddr { } parse_ip_impl! { - #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] + #[cfg(any(feature = "std", not(no_core_net)))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] net::Ipv4Addr, "IPv4 address", 4 } parse_ip_impl! { - #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] + #[cfg(any(feature = "std", not(no_core_net)))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] net::Ipv6Addr, "IPv6 address", 16 } @@ -1770,8 +1770,8 @@ macro_rules! parse_socket_impl { }; } -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +#[cfg(any(feature = "std", not(no_core_net)))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] impl<'de> Deserialize<'de> for net::SocketAddr { fn deserialize(deserializer: D) -> Result where @@ -1791,15 +1791,15 @@ impl<'de> Deserialize<'de> for net::SocketAddr { } parse_socket_impl! { - #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] + #[cfg(any(feature = "std", not(no_core_net)))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] net::SocketAddrV4, "IPv4 socket address", |(ip, port)| net::SocketAddrV4::new(ip, port), } parse_socket_impl! { - #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] + #[cfg(any(feature = "std", not(no_core_net)))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] net::SocketAddrV6, "IPv6 socket address", |(ip, port)| net::SocketAddrV6::new(ip, port, 0, 0), } @@ -3160,13 +3160,13 @@ atomic_impl! { AtomicU64 "64" } -#[cfg(feature = "std")] +#[cfg(any(feature = "std", not(no_core_net)))] struct FromStrVisitor { expecting: &'static str, ty: PhantomData, } -#[cfg(feature = "std")] +#[cfg(any(feature = "std", not(no_core_net)))] impl FromStrVisitor { fn new(expecting: &'static str) -> Self { FromStrVisitor { @@ -3176,7 +3176,7 @@ impl FromStrVisitor { } } -#[cfg(feature = "std")] +#[cfg(any(feature = "std", not(no_core_net)))] impl<'de, T> Visitor<'de> for FromStrVisitor where T: str::FromStr, diff --git a/serde/src/lib.rs b/serde/src/lib.rs index e9fc96cba..32509ca85 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -238,8 +238,13 @@ mod lib { #[cfg(feature = "std")] pub use std::ffi::CString; + #[cfg(all(not(no_core_net), not(feature = "std")))] + pub use self::core::net; #[cfg(feature = "std")] - pub use std::{error, net}; + pub use std::net; + + #[cfg(feature = "std")] + pub use std::error; #[cfg(feature = "std")] pub use std::collections::{HashMap, HashSet}; diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index 557b6aa12..aae7ec453 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -769,20 +769,47 @@ impl Serialize for SystemTime { //////////////////////////////////////////////////////////////////////////////// +#[cfg(any(feature = "std", not(no_core_net)))] +struct Wrapper<'a> { + pub buf: &'a mut [u8], + pub offset: usize, +} + +#[cfg(any(feature = "std", not(no_core_net)))] +impl<'a> fmt::Write for Wrapper<'a> { + fn write_str(&mut self, s: &str) -> fmt::Result { + if self.offset > self.buf.len() { + return Err(fmt::Error); + } + let remaining_buf = &mut self.buf[self.offset..]; + let raw_s = s.as_bytes(); + let write_num = core::cmp::min(raw_s.len(), remaining_buf.len()); + remaining_buf[..write_num].copy_from_slice(&raw_s[..write_num]); + self.offset += raw_s.len(); + if write_num < raw_s.len() { + Err(fmt::Error) + } else { + Ok(()) + } + } +} + /// Serialize a value that implements `Display` as a string, when that string is /// statically known to never have more than a constant `MAX_LEN` bytes. /// /// Panics if the `Display` impl tries to write more than `MAX_LEN` bytes. -#[cfg(feature = "std")] +#[cfg(any(feature = "std", not(no_core_net)))] macro_rules! serialize_display_bounded_length { ($value:expr, $max:expr, $serializer:expr) => {{ let mut buffer = [0u8; $max]; - let remaining_len = { - let mut remaining = &mut buffer[..]; - write!(remaining, "{}", $value).unwrap(); - remaining.len() + let written_len = { + let mut w = Wrapper { + buf: &mut buffer, + offset: 0, + }; + write!(&mut w, "{}", $value).unwrap(); + w.offset }; - let written_len = buffer.len() - remaining_len; let written = &buffer[..written_len]; // write! only provides fmt::Formatter to Display implementations, which @@ -793,8 +820,8 @@ macro_rules! serialize_display_bounded_length { }}; } -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +#[cfg(any(feature = "std", not(no_core_net)))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] impl Serialize for net::IpAddr { fn serialize(&self, serializer: S) -> Result where @@ -818,7 +845,7 @@ impl Serialize for net::IpAddr { } } -#[cfg(feature = "std")] +#[cfg(any(feature = "std", not(no_core_net)))] const DEC_DIGITS_LUT: &[u8] = b"\ 0001020304050607080910111213141516171819\ 2021222324252627282930313233343536373839\ @@ -826,7 +853,7 @@ const DEC_DIGITS_LUT: &[u8] = b"\ 6061626364656667686970717273747576777879\ 8081828384858687888990919293949596979899"; -#[cfg(feature = "std")] +#[cfg(any(feature = "std", not(no_core_net)))] #[inline] fn format_u8(mut n: u8, out: &mut [u8]) -> usize { if n >= 100 { @@ -847,7 +874,7 @@ fn format_u8(mut n: u8, out: &mut [u8]) -> usize { } } -#[cfg(feature = "std")] +#[cfg(any(feature = "std", not(no_core_net)))] #[test] fn test_format_u8() { let mut i = 0u8; @@ -864,8 +891,8 @@ fn test_format_u8() { } } -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +#[cfg(any(feature = "std", not(no_core_net)))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] impl Serialize for net::Ipv4Addr { fn serialize(&self, serializer: S) -> Result where @@ -889,8 +916,8 @@ impl Serialize for net::Ipv4Addr { } } -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +#[cfg(any(feature = "std", not(no_core_net)))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] impl Serialize for net::Ipv6Addr { fn serialize(&self, serializer: S) -> Result where @@ -906,8 +933,8 @@ impl Serialize for net::Ipv6Addr { } } -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +#[cfg(any(feature = "std", not(no_core_net)))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] impl Serialize for net::SocketAddr { fn serialize(&self, serializer: S) -> Result where @@ -931,8 +958,8 @@ impl Serialize for net::SocketAddr { } } -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +#[cfg(any(feature = "std", not(no_core_net)))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] impl Serialize for net::SocketAddrV4 { fn serialize(&self, serializer: S) -> Result where @@ -948,8 +975,8 @@ impl Serialize for net::SocketAddrV4 { } } -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +#[cfg(any(feature = "std", not(no_core_net)))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] impl Serialize for net::SocketAddrV6 { fn serialize(&self, serializer: S) -> Result where From d940fe1b4934f097b0333dcb87bec5ee308d39cd Mon Sep 17 00:00:00 2001 From: Mathias Date: Thu, 5 Sep 2024 14:24:44 +0200 Subject: [PATCH 187/258] Reuse existing Buf wrapper as replacement for std::io::Write --- serde/src/de/mod.rs | 5 ++--- serde/src/{de => }/format.rs | 0 serde/src/lib.rs | 2 ++ serde/src/ser/impls.rs | 43 +++--------------------------------- 4 files changed, 7 insertions(+), 43 deletions(-) rename serde/src/{de => }/format.rs (100%) diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index d6b9f5ab4..a87558ec5 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -118,7 +118,6 @@ use crate::lib::*; pub mod value; -mod format; mod ignored_any; mod impls; pub(crate) mod size_hint; @@ -1374,7 +1373,7 @@ pub trait Visitor<'de>: Sized { E: Error, { let mut buf = [0u8; 58]; - let mut writer = format::Buf::new(&mut buf); + let mut writer = crate::format::Buf::new(&mut buf); fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as i128", v)).unwrap(); Err(Error::invalid_type( Unexpected::Other(writer.as_str()), @@ -1436,7 +1435,7 @@ pub trait Visitor<'de>: Sized { E: Error, { let mut buf = [0u8; 57]; - let mut writer = format::Buf::new(&mut buf); + let mut writer = crate::format::Buf::new(&mut buf); fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as u128", v)).unwrap(); Err(Error::invalid_type( Unexpected::Other(writer.as_str()), diff --git a/serde/src/de/format.rs b/serde/src/format.rs similarity index 100% rename from serde/src/de/format.rs rename to serde/src/format.rs diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 32509ca85..f40f6a60e 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -310,6 +310,8 @@ mod integer128; pub mod de; pub mod ser; +mod format; + #[doc(inline)] pub use crate::de::{Deserialize, Deserializer}; #[doc(inline)] diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index aae7ec453..235c9cdeb 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -769,31 +769,6 @@ impl Serialize for SystemTime { //////////////////////////////////////////////////////////////////////////////// -#[cfg(any(feature = "std", not(no_core_net)))] -struct Wrapper<'a> { - pub buf: &'a mut [u8], - pub offset: usize, -} - -#[cfg(any(feature = "std", not(no_core_net)))] -impl<'a> fmt::Write for Wrapper<'a> { - fn write_str(&mut self, s: &str) -> fmt::Result { - if self.offset > self.buf.len() { - return Err(fmt::Error); - } - let remaining_buf = &mut self.buf[self.offset..]; - let raw_s = s.as_bytes(); - let write_num = core::cmp::min(raw_s.len(), remaining_buf.len()); - remaining_buf[..write_num].copy_from_slice(&raw_s[..write_num]); - self.offset += raw_s.len(); - if write_num < raw_s.len() { - Err(fmt::Error) - } else { - Ok(()) - } - } -} - /// Serialize a value that implements `Display` as a string, when that string is /// statically known to never have more than a constant `MAX_LEN` bytes. /// @@ -802,21 +777,9 @@ impl<'a> fmt::Write for Wrapper<'a> { macro_rules! serialize_display_bounded_length { ($value:expr, $max:expr, $serializer:expr) => {{ let mut buffer = [0u8; $max]; - let written_len = { - let mut w = Wrapper { - buf: &mut buffer, - offset: 0, - }; - write!(&mut w, "{}", $value).unwrap(); - w.offset - }; - let written = &buffer[..written_len]; - - // write! only provides fmt::Formatter to Display implementations, which - // has methods write_str and write_char but no method to write arbitrary - // bytes. Therefore `written` must be valid UTF-8. - let written_str = str::from_utf8(written).expect("must be valid UTF-8"); - $serializer.serialize_str(written_str) + let mut writer = crate::format::Buf::new(&mut buffer); + write!(&mut writer, "{}", $value).unwrap(); + $serializer.serialize_str(writer.as_str()) }}; } From b1f899fbe81f070803d9f7ca6e5d1cc3f19c9ea2 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 6 Sep 2024 11:00:55 -0700 Subject: [PATCH 188/258] Delete doc(cfg) attribute from impls that are supported in no-std --- serde/src/de/impls.rs | 6 ------ serde/src/ser/impls.rs | 6 ------ 2 files changed, 12 deletions(-) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index c85aa30d0..303d0516d 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -1717,7 +1717,6 @@ macro_rules! deserialize_enum { } #[cfg(any(feature = "std", not(no_core_net)))] -#[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] impl<'de> Deserialize<'de> for net::IpAddr { fn deserialize(deserializer: D) -> Result where @@ -1738,13 +1737,11 @@ impl<'de> Deserialize<'de> for net::IpAddr { parse_ip_impl! { #[cfg(any(feature = "std", not(no_core_net)))] - #[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] net::Ipv4Addr, "IPv4 address", 4 } parse_ip_impl! { #[cfg(any(feature = "std", not(no_core_net)))] - #[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] net::Ipv6Addr, "IPv6 address", 16 } @@ -1771,7 +1768,6 @@ macro_rules! parse_socket_impl { } #[cfg(any(feature = "std", not(no_core_net)))] -#[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] impl<'de> Deserialize<'de> for net::SocketAddr { fn deserialize(deserializer: D) -> Result where @@ -1792,14 +1788,12 @@ impl<'de> Deserialize<'de> for net::SocketAddr { parse_socket_impl! { #[cfg(any(feature = "std", not(no_core_net)))] - #[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] net::SocketAddrV4, "IPv4 socket address", |(ip, port)| net::SocketAddrV4::new(ip, port), } parse_socket_impl! { #[cfg(any(feature = "std", not(no_core_net)))] - #[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] net::SocketAddrV6, "IPv6 socket address", |(ip, port)| net::SocketAddrV6::new(ip, port, 0, 0), } diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index 235c9cdeb..fb574eae1 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -784,7 +784,6 @@ macro_rules! serialize_display_bounded_length { } #[cfg(any(feature = "std", not(no_core_net)))] -#[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] impl Serialize for net::IpAddr { fn serialize(&self, serializer: S) -> Result where @@ -855,7 +854,6 @@ fn test_format_u8() { } #[cfg(any(feature = "std", not(no_core_net)))] -#[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] impl Serialize for net::Ipv4Addr { fn serialize(&self, serializer: S) -> Result where @@ -880,7 +878,6 @@ impl Serialize for net::Ipv4Addr { } #[cfg(any(feature = "std", not(no_core_net)))] -#[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] impl Serialize for net::Ipv6Addr { fn serialize(&self, serializer: S) -> Result where @@ -897,7 +894,6 @@ impl Serialize for net::Ipv6Addr { } #[cfg(any(feature = "std", not(no_core_net)))] -#[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] impl Serialize for net::SocketAddr { fn serialize(&self, serializer: S) -> Result where @@ -922,7 +918,6 @@ impl Serialize for net::SocketAddr { } #[cfg(any(feature = "std", not(no_core_net)))] -#[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] impl Serialize for net::SocketAddrV4 { fn serialize(&self, serializer: S) -> Result where @@ -939,7 +934,6 @@ impl Serialize for net::SocketAddrV4 { } #[cfg(any(feature = "std", not(no_core_net)))] -#[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] impl Serialize for net::SocketAddrV6 { fn serialize(&self, serializer: S) -> Result where From 26fb1341651c4e0ae4d58c675db3ca2a0d6e12c2 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 6 Sep 2024 11:03:41 -0700 Subject: [PATCH 189/258] Relocate cfg attrs out of parse_ip_impl and parse_socket_impl --- serde/src/de/impls.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 303d0516d..2db681cdb 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -1583,6 +1583,7 @@ map_impl! { //////////////////////////////////////////////////////////////////////////////// +#[cfg(any(feature = "std", not(no_core_net)))] macro_rules! parse_ip_impl { ( $(#[$attr:meta])* @@ -1735,16 +1736,17 @@ impl<'de> Deserialize<'de> for net::IpAddr { } } +#[cfg(any(feature = "std", not(no_core_net)))] parse_ip_impl! { - #[cfg(any(feature = "std", not(no_core_net)))] net::Ipv4Addr, "IPv4 address", 4 } +#[cfg(any(feature = "std", not(no_core_net)))] parse_ip_impl! { - #[cfg(any(feature = "std", not(no_core_net)))] net::Ipv6Addr, "IPv6 address", 16 } +#[cfg(any(feature = "std", not(no_core_net)))] macro_rules! parse_socket_impl { ( $(#[$attr:meta])* @@ -1786,14 +1788,14 @@ impl<'de> Deserialize<'de> for net::SocketAddr { } } +#[cfg(any(feature = "std", not(no_core_net)))] parse_socket_impl! { - #[cfg(any(feature = "std", not(no_core_net)))] net::SocketAddrV4, "IPv4 socket address", |(ip, port)| net::SocketAddrV4::new(ip, port), } +#[cfg(any(feature = "std", not(no_core_net)))] parse_socket_impl! { - #[cfg(any(feature = "std", not(no_core_net)))] net::SocketAddrV6, "IPv6 socket address", |(ip, port)| net::SocketAddrV6::new(ip, port, 0, 0), } From 4c0dd63011434905265e2710bb9186e09e4f8ec2 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 6 Sep 2024 11:05:00 -0700 Subject: [PATCH 190/258] Delete attr support from core::net deserialization macros --- serde/src/de/impls.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 2db681cdb..f9cdca7d7 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -1586,10 +1586,8 @@ map_impl! { #[cfg(any(feature = "std", not(no_core_net)))] macro_rules! parse_ip_impl { ( - $(#[$attr:meta])* $ty:ty, $expecting:expr, $size:tt ) => { - $(#[$attr])* impl<'de> Deserialize<'de> for $ty { fn deserialize(deserializer: D) -> Result where @@ -1749,11 +1747,9 @@ parse_ip_impl! { #[cfg(any(feature = "std", not(no_core_net)))] macro_rules! parse_socket_impl { ( - $(#[$attr:meta])* $ty:ty, $expecting:tt, $new:expr, ) => { - $(#[$attr])* impl<'de> Deserialize<'de> for $ty { fn deserialize(deserializer: D) -> Result where From d549f048e10bcb5e677afaf7b99d0ed3604b113b Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 6 Sep 2024 11:05:41 -0700 Subject: [PATCH 191/258] Reformat parse_ip_impl definition and calls --- serde/src/de/impls.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index f9cdca7d7..2d8c99030 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -1585,9 +1585,7 @@ map_impl! { #[cfg(any(feature = "std", not(no_core_net)))] macro_rules! parse_ip_impl { - ( - $ty:ty, $expecting:expr, $size:tt - ) => { + ($ty:ty, $expecting:expr, $size:tt) => { impl<'de> Deserialize<'de> for $ty { fn deserialize(deserializer: D) -> Result where @@ -1735,14 +1733,10 @@ impl<'de> Deserialize<'de> for net::IpAddr { } #[cfg(any(feature = "std", not(no_core_net)))] -parse_ip_impl! { - net::Ipv4Addr, "IPv4 address", 4 -} +parse_ip_impl!(net::Ipv4Addr, "IPv4 address", 4); #[cfg(any(feature = "std", not(no_core_net)))] -parse_ip_impl! { - net::Ipv6Addr, "IPv6 address", 16 -} +parse_ip_impl!(net::Ipv6Addr, "IPv6 address", 16); #[cfg(any(feature = "std", not(no_core_net)))] macro_rules! parse_socket_impl { From 785c2d9605ee73cc172dfd421228c1dccca984c9 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 6 Sep 2024 11:09:11 -0700 Subject: [PATCH 192/258] Stabilize no-std StdError trait --- serde/build.rs | 7 +++++++ serde/src/de/mod.rs | 4 ++-- serde/src/lib.rs | 2 +- serde/src/ser/mod.rs | 4 ++-- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/serde/build.rs b/serde/build.rs index 604511587..8a4f7257c 100644 --- a/serde/build.rs +++ b/serde/build.rs @@ -15,6 +15,7 @@ fn main() { if minor >= 77 { println!("cargo:rustc-check-cfg=cfg(no_core_cstr)"); + println!("cargo:rustc-check-cfg=cfg(no_core_error)"); println!("cargo:rustc-check-cfg=cfg(no_core_net)"); println!("cargo:rustc-check-cfg=cfg(no_core_num_saturating)"); println!("cargo:rustc-check-cfg=cfg(no_core_try_from)"); @@ -98,6 +99,12 @@ fn main() { if minor < 78 { println!("cargo:rustc-cfg=no_diagnostic_namespace"); } + + // The Error trait became available in core in 1.81. + // https://blog.rust-lang.org/2024/09/05/Rust-1.81.0.html#coreerrorerror + if minor < 81 { + println!("cargo:rustc-cfg=no_core_error"); + } } fn rustc_minor_version() -> Option { diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index a87558ec5..21cfd0414 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -124,10 +124,10 @@ pub(crate) mod size_hint; pub use self::ignored_any::IgnoredAny; -#[cfg(not(any(feature = "std", feature = "unstable")))] +#[cfg(all(not(feature = "std"), no_core_error))] #[doc(no_inline)] pub use crate::std_error::Error as StdError; -#[cfg(all(feature = "unstable", not(feature = "std")))] +#[cfg(not(any(feature = "std", no_core_error)))] #[doc(no_inline)] pub use core::error::Error as StdError; #[cfg(feature = "std")] diff --git a/serde/src/lib.rs b/serde/src/lib.rs index f40f6a60e..72f6f8bcc 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -325,7 +325,7 @@ pub mod __private; #[path = "de/seed.rs"] mod seed; -#[cfg(not(any(feature = "std", feature = "unstable")))] +#[cfg(all(not(feature = "std"), no_core_error))] mod std_error; // Re-export #[derive(Serialize, Deserialize)]. diff --git a/serde/src/ser/mod.rs b/serde/src/ser/mod.rs index 30a648093..fb0033ec0 100644 --- a/serde/src/ser/mod.rs +++ b/serde/src/ser/mod.rs @@ -115,10 +115,10 @@ mod impossible; pub use self::impossible::Impossible; -#[cfg(not(any(feature = "std", feature = "unstable")))] +#[cfg(all(not(feature = "std"), no_core_error))] #[doc(no_inline)] pub use crate::std_error::Error as StdError; -#[cfg(all(feature = "unstable", not(feature = "std")))] +#[cfg(not(any(feature = "std", no_core_error)))] #[doc(no_inline)] pub use core::error::Error as StdError; #[cfg(feature = "std")] From 89c4b02bf32ceae5b17d89f93a452ccc195ca038 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 6 Sep 2024 11:17:20 -0700 Subject: [PATCH 193/258] Release 1.0.210 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 7f3a9ccc8..b6ad57682 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.209" +version = "1.0.210" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.209", path = "../serde_derive" } +serde_derive = { version = "=1.0.210", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 72f6f8bcc..15710d8d9 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.209")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.210")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 4476a5e68..d6e5c24e6 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.209" +version = "1.0.210" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index 48104ed32..bedd1cb3d 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.209")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.210")] #![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] // Ignored clippy lints #![allow( From 1d7b009aec79e99a59441e6dc20dd186c3e89d1b Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 6 Sep 2024 16:26:14 -0700 Subject: [PATCH 194/258] Eliminate closures capturing needlessly many type parameters --- serde/src/private/de.rs | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index f0eca71ff..34a2d50c4 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -476,14 +476,16 @@ mod content { where D: Deserializer<'de>, { - Deserialize::deserialize(deserializer).map(|v| Content::Some(Box::new(v))) + let v = tri!(Deserialize::deserialize(deserializer)); + Ok(Content::Some(Box::new(v))) } fn visit_newtype_struct(self, deserializer: D) -> Result where D: Deserializer<'de>, { - Deserialize::deserialize(deserializer).map(|v| Content::Newtype(Box::new(v))) + let v = tri!(Deserialize::deserialize(deserializer)); + Ok(Content::Newtype(Box::new(v))) } fn visit_seq(self, mut visitor: V) -> Result @@ -1113,9 +1115,13 @@ mod content { V: Visitor<'de>, E: de::Error, { - let map = content - .into_iter() - .map(|(k, v)| (ContentDeserializer::new(k), ContentDeserializer::new(v))); + fn content_deserializer_pair<'de, E>( + (k, v): (Content<'de>, Content<'de>), + ) -> (ContentDeserializer<'de, E>, ContentDeserializer<'de, E>) { + (ContentDeserializer::new(k), ContentDeserializer::new(v)) + } + + let map = content.into_iter().map(content_deserializer_pair); let mut map_visitor = MapDeserializer::new(map); let value = tri!(visitor.visit_map(&mut map_visitor)); tri!(map_visitor.end()); @@ -1709,12 +1715,19 @@ mod content { V: Visitor<'de>, E: de::Error, { - let map = content.iter().map(|(k, v)| { + fn content_ref_deserializer_pair<'a, 'de, E>( + (k, v): &'a (Content<'de>, Content<'de>), + ) -> ( + ContentRefDeserializer<'a, 'de, E>, + ContentRefDeserializer<'a, 'de, E>, + ) { ( ContentRefDeserializer::new(k), ContentRefDeserializer::new(v), ) - }); + } + + let map = content.iter().map(content_ref_deserializer_pair); let mut map_visitor = MapDeserializer::new(map); let value = tri!(visitor.visit_map(&mut map_visitor)); tri!(map_visitor.end()); From aba4e1855395dea04f1b44705109e320c38c5942 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 7 Sep 2024 16:22:11 -0700 Subject: [PATCH 195/258] Remove explicit ContentDeserializer construction in visit functions --- serde/src/private/de.rs | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index 34a2d50c4..50ae6ed15 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -313,6 +313,17 @@ mod content { } } + impl<'a, 'de, E> de::IntoDeserializer<'de, E> for &'a Content<'de> + where + E: de::Error, + { + type Deserializer = ContentRefDeserializer<'a, 'de, E>; + + fn into_deserializer(self) -> Self::Deserializer { + ContentRefDeserializer::new(self) + } + } + /// Used to capture data in [`Content`] from other deserializers. /// Cannot capture externally tagged enums, `i128` and `u128`. struct ContentVisitor<'de> { @@ -1100,8 +1111,7 @@ mod content { V: Visitor<'de>, E: de::Error, { - let seq = content.into_iter().map(ContentDeserializer::new); - let mut seq_visitor = SeqDeserializer::new(seq); + let mut seq_visitor = SeqDeserializer::new(content.into_iter()); let value = tri!(visitor.visit_seq(&mut seq_visitor)); tri!(seq_visitor.end()); Ok(value) @@ -1115,14 +1125,7 @@ mod content { V: Visitor<'de>, E: de::Error, { - fn content_deserializer_pair<'de, E>( - (k, v): (Content<'de>, Content<'de>), - ) -> (ContentDeserializer<'de, E>, ContentDeserializer<'de, E>) { - (ContentDeserializer::new(k), ContentDeserializer::new(v)) - } - - let map = content.into_iter().map(content_deserializer_pair); - let mut map_visitor = MapDeserializer::new(map); + let mut map_visitor = MapDeserializer::new(content.into_iter()); let value = tri!(visitor.visit_map(&mut map_visitor)); tri!(map_visitor.end()); Ok(value) @@ -1700,8 +1703,7 @@ mod content { V: Visitor<'de>, E: de::Error, { - let seq = content.iter().map(ContentRefDeserializer::new); - let mut seq_visitor = SeqDeserializer::new(seq); + let mut seq_visitor = SeqDeserializer::new(content.iter()); let value = tri!(visitor.visit_seq(&mut seq_visitor)); tri!(seq_visitor.end()); Ok(value) @@ -1715,16 +1717,10 @@ mod content { V: Visitor<'de>, E: de::Error, { - fn content_ref_deserializer_pair<'a, 'de, E>( + fn content_ref_deserializer_pair<'a, 'de>( (k, v): &'a (Content<'de>, Content<'de>), - ) -> ( - ContentRefDeserializer<'a, 'de, E>, - ContentRefDeserializer<'a, 'de, E>, - ) { - ( - ContentRefDeserializer::new(k), - ContentRefDeserializer::new(v), - ) + ) -> (&'a Content<'de>, &'a Content<'de>) { + (k, v) } let map = content.iter().map(content_ref_deserializer_pair); From 31000e1874ff01362f91e7b53794e402fab4fc78 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 23 Sep 2024 15:38:03 -0700 Subject: [PATCH 196/258] Add a funding file --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..750707701 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: dtolnay From 8e1ae68569db46251a88997e5e212392d4ad83ea Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 7 Oct 2024 20:54:22 +0200 Subject: [PATCH 197/258] Resolve some needless_lifetimes clippy lints warning: the following explicit lifetimes could be elided: 'a --> serde/src/de/mod.rs:489:6 | 489 | impl<'a> Expected for &'a str { | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 489 - impl<'a> Expected for &'a str { 489 + impl Expected for &str { | warning: the following explicit lifetimes could be elided: 'a --> serde/src/de/mod.rs:495:6 | 495 | impl<'a> Display for Expected + 'a { | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 495 - impl<'a> Display for Expected + 'a { 495 + impl Display for Expected + '_ { | warning: the following explicit lifetimes could be elided: 'a --> serde/src/de/mod.rs:1744:11 | 1744 | impl<'de, 'a, A> SeqAccess<'de> for &'a mut A | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 1744 - impl<'de, 'a, A> SeqAccess<'de> for &'a mut A 1744 + impl<'de, A> SeqAccess<'de> for &mut A | warning: the following explicit lifetimes could be elided: 'a --> serde/src/de/mod.rs:1897:11 | 1897 | impl<'de, 'a, A> MapAccess<'de> for &'a mut A | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 1897 - impl<'de, 'a, A> MapAccess<'de> for &'a mut A 1897 + impl<'de, A> MapAccess<'de> for &mut A | warning: the following explicit lifetimes could be elided: 'a, 'b --> serde/src/ser/fmt.rs:38:6 | 38 | impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> { | ^^ ^^ ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 38 - impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> { 38 + impl Serializer for &mut fmt::Formatter<'_> { | warning: the following explicit lifetimes could be elided: 'a --> serde_derive/src/internals/symbol.rs:49:6 | 49 | impl<'a> PartialEq for &'a Ident { | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 49 - impl<'a> PartialEq for &'a Ident { 49 + impl PartialEq for &Ident { | warning: the following explicit lifetimes could be elided: 'a --> serde_derive/src/internals/symbol.rs:61:6 | 61 | impl<'a> PartialEq for &'a Path { | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 61 - impl<'a> PartialEq for &'a Path { 61 + impl PartialEq for &Path { | --- serde/src/de/mod.rs | 8 ++++---- serde/src/ser/fmt.rs | 2 +- serde_derive/src/internals/symbol.rs | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index 21cfd0414..b86ebe5ed 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -486,13 +486,13 @@ where } } -impl<'a> Expected for &'a str { +impl Expected for &str { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(self) } } -impl<'a> Display for Expected + 'a { +impl Display for Expected + '_ { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { Expected::fmt(self, formatter) } @@ -1741,7 +1741,7 @@ pub trait SeqAccess<'de> { } } -impl<'de, 'a, A> SeqAccess<'de> for &'a mut A +impl<'de, A> SeqAccess<'de> for &mut A where A: ?Sized + SeqAccess<'de>, { @@ -1894,7 +1894,7 @@ pub trait MapAccess<'de> { } } -impl<'de, 'a, A> MapAccess<'de> for &'a mut A +impl<'de, A> MapAccess<'de> for &mut A where A: ?Sized + MapAccess<'de>, { diff --git a/serde/src/ser/fmt.rs b/serde/src/ser/fmt.rs index 04684aded..4b1549f08 100644 --- a/serde/src/ser/fmt.rs +++ b/serde/src/ser/fmt.rs @@ -35,7 +35,7 @@ macro_rules! fmt_primitives { /// } /// } /// ``` -impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> { +impl<'a> Serializer for &mut fmt::Formatter<'a> { type Ok = (); type Error = fmt::Error; type SerializeSeq = Impossible<(), fmt::Error>; diff --git a/serde_derive/src/internals/symbol.rs b/serde_derive/src/internals/symbol.rs index 572391a80..59ef8de7c 100644 --- a/serde_derive/src/internals/symbol.rs +++ b/serde_derive/src/internals/symbol.rs @@ -46,7 +46,7 @@ impl PartialEq for Ident { } } -impl<'a> PartialEq for &'a Ident { +impl PartialEq for &Ident { fn eq(&self, word: &Symbol) -> bool { *self == word.0 } @@ -58,7 +58,7 @@ impl PartialEq for Path { } } -impl<'a> PartialEq for &'a Path { +impl PartialEq for &Path { fn eq(&self, word: &Symbol) -> bool { self.is_ident(word.0) } From 4b3178b053683b8e13f9f551e2a40fbe4a927e43 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 7 Oct 2024 20:55:52 +0200 Subject: [PATCH 198/258] Ignore needless_lifetimes clippy lint warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/value.rs:124:6 | 124 | impl<'de, E> IntoDeserializer<'de, E> for () | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes = note: `-W clippy::needless-lifetimes` implied by `-W clippy::all` = help: to override `-W clippy::all` add `#[allow(clippy::needless_lifetimes)]` help: elide the lifetimes | 124 - impl<'de, E> IntoDeserializer<'de, E> for () 124 + impl IntoDeserializer<'_, E> for () | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/value.rs:196:6 | 196 | impl<'de, E> IntoDeserializer<'de, E> for ! | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 196 - impl<'de, E> IntoDeserializer<'de, E> for ! 196 + impl IntoDeserializer<'_, E> for ! | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/value.rs:317:6 | 317 | impl<'de, E> IntoDeserializer<'de, E> for u32 | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 317 - impl<'de, E> IntoDeserializer<'de, E> for u32 317 + impl IntoDeserializer<'_, E> for u32 | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/value.rs:406:6 | 406 | impl<'de, 'a, E> IntoDeserializer<'de, E> for &'a str | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 406 - impl<'de, 'a, E> IntoDeserializer<'de, E> for &'a str 406 + impl<'a, E> IntoDeserializer<'_, E> for &'a str | warning: the following explicit lifetimes could be elided: 'a --> serde/src/de/value.rs:427:11 | 427 | impl<'de, 'a, E> de::Deserializer<'de> for StrDeserializer<'a, E> | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 427 - impl<'de, 'a, E> de::Deserializer<'de> for StrDeserializer<'a, E> 427 + impl<'de, E> de::Deserializer<'de> for StrDeserializer<'_, E> | warning: the following explicit lifetimes could be elided: 'a --> serde/src/de/value.rs:461:11 | 461 | impl<'de, 'a, E> de::EnumAccess<'de> for StrDeserializer<'a, E> | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 461 - impl<'de, 'a, E> de::EnumAccess<'de> for StrDeserializer<'a, E> 461 + impl<'de, E> de::EnumAccess<'de> for StrDeserializer<'_, E> | warning: the following explicit lifetimes could be elided: 'a --> serde/src/de/value.rs:476:6 | 476 | impl<'a, E> Debug for StrDeserializer<'a, E> { | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 476 - impl<'a, E> Debug for StrDeserializer<'a, E> { 476 + impl Debug for StrDeserializer<'_, E> { | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/value.rs:555:6 | 555 | impl<'de, E> Debug for BorrowedStrDeserializer<'de, E> { | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 555 - impl<'de, E> Debug for BorrowedStrDeserializer<'de, E> { 555 + impl Debug for BorrowedStrDeserializer<'_, E> { | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/value.rs:586:6 | 586 | impl<'de, E> IntoDeserializer<'de, E> for String | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 586 - impl<'de, E> IntoDeserializer<'de, E> for String 586 + impl IntoDeserializer<'_, E> for String | warning: the following explicit lifetimes could be elided: 'a --> serde/src/de/value.rs:680:6 | 680 | impl<'a, E> Clone for CowStrDeserializer<'a, E> { | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 680 - impl<'a, E> Clone for CowStrDeserializer<'a, E> { 680 + impl Clone for CowStrDeserializer<'_, E> { | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/value.rs:691:6 | 691 | impl<'de, 'a, E> IntoDeserializer<'de, E> for Cow<'a, str> | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 691 - impl<'de, 'a, E> IntoDeserializer<'de, E> for Cow<'a, str> 691 + impl<'a, E> IntoDeserializer<'_, E> for Cow<'a, str> | warning: the following explicit lifetimes could be elided: 'a --> serde/src/de/value.rs:714:11 | 714 | impl<'de, 'a, E> de::Deserializer<'de> for CowStrDeserializer<'a, E> | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 714 - impl<'de, 'a, E> de::Deserializer<'de> for CowStrDeserializer<'a, E> 714 + impl<'de, E> de::Deserializer<'de> for CowStrDeserializer<'_, E> | warning: the following explicit lifetimes could be elided: 'a --> serde/src/de/value.rs:752:11 | 752 | impl<'de, 'a, E> de::EnumAccess<'de> for CowStrDeserializer<'a, E> | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 752 - impl<'de, 'a, E> de::EnumAccess<'de> for CowStrDeserializer<'a, E> 752 + impl<'de, E> de::EnumAccess<'de> for CowStrDeserializer<'_, E> | warning: the following explicit lifetimes could be elided: 'a --> serde/src/de/value.rs:768:6 | 768 | impl<'a, E> Debug for CowStrDeserializer<'a, E> { | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 768 - impl<'a, E> Debug for CowStrDeserializer<'a, E> { 768 + impl Debug for CowStrDeserializer<'_, E> { | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/value.rs:797:6 | 797 | impl<'de, 'a, E> IntoDeserializer<'de, E> for &'a [u8] | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 797 - impl<'de, 'a, E> IntoDeserializer<'de, E> for &'a [u8] 797 + impl<'a, E> IntoDeserializer<'_, E> for &'a [u8] | warning: the following explicit lifetimes could be elided: 'a --> serde/src/de/value.rs:808:11 | 808 | impl<'de, 'a, E> Deserializer<'de> for BytesDeserializer<'a, E> | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 808 - impl<'de, 'a, E> Deserializer<'de> for BytesDeserializer<'a, E> 808 + impl<'de, E> Deserializer<'de> for BytesDeserializer<'_, E> | warning: the following explicit lifetimes could be elided: 'a --> serde/src/de/value.rs:828:6 | 828 | impl<'a, E> Debug for BytesDeserializer<'a, E> { | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 828 - impl<'a, E> Debug for BytesDeserializer<'a, E> { 828 + impl Debug for BytesDeserializer<'_, E> { | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/value.rs:876:6 | 876 | impl<'de, E> Debug for BorrowedBytesDeserializer<'de, E> { | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 876 - impl<'de, E> Debug for BorrowedBytesDeserializer<'de, E> { 876 + impl Debug for BorrowedBytesDeserializer<'_, E> { | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/value.rs:1101:6 | 1101 | impl<'de, I, E> MapDeserializer<'de, I, E> | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 1101 - impl<'de, I, E> MapDeserializer<'de, I, E> 1101 + impl MapDeserializer<'_, I, E> | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/value.rs:1118:6 | 1118 | impl<'de, I, E> MapDeserializer<'de, I, E> | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 1118 - impl<'de, I, E> MapDeserializer<'de, I, E> 1118 + impl MapDeserializer<'_, I, E> | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/value.rs:1141:6 | 1141 | impl<'de, I, E> MapDeserializer<'de, I, E> | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 1141 - impl<'de, I, E> MapDeserializer<'de, I, E> 1141 + impl MapDeserializer<'_, I, E> | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/value.rs:1287:6 | 1287 | impl<'de, I, E> Clone for MapDeserializer<'de, I, E> | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 1287 - impl<'de, I, E> Clone for MapDeserializer<'de, I, E> 1287 + impl Clone for MapDeserializer<'_, I, E> | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/value.rs:1304:6 | 1304 | impl<'de, I, E> Debug for MapDeserializer<'de, I, E> | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 1304 - impl<'de, I, E> Debug for MapDeserializer<'de, I, E> 1304 + impl Debug for MapDeserializer<'_, I, E> | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/impls.rs:17:6 | 17 | impl<'de> Visitor<'de> for UnitVisitor { | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 17 - impl<'de> Visitor<'de> for UnitVisitor { 17 + impl Visitor<'_> for UnitVisitor { | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/impls.rs:56:6 | 56 | impl<'de> Visitor<'de> for BoolVisitor { | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 56 - impl<'de> Visitor<'de> for BoolVisitor { 56 + impl Visitor<'_> for BoolVisitor { | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/impls.rs:550:6 | 550 | impl<'de> Visitor<'de> for CharVisitor { | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 550 - impl<'de> Visitor<'de> for CharVisitor { 550 + impl Visitor<'_> for CharVisitor { | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/impls.rs:596:6 | 596 | impl<'de> Visitor<'de> for StringVisitor { | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 596 - impl<'de> Visitor<'de> for StringVisitor { 596 + impl Visitor<'_> for StringVisitor { | warning: the following explicit lifetimes could be elided: 'de, 'a --> serde/src/de/impls.rs:642:6 | 642 | impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> { | ^^ ^^^ ^^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 642 - impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> { 642 + impl Visitor<'_> for StringInPlaceVisitor<'_> { | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/impls.rs:953:6 | 953 | impl<'de, T> Visitor<'de> for PhantomDataVisitor | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 953 - impl<'de, T> Visitor<'de> for PhantomDataVisitor 953 + impl Visitor<'_> for PhantomDataVisitor | warning: the following explicit lifetimes could be elided: 'a --> serde/src/de/impls.rs:1195:14 | 1195 | impl<'a, 'de, T> Visitor<'de> for VecInPlaceVisitor<'a, T> | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 1195 - impl<'a, 'de, T> Visitor<'de> for VecInPlaceVisitor<'a, T> 1195 + impl<'de, T> Visitor<'de> for VecInPlaceVisitor<'_, T> | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/impls.rs:1838:6 | 1838 | impl<'de> Visitor<'de> for PathBufVisitor { | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 1838 - impl<'de> Visitor<'de> for PathBufVisitor { 1838 + impl Visitor<'_> for PathBufVisitor { | warning: the following explicit lifetimes could be elided: 'a --> serde/src/de/impls.rs:1991:11 | 1991 | impl<'de, 'a, T> Deserialize<'de> for Cow<'a, T> | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 1991 - impl<'de, 'a, T> Deserialize<'de> for Cow<'a, T> 1991 + impl<'de, T> Deserialize<'de> for Cow<'_, T> | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/impls.rs:2161:22 | 2161 | impl<'de> Visitor<'de> for FieldVisitor { | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 2161 - impl<'de> Visitor<'de> for FieldVisitor { 2161 + impl Visitor<'_> for FieldVisitor { | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/impls.rs:2300:22 | 2300 | impl<'de> Visitor<'de> for FieldVisitor { | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 2300 - impl<'de> Visitor<'de> for FieldVisitor { 2300 + impl Visitor<'_> for FieldVisitor { | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/impls.rs:2501:18 | 2501 | impl<'de> Visitor<'de> for FieldVisitor { | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 2501 - impl<'de> Visitor<'de> for FieldVisitor { 2501 + impl Visitor<'_> for FieldVisitor { | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/impls.rs:2658:18 | 2658 | impl<'de> Visitor<'de> for FieldVisitor { | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 2658 - impl<'de> Visitor<'de> for FieldVisitor { 2658 + impl Visitor<'_> for FieldVisitor { | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/impls.rs:2796:18 | 2796 | impl<'de> Visitor<'de> for FieldVisitor { | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 2796 - impl<'de> Visitor<'de> for FieldVisitor { 2796 + impl Visitor<'_> for FieldVisitor { | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/impls.rs:2907:22 | 2907 | impl<'de> Visitor<'de> for FieldVisitor { | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 2907 - impl<'de> Visitor<'de> for FieldVisitor { 2907 + impl Visitor<'_> for FieldVisitor { | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/impls.rs:3018:22 | 3018 | impl<'de> Visitor<'de> for FieldVisitor { | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 3018 - impl<'de> Visitor<'de> for FieldVisitor { 3018 + impl Visitor<'_> for FieldVisitor { | warning: the following explicit lifetimes could be elided: 'de --> serde/src/de/impls.rs:3166:6 | 3166 | impl<'de, T> Visitor<'de> for FromStrVisitor | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 3166 - impl<'de, T> Visitor<'de> for FromStrVisitor 3166 + impl Visitor<'_> for FromStrVisitor | warning: the following explicit lifetimes could be elided: 'a --> serde/src/de/mod.rs:397:6 | 397 | impl<'a> fmt::Display for Unexpected<'a> { | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 397 - impl<'a> fmt::Display for Unexpected<'a> { 397 + impl fmt::Display for Unexpected<'_> { | warning: the following explicit lifetimes could be elided: 'f, 'a --> serde/src/de/mod.rs:2309:14 | 2309 | impl<'f, 'a> fmt::Write for LookForDecimalPoint<'f, 'a> { | ^^ ^^ ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 2309 - impl<'f, 'a> fmt::Write for LookForDecimalPoint<'f, 'a> { 2309 + impl fmt::Write for LookForDecimalPoint<'_, '_> { | warning: the following explicit lifetimes could be elided: 'a --> serde/src/ser/fmt.rs:38:6 | 38 | impl<'a> Serializer for &mut fmt::Formatter<'a> { | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 38 - impl<'a> Serializer for &mut fmt::Formatter<'a> { 38 + impl Serializer for &mut fmt::Formatter<'_> { | warning: the following explicit lifetimes could be elided: 'a --> serde/src/ser/impls.rs:62:6 | 62 | impl<'a> Serialize for fmt::Arguments<'a> { | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 62 - impl<'a> Serialize for fmt::Arguments<'a> { 62 + impl Serialize for fmt::Arguments<'_> { | warning: the following explicit lifetimes could be elided: 'a --> serde/src/format.rs:20:6 | 20 | impl<'a> Write for Buf<'a> { | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 20 - impl<'a> Write for Buf<'a> { 20 + impl Write for Buf<'_> { | warning: the following explicit lifetimes could be elided: 'de --> serde/src/private/de.rs:254:10 | 254 | impl<'de> Content<'de> { | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 254 - impl<'de> Content<'de> { 254 + impl Content<'_> { | warning: the following explicit lifetimes could be elided: 'de --> serde/src/private/de.rs:333:10 | 333 | impl<'de> ContentVisitor<'de> { | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 333 - impl<'de> ContentVisitor<'de> { 333 + impl ContentVisitor<'_> { | warning: the following explicit lifetimes could be elided: 'de --> serde/src/private/de.rs:553:10 | 553 | impl<'de> TagOrContentVisitor<'de> { | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 553 - impl<'de> TagOrContentVisitor<'de> { 553 + impl TagOrContentVisitor<'_> { | warning: the following explicit lifetimes could be elided: 'de --> serde/src/private/de.rs:937:10 | 937 | impl<'de> Visitor<'de> for TagOrContentFieldVisitor { | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 937 - impl<'de> Visitor<'de> for TagOrContentFieldVisitor { 937 + impl Visitor<'_> for TagOrContentFieldVisitor { | warning: the following explicit lifetimes could be elided: 'de --> serde/src/private/de.rs:1014:10 | 1014 | impl<'de> Visitor<'de> for TagContentOtherFieldVisitor { | ^^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 1014 - impl<'de> Visitor<'de> for TagContentOtherFieldVisitor { 1014 + impl Visitor<'_> for TagContentOtherFieldVisitor { | warning: the following explicit lifetimes could be elided: 'a --> serde/src/private/de.rs:1652:10 | 1652 | impl<'a, 'de, E> ContentRefDeserializer<'a, 'de, E> | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 1652 - impl<'a, 'de, E> ContentRefDeserializer<'a, 'de, E> 1652 + impl<'de, E> ContentRefDeserializer<'_, 'de, E> | warning: the following explicit lifetimes could be elided: 'a --> serde/src/private/de.rs:1735:15 | 1735 | impl<'de, 'a, E> Deserializer<'de> for ContentRefDeserializer<'a, 'de, E> | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 1735 - impl<'de, 'a, E> Deserializer<'de> for ContentRefDeserializer<'a, 'de, E> 1735 + impl<'de, E> Deserializer<'de> for ContentRefDeserializer<'_, 'de, E> | warning: the following explicit lifetimes could be elided: 'a --> serde/src/private/de.rs:2162:15 | 2162 | impl<'de, 'a, E> de::VariantAccess<'de> for VariantRefDeserializer<'a, 'de, E> | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 2162 - impl<'de, 'a, E> de::VariantAccess<'de> for VariantRefDeserializer<'a, 'de, E> 2162 + impl<'de, E> de::VariantAccess<'de> for VariantRefDeserializer<'_, 'de, E> | warning: the following explicit lifetimes could be elided: 'a --> serde/src/private/de.rs:2259:15 | 2259 | impl<'de, 'a, E> de::IntoDeserializer<'de, E> for ContentRefDeserializer<'a, 'de, E> | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 2259 - impl<'de, 'a, E> de::IntoDeserializer<'de, E> for ContentRefDeserializer<'a, 'de, E> 2259 + impl<'de, E> de::IntoDeserializer<'de, E> for ContentRefDeserializer<'_, 'de, E> | warning: the following explicit lifetimes could be elided: 'a --> serde/src/private/de.rs:2288:15 | 2288 | impl<'de, 'a> Visitor<'de> for InternallyTaggedUnitVisitor<'a> { | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 2288 - impl<'de, 'a> Visitor<'de> for InternallyTaggedUnitVisitor<'a> { 2288 + impl<'de> Visitor<'de> for InternallyTaggedUnitVisitor<'_> { | warning: the following explicit lifetimes could be elided: 'a, 'de --> serde/src/private/de.rs:2333:10 | 2333 | impl<'de, 'a> Visitor<'de> for UntaggedUnitVisitor<'a> { | ^^^ ^^ ^^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 2333 - impl<'de, 'a> Visitor<'de> for UntaggedUnitVisitor<'a> { 2333 + impl Visitor<'_> for UntaggedUnitVisitor<'_> { | warning: the following explicit lifetimes could be elided: 'a --> serde/src/private/de.rs:2396:11 | 2396 | impl<'de, 'a, E> Deserializer<'de> for StrDeserializer<'a, E> | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 2396 - impl<'de, 'a, E> Deserializer<'de> for StrDeserializer<'a, E> 2396 + impl<'de, E> Deserializer<'de> for StrDeserializer<'_, E> | warning: the following explicit lifetimes could be elided: 'a, 'de --> serde/src/private/de.rs:2498:6 | 2498 | impl<'a, 'de, E> FlatMapDeserializer<'a, 'de, E> | ^^ ^^^ ^^ ^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 2498 - impl<'a, 'de, E> FlatMapDeserializer<'a, 'de, E> 2498 + impl FlatMapDeserializer<'_, '_, E> | warning: the following explicit lifetimes could be elided: 'a --> serde/src/private/de.rs:2522:6 | 2522 | impl<'a, 'de, E> Deserializer<'de> for FlatMapDeserializer<'a, 'de, E> | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 2522 - impl<'a, 'de, E> Deserializer<'de> for FlatMapDeserializer<'a, 'de, E> 2522 + impl<'de, E> Deserializer<'de> for FlatMapDeserializer<'_, 'de, E> | warning: the following explicit lifetimes could be elided: 'a --> serde/src/private/de.rs:2658:6 | 2658 | impl<'a, 'de, E> MapAccess<'de> for FlatMapAccess<'a, 'de, E> | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 2658 - impl<'a, 'de, E> MapAccess<'de> for FlatMapAccess<'a, 'de, E> 2658 + impl<'de, E> MapAccess<'de> for FlatMapAccess<'_, 'de, E> | warning: the following explicit lifetimes could be elided: 'a --> serde/src/private/de.rs:2702:6 | 2702 | impl<'a, 'de, E> MapAccess<'de> for FlatStructAccess<'a, 'de, E> | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 2702 - impl<'a, 'de, E> MapAccess<'de> for FlatStructAccess<'a, 'de, E> 2702 + impl<'de, E> MapAccess<'de> for FlatStructAccess<'_, 'de, E> | warning: the following explicit lifetimes could be elided: 'a --> serde/src/de/seed.rs:8:6 | 8 | impl<'a, 'de, T> DeserializeSeed<'de> for InPlaceSeed<'a, T> | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 8 - impl<'a, 'de, T> DeserializeSeed<'de> for InPlaceSeed<'a, T> 8 + impl<'de, T> DeserializeSeed<'de> for InPlaceSeed<'_, T> | warning: the following explicit lifetimes could be elided: 'a --> serde_derive/src/internals/case.rs:124:6 | 124 | impl<'a> Display for ParseError<'a> { | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes = note: `-W clippy::needless-lifetimes` implied by `-W clippy::all` = help: to override `-W clippy::all` add `#[allow(clippy::needless_lifetimes)]` help: elide the lifetimes | 124 - impl<'a> Display for ParseError<'a> { 124 + impl Display for ParseError<'_> { | warning: the following explicit lifetimes could be elided: 'a --> serde_derive/src/de.rs:3042:6 | 3042 | impl<'a> ToTokens for DeImplGenerics<'a> { | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 3042 - impl<'a> ToTokens for DeImplGenerics<'a> { 3042 + impl ToTokens for DeImplGenerics<'_> { | warning: the following explicit lifetimes could be elided: 'a --> serde_derive/src/de.rs:3124:6 | 3124 | impl<'a> ToTokens for DeTypeGenerics<'a> { | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes help: elide the lifetimes | 3124 - impl<'a> ToTokens for DeTypeGenerics<'a> { 3124 + impl ToTokens for DeTypeGenerics<'_> { | warning: the following explicit lifetimes could be elided: 'a --> test_suite/tests/test_serde_path.rs:15:10 | 15 | impl<'a> AssertNotSerdeDeserialize<'a> for Foo {} | ^^ ^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes = note: `-W clippy::needless-lifetimes` implied by `-W clippy::all` = help: to override `-W clippy::all` add `#[allow(clippy::needless_lifetimes)]` help: elide the lifetimes | 15 - impl<'a> AssertNotSerdeDeserialize<'a> for Foo {} 15 + impl AssertNotSerdeDeserialize<'_> for Foo {} | --- serde/src/lib.rs | 1 + serde_derive/src/lib.rs | 1 + serde_derive_internals/lib.rs | 1 + test_suite/tests/test_serde_path.rs | 1 + 4 files changed, 4 insertions(+) diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 15710d8d9..59929e0ba 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -144,6 +144,7 @@ clippy::too_many_lines, // preference clippy::doc_markdown, + clippy::needless_lifetimes, clippy::unseparated_literal_suffix, // false positive clippy::needless_doctest_main, diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index bedd1cb3d..1e415fb20 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -27,6 +27,7 @@ // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797 clippy::manual_map, clippy::match_like_matches_macro, + clippy::needless_lifetimes, clippy::needless_pass_by_value, clippy::too_many_arguments, clippy::trivially_copy_pass_by_ref, diff --git a/serde_derive_internals/lib.rs b/serde_derive_internals/lib.rs index 6edb07ee0..c907b5a24 100644 --- a/serde_derive_internals/lib.rs +++ b/serde_derive_internals/lib.rs @@ -9,6 +9,7 @@ // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797 clippy::manual_map, clippy::missing_panics_doc, + clippy::needless_lifetimes, clippy::redundant_field_names, clippy::result_unit_err, clippy::should_implement_trait, diff --git a/test_suite/tests/test_serde_path.rs b/test_suite/tests/test_serde_path.rs index 127b557ec..1a54e12e3 100644 --- a/test_suite/tests/test_serde_path.rs +++ b/test_suite/tests/test_serde_path.rs @@ -1,5 +1,6 @@ #![allow( clippy::extra_unused_type_parameters, + clippy::needless_lifetimes, clippy::type_repetition_in_bounds )] From 8b0f482666c5deca3bdc440f6b1dcaf84d2d2a62 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 20 Oct 2024 20:35:40 -0700 Subject: [PATCH 199/258] Update for precise capture bounds warning: some variants are not matched explicitly --> serde_derive/src/internals/receiver.rs:209:15 | 209 | match bound { | ^^^^^ pattern `&mut TypeParamBound::PreciseCapture(_)` not covered | = help: ensure that all variants are matched explicitly by adding the suggested match arms = note: the matched value is of type `&mut TypeParamBound` and the `non_exhaustive_omitted_patterns` attribute was found note: the lint level is defined here --> serde_derive/src/internals/receiver.rs:210:53 | 210 | #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: some variants are not matched explicitly --> serde_derive/src/bound.rs:227:19 | 227 | match bound { | ^^^^^ pattern `&TypeParamBound::PreciseCapture(_)` not covered | = help: ensure that all variants are matched explicitly by adding the suggested match arms = note: the matched value is of type `&TypeParamBound` and the `non_exhaustive_omitted_patterns` attribute was found note: the lint level is defined here --> serde_derive/src/bound.rs:228:57 | 228 | #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --- Cargo.toml | 2 +- serde_derive/src/bound.rs | 4 +++- serde_derive/src/internals/receiver.rs | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ac94fb08c..41c11afaa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,4 +12,4 @@ serde = { path = "serde" } [workspace.dependencies] proc-macro2 = { version = "1.0.74", default-features = false } quote = { version = "1.0.35", default-features = false } -syn = { version = "2.0.46", default-features = false } +syn = { version = "2.0.81", default-features = false } diff --git a/serde_derive/src/bound.rs b/serde_derive/src/bound.rs index fe8ccfff5..2ff6521fe 100644 --- a/serde_derive/src/bound.rs +++ b/serde_derive/src/bound.rs @@ -227,7 +227,9 @@ pub fn with_bound( match bound { #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] syn::TypeParamBound::Trait(bound) => self.visit_path(&bound.path), - syn::TypeParamBound::Lifetime(_) | syn::TypeParamBound::Verbatim(_) => {} + syn::TypeParamBound::Lifetime(_) + | syn::TypeParamBound::PreciseCapture(_) + | syn::TypeParamBound::Verbatim(_) => {} _ => {} } } diff --git a/serde_derive/src/internals/receiver.rs b/serde_derive/src/internals/receiver.rs index 852e857b8..1e7fc54f1 100644 --- a/serde_derive/src/internals/receiver.rs +++ b/serde_derive/src/internals/receiver.rs @@ -209,7 +209,9 @@ impl ReplaceReceiver<'_> { match bound { #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] TypeParamBound::Trait(bound) => self.visit_path_mut(&mut bound.path), - TypeParamBound::Lifetime(_) | TypeParamBound::Verbatim(_) => {} + TypeParamBound::Lifetime(_) + | TypeParamBound::PreciseCapture(_) + | TypeParamBound::Verbatim(_) => {} _ => {} } } From 422c71935217643782c6b7624d5ab1b81f5ac417 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 21 Oct 2024 18:47:52 -0700 Subject: [PATCH 200/258] Temporarily disable 1.56 CI While fixing other errors from recently merged PRs. --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 81a861a55..731d99af3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -105,6 +105,7 @@ jobs: - run: cd serde && cargo check --no-default-features - run: cd serde && cargo check - run: cd serde_derive && cargo check + continue-on-error: true # FIXME alloc: name: Rust 1.36.0 From 53ade1013718a6f85c82bcc60a2e02db1684337a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 21 Oct 2024 18:52:49 -0700 Subject: [PATCH 201/258] Update ui tests from PR 2558 --- test_suite/tests/ui/with/incorrect_type.stderr | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test_suite/tests/ui/with/incorrect_type.stderr b/test_suite/tests/ui/with/incorrect_type.stderr index 9981948b5..d974fa4a1 100644 --- a/test_suite/tests/ui/with/incorrect_type.stderr +++ b/test_suite/tests/ui/with/incorrect_type.stderr @@ -7,7 +7,7 @@ error[E0277]: the trait bound `&u8: Serializer` is not satisfied | --- required by a bound introduced by this call | = help: the following other types implement trait `Serializer`: - &'a mut Formatter<'b> + &mut Formatter<'a> FlatMapSerializer<'a, M> _::_serde::__private::ser::content::ContentSerializer note: required by a bound in `w::serialize` @@ -35,7 +35,7 @@ error[E0277]: the trait bound `&u8: Serializer` is not satisfied | ^^^ the trait `Serializer` is not implemented for `&u8` | = help: the following other types implement trait `Serializer`: - &'a mut Formatter<'b> + &mut Formatter<'a> FlatMapSerializer<'a, M> _::_serde::__private::ser::content::ContentSerializer @@ -56,7 +56,7 @@ error[E0277]: the trait bound `&u8: Serializer` is not satisfied | -------------- required by a bound introduced by this call | = help: the following other types implement trait `Serializer`: - &'a mut Formatter<'b> + &mut Formatter<'a> FlatMapSerializer<'a, M> _::_serde::__private::ser::content::ContentSerializer note: required by a bound in `w::serialize` @@ -84,7 +84,7 @@ error[E0277]: the trait bound `&u8: Serializer` is not satisfied | ^^^^^^^^^^^^^^ the trait `Serializer` is not implemented for `&u8` | = help: the following other types implement trait `Serializer`: - &'a mut Formatter<'b> + &mut Formatter<'a> FlatMapSerializer<'a, M> _::_serde::__private::ser::content::ContentSerializer From a8cbc9184ed37beedabc910f1be75e2ae29344c3 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 21 Oct 2024 19:12:52 -0700 Subject: [PATCH 202/258] Ignore needless_lifetimes clippy lint in generated code --- serde_derive/src/dummy.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/serde_derive/src/dummy.rs b/serde_derive/src/dummy.rs index 095f950f3..7883090fc 100644 --- a/serde_derive/src/dummy.rs +++ b/serde_derive/src/dummy.rs @@ -14,7 +14,12 @@ pub fn wrap_in_const(serde_path: Option<&syn::Path>, code: TokenStream) -> Token quote! { #[doc(hidden)] - #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] + #[allow( + clippy::needless_lifetimes, + non_upper_case_globals, + unused_attributes, + unused_qualifications, + )] const _: () = { #use_serde #code From 6a7de26e5ab13fe902ef4fd0eade0db6e3f173a1 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 21 Oct 2024 19:29:33 -0700 Subject: [PATCH 203/258] Ignore uninlined_format_args pedantic clippy lint warning: variables can be used directly in the `format!` string --> serde_derive/src/internals/attr.rs:546:36 | 546 | meta.error(format_args!("unknown serde container attribute `{}`", path)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args = note: `-W clippy::uninlined-format-args` implied by `-W clippy::pedantic` = help: to override `-W clippy::pedantic` add `#[allow(clippy::uninlined_format_args)]` help: change this to | 546 - meta.error(format_args!("unknown serde container attribute `{}`", path)) 546 + meta.error(format_args!("unknown serde container attribute `{path}`")) | warning: variables can be used directly in the `format!` string --> serde_derive/src/internals/attr.rs:940:36 | 940 | meta.error(format_args!("unknown serde variant attribute `{}`", path)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args help: change this to | 940 - meta.error(format_args!("unknown serde variant attribute `{}`", path)) 940 + meta.error(format_args!("unknown serde variant attribute `{path}`")) | warning: variables can be used directly in the `format!` string --> serde_derive/src/internals/attr.rs:1095:33 | 1095 | ... format!("field `{}` does not have lifetime {}", ident, lifetime); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args help: change this to | 1095 - format!("field `{}` does not have lifetime {}", ident, lifetime); 1095 + format!("field `{ident}` does not have lifetime {lifetime}"); | warning: variables can be used directly in the `format!` string --> serde_derive/src/internals/attr.rs:1196:47 | 1196 | ... let msg = format!( | _________________________________^ 1197 | | ... "field `{}` does not have lifetime {}", 1198 | | ... ident, lifetime, 1199 | | ... ); | |_______________________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args warning: variables can be used directly in the `format!` string --> serde_derive/src/internals/attr.rs:1222:36 | 1222 | meta.error(format_args!("unknown serde field attribute `{}`", path)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args help: change this to | 1222 - meta.error(format_args!("unknown serde field attribute `{}`", path)) 1222 + meta.error(format_args!("unknown serde field attribute `{path}`")) | warning: variables can be used directly in the `format!` string --> serde_derive/src/internals/attr.rs:1415:39 | 1415 | return Err(meta.error(format_args!( | _______________________________________^ 1416 | | "malformed {0} attribute, expected `{0}(serialize = ..., deserialize = ...)`", 1417 | | attr_name, 1418 | | ))); | |_________________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args warning: variables can be used directly in the `format!` string --> serde_derive/src/internals/attr.rs:1482:17 | 1482 | format!("unexpected suffix `{}` on string literal", suffix), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args help: change this to | 1482 - format!("unexpected suffix `{}` on string literal", suffix), 1482 + format!("unexpected suffix `{suffix}` on string literal"), | warning: variables can be used directly in the `format!` string --> serde_derive/src/internals/attr.rs:1489:13 | 1489 | / format!( 1490 | | "expected serde {} attribute to be a string: `{} = \"...\"`", 1491 | | attr_name, meta_item_name 1492 | | ), | |_____________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args warning: variables can be used directly in the `format!` string --> serde_derive/src/internals/attr.rs:1604:21 | 1604 | format!("duplicate borrowed lifetime `{}`", lifetime), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args help: change this to | 1604 - format!("duplicate borrowed lifetime `{}`", lifetime), 1604 + format!("duplicate borrowed lifetime `{lifetime}`"), | warning: variables can be used directly in the `format!` string --> serde_derive/src/internals/attr.rs:1778:19 | 1778 | let msg = format!("field `{}` has no lifetimes to borrow", name); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args help: change this to | 1778 - let msg = format!("field `{}` has no lifetimes to borrow", name); 1778 + let msg = format!("field `{name}` has no lifetimes to borrow"); | warning: variables can be used directly in the `format!` string --> serde_derive/src/internals/check.rs:41:29 | 41 | ... format!("field must have #[serde(default)] because previous field {} has #[serde(default)]", first), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args help: change this to | 41 - format!("field must have #[serde(default)] because previous field {} has #[serde(default)]", first), 41 + format!("field must have #[serde(default)] because previous field {first} has #[serde(default)]"), | warning: variables can be used directly in the `format!` string --> serde_derive/src/internals/check.rs:314:13 | 314 | format!("variant field name `{}` conflicts with internal tag", tag), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args help: change this to | 314 - format!("variant field name `{}` conflicts with internal tag", tag), 314 + format!("variant field name `{tag}` conflicts with internal tag"), | warning: variables can be used directly in the `format!` string --> serde_derive/src/internals/check.rs:361:13 | 361 | / format!( 362 | | "enum tags `{}` for type and content conflict with each other", 363 | | type_tag 364 | | ), | |_____________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args warning: variables can be used directly in the `format!` string --> serde_derive/src/internals/check.rs:450:33 | 450 | Member::Named(ident) => format!("`{}`", ident), | ^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args help: change this to | 450 - Member::Named(ident) => format!("`{}`", ident), 450 + Member::Named(ident) => format!("`{ident}`"), | warning: variables can be used directly in the `format!` string --> serde_derive/src/de.rs:697:9 | 697 | format!("{} with 1 element", expecting) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args help: change this to | 697 - format!("{} with 1 element", expecting) 697 + format!("{expecting} with 1 element") | warning: variables can be used directly in the `format!` string --> serde_derive/src/de.rs:699:9 | 699 | format!("{} with {} elements", expecting, deserialized_count) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args help: change this to | 699 - format!("{} with {} elements", expecting, deserialized_count) 699 + format!("{expecting} with {deserialized_count} elements") | warning: variables can be used directly in the `format!` string --> serde_derive/src/de.rs:1442:21 | 1442 | let expecting = format!("adjacently tagged enum {}", rust_name); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args help: change this to | 1442 - let expecting = format!("adjacently tagged enum {}", rust_name); 1442 + let expecting = format!("adjacently tagged enum {rust_name}"); | warning: variables can be used directly in the `format!` string --> serde_derive/src/de.rs:2842:17 | 2842 | Ident::new(&format!("__field{}", i), Span::call_site()) | ^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args help: change this to | 2842 - Ident::new(&format!("__field{}", i), Span::call_site()) 2842 + Ident::new(&format!("__field{i}"), Span::call_site()) | warning: variables can be used directly in the `format!` string --> serde_derive/src/ser.rs:457:42 | 457 | .map(|i| Ident::new(&format!("__field{}", i), Span::call_site())); | ^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args help: change this to | 457 - .map(|i| Ident::new(&format!("__field{}", i), Span::call_site())); 457 + .map(|i| Ident::new(&format!("__field{i}"), Span::call_site())); | warning: variables can be used directly in the `format!` string --> serde_derive/src/ser.rs:714:48 | 714 | .map(|i| Member::Named(Ident::new(&format!("__field{}", i), Span::call_site()))) | ^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args help: change this to | 714 - .map(|i| Member::Named(Ident::new(&format!("__field{}", i), Span::call_site()))) 714 + .map(|i| Member::Named(Ident::new(&format!("__field{i}"), Span::call_site()))) | warning: variables can be used directly in the `format!` string --> serde_derive/src/ser.rs:832:46 | 832 | let field_expr = Ident::new(&format!("__field{}", i), Span::call_site()); | ^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args help: change this to | 832 - let field_expr = Ident::new(&format!("__field{}", i), Span::call_site()); 832 + let field_expr = Ident::new(&format!("__field{i}"), Span::call_site()); | warning: variables can be used directly in the `format!` string --> serde_derive/src/ser.rs:1062:38 | 1062 | let id = Ident::new(&format!("__field{}", i), Span::call_site()); | ^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args help: change this to | 1062 - let id = Ident::new(&format!("__field{}", i), Span::call_site()); 1062 + let id = Ident::new(&format!("__field{i}"), Span::call_site()); | --- serde_derive/src/lib.rs | 1 + serde_derive_internals/lib.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index 1e415fb20..15a10cd2f 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -56,6 +56,7 @@ clippy::single_match_else, clippy::struct_excessive_bools, clippy::too_many_lines, + clippy::uninlined_format_args, clippy::unseparated_literal_suffix, clippy::unused_self, clippy::use_self, diff --git a/serde_derive_internals/lib.rs b/serde_derive_internals/lib.rs index c907b5a24..d07485771 100644 --- a/serde_derive_internals/lib.rs +++ b/serde_derive_internals/lib.rs @@ -36,6 +36,7 @@ clippy::single_match_else, clippy::struct_excessive_bools, clippy::too_many_lines, + clippy::uninlined_format_args, clippy::unused_self, clippy::wildcard_imports )] From 991e344804059226cb89dd8d295085f653339a31 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 21 Oct 2024 18:15:01 -0700 Subject: [PATCH 204/258] Raise required compiler for serde_derive to 1.61 This is the rust-version declared by recent versions of Syn. --- .github/workflows/ci.yml | 10 ++++++---- README.md | 4 ++-- serde/build.rs | 10 +++++----- serde_derive/Cargo.toml | 2 +- serde_derive_internals/Cargo.toml | 2 +- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 731d99af3..f60449aac 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -95,17 +95,19 @@ jobs: - run: cd serde && cargo build derive: - name: Rust 1.56.0 + name: Rust 1.61.0 runs-on: ubuntu-latest timeout-minutes: 45 steps: - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@1.56.0 - - run: sed -i '/"test_suite"/d' Cargo.toml + - uses: dtolnay/rust-toolchain@1.61.0 + - run: | + sed -i 's/proc-macro2 = { workspace = true/proc-macro2 = { version = "1"/' serde_derive*/Cargo.toml + sed -i 's/quote = { workspace = true/quote = { version = "1"/' serde_derive*/Cargo.toml + sed -i 's/syn = { workspace = true/syn = { version = "2"/' serde_derive*/Cargo.toml - run: cd serde && cargo check --no-default-features - run: cd serde && cargo check - run: cd serde_derive && cargo check - continue-on-error: true # FIXME alloc: name: Rust 1.36.0 diff --git a/README.md b/README.md index 31292944a..e3da0cbc8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Serde   [![Build Status]][actions] [![Latest Version]][crates.io] [![serde msrv]][Rust 1.31] [![serde_derive msrv]][Rust 1.56] +# Serde   [![Build Status]][actions] [![Latest Version]][crates.io] [![serde msrv]][Rust 1.31] [![serde_derive msrv]][Rust 1.61] [Build Status]: https://img.shields.io/github/actions/workflow/status/serde-rs/serde/ci.yml?branch=master [actions]: https://github.com/serde-rs/serde/actions?query=branch%3Amaster @@ -7,7 +7,7 @@ [serde msrv]: https://img.shields.io/crates/msrv/serde.svg?label=serde%20msrv&color=lightgray [serde_derive msrv]: https://img.shields.io/crates/msrv/serde_derive.svg?label=serde_derive%20msrv&color=lightgray [Rust 1.31]: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html -[Rust 1.56]: https://blog.rust-lang.org/2021/10/21/Rust-1.56.0.html +[Rust 1.61]: https://blog.rust-lang.org/2022/05/19/Rust-1.61.0.html **Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.** diff --git a/serde/build.rs b/serde/build.rs index 8a4f7257c..d7ab56562 100644 --- a/serde/build.rs +++ b/serde/build.rs @@ -50,11 +50,6 @@ fn main() { println!("cargo:rustc-cfg=no_float_copysign"); } - // Current minimum supported version of serde_derive crate is Rust 1.56. - if minor < 56 { - println!("cargo:rustc-cfg=no_serde_derive"); - } - // Support for #[cfg(target_has_atomic = "...")] stabilized in Rust 1.60. if minor < 60 { println!("cargo:rustc-cfg=no_target_has_atomic"); @@ -76,6 +71,11 @@ fn main() { } } + // Current minimum supported version of serde_derive crate is Rust 1.61. + if minor < 61 { + println!("cargo:rustc-cfg=no_serde_derive"); + } + // Support for core::ffi::CStr and alloc::ffi::CString stabilized in Rust 1.64. // https://blog.rust-lang.org/2022/09/22/Rust-1.64.0.html#c-compatible-ffi-types-in-core-and-alloc if minor < 64 { diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index d6e5c24e6..6bb1e3157 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -12,7 +12,7 @@ keywords = ["serde", "serialization", "no_std", "derive"] license = "MIT OR Apache-2.0" readme = "crates-io.md" repository = "https://github.com/serde-rs/serde" -rust-version = "1.56" +rust-version = "1.61" [features] default = [] diff --git a/serde_derive_internals/Cargo.toml b/serde_derive_internals/Cargo.toml index bf99c1399..efd6df58c 100644 --- a/serde_derive_internals/Cargo.toml +++ b/serde_derive_internals/Cargo.toml @@ -10,7 +10,7 @@ homepage = "https://serde.rs" keywords = ["serde", "serialization"] license = "MIT OR Apache-2.0" repository = "https://github.com/serde-rs/serde" -rust-version = "1.56" +rust-version = "1.61" [lib] path = "lib.rs" From d4486be2b9f7050d5007887f9e0cdc03759b3e77 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 21 Oct 2024 19:43:27 -0700 Subject: [PATCH 205/258] Format all ui tests from PR 2558 using rustfmt --- .../incorrect_type_enum_adjacently_tagged.rs | 5 +--- ...correct_type_enum_adjacently_tagged.stderr | 26 +++++++++---------- .../incorrect_type_enum_externally_tagged.rs | 5 +--- ...correct_type_enum_externally_tagged.stderr | 26 +++++++++---------- .../incorrect_type_enum_untagged.rs | 5 +--- .../incorrect_type_enum_untagged.stderr | 26 +++++++++---------- .../default-attribute/incorrect_type_tuple.rs | 5 +--- .../incorrect_type_tuple.stderr | 18 ++++++------- 8 files changed, 52 insertions(+), 64 deletions(-) diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs b/test_suite/tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs index 63a88fed6..339af63d9 100644 --- a/test_suite/tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs +++ b/test_suite/tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs @@ -6,10 +6,7 @@ use serde_derive::Deserialize; enum Enum { // Newtype variants does not use the provided path, so it is forbidden here // Newtype(#[serde(default = "main")] u8), - Tuple( - u8, - #[serde(default = "main")] i8, - ), + Tuple(u8, #[serde(default = "main")] i8), Struct { #[serde(default = "main")] f1: u8, diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.stderr b/test_suite/tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.stderr index eefe58500..984f24252 100644 --- a/test_suite/tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.stderr +++ b/test_suite/tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.stderr @@ -1,17 +1,17 @@ error[E0308]: `match` arms have incompatible types - --> tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs:11:27 - | -4 | #[derive(Deserialize)] - | ----------- - | | - | this is found to be of type `i8` - | `match` arms have incompatible types + --> tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs:9:33 + | +4 | #[derive(Deserialize)] + | ----------- + | | + | this is found to be of type `i8` + | `match` arms have incompatible types ... -11 | #[serde(default = "main")] i8, - | ^^^^^^ expected `i8`, found `()` +9 | Tuple(u8, #[serde(default = "main")] i8), + | ^^^^^^ expected `i8`, found `()` error[E0308]: `match` arms have incompatible types - --> tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs:14:27 + --> tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs:11:27 | 4 | #[derive(Deserialize)] | ----------- @@ -19,11 +19,11 @@ error[E0308]: `match` arms have incompatible types | this is found to be of type `u8` | `match` arms have incompatible types ... -14 | #[serde(default = "main")] +11 | #[serde(default = "main")] | ^^^^^^ expected `u8`, found `()` error[E0308]: `match` arms have incompatible types - --> tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs:17:27 + --> tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs:14:27 | 4 | #[derive(Deserialize)] | ----------- @@ -31,5 +31,5 @@ error[E0308]: `match` arms have incompatible types | this is found to be of type `i8` | `match` arms have incompatible types ... -17 | #[serde(default = "main")] +14 | #[serde(default = "main")] | ^^^^^^ expected `i8`, found `()` diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs b/test_suite/tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs index ae6144d8b..02dc64462 100644 --- a/test_suite/tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs +++ b/test_suite/tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs @@ -5,10 +5,7 @@ use serde_derive::Deserialize; enum Enum { // Newtype variants does not use the provided path, so it is forbidden here // Newtype(#[serde(default = "main")] u8), - Tuple( - u8, - #[serde(default = "main")] i8, - ), + Tuple(u8, #[serde(default = "main")] i8), Struct { #[serde(default = "main")] f1: u8, diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_enum_externally_tagged.stderr b/test_suite/tests/ui/default-attribute/incorrect_type_enum_externally_tagged.stderr index dd6f8b0d6..01672cfa4 100644 --- a/test_suite/tests/ui/default-attribute/incorrect_type_enum_externally_tagged.stderr +++ b/test_suite/tests/ui/default-attribute/incorrect_type_enum_externally_tagged.stderr @@ -1,17 +1,17 @@ error[E0308]: `match` arms have incompatible types - --> tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs:10:27 - | -4 | #[derive(Deserialize)] - | ----------- - | | - | this is found to be of type `i8` - | `match` arms have incompatible types + --> tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs:8:33 + | +4 | #[derive(Deserialize)] + | ----------- + | | + | this is found to be of type `i8` + | `match` arms have incompatible types ... -10 | #[serde(default = "main")] i8, - | ^^^^^^ expected `i8`, found `()` +8 | Tuple(u8, #[serde(default = "main")] i8), + | ^^^^^^ expected `i8`, found `()` error[E0308]: `match` arms have incompatible types - --> tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs:13:27 + --> tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs:10:27 | 4 | #[derive(Deserialize)] | ----------- @@ -19,11 +19,11 @@ error[E0308]: `match` arms have incompatible types | this is found to be of type `u8` | `match` arms have incompatible types ... -13 | #[serde(default = "main")] +10 | #[serde(default = "main")] | ^^^^^^ expected `u8`, found `()` error[E0308]: `match` arms have incompatible types - --> tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs:16:27 + --> tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs:13:27 | 4 | #[derive(Deserialize)] | ----------- @@ -31,5 +31,5 @@ error[E0308]: `match` arms have incompatible types | this is found to be of type `i8` | `match` arms have incompatible types ... -16 | #[serde(default = "main")] +13 | #[serde(default = "main")] | ^^^^^^ expected `i8`, found `()` diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_enum_untagged.rs b/test_suite/tests/ui/default-attribute/incorrect_type_enum_untagged.rs index 8fa6c04e9..530f4a9da 100644 --- a/test_suite/tests/ui/default-attribute/incorrect_type_enum_untagged.rs +++ b/test_suite/tests/ui/default-attribute/incorrect_type_enum_untagged.rs @@ -6,10 +6,7 @@ use serde_derive::Deserialize; enum Enum { // Newtype variants does not use the provided path, so it is forbidden here // Newtype(#[serde(default = "main")] u8), - Tuple( - u8, - #[serde(default = "main")] i8, - ), + Tuple(u8, #[serde(default = "main")] i8), Struct { #[serde(default = "main")] f1: u8, diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_enum_untagged.stderr b/test_suite/tests/ui/default-attribute/incorrect_type_enum_untagged.stderr index 9ffa6bb4e..d782fe30f 100644 --- a/test_suite/tests/ui/default-attribute/incorrect_type_enum_untagged.stderr +++ b/test_suite/tests/ui/default-attribute/incorrect_type_enum_untagged.stderr @@ -1,17 +1,17 @@ error[E0308]: `match` arms have incompatible types - --> tests/ui/default-attribute/incorrect_type_enum_untagged.rs:11:27 - | -4 | #[derive(Deserialize)] - | ----------- - | | - | this is found to be of type `i8` - | `match` arms have incompatible types + --> tests/ui/default-attribute/incorrect_type_enum_untagged.rs:9:33 + | +4 | #[derive(Deserialize)] + | ----------- + | | + | this is found to be of type `i8` + | `match` arms have incompatible types ... -11 | #[serde(default = "main")] i8, - | ^^^^^^ expected `i8`, found `()` +9 | Tuple(u8, #[serde(default = "main")] i8), + | ^^^^^^ expected `i8`, found `()` error[E0308]: `match` arms have incompatible types - --> tests/ui/default-attribute/incorrect_type_enum_untagged.rs:14:27 + --> tests/ui/default-attribute/incorrect_type_enum_untagged.rs:11:27 | 4 | #[derive(Deserialize)] | ----------- @@ -19,11 +19,11 @@ error[E0308]: `match` arms have incompatible types | this is found to be of type `u8` | `match` arms have incompatible types ... -14 | #[serde(default = "main")] +11 | #[serde(default = "main")] | ^^^^^^ expected `u8`, found `()` error[E0308]: `match` arms have incompatible types - --> tests/ui/default-attribute/incorrect_type_enum_untagged.rs:17:27 + --> tests/ui/default-attribute/incorrect_type_enum_untagged.rs:14:27 | 4 | #[derive(Deserialize)] | ----------- @@ -31,5 +31,5 @@ error[E0308]: `match` arms have incompatible types | this is found to be of type `i8` | `match` arms have incompatible types ... -17 | #[serde(default = "main")] +14 | #[serde(default = "main")] | ^^^^^^ expected `i8`, found `()` diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_tuple.rs b/test_suite/tests/ui/default-attribute/incorrect_type_tuple.rs index b5f0c5c9e..895ce652e 100644 --- a/test_suite/tests/ui/default-attribute/incorrect_type_tuple.rs +++ b/test_suite/tests/ui/default-attribute/incorrect_type_tuple.rs @@ -3,9 +3,6 @@ use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(default = "main")] -struct Tuple( - u8, - #[serde(default = "main")] i8, -); +struct Tuple(u8, #[serde(default = "main")] i8); fn main() {} diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_tuple.stderr b/test_suite/tests/ui/default-attribute/incorrect_type_tuple.stderr index e473e6ff6..a767c8c55 100644 --- a/test_suite/tests/ui/default-attribute/incorrect_type_tuple.stderr +++ b/test_suite/tests/ui/default-attribute/incorrect_type_tuple.stderr @@ -8,30 +8,30 @@ error[E0308]: mismatched types | expected due to this error[E0308]: `match` arms have incompatible types - --> tests/ui/default-attribute/incorrect_type_tuple.rs:8:23 + --> tests/ui/default-attribute/incorrect_type_tuple.rs:6:36 | 4 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `i8` | `match` arms have incompatible types -... -8 | #[serde(default = "main")] i8, - | ^^^^^^ expected `i8`, found `()` +5 | #[serde(default = "main")] +6 | struct Tuple(u8, #[serde(default = "main")] i8); + | ^^^^^^ expected `i8`, found `()` error[E0308]: mismatched types --> tests/ui/default-attribute/incorrect_type_tuple.rs:5:19 | 5 | #[serde(default = "main")] | ^^^^^^ expected `Tuple`, found `()` -6 | struct Tuple( +6 | struct Tuple(u8, #[serde(default = "main")] i8); | ----- expected due to this error[E0308]: mismatched types - --> tests/ui/default-attribute/incorrect_type_tuple.rs:8:23 + --> tests/ui/default-attribute/incorrect_type_tuple.rs:6:36 | 4 | #[derive(Deserialize)] | ----------- expected due to the type of this binding -... -8 | #[serde(default = "main")] i8, - | ^^^^^^ expected `i8`, found `()` +5 | #[serde(default = "main")] +6 | struct Tuple(u8, #[serde(default = "main")] i8); + | ^^^^^^ expected `i8`, found `()` From 00460b8dee15a098a5218b9ec3117e1082dbeccb Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 21 Oct 2024 19:41:43 -0700 Subject: [PATCH 206/258] Fix wording in comments from PR 2558 --- serde_derive/src/ser.rs | 2 +- .../incorrect_type_enum_adjacently_tagged.rs | 5 +-- ...correct_type_enum_adjacently_tagged.stderr | 30 ++++++++-------- .../incorrect_type_enum_externally_tagged.rs | 5 +-- ...correct_type_enum_externally_tagged.stderr | 18 +++++----- .../incorrect_type_enum_internally_tagged.rs | 7 ++-- ...correct_type_enum_internally_tagged.stderr | 12 +++---- .../incorrect_type_enum_untagged.rs | 5 +-- .../incorrect_type_enum_untagged.stderr | 30 ++++++++-------- .../incorrect_type_newtype.rs | 3 +- .../incorrect_type_newtype.stderr | 26 +++++++------- .../incorrect_type_struct.rs | 3 +- .../incorrect_type_struct.stderr | 34 +++++++++---------- .../default-attribute/incorrect_type_tuple.rs | 3 +- .../incorrect_type_tuple.stderr | 26 +++++++------- 15 files changed, 108 insertions(+), 101 deletions(-) diff --git a/serde_derive/src/ser.rs b/serde_derive/src/ser.rs index 9a45b81d4..725851212 100644 --- a/serde_derive/src/ser.rs +++ b/serde_derive/src/ser.rs @@ -1227,7 +1227,7 @@ fn wrap_serialize_with( quote_spanned!(serialize_with.span()=> { #[doc(hidden)] struct __SerializeWith #wrapper_impl_generics #where_clause { - // If #field_tys is empty, `values` does not used + // If #field_tys is empty, this field is unused #[allow(dead_code)] values: (#(&'__a #field_tys, )*), phantom: _serde::__private::PhantomData<#this_type #ty_generics>, diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs b/test_suite/tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs index 339af63d9..2e0fc8675 100644 --- a/test_suite/tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs +++ b/test_suite/tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs @@ -1,10 +1,11 @@ -//! Ensures that error message points to the path in attribute +// Tests that type error points to the path in attribute + use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(tag = "tag", content = "content")] enum Enum { - // Newtype variants does not use the provided path, so it is forbidden here + // Newtype variants do not use the provided path, so it is forbidden here // Newtype(#[serde(default = "main")] u8), Tuple(u8, #[serde(default = "main")] i8), Struct { diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.stderr b/test_suite/tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.stderr index 984f24252..c21b4769b 100644 --- a/test_suite/tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.stderr +++ b/test_suite/tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.stderr @@ -1,35 +1,35 @@ error[E0308]: `match` arms have incompatible types - --> tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs:9:33 - | -4 | #[derive(Deserialize)] - | ----------- - | | - | this is found to be of type `i8` - | `match` arms have incompatible types + --> tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs:10:33 + | +5 | #[derive(Deserialize)] + | ----------- + | | + | this is found to be of type `i8` + | `match` arms have incompatible types ... -9 | Tuple(u8, #[serde(default = "main")] i8), - | ^^^^^^ expected `i8`, found `()` +10 | Tuple(u8, #[serde(default = "main")] i8), + | ^^^^^^ expected `i8`, found `()` error[E0308]: `match` arms have incompatible types - --> tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs:11:27 + --> tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs:12:27 | -4 | #[derive(Deserialize)] +5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `u8` | `match` arms have incompatible types ... -11 | #[serde(default = "main")] +12 | #[serde(default = "main")] | ^^^^^^ expected `u8`, found `()` error[E0308]: `match` arms have incompatible types - --> tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs:14:27 + --> tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs:15:27 | -4 | #[derive(Deserialize)] +5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `i8` | `match` arms have incompatible types ... -14 | #[serde(default = "main")] +15 | #[serde(default = "main")] | ^^^^^^ expected `i8`, found `()` diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs b/test_suite/tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs index 02dc64462..7c92b15f1 100644 --- a/test_suite/tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs +++ b/test_suite/tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs @@ -1,9 +1,10 @@ -//! Ensures that error message points to the path in attribute +// Tests that type error points to the path in attribute + use serde_derive::Deserialize; #[derive(Deserialize)] enum Enum { - // Newtype variants does not use the provided path, so it is forbidden here + // Newtype variants do not use the provided path, so it is forbidden here // Newtype(#[serde(default = "main")] u8), Tuple(u8, #[serde(default = "main")] i8), Struct { diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_enum_externally_tagged.stderr b/test_suite/tests/ui/default-attribute/incorrect_type_enum_externally_tagged.stderr index 01672cfa4..09da24386 100644 --- a/test_suite/tests/ui/default-attribute/incorrect_type_enum_externally_tagged.stderr +++ b/test_suite/tests/ui/default-attribute/incorrect_type_enum_externally_tagged.stderr @@ -1,35 +1,35 @@ error[E0308]: `match` arms have incompatible types - --> tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs:8:33 + --> tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs:9:33 | -4 | #[derive(Deserialize)] +5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `i8` | `match` arms have incompatible types ... -8 | Tuple(u8, #[serde(default = "main")] i8), +9 | Tuple(u8, #[serde(default = "main")] i8), | ^^^^^^ expected `i8`, found `()` error[E0308]: `match` arms have incompatible types - --> tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs:10:27 + --> tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs:11:27 | -4 | #[derive(Deserialize)] +5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `u8` | `match` arms have incompatible types ... -10 | #[serde(default = "main")] +11 | #[serde(default = "main")] | ^^^^^^ expected `u8`, found `()` error[E0308]: `match` arms have incompatible types - --> tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs:13:27 + --> tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs:14:27 | -4 | #[derive(Deserialize)] +5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `i8` | `match` arms have incompatible types ... -13 | #[serde(default = "main")] +14 | #[serde(default = "main")] | ^^^^^^ expected `i8`, found `()` diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_enum_internally_tagged.rs b/test_suite/tests/ui/default-attribute/incorrect_type_enum_internally_tagged.rs index d50264155..5e1a4e848 100644 --- a/test_suite/tests/ui/default-attribute/incorrect_type_enum_internally_tagged.rs +++ b/test_suite/tests/ui/default-attribute/incorrect_type_enum_internally_tagged.rs @@ -1,12 +1,13 @@ -//! Ensures that error message points to the path in attribute +// Tests that type error points to the path in attribute + use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(tag = "tag")] enum Enum { - // Newtype variants does not use the provided path, so it is forbidden here + // Newtype variants do not use the provided path, so it is forbidden here // Newtype(#[serde(default = "main")] u8), - // Tuple variants does not supported in internally tagged enums + // Tuple variants are not supported in internally tagged enums Struct { #[serde(default = "main")] f1: u8, diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_enum_internally_tagged.stderr b/test_suite/tests/ui/default-attribute/incorrect_type_enum_internally_tagged.stderr index 752806b64..74fead2da 100644 --- a/test_suite/tests/ui/default-attribute/incorrect_type_enum_internally_tagged.stderr +++ b/test_suite/tests/ui/default-attribute/incorrect_type_enum_internally_tagged.stderr @@ -1,23 +1,23 @@ error[E0308]: `match` arms have incompatible types - --> tests/ui/default-attribute/incorrect_type_enum_internally_tagged.rs:11:27 + --> tests/ui/default-attribute/incorrect_type_enum_internally_tagged.rs:12:27 | -4 | #[derive(Deserialize)] +5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `u8` | `match` arms have incompatible types ... -11 | #[serde(default = "main")] +12 | #[serde(default = "main")] | ^^^^^^ expected `u8`, found `()` error[E0308]: `match` arms have incompatible types - --> tests/ui/default-attribute/incorrect_type_enum_internally_tagged.rs:14:27 + --> tests/ui/default-attribute/incorrect_type_enum_internally_tagged.rs:15:27 | -4 | #[derive(Deserialize)] +5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `i8` | `match` arms have incompatible types ... -14 | #[serde(default = "main")] +15 | #[serde(default = "main")] | ^^^^^^ expected `i8`, found `()` diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_enum_untagged.rs b/test_suite/tests/ui/default-attribute/incorrect_type_enum_untagged.rs index 530f4a9da..1c5e910d7 100644 --- a/test_suite/tests/ui/default-attribute/incorrect_type_enum_untagged.rs +++ b/test_suite/tests/ui/default-attribute/incorrect_type_enum_untagged.rs @@ -1,10 +1,11 @@ -//! Ensures that error message points to the path in attribute +// Tests that type error points to the path in attribute + use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(untagged)] enum Enum { - // Newtype variants does not use the provided path, so it is forbidden here + // Newtype variants do not use the provided path, so it is forbidden here // Newtype(#[serde(default = "main")] u8), Tuple(u8, #[serde(default = "main")] i8), Struct { diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_enum_untagged.stderr b/test_suite/tests/ui/default-attribute/incorrect_type_enum_untagged.stderr index d782fe30f..9e1167d9d 100644 --- a/test_suite/tests/ui/default-attribute/incorrect_type_enum_untagged.stderr +++ b/test_suite/tests/ui/default-attribute/incorrect_type_enum_untagged.stderr @@ -1,35 +1,35 @@ error[E0308]: `match` arms have incompatible types - --> tests/ui/default-attribute/incorrect_type_enum_untagged.rs:9:33 - | -4 | #[derive(Deserialize)] - | ----------- - | | - | this is found to be of type `i8` - | `match` arms have incompatible types + --> tests/ui/default-attribute/incorrect_type_enum_untagged.rs:10:33 + | +5 | #[derive(Deserialize)] + | ----------- + | | + | this is found to be of type `i8` + | `match` arms have incompatible types ... -9 | Tuple(u8, #[serde(default = "main")] i8), - | ^^^^^^ expected `i8`, found `()` +10 | Tuple(u8, #[serde(default = "main")] i8), + | ^^^^^^ expected `i8`, found `()` error[E0308]: `match` arms have incompatible types - --> tests/ui/default-attribute/incorrect_type_enum_untagged.rs:11:27 + --> tests/ui/default-attribute/incorrect_type_enum_untagged.rs:12:27 | -4 | #[derive(Deserialize)] +5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `u8` | `match` arms have incompatible types ... -11 | #[serde(default = "main")] +12 | #[serde(default = "main")] | ^^^^^^ expected `u8`, found `()` error[E0308]: `match` arms have incompatible types - --> tests/ui/default-attribute/incorrect_type_enum_untagged.rs:14:27 + --> tests/ui/default-attribute/incorrect_type_enum_untagged.rs:15:27 | -4 | #[derive(Deserialize)] +5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `i8` | `match` arms have incompatible types ... -14 | #[serde(default = "main")] +15 | #[serde(default = "main")] | ^^^^^^ expected `i8`, found `()` diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_newtype.rs b/test_suite/tests/ui/default-attribute/incorrect_type_newtype.rs index 7db2a3d4b..84b60942d 100644 --- a/test_suite/tests/ui/default-attribute/incorrect_type_newtype.rs +++ b/test_suite/tests/ui/default-attribute/incorrect_type_newtype.rs @@ -1,4 +1,5 @@ -//! Ensures that error message points to the path in attribute +// Tests that type error points to the path in attribute + use serde_derive::Deserialize; #[derive(Deserialize)] diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_newtype.stderr b/test_suite/tests/ui/default-attribute/incorrect_type_newtype.stderr index b8910514e..b4e066ae2 100644 --- a/test_suite/tests/ui/default-attribute/incorrect_type_newtype.stderr +++ b/test_suite/tests/ui/default-attribute/incorrect_type_newtype.stderr @@ -1,37 +1,37 @@ error[E0308]: mismatched types - --> tests/ui/default-attribute/incorrect_type_newtype.rs:5:19 + --> tests/ui/default-attribute/incorrect_type_newtype.rs:6:19 | -5 | #[serde(default = "main")] +6 | #[serde(default = "main")] | ^^^^^^ | | | expected `Newtype`, found `()` | expected due to this error[E0308]: `match` arms have incompatible types - --> tests/ui/default-attribute/incorrect_type_newtype.rs:6:34 + --> tests/ui/default-attribute/incorrect_type_newtype.rs:7:34 | -4 | #[derive(Deserialize)] +5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `u8` | `match` arms have incompatible types -5 | #[serde(default = "main")] -6 | struct Newtype(#[serde(default = "main")] u8); +6 | #[serde(default = "main")] +7 | struct Newtype(#[serde(default = "main")] u8); | ^^^^^^ expected `u8`, found `()` error[E0308]: mismatched types - --> tests/ui/default-attribute/incorrect_type_newtype.rs:5:19 + --> tests/ui/default-attribute/incorrect_type_newtype.rs:6:19 | -5 | #[serde(default = "main")] +6 | #[serde(default = "main")] | ^^^^^^ expected `Newtype`, found `()` -6 | struct Newtype(#[serde(default = "main")] u8); +7 | struct Newtype(#[serde(default = "main")] u8); | ------- expected due to this error[E0308]: mismatched types - --> tests/ui/default-attribute/incorrect_type_newtype.rs:6:34 + --> tests/ui/default-attribute/incorrect_type_newtype.rs:7:34 | -4 | #[derive(Deserialize)] +5 | #[derive(Deserialize)] | ----------- expected due to the type of this binding -5 | #[serde(default = "main")] -6 | struct Newtype(#[serde(default = "main")] u8); +6 | #[serde(default = "main")] +7 | struct Newtype(#[serde(default = "main")] u8); | ^^^^^^ expected `u8`, found `()` diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_struct.rs b/test_suite/tests/ui/default-attribute/incorrect_type_struct.rs index 52d5af9aa..3c5370b8e 100644 --- a/test_suite/tests/ui/default-attribute/incorrect_type_struct.rs +++ b/test_suite/tests/ui/default-attribute/incorrect_type_struct.rs @@ -1,4 +1,5 @@ -//! Ensures that error message points to the path in attribute +// Tests that type error points to the path in attribute + use serde_derive::Deserialize; #[derive(Deserialize)] diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_struct.stderr b/test_suite/tests/ui/default-attribute/incorrect_type_struct.stderr index 5663c3200..13431b034 100644 --- a/test_suite/tests/ui/default-attribute/incorrect_type_struct.stderr +++ b/test_suite/tests/ui/default-attribute/incorrect_type_struct.stderr @@ -1,58 +1,58 @@ error[E0308]: mismatched types - --> tests/ui/default-attribute/incorrect_type_struct.rs:5:19 + --> tests/ui/default-attribute/incorrect_type_struct.rs:6:19 | -5 | #[serde(default = "main")] +6 | #[serde(default = "main")] | ^^^^^^ | | | expected `Struct`, found `()` | expected due to this error[E0308]: `match` arms have incompatible types - --> tests/ui/default-attribute/incorrect_type_struct.rs:7:23 + --> tests/ui/default-attribute/incorrect_type_struct.rs:8:23 | -4 | #[derive(Deserialize)] +5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `u8` | `match` arms have incompatible types ... -7 | #[serde(default = "main")] +8 | #[serde(default = "main")] | ^^^^^^ expected `u8`, found `()` error[E0308]: `match` arms have incompatible types - --> tests/ui/default-attribute/incorrect_type_struct.rs:10:23 + --> tests/ui/default-attribute/incorrect_type_struct.rs:11:23 | -4 | #[derive(Deserialize)] +5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `i8` | `match` arms have incompatible types ... -10 | #[serde(default = "main")] +11 | #[serde(default = "main")] | ^^^^^^ expected `i8`, found `()` error[E0308]: mismatched types - --> tests/ui/default-attribute/incorrect_type_struct.rs:5:19 + --> tests/ui/default-attribute/incorrect_type_struct.rs:6:19 | -5 | #[serde(default = "main")] +6 | #[serde(default = "main")] | ^^^^^^ expected `Struct`, found `()` -6 | struct Struct { +7 | struct Struct { | ------ expected due to this error[E0308]: mismatched types - --> tests/ui/default-attribute/incorrect_type_struct.rs:7:23 + --> tests/ui/default-attribute/incorrect_type_struct.rs:8:23 | -4 | #[derive(Deserialize)] +5 | #[derive(Deserialize)] | ----------- expected due to the type of this binding ... -7 | #[serde(default = "main")] +8 | #[serde(default = "main")] | ^^^^^^ expected `u8`, found `()` error[E0308]: mismatched types - --> tests/ui/default-attribute/incorrect_type_struct.rs:10:23 + --> tests/ui/default-attribute/incorrect_type_struct.rs:11:23 | -4 | #[derive(Deserialize)] +5 | #[derive(Deserialize)] | ----------- expected due to the type of this binding ... -10 | #[serde(default = "main")] +11 | #[serde(default = "main")] | ^^^^^^ expected `i8`, found `()` diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_tuple.rs b/test_suite/tests/ui/default-attribute/incorrect_type_tuple.rs index 895ce652e..f40e11651 100644 --- a/test_suite/tests/ui/default-attribute/incorrect_type_tuple.rs +++ b/test_suite/tests/ui/default-attribute/incorrect_type_tuple.rs @@ -1,4 +1,5 @@ -//! Ensures that error message points to the path in attribute +// Tests that type error points to the path in attribute + use serde_derive::Deserialize; #[derive(Deserialize)] diff --git a/test_suite/tests/ui/default-attribute/incorrect_type_tuple.stderr b/test_suite/tests/ui/default-attribute/incorrect_type_tuple.stderr index a767c8c55..131158e28 100644 --- a/test_suite/tests/ui/default-attribute/incorrect_type_tuple.stderr +++ b/test_suite/tests/ui/default-attribute/incorrect_type_tuple.stderr @@ -1,37 +1,37 @@ error[E0308]: mismatched types - --> tests/ui/default-attribute/incorrect_type_tuple.rs:5:19 + --> tests/ui/default-attribute/incorrect_type_tuple.rs:6:19 | -5 | #[serde(default = "main")] +6 | #[serde(default = "main")] | ^^^^^^ | | | expected `Tuple`, found `()` | expected due to this error[E0308]: `match` arms have incompatible types - --> tests/ui/default-attribute/incorrect_type_tuple.rs:6:36 + --> tests/ui/default-attribute/incorrect_type_tuple.rs:7:36 | -4 | #[derive(Deserialize)] +5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `i8` | `match` arms have incompatible types -5 | #[serde(default = "main")] -6 | struct Tuple(u8, #[serde(default = "main")] i8); +6 | #[serde(default = "main")] +7 | struct Tuple(u8, #[serde(default = "main")] i8); | ^^^^^^ expected `i8`, found `()` error[E0308]: mismatched types - --> tests/ui/default-attribute/incorrect_type_tuple.rs:5:19 + --> tests/ui/default-attribute/incorrect_type_tuple.rs:6:19 | -5 | #[serde(default = "main")] +6 | #[serde(default = "main")] | ^^^^^^ expected `Tuple`, found `()` -6 | struct Tuple(u8, #[serde(default = "main")] i8); +7 | struct Tuple(u8, #[serde(default = "main")] i8); | ----- expected due to this error[E0308]: mismatched types - --> tests/ui/default-attribute/incorrect_type_tuple.rs:6:36 + --> tests/ui/default-attribute/incorrect_type_tuple.rs:7:36 | -4 | #[derive(Deserialize)] +5 | #[derive(Deserialize)] | ----------- expected due to the type of this binding -5 | #[serde(default = "main")] -6 | struct Tuple(u8, #[serde(default = "main")] i8); +6 | #[serde(default = "main")] +7 | struct Tuple(u8, #[serde(default = "main")] i8); | ^^^^^^ expected `i8`, found `()` From ab4f3f3111a08d5a55f122dc6ee2596cfd238a19 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 21 Oct 2024 21:03:12 -0700 Subject: [PATCH 207/258] Reduce scope of quote_spanned on SerializeWith wrapper --- serde_derive/src/dummy.rs | 7 +------ serde_derive/src/ser.rs | 10 ++++++---- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/serde_derive/src/dummy.rs b/serde_derive/src/dummy.rs index 7883090fc..095f950f3 100644 --- a/serde_derive/src/dummy.rs +++ b/serde_derive/src/dummy.rs @@ -14,12 +14,7 @@ pub fn wrap_in_const(serde_path: Option<&syn::Path>, code: TokenStream) -> Token quote! { #[doc(hidden)] - #[allow( - clippy::needless_lifetimes, - non_upper_case_globals, - unused_attributes, - unused_qualifications, - )] + #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] const _: () = { #use_serde #code diff --git a/serde_derive/src/ser.rs b/serde_derive/src/ser.rs index 725851212..191c0def9 100644 --- a/serde_derive/src/ser.rs +++ b/serde_derive/src/ser.rs @@ -1224,11 +1224,13 @@ fn wrap_serialize_with( // We attach span of the path to this piece so error will be reported // on the #[serde(with = "...")] // ^^^^^ - quote_spanned!(serialize_with.span()=> { + let wrapper_serialize = quote_spanned! {serialize_with.span()=> + #serialize_with(#(self.values.#field_access, )* __s) + }; + + quote!({ #[doc(hidden)] struct __SerializeWith #wrapper_impl_generics #where_clause { - // If #field_tys is empty, this field is unused - #[allow(dead_code)] values: (#(&'__a #field_tys, )*), phantom: _serde::__private::PhantomData<#this_type #ty_generics>, } @@ -1238,7 +1240,7 @@ fn wrap_serialize_with( where __S: _serde::Serializer, { - #serialize_with(#(self.values.#field_access, )* __s) + #wrapper_serialize } } From 3393ad6760a212585aefdc3e8a0cb7fd37e3a9a3 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 21 Oct 2024 22:47:42 -0700 Subject: [PATCH 208/258] Make most of prepare_enum_variant_enum independent of variant_names_idents item type --- serde_derive/src/de.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index f94097cd8..56c42caa3 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -1225,33 +1225,33 @@ fn deserialize_homogeneous_enum( } fn prepare_enum_variant_enum(variants: &[Variant]) -> (TokenStream, Stmts) { - let mut deserialized_variants = variants + let deserialized_variants = variants .iter() .enumerate() - .filter(|&(_, variant)| !variant.attrs.skip_deserializing()); - - let variant_names_idents: Vec<_> = deserialized_variants - .clone() - .map(|(i, variant)| (field_i(i), variant.attrs.aliases())) - .collect(); + .filter(|&(_i, variant)| !variant.attrs.skip_deserializing()); let fallthrough = deserialized_variants - .position(|(_, variant)| variant.attrs.other()) - .map(|other_idx| { - let ignore_variant = variant_names_idents[other_idx].0.clone(); + .clone() + .find(|(_i, variant)| variant.attrs.other()) + .map(|(i, _variant)| { + let ignore_variant = field_i(i); quote!(_serde::__private::Ok(__Field::#ignore_variant)) }); let variants_stmt = { - let variant_names = variant_names_idents - .iter() - .flat_map(|&(_, aliases)| aliases); + let variant_names = deserialized_variants + .clone() + .flat_map(|(_i, variant)| variant.attrs.aliases()); quote! { #[doc(hidden)] const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ]; } }; + let variant_names_idents: Vec<_> = deserialized_variants + .map(|(i, variant)| (field_i(i), variant.attrs.aliases())) + .collect(); + let variant_visitor = Stmts(deserialize_generated_identifier( &variant_names_idents, false, // variant identifiers do not depend on the presence of flatten fields From 0a06af8d216f066313f33855f44208accba2da06 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 21 Oct 2024 22:13:55 -0700 Subject: [PATCH 209/258] Rename field_names_idents -> field_idents_aliases --- serde_derive/src/de.rs | 56 ++++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index 56c42caa3..c4eebff86 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -966,7 +966,7 @@ fn deserialize_struct( }; let expecting = cattrs.expecting().unwrap_or(&expecting); - let field_names_idents: Vec<_> = fields + let field_idents_aliases: Vec<_> = fields .iter() .enumerate() // Skip fields that shouldn't be deserialized or that were flattened, @@ -976,7 +976,7 @@ fn deserialize_struct( .collect(); let has_flatten = has_flatten(fields); - let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs, has_flatten); + let field_visitor = deserialize_field_identifier(&field_idents_aliases, cattrs, has_flatten); // untagged struct variants do not get a visit_seq method. The same applies to // structs that only have a map representation. @@ -984,7 +984,7 @@ fn deserialize_struct( StructForm::Untagged(..) => None, _ if has_flatten => None, _ => { - let mut_seq = if field_names_idents.is_empty() { + let mut_seq = if field_idents_aliases.is_empty() { quote!(_) } else { quote!(mut __seq) @@ -1032,7 +1032,9 @@ fn deserialize_struct( let fields_stmt = if has_flatten { None } else { - let field_names = field_names_idents.iter().flat_map(|&(_, aliases)| aliases); + let field_names = field_idents_aliases + .iter() + .flat_map(|&(_, aliases)| aliases); Some(quote! { #[doc(hidden)] @@ -1125,23 +1127,25 @@ fn deserialize_struct_in_place( let expecting = format!("struct {}", params.type_name()); let expecting = cattrs.expecting().unwrap_or(&expecting); - let field_names_idents: Vec<_> = fields + let field_idents_aliases: Vec<_> = fields .iter() .enumerate() .filter(|&(_, field)| !field.attrs.skip_deserializing()) .map(|(i, field)| (field_i(i), field.attrs.aliases())) .collect(); - let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs, false); + let field_visitor = deserialize_field_identifier(&field_idents_aliases, cattrs, false); - let mut_seq = if field_names_idents.is_empty() { + let mut_seq = if field_idents_aliases.is_empty() { quote!(_) } else { quote!(mut __seq) }; let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting)); let visit_map = Stmts(deserialize_map_in_place(params, fields, cattrs)); - let field_names = field_names_idents.iter().flat_map(|&(_, aliases)| aliases); + let field_names = field_idents_aliases + .iter() + .flat_map(|&(_, aliases)| aliases); let type_name = cattrs.name().deserialize_name(); let in_place_impl_generics = de_impl_generics.in_place(); @@ -1991,18 +1995,21 @@ fn deserialize_untagged_newtype_variant( } fn deserialize_generated_identifier( - fields: &[(Ident, &BTreeSet)], + field_idents_aliases: &[(Ident, &BTreeSet)], has_flatten: bool, is_variant: bool, ignore_variant: Option, fallthrough: Option, ) -> Fragment { let this_value = quote!(__Field); - let field_idents: &Vec<_> = &fields.iter().map(|(ident, _)| ident).collect(); + let field_idents: &Vec<_> = &field_idents_aliases + .iter() + .map(|(ident, _)| ident) + .collect(); let visitor_impl = Stmts(deserialize_identifier( &this_value, - fields, + field_idents_aliases, is_variant, fallthrough, None, @@ -2048,7 +2055,7 @@ fn deserialize_generated_identifier( /// Generates enum and its `Deserialize` implementation that represents each /// non-skipped field of the struct fn deserialize_field_identifier( - fields: &[(Ident, &BTreeSet)], + field_idents_aliases: &[(Ident, &BTreeSet)], cattrs: &attr::Container, has_flatten: bool, ) -> Stmts { @@ -2065,7 +2072,7 @@ fn deserialize_field_identifier( }; Stmts(deserialize_generated_identifier( - fields, + field_idents_aliases, has_flatten, false, ignore_variant, @@ -2184,18 +2191,18 @@ fn deserialize_custom_identifier( fn deserialize_identifier( this_value: &TokenStream, - fields: &[(Ident, &BTreeSet)], + field_idents_aliases: &[(Ident, &BTreeSet)], is_variant: bool, fallthrough: Option, fallthrough_borrowed: Option, collect_other_fields: bool, expecting: Option<&str>, ) -> Fragment { - let str_mapping = fields.iter().map(|(ident, aliases)| { + let str_mapping = field_idents_aliases.iter().map(|(ident, aliases)| { // `aliases` also contains a main name quote!(#(#aliases)|* => _serde::__private::Ok(#this_value::#ident)) }); - let bytes_mapping = fields.iter().map(|(ident, aliases)| { + let bytes_mapping = field_idents_aliases.iter().map(|(ident, aliases)| { // `aliases` also contains a main name let aliases = aliases .iter() @@ -2350,17 +2357,24 @@ fn deserialize_identifier( } } } else { - let u64_mapping = fields.iter().enumerate().map(|(i, (ident, _))| { - let i = i as u64; - quote!(#i => _serde::__private::Ok(#this_value::#ident)) - }); + let u64_mapping = field_idents_aliases + .iter() + .enumerate() + .map(|(i, (ident, _))| { + let i = i as u64; + quote!(#i => _serde::__private::Ok(#this_value::#ident)) + }); let u64_fallthrough_arm_tokens; let u64_fallthrough_arm = if let Some(fallthrough) = &fallthrough { fallthrough } else { let index_expecting = if is_variant { "variant" } else { "field" }; - let fallthrough_msg = format!("{} index 0 <= i < {}", index_expecting, fields.len()); + let fallthrough_msg = format!( + "{} index 0 <= i < {}", + index_expecting, + field_idents_aliases.len(), + ); u64_fallthrough_arm_tokens = quote! { _serde::__private::Err(_serde::de::Error::invalid_value( _serde::de::Unexpected::Unsigned(__value), From c6a5be7f6ab350931a13166fbe63d91932705061 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 21 Oct 2024 22:48:52 -0700 Subject: [PATCH 210/258] Rename variant_names_idents -> variant_idents_aliases --- serde_derive/src/de.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index c4eebff86..bc55f165b 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -1252,12 +1252,12 @@ fn prepare_enum_variant_enum(variants: &[Variant]) -> (TokenStream, Stmts) { } }; - let variant_names_idents: Vec<_> = deserialized_variants + let variant_idents_aliases: Vec<_> = deserialized_variants .map(|(i, variant)| (field_i(i), variant.attrs.aliases())) .collect(); let variant_visitor = Stmts(deserialize_generated_identifier( - &variant_names_idents, + &variant_idents_aliases, false, // variant identifiers do not depend on the presence of flatten fields true, None, @@ -2130,12 +2130,12 @@ fn deserialize_custom_identifier( (variants, None, None) }; - let names_idents: Vec<_> = ordinary + let idents_aliases: Vec<_> = ordinary .iter() .map(|variant| (variant.ident.clone(), variant.attrs.aliases())) .collect(); - let names = names_idents.iter().flat_map(|&(_, aliases)| aliases); + let names = idents_aliases.iter().flat_map(|&(_, aliases)| aliases); let names_const = if fallthrough.is_some() { None @@ -2158,7 +2158,7 @@ fn deserialize_custom_identifier( let delife = params.borrowed.de_lifetime(); let visitor_impl = Stmts(deserialize_identifier( &this_value, - &names_idents, + &idents_aliases, is_variant, fallthrough, fallthrough_borrowed, From 09f6d9361d464d5ed92afc8f7a5107069f95beb0 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 21 Oct 2024 22:53:03 -0700 Subject: [PATCH 211/258] Collect field ident and aliases into a struct --- serde_derive/src/de.rs | 89 ++++++++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 37 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index bc55f165b..136da8e9f 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -966,17 +966,20 @@ fn deserialize_struct( }; let expecting = cattrs.expecting().unwrap_or(&expecting); - let field_idents_aliases: Vec<_> = fields + let deserialized_fields: Vec<_> = fields .iter() .enumerate() // Skip fields that shouldn't be deserialized or that were flattened, // so they don't appear in the storage in their literal form .filter(|&(_, field)| !field.attrs.skip_deserializing() && !field.attrs.flatten()) - .map(|(i, field)| (field_i(i), field.attrs.aliases())) + .map(|(i, field)| FieldWithAliases { + ident: field_i(i), + aliases: field.attrs.aliases(), + }) .collect(); let has_flatten = has_flatten(fields); - let field_visitor = deserialize_field_identifier(&field_idents_aliases, cattrs, has_flatten); + let field_visitor = deserialize_field_identifier(&deserialized_fields, cattrs, has_flatten); // untagged struct variants do not get a visit_seq method. The same applies to // structs that only have a map representation. @@ -984,7 +987,7 @@ fn deserialize_struct( StructForm::Untagged(..) => None, _ if has_flatten => None, _ => { - let mut_seq = if field_idents_aliases.is_empty() { + let mut_seq = if deserialized_fields.is_empty() { quote!(_) } else { quote!(mut __seq) @@ -1032,9 +1035,7 @@ fn deserialize_struct( let fields_stmt = if has_flatten { None } else { - let field_names = field_idents_aliases - .iter() - .flat_map(|&(_, aliases)| aliases); + let field_names = deserialized_fields.iter().flat_map(|field| field.aliases); Some(quote! { #[doc(hidden)] @@ -1127,25 +1128,26 @@ fn deserialize_struct_in_place( let expecting = format!("struct {}", params.type_name()); let expecting = cattrs.expecting().unwrap_or(&expecting); - let field_idents_aliases: Vec<_> = fields + let deserialized_fields: Vec<_> = fields .iter() .enumerate() .filter(|&(_, field)| !field.attrs.skip_deserializing()) - .map(|(i, field)| (field_i(i), field.attrs.aliases())) + .map(|(i, field)| FieldWithAliases { + ident: field_i(i), + aliases: field.attrs.aliases(), + }) .collect(); - let field_visitor = deserialize_field_identifier(&field_idents_aliases, cattrs, false); + let field_visitor = deserialize_field_identifier(&deserialized_fields, cattrs, false); - let mut_seq = if field_idents_aliases.is_empty() { + let mut_seq = if deserialized_fields.is_empty() { quote!(_) } else { quote!(mut __seq) }; let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting)); let visit_map = Stmts(deserialize_map_in_place(params, fields, cattrs)); - let field_names = field_idents_aliases - .iter() - .flat_map(|&(_, aliases)| aliases); + let field_names = deserialized_fields.iter().flat_map(|field| field.aliases); let type_name = cattrs.name().deserialize_name(); let in_place_impl_generics = de_impl_generics.in_place(); @@ -1252,12 +1254,15 @@ fn prepare_enum_variant_enum(variants: &[Variant]) -> (TokenStream, Stmts) { } }; - let variant_idents_aliases: Vec<_> = deserialized_variants - .map(|(i, variant)| (field_i(i), variant.attrs.aliases())) + let deserialized_variants: Vec<_> = deserialized_variants + .map(|(i, variant)| FieldWithAliases { + ident: field_i(i), + aliases: variant.attrs.aliases(), + }) .collect(); let variant_visitor = Stmts(deserialize_generated_identifier( - &variant_idents_aliases, + &deserialized_variants, false, // variant identifiers do not depend on the presence of flatten fields true, None, @@ -1994,22 +1999,27 @@ fn deserialize_untagged_newtype_variant( } } +struct FieldWithAliases<'a> { + ident: Ident, + aliases: &'a BTreeSet, +} + fn deserialize_generated_identifier( - field_idents_aliases: &[(Ident, &BTreeSet)], + deserialized_fields: &[FieldWithAliases], has_flatten: bool, is_variant: bool, ignore_variant: Option, fallthrough: Option, ) -> Fragment { let this_value = quote!(__Field); - let field_idents: &Vec<_> = &field_idents_aliases + let field_idents: &Vec<_> = &deserialized_fields .iter() - .map(|(ident, _)| ident) + .map(|field| &field.ident) .collect(); let visitor_impl = Stmts(deserialize_identifier( &this_value, - field_idents_aliases, + deserialized_fields, is_variant, fallthrough, None, @@ -2055,7 +2065,7 @@ fn deserialize_generated_identifier( /// Generates enum and its `Deserialize` implementation that represents each /// non-skipped field of the struct fn deserialize_field_identifier( - field_idents_aliases: &[(Ident, &BTreeSet)], + deserialized_fields: &[FieldWithAliases], cattrs: &attr::Container, has_flatten: bool, ) -> Stmts { @@ -2072,7 +2082,7 @@ fn deserialize_field_identifier( }; Stmts(deserialize_generated_identifier( - field_idents_aliases, + deserialized_fields, has_flatten, false, ignore_variant, @@ -2132,10 +2142,13 @@ fn deserialize_custom_identifier( let idents_aliases: Vec<_> = ordinary .iter() - .map(|variant| (variant.ident.clone(), variant.attrs.aliases())) + .map(|variant| FieldWithAliases { + ident: variant.ident.clone(), + aliases: variant.attrs.aliases(), + }) .collect(); - let names = idents_aliases.iter().flat_map(|&(_, aliases)| aliases); + let names = idents_aliases.iter().flat_map(|variant| variant.aliases); let names_const = if fallthrough.is_some() { None @@ -2191,20 +2204,24 @@ fn deserialize_custom_identifier( fn deserialize_identifier( this_value: &TokenStream, - field_idents_aliases: &[(Ident, &BTreeSet)], + deserialized_fields: &[FieldWithAliases], is_variant: bool, fallthrough: Option, fallthrough_borrowed: Option, collect_other_fields: bool, expecting: Option<&str>, ) -> Fragment { - let str_mapping = field_idents_aliases.iter().map(|(ident, aliases)| { + let str_mapping = deserialized_fields.iter().map(|field| { + let ident = &field.ident; + let aliases = field.aliases; // `aliases` also contains a main name quote!(#(#aliases)|* => _serde::__private::Ok(#this_value::#ident)) }); - let bytes_mapping = field_idents_aliases.iter().map(|(ident, aliases)| { + let bytes_mapping = deserialized_fields.iter().map(|field| { + let ident = &field.ident; // `aliases` also contains a main name - let aliases = aliases + let aliases = field + .aliases .iter() .map(|alias| Literal::byte_string(alias.as_bytes())); quote!(#(#aliases)|* => _serde::__private::Ok(#this_value::#ident)) @@ -2357,13 +2374,11 @@ fn deserialize_identifier( } } } else { - let u64_mapping = field_idents_aliases - .iter() - .enumerate() - .map(|(i, (ident, _))| { - let i = i as u64; - quote!(#i => _serde::__private::Ok(#this_value::#ident)) - }); + let u64_mapping = deserialized_fields.iter().enumerate().map(|(i, field)| { + let i = i as u64; + let ident = &field.ident; + quote!(#i => _serde::__private::Ok(#this_value::#ident)) + }); let u64_fallthrough_arm_tokens; let u64_fallthrough_arm = if let Some(fallthrough) = &fallthrough { @@ -2373,7 +2388,7 @@ fn deserialize_identifier( let fallthrough_msg = format!( "{} index 0 <= i < {}", index_expecting, - field_idents_aliases.len(), + deserialized_fields.len(), ); u64_fallthrough_arm_tokens = quote! { _serde::__private::Err(_serde::de::Error::invalid_value( From 1b8310d98abf7366cad421e1ece94a42e43744b1 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 21 Oct 2024 23:27:57 -0700 Subject: [PATCH 212/258] Release 1.0.211 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index b6ad57682..eb73dc163 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.210" +version = "1.0.211" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.210", path = "../serde_derive" } +serde_derive = { version = "=1.0.211", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 59929e0ba..86d2ce5a2 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.210")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.211")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 6bb1e3157..c6da55d07 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.210" +version = "1.0.211" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index 15a10cd2f..adb841977 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.210")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.211")] #![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] // Ignored clippy lints #![allow( From 29d4f3e88799b10ecfff80e743049e0f58dde56e Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 22 Oct 2024 09:28:03 -0700 Subject: [PATCH 213/258] Format regression tests with rustfmt --- test_suite/tests/regression/issue2565.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/test_suite/tests/regression/issue2565.rs b/test_suite/tests/regression/issue2565.rs index 65cbb0a31..f13cacf04 100644 --- a/test_suite/tests/regression/issue2565.rs +++ b/test_suite/tests/regression/issue2565.rs @@ -1,4 +1,4 @@ -use serde_derive::{Serialize, Deserialize}; +use serde_derive::{Deserialize, Serialize}; use serde_test::{assert_tokens, Token}; #[derive(Serialize, Deserialize, Debug, PartialEq)] @@ -18,11 +18,15 @@ fn simple_variant() { assert_tokens( &Enum::Simple { a: 42 }, &[ - Token::StructVariant { name: "Enum", variant: "Simple", len: 1 }, + Token::StructVariant { + name: "Enum", + variant: "Simple", + len: 1, + }, Token::Str("a"), Token::I32(42), Token::StructVariantEnd, - ] + ], ); } @@ -31,11 +35,14 @@ fn flatten_variant() { assert_tokens( &Enum::Flatten { flatten: (), a: 42 }, &[ - Token::NewtypeVariant { name: "Enum", variant: "Flatten" }, + Token::NewtypeVariant { + name: "Enum", + variant: "Flatten", + }, Token::Map { len: None }, Token::Str("a"), Token::I32(42), Token::MapEnd, - ] + ], ); } From 0058c7226e72e653d9e22c0879403ff6df195ec6 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 22 Oct 2024 09:27:40 -0700 Subject: [PATCH 214/258] Add regression test for issue 2844 error[E0424]: expected value, found module `self` --> test_suite/tests/regression/issue2844.rs:13:19 | 5 | #[derive(Serialize, Deserialize)] | --------- this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters ... 13 | declare_in_macro!("with"); | ^^^^^^ `self` value is a keyword only available in methods with a `self` parameter error[E0425]: cannot find value `__s` in this scope --> test_suite/tests/regression/issue2844.rs:13:19 | 13 | declare_in_macro!("with"); | ^^^^^^ not found in this scope error[E0425]: cannot find value `__deserializer` in this scope --> test_suite/tests/regression/issue2844.rs:13:19 | 13 | declare_in_macro!("with"); | ^^^^^^ not found in this scope --- test_suite/tests/regression/issue2844.rs | 31 ++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 test_suite/tests/regression/issue2844.rs diff --git a/test_suite/tests/regression/issue2844.rs b/test_suite/tests/regression/issue2844.rs new file mode 100644 index 000000000..492718c8b --- /dev/null +++ b/test_suite/tests/regression/issue2844.rs @@ -0,0 +1,31 @@ +use serde_derive::{Deserialize, Serialize}; + +macro_rules! declare_in_macro { + ($with:literal) => { + #[derive(Serialize, Deserialize)] + pub struct S { + #[serde(with = $with)] + f: i32, + } + }; +} + +declare_in_macro!("with"); + +mod with { + use serde::{Deserializer, Serializer}; + + pub fn serialize(_: &i32, _: S) -> Result + where + S: Serializer, + { + unimplemented!() + } + + pub fn deserialize<'de, D>(_: D) -> Result + where + D: Deserializer<'de>, + { + unimplemented!() + } +} From 1e36ef551dae96d1f93e9f23de78dbfc514aed07 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 22 Oct 2024 09:35:52 -0700 Subject: [PATCH 215/258] Fix hygiene of macro-generated local variable accesses in serde(with) wrappers --- serde_derive/src/de.rs | 5 +++-- serde_derive/src/ser.rs | 7 +++++-- test_suite/tests/ui/with/incorrect_type.stderr | 8 ++++++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index 136da8e9f..a50010ca3 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -2882,13 +2882,14 @@ fn wrap_deserialize_with( let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let delife = params.borrowed.de_lifetime(); + let deserializer_var = quote!(__deserializer); // If #deserialize_with returns wrong type, error will be reported here (^^^^^). // We attach span of the path to the function so it will be reported // on the #[serde(with = "...")] // ^^^^^ let value = quote_spanned! {deserialize_with.span()=> - #deserialize_with(__deserializer)? + #deserialize_with(#deserializer_var)? }; let wrapper = quote! { #[doc(hidden)] @@ -2899,7 +2900,7 @@ fn wrap_deserialize_with( } impl #de_impl_generics _serde::Deserialize<#delife> for __DeserializeWith #de_ty_generics #where_clause { - fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result + fn deserialize<__D>(#deserializer_var: __D) -> _serde::__private::Result where __D: _serde::Deserializer<#delife>, { diff --git a/serde_derive/src/ser.rs b/serde_derive/src/ser.rs index 191c0def9..47384f16f 100644 --- a/serde_derive/src/ser.rs +++ b/serde_derive/src/ser.rs @@ -1220,12 +1220,15 @@ fn wrap_serialize_with( }) }); + let self_var = quote!(self); + let serializer_var = quote!(__s); + // If #serialize_with returns wrong type, error will be reported on here. // We attach span of the path to this piece so error will be reported // on the #[serde(with = "...")] // ^^^^^ let wrapper_serialize = quote_spanned! {serialize_with.span()=> - #serialize_with(#(self.values.#field_access, )* __s) + #serialize_with(#(#self_var.values.#field_access, )* #serializer_var) }; quote!({ @@ -1236,7 +1239,7 @@ fn wrap_serialize_with( } impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause { - fn serialize<__S>(&self, __s: __S) -> _serde::__private::Result<__S::Ok, __S::Error> + fn serialize<__S>(&#self_var, #serializer_var: __S) -> _serde::__private::Result<__S::Ok, __S::Error> where __S: _serde::Serializer, { diff --git a/test_suite/tests/ui/with/incorrect_type.stderr b/test_suite/tests/ui/with/incorrect_type.stderr index d974fa4a1..cfddf1cec 100644 --- a/test_suite/tests/ui/with/incorrect_type.stderr +++ b/test_suite/tests/ui/with/incorrect_type.stderr @@ -19,8 +19,10 @@ note: required by a bound in `w::serialize` error[E0061]: this function takes 1 argument but 2 arguments were supplied --> tests/ui/with/incorrect_type.rs:15:25 | +14 | #[derive(Serialize, Deserialize)] + | --------- unexpected argument #2 of type `__S` 15 | struct W(#[serde(with = "w")] u8, u8); - | ^^^ unexpected argument #2 of type `__S` + | ^^^ | note: function defined here --> tests/ui/with/incorrect_type.rs:9:12 @@ -68,8 +70,10 @@ note: required by a bound in `w::serialize` error[E0061]: this function takes 1 argument but 2 arguments were supplied --> tests/ui/with/incorrect_type.rs:18:35 | +17 | #[derive(Serialize, Deserialize)] + | --------- unexpected argument #2 of type `__S` 18 | struct S(#[serde(serialize_with = "w::serialize")] u8, u8); - | ^^^^^^^^^^^^^^ unexpected argument #2 of type `__S` + | ^^^^^^^^^^^^^^ | note: function defined here --> tests/ui/with/incorrect_type.rs:9:12 From 7ae1b5f8f39d7a80daaddcc04565f995427bfc41 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 22 Oct 2024 09:41:55 -0700 Subject: [PATCH 216/258] Release 1.0.212 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index eb73dc163..4b5f53cec 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.211" +version = "1.0.212" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.211", path = "../serde_derive" } +serde_derive = { version = "=1.0.212", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 86d2ce5a2..2a5131ebc 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.211")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.212")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index c6da55d07..7875cb2cd 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.211" +version = "1.0.212" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index adb841977..bf2245d74 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.211")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.212")] #![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] // Ignored clippy lints #![allow( From 49e11ce1bae9fbb9128c9144c4e1051daf7a29ed Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 22 Oct 2024 09:56:07 -0700 Subject: [PATCH 217/258] Ignore trivially_copy_pass_by_ref pedantic clippy lint in test warning: this argument (4 byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte) --> test_suite/tests/regression/issue2844.rs:18:28 | 18 | pub fn serialize(_: &i32, _: S) -> Result | ^^^^ help: consider passing by value instead: `i32` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref = note: `-W clippy::trivially-copy-pass-by-ref` implied by `-W clippy::pedantic` = help: to override `-W clippy::pedantic` add `#[allow(clippy::trivially_copy_pass_by_ref)]` --- test_suite/tests/regression/issue2844.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test_suite/tests/regression/issue2844.rs b/test_suite/tests/regression/issue2844.rs index 492718c8b..3ad2012b9 100644 --- a/test_suite/tests/regression/issue2844.rs +++ b/test_suite/tests/regression/issue2844.rs @@ -1,3 +1,5 @@ +#![allow(clippy::trivially_copy_pass_by_ref)] + use serde_derive::{Deserialize, Serialize}; macro_rules! declare_in_macro { From fdc36e5c06def28b33d3154f0517969d90b744d8 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 22 Oct 2024 11:08:17 -0700 Subject: [PATCH 218/258] Add regression test for issue 2846 error[E0425]: cannot find value `__e` in this scope --> test_suite/tests/regression/issue2846.rs:12:19 | 12 | declare_in_macro!("with"); | ^^^^^^ not found in this scope --- test_suite/tests/regression/issue2846.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 test_suite/tests/regression/issue2846.rs diff --git a/test_suite/tests/regression/issue2846.rs b/test_suite/tests/regression/issue2846.rs new file mode 100644 index 000000000..c4a91330c --- /dev/null +++ b/test_suite/tests/regression/issue2846.rs @@ -0,0 +1,23 @@ +#![allow(clippy::trivially_copy_pass_by_ref)] + +use serde_derive::Deserialize; + +macro_rules! declare_in_macro { + ($with:literal) => { + #[derive(Deserialize)] + pub struct S(#[serde(with = $with)] i32); + }; +} + +declare_in_macro!("with"); + +mod with { + use serde::Deserializer; + + pub fn deserialize<'de, D>(_: D) -> Result + where + D: Deserializer<'de>, + { + unimplemented!() + } +} From b60e4092ec83c70e8c7d39574778349b2c5d9f05 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 22 Oct 2024 11:10:40 -0700 Subject: [PATCH 219/258] Hygiene for macro-generated newtype struct deserialization with 'with' attr --- serde_derive/src/de.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index a50010ca3..518f84320 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -875,13 +875,14 @@ fn deserialize_newtype_struct( ) -> TokenStream { let delife = params.borrowed.de_lifetime(); let field_ty = field.ty; + let deserializer_var = quote!(__e); let value = match field.attrs.deserialize_with() { None => { let span = field.original.span(); let func = quote_spanned!(span=> <#field_ty as _serde::Deserialize>::deserialize); quote! { - #func(__e)? + #func(#deserializer_var)? } } Some(path) => { @@ -890,7 +891,7 @@ fn deserialize_newtype_struct( // on the #[serde(with = "...")] // ^^^^^ quote_spanned! {path.span()=> - #path(__e)? + #path(#deserializer_var)? } } }; @@ -906,7 +907,7 @@ fn deserialize_newtype_struct( quote! { #[inline] - fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::__private::Result + fn visit_newtype_struct<__E>(self, #deserializer_var: __E) -> _serde::__private::Result where __E: _serde::Deserializer<#delife>, { From 79925ac3947483013ba8136e43bc0449b99bd10c Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 22 Oct 2024 11:10:51 -0700 Subject: [PATCH 220/258] Ignore dead_code warning in regression test warning: field `0` is never read --> test_suite/tests/regression/issue2846.rs:8:45 | 8 | pub struct S(#[serde(with = $with)] i32); | - field in this struct ^^^ ... 12 | declare_in_macro!("with"); | ------------------------- in this macro invocation | = help: consider removing this field = note: `#[warn(dead_code)]` on by default = note: this warning originates in the macro `declare_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) --- test_suite/tests/regression/issue2846.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test_suite/tests/regression/issue2846.rs b/test_suite/tests/regression/issue2846.rs index c4a91330c..c5258a5b3 100644 --- a/test_suite/tests/regression/issue2846.rs +++ b/test_suite/tests/regression/issue2846.rs @@ -5,7 +5,11 @@ use serde_derive::Deserialize; macro_rules! declare_in_macro { ($with:literal) => { #[derive(Deserialize)] - pub struct S(#[serde(with = $with)] i32); + pub struct S( + #[serde(with = $with)] + #[allow(dead_code)] + i32, + ); }; } From 58a8d229315553c4ae0a8d7eee8e382fbae4b4bf Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 22 Oct 2024 11:14:58 -0700 Subject: [PATCH 221/258] Release 1.0.213 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 4b5f53cec..b2d6bd4c8 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.212" +version = "1.0.213" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.212", path = "../serde_derive" } +serde_derive = { version = "=1.0.213", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 2a5131ebc..5b1f72763 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.212")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.213")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 7875cb2cd..27ac1d7d9 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.212" +version = "1.0.213" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index bf2245d74..3c9b2f763 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.212")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.213")] #![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] // Ignored clippy lints #![allow( From 9cda0157331ca09dec16cd8a0b57bd8eb24f8442 Mon Sep 17 00:00:00 2001 From: Mingun Date: Fri, 11 Aug 2023 18:38:05 +0500 Subject: [PATCH 222/258] Implement IntoDeserializer for all Deserializers in serde::de::value module Unfortunately, blanket implementation IntoDeserializer for Deserializer is impossible right now because this would be a breaking change. External crates may have this such implementation (and serde_json actually have it for Value) --- serde/src/de/value.rs | 174 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) diff --git a/serde/src/de/value.rs b/serde/src/de/value.rs index 1ec947786..8f9c0b48e 100644 --- a/serde/src/de/value.rs +++ b/serde/src/de/value.rs @@ -175,6 +175,17 @@ where } } +impl<'de, E> IntoDeserializer<'de, E> for UnitDeserializer +where + E: de::Error, +{ + type Deserializer = Self; + + fn into_deserializer(self) -> Self { + self + } +} + impl Debug for UnitDeserializer { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.debug_struct("UnitDeserializer").finish() @@ -225,6 +236,18 @@ where } } +#[cfg(feature = "unstable")] +impl<'de, E> IntoDeserializer<'de, E> for NeverDeserializer +where + E: de::Error, +{ + type Deserializer = Self; + + fn into_deserializer(self) -> Self { + self + } +} + //////////////////////////////////////////////////////////////////////////////// macro_rules! primitive_deserializer { @@ -279,6 +302,17 @@ macro_rules! primitive_deserializer { } } + impl<'de, E> IntoDeserializer<'de, E> for $name + where + E: de::Error, + { + type Deserializer = Self; + + fn into_deserializer(self) -> Self { + self + } + } + impl Debug for $name { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter @@ -369,6 +403,17 @@ where } } +impl<'de, E> IntoDeserializer<'de, E> for U32Deserializer +where + E: de::Error, +{ + type Deserializer = Self; + + fn into_deserializer(self) -> Self { + self + } +} + impl<'de, E> de::EnumAccess<'de> for U32Deserializer where E: de::Error, @@ -458,6 +503,17 @@ where } } +impl<'de, 'a, E> IntoDeserializer<'de, E> for StrDeserializer<'a, E> +where + E: de::Error, +{ + type Deserializer = Self; + + fn into_deserializer(self) -> Self { + self + } +} + impl<'de, 'a, E> de::EnumAccess<'de> for StrDeserializer<'a, E> where E: de::Error, @@ -537,6 +593,17 @@ where } } +impl<'de, E> IntoDeserializer<'de, E> for BorrowedStrDeserializer<'de, E> +where + E: de::Error, +{ + type Deserializer = Self; + + fn into_deserializer(self) -> Self { + self + } +} + impl<'de, E> de::EnumAccess<'de> for BorrowedStrDeserializer<'de, E> where E: de::Error, @@ -640,6 +707,18 @@ where } } +#[cfg(any(feature = "std", feature = "alloc"))] +impl<'de, E> IntoDeserializer<'de, E> for StringDeserializer +where + E: de::Error, +{ + type Deserializer = Self; + + fn into_deserializer(self) -> Self { + self + } +} + #[cfg(any(feature = "std", feature = "alloc"))] impl<'de, E> de::EnumAccess<'de> for StringDeserializer where @@ -748,6 +827,18 @@ where } } +#[cfg(any(feature = "std", feature = "alloc"))] +impl<'de, 'a, E> IntoDeserializer<'de, E> for CowStrDeserializer<'a, E> +where + E: de::Error, +{ + type Deserializer = Self; + + fn into_deserializer(self) -> Self { + self + } +} + #[cfg(any(feature = "std", feature = "alloc"))] impl<'de, 'a, E> de::EnumAccess<'de> for CowStrDeserializer<'a, E> where @@ -825,6 +916,17 @@ where } } +impl<'de, 'a, E> IntoDeserializer<'de, E> for BytesDeserializer<'a, E> +where + E: de::Error, +{ + type Deserializer = Self; + + fn into_deserializer(self) -> Self { + self + } +} + impl<'a, E> Debug for BytesDeserializer<'a, E> { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter @@ -873,6 +975,17 @@ where } } +impl<'de, E> IntoDeserializer<'de, E> for BorrowedBytesDeserializer<'de, E> +where + E: de::Error, +{ + type Deserializer = Self; + + fn into_deserializer(self) -> Self { + self + } +} + impl<'de, E> Debug for BorrowedBytesDeserializer<'de, E> { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter @@ -952,6 +1065,19 @@ where } } +impl<'de, I, T, E> IntoDeserializer<'de, E> for SeqDeserializer +where + I: Iterator, + T: IntoDeserializer<'de, E>, + E: de::Error, +{ + type Deserializer = Self; + + fn into_deserializer(self) -> Self { + self + } +} + impl<'de, I, T, E> de::SeqAccess<'de> for SeqDeserializer where I: Iterator, @@ -1083,6 +1209,17 @@ where } } +impl<'de, A> IntoDeserializer<'de, A::Error> for SeqAccessDeserializer +where + A: de::SeqAccess<'de>, +{ + type Deserializer = Self; + + fn into_deserializer(self) -> Self { + self + } +} + //////////////////////////////////////////////////////////////////////////////// /// A deserializer that iterates over a map. @@ -1197,6 +1334,21 @@ where } } +impl<'de, I, E> IntoDeserializer<'de, E> for MapDeserializer<'de, I, E> +where + I: Iterator, + I::Item: private::Pair, + First: IntoDeserializer<'de, E>, + Second: IntoDeserializer<'de, E>, + E: de::Error, +{ + type Deserializer = Self; + + fn into_deserializer(self) -> Self { + self + } +} + impl<'de, I, E> de::MapAccess<'de> for MapDeserializer<'de, I, E> where I: Iterator, @@ -1498,6 +1650,17 @@ where } } +impl<'de, A> IntoDeserializer<'de, A::Error> for MapAccessDeserializer +where + A: de::MapAccess<'de>, +{ + type Deserializer = Self; + + fn into_deserializer(self) -> Self { + self + } +} + impl<'de, A> de::EnumAccess<'de> for MapAccessDeserializer where A: de::MapAccess<'de>, @@ -1551,6 +1714,17 @@ where } } +impl<'de, A> IntoDeserializer<'de, A::Error> for EnumAccessDeserializer +where + A: de::EnumAccess<'de>, +{ + type Deserializer = Self; + + fn into_deserializer(self) -> Self { + self + } +} + //////////////////////////////////////////////////////////////////////////////// mod private { From 5f9fffa53e8a48d9e1f32b1735542207c42f3ead Mon Sep 17 00:00:00 2001 From: Mingun Date: Tue, 8 Aug 2023 22:07:22 +0500 Subject: [PATCH 223/258] Add checks for conflicts for aliases - Check that alias is not the same as name of other field (it still can be the name of owning field/variant) - Check that aliases are unique, i. e. two different fields does not use the same alias --- serde_derive/src/internals/check.rs | 136 +++++++++++++++++- test_suite/tests/ui/conflict/alias-enum.rs | 79 ++++++++++ .../tests/ui/conflict/alias-enum.stderr | 71 +++++++++ test_suite/tests/ui/conflict/alias.rs | 40 ++++++ test_suite/tests/ui/conflict/alias.stderr | 35 +++++ 5 files changed, 360 insertions(+), 1 deletion(-) create mode 100644 test_suite/tests/ui/conflict/alias-enum.rs create mode 100644 test_suite/tests/ui/conflict/alias-enum.stderr create mode 100644 test_suite/tests/ui/conflict/alias.rs create mode 100644 test_suite/tests/ui/conflict/alias.stderr diff --git a/serde_derive/src/internals/check.rs b/serde_derive/src/internals/check.rs index 52b0f379f..df5d63f01 100644 --- a/serde_derive/src/internals/check.rs +++ b/serde_derive/src/internals/check.rs @@ -1,6 +1,8 @@ -use crate::internals::ast::{Container, Data, Field, Style}; +use crate::internals::ast::{Container, Data, Field, Style, Variant}; use crate::internals::attr::{Default, Identifier, TagType}; use crate::internals::{ungroup, Ctxt, Derive}; +use std::collections::btree_map::Entry; +use std::collections::{BTreeMap, BTreeSet}; use syn::{Member, Type}; // Cross-cutting checks that require looking at more than a single attrs object. @@ -16,6 +18,7 @@ pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) { check_adjacent_tag_conflict(cx, cont); check_transparent(cx, cont, derive); check_from_and_try_from(cx, cont); + check_name_conflicts(cx, cont, derive); } // If some field of a tuple struct is marked #[serde(default)] then all fields @@ -475,3 +478,134 @@ fn check_from_and_try_from(cx: &Ctxt, cont: &mut Container) { ); } } + +// Checks that aliases does not repeated +fn check_name_conflicts(cx: &Ctxt, cont: &Container, derive: Derive) { + if let Derive::Deserialize = derive { + match &cont.data { + Data::Enum(variants) => check_variant_name_conflicts(cx, &variants), + Data::Struct(Style::Struct, fields) => check_field_name_conflicts(cx, fields), + _ => {} + } + } +} + +// All renames already applied +fn check_variant_name_conflicts(cx: &Ctxt, variants: &[Variant]) { + let names: BTreeSet<_> = variants + .iter() + .filter_map(|variant| { + if variant.attrs.skip_deserializing() { + None + } else { + Some(variant.attrs.name().deserialize_name().to_owned()) + } + }) + .collect(); + let mut alias_owners = BTreeMap::new(); + + for variant in variants { + let name = variant.attrs.name().deserialize_name(); + + for alias in variant.attrs.aliases().intersection(&names) { + // Aliases contains variant names, so filter them out + if alias == name { + continue; + } + + // TODO: report other variant location when this become possible + cx.error_spanned_by( + variant.original, + format!( + "alias `{}` conflicts with deserialization name of other variant", + alias + ), + ); + } + + for alias in variant.attrs.aliases() { + // Aliases contains variant names, so filter them out + if alias == name { + continue; + } + + match alias_owners.entry(alias) { + Entry::Vacant(e) => { + e.insert(variant); + } + Entry::Occupied(e) => { + // TODO: report other variant location when this become possible + cx.error_spanned_by( + variant.original, + format!( + "alias `{}` already used by variant {}", + alias, + e.get().original.ident + ), + ); + } + } + } + + check_field_name_conflicts(cx, &variant.fields); + } +} + +// All renames already applied +fn check_field_name_conflicts(cx: &Ctxt, fields: &[Field]) { + let names: BTreeSet<_> = fields + .iter() + .filter_map(|field| { + if field.attrs.skip_deserializing() { + None + } else { + Some(field.attrs.name().deserialize_name().to_owned()) + } + }) + .collect(); + let mut alias_owners = BTreeMap::new(); + + for field in fields { + let name = field.attrs.name().deserialize_name(); + + for alias in field.attrs.aliases().intersection(&names) { + // Aliases contains field names, so filter them out + if alias == name { + continue; + } + + // TODO: report other field location when this become possible + cx.error_spanned_by( + field.original, + format!( + "alias `{}` conflicts with deserialization name of other field", + alias + ), + ); + } + + for alias in field.attrs.aliases() { + // Aliases contains field names, so filter them out + if alias == name { + continue; + } + + match alias_owners.entry(alias) { + Entry::Vacant(e) => { + e.insert(field); + } + Entry::Occupied(e) => { + // TODO: report other field location when this become possible + cx.error_spanned_by( + field.original, + format!( + "alias `{}` already used by field {}", + alias, + e.get().original.ident.as_ref().unwrap() + ), + ); + } + } + } + } +} diff --git a/test_suite/tests/ui/conflict/alias-enum.rs b/test_suite/tests/ui/conflict/alias-enum.rs new file mode 100644 index 000000000..52af74b97 --- /dev/null +++ b/test_suite/tests/ui/conflict/alias-enum.rs @@ -0,0 +1,79 @@ +#![allow(non_camel_case_types)] + +use serde_derive::Deserialize; + +#[derive(Deserialize)] +enum E { + S1 { + /// Expected error on "alias b", because this is a name of other field + /// Error on "alias a" is not expected because this is a name of this field + /// Error on "alias c" is not expected because field `c` is skipped + #[serde(alias = "a", alias = "b", alias = "c")] + a: (), + + /// Expected error on "alias c", because it is already used as alias of `a` + #[serde(alias = "c")] + b: (), + + #[serde(skip_deserializing)] + c: (), + }, + + S2 { + /// Expected error on "alias c", because this is a name of other field after + /// applying rename rules + #[serde(alias = "b", alias = "c")] + a: (), + + #[serde(rename = "c")] + b: (), + }, + + #[serde(rename_all = "UPPERCASE")] + S3 { + /// Expected error on "alias B", because this is a name of field after + /// applying rename rules + #[serde(alias = "B", alias = "c")] + a: (), + b: (), + }, +} + +#[derive(Deserialize)] +enum E1 { + /// Expected error on "alias b", because this is a name of other variant + /// Error on "alias a" is not expected because this is a name of this variant + /// Error on "alias c" is not expected because variant `c` is skipped + #[serde(alias = "a", alias = "b", alias = "c")] + a, + + /// Expected error on "alias c", because it is already used as alias of `a` + #[serde(alias = "c")] + b, + + #[serde(skip_deserializing)] + c, +} + +#[derive(Deserialize)] +enum E2 { + /// Expected error on "alias c", because this is a name of other variant after + /// applying rename rules + #[serde(alias = "b", alias = "c")] + a, + + #[serde(rename = "c")] + b, +} + +#[derive(Deserialize)] +#[serde(rename_all = "UPPERCASE")] +enum E3 { + /// Expected error on "alias B", because this is a name of variant after + /// applying rename rules + #[serde(alias = "B", alias = "c")] + a, + b, +} + +fn main() {} diff --git a/test_suite/tests/ui/conflict/alias-enum.stderr b/test_suite/tests/ui/conflict/alias-enum.stderr new file mode 100644 index 000000000..36e036f65 --- /dev/null +++ b/test_suite/tests/ui/conflict/alias-enum.stderr @@ -0,0 +1,71 @@ +error: alias `b` conflicts with deserialization name of other field + --> tests/ui/conflict/alias-enum.rs:8:9 + | +8 | / /// Expected error on "alias b", because this is a name of other field +9 | | /// Error on "alias a" is not expected because this is a name of this field +10 | | /// Error on "alias c" is not expected because field `c` is skipped +11 | | #[serde(alias = "a", alias = "b", alias = "c")] +12 | | a: (), + | |_____________^ + +error: alias `c` already used by field a + --> tests/ui/conflict/alias-enum.rs:14:9 + | +14 | / /// Expected error on "alias c", because it is already used as alias of `a` +15 | | #[serde(alias = "c")] +16 | | b: (), + | |_____________^ + +error: alias `c` conflicts with deserialization name of other field + --> tests/ui/conflict/alias-enum.rs:23:9 + | +23 | / /// Expected error on "alias c", because this is a name of other field after +24 | | /// applying rename rules +25 | | #[serde(alias = "b", alias = "c")] +26 | | a: (), + | |_____________^ + +error: alias `B` conflicts with deserialization name of other field + --> tests/ui/conflict/alias-enum.rs:34:9 + | +34 | / /// Expected error on "alias B", because this is a name of field after +35 | | /// applying rename rules +36 | | #[serde(alias = "B", alias = "c")] +37 | | a: (), + | |_____________^ + +error: alias `b` conflicts with deserialization name of other variant + --> tests/ui/conflict/alias-enum.rs:44:5 + | +44 | / /// Expected error on "alias b", because this is a name of other variant +45 | | /// Error on "alias a" is not expected because this is a name of this variant +46 | | /// Error on "alias c" is not expected because variant `c` is skipped +47 | | #[serde(alias = "a", alias = "b", alias = "c")] +48 | | a, + | |_____^ + +error: alias `c` already used by variant a + --> tests/ui/conflict/alias-enum.rs:50:5 + | +50 | / /// Expected error on "alias c", because it is already used as alias of `a` +51 | | #[serde(alias = "c")] +52 | | b, + | |_____^ + +error: alias `c` conflicts with deserialization name of other variant + --> tests/ui/conflict/alias-enum.rs:60:5 + | +60 | / /// Expected error on "alias c", because this is a name of other variant after +61 | | /// applying rename rules +62 | | #[serde(alias = "b", alias = "c")] +63 | | a, + | |_____^ + +error: alias `B` conflicts with deserialization name of other variant + --> tests/ui/conflict/alias-enum.rs:72:5 + | +72 | / /// Expected error on "alias B", because this is a name of variant after +73 | | /// applying rename rules +74 | | #[serde(alias = "B", alias = "c")] +75 | | a, + | |_____^ diff --git a/test_suite/tests/ui/conflict/alias.rs b/test_suite/tests/ui/conflict/alias.rs new file mode 100644 index 000000000..f52a90586 --- /dev/null +++ b/test_suite/tests/ui/conflict/alias.rs @@ -0,0 +1,40 @@ +use serde_derive::Deserialize; + +#[derive(Deserialize)] +struct S1 { + /// Expected error on "alias b", because this is a name of other field + /// Error on "alias a" is not expected because this is a name of this field + /// Error on "alias c" is not expected because field `c` is skipped + #[serde(alias = "a", alias = "b", alias = "c")] + a: (), + + /// Expected error on "alias c", because it is already used as alias of `a` + #[serde(alias = "c")] + b: (), + + #[serde(skip_deserializing)] + c: (), +} + +#[derive(Deserialize)] +struct S2 { + /// Expected error on "alias c", because this is a name of other field after + /// applying rename rules + #[serde(alias = "b", alias = "c")] + a: (), + + #[serde(rename = "c")] + b: (), +} + +#[derive(Deserialize)] +#[serde(rename_all = "UPPERCASE")] +struct S3 { + /// Expected error on "alias B", because this is a name of field after + /// applying rename rules + #[serde(alias = "B", alias = "c")] + a: (), + b: (), +} + +fn main() {} diff --git a/test_suite/tests/ui/conflict/alias.stderr b/test_suite/tests/ui/conflict/alias.stderr new file mode 100644 index 000000000..2115b21b1 --- /dev/null +++ b/test_suite/tests/ui/conflict/alias.stderr @@ -0,0 +1,35 @@ +error: alias `b` conflicts with deserialization name of other field + --> tests/ui/conflict/alias.rs:5:5 + | +5 | / /// Expected error on "alias b", because this is a name of other field +6 | | /// Error on "alias a" is not expected because this is a name of this field +7 | | /// Error on "alias c" is not expected because field `c` is skipped +8 | | #[serde(alias = "a", alias = "b", alias = "c")] +9 | | a: (), + | |_________^ + +error: alias `c` already used by field a + --> tests/ui/conflict/alias.rs:11:5 + | +11 | / /// Expected error on "alias c", because it is already used as alias of `a` +12 | | #[serde(alias = "c")] +13 | | b: (), + | |_________^ + +error: alias `c` conflicts with deserialization name of other field + --> tests/ui/conflict/alias.rs:21:5 + | +21 | / /// Expected error on "alias c", because this is a name of other field after +22 | | /// applying rename rules +23 | | #[serde(alias = "b", alias = "c")] +24 | | a: (), + | |_________^ + +error: alias `B` conflicts with deserialization name of other field + --> tests/ui/conflict/alias.rs:33:5 + | +33 | / /// Expected error on "alias B", because this is a name of field after +34 | | /// applying rename rules +35 | | #[serde(alias = "B", alias = "c")] +36 | | a: (), + | |_________^ From 418062165f9fe395461db9f61569c3142c584854 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 28 Oct 2024 09:41:44 -0700 Subject: [PATCH 224/258] Release 1.0.214 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index b2d6bd4c8..13cdede23 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.213" +version = "1.0.214" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.213", path = "../serde_derive" } +serde_derive = { version = "=1.0.214", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 5b1f72763..afc1cb5a7 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.213")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.214")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 27ac1d7d9..c1541961a 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.213" +version = "1.0.214" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index 3c9b2f763..a980601bf 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.213")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.214")] #![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] // Ignored clippy lints #![allow( From 951ca5ace0ca0abf9b44e0d6c76005fbd3b77c5c Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 1 Nov 2024 15:20:51 +0100 Subject: [PATCH 225/258] pacify clippy --- serde_derive/src/internals/check.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serde_derive/src/internals/check.rs b/serde_derive/src/internals/check.rs index df5d63f01..9594b35a5 100644 --- a/serde_derive/src/internals/check.rs +++ b/serde_derive/src/internals/check.rs @@ -483,7 +483,7 @@ fn check_from_and_try_from(cx: &Ctxt, cont: &mut Container) { fn check_name_conflicts(cx: &Ctxt, cont: &Container, derive: Derive) { if let Derive::Deserialize = derive { match &cont.data { - Data::Enum(variants) => check_variant_name_conflicts(cx, &variants), + Data::Enum(variants) => check_variant_name_conflicts(cx, variants), Data::Struct(Style::Struct, fields) => check_field_name_conflicts(cx, fields), _ => {} } From 60ac737439a26542921b099b1a298a140a7b980f Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 8 Nov 2024 21:45:52 -0500 Subject: [PATCH 226/258] Prevent upload-artifact step from causing CI failure This step has been failing way more than reasonable across my various repos. With the provided path, there will be 1 file uploaded Artifact name is valid! Root directory input is valid! Attempt 1 of 5 failed with error: Request timeout: /twirp/github.actions.results.api.v1.ArtifactService/CreateArtifact. Retrying request in 3000 ms... Attempt 2 of 5 failed with error: Request timeout: /twirp/github.actions.results.api.v1.ArtifactService/CreateArtifact. Retrying request in 6029 ms... Attempt 3 of 5 failed with error: Request timeout: /twirp/github.actions.results.api.v1.ArtifactService/CreateArtifact. Retrying request in 8270 ms... Attempt 4 of 5 failed with error: Request timeout: /twirp/github.actions.results.api.v1.ArtifactService/CreateArtifact. Retrying request in 12577 ms... Error: Failed to CreateArtifact: Failed to make request after 5 attempts: Request timeout: /twirp/github.actions.results.api.v1.ArtifactService/CreateArtifact --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f60449aac..fd383e901 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,6 +26,7 @@ jobs: with: name: Cargo.lock path: Cargo.lock + continue-on-error: true windows: name: Test suite (windows) From 3035d4fa34dea5da87640fb61c4993a6077dac64 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 10 Nov 2024 19:34:25 -0800 Subject: [PATCH 227/258] Rename Name -> MultiName --- serde_derive/src/internals/attr.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/serde_derive/src/internals/attr.rs b/serde_derive/src/internals/attr.rs index dd9e2b7dd..96f94f3eb 100644 --- a/serde_derive/src/internals/attr.rs +++ b/serde_derive/src/internals/attr.rs @@ -130,7 +130,7 @@ impl<'c, T> VecAttr<'c, T> { } } -pub struct Name { +pub struct MultiName { serialize: String, serialize_renamed: bool, deserialize: String, @@ -142,13 +142,13 @@ fn unraw(ident: &Ident) -> String { ident.to_string().trim_start_matches("r#").to_owned() } -impl Name { +impl MultiName { fn from_attrs( source_name: String, ser_name: Attr, de_name: Attr, de_aliases: Option>, - ) -> Name { + ) -> Self { let mut alias_set = BTreeSet::new(); if let Some(de_aliases) = de_aliases { for alias_name in de_aliases.get() { @@ -160,7 +160,7 @@ impl Name { let ser_renamed = ser_name.is_some(); let de_name = de_name.get(); let de_renamed = de_name.is_some(); - Name { + MultiName { serialize: ser_name.unwrap_or_else(|| source_name.clone()), serialize_renamed: ser_renamed, deserialize: de_name.unwrap_or(source_name), @@ -203,7 +203,7 @@ impl RenameAllRules { /// Represents struct or enum attribute information. pub struct Container { - name: Name, + name: MultiName, transparent: bool, deny_unknown_fields: bool, default: Default, @@ -567,7 +567,7 @@ impl Container { } Container { - name: Name::from_attrs(unraw(&item.ident), ser_name, de_name, None), + name: MultiName::from_attrs(unraw(&item.ident), ser_name, de_name, None), transparent: transparent.get(), deny_unknown_fields: deny_unknown_fields.get(), default: default.get().unwrap_or(Default::None), @@ -594,7 +594,7 @@ impl Container { } } - pub fn name(&self) -> &Name { + pub fn name(&self) -> &MultiName { &self.name } @@ -781,7 +781,7 @@ fn decide_identifier( /// Represents variant attribute information pub struct Variant { - name: Name, + name: MultiName, rename_all_rules: RenameAllRules, ser_bound: Option>, de_bound: Option>, @@ -947,7 +947,7 @@ impl Variant { } Variant { - name: Name::from_attrs(unraw(&variant.ident), ser_name, de_name, Some(de_aliases)), + name: MultiName::from_attrs(unraw(&variant.ident), ser_name, de_name, Some(de_aliases)), rename_all_rules: RenameAllRules { serialize: rename_all_ser_rule.get().unwrap_or(RenameRule::None), deserialize: rename_all_de_rule.get().unwrap_or(RenameRule::None), @@ -964,7 +964,7 @@ impl Variant { } } - pub fn name(&self) -> &Name { + pub fn name(&self) -> &MultiName { &self.name } @@ -1023,7 +1023,7 @@ impl Variant { /// Represents field attribute information pub struct Field { - name: Name, + name: MultiName, skip_serializing: bool, skip_deserializing: bool, skip_serializing_if: Option, @@ -1290,7 +1290,7 @@ impl Field { } Field { - name: Name::from_attrs(ident, ser_name, de_name, Some(de_aliases)), + name: MultiName::from_attrs(ident, ser_name, de_name, Some(de_aliases)), skip_serializing: skip_serializing.get(), skip_deserializing: skip_deserializing.get(), skip_serializing_if: skip_serializing_if.get(), @@ -1306,7 +1306,7 @@ impl Field { } } - pub fn name(&self) -> &Name { + pub fn name(&self) -> &MultiName { &self.name } From f0b5c4f8574d9417e6a89bf802014f4266126d5f Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 10 Nov 2024 19:37:57 -0800 Subject: [PATCH 228/258] Move MultiName to a new module --- serde_derive/src/internals/attr.rs | 59 +++--------------------------- serde_derive/src/internals/mod.rs | 1 + serde_derive/src/internals/name.rs | 52 ++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 54 deletions(-) create mode 100644 serde_derive/src/internals/name.rs diff --git a/serde_derive/src/internals/attr.rs b/serde_derive/src/internals/attr.rs index 96f94f3eb..44e7796af 100644 --- a/serde_derive/src/internals/attr.rs +++ b/serde_derive/src/internals/attr.rs @@ -1,3 +1,4 @@ +use crate::internals::name::MultiName; use crate::internals::symbol::*; use crate::internals::{ungroup, Ctxt}; use proc_macro2::{Spacing, Span, TokenStream, TokenTree}; @@ -21,7 +22,7 @@ use syn::{parse_quote, token, Ident, Lifetime, Token}; pub use crate::internals::case::RenameRule; -struct Attr<'c, T> { +pub(crate) struct Attr<'c, T> { cx: &'c Ctxt, name: Symbol, tokens: TokenStream, @@ -62,7 +63,7 @@ impl<'c, T> Attr<'c, T> { } } - fn get(self) -> Option { + pub(crate) fn get(self) -> Option { self.value } @@ -90,7 +91,7 @@ impl<'c> BoolAttr<'c> { } } -struct VecAttr<'c, T> { +pub(crate) struct VecAttr<'c, T> { cx: &'c Ctxt, name: Symbol, first_dup_tokens: TokenStream, @@ -125,65 +126,15 @@ impl<'c, T> VecAttr<'c, T> { } } - fn get(self) -> Vec { + pub(crate) fn get(self) -> Vec { self.values } } -pub struct MultiName { - serialize: String, - serialize_renamed: bool, - deserialize: String, - deserialize_renamed: bool, - deserialize_aliases: BTreeSet, -} - fn unraw(ident: &Ident) -> String { ident.to_string().trim_start_matches("r#").to_owned() } -impl MultiName { - fn from_attrs( - source_name: String, - ser_name: Attr, - de_name: Attr, - de_aliases: Option>, - ) -> Self { - let mut alias_set = BTreeSet::new(); - if let Some(de_aliases) = de_aliases { - for alias_name in de_aliases.get() { - alias_set.insert(alias_name); - } - } - - let ser_name = ser_name.get(); - let ser_renamed = ser_name.is_some(); - let de_name = de_name.get(); - let de_renamed = de_name.is_some(); - MultiName { - serialize: ser_name.unwrap_or_else(|| source_name.clone()), - serialize_renamed: ser_renamed, - deserialize: de_name.unwrap_or(source_name), - deserialize_renamed: de_renamed, - deserialize_aliases: alias_set, - } - } - - /// Return the container name for the container when serializing. - pub fn serialize_name(&self) -> &str { - &self.serialize - } - - /// Return the container name for the container when deserializing. - pub fn deserialize_name(&self) -> &str { - &self.deserialize - } - - fn deserialize_aliases(&self) -> &BTreeSet { - &self.deserialize_aliases - } -} - #[derive(Copy, Clone)] pub struct RenameAllRules { pub serialize: RenameRule, diff --git a/serde_derive/src/internals/mod.rs b/serde_derive/src/internals/mod.rs index f98ef08e8..8cdc026f2 100644 --- a/serde_derive/src/internals/mod.rs +++ b/serde_derive/src/internals/mod.rs @@ -4,6 +4,7 @@ pub mod attr; mod case; mod check; mod ctxt; +mod name; mod receiver; mod respan; mod symbol; diff --git a/serde_derive/src/internals/name.rs b/serde_derive/src/internals/name.rs new file mode 100644 index 000000000..1bc8976da --- /dev/null +++ b/serde_derive/src/internals/name.rs @@ -0,0 +1,52 @@ +use crate::internals::attr::{Attr, VecAttr}; +use std::collections::BTreeSet; + +pub struct MultiName { + pub(crate) serialize: String, + pub(crate) serialize_renamed: bool, + pub(crate) deserialize: String, + pub(crate) deserialize_renamed: bool, + pub(crate) deserialize_aliases: BTreeSet, +} + +impl MultiName { + pub(crate) fn from_attrs( + source_name: String, + ser_name: Attr, + de_name: Attr, + de_aliases: Option>, + ) -> Self { + let mut alias_set = BTreeSet::new(); + if let Some(de_aliases) = de_aliases { + for alias_name in de_aliases.get() { + alias_set.insert(alias_name); + } + } + + let ser_name = ser_name.get(); + let ser_renamed = ser_name.is_some(); + let de_name = de_name.get(); + let de_renamed = de_name.is_some(); + MultiName { + serialize: ser_name.unwrap_or_else(|| source_name.clone()), + serialize_renamed: ser_renamed, + deserialize: de_name.unwrap_or(source_name), + deserialize_renamed: de_renamed, + deserialize_aliases: alias_set, + } + } + + /// Return the container name for the container when serializing. + pub fn serialize_name(&self) -> &str { + &self.serialize + } + + /// Return the container name for the container when deserializing. + pub fn deserialize_name(&self) -> &str { + &self.deserialize + } + + pub(crate) fn deserialize_aliases(&self) -> &BTreeSet { + &self.deserialize_aliases + } +} From 373edcd0559639dc392cbf7dd62c709b87c6266e Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 10 Nov 2024 19:08:28 -0800 Subject: [PATCH 229/258] Keep track of a span for alias strings --- serde_derive/src/de.rs | 5 +- serde_derive/src/internals/attr.rs | 61 +++++++++++++--------- serde_derive/src/internals/check.rs | 4 +- serde_derive/src/internals/mod.rs | 2 +- serde_derive/src/internals/name.rs | 81 +++++++++++++++++++++++++---- serde_derive/src/ser.rs | 13 ++--- 6 files changed, 121 insertions(+), 45 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index 518f84320..2f18dd8b1 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -1,5 +1,6 @@ use crate::fragment::{Expr, Fragment, Match, Stmts}; use crate::internals::ast::{Container, Data, Field, Style, Variant}; +use crate::internals::name::Name; use crate::internals::{attr, replace_receiver, ungroup, Ctxt, Derive}; use crate::{bound, dummy, pretend, this}; use proc_macro2::{Literal, Span, TokenStream}; @@ -2002,7 +2003,7 @@ fn deserialize_untagged_newtype_variant( struct FieldWithAliases<'a> { ident: Ident, - aliases: &'a BTreeSet, + aliases: &'a BTreeSet, } fn deserialize_generated_identifier( @@ -2224,7 +2225,7 @@ fn deserialize_identifier( let aliases = field .aliases .iter() - .map(|alias| Literal::byte_string(alias.as_bytes())); + .map(|alias| Literal::byte_string(alias.value.as_bytes())); quote!(#(#aliases)|* => _serde::__private::Ok(#this_value::#ident)) }); diff --git a/serde_derive/src/internals/attr.rs b/serde_derive/src/internals/attr.rs index 44e7796af..6d846ed01 100644 --- a/serde_derive/src/internals/attr.rs +++ b/serde_derive/src/internals/attr.rs @@ -1,4 +1,4 @@ -use crate::internals::name::MultiName; +use crate::internals::name::{MultiName, Name}; use crate::internals::symbol::*; use crate::internals::{ungroup, Ctxt}; use proc_macro2::{Spacing, Span, TokenStream, TokenTree}; @@ -131,8 +131,8 @@ impl<'c, T> VecAttr<'c, T> { } } -fn unraw(ident: &Ident) -> String { - ident.to_string().trim_start_matches("r#").to_owned() +fn unraw(ident: &Ident) -> Ident { + Ident::new(ident.to_string().trim_start_matches("r#"), ident.span()) } #[derive(Copy, Clone)] @@ -278,8 +278,8 @@ impl Container { // #[serde(rename = "foo")] // #[serde(rename(serialize = "foo", deserialize = "bar"))] let (ser, de) = get_renames(cx, RENAME, &meta)?; - ser_name.set_opt(&meta.path, ser.as_ref().map(syn::LitStr::value)); - de_name.set_opt(&meta.path, de.as_ref().map(syn::LitStr::value)); + ser_name.set_opt(&meta.path, ser.as_ref().map(Name::from)); + de_name.set_opt(&meta.path, de.as_ref().map(Name::from)); } else if meta.path == RENAME_ALL { // #[serde(rename_all = "foo")] // #[serde(rename_all(serialize = "foo", deserialize = "bar"))] @@ -518,7 +518,7 @@ impl Container { } Container { - name: MultiName::from_attrs(unraw(&item.ident), ser_name, de_name, None), + name: MultiName::from_attrs(Name::from(&unraw(&item.ident)), ser_name, de_name, None), transparent: transparent.get(), deny_unknown_fields: deny_unknown_fields.get(), default: default.get().unwrap_or(Default::None), @@ -783,15 +783,15 @@ impl Variant { // #[serde(rename = "foo")] // #[serde(rename(serialize = "foo", deserialize = "bar"))] let (ser, de) = get_multiple_renames(cx, &meta)?; - ser_name.set_opt(&meta.path, ser.as_ref().map(syn::LitStr::value)); + ser_name.set_opt(&meta.path, ser.as_ref().map(Name::from)); for de_value in de { - de_name.set_if_none(de_value.value()); - de_aliases.insert(&meta.path, de_value.value()); + de_name.set_if_none(Name::from(&de_value)); + de_aliases.insert(&meta.path, Name::from(&de_value)); } } else if meta.path == ALIAS { // #[serde(alias = "foo")] if let Some(s) = get_lit_str(cx, ALIAS, &meta)? { - de_aliases.insert(&meta.path, s.value()); + de_aliases.insert(&meta.path, Name::from(&s)); } } else if meta.path == RENAME_ALL { // #[serde(rename_all = "foo")] @@ -898,7 +898,12 @@ impl Variant { } Variant { - name: MultiName::from_attrs(unraw(&variant.ident), ser_name, de_name, Some(de_aliases)), + name: MultiName::from_attrs( + Name::from(&unraw(&variant.ident)), + ser_name, + de_name, + Some(de_aliases), + ), rename_all_rules: RenameAllRules { serialize: rename_all_ser_rule.get().unwrap_or(RenameRule::None), deserialize: rename_all_de_rule.get().unwrap_or(RenameRule::None), @@ -919,16 +924,19 @@ impl Variant { &self.name } - pub fn aliases(&self) -> &BTreeSet { + pub fn aliases(&self) -> &BTreeSet { self.name.deserialize_aliases() } pub fn rename_by_rules(&mut self, rules: RenameAllRules) { if !self.name.serialize_renamed { - self.name.serialize = rules.serialize.apply_to_variant(&self.name.serialize); + self.name.serialize.value = + rules.serialize.apply_to_variant(&self.name.serialize.value); } if !self.name.deserialize_renamed { - self.name.deserialize = rules.deserialize.apply_to_variant(&self.name.deserialize); + self.name.deserialize.value = rules + .deserialize + .apply_to_variant(&self.name.deserialize.value); } self.name .deserialize_aliases @@ -1033,8 +1041,11 @@ impl Field { let mut flatten = BoolAttr::none(cx, FLATTEN); let ident = match &field.ident { - Some(ident) => unraw(ident), - None => index.to_string(), + Some(ident) => Name::from(&unraw(ident)), + None => Name { + value: index.to_string(), + span: Span::call_site(), + }, }; if let Some(borrow_attribute) = attrs.and_then(|variant| variant.borrow.as_ref()) { @@ -1070,15 +1081,15 @@ impl Field { // #[serde(rename = "foo")] // #[serde(rename(serialize = "foo", deserialize = "bar"))] let (ser, de) = get_multiple_renames(cx, &meta)?; - ser_name.set_opt(&meta.path, ser.as_ref().map(syn::LitStr::value)); + ser_name.set_opt(&meta.path, ser.as_ref().map(Name::from)); for de_value in de { - de_name.set_if_none(de_value.value()); - de_aliases.insert(&meta.path, de_value.value()); + de_name.set_if_none(Name::from(&de_value)); + de_aliases.insert(&meta.path, Name::from(&de_value)); } } else if meta.path == ALIAS { // #[serde(alias = "foo")] if let Some(s) = get_lit_str(cx, ALIAS, &meta)? { - de_aliases.insert(&meta.path, s.value()); + de_aliases.insert(&meta.path, Name::from(&s)); } } else if meta.path == DEFAULT { if meta.input.peek(Token![=]) { @@ -1261,16 +1272,18 @@ impl Field { &self.name } - pub fn aliases(&self) -> &BTreeSet { + pub fn aliases(&self) -> &BTreeSet { self.name.deserialize_aliases() } pub fn rename_by_rules(&mut self, rules: RenameAllRules) { if !self.name.serialize_renamed { - self.name.serialize = rules.serialize.apply_to_field(&self.name.serialize); + self.name.serialize.value = rules.serialize.apply_to_field(&self.name.serialize.value); } if !self.name.deserialize_renamed { - self.name.deserialize = rules.deserialize.apply_to_field(&self.name.deserialize); + self.name.deserialize.value = rules + .deserialize + .apply_to_field(&self.name.deserialize.value); } self.name .deserialize_aliases @@ -1720,7 +1733,7 @@ fn is_primitive_path(path: &syn::Path, primitive: &str) -> bool { // attribute on the field so there must be at least one borrowable lifetime. fn borrowable_lifetimes( cx: &Ctxt, - name: &str, + name: &Name, field: &syn::Field, ) -> Result, ()> { let mut lifetimes = BTreeSet::new(); diff --git a/serde_derive/src/internals/check.rs b/serde_derive/src/internals/check.rs index 9594b35a5..c9c0fa46d 100644 --- a/serde_derive/src/internals/check.rs +++ b/serde_derive/src/internals/check.rs @@ -332,13 +332,13 @@ fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) { let name = field.attrs.name(); let ser_name = name.serialize_name(); - if check_ser && ser_name == tag { + if check_ser && ser_name.value == tag { diagnose_conflict(); return; } for de_name in field.attrs.aliases() { - if check_de && de_name == tag { + if check_de && de_name.value == tag { diagnose_conflict(); return; } diff --git a/serde_derive/src/internals/mod.rs b/serde_derive/src/internals/mod.rs index 8cdc026f2..cd1e81052 100644 --- a/serde_derive/src/internals/mod.rs +++ b/serde_derive/src/internals/mod.rs @@ -1,10 +1,10 @@ pub mod ast; pub mod attr; +pub mod name; mod case; mod check; mod ctxt; -mod name; mod receiver; mod respan; mod symbol; diff --git a/serde_derive/src/internals/name.rs b/serde_derive/src/internals/name.rs index 1bc8976da..4c59f9636 100644 --- a/serde_derive/src/internals/name.rs +++ b/serde_derive/src/internals/name.rs @@ -1,20 +1,25 @@ use crate::internals::attr::{Attr, VecAttr}; +use proc_macro2::{Ident, Span, TokenStream}; +use quote::ToTokens; +use std::cmp::Ordering; use std::collections::BTreeSet; +use std::fmt::{self, Display}; +use syn::LitStr; pub struct MultiName { - pub(crate) serialize: String, + pub(crate) serialize: Name, pub(crate) serialize_renamed: bool, - pub(crate) deserialize: String, + pub(crate) deserialize: Name, pub(crate) deserialize_renamed: bool, - pub(crate) deserialize_aliases: BTreeSet, + pub(crate) deserialize_aliases: BTreeSet, } impl MultiName { pub(crate) fn from_attrs( - source_name: String, - ser_name: Attr, - de_name: Attr, - de_aliases: Option>, + source_name: Name, + ser_name: Attr, + de_name: Attr, + de_aliases: Option>, ) -> Self { let mut alias_set = BTreeSet::new(); if let Some(de_aliases) = de_aliases { @@ -37,16 +42,72 @@ impl MultiName { } /// Return the container name for the container when serializing. - pub fn serialize_name(&self) -> &str { + pub fn serialize_name(&self) -> &Name { &self.serialize } /// Return the container name for the container when deserializing. - pub fn deserialize_name(&self) -> &str { + pub fn deserialize_name(&self) -> &Name { &self.deserialize } - pub(crate) fn deserialize_aliases(&self) -> &BTreeSet { + pub(crate) fn deserialize_aliases(&self) -> &BTreeSet { &self.deserialize_aliases } } + +#[derive(Clone)] +pub struct Name { + pub value: String, + pub span: Span, +} + +impl ToTokens for Name { + fn to_tokens(&self, tokens: &mut TokenStream) { + LitStr::new(&self.value, self.span).to_tokens(tokens); + } +} + +impl Ord for Name { + fn cmp(&self, other: &Self) -> Ordering { + Ord::cmp(&self.value, &other.value) + } +} + +impl PartialOrd for Name { + fn partial_cmp(&self, other: &Self) -> Option { + Some(Ord::cmp(self, other)) + } +} + +impl Eq for Name {} + +impl PartialEq for Name { + fn eq(&self, other: &Self) -> bool { + self.value == other.value + } +} + +impl From<&Ident> for Name { + fn from(ident: &Ident) -> Self { + Name { + value: ident.to_string(), + span: ident.span(), + } + } +} + +impl From<&LitStr> for Name { + fn from(lit: &LitStr) -> Self { + Name { + value: lit.value(), + span: lit.span(), + } + } +} + +impl Display for Name { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(&self.value, formatter) + } +} diff --git a/serde_derive/src/ser.rs b/serde_derive/src/ser.rs index 47384f16f..ecdf6470d 100644 --- a/serde_derive/src/ser.rs +++ b/serde_derive/src/ser.rs @@ -1,5 +1,6 @@ use crate::fragment::{Fragment, Match, Stmts}; use crate::internals::ast::{Container, Data, Field, Style, Variant}; +use crate::internals::name::Name; use crate::internals::{attr, replace_receiver, Ctxt, Derive}; use crate::{bound, dummy, pretend, this}; use proc_macro2::{Span, TokenStream}; @@ -798,9 +799,9 @@ fn serialize_untagged_variant( enum TupleVariant<'a> { ExternallyTagged { - type_name: &'a str, + type_name: &'a Name, variant_index: u32, - variant_name: &'a str, + variant_name: &'a Name, }, Untagged, } @@ -867,11 +868,11 @@ fn serialize_tuple_variant( enum StructVariant<'a> { ExternallyTagged { variant_index: u32, - variant_name: &'a str, + variant_name: &'a Name, }, InternallyTagged { tag: &'a str, - variant_name: &'a str, + variant_name: &'a Name, }, Untagged, } @@ -880,7 +881,7 @@ fn serialize_struct_variant( context: StructVariant, params: &Parameters, fields: &[Field], - name: &str, + name: &Name, ) -> Fragment { if fields.iter().any(|field| field.attrs.flatten()) { return serialize_struct_variant_with_flatten(context, params, fields, name); @@ -964,7 +965,7 @@ fn serialize_struct_variant_with_flatten( context: StructVariant, params: &Parameters, fields: &[Field], - name: &str, + name: &Name, ) -> Fragment { let struct_trait = StructTrait::SerializeMap; let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait); From c59e876bb37ad690090d83e92a7799b75b1a3f49 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 10 Nov 2024 23:23:09 -0800 Subject: [PATCH 230/258] Produce a separate warning for every colliding name --- serde_derive/src/de.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index 2f18dd8b1..979964cd0 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -2217,7 +2217,11 @@ fn deserialize_identifier( let ident = &field.ident; let aliases = field.aliases; // `aliases` also contains a main name - quote!(#(#aliases)|* => _serde::__private::Ok(#this_value::#ident)) + quote! { + #( + #aliases => _serde::__private::Ok(#this_value::#ident), + )* + } }); let bytes_mapping = deserialized_fields.iter().map(|field| { let ident = &field.ident; @@ -2226,7 +2230,11 @@ fn deserialize_identifier( .aliases .iter() .map(|alias| Literal::byte_string(alias.value.as_bytes())); - quote!(#(#aliases)|* => _serde::__private::Ok(#this_value::#ident)) + quote! { + #( + #aliases => _serde::__private::Ok(#this_value::#ident), + )* + } }); let expecting = expecting.unwrap_or(if is_variant { @@ -2424,7 +2432,7 @@ fn deserialize_identifier( __E: _serde::de::Error, { match __value { - #(#str_mapping,)* + #(#str_mapping)* _ => { #value_as_borrowed_str_content #fallthrough_borrowed_arm @@ -2437,7 +2445,7 @@ fn deserialize_identifier( __E: _serde::de::Error, { match __value { - #(#bytes_mapping,)* + #(#bytes_mapping)* _ => { #bytes_to_str #value_as_borrowed_bytes_content @@ -2462,7 +2470,7 @@ fn deserialize_identifier( __E: _serde::de::Error, { match __value { - #(#str_mapping,)* + #(#str_mapping)* _ => { #value_as_str_content #fallthrough_arm @@ -2475,7 +2483,7 @@ fn deserialize_identifier( __E: _serde::de::Error, { match __value { - #(#bytes_mapping,)* + #(#bytes_mapping)* _ => { #bytes_to_str #value_as_bytes_content From a20e9249c5849b6855ca2d2aa1d0ce563855c3bd Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 10 Nov 2024 22:32:55 -0800 Subject: [PATCH 231/258] Revert "pacify clippy" This reverts commit 951ca5ace0ca0abf9b44e0d6c76005fbd3b77c5c. --- serde_derive/src/internals/check.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serde_derive/src/internals/check.rs b/serde_derive/src/internals/check.rs index c9c0fa46d..6892d4403 100644 --- a/serde_derive/src/internals/check.rs +++ b/serde_derive/src/internals/check.rs @@ -483,7 +483,7 @@ fn check_from_and_try_from(cx: &Ctxt, cont: &mut Container) { fn check_name_conflicts(cx: &Ctxt, cont: &Container, derive: Derive) { if let Derive::Deserialize = derive { match &cont.data { - Data::Enum(variants) => check_variant_name_conflicts(cx, variants), + Data::Enum(variants) => check_variant_name_conflicts(cx, &variants), Data::Struct(Style::Struct, fields) => check_field_name_conflicts(cx, fields), _ => {} } From edd6fe954bc35bbafb454835c6529d0e30148624 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 10 Nov 2024 22:33:03 -0800 Subject: [PATCH 232/258] Revert "Add checks for conflicts for aliases" This reverts commit 5f9fffa53e8a48d9e1f32b1735542207c42f3ead. --- serde_derive/src/internals/check.rs | 136 +--------------------------- 1 file changed, 1 insertion(+), 135 deletions(-) diff --git a/serde_derive/src/internals/check.rs b/serde_derive/src/internals/check.rs index 6892d4403..da2a0fbdc 100644 --- a/serde_derive/src/internals/check.rs +++ b/serde_derive/src/internals/check.rs @@ -1,8 +1,6 @@ -use crate::internals::ast::{Container, Data, Field, Style, Variant}; +use crate::internals::ast::{Container, Data, Field, Style}; use crate::internals::attr::{Default, Identifier, TagType}; use crate::internals::{ungroup, Ctxt, Derive}; -use std::collections::btree_map::Entry; -use std::collections::{BTreeMap, BTreeSet}; use syn::{Member, Type}; // Cross-cutting checks that require looking at more than a single attrs object. @@ -18,7 +16,6 @@ pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) { check_adjacent_tag_conflict(cx, cont); check_transparent(cx, cont, derive); check_from_and_try_from(cx, cont); - check_name_conflicts(cx, cont, derive); } // If some field of a tuple struct is marked #[serde(default)] then all fields @@ -478,134 +475,3 @@ fn check_from_and_try_from(cx: &Ctxt, cont: &mut Container) { ); } } - -// Checks that aliases does not repeated -fn check_name_conflicts(cx: &Ctxt, cont: &Container, derive: Derive) { - if let Derive::Deserialize = derive { - match &cont.data { - Data::Enum(variants) => check_variant_name_conflicts(cx, &variants), - Data::Struct(Style::Struct, fields) => check_field_name_conflicts(cx, fields), - _ => {} - } - } -} - -// All renames already applied -fn check_variant_name_conflicts(cx: &Ctxt, variants: &[Variant]) { - let names: BTreeSet<_> = variants - .iter() - .filter_map(|variant| { - if variant.attrs.skip_deserializing() { - None - } else { - Some(variant.attrs.name().deserialize_name().to_owned()) - } - }) - .collect(); - let mut alias_owners = BTreeMap::new(); - - for variant in variants { - let name = variant.attrs.name().deserialize_name(); - - for alias in variant.attrs.aliases().intersection(&names) { - // Aliases contains variant names, so filter them out - if alias == name { - continue; - } - - // TODO: report other variant location when this become possible - cx.error_spanned_by( - variant.original, - format!( - "alias `{}` conflicts with deserialization name of other variant", - alias - ), - ); - } - - for alias in variant.attrs.aliases() { - // Aliases contains variant names, so filter them out - if alias == name { - continue; - } - - match alias_owners.entry(alias) { - Entry::Vacant(e) => { - e.insert(variant); - } - Entry::Occupied(e) => { - // TODO: report other variant location when this become possible - cx.error_spanned_by( - variant.original, - format!( - "alias `{}` already used by variant {}", - alias, - e.get().original.ident - ), - ); - } - } - } - - check_field_name_conflicts(cx, &variant.fields); - } -} - -// All renames already applied -fn check_field_name_conflicts(cx: &Ctxt, fields: &[Field]) { - let names: BTreeSet<_> = fields - .iter() - .filter_map(|field| { - if field.attrs.skip_deserializing() { - None - } else { - Some(field.attrs.name().deserialize_name().to_owned()) - } - }) - .collect(); - let mut alias_owners = BTreeMap::new(); - - for field in fields { - let name = field.attrs.name().deserialize_name(); - - for alias in field.attrs.aliases().intersection(&names) { - // Aliases contains field names, so filter them out - if alias == name { - continue; - } - - // TODO: report other field location when this become possible - cx.error_spanned_by( - field.original, - format!( - "alias `{}` conflicts with deserialization name of other field", - alias - ), - ); - } - - for alias in field.attrs.aliases() { - // Aliases contains field names, so filter them out - if alias == name { - continue; - } - - match alias_owners.entry(alias) { - Entry::Vacant(e) => { - e.insert(field); - } - Entry::Occupied(e) => { - // TODO: report other field location when this become possible - cx.error_spanned_by( - field.original, - format!( - "alias `{}` already used by field {}", - alias, - e.get().original.ident.as_ref().unwrap() - ), - ); - } - } - } - } -} From 111ecc5d8c01cf7795059f3bc436bfd0e57d1d64 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 10 Nov 2024 22:38:59 -0800 Subject: [PATCH 233/258] Update ui tests for warning on colliding aliases --- test_suite/tests/ui/conflict/alias-enum.rs | 4 +- .../tests/ui/conflict/alias-enum.stderr | 120 ++++++++++-------- test_suite/tests/ui/conflict/alias.rs | 4 +- test_suite/tests/ui/conflict/alias.stderr | 66 +++++----- 4 files changed, 107 insertions(+), 87 deletions(-) diff --git a/test_suite/tests/ui/conflict/alias-enum.rs b/test_suite/tests/ui/conflict/alias-enum.rs index 52af74b97..faceae3e7 100644 --- a/test_suite/tests/ui/conflict/alias-enum.rs +++ b/test_suite/tests/ui/conflict/alias-enum.rs @@ -76,4 +76,6 @@ enum E3 { b, } -fn main() {} +fn main() { + @//fail +} diff --git a/test_suite/tests/ui/conflict/alias-enum.stderr b/test_suite/tests/ui/conflict/alias-enum.stderr index 36e036f65..aa0ca687c 100644 --- a/test_suite/tests/ui/conflict/alias-enum.stderr +++ b/test_suite/tests/ui/conflict/alias-enum.stderr @@ -1,71 +1,79 @@ -error: alias `b` conflicts with deserialization name of other field - --> tests/ui/conflict/alias-enum.rs:8:9 +error: expected expression, found `@` + --> tests/ui/conflict/alias-enum.rs:80:5 | -8 | / /// Expected error on "alias b", because this is a name of other field -9 | | /// Error on "alias a" is not expected because this is a name of this field -10 | | /// Error on "alias c" is not expected because field `c` is skipped -11 | | #[serde(alias = "a", alias = "b", alias = "c")] -12 | | a: (), - | |_____________^ +80 | @//fail + | ^ expected expression -error: alias `c` already used by field a - --> tests/ui/conflict/alias-enum.rs:14:9 +warning: unreachable pattern + --> tests/ui/conflict/alias-enum.rs:16:9 | -14 | / /// Expected error on "alias c", because it is already used as alias of `a` -15 | | #[serde(alias = "c")] -16 | | b: (), - | |_____________^ +11 | #[serde(alias = "a", alias = "b", alias = "c")] + | --- matches all the relevant values +... +16 | b: (), + | ^ no value can reach this + | + = note: `#[warn(unreachable_patterns)]` on by default + +warning: unreachable pattern + --> tests/ui/conflict/alias-enum.rs:15:25 + | +11 | #[serde(alias = "a", alias = "b", alias = "c")] + | --- matches all the relevant values +... +15 | #[serde(alias = "c")] + | ^^^ no value can reach this -error: alias `c` conflicts with deserialization name of other field - --> tests/ui/conflict/alias-enum.rs:23:9 +warning: unreachable pattern + --> tests/ui/conflict/alias-enum.rs:28:26 | -23 | / /// Expected error on "alias c", because this is a name of other field after -24 | | /// applying rename rules -25 | | #[serde(alias = "b", alias = "c")] -26 | | a: (), - | |_____________^ +25 | #[serde(alias = "b", alias = "c")] + | --- matches all the relevant values +... +28 | #[serde(rename = "c")] + | ^^^ no value can reach this -error: alias `B` conflicts with deserialization name of other field - --> tests/ui/conflict/alias-enum.rs:34:9 +warning: unreachable pattern + --> tests/ui/conflict/alias-enum.rs:38:9 | -34 | / /// Expected error on "alias B", because this is a name of field after -35 | | /// applying rename rules -36 | | #[serde(alias = "B", alias = "c")] -37 | | a: (), - | |_____________^ +36 | #[serde(alias = "B", alias = "c")] + | --- matches all the relevant values +37 | a: (), +38 | b: (), + | ^ no value can reach this -error: alias `b` conflicts with deserialization name of other variant - --> tests/ui/conflict/alias-enum.rs:44:5 +warning: unreachable pattern + --> tests/ui/conflict/alias-enum.rs:52:5 | -44 | / /// Expected error on "alias b", because this is a name of other variant -45 | | /// Error on "alias a" is not expected because this is a name of this variant -46 | | /// Error on "alias c" is not expected because variant `c` is skipped -47 | | #[serde(alias = "a", alias = "b", alias = "c")] -48 | | a, - | |_____^ +47 | #[serde(alias = "a", alias = "b", alias = "c")] + | --- matches all the relevant values +... +52 | b, + | ^ no value can reach this -error: alias `c` already used by variant a - --> tests/ui/conflict/alias-enum.rs:50:5 +warning: unreachable pattern + --> tests/ui/conflict/alias-enum.rs:51:21 | -50 | / /// Expected error on "alias c", because it is already used as alias of `a` -51 | | #[serde(alias = "c")] -52 | | b, - | |_____^ +47 | #[serde(alias = "a", alias = "b", alias = "c")] + | --- matches all the relevant values +... +51 | #[serde(alias = "c")] + | ^^^ no value can reach this -error: alias `c` conflicts with deserialization name of other variant - --> tests/ui/conflict/alias-enum.rs:60:5 +warning: unreachable pattern + --> tests/ui/conflict/alias-enum.rs:65:22 | -60 | / /// Expected error on "alias c", because this is a name of other variant after -61 | | /// applying rename rules -62 | | #[serde(alias = "b", alias = "c")] -63 | | a, - | |_____^ +62 | #[serde(alias = "b", alias = "c")] + | --- matches all the relevant values +... +65 | #[serde(rename = "c")] + | ^^^ no value can reach this -error: alias `B` conflicts with deserialization name of other variant - --> tests/ui/conflict/alias-enum.rs:72:5 +warning: unreachable pattern + --> tests/ui/conflict/alias-enum.rs:76:5 | -72 | / /// Expected error on "alias B", because this is a name of variant after -73 | | /// applying rename rules -74 | | #[serde(alias = "B", alias = "c")] -75 | | a, - | |_____^ +74 | #[serde(alias = "B", alias = "c")] + | --- matches all the relevant values +75 | a, +76 | b, + | ^ no value can reach this diff --git a/test_suite/tests/ui/conflict/alias.rs b/test_suite/tests/ui/conflict/alias.rs index f52a90586..3f6cee295 100644 --- a/test_suite/tests/ui/conflict/alias.rs +++ b/test_suite/tests/ui/conflict/alias.rs @@ -37,4 +37,6 @@ struct S3 { b: (), } -fn main() {} +fn main() { + @//fail +} diff --git a/test_suite/tests/ui/conflict/alias.stderr b/test_suite/tests/ui/conflict/alias.stderr index 2115b21b1..7e665a630 100644 --- a/test_suite/tests/ui/conflict/alias.stderr +++ b/test_suite/tests/ui/conflict/alias.stderr @@ -1,35 +1,43 @@ -error: alias `b` conflicts with deserialization name of other field - --> tests/ui/conflict/alias.rs:5:5 - | -5 | / /// Expected error on "alias b", because this is a name of other field -6 | | /// Error on "alias a" is not expected because this is a name of this field -7 | | /// Error on "alias c" is not expected because field `c` is skipped -8 | | #[serde(alias = "a", alias = "b", alias = "c")] -9 | | a: (), - | |_________^ +error: expected expression, found `@` + --> tests/ui/conflict/alias.rs:41:5 + | +41 | @//fail + | ^ expected expression + +warning: unreachable pattern + --> tests/ui/conflict/alias.rs:13:5 + | +8 | #[serde(alias = "a", alias = "b", alias = "c")] + | --- matches all the relevant values +... +13 | b: (), + | ^ no value can reach this + | + = note: `#[warn(unreachable_patterns)]` on by default -error: alias `c` already used by field a - --> tests/ui/conflict/alias.rs:11:5 +warning: unreachable pattern + --> tests/ui/conflict/alias.rs:12:21 | -11 | / /// Expected error on "alias c", because it is already used as alias of `a` -12 | | #[serde(alias = "c")] -13 | | b: (), - | |_________^ +8 | #[serde(alias = "a", alias = "b", alias = "c")] + | --- matches all the relevant values +... +12 | #[serde(alias = "c")] + | ^^^ no value can reach this -error: alias `c` conflicts with deserialization name of other field - --> tests/ui/conflict/alias.rs:21:5 +warning: unreachable pattern + --> tests/ui/conflict/alias.rs:26:22 | -21 | / /// Expected error on "alias c", because this is a name of other field after -22 | | /// applying rename rules -23 | | #[serde(alias = "b", alias = "c")] -24 | | a: (), - | |_________^ +23 | #[serde(alias = "b", alias = "c")] + | --- matches all the relevant values +... +26 | #[serde(rename = "c")] + | ^^^ no value can reach this -error: alias `B` conflicts with deserialization name of other field - --> tests/ui/conflict/alias.rs:33:5 +warning: unreachable pattern + --> tests/ui/conflict/alias.rs:37:5 | -33 | / /// Expected error on "alias B", because this is a name of field after -34 | | /// applying rename rules -35 | | #[serde(alias = "B", alias = "c")] -36 | | a: (), - | |_________^ +35 | #[serde(alias = "B", alias = "c")] + | --- matches all the relevant values +36 | a: (), +37 | b: (), + | ^ no value can reach this From 1a3cf4b3c18396a1c5da6999ff7695d822709044 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 10 Nov 2024 23:46:08 -0800 Subject: [PATCH 234/258] Update PR 2562 ui tests --- test_suite/tests/ui/conflict/alias-enum.rs | 26 ++++----- .../tests/ui/conflict/alias-enum.stderr | 56 +++++++++---------- test_suite/tests/ui/conflict/alias.rs | 13 ++--- test_suite/tests/ui/conflict/alias.stderr | 36 ++++++------ 4 files changed, 61 insertions(+), 70 deletions(-) diff --git a/test_suite/tests/ui/conflict/alias-enum.rs b/test_suite/tests/ui/conflict/alias-enum.rs index faceae3e7..e5e614e29 100644 --- a/test_suite/tests/ui/conflict/alias-enum.rs +++ b/test_suite/tests/ui/conflict/alias-enum.rs @@ -5,13 +5,10 @@ use serde_derive::Deserialize; #[derive(Deserialize)] enum E { S1 { - /// Expected error on "alias b", because this is a name of other field - /// Error on "alias a" is not expected because this is a name of this field - /// Error on "alias c" is not expected because field `c` is skipped #[serde(alias = "a", alias = "b", alias = "c")] a: (), - /// Expected error on "alias c", because it is already used as alias of `a` + // Warning on "c" and "b" #[serde(alias = "c")] b: (), @@ -20,34 +17,31 @@ enum E { }, S2 { - /// Expected error on "alias c", because this is a name of other field after - /// applying rename rules #[serde(alias = "b", alias = "c")] a: (), + // Warning on "c" #[serde(rename = "c")] b: (), }, #[serde(rename_all = "UPPERCASE")] S3 { - /// Expected error on "alias B", because this is a name of field after - /// applying rename rules #[serde(alias = "B", alias = "c")] a: (), + + // Warning on "b" because this collides with the "B" above after + // applying rename rules b: (), }, } #[derive(Deserialize)] enum E1 { - /// Expected error on "alias b", because this is a name of other variant - /// Error on "alias a" is not expected because this is a name of this variant - /// Error on "alias c" is not expected because variant `c` is skipped #[serde(alias = "a", alias = "b", alias = "c")] a, - /// Expected error on "alias c", because it is already used as alias of `a` + // Warning on "c" and "b" #[serde(alias = "c")] b, @@ -57,11 +51,10 @@ enum E1 { #[derive(Deserialize)] enum E2 { - /// Expected error on "alias c", because this is a name of other variant after - /// applying rename rules #[serde(alias = "b", alias = "c")] a, + // Warning on "c" #[serde(rename = "c")] b, } @@ -69,10 +62,11 @@ enum E2 { #[derive(Deserialize)] #[serde(rename_all = "UPPERCASE")] enum E3 { - /// Expected error on "alias B", because this is a name of variant after - /// applying rename rules #[serde(alias = "B", alias = "c")] a, + + // Warning on "b" because this collides with the "B" above after applying + // rename rules b, } diff --git a/test_suite/tests/ui/conflict/alias-enum.stderr b/test_suite/tests/ui/conflict/alias-enum.stderr index aa0ca687c..ea2ed1009 100644 --- a/test_suite/tests/ui/conflict/alias-enum.stderr +++ b/test_suite/tests/ui/conflict/alias-enum.stderr @@ -1,79 +1,79 @@ error: expected expression, found `@` - --> tests/ui/conflict/alias-enum.rs:80:5 + --> tests/ui/conflict/alias-enum.rs:74:5 | -80 | @//fail +74 | @//fail | ^ expected expression warning: unreachable pattern - --> tests/ui/conflict/alias-enum.rs:16:9 + --> tests/ui/conflict/alias-enum.rs:13:9 | -11 | #[serde(alias = "a", alias = "b", alias = "c")] +8 | #[serde(alias = "a", alias = "b", alias = "c")] | --- matches all the relevant values ... -16 | b: (), +13 | b: (), | ^ no value can reach this | = note: `#[warn(unreachable_patterns)]` on by default warning: unreachable pattern - --> tests/ui/conflict/alias-enum.rs:15:25 + --> tests/ui/conflict/alias-enum.rs:12:25 | -11 | #[serde(alias = "a", alias = "b", alias = "c")] +8 | #[serde(alias = "a", alias = "b", alias = "c")] | --- matches all the relevant values ... -15 | #[serde(alias = "c")] +12 | #[serde(alias = "c")] | ^^^ no value can reach this warning: unreachable pattern - --> tests/ui/conflict/alias-enum.rs:28:26 + --> tests/ui/conflict/alias-enum.rs:24:26 | -25 | #[serde(alias = "b", alias = "c")] +20 | #[serde(alias = "b", alias = "c")] | --- matches all the relevant values ... -28 | #[serde(rename = "c")] +24 | #[serde(rename = "c")] | ^^^ no value can reach this warning: unreachable pattern - --> tests/ui/conflict/alias-enum.rs:38:9 + --> tests/ui/conflict/alias-enum.rs:35:9 | -36 | #[serde(alias = "B", alias = "c")] +30 | #[serde(alias = "B", alias = "c")] | --- matches all the relevant values -37 | a: (), -38 | b: (), +... +35 | b: (), | ^ no value can reach this warning: unreachable pattern - --> tests/ui/conflict/alias-enum.rs:52:5 + --> tests/ui/conflict/alias-enum.rs:46:5 | -47 | #[serde(alias = "a", alias = "b", alias = "c")] +41 | #[serde(alias = "a", alias = "b", alias = "c")] | --- matches all the relevant values ... -52 | b, +46 | b, | ^ no value can reach this warning: unreachable pattern - --> tests/ui/conflict/alias-enum.rs:51:21 + --> tests/ui/conflict/alias-enum.rs:45:21 | -47 | #[serde(alias = "a", alias = "b", alias = "c")] +41 | #[serde(alias = "a", alias = "b", alias = "c")] | --- matches all the relevant values ... -51 | #[serde(alias = "c")] +45 | #[serde(alias = "c")] | ^^^ no value can reach this warning: unreachable pattern - --> tests/ui/conflict/alias-enum.rs:65:22 + --> tests/ui/conflict/alias-enum.rs:58:22 | -62 | #[serde(alias = "b", alias = "c")] +54 | #[serde(alias = "b", alias = "c")] | --- matches all the relevant values ... -65 | #[serde(rename = "c")] +58 | #[serde(rename = "c")] | ^^^ no value can reach this warning: unreachable pattern - --> tests/ui/conflict/alias-enum.rs:76:5 + --> tests/ui/conflict/alias-enum.rs:70:5 | -74 | #[serde(alias = "B", alias = "c")] +65 | #[serde(alias = "B", alias = "c")] | --- matches all the relevant values -75 | a, -76 | b, +... +70 | b, | ^ no value can reach this diff --git a/test_suite/tests/ui/conflict/alias.rs b/test_suite/tests/ui/conflict/alias.rs index 3f6cee295..8158301c2 100644 --- a/test_suite/tests/ui/conflict/alias.rs +++ b/test_suite/tests/ui/conflict/alias.rs @@ -2,13 +2,10 @@ use serde_derive::Deserialize; #[derive(Deserialize)] struct S1 { - /// Expected error on "alias b", because this is a name of other field - /// Error on "alias a" is not expected because this is a name of this field - /// Error on "alias c" is not expected because field `c` is skipped #[serde(alias = "a", alias = "b", alias = "c")] a: (), - /// Expected error on "alias c", because it is already used as alias of `a` + // Warning on "c" and "b" #[serde(alias = "c")] b: (), @@ -18,11 +15,10 @@ struct S1 { #[derive(Deserialize)] struct S2 { - /// Expected error on "alias c", because this is a name of other field after - /// applying rename rules #[serde(alias = "b", alias = "c")] a: (), + // Warning on "c" #[serde(rename = "c")] b: (), } @@ -30,10 +26,11 @@ struct S2 { #[derive(Deserialize)] #[serde(rename_all = "UPPERCASE")] struct S3 { - /// Expected error on "alias B", because this is a name of field after - /// applying rename rules #[serde(alias = "B", alias = "c")] a: (), + + // Warning on "b" because this collides with the "B" above after applying + // rename rules b: (), } diff --git a/test_suite/tests/ui/conflict/alias.stderr b/test_suite/tests/ui/conflict/alias.stderr index 7e665a630..2040cec32 100644 --- a/test_suite/tests/ui/conflict/alias.stderr +++ b/test_suite/tests/ui/conflict/alias.stderr @@ -1,43 +1,43 @@ error: expected expression, found `@` - --> tests/ui/conflict/alias.rs:41:5 + --> tests/ui/conflict/alias.rs:38:5 | -41 | @//fail +38 | @//fail | ^ expected expression warning: unreachable pattern - --> tests/ui/conflict/alias.rs:13:5 + --> tests/ui/conflict/alias.rs:10:5 | -8 | #[serde(alias = "a", alias = "b", alias = "c")] +5 | #[serde(alias = "a", alias = "b", alias = "c")] | --- matches all the relevant values ... -13 | b: (), +10 | b: (), | ^ no value can reach this | = note: `#[warn(unreachable_patterns)]` on by default warning: unreachable pattern - --> tests/ui/conflict/alias.rs:12:21 - | -8 | #[serde(alias = "a", alias = "b", alias = "c")] - | --- matches all the relevant values + --> tests/ui/conflict/alias.rs:9:21 + | +5 | #[serde(alias = "a", alias = "b", alias = "c")] + | --- matches all the relevant values ... -12 | #[serde(alias = "c")] - | ^^^ no value can reach this +9 | #[serde(alias = "c")] + | ^^^ no value can reach this warning: unreachable pattern - --> tests/ui/conflict/alias.rs:26:22 + --> tests/ui/conflict/alias.rs:22:22 | -23 | #[serde(alias = "b", alias = "c")] +18 | #[serde(alias = "b", alias = "c")] | --- matches all the relevant values ... -26 | #[serde(rename = "c")] +22 | #[serde(rename = "c")] | ^^^ no value can reach this warning: unreachable pattern - --> tests/ui/conflict/alias.rs:37:5 + --> tests/ui/conflict/alias.rs:34:5 | -35 | #[serde(alias = "B", alias = "c")] +29 | #[serde(alias = "B", alias = "c")] | --- matches all the relevant values -36 | a: (), -37 | b: (), +... +34 | b: (), | ^ no value can reach this From fa5d58cd007812b5990ec5721082bac293a97467 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 10 Nov 2024 23:50:37 -0800 Subject: [PATCH 235/258] Use ui test syntax that does not interfere with rustfmt --- test_suite/tests/ui/conflict/alias-enum.rs | 2 +- test_suite/tests/ui/conflict/alias-enum.stderr | 6 +++--- test_suite/tests/ui/conflict/alias.rs | 2 +- test_suite/tests/ui/conflict/alias.stderr | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/test_suite/tests/ui/conflict/alias-enum.rs b/test_suite/tests/ui/conflict/alias-enum.rs index e5e614e29..5ca958b6d 100644 --- a/test_suite/tests/ui/conflict/alias-enum.rs +++ b/test_suite/tests/ui/conflict/alias-enum.rs @@ -71,5 +71,5 @@ enum E3 { } fn main() { - @//fail + __FAIL__; } diff --git a/test_suite/tests/ui/conflict/alias-enum.stderr b/test_suite/tests/ui/conflict/alias-enum.stderr index ea2ed1009..c84041051 100644 --- a/test_suite/tests/ui/conflict/alias-enum.stderr +++ b/test_suite/tests/ui/conflict/alias-enum.stderr @@ -1,8 +1,8 @@ -error: expected expression, found `@` +error[E0425]: cannot find value `__FAIL__` in this scope --> tests/ui/conflict/alias-enum.rs:74:5 | -74 | @//fail - | ^ expected expression +74 | __FAIL__; + | ^^^^^^^^ not found in this scope warning: unreachable pattern --> tests/ui/conflict/alias-enum.rs:13:9 diff --git a/test_suite/tests/ui/conflict/alias.rs b/test_suite/tests/ui/conflict/alias.rs index 8158301c2..e18254759 100644 --- a/test_suite/tests/ui/conflict/alias.rs +++ b/test_suite/tests/ui/conflict/alias.rs @@ -35,5 +35,5 @@ struct S3 { } fn main() { - @//fail + __FAIL__; } diff --git a/test_suite/tests/ui/conflict/alias.stderr b/test_suite/tests/ui/conflict/alias.stderr index 2040cec32..4c1a96d1c 100644 --- a/test_suite/tests/ui/conflict/alias.stderr +++ b/test_suite/tests/ui/conflict/alias.stderr @@ -1,8 +1,8 @@ -error: expected expression, found `@` +error[E0425]: cannot find value `__FAIL__` in this scope --> tests/ui/conflict/alias.rs:38:5 | -38 | @//fail - | ^ expected expression +38 | __FAIL__; + | ^^^^^^^^ not found in this scope warning: unreachable pattern --> tests/ui/conflict/alias.rs:10:5 From 8939af48fecb965eb3ff04dc8969146d5af5ca0f Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 11 Nov 2024 13:03:35 -0800 Subject: [PATCH 236/258] Release 1.0.215 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 13cdede23..c5cf4f8f8 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.214" +version = "1.0.215" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.214", path = "../serde_derive" } +serde_derive = { version = "=1.0.215", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index afc1cb5a7..da1ecab00 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.214")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.215")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index c1541961a..5c679b2ef 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.214" +version = "1.0.215" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index a980601bf..fbc9b9ec3 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.214")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.215")] #![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] // Ignored clippy lints #![allow( From 0307f604ea5ca91de1f65d1db075d5cc5abb00ad Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 15 Nov 2024 18:55:45 -0800 Subject: [PATCH 237/258] Resolve question_mark clippy lint in build script warning: this `match` expression can be replaced with `?` --> serde/build.rs:111:17 | 111 | let rustc = match env::var_os("RUSTC") { | _________________^ 112 | | Some(rustc) => rustc, 113 | | None => return None, 114 | | }; | |_____^ help: try instead: `env::var_os("RUSTC")?` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#question_mark = note: `-W clippy::question-mark` implied by `-W clippy::all` = help: to override `-W clippy::all` add `#[allow(clippy::question_mark)]` warning: this `match` expression can be replaced with `?` --> serde/build.rs:131:16 | 131 | let next = match pieces.next() { | ________________^ 132 | | Some(next) => next, 133 | | None => return None, 134 | | }; | |_____^ help: try instead: `pieces.next()?` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#question_mark --- serde/build.rs | 28 +++++----------------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/serde/build.rs b/serde/build.rs index d7ab56562..24aa0e6d2 100644 --- a/serde/build.rs +++ b/serde/build.rs @@ -1,6 +1,6 @@ use std::env; use std::process::Command; -use std::str::{self, FromStr}; +use std::str; // The rustc-cfg strings below are *not* public API. Please let us know by // opening a GitHub issue if your build environment requires some way to enable @@ -108,30 +108,12 @@ fn main() { } fn rustc_minor_version() -> Option { - let rustc = match env::var_os("RUSTC") { - Some(rustc) => rustc, - None => return None, - }; - - let output = match Command::new(rustc).arg("--version").output() { - Ok(output) => output, - Err(_) => return None, - }; - - let version = match str::from_utf8(&output.stdout) { - Ok(version) => version, - Err(_) => return None, - }; - + let rustc = env::var_os("RUSTC")?; + let output = Command::new(rustc).arg("--version").output().ok()?; + let version = str::from_utf8(&output.stdout).ok()?; let mut pieces = version.split('.'); if pieces.next() != Some("rustc 1") { return None; } - - let next = match pieces.next() { - Some(next) => next, - None => return None, - }; - - u32::from_str(next).ok() + pieces.next()?.parse().ok() } From c270e27a4d37f008c199523f223843e8659b7fd9 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 16 Nov 2024 12:22:47 -0800 Subject: [PATCH 238/258] Use BuildHasher instead of Hasher in collection macros --- test_suite/tests/macros/mod.rs | 10 ++++------ test_suite/tests/test_de.rs | 6 +++--- test_suite/tests/test_ser.rs | 6 +++--- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/test_suite/tests/macros/mod.rs b/test_suite/tests/macros/mod.rs index d66324464..44b98ae2f 100644 --- a/test_suite/tests/macros/mod.rs +++ b/test_suite/tests/macros/mod.rs @@ -34,9 +34,8 @@ macro_rules! hashset { $(set.insert($value);)+ set }}; - ($hasher:ident @ $($value:expr),+) => {{ - use std::hash::BuildHasherDefault; - let mut set = HashSet::with_hasher(BuildHasherDefault::<$hasher>::default()); + ($hasher:ty; $($value:expr),+) => {{ + let mut set = HashSet::<_, $hasher>::default(); $(set.insert($value);)+ set }}; @@ -51,9 +50,8 @@ macro_rules! hashmap { $(map.insert($key, $value);)+ map }}; - ($hasher:ident @ $($key:expr => $value:expr),+) => {{ - use std::hash::BuildHasherDefault; - let mut map = HashMap::with_hasher(BuildHasherDefault::<$hasher>::default()); + ($hasher:ty; $($key:expr => $value:expr),+) => {{ + let mut map = HashMap::<_, _, $hasher>::default(); $(map.insert($key, $value);)+ map }}; diff --git a/test_suite/tests/test_de.rs b/test_suite/tests/test_de.rs index 31e726d4b..9726ef543 100644 --- a/test_suite/tests/test_de.rs +++ b/test_suite/tests/test_de.rs @@ -10,7 +10,7 @@ )] #![cfg_attr(feature = "unstable", feature(never_type))] -use fnv::FnvHasher; +use fnv::FnvBuildHasher; use serde::de::value::{F32Deserializer, F64Deserializer}; use serde::de::{Deserialize, DeserializeOwned, Deserializer, IntoDeserializer}; use serde_derive::Deserialize; @@ -1040,7 +1040,7 @@ fn test_hashset() { ], ); test( - hashset![FnvHasher @ 1, 2, 3], + hashset![FnvBuildHasher; 1, 2, 3], &[ Token::Seq { len: Some(3) }, Token::I32(1), @@ -1275,7 +1275,7 @@ fn test_hashmap() { ], ); test( - hashmap![FnvHasher @ 1 => 2, 3 => 4], + hashmap![FnvBuildHasher; 1 => 2, 3 => 4], &[ Token::Map { len: Some(2) }, Token::I32(1), diff --git a/test_suite/tests/test_ser.rs b/test_suite/tests/test_ser.rs index b60d03ab2..0a1c1ee97 100644 --- a/test_suite/tests/test_ser.rs +++ b/test_suite/tests/test_ser.rs @@ -1,7 +1,7 @@ #![allow(clippy::derive_partial_eq_without_eq, clippy::unreadable_literal)] #![cfg_attr(feature = "unstable", feature(never_type))] -use fnv::FnvHasher; +use fnv::FnvBuildHasher; use serde_derive::Serialize; use serde_test::{assert_ser_tokens, assert_ser_tokens_error, Configure, Token}; use std::cell::RefCell; @@ -220,7 +220,7 @@ fn test_hashset() { &[Token::Seq { len: Some(1) }, Token::I32(1), Token::SeqEnd], ); assert_ser_tokens( - &hashset![FnvHasher @ 1], + &hashset![FnvBuildHasher; 1], &[Token::Seq { len: Some(1) }, Token::I32(1), Token::SeqEnd], ); } @@ -300,7 +300,7 @@ fn test_hashmap() { ], ); assert_ser_tokens( - &hashmap![FnvHasher @ 1 => 2], + &hashmap![FnvBuildHasher; 1 => 2], &[ Token::Map { len: Some(1) }, Token::I32(1), From b9dbfcb4ac3b7a663d9efc6eb1387c62302a6fb4 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 16 Nov 2024 12:24:01 -0800 Subject: [PATCH 239/258] Switch out fnv in favor of foldhash in test --- test_suite/Cargo.toml | 2 +- test_suite/tests/test_de.rs | 5 ++--- test_suite/tests/test_ser.rs | 5 ++--- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/test_suite/Cargo.toml b/test_suite/Cargo.toml index 07e62656a..4076e735a 100644 --- a/test_suite/Cargo.toml +++ b/test_suite/Cargo.toml @@ -13,7 +13,7 @@ serde = { path = "../serde" } [dev-dependencies] automod = "1.0.1" -fnv = "1.0" +foldhash = "0.1" rustversion = "1.0" serde = { path = "../serde", features = ["rc"] } serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] } diff --git a/test_suite/tests/test_de.rs b/test_suite/tests/test_de.rs index 9726ef543..2e80fbaf9 100644 --- a/test_suite/tests/test_de.rs +++ b/test_suite/tests/test_de.rs @@ -10,7 +10,6 @@ )] #![cfg_attr(feature = "unstable", feature(never_type))] -use fnv::FnvBuildHasher; use serde::de::value::{F32Deserializer, F64Deserializer}; use serde::de::{Deserialize, DeserializeOwned, Deserializer, IntoDeserializer}; use serde_derive::Deserialize; @@ -1040,7 +1039,7 @@ fn test_hashset() { ], ); test( - hashset![FnvBuildHasher; 1, 2, 3], + hashset![foldhash::fast::FixedState; 1, 2, 3], &[ Token::Seq { len: Some(3) }, Token::I32(1), @@ -1275,7 +1274,7 @@ fn test_hashmap() { ], ); test( - hashmap![FnvBuildHasher; 1 => 2, 3 => 4], + hashmap![foldhash::fast::FixedState; 1 => 2, 3 => 4], &[ Token::Map { len: Some(2) }, Token::I32(1), diff --git a/test_suite/tests/test_ser.rs b/test_suite/tests/test_ser.rs index 0a1c1ee97..1c8063184 100644 --- a/test_suite/tests/test_ser.rs +++ b/test_suite/tests/test_ser.rs @@ -1,7 +1,6 @@ #![allow(clippy::derive_partial_eq_without_eq, clippy::unreadable_literal)] #![cfg_attr(feature = "unstable", feature(never_type))] -use fnv::FnvBuildHasher; use serde_derive::Serialize; use serde_test::{assert_ser_tokens, assert_ser_tokens_error, Configure, Token}; use std::cell::RefCell; @@ -220,7 +219,7 @@ fn test_hashset() { &[Token::Seq { len: Some(1) }, Token::I32(1), Token::SeqEnd], ); assert_ser_tokens( - &hashset![FnvBuildHasher; 1], + &hashset![foldhash::fast::FixedState; 1], &[Token::Seq { len: Some(1) }, Token::I32(1), Token::SeqEnd], ); } @@ -300,7 +299,7 @@ fn test_hashmap() { ], ); assert_ser_tokens( - &hashmap![FnvBuildHasher; 1 => 2], + &hashmap![foldhash::fast::FixedState; 1 => 2], &[ Token::Map { len: Some(1) }, Token::I32(1), From e9c399c822aad494ab1e935a95f1a591a99b44ad Mon Sep 17 00:00:00 2001 From: Tamme Dittrich Date: Thu, 5 Dec 2024 17:26:13 +0100 Subject: [PATCH 240/258] Mark generated `impl de::Visitor` blocks as `#[automatically_derived]` This hides the generated visitors and field visitors from code coverage. --- serde_derive/src/de.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index 979964cd0..1b533e19c 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -424,6 +424,7 @@ fn deserialize_unit_struct(params: &Parameters, cattrs: &attr::Container) -> Fra lifetime: _serde::__private::PhantomData<&#delife ()>, } + #[automatically_derived] impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause { type Value = #this_type #ty_generics; @@ -559,6 +560,7 @@ fn deserialize_tuple( lifetime: _serde::__private::PhantomData<&#delife ()>, } + #[automatically_derived] impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause { type Value = #this_type #ty_generics; @@ -658,6 +660,7 @@ fn deserialize_tuple_in_place( lifetime: _serde::__private::PhantomData<&#delife ()>, } + #[automatically_derived] impl #in_place_impl_generics _serde::de::Visitor<#delife> for __Visitor #in_place_ty_generics #where_clause { type Value = (); @@ -1020,6 +1023,7 @@ fn deserialize_struct( let visitor_seed = match form { StructForm::ExternallyTagged(..) if has_flatten => Some(quote! { + #[automatically_derived] impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Visitor #de_ty_generics #where_clause { type Value = #this_type #ty_generics; @@ -1084,6 +1088,7 @@ fn deserialize_struct( lifetime: _serde::__private::PhantomData<&#delife ()>, } + #[automatically_derived] impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause { type Value = #this_type #ty_generics; @@ -1165,6 +1170,7 @@ fn deserialize_struct_in_place( lifetime: _serde::__private::PhantomData<&#delife ()>, } + #[automatically_derived] impl #in_place_impl_generics _serde::de::Visitor<#delife> for __Visitor #in_place_ty_generics #where_clause { type Value = (); @@ -1338,6 +1344,7 @@ fn deserialize_externally_tagged_enum( lifetime: _serde::__private::PhantomData<&#delife ()>, } + #[automatically_derived] impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause { type Value = #this_type #ty_generics; @@ -1618,6 +1625,7 @@ fn deserialize_adjacently_tagged_enum( lifetime: _serde::__private::PhantomData<&#delife ()>, } + #[automatically_derived] impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause { type Value = #this_type #ty_generics; @@ -2046,12 +2054,14 @@ fn deserialize_generated_identifier( #[doc(hidden)] struct __FieldVisitor; + #[automatically_derived] impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { type Value = __Field #lifetime; #visitor_impl } + #[automatically_derived] impl<'de> _serde::Deserialize<'de> for __Field #lifetime { #[inline] fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result @@ -2190,6 +2200,7 @@ fn deserialize_custom_identifier( lifetime: _serde::__private::PhantomData<&#delife ()>, } + #[automatically_derived] impl #de_impl_generics _serde::de::Visitor<#delife> for __FieldVisitor #de_ty_generics #where_clause { type Value = #this_type #ty_generics; From 9497463718813e83b69db4343bb6e8db5f28441e Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 10 Dec 2024 17:57:05 -0800 Subject: [PATCH 241/258] Mark all generated trait impls as #[automatically_derived] --- serde_derive/src/de.rs | 3 +++ serde_derive/src/ser.rs | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index 1b533e19c..4967e35d1 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -33,6 +33,7 @@ pub fn expand_derive_deserialize(input: &mut syn::DeriveInput) -> syn::Result(__deserializer: __D) -> #serde::__private::Result<#remote #ty_generics, __D::Error> where @@ -1606,6 +1607,7 @@ fn deserialize_adjacently_tagged_enum( lifetime: _serde::__private::PhantomData<&#delife ()>, } + #[automatically_derived] impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Seed #de_ty_generics #where_clause { type Value = #this_type #ty_generics; @@ -2920,6 +2922,7 @@ fn wrap_deserialize_with( lifetime: _serde::__private::PhantomData<&#delife ()>, } + #[automatically_derived] impl #de_impl_generics _serde::Deserialize<#delife> for __DeserializeWith #de_ty_generics #where_clause { fn deserialize<__D>(#deserializer_var: __D) -> _serde::__private::Result where diff --git a/serde_derive/src/ser.rs b/serde_derive/src/ser.rs index ecdf6470d..c92800d51 100644 --- a/serde_derive/src/ser.rs +++ b/serde_derive/src/ser.rs @@ -29,6 +29,7 @@ pub fn expand_derive_serialize(input: &mut syn::DeriveInput) -> syn::Result(__self: &#remote #ty_generics, __serializer: __S) -> #serde::__private::Result<__S::Ok, __S::Error> where @@ -733,6 +734,7 @@ fn serialize_adjacently_tagged_variant( phantom: _serde::__private::PhantomData<#this_type #ty_generics>, } + #[automatically_derived] impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause { fn serialize<__S>(&self, __serializer: __S) -> _serde::__private::Result<__S::Ok, __S::Error> where @@ -997,6 +999,7 @@ fn serialize_struct_variant_with_flatten( phantom: _serde::__private::PhantomData<#this_type #ty_generics>, } + #[automatically_derived] impl #wrapper_impl_generics _serde::Serialize for __EnumFlatten #wrapper_ty_generics #where_clause { fn serialize<__S>(&self, __serializer: __S) -> _serde::__private::Result<__S::Ok, __S::Error> where @@ -1239,6 +1242,7 @@ fn wrap_serialize_with( phantom: _serde::__private::PhantomData<#this_type #ty_generics>, } + #[automatically_derived] impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause { fn serialize<__S>(&#self_var, #serializer_var: __S) -> _serde::__private::Result<__S::Ok, __S::Error> where From ad8dd4148b5fabf0d643d4de604a0616f2796506 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 10 Dec 2024 18:05:39 -0800 Subject: [PATCH 242/258] Release 1.0.216 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index c5cf4f8f8..cac66df1e 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.215" +version = "1.0.216" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.215", path = "../serde_derive" } +serde_derive = { version = "=1.0.216", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index da1ecab00..83b545951 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.215")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.216")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 5c679b2ef..f281d758a 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.215" +version = "1.0.216" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index fbc9b9ec3..4d6a2834a 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.215")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.216")] #![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] // Ignored clippy lints #![allow( From dbb909136e610b9753dcd9ffcfb8f6a3f6510060 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 20 Dec 2024 04:20:26 -0800 Subject: [PATCH 243/258] Replace #[start] with extern fn main --- test_suite/no_std/src/main.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test_suite/no_std/src/main.rs b/test_suite/no_std/src/main.rs index f8ef34b44..e53389229 100644 --- a/test_suite/no_std/src/main.rs +++ b/test_suite/no_std/src/main.rs @@ -1,9 +1,12 @@ #![allow(internal_features)] -#![feature(lang_items, start)] +#![feature(lang_items)] #![no_std] +#![no_main] -#[start] -fn start(_argc: isize, _argv: *const *const u8) -> isize { +use core::ffi::c_int; + +#[no_mangle] +extern "C" fn main(_argc: c_int, _argv: *const *const u8) -> c_int { 0 } From eb5cd476ba7e71e22b0a856c1e78a3af1b7bbe0a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 20 Dec 2024 04:28:08 -0800 Subject: [PATCH 244/258] Drop #[lang = "eh_personality"] from no-std test --- test_suite/no_std/Cargo.toml | 6 ++++++ test_suite/no_std/src/main.rs | 6 ------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test_suite/no_std/Cargo.toml b/test_suite/no_std/Cargo.toml index 5bf7eb2d1..9c8f6aa54 100644 --- a/test_suite/no_std/Cargo.toml +++ b/test_suite/no_std/Cargo.toml @@ -10,4 +10,10 @@ libc = { version = "0.2", default-features = false } serde = { path = "../../serde", default-features = false } serde_derive = { path = "../../serde_derive" } +[profile.dev] +panic = "abort" + +[profile.release] +panic = "abort" + [workspace] diff --git a/test_suite/no_std/src/main.rs b/test_suite/no_std/src/main.rs index e53389229..71d553e10 100644 --- a/test_suite/no_std/src/main.rs +++ b/test_suite/no_std/src/main.rs @@ -1,5 +1,3 @@ -#![allow(internal_features)] -#![feature(lang_items)] #![no_std] #![no_main] @@ -10,10 +8,6 @@ extern "C" fn main(_argc: c_int, _argv: *const *const u8) -> c_int { 0 } -#[lang = "eh_personality"] -#[no_mangle] -pub extern "C" fn rust_eh_personality() {} - #[panic_handler] fn panic(_info: &core::panic::PanicInfo) -> ! { unsafe { From b9f93f99aaa90760d421b60b8de6273999ca8980 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 20 Dec 2024 04:30:14 -0800 Subject: [PATCH 245/258] Add no-std CI on stable compiler --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fd383e901..50139b6d0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,6 +52,7 @@ jobs: toolchain: ${{matrix.rust}} - run: cd serde && cargo build --features rc - run: cd serde && cargo build --no-default-features + - run: cd test_suite/no_std && cargo build nightly: name: Rust nightly ${{matrix.os == 'windows' && '(windows)' || ''}} From b6f339ca3676584e1c26028b4040c337b0105e34 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 26 Dec 2024 18:33:27 -0800 Subject: [PATCH 246/258] Resolve repr_packed_without_abi clippy lint in tests warning: item uses `packed` representation without ABI-qualification --> test_suite/tests/test_gen.rs:774:5 | 772 | #[repr(packed)] | ------ `packed` representation set here 773 | #[allow(dead_code)] 774 | / struct Packed { 775 | | x: u8, 776 | | y: u16, 777 | | } | |_____^ | = warning: unqualified `#[repr(packed)]` defaults to `#[repr(Rust, packed)]`, which has no stable ABI = help: qualify the desired ABI explicity via `#[repr(C, packed)]` or `#[repr(Rust, packed)]` = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#repr_packed_without_abi note: the lint level is defined here --> test_suite/tests/test_gen.rs:5:9 | 5 | #![deny(warnings)] | ^^^^^^^^ = note: `#[warn(clippy::repr_packed_without_abi)]` implied by `#[warn(warnings)]` warning: item uses `packed` representation without ABI-qualification --> test_suite/tests/test_gen.rs:919:1 | 918 | #[repr(packed)] | ------ `packed` representation set here 919 | / pub struct RemotePacked { 920 | | pub a: u16, 921 | | pub b: u32, 922 | | } | |_^ | = warning: unqualified `#[repr(packed)]` defaults to `#[repr(Rust, packed)]`, which has no stable ABI = help: qualify the desired ABI explicity via `#[repr(C, packed)]` or `#[repr(Rust, packed)]` = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#repr_packed_without_abi warning: item uses `packed` representation without ABI-qualification --> test_suite/tests/test_gen.rs:927:1 | 925 | #[repr(packed)] | ------ `packed` representation set here 926 | #[serde(remote = "RemotePacked")] 927 | / pub struct RemotePackedDef { 928 | | a: u16, 929 | | b: u32, 930 | | } | |_^ | = warning: unqualified `#[repr(packed)]` defaults to `#[repr(Rust, packed)]`, which has no stable ABI = help: qualify the desired ABI explicity via `#[repr(C, packed)]` or `#[repr(Rust, packed)]` = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#repr_packed_without_abi warning: item uses `packed` representation without ABI-qualification --> test_suite/tests/test_gen.rs:937:1 | 936 | #[repr(packed)] | ------ `packed` representation set here 937 | / pub struct RemotePackedNonCopy { 938 | | pub a: u16, 939 | | pub b: String, 940 | | } | |_^ | = warning: unqualified `#[repr(packed)]` defaults to `#[repr(Rust, packed)]`, which has no stable ABI = help: qualify the desired ABI explicity via `#[repr(C, packed)]` or `#[repr(Rust, packed)]` = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#repr_packed_without_abi warning: item uses `packed` representation without ABI-qualification --> test_suite/tests/test_gen.rs:945:1 | 943 | #[repr(packed)] | ------ `packed` representation set here 944 | #[serde(remote = "RemotePackedNonCopy")] 945 | / pub struct RemotePackedNonCopyDef { 946 | | a: u16, 947 | | b: String, 948 | | } | |_^ | = warning: unqualified `#[repr(packed)]` defaults to `#[repr(Rust, packed)]`, which has no stable ABI = help: qualify the desired ABI explicity via `#[repr(C, packed)]` or `#[repr(Rust, packed)]` = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#repr_packed_without_abi --- test_suite/tests/test_gen.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test_suite/tests/test_gen.rs b/test_suite/tests/test_gen.rs index ed9dc725e..e7338e359 100644 --- a/test_suite/tests/test_gen.rs +++ b/test_suite/tests/test_gen.rs @@ -769,7 +769,7 @@ fn test_gen() { } #[derive(Serialize)] - #[repr(packed)] + #[repr(C, packed)] #[allow(dead_code)] struct Packed { x: u8, @@ -915,14 +915,14 @@ where ////////////////////////////////////////////////////////////////////////// -#[repr(packed)] +#[repr(C, packed)] pub struct RemotePacked { pub a: u16, pub b: u32, } #[derive(Serialize)] -#[repr(packed)] +#[repr(C, packed)] #[serde(remote = "RemotePacked")] pub struct RemotePackedDef { a: u16, @@ -933,14 +933,14 @@ impl Drop for RemotePackedDef { fn drop(&mut self) {} } -#[repr(packed)] +#[repr(C, packed)] pub struct RemotePackedNonCopy { pub a: u16, pub b: String, } #[derive(Deserialize)] -#[repr(packed)] +#[repr(C, packed)] #[serde(remote = "RemotePackedNonCopy")] pub struct RemotePackedNonCopyDef { a: u16, From cb6eaea151b831db36457fff17f16a195702dad4 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 3 Aug 2024 15:12:21 +0500 Subject: [PATCH 247/258] Fix roundtrip inconsistency: - deserialization of flatten unit variant is possible - serialization of such variant gives Err("can only flatten structs and maps (got an enum)") --- serde/src/private/ser.rs | 6 +++-- test_suite/tests/test_annotations.rs | 35 ++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/serde/src/private/ser.rs b/serde/src/private/ser.rs index ebfeba97e..2f2073901 100644 --- a/serde/src/private/ser.rs +++ b/serde/src/private/ser.rs @@ -54,6 +54,7 @@ enum Unsupported { Sequence, Tuple, TupleStruct, + #[cfg(not(any(feature = "std", feature = "alloc")))] Enum, } @@ -70,6 +71,7 @@ impl Display for Unsupported { Unsupported::Sequence => formatter.write_str("a sequence"), Unsupported::Tuple => formatter.write_str("a tuple"), Unsupported::TupleStruct => formatter.write_str("a tuple struct"), + #[cfg(not(any(feature = "std", feature = "alloc")))] Unsupported::Enum => formatter.write_str("an enum"), } } @@ -1095,9 +1097,9 @@ where self, _: &'static str, _: u32, - _: &'static str, + variant: &'static str, ) -> Result { - Err(Self::bad_type(Unsupported::Enum)) + self.0.serialize_entry(variant, &()) } fn serialize_newtype_struct( diff --git a/test_suite/tests/test_annotations.rs b/test_suite/tests/test_annotations.rs index 685bf329d..878c88981 100644 --- a/test_suite/tests/test_annotations.rs +++ b/test_suite/tests/test_annotations.rs @@ -2655,11 +2655,46 @@ mod flatten { #[derive(Debug, PartialEq, Serialize, Deserialize)] enum Enum { + Unit, Newtype(HashMap), Tuple(u32, u32), Struct { index: u32, value: u32 }, } + #[test] + fn unit() { + let value = Flatten { + data: Enum::Unit, + extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]), + }; + assert_tokens( + &value, + &[ + Token::Map { len: None }, + // data + Token::Str("Unit"), // variant + Token::Unit, + // extra + Token::Str("extra_key"), + Token::Str("extra value"), + Token::MapEnd, + ], + ); + assert_de_tokens( + &value, + &[ + Token::Map { len: None }, + // extra + Token::Str("extra_key"), + Token::Str("extra value"), + // data + Token::Str("Unit"), // variant + Token::Unit, + Token::MapEnd, + ], + ); + } + #[test] fn newtype() { assert_tokens( From 930401b0dd58a809fce34da091b8aa3d6083cb33 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 27 Dec 2024 12:41:22 -0800 Subject: [PATCH 248/258] Release 1.0.217 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index cac66df1e..a569bc18e 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.216" +version = "1.0.217" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.216", path = "../serde_derive" } +serde_derive = { version = "=1.0.217", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 83b545951..efa3780af 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.216")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.217")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index f281d758a..c0222e34b 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.216" +version = "1.0.217" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index 4d6a2834a..6b3f86004 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.216")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.217")] #![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] // Ignored clippy lints #![allow( From 1e2f931d0cf553039ffce4f5527137f6db119574 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 22 Jan 2025 19:30:32 -0800 Subject: [PATCH 249/258] Remove **/*.rs.bk from project-specific gitignore Cargo stopped generating this in its project template 5 years ago. It would belong in a global gitignore instead. --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 165eb22d0..2a8a14e9e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ target/ -**/*.rs.bk *.sw[po] Cargo.lock From dc3031b614eba65d8930bc90daabc45e627230d1 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 22 Jan 2025 19:36:55 -0800 Subject: [PATCH 250/258] Remove *.sw[po] from gitignore This belongs in someone's global gitignore. --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 2a8a14e9e..2c96eb1b6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ target/ -*.sw[po] Cargo.lock From 04ff3e8f950eb9862759781d85ec29d906917b70 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 23 Jan 2025 01:41:05 -0800 Subject: [PATCH 251/258] More precise gitignore patterns --- .gitignore | 4 ++-- test_suite/no_std/.gitignore | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 test_suite/no_std/.gitignore diff --git a/.gitignore b/.gitignore index 2c96eb1b6..e9e21997b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ -target/ -Cargo.lock +/target/ +/Cargo.lock diff --git a/test_suite/no_std/.gitignore b/test_suite/no_std/.gitignore new file mode 100644 index 000000000..e9e21997b --- /dev/null +++ b/test_suite/no_std/.gitignore @@ -0,0 +1,2 @@ +/target/ +/Cargo.lock From 7cd4d84cac270200ed2ab1adb3a2847fa54a3766 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 6 Feb 2025 19:35:51 -0800 Subject: [PATCH 252/258] Update ui test suite to nightly-2025-02-07 --- test_suite/tests/ui/with/incorrect_type.stderr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test_suite/tests/ui/with/incorrect_type.stderr b/test_suite/tests/ui/with/incorrect_type.stderr index cfddf1cec..fd08ebada 100644 --- a/test_suite/tests/ui/with/incorrect_type.stderr +++ b/test_suite/tests/ui/with/incorrect_type.stderr @@ -28,7 +28,7 @@ note: function defined here --> tests/ui/with/incorrect_type.rs:9:12 | 9 | pub fn serialize(_: S) -> Result { - | ^^^^^^^^^ ---- + | ^^^^^^^^^ error[E0277]: the trait bound `&u8: Serializer` is not satisfied --> tests/ui/with/incorrect_type.rs:15:25 @@ -79,7 +79,7 @@ note: function defined here --> tests/ui/with/incorrect_type.rs:9:12 | 9 | pub fn serialize(_: S) -> Result { - | ^^^^^^^^^ ---- + | ^^^^^^^^^ error[E0277]: the trait bound `&u8: Serializer` is not satisfied --> tests/ui/with/incorrect_type.rs:18:35 From aaccac7413fa44c74ca40c3b7d956a70bb144330 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 9 Feb 2025 17:52:36 -0800 Subject: [PATCH 253/258] Unset doc-scrape-examples for lib target False is the default value since Cargo PR 11499. --- serde/Cargo.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index a569bc18e..259e72971 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -20,9 +20,6 @@ serde_derive = { version = "1", optional = true, path = "../serde_derive" } [dev-dependencies] serde_derive = { version = "1", path = "../serde_derive" } -[lib] -doc-scrape-examples = false - [package.metadata.playground] features = ["derive", "rc"] From abe71944803429f3ba160528237f66689a0440dd Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 11 Feb 2025 18:19:35 -0800 Subject: [PATCH 254/258] Update ui test suite to nightly-2025-02-12 --- test_suite/tests/ui/remote/unknown_field.stderr | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test_suite/tests/ui/remote/unknown_field.stderr b/test_suite/tests/ui/remote/unknown_field.stderr index f7efacdef..5c851ce1e 100644 --- a/test_suite/tests/ui/remote/unknown_field.stderr +++ b/test_suite/tests/ui/remote/unknown_field.stderr @@ -6,8 +6,9 @@ error[E0609]: no field `b` on type `&remote::S` | help: a field with a similar name exists | -12 | a: u8, - | ~ +12 - b: u8, +12 + a: u8, + | error[E0560]: struct `remote::S` has no field named `b` --> tests/ui/remote/unknown_field.rs:12:5 From 85cb0c478e249e47b897dbfe59e5d271377e0bc3 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 19 Feb 2025 20:51:41 -0800 Subject: [PATCH 255/258] Convert html links to intra-doc links --- serde/src/de/mod.rs | 4 ++-- serde/src/macros.rs | 6 +++--- serde/src/ser/impossible.rs | 16 ++++++++-------- serde/src/ser/mod.rs | 23 +++++++++++------------ 4 files changed, 24 insertions(+), 25 deletions(-) diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index b86ebe5ed..540632f4a 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -101,8 +101,8 @@ //! - SocketAddrV6 //! //! [Implementing `Deserialize`]: https://serde.rs/impl-deserialize.html -//! [`Deserialize`]: ../trait.Deserialize.html -//! [`Deserializer`]: ../trait.Deserializer.html +//! [`Deserialize`]: crate::Deserialize +//! [`Deserializer`]: crate::Deserializer //! [`LinkedHashMap`]: https://docs.rs/linked-hash-map/*/linked_hash_map/struct.LinkedHashMap.html //! [`postcard`]: https://github.com/jamesmunns/postcard //! [`linked-hash-map`]: https://crates.io/crates/linked-hash-map diff --git a/serde/src/macros.rs b/serde/src/macros.rs index 9646cb375..82a1105b1 100644 --- a/serde/src/macros.rs +++ b/serde/src/macros.rs @@ -104,9 +104,9 @@ /// # } /// ``` /// -/// [`Deserializer`]: trait.Deserializer.html -/// [`Visitor`]: de/trait.Visitor.html -/// [`Deserializer::deserialize_any`]: trait.Deserializer.html#tymethod.deserialize_any +/// [`Deserializer`]: crate::Deserializer +/// [`Visitor`]: crate::de::Visitor +/// [`Deserializer::deserialize_any`]: crate::Deserializer::deserialize_any #[macro_export(local_inner_macros)] macro_rules! forward_to_deserialize_any { (<$visitor:ident: Visitor<$lifetime:tt>> $($func:ident)*) => { diff --git a/serde/src/ser/impossible.rs b/serde/src/ser/impossible.rs index 6432d5775..e2566b29a 100644 --- a/serde/src/ser/impossible.rs +++ b/serde/src/ser/impossible.rs @@ -49,14 +49,14 @@ use crate::ser::{ /// } /// ``` /// -/// [`Serializer`]: trait.Serializer.html -/// [`SerializeSeq`]: trait.SerializeSeq.html -/// [`SerializeTuple`]: trait.SerializeTuple.html -/// [`SerializeTupleStruct`]: trait.SerializeTupleStruct.html -/// [`SerializeTupleVariant`]: trait.SerializeTupleVariant.html -/// [`SerializeMap`]: trait.SerializeMap.html -/// [`SerializeStruct`]: trait.SerializeStruct.html -/// [`SerializeStructVariant`]: trait.SerializeStructVariant.html +/// [`Serializer`]: crate::Serializer +/// [`SerializeSeq`]: crate::ser::SerializeSeq +/// [`SerializeTuple`]: crate::ser::SerializeTuple +/// [`SerializeTupleStruct`]: crate::ser::SerializeTupleStruct +/// [`SerializeTupleVariant`]: crate::ser::SerializeTupleVariant +/// [`SerializeMap`]: crate::ser::SerializeMap +/// [`SerializeStruct`]: crate::ser::SerializeStruct +/// [`SerializeStructVariant`]: crate::ser::SerializeStructVariant pub struct Impossible { void: Void, ok: PhantomData, diff --git a/serde/src/ser/mod.rs b/serde/src/ser/mod.rs index fb0033ec0..23418f9f8 100644 --- a/serde/src/ser/mod.rs +++ b/serde/src/ser/mod.rs @@ -97,8 +97,8 @@ //! //! [Implementing `Serialize`]: https://serde.rs/impl-serialize.html //! [`LinkedHashMap`]: https://docs.rs/linked-hash-map/*/linked_hash_map/struct.LinkedHashMap.html -//! [`Serialize`]: ../trait.Serialize.html -//! [`Serializer`]: ../trait.Serializer.html +//! [`Serialize`]: crate::Serialize +//! [`Serializer`]: crate::Serializer //! [`postcard`]: https://github.com/jamesmunns/postcard //! [`linked-hash-map`]: https://crates.io/crates/linked-hash-map //! [`serde_derive`]: https://crates.io/crates/serde_derive @@ -173,8 +173,8 @@ macro_rules! declare_error_trait { /// } /// ``` /// - /// [`Path`]: https://doc.rust-lang.org/std/path/struct.Path.html - /// [`Serialize`]: ../trait.Serialize.html + /// [`Path`]: std::path::Path + /// [`Serialize`]: crate::Serialize fn custom(msg: T) -> Self where T: Display; @@ -345,7 +345,7 @@ pub trait Serializer: Sized { /// in-memory data structures may be simplified by using `Ok` to propagate /// the data structure around. /// - /// [`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html + /// [`io::Write`]: std::io::Write type Ok; /// The error type when some error occurs during serialization. @@ -769,7 +769,7 @@ pub trait Serializer: Sized { /// # fn main() {} /// ``` /// - /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None + /// [`None`]: core::option::Option::None fn serialize_none(self) -> Result; /// Serialize a [`Some(T)`] value. @@ -802,7 +802,7 @@ pub trait Serializer: Sized { /// # fn main() {} /// ``` /// - /// [`Some(T)`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.Some + /// [`Some(T)`]: core::option::Option::Some fn serialize_some(self, value: &T) -> Result where T: ?Sized + Serialize; @@ -1353,8 +1353,7 @@ pub trait Serializer: Sized { /// } /// ``` /// - /// [`String`]: https://doc.rust-lang.org/std/string/struct.String.html - /// [`serialize_str`]: #tymethod.serialize_str + /// [`serialize_str`]: Self::serialize_str #[cfg(any(feature = "std", feature = "alloc"))] fn collect_str(self, value: &T) -> Result where @@ -1805,9 +1804,9 @@ pub trait SerializeMap { /// care about performance or are not able to optimize `serialize_entry` any /// better than this. /// - /// [`Serialize`]: ../trait.Serialize.html - /// [`serialize_key`]: #tymethod.serialize_key - /// [`serialize_value`]: #tymethod.serialize_value + /// [`Serialize`]: crate::Serialize + /// [`serialize_key`]: Self::serialize_key + /// [`serialize_value`]: Self::serialize_value fn serialize_entry(&mut self, key: &K, value: &V) -> Result<(), Self::Error> where K: ?Sized + Serialize, From 2b44efb085aa219cb9f474983cb081731f4443d6 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 19 Feb 2025 21:08:50 -0800 Subject: [PATCH 256/258] Point standard library links to stable --- serde/Cargo.toml | 7 ++++++- serde_derive/Cargo.toml | 7 ++++++- serde_derive_internals/Cargo.toml | 7 ++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 259e72971..e99c4da30 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -26,7 +26,12 @@ features = ["derive", "rc"] [package.metadata.docs.rs] features = ["derive", "rc", "unstable"] targets = ["x86_64-unknown-linux-gnu"] -rustdoc-args = ["--generate-link-to-definition"] +rustdoc-args = [ + "--generate-link-to-definition", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org", +] # This cfg cannot be enabled, but it still forces Cargo to keep serde_derive's # version in lockstep with serde's, even if someone depends on the two crates diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index c0222e34b..0b473b286 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -32,4 +32,9 @@ serde = { version = "1", path = "../serde" } [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] -rustdoc-args = ["--generate-link-to-definition"] +rustdoc-args = [ + "--generate-link-to-definition", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org", +] diff --git a/serde_derive_internals/Cargo.toml b/serde_derive_internals/Cargo.toml index efd6df58c..264803a4e 100644 --- a/serde_derive_internals/Cargo.toml +++ b/serde_derive_internals/Cargo.toml @@ -22,4 +22,9 @@ syn = { workspace = true, features = ["clone-impls", "derive", "parsing", "print [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] -rustdoc-args = ["--generate-link-to-definition"] +rustdoc-args = [ + "--generate-link-to-definition", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org", +] From 7bfd518dd44a3fcf17bb6d46345c23fe7e60e8e3 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 19 Feb 2025 21:20:03 -0800 Subject: [PATCH 257/258] Release 1.0.218 --- serde/Cargo.toml | 4 ++-- serde/src/lib.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index e99c4da30..948f24d19 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.217" +version = "1.0.218" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -39,7 +39,7 @@ rustdoc-args = [ # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.217", path = "../serde_derive" } +serde_derive = { version = "=1.0.218", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/src/lib.rs b/serde/src/lib.rs index efa3780af..cba89efcf 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.217")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.218")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 0b473b286..b0a3e55c9 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "1.0.217" +version = "1.0.218" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index 6b3f86004..5216446ba 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.217")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.218")] #![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] // Ignored clippy lints #![allow( From 6a630cf2835efe74cfad8258d9433611f0a3151c Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 19 Feb 2025 21:26:32 -0800 Subject: [PATCH 258/258] Also link to stable proc_macro --- serde_derive/Cargo.toml | 1 + serde_derive_internals/Cargo.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index b0a3e55c9..393a5e0a3 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -37,4 +37,5 @@ rustdoc-args = [ "--extern-html-root-url=core=https://doc.rust-lang.org", "--extern-html-root-url=alloc=https://doc.rust-lang.org", "--extern-html-root-url=std=https://doc.rust-lang.org", + "--extern-html-root-url=proc_macro=https://doc.rust-lang.org", ] diff --git a/serde_derive_internals/Cargo.toml b/serde_derive_internals/Cargo.toml index 264803a4e..20bdbccc3 100644 --- a/serde_derive_internals/Cargo.toml +++ b/serde_derive_internals/Cargo.toml @@ -27,4 +27,5 @@ rustdoc-args = [ "--extern-html-root-url=core=https://doc.rust-lang.org", "--extern-html-root-url=alloc=https://doc.rust-lang.org", "--extern-html-root-url=std=https://doc.rust-lang.org", + "--extern-html-root-url=proc_macro=https://doc.rust-lang.org", ]