Merge "Update num-derive crate to 0.4.2" into main
diff --git a/crates/num-derive/.android-checksum.json b/crates/num-derive/.android-checksum.json
index 3a0160a..2219d85 100644
--- a/crates/num-derive/.android-checksum.json
+++ b/crates/num-derive/.android-checksum.json
@@ -1 +1 @@
-{"package":null,"files":{".cargo-checksum.json":"a195d5eac19096f41233f909409e56ec1281fb117f161b95fa411b3c52f1a9e7","Android.bp":"f34da70ee24ec62b7cfca1ceb9cd4fa664ba336a728a20416af580658cddb0c4","Cargo.toml":"8c0e6a0544621eb91c3ad8278fb2f44455a1a57fcbdbd2ee8bbcf82c0246a0c6","LICENSE":"3c7cd2396b5b772507febd2615d3d5a55b80103845037df77c87ba6e64872f2c","LICENSE-APACHE":"3c7cd2396b5b772507febd2615d3d5a55b80103845037df77c87ba6e64872f2c","LICENSE-MIT":"16693a68efd65bc6a9df3448c8f7ee6745418c73faff4ec4d443648c04285fa4","METADATA":"648522ac08a1fa0f9b7e6f818232bec7290b67e9a08ebc2103991dd3a8e90eac","MODULE_LICENSE_APACHE2":"0d6f8afa3940b7f06bebee651376d43bc8b0d5b437337be2696d30377451e93a","README.md":"46c68bd576295970b4e5e852ef411fef77bee597becac3ddeb393650c93c6b32","RELEASES.md":"1a8e23877e3d46773a8161a0ce6c518ac8f07096b248bce60a3f45702c903e20","TEST_MAPPING":"54bed59d3a8f6ed067bc298afafee36b8387d10c5011132b499429e0a289a7fc","cargo_embargo.json":"feff82698fcf8425b6b440bb976fcc7591d4da88f81f2237658d844c612a2501","patches/syn-2.patch":"572f7ad746cd290ad667a38c68bb4b4e0facae5d167776435996784104e1640d","rules.mk":"b6cdc169f165f1d23b564c32e5f75d401092db7b177fc21d72e839f809c9d8ac","src/lib.rs":"94ada8dd9cb02522df53168e7805c7d3ed72431e87d283967f49f63ceae36830","tests/empty_enum.rs":"8976adddd4a5d80e2ddf8b91846e66f42ee621b7fa82d1eb663c24a16ebfb21c","tests/issue-16.rs":"adf0321e3faee0cbae6038de403aeaabe5bd08d37e563662a422db3879ec8d50","tests/issue-6.rs":"36ed14eae767ce4d666f867612faae5b630aeb9789461670a30fb79f7fc6e350","tests/issue-9.rs":"8ca1ba775f3ef077651e3617704490e87225f278f63a9919c006fc6f27a5aab3","tests/newtype-2015.rs":"c0416ac4e0755f3b30ae1c2b54681f0547f6e64c3591f680e88d0d9157cb801b","tests/newtype.rs":"99a8e3da9806fbe9888b715f27d5bcf39344e4715e5c65e0e360d2c226496253","tests/num_derive_without_num.rs":"6a920c2f8089882fea6dc209390d8faa4b7c7543a7de667165dea6c8647f6dd6","tests/trivial-2015.rs":"38ecd04a62f3a2ac5fef92c8e84e1711d8c67823056a2f800f144eba09509332","tests/trivial.rs":"8c773f06b59b100004d5fb1616fee68f3e9b994f131f574daaee5d3fbff085f6","tests/with_custom_values.rs":"35fe621d9d500a88920e1aef40ea261372b8b56d8cbd6ce6ca4222040c144e5f"}}
\ No newline at end of file
+{"package":null,"files":{".cargo-checksum.json":"7437707392dce551b98cd3ede32fa320f7640450c3b8487928b001e65a05ff1e","Android.bp":"ff60a6fbc166fc34a031e136c7f9839f7d70e102f21c6d46fdb2ca435d6d1c17","Cargo.toml":"d428522d21a216fcd9a06d4621c3ff84a4ce4edd3c3f45af8fd5cfc26729f1a7","LICENSE":"3c7cd2396b5b772507febd2615d3d5a55b80103845037df77c87ba6e64872f2c","LICENSE-APACHE":"3c7cd2396b5b772507febd2615d3d5a55b80103845037df77c87ba6e64872f2c","LICENSE-MIT":"16693a68efd65bc6a9df3448c8f7ee6745418c73faff4ec4d443648c04285fa4","METADATA":"a3e679e6b58077e9b0ee4b54726e5df1fcf7afcc6efd82016cd856660ff24f11","MODULE_LICENSE_APACHE2":"0d6f8afa3940b7f06bebee651376d43bc8b0d5b437337be2696d30377451e93a","README.md":"9ca1c66b82881d84c12b160e77e1b2b4d29739227a24031eb2620df73757496b","RELEASES.md":"84611ba4706c0764dedcbdd693b5aa85b66d64ae01c33e74b70301f82db96df6","TEST_MAPPING":"54bed59d3a8f6ed067bc298afafee36b8387d10c5011132b499429e0a289a7fc","cargo_embargo.json":"feff82698fcf8425b6b440bb976fcc7591d4da88f81f2237658d844c612a2501","rules.mk":"5f8159daa708f8918423aa458e2e14774cbfa4629cd4635a2f5e363058f8476e","src/lib.rs":"b2123a4b017f8a22c384603d0ffc790a693f5bb76ba2b8aa8112415886941db0","tests/empty_enum.rs":"8976adddd4a5d80e2ddf8b91846e66f42ee621b7fa82d1eb663c24a16ebfb21c","tests/issue-16.rs":"2978256c5aa4bfd0294cf4b2bb92bb7d3379ca83ececb3f1a1ee07cabdd7739b","tests/issue-6.rs":"36ed14eae767ce4d666f867612faae5b630aeb9789461670a30fb79f7fc6e350","tests/issue-9.rs":"8ca1ba775f3ef077651e3617704490e87225f278f63a9919c006fc6f27a5aab3","tests/newtype-2015.rs":"c0416ac4e0755f3b30ae1c2b54681f0547f6e64c3591f680e88d0d9157cb801b","tests/newtype-2018.rs":"59cbee55b32b5e2b010a9c8d5eda2672fce4d7920d29a7cfba2ac47330069685","tests/newtype.rs":"2432d328cc26da4bcaad39977fa5379818f61f744666db76775b23ee99c6ccc2","tests/no_implicit_prelude.rs":"4a86e1b6cc70ac19956275b14821a897ac7fa03e5f6557efce0cab604dc8333c","tests/num_derive_without_num.rs":"6a920c2f8089882fea6dc209390d8faa4b7c7543a7de667165dea6c8647f6dd6","tests/trivial-2015.rs":"38ecd04a62f3a2ac5fef92c8e84e1711d8c67823056a2f800f144eba09509332","tests/trivial-2018.rs":"4deba7e50d07b9c87c94288ef84a8decd3472c47665dfd02ee773174725f2b36","tests/trivial.rs":"8c773f06b59b100004d5fb1616fee68f3e9b994f131f574daaee5d3fbff085f6","tests/with_custom_values.rs":"46dd854093137efad7b3dcfa54baaa2b2e6dcc2b701d4b69ace70a8a2aadaad7"}}
\ No newline at end of file
diff --git a/crates/num-derive/.cargo-checksum.json b/crates/num-derive/.cargo-checksum.json
index fe87985..2defb82 100644
--- a/crates/num-derive/.cargo-checksum.json
+++ b/crates/num-derive/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"aeffa6070dd5f4311b70d4baf3723f48c58bf5895a529ddd3f2548042ecedce8","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"d772e283044982c8d132220666f831a2add33d2d891aee4faf61d6b1c8b81b6c","RELEASES.md":"a9031e1846496d2c19baea11378d038fc4c4789e224365c20f8e4f783a45fb23","src/lib.rs":"e0e97564d9e1ddb6bb70bc5e2a5b3825dbbfe689dacedd019d5e77cde8c56693","src/test.rs":"59cd2e3ab76bf4c4adae9bf9fe49d8c1f9e98d35f7c8ca47c8199b117bb13b22","tests/empty_enum.rs":"1b2312ec2fc9866fce7172e71e0aa2efcc3cb9d7659d0b633eb352bb1e080d53","tests/issue-6.rs":"b7fbbe86ff82933c15ec09fabadca02d2c70e184af30b9887cae83ed2f60367e","tests/issue-9.rs":"4c87f70a63e56c24480028fafa39a845d127620141df21bc0abfa23f84ff9bb7","tests/newtype-2015.rs":"163f76f0c139c3621ba7416cec5f9fb966c86c5ebed270df77196cf75d62402f","tests/newtype.rs":"bc1ff3fb3680935c2280cc91441c91ea104be24f525428987b49b86bc880217a","tests/num_derive_without_num.rs":"3ce528221a2cb752859e20c5423c4b474fec714b41d8c1b62f5614b165d7262b","tests/trivial-2015.rs":"1745e23dfafb8c717365e57d79323c61c7d4ceaa092d7399ed793fd4f2de8ff6","tests/trivial.rs":"a6b0faab04527f6835f43cd72317a00065a7a6cf4c506d04e77f898134f7a59b","tests/with_custom_values.rs":"9f15c4b732050a5498a9691c2b41902bd9172f0c7c5d3af152ea9bd4a272e885"},"package":"876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d"}
\ No newline at end of file
+{"files":{"Cargo.toml":"659a3cf18a53cb7bcf017efaf2e498494e854f91ebb56c9acb067e94f076f43a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"4087ceabb42281161bc074db61ad4d888343f159e60e49776559a179eda34193","RELEASES.md":"044558c5a745c96d6aecec2cd073a522d9919ba9873aa21b54c90c73e850accd","src/lib.rs":"dc254b4419136764ea0d5217e21cdbb8081142b6bc87a659c0d285573aebb181","tests/empty_enum.rs":"1b2312ec2fc9866fce7172e71e0aa2efcc3cb9d7659d0b633eb352bb1e080d53","tests/issue-16.rs":"4a056b4a688805fc95f01642f016da6dadb46d1c67ceb82e5b5eaf9fe2db92cd","tests/issue-6.rs":"b7fbbe86ff82933c15ec09fabadca02d2c70e184af30b9887cae83ed2f60367e","tests/issue-9.rs":"4c87f70a63e56c24480028fafa39a845d127620141df21bc0abfa23f84ff9bb7","tests/newtype-2015.rs":"163f76f0c139c3621ba7416cec5f9fb966c86c5ebed270df77196cf75d62402f","tests/newtype-2018.rs":"ce5b005d805690b8200f6752d24a5ebe7d248703d0aa619489c6d821b3df4b9c","tests/newtype.rs":"e7beacc831d911bae50424624a6d8823ef9eb6f7a0e2774b99be30c7977b927e","tests/no_implicit_prelude.rs":"7274f4fef6c35eb374eb2be2d352808f51deef06c02f819ae0e3d1521eebc610","tests/num_derive_without_num.rs":"3ce528221a2cb752859e20c5423c4b474fec714b41d8c1b62f5614b165d7262b","tests/trivial-2015.rs":"1745e23dfafb8c717365e57d79323c61c7d4ceaa092d7399ed793fd4f2de8ff6","tests/trivial-2018.rs":"645f0ff3c3c0d014b6891bd310de2bc5f3ccb3019cb70d0b653061eb6571f7cf","tests/trivial.rs":"a6b0faab04527f6835f43cd72317a00065a7a6cf4c506d04e77f898134f7a59b","tests/with_custom_values.rs":"4f2ea85d1f987c6620efe5bda095477c3b669af3cb67f98935c5a7d59d28b339"},"package":"ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"}
\ No newline at end of file
diff --git a/crates/num-derive/Android.bp b/crates/num-derive/Android.bp
index 54ab3dd..26b8a2f 100644
--- a/crates/num-derive/Android.bp
+++ b/crates/num-derive/Android.bp
@@ -17,9 +17,9 @@
     name: "libnum_derive",
     crate_name: "num_derive",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.3.3",
+    cargo_pkg_version: "0.4.2",
     crate_root: "src/lib.rs",
-    edition: "2018",
+    edition: "2021",
     rustlibs: [
         "libproc_macro2",
         "libquote",
diff --git a/crates/num-derive/Cargo.toml b/crates/num-derive/Cargo.toml
index d0ccb4b..36a8899 100644
--- a/crates/num-derive/Cargo.toml
+++ b/crates/num-derive/Cargo.toml
@@ -3,24 +3,30 @@
 # When uploading crates to the registry Cargo will automatically
 # "normalize" Cargo.toml files for maximal compatibility
 # with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
 #
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
 
 [package]
-edition = "2018"
+edition = "2021"
+rust-version = "1.56.0"
 name = "num-derive"
-version = "0.3.3"
+version = "0.4.2"
 authors = ["The Rust Project Developers"]
-exclude = ["/bors.toml", "/ci/*", "/.github/*"]
+exclude = [
+    "/ci/*",
+    "/.github/*",
+]
 description = "Numeric syntax extensions"
 homepage = "https://github.com/rust-num/num-derive"
 documentation = "https://docs.rs/num-derive"
 readme = "README.md"
-keywords = ["mathematics", "numerics"]
+keywords = [
+    "mathematics",
+    "numerics",
+]
 categories = ["science"]
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/rust-num/num-derive"
@@ -35,8 +41,17 @@
 edition = "2015"
 
 [[test]]
+name = "newtype-2018"
+edition = "2018"
+
+[[test]]
 name = "trivial-2015"
 edition = "2015"
+
+[[test]]
+name = "trivial-2018"
+edition = "2018"
+
 [dependencies.proc-macro2]
 version = "1"
 
@@ -44,12 +59,10 @@
 version = "1"
 
 [dependencies.syn]
-version = "2"
+version = "2.0.5"
+
 [dev-dependencies.num]
-version = "0.3"
+version = "0.4"
 
 [dev-dependencies.num-traits]
 version = "0.2"
-
-[features]
-full-syntax = ["syn/full"]
diff --git a/crates/num-derive/METADATA b/crates/num-derive/METADATA
index d696f30..6a1ab62 100644
--- a/crates/num-derive/METADATA
+++ b/crates/num-derive/METADATA
@@ -1,17 +1,17 @@
 name: "num-derive"
 description: "Numeric syntax extensions"
 third_party {
-  version: "0.3.3"
+  version: "0.4.2"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2020
-    month: 10
-    day: 29
+    year: 2025
+    month: 1
+    day: 15
   }
   homepage: "https://crates.io/crates/num-derive"
   identifier {
     type: "Archive"
-    value: "https://static.crates.io/crates/num-derive/num-derive-0.3.3.crate"
-    version: "0.3.3"
+    value: "https://static.crates.io/crates/num-derive/num-derive-0.4.2.crate"
+    version: "0.4.2"
   }
 }
diff --git a/crates/num-derive/README.md b/crates/num-derive/README.md
index 9826cdf..20d66a6 100644
--- a/crates/num-derive/README.md
+++ b/crates/num-derive/README.md
@@ -2,7 +2,7 @@
 
 [![crate](https://img.shields.io/crates/v/num-derive.svg)](https://crates.io/crates/num-derive)
 [![documentation](https://docs.rs/num-derive/badge.svg)](https://docs.rs/num-derive)
-[![minimum rustc 1.31](https://img.shields.io/badge/rustc-1.31+-red.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html)
+[![minimum rustc 1.56](https://img.shields.io/badge/rustc-1.56+-red.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html)
 [![build status](https://github.com/rust-num/num-derive/workflows/master/badge.svg)](https://github.com/rust-num/num-derive/actions)
 
 Procedural macros to derive numeric traits in Rust.
@@ -14,7 +14,7 @@
 ```toml
 [dependencies]
 num-traits = "0.2"
-num-derive = "0.3"
+num-derive = "0.4"
 ```
 
 and this to your crate root:
@@ -51,7 +51,7 @@
 
 ## Compatibility
 
-The `num-derive` crate is tested for rustc 1.31 and greater.
+The `num-derive` crate is tested for rustc 1.56 and greater.
 
 ## License
 
diff --git a/crates/num-derive/RELEASES.md b/crates/num-derive/RELEASES.md
index c3e18cc..bbf6d53 100644
--- a/crates/num-derive/RELEASES.md
+++ b/crates/num-derive/RELEASES.md
@@ -1,3 +1,27 @@
+# Release 0.4.2 (2024-02-06)
+
+- [Use anon-const to avoid RFC 3373 warnings.][62]
+
+[62]: https://github.com/rust-num/num-derive/pull/62
+
+# Release 0.4.1 (2023-10-07)
+
+- [Make `Float` work with `no_std`][56] -- thanks @vkahl!
+- [Emit full paths for `Option` and `Result`.][57]
+- [Add derive macro for `num_traits::Signed` and `Unsigned`][55] -- thanks @tdelabro!
+
+[55]: https://github.com/rust-num/num-derive/pull/55
+[56]: https://github.com/rust-num/num-derive/pull/56
+[57]: https://github.com/rust-num/num-derive/pull/57
+
+# Release 0.4.0 (2023-06-29)
+
+- [Update to syn-2][54] -- thanks @maurer!
+  - This raises the minimum supported rustc to 1.56.
+  - The "full-syntax" feature has also been removed.
+
+[54]: https://github.com/rust-num/num-derive/pull/54
+
 # Release 0.3.3 (2020-10-29)
 
 - [Make `NumOps` work with `no_std`][41] -- thanks @jedrzejboczar!
diff --git a/crates/num-derive/patches/syn-2.patch b/crates/num-derive/patches/syn-2.patch
deleted file mode 100644
index dc867af..0000000
--- a/crates/num-derive/patches/syn-2.patch
+++ /dev/null
@@ -1,119 +0,0 @@
-From 1d2c6fa2ea2f3ab560c30c631fdde0034f5789a4 Mon Sep 17 00:00:00 2001
-From: Matthew Maurer <[email protected]>
-Date: Mon, 3 Apr 2023 16:13:04 +0000
-Subject: [PATCH] Update to syn-2
-
-Bug: 276463929
-Test: m
-Change-Id: If2f4b9e451716cae4e7cc5d037764de4582aa761
----
- src/lib.rs        | 20 ++++++++------------
- src/test.rs       | 31 -------------------------------
- tests/issue-16.rs |  9 +++++++++
- 3 files changed, 17 insertions(+), 43 deletions(-)
- delete mode 100644 src/test.rs
- create mode 100644 tests/issue-16.rs
-
-diff --git a/src/lib.rs b/src/lib.rs
-index ef55e4b..0b821f9 100644
---- a/src/lib.rs
-+++ b/src/lib.rs
-@@ -170,16 +170,14 @@ impl NumTraits {
-         // retrieve its value, and use it to create an `Ident` to be used
-         // to import the `num_traits` crate.
-         for attr in &ast.attrs {
--            if let Ok(syn::Meta::NameValue(mnv)) = attr.parse_meta() {
--                if mnv.path.is_ident("num_traits") {
--                    if let syn::Lit::Str(lit_str) = mnv.lit {
--                        return NumTraits {
--                            import: syn::Ident::new(&lit_str.value(), lit_str.span()),
--                            explicit: true,
--                        };
--                    } else {
--                        panic!("#[num_traits] attribute value must be a str");
--                    }
-+            if attr.path().is_ident("num_traits") {
-+                if let syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Str(ref lit_str), .. }) = attr.meta.require_name_value().unwrap().value {
-+                  return NumTraits {
-+                      import: syn::Ident::new(&lit_str.value(), lit_str.span()),
-+                      explicit: true,
-+                  }
-+                } else {
-+                    panic!("#[num_traits] attribute value must be a str");
-                 }
-             }
-         }
-@@ -954,5 +952,3 @@ pub fn float(input: TokenStream) -> TokenStream {
- 
-     import.wrap("Float", &name, impl_).into()
- }
--
--mod test;
-diff --git a/src/test.rs b/src/test.rs
-deleted file mode 100644
-index c4cd7fe..0000000
---- a/src/test.rs
-+++ /dev/null
-@@ -1,31 +0,0 @@
--//! This module uses doc-tests on modules for `compile_fail`
--
--// We need "syn/full" to parse macros.
--// Use `--nocapture` to check the quality of the error message.
--#[cfg(not(feature = "full-syntax"))]
--/// ```compile_fail
--/// macro_rules! get_an_isize {
--///     () => (0_isize)
--/// }
--///
--/// #[derive(num_derive::FromPrimitive)]
--/// pub enum CLikeEnum {
--///     VarA = get_an_isize!(), // error without "syn/full"
--///     VarB = 2,
--/// }
--/// ```
--mod issue16 {}
--
--#[cfg(feature = "full-syntax")]
--/// ```
--/// macro_rules! get_an_isize {
--///     () => (0_isize)
--/// }
--///
--/// #[derive(num_derive::FromPrimitive)]
--/// pub enum CLikeEnum {
--///     VarA = get_an_isize!(), // ok with "syn/full"
--///     VarB = 2,
--/// }
--/// ```
--mod issue16 {}
-diff --git a/tests/issue-16.rs b/tests/issue-16.rs
-new file mode 100644
-index 0000000..0db3b6f
---- /dev/null
-+++ b/tests/issue-16.rs
-@@ -0,0 +1,9 @@
-+macro_rules! get_an_isize {
-+    () => (0_isize)
-+}
-+
-+#[derive(num_derive::FromPrimitive)]
-+pub enum CLikeEnum {
-+    VarA = get_an_isize!(),
-+    VarB = 2,
-+}
-diff --git b/Cargo.toml a/Cargo.toml
-index 90c5d27..d0ccb4b 100644
---- b/Cargo.toml
-+++ a/Cargo.toml
-@@ -44,7 +44,7 @@ version = "1"
- version = "1"
-
- [dependencies.syn]
--version = "1"
-+version = "2"
- [dev-dependencies.num]
- version = "0.3"
-
--- 
-2.40.0.348.gf938b09366-goog
-
diff --git a/crates/num-derive/rules.mk b/crates/num-derive/rules.mk
index ddaa928..c1744f9 100644
--- a/crates/num-derive/rules.mk
+++ b/crates/num-derive/rules.mk
@@ -8,7 +8,7 @@
 MODULE_CRATE_NAME := num_derive
 MODULE_RUST_CRATE_TYPES := proc-macro
 MODULE_SRCS := $(LOCAL_DIR)/src/lib.rs
-MODULE_RUST_EDITION := 2018
+MODULE_RUST_EDITION := 2021
 MODULE_LIBRARY_DEPS := \
 	$(call FIND_CRATE,proc-macro2) \
 	$(call FIND_CRATE,quote) \
diff --git a/crates/num-derive/src/lib.rs b/crates/num-derive/src/lib.rs
index 0b821f9..207602b 100644
--- a/crates/num-derive/src/lib.rs
+++ b/crates/num-derive/src/lib.rs
@@ -71,19 +71,11 @@
 use syn::{Data, Fields, Ident};
 
 /// Try to parse the tokens, or else return a compilation error
-/// suggesting "full-syntax" if that's not already enabled.
 macro_rules! parse {
     ($tokens:ident as $type:ty) => {
         match syn::parse::<$type>($tokens) {
             Ok(parsed) => parsed,
-            Err(mut error) => {
-                if cfg!(not(feature = "full-syntax")) {
-                    let hint = syn::Error::new(
-                        Span::call_site(),
-                        r#"this might need the "full-syntax" feature of `num-derive`"#,
-                    );
-                    error.combine(hint);
-                }
+            Err(error) => {
                 return TokenStream::from(error.to_compile_error());
             }
         }
@@ -105,16 +97,12 @@
 // we're deriving for a newtype, where the inner type is defined in the same module, but not
 // exported.
 //
-// Solution: use the dummy const trick.  For some reason, `extern crate` statements are allowed
+// Solution: use the anonymous const trick.  For some reason, `extern crate` statements are allowed
 // here, but everything from the surrounding module is in scope.  This trick is taken from serde.
-fn dummy_const_trick(trait_: &str, name: &Ident, exp: TokenStream2) -> TokenStream2 {
-    let dummy_const = Ident::new(
-        &format!("_IMPL_NUM_{}_FOR_{}", trait_, unraw(name)),
-        Span::call_site(),
-    );
+fn anon_const_trick(exp: TokenStream2) -> TokenStream2 {
     quote! {
         #[allow(non_upper_case_globals, unused_qualifications)]
-        const #dummy_const: () = {
+        const _: () = {
             #[allow(clippy::useless_attribute)]
             #[allow(rust_2018_idioms)]
             extern crate num_traits as _num_traits;
@@ -123,10 +111,6 @@
     }
 }
 
-fn unraw(ident: &Ident) -> String {
-    ident.to_string().trim_start_matches("r#").to_owned()
-}
-
 // If `data` is a newtype, return the type it's wrapping.
 fn newtype_inner(data: &syn::Data) -> Option<syn::Type> {
     match *data {
@@ -171,11 +155,19 @@
         // to import the `num_traits` crate.
         for attr in &ast.attrs {
             if attr.path().is_ident("num_traits") {
-                if let syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Str(ref lit_str), .. }) = attr.meta.require_name_value().unwrap().value {
-                  return NumTraits {
-                      import: syn::Ident::new(&lit_str.value(), lit_str.span()),
-                      explicit: true,
-                  }
+                if let Ok(syn::MetaNameValue {
+                    value:
+                        syn::Expr::Lit(syn::ExprLit {
+                            lit: syn::Lit::Str(ref lit_str),
+                            ..
+                        }),
+                    ..
+                }) = attr.meta.require_name_value()
+                {
+                    return NumTraits {
+                        import: syn::Ident::new(&lit_str.value(), lit_str.span()),
+                        explicit: true,
+                    };
                 } else {
                     panic!("#[num_traits] attribute value must be a str");
                 }
@@ -189,11 +181,11 @@
         }
     }
 
-    fn wrap(&self, trait_: &str, name: &Ident, output: TokenStream2) -> TokenStream2 {
+    fn wrap(&self, output: TokenStream2) -> TokenStream2 {
         if self.explicit {
             output
         } else {
-            dummy_const_trick(trait_, &name, output)
+            anon_const_trick(output)
         }
     }
 }
@@ -257,59 +249,59 @@
         quote! {
             impl #import::FromPrimitive for #name {
                 #[inline]
-                fn from_i64(n: i64) -> Option<Self> {
+                fn from_i64(n: i64) -> ::core::option::Option<Self> {
                     <#inner_ty as #import::FromPrimitive>::from_i64(n).map(#name)
                 }
                 #[inline]
-                fn from_u64(n: u64) -> Option<Self> {
+                fn from_u64(n: u64) -> ::core::option::Option<Self> {
                     <#inner_ty as #import::FromPrimitive>::from_u64(n).map(#name)
                 }
                 #[inline]
-                fn from_isize(n: isize) -> Option<Self> {
+                fn from_isize(n: isize) -> ::core::option::Option<Self> {
                     <#inner_ty as #import::FromPrimitive>::from_isize(n).map(#name)
                 }
                 #[inline]
-                fn from_i8(n: i8) -> Option<Self> {
+                fn from_i8(n: i8) -> ::core::option::Option<Self> {
                     <#inner_ty as #import::FromPrimitive>::from_i8(n).map(#name)
                 }
                 #[inline]
-                fn from_i16(n: i16) -> Option<Self> {
+                fn from_i16(n: i16) -> ::core::option::Option<Self> {
                     <#inner_ty as #import::FromPrimitive>::from_i16(n).map(#name)
                 }
                 #[inline]
-                fn from_i32(n: i32) -> Option<Self> {
+                fn from_i32(n: i32) -> ::core::option::Option<Self> {
                     <#inner_ty as #import::FromPrimitive>::from_i32(n).map(#name)
                 }
                 #[inline]
-                fn from_i128(n: i128) -> Option<Self> {
+                fn from_i128(n: i128) -> ::core::option::Option<Self> {
                     <#inner_ty as #import::FromPrimitive>::from_i128(n).map(#name)
                 }
                 #[inline]
-                fn from_usize(n: usize) -> Option<Self> {
+                fn from_usize(n: usize) -> ::core::option::Option<Self> {
                     <#inner_ty as #import::FromPrimitive>::from_usize(n).map(#name)
                 }
                 #[inline]
-                fn from_u8(n: u8) -> Option<Self> {
+                fn from_u8(n: u8) -> ::core::option::Option<Self> {
                     <#inner_ty as #import::FromPrimitive>::from_u8(n).map(#name)
                 }
                 #[inline]
-                fn from_u16(n: u16) -> Option<Self> {
+                fn from_u16(n: u16) -> ::core::option::Option<Self> {
                     <#inner_ty as #import::FromPrimitive>::from_u16(n).map(#name)
                 }
                 #[inline]
-                fn from_u32(n: u32) -> Option<Self> {
+                fn from_u32(n: u32) -> ::core::option::Option<Self> {
                     <#inner_ty as #import::FromPrimitive>::from_u32(n).map(#name)
                 }
                 #[inline]
-                fn from_u128(n: u128) -> Option<Self> {
+                fn from_u128(n: u128) -> ::core::option::Option<Self> {
                     <#inner_ty as #import::FromPrimitive>::from_u128(n).map(#name)
                 }
                 #[inline]
-                fn from_f32(n: f32) -> Option<Self> {
+                fn from_f32(n: f32) -> ::core::option::Option<Self> {
                     <#inner_ty as #import::FromPrimitive>::from_f32(n).map(#name)
                 }
                 #[inline]
-                fn from_f64(n: f64) -> Option<Self> {
+                fn from_f64(n: f64) -> ::core::option::Option<Self> {
                     <#inner_ty as #import::FromPrimitive>::from_f64(n).map(#name)
                 }
             }
@@ -339,7 +331,7 @@
 
                 quote! {
                     if #from_i64_var == #name::#ident as i64 {
-                        Some(#name::#ident)
+                        ::core::option::Option::Some(#name::#ident)
                     }
                 }
             })
@@ -355,21 +347,21 @@
             impl #import::FromPrimitive for #name {
                 #[allow(trivial_numeric_casts)]
                 #[inline]
-                fn from_i64(#from_i64_var: i64) -> Option<Self> {
+                fn from_i64(#from_i64_var: i64) -> ::core::option::Option<Self> {
                     #(#clauses else)* {
-                        None
+                        ::core::option::Option::None
                     }
                 }
 
                 #[inline]
-                fn from_u64(n: u64) -> Option<Self> {
+                fn from_u64(n: u64) -> ::core::option::Option<Self> {
                     Self::from_i64(n as i64)
                 }
             }
         }
     };
 
-    import.wrap("FromPrimitive", &name, impl_).into()
+    import.wrap(impl_).into()
 }
 
 /// Derives [`num_traits::ToPrimitive`][to] for simple enums and newtypes.
@@ -431,59 +423,59 @@
         quote! {
             impl #import::ToPrimitive for #name {
                 #[inline]
-                fn to_i64(&self) -> Option<i64> {
+                fn to_i64(&self) -> ::core::option::Option<i64> {
                     <#inner_ty as #import::ToPrimitive>::to_i64(&self.0)
                 }
                 #[inline]
-                fn to_u64(&self) -> Option<u64> {
+                fn to_u64(&self) -> ::core::option::Option<u64> {
                     <#inner_ty as #import::ToPrimitive>::to_u64(&self.0)
                 }
                 #[inline]
-                fn to_isize(&self) -> Option<isize> {
+                fn to_isize(&self) -> ::core::option::Option<isize> {
                     <#inner_ty as #import::ToPrimitive>::to_isize(&self.0)
                 }
                 #[inline]
-                fn to_i8(&self) -> Option<i8> {
+                fn to_i8(&self) -> ::core::option::Option<i8> {
                     <#inner_ty as #import::ToPrimitive>::to_i8(&self.0)
                 }
                 #[inline]
-                fn to_i16(&self) -> Option<i16> {
+                fn to_i16(&self) -> ::core::option::Option<i16> {
                     <#inner_ty as #import::ToPrimitive>::to_i16(&self.0)
                 }
                 #[inline]
-                fn to_i32(&self) -> Option<i32> {
+                fn to_i32(&self) -> ::core::option::Option<i32> {
                     <#inner_ty as #import::ToPrimitive>::to_i32(&self.0)
                 }
                 #[inline]
-                fn to_i128(&self) -> Option<i128> {
+                fn to_i128(&self) -> ::core::option::Option<i128> {
                     <#inner_ty as #import::ToPrimitive>::to_i128(&self.0)
                 }
                 #[inline]
-                fn to_usize(&self) -> Option<usize> {
+                fn to_usize(&self) -> ::core::option::Option<usize> {
                     <#inner_ty as #import::ToPrimitive>::to_usize(&self.0)
                 }
                 #[inline]
-                fn to_u8(&self) -> Option<u8> {
+                fn to_u8(&self) -> ::core::option::Option<u8> {
                     <#inner_ty as #import::ToPrimitive>::to_u8(&self.0)
                 }
                 #[inline]
-                fn to_u16(&self) -> Option<u16> {
+                fn to_u16(&self) -> ::core::option::Option<u16> {
                     <#inner_ty as #import::ToPrimitive>::to_u16(&self.0)
                 }
                 #[inline]
-                fn to_u32(&self) -> Option<u32> {
+                fn to_u32(&self) -> ::core::option::Option<u32> {
                     <#inner_ty as #import::ToPrimitive>::to_u32(&self.0)
                 }
                 #[inline]
-                fn to_u128(&self) -> Option<u128> {
+                fn to_u128(&self) -> ::core::option::Option<u128> {
                     <#inner_ty as #import::ToPrimitive>::to_u128(&self.0)
                 }
                 #[inline]
-                fn to_f32(&self) -> Option<f32> {
+                fn to_f32(&self) -> ::core::option::Option<f32> {
                     <#inner_ty as #import::ToPrimitive>::to_f32(&self.0)
                 }
                 #[inline]
-                fn to_f64(&self) -> Option<f64> {
+                fn to_f64(&self) -> ::core::option::Option<f64> {
                     <#inner_ty as #import::ToPrimitive>::to_f64(&self.0)
                 }
             }
@@ -522,7 +514,7 @@
             }
         } else {
             quote! {
-                Some(match *self {
+                ::core::option::Option::Some(match *self {
                     #(#variants,)*
                 })
             }
@@ -532,19 +524,19 @@
             impl #import::ToPrimitive for #name {
                 #[inline]
                 #[allow(trivial_numeric_casts)]
-                fn to_i64(&self) -> Option<i64> {
+                fn to_i64(&self) -> ::core::option::Option<i64> {
                     #match_expr
                 }
 
                 #[inline]
-                fn to_u64(&self) -> Option<u64> {
+                fn to_u64(&self) -> ::core::option::Option<u64> {
                     self.to_i64().map(|x| x as u64)
                 }
             }
         }
     };
 
-    import.wrap("ToPrimitive", &name, impl_).into()
+    import.wrap(impl_).into()
 }
 
 const NEWTYPE_ONLY: &str = "This trait can only be derived for newtypes";
@@ -617,13 +609,13 @@
     let impl_ = quote! {
         impl #import::NumCast for #name {
             #[inline]
-            fn from<T: #import::ToPrimitive>(n: T) -> Option<Self> {
+            fn from<T: #import::ToPrimitive>(n: T) -> ::core::option::Option<Self> {
                 <#inner_ty as #import::NumCast>::from(n).map(#name)
             }
         }
     };
 
-    import.wrap("NumCast", &name, impl_).into()
+    import.wrap(impl_).into()
 }
 
 /// Derives [`num_traits::Zero`][zero] for newtypes.  The inner type must already implement `Zero`.
@@ -650,7 +642,7 @@
         }
     };
 
-    import.wrap("Zero", &name, impl_).into()
+    import.wrap(impl_).into()
 }
 
 /// Derives [`num_traits::One`][one] for newtypes.  The inner type must already implement `One`.
@@ -677,7 +669,7 @@
         }
     };
 
-    import.wrap("One", &name, impl_).into()
+    import.wrap(impl_).into()
 }
 
 /// Derives [`num_traits::Num`][num] for newtypes.  The inner type must already implement `Num`.
@@ -695,13 +687,13 @@
         impl #import::Num for #name {
             type FromStrRadixErr = <#inner_ty as #import::Num>::FromStrRadixErr;
             #[inline]
-            fn from_str_radix(s: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
+            fn from_str_radix(s: &str, radix: u32) -> ::core::result::Result<Self, Self::FromStrRadixErr> {
                 <#inner_ty as #import::Num>::from_str_radix(s, radix).map(#name)
             }
         }
     };
 
-    import.wrap("Num", &name, impl_).into()
+    import.wrap(impl_).into()
 }
 
 /// Derives [`num_traits::Float`][float] for newtypes.  The inner type must already implement
@@ -763,7 +755,7 @@
                 <#inner_ty as #import::Float>::is_normal(self.0)
             }
             #[inline]
-            fn classify(self) -> ::std::num::FpCategory {
+            fn classify(self) -> ::core::num::FpCategory {
                 <#inner_ty as #import::Float>::classify(self.0)
             }
             #[inline]
@@ -950,5 +942,63 @@
         }
     };
 
-    import.wrap("Float", &name, impl_).into()
+    import.wrap(impl_).into()
+}
+
+/// Derives [`num_traits::Signed`][signed] for newtypes.  The inner type must already implement
+/// `Signed`.
+///
+/// [signed]: https://docs.rs/num-traits/0.2/num_traits/sign/trait.Signed.html
+#[proc_macro_derive(Signed, attributes(num_traits))]
+pub fn signed(input: TokenStream) -> TokenStream {
+    let ast = parse!(input as syn::DeriveInput);
+    let name = &ast.ident;
+    let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY);
+
+    let import = NumTraits::new(&ast);
+
+    let impl_ = quote! {
+        impl #import::Signed for #name {
+            #[inline]
+            fn abs(&self) -> Self {
+                #name(<#inner_ty as #import::Signed>::abs(&self.0))
+            }
+            #[inline]
+            fn abs_sub(&self, other: &Self) -> Self {
+                #name(<#inner_ty as #import::Signed>::abs_sub(&self.0, &other.0))
+            }
+            #[inline]
+            fn signum(&self) -> Self {
+                #name(<#inner_ty as #import::Signed>::signum(&self.0))
+            }
+            #[inline]
+            fn is_positive(&self) -> bool {
+                <#inner_ty as #import::Signed>::is_positive(&self.0)
+            }
+            #[inline]
+            fn is_negative(&self) -> bool {
+                <#inner_ty as #import::Signed>::is_negative(&self.0)
+            }
+        }
+    };
+
+    import.wrap(impl_).into()
+}
+
+/// Derives [`num_traits::Unsigned`][unsigned].  The inner type must already implement
+/// `Unsigned`.
+///
+/// [unsigned]: https://docs.rs/num/latest/num/traits/trait.Unsigned.html
+#[proc_macro_derive(Unsigned, attributes(num_traits))]
+pub fn unsigned(input: TokenStream) -> TokenStream {
+    let ast = parse!(input as syn::DeriveInput);
+    let name = &ast.ident;
+
+    let import = NumTraits::new(&ast);
+
+    let impl_ = quote! {
+        impl #import::Unsigned for #name {}
+    };
+
+    import.wrap(impl_).into()
 }
diff --git a/crates/num-derive/tests/issue-16.rs b/crates/num-derive/tests/issue-16.rs
index 0db3b6f..48cc2fb 100644
--- a/crates/num-derive/tests/issue-16.rs
+++ b/crates/num-derive/tests/issue-16.rs
@@ -1,5 +1,7 @@
 macro_rules! get_an_isize {
-    () => (0_isize)
+    () => {
+        0_isize
+    };
 }
 
 #[derive(num_derive::FromPrimitive)]
diff --git a/crates/num-derive/tests/newtype-2018.rs b/crates/num-derive/tests/newtype-2018.rs
new file mode 100644
index 0000000..814529e
--- /dev/null
+++ b/crates/num-derive/tests/newtype-2018.rs
@@ -0,0 +1,2 @@
+// Same source, just compiled for 2018 edition
+include!("newtype.rs");
diff --git a/crates/num-derive/tests/newtype.rs b/crates/num-derive/tests/newtype.rs
index 6eafd09..71b06b3 100644
--- a/crates/num-derive/tests/newtype.rs
+++ b/crates/num-derive/tests/newtype.rs
@@ -2,9 +2,22 @@
 #[macro_use]
 extern crate num_derive;
 
-use crate::num_renamed::{Float, FromPrimitive, Num, NumCast, One, ToPrimitive, Zero};
+use crate::num_renamed::{
+    Float, FromPrimitive, Num, NumCast, One, Signed, ToPrimitive, Unsigned, Zero,
+};
 use std::ops::Neg;
 
+#[derive(PartialEq, Zero, One, NumOps, Num, Unsigned)]
+struct MyNum(u32);
+
+#[test]
+fn test_derive_unsigned_works() {
+    fn do_nothing_on_unsigned(_input: impl Unsigned) {}
+
+    let x = MyNum(42);
+    do_nothing_on_unsigned(x);
+}
+
 #[derive(
     Debug,
     Clone,
@@ -19,6 +32,7 @@
     Zero,
     Num,
     Float,
+    Signed,
 )]
 struct MyFloat(f64);
 
@@ -87,3 +101,8 @@
 fn test_float() {
     assert_eq!(MyFloat(4.0).log(MyFloat(2.0)), MyFloat(2.0));
 }
+
+#[test]
+fn test_signed() {
+    assert!(MyFloat(-2.0).is_negative())
+}
diff --git a/crates/num-derive/tests/no_implicit_prelude.rs b/crates/num-derive/tests/no_implicit_prelude.rs
new file mode 100644
index 0000000..cb82dec
--- /dev/null
+++ b/crates/num-derive/tests/no_implicit_prelude.rs
@@ -0,0 +1,13 @@
+#![no_implicit_prelude]
+
+use ::num_derive::*;
+
+#[derive(FromPrimitive, ToPrimitive)]
+enum Color {
+    Red,
+    Blue,
+    Green,
+}
+
+#[derive(FromPrimitive, ToPrimitive, NumCast, PartialEq, Zero, One, NumOps, Num)]
+struct NewI32(i32);
diff --git a/crates/num-derive/tests/trivial-2018.rs b/crates/num-derive/tests/trivial-2018.rs
new file mode 100644
index 0000000..92b971b
--- /dev/null
+++ b/crates/num-derive/tests/trivial-2018.rs
@@ -0,0 +1,2 @@
+// Same source, just compiled for 2018 edition
+include!("trivial.rs");
diff --git a/crates/num-derive/tests/with_custom_values.rs b/crates/num-derive/tests/with_custom_values.rs
index 94c8445..9b202f4 100644
--- a/crates/num-derive/tests/with_custom_values.rs
+++ b/crates/num-derive/tests/with_custom_values.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![cfg(feature = "full-syntax")]
-
 extern crate num as num_renamed;
 #[macro_use]
 extern crate num_derive;
diff --git a/pseudo_crate/Cargo.lock b/pseudo_crate/Cargo.lock
index 610b608..09d3af1 100644
--- a/pseudo_crate/Cargo.lock
+++ b/pseudo_crate/Cargo.lock
@@ -3461,13 +3461,13 @@
 
 [[package]]
 name = "num-derive"
-version = "0.3.3"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d"
+checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
 dependencies = [
  "proc-macro2 1.0.93",
  "quote 1.0.38",
- "syn 1.0.109",
+ "syn 2.0.96",
 ]
 
 [[package]]
diff --git a/pseudo_crate/Cargo.toml b/pseudo_crate/Cargo.toml
index b27d175..1cde88a 100644
--- a/pseudo_crate/Cargo.toml
+++ b/pseudo_crate/Cargo.toml
@@ -210,7 +210,7 @@
 nom = "=7.1.3"
 num-bigint = "=0.4.4"
 num-complex = "=0.4.6"
-num-derive = "=0.3.3"
+num-derive = "=0.4.2"
 num-integer = "=0.1.46"
 num-traits = "=0.2.19"
 num_cpus = "=1.16.0"