From 2318d5a90beb4b1363b9376493f4b8db4dc1f6be Mon Sep 17 00:00:00 2001
From: Manish Goregaokar <manishsmail@gmail.com>
Date: Thu, 13 Apr 2023 14:24:56 -0700
Subject: [PATCH] Update syn to 2.0

---
 Cargo.lock                              |  34 ++--
 ffi/gn/Cargo.lock                       |  49 +++--
 ffi/gn/icu4x/BUILD.gn                   |  75 ++++++-
 provider/datagen/Cargo.toml             |   2 +-
 provider/macros/Cargo.toml              |   2 +-
 provider/macros/src/lib.rs              | 251 +++++++++++++++++-------
 provider/macros/src/tests.rs            |  35 ++--
 utils/databake/Cargo.toml               |   2 +-
 utils/databake/derive/Cargo.toml        |   4 +-
 utils/databake/derive/src/lib.rs        |   2 +-
 utils/yoke/derive/Cargo.toml            |   4 +-
 utils/zerofrom/derive/Cargo.toml        |   4 +-
 utils/zerovec/derive/Cargo.toml         |   2 +-
 utils/zerovec/derive/src/lib.rs         |   7 +-
 utils/zerovec/derive/src/make_ule.rs    |  23 +--
 utils/zerovec/derive/src/make_varule.rs |  16 +-
 utils/zerovec/derive/src/utils.rs       |  29 ++-
 17 files changed, 349 insertions(+), 192 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index e99a420bf4c..62b74916dd1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -790,7 +790,7 @@ dependencies = [
  "databake-derive",
  "proc-macro2",
  "quote",
- "syn 1.0.109",
+ "syn 2.0.15",
 ]
 
 [[package]]
@@ -800,8 +800,8 @@ dependencies = [
  "databake",
  "proc-macro2",
  "quote",
- "syn 1.0.109",
- "synstructure",
+ "syn 2.0.15",
+ "synstructure 0.13.0",
 ]
 
 [[package]]
@@ -1768,7 +1768,7 @@ dependencies = [
  "serde-aux",
  "serde_json",
  "simple_logger",
- "syn 1.0.109",
+ "syn 2.0.15",
  "tinystr",
  "toml",
  "writeable",
@@ -2080,7 +2080,7 @@ dependencies = [
  "icu_provider",
  "proc-macro2",
  "quote",
- "syn 1.0.109",
+ "syn 2.0.15",
 ]
 
 [[package]]
@@ -3614,6 +3614,18 @@ dependencies = [
  "unicode-xid",
 ]
 
+[[package]]
+name = "synstructure"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.15",
+ "unicode-xid",
+]
+
 [[package]]
 name = "sys-info"
 version = "0.9.1"
@@ -4719,8 +4731,8 @@ version = "0.7.1"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.109",
- "synstructure",
+ "syn 2.0.15",
+ "synstructure 0.13.0",
  "yoke",
  "zerovec",
 ]
@@ -4738,8 +4750,8 @@ version = "0.1.2"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.109",
- "synstructure",
+ "syn 2.0.15",
+ "synstructure 0.13.0",
  "zerofrom",
  "zerovec",
 ]
@@ -4775,8 +4787,8 @@ dependencies = [
  "quote",
  "serde",
  "serde_json",
- "syn 1.0.109",
- "synstructure",
+ "syn 2.0.15",
+ "synstructure 0.12.6",
  "zerofrom",
  "zerovec",
 ]
diff --git a/ffi/gn/Cargo.lock b/ffi/gn/Cargo.lock
index 8ac8995a438..90b6847056c 100644
--- a/ffi/gn/Cargo.lock
+++ b/ffi/gn/Cargo.lock
@@ -36,7 +36,7 @@ dependencies = [
  "argh_shared",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -115,7 +115,7 @@ dependencies = [
  "diplomat_core",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -136,7 +136,7 @@ dependencies = [
  "serde",
  "smallvec",
  "strck_ident",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -147,7 +147,7 @@ checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -457,7 +457,7 @@ version = "1.2.0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 2.0.15",
 ]
 
 [[package]]
@@ -678,7 +678,7 @@ checksum = "d7e29c4601e36bcec74a223228dce795f4cd3616341a4af93520ca1a837c087d"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -731,6 +731,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 = "synstructure"
 version = "0.12.6"
@@ -739,7 +750,19 @@ checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
+ "unicode-xid",
+]
+
+[[package]]
+name = "synstructure"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.15",
  "unicode-xid",
 ]
 
@@ -983,8 +1006,8 @@ version = "0.7.1"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
- "synstructure",
+ "syn 2.0.15",
+ "synstructure 0.13.0",
 ]
 
 [[package]]
@@ -1000,8 +1023,8 @@ version = "0.1.2"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
- "synstructure",
+ "syn 2.0.15",
+ "synstructure 0.13.0",
 ]
 
 [[package]]
@@ -1019,6 +1042,6 @@ version = "0.9.4"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
- "synstructure",
+ "syn 2.0.15",
+ "synstructure 0.12.6",
 ]
