diff --git a/Cargo.lock b/Cargo.lock index 49156f28..ac54f2cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -98,14 +98,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" dependencies = [ "quote", - "syn", + "syn 1.0.107", ] [[package]] name = "cxx" -version = "1.0.91" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62" +checksum = "a9c00419335c41018365ddf7e4d5f1c12ee3659ddcf3e01974650ba1de73d038" dependencies = [ "cc", "cxxbridge-flags", @@ -115,9 +115,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.91" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690" +checksum = "fb8307ad413a98fff033c8545ecf133e3257747b3bae935e7602aab8aa92d4ca" dependencies = [ "cc", "codespan-reporting", @@ -125,31 +125,31 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn", + "syn 2.0.15", ] [[package]] name = "cxxbridge-flags" -version = "1.0.91" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf" +checksum = "edc52e2eb08915cb12596d29d55f0b5384f00d697a646dbd269b6ecb0fbd9d31" [[package]] name = "cxxbridge-macro" -version = "1.0.91" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892" +checksum = "631569015d0d8d54e6c241733f944042623ab6df7bc3be7466874b05fcdb1c5f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.15", ] [[package]] name = "darling" -version = "0.14.3" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0808e1bd8671fb44a113a14e13497557533369847788fa2ae912b6ebfce9fa8" +checksum = "e7c99d16b88c92aef47e58dadd53e87b4bd234c29934947a6cec8b466300f99b" dependencies = [ "darling_core", "darling_macro", @@ -157,27 +157,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.14.3" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "001d80444f28e193f30c2f293455da62dcf9a6b29918a4253152ae2b1de592cb" +checksum = "2ea05d2fcb27b53f7a98faddaf5f2914760330ab7703adfc9df13332b42189f9" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn", + "syn 2.0.15", ] [[package]] name = "darling_macro" -version = "0.14.3" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b36230598a2d5de7ec1c6f51f72d8a99a9208daff41de2084d06e3fd3ea56685" +checksum = "7bfb82b62b1b8a2a9808fb4caf844ede819a76cfc23b2827d7f94eefb49551eb" dependencies = [ "darling_core", "quote", - "syn", + "syn 2.0.15", ] [[package]] @@ -403,9 +403,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.51" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" +checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" dependencies = [ "unicode-ident", ] @@ -423,9 +423,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.23" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" dependencies = [ "proc-macro2", ] @@ -504,9 +504,9 @@ checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" [[package]] name = "serde" -version = "1.0.152" +version = "1.0.157" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +checksum = "707de5fcf5df2b5788fca98dd7eab490bc2fd9b7ef1404defc462833b83f25ca" dependencies = [ "serde_derive", ] @@ -525,13 +525,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.152" +version = "1.0.157" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +checksum = "78997f4555c22a7971214540c4a661291970619afd56de19f77e0de86296e1e5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.15", ] [[package]] @@ -595,7 +595,7 @@ dependencies = [ "rustversion", "serde", "serde_json", - "syn", + "syn 2.0.15", "trybuild", "version-sync", ] @@ -639,6 +639,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "termcolor" version = "1.2.0" @@ -650,22 +661,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.38" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.38" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.15", ] [[package]] @@ -797,7 +808,7 @@ dependencies = [ "pulldown-cmark", "regex", "semver", - "syn", + "syn 1.0.107", "toml", "url", ] @@ -829,7 +840,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 1.0.107", "wasm-bindgen-shared", ] @@ -851,7 +862,7 @@ checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.107", "wasm-bindgen-backend", "wasm-bindgen-shared", ] diff --git a/serde_with/CHANGELOG.md b/serde_with/CHANGELOG.md index 99262ede..b2917475 100644 --- a/serde_with/CHANGELOG.md +++ b/serde_with/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Changed + +* Update `syn` to v2 and `darling` to v0.20 (#578) + Update proc-macro dependencies. + This change should have no impact on users, but now uses the same dependency as `serde_derive`. + ## [2.3.2] - 2023-04-05 ### Changed diff --git a/serde_with/Cargo.toml b/serde_with/Cargo.toml index 5d6a54bb..63111f0d 100644 --- a/serde_with/Cargo.toml +++ b/serde_with/Cargo.toml @@ -67,7 +67,7 @@ hex = {version = "0.4.3", optional = true, default-features = false} indexmap_1 = {package = "indexmap", version = "1.8", optional = true, default-features = false, features = ["serde-1"]} # The derive feature is needed for the flattened_maybe macro. # https://github.com/jonasbb/serde_with/blob/eb1965a74a3be073ecd13ec05f02a01bc1c44309/serde_with/src/flatten_maybe.rs#L67 -serde = {version = "1.0.139", default-features = false, features = ["derive"] } +serde = {version = "1.0.157", default-features = false, features = ["derive"] } serde_json = {version = "1.0.45", optional = true, default-features = false} serde_with_macros = {path = "../serde_with_macros", version = "=2.3.2", optional = true} time_0_3 = {package = "time", version = "~0.3.11", optional = true, default-features = false} diff --git a/serde_with/src/flatten_maybe.rs b/serde_with/src/flatten_maybe.rs index b5fc7e1a..6dab1618 100644 --- a/serde_with/src/flatten_maybe.rs +++ b/serde_with/src/flatten_maybe.rs @@ -50,7 +50,7 @@ /// ``` #[macro_export] macro_rules! flattened_maybe { - ($fn:ident, $field:literal) => { + ($fn:ident, $field:tt) => { fn $fn<'de, T, D>(deserializer: D) -> $crate::__private__::Result where T: $crate::serde::Deserialize<'de>, diff --git a/serde_with_macros/CHANGELOG.md b/serde_with_macros/CHANGELOG.md index 0f256545..c0243328 100644 --- a/serde_with_macros/CHANGELOG.md +++ b/serde_with_macros/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Changed + +* Update `syn` to v2 and `darling` to v0.20 (#578) + Update proc-macro dependencies. + This change should have no impact on users, but now uses the same dependency as `serde_derive`. + ## [2.3.2] - 2023-04-05 No changes. diff --git a/serde_with_macros/Cargo.toml b/serde_with_macros/Cargo.toml index cbdb9276..42d8603b 100644 --- a/serde_with_macros/Cargo.toml +++ b/serde_with_macros/Cargo.toml @@ -30,7 +30,7 @@ proc-macro = true maintenance = {status = "actively-developed"} [dependencies] -darling = "0.14.0" +darling = "0.20.0" proc-macro2 = "1.0.1" quote = "1.0.0" @@ -40,13 +40,13 @@ features = [ "full", "parsing", ] -version = "1.0.3" +version = "2.0.0" [dev-dependencies] expect-test = "1.4.0" pretty_assertions = "1.0.0" rustversion = "1.0.0" -serde = {version = "1.0.75", features = ["derive"]} +serde = {version = "1.0.157", features = ["derive"]} serde_json = "1.0.25" trybuild = "1.0.80" version-sync = "0.9.1" diff --git a/serde_with_macros/src/apply.rs b/serde_with_macros/src/apply.rs index 20496861..9cab8984 100644 --- a/serde_with_macros/src/apply.rs +++ b/serde_with_macros/src/apply.rs @@ -1,11 +1,11 @@ -use darling::{Error as DarlingError, FromMeta}; +use darling::{ast::NestedMeta, Error as DarlingError, FromMeta}; use proc_macro::TokenStream; use quote::ToTokens as _; use syn::{ parse::{Parse, ParseStream}, punctuated::Punctuated, - Attribute, Error, Field, NestedMeta, Path, Token, Type, TypeArray, TypeGroup, TypeParen, - TypePath, TypePtr, TypeReference, TypeSlice, TypeTuple, + Attribute, Error, Field, Path, Token, Type, TypeArray, TypeGroup, TypeParen, TypePath, TypePtr, + TypeReference, TypeSlice, TypeTuple, }; /// Parsed form of a single rule in the `#[apply(...)]` attribute. @@ -53,7 +53,7 @@ impl Parse for ApplyInput { } let rules: Punctuated = - input.parse_terminated(AddAttributesRule::parse)?; + input.parse_terminated(AddAttributesRule::parse, Token![,])?; Ok(Self { metas, rules }) } } diff --git a/serde_with_macros/src/lib.rs b/serde_with_macros/src/lib.rs index df038518..6ef732c5 100644 --- a/serde_with_macros/src/lib.rs +++ b/serde_with_macros/src/lib.rs @@ -49,6 +49,7 @@ mod utils; use crate::utils::{split_with_de_lifetime, DeriveOptions, IteratorExt as _}; use darling::{ + ast::NestedMeta, util::{Flag, Override}, Error as DarlingError, FromField, FromMeta, }; @@ -56,9 +57,12 @@ use proc_macro::TokenStream; use proc_macro2::{Span, TokenStream as TokenStream2}; use quote::quote; use syn::{ - parse_macro_input, parse_quote, punctuated::Pair, spanned::Spanned, AttributeArgs, DeriveInput, - Error, Field, Fields, GenericArgument, ItemEnum, ItemStruct, Meta, NestedMeta, Path, - PathArguments, ReturnType, Type, + parse::Parser, + parse_macro_input, parse_quote, + punctuated::{Pair, Punctuated}, + spanned::Spanned, + DeriveInput, Error, Field, Fields, GenericArgument, ItemEnum, ItemStruct, Meta, Path, + PathArguments, ReturnType, Token, Type, }; /// Apply function on every field of structs or enums @@ -184,7 +188,7 @@ where .iter() .flat_map(|variant| { variant.attrs.iter().filter_map(|attr| { - if attr.path.is_ident("serde_as") { + if attr.path().is_ident("serde_as") { Some( DarlingError::custom( "serde_as attribute is not allowed on enum variants", @@ -331,7 +335,7 @@ fn skip_serializing_none_add_attr_to_field(field: &mut Field) -> Result<(), Stri // Remove the `serialize_always` attribute let mut has_always_attr = false; field.attrs.retain(|attr| { - let has_attr = attr.path.is_ident("serialize_always"); + let has_attr = attr.path().is_ident("serialize_always"); has_always_attr |= has_attr; !has_attr }); @@ -363,7 +367,7 @@ fn skip_serializing_none_add_attr_to_field(field: &mut Field) -> Result<(), Stri let has_attr = field .attrs .iter() - .any(|attr| attr.path.is_ident("serialize_always")); + .any(|attr| attr.path().is_ident("serialize_always")); if has_attr { return Err("`serialize_always` may only be used on fields of type `Option`.".into()); } @@ -424,19 +428,25 @@ fn is_std_option(type_: &Type) -> bool { /// * with the name being `skip_serializing_if` fn field_has_attribute(field: &Field, namespace: &str, name: &str) -> bool { for attr in &field.attrs { - if attr.path.is_ident(namespace) { + if attr.path().is_ident(namespace) { // Ignore non parsable attributes, as these are not important for us - if let Ok(Meta::List(expr)) = attr.parse_meta() { - for expr in expr.nested { + if let Meta::List(expr) = &attr.meta { + let nested = match Punctuated::::parse_terminated + .parse2(expr.tokens.clone()) + { + Ok(nested) => nested, + Err(_) => continue, + }; + for expr in nested { match expr { - NestedMeta::Meta(Meta::NameValue(expr)) => { + Meta::NameValue(expr) => { if let Some(ident) = expr.path.get_ident() { if *ident == name { return true; } } } - NestedMeta::Meta(Meta::Path(expr)) => { + Meta::Path(expr) => { if let Some(ident) = expr.get_ident() { if *ident == name { return true; @@ -590,28 +600,32 @@ pub fn serde_as(args: TokenStream, input: TokenStream) -> TokenStream { alt_crate_path: Option, } - let args: AttributeArgs = parse_macro_input!(args); - let container_options = match SerdeContainerOptions::from_list(&args) { - Ok(v) => v, - Err(e) => { - return TokenStream::from(e.write_errors()); - } - }; + match NestedMeta::parse_meta_list(args.into()) { + Ok(list) => { + let container_options = match SerdeContainerOptions::from_list(&list) { + Ok(v) => v, + Err(e) => { + return TokenStream::from(e.write_errors()); + } + }; - let serde_with_crate_path = container_options - .alt_crate_path - .unwrap_or_else(|| syn::parse_quote!(::serde_with)); + let serde_with_crate_path = container_options + .alt_crate_path + .unwrap_or_else(|| syn::parse_quote!(::serde_with)); - // Convert any error message into a nice compiler error - let res = match apply_function_to_struct_and_enum_fields_darling( - input, - &serde_with_crate_path, - |field| serde_as_add_attr_to_field(field, &serde_with_crate_path), - ) { - Ok(res) => res, - Err(err) => err.write_errors(), - }; - TokenStream::from(res) + // Convert any error message into a nice compiler error + let res = match apply_function_to_struct_and_enum_fields_darling( + input, + &serde_with_crate_path, + |field| serde_as_add_attr_to_field(field, &serde_with_crate_path), + ) { + Ok(res) => res, + Err(err) => err.write_errors(), + }; + TokenStream::from(res) + } + Err(e) => TokenStream::from(DarlingError::from(e).write_errors()), + } } /// Inspect the field and convert the `serde_as` attribute into the classical `serde` @@ -622,7 +636,6 @@ fn serde_as_add_attr_to_field( #[derive(FromField)] #[darling(attributes(serde_as))] struct SerdeAsOptions { - #[darling(rename = "as")] r#as: Option, deserialize_as: Option, serialize_as: Option, @@ -679,12 +692,36 @@ fn serde_as_add_attr_to_field( } } - // Check if there even is any `serde_as` attribute and exit early if not. - if !field - .attrs - .iter() - .any(|attr| attr.path.is_ident("serde_as")) - { + // syn v2 no longer supports keywords in the path position of an attribute. + // That breaks #[serde_as(as = "FooBar")], since `as` is a keyword. + // For each attribute, that is named `serde_as`, we replace the `as` keyword with `r#as`. + let mut has_serde_as = false; + field.attrs.iter_mut().for_each(|attr| { + if attr.path().is_ident("serde_as") { + // We found a `serde_as` attribute. + // Remember that such that we can quick exit otherwise + has_serde_as = true; + + if let Meta::List(metalist) = &mut attr.meta { + metalist.tokens = std::mem::take(&mut metalist.tokens) + .into_iter() + .map(|token| { + use proc_macro2::{Ident, TokenTree}; + + // Replace `as` with `r#as`. + match token { + TokenTree::Ident(ident) if ident == "as" => { + TokenTree::Ident(Ident::new_raw("as", ident.span())) + } + _ => token, + } + }) + .collect(); + } + } + }); + // If there is no `serde_as` attribute, we can exit early. + if !has_serde_as { return Ok(()); } let serde_as_options = SerdeAsOptions::from_field(field)?; diff --git a/serde_with_macros/tests/compile-fail/serde_as.stderr b/serde_with_macros/tests/compile-fail/serde_as.stderr index 5f1022bd..d6f1e296 100644 --- a/serde_with_macros/tests/compile-fail/serde_as.stderr +++ b/serde_with_macros/tests/compile-fail/serde_as.stderr @@ -88,7 +88,13 @@ error: Unknown field: `unknw2` 59 | #[serde_as(unknwn1 = "Hello", unknw2 = "World")] | ^^^^^^ -error: Unable to parse attribute: expected literal +error: Unknown literal value `123` + --> tests/compile-fail/serde_as.rs:67:31 + | +67 | #[serde_as(serialize_as = "123", deserialize_as = DisplayFromStr)] + | ^^^^^ + +error: Unexpected literal type `path` --> tests/compile-fail/serde_as.rs:67:55 | 67 | #[serde_as(serialize_as = "123", deserialize_as = DisplayFromStr)]