diff --git a/ffi/gn/icu4x/BUILD.gn b/ffi/gn/icu4x/BUILD.gn
index 5c2bcc4537c..f0c47323386 100644
--- a/ffi/gn/icu4x/BUILD.gn
+++ b/ffi/gn/icu4x/BUILD.gn
@@ -630,7 +630,7 @@ rust_proc_macro("icu_provider_macros-v1_2_0") {
   deps = []
   deps += [ ":proc-macro2-v1_0_56" ]
   deps += [ ":quote-v1_0_26" ]
-  deps += [ ":syn-v1_0_109" ]
+  deps += [ ":syn-v2_0_15" ]
 
   rustenv = []
 
@@ -1088,7 +1088,7 @@ rust_library("strck_ident-v0_1_2") {
 
 rust_library("syn-v1_0_109") {
   crate_name = "syn"
-  crate_root = "//ffi/gn/vendor/syn/src/lib.rs"
+  crate_root = "//ffi/gn/vendor/syn-1.0.109/src/lib.rs"
   output_name = "syn-1f55ec6ab1286b6d"
 
   deps = []
@@ -1107,7 +1107,6 @@ rust_library("syn-v1_0_109") {
     "--cfg=feature=\"default\"",
     "--cfg=feature=\"derive\"",
     "--cfg=feature=\"extra-traits\"",
-    "--cfg=feature=\"fold\"",
     "--cfg=feature=\"full\"",
     "--cfg=feature=\"parsing\"",
     "--cfg=feature=\"printing\"",
@@ -1120,9 +1119,42 @@ rust_library("syn-v1_0_109") {
   visibility = [ ":*" ]
 }
 
+rust_library("syn-v2_0_15") {
+  crate_name = "syn"
+  crate_root = "//ffi/gn/vendor/syn/src/lib.rs"
+  output_name = "syn-81efed302294e4e7"
+
+  deps = []
+  deps += [ ":proc-macro2-v1_0_56" ]
+  deps += [ ":quote-v1_0_26" ]
+  deps += [ ":unicode-ident-v1_0_8" ]
+
+  rustenv = []
+
+  rustflags = [
+    "--cap-lints=allow",
+    "--edition=2021",
+    "-Cmetadata=81efed302294e4e7",
+    "-Cextra-filename=-81efed302294e4e7",
+    "--cfg=feature=\"clone-impls\"",
+    "--cfg=feature=\"default\"",
+    "--cfg=feature=\"derive\"",
+    "--cfg=feature=\"extra-traits\"",
+    "--cfg=feature=\"fold\"",
+    "--cfg=feature=\"full\"",
+    "--cfg=feature=\"parsing\"",
+    "--cfg=feature=\"printing\"",
+    "--cfg=feature=\"proc-macro\"",
+    "--cfg=feature=\"quote\"",
+    "--cfg=feature=\"visit\"",
+  ]
+
+  visibility = [ ":*" ]
+}
+
 rust_library("synstructure-v0_12_6") {
   crate_name = "synstructure"
-  crate_root = "//ffi/gn/vendor/synstructure/src/lib.rs"
+  crate_root = "//ffi/gn/vendor/synstructure-0.12.6/src/lib.rs"
   output_name = "synstructure-b30be16cba2970c4"
 
   deps = []
@@ -1145,6 +1177,31 @@ rust_library("synstructure-v0_12_6") {
   visibility = [ ":*" ]
 }
 
+rust_library("synstructure-v0_13_0") {
+  crate_name = "synstructure"
+  crate_root = "//ffi/gn/vendor/synstructure/src/lib.rs"
+  output_name = "synstructure-d99d51d75122a755"
+
+  deps = []
+  deps += [ ":proc-macro2-v1_0_56" ]
+  deps += [ ":quote-v1_0_26" ]
+  deps += [ ":syn-v2_0_15" ]
+  deps += [ ":unicode-xid-v0_2_4" ]
+
+  rustenv = []
+
+  rustflags = [
+    "--cap-lints=allow",
+    "--edition=2018",
+    "-Cmetadata=d99d51d75122a755",
+    "-Cextra-filename=-d99d51d75122a755",
+    "--cfg=feature=\"default\"",
+    "--cfg=feature=\"proc-macro\"",
+  ]
+
+  visibility = [ ":*" ]
+}
+
 rust_library("tinystr-v0_7_1") {
   crate_name = "tinystr"
   crate_root = "//utils/tinystr/src/lib.rs"
@@ -1339,8 +1396,8 @@ rust_proc_macro("yoke-derive-v0_7_1") {
   deps = []
   deps += [ ":proc-macro2-v1_0_56" ]
   deps += [ ":quote-v1_0_26" ]
-  deps += [ ":syn-v1_0_109" ]
-  deps += [ ":synstructure-v0_12_6" ]
+  deps += [ ":syn-v2_0_15" ]
+  deps += [ ":synstructure-v0_13_0" ]
 
   rustenv = []
 
@@ -1385,8 +1442,8 @@ rust_proc_macro("zerofrom-derive-v0_1_2") {
   deps = []
   deps += [ ":proc-macro2-v1_0_56" ]
   deps += [ ":quote-v1_0_26" ]
-  deps += [ ":syn-v1_0_109" ]
-  deps += [ ":synstructure-v0_12_6" ]
+  deps += [ ":syn-v2_0_15" ]
+  deps += [ ":synstructure-v0_13_0" ]
 
   rustenv = []
 
@@ -1432,7 +1489,7 @@ rust_proc_macro("zerovec-derive-v0_9_4") {
   deps = []
   deps += [ ":proc-macro2-v1_0_56" ]
   deps += [ ":quote-v1_0_26" ]
-  deps += [ ":syn-v1_0_109" ]
+  deps += [ ":syn-v2_0_15" ]
   deps += [ ":synstructure-v0_12_6" ]
 
   rustenv = []
diff --git a/provider/datagen/Cargo.toml b/provider/datagen/Cargo.toml
index 816c1c43498..bf7ec81c60c 100644
--- a/provider/datagen/Cargo.toml
+++ b/provider/datagen/Cargo.toml
@@ -73,7 +73,7 @@ rust-format = { version = "0.3.4", features = ["token_stream"] }
 serde = { version = "1.0", default-features = false, features = ["derive", "alloc"] }
 serde_json = { version = "1.0", default-features = false, features = ["alloc"] }
 serde-aux = { version = "4.1.2", default-features = false }
-syn = {version = "1.0", features = ["parsing"] }
+syn = {version = "2", features = ["parsing"] }
 tinystr = { version = "0.7.1", path = "../../utils/tinystr", features = ["alloc", "serde", "zerovec"], default-features = false }
 toml = "0.5"
 writeable = { version = "0.5.1", path = "../../utils/writeable" }
diff --git a/provider/macros/Cargo.toml b/provider/macros/Cargo.toml
index 92a962a505e..666ae6b1b0f 100644
--- a/provider/macros/Cargo.toml
+++ b/provider/macros/Cargo.toml
@@ -30,7 +30,7 @@ proc-macro = true
 [dependencies]
 proc-macro2 = "1.0.27"
 quote = "1.0.9"
-syn = { version = "1.0.73", features = ["full"]}
+syn = { version = "2", features = ["full", "parsing"]}
 
 [dev-dependencies]
 icu_provider = { path = "../core", features = ["macros"] }
diff --git a/provider/macros/src/lib.rs b/provider/macros/src/lib.rs
index fee0c8afa33..781d7d76cde 100644
--- a/provider/macros/src/lib.rs
+++ b/provider/macros/src/lib.rs
@@ -24,16 +24,16 @@
 
 extern crate proc_macro;
 use proc_macro::TokenStream;
+use proc_macro2::Span;
 use proc_macro2::TokenStream as TokenStream2;
 use quote::quote;
+use syn::parenthesized;
+use syn::parse::{self, Parse, ParseStream};
 use syn::parse_macro_input;
+use syn::punctuated::Punctuated;
 use syn::spanned::Spanned;
-use syn::AttributeArgs;
 use syn::DeriveInput;
-use syn::Lit;
-use syn::Meta;
-use syn::NestedMeta;
-
+use syn::{Ident, LitStr, Path, Token};
 #[cfg(test)]
 mod tests;
 
@@ -92,12 +92,167 @@ mod tests;
 /// implement it on the markers.
 pub fn data_struct(attr: TokenStream, item: TokenStream) -> TokenStream {
     TokenStream::from(data_struct_impl(
-        parse_macro_input!(attr as AttributeArgs),
+        parse_macro_input!(attr as DataStructArgs),
         parse_macro_input!(item as DeriveInput),
     ))
 }
 
-fn data_struct_impl(attr: AttributeArgs, input: DeriveInput) -> TokenStream2 {
+pub(crate) struct DataStructArgs {
+    args: Punctuated<DataStructArg, Token![,]>,
+}
+
+impl Parse for DataStructArgs {
+    fn parse(input: ParseStream<'_>) -> parse::Result<Self> {
+        let args = input.parse_terminated(DataStructArg::parse, Token![,])?;
+        Ok(Self { args })
+    }
+}
+struct DataStructArg {
+    marker_name: Path,
+    key_lit: Option<LitStr>,
+    fallback_by: Option<LitStr>,
+    extension_key: Option<LitStr>,
+    fallback_supplement: Option<LitStr>,
+}
+
+impl DataStructArg {
+    fn new(marker_name: Path) -> Self {
+        Self {
+            marker_name,
+            key_lit: None,
+            fallback_by: None,
+            extension_key: None,
+            fallback_supplement: None,
+        }
+    }
+}
+
+impl Parse for DataStructArg {
+    fn parse(input: ParseStream<'_>) -> parse::Result<Self> {
+        let path: Path = input.parse()?;
+
+        fn at_most_one_option<T>(
+            o: &mut Option<T>,
+            new: T,
+            name: &str,
+            span: Span,
+        ) -> parse::Result<()> {
+            if o.replace(new).is_some() {
+                Err(parse::Error::new(
+                    span,
+                    format!("marker() cannot contain multiple {name}s"),
+                ))
+            } else {
+                Ok(())
+            }
+        }
+
+        if path.is_ident("marker") {
+            let content;
+            let _paren = parenthesized!(content in input);
+            let mut marker_name: Option<Path> = None;
+            let mut key_lit: Option<LitStr> = None;
+            let mut fallback_by: Option<LitStr> = None;
+            let mut extension_key: Option<LitStr> = None;
+            let mut fallback_supplement: Option<LitStr> = None;
+            let punct = content.parse_terminated(DataStructMarkerArg::parse, Token![,])?;
+
+            for entry in punct.into_iter() {
+                match entry {
+                    DataStructMarkerArg::Path(path) => {
+                        at_most_one_option(&mut marker_name, path, "marker", input.span())?;
+                    }
+                    DataStructMarkerArg::NameValue(name, value) => {
+                        if name == "fallback_by" {
+                            at_most_one_option(
+                                &mut fallback_by,
+                                value,
+                                "fallback_by",
+                                input.span(),
+                            )?;
+                        } else if name == "extension_key" {
+                            at_most_one_option(
+                                &mut extension_key,
+                                value,
+                                "extension_key",
+                                input.span(),
+                            )?;
+                        } else if name == "fallback_supplement" {
+                            at_most_one_option(
+                                &mut fallback_supplement,
+                                value,
+                                "fallback_supplement",
+                                input.span(),
+                            )?;
+                        }
+                    }
+                    DataStructMarkerArg::Lit(lit) => {
+                        at_most_one_option(&mut key_lit, lit, "literal key", input.span())?;
+                    }
+                }
+            }
+            let marker_name = if let Some(marker_name) = marker_name {
+                marker_name
+            } else {
+                return Err(parse::Error::new(
+                    input.span(),
+                    "marker() must contain a marker!",
+                ));
+            };
+
+            Ok(Self {
+                marker_name,
+                key_lit,
+                fallback_by,
+                extension_key,
+                fallback_supplement,
+            })
+        } else {
+            let mut this = DataStructArg::new(path);
+            let lookahead = input.lookahead1();
+            if lookahead.peek(Token![=]) {
+                let _t: Token![=] = input.parse()?;
+                let lit: LitStr = input.parse()?;
+                this.key_lit = Some(lit);
+                Ok(this)
+            } else {
+                Ok(this)
+            }
+        }
+    }
+}
+
+/// A single argument to `marker()` in `#[data_struct(..., marker(...), ...)]
+enum DataStructMarkerArg {
+    Path(Path),
+    NameValue(Ident, LitStr),
+    Lit(LitStr),
+}
+impl Parse for DataStructMarkerArg {
+    fn parse(input: ParseStream<'_>) -> parse::Result<Self> {
+        let lookahead = input.lookahead1();
+        if lookahead.peek(LitStr) {
+            Ok(DataStructMarkerArg::Lit(input.parse()?))
+        } else {
+            let path: Path = input.parse()?;
+            let lookahead = input.lookahead1();
+            if lookahead.peek(Token![=]) {
+                let _tok: Token![=] = input.parse()?;
+                let ident = path.get_ident().ok_or_else(|| {
+                    parse::Error::new(input.span(), "Expected identifier before `=`, found path")
+                })?;
+                Ok(DataStructMarkerArg::NameValue(
+                    ident.clone(),
+                    input.parse()?,
+                ))
+            } else {
+                Ok(DataStructMarkerArg::Path(path))
+            }
+        }
+    }
+}
+
+fn data_struct_impl(attr: DataStructArgs, input: DeriveInput) -> TokenStream2 {
     if input.generics.type_params().count() > 0 {
         return syn::Error::new(
             input.generics.span(),
@@ -126,7 +281,7 @@ fn data_struct_impl(attr: AttributeArgs, input: DeriveInput) -> TokenStream2 {
     let bake_derive = input
         .attrs
         .iter()
-        .find(|a| a.path.is_ident("databake"))
+        .find(|a| a.path().is_ident("databake"))
         .map(|a| {
             quote! {
                 #[derive(databake::Bake)]
@@ -137,74 +292,22 @@ fn data_struct_impl(attr: AttributeArgs, input: DeriveInput) -> TokenStream2 {
 
     let mut result = TokenStream2::new();
 
-    for single_attr in attr.into_iter() {
-        let mut marker_name: Option<syn::Path> = None;
-        let mut key_lit: Option<syn::LitStr> = None;
-        let mut fallback_by: Option<syn::LitStr> = None;
-        let mut extension_key: Option<syn::LitStr> = None;
-        let mut fallback_supplement: Option<syn::LitStr> = None;
-
-        match single_attr {
-            NestedMeta::Meta(Meta::List(meta_list)) => {
-                match meta_list.path.get_ident() {
-                    Some(ident) if ident.to_string().as_str() == "marker" => (),
-                    _ => panic!("Meta list must be `marker(...)`"),
-                }
-                for inner_meta in meta_list.nested.into_iter() {
-                    match inner_meta {
-                        NestedMeta::Meta(Meta::Path(path)) => {
-                            marker_name = Some(path);
-                        }
-                        NestedMeta::Lit(Lit::Str(lit_str)) => {
-                            key_lit = Some(lit_str);
-                        }
-                        NestedMeta::Meta(Meta::NameValue(name_value)) => {
-                            let lit_str = match name_value.lit {
-                                Lit::Str(lit_str) => lit_str,
-                                _ => panic!("Values in marker() must be strings"),
-                            };
-                            let name_ident_str = match name_value.path.get_ident() {
-                                Some(ident) => ident.to_string(),
-                                None => panic!("Names in marker() must be identifiers"),
-                            };
-                            match name_ident_str.as_str() {
-                                "fallback_by" => fallback_by = Some(lit_str),
-                                "extension_key" => extension_key = Some(lit_str),
-                                "fallback_supplement" => fallback_supplement = Some(lit_str),
-                                _ => panic!("Invalid argument name in marker()"),
-                            }
-                        }
-                        _ => panic!("Invalid argument in marker()"),
-                    }
-                }
-            }
-            NestedMeta::Meta(Meta::NameValue(name_value)) => {
-                marker_name = Some(name_value.path);
-                match name_value.lit {
-                    syn::Lit::Str(lit_str) => key_lit = Some(lit_str),
-                    _ => panic!("Key must be a string"),
-                };
-            }
-            NestedMeta::Meta(Meta::Path(path)) => {
-                marker_name = Some(path);
-            }
-            _ => {
-                panic!("Invalid attribute to #[data_struct]")
-            }
-        }
-
-        let marker_name = match marker_name {
-            Some(path) => path,
-            None => panic!("#[data_struct] arguments must include a marker name"),
-        };
+    for single_attr in attr.args.into_iter() {
+        let DataStructArg {
+            marker_name,
+            key_lit,
+            fallback_by,
+            extension_key,
+            fallback_supplement,
+        } = single_attr;
 
-        let docs = if let Some(key_lit) = &key_lit {
-            let fallback_by_docs_str = match &fallback_by {
-                Some(fallback_by) => fallback_by.value(),
+        let docs = if let Some(ref key_lit) = key_lit {
+            let fallback_by_docs_str = match fallback_by {
+                Some(ref fallback_by) => fallback_by.value(),
                 None => "language (default)".to_string(),
             };
-            let extension_key_docs_str = match &extension_key {
-                Some(extension_key) => extension_key.value(),
+            let extension_key_docs_str = match extension_key {
+                Some(ref extension_key) => extension_key.value(),
                 None => "none (default)".to_string(),
             };
             format!("Marker type for [`{}`]: \"{}\"\n\n- Fallback priority: {}\n- Extension keyword: {}", name, key_lit.value(), fallback_by_docs_str, extension_key_docs_str)
@@ -221,7 +324,7 @@ fn data_struct_impl(attr: AttributeArgs, input: DeriveInput) -> TokenStream2 {
             }
         ));
 
-        if let Some(key_lit) = &key_lit {
+        if let Some(key_lit) = key_lit {
             let key_str = key_lit.value();
             let fallback_by_expr = if let Some(fallback_by_lit) = fallback_by {
                 match fallback_by_lit.value().as_str() {
diff --git a/provider/macros/src/tests.rs b/provider/macros/src/tests.rs
index 32be158c780..b985c1af522 100644
--- a/provider/macros/src/tests.rs
+++ b/provider/macros/src/tests.rs
@@ -5,16 +5,9 @@
 use crate::data_struct_impl;
 use proc_macro2::TokenStream as TokenStream2;
 use quote::quote;
-use syn::{DeriveInput, NestedMeta};
 
-fn check(attr: Vec<TokenStream2>, item: TokenStream2, expected: TokenStream2) {
-    let actual = data_struct_impl(
-        attr.into_iter()
-            .map(syn::parse2)
-            .collect::<syn::parse::Result<Vec<NestedMeta>>>()
-            .unwrap(),
-        syn::parse2::<DeriveInput>(item).unwrap(),
-    );
+fn check(attr: TokenStream2, item: TokenStream2, expected: TokenStream2) {
+    let actual = data_struct_impl(syn::parse2(attr).unwrap(), syn::parse2(item).unwrap());
     assert_eq!(expected.to_string(), actual.to_string());
 }
 
@@ -23,7 +16,7 @@ fn check(attr: Vec<TokenStream2>, item: TokenStream2, expected: TokenStream2) {
 fn test_basic() {
     // #[data_struct]
     check(
-        vec![],
+        quote!(),
         quote!(
             pub struct FooV1;
         ),
@@ -38,7 +31,7 @@ fn test_basic() {
 fn test_data_marker() {
     // #[data_struct(FooV1Marker)]
     check(
-        vec![quote!(FooV1Marker)],
+        quote!(FooV1Marker),
         quote!(
             pub struct FooV1;
         ),
@@ -58,7 +51,7 @@ fn test_data_marker() {
 fn test_keyed_data_marker() {
     // #[data_struct(BarV1Marker = "demo/bar@1")]
     check(
-        vec![quote!(BarV1Marker = "demo/bar@1")],
+        quote!(BarV1Marker = "demo/bar@1"),
         quote!(
             pub struct FooV1;
         ),
@@ -87,10 +80,10 @@ fn test_keyed_data_marker() {
 fn test_multi_named_keyed_data_marker() {
     // #[data_struct(FooV1Marker, BarV1Marker = "demo/bar@1", BazV1Marker = "demo/baz@1")]
     check(
-        vec![
-            quote!(FooV1Marker),
-            quote!(BarV1Marker = "demo/bar@1"),
-            quote!(BazV1Marker = "demo/baz@1"),
+        quote![
+            FooV1Marker,
+            BarV1Marker = "demo/bar@1",
+            BazV1Marker = "demo/baz@1",
         ],
         quote!(
             pub struct FooV1<'data>;
@@ -138,7 +131,7 @@ fn test_multi_named_keyed_data_marker() {
 #[test]
 fn test_databake() {
     check(
-        vec![quote!(BarV1Marker = "demo/bar@1")],
+        quote!(BarV1Marker = "demo/bar@1"),
         quote!(
             #[databake(path = test::path)]
             pub struct FooV1;
@@ -171,15 +164,15 @@ fn test_databake() {
 fn test_attributes() {
     // #[data_struct(FooV1Marker, marker(BarV1Marker, "demo/bar@1", fallback_by = "region", extension_kw = "ca"))]
     check(
-        vec![
-            quote!(FooV1Marker),
-            quote!(marker(
+        quote![
+            FooV1Marker,
+            marker(
                 BarV1Marker,
                 "demo/bar@1",
                 fallback_by = "region",
                 extension_key = "ca",
                 fallback_supplement = "collation"
-            )),
+            ),
         ],
         quote!(
             pub struct FooV1<'data>;
diff --git a/utils/databake/Cargo.toml b/utils/databake/Cargo.toml
index 5fbd9d7f918..5e199b064a9 100644
--- a/utils/databake/Cargo.toml
+++ b/utils/databake/Cargo.toml
@@ -36,5 +36,5 @@ derive = ["dep:databake-derive"]
 [dependencies]
 proc-macro2 = "1.0.27"
 quote = "1.0.9"
-syn = { version = "1.0.73", features = ["derive", "fold"] }
+syn = { version = "2", features = ["derive", "fold"] }
 databake-derive = { version = "0.1.3", path = "./derive", optional = true}
diff --git a/utils/databake/derive/Cargo.toml b/utils/databake/derive/Cargo.toml
index 643b463f7bc..1895abec091 100644
--- a/utils/databake/derive/Cargo.toml
+++ b/utils/databake/derive/Cargo.toml
@@ -33,8 +33,8 @@ path = "src/lib.rs"
 [dependencies]
 proc-macro2 = "1.0.27"
 quote = "1.0.9"
-syn = { version = "1.0.73", features = ["derive", "fold"] }
-synstructure = "0.12.4"
+syn = { version = "2", features = ["derive", "fold"] }
+synstructure = "0.13"
 
 [dev-dependencies]
 databake = { path = "..", features = ["derive"]}
diff --git a/utils/databake/derive/src/lib.rs b/utils/databake/derive/src/lib.rs
index e4267fec781..55967b1d2c0 100644
--- a/utils/databake/derive/src/lib.rs
+++ b/utils/databake/derive/src/lib.rs
@@ -56,7 +56,7 @@ fn bake_derive_impl(input: &DeriveInput) -> TokenStream2 {
     let path = input
         .attrs
         .iter()
-        .find(|a| a.path.is_ident("databake"))
+        .find(|a| a.path().is_ident("databake"))
         .expect("missing databake(path = ...) attribute")
         .parse_args::<PathAttr>()
         .unwrap()
diff --git a/utils/yoke/derive/Cargo.toml b/utils/yoke/derive/Cargo.toml
index d23a42c201c..374610bae8e 100644
--- a/utils/yoke/derive/Cargo.toml
+++ b/utils/yoke/derive/Cargo.toml
@@ -23,8 +23,8 @@ path = "src/lib.rs"
 [dependencies]
 proc-macro2 = "1.0.27"
 quote = "1.0.9"
-syn = { version = "1.0.73", features = ["derive", "fold"] }
-synstructure = "0.12.4"
+syn = { version = "2", features = ["derive", "fold"] }
+synstructure = "0.13"
 
 [dev-dependencies]
 yoke = { path = "..", features = ["derive"]}
diff --git a/utils/zerofrom/derive/Cargo.toml b/utils/zerofrom/derive/Cargo.toml
index ddbc7ac67e7..0d39a1c43a8 100644
--- a/utils/zerofrom/derive/Cargo.toml
+++ b/utils/zerofrom/derive/Cargo.toml
@@ -23,8 +23,8 @@ path = "src/lib.rs"
 [dependencies]
 proc-macro2 = "1.0.27"
 quote = "1.0.9"
-syn = { version = "1.0.73", features = ["derive", "fold"] }
-synstructure = "0.12.4"
+syn = { version = "2", features = ["derive", "fold", "visit"] }
+synstructure = "0.13"
 
 [dev-dependencies]
 zerofrom = { path = "..", features = ["derive"]}
diff --git a/utils/zerovec/derive/Cargo.toml b/utils/zerovec/derive/Cargo.toml
index 4f579494429..0ebe12ec7bb 100644
--- a/utils/zerovec/derive/Cargo.toml
+++ b/utils/zerovec/derive/Cargo.toml
@@ -23,7 +23,7 @@ path = "src/lib.rs"
 [dependencies]
 proc-macro2 = "1.0.27"
 quote = "1.0.9"
-syn = { version = "1.0.73", features = ["derive", "parsing"] }
+syn = { version = "2", features = ["derive", "parsing", "extra-traits"] }
 synstructure = "0.12.4"
 
 [dev-dependencies]
diff --git a/utils/zerovec/derive/src/lib.rs b/utils/zerovec/derive/src/lib.rs
index 5a0de642982..9c3007147ae 100644
--- a/utils/zerovec/derive/src/lib.rs
+++ b/utils/zerovec/derive/src/lib.rs
@@ -5,8 +5,7 @@
 //! Proc macros for generating `ULE`, `VarULE` impls and types for the `zerovec` crate
 
 use proc_macro::TokenStream;
-use syn::{parse_macro_input, AttributeArgs, DeriveInput};
-
+use syn::{parse_macro_input, DeriveInput, Ident};
 mod make_ule;
 mod make_varule;
 pub(crate) mod ule;
@@ -31,7 +30,7 @@ pub fn varule_derive(input: TokenStream) -> TokenStream {
 #[proc_macro_attribute]
 pub fn make_ule(attr: TokenStream, item: TokenStream) -> TokenStream {
     let input = parse_macro_input!(item as DeriveInput);
-    let attr = parse_macro_input!(attr as AttributeArgs);
+    let attr = parse_macro_input!(attr as Ident);
     TokenStream::from(make_ule::make_ule_impl(attr, input))
 }
 
@@ -39,6 +38,6 @@ pub fn make_ule(attr: TokenStream, item: TokenStream) -> TokenStream {
 #[proc_macro_attribute]
 pub fn make_varule(attr: TokenStream, item: TokenStream) -> TokenStream {
     let input = parse_macro_input!(item as DeriveInput);
-    let attr = parse_macro_input!(attr as AttributeArgs);
+    let attr = parse_macro_input!(attr as Ident);
     TokenStream::from(make_varule::make_varule_impl(attr, input))
 }
diff --git a/utils/zerovec/derive/src/make_ule.rs b/utils/zerovec/derive/src/make_ule.rs
index fb94cbc2cc5..f87fadb482d 100644
--- a/utils/zerovec/derive/src/make_ule.rs
+++ b/utils/zerovec/derive/src/make_ule.rs
@@ -6,15 +6,11 @@ use proc_macro2::TokenStream as TokenStream2;
 use quote::quote;
 
 use crate::utils::{self, FieldInfo, ZeroVecAttrs};
-use syn::spanned::Spanned;
-use syn::{
-    parse_quote, AttributeArgs, Data, DataEnum, DataStruct, DeriveInput, Error, Expr, Fields,
-    Ident, Lit,
-};
-
 use std::collections::HashSet;
+use syn::spanned::Spanned;
+use syn::{parse_quote, Data, DataEnum, DataStruct, DeriveInput, Error, Expr, Fields, Ident, Lit};
 
-pub fn make_ule_impl(attr: AttributeArgs, mut input: DeriveInput) -> TokenStream2 {
+pub fn make_ule_impl(ule_name: Ident, mut input: DeriveInput) -> TokenStream2 {
     if input.generics.type_params().next().is_some()
         || input.generics.lifetimes().next().is_some()
         || input.generics.const_params().next().is_some()
@@ -25,17 +21,6 @@ pub fn make_ule_impl(attr: AttributeArgs, mut input: DeriveInput) -> TokenStream
         )
         .to_compile_error();
     }
-
-    if attr.len() != 1 {
-        return Error::new(
-            input.span(),
-            "#[make_ule] takes one argument for the name of the ULE type it produces",
-        )
-        .to_compile_error();
-    }
-    let arg = &attr[0];
-    let ule_name: Ident = parse_quote!(#arg);
-
     let sp = input.span();
     let attrs = match utils::extract_attributes_common(&mut input.attrs, sp, false) {
         Ok(val) => val,
@@ -112,7 +97,7 @@ fn make_ule_enum_impl(
     let mut not_found = HashSet::new();
 
     for (i, variant) in enu.variants.iter().enumerate() {
-        if variant.fields != Fields::Unit {
+        if !matches!(variant.fields, Fields::Unit) {
             // This can be supported in the future, see zerovec/design_doc.md
             return Error::new(
                 variant.span(),
diff --git a/utils/zerovec/derive/src/make_varule.rs b/utils/zerovec/derive/src/make_varule.rs
index 62cf0d9dbed..b561ea51e17 100644
--- a/utils/zerovec/derive/src/make_varule.rs
+++ b/utils/zerovec/derive/src/make_varule.rs
@@ -8,11 +8,11 @@ use proc_macro2::TokenStream as TokenStream2;
 use quote::{quote, ToTokens};
 use syn::spanned::Spanned;
 use syn::{
-    parse_quote, AttributeArgs, Data, DeriveInput, Error, Field, Fields, GenericArgument, Ident,
-    Lifetime, PathArguments, Type,
+    parse_quote, Data, DeriveInput, Error, Field, Fields, GenericArgument, Ident, Lifetime,
+    PathArguments, Type,
 };
 
-pub fn make_varule_impl(attr: AttributeArgs, mut input: DeriveInput) -> TokenStream2 {
+pub fn make_varule_impl(ule_name: Ident, mut input: DeriveInput) -> TokenStream2 {
     if input.generics.type_params().next().is_some()
         || input.generics.const_params().next().is_some()
         || input.generics.lifetimes().count() > 1
@@ -44,16 +44,6 @@ pub fn make_varule_impl(attr: AttributeArgs, mut input: DeriveInput) -> TokenStr
 
     let lt = lt.map(|l| &l.lifetime);
 
-    if attr.len() != 1 {
-        return Error::new(
-            input.span(),
-            "#[make_ule] takes one argument for the name of the ULE type it produces",
-        )
-        .to_compile_error();
-    }
-    let arg = &attr[0];
-    let ule_name: Ident = parse_quote!(#arg);
-
     let name = &input.ident;
 
     let fields = match input.data {
diff --git a/utils/zerovec/derive/src/utils.rs b/utils/zerovec/derive/src/utils.rs
index 3ebf33bf006..8863540c2e4 100644
--- a/utils/zerovec/derive/src/utils.rs
+++ b/utils/zerovec/derive/src/utils.rs
@@ -9,19 +9,16 @@ use proc_macro2::TokenStream as TokenStream2;
 use syn::parse::{Parse, ParseStream};
 use syn::punctuated::Punctuated;
 use syn::spanned::Spanned;
-use syn::{parenthesized, parse2, Attribute, Error, Field, Fields, Ident, Index, Result, Token};
+use syn::{Attribute, Error, Field, Fields, Ident, Index, Result, Token};
 
 // Check that there are repr attributes satisfying the given predicate
 pub fn has_valid_repr(attrs: &[Attribute], predicate: impl Fn(&Ident) -> bool + Copy) -> bool {
-    attrs
-        .iter()
-        .filter(|a| a.path.get_ident().map(|a| a == "repr").unwrap_or(false))
-        .any(|a| {
-            parse2::<IdentListAttribute>(a.tokens.clone())
-                .ok()
-                .and_then(|s| s.idents.iter().find(|s| predicate(s)).map(|_| ()))
-                .is_some()
-        })
+    attrs.iter().filter(|a| a.path().is_ident("repr")).any(|a| {
+        a.parse_args::<IdentListAttribute>()
+            .ok()
+            .and_then(|s| s.idents.iter().find(|s| predicate(s)).map(|_| ()))
+            .is_some()
+    })
 }
 
 // An attribute that is a list of idents
@@ -31,10 +28,8 @@ struct IdentListAttribute {
 
 impl Parse for IdentListAttribute {
     fn parse(input: ParseStream) -> Result<Self> {
-        let content;
-        let _paren = parenthesized!(content in input);
         Ok(IdentListAttribute {
-            idents: content.parse_terminated(Ident::parse)?,
+            idents: input.parse_terminated(Ident::parse, Token![,])?,
         })
     }
 }
@@ -164,16 +159,16 @@ pub fn extract_parenthetical_zerovec_attrs(
     let mut error = None;
     attrs.retain(|a| {
         // skip the "zerovec" part
-        let second_segment = a.path.segments.iter().nth(1);
+        let second_segment = a.path().segments.iter().nth(1);
 
         if let Some(second) = second_segment {
             if second.ident == name {
-                let list = match parse2::<IdentListAttribute>(a.tokens.clone()) {
+                let list = match a.parse_args::<IdentListAttribute>() {
                     Ok(l) => l,
                     Err(_) => {
                         error = Some(Error::new(
                             a.span(),
-                            "#[zerovec::name(..)] takes in a comma separated list of identifiers",
+                            format!("#[zerovec::{name}(..)] takes in a comma separated list of identifiers"),
                         ));
                         return false;
                     }
@@ -196,7 +191,7 @@ pub fn extract_parenthetical_zerovec_attrs(
 pub fn extract_zerovec_attributes(attrs: &mut Vec<Attribute>) -> Vec<Attribute> {
     let mut ret = vec![];
     attrs.retain(|a| {
-        if a.path.segments.len() == 2 && a.path.segments[0].ident == "zerovec" {
+        if a.path().segments.len() == 2 && a.path().segments[0].ident == "zerovec" {
             ret.push(a.clone());
             return false;
         }