summaryrefslogtreecommitdiffstats
path: root/third_party/rust/derive_more-impl
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /third_party/rust/derive_more-impl
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/derive_more-impl')
-rw-r--r--third_party/rust/derive_more-impl/.cargo-checksum.json1
-rw-r--r--third_party/rust/derive_more-impl/Cargo.toml127
-rw-r--r--third_party/rust/derive_more-impl/LICENSE21
-rw-r--r--third_party/rust/derive_more-impl/README.md12
-rw-r--r--third_party/rust/derive_more-impl/doc/add.md152
-rw-r--r--third_party/rust/derive_more-impl/doc/add_assign.md78
-rw-r--r--third_party/rust/derive_more-impl/doc/as_mut.md129
-rw-r--r--third_party/rust/derive_more-impl/doc/as_ref.md130
-rw-r--r--third_party/rust/derive_more-impl/doc/constructor.md80
-rw-r--r--third_party/rust/derive_more-impl/doc/debug.md126
-rw-r--r--third_party/rust/derive_more-impl/doc/deref.md107
-rw-r--r--third_party/rust/derive_more-impl/doc/deref_mut.md130
-rw-r--r--third_party/rust/derive_more-impl/doc/display.md182
-rw-r--r--third_party/rust/derive_more-impl/doc/error.md150
-rw-r--r--third_party/rust/derive_more-impl/doc/from.md188
-rw-r--r--third_party/rust/derive_more-impl/doc/from_str.md135
-rw-r--r--third_party/rust/derive_more-impl/doc/index.md74
-rw-r--r--third_party/rust/derive_more-impl/doc/index_mut.md91
-rw-r--r--third_party/rust/derive_more-impl/doc/into.md119
-rw-r--r--third_party/rust/derive_more-impl/doc/into_iterator.md101
-rw-r--r--third_party/rust/derive_more-impl/doc/is_variant.md43
-rw-r--r--third_party/rust/derive_more-impl/doc/mul.md148
-rw-r--r--third_party/rust/derive_more-impl/doc/mul_assign.md92
-rw-r--r--third_party/rust/derive_more-impl/doc/not.md159
-rw-r--r--third_party/rust/derive_more-impl/doc/sum.md77
-rw-r--r--third_party/rust/derive_more-impl/doc/try_into.md182
-rw-r--r--third_party/rust/derive_more-impl/doc/try_unwrap.md80
-rw-r--r--third_party/rust/derive_more-impl/doc/unwrap.md70
-rw-r--r--third_party/rust/derive_more-impl/src/add_assign_like.rs39
-rw-r--r--third_party/rust/derive_more-impl/src/add_helpers.rs28
-rw-r--r--third_party/rust/derive_more-impl/src/add_like.rs153
-rw-r--r--third_party/rust/derive_more-impl/src/as_mut.rs81
-rw-r--r--third_party/rust/derive_more-impl/src/as_ref.rs81
-rw-r--r--third_party/rust/derive_more-impl/src/constructor.rs50
-rw-r--r--third_party/rust/derive_more-impl/src/deref.rs55
-rw-r--r--third_party/rust/derive_more-impl/src/deref_mut.rs44
-rw-r--r--third_party/rust/derive_more-impl/src/error.rs481
-rw-r--r--third_party/rust/derive_more-impl/src/fmt/debug.rs373
-rw-r--r--third_party/rust/derive_more-impl/src/fmt/display.rs377
-rw-r--r--third_party/rust/derive_more-impl/src/fmt/mod.rs444
-rw-r--r--third_party/rust/derive_more-impl/src/fmt/parsing.rs1096
-rw-r--r--third_party/rust/derive_more-impl/src/from.rs478
-rw-r--r--third_party/rust/derive_more-impl/src/from_str.rs112
-rw-r--r--third_party/rust/derive_more-impl/src/index.rs47
-rw-r--r--third_party/rust/derive_more-impl/src/index_mut.rs44
-rw-r--r--third_party/rust/derive_more-impl/src/into.rs448
-rw-r--r--third_party/rust/derive_more-impl/src/into_iterator.rs59
-rw-r--r--third_party/rust/derive_more-impl/src/is_variant.rs65
-rw-r--r--third_party/rust/derive_more-impl/src/lib.rs281
-rw-r--r--third_party/rust/derive_more-impl/src/mul_assign_like.rs63
-rw-r--r--third_party/rust/derive_more-impl/src/mul_helpers.rs36
-rw-r--r--third_party/rust/derive_more-impl/src/mul_like.rs61
-rw-r--r--third_party/rust/derive_more-impl/src/not_like.rs171
-rw-r--r--third_party/rust/derive_more-impl/src/parsing.rs469
-rw-r--r--third_party/rust/derive_more-impl/src/sum_like.rs53
-rw-r--r--third_party/rust/derive_more-impl/src/try_into.rs123
-rw-r--r--third_party/rust/derive_more-impl/src/try_unwrap.rs166
-rw-r--r--third_party/rust/derive_more-impl/src/unwrap.rs169
-rw-r--r--third_party/rust/derive_more-impl/src/utils.rs1514
59 files changed, 10645 insertions, 0 deletions
diff --git a/third_party/rust/derive_more-impl/.cargo-checksum.json b/third_party/rust/derive_more-impl/.cargo-checksum.json
new file mode 100644
index 0000000000..c6cc635852
--- /dev/null
+++ b/third_party/rust/derive_more-impl/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"79cc66b8dc35ff10185c05aac941e61cc8ea22ea43d7d606874413470c4de147","LICENSE":"8a35369f3ca263b3c62fbb5032947e53b6bfebc6c8a4d1bb982de1c069f6fba5","README.md":"9ef58c81f6e1e03c19aacdb4cc0e96370497e4566db2c495c15d824f59a948ac","doc/add.md":"3e8764b90f4ccf06e7903f63c6a29af933b65ee8f39975bf83d7028fc14537d7","doc/add_assign.md":"7a67a1d5e147d4a37f9c81ec7c50bd02b5c469c48b39875ad06d92592dadc73d","doc/as_mut.md":"59d4fbfb4dc30502f00aba899d4b6a12da9a114ad9c53fa803ae7103049abf6c","doc/as_ref.md":"892562f3b3c7214932f75ae3e2c2c75615a2f54523fd2275393a5bc0fc1049da","doc/constructor.md":"1efface08ac87ce8f53b0a22dd0af4b812c8de6a7b74679a4305136efb60a968","doc/debug.md":"82bd046725cf487f3ddd32cabe9366205fea8689f63184e12488e6461afe97f4","doc/deref.md":"d91ada503cfc2744aeba89135bcaf8bb75494e8ed4a59e8d523fe4294ae9fa30","doc/deref_mut.md":"8d74d418127ef517baa87da9499ffc3f5a617bbb392b8103011435dd5992950b","doc/display.md":"b340ad60fad4cec93a5ee539a702293fc54f49fcab003b2fb9ce6ec0f21d9ffd","doc/error.md":"650bd28511b68823b5d7578469c4b15920c093555c31a88bef8cd6b6a15853fd","doc/from.md":"3317f1cd37f9b0615329016c10db0b909274117516408e276f65afbcda2e38ae","doc/from_str.md":"f434e28a9c9bac1161af90ea833a1bcea38c52de07cee235750342ecfd76ae2d","doc/index.md":"54c194da4ce8753b2c0a708e5d1efbd1c718f39408c582165fd9298ca9584d49","doc/index_mut.md":"cf8df23ddbedc85b57cbc5a91d0be1408fa2e6ed1c0b91b577bbde5904737e7a","doc/into.md":"9f4207cc211eec76868bf6ca757ad225ce4a3f77418e3e333483f644389c2168","doc/into_iterator.md":"0f31affff9f809d54cd4bfe2ce206e3b6d126f635f0d2afa3ec45e3aee33f6db","doc/is_variant.md":"baa1cef7c8a6d700c410729d4a4e4c25790653cb8453439850ca98787924008f","doc/mul.md":"b6d7851263730b36039ea96947bffea82cae509c31d86c289740b1cead22f6da","doc/mul_assign.md":"32d5db458af1c45c4461650f8f2e32e12a5dab6ed7fa31d2a67f849465ab8945","doc/not.md":"702d0661b9413d4d63815999e0e35ae88dc53428ed9f625e7c4930d47f13af0c","doc/sum.md":"ae064095e5d32ee2f273a033bc5459b06a74add1036f43edd8ac65240195a9f9","doc/try_into.md":"221b3037a686d672bbd2ae22e527931e88e874e88670d5e301db30881c0a0821","doc/try_unwrap.md":"d316d613515e5a704d340659ceead0354e282df136d5286ade5e5b26e638156c","doc/unwrap.md":"d8a5d3393e3da685869f50f9aab8d3ab992e4bb0cd47415b5127f12ae04e0b86","src/add_assign_like.rs":"52fbff906fc8c5e9ac709448a555618f20d31947ce78245684502c84c64f0fb5","src/add_helpers.rs":"fb08a98fa061a64cdf23f8fd8442d9721d32c20427a4b46fa1a4ee5d99e9a609","src/add_like.rs":"4f779f110136975e064851a149471082541cd04e79cbc1f64b06679af2ef6964","src/as_mut.rs":"ce1aaff0318ceedd5aba2f29db97840e7680b13a78b8554eeaf3f34f24560336","src/as_ref.rs":"abec5e9230d787fcf91555400a7e2db5c8da9f54e50994d25ccca94bb19740bf","src/constructor.rs":"11c043caa501f2c21154e1bbe14b247027c813b994162e0f788a29c8a06580f2","src/deref.rs":"43e715383c06844fe555e34f8e4be65ddaa37f7c96da645707ec0a8e3b4217fa","src/deref_mut.rs":"8bea9c9797e51490a31d4138caf3c015a09e74719fcc3a8939509a04709e6468","src/error.rs":"d7dee4d5f4bbcfd40592476da1247d8b47ca4c49996fa53ebbea81e359446005","src/fmt/debug.rs":"8c9691db074499d0b7b1745d3c74cda5ea9504d98ad85f9076799dcfebf95890","src/fmt/display.rs":"9c66c05c79a4cdcf3f27227e3fef7634250c8cc8f160eea56e02448d6e24d08e","src/fmt/mod.rs":"b8be648a76fa1591e3ec1ace29950e0ff573a31797b36399bb7c47bac2d9673e","src/fmt/parsing.rs":"12aabefd35c2575b3d7e65d5871e2e73c898b4b08debc6d6446971d0b170dc04","src/from.rs":"5d950436eb4d169d07b729c15427fec1a75fe78f794addf0542041d20cdc4b7e","src/from_str.rs":"7af011a1a72d362ca61d1790540b803b63ce96e6d418c70c98b7c101a06ac179","src/index.rs":"6604e4c89286cfcb4973335cc8e680e4f2b92d5cfc22e2e88911f867dff65993","src/index_mut.rs":"ed30934c9df2614095877320e1ed046fe4bc6b6c573f3c65c733ce6f9a384424","src/into.rs":"19d5403ca01bd3dcd3588cc0ea87dbb120150cbec7a26e281dd16f8875a2246d","src/into_iterator.rs":"9e43f7aae7b5be51842e7d727ab84d1b959cca6e81762ef6f41fc8d4ae5f96ff","src/is_variant.rs":"d0d55fc32f65c4241ae7eb8f1e3fe9e0943e2a502b23b732e67c972ebdb9a5f3","src/lib.rs":"175336e15f1337347ead1983266a1454f92f1cac92cdd6a68b59e40252bab55a","src/mul_assign_like.rs":"0f3e49242c68f7a4577aa51fa7a2970f324186e6104e1f76107f05e9500c6d29","src/mul_helpers.rs":"10e03b42b1e1c8257c3af3836a711e6cfcb1cf446e9767991ba208acd7f65536","src/mul_like.rs":"eba4316e78417a27aae6c5aa740fdbcadfb9e790fd6e6049ffdf546786ab32f7","src/not_like.rs":"de72bf8dc9db9a15459e3a897ea956b6f37256d182f98278eb0e5c9d4b548aac","src/parsing.rs":"c4ff6dbda866d2baf8a0fac71fac2dfd122b6fa4853916eaf2477e32ab871668","src/sum_like.rs":"c8dfca148fb35252df04ecd30256ecc0b35581c86276709837921b23c78019c1","src/try_into.rs":"e6311bed505b09f790f8a78a8b82187c403ca91be4c4d0a306c3d3c155d1ba89","src/try_unwrap.rs":"1785fd4816188e52361509fb8610dcbbd40c5062ad21ca61f6497315d6977754","src/unwrap.rs":"727ca9a25b0ee0f33b976a0555e37dfd2125aa737c1d5449dcb4adc8e0debd34","src/utils.rs":"65aa7845dff2f4792f9f5df347bf26bbb0ef343fb77ef064d8de4313a6699fdc"},"package":"395aee42a456ecfd4c7034be5011e1a98edcbab2611867c8988a0f40d0bb242a"} \ No newline at end of file
diff --git a/third_party/rust/derive_more-impl/Cargo.toml b/third_party/rust/derive_more-impl/Cargo.toml
new file mode 100644
index 0000000000..ff2d5463d1
--- /dev/null
+++ b/third_party/rust/derive_more-impl/Cargo.toml
@@ -0,0 +1,127 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# 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.
+#
+# 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 = "2021"
+rust-version = "1.65.0"
+name = "derive_more-impl"
+version = "1.0.0-beta.2"
+authors = ["Jelte Fennema <github-tech@jeltef.nl>"]
+include = [
+ "src/**/*.rs",
+ "doc/**/*.md",
+ "Cargo.toml",
+ "README.md",
+ "LICENSE",
+]
+description = "Internal implementation of `derive_more` crate"
+documentation = "https://docs.rs/derive_more"
+readme = "README.md"
+license = "MIT"
+repository = "https://github.com/JelteF/derive_more"
+
+[package.metadata.docs.rs]
+features = ["full"]
+rustdoc-args = [
+ "--cfg",
+ "docsrs",
+]
+
+[lib]
+proc-macro = true
+
+[dependencies.convert_case]
+version = "0.6"
+optional = true
+
+[dependencies.proc-macro2]
+version = "1.0"
+
+[dependencies.quote]
+version = "1.0"
+
+[dependencies.syn]
+version = "2.0"
+
+[dependencies.unicode-xid]
+version = "0.2.2"
+optional = true
+
+[dev-dependencies.itertools]
+version = "0.11.0"
+
+[build-dependencies.rustc_version]
+version = "0.4"
+optional = true
+
+[features]
+add = []
+add_assign = []
+as_mut = []
+as_ref = []
+constructor = []
+debug = [
+ "syn/extra-traits",
+ "dep:unicode-xid",
+]
+default = []
+deref = []
+deref_mut = []
+display = [
+ "syn/extra-traits",
+ "dep:unicode-xid",
+]
+error = ["syn/extra-traits"]
+from = ["syn/extra-traits"]
+from_str = []
+full = [
+ "add",
+ "add_assign",
+ "as_mut",
+ "as_ref",
+ "constructor",
+ "debug",
+ "deref",
+ "deref_mut",
+ "display",
+ "error",
+ "from",
+ "from_str",
+ "index",
+ "index_mut",
+ "into",
+ "into_iterator",
+ "is_variant",
+ "mul",
+ "mul_assign",
+ "not",
+ "sum",
+ "try_into",
+ "try_unwrap",
+ "unwrap",
+]
+index = []
+index_mut = []
+into = ["syn/extra-traits"]
+into_iterator = []
+is_variant = ["dep:convert_case"]
+mul = ["syn/extra-traits"]
+mul_assign = ["syn/extra-traits"]
+not = ["syn/extra-traits"]
+sum = []
+testing-helpers = ["dep:rustc_version"]
+try_into = ["syn/extra-traits"]
+try_unwrap = ["dep:convert_case"]
+unwrap = ["dep:convert_case"]
+
+[badges.github]
+repository = "JelteF/derive_more"
+workflow = "CI"
diff --git a/third_party/rust/derive_more-impl/LICENSE b/third_party/rust/derive_more-impl/LICENSE
new file mode 100644
index 0000000000..602cf050e2
--- /dev/null
+++ b/third_party/rust/derive_more-impl/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Jelte Fennema
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/third_party/rust/derive_more-impl/README.md b/third_party/rust/derive_more-impl/README.md
new file mode 100644
index 0000000000..2a7de75214
--- /dev/null
+++ b/third_party/rust/derive_more-impl/README.md
@@ -0,0 +1,12 @@
+# `derive_more-impl`
+
+This crate is an implementation detail of the [`derive_more`][crates.io]. If you
+found this crate by accident you're probably looking for one of the following
+pages of [`derive_more`][crates.io]:
+1. [crates.io]
+2. [docs.rs]
+3. [GitHub]
+
+[crates.io]: https://crates.io/crates/derive_more
+[docs.rs]: https://docs.rs/derive_more/latest/derive_more
+[GitHub]: https://github.com/JelteF/derive_more
diff --git a/third_party/rust/derive_more-impl/doc/add.md b/third_party/rust/derive_more-impl/doc/add.md
new file mode 100644
index 0000000000..5d58996a28
--- /dev/null
+++ b/third_party/rust/derive_more-impl/doc/add.md
@@ -0,0 +1,152 @@
+# What `#[derive(Add)]` generates
+
+The derived `Add` implementation will allow two structs from the same type to be
+added together. This done by adding their respective fields together and
+creating a new struct with those values.
+For enums each variant can be added in a similar way to another instance of that
+same variant. There's one big difference however, it returns a
+`Result<EnumType>`, because an error is returned when to different variants are
+added together.
+
+
+
+
+## Tuple structs
+
+When deriving `Add` for a tuple struct with two fields like this:
+
+```rust
+# use derive_more::Add;
+#
+#[derive(Add)]
+struct MyInts(i32, i32);
+```
+
+Code like this will be generated:
+
+```rust
+# struct MyInts(i32, i32);
+impl ::core::ops::Add for MyInts {
+ type Output = MyInts;
+ fn add(self, rhs: MyInts) -> MyInts {
+ MyInts(self.0.add(rhs.0), self.1.add(rhs.1))
+ }
+}
+```
+
+The behaviour is similar with more or less fields.
+
+
+
+
+## Regular structs
+
+When deriving `Add` for a regular struct with two fields like this:
+
+```rust
+# use derive_more::Add;
+#
+#[derive(Add)]
+struct Point2D {
+ x: i32,
+ y: i32,
+}
+```
+
+Code like this will be generated:
+
+```rust
+# struct Point2D {
+# x: i32,
+# y: i32,
+# }
+impl ::core::ops::Add for Point2D {
+ type Output = Point2D;
+ fn add(self, rhs: Point2D) -> Point2D {
+ Point2D {
+ x: self.x.add(rhs.x),
+ y: self.y.add(rhs.y),
+ }
+ }
+}
+```
+
+The behaviour is similar for more or less fields.
+
+
+
+
+## Enums
+
+There's a big difference between the code that is generated for the two struct
+types and the one that is generated for enums. The code for enums returns
+`Result<EnumType>` instead of an `EnumType` itself. This is because adding an
+enum to another enum is only possible if both are the same variant. This makes
+the generated code much more complex as well, because this check needs to be
+done. For instance when deriving `Add` for an enum like this:
+
+```rust
+# use derive_more::Add;
+#
+#[derive(Add)]
+enum MixedInts {
+ SmallInt(i32),
+ BigInt(i64),
+ TwoSmallInts(i32, i32),
+ NamedSmallInts { x: i32, y: i32 },
+ UnsignedOne(u32),
+ UnsignedTwo(u32),
+ Unit,
+}
+```
+
+Code like this will be generated:
+
+```rust
+# enum MixedInts {
+# SmallInt(i32),
+# BigInt(i64),
+# TwoSmallInts(i32, i32),
+# NamedSmallInts { x: i32, y: i32 },
+# UnsignedOne(u32),
+# UnsignedTwo(u32),
+# Unit,
+# }
+impl ::core::ops::Add for MixedInts {
+ type Output = Result<MixedInts, ::derive_more::ops::BinaryError>;
+ fn add(self, rhs: MixedInts) -> Result<MixedInts, ::derive_more::ops::BinaryError> {
+ match (self, rhs) {
+ (MixedInts::SmallInt(__l_0), MixedInts::SmallInt(__r_0)) => {
+ Ok(MixedInts::SmallInt(__l_0.add(__r_0)))
+ }
+ (MixedInts::BigInt(__l_0), MixedInts::BigInt(__r_0)) => {
+ Ok(MixedInts::BigInt(__l_0.add(__r_0)))
+ }
+ (MixedInts::TwoSmallInts(__l_0, __l_1), MixedInts::TwoSmallInts(__r_0, __r_1)) => {
+ Ok(MixedInts::TwoSmallInts(__l_0.add(__r_0), __l_1.add(__r_1)))
+ }
+ (MixedInts::NamedSmallInts { x: __l_0, y: __l_1 },
+ MixedInts::NamedSmallInts { x: __r_0, y: __r_1 }) => {
+ Ok(MixedInts::NamedSmallInts {
+ x: __l_0.add(__r_0),
+ y: __l_1.add(__r_1),
+ })
+ }
+ (MixedInts::UnsignedOne(__l_0), MixedInts::UnsignedOne(__r_0)) => {
+ Ok(MixedInts::UnsignedOne(__l_0.add(__r_0)))
+ }
+ (MixedInts::UnsignedTwo(__l_0), MixedInts::UnsignedTwo(__r_0)) => {
+ Ok(MixedInts::UnsignedTwo(__l_0.add(__r_0)))
+ }
+ (MixedInts::Unit, MixedInts::Unit) => Err(::derive_more::ops::BinaryError::Unit(
+ ::derive_more::ops::UnitError::new("add"),
+ )),
+ _ => Err(::derive_more::ops::BinaryError::Mismatch(
+ ::derive_more::ops::WrongVariantError::new("add"),
+ )),
+ }
+ }
+}
+```
+
+Also note the Unit type that throws an error when adding it to itself.
diff --git a/third_party/rust/derive_more-impl/doc/add_assign.md b/third_party/rust/derive_more-impl/doc/add_assign.md
new file mode 100644
index 0000000000..04a85a186b
--- /dev/null
+++ b/third_party/rust/derive_more-impl/doc/add_assign.md
@@ -0,0 +1,78 @@
+# What `#[derive(AddAssign)]` generates
+
+This code is very similar to the code that is generated for `#[derive(Add)]`.
+The difference is that it mutates the existing instance instead of creating a
+new one.
+
+
+
+
+## Tuple structs
+
+When deriving `AddAssign` for a tuple struct with two fields like this:
+
+```rust
+# use derive_more::AddAssign;
+#
+#[derive(AddAssign)]
+struct MyInts(i32, i32);
+```
+
+Code like this will be generated:
+
+```rust
+# struct MyInts(i32, i32);
+impl ::core::ops::AddAssign for MyInts {
+ fn add_assign(&mut self, rhs: MyInts) {
+ self.0.add_assign(rhs.0);
+ self.1.add_assign(rhs.1);
+ }
+}
+```
+
+The behaviour is similar with more or less fields.
+
+
+
+
+## Regular structs
+
+When deriving for a regular struct with two fields like this:
+
+```rust
+# use derive_more::AddAssign;
+#
+#[derive(AddAssign)]
+struct Point2D {
+ x: i32,
+ y: i32,
+}
+```
+
+Code like this will be generated:
+
+```rust
+# struct Point2D {
+# x: i32,
+# y: i32,
+# }
+impl ::core::ops::AddAssign for Point2D {
+ fn add_assign(&mut self, rhs: Point2D) {
+ self.x.add_assign(rhs.x);
+ self.y.add_assign(rhs.y);
+ }
+}
+```
+
+The behaviour is similar with more or less fields.
+
+
+
+
+## Enums
+
+Deriving `AddAssign` is not (yet) supported for enums.
+This is mostly due to the fact that it is not trivial convert the `Add`
+derivation code, because that returns a `Result<EnumType>` instead of an
+`EnumType`.
+Handling the case where it errors would be hard and maybe impossible.
diff --git a/third_party/rust/derive_more-impl/doc/as_mut.md b/third_party/rust/derive_more-impl/doc/as_mut.md
new file mode 100644
index 0000000000..a1e6127d3a
--- /dev/null
+++ b/third_party/rust/derive_more-impl/doc/as_mut.md
@@ -0,0 +1,129 @@
+# What `#[derive(AsMut)]` generates
+
+Deriving `AsMut` generates one or more implementations of `AsMut`, each
+corresponding to one of the fields of the decorated type.
+This allows types which contain some `T` to be passed anywhere that an
+`AsMut<T>` is accepted.
+
+
+
+
+## Newtypes and Structs with One Field
+
+When `AsMut` is derived for a newtype or struct with one field, a single
+implementation is generated to expose the underlying field.
+
+```rust
+# use derive_more::AsMut;
+#
+#[derive(AsMut)]
+struct MyWrapper(String);
+```
+
+Generates:
+
+```rust
+# struct MyWrapper(String);
+impl AsMut<String> for MyWrapper {
+ fn as_mut(&mut self) -> &mut String {
+ &mut self.0
+ }
+}
+```
+
+It's also possible to use the `#[as_mut(forward)]` attribute to forward
+to the `as_mut` implementation of the field. So here `SingleFieldForward`
+implements all `AsMut` for all types that `Vec<i32>` implements `AsMut` for.
+
+```rust
+# use derive_more::AsMut;
+#
+#[derive(AsMut)]
+#[as_mut(forward)]
+struct SingleFieldForward(Vec<i32>);
+
+let mut item = SingleFieldForward(vec![]);
+let _: &mut [i32] = (&mut item).as_mut();
+```
+
+This generates:
+
+```rust
+# struct SingleFieldForward(Vec<i32>);
+impl<__AsMutT: ?::core::marker::Sized> ::core::convert::AsMut<__AsMutT> for SingleFieldForward
+where
+ Vec<i32>: ::core::convert::AsMut<__AsMutT>,
+{
+ #[inline]
+ fn as_mut(&mut self) -> &mut __AsMutT {
+ <Vec<i32> as ::core::convert::AsMut<__AsMutT>>::as_mut(&mut self.0)
+ }
+}
+```
+
+
+
+
+## Structs with Multiple Fields
+
+When `AsMut` is derived for a struct with more than one field (including tuple
+structs), you must also mark one or more fields with the `#[as_mut]` attribute.
+An implementation will be generated for each indicated field.
+You can also exclude a specific field by using `#[as_mut(ignore)]`.
+
+```rust
+# use derive_more::AsMut;
+#
+#[derive(AsMut)]
+struct MyWrapper {
+ #[as_mut]
+ name: String,
+ #[as_mut]
+ num: i32,
+ valid: bool,
+}
+```
+
+Generates:
+
+```rust
+# struct MyWrapper {
+# name: String,
+# num: i32,
+# valid: bool,
+# }
+impl AsMut<String> for MyWrapper {
+ fn as_mut(&mut self) -> &mut String {
+ &mut self.name
+ }
+}
+
+impl AsMut<i32> for MyWrapper {
+ fn as_mut(&mut self) -> &mut i32 {
+ &mut self.num
+ }
+}
+```
+
+Note that `AsMut<T>` may only be implemented once for any given type `T`. This means any attempt to
+mark more than one field of the same type with `#[as_mut]` will result in a compilation error.
+
+```rust,compile_fail
+# use derive_more::AsMut;
+#
+// Error! Conflicting implementations of AsMut<String>
+#[derive(AsMut)]
+struct MyWrapper {
+ #[as_mut]
+ str1: String,
+ #[as_mut]
+ str2: String,
+}
+```
+
+
+
+
+## Enums
+
+Deriving `AsMut` for enums is not supported.
diff --git a/third_party/rust/derive_more-impl/doc/as_ref.md b/third_party/rust/derive_more-impl/doc/as_ref.md
new file mode 100644
index 0000000000..112ba15a1c
--- /dev/null
+++ b/third_party/rust/derive_more-impl/doc/as_ref.md
@@ -0,0 +1,130 @@
+# What `#[derive(AsRef)]` generates
+
+Deriving `AsRef` generates one or more implementations of `AsRef`, each
+corresponding to one of the fields of the decorated type.
+This allows types which contain some `T` to be passed anywhere that an
+`AsRef<T>` is accepted.
+
+
+
+
+## Newtypes and Structs with One Field
+
+When `AsRef` is derived for a newtype or struct with one field, a single
+implementation is generated to expose the underlying field.
+
+```rust
+# use derive_more::AsRef;
+#
+#[derive(AsRef)]
+struct MyWrapper(String);
+```
+
+Generates:
+
+```rust
+# struct MyWrapper(String);
+impl AsRef<String> for MyWrapper {
+ fn as_ref(&self) -> &String {
+ &self.0
+ }
+}
+```
+
+It's also possible to use the `#[as_ref(forward)]` attribute to forward
+to the `as_ref` implementation of the field. So here `SingleFieldForward`
+implements all `AsRef` for all types that `Vec<i32>` implements `AsRef` for.
+
+```rust
+# use derive_more::AsRef;
+#
+#[derive(AsRef)]
+#[as_ref(forward)]
+struct SingleFieldForward(Vec<i32>);
+
+let item = SingleFieldForward(vec![]);
+let _: &[i32] = (&item).as_ref();
+```
+
+This generates:
+
+```rust
+# struct SingleFieldForward(Vec<i32>);
+impl<__AsRefT: ?::core::marker::Sized> ::core::convert::AsRef<__AsRefT> for SingleFieldForward
+where
+ Vec<i32>: ::core::convert::AsRef<__AsRefT>,
+{
+ #[inline]
+ fn as_ref(&self) -> &__AsRefT {
+ <Vec<i32> as ::core::convert::AsRef<__AsRefT>>::as_ref(&self.0)
+ }
+}
+```
+
+
+
+
+## Structs with Multiple Fields
+
+When `AsRef` is derived for a struct with more than one field (including tuple
+structs), you must also mark one or more fields with the `#[as_ref]` attribute.
+An implementation will be generated for each indicated field.
+You can also exclude a specific field by using `#[as_ref(ignore)]`.
+
+```rust
+# use derive_more::AsRef;
+#
+#[derive(AsRef)]
+struct MyWrapper {
+ #[as_ref]
+ name: String,
+ #[as_ref]
+ num: i32,
+ valid: bool,
+}
+```
+
+Generates:
+
+```rust
+# struct MyWrapper {
+# name: String,
+# num: i32,
+# valid: bool,
+# }
+impl AsRef<String> for MyWrapper {
+ fn as_ref(&self) -> &String {
+ &self.name
+ }
+}
+
+impl AsRef<i32> for MyWrapper {
+ fn as_ref(&self) -> &i32 {
+ &self.num
+ }
+}
+```
+
+Note that `AsRef<T>` may only be implemented once for any given type `T`.
+This means any attempt to mark more than one field of the same type with
+`#[as_ref]` will result in a compilation error.
+
+```rust,compile_fail
+# use derive_more::AsRef;
+#
+// Error! Conflicting implementations of AsRef<String>
+#[derive(AsRef)]
+struct MyWrapper {
+ #[as_ref]
+ str1: String,
+ #[as_ref]
+ str2: String,
+}
+```
+
+
+
+
+## Enums
+
+Deriving `AsRef` for enums is not supported.
diff --git a/third_party/rust/derive_more-impl/doc/constructor.md b/third_party/rust/derive_more-impl/doc/constructor.md
new file mode 100644
index 0000000000..43f55c06d6
--- /dev/null
+++ b/third_party/rust/derive_more-impl/doc/constructor.md
@@ -0,0 +1,80 @@
+# What `#[derive(Constructor)]` generates
+
+A common pattern in Rust is to create a static constructor method called
+`new`. This method is can then be used to create an instance of a struct. You
+can now derive this method by using `#[derive(Constructor)]`, even though
+`Constructor` it is not an actual trait. The generated `new` method is very
+similar to the `from` method when deriving `From`, except that it takes multiple
+arguments instead of a tuple.
+
+
+
+
+## Tuple structs
+
+When deriving `Constructor` for a tuple struct with a two fields like this:
+
+```rust
+# use derive_more::Constructor;
+#
+#[derive(Constructor)]
+struct MyInts(i32, i32);
+```
+
+Code like this will be generated:
+
+```rust
+# struct MyInts(i32, i32);
+impl MyInts {
+ pub const fn new(__0: i32, __1: i32) -> MyInts {
+ MyInts(__0, __1)
+ }
+}
+```
+
+The generated code is similar for more or less fields.
+
+
+
+
+## Regular structs
+
+For regular structs almost the same code is generated as for tuple structs
+except that it assigns the fields differently.
+
+```rust
+# use derive_more::Constructor;
+#
+#[derive(Constructor)]
+struct Point2D {
+ x: i32,
+ y: i32,
+}
+```
+
+Code like this will be generated:
+
+```rust
+# struct Point2D {
+# x: i32,
+# y: i32,
+# }
+impl Point2D {
+ pub const fn new(x: i32, y: i32) -> Point2D {
+ Point2D { x: x, y: y }
+ }
+}
+```
+
+The generated code is similar for more or less fields.
+
+
+
+
+## Enums
+
+Currently `Constructor` cannot be derived for enums. This is because the `new`
+method might then need to have a different number of arguments. This is
+currently not supported by Rust. So this functionality will not be added until
+this [RFC](https://github.com/rust-lang/rfcs/issues/376) (or a similar one) is
+accepted and implemented.
diff --git a/third_party/rust/derive_more-impl/doc/debug.md b/third_party/rust/derive_more-impl/doc/debug.md
new file mode 100644
index 0000000000..b643976d04
--- /dev/null
+++ b/third_party/rust/derive_more-impl/doc/debug.md
@@ -0,0 +1,126 @@
+# What `#[derive(Debug)]` generates
+
+This derive macro is a clever superset of `Debug` from standard library. Additional features include:
+- not imposing redundant trait bounds;
+- `#[debug(skip)]` attribute to skip formatting struct field or enum variant;
+- `#[debug("...", args...)]` to specify custom formatting for a particular struct or enum variant field;
+- `#[debug(bounds(...))]` to impose additional custom trait bounds.
+
+
+
+
+## The format of the format
+
+You supply a format by placing an attribute on particular struct or enum variant field (not enum variant itself):
+`#[debug("...", args...)]`. The format is exactly like in [`format!()`] or any other [`format_args!()`]-based macros.
+
+The variables available in the arguments is `self` and each member of the variant, with members of tuple structs being
+named with a leading underscore and their index, i.e. `_0`, `_1`, `_2`, etc.
+
+
+
+
+### Generic data types
+
+When deriving `Debug` for a generic struct/enum, all generic type arguments _used_ during formatting
+are bound by respective formatting trait.
+
+E.g., for a structure `Foo` defined like this:
+```rust
+use derive_more::Debug;
+
+#[derive(Debug)]
+struct Foo<'a, T1, T2: Trait, T3, T4> {
+ #[debug("{a}")]
+ a: T1,
+ #[debug("{b}")]
+ b: <T2 as Trait>::Type,
+ #[debug("{c:?}")]
+ c: Vec<T3>,
+ #[debug("{d:p}")]
+ d: &'a T1,
+ #[debug(skip)]
+ e: T4,
+}
+
+trait Trait { type Type; }
+```
+
+The following where clauses would be generated:
+* `T1: Display + Pointer`
+* `<T2 as Trait>::Type: Debug`
+* `Bar<T3>: Display`
+
+
+
+
+### Custom trait bounds
+
+Sometimes you may want to specify additional trait bounds on your generic type parameters, so that they could be used
+during formatting. This can be done with a `#[debug(bound(...))]` attribute.
+
+`#[debug(bound(...))]` accepts code tokens in a format similar to the format used in angle bracket list (or `where`
+clause predicates): `T: MyTrait, U: Trait1 + Trait2`.
+
+Using `#[debug("...", ...)]` formatting we'll try our best to infer trait bounds, but in more advanced cases this isn't
+possible. Our aim is to avoid imposing additional bounds, as they can be added with `#[debug(bound(...))]`.
+In the example below, we can infer only that `V: Display`, other bounds have to be supplied by the user:
+
+```rust
+use std::fmt::Display;
+use derive_more::Debug;
+
+#[derive(Debug)]
+#[debug(bound(T: MyTrait, U: Display))]
+struct MyStruct<T, U, V, F> {
+ #[debug("{}", a.my_function())]
+ a: T,
+ #[debug("{}", b.to_string().len())]
+ b: U,
+ #[debug("{c}")]
+ c: V,
+ #[debug(skip)]
+ d: F,
+}
+
+trait MyTrait { fn my_function(&self) -> i32; }
+```
+
+
+
+
+## Example usage
+
+```rust
+use std::path::PathBuf;
+use derive_more::Debug;
+
+#[derive(Debug)]
+struct MyInt(i32);
+
+#[derive(Debug)]
+struct MyIntHex(#[debug("{_0:x}")] i32);
+
+#[derive(Debug)]
+enum E {
+ Skipped {
+ x: u32,
+ #[debug(skip)]
+ y: u32,
+ },
+ Binary {
+ #[debug("{i:b}")]
+ i: i8,
+ },
+ Path(#[debug("{}", _0.display())] PathBuf),
+}
+
+assert_eq!(format!("{:?}", MyInt(-2)), "MyInt(-2)");
+assert_eq!(format!("{:?}", MyIntHex(-255)), "MyIntHex(ffffff01)");
+assert_eq!(format!("{:?}", E::Skipped { x: 10, y: 20 }), "Skipped { x: 10, .. }");
+assert_eq!(format!("{:?}", E::Binary { i: -2 }), "Binary { i: 11111110 }");
+assert_eq!(format!("{:?}", E::Path("abc".into())), "Path(abc)");
+```
+
+[`format!()`]: https://doc.rust-lang.org/stable/std/macro.format.html
+[`format_args!()`]: https://doc.rust-lang.org/stable/std/macro.format_args.html
diff --git a/third_party/rust/derive_more-impl/doc/deref.md b/third_party/rust/derive_more-impl/doc/deref.md
new file mode 100644
index 0000000000..f1719e9b16
--- /dev/null
+++ b/third_party/rust/derive_more-impl/doc/deref.md
@@ -0,0 +1,107 @@
+# Using `#[derive(Deref)]`
+
+Deriving `Deref` only works for a single field of a struct.
+It's possible to use it in two ways:
+
+1. Dereferencing to the field, i.e. like if your type was a reference type.
+2. Doing a dereference on the field, for when the field itself is a reference type like `&` and `Box`.
+
+With `#[deref]` or `#[deref(ignore)]` it's possible to indicate the field that
+you want to derive `Deref` for.
+
+
+
+
+## Example usage
+
+```rust
+# use derive_more::Deref;
+#
+#[derive(Deref)]
+struct Num {
+ num: i32,
+}
+
+#[derive(Deref)]
+#[deref(forward)]
+struct MyBoxedInt(Box<i32>);
+
+// You can specify the field you want to derive `Deref` for.
+#[derive(Deref)]
+struct CoolVec {
+ cool: bool,
+ #[deref]
+ vec: Vec<i32>,
+}
+
+let num = Num{num: 123};
+let boxed = MyBoxedInt(Box::new(123));
+let cool_vec = CoolVec{cool: true, vec: vec![123]};
+assert_eq!(123, *num);
+assert_eq!(123, *boxed);
+assert_eq!(vec![123], *cool_vec);
+```
+
+
+
+
+## Structs
+
+When deriving a non-forwarded `Deref` for a struct:
+
+```rust
+# use derive_more::Deref;
+#
+#[derive(Deref)]
+struct CoolVec {
+ cool: bool,
+ #[deref]
+ vec: Vec<i32>,
+}
+```
+
+Code like this will be generated:
+
+```rust
+# struct CoolVec {
+# cool: bool,
+# vec: Vec<i32>,
+# }
+impl ::core::ops::Deref for CoolVec {
+ type Target = Vec<i32>;
+ #[inline]
+ fn deref(&self) -> &Self::Target {
+ &self.vec
+ }
+}
+```
+
+When deriving a forwarded `Deref` for a struct:
+
+```rust
+# use derive_more::Deref;
+#
+#[derive(Deref)]
+#[deref(forward)]
+struct MyBoxedInt(Box<i32>);
+```
+
+Code like this will be generated:
+
+```rust
+# struct MyBoxedInt(Box<i32>);
+impl ::core::ops::Deref for MyBoxedInt {
+ type Target = <Box<i32> as ::core::ops::Deref>::Target;
+ #[inline]
+ fn deref(&self) -> &Self::Target {
+ <Box<i32> as ::core::ops::Deref>::deref(&self.0)
+ }
+}
+```
+
+
+
+
+## Enums
+
+Deriving `Deref` is not supported for enums.
diff --git a/third_party/rust/derive_more-impl/doc/deref_mut.md b/third_party/rust/derive_more-impl/doc/deref_mut.md
new file mode 100644
index 0000000000..8cde33d0dd
--- /dev/null
+++ b/third_party/rust/derive_more-impl/doc/deref_mut.md
@@ -0,0 +1,130 @@
+# What `#[derive(DerefMut)]` generates
+
+Deriving `Deref` only works for a single field of a struct.
+Furthermore it requires that the type also implements `Deref`, so usually
+`Deref` should also be derived.
+The resulting implementation of `Deref` will allow you to mutably dereference
+the struct its member directly.
+
+1. Dereferencing to the field, i.e. like if your type was a reference type.
+2. Doing a dereference on the field, for when the field itself is a reference
+ type like `&mut` and `Box`.
+
+With `#[deref_mut]` or `#[deref_mut(ignore)]` it's possible to indicate the
+field that you want to derive `DerefMut` for.
+
+
+
+
+## Example usage
+
+```rust
+# use derive_more::{Deref, DerefMut};
+#
+#[derive(Deref, DerefMut)]
+struct Num {
+ num: i32,
+}
+
+#[derive(Deref, DerefMut)]
+#[deref(forward)]
+#[deref_mut(forward)]
+struct MyBoxedInt(Box<i32>);
+
+// You can specify the field you want to derive DerefMut for
+#[derive(Deref, DerefMut)]
+struct CoolVec {
+ cool: bool,
+ #[deref]
+ #[deref_mut]
+ vec: Vec<i32>,
+}
+
+let mut num = Num{num: 123};
+let mut boxed = MyBoxedInt(Box::new(123));
+let mut cool_vec = CoolVec{cool: true, vec: vec![123]};
+*num += 123;
+assert_eq!(246, *num);
+*boxed += 1000;
+assert_eq!(1123, *boxed);
+cool_vec.push(456);
+assert_eq!(vec![123, 456], *cool_vec);
+```
+
+
+
+
+## Structs
+
+When deriving a non-forwarded `Deref` for a struct:
+
+```rust
+# use derive_more::{Deref, DerefMut};
+#
+#[derive(Deref, DerefMut)]
+struct CoolVec {
+ cool: bool,
+ #[deref]
+ #[deref_mut]
+ vec: Vec<i32>,
+}
+```
+
+Code like this will be generated:
+
+```rust
+# struct CoolVec {
+# cool: bool,
+# vec: Vec<i32>,
+# }
+# impl ::core::ops::Deref for CoolVec {
+# type Target = Vec<i32>;
+# #[inline]
+# fn deref(&self) -> &Self::Target {
+# &self.vec
+# }
+# }
+impl ::core::ops::DerefMut for CoolVec {
+ #[inline]
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.vec
+ }
+}
+```
+
+When deriving `DerefMut` for a tuple struct with one field:
+
+```rust
+# use derive_more::{Deref, DerefMut};
+#
+#[derive(Deref, DerefMut)]
+#[deref(forward)]
+#[deref_mut(forward)]
+struct MyBoxedInt(Box<i32>);
+```
+
+When deriving a forwarded `DerefMut` for a struct:
+
+```rust
+# struct MyBoxedInt(Box<i32>);
+# impl ::core::ops::Deref for MyBoxedInt {
+# type Target = <Box<i32> as ::core::ops::Deref>::Target;
+# #[inline]
+# fn deref(&self) -> &Self::Target {
+# <Box<i32> as ::core::ops::Deref>::deref(&self.0)
+# }
+# }
+impl ::core::ops::DerefMut for MyBoxedInt {
+ #[inline]
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ <Box<i32> as ::core::ops::DerefMut>::deref_mut(&mut self.0)
+ }
+}
+```
+
+
+
+
+## Enums
+
+Deriving `DerefMut` is not supported for enums.
diff --git a/third_party/rust/derive_more-impl/doc/display.md b/third_party/rust/derive_more-impl/doc/display.md
new file mode 100644
index 0000000000..5b616ca4d2
--- /dev/null
+++ b/third_party/rust/derive_more-impl/doc/display.md
@@ -0,0 +1,182 @@
+# What `#[derive(Display)]` generates
+
+Deriving `Display` will generate a `Display` implementation, with a `fmt`
+method that matches `self` and each of its variants. In the case of a struct or union,
+only a single variant is available, and it is thus equivalent to a simple `let` statement.
+In the case of an enum, each of its variants is matched.
+
+For each matched variant, a `write!` expression will be generated with
+the supplied format, or an automatically inferred one.
+
+You specify the format on each variant by writing e.g. `#[display("my val: {}", some_val * 2)]`.
+For enums, you can either specify it on each variant, or on the enum as a whole.
+
+For variants that don't have a format specified, it will simply defer to the format of the
+inner variable. If there is no such variable, or there is more than 1, an error is generated.
+
+
+
+
+## The format of the format
+
+You supply a format by attaching an attribute of the syntax: `#[display("...", args...)]`.
+The format supplied is passed verbatim to `write!`. The arguments supplied handled specially,
+due to constraints in the syntax of attributes. In the case of an argument being a simple
+identifier, it is passed verbatim. If an argument is a string, it is **parsed as an expression**,
+and then passed to `write!`.
+
+The variables available in the arguments is `self` and each member of the variant,
+with members of tuple structs being named with a leading underscore and their index,
+i.e. `_0`, `_1`, `_2`, etc.
+
+
+### Other formatting traits
+
+The syntax does not change, but the name of the attribute is the snake case version of the trait.
+E.g. `Octal` -> `octal`, `Pointer` -> `pointer`, `UpperHex` -> `upper_hex`.
+
+Note, that `Debug` has a slightly different API and semantics, described in its docs, and so,
+requires a separate `debug` feature.
+
+
+### Generic data types
+
+When deriving `Display` (or other formatting trait) for a generic struct/enum, all generic type
+arguments used during formatting are bound by respective formatting trait.
+
+E.g., for a structure `Foo` defined like this:
+```rust
+# use derive_more::Display;
+#
+# trait Trait { type Type; }
+#
+#[derive(Display)]
+#[display("{} {} {:?} {:p}", a, b, c, d)]
+struct Foo<'a, T1, T2: Trait, T3> {
+ a: T1,
+ b: <T2 as Trait>::Type,
+ c: Vec<T3>,
+ d: &'a T1,
+}
+```
+
+The following where clauses would be generated:
+* `T1: Display + Pointer`
+* `<T2 as Trait>::Type: Debug`
+* `Bar<T3>: Display`
+
+
+### Custom trait bounds
+
+Sometimes you may want to specify additional trait bounds on your generic type parameters, so that they
+could be used during formatting. This can be done with a `#[display(bound(...))]` attribute.
+
+`#[display(bound(...))]` accepts code tokens in a format similar to the format
+used in angle bracket list (or `where` clause predicates): `T: MyTrait, U: Trait1 + Trait2`.
+
+Only type parameters defined on a struct allowed to appear in bound-string and they can only be bound
+by traits, i.e. no lifetime parameters or lifetime bounds allowed in bound-string.
+
+`#[display("fmt", ...)]` arguments are parsed as an arbitrary Rust expression and passed to generated
+`write!` as-is, it's impossible to meaningfully infer any kind of trait bounds for generic type parameters
+used this way. That means that you'll **have to** explicitly specify all trait bound used. Either in the
+struct/enum definition, or via `#[display(bound(...))]` attribute.
+
+Note how we have to bound `U` and `V` by `Display` in the following example, as no bound is inferred.
+Not even `Display`.
+
+```rust
+# use derive_more::Display;
+#
+# trait MyTrait { fn my_function(&self) -> i32; }
+#
+#[derive(Display)]
+#[display(bound(T: MyTrait, U: Display))]
+#[display("{} {} {}", a.my_function(), b.to_string().len(), c)]
+struct MyStruct<T, U, V> {
+ a: T,
+ b: U,
+ c: V,
+}
+```
+
+
+
+
+## Example usage
+
+```rust
+# use std::path::PathBuf;
+#
+# use derive_more::{Display, Octal, UpperHex};
+#
+#[derive(Display)]
+struct MyInt(i32);
+
+#[derive(Display)]
+#[display("({x}, {y})")]
+struct Point2D {
+ x: i32,
+ y: i32,
+}
+
+#[derive(Display)]
+enum E {
+ Uint(u32),
+ #[display("I am B {:b}", i)]
+ Binary {
+ i: i8,
+ },
+ #[display("I am C {}", _0.display())]
+ Path(PathBuf),
+}
+
+#[derive(Display)]
+#[display("Hello there!")]
+union U {
+ i: u32,
+}
+
+#[derive(Octal)]
+#[octal("7")]
+struct S;
+
+#[derive(UpperHex)]
+#[upper_hex("UpperHex")]
+struct UH;
+
+#[derive(Display)]
+struct Unit;
+
+#[derive(Display)]
+struct UnitStruct {}
+
+#[derive(Display)]
+#[display("{}", self.sign())]
+struct PositiveOrNegative {
+ x: i32,
+}
+
+impl PositiveOrNegative {
+ fn sign(&self) -> &str {
+ if self.x >= 0 {
+ "Positive"
+ } else {
+ "Negative"
+ }
+ }
+}
+
+assert_eq!(MyInt(-2).to_string(), "-2");
+assert_eq!(Point2D { x: 3, y: 4 }.to_string(), "(3, 4)");
+assert_eq!(E::Uint(2).to_string(), "2");
+assert_eq!(E::Binary { i: -2 }.to_string(), "I am B 11111110");
+assert_eq!(E::Path("abc".into()).to_string(), "I am C abc");
+assert_eq!(U { i: 2 }.to_string(), "Hello there!");
+assert_eq!(format!("{:o}", S), "7");
+assert_eq!(format!("{:X}", UH), "UpperHex");
+assert_eq!(Unit.to_string(), "Unit");
+assert_eq!(UnitStruct {}.to_string(), "UnitStruct");
+assert_eq!(PositiveOrNegative { x: 1 }.to_string(), "Positive");
+assert_eq!(PositiveOrNegative { x: -1 }.to_string(), "Negative");
+```
diff --git a/third_party/rust/derive_more-impl/doc/error.md b/third_party/rust/derive_more-impl/doc/error.md
new file mode 100644
index 0000000000..20ff24cfe4
--- /dev/null
+++ b/third_party/rust/derive_more-impl/doc/error.md
@@ -0,0 +1,150 @@
+# Using `#[derive(Error)]`
+
+Deriving `Error` will generate an `Error` implementation, that contains
+(depending on the type) a `source()` and a `provide()` method. Please note,
+at the time of writing `provide()` is only supported on nightly rust. So you
+have to use that to make use of it.
+
+For a struct, these methods always do the same. For an `enum` they have separate
+behaviour for each of the variants. The variant is first matched and then the
+implementation will do the same as it would have done if the variant was a
+struct.
+
+Usually when you derive `Error` you will also want to [derive `Display`](crate::Display) and
+often [`From` as well](crate::From).
+
+
+### When and how does it derive `source()`?
+
+1. It's a struct/variant with named fields and one is the fields is
+ called `source`. Then it would return that field as the `source`.
+2. It's a tuple struct/variant and there's exactly one field that is not used as
+ the `backtrace`. So either a tuple struct with one field, or one with two where one
+ is the `backtrace`. Then it returns this field as the `source`.
+3. One of the fields is annotated with `#[error(source)]`. Then it would
+ return that field as the `source`.
+
+### When and how does it derive `provide()`?
+
+1. It's a struct/variant with named fields and one of the fields is
+ called `backtrace`. Then it would return that field as the `backtrace`.
+2. It's a tuple struct/variant and the type of exactly one of the fields is
+ called `Backtrace`. Then it would return that field as the `backtrace`.
+3. One of the fields is annotated with `#[error(backtrace)]`. Then it would
+ return that field as the `backtrace`.
+
+### Ignoring fields for derives
+
+It's possible to ignore a field or a whole enum variant completely for this
+derive using the `#[error(ignore)]` attribute. This will ignore it both for
+detecting `backtrace` and `source`. It's also possible to mark a field only
+ignored for one of these methods by using `#[error(not(backtrace))]` or
+`#[error(not(source))]`.
+
+
+### What works in `no_std`?
+
+If you want to use the `Error` derive on `no_std` environments, then you need to
+compile with nightly and enable this feature:
+```ignore
+#![feature(error_in_core)]
+```
+
+Backtraces don't work though, because the `Backtrace` type is only available in
+`std`.
+
+
+
+
+## Example usage
+
+```rust
+# #![cfg_attr(nightly, feature(error_generic_member_access, provide_any))]
+// Nightly requires enabling these features:
+// #![feature(error_generic_member_access, provide_any)]
+# #[cfg(not(nightly))] fn main() {}
+# #[cfg(nightly)] fn main() {
+# use std::{any, error::Error as _, backtrace::Backtrace};
+#
+# use derive_more::{Display, Error, From};
+
+// std::error::Error requires std::fmt::Debug and std::fmt::Display,
+// so we can also use derive_more::Display for fully declarative
+// error-type definitions.
+
+#[derive(Default, Debug, Display, Error)]
+struct Simple;
+
+#[derive(Default, Debug, Display, Error)]
+struct WithSource {
+ source: Simple,
+}
+#[derive(Default, Debug, Display, Error)]
+struct WithExplicitSource {
+ #[error(source)]
+ explicit_source: Simple,
+}
+
+#[derive(Default, Debug, Display, Error)]
+struct Tuple(Simple);
+
+#[derive(Default, Debug, Display, Error)]
+struct WithoutSource(#[error(not(source))] i32);
+
+#[derive(Debug, Display, Error)]
+#[display("An error with a backtrace")]
+struct WithSourceAndBacktrace {
+ source: Simple,
+ backtrace: Backtrace,
+}
+
+// derive_more::From fits nicely into this pattern as well
+#[derive(Debug, Display, Error, From)]
+enum CompoundError {
+ Simple,
+ WithSource {
+ source: Simple,
+ },
+ #[from(ignore)]
+ WithBacktraceFromSource {
+ #[error(backtrace)]
+ source: Simple,
+ },
+ #[display("{source}")]
+ WithDifferentBacktrace {
+ source: Simple,
+ backtrace: Backtrace,
+ },
+ WithExplicitSource {
+ #[error(source)]
+ explicit_source: WithSource,
+ },
+ #[from(ignore)]
+ WithBacktraceFromExplicitSource {
+ #[error(backtrace, source)]
+ explicit_source: WithSource,
+ },
+ Tuple(WithExplicitSource),
+ WithoutSource(#[error(not(source))] Tuple),
+}
+
+assert!(Simple.source().is_none());
+assert!(any::request_ref::<Backtrace>(&Simple).is_none());
+assert!(WithSource::default().source().is_some());
+assert!(WithExplicitSource::default().source().is_some());
+assert!(Tuple::default().source().is_some());
+assert!(WithoutSource::default().source().is_none());
+let with_source_and_backtrace = WithSourceAndBacktrace {
+ source: Simple,
+ backtrace: Backtrace::capture(),
+};
+assert!(with_source_and_backtrace.source().is_some());
+assert!(any::request_ref::<Backtrace>(&with_source_and_backtrace).is_some());
+
+assert!(CompoundError::Simple.source().is_none());
+assert!(CompoundError::from(Simple).source().is_some());
+assert!(CompoundError::from(WithSource::default()).source().is_some());
+assert!(CompoundError::from(WithExplicitSource::default()).source().is_some());
+assert!(CompoundError::from(Tuple::default()).source().is_none());
+# }
+```
diff --git a/third_party/rust/derive_more-impl/doc/from.md b/third_party/rust/derive_more-impl/doc/from.md
new file mode 100644
index 0000000000..1bc0cb4de3
--- /dev/null
+++ b/third_party/rust/derive_more-impl/doc/from.md
@@ -0,0 +1,188 @@
+# What `#[derive(From)]` generates
+
+The point of deriving this type is that it makes it easy to create a new
+instance of the type by using the `.into()` method on the value(s) that it
+should contain. This is done by implementing the `From` trait for the type
+that is passed to the derive.
+
+
+
+
+## Structs
+
+For structs with a single field you can call `.into()` on the desired content
+itself after deriving `From`.
+
+```rust
+# use derive_more::From;
+#
+#[derive(Debug, From, PartialEq)]
+struct Int(i32);
+
+assert_eq!(Int(2), 2.into());
+```
+
+For structs that have multiple fields `.into()` needs to be called on a tuple
+containing the desired content for each field.
+
+```rust
+# use derive_more::From;
+#
+#[derive(Debug, From, PartialEq)]
+struct Point(i32, i32);
+
+assert_eq!(Point(1, 2), (1, 2).into());
+```
+
+To specify concrete types to derive convert from use `#[from(<types>)]`.
+
+```rust
+# use std::borrow::Cow;
+#
+# use derive_more::From;
+#
+#[derive(Debug, From, PartialEq)]
+#[from(Cow<'static, str>, String, &'static str)]
+struct Str(Cow<'static, str>);
+
+assert_eq!(Str("&str".into()), "&str".into());
+assert_eq!(Str("String".into()), "String".to_owned().into());
+assert_eq!(Str("Cow".into()), Cow::Borrowed("Cow").to_owned().into());
+
+#[derive(Debug, From, PartialEq)]
+#[from((i16, i16), (i32, i32))]
+struct Point {
+ x: i32,
+ y: i32,
+}
+
+assert_eq!(Point { x: 1_i32, y: 2_i32 }, (1_i16, 2_i16).into());
+assert_eq!(Point { x: 3_i32, y: 4_i32 }, (3_i32, 4_i32).into());
+```
+
+Also, you can forward implementation to the inner type, which means deriving `From` for any type, that derives `From`
+inner type.
+
+```rust
+# use std::borrow::Cow;
+#
+# use derive_more::From;
+#
+#[derive(Debug, From, PartialEq)]
+#[from(forward)]
+struct Str {
+ inner: Cow<'static, str>,
+}
+
+assert_eq!(Str { inner: "&str".into() }, "&str".into());
+assert_eq!(Str { inner: "String".into() }, "String".to_owned().into());
+assert_eq!(Str { inner: "Cow".into() }, Cow::Borrowed("Cow").to_owned().into());
+```
+
+
+
+
+## Enums
+
+For enums `.into()` works for each variant as if they were structs. This
+includes specifying concrete types via `#[from(<types>)]` or forwarding
+implementation with `#[from(forward)]`.
+
+```rust
+# use derive_more::From;
+#
+#[derive(Debug, From, PartialEq)]
+enum IntOrPoint {
+ Int(i32),
+ Point {
+ x: i32,
+ y: i32,
+ },
+}
+
+assert_eq!(IntOrPoint::Int(1), 1.into());
+assert_eq!(IntOrPoint::Point { x: 1, y: 2 }, (1, 2).into());
+```
+
+By default, `From` is generated for every enum variant, but you can skip some
+variants via `#[from(skip)]` or only concrete fields via `#[from]`.
+
+```rust
+# mod from {
+# use derive_more::From;
+#[derive(Debug, From, PartialEq)]
+enum Int {
+ #[from]
+ Derived(i32),
+ NotDerived(i32),
+}
+# }
+
+// Is equivalent to:
+
+# mod skip {
+# use derive_more::From;
+#[derive(Debug, From, PartialEq)]
+enum Int {
+ Derived(i32),
+ #[from(skip)]
+ NotDerived(i32),
+}
+# }
+```
+
+
+
+
+## Example usage
+
+```rust
+# use derive_more::From;
+#
+// Allow converting from i32
+#[derive(From, PartialEq)]
+struct MyInt(i32);
+
+// Forward from call to the field, so allow converting
+// from anything that can be converted into an i64 (so most integers)
+#[derive(From, PartialEq)]
+#[from(forward)]
+struct MyInt64(i64);
+
+// You can ignore a variant
+#[derive(From, PartialEq)]
+enum MyEnum {
+ SmallInt(i32),
+ NamedBigInt { int: i64 },
+ #[from(ignore)]
+ NoFromImpl(i64),
+}
+
+// Or explicitly annotate the ones you need
+#[derive(From, PartialEq)]
+enum MyEnum2 {
+ #[from]
+ SmallInt(i32),
+ #[from]
+ NamedBigInt { int: i64 },
+ NoFromImpl(i64),
+}
+
+// And even specify additional conversions for them
+#[derive(From, PartialEq)]
+enum MyEnum3 {
+ #[from(i8, i32)]
+ SmallInt(i32),
+ #[from(i16, i64)]
+ NamedBigInt { int: i64 },
+ NoFromImpl(i64),
+}
+
+assert!(MyInt(2) == 2.into());
+assert!(MyInt64(6) == 6u8.into());
+assert!(MyEnum::SmallInt(123) == 123i32.into());
+assert!(MyEnum::SmallInt(123) != 123i64.into());
+assert!(MyEnum::NamedBigInt{int: 123} == 123i64.into());
+assert!(MyEnum3::SmallInt(123) == 123i8.into());
+assert!(MyEnum3::NamedBigInt{int: 123} == 123i16.into());
+```
diff --git a/third_party/rust/derive_more-impl/doc/from_str.md b/third_party/rust/derive_more-impl/doc/from_str.md
new file mode 100644
index 0000000000..d888e825db
--- /dev/null
+++ b/third_party/rust/derive_more-impl/doc/from_str.md
@@ -0,0 +1,135 @@
+# What `#[derive(FromStr)]` generates
+
+Deriving `FromStr` only works for enums with no fields
+or newtypes, i.e structs with only a single
+field. The result is that you will be able to call the `parse()` method on a
+string to convert it to your newtype. This only works when the type that is
+contained in the type implements `FromStr`.
+
+
+
+
+## Example usage
+
+```rust
+# use derive_more::FromStr;
+#
+#[derive(FromStr, Debug, Eq, PartialEq)]
+struct MyInt(i32);
+
+#[derive(FromStr, Debug, Eq, PartialEq)]
+struct Point1D{
+ x: i32,
+}
+
+assert_eq!(MyInt(5), "5".parse().unwrap());
+assert_eq!(Point1D{x: 100}, "100".parse().unwrap());
+```
+
+
+
+
+## Tuple structs
+
+When deriving `FromStr` for a tuple struct with one field:
+
+```rust
+# use derive_more::FromStr;
+#
+#[derive(FromStr)]
+struct MyInt(i32);
+```
+
+Code like this will be generated:
+
+```rust
+# struct MyInt(i32);
+impl ::core::str::FromStr for MyInt {
+ type Err = <i32 as ::core::str::FromStr>::Err;
+ fn from_str(src: &str) -> Result<Self, Self::Err> {
+ return Ok(MyInt(i32::from_str(src)?));
+ }
+}
+```
+
+
+
+
+## Regular structs
+
+When deriving `FromStr` for a regular struct with one field:
+
+```rust
+# use derive_more::FromStr;
+#
+#[derive(FromStr)]
+struct Point1D {
+ x: i32,
+}
+```
+
+Code like this will be generated:
+
+```rust
+# struct Point1D {
+# x: i32,
+# }
+impl ::core::str::FromStr for Point1D {
+ type Err = <i32 as ::core::str::FromStr>::Err;
+ fn from_str(src: &str) -> Result<Self, Self::Err> {
+ return Ok(Point1D {
+ x: i32::from_str(src)?,
+ });
+ }
+}
+```
+
+
+
+
+## Enums
+
+When deriving `FromStr` for an enums with variants with no fields it will
+generate a `from_str` method that converts strings that match the variant name
+to the variant. If using a case insensitive match would give a unique variant
+(i.e you dont have both a `MyEnum::Foo` and a `MyEnum::foo` variant) then case
+insensitive matching will be used, otherwise it will fall back to exact string
+matching.
+
+Since the string may not match any variants an error type is needed, so the
+`derive_more::FromStrError` will be used for that purpose.
+
+e.g. Given the following enum:
+
+```rust
+# use derive_more::FromStr;
+#
+#[derive(FromStr)]
+enum EnumNoFields {
+ Foo,
+ Bar,
+ Baz,
+}
+```
+
+Code like this will be generated:
+
+```rust
+# enum EnumNoFields {
+# Foo,
+# Bar,
+# Baz,
+# }
+#
+impl ::core::str::FromStr for EnumNoFields {
+ type Err = ::derive_more::FromStrError;
+ fn from_str(src: &str) -> Result<Self, Self::Err> {
+ Ok(match src.to_lowercase().as_str() {
+ "foo" => EnumNoFields::Foo,
+ "bar" => EnumNoFields::Bar,
+ "baz" => EnumNoFields::Baz,
+ _ => return Err(::derive_more::FromStrError::new("EnumNoFields")),
+ })
+ }
+}
+```
diff --git a/third_party/rust/derive_more-impl/doc/index.md b/third_party/rust/derive_more-impl/doc/index.md
new file mode 100644
index 0000000000..c45fb46df5
--- /dev/null
+++ b/third_party/rust/derive_more-impl/doc/index.md
@@ -0,0 +1,74 @@
+# What `#[derive(Index)]` generates
+
+Deriving `Index` only works for a single field of a struct.
+The result is that you will index it's member directly.
+
+With `#[index]` or `#[index(ignore)]` it's possible to indicate the field that
+you want to derive `Index` for.
+
+
+
+
+## Example usage
+
+```rust
+# use derive_more::Index;
+#
+#[derive(Index)]
+struct MyVec(Vec<i32>);
+
+// You can specify the field you want to derive Index for
+#[derive(Index)]
+struct Numbers {
+ #[index]
+ numbers: Vec<i32>,
+ useless: bool,
+}
+
+assert_eq!(5, MyVec(vec![5, 8])[0]);
+assert_eq!(200, Numbers { numbers: vec![100, 200], useless: false }[1]);
+```
+
+
+
+
+## Structs
+
+When deriving `Index` for a struct:
+
+```rust
+# use derive_more::Index;
+#
+#[derive(Index)]
+struct Numbers {
+ #[index]
+ numbers: Vec<i32>,
+ useless: bool,
+}
+```
+
+Code like this will be generated:
+
+```rust
+# struct Numbers {
+# numbers: Vec<i32>,
+# useless: bool,
+# }
+impl<__IdxT> ::core::ops::Index<__IdxT> for Numbers
+where
+ Vec<i32>: ::core::ops::Index<__IdxT>,
+{
+ type Output = <Vec<i32> as ::core::ops::Index<__IdxT>>::Output;
+ #[inline]
+ fn index(&self, idx: __IdxT) -> &Self::Output {
+ <Vec<i32> as ::core::ops::Index<__IdxT>>::index(&self.numbers, idx)
+ }
+}
+```
+
+
+
+
+## Enums
+
+Deriving `Index` is not supported for enums.
diff --git a/third_party/rust/derive_more-impl/doc/index_mut.md b/third_party/rust/derive_more-impl/doc/index_mut.md
new file mode 100644
index 0000000000..ff2347796e
--- /dev/null
+++ b/third_party/rust/derive_more-impl/doc/index_mut.md
@@ -0,0 +1,91 @@
+# What `#[derive(IndexMut)]` generates
+
+Deriving `IndexMut` only works for a single field of a struct.
+Furthermore it requires that the type also implements `Index`, so usually
+`Index` should also be derived.
+The result is that you will mutably index it's member directly.
+
+With `#[index_mut]` or `#[index_mut(ignore)]` it's possible to indicate the
+field that you want to derive `IndexMut` for.
+
+
+
+
+## Example usage
+
+```rust
+# use derive_more::{Index, IndexMut};
+#
+#[derive(Index, IndexMut)]
+struct MyVec(Vec<i32>);
+
+#[derive(Index, IndexMut)]
+struct Numbers {
+ #[index]
+ #[index_mut]
+ numbers: Vec<i32>,
+ useless: bool,
+}
+
+let mut myvec = MyVec(vec![5, 8]);
+myvec[0] = 50;
+assert_eq!(50, myvec[0]);
+
+let mut numbers = Numbers{numbers: vec![100, 200], useless: false};
+numbers[1] = 400;
+assert_eq!(400, numbers[1]);
+```
+
+
+
+
+## Regular structs
+
+When deriving `IndexMut` for a struct:
+
+```rust
+# use derive_more::{Index, IndexMut};
+#
+#[derive(Index, IndexMut)]
+struct Numbers {
+ #[index]
+ #[index_mut]
+ numbers: Vec<i32>,
+ useless: bool,
+}
+```
+
+Code like this will be generated to implement `IndexMut`:
+
+```rust
+# struct Numbers {
+# numbers: Vec<i32>,
+# useless: bool,
+# }
+# impl<__IdxT> ::core::ops::Index<__IdxT> for Numbers
+# where
+# Vec<i32>: ::core::ops::Index<__IdxT>,
+# {
+# type Output = <Vec<i32> as ::core::ops::Index<__IdxT>>::Output;
+# #[inline]
+# fn index(&self, idx: __IdxT) -> &Self::Output {
+# <Vec<i32> as ::core::ops::Index<__IdxT>>::index(&self.numbers, idx)
+# }
+# }
+impl<__IdxT> ::core::ops::IndexMut<__IdxT> for Numbers
+where
+ Vec<i32>: ::core::ops::IndexMut<__IdxT>,
+{
+ #[inline]
+ fn index_mut(&mut self, idx: __IdxT) -> &mut Self::Output {
+ <Vec<i32> as ::core::ops::IndexMut<__IdxT>>::index_mut(&mut self.numbers, idx)
+ }
+}
+```
+
+
+
+
+## Enums
+
+Deriving `IndexMut` is not supported for enums.
diff --git a/third_party/rust/derive_more-impl/doc/into.md b/third_party/rust/derive_more-impl/doc/into.md
new file mode 100644
index 0000000000..0ca676d9b3
--- /dev/null
+++ b/third_party/rust/derive_more-impl/doc/into.md
@@ -0,0 +1,119 @@
+# What `#[derive(Into)]` generates
+
+This derive creates the exact opposite of `#[derive(From)]`.
+Instead of allowing you to create a new instance of the struct from the values
+it should contain, it allows you to extract the values from the struct. One
+thing to note is that this derive doesn't actually generate an implementation
+for the `Into` trait. Instead, it derives `From` for the values contained in
+the struct and thus has an indirect implementation of `Into` as
+[recommended by the docs][1].
+
+
+
+
+## Structs
+
+For structs with a single field you can call `.into()` to extract the inner type.
+
+```rust
+# use derive_more::Into;
+#
+#[derive(Debug, Into, PartialEq)]
+struct Int(i32);
+
+assert_eq!(2, Int(2).into());
+```
+
+For structs having multiple fields, `.into()` extracts a tuple containing the
+desired content for each field.
+
+```rust
+# use derive_more::Into;
+#
+#[derive(Debug, Into, PartialEq)]
+struct Point(i32, i32);
+
+assert_eq!((1, 2), Point(1, 2).into());
+```
+
+To specify concrete types for deriving conversions into, use `#[into(<types>)]`.
+
+```rust
+# use std::borrow::Cow;
+#
+# use derive_more::Into;
+#
+#[derive(Debug, Into, PartialEq)]
+#[into(Cow<'static, str>, String)]
+struct Str(Cow<'static, str>);
+
+assert_eq!("String".to_owned(), String::from(Str("String".into())));
+assert_eq!(Cow::Borrowed("Cow"), <Cow<_>>::from(Str("Cow".into())));
+
+#[derive(Debug, Into, PartialEq)]
+#[into((i64, i64), (i32, i32))]
+struct Point {
+ x: i32,
+ y: i32,
+}
+
+assert_eq!((1_i64, 2_i64), Point { x: 1_i32, y: 2_i32 }.into());
+assert_eq!((3_i32, 4_i32), Point { x: 3_i32, y: 4_i32 }.into());
+```
+
+In addition to converting to owned types, this macro supports deriving into
+reference (mutable or not) via `#[into(ref(...))]`/`#[into(ref_mut(...))]`.
+
+```rust
+# use derive_more::Into;
+#
+#[derive(Debug, Into, PartialEq)]
+#[into(owned, ref(i32), ref_mut)]
+struct Int(i32);
+
+assert_eq!(2, Int(2).into());
+assert_eq!(&2, <&i32>::from(&Int(2)));
+assert_eq!(&mut 2, <&mut i32>::from(&mut Int(2)));
+```
+
+In case there are fields, that shouldn't be included in the conversion, use the
+`#[into(skip)]` attribute.
+
+```rust
+# use std::marker::PhantomData;
+#
+# use derive_more::Into;
+#
+# struct Gram;
+#
+#[derive(Debug, Into, PartialEq)]
+#[into(i32, i64, i128)]
+struct Mass<Unit> {
+ value: i32,
+ #[into(skip)]
+ _unit: PhantomData<Unit>,
+}
+
+assert_eq!(5, Mass::<Gram>::new(5).into());
+assert_eq!(5_i64, Mass::<Gram>::new(5).into());
+assert_eq!(5_i128, Mass::<Gram>::new(5).into());
+#
+# impl<Unit> Mass<Unit> {
+# fn new(value: i32) -> Self {
+# Self {
+# value,
+# _unit: PhantomData,
+# }
+# }
+# }
+```
+
+## Enums
+
+Deriving `Into` for enums is not supported as it would not always be successful,
+so `TryInto` should be used instead.
+
+
+
+
+[1]: https://doc.rust-lang.org/core/convert/trait.Into.html
diff --git a/third_party/rust/derive_more-impl/doc/into_iterator.md b/third_party/rust/derive_more-impl/doc/into_iterator.md
new file mode 100644
index 0000000000..c9abe66c28
--- /dev/null
+++ b/third_party/rust/derive_more-impl/doc/into_iterator.md
@@ -0,0 +1,101 @@
+# Using `#[derive(IntoIterator)]`
+
+Deriving `IntoIterator` only works for a single field of a struct.
+The result is that you will call `.into_iter()` on this field directly.
+
+With `#[into_iterator]` or `#[into_iterator(ignore)]` it's possible to indicate
+the field that you want to derive `IntoIterator` for.
+
+By using `#[into_iterator(owned, ref, ref_mut)]` it's possible to derive an
+`IntoIterator` implementation for reference types as well.
+You can pick any combination of `owned`, `ref` and `ref_mut`.
+If that's not provided the default is `#[IntoIterator(owned)]`.
+
+
+
+
+## Example usage
+
+```rust
+# use derive_more::IntoIterator;
+#
+#[derive(IntoIterator)]
+struct MyVec(Vec<i32>);
+
+// You can specify the field you want to derive `IntoIterator` for
+#[derive(IntoIterator)]
+struct Numbers {
+ #[into_iterator(owned, ref, ref_mut)]
+ numbers: Vec<i32>,
+ useless: bool,
+}
+
+assert_eq!(Some(5), MyVec(vec![5, 8]).into_iter().next());
+
+let mut nums = Numbers{numbers: vec![100, 200], useless: false};
+assert_eq!(Some(&100), (&nums).into_iter().next());
+assert_eq!(Some(&mut 100), (&mut nums).into_iter().next());
+assert_eq!(Some(100), nums.into_iter().next());
+```
+
+
+
+
+## Structs
+
+When deriving `IntoIterator` for a struct:
+
+```rust
+# use derive_more::IntoIterator;
+#
+#[derive(IntoIterator)]
+struct Numbers {
+ #[into_iterator(owned, ref, ref_mut)]
+ numbers: Vec<i32>,
+ useless: bool,
+}
+```
+
+Code like this will be generated:
+
+```rust
+# struct Numbers {
+# numbers: Vec<i32>,
+# useless: bool,
+# }
+impl ::core::iter::IntoIterator for Numbers {
+ type Item = <Vec<i32> as ::core::iter::IntoIterator>::Item;
+ type IntoIter = <Vec<i32> as ::core::iter::IntoIterator>::IntoIter;
+ #[inline]
+ fn into_iter(self) -> Self::IntoIter {
+ <Vec<i32> as ::core::iter::IntoIterator>::into_iter(self.numbers)
+ }
+}
+
+impl<'__deriveMoreLifetime> ::core::iter::IntoIterator for &'__deriveMoreLifetime Numbers {
+ type Item = <&'__deriveMoreLifetime Vec<i32> as ::core::iter::IntoIterator>::Item;
+ type IntoIter = <&'__deriveMoreLifetime Vec<i32> as ::core::iter::IntoIterator>::IntoIter;
+ #[inline]
+ fn into_iter(self) -> Self::IntoIter {
+ <&'__deriveMoreLifetime Vec<i32> as ::core::iter::IntoIterator>::into_iter(&self.numbers)
+ }
+}
+
+impl<'__deriveMoreLifetime> ::core::iter::IntoIterator for &'__deriveMoreLifetime mut Numbers {
+ type Item = <&'__deriveMoreLifetime mut Vec<i32> as ::core::iter::IntoIterator>::Item;
+ type IntoIter = <&'__deriveMoreLifetime mut Vec<i32> as ::core::iter::IntoIterator>::IntoIter;
+ #[inline]
+ fn into_iter(self) -> Self::IntoIter {
+ <&'__deriveMoreLifetime mut Vec<i32> as ::core::iter::IntoIterator>::into_iter(
+ &mut self.numbers,
+ )
+ }
+}
+```
+
+
+
+
+## Enums
+
+Deriving `IntoIterator` is not supported for enums.
diff --git a/third_party/rust/derive_more-impl/doc/is_variant.md b/third_party/rust/derive_more-impl/doc/is_variant.md
new file mode 100644
index 0000000000..9e549dc1bd
--- /dev/null
+++ b/third_party/rust/derive_more-impl/doc/is_variant.md
@@ -0,0 +1,43 @@
+# What `#[derive(IsVariant)]` generates
+
+When an enum is decorated with `#[derive(IsVariant)]`, for each variant `foo` in
+the enum, a public instance method `is_foo(&self) -> bool` is generated. If you
+don't want the `is_foo` method generated for a variant you can put the
+`#[is_variant(ignore)]` attribute on that variant.
+
+
+
+
+## Example usage
+
+```rust
+# use derive_more::IsVariant;
+#
+#[derive(IsVariant)]
+enum Maybe<T> {
+ Just(T),
+ Nothing
+}
+
+assert!(Maybe::<()>::Nothing.is_nothing());
+assert!(!Maybe::<()>::Nothing.is_just());
+```
+
+
+### What is generated?
+
+The derive in the above example code generates the following code:
+```rust
+# enum Maybe<T> {
+# Just(T),
+# Nothing
+# }
+impl <T> Maybe<T>{
+ pub const fn is_just(&self) -> bool {
+ match self {Self::Just(..) => true, _ => false}
+ }
+ pub const fn is_nothing(&self) -> bool {
+ match self {Self::Nothing => true, _ => false}
+ }
+}
+```
diff --git a/third_party/rust/derive_more-impl/doc/mul.md b/third_party/rust/derive_more-impl/doc/mul.md
new file mode 100644
index 0000000000..a1068bef0d
--- /dev/null
+++ b/third_party/rust/derive_more-impl/doc/mul.md
@@ -0,0 +1,148 @@
+# What `#[derive(Mul)]` generates
+
+Deriving `Mul` is quite different from deriving `Add`. It is not used to
+multiply two structs together. Instead it will normally multiply a struct, which
+can have multiple fields, with a single primitive type (e.g. a `u64`). A new
+struct is then created with all the fields from the previous struct multiplied
+by this other value.
+
+A simple way of explaining the reasoning behind this difference between `Add`
+and `Mul` deriving, is looking at arithmetic on meters.
+One meter can be added to one meter, to get two meters. Also, one meter times
+two would be two meters, but one meter times one meter would be one square meter.
+As this second case clearly requires more knowledge about the meaning of the
+type in question deriving for this is not implemented.
+
+NOTE: In case you don't want this behaviour you can add `#[mul(forward)]` in
+addition to `#[derive(Mul)]`. This will instead generate a `Mul` implementation
+with the same semantics as `Add`.
+
+
+
+
+## Tuple structs
+
+When deriving for a tuple struct with a single field (i.e. a newtype) like this:
+
+```rust
+# use derive_more::Mul;
+#
+#[derive(Mul)]
+struct MyInt(i32);
+```
+
+Code like this will be generated:
+
+```rust
+# struct MyInt(i32);
+impl<__RhsT> ::core::ops::Mul<__RhsT> for MyInt
+ where i32: ::core::ops::Mul<__RhsT, Output = i32>
+{
+ type Output = MyInt;
+ fn mul(self, rhs: __RhsT) -> MyInt {
+ MyInt(self.0.mul(rhs))
+ }
+}
+```
+
+The behaviour is slightly different for multiple fields, since the right hand
+side of the multiplication now needs the `Copy` trait.
+For instance when deriving for a tuple struct with two fields like this:
+
+```rust
+# use derive_more::Mul;
+#
+#[derive(Mul)]
+struct MyInts(i32, i32);
+```
+
+Code like this will be generated:
+
+```rust
+# struct MyInts(i32, i32);
+impl<__RhsT: ::core::marker::Copy> ::core::ops::Mul<__RhsT> for MyInts
+ where i32: ::core::ops::Mul<__RhsT, Output = i32>
+{
+ type Output = MyInts;
+ fn mul(self, rhs: __RhsT) -> MyInts {
+ MyInts(self.0.mul(rhs), self.1.mul(rhs))
+ }
+}
+```
+
+The behaviour is similar with more or less fields.
+
+
+
+
+## Regular structs
+
+When deriving `Mul` for a regular struct with a single field like this:
+
+```rust
+# use derive_more::Mul;
+#
+#[derive(Mul)]
+struct Point1D {
+ x: i32,
+}
+```
+
+Code like this will be generated:
+
+```rust
+# struct Point1D {
+# x: i32,
+# }
+impl<__RhsT> ::core::ops::Mul<__RhsT> for Point1D
+ where i32: ::core::ops::Mul<__RhsT, Output = i32>
+{
+ type Output = Point1D;
+ fn mul(self, rhs: __RhsT) -> Point1D {
+ Point1D { x: self.x.mul(rhs) }
+ }
+}
+```
+
+The behaviour is again slightly different when deriving for a struct with multiple
+fields, because it still needs the `Copy` as well.
+For instance when deriving for a tuple struct with two fields like this:
+
+```rust
+# use derive_more::Mul;
+#
+#[derive(Mul)]
+struct Point2D {
+ x: i32,
+ y: i32,
+}
+```
+
+Code like this will be generated:
+
+```rust
+# struct Point2D {
+# x: i32,
+# y: i32,
+# }
+impl<__RhsT: ::core::marker::Copy> ::core::ops::Mul<__RhsT> for Point2D
+ where i32: ::core::ops::Mul<__RhsT, Output = i32>
+{
+ type Output = Point2D;
+ fn mul(self, rhs: __RhsT) -> Point2D {
+ Point2D {
+ x: self.x.mul(rhs),
+ y: self.y.mul(rhs),
+ }
+ }
+}
+```
+
+
+
+
+## Enums
+
+Deriving `Mul` for enums is not (yet) supported, except when you use
+`#[mul(forward)]`.
+Although it shouldn't be impossible no effort has been put into this yet.
diff --git a/third_party/rust/derive_more-impl/doc/mul_assign.md b/third_party/rust/derive_more-impl/doc/mul_assign.md
new file mode 100644
index 0000000000..e5d9225ef3
--- /dev/null
+++ b/third_party/rust/derive_more-impl/doc/mul_assign.md
@@ -0,0 +1,92 @@
+# What `#[derive(MulAssign)]` generates
+
+This code is very similar to the code that is generated for `#[derive(Mul)]`.
+The difference is that it mutates the existing instance instead of creating a
+new one.
+
+You can add the `#[mul_assign(forward)]` attribute if you don't want the same
+semantics as `Mul`.
+This will instead generate a `MulAssign` implementation with the same semantics
+as `AddAssign`.
+
+
+
+
+## Tuple structs
+
+When deriving `MulAssign` for a tuple struct with two fields like this:
+
+```rust
+# use derive_more::MulAssign;
+#
+#[derive(MulAssign)]
+struct MyInts(i32, i32);
+```
+
+Code like this will be generated:
+
+```rust
+# struct MyInts(i32, i32);
+impl<__RhsT: ::core::marker::Copy> ::core::ops::MulAssign<__RhsT> for MyInts
+ where i32: ::core::ops::MulAssign<__RhsT>
+{
+ fn mul_assign(&mut self, rhs: __RhsT) {
+ self.0.mul_assign(rhs);
+ self.1.mul_assign(rhs);
+ }
+}
+```
+
+The behaviour is similar with more or less fields, except for the fact that
+`__RhsT` does not need to implement `Copy` when only a single field is present.
+
+
+
+
+## Regular structs
+
+When deriving `MulAssign` for a regular struct with two fields like this:
+
+```rust
+# use derive_more::MulAssign;
+#
+#[derive(MulAssign)]
+struct Point2D {
+ x: i32,
+ y: i32,
+}
+```
+
+Code like this will be generated:
+
+```rust
+# struct Point2D {
+# x: i32,
+# y: i32,
+# }
+impl<__RhsT: ::core::marker::Copy> ::core::ops::MulAssign<__RhsT> for Point2D
+ where i32: ::core::ops::MulAssign<__RhsT>
+{
+ fn mul_assign(&mut self, rhs: __RhsT) {
+ self.x.mul_assign(rhs);
+ self.y.mul_assign(rhs);
+ }
+}
+```
+
+The behaviour is again similar with more or less fields, except that `Copy`
+doesn't have to be implemented for `__Rhst` when the struct has only a single
+field.
+
+
+
+
+## Enums
+
+Deriving `MulAssign` for enums is not (yet) supported.
+This has two reason, the first being that deriving `Mul` is also not implemented
+for enums yet.
+The second reason is the same as for `AddAssign`.
+Even if it would be deriving `Mul` was implemented it would likely return a
+`Result<EnumType>` instead of an `EnumType`.
+Handling the case where it errors would be hard and maybe impossible.
diff --git a/third_party/rust/derive_more-impl/doc/not.md b/third_party/rust/derive_more-impl/doc/not.md
new file mode 100644
index 0000000000..9997c085ab
--- /dev/null
+++ b/third_party/rust/derive_more-impl/doc/not.md
@@ -0,0 +1,159 @@
+# What `#[derive(Not)]` generates
+
+The derived `Not` implementation simply negates all the fields of a
+struct and returns that as a new instance of the struct.
+For enums all fields of the active variant of the enum are negated and a new
+instance of the same variant with these negated fields is returned.
+
+
+
+
+## Tuple structs
+
+When deriving for a tuple struct with two fields like this:
+
+```rust
+# use derive_more::Not;
+#
+#[derive(Not)]
+struct MyInts(i32, i32);
+```
+
+Code like this will be generated:
+
+```rust
+# struct MyInts(i32, i32);
+impl ::core::ops::Not for MyInts {
+ type Output = MyInts;
+ fn not(self) -> MyInts {
+ MyInts(self.0.not(), self.1.not())
+ }
+}
+```
+
+The behaviour is similar with more or less fields.
+
+
+
+
+## Regular structs
+
+When deriving for a regular struct with two fields like this:
+
+```rust
+# use derive_more::Not;
+#
+#[derive(Not)]
+struct Point2D {
+ x: i32,
+ y: i32,
+}
+```
+
+Code like this will be generated:
+
+```rust
+# struct Point2D {
+# x: i32,
+# y: i32,
+# }
+impl ::core::ops::Not for Point2D {
+ type Output = Point2D;
+ fn not(self) -> Point2D {
+ Point2D {
+ x: self.x.not(),
+ y: self.y.not(),
+ }
+ }
+}
+```
+
+The behaviour is similar with more or less fields.
+
+
+
+
+## Enums
+
+For each enum variant `Not` is derived in a similar way as it would be derived
+if it would be its own type.
+For instance when deriving `Not` for an enum like this:
+
+```rust
+# use derive_more::Not;
+#
+#[derive(Not)]
+enum MixedInts {
+ SmallInt(i32),
+ BigInt(i64),
+ TwoSmallInts(i32, i32),
+ NamedSmallInts { x: i32, y: i32 },
+ UnsignedOne(u32),
+ UnsignedTwo(u32),
+}
+```
+
+Code like this will be generated:
+
+```rust
+# enum MixedInts {
+# SmallInt(i32),
+# BigInt(i64),
+# TwoSmallInts(i32, i32),
+# NamedSmallInts { x: i32, y: i32 },
+# UnsignedOne(u32),
+# UnsignedTwo(u32),
+# }
+impl ::core::ops::Not for MixedInts {
+ type Output = MixedInts;
+ fn not(self) -> MixedInts {
+ match self {
+ MixedInts::SmallInt(__0) => MixedInts::SmallInt(__0.not()),
+ MixedInts::BigInt(__0) => MixedInts::BigInt(__0.not()),
+ MixedInts::TwoSmallInts(__0, __1) => MixedInts::TwoSmallInts(__0.not(), __1.not()),
+ MixedInts::NamedSmallInts { x: __0, y: __1 } => {
+ MixedInts::NamedSmallInts {
+ x: __0.not(),
+ y: __1.not(),
+ }
+ }
+ MixedInts::UnsignedOne(__0) => MixedInts::UnsignedOne(__0.not()),
+ MixedInts::UnsignedTwo(__0) => MixedInts::UnsignedTwo(__0.not()),
+ }
+ }
+}
+```
+
+There is one important thing to remember though.
+If you add a unit variant to the enum its return type will change from
+`EnumType` to `Result<EnumType>`.
+This is because Unit cannot have `Not` implemented.
+So, when deriving `Not` for an enum like this:
+
+```rust
+# use derive_more::Not;
+#
+#[derive(Not)]
+enum EnumWithUnit {
+ SmallInt(i32),
+ Unit,
+}
+```
+
+Code like this will be generated:
+
+```rust
+# enum EnumWithUnit {
+# SmallInt(i32),
+# Unit,
+# }
+impl ::core::ops::Not for EnumWithUnit {
+ type Output = Result<EnumWithUnit, ::derive_more::ops::UnitError>;
+ fn not(self) -> Result<EnumWithUnit, ::derive_more::ops::UnitError> {
+ match self {
+ EnumWithUnit::SmallInt(__0) => Ok(EnumWithUnit::SmallInt(__0.not())),
+ EnumWithUnit::Unit => Err(::derive_more::ops::UnitError::new("not")),
+ }
+ }
+}
+```
diff --git a/third_party/rust/derive_more-impl/doc/sum.md b/third_party/rust/derive_more-impl/doc/sum.md
new file mode 100644
index 0000000000..ffb5ea6be2
--- /dev/null
+++ b/third_party/rust/derive_more-impl/doc/sum.md
@@ -0,0 +1,77 @@
+# Using `#[derive(Sum)]`
+
+The derived `Sum` implementation will allow an iterator of your type to be
+summed together into a new instance of the type with all the fields added
+together. Apart from the original types requiring an implementation of `Sum`, it
+is also required that your type to implements `Add`. So normally you want to
+derive that one as well.
+
+All this is also true for the `Product`, except that then all the fields are
+multiplied and an implementation of `Mul` is required. This is usually the
+easiest to implement by adding `#[derive(MulSelf)]`.
+
+
+
+
+## Example usage
+
+```rust
+# use derive_more::{Add, Sum};
+#
+#[derive(Add, Sum, PartialEq)]
+struct MyInts(i32, i64);
+
+let int_vec = vec![MyInts(2, 3), MyInts(4, 5), MyInts(6, 7)];
+assert!(MyInts(12, 15) == int_vec.into_iter().sum())
+```
+
+
+
+
+## Structs
+
+When deriving `Sum` for a struct with two fields its like this:
+
+```rust
+# use derive_more::{Add, Sum};
+#
+#[derive(Add, Sum)]
+struct MyInts(i32, i64);
+```
+
+Code like this will be generated for the `Sum` implementation:
+
+```rust
+# struct MyInts(i32, i64);
+# impl ::core::ops::Add for MyInts {
+# type Output = MyInts;
+# #[inline]
+# fn add(self, rhs: MyInts) -> MyInts {
+# MyInts(self.0.add(rhs.0), self.1.add(rhs.1))
+# }
+# }
+impl ::core::iter::Sum for MyInts {
+ #[inline]
+ fn sum<I: ::core::iter::Iterator<Item = Self>>(iter: I) -> Self {
+ iter.fold(
+ MyInts(
+ ::core::iter::empty::<i32>().sum(),
+ ::core::iter::empty::<i64>().sum(),
+ ),
+ ::core::ops::Add::add,
+ )
+ }
+}
+```
+
+The trick here is that we get the identity struct by calling sum on empty
+iterators.
+This way we can get the identity for sum (i.e. `0`) and the identity for product
+(i.e. `1`).
+
+
+
+
+## Enums
+
+Deriving `Sum` for enums is not supported.
diff --git a/third_party/rust/derive_more-impl/doc/try_into.md b/third_party/rust/derive_more-impl/doc/try_into.md
new file mode 100644
index 0000000000..252a33bf4d
--- /dev/null
+++ b/third_party/rust/derive_more-impl/doc/try_into.md
@@ -0,0 +1,182 @@
+# What `#[derive(TryInto)]` generates
+
+This derive allows you to convert enum variants into their corresponding
+variant types.
+One thing to note is that this derive doesn't actually generate an
+implementation for the `TryInto` trait.
+Instead it derives `TryFrom` for each variant in the enum and thus has an
+indirect implementation of `TryInto` as recommended by the
+[docs](https://doc.rust-lang.org/core/convert/trait.TryInto.html).
+
+By using `#[try_into(owned, ref, ref_mut)]` it's possible to derive a `TryInto`
+implementation for reference types as well.
+You can pick any combination of `owned`, `ref` and `ref_mut`.
+If that's not provided the default is `#[try_into(owned)]`.
+
+With `#[try_into]` or `#[try_into(ignore)]` it's possible to indicate which
+variants you want to derive `TryInto` for.
+
+
+
+
+## Example usage
+
+```rust
+# use derive_more::TryInto;
+#
+#[derive(TryInto, Clone, Debug)]
+#[try_into(owned, ref, ref_mut)]
+enum MixedData {
+ Int(u32),
+ String(String),
+}
+
+let mixed_string = MixedData::String("foo".to_string());
+let mixed_int1 = MixedData::Int(123);
+let mixed_int2 = mixed_int1.clone();
+let mut mixed_int3 = mixed_int1.clone();
+
+assert_eq!(123u32, mixed_int1.try_into().unwrap());
+
+let int_ref : &u32 = (&mixed_int2).try_into().unwrap();
+assert_eq!(&123u32, int_ref);
+
+let int_ref_mut : &mut u32 = (&mut mixed_int3).try_into().unwrap();
+assert_eq!(&mut 123u32, int_ref_mut);
+
+assert_eq!("foo".to_string(), String::try_from(mixed_string.clone()).unwrap());
+
+assert!(u32::try_from(mixed_string).is_err());
+```
+
+
+
+
+## Structs
+
+Deriving `TryInto` for structs is not supported because there is no failing
+mode. Use `#[derive(Into)]` instead. `TryInto` will automatically get a
+blanket implementation through `TryFrom`, automatically derived from `From`,
+which `#[derive(Into)]` produces.
+
+
+
+
+## Enums
+
+When deriving `TryInto` for an enum, each enum variant gets its own
+`TryFrom` implementation.
+For instance, when deriving `TryInto` for an enum link this:
+
+```rust
+# use derive_more::TryInto;
+#
+#[derive(TryInto)]
+enum MixedInts {
+ SmallInt(i32),
+ BigInt(i64),
+ TwoSmallInts(i32, i32),
+ NamedSmallInts { x: i64, y: i64 },
+ UnsignedOne(u32),
+ UnsignedTwo(u32),
+ #[try_into(ignore)]
+ NotImportant,
+}
+```
+
+Code like this will be generated:
+
+```rust
+# enum MixedInts {
+# SmallInt(i32),
+# BigInt(i64),
+# TwoSmallInts(i32, i32),
+# NamedSmallInts { x: i64, y: i64 },
+# UnsignedOne(u32),
+# UnsignedTwo(u32),
+# }
+impl ::core::convert::TryFrom<MixedInts> for (i32) {
+ type Error = &'static str;
+ fn try_from(value: MixedInts) -> Result<Self, Self::Error> {
+ match value {
+ MixedInts::SmallInt(__0) => Ok(__0),
+ _ => Err("Only SmallInt can be converted to i32"),
+ }
+ }
+}
+impl ::core::convert::TryFrom<MixedInts> for (i64) {
+ type Error = &'static str;
+ fn try_from(value: MixedInts) -> Result<Self, Self::Error> {
+ match value {
+ MixedInts::BigInt(__0) => Ok(__0),
+ _ => Err("Only BigInt can be converted to i64"),
+ }
+ }
+}
+impl ::core::convert::TryFrom<MixedInts> for (i32, i32) {
+ type Error = &'static str;
+ fn try_from(value: MixedInts) -> Result<Self, Self::Error> {
+ match value {
+ MixedInts::TwoSmallInts(__0, __1) => Ok((__0, __1)),
+ _ => Err("Only TwoSmallInts can be converted to (i32, i32)"),
+ }
+ }
+}
+impl ::core::convert::TryFrom<MixedInts> for (i64, i64) {
+ type Error = &'static str;
+ fn try_from(value: MixedInts) -> Result<Self, Self::Error> {
+ match value {
+ MixedInts::NamedSmallInts { x: __0, y: __1 } => Ok((__0, __1)),
+ _ => Err("Only NamedSmallInts can be converted to (i64, i64)"),
+ }
+ }
+}
+impl ::core::convert::TryFrom<MixedInts> for (u32) {
+ type Error = &'static str;
+ fn try_from(value: MixedInts) -> Result<Self, Self::Error> {
+ match value {
+ MixedInts::UnsignedOne(__0) | MixedInts::UnsignedTwo(__0) => Ok(__0),
+ _ => Err("Only UnsignedOne, UnsignedTwo can be converted to u32"),
+ }
+ }
+}
+```
+
+When deriving `TryInto` for an enum with Unit variants like this:
+
+```rust
+# use derive_more::TryInto;
+#
+#[derive(TryInto)]
+enum EnumWithUnit {
+ SmallInt(i32),
+ Unit,
+}
+```
+
+Code like this will be generated:
+
+```rust
+# enum EnumWithUnit {
+# SmallInt(i32),
+# Unit,
+# }
+impl ::core::convert::TryFrom<EnumWithUnit> for (i32) {
+ type Error = &'static str;
+ fn try_from(value: EnumWithUnit) -> Result<Self, Self::Error> {
+ match value {
+ EnumWithUnit::SmallInt(__0) => Ok(__0),
+ _ => Err("Only SmallInt can be converted to i32"),
+ }
+ }
+}
+impl ::core::convert::TryFrom<EnumWithUnit> for () {
+ type Error = &'static str;
+ fn try_from(value: EnumWithUnit) -> Result<Self, Self::Error> {
+ match value {
+ EnumWithUnit::Unit => Ok(()),
+ _ => Err("Only Unit can be converted to ()"),
+ }
+ }
+}
+```
diff --git a/third_party/rust/derive_more-impl/doc/try_unwrap.md b/third_party/rust/derive_more-impl/doc/try_unwrap.md
new file mode 100644
index 0000000000..f6ec49ee01
--- /dev/null
+++ b/third_party/rust/derive_more-impl/doc/try_unwrap.md
@@ -0,0 +1,80 @@
+# What `#[derive(TryUnwrap)]` generates
+
+This works almost like `Unwrap`.
+When an enum is decorated with `#[derive(TryUnwrap)]`, for each variant `foo` in the enum, with fields `(a, b, c, ...)` a public instance method `try_unwrap_foo(self) -> Result<(a, b, c, ...), TryUnwrapError<Self>>` is generated.
+If you don't want the `try_unwrap_foo` method generated for a variant, you can put the `#[try_unwrap(ignore)]` attribute on that variant.
+If you want to treat a reference, you can put the `#[try_unwrap(ref)]` attribute on the enum declaration or that variant, then `try_unwrap_foo_ref(self) -> Result<(&a, &b, &c, ...), TryUnwrapError<&Self>>` will be generated. You can also use mutable references by putting `#[unwrap(ref_mut)]`.
+However, unlike `Unwrap`, it does not panic if the conversion fails. Also, values that fail to convert are not dropped but returned as an `Err`.
+
+## Example usage
+
+```rust
+# use derive_more::TryUnwrap;
+#
+# #[derive(Debug, PartialEq)]
+#[derive(TryUnwrap)]
+#[try_unwrap(ref)]
+enum Maybe<T> {
+ Nothing,
+ Just(T),
+}
+
+fn main() {
+ assert_eq!(Maybe::Just(1).try_unwrap_just(), Ok(1));
+
+ // Unlike `Unwrap`, it does not panic.
+ assert_eq!(
+ Maybe::<()>::Nothing.try_unwrap_just().map_err(|err| err.input),
+ Err(Maybe::<()>::Nothing), // and the value is returned!
+ );
+ assert_eq!(
+ Maybe::Just(2).try_unwrap_nothing().map_err(|err| err.input),
+ Err(Maybe::Just(2)),
+ );
+ assert_eq!(
+ Maybe::<()>::Nothing.try_unwrap_just().map_err(|err| err.to_string()),
+ Err("Attempt to call `Maybe::try_unwrap_just()` on a `Maybe::Nothing` value".into()),
+ );
+
+ assert_eq!((&Maybe::Just(42)).try_unwrap_just_ref(), Ok(&42));
+}
+```
+
+### What is generated?
+
+The derive in the above example code generates the following code:
+```rust
+# use derive_more::TryUnwrapError;
+#
+# enum Maybe<T> {
+# Just(T),
+# Nothing,
+# }
+#
+impl<T> Maybe<T> {
+ pub fn try_unwrap_nothing(self) -> Result<(), TryUnwrapError<Self>> {
+ match self {
+ Maybe::Nothing => Ok(()),
+ val @ _ => Err(todo!("TryUnwrapError::new(val, /* omitted */)")),
+ }
+ }
+ pub fn try_unwrap_nothing_ref(&self) -> Result<(), TryUnwrapError<&Self>> {
+ match self {
+ Maybe::Nothing => Ok(()),
+ val @ _ => Err(todo!("TryUnwrapError::new(val, /* omitted */)")),
+ }
+ }
+ pub fn try_unwrap_just(self) -> Result<T, TryUnwrapError<Self>> {
+ match self {
+ Maybe::Just(field_0) => Ok(field_0),
+ val @ _ => Err(todo!("TryUnwrapError::new(val, /* omitted */)")),
+ }
+ }
+ pub fn try_unwrap_just_ref(&self) -> Result<&T, TryUnwrapError<&Self>> {
+ match self {
+ Maybe::Just(field_0) => Ok(field_0),
+ val @ _ => Err(todo!("TryUnwrapError::new(val, /* omitted */)")),
+ }
+ }
+}
+```
diff --git a/third_party/rust/derive_more-impl/doc/unwrap.md b/third_party/rust/derive_more-impl/doc/unwrap.md
new file mode 100644
index 0000000000..e1a103476b
--- /dev/null
+++ b/third_party/rust/derive_more-impl/doc/unwrap.md
@@ -0,0 +1,70 @@
+# What `#[derive(Unwrap)]` generates
+
+When an enum is decorated with `#[derive(Unwrap)]`, for each variant `foo` in the enum, with fields `(a, b, c, ...)` a public instance method `unwrap_foo(self) -> (a, b, c, ...)` is generated.
+If you don't want the `unwrap_foo` method generated for a variant, you can put the `#[unwrap(ignore)]` attribute on that variant.
+If you want to treat a reference, you can put the `#[unwrap(ref)]` attribute on the enum declaration or that variant, then `unwrap_foo_ref(self) -> (&a, &b, &c, ...)` will be generated. You can also use mutable references by putting `#[unwrap(ref_mut)]`.
+
+
+
+
+## Example usage
+
+```rust
+# use derive_more::Unwrap;
+#
+# #[derive(Debug, PartialEq)]
+#[derive(Unwrap)]
+#[unwrap(ref)]
+enum Maybe<T> {
+ Just(T),
+ Nothing,
+}
+
+fn main() {
+ assert_eq!(Maybe::Just(1).unwrap_just(), 1);
+
+ // Panics if variants are different
+ // assert_eq!(Maybe::<()>::Nothing.unwrap_just(), /* panic */);
+ // assert_eq!(Maybe::Just(2).unwrap_nothing(), /* panic */);
+
+ assert_eq!((&Maybe::Just(42)).unwrap_just_ref(), &42);
+}
+```
+
+
+### What is generated?
+
+The derive in the above example code generates the following code:
+```rust
+# enum Maybe<T> {
+# Just(T),
+# Nothing,
+# }
+#
+impl<T> Maybe<T> {
+ pub fn unwrap_nothing(self) -> () {
+ match self {
+ Maybe::Nothing => (),
+ _ => panic!(),
+ }
+ }
+ pub fn unwrap_nothing_ref(&self) -> () {
+ match self {
+ Maybe::Nothing => (),
+ _ => panic!(),
+ }
+ }
+ pub fn unwrap_just(self) -> T {
+ match self {
+ Maybe::Just(field_0) => field_0,
+ _ => panic!(),
+ }
+ }
+ pub fn unwrap_just_ref(&self) -> &T {
+ match self {
+ Maybe::Just(field_0) => field_0,
+ _ => panic!(),
+ }
+ }
+}
+```
diff --git a/third_party/rust/derive_more-impl/src/add_assign_like.rs b/third_party/rust/derive_more-impl/src/add_assign_like.rs
new file mode 100644
index 0000000000..610ba983e0
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/add_assign_like.rs
@@ -0,0 +1,39 @@
+use crate::add_helpers::{struct_exprs, tuple_exprs};
+use crate::utils::{add_extra_ty_param_bound_op, named_to_vec, unnamed_to_vec};
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote};
+use syn::{Data, DeriveInput, Fields};
+
+pub fn expand(input: &DeriveInput, trait_name: &str) -> TokenStream {
+ let trait_ident = format_ident!("{trait_name}");
+ let method_name = trait_name.trim_end_matches("Assign").to_lowercase();
+ let method_ident = format_ident!("{method_name}_assign");
+ let input_type = &input.ident;
+
+ let generics = add_extra_ty_param_bound_op(&input.generics, &trait_ident);
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ let exprs = match input.data {
+ Data::Struct(ref data_struct) => match data_struct.fields {
+ Fields::Unnamed(ref fields) => {
+ tuple_exprs(&unnamed_to_vec(fields), &method_ident)
+ }
+ Fields::Named(ref fields) => {
+ struct_exprs(&named_to_vec(fields), &method_ident)
+ }
+ _ => panic!("Unit structs cannot use derive({trait_name})"),
+ },
+
+ _ => panic!("Only structs can use derive({trait_name})"),
+ };
+
+ quote! {
+ #[automatically_derived]
+ impl #impl_generics ::core::ops::#trait_ident for #input_type #ty_generics #where_clause {
+ #[inline]
+ fn #method_ident(&mut self, rhs: #input_type #ty_generics) {
+ #( #exprs; )*
+ }
+ }
+ }
+}
diff --git a/third_party/rust/derive_more-impl/src/add_helpers.rs b/third_party/rust/derive_more-impl/src/add_helpers.rs
new file mode 100644
index 0000000000..b9cee1a682
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/add_helpers.rs
@@ -0,0 +1,28 @@
+use proc_macro2::TokenStream;
+use quote::quote;
+use syn::{Field, Ident, Index};
+
+pub fn tuple_exprs(fields: &[&Field], method_ident: &Ident) -> Vec<TokenStream> {
+ let mut exprs = vec![];
+
+ for i in 0..fields.len() {
+ let i = Index::from(i);
+ // generates `self.0.add(rhs.0)`
+ let expr = quote! { self.#i.#method_ident(rhs.#i) };
+ exprs.push(expr);
+ }
+ exprs
+}
+
+pub fn struct_exprs(fields: &[&Field], method_ident: &Ident) -> Vec<TokenStream> {
+ let mut exprs = vec![];
+
+ for field in fields {
+ // It's safe to unwrap because struct fields always have an identifier
+ let field_id = field.ident.as_ref().unwrap();
+ // generates `x: self.x.add(rhs.x)`
+ let expr = quote! { self.#field_id.#method_ident(rhs.#field_id) };
+ exprs.push(expr)
+ }
+ exprs
+}
diff --git a/third_party/rust/derive_more-impl/src/add_like.rs b/third_party/rust/derive_more-impl/src/add_like.rs
new file mode 100644
index 0000000000..58076461ca
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/add_like.rs
@@ -0,0 +1,153 @@
+use crate::add_helpers::{struct_exprs, tuple_exprs};
+use crate::utils::{
+ add_extra_type_param_bound_op_output, field_idents, named_to_vec, numbered_vars,
+ unnamed_to_vec,
+};
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote, ToTokens};
+use std::iter;
+use syn::{Data, DataEnum, DeriveInput, Field, Fields, Ident};
+
+pub fn expand(input: &DeriveInput, trait_name: &str) -> TokenStream {
+ let trait_name = trait_name.trim_end_matches("Self");
+ let trait_ident = format_ident!("{trait_name}");
+ let method_name = trait_name.to_lowercase();
+ let method_ident = format_ident!("{method_name}");
+ let input_type = &input.ident;
+
+ let generics = add_extra_type_param_bound_op_output(&input.generics, &trait_ident);
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ let (output_type, block) = match input.data {
+ Data::Struct(ref data_struct) => match data_struct.fields {
+ Fields::Unnamed(ref fields) => (
+ quote! { #input_type #ty_generics },
+ tuple_content(input_type, &unnamed_to_vec(fields), &method_ident),
+ ),
+ Fields::Named(ref fields) => (
+ quote! { #input_type #ty_generics },
+ struct_content(input_type, &named_to_vec(fields), &method_ident),
+ ),
+ _ => panic!("Unit structs cannot use derive({trait_name})"),
+ },
+ Data::Enum(ref data_enum) => (
+ quote! {
+ ::core::result::Result<#input_type #ty_generics, ::derive_more::ops::BinaryError>
+ },
+ enum_content(input_type, data_enum, &method_ident),
+ ),
+
+ _ => panic!("Only structs and enums can use derive({trait_name})"),
+ };
+
+ quote! {
+ #[automatically_derived]
+ impl #impl_generics ::derive_more::#trait_ident for #input_type #ty_generics #where_clause {
+ type Output = #output_type;
+
+ #[inline]
+ fn #method_ident(self, rhs: #input_type #ty_generics) -> #output_type {
+ #block
+ }
+ }
+ }
+}
+
+fn tuple_content<T: ToTokens>(
+ input_type: &T,
+ fields: &[&Field],
+ method_ident: &Ident,
+) -> TokenStream {
+ let exprs = tuple_exprs(fields, method_ident);
+ quote! { #input_type(#(#exprs),*) }
+}
+
+fn struct_content(
+ input_type: &Ident,
+ fields: &[&Field],
+ method_ident: &Ident,
+) -> TokenStream {
+ // It's safe to unwrap because struct fields always have an identifier
+ let exprs = struct_exprs(fields, method_ident);
+ let field_names = field_idents(fields);
+
+ quote! { #input_type{#(#field_names: #exprs),*} }
+}
+
+#[allow(clippy::cognitive_complexity)]
+fn enum_content(
+ input_type: &Ident,
+ data_enum: &DataEnum,
+ method_ident: &Ident,
+) -> TokenStream {
+ let mut matches = vec![];
+ let mut method_iter = iter::repeat(method_ident);
+
+ for variant in &data_enum.variants {
+ let subtype = &variant.ident;
+ let subtype = quote! { #input_type::#subtype };
+
+ match variant.fields {
+ Fields::Unnamed(ref fields) => {
+ // The pattern that is outputted should look like this:
+ // (Subtype(left_vars), TypePath(right_vars)) => Ok(TypePath(exprs))
+ let size = unnamed_to_vec(fields).len();
+ let l_vars = &numbered_vars(size, "l_");
+ let r_vars = &numbered_vars(size, "r_");
+ let method_iter = method_iter.by_ref();
+ let matcher = quote! {
+ (#subtype(#(#l_vars),*),
+ #subtype(#(#r_vars),*)) => {
+ ::core::result::Result::Ok(#subtype(#(#l_vars.#method_iter(#r_vars)),*))
+ }
+ };
+ matches.push(matcher);
+ }
+ Fields::Named(ref fields) => {
+ // The pattern that is outputted should look like this:
+ // (Subtype{a: __l_a, ...}, Subtype{a: __r_a, ...} => {
+ // Ok(Subtype{a: __l_a.add(__r_a), ...})
+ // }
+ let field_vec = named_to_vec(fields);
+ let size = field_vec.len();
+ let field_names = &field_idents(&field_vec);
+ let l_vars = &numbered_vars(size, "l_");
+ let r_vars = &numbered_vars(size, "r_");
+ let method_iter = method_iter.by_ref();
+ let matcher = quote! {
+ (#subtype{#(#field_names: #l_vars),*},
+ #subtype{#(#field_names: #r_vars),*}) => {
+ ::core::result::Result::Ok(#subtype{#(#field_names: #l_vars.#method_iter(#r_vars)),*})
+ }
+ };
+ matches.push(matcher);
+ }
+ Fields::Unit => {
+ let operation_name = method_ident.to_string();
+ matches.push(quote! {
+ (#subtype, #subtype) => ::core::result::Result::Err(
+ ::derive_more::ops::BinaryError::Unit(
+ ::derive_more::ops::UnitError::new(#operation_name)
+ )
+ )
+ });
+ }
+ }
+ }
+
+ if data_enum.variants.len() > 1 {
+ // In the strange case where there's only one enum variant this is would be an unreachable
+ // match.
+ let operation_name = method_ident.to_string();
+ matches.push(quote! {
+ _ => ::core::result::Result::Err(::derive_more::ops::BinaryError::Mismatch(
+ ::derive_more::ops::WrongVariantError::new(#operation_name)
+ ))
+ });
+ }
+ quote! {
+ match (self, rhs) {
+ #(#matches),*
+ }
+ }
+}
diff --git a/third_party/rust/derive_more-impl/src/as_mut.rs b/third_party/rust/derive_more-impl/src/as_mut.rs
new file mode 100644
index 0000000000..1d05adc505
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/as_mut.rs
@@ -0,0 +1,81 @@
+use crate::utils::{
+ add_where_clauses_for_new_ident, AttrParams, MultiFieldData, State,
+};
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote};
+use syn::{parse::Result, DeriveInput};
+
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let as_mut_type = format_ident!("__AsMutT");
+ let state = State::with_type_bound(
+ input,
+ trait_name,
+ "as_mut".into(),
+ AttrParams::ignore_and_forward(),
+ false,
+ )?;
+ let MultiFieldData {
+ fields,
+ input_type,
+ members,
+ infos,
+ trait_path,
+ impl_generics,
+ ty_generics,
+ where_clause,
+ ..
+ } = state.enabled_fields_data();
+ let sub_items: Vec<_> = infos
+ .iter()
+ .zip(members.iter())
+ .zip(fields)
+ .map(|((info, member), field)| {
+ let field_type = &field.ty;
+ if info.forward {
+ let trait_path = quote! { #trait_path<#as_mut_type> };
+ let type_where_clauses = quote! {
+ where #field_type: #trait_path
+ };
+ let new_generics = add_where_clauses_for_new_ident(
+ &input.generics,
+ &[field],
+ &as_mut_type,
+ type_where_clauses,
+ false,
+ );
+ let (impl_generics, _, where_clause) = new_generics.split_for_impl();
+ let casted_trait = quote! { <#field_type as #trait_path> };
+ (
+ quote! { #casted_trait::as_mut(&mut #member) },
+ quote! { #impl_generics },
+ quote! { #where_clause },
+ quote! { #trait_path },
+ quote! { #as_mut_type },
+ )
+ } else {
+ (
+ quote! { &mut #member },
+ quote! { #impl_generics },
+ quote! { #where_clause },
+ quote! { #trait_path<#field_type> },
+ quote! { #field_type },
+ )
+ }
+ })
+ .collect();
+ let bodies = sub_items.iter().map(|i| &i.0);
+ let impl_genericses = sub_items.iter().map(|i| &i.1);
+ let where_clauses = sub_items.iter().map(|i| &i.2);
+ let trait_paths = sub_items.iter().map(|i| &i.3);
+ let return_types = sub_items.iter().map(|i| &i.4);
+
+ Ok(quote! {#(
+ #[automatically_derived]
+ impl #impl_genericses #trait_paths for #input_type #ty_generics #where_clauses {
+ #[inline]
+ fn as_mut(&mut self) -> &mut #return_types {
+ #bodies
+ }
+ }
+ )*})
+}
diff --git a/third_party/rust/derive_more-impl/src/as_ref.rs b/third_party/rust/derive_more-impl/src/as_ref.rs
new file mode 100644
index 0000000000..71f1259867
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/as_ref.rs
@@ -0,0 +1,81 @@
+use crate::utils::{
+ add_where_clauses_for_new_ident, AttrParams, MultiFieldData, State,
+};
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote};
+use syn::{parse::Result, DeriveInput};
+
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let as_ref_type = format_ident!("__AsRefT");
+ let state = State::with_type_bound(
+ input,
+ trait_name,
+ "as_ref".into(),
+ AttrParams::ignore_and_forward(),
+ false,
+ )?;
+ let MultiFieldData {
+ fields,
+ input_type,
+ members,
+ infos,
+ trait_path,
+ impl_generics,
+ ty_generics,
+ where_clause,
+ ..
+ } = state.enabled_fields_data();
+ let sub_items: Vec<_> = infos
+ .iter()
+ .zip(members.iter())
+ .zip(fields)
+ .map(|((info, member), field)| {
+ let field_type = &field.ty;
+ if info.forward {
+ let trait_path = quote! { #trait_path<#as_ref_type> };
+ let type_where_clauses = quote! {
+ where #field_type: #trait_path
+ };
+ let new_generics = add_where_clauses_for_new_ident(
+ &input.generics,
+ &[field],
+ &as_ref_type,
+ type_where_clauses,
+ false,
+ );
+ let (impl_generics, _, where_clause) = new_generics.split_for_impl();
+ let casted_trait = quote! { <#field_type as #trait_path> };
+ (
+ quote! { #casted_trait::as_ref(&#member) },
+ quote! { #impl_generics },
+ quote! { #where_clause },
+ quote! { #trait_path },
+ quote! { #as_ref_type },
+ )
+ } else {
+ (
+ quote! { &#member },
+ quote! { #impl_generics },
+ quote! { #where_clause },
+ quote! { #trait_path<#field_type> },
+ quote! { #field_type },
+ )
+ }
+ })
+ .collect();
+ let bodies = sub_items.iter().map(|i| &i.0);
+ let impl_generics = sub_items.iter().map(|i| &i.1);
+ let where_clauses = sub_items.iter().map(|i| &i.2);
+ let trait_paths = sub_items.iter().map(|i| &i.3);
+ let return_types = sub_items.iter().map(|i| &i.4);
+
+ Ok(quote! {#(
+ #[automatically_derived]
+ impl #impl_generics #trait_paths for #input_type #ty_generics #where_clauses {
+ #[inline]
+ fn as_ref(&self) -> &#return_types {
+ #bodies
+ }
+ }
+ )*})
+}
diff --git a/third_party/rust/derive_more-impl/src/constructor.rs b/third_party/rust/derive_more-impl/src/constructor.rs
new file mode 100644
index 0000000000..284b0643fc
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/constructor.rs
@@ -0,0 +1,50 @@
+use crate::utils::{
+ field_idents, get_field_types, named_to_vec, numbered_vars, unnamed_to_vec,
+};
+use proc_macro2::TokenStream;
+use quote::quote;
+use syn::{Data, DeriveInput, Field, Fields, Ident};
+
+/// Provides the hook to expand `#[derive(Constructor)]` into an implementation of `Constructor`
+pub fn expand(input: &DeriveInput, _: &str) -> TokenStream {
+ let input_type = &input.ident;
+ let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
+ let ((body, vars), fields) = match input.data {
+ Data::Struct(ref data_struct) => match data_struct.fields {
+ Fields::Unnamed(ref fields) => {
+ let field_vec = unnamed_to_vec(fields);
+ (tuple_body(input_type, &field_vec), field_vec)
+ }
+ Fields::Named(ref fields) => {
+ let field_vec = named_to_vec(fields);
+ (struct_body(input_type, &field_vec), field_vec)
+ }
+ Fields::Unit => (struct_body(input_type, &[]), vec![]),
+ },
+ _ => panic!("Only structs can derive a constructor"),
+ };
+ let original_types = &get_field_types(&fields);
+ quote! {
+ #[allow(missing_docs)]
+ #[automatically_derived]
+ impl #impl_generics #input_type #ty_generics #where_clause {
+ #[inline]
+ pub const fn new(#(#vars: #original_types),*) -> #input_type #ty_generics {
+ #body
+ }
+ }
+ }
+}
+
+fn tuple_body(return_type: &Ident, fields: &[&Field]) -> (TokenStream, Vec<Ident>) {
+ let vars = &numbered_vars(fields.len(), "");
+ (quote! { #return_type(#(#vars),*) }, vars.clone())
+}
+
+fn struct_body(return_type: &Ident, fields: &[&Field]) -> (TokenStream, Vec<Ident>) {
+ let field_names: &Vec<Ident> =
+ &field_idents(fields).iter().map(|f| (**f).clone()).collect();
+ let vars = field_names;
+ let ret_vars = field_names.clone();
+ (quote! { #return_type{#(#field_names: #vars),*} }, ret_vars)
+}
diff --git a/third_party/rust/derive_more-impl/src/deref.rs b/third_party/rust/derive_more-impl/src/deref.rs
new file mode 100644
index 0000000000..f87c64cc61
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/deref.rs
@@ -0,0 +1,55 @@
+use crate::utils::{add_extra_where_clauses, SingleFieldData, State};
+use proc_macro2::TokenStream;
+use quote::quote;
+use syn::{parse::Result, DeriveInput};
+
+/// Provides the hook to expand `#[derive(Deref)]` into an implementation of `Deref`
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let state = State::with_field_ignore_and_forward(
+ input,
+ trait_name,
+ trait_name.to_lowercase(),
+ )?;
+ let SingleFieldData {
+ input_type,
+ field_type,
+ trait_path,
+ casted_trait,
+ ty_generics,
+ member,
+ info,
+ ..
+ } = state.assert_single_enabled_field();
+
+ let (target, body, generics) = if info.forward {
+ (
+ quote! { #casted_trait::Target },
+ quote! { #casted_trait::deref(&#member) },
+ add_extra_where_clauses(
+ &input.generics,
+ quote! {
+ where #field_type: #trait_path
+ },
+ ),
+ )
+ } else {
+ (
+ quote! { #field_type },
+ quote! { &#member },
+ input.generics.clone(),
+ )
+ };
+ let (impl_generics, _, where_clause) = generics.split_for_impl();
+
+ Ok(quote! {
+ #[automatically_derived]
+ impl #impl_generics #trait_path for #input_type #ty_generics #where_clause {
+ type Target = #target;
+
+ #[inline]
+ fn deref(&self) -> &Self::Target {
+ #body
+ }
+ }
+ })
+}
diff --git a/third_party/rust/derive_more-impl/src/deref_mut.rs b/third_party/rust/derive_more-impl/src/deref_mut.rs
new file mode 100644
index 0000000000..2d7a79db2a
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/deref_mut.rs
@@ -0,0 +1,44 @@
+use crate::utils::{add_extra_where_clauses, SingleFieldData, State};
+use proc_macro2::TokenStream;
+use quote::quote;
+use syn::{parse::Result, DeriveInput};
+
+/// Provides the hook to expand `#[derive(DerefMut)]` into an implementation of `DerefMut`
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let state =
+ State::with_field_ignore_and_forward(input, trait_name, "deref_mut".into())?;
+ let SingleFieldData {
+ input_type,
+ trait_path,
+ casted_trait,
+ ty_generics,
+ field_type,
+ member,
+ info,
+ ..
+ } = state.assert_single_enabled_field();
+ let (body, generics) = if info.forward {
+ (
+ quote! { #casted_trait::deref_mut(&mut #member) },
+ add_extra_where_clauses(
+ &input.generics,
+ quote! {
+ where #field_type: #trait_path
+ },
+ ),
+ )
+ } else {
+ (quote! { &mut #member }, input.generics.clone())
+ };
+ let (impl_generics, _, where_clause) = generics.split_for_impl();
+
+ Ok(quote! {
+ #[automatically_derived]
+ impl #impl_generics #trait_path for #input_type #ty_generics #where_clause {
+ #[inline]
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ #body
+ }
+ }
+ })
+}
diff --git a/third_party/rust/derive_more-impl/src/error.rs b/third_party/rust/derive_more-impl/src/error.rs
new file mode 100644
index 0000000000..99771b4d9e
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/error.rs
@@ -0,0 +1,481 @@
+use proc_macro2::TokenStream;
+use quote::quote;
+use syn::{spanned::Spanned as _, Error, Result};
+
+use crate::utils::{
+ self, AttrParams, DeriveType, FullMetaInfo, HashSet, MetaInfo, MultiFieldData,
+ State,
+};
+
+pub fn expand(
+ input: &syn::DeriveInput,
+ trait_name: &'static str,
+) -> Result<TokenStream> {
+ let syn::DeriveInput {
+ ident, generics, ..
+ } = input;
+
+ let state = State::with_attr_params(
+ input,
+ trait_name,
+ trait_name.to_lowercase(),
+ allowed_attr_params(),
+ )?;
+
+ let type_params: HashSet<_> = generics
+ .params
+ .iter()
+ .filter_map(|generic| match generic {
+ syn::GenericParam::Type(ty) => Some(ty.ident.clone()),
+ _ => None,
+ })
+ .collect();
+
+ let (bounds, source, provide) = match state.derive_type {
+ DeriveType::Named | DeriveType::Unnamed => render_struct(&type_params, &state)?,
+ DeriveType::Enum => render_enum(&type_params, &state)?,
+ };
+
+ let source = source.map(|source| {
+ quote! {
+ fn source(&self) -> Option<&(dyn ::derive_more::Error + 'static)> {
+ use ::derive_more::__private::AsDynError;
+ #source
+ }
+ }
+ });
+
+ let provide = provide.map(|provide| {
+ quote! {
+ fn provide<'_demand>(&'_demand self, demand: &mut ::core::any::Demand<'_demand>) {
+ #provide
+ }
+ }
+ });
+
+ let mut generics = generics.clone();
+
+ if !type_params.is_empty() {
+ let (_, ty_generics, _) = generics.split_for_impl();
+ generics = utils::add_extra_where_clauses(
+ &generics,
+ quote! {
+ where
+ #ident #ty_generics: ::core::fmt::Debug + ::core::fmt::Display
+ },
+ );
+ }
+
+ if !bounds.is_empty() {
+ let bounds = bounds.iter();
+ generics = utils::add_extra_where_clauses(
+ &generics,
+ quote! {
+ where
+ #(#bounds: ::core::fmt::Debug + ::core::fmt::Display + ::derive_more::Error + 'static),*
+ },
+ );
+ }
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ let render = quote! {
+ #[automatically_derived]
+ impl #impl_generics ::derive_more::Error for #ident #ty_generics #where_clause {
+ #source
+ #provide
+ }
+ };
+
+ Ok(render)
+}
+
+fn render_struct(
+ type_params: &HashSet<syn::Ident>,
+ state: &State,
+) -> Result<(HashSet<syn::Type>, Option<TokenStream>, Option<TokenStream>)> {
+ let parsed_fields = parse_fields(type_params, state)?;
+
+ let source = parsed_fields.render_source_as_struct();
+ let provide = parsed_fields.render_provide_as_struct();
+
+ Ok((parsed_fields.bounds, source, provide))
+}
+
+fn render_enum(
+ type_params: &HashSet<syn::Ident>,
+ state: &State,
+) -> Result<(HashSet<syn::Type>, Option<TokenStream>, Option<TokenStream>)> {
+ let mut bounds = HashSet::default();
+ let mut source_match_arms = Vec::new();
+ let mut provide_match_arms = Vec::new();
+
+ for variant in state.enabled_variant_data().variants {
+ let default_info = FullMetaInfo {
+ enabled: true,
+ ..FullMetaInfo::default()
+ };
+
+ let state = State::from_variant(
+ state.input,
+ state.trait_name,
+ state.trait_attr.clone(),
+ allowed_attr_params(),
+ variant,
+ default_info,
+ )?;
+
+ let parsed_fields = parse_fields(type_params, &state)?;
+
+ if let Some(expr) = parsed_fields.render_source_as_enum_variant_match_arm() {
+ source_match_arms.push(expr);
+ }
+
+ if let Some(expr) = parsed_fields.render_provide_as_enum_variant_match_arm() {
+ provide_match_arms.push(expr);
+ }
+
+ bounds.extend(parsed_fields.bounds.into_iter());
+ }
+
+ let render = |match_arms: &mut Vec<TokenStream>, unmatched| {
+ if !match_arms.is_empty() && match_arms.len() < state.variants.len() {
+ match_arms.push(quote! { _ => #unmatched });
+ }
+
+ (!match_arms.is_empty()).then(|| {
+ quote! {
+ match self {
+ #(#match_arms),*
+ }
+ }
+ })
+ };
+
+ let source = render(&mut source_match_arms, quote! { None });
+ let provide = render(&mut provide_match_arms, quote! { () });
+
+ Ok((bounds, source, provide))
+}
+
+fn allowed_attr_params() -> AttrParams {
+ AttrParams {
+ enum_: vec!["ignore"],
+ struct_: vec!["ignore"],
+ variant: vec!["ignore"],
+ field: vec!["ignore", "source", "backtrace"],
+ }
+}
+
+struct ParsedFields<'input, 'state> {
+ data: MultiFieldData<'input, 'state>,
+ source: Option<usize>,
+ backtrace: Option<usize>,
+ bounds: HashSet<syn::Type>,
+}
+
+impl<'input, 'state> ParsedFields<'input, 'state> {
+ fn new(data: MultiFieldData<'input, 'state>) -> Self {
+ Self {
+ data,
+ source: None,
+ backtrace: None,
+ bounds: HashSet::default(),
+ }
+ }
+}
+
+impl<'input, 'state> ParsedFields<'input, 'state> {
+ fn render_source_as_struct(&self) -> Option<TokenStream> {
+ let source = self.source?;
+ let ident = &self.data.members[source];
+ Some(render_some(quote! { #ident }))
+ }
+
+ fn render_source_as_enum_variant_match_arm(&self) -> Option<TokenStream> {
+ let source = self.source?;
+ let pattern = self.data.matcher(&[source], &[quote! { source }]);
+ let expr = render_some(quote! { source });
+ Some(quote! { #pattern => #expr })
+ }
+
+ fn render_provide_as_struct(&self) -> Option<TokenStream> {
+ let backtrace = self.backtrace?;
+
+ let source_provider = self.source.map(|source| {
+ let source_expr = &self.data.members[source];
+ quote! {
+ ::derive_more::Error::provide(&#source_expr, demand);
+ }
+ });
+ let backtrace_provider = self
+ .source
+ .filter(|source| *source == backtrace)
+ .is_none()
+ .then(|| {
+ let backtrace_expr = &self.data.members[backtrace];
+ quote! {
+ demand.provide_ref::<::std::backtrace::Backtrace>(&#backtrace_expr);
+ }
+ });
+
+ (source_provider.is_some() || backtrace_provider.is_some()).then(|| {
+ quote! {
+ #backtrace_provider
+ #source_provider
+ }
+ })
+ }
+
+ fn render_provide_as_enum_variant_match_arm(&self) -> Option<TokenStream> {
+ let backtrace = self.backtrace?;
+
+ match self.source {
+ Some(source) if source == backtrace => {
+ let pattern = self.data.matcher(&[source], &[quote! { source }]);
+ Some(quote! {
+ #pattern => {
+ ::derive_more::Error::provide(source, demand);
+ }
+ })
+ }
+ Some(source) => {
+ let pattern = self.data.matcher(
+ &[source, backtrace],
+ &[quote! { source }, quote! { backtrace }],
+ );
+ Some(quote! {
+ #pattern => {
+ demand.provide_ref::<::std::backtrace::Backtrace>(backtrace);
+ ::derive_more::Error::provide(source, demand);
+ }
+ })
+ }
+ None => {
+ let pattern = self.data.matcher(&[backtrace], &[quote! { backtrace }]);
+ Some(quote! {
+ #pattern => {
+ demand.provide_ref::<::std::backtrace::Backtrace>(backtrace);
+ }
+ })
+ }
+ }
+ }
+}
+
+fn render_some<T>(expr: T) -> TokenStream
+where
+ T: quote::ToTokens,
+{
+ quote! { Some(#expr.as_dyn_error()) }
+}
+
+fn parse_fields<'input, 'state>(
+ type_params: &HashSet<syn::Ident>,
+ state: &'state State<'input>,
+) -> Result<ParsedFields<'input, 'state>> {
+ let mut parsed_fields = match state.derive_type {
+ DeriveType::Named => {
+ parse_fields_impl(state, |attr, field, _| {
+ // Unwrapping is safe, cause fields in named struct
+ // always have an ident
+ let ident = field.ident.as_ref().unwrap();
+
+ match attr {
+ "source" => ident == "source",
+ "backtrace" => {
+ ident == "backtrace"
+ || is_type_path_ends_with_segment(&field.ty, "Backtrace")
+ }
+ _ => unreachable!(),
+ }
+ })
+ }
+
+ DeriveType::Unnamed => {
+ let mut parsed_fields =
+ parse_fields_impl(state, |attr, field, len| match attr {
+ "source" => {
+ len == 1
+ && !is_type_path_ends_with_segment(&field.ty, "Backtrace")
+ }
+ "backtrace" => {
+ is_type_path_ends_with_segment(&field.ty, "Backtrace")
+ }
+ _ => unreachable!(),
+ })?;
+
+ parsed_fields.source = parsed_fields
+ .source
+ .or_else(|| infer_source_field(&state.fields, &parsed_fields));
+
+ Ok(parsed_fields)
+ }
+
+ _ => unreachable!(),
+ }?;
+
+ if let Some(source) = parsed_fields.source {
+ add_bound_if_type_parameter_used_in_type(
+ &mut parsed_fields.bounds,
+ type_params,
+ &state.fields[source].ty,
+ );
+ }
+
+ Ok(parsed_fields)
+}
+
+/// Checks if `ty` is [`syn::Type::Path`] and ends with segment matching `tail`
+/// and doesn't contain any generic parameters.
+fn is_type_path_ends_with_segment(ty: &syn::Type, tail: &str) -> bool {
+ let syn::Type::Path(ty) = ty else {
+ return false;
+ };
+
+ // Unwrapping is safe, cause 'syn::TypePath.path.segments'
+ // have to have at least one segment
+ let segment = ty.path.segments.last().unwrap();
+
+ if !matches!(segment.arguments, syn::PathArguments::None) {
+ return false;
+ }
+
+ segment.ident == tail
+}
+
+fn infer_source_field(
+ fields: &[&syn::Field],
+ parsed_fields: &ParsedFields,
+) -> Option<usize> {
+ // if we have exactly two fields
+ if fields.len() != 2 {
+ return None;
+ }
+
+ // no source field was specified/inferred
+ if parsed_fields.source.is_some() {
+ return None;
+ }
+
+ // but one of the fields was specified/inferred as backtrace field
+ if let Some(backtrace) = parsed_fields.backtrace {
+ // then infer *other field* as source field
+ let source = (backtrace + 1) % 2;
+ // unless it was explicitly marked as non-source
+ if parsed_fields.data.infos[source].info.source != Some(false) {
+ return Some(source);
+ }
+ }
+
+ None
+}
+
+fn parse_fields_impl<'input, 'state, P>(
+ state: &'state State<'input>,
+ is_valid_default_field_for_attr: P,
+) -> Result<ParsedFields<'input, 'state>>
+where
+ P: Fn(&str, &syn::Field, usize) -> bool,
+{
+ let MultiFieldData { fields, infos, .. } = state.enabled_fields_data();
+
+ let iter = fields
+ .iter()
+ .zip(infos.iter().map(|info| &info.info))
+ .enumerate()
+ .map(|(index, (field, info))| (index, *field, info));
+
+ let source = parse_field_impl(
+ &is_valid_default_field_for_attr,
+ state.fields.len(),
+ iter.clone(),
+ "source",
+ |info| info.source,
+ )?;
+
+ let backtrace = parse_field_impl(
+ &is_valid_default_field_for_attr,
+ state.fields.len(),
+ iter.clone(),
+ "backtrace",
+ |info| info.backtrace,
+ )?;
+
+ let mut parsed_fields = ParsedFields::new(state.enabled_fields_data());
+
+ if let Some((index, _, _)) = source {
+ parsed_fields.source = Some(index);
+ }
+
+ if let Some((index, _, _)) = backtrace {
+ parsed_fields.backtrace = Some(index);
+ }
+
+ Ok(parsed_fields)
+}
+
+fn parse_field_impl<'a, P, V>(
+ is_valid_default_field_for_attr: &P,
+ len: usize,
+ iter: impl Iterator<Item = (usize, &'a syn::Field, &'a MetaInfo)> + Clone,
+ attr: &str,
+ value: V,
+) -> Result<Option<(usize, &'a syn::Field, &'a MetaInfo)>>
+where
+ P: Fn(&str, &syn::Field, usize) -> bool,
+ V: Fn(&MetaInfo) -> Option<bool>,
+{
+ let explicit_fields = iter
+ .clone()
+ .filter(|(_, _, info)| matches!(value(info), Some(true)));
+
+ let inferred_fields = iter.filter(|(_, field, info)| match value(info) {
+ None => is_valid_default_field_for_attr(attr, field, len),
+ _ => false,
+ });
+
+ let field = assert_iter_contains_zero_or_one_item(
+ explicit_fields,
+ &format!(
+ "Multiple `{attr}` attributes specified. \
+ Single attribute per struct/enum variant allowed.",
+ ),
+ )?;
+
+ let field = match field {
+ field @ Some(_) => field,
+ None => assert_iter_contains_zero_or_one_item(
+ inferred_fields,
+ "Conflicting fields found. Consider specifying some \
+ `#[error(...)]` attributes to resolve conflict.",
+ )?,
+ };
+
+ Ok(field)
+}
+
+fn assert_iter_contains_zero_or_one_item<'a>(
+ mut iter: impl Iterator<Item = (usize, &'a syn::Field, &'a MetaInfo)>,
+ error_msg: &str,
+) -> Result<Option<(usize, &'a syn::Field, &'a MetaInfo)>> {
+ let Some(item) = iter.next() else {
+ return Ok(None);
+ };
+
+ if let Some((_, field, _)) = iter.next() {
+ return Err(Error::new(field.span(), error_msg));
+ }
+
+ Ok(Some(item))
+}
+
+fn add_bound_if_type_parameter_used_in_type(
+ bounds: &mut HashSet<syn::Type>,
+ type_params: &HashSet<syn::Ident>,
+ ty: &syn::Type,
+) {
+ if let Some(ty) = utils::get_if_type_parameter_used_in_type(type_params, ty) {
+ bounds.insert(ty);
+ }
+}
diff --git a/third_party/rust/derive_more-impl/src/fmt/debug.rs b/third_party/rust/derive_more-impl/src/fmt/debug.rs
new file mode 100644
index 0000000000..d1f427e1f6
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/fmt/debug.rs
@@ -0,0 +1,373 @@
+//! Implementation of a [`fmt::Debug`] derive macro.
+//!
+//! [`fmt::Debug`]: std::fmt::Debug
+
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote};
+use syn::{
+ parse::{Error, Parse, ParseStream, Result},
+ parse_quote,
+ spanned::Spanned as _,
+ Ident,
+};
+
+use super::{BoundsAttribute, FmtAttribute};
+
+/// Expands a [`fmt::Debug`] derive macro.
+///
+/// [`fmt::Debug`]: std::fmt::Debug
+pub fn expand(input: &syn::DeriveInput, _: &str) -> Result<TokenStream> {
+ let attrs = ContainerAttributes::parse_attrs(&input.attrs)?;
+ let ident = &input.ident;
+
+ let (bounds, body) = match &input.data {
+ syn::Data::Struct(s) => expand_struct(attrs, ident, s),
+ syn::Data::Enum(e) => expand_enum(attrs, e),
+ syn::Data::Union(_) => {
+ return Err(Error::new(
+ input.span(),
+ "`Debug` cannot be derived for unions",
+ ));
+ }
+ }?;
+
+ let (impl_gens, ty_gens, where_clause) = {
+ let (impl_gens, ty_gens, where_clause) = input.generics.split_for_impl();
+ let mut where_clause = where_clause
+ .cloned()
+ .unwrap_or_else(|| parse_quote! { where });
+ where_clause.predicates.extend(bounds);
+ (impl_gens, ty_gens, where_clause)
+ };
+
+ Ok(quote! {
+ #[automatically_derived]
+ impl #impl_gens ::core::fmt::Debug for #ident #ty_gens
+ #where_clause
+ {
+ fn fmt(
+ &self, __derive_more_f: &mut ::core::fmt::Formatter<'_>
+ ) -> ::core::fmt::Result {
+ #body
+ }
+ }
+ })
+}
+
+/// Expands a [`fmt::Debug`] derive macro for the provided struct.
+///
+/// [`fmt::Debug`]: std::fmt::Debug
+fn expand_struct(
+ attrs: ContainerAttributes,
+ ident: &Ident,
+ s: &syn::DataStruct,
+) -> Result<(Vec<syn::WherePredicate>, TokenStream)> {
+ let s = Expansion {
+ attr: &attrs,
+ fields: &s.fields,
+ ident,
+ };
+ let bounds = s.generate_bounds()?;
+ let body = s.generate_body()?;
+
+ let vars = s.fields.iter().enumerate().map(|(i, f)| {
+ let var = f.ident.clone().unwrap_or_else(|| format_ident!("_{i}"));
+ let member = f
+ .ident
+ .clone()
+ .map_or_else(|| syn::Member::Unnamed(i.into()), syn::Member::Named);
+ quote! { let #var = &self.#member; }
+ });
+
+ let body = quote! {
+ #( #vars )*
+ #body
+ };
+
+ Ok((bounds, body))
+}
+
+/// Expands a [`fmt::Debug`] derive macro for the provided enum.
+///
+/// [`fmt::Debug`]: std::fmt::Debug
+fn expand_enum(
+ attrs: ContainerAttributes,
+ e: &syn::DataEnum,
+) -> Result<(Vec<syn::WherePredicate>, TokenStream)> {
+ let (bounds, match_arms) = e.variants.iter().try_fold(
+ (Vec::new(), TokenStream::new()),
+ |(mut bounds, mut arms), variant| {
+ let ident = &variant.ident;
+
+ let v = Expansion {
+ attr: &attrs,
+ fields: &variant.fields,
+ ident,
+ };
+ let arm_body = v.generate_body()?;
+ bounds.extend(v.generate_bounds()?);
+
+ let fields_idents =
+ variant.fields.iter().enumerate().map(|(i, f)| {
+ f.ident.clone().unwrap_or_else(|| format_ident!("_{i}"))
+ });
+ let matcher = match variant.fields {
+ syn::Fields::Named(_) => {
+ quote! { Self::#ident { #( #fields_idents ),* } }
+ }
+ syn::Fields::Unnamed(_) => {
+ quote! { Self::#ident ( #( #fields_idents ),* ) }
+ }
+ syn::Fields::Unit => quote! { Self::#ident },
+ };
+
+ arms.extend([quote! { #matcher => { #arm_body }, }]);
+
+ Ok::<_, Error>((bounds, arms))
+ },
+ )?;
+
+ let body = match_arms
+ .is_empty()
+ .then(|| quote! { match *self {} })
+ .unwrap_or_else(|| quote! { match self { #match_arms } });
+
+ Ok((bounds, body))
+}
+
+/// Representation of a [`fmt::Debug`] derive macro container attribute.
+///
+/// ```rust,ignore
+/// #[debug(bound(<bounds>))]
+/// ```
+///
+/// [`fmt::Debug`]: std::fmt::Debug
+#[derive(Debug, Default)]
+struct ContainerAttributes {
+ /// Additional trait bounds.
+ bounds: BoundsAttribute,
+}
+
+impl ContainerAttributes {
+ /// Parses [`ContainerAttributes`] from the provided [`syn::Attribute`]s.
+ fn parse_attrs(attrs: impl AsRef<[syn::Attribute]>) -> Result<Self> {
+ attrs
+ .as_ref()
+ .iter()
+ .filter(|attr| attr.path().is_ident("debug"))
+ .try_fold(ContainerAttributes::default(), |mut attrs, attr| {
+ let attr = attr.parse_args::<ContainerAttributes>()?;
+ attrs.bounds.0.extend(attr.bounds.0);
+ Ok(attrs)
+ })
+ }
+}
+
+impl Parse for ContainerAttributes {
+ fn parse(input: ParseStream) -> Result<Self> {
+ BoundsAttribute::check_legacy_fmt(input)?;
+
+ input.parse().map(|bounds| ContainerAttributes { bounds })
+ }
+}
+
+/// Representation of a [`fmt::Debug`] derive macro field attribute.
+///
+/// ```rust,ignore
+/// #[debug("<fmt_literal>", <fmt_args>)]
+/// #[debug(skip)]
+/// ```
+///
+/// [`fmt::Debug`]: std::fmt::Debug
+enum FieldAttribute {
+ /// [`fmt`] attribute.
+ ///
+ /// [`fmt`]: std::fmt
+ Fmt(FmtAttribute),
+
+ /// Attribute for skipping field.
+ Skip,
+}
+
+impl FieldAttribute {
+ /// Parses [`ContainerAttributes`] from the provided [`syn::Attribute`]s.
+ fn parse_attrs(attrs: impl AsRef<[syn::Attribute]>) -> Result<Option<Self>> {
+ Ok(attrs
+ .as_ref()
+ .iter()
+ .filter(|attr| attr.path().is_ident("debug"))
+ .try_fold(None, |mut attrs, attr| {
+ let field_attr = attr.parse_args::<FieldAttribute>()?;
+ if let Some((path, _)) = attrs.replace((attr.path(), field_attr)) {
+ Err(Error::new(
+ path.span(),
+ "only single `#[debug(...)]` attribute is allowed here",
+ ))
+ } else {
+ Ok(attrs)
+ }
+ })?
+ .map(|(_, attr)| attr))
+ }
+}
+
+impl Parse for FieldAttribute {
+ fn parse(input: ParseStream) -> Result<Self> {
+ FmtAttribute::check_legacy_fmt(input)?;
+
+ if input.peek(syn::LitStr) {
+ input.parse().map(Self::Fmt)
+ } else {
+ let _ = input.parse::<syn::Path>().and_then(|p| {
+ if ["skip", "ignore"].into_iter().any(|i| p.is_ident(i)) {
+ Ok(p)
+ } else {
+ Err(Error::new(
+ p.span(),
+ "unknown attribute, expected `skip` or `ignore`",
+ ))
+ }
+ })?;
+ Ok(Self::Skip)
+ }
+ }
+}
+
+/// Helper struct to generate [`Debug::fmt()`] implementation body and trait
+/// bounds for a struct or an enum variant.
+///
+/// [`Debug::fmt()`]: std::fmt::Debug::fmt()
+#[derive(Debug)]
+struct Expansion<'a> {
+ attr: &'a ContainerAttributes,
+
+ /// Struct or enum [`Ident`](struct@Ident).
+ ident: &'a Ident,
+
+ /// Struct or enum [`syn::Fields`].
+ fields: &'a syn::Fields,
+}
+
+impl<'a> Expansion<'a> {
+ /// Generates [`Debug::fmt()`] implementation for a struct or an enum variant.
+ ///
+ /// [`Debug::fmt()`]: std::fmt::Debug::fmt()
+ fn generate_body(&self) -> Result<TokenStream> {
+ match self.fields {
+ syn::Fields::Unit => {
+ let ident = self.ident.to_string();
+ Ok(quote! {
+ ::core::fmt::Formatter::write_str(
+ __derive_more_f,
+ #ident,
+ )
+ })
+ }
+ syn::Fields::Unnamed(unnamed) => {
+ let mut exhaustive = true;
+ let ident_str = self.ident.to_string();
+
+ let out = quote! {
+ &mut ::derive_more::__private::debug_tuple(
+ __derive_more_f,
+ #ident_str,
+ )
+ };
+ let out = unnamed.unnamed.iter().enumerate().try_fold(
+ out,
+ |out, (i, field)| match FieldAttribute::parse_attrs(&field.attrs)? {
+ Some(FieldAttribute::Skip) => {
+ exhaustive = false;
+ Ok::<_, Error>(out)
+ }
+ Some(FieldAttribute::Fmt(fmt)) => Ok(quote! {
+ ::derive_more::__private::DebugTuple::field(
+ #out,
+ &::core::format_args!(#fmt),
+ )
+ }),
+ None => {
+ let ident = format_ident!("_{i}");
+ Ok(quote! {
+ ::derive_more::__private::DebugTuple::field(#out, #ident)
+ })
+ }
+ },
+ )?;
+ Ok(if exhaustive {
+ quote! { ::derive_more::__private::DebugTuple::finish(#out) }
+ } else {
+ quote! { ::derive_more::__private::DebugTuple::finish_non_exhaustive(#out) }
+ })
+ }
+ syn::Fields::Named(named) => {
+ let mut exhaustive = true;
+ let ident = self.ident.to_string();
+
+ let out = quote! {
+ &mut ::core::fmt::Formatter::debug_struct(
+ __derive_more_f,
+ #ident,
+ )
+ };
+ let out = named.named.iter().try_fold(out, |out, field| {
+ let field_ident = field.ident.as_ref().unwrap_or_else(|| {
+ unreachable!("`syn::Fields::Named`");
+ });
+ let field_str = field_ident.to_string();
+ match FieldAttribute::parse_attrs(&field.attrs)? {
+ Some(FieldAttribute::Skip) => {
+ exhaustive = false;
+ Ok::<_, Error>(out)
+ }
+ Some(FieldAttribute::Fmt(fmt)) => Ok(quote! {
+ ::core::fmt::DebugStruct::field(
+ #out,
+ #field_str,
+ &::core::format_args!(#fmt),
+ )
+ }),
+ None => Ok(quote! {
+ ::core::fmt::DebugStruct::field(#out, #field_str, #field_ident)
+ }),
+ }
+ })?;
+ Ok(if exhaustive {
+ quote! { ::core::fmt::DebugStruct::finish(#out) }
+ } else {
+ quote! { ::core::fmt::DebugStruct::finish_non_exhaustive(#out) }
+ })
+ }
+ }
+ }
+
+ /// Generates trait bounds for a struct or an enum variant.
+ fn generate_bounds(&self) -> Result<Vec<syn::WherePredicate>> {
+ self.fields.iter().try_fold(
+ self.attr.bounds.0.clone().into_iter().collect::<Vec<_>>(),
+ |mut out, field| {
+ let fmt_attr =
+ FieldAttribute::parse_attrs(&field.attrs)?.and_then(|attr| {
+ match attr {
+ FieldAttribute::Fmt(fmt) => Some(fmt),
+ FieldAttribute::Skip => None,
+ }
+ });
+ let ty = &field.ty;
+
+ if let Some(attr) = fmt_attr {
+ out.extend(attr.bounded_types(self.fields).map(
+ |(ty, trait_name)| {
+ let trait_name = format_ident!("{trait_name}");
+ parse_quote! { #ty: ::core::fmt::#trait_name }
+ },
+ ));
+ } else {
+ out.extend([parse_quote! { #ty: ::core::fmt::Debug }]);
+ }
+
+ Ok(out)
+ },
+ )
+ }
+}
diff --git a/third_party/rust/derive_more-impl/src/fmt/display.rs b/third_party/rust/derive_more-impl/src/fmt/display.rs
new file mode 100644
index 0000000000..ff8f928070
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/fmt/display.rs
@@ -0,0 +1,377 @@
+//! Implementation of [`fmt::Display`]-like derive macros.
+
+#[cfg(doc)]
+use std::fmt;
+
+use proc_macro2::{Ident, TokenStream};
+use quote::{format_ident, quote};
+use syn::{
+ parse::{Parse, ParseStream},
+ parse_quote,
+ spanned::Spanned as _,
+};
+
+use super::{BoundsAttribute, FmtAttribute};
+
+/// Expands a [`fmt::Display`]-like derive macro.
+///
+/// Available macros:
+/// - [`Binary`](fmt::Binary)
+/// - [`Display`](fmt::Display)
+/// - [`LowerExp`](fmt::LowerExp)
+/// - [`LowerHex`](fmt::LowerHex)
+/// - [`Octal`](fmt::Octal)
+/// - [`Pointer`](fmt::Pointer)
+/// - [`UpperExp`](fmt::UpperExp)
+/// - [`UpperHex`](fmt::UpperHex)
+pub fn expand(input: &syn::DeriveInput, trait_name: &str) -> syn::Result<TokenStream> {
+ let trait_name = normalize_trait_name(trait_name);
+
+ let attrs = Attributes::parse_attrs(&input.attrs, trait_name)?;
+ let trait_ident = format_ident!("{trait_name}");
+ let ident = &input.ident;
+
+ let ctx = (&attrs, ident, &trait_ident, trait_name);
+ let (bounds, body) = match &input.data {
+ syn::Data::Struct(s) => expand_struct(s, ctx),
+ syn::Data::Enum(e) => expand_enum(e, ctx),
+ syn::Data::Union(u) => expand_union(u, ctx),
+ }?;
+
+ let (impl_gens, ty_gens, where_clause) = {
+ let (impl_gens, ty_gens, where_clause) = input.generics.split_for_impl();
+ let mut where_clause = where_clause
+ .cloned()
+ .unwrap_or_else(|| parse_quote! { where });
+ where_clause.predicates.extend(bounds);
+ (impl_gens, ty_gens, where_clause)
+ };
+
+ Ok(quote! {
+ #[automatically_derived]
+ impl #impl_gens ::core::fmt::#trait_ident for #ident #ty_gens
+ #where_clause
+ {
+ fn fmt(
+ &self, __derive_more_f: &mut ::core::fmt::Formatter<'_>
+ ) -> ::core::fmt::Result {
+ #body
+ }
+ }
+ })
+}
+
+/// Type alias for an expansion context:
+/// - [`Attributes`].
+/// - Struct/enum/union [`Ident`].
+/// - Derived trait [`Ident`].
+/// - Derived trait `&`[`str`].
+type ExpansionCtx<'a> = (&'a Attributes, &'a Ident, &'a Ident, &'a str);
+
+/// Expands a [`fmt::Display`]-like derive macro for the provided struct.
+fn expand_struct(
+ s: &syn::DataStruct,
+ (attrs, ident, trait_ident, _): ExpansionCtx<'_>,
+) -> syn::Result<(Vec<syn::WherePredicate>, TokenStream)> {
+ let s = Expansion {
+ attrs,
+ fields: &s.fields,
+ trait_ident,
+ ident,
+ };
+ let bounds = s.generate_bounds();
+ let body = s.generate_body()?;
+
+ let vars = s.fields.iter().enumerate().map(|(i, f)| {
+ let var = f.ident.clone().unwrap_or_else(|| format_ident!("_{i}"));
+ let member = f
+ .ident
+ .clone()
+ .map_or_else(|| syn::Member::Unnamed(i.into()), syn::Member::Named);
+ quote! {
+ let #var = &self.#member;
+ }
+ });
+
+ let body = quote! {
+ #( #vars )*
+ #body
+ };
+
+ Ok((bounds, body))
+}
+
+/// Expands a [`fmt`]-like derive macro for the provided enum.
+fn expand_enum(
+ e: &syn::DataEnum,
+ (attrs, _, trait_ident, trait_name): ExpansionCtx<'_>,
+) -> syn::Result<(Vec<syn::WherePredicate>, TokenStream)> {
+ if attrs.fmt.is_some() {
+ todo!("https://github.com/JelteF/derive_more/issues/142");
+ }
+
+ let (bounds, match_arms) = e.variants.iter().try_fold(
+ (Vec::new(), TokenStream::new()),
+ |(mut bounds, mut arms), variant| {
+ let attrs = Attributes::parse_attrs(&variant.attrs, trait_name)?;
+ let ident = &variant.ident;
+
+ if attrs.fmt.is_none()
+ && variant.fields.is_empty()
+ && trait_name != "Display"
+ {
+ return Err(syn::Error::new(
+ e.variants.span(),
+ format!(
+ "implicit formatting of unit enum variant is supported \
+ only for `Display` macro, use `#[{}(\"...\")]` to \
+ explicitly specify the formatting",
+ trait_name_to_attribute_name(trait_name),
+ ),
+ ));
+ }
+
+ let v = Expansion {
+ attrs: &attrs,
+ fields: &variant.fields,
+ trait_ident,
+ ident,
+ };
+ let arm_body = v.generate_body()?;
+ bounds.extend(v.generate_bounds());
+
+ let fields_idents =
+ variant.fields.iter().enumerate().map(|(i, f)| {
+ f.ident.clone().unwrap_or_else(|| format_ident!("_{i}"))
+ });
+ let matcher = match variant.fields {
+ syn::Fields::Named(_) => {
+ quote! { Self::#ident { #( #fields_idents ),* } }
+ }
+ syn::Fields::Unnamed(_) => {
+ quote! { Self::#ident ( #( #fields_idents ),* ) }
+ }
+ syn::Fields::Unit => quote! { Self::#ident },
+ };
+
+ arms.extend([quote! { #matcher => { #arm_body }, }]);
+
+ Ok::<_, syn::Error>((bounds, arms))
+ },
+ )?;
+
+ let body = match_arms
+ .is_empty()
+ .then(|| quote! { match *self {} })
+ .unwrap_or_else(|| quote! { match self { #match_arms } });
+
+ Ok((bounds, body))
+}
+
+/// Expands a [`fmt::Display`]-like derive macro for the provided union.
+fn expand_union(
+ u: &syn::DataUnion,
+ (attrs, _, _, trait_name): ExpansionCtx<'_>,
+) -> syn::Result<(Vec<syn::WherePredicate>, TokenStream)> {
+ let fmt = &attrs.fmt.as_ref().ok_or_else(|| {
+ syn::Error::new(
+ u.fields.span(),
+ format!(
+ "unions must have `#[{}(\"...\", ...)]` attribute",
+ trait_name_to_attribute_name(trait_name),
+ ),
+ )
+ })?;
+
+ Ok((
+ attrs.bounds.0.clone().into_iter().collect(),
+ quote! { ::core::write!(__derive_more_f, #fmt) },
+ ))
+}
+
+/// Representation of a [`fmt::Display`]-like derive macro attribute.
+///
+/// ```rust,ignore
+/// #[<fmt_trait>("<fmt_literal>", <fmt_args>)]
+/// #[bound(<bounds>)]
+/// ```
+///
+/// `#[<fmt_trait>(...)]` can be specified only once, while multiple
+/// `#[<fmt_trait>(bound(...))]` are allowed.
+#[derive(Debug, Default)]
+struct Attributes {
+ /// Interpolation [`FmtAttribute`].
+ fmt: Option<FmtAttribute>,
+
+ /// Addition trait bounds.
+ bounds: BoundsAttribute,
+}
+
+impl Attributes {
+ /// Parses [`Attributes`] from the provided [`syn::Attribute`]s.
+ fn parse_attrs(
+ attrs: impl AsRef<[syn::Attribute]>,
+ trait_name: &str,
+ ) -> syn::Result<Self> {
+ attrs
+ .as_ref()
+ .iter()
+ .filter(|attr| attr.path().is_ident(trait_name_to_attribute_name(trait_name)))
+ .try_fold(Attributes::default(), |mut attrs, attr| {
+ let attr = attr.parse_args::<Attribute>()?;
+ match attr {
+ Attribute::Bounds(more) => {
+ attrs.bounds.0.extend(more.0);
+ }
+ Attribute::Fmt(fmt) => {
+ attrs.fmt.replace(fmt).map_or(Ok(()), |dup| Err(syn::Error::new(
+ dup.span(),
+ format!(
+ "multiple `#[{}(\"...\", ...)]` attributes aren't allowed",
+ trait_name_to_attribute_name(trait_name),
+ ))))?;
+ }
+ };
+ Ok(attrs)
+ })
+ }
+}
+
+/// Representation of a single [`fmt::Display`]-like derive macro attribute.
+#[derive(Debug)]
+enum Attribute {
+ /// [`fmt`] attribute.
+ Fmt(FmtAttribute),
+
+ /// Addition trait bounds.
+ Bounds(BoundsAttribute),
+}
+
+impl Parse for Attribute {
+ fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
+ BoundsAttribute::check_legacy_fmt(input)?;
+ FmtAttribute::check_legacy_fmt(input)?;
+
+ if input.peek(syn::LitStr) {
+ input.parse().map(Attribute::Fmt)
+ } else {
+ input.parse().map(Attribute::Bounds)
+ }
+ }
+}
+
+/// Helper struct to generate [`Display::fmt()`] implementation body and trait
+/// bounds for a struct or an enum variant.
+///
+/// [`Display::fmt()`]: fmt::Display::fmt()
+#[derive(Debug)]
+struct Expansion<'a> {
+ /// Derive macro [`Attributes`].
+ attrs: &'a Attributes,
+
+ /// Struct or enum [`Ident`].
+ ident: &'a Ident,
+
+ /// Struct or enum [`syn::Fields`].
+ fields: &'a syn::Fields,
+
+ /// [`fmt`] trait [`Ident`].
+ trait_ident: &'a Ident,
+}
+
+impl<'a> Expansion<'a> {
+ /// Generates [`Display::fmt()`] implementation for a struct or an enum variant.
+ ///
+ /// # Errors
+ ///
+ /// In case [`FmtAttribute`] is [`None`] and [`syn::Fields`] length is
+ /// greater than 1.
+ ///
+ /// [`Display::fmt()`]: fmt::Display::fmt()
+ fn generate_body(&self) -> syn::Result<TokenStream> {
+ match &self.attrs.fmt {
+ Some(fmt) => Ok(quote! { ::core::write!(__derive_more_f, #fmt) }),
+ None if self.fields.is_empty() => {
+ let ident_str = self.ident.to_string();
+ Ok(quote! { ::core::write!(__derive_more_f, #ident_str) })
+ }
+ None if self.fields.len() == 1 => {
+ let field = self
+ .fields
+ .iter()
+ .next()
+ .unwrap_or_else(|| unreachable!("count() == 1"));
+ let ident = field.ident.clone().unwrap_or_else(|| format_ident!("_0"));
+ let trait_ident = self.trait_ident;
+ Ok(quote! {
+ ::core::fmt::#trait_ident::fmt(#ident, __derive_more_f)
+ })
+ }
+ _ => Err(syn::Error::new(
+ self.fields.span(),
+ format!(
+ "struct or enum variant with more than 1 field must have \
+ `#[{}(\"...\", ...)]` attribute",
+ trait_name_to_attribute_name(self.trait_ident),
+ ),
+ )),
+ }
+ }
+
+ /// Generates trait bounds for a struct or an enum variant.
+ fn generate_bounds(&self) -> Vec<syn::WherePredicate> {
+ let Some(fmt) = &self.attrs.fmt else {
+ return self
+ .fields
+ .iter()
+ .next()
+ .map(|f| {
+ let ty = &f.ty;
+ let trait_ident = &self.trait_ident;
+ vec![parse_quote! { #ty: ::core::fmt::#trait_ident }]
+ })
+ .unwrap_or_default();
+ };
+
+ fmt.bounded_types(self.fields)
+ .map(|(ty, trait_name)| {
+ let tr = format_ident!("{}", trait_name);
+ parse_quote! { #ty: ::core::fmt::#tr }
+ })
+ .chain(self.attrs.bounds.0.clone())
+ .collect()
+ }
+}
+
+/// Matches the provided `trait_name` to appropriate [`Attribute::Fmt`] argument name.
+fn trait_name_to_attribute_name<T>(trait_name: T) -> &'static str
+where
+ T: for<'a> PartialEq<&'a str>,
+{
+ match () {
+ _ if trait_name == "Binary" => "binary",
+ _ if trait_name == "Display" => "display",
+ _ if trait_name == "LowerExp" => "lower_exp",
+ _ if trait_name == "LowerHex" => "lower_hex",
+ _ if trait_name == "Octal" => "octal",
+ _ if trait_name == "Pointer" => "pointer",
+ _ if trait_name == "UpperExp" => "upper_exp",
+ _ if trait_name == "UpperHex" => "upper_hex",
+ _ => unimplemented!(),
+ }
+}
+
+/// Matches the provided derive macro `name` to appropriate actual trait name.
+fn normalize_trait_name(name: &str) -> &'static str {
+ match name {
+ "Binary" => "Binary",
+ "Display" => "Display",
+ "LowerExp" => "LowerExp",
+ "LowerHex" => "LowerHex",
+ "Octal" => "Octal",
+ "Pointer" => "Pointer",
+ "UpperExp" => "UpperExp",
+ "UpperHex" => "UpperHex",
+ _ => unimplemented!(),
+ }
+}
diff --git a/third_party/rust/derive_more-impl/src/fmt/mod.rs b/third_party/rust/derive_more-impl/src/fmt/mod.rs
new file mode 100644
index 0000000000..5727d671f5
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/fmt/mod.rs
@@ -0,0 +1,444 @@
+//! Implementations of [`fmt`]-like derive macros.
+//!
+//! [`fmt`]: std::fmt
+
+#[cfg(feature = "debug")]
+pub(crate) mod debug;
+#[cfg(feature = "display")]
+pub(crate) mod display;
+mod parsing;
+
+use proc_macro2::TokenStream;
+use quote::ToTokens;
+use syn::{
+ parse::{Parse, ParseStream},
+ punctuated::Punctuated,
+ spanned::Spanned as _,
+ token, Ident,
+};
+
+use crate::parsing::Expr;
+
+/// Representation of a macro attribute expressing additional trait bounds.
+#[derive(Debug, Default)]
+struct BoundsAttribute(Punctuated<syn::WherePredicate, syn::token::Comma>);
+
+impl BoundsAttribute {
+ /// Errors in case legacy syntax is encountered: `bound = "..."`.
+ fn check_legacy_fmt(input: ParseStream<'_>) -> syn::Result<()> {
+ let fork = input.fork();
+
+ let path = fork
+ .parse::<syn::Path>()
+ .and_then(|path| fork.parse::<syn::token::Eq>().map(|_| path));
+ match path {
+ Ok(path) if path.is_ident("bound") => fork
+ .parse::<syn::Lit>()
+ .ok()
+ .and_then(|lit| match lit {
+ syn::Lit::Str(s) => Some(s.value()),
+ _ => None,
+ })
+ .map_or(Ok(()), |bound| {
+ Err(syn::Error::new(
+ input.span(),
+ format!("legacy syntax, use `bound({bound})` instead"),
+ ))
+ }),
+ Ok(_) | Err(_) => Ok(()),
+ }
+ }
+}
+
+impl Parse for BoundsAttribute {
+ fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
+ let _ = input.parse::<syn::Path>().and_then(|p| {
+ if ["bound", "bounds", "where"]
+ .into_iter()
+ .any(|i| p.is_ident(i))
+ {
+ Ok(p)
+ } else {
+ Err(syn::Error::new(
+ p.span(),
+ "unknown attribute, expected `bound(...)`",
+ ))
+ }
+ })?;
+
+ let content;
+ syn::parenthesized!(content in input);
+
+ content
+ .parse_terminated(syn::WherePredicate::parse, token::Comma)
+ .map(Self)
+ }
+}
+
+/// Representation of a [`fmt`]-like attribute.
+///
+/// [`fmt`]: std::fmt
+#[derive(Debug)]
+struct FmtAttribute {
+ /// Interpolation [`syn::LitStr`].
+ ///
+ /// [`syn::LitStr`]: struct@syn::LitStr
+ lit: syn::LitStr,
+
+ /// Optional [`token::Comma`].
+ comma: Option<token::Comma>,
+
+ /// Interpolation arguments.
+ args: Punctuated<FmtArgument, token::Comma>,
+}
+
+impl FmtAttribute {
+ /// Returns an [`Iterator`] over bounded [`syn::Type`]s and trait names.
+ fn bounded_types<'a>(
+ &'a self,
+ fields: &'a syn::Fields,
+ ) -> impl Iterator<Item = (&'a syn::Type, &'static str)> {
+ let placeholders = Placeholder::parse_fmt_string(&self.lit.value());
+
+ // We ignore unknown fields, as compiler will produce better error messages.
+ placeholders.into_iter().filter_map(move |placeholder| {
+ let name = match placeholder.arg {
+ Parameter::Named(name) => self
+ .args
+ .iter()
+ .find_map(|a| (a.alias()? == &name).then_some(&a.expr))
+ .map_or(Some(name), |expr| expr.ident().map(ToString::to_string))?,
+ Parameter::Positional(i) => self
+ .args
+ .iter()
+ .nth(i)
+ .and_then(|a| a.expr.ident().filter(|_| a.alias.is_none()))?
+ .to_string(),
+ };
+
+ let unnamed = name.strip_prefix('_').and_then(|s| s.parse().ok());
+ let ty = match (&fields, unnamed) {
+ (syn::Fields::Unnamed(f), Some(i)) => {
+ f.unnamed.iter().nth(i).map(|f| &f.ty)
+ }
+ (syn::Fields::Named(f), None) => f.named.iter().find_map(|f| {
+ f.ident.as_ref().filter(|s| **s == name).map(|_| &f.ty)
+ }),
+ _ => None,
+ }?;
+
+ Some((ty, placeholder.trait_name))
+ })
+ }
+
+ /// Errors in case legacy syntax is encountered: `fmt = "...", (arg),*`.
+ fn check_legacy_fmt(input: ParseStream<'_>) -> syn::Result<()> {
+ let fork = input.fork();
+
+ let path = fork
+ .parse::<syn::Path>()
+ .and_then(|path| fork.parse::<syn::token::Eq>().map(|_| path));
+ match path {
+ Ok(path) if path.is_ident("fmt") => (|| {
+ let args = fork
+ .parse_terminated(syn::Lit::parse, token::Comma)
+ .ok()?
+ .into_iter()
+ .enumerate()
+ .filter_map(|(i, lit)| match lit {
+ syn::Lit::Str(str) => Some(if i == 0 {
+ format!("\"{}\"", str.value())
+ } else {
+ str.value()
+ }),
+ _ => None,
+ })
+ .collect::<Vec<_>>();
+ (!args.is_empty()).then_some(args)
+ })()
+ .map_or(Ok(()), |fmt| {
+ Err(syn::Error::new(
+ input.span(),
+ format!(
+ "legacy syntax, remove `fmt =` and use `{}` instead",
+ fmt.join(", "),
+ ),
+ ))
+ }),
+ Ok(_) | Err(_) => Ok(()),
+ }
+ }
+}
+
+impl Parse for FmtAttribute {
+ fn parse(input: ParseStream) -> syn::Result<Self> {
+ Ok(Self {
+ lit: input.parse()?,
+ comma: input
+ .peek(syn::token::Comma)
+ .then(|| input.parse())
+ .transpose()?,
+ args: input.parse_terminated(FmtArgument::parse, token::Comma)?,
+ })
+ }
+}
+
+impl ToTokens for FmtAttribute {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.lit.to_tokens(tokens);
+ self.comma.to_tokens(tokens);
+ self.args.to_tokens(tokens);
+ }
+}
+
+/// Representation of a [named parameter][1] (`identifier '=' expression`) in
+/// in a [`FmtAttribute`].
+///
+/// [1]: https://doc.rust-lang.org/stable/std/fmt/index.html#named-parameters
+#[derive(Debug)]
+struct FmtArgument {
+ /// `identifier =` [`Ident`].
+ alias: Option<(Ident, token::Eq)>,
+
+ /// `expression` [`Expr`].
+ expr: Expr,
+}
+
+impl FmtArgument {
+ /// Returns an `identifier` of the [named parameter][1].
+ ///
+ /// [1]: https://doc.rust-lang.org/stable/std/fmt/index.html#named-parameters
+ fn alias(&self) -> Option<&Ident> {
+ self.alias.as_ref().map(|(ident, _)| ident)
+ }
+}
+
+impl Parse for FmtArgument {
+ fn parse(input: ParseStream) -> syn::Result<Self> {
+ Ok(Self {
+ alias: (input.peek(Ident) && input.peek2(token::Eq))
+ .then(|| Ok::<_, syn::Error>((input.parse()?, input.parse()?)))
+ .transpose()?,
+ expr: input.parse()?,
+ })
+ }
+}
+
+impl ToTokens for FmtArgument {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ if let Some((ident, eq)) = &self.alias {
+ ident.to_tokens(tokens);
+ eq.to_tokens(tokens);
+ }
+ self.expr.to_tokens(tokens);
+ }
+}
+
+/// Representation of a [parameter][1] used in a [`Placeholder`].
+///
+/// [1]: https://doc.rust-lang.org/stable/std/fmt/index.html#formatting-parameters
+#[derive(Debug, Eq, PartialEq)]
+enum Parameter {
+ /// [Positional parameter][1].
+ ///
+ /// [1]: https://doc.rust-lang.org/stable/std/fmt/index.html#positional-parameters
+ Positional(usize),
+
+ /// [Named parameter][1].
+ ///
+ /// [1]: https://doc.rust-lang.org/stable/std/fmt/index.html#named-parameters
+ Named(String),
+}
+
+impl<'a> From<parsing::Argument<'a>> for Parameter {
+ fn from(arg: parsing::Argument<'a>) -> Self {
+ match arg {
+ parsing::Argument::Integer(i) => Self::Positional(i),
+ parsing::Argument::Identifier(i) => Self::Named(i.to_owned()),
+ }
+ }
+}
+
+/// Representation of a formatting placeholder.
+#[derive(Debug, PartialEq, Eq)]
+struct Placeholder {
+ /// Formatting argument (either named or positional) to be used by this placeholder.
+ arg: Parameter,
+
+ /// [Width parameter][1], if present.
+ ///
+ /// [1]: https://doc.rust-lang.org/stable/std/fmt/index.html#width
+ width: Option<Parameter>,
+
+ /// [Precision parameter][1], if present.
+ ///
+ /// [1]: https://doc.rust-lang.org/stable/std/fmt/index.html#precision
+ precision: Option<Parameter>,
+
+ /// Name of [`std::fmt`] trait to be used for rendering this placeholder.
+ trait_name: &'static str,
+}
+
+impl Placeholder {
+ /// Parses [`Placeholder`]s from the provided formatting string.
+ fn parse_fmt_string(s: &str) -> Vec<Self> {
+ let mut n = 0;
+ parsing::format_string(s)
+ .into_iter()
+ .flat_map(|f| f.formats)
+ .map(|format| {
+ let (maybe_arg, ty) = (
+ format.arg,
+ format.spec.map(|s| s.ty).unwrap_or(parsing::Type::Display),
+ );
+ let position = maybe_arg.map(Into::into).unwrap_or_else(|| {
+ // Assign "the next argument".
+ // https://doc.rust-lang.org/stable/std/fmt/index.html#positional-parameters
+ n += 1;
+ Parameter::Positional(n - 1)
+ });
+
+ Self {
+ arg: position,
+ width: format.spec.and_then(|s| match s.width {
+ Some(parsing::Count::Parameter(arg)) => Some(arg.into()),
+ _ => None,
+ }),
+ precision: format.spec.and_then(|s| match s.precision {
+ Some(parsing::Precision::Count(parsing::Count::Parameter(
+ arg,
+ ))) => Some(arg.into()),
+ _ => None,
+ }),
+ trait_name: ty.trait_name(),
+ }
+ })
+ .collect()
+ }
+}
+
+#[cfg(test)]
+mod fmt_attribute_spec {
+ use itertools::Itertools as _;
+ use quote::ToTokens;
+ use syn;
+
+ use super::FmtAttribute;
+
+ fn assert<'a>(input: &'a str, parsed: impl AsRef<[&'a str]>) {
+ let parsed = parsed.as_ref();
+ let attr = syn::parse_str::<FmtAttribute>(&format!("\"\", {}", input)).unwrap();
+ let fmt_args = attr
+ .args
+ .into_iter()
+ .map(|arg| arg.into_token_stream().to_string())
+ .collect::<Vec<String>>();
+ fmt_args.iter().zip_eq(parsed).enumerate().for_each(
+ |(i, (found, expected))| {
+ assert_eq!(
+ *expected, found,
+ "Mismatch at index {i}\n\
+ Expected: {parsed:?}\n\
+ Found: {fmt_args:?}",
+ );
+ },
+ );
+ }
+
+ #[test]
+ fn cases() {
+ let cases = [
+ "ident",
+ "alias = ident",
+ "[a , b , c , d]",
+ "counter += 1",
+ "async { fut . await }",
+ "a < b",
+ "a > b",
+ "{ let x = (a , b) ; }",
+ "invoke (a , b)",
+ "foo as f64",
+ "| a , b | a + b",
+ "obj . k",
+ "for pat in expr { break pat ; }",
+ "if expr { true } else { false }",
+ "vector [2]",
+ "1",
+ "\"foo\"",
+ "loop { break i ; }",
+ "format ! (\"{}\" , q)",
+ "match n { Some (n) => { } , None => { } }",
+ "x . foo ::< T > (a , b)",
+ "x . foo ::< T < [T < T >; if a < b { 1 } else { 2 }] >, { a < b } > (a , b)",
+ "(a + b)",
+ "i32 :: MAX",
+ "1 .. 2",
+ "& a",
+ "[0u8 ; N]",
+ "(a , b , c , d)",
+ "< Ty as Trait > :: T",
+ "< Ty < Ty < T >, { a < b } > as Trait < T > > :: T",
+ ];
+
+ assert("", []);
+ for i in 1..4 {
+ for permutations in cases.into_iter().permutations(i) {
+ let mut input = permutations.clone().join(",");
+ assert(&input, &permutations);
+ input.push(',');
+ assert(&input, &permutations);
+ }
+ }
+ }
+}
+
+#[cfg(test)]
+mod placeholder_parse_fmt_string_spec {
+ use super::{Parameter, Placeholder};
+
+ #[test]
+ fn indicates_position_and_trait_name_for_each_fmt_placeholder() {
+ let fmt_string = "{},{:?},{{}},{{{1:0$}}}-{2:.1$x}{par:#?}{:width$}";
+ assert_eq!(
+ Placeholder::parse_fmt_string(&fmt_string),
+ vec![
+ Placeholder {
+ arg: Parameter::Positional(0),
+ width: None,
+ precision: None,
+ trait_name: "Display",
+ },
+ Placeholder {
+ arg: Parameter::Positional(1),
+ width: None,
+ precision: None,
+ trait_name: "Debug",
+ },
+ Placeholder {
+ arg: Parameter::Positional(1),
+ width: Some(Parameter::Positional(0)),
+ precision: None,
+ trait_name: "Display",
+ },
+ Placeholder {
+ arg: Parameter::Positional(2),
+ width: None,
+ precision: Some(Parameter::Positional(1)),
+ trait_name: "LowerHex",
+ },
+ Placeholder {
+ arg: Parameter::Named("par".to_owned()),
+ width: None,
+ precision: None,
+ trait_name: "Debug",
+ },
+ Placeholder {
+ arg: Parameter::Positional(2),
+ width: Some(Parameter::Named("width".to_owned())),
+ precision: None,
+ trait_name: "Display",
+ },
+ ],
+ );
+ }
+}
diff --git a/third_party/rust/derive_more-impl/src/fmt/parsing.rs b/third_party/rust/derive_more-impl/src/fmt/parsing.rs
new file mode 100644
index 0000000000..e4586668f0
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/fmt/parsing.rs
@@ -0,0 +1,1096 @@
+//! Parsing of [Rust `fmt` syntax][0].
+//!
+//! [0]: std::fmt#syntax
+
+use std::{convert::identity, iter};
+
+use unicode_xid::UnicodeXID as XID;
+
+/// Output of the [`format_string`] parser.
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub(crate) struct FormatString<'a> {
+ pub(crate) formats: Vec<Format<'a>>,
+}
+
+/// Output of the [`format`] parser.
+///
+/// [`format`]: fn@format
+#[derive(Debug, Clone, Copy, Eq, PartialEq)]
+pub(crate) struct Format<'a> {
+ pub(crate) arg: Option<Argument<'a>>,
+ pub(crate) spec: Option<FormatSpec<'a>>,
+}
+
+/// Output of the [`format_spec`] parser.
+#[derive(Debug, Clone, Copy, Eq, PartialEq)]
+pub(crate) struct FormatSpec<'a> {
+ pub(crate) width: Option<Width<'a>>,
+ pub(crate) precision: Option<Precision<'a>>,
+ pub(crate) ty: Type,
+}
+
+/// Output of the [`argument`] parser.
+#[derive(Debug, Clone, Copy, Eq, PartialEq)]
+pub(crate) enum Argument<'a> {
+ Integer(usize),
+ Identifier(&'a str),
+}
+
+/// Output of the [`precision`] parser.
+#[derive(Debug, Clone, Copy, Eq, PartialEq)]
+pub(crate) enum Precision<'a> {
+ Count(Count<'a>),
+ Star,
+}
+
+/// Output of the [`count`] parser.
+#[derive(Debug, Clone, Copy, Eq, PartialEq)]
+pub(crate) enum Count<'a> {
+ Integer(usize),
+ Parameter(Parameter<'a>),
+}
+
+/// Output of the [`type_`] parser. See [formatting traits][1] for more info.
+///
+/// [1]: https://doc.rust-lang.org/stable/std/fmt/index.html#formatting-traits
+#[derive(Debug, Clone, Copy, Eq, PartialEq)]
+pub(crate) enum Type {
+ Display,
+ Debug,
+ LowerDebug,
+ UpperDebug,
+ Octal,
+ LowerHex,
+ UpperHex,
+ Pointer,
+ Binary,
+ LowerExp,
+ UpperExp,
+}
+
+impl Type {
+ /// Returns trait name of this [`Type`].
+ pub(crate) fn trait_name(&self) -> &'static str {
+ match self {
+ Type::Display => "Display",
+ Type::Debug | Type::LowerDebug | Type::UpperDebug => "Debug",
+ Type::Octal => "Octal",
+ Type::LowerHex => "LowerHex",
+ Type::UpperHex => "UpperHex",
+ Type::Pointer => "Pointer",
+ Type::Binary => "Binary",
+ Type::LowerExp => "LowerExp",
+ Type::UpperExp => "UpperExp",
+ }
+ }
+}
+
+/// Type alias for the [`FormatSpec::width`].
+type Width<'a> = Count<'a>;
+
+/// Output of the [`maybe_format`] parser.
+type MaybeFormat<'a> = Option<Format<'a>>;
+
+/// Output of the [`identifier`] parser.
+type Identifier<'a> = &'a str;
+
+/// Output of the [`parameter`] parser.
+type Parameter<'a> = Argument<'a>;
+
+/// [`str`] left to parse.
+///
+/// [`str`]: prim@str
+type LeftToParse<'a> = &'a str;
+
+/// Parses a `format_string` as defined in the [grammar spec][1].
+///
+/// # Grammar
+///
+/// [`format_string`]` := `[`text`]` [`[`maybe_format text`]`] *`
+///
+/// # Example
+///
+/// ```text
+/// Hello
+/// Hello, {}!
+/// {:?}
+/// Hello {people}!
+/// {} {}
+/// {:04}
+/// {par:-^#.0$?}
+/// ```
+///
+/// # Return value
+///
+/// - [`Some`] in case of successful parse.
+/// - [`None`] otherwise (not all characters are consumed by underlying
+/// parsers).
+///
+/// [1]: https://doc.rust-lang.org/stable/std/fmt/index.html#syntax
+pub(crate) fn format_string(input: &str) -> Option<FormatString<'_>> {
+ let (mut input, _) = optional_result(text)(input);
+
+ let formats = iter::repeat(())
+ .scan(&mut input, |input, _| {
+ let (curr, format) =
+ alt(&mut [&mut maybe_format, &mut map(text, |(i, _)| (i, None))])(
+ input,
+ )?;
+ **input = curr;
+ Some(format)
+ })
+ .flatten()
+ .collect();
+
+ // Should consume all tokens for a successful parse.
+ input.is_empty().then_some(FormatString { formats })
+}
+
+/// Parses a `maybe_format` as defined in the [grammar spec][1].
+///
+/// # Grammar
+///
+/// [`maybe_format`]` := '{' '{' | '}' '}' | `[`format`]
+///
+/// # Example
+///
+/// ```text
+/// {{
+/// }}
+/// {:04}
+/// {:#?}
+/// {par:-^#.0$?}
+/// ```
+///
+/// [`format`]: fn@format
+/// [1]: https://doc.rust-lang.org/stable/std/fmt/index.html#syntax
+fn maybe_format(input: &str) -> Option<(LeftToParse<'_>, MaybeFormat<'_>)> {
+ alt(&mut [
+ &mut map(str("{{"), |i| (i, None)),
+ &mut map(str("}}"), |i| (i, None)),
+ &mut map(format, |(i, format)| (i, Some(format))),
+ ])(input)
+}
+
+/// Parses a `format` as defined in the [grammar spec][1].
+///
+/// # Grammar
+///
+/// [`format`]` := '{' [`[`argument`]`] [':' `[`format_spec`]`] '}'`
+///
+/// # Example
+///
+/// ```text
+/// {par}
+/// {:#?}
+/// {par:-^#.0$?}
+/// ```
+///
+/// [`format`]: fn@format
+/// [1]: https://doc.rust-lang.org/stable/std/fmt/index.html#syntax
+fn format(input: &str) -> Option<(LeftToParse<'_>, Format<'_>)> {
+ let input = char('{')(input)?;
+
+ let (input, arg) = optional_result(argument)(input);
+
+ let (input, spec) = map_or_else(
+ char(':'),
+ |i| Some((i, None)),
+ map(format_spec, |(i, s)| (i, Some(s))),
+ )(input)?;
+
+ let input = char('}')(input)?;
+
+ Some((input, Format { arg, spec }))
+}
+
+/// Parses an `argument` as defined in the [grammar spec][1].
+///
+/// # Grammar
+///
+/// [`argument`]` := `[`integer`]` | `[`identifier`]
+///
+/// # Example
+///
+/// ```text
+/// 0
+/// ident
+/// Минск
+/// ```
+///
+/// [1]: https://doc.rust-lang.org/stable/std/fmt/index.html#syntax
+fn argument(input: &str) -> Option<(LeftToParse<'_>, Argument)> {
+ alt(&mut [
+ &mut map(identifier, |(i, ident)| (i, Argument::Identifier(ident))),
+ &mut map(integer, |(i, int)| (i, Argument::Integer(int))),
+ ])(input)
+}
+
+/// Parses a `format_spec` as defined in the [grammar spec][1].
+///
+/// # Grammar
+///
+/// [`format_spec`]` := [[fill]align][sign]['#']['0'][width]`
+/// `['.' `[`precision`]`]`[`type`]
+///
+/// # Example
+///
+/// ```text
+/// ^
+/// <^
+/// ->+#0width$.precision$x?
+/// ```
+///
+/// [`type`]: type_
+/// [1]: https://doc.rust-lang.org/stable/std/fmt/index.html#syntax
+fn format_spec(input: &str) -> Option<(LeftToParse<'_>, FormatSpec<'_>)> {
+ let input = unwrap_or_else(
+ alt(&mut [
+ &mut try_seq(&mut [&mut any_char, &mut one_of("<^>")]),
+ &mut one_of("<^>"),
+ ]),
+ identity,
+ )(input);
+
+ let input = seq(&mut [
+ &mut optional(one_of("+-")),
+ &mut optional(char('#')),
+ &mut optional(try_seq(&mut [
+ &mut char('0'),
+ &mut lookahead(check_char(|c| !matches!(c, '$'))),
+ ])),
+ ])(input);
+
+ let (input, width) = optional_result(count)(input);
+
+ let (input, precision) = map_or_else(
+ char('.'),
+ |i| Some((i, None)),
+ map(precision, |(i, p)| (i, Some(p))),
+ )(input)?;
+
+ let (input, ty) = type_(input)?;
+
+ Some((
+ input,
+ FormatSpec {
+ width,
+ precision,
+ ty,
+ },
+ ))
+}
+
+/// Parses a `precision` as defined in the [grammar spec][1].
+///
+/// # Grammar
+///
+/// [`precision`]` := `[`count`]` | '*'`
+///
+/// # Example
+///
+/// ```text
+/// 0
+/// 42$
+/// par$
+/// *
+/// ```
+///
+/// [1]: https://doc.rust-lang.org/stable/std/fmt/index.html#syntax
+fn precision(input: &str) -> Option<(LeftToParse<'_>, Precision<'_>)> {
+ alt(&mut [
+ &mut map(count, |(i, c)| (i, Precision::Count(c))),
+ &mut map(char('*'), |i| (i, Precision::Star)),
+ ])(input)
+}
+
+/// Parses a `type` as defined in the [grammar spec][1].
+///
+/// # Grammar
+///
+/// [`type`]` := '' | '?' | 'x?' | 'X?' | identifier`
+///
+/// # Example
+///
+/// All possible [`Type`]s.
+///
+/// ```text
+/// ?
+/// x?
+/// X?
+/// o
+/// x
+/// X
+/// p
+/// b
+/// e
+/// E
+/// ```
+///
+/// [`type`]: type_
+/// [1]: https://doc.rust-lang.org/stable/std/fmt/index.html#syntax
+fn type_(input: &str) -> Option<(&str, Type)> {
+ alt(&mut [
+ &mut map(str("x?"), |i| (i, Type::LowerDebug)),
+ &mut map(str("X?"), |i| (i, Type::UpperDebug)),
+ &mut map(char('?'), |i| (i, Type::Debug)),
+ &mut map(char('o'), |i| (i, Type::Octal)),
+ &mut map(char('x'), |i| (i, Type::LowerHex)),
+ &mut map(char('X'), |i| (i, Type::UpperHex)),
+ &mut map(char('p'), |i| (i, Type::Pointer)),
+ &mut map(char('b'), |i| (i, Type::Binary)),
+ &mut map(char('e'), |i| (i, Type::LowerExp)),
+ &mut map(char('E'), |i| (i, Type::UpperExp)),
+ &mut map(lookahead(char('}')), |i| (i, Type::Display)),
+ ])(input)
+}
+
+/// Parses a `count` as defined in the [grammar spec][1].
+///
+/// # Grammar
+///
+/// [`count`]` := `[`parameter`]` | `[`integer`]
+///
+/// # Example
+///
+/// ```text
+/// 0
+/// 42$
+/// par$
+/// ```
+///
+/// [1]: https://doc.rust-lang.org/stable/std/fmt/index.html#syntax
+fn count(input: &str) -> Option<(LeftToParse<'_>, Count<'_>)> {
+ alt(&mut [
+ &mut map(parameter, |(i, p)| (i, Count::Parameter(p))),
+ &mut map(integer, |(i, int)| (i, Count::Integer(int))),
+ ])(input)
+}
+
+/// Parses a `parameter` as defined in the [grammar spec][1].
+///
+/// # Grammar
+///
+/// [`parameter`]` := `[`argument`]` '$'`
+///
+/// # Example
+///
+/// ```text
+/// 42$
+/// par$
+/// ```
+///
+/// [1]: https://doc.rust-lang.org/stable/std/fmt/index.html#syntax
+fn parameter(input: &str) -> Option<(LeftToParse<'_>, Parameter<'_>)> {
+ and_then(argument, |(i, arg)| map(char('$'), |i| (i, arg))(i))(input)
+}
+
+/// Parses an `identifier` as defined in the [grammar spec][1].
+///
+/// # Grammar
+///
+/// `IDENTIFIER_OR_KEYWORD : XID_Start XID_Continue* | _ XID_Continue+`
+///
+/// See [rust reference][2] for more info.
+///
+/// # Example
+///
+/// ```text
+/// identifier
+/// Минск
+/// ```
+///
+/// [1]: https://doc.rust-lang.org/stable/std/fmt/index.html#syntax
+/// [2]: https://doc.rust-lang.org/reference/identifiers.html
+fn identifier(input: &str) -> Option<(LeftToParse<'_>, Identifier<'_>)> {
+ map(
+ alt(&mut [
+ &mut map(
+ check_char(XID::is_xid_start),
+ take_while0(check_char(XID::is_xid_continue)),
+ ),
+ &mut and_then(char('_'), take_while1(check_char(XID::is_xid_continue))),
+ ]),
+ |(i, _)| (i, &input[..(input.as_bytes().len() - i.as_bytes().len())]),
+ )(input)
+}
+
+/// Parses an `integer` as defined in the [grammar spec][1].
+///
+/// [1]: https://doc.rust-lang.org/stable/std/fmt/index.html#syntax
+fn integer(input: &str) -> Option<(LeftToParse<'_>, usize)> {
+ and_then(
+ take_while1(check_char(|c| c.is_ascii_digit())),
+ |(i, int)| int.parse().ok().map(|int| (i, int)),
+ )(input)
+}
+
+/// Parses a `text` as defined in the [grammar spec][1].
+///
+/// [1]: https://doc.rust-lang.org/stable/std/fmt/index.html#syntax
+fn text(input: &str) -> Option<(LeftToParse<'_>, &str)> {
+ take_until1(any_char, one_of("{}"))(input)
+}
+
+type Parser<'p> = &'p mut dyn FnMut(&str) -> &str;
+
+/// Applies non-failing parsers in sequence.
+fn seq<'p>(parsers: &'p mut [Parser<'p>]) -> impl FnMut(&str) -> LeftToParse<'_> + 'p {
+ move |input| parsers.iter_mut().fold(input, |i, p| (**p)(i))
+}
+
+type FallibleParser<'p> = &'p mut dyn FnMut(&str) -> Option<&str>;
+
+/// Tries to apply parsers in sequence. Returns [`None`] in case one of them
+/// returned [`None`].
+fn try_seq<'p>(
+ parsers: &'p mut [FallibleParser<'p>],
+) -> impl FnMut(&str) -> Option<LeftToParse<'_>> + 'p {
+ move |input| parsers.iter_mut().try_fold(input, |i, p| (**p)(i))
+}
+
+/// Returns first successful parser or [`None`] in case all of them returned
+/// [`None`].
+fn alt<'p, 'i, T: 'i>(
+ parsers: &'p mut [&'p mut dyn FnMut(&'i str) -> Option<T>],
+) -> impl FnMut(&'i str) -> Option<T> + 'p {
+ move |input| parsers.iter_mut().find_map(|p| (**p)(input))
+}
+
+/// Maps output of the parser in case it returned [`Some`].
+fn map<'i, I: 'i, O: 'i>(
+ mut parser: impl FnMut(&'i str) -> Option<I>,
+ mut f: impl FnMut(I) -> O,
+) -> impl FnMut(&'i str) -> Option<O> {
+ move |input| parser(input).map(&mut f)
+}
+
+/// Maps output of the parser in case it returned [`Some`] or uses `default`.
+fn map_or_else<'i, I: 'i, O: 'i>(
+ mut parser: impl FnMut(&'i str) -> Option<I>,
+ mut default: impl FnMut(&'i str) -> O,
+ mut f: impl FnMut(I) -> O,
+) -> impl FnMut(&'i str) -> O {
+ move |input| parser(input).map_or_else(|| default(input), &mut f)
+}
+
+/// Returns the contained [`Some`] value or computes it from a closure.
+fn unwrap_or_else<'i, O: 'i>(
+ mut parser: impl FnMut(&'i str) -> Option<O>,
+ mut f: impl FnMut(&'i str) -> O,
+) -> impl FnMut(&'i str) -> O {
+ move |input| parser(input).unwrap_or_else(|| f(input))
+}
+
+/// Returns [`None`] if the parser returned is [`None`], otherwise calls `f`
+/// with the wrapped value and returns the result.
+fn and_then<'i, I: 'i, O: 'i>(
+ mut parser: impl FnMut(&'i str) -> Option<I>,
+ mut f: impl FnMut(I) -> Option<O>,
+) -> impl FnMut(&'i str) -> Option<O> {
+ move |input| parser(input).and_then(&mut f)
+}
+
+/// Checks whether `parser` is successful while not advancing the original
+/// `input`.
+fn lookahead(
+ mut parser: impl FnMut(&str) -> Option<&str>,
+) -> impl FnMut(&str) -> Option<LeftToParse<'_>> {
+ move |input| map(&mut parser, |_| input)(input)
+}
+
+/// Makes underlying `parser` optional by returning the original `input` in case
+/// it returned [`None`].
+fn optional(
+ mut parser: impl FnMut(&str) -> Option<&str>,
+) -> impl FnMut(&str) -> LeftToParse<'_> {
+ move |input: &str| parser(input).unwrap_or(input)
+}
+
+/// Makes underlying `parser` optional by returning the original `input` and
+/// [`None`] in case it returned [`None`].
+fn optional_result<'i, T: 'i>(
+ mut parser: impl FnMut(&'i str) -> Option<(&'i str, T)>,
+) -> impl FnMut(&'i str) -> (LeftToParse<'i>, Option<T>) {
+ move |input: &str| {
+ map_or_else(&mut parser, |i| (i, None), |(i, c)| (i, Some(c)))(input)
+ }
+}
+
+/// Parses while `parser` is successful. Never fails.
+fn take_while0(
+ mut parser: impl FnMut(&str) -> Option<&str>,
+) -> impl FnMut(&str) -> (LeftToParse<'_>, &str) {
+ move |input| {
+ let mut cur = input;
+ while let Some(step) = parser(cur) {
+ cur = step;
+ }
+ (
+ cur,
+ &input[..(input.as_bytes().len() - cur.as_bytes().len())],
+ )
+ }
+}
+
+/// Parses while `parser` is successful. Returns [`None`] in case `parser` never
+/// succeeded.
+fn take_while1(
+ mut parser: impl FnMut(&str) -> Option<&str>,
+) -> impl FnMut(&str) -> Option<(LeftToParse<'_>, &str)> {
+ move |input| {
+ let mut cur = parser(input)?;
+ while let Some(step) = parser(cur) {
+ cur = step;
+ }
+ Some((
+ cur,
+ &input[..(input.as_bytes().len() - cur.as_bytes().len())],
+ ))
+ }
+}
+
+/// Parses with `basic` while `until` returns [`None`]. Returns [`None`] in case
+/// `until` succeeded initially or `basic` never succeeded. Doesn't consume
+/// [`char`]s parsed by `until`.
+///
+/// [`char`]: fn@char
+fn take_until1(
+ mut basic: impl FnMut(&str) -> Option<&str>,
+ mut until: impl FnMut(&str) -> Option<&str>,
+) -> impl FnMut(&str) -> Option<(LeftToParse<'_>, &str)> {
+ move |input: &str| {
+ if until(input).is_some() {
+ return None;
+ }
+ let mut cur = basic(input)?;
+ loop {
+ if until(cur).is_some() {
+ break;
+ }
+ let Some(b) = basic(cur) else {
+ break;
+ };
+ cur = b;
+ }
+
+ Some((
+ cur,
+ &input[..(input.as_bytes().len() - cur.as_bytes().len())],
+ ))
+ }
+}
+
+/// Checks whether `input` starts with `s`.
+fn str(s: &str) -> impl FnMut(&str) -> Option<LeftToParse<'_>> + '_ {
+ move |input| input.starts_with(s).then(|| &input[s.as_bytes().len()..])
+}
+
+/// Checks whether `input` starts with `c`.
+fn char(c: char) -> impl FnMut(&str) -> Option<LeftToParse<'_>> {
+ move |input| input.starts_with(c).then(|| &input[c.len_utf8()..])
+}
+
+/// Checks whether first [`char`] suits `check`.
+///
+/// [`char`]: fn@char
+fn check_char(
+ mut check: impl FnMut(char) -> bool,
+) -> impl FnMut(&str) -> Option<LeftToParse<'_>> {
+ move |input| {
+ input
+ .chars()
+ .next()
+ .and_then(|c| check(c).then(|| &input[c.len_utf8()..]))
+ }
+}
+
+/// Checks whether first [`char`] of input is present in `chars`.
+///
+/// [`char`]: fn@char
+fn one_of(chars: &str) -> impl FnMut(&str) -> Option<LeftToParse<'_>> + '_ {
+ move |input: &str| chars.chars().find_map(|c| char(c)(input))
+}
+
+/// Parses any [`char`].
+///
+/// [`char`]: fn@char
+fn any_char(input: &str) -> Option<LeftToParse<'_>> {
+ input.chars().next().map(|c| &input[c.len_utf8()..])
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn text() {
+ assert_eq!(format_string(""), Some(FormatString { formats: vec![] }));
+ assert_eq!(
+ format_string("test"),
+ Some(FormatString { formats: vec![] }),
+ );
+ assert_eq!(
+ format_string("Минск"),
+ Some(FormatString { formats: vec![] }),
+ );
+ assert_eq!(format_string("🦀"), Some(FormatString { formats: vec![] }));
+ }
+
+ #[test]
+ fn argument() {
+ assert_eq!(
+ format_string("{}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: None,
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{0}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: Some(Argument::Integer(0)),
+ spec: None,
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{par}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: Some(Argument::Identifier("par")),
+ spec: None,
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{Минск}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: Some(Argument::Identifier("Минск")),
+ spec: None,
+ }],
+ }),
+ );
+ }
+
+ #[test]
+ fn spec() {
+ assert_eq!(
+ format_string("{:}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: None,
+ precision: None,
+ ty: Type::Display,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{:^}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: None,
+ precision: None,
+ ty: Type::Display,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{:-<}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: None,
+ precision: None,
+ ty: Type::Display,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{: <}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: None,
+ precision: None,
+ ty: Type::Display,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{:^<}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: None,
+ precision: None,
+ ty: Type::Display,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{:+}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: None,
+ precision: None,
+ ty: Type::Display,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{:^<-}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: None,
+ precision: None,
+ ty: Type::Display,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{:#}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: None,
+ precision: None,
+ ty: Type::Display,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{:+#}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: None,
+ precision: None,
+ ty: Type::Display,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{:-<#}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: None,
+ precision: None,
+ ty: Type::Display,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{:^<-#}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: None,
+ precision: None,
+ ty: Type::Display,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{:0}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: None,
+ precision: None,
+ ty: Type::Display,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{:#0}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: None,
+ precision: None,
+ ty: Type::Display,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{:-0}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: None,
+ precision: None,
+ ty: Type::Display,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{:^<0}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: None,
+ precision: None,
+ ty: Type::Display,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{:^<+#0}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: None,
+ precision: None,
+ ty: Type::Display,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{:1}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: Some(Count::Integer(1)),
+ precision: None,
+ ty: Type::Display,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{:1$}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: Some(Count::Parameter(Argument::Integer(1))),
+ precision: None,
+ ty: Type::Display,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{:par$}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: Some(Count::Parameter(Argument::Identifier("par"))),
+ precision: None,
+ ty: Type::Display,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{:-^-#0Минск$}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: Some(Count::Parameter(Argument::Identifier("Минск"))),
+ precision: None,
+ ty: Type::Display,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{:.*}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: None,
+ precision: Some(Precision::Star),
+ ty: Type::Display,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{:.0}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: None,
+ precision: Some(Precision::Count(Count::Integer(0))),
+ ty: Type::Display,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{:.0$}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: None,
+ precision: Some(Precision::Count(Count::Parameter(
+ Argument::Integer(0),
+ ))),
+ ty: Type::Display,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{:.par$}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: None,
+ precision: Some(Precision::Count(Count::Parameter(
+ Argument::Identifier("par"),
+ ))),
+ ty: Type::Display,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{: >+#2$.par$}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: Some(Count::Parameter(Argument::Integer(2))),
+ precision: Some(Precision::Count(Count::Parameter(
+ Argument::Identifier("par"),
+ ))),
+ ty: Type::Display,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{:x?}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: None,
+ precision: None,
+ ty: Type::LowerDebug,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{:E}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: None,
+ precision: None,
+ ty: Type::UpperExp,
+ }),
+ }],
+ }),
+ );
+ assert_eq!(
+ format_string("{: >+#par$.par$X?}"),
+ Some(FormatString {
+ formats: vec![Format {
+ arg: None,
+ spec: Some(FormatSpec {
+ width: Some(Count::Parameter(Argument::Identifier("par"))),
+ precision: Some(Precision::Count(Count::Parameter(
+ Argument::Identifier("par"),
+ ))),
+ ty: Type::UpperDebug,
+ }),
+ }],
+ }),
+ );
+ }
+
+ #[test]
+ fn full() {
+ assert_eq!(
+ format_string("prefix{{{0:#?}postfix{par:-^par$.a$}}}"),
+ Some(FormatString {
+ formats: vec![
+ Format {
+ arg: Some(Argument::Integer(0)),
+ spec: Some(FormatSpec {
+ width: None,
+ precision: None,
+ ty: Type::Debug,
+ }),
+ },
+ Format {
+ arg: Some(Argument::Identifier("par")),
+ spec: Some(FormatSpec {
+ width: Some(Count::Parameter(Argument::Identifier("par"))),
+ precision: Some(Precision::Count(Count::Parameter(
+ Argument::Identifier("a"),
+ ))),
+ ty: Type::Display,
+ }),
+ },
+ ],
+ }),
+ );
+ }
+
+ #[test]
+ fn error() {
+ assert_eq!(format_string("{"), None);
+ assert_eq!(format_string("}"), None);
+ assert_eq!(format_string("{{}"), None);
+ assert_eq!(format_string("{:x?"), None);
+ assert_eq!(format_string("{:.}"), None);
+ assert_eq!(format_string("{:q}"), None);
+ assert_eq!(format_string("{:par}"), None);
+ assert_eq!(format_string("{⚙️}"), None);
+ }
+}
diff --git a/third_party/rust/derive_more-impl/src/from.rs b/third_party/rust/derive_more-impl/src/from.rs
new file mode 100644
index 0000000000..cefab9baac
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/from.rs
@@ -0,0 +1,478 @@
+//! Implementation of a [`From`] derive macro.
+
+use std::iter;
+
+use proc_macro2::{Span, TokenStream};
+use quote::{format_ident, quote, ToTokens as _, TokenStreamExt as _};
+use syn::{
+ parse::{discouraged::Speculative as _, Parse, ParseStream},
+ parse_quote,
+ punctuated::Punctuated,
+ spanned::Spanned as _,
+ token, Ident,
+};
+
+use crate::{
+ parsing::Type,
+ utils::{polyfill, Either},
+};
+
+/// Expands a [`From`] derive macro.
+pub fn expand(input: &syn::DeriveInput, _: &'static str) -> syn::Result<TokenStream> {
+ match &input.data {
+ syn::Data::Struct(data) => Expansion {
+ attrs: StructAttribute::parse_attrs(&input.attrs, &data.fields)?
+ .map(Into::into)
+ .as_ref(),
+ ident: &input.ident,
+ variant: None,
+ fields: &data.fields,
+ generics: &input.generics,
+ has_explicit_from: false,
+ }
+ .expand(),
+ syn::Data::Enum(data) => {
+ let mut has_explicit_from = false;
+ let attrs = data
+ .variants
+ .iter()
+ .map(|variant| {
+ let attrs =
+ VariantAttribute::parse_attrs(&variant.attrs, &variant.fields)?;
+ if matches!(
+ attrs,
+ Some(
+ VariantAttribute::From
+ | VariantAttribute::Types(_)
+ | VariantAttribute::Forward
+ ),
+ ) {
+ has_explicit_from = true;
+ }
+ Ok(attrs)
+ })
+ .collect::<syn::Result<Vec<_>>>()?;
+
+ data.variants
+ .iter()
+ .zip(&attrs)
+ .map(|(variant, attrs)| {
+ Expansion {
+ attrs: attrs.as_ref(),
+ ident: &input.ident,
+ variant: Some(&variant.ident),
+ fields: &variant.fields,
+ generics: &input.generics,
+ has_explicit_from,
+ }
+ .expand()
+ })
+ .collect()
+ }
+ syn::Data::Union(data) => Err(syn::Error::new(
+ data.union_token.span(),
+ "`From` cannot be derived for unions",
+ )),
+ }
+}
+
+/// Representation of a [`From`] derive macro struct container attribute.
+///
+/// ```rust,ignore
+/// #[from(<types>)]
+/// #[from(forward)]
+/// ```
+enum StructAttribute {
+ /// [`Type`]s to derive [`From`].
+ Types(Punctuated<Type, token::Comma>),
+
+ /// Forward [`From`] implementation.
+ Forward,
+}
+
+impl StructAttribute {
+ /// Parses a [`StructAttribute`] from the provided [`syn::Attribute`]s.
+ fn parse_attrs(
+ attrs: impl AsRef<[syn::Attribute]>,
+ fields: &syn::Fields,
+ ) -> syn::Result<Option<Self>> {
+ Ok(attrs
+ .as_ref()
+ .iter()
+ .filter(|attr| attr.path().is_ident("from"))
+ .try_fold(None, |attrs, attr| {
+ let field_attr = attr.parse_args_with(|stream: ParseStream<'_>| {
+ Self::parse(stream, fields)
+ })?;
+ match (attrs, field_attr) {
+ (
+ Some((path, StructAttribute::Types(mut tys))),
+ StructAttribute::Types(more),
+ ) => {
+ tys.extend(more);
+ Ok(Some((path, StructAttribute::Types(tys))))
+ }
+ (None, field_attr) => Ok(Some((attr.path(), field_attr))),
+ _ => Err(syn::Error::new(
+ attr.path().span(),
+ "only single `#[from(...)]` attribute is allowed here",
+ )),
+ }
+ })?
+ .map(|(_, attr)| attr))
+ }
+
+ /// Parses single [`StructAttribute`].
+ fn parse(input: ParseStream<'_>, fields: &syn::Fields) -> syn::Result<Self> {
+ let ahead = input.fork();
+ match ahead.parse::<syn::Path>() {
+ Ok(p) if p.is_ident("forward") => {
+ input.advance_to(&ahead);
+ Ok(Self::Forward)
+ }
+ Ok(p) if p.is_ident("types") => legacy_error(&ahead, input.span(), fields),
+ _ => input
+ .parse_terminated(Type::parse, token::Comma)
+ .map(Self::Types),
+ }
+ }
+}
+
+/// Representation of a [`From`] derive macro enum variant attribute.
+///
+/// ```rust,ignore
+/// #[from]
+/// #[from(<types>)]
+/// #[from(forward)]
+/// #[from(skip)]
+/// ```
+enum VariantAttribute {
+ /// Explicitly derive [`From`].
+ From,
+
+ /// [`Type`]s to derive [`From`].
+ Types(Punctuated<Type, token::Comma>),
+
+ /// Forward [`From`] implementation.
+ Forward,
+
+ /// Skip variant.
+ Skip,
+}
+
+impl VariantAttribute {
+ /// Parses a [`VariantAttribute`] from the provided [`syn::Attribute`]s.
+ fn parse_attrs(
+ attrs: impl AsRef<[syn::Attribute]>,
+ fields: &syn::Fields,
+ ) -> syn::Result<Option<Self>> {
+ Ok(attrs
+ .as_ref()
+ .iter()
+ .filter(|attr| attr.path().is_ident("from"))
+ .try_fold(None, |mut attrs, attr| {
+ let field_attr = Self::parse_attr(attr, fields)?;
+ if let Some((path, _)) = attrs.replace((attr.path(), field_attr)) {
+ Err(syn::Error::new(
+ path.span(),
+ "only single `#[from(...)]` attribute is allowed here",
+ ))
+ } else {
+ Ok(attrs)
+ }
+ })?
+ .map(|(_, attr)| attr))
+ }
+
+ /// Parses a [`VariantAttribute`] from the single provided [`syn::Attribute`].
+ fn parse_attr(attr: &syn::Attribute, fields: &syn::Fields) -> syn::Result<Self> {
+ if matches!(attr.meta, syn::Meta::Path(_)) {
+ return Ok(Self::From);
+ }
+
+ attr.parse_args_with(|input: ParseStream<'_>| {
+ let ahead = input.fork();
+ match ahead.parse::<syn::Path>() {
+ Ok(p) if p.is_ident("forward") => {
+ input.advance_to(&ahead);
+ Ok(Self::Forward)
+ }
+ Ok(p) if p.is_ident("skip") || p.is_ident("ignore") => {
+ input.advance_to(&ahead);
+ Ok(Self::Skip)
+ }
+ Ok(p) if p.is_ident("types") => {
+ legacy_error(&ahead, input.span(), fields)
+ }
+ _ => input
+ .parse_terminated(Type::parse, token::Comma)
+ .map(Self::Types),
+ }
+ })
+ }
+}
+
+impl From<StructAttribute> for VariantAttribute {
+ fn from(value: StructAttribute) -> Self {
+ match value {
+ StructAttribute::Types(tys) => Self::Types(tys),
+ StructAttribute::Forward => Self::Forward,
+ }
+ }
+}
+
+/// Expansion of a macro for generating [`From`] implementation of a struct or
+/// enum.
+struct Expansion<'a> {
+ /// [`From`] attributes.
+ ///
+ /// As a [`VariantAttribute`] is superset of a [`StructAttribute`], we use
+ /// it for both derives.
+ attrs: Option<&'a VariantAttribute>,
+
+ /// Struct or enum [`Ident`].
+ ident: &'a Ident,
+
+ /// Variant [`Ident`] in case of enum expansion.
+ variant: Option<&'a Ident>,
+
+ /// Struct or variant [`syn::Fields`].
+ fields: &'a syn::Fields,
+
+ /// Struct or enum [`syn::Generics`].
+ generics: &'a syn::Generics,
+
+ /// Indicator whether one of the enum variants has
+ /// [`VariantAttribute::From`], [`VariantAttribute::Types`] or
+ /// [`VariantAttribute::Forward`].
+ ///
+ /// Always [`false`] for structs.
+ has_explicit_from: bool,
+}
+
+impl<'a> Expansion<'a> {
+ /// Expands [`From`] implementations for a struct or an enum variant.
+ fn expand(&self) -> syn::Result<TokenStream> {
+ use crate::utils::FieldsExt as _;
+
+ let ident = self.ident;
+ let field_tys = self.fields.iter().map(|f| &f.ty).collect::<Vec<_>>();
+ let (impl_gens, ty_gens, where_clause) = self.generics.split_for_impl();
+
+ let skip_variant = self.has_explicit_from
+ || (self.variant.is_some() && self.fields.is_empty());
+ match (self.attrs, skip_variant) {
+ (Some(VariantAttribute::Types(tys)), _) => {
+ tys.iter().map(|ty| {
+ let variant = self.variant.iter();
+
+ let mut from_tys = self.fields.validate_type(ty)?;
+ let init = self.expand_fields(|ident, ty, index| {
+ let ident = ident.into_iter();
+ let index = index.into_iter();
+ let from_ty = from_tys.next().unwrap_or_else(|| unreachable!());
+ quote! {
+ #( #ident: )* <#ty as ::core::convert::From<#from_ty>>::from(
+ value #( .#index )*
+ ),
+ }
+ });
+
+ Ok(quote! {
+ #[automatically_derived]
+ impl #impl_gens ::core::convert::From<#ty>
+ for #ident #ty_gens #where_clause
+ {
+ #[inline]
+ fn from(value: #ty) -> Self {
+ #ident #( :: #variant )* #init
+ }
+ }
+ })
+ })
+ .collect()
+ }
+ (Some(VariantAttribute::From), _) | (None, false) => {
+ let variant = self.variant.iter();
+ let init = self.expand_fields(|ident, _, index| {
+ let ident = ident.into_iter();
+ let index = index.into_iter();
+ quote! { #( #ident: )* value #( . #index )*, }
+ });
+
+ Ok(quote! {
+ #[automatically_derived]
+ impl #impl_gens ::core::convert::From<(#( #field_tys ),*)>
+ for #ident #ty_gens #where_clause
+ {
+ #[inline]
+ fn from(value: (#( #field_tys ),*)) -> Self {
+ #ident #( :: #variant )* #init
+ }
+ }
+ })
+ }
+ (Some(VariantAttribute::Forward), _) => {
+ let mut i = 0;
+ let mut gen_idents = Vec::with_capacity(self.fields.len());
+ let init = self.expand_fields(|ident, ty, index| {
+ let ident = ident.into_iter();
+ let index = index.into_iter();
+ let gen_ident = format_ident!("__FromT{i}");
+ let out = quote! {
+ #( #ident: )* <#ty as ::core::convert::From<#gen_ident>>::from(
+ value #( .#index )*
+ ),
+ };
+ gen_idents.push(gen_ident);
+ i += 1;
+ out
+ });
+
+ let variant = self.variant.iter();
+ let generics = {
+ let mut generics = self.generics.clone();
+ for (ty, ident) in field_tys.iter().zip(&gen_idents) {
+ generics.make_where_clause().predicates.push(
+ parse_quote! { #ty: ::core::convert::From<#ident> },
+ );
+ generics
+ .params
+ .push(syn::TypeParam::from(ident.clone()).into());
+ }
+ generics
+ };
+ let (impl_gens, _, where_clause) = generics.split_for_impl();
+
+ Ok(quote! {
+ #[automatically_derived]
+ impl #impl_gens ::core::convert::From<(#( #gen_idents ),*)>
+ for #ident #ty_gens #where_clause
+ {
+ #[inline]
+ fn from(value: (#( #gen_idents ),*)) -> Self {
+ #ident #(:: #variant)* #init
+ }
+ }
+ })
+ }
+ (Some(VariantAttribute::Skip), _) | (None, true) => {
+ Ok(TokenStream::new())
+ }
+ }
+ }
+
+ /// Expands fields initialization wrapped into [`token::Brace`]s in case of
+ /// [`syn::FieldsNamed`], or [`token::Paren`] in case of
+ /// [`syn::FieldsUnnamed`].
+ fn expand_fields(
+ &self,
+ mut wrap: impl FnMut(Option<&Ident>, &syn::Type, Option<syn::Index>) -> TokenStream,
+ ) -> TokenStream {
+ let surround = match self.fields {
+ syn::Fields::Named(_) | syn::Fields::Unnamed(_) => {
+ Some(|tokens| match self.fields {
+ syn::Fields::Named(named) => {
+ let mut out = TokenStream::new();
+ named
+ .brace_token
+ .surround(&mut out, |out| out.append_all(tokens));
+ out
+ }
+ syn::Fields::Unnamed(unnamed) => {
+ let mut out = TokenStream::new();
+ unnamed
+ .paren_token
+ .surround(&mut out, |out| out.append_all(tokens));
+ out
+ }
+ syn::Fields::Unit => unreachable!(),
+ })
+ }
+ syn::Fields::Unit => None,
+ };
+
+ surround
+ .map(|surround| {
+ surround(if self.fields.len() == 1 {
+ let field = self
+ .fields
+ .iter()
+ .next()
+ .unwrap_or_else(|| unreachable!("self.fields.len() == 1"));
+ wrap(field.ident.as_ref(), &field.ty, None)
+ } else {
+ self.fields
+ .iter()
+ .enumerate()
+ .map(|(i, field)| {
+ wrap(field.ident.as_ref(), &field.ty, Some(i.into()))
+ })
+ .collect()
+ })
+ })
+ .unwrap_or_default()
+ }
+}
+
+/// Constructs a [`syn::Error`] for legacy syntax: `#[from(types(i32, "&str"))]`.
+fn legacy_error<T>(
+ tokens: ParseStream<'_>,
+ span: Span,
+ fields: &syn::Fields,
+) -> syn::Result<T> {
+ let content;
+ syn::parenthesized!(content in tokens);
+
+ let types = content
+ .parse_terminated(polyfill::NestedMeta::parse, token::Comma)?
+ .into_iter()
+ .map(|meta| {
+ let value = match meta {
+ polyfill::NestedMeta::Meta(meta) => {
+ meta.into_token_stream().to_string()
+ }
+ polyfill::NestedMeta::Lit(syn::Lit::Str(str)) => str.value(),
+ polyfill::NestedMeta::Lit(_) => unreachable!(),
+ };
+ if fields.len() > 1 {
+ format!(
+ "({})",
+ fields
+ .iter()
+ .map(|_| value.clone())
+ .collect::<Vec<_>>()
+ .join(", "),
+ )
+ } else {
+ value
+ }
+ })
+ .chain(match fields.len() {
+ 0 => Either::Left(iter::empty()),
+ 1 => Either::Right(iter::once(
+ fields
+ .iter()
+ .next()
+ .unwrap_or_else(|| unreachable!("fields.len() == 1"))
+ .ty
+ .to_token_stream()
+ .to_string(),
+ )),
+ _ => Either::Right(iter::once(format!(
+ "({})",
+ fields
+ .iter()
+ .map(|f| f.ty.to_token_stream().to_string())
+ .collect::<Vec<_>>()
+ .join(", ")
+ ))),
+ })
+ .collect::<Vec<_>>()
+ .join(", ");
+
+ Err(syn::Error::new(
+ span,
+ format!("legacy syntax, remove `types` and use `{types}` instead"),
+ ))
+}
diff --git a/third_party/rust/derive_more-impl/src/from_str.rs b/third_party/rust/derive_more-impl/src/from_str.rs
new file mode 100644
index 0000000000..bc0ec5413a
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/from_str.rs
@@ -0,0 +1,112 @@
+use crate::utils::{DeriveType, HashMap};
+use crate::utils::{SingleFieldData, State};
+use proc_macro2::TokenStream;
+use quote::quote;
+use syn::{parse::Result, DeriveInput};
+
+/// Provides the hook to expand `#[derive(FromStr)]` into an implementation of `FromStr`
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let state = State::new(input, trait_name, trait_name.to_lowercase())?;
+
+ if state.derive_type == DeriveType::Enum {
+ Ok(enum_from(input, state, trait_name))
+ } else {
+ Ok(struct_from(&state, trait_name))
+ }
+}
+
+pub fn struct_from(state: &State, trait_name: &'static str) -> TokenStream {
+ // We cannot set defaults for fields, once we do we can remove this check
+ if state.fields.len() != 1 || state.enabled_fields().len() != 1 {
+ panic_one_field(trait_name);
+ }
+
+ let single_field_data = state.assert_single_enabled_field();
+ let SingleFieldData {
+ input_type,
+ field_type,
+ trait_path,
+ casted_trait,
+ impl_generics,
+ ty_generics,
+ where_clause,
+ ..
+ } = single_field_data.clone();
+
+ let initializers = [quote! { #casted_trait::from_str(src)? }];
+ let body = single_field_data.initializer(&initializers);
+
+ quote! {
+ #[automatically_derived]
+ impl #impl_generics #trait_path for #input_type #ty_generics #where_clause {
+ type Err = <#field_type as #trait_path>::Err;
+
+ #[inline]
+ fn from_str(src: &str) -> ::core::result::Result<Self, Self::Err> {
+ Ok(#body)
+ }
+ }
+ }
+}
+
+fn enum_from(
+ input: &DeriveInput,
+ state: State,
+ trait_name: &'static str,
+) -> TokenStream {
+ let mut variants_caseinsensitive = HashMap::default();
+ for variant_state in state.enabled_variant_data().variant_states {
+ let variant = variant_state.variant.unwrap();
+ if !variant.fields.is_empty() {
+ panic!("Only enums with no fields can derive({trait_name})")
+ }
+
+ variants_caseinsensitive
+ .entry(variant.ident.to_string().to_lowercase())
+ .or_insert_with(Vec::new)
+ .push(variant.ident.clone());
+ }
+
+ let input_type = &input.ident;
+ let input_type_name = input_type.to_string();
+
+ let mut cases = vec![];
+
+ // if a case insensitive match is unique match do that
+ // otherwise do a case sensitive match
+ for (ref canonical, ref variants) in variants_caseinsensitive {
+ if variants.len() == 1 {
+ let variant = &variants[0];
+ cases.push(quote! {
+ #canonical => #input_type::#variant,
+ })
+ } else {
+ for variant in variants {
+ let variant_str = variant.to_string();
+ cases.push(quote! {
+ #canonical if(src == #variant_str) => #input_type::#variant,
+ })
+ }
+ }
+ }
+
+ let trait_path = state.trait_path;
+
+ quote! {
+ impl #trait_path for #input_type {
+ type Err = ::derive_more::FromStrError;
+
+ #[inline]
+ fn from_str(src: &str) -> ::core::result::Result<Self, Self::Err> {
+ Ok(match src.to_lowercase().as_str() {
+ #(#cases)*
+ _ => return Err(::derive_more::FromStrError::new(#input_type_name)),
+ })
+ }
+ }
+ }
+}
+
+fn panic_one_field(trait_name: &str) -> ! {
+ panic!("Only structs with one field can derive({trait_name})")
+}
diff --git a/third_party/rust/derive_more-impl/src/index.rs b/third_party/rust/derive_more-impl/src/index.rs
new file mode 100644
index 0000000000..bf4f0d7b19
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/index.rs
@@ -0,0 +1,47 @@
+use crate::utils::{add_where_clauses_for_new_ident, SingleFieldData, State};
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote};
+use syn::{parse::Result, DeriveInput};
+
+/// Provides the hook to expand `#[derive(Index)]` into an implementation of `Index`
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let index_type = format_ident!("__IdxT");
+ let mut state =
+ State::with_field_ignore(input, trait_name, trait_name.to_lowercase())?;
+ state.add_trait_path_type_param(quote! { #index_type });
+ let SingleFieldData {
+ field,
+ field_type,
+ input_type,
+ trait_path_with_params,
+ casted_trait,
+ member,
+ ..
+ } = state.assert_single_enabled_field();
+
+ let type_where_clauses = quote! {
+ where #field_type: #trait_path_with_params
+ };
+
+ let new_generics = add_where_clauses_for_new_ident(
+ &input.generics,
+ &[field],
+ &index_type,
+ type_where_clauses,
+ true,
+ );
+
+ let (impl_generics, _, where_clause) = new_generics.split_for_impl();
+ let (_, ty_generics, _) = input.generics.split_for_impl();
+ Ok(quote! {
+ #[automatically_derived]
+ impl #impl_generics #trait_path_with_params for #input_type #ty_generics #where_clause {
+ type Output = #casted_trait::Output;
+
+ #[inline]
+ fn index(&self, idx: #index_type) -> &Self::Output {
+ #casted_trait::index(&#member, idx)
+ }
+ }
+ })
+}
diff --git a/third_party/rust/derive_more-impl/src/index_mut.rs b/third_party/rust/derive_more-impl/src/index_mut.rs
new file mode 100644
index 0000000000..0e030cf6f5
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/index_mut.rs
@@ -0,0 +1,44 @@
+use crate::utils::{add_where_clauses_for_new_ident, SingleFieldData, State};
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote};
+use syn::{parse::Result, DeriveInput};
+
+/// Provides the hook to expand `#[derive(IndexMut)]` into an implementation of `IndexMut`
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let index_type = format_ident!("__IdxT");
+ let mut state = State::with_field_ignore(input, trait_name, "index_mut".into())?;
+ state.add_trait_path_type_param(quote! { #index_type });
+ let SingleFieldData {
+ field,
+ field_type,
+ input_type,
+ trait_path_with_params,
+ casted_trait,
+ member,
+ ..
+ } = state.assert_single_enabled_field();
+
+ let type_where_clauses = quote! {
+ where #field_type: #trait_path_with_params
+ };
+
+ let new_generics = add_where_clauses_for_new_ident(
+ &input.generics,
+ &[field],
+ &index_type,
+ type_where_clauses,
+ true,
+ );
+
+ let (impl_generics, _, where_clause) = new_generics.split_for_impl();
+ let (_, ty_generics, _) = input.generics.split_for_impl();
+ Ok(quote! {
+ #[automatically_derived]
+ impl #impl_generics #trait_path_with_params for #input_type #ty_generics #where_clause {
+ #[inline]
+ fn index_mut(&mut self, idx: #index_type) -> &mut Self::Output {
+ #casted_trait::index_mut(&mut #member, idx)
+ }
+ }
+ })
+}
diff --git a/third_party/rust/derive_more-impl/src/into.rs b/third_party/rust/derive_more-impl/src/into.rs
new file mode 100644
index 0000000000..91e23bf403
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/into.rs
@@ -0,0 +1,448 @@
+//! Implementation of an [`Into`] derive macro.
+
+use std::{borrow::Cow, iter};
+
+use proc_macro2::{Span, TokenStream};
+use quote::{quote, ToTokens as _};
+use syn::{
+ ext::IdentExt as _,
+ parse::{discouraged::Speculative as _, Parse, ParseStream},
+ punctuated::Punctuated,
+ spanned::Spanned as _,
+ token, Ident,
+};
+
+use crate::{
+ parsing::Type,
+ utils::{polyfill, Either, FieldsExt as _},
+};
+
+/// Expands an [`Into`] derive macro.
+pub fn expand(input: &syn::DeriveInput, _: &'static str) -> syn::Result<TokenStream> {
+ let data = match &input.data {
+ syn::Data::Struct(data) => Ok(data),
+ syn::Data::Enum(e) => Err(syn::Error::new(
+ e.enum_token.span(),
+ "`Into` cannot be derived for enums",
+ )),
+ syn::Data::Union(u) => Err(syn::Error::new(
+ u.union_token.span(),
+ "`Into` cannot be derived for unions",
+ )),
+ }?;
+
+ let attr = StructAttribute::parse_attrs(&input.attrs, &data.fields)?
+ .unwrap_or_else(|| StructAttribute {
+ owned: Some(Punctuated::new()),
+ r#ref: None,
+ ref_mut: None,
+ });
+ let ident = &input.ident;
+ let fields = data
+ .fields
+ .iter()
+ .enumerate()
+ .filter_map(|(i, f)| match SkipFieldAttribute::parse_attrs(&f.attrs) {
+ Ok(None) => Some(Ok((
+ &f.ty,
+ f.ident
+ .as_ref()
+ .map_or_else(|| Either::Right(syn::Index::from(i)), Either::Left),
+ ))),
+ Ok(Some(_)) => None,
+ Err(e) => Some(Err(e)),
+ })
+ .collect::<syn::Result<Vec<_>>>()?;
+ let (fields_tys, fields_idents): (Vec<_>, Vec<_>) = fields.into_iter().unzip();
+ let (fields_tys, fields_idents) = (&fields_tys, &fields_idents);
+
+ let expand = |tys: Option<Punctuated<_, _>>, r: bool, m: bool| {
+ let Some(tys) = tys else {
+ return Either::Left(iter::empty());
+ };
+
+ let lf =
+ r.then(|| syn::Lifetime::new("'__derive_more_into", Span::call_site()));
+ let r = r.then(token::And::default);
+ let m = m.then(token::Mut::default);
+
+ let gens = if let Some(lf) = lf.clone() {
+ let mut gens = input.generics.clone();
+ gens.params.push(syn::LifetimeParam::new(lf).into());
+ Cow::Owned(gens)
+ } else {
+ Cow::Borrowed(&input.generics)
+ };
+
+ Either::Right(
+ if tys.is_empty() {
+ Either::Left(iter::once(Type::tuple(fields_tys.clone())))
+ } else {
+ Either::Right(tys.into_iter())
+ }
+ .map(move |ty| {
+ let tys = fields_tys.validate_type(&ty)?.collect::<Vec<_>>();
+ let (impl_gens, _, where_clause) = gens.split_for_impl();
+ let (_, ty_gens, _) = input.generics.split_for_impl();
+
+ Ok(quote! {
+ #[automatically_derived]
+ impl #impl_gens ::core::convert::From<#r #lf #m #ident #ty_gens>
+ for ( #( #r #lf #m #tys ),* ) #where_clause
+ {
+ #[inline]
+ fn from(value: #r #lf #m #ident #ty_gens) -> Self {
+ (#(
+ <#r #m #tys as ::core::convert::From<_>>::from(
+ #r #m value. #fields_idents
+ )
+ ),*)
+ }
+ }
+ })
+ }),
+ )
+ };
+
+ [
+ expand(attr.owned, false, false),
+ expand(attr.r#ref, true, false),
+ expand(attr.ref_mut, true, true),
+ ]
+ .into_iter()
+ .flatten()
+ .collect()
+}
+
+/// Representation of an [`Into`] derive macro struct container attribute.
+///
+/// ```rust,ignore
+/// #[into(<types>)]
+/// #[into(owned(<types>), ref(<types>), ref_mut(<types>))]
+/// ```
+#[derive(Debug, Default)]
+struct StructAttribute {
+ /// [`Type`]s wrapped into `owned(...)` or simply `#[into(...)]`.
+ owned: Option<Punctuated<Type, token::Comma>>,
+
+ /// [`Type`]s wrapped into `ref(...)`.
+ r#ref: Option<Punctuated<Type, token::Comma>>,
+
+ /// [`Type`]s wrapped into `ref_mut(...)`.
+ ref_mut: Option<Punctuated<Type, token::Comma>>,
+}
+
+impl StructAttribute {
+ /// Parses a [`StructAttribute`] from the provided [`syn::Attribute`]s.
+ fn parse_attrs(
+ attrs: impl AsRef<[syn::Attribute]>,
+ fields: &syn::Fields,
+ ) -> syn::Result<Option<Self>> {
+ fn infer<T>(v: T) -> T
+ where
+ T: for<'a> FnOnce(ParseStream<'a>) -> syn::Result<StructAttribute>,
+ {
+ v
+ }
+
+ attrs
+ .as_ref()
+ .iter()
+ .filter(|attr| attr.path().is_ident("into"))
+ .try_fold(None, |mut attrs, attr| {
+ let merge = |out: &mut Option<_>, tys| match (out.as_mut(), tys) {
+ (None, Some(tys)) => {
+ *out = Some::<Punctuated<_, _>>(tys);
+ }
+ (Some(out), Some(tys)) => out.extend(tys),
+ (Some(_), None) | (None, None) => {}
+ };
+
+ let field_attr =
+ attr.parse_args_with(infer(|stream| Self::parse(stream, fields)))?;
+ let out = attrs.get_or_insert_with(Self::default);
+ merge(&mut out.owned, field_attr.owned);
+ merge(&mut out.r#ref, field_attr.r#ref);
+ merge(&mut out.ref_mut, field_attr.ref_mut);
+
+ Ok(attrs)
+ })
+ }
+
+ /// Parses a single [`StructAttribute`].
+ fn parse(content: ParseStream<'_>, fields: &syn::Fields) -> syn::Result<Self> {
+ check_legacy_syntax(content, fields)?;
+
+ let mut out = Self::default();
+
+ let parse_inner = |ahead, types: &mut Option<_>| {
+ content.advance_to(&ahead);
+
+ let types = types.get_or_insert_with(Punctuated::new);
+ if content.peek(token::Paren) {
+ let inner;
+ syn::parenthesized!(inner in content);
+
+ types.extend(
+ inner
+ .parse_terminated(Type::parse, token::Comma)?
+ .into_pairs(),
+ );
+ }
+ if content.peek(token::Comma) {
+ let comma = content.parse::<token::Comma>()?;
+ if !types.empty_or_trailing() {
+ types.push_punct(comma);
+ }
+ }
+
+ Ok(())
+ };
+
+ let mut has_wrapped_type = false;
+ let mut top_level_type = None;
+
+ while !content.is_empty() {
+ let ahead = content.fork();
+ let res = if ahead.peek(Ident::peek_any) {
+ ahead.call(Ident::parse_any).map(Into::into)
+ } else {
+ ahead.parse::<syn::Path>()
+ };
+ match res {
+ Ok(p) if p.is_ident("owned") => {
+ has_wrapped_type = true;
+ parse_inner(ahead, &mut out.owned)?;
+ }
+ Ok(p) if p.is_ident("ref") => {
+ has_wrapped_type = true;
+ parse_inner(ahead, &mut out.r#ref)?;
+ }
+ Ok(p) if p.is_ident("ref_mut") => {
+ has_wrapped_type = true;
+ parse_inner(ahead, &mut out.ref_mut)?;
+ }
+ _ => {
+ let ty = content.parse::<Type>()?;
+ let _ = top_level_type.get_or_insert_with(|| ty.clone());
+ out.owned.get_or_insert_with(Punctuated::new).push_value(ty);
+
+ if content.peek(token::Comma) {
+ out.owned
+ .get_or_insert_with(Punctuated::new)
+ .push_punct(content.parse::<token::Comma>()?)
+ }
+ }
+ }
+ }
+
+ if let Some(ty) = top_level_type.filter(|_| has_wrapped_type) {
+ Err(syn::Error::new(
+ ty.span(),
+ format!(
+ "mixing regular types with wrapped into \
+ `owned`/`ref`/`ref_mut` is not allowed, try wrapping \
+ this type into `owned({ty}), ref({ty}), ref_mut({ty})`",
+ ty = ty.into_token_stream(),
+ ),
+ ))
+ } else {
+ Ok(out)
+ }
+ }
+}
+
+/// `#[into(skip)]` field attribute.
+struct SkipFieldAttribute;
+
+impl SkipFieldAttribute {
+ /// Parses a [`SkipFieldAttribute`] from the provided [`syn::Attribute`]s.
+ fn parse_attrs(attrs: impl AsRef<[syn::Attribute]>) -> syn::Result<Option<Self>> {
+ Ok(attrs
+ .as_ref()
+ .iter()
+ .filter(|attr| attr.path().is_ident("into"))
+ .try_fold(None, |mut attrs, attr| {
+ let field_attr = attr.parse_args::<SkipFieldAttribute>()?;
+ if let Some((path, _)) = attrs.replace((attr.path(), field_attr)) {
+ Err(syn::Error::new(
+ path.span(),
+ "only single `#[into(...)]` attribute is allowed here",
+ ))
+ } else {
+ Ok(attrs)
+ }
+ })?
+ .map(|(_, attr)| attr))
+ }
+}
+
+impl Parse for SkipFieldAttribute {
+ fn parse(content: ParseStream) -> syn::Result<Self> {
+ match content.parse::<syn::Path>()? {
+ p if p.is_ident("skip") | p.is_ident("ignore") => Ok(Self),
+ p => Err(syn::Error::new(
+ p.span(),
+ format!("expected `skip`, found: `{}`", p.into_token_stream()),
+ )),
+ }
+ }
+}
+
+/// [`Error`]ors for legacy syntax: `#[into(types(i32, "&str"))]`.
+fn check_legacy_syntax(
+ tokens: ParseStream<'_>,
+ fields: &syn::Fields,
+) -> syn::Result<()> {
+ let span = tokens.span();
+ let tokens = tokens.fork();
+
+ let map_ty = |s: String| {
+ if fields.len() > 1 {
+ format!(
+ "({})",
+ (0..fields.len())
+ .map(|_| s.as_str())
+ .collect::<Vec<_>>()
+ .join(", ")
+ )
+ } else {
+ s
+ }
+ };
+ let field = match fields.len() {
+ 0 => None,
+ 1 => Some(
+ fields
+ .iter()
+ .next()
+ .unwrap_or_else(|| unreachable!("fields.len() == 1"))
+ .ty
+ .to_token_stream()
+ .to_string(),
+ ),
+ _ => Some(format!(
+ "({})",
+ fields
+ .iter()
+ .map(|f| f.ty.to_token_stream().to_string())
+ .collect::<Vec<_>>()
+ .join(", ")
+ )),
+ };
+
+ let Ok(metas) = tokens.parse_terminated(polyfill::Meta::parse, token::Comma) else {
+ return Ok(());
+ };
+
+ let parse_list = |list: polyfill::MetaList, attrs: &mut Option<Vec<_>>| {
+ if !list.path.is_ident("types") {
+ return None;
+ }
+ for meta in list
+ .parse_args_with(Punctuated::<_, token::Comma>::parse_terminated)
+ .ok()?
+ {
+ attrs.get_or_insert_with(Vec::new).push(match meta {
+ polyfill::NestedMeta::Lit(syn::Lit::Str(str)) => str.value(),
+ polyfill::NestedMeta::Meta(polyfill::Meta::Path(path)) => {
+ path.into_token_stream().to_string()
+ }
+ _ => return None,
+ })
+ }
+ Some(())
+ };
+
+ let Some((top_level, owned, ref_, ref_mut)) = metas
+ .into_iter()
+ .try_fold(
+ (None, None, None, None),
+ |(mut top_level, mut owned, mut ref_, mut ref_mut), meta| {
+ let is = |name| {
+ matches!(&meta, polyfill::Meta::Path(p) if p.is_ident(name))
+ || matches!(&meta, polyfill::Meta::List(list) if list.path.is_ident(name))
+ };
+ let parse_inner = |meta, attrs: &mut Option<_>| {
+ match meta {
+ polyfill::Meta::Path(_) => {
+ let _ = attrs.get_or_insert_with(Vec::new);
+ Some(())
+ }
+ polyfill::Meta::List(list) => {
+ if let polyfill::NestedMeta::Meta(polyfill::Meta::List(list)) = list
+ .parse_args_with(Punctuated::<_, token::Comma>::parse_terminated)
+ .ok()?
+ .pop()?
+ .into_value()
+ {
+ parse_list(list, attrs)
+ } else {
+ None
+ }
+ }
+ }
+ };
+
+ match meta {
+ meta if is("owned") => parse_inner(meta, &mut owned),
+ meta if is("ref") => parse_inner(meta, &mut ref_),
+ meta if is("ref_mut") => parse_inner(meta, &mut ref_mut),
+ polyfill::Meta::List(list) => parse_list(list, &mut top_level),
+ _ => None,
+ }
+ .map(|_| (top_level, owned, ref_, ref_mut))
+ },
+ )
+ .filter(|(top_level, owned, ref_, ref_mut)| {
+ [top_level, owned, ref_, ref_mut]
+ .into_iter()
+ .any(|l| l.as_ref().map_or(false, |l| !l.is_empty()))
+ })
+ else {
+ return Ok(());
+ };
+
+ if [&owned, &ref_, &ref_mut].into_iter().any(Option::is_some) {
+ let format = |list: Option<Vec<_>>, name: &str| match list {
+ Some(l)
+ if top_level.as_ref().map_or(true, Vec::is_empty) && l.is_empty() =>
+ {
+ Some(name.to_owned())
+ }
+ Some(l) => Some(format!(
+ "{}({})",
+ name,
+ l.into_iter()
+ .chain(top_level.clone().into_iter().flatten())
+ .map(map_ty)
+ .chain(field.clone())
+ .collect::<Vec<_>>()
+ .join(", "),
+ )),
+ None => None,
+ };
+ let format = [
+ format(owned, "owned"),
+ format(ref_, "ref"),
+ format(ref_mut, "ref_mut"),
+ ]
+ .into_iter()
+ .flatten()
+ .collect::<Vec<_>>()
+ .join(", ");
+
+ Err(syn::Error::new(
+ span,
+ format!("legacy syntax, use `{format}` instead"),
+ ))
+ } else {
+ Err(syn::Error::new(
+ span,
+ format!(
+ "legacy syntax, remove `types` and use `{}` instead",
+ top_level.unwrap_or_else(|| unreachable!()).join(", "),
+ ),
+ ))
+ }
+}
diff --git a/third_party/rust/derive_more-impl/src/into_iterator.rs b/third_party/rust/derive_more-impl/src/into_iterator.rs
new file mode 100644
index 0000000000..f10dbf7a0b
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/into_iterator.rs
@@ -0,0 +1,59 @@
+use crate::utils::{
+ add_extra_generic_param, add_extra_ty_param_bound_ref, SingleFieldData, State,
+};
+use proc_macro2::TokenStream;
+use quote::{quote, ToTokens};
+use syn::{parse::Result, DeriveInput};
+
+/// Provides the hook to expand `#[derive(IntoIterator)]` into an implementation of `IntoIterator`
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let state =
+ State::with_field_ignore_and_refs(input, trait_name, "into_iterator".into())?;
+ let SingleFieldData {
+ input_type,
+ info,
+ field_type,
+ member,
+ trait_path,
+ ..
+ } = state.assert_single_enabled_field();
+
+ let mut tokens = TokenStream::new();
+
+ for ref_type in info.ref_types() {
+ let reference = ref_type.reference();
+ let lifetime = ref_type.lifetime();
+ let reference_with_lifetime = ref_type.reference_with_lifetime();
+
+ let generics_impl;
+ let generics =
+ add_extra_ty_param_bound_ref(&input.generics, trait_path, ref_type);
+ let (_, ty_generics, where_clause) = generics.split_for_impl();
+ let (impl_generics, _, _) = if ref_type.is_ref() {
+ generics_impl = add_extra_generic_param(&generics, lifetime.clone());
+ generics_impl.split_for_impl()
+ } else {
+ generics.split_for_impl()
+ };
+ // let generics = add_extra_ty_param_bound(&input.generics, trait_path);
+ let casted_trait = &quote! {
+ <#reference_with_lifetime #field_type as #trait_path>
+ };
+ let into_iterator = quote! {
+ #[automatically_derived]
+ impl #impl_generics #trait_path for #reference_with_lifetime #input_type #ty_generics
+ #where_clause
+ {
+ type Item = #casted_trait::Item;
+ type IntoIter = #casted_trait::IntoIter;
+
+ #[inline]
+ fn into_iter(self) -> Self::IntoIter {
+ #casted_trait::into_iter(#reference #member)
+ }
+ }
+ };
+ into_iterator.to_tokens(&mut tokens);
+ }
+ Ok(tokens)
+}
diff --git a/third_party/rust/derive_more-impl/src/is_variant.rs b/third_party/rust/derive_more-impl/src/is_variant.rs
new file mode 100644
index 0000000000..123e3fb7bb
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/is_variant.rs
@@ -0,0 +1,65 @@
+use crate::utils::{AttrParams, DeriveType, State};
+use convert_case::{Case, Casing};
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote};
+use syn::{DeriveInput, Fields, Result};
+
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let state = State::with_attr_params(
+ input,
+ trait_name,
+ "is_variant".into(),
+ AttrParams {
+ enum_: vec!["ignore"],
+ variant: vec!["ignore"],
+ struct_: vec!["ignore"],
+ field: vec!["ignore"],
+ },
+ )?;
+ assert!(
+ state.derive_type == DeriveType::Enum,
+ "IsVariant can only be derived for enums",
+ );
+
+ let enum_name = &input.ident;
+ let (imp_generics, type_generics, where_clause) = input.generics.split_for_impl();
+
+ let mut funcs = vec![];
+ for variant_state in state.enabled_variant_data().variant_states {
+ let variant = variant_state.variant.unwrap();
+ let fn_name = format_ident!(
+ "is_{}",
+ variant.ident.to_string().to_case(Case::Snake),
+ span = variant.ident.span(),
+ );
+ let variant_ident = &variant.ident;
+
+ let data_pattern = match variant.fields {
+ Fields::Named(_) => quote! { {..} },
+ Fields::Unnamed(_) => quote! { (..) },
+ Fields::Unit => quote! {},
+ };
+ let variant_name = stringify!(variant_ident);
+ let func = quote! {
+ #[doc = "Returns `true` if this value is of type `"]
+ #[doc = #variant_name]
+ #[doc = "`. Returns `false` otherwise"]
+ pub const fn #fn_name(&self) -> bool {
+ match self {
+ #enum_name ::#variant_ident #data_pattern => true,
+ _ => false
+ }
+ }
+ };
+ funcs.push(func);
+ }
+
+ let imp = quote! {
+ #[automatically_derived]
+ impl #imp_generics #enum_name #type_generics #where_clause {
+ #(#funcs)*
+ }
+ };
+
+ Ok(imp)
+}
diff --git a/third_party/rust/derive_more-impl/src/lib.rs b/third_party/rust/derive_more-impl/src/lib.rs
new file mode 100644
index 0000000000..8cb86b1f1a
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/lib.rs
@@ -0,0 +1,281 @@
+#![doc = include_str!("../README.md")]
+#![cfg_attr(docsrs, feature(doc_auto_cfg))]
+#![recursion_limit = "128"]
+#![cfg_attr(any(not(docsrs), ci), deny(rustdoc::all))]
+#![forbid(non_ascii_idents, unsafe_code)]
+#![warn(clippy::nonstandard_macro_braces)]
+
+use proc_macro::TokenStream;
+use syn::parse::Error as ParseError;
+
+mod utils;
+
+#[cfg(any(feature = "add_assign", feature = "mul_assign"))]
+mod add_assign_like;
+#[cfg(any(
+ feature = "add",
+ feature = "add_assign",
+ feature = "mul",
+ feature = "mul_assign",
+))]
+mod add_helpers;
+#[cfg(any(feature = "add", feature = "mul"))]
+mod add_like;
+#[cfg(feature = "as_mut")]
+mod as_mut;
+#[cfg(feature = "as_ref")]
+mod as_ref;
+#[cfg(feature = "constructor")]
+mod constructor;
+#[cfg(feature = "deref")]
+mod deref;
+#[cfg(feature = "deref_mut")]
+mod deref_mut;
+#[cfg(feature = "error")]
+mod error;
+#[cfg(any(feature = "debug", feature = "display"))]
+mod fmt;
+#[cfg(feature = "from")]
+mod from;
+#[cfg(feature = "from_str")]
+mod from_str;
+#[cfg(feature = "index")]
+mod index;
+#[cfg(feature = "index_mut")]
+mod index_mut;
+#[cfg(feature = "into")]
+mod into;
+#[cfg(feature = "into_iterator")]
+mod into_iterator;
+#[cfg(feature = "is_variant")]
+mod is_variant;
+#[cfg(feature = "mul_assign")]
+mod mul_assign_like;
+#[cfg(any(feature = "mul", feature = "mul_assign"))]
+mod mul_helpers;
+#[cfg(feature = "mul")]
+mod mul_like;
+#[cfg(feature = "not")]
+mod not_like;
+#[cfg(any(
+ feature = "debug",
+ feature = "display",
+ feature = "from",
+ feature = "into",
+))]
+pub(crate) mod parsing;
+#[cfg(feature = "sum")]
+mod sum_like;
+#[cfg(feature = "try_into")]
+mod try_into;
+#[cfg(feature = "try_unwrap")]
+mod try_unwrap;
+#[cfg(feature = "unwrap")]
+mod unwrap;
+
+// This trait describes the possible return types of
+// the derives. A derive can generally be infallible and
+// return a TokenStream, or it can be fallible and return
+// a Result<TokenStream, syn::parse::Error>.
+trait Output {
+ fn process(self) -> TokenStream;
+}
+
+impl Output for proc_macro2::TokenStream {
+ fn process(self) -> TokenStream {
+ self.into()
+ }
+}
+
+impl Output for Result<proc_macro2::TokenStream, ParseError> {
+ fn process(self) -> TokenStream {
+ match self {
+ Ok(ts) => ts.into(),
+ Err(e) => e.to_compile_error().into(),
+ }
+ }
+}
+
+macro_rules! create_derive(
+ ($feature:literal, $mod_:ident $(:: $mod_rest:ident)*, $trait_:ident, $fn_name: ident $(,$attribute:ident)* $(,)?) => {
+ #[cfg(feature = $feature)]
+ #[proc_macro_derive($trait_, attributes($($attribute),*))]
+ #[doc = include_str!(concat!("../doc/", $feature, ".md"))]
+ pub fn $fn_name(input: TokenStream) -> TokenStream {
+ let ast = syn::parse(input).unwrap();
+ Output::process($mod_$(:: $mod_rest)*::expand(&ast, stringify!($trait_)))
+ }
+ }
+);
+
+create_derive!("add", add_like, Add, add_derive);
+create_derive!("add", add_like, Sub, sub_derive);
+create_derive!("add", add_like, BitAnd, bit_and_derive);
+create_derive!("add", add_like, BitOr, bit_or_derive);
+create_derive!("add", add_like, BitXor, bit_xor_derive);
+
+create_derive!("add_assign", add_assign_like, AddAssign, add_assign_derive,);
+create_derive!("add_assign", add_assign_like, SubAssign, sub_assign_derive,);
+create_derive!(
+ "add_assign",
+ add_assign_like,
+ BitAndAssign,
+ bit_and_assign_derive,
+);
+create_derive!(
+ "add_assign",
+ add_assign_like,
+ BitOrAssign,
+ bit_or_assign_derive,
+);
+create_derive!(
+ "add_assign",
+ add_assign_like,
+ BitXorAssign,
+ bit_xor_assign_derive,
+);
+
+create_derive!("as_mut", as_mut, AsMut, as_mut_derive, as_mut);
+
+create_derive!("as_ref", as_ref, AsRef, as_ref_derive, as_ref);
+
+create_derive!("constructor", constructor, Constructor, constructor_derive);
+
+create_derive!("debug", fmt::debug, Debug, debug_derive, debug);
+
+create_derive!("deref", deref, Deref, deref_derive, deref);
+
+create_derive!(
+ "deref_mut",
+ deref_mut,
+ DerefMut,
+ deref_mut_derive,
+ deref_mut,
+);
+
+create_derive!("display", fmt::display, Display, display_derive, display);
+create_derive!("display", fmt::display, Binary, binary_derive, binary);
+create_derive!("display", fmt::display, Octal, octal_derive, octal);
+create_derive!(
+ "display",
+ fmt::display,
+ LowerHex,
+ lower_hex_derive,
+ lower_hex,
+);
+create_derive!(
+ "display",
+ fmt::display,
+ UpperHex,
+ upper_hex_derive,
+ upper_hex,
+);
+create_derive!(
+ "display",
+ fmt::display,
+ LowerExp,
+ lower_exp_derive,
+ lower_exp,
+);
+create_derive!(
+ "display",
+ fmt::display,
+ UpperExp,
+ upper_exp_derive,
+ upper_exp,
+);
+create_derive!("display", fmt::display, Pointer, pointer_derive, pointer);
+
+create_derive!("error", error, Error, error_derive, error);
+
+create_derive!("from", from, From, from_derive, from);
+
+create_derive!("from_str", from_str, FromStr, from_str_derive);
+
+create_derive!("index", index, Index, index_derive, index);
+
+create_derive!(
+ "index_mut",
+ index_mut,
+ IndexMut,
+ index_mut_derive,
+ index_mut,
+);
+
+create_derive!("into", into, Into, into_derive, into);
+
+create_derive!(
+ "into_iterator",
+ into_iterator,
+ IntoIterator,
+ into_iterator_derive,
+ into_iterator,
+);
+
+create_derive!(
+ "is_variant",
+ is_variant,
+ IsVariant,
+ is_variant_derive,
+ is_variant,
+);
+
+create_derive!("mul", mul_like, Mul, mul_derive, mul);
+create_derive!("mul", mul_like, Div, div_derive, div);
+create_derive!("mul", mul_like, Rem, rem_derive, rem);
+create_derive!("mul", mul_like, Shr, shr_derive, shr);
+create_derive!("mul", mul_like, Shl, shl_derive, shl);
+
+create_derive!(
+ "mul_assign",
+ mul_assign_like,
+ MulAssign,
+ mul_assign_derive,
+ mul_assign,
+);
+create_derive!(
+ "mul_assign",
+ mul_assign_like,
+ DivAssign,
+ div_assign_derive,
+ div_assign,
+);
+create_derive!(
+ "mul_assign",
+ mul_assign_like,
+ RemAssign,
+ rem_assign_derive,
+ rem_assign,
+);
+create_derive!(
+ "mul_assign",
+ mul_assign_like,
+ ShrAssign,
+ shr_assign_derive,
+ shr_assign,
+);
+create_derive!(
+ "mul_assign",
+ mul_assign_like,
+ ShlAssign,
+ shl_assign_derive,
+ shl_assign,
+);
+
+create_derive!("not", not_like, Not, not_derive);
+create_derive!("not", not_like, Neg, neg_derive);
+
+create_derive!("sum", sum_like, Sum, sum_derive);
+create_derive!("sum", sum_like, Product, product_derive);
+
+create_derive!("try_into", try_into, TryInto, try_into_derive, try_into);
+
+create_derive!(
+ "try_unwrap",
+ try_unwrap,
+ TryUnwrap,
+ try_unwrap_derive,
+ try_unwrap,
+);
+
+create_derive!("unwrap", unwrap, Unwrap, unwrap_derive, unwrap);
diff --git a/third_party/rust/derive_more-impl/src/mul_assign_like.rs b/third_party/rust/derive_more-impl/src/mul_assign_like.rs
new file mode 100644
index 0000000000..8e3f2cb760
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/mul_assign_like.rs
@@ -0,0 +1,63 @@
+use crate::add_assign_like;
+use crate::mul_helpers::generics_and_exprs;
+use crate::utils::{AttrParams, HashSet, MultiFieldData, RefType, State};
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote};
+use std::iter;
+use syn::{DeriveInput, Result};
+
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let method_name = trait_name
+ .to_lowercase()
+ .trim_end_matches("assign")
+ .to_string()
+ + "_assign";
+
+ let mut state = State::with_attr_params(
+ input,
+ trait_name,
+ method_name,
+ AttrParams::struct_(vec!["forward"]),
+ )?;
+ if state.default_info.forward {
+ return Ok(add_assign_like::expand(input, trait_name));
+ }
+ let scalar_ident = format_ident!("__RhsT");
+ state.add_trait_path_type_param(quote! { #scalar_ident });
+ let multi_field_data = state.enabled_fields_data();
+ let MultiFieldData {
+ input_type,
+ field_types,
+ ty_generics,
+ trait_path,
+ trait_path_with_params,
+ method_ident,
+ ..
+ } = multi_field_data.clone();
+
+ let tys = field_types.iter().collect::<HashSet<_>>();
+ let tys = tys.iter();
+ let trait_path_iter = iter::repeat(trait_path_with_params);
+
+ let type_where_clauses = quote! {
+ where #(#tys: #trait_path_iter),*
+ };
+
+ let (generics, exprs) = generics_and_exprs(
+ multi_field_data.clone(),
+ &scalar_ident,
+ type_where_clauses,
+ RefType::Mut,
+ );
+ let (impl_generics, _, where_clause) = generics.split_for_impl();
+
+ Ok(quote! {
+ #[automatically_derived]
+ impl #impl_generics #trait_path<#scalar_ident> for #input_type #ty_generics #where_clause {
+ #[inline]
+ fn #method_ident(&mut self, rhs: #scalar_ident) {
+ #( #exprs; )*
+ }
+ }
+ })
+}
diff --git a/third_party/rust/derive_more-impl/src/mul_helpers.rs b/third_party/rust/derive_more-impl/src/mul_helpers.rs
new file mode 100644
index 0000000000..dbc1c6257c
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/mul_helpers.rs
@@ -0,0 +1,36 @@
+use crate::utils::{add_where_clauses_for_new_ident, MultiFieldData, RefType};
+use proc_macro2::TokenStream;
+use quote::quote;
+use syn::{Generics, Ident};
+
+pub fn generics_and_exprs(
+ multi_field_data: MultiFieldData,
+ scalar_ident: &Ident,
+ type_where_clauses: TokenStream,
+ ref_type: RefType,
+) -> (Generics, Vec<TokenStream>) {
+ let MultiFieldData {
+ fields,
+ casted_traits,
+ members,
+ method_ident,
+ ..
+ } = multi_field_data;
+ let reference = ref_type.reference();
+ let exprs: Vec<_> = casted_traits
+ .iter()
+ .zip(members)
+ .map(|(casted_trait, member)| {
+ quote! { #casted_trait::#method_ident(#reference #member, rhs) }
+ })
+ .collect();
+
+ let new_generics = add_where_clauses_for_new_ident(
+ &multi_field_data.state.input.generics,
+ &fields,
+ scalar_ident,
+ type_where_clauses,
+ true,
+ );
+ (new_generics, exprs)
+}
diff --git a/third_party/rust/derive_more-impl/src/mul_like.rs b/third_party/rust/derive_more-impl/src/mul_like.rs
new file mode 100644
index 0000000000..d06372f38a
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/mul_like.rs
@@ -0,0 +1,61 @@
+use crate::add_like;
+use crate::mul_helpers::generics_and_exprs;
+use crate::utils::{AttrParams, HashSet, MultiFieldData, RefType, State};
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote};
+use std::iter;
+use syn::{DeriveInput, Result};
+
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let mut state = State::with_attr_params(
+ input,
+ trait_name,
+ trait_name.to_lowercase(),
+ AttrParams::struct_(vec!["forward"]),
+ )?;
+ if state.default_info.forward {
+ return Ok(add_like::expand(input, trait_name));
+ }
+
+ let scalar_ident = format_ident!("__RhsT");
+ state.add_trait_path_type_param(quote! { #scalar_ident });
+ let multi_field_data = state.enabled_fields_data();
+ let MultiFieldData {
+ input_type,
+ field_types,
+ ty_generics,
+ trait_path,
+ trait_path_with_params,
+ method_ident,
+ ..
+ } = multi_field_data.clone();
+
+ let tys = field_types.iter().collect::<HashSet<_>>();
+ let tys = tys.iter();
+ let scalar_iter = iter::repeat(&scalar_ident);
+ let trait_path_iter = iter::repeat(trait_path);
+
+ let type_where_clauses = quote! {
+ where #(#tys: #trait_path_iter<#scalar_iter, Output=#tys>),*
+ };
+
+ let (generics, initializers) = generics_and_exprs(
+ multi_field_data.clone(),
+ &scalar_ident,
+ type_where_clauses,
+ RefType::No,
+ );
+ let body = multi_field_data.initializer(&initializers);
+ let (impl_generics, _, where_clause) = generics.split_for_impl();
+ Ok(quote! {
+ #[automatically_derived]
+ impl #impl_generics #trait_path_with_params for #input_type #ty_generics #where_clause {
+ type Output = #input_type #ty_generics;
+
+ #[inline]
+ fn #method_ident(self, rhs: #scalar_ident) -> #input_type #ty_generics {
+ #body
+ }
+ }
+ })
+}
diff --git a/third_party/rust/derive_more-impl/src/not_like.rs b/third_party/rust/derive_more-impl/src/not_like.rs
new file mode 100644
index 0000000000..6bab7c8ec0
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/not_like.rs
@@ -0,0 +1,171 @@
+use crate::utils::{
+ add_extra_type_param_bound_op_output, named_to_vec, unnamed_to_vec,
+};
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote, ToTokens};
+use std::iter;
+use syn::{Data, DataEnum, DeriveInput, Field, Fields, Ident, Index};
+
+pub fn expand(input: &DeriveInput, trait_name: &str) -> TokenStream {
+ let trait_ident = format_ident!("{trait_name}");
+ let method_name = trait_name.to_lowercase();
+ let method_ident = format_ident!("{method_name}");
+ let input_type = &input.ident;
+
+ let generics = add_extra_type_param_bound_op_output(&input.generics, &trait_ident);
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ let (output_type, block) = match input.data {
+ Data::Struct(ref data_struct) => match data_struct.fields {
+ Fields::Unnamed(ref fields) => (
+ quote! { #input_type #ty_generics },
+ tuple_content(input_type, &unnamed_to_vec(fields), &method_ident),
+ ),
+ Fields::Named(ref fields) => (
+ quote! { #input_type #ty_generics },
+ struct_content(input_type, &named_to_vec(fields), &method_ident),
+ ),
+ _ => panic!("Unit structs cannot use derive({trait_name})"),
+ },
+ Data::Enum(ref data_enum) => {
+ enum_output_type_and_content(input, data_enum, &method_ident)
+ }
+
+ _ => panic!("Only structs and enums can use derive({trait_name})"),
+ };
+
+ quote! {
+ #[automatically_derived]
+ impl #impl_generics ::core::ops::#trait_ident for #input_type #ty_generics #where_clause {
+ type Output = #output_type;
+
+ #[inline]
+ fn #method_ident(self) -> #output_type {
+ #block
+ }
+ }
+ }
+}
+
+fn tuple_content<T: ToTokens>(
+ input_type: &T,
+ fields: &[&Field],
+ method_ident: &Ident,
+) -> TokenStream {
+ let mut exprs = vec![];
+
+ for i in 0..fields.len() {
+ let i = Index::from(i);
+ // generates `self.0.add()`
+ let expr = quote! { self.#i.#method_ident() };
+ exprs.push(expr);
+ }
+
+ quote! { #input_type(#(#exprs),*) }
+}
+
+fn struct_content(
+ input_type: &Ident,
+ fields: &[&Field],
+ method_ident: &Ident,
+) -> TokenStream {
+ let mut exprs = vec![];
+
+ for field in fields {
+ // It's safe to unwrap because struct fields always have an identifier
+ let field_id = field.ident.as_ref();
+ // generates `x: self.x.not()`
+ let expr = quote! { #field_id: self.#field_id.#method_ident() };
+ exprs.push(expr)
+ }
+
+ quote! { #input_type{#(#exprs),*} }
+}
+
+fn enum_output_type_and_content(
+ input: &DeriveInput,
+ data_enum: &DataEnum,
+ method_ident: &Ident,
+) -> (TokenStream, TokenStream) {
+ let input_type = &input.ident;
+ let (_, ty_generics, _) = input.generics.split_for_impl();
+ let mut matches = vec![];
+ let mut method_iter = iter::repeat(method_ident);
+ // If the enum contains unit types that means it can error.
+ let has_unit_type = data_enum.variants.iter().any(|v| v.fields == Fields::Unit);
+
+ for variant in &data_enum.variants {
+ let subtype = &variant.ident;
+ let subtype = quote! { #input_type::#subtype };
+
+ match variant.fields {
+ Fields::Unnamed(ref fields) => {
+ // The pattern that is outputted should look like this:
+ // (Subtype(vars)) => Ok(TypePath(exprs))
+ let size = unnamed_to_vec(fields).len();
+ let vars: &Vec<_> =
+ &(0..size).map(|i| format_ident!("__{i}")).collect();
+ let method_iter = method_iter.by_ref();
+ let mut body = quote! { #subtype(#(#vars.#method_iter()),*) };
+ if has_unit_type {
+ body = quote! { ::core::result::Result::Ok(#body) }
+ }
+ let matcher = quote! {
+ #subtype(#(#vars),*) => {
+ #body
+ }
+ };
+ matches.push(matcher);
+ }
+ Fields::Named(ref fields) => {
+ // The pattern that is outputted should look like this:
+ // (Subtype{a: __l_a, ...} => {
+ // Ok(Subtype{a: __l_a.neg(__r_a), ...})
+ // }
+ let field_vec = named_to_vec(fields);
+ let size = field_vec.len();
+ let field_names: &Vec<_> = &field_vec
+ .iter()
+ .map(|f| f.ident.as_ref().unwrap())
+ .collect();
+ let vars: &Vec<_> =
+ &(0..size).map(|i| format_ident!("__{i}")).collect();
+ let method_iter = method_iter.by_ref();
+ let mut body = quote! {
+ #subtype{#(#field_names: #vars.#method_iter()),*}
+ };
+ if has_unit_type {
+ body = quote! { ::core::result::Result::Ok(#body) }
+ }
+ let matcher = quote! {
+ #subtype{#(#field_names: #vars),*} => {
+ #body
+ }
+ };
+ matches.push(matcher);
+ }
+ Fields::Unit => {
+ let operation_name = method_ident.to_string();
+ matches.push(quote! {
+ #subtype => ::core::result::Result::Err(
+ ::derive_more::ops::UnitError::new(#operation_name)
+ )
+ });
+ }
+ }
+ }
+
+ let body = quote! {
+ match self {
+ #(#matches),*
+ }
+ };
+
+ let output_type = if has_unit_type {
+ quote! { ::core::result::Result<#input_type #ty_generics, ::derive_more::ops::UnitError> }
+ } else {
+ quote! { #input_type #ty_generics }
+ };
+
+ (output_type, body)
+}
diff --git a/third_party/rust/derive_more-impl/src/parsing.rs b/third_party/rust/derive_more-impl/src/parsing.rs
new file mode 100644
index 0000000000..42b66376f5
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/parsing.rs
@@ -0,0 +1,469 @@
+//! Common parsing utilities for derive macros.
+//!
+//! Fair parsing of [`syn::Type`] and [`syn::Expr`] requires [`syn`]'s `full`
+//! feature to be enabled, which unnecessary increases compile times. As we
+//! don't have complex AST manipulation, usually requiring only understanding
+//! where syntax item begins and ends, simpler manual parsing is implemented.
+
+use proc_macro2::{Delimiter, Spacing, TokenStream};
+use quote::ToTokens;
+use syn::{
+ buffer::Cursor,
+ parse::{Parse, ParseStream},
+ punctuated::Punctuated,
+ spanned::Spanned as _,
+ token, Error, Ident, Result,
+};
+
+/// [`syn::Type`] [`Parse`]ing polyfill.
+#[derive(Clone, Debug)]
+pub(crate) enum Type {
+ /// [`syn::Type::Tuple`] [`Parse`]ing polyfill.
+ Tuple {
+ paren: token::Paren,
+ items: Punctuated<TokenStream, token::Comma>,
+ },
+
+ /// Every other [`syn::Type`] variant.
+ Other(TokenStream),
+}
+
+impl Type {
+ /// Creates a [`Type::Tuple`] from the provided [`Iterator`] of [`TokenStream`]s.
+ pub(crate) fn tuple<T: ToTokens>(items: impl IntoIterator<Item = T>) -> Self {
+ Self::Tuple {
+ paren: token::Paren::default(),
+ items: items.into_iter().map(ToTokens::into_token_stream).collect(),
+ }
+ }
+}
+
+impl Parse for Type {
+ fn parse(input: ParseStream) -> Result<Self> {
+ input.step(|c| {
+ let outer = *c;
+
+ if let Some((mut cursor, paren_span, next_item)) =
+ outer.group(Delimiter::Parenthesis)
+ {
+ let mut items = Punctuated::new();
+ while !cursor.eof() {
+ let (stream, c) = Self::parse_other(cursor).ok_or_else(|| {
+ Error::new(cursor.span(), "failed to parse type")
+ })?;
+ items.push_value(stream);
+ cursor = c;
+ if let Some((p, c)) = punct(',')(cursor) {
+ items.push_punct(token::Comma(p.span()));
+ cursor = c;
+ }
+ }
+ // `(Type)` is equivalent to `Type`, so isn't top-level tuple.
+ if items.len() == 1 && !items.trailing_punct() {
+ let stream = outer
+ .token_tree()
+ .unwrap_or_else(|| unreachable!())
+ .0
+ .into_token_stream();
+ Ok((Type::Other(stream), next_item))
+ } else {
+ Ok((
+ Type::Tuple {
+ paren: token::Paren(paren_span),
+ items,
+ },
+ next_item,
+ ))
+ }
+ } else {
+ Self::parse_other(outer)
+ .map(|(s, c)| (Self::Other(s), c))
+ .ok_or_else(|| Error::new(outer.span(), "failed to parse type"))
+ }
+ })
+ }
+}
+
+impl ToTokens for Type {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ match self {
+ Type::Tuple { paren, items } => {
+ paren.surround(tokens, |tokens| items.to_tokens(tokens))
+ }
+ Type::Other(other) => other.to_tokens(tokens),
+ }
+ }
+}
+
+impl Type {
+ /// Parses a single [`Type::Other`].
+ pub fn parse_other(c: Cursor<'_>) -> Option<(TokenStream, Cursor<'_>)> {
+ take_until1(
+ alt([&mut balanced_pair(punct('<'), punct('>')), &mut token_tree]),
+ punct(','),
+ )(c)
+ }
+}
+
+/// [`syn::Expr`] [`Parse`]ing polyfill.
+#[derive(Debug)]
+pub(crate) enum Expr {
+ /// [`syn::Expr::Path`] of length 1 [`Parse`]ing polyfill.
+ Ident(Ident),
+
+ /// Every other [`syn::Expr`] variant.
+ Other(TokenStream),
+}
+
+impl Expr {
+ /// Returns an [`Ident`] in case this [`Expr`] is represented only by it.
+ pub(crate) fn ident(&self) -> Option<&Ident> {
+ match self {
+ Self::Ident(ident) => Some(ident),
+ Self::Other(_) => None,
+ }
+ }
+}
+
+impl Parse for Expr {
+ fn parse(input: ParseStream) -> Result<Self> {
+ if let Ok(ident) = input.step(|c| {
+ c.ident()
+ .filter(|(_, c)| c.eof() || punct(',')(*c).is_some())
+ .ok_or_else(|| Error::new(c.span(), "expected `ident(,|eof)`"))
+ }) {
+ Ok(Self::Ident(ident))
+ } else {
+ input.step(|c| {
+ take_until1(
+ alt([
+ &mut seq([
+ &mut colon2,
+ &mut balanced_pair(punct('<'), punct('>')),
+ ]),
+ &mut seq([
+ &mut balanced_pair(punct('<'), punct('>')),
+ &mut colon2,
+ ]),
+ &mut balanced_pair(punct('|'), punct('|')),
+ &mut token_tree,
+ ]),
+ punct(','),
+ )(*c)
+ .map(|(stream, cursor)| (Self::Other(stream), cursor))
+ .ok_or_else(|| Error::new(c.span(), "failed to parse expression"))
+ })
+ }
+ }
+}
+
+impl ToTokens for Expr {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ match self {
+ Self::Ident(ident) => ident.to_tokens(tokens),
+ Self::Other(other) => other.to_tokens(tokens),
+ }
+ }
+}
+
+/// Result of parsing.
+type ParsingResult<'a> = Option<(TokenStream, Cursor<'a>)>;
+
+/// Tries to parse a [`syn::token::Colon2`].
+pub fn colon2(c: Cursor<'_>) -> ParsingResult<'_> {
+ seq([
+ &mut punct_with_spacing(':', Spacing::Joint),
+ &mut punct(':'),
+ ])(c)
+}
+
+/// Tries to parse a [`punct`] with [`Spacing`].
+pub fn punct_with_spacing(
+ p: char,
+ spacing: Spacing,
+) -> impl FnMut(Cursor<'_>) -> ParsingResult<'_> {
+ move |c| {
+ c.punct().and_then(|(punct, c)| {
+ (punct.as_char() == p && punct.spacing() == spacing)
+ .then(|| (punct.into_token_stream(), c))
+ })
+ }
+}
+
+/// Tries to parse a [`Punct`].
+///
+/// [`Punct`]: proc_macro2::Punct
+pub fn punct(p: char) -> impl FnMut(Cursor<'_>) -> ParsingResult<'_> {
+ move |c| {
+ c.punct().and_then(|(punct, c)| {
+ (punct.as_char() == p).then(|| (punct.into_token_stream(), c))
+ })
+ }
+}
+
+/// Tries to parse any [`TokenTree`].
+///
+/// [`TokenTree`]: proc_macro2::TokenTree
+pub fn token_tree(c: Cursor<'_>) -> ParsingResult<'_> {
+ c.token_tree().map(|(tt, c)| (tt.into_token_stream(), c))
+}
+
+/// Parses until balanced amount of `open` and `close` or eof.
+///
+/// [`Cursor`] should be pointing **right after** the first `open`ing.
+pub fn balanced_pair(
+ mut open: impl FnMut(Cursor<'_>) -> ParsingResult<'_>,
+ mut close: impl FnMut(Cursor<'_>) -> ParsingResult<'_>,
+) -> impl FnMut(Cursor<'_>) -> ParsingResult<'_> {
+ move |c| {
+ let (mut out, mut c) = open(c)?;
+ let mut count = 1;
+
+ while count != 0 {
+ let (stream, cursor) = if let Some(closing) = close(c) {
+ count -= 1;
+ closing
+ } else if let Some(opening) = open(c) {
+ count += 1;
+ opening
+ } else {
+ let (tt, c) = c.token_tree()?;
+ (tt.into_token_stream(), c)
+ };
+ out.extend(stream);
+ c = cursor;
+ }
+
+ Some((out, c))
+ }
+}
+
+/// Tries to execute the provided sequence of `parsers`.
+pub fn seq<const N: usize>(
+ mut parsers: [&mut dyn FnMut(Cursor<'_>) -> ParsingResult<'_>; N],
+) -> impl FnMut(Cursor<'_>) -> ParsingResult<'_> + '_ {
+ move |c| {
+ parsers
+ .iter_mut()
+ .fold(Some((TokenStream::new(), c)), |out, parser| {
+ let (mut out, mut c) = out?;
+ let (stream, cursor) = parser(c)?;
+ out.extend(stream);
+ c = cursor;
+ Some((out, c))
+ })
+ }
+}
+
+/// Tries to execute the first successful parser.
+pub fn alt<const N: usize>(
+ mut parsers: [&mut dyn FnMut(Cursor<'_>) -> ParsingResult<'_>; N],
+) -> impl FnMut(Cursor<'_>) -> ParsingResult<'_> + '_ {
+ move |c| {
+ parsers
+ .iter_mut()
+ .find_map(|parser| parser(c).map(|(s, c)| (s, c)))
+ }
+}
+
+/// Parses with `basic` while `until` fails. Returns [`None`] in case
+/// `until` succeeded initially or `basic` never succeeded. Doesn't consume
+/// tokens parsed by `until`.
+pub fn take_until1<P, U>(
+ mut parser: P,
+ mut until: U,
+) -> impl FnMut(Cursor<'_>) -> ParsingResult<'_>
+where
+ P: FnMut(Cursor<'_>) -> ParsingResult<'_>,
+ U: FnMut(Cursor<'_>) -> ParsingResult<'_>,
+{
+ move |mut cursor| {
+ let mut out = TokenStream::new();
+ let mut parsed = false;
+
+ loop {
+ if cursor.eof() || until(cursor).is_some() {
+ return parsed.then_some((out, cursor));
+ }
+
+ let (stream, c) = parser(cursor)?;
+ out.extend(stream);
+ cursor = c;
+ parsed = true;
+ }
+ }
+}
+
+#[cfg(test)]
+mod spec {
+ use std::{fmt::Debug, str::FromStr};
+
+ use itertools::Itertools as _;
+ use proc_macro2::TokenStream;
+ use quote::ToTokens;
+ use syn::{
+ parse::{Parse, Parser as _},
+ punctuated::Punctuated,
+ token::Comma,
+ };
+
+ use super::{Expr, Type};
+
+ fn assert<'a, T: Debug + Parse + ToTokens>(
+ input: &'a str,
+ parsed: impl AsRef<[&'a str]>,
+ ) {
+ let parsed = parsed.as_ref();
+ let punctuated = Punctuated::<T, Comma>::parse_terminated
+ .parse2(TokenStream::from_str(input).unwrap())
+ .unwrap();
+
+ assert_eq!(
+ parsed.len(),
+ punctuated.len(),
+ "Wrong length\n\
+ Expected: {parsed:?}\n\
+ Found: {punctuated:?}",
+ );
+
+ punctuated
+ .iter()
+ .map(|ty| ty.to_token_stream().to_string())
+ .zip(parsed)
+ .enumerate()
+ .for_each(|(i, (found, expected))| {
+ assert_eq!(
+ *expected, &found,
+ "Mismatch at index {i}\n\
+ Expected: {parsed:?}\n\
+ Found: {punctuated:?}",
+ );
+ });
+ }
+
+ mod tuple {
+ use super::*;
+
+ #[test]
+ fn zst_is_tuple() {
+ let zst = "()";
+ match syn::parse_str::<Type>(zst).unwrap() {
+ Type::Tuple { items, .. } => {
+ assert!(items.is_empty(), "Expected empty tuple, found: {items:?}");
+ }
+ other => panic!("Expected `Type::Tuple {{ .. }}`, found: {other:?}"),
+ }
+ }
+
+ #[test]
+ fn group_not_tuple() {
+ let group = "(Type)";
+ match syn::parse_str::<Type>(group).unwrap() {
+ Type::Other(tokens) => {
+ assert_eq!(tokens.to_string(), group);
+ }
+ tuple => panic!("Expected `Type::Other(_)`, found: {tuple:?}"),
+ }
+ }
+
+ #[test]
+ fn single_element_tuple() {
+ let tuple = "(Type,)";
+ match syn::parse_str::<Type>(tuple).unwrap() {
+ Type::Tuple { items, .. } => {
+ assert_eq!(
+ items.len(),
+ 1,
+ "Expected empty tuple, found: {items:?}",
+ );
+ assert_eq!(items.first().unwrap().to_string(), "Type");
+ }
+ other => panic!("Expected `Type::Tuple {{ .. }}`, found: {other:?}"),
+ }
+ }
+
+ #[test]
+ fn cases() {
+ let cases = [
+ "[Type ; 3]",
+ "fn (usize) -> bool",
+ "for <'a > fn (&'a usize) -> bool",
+ "(Type)",
+ "path :: to :: Type",
+ "path :: to :: Generic < Type >",
+ "< Type as Trait >:: Assoc",
+ "< Type as Trait >:: Assoc < GAT >",
+ "* const ()",
+ "* mut ()",
+ "& i32",
+ "&'static str",
+ "& [str]",
+ "dyn Trait",
+ "dyn Trait + Send",
+ "()",
+ "(Type ,)",
+ "(Type , Type)",
+ "(Type , Type ,)",
+ ];
+
+ assert::<Type>("", []);
+ for i in 1..4 {
+ for permutations in cases.into_iter().permutations(i) {
+ let mut input = permutations.join(",");
+ assert::<Type>(&input, &permutations);
+ input.push(',');
+ assert::<Type>(&input, &permutations);
+ }
+ }
+ }
+ }
+
+ mod expr {
+ use super::*;
+
+ #[test]
+ fn cases() {
+ let cases = [
+ "ident",
+ "[a , b , c , d]",
+ "counter += 1",
+ "async { fut . await }",
+ "a < b",
+ "a > b",
+ "{ let x = (a , b) ; }",
+ "invoke (a , b)",
+ "foo as f64",
+ "| a , b | a + b",
+ "obj . k",
+ "for pat in expr { break pat ; }",
+ "if expr { true } else { false }",
+ "vector [2]",
+ "1",
+ "\"foo\"",
+ "loop { break i ; }",
+ "format ! (\"{}\" , q)",
+ "match n { Some (n) => { } , None => { } }",
+ "x . foo ::< T > (a , b)",
+ "x . foo ::< T < [T < T >; if a < b { 1 } else { 2 }] >, { a < b } > (a , b)",
+ "(a + b)",
+ "i32 :: MAX",
+ "1 .. 2",
+ "& a",
+ "[0u8 ; N]",
+ "(a , b , c , d)",
+ "< Ty as Trait > :: T",
+ "< Ty < Ty < T >, { a < b } > as Trait < T > > :: T",
+ ];
+
+ assert::<Expr>("", []);
+ for i in 1..4 {
+ for permutations in cases.into_iter().permutations(i) {
+ let mut input = permutations.clone().join(",");
+ assert::<Expr>(&input, &permutations);
+ input.push(',');
+ assert::<Expr>(&input, &permutations);
+ }
+ }
+ }
+ }
+}
diff --git a/third_party/rust/derive_more-impl/src/sum_like.rs b/third_party/rust/derive_more-impl/src/sum_like.rs
new file mode 100644
index 0000000000..97d73fce4b
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/sum_like.rs
@@ -0,0 +1,53 @@
+use crate::utils::{
+ add_extra_ty_param_bound, add_extra_where_clauses, MultiFieldData, State,
+};
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote};
+use syn::{DeriveInput, Result};
+
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let state = State::new(input, trait_name, trait_name.to_lowercase())?;
+ let multi_field_data = state.enabled_fields_data();
+ let MultiFieldData {
+ input_type,
+ field_types,
+ trait_path,
+ method_ident,
+ ..
+ } = multi_field_data.clone();
+
+ let op_trait_name = if trait_name == "Sum" { "Add" } else { "Mul" };
+ let op_trait_ident = format_ident!("{op_trait_name}");
+ let op_path = quote! { ::core::ops::#op_trait_ident };
+ let op_method_ident = format_ident!("{}", op_trait_name.to_lowercase());
+ let has_type_params = input.generics.type_params().next().is_none();
+ let generics = if has_type_params {
+ input.generics.clone()
+ } else {
+ let (_, ty_generics, _) = input.generics.split_for_impl();
+ let generics = add_extra_ty_param_bound(&input.generics, trait_path);
+ let operator_where_clause = quote! {
+ where #input_type #ty_generics: #op_path<Output=#input_type #ty_generics>
+ };
+ add_extra_where_clauses(&generics, operator_where_clause)
+ };
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ let initializers: Vec<_> = field_types
+ .iter()
+ .map(|field_type| {
+ quote! { #trait_path::#method_ident(::core::iter::empty::<#field_type>()) }
+ })
+ .collect();
+ let identity = multi_field_data.initializer(&initializers);
+
+ Ok(quote! {
+ #[automatically_derived]
+ impl #impl_generics #trait_path for #input_type #ty_generics #where_clause {
+ #[inline]
+ fn #method_ident<I: ::core::iter::Iterator<Item = Self>>(iter: I) -> Self {
+ iter.fold(#identity, #op_path::#op_method_ident)
+ }
+ }
+ })
+}
diff --git a/third_party/rust/derive_more-impl/src/try_into.rs b/third_party/rust/derive_more-impl/src/try_into.rs
new file mode 100644
index 0000000000..f3066c1d4a
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/try_into.rs
@@ -0,0 +1,123 @@
+use crate::utils::{
+ add_extra_generic_param, numbered_vars, AttrParams, DeriveType, MultiFieldData,
+ State,
+};
+use proc_macro2::TokenStream;
+use quote::{quote, ToTokens};
+use syn::{DeriveInput, Result};
+
+use crate::utils::HashMap;
+
+/// Provides the hook to expand `#[derive(TryInto)]` into an implementation of `TryInto`
+#[allow(clippy::cognitive_complexity)]
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let state = State::with_attr_params(
+ input,
+ trait_name,
+ "try_into".into(),
+ AttrParams {
+ enum_: vec!["ignore", "owned", "ref", "ref_mut"],
+ variant: vec!["ignore", "owned", "ref", "ref_mut"],
+ struct_: vec!["ignore", "owned", "ref", "ref_mut"],
+ field: vec!["ignore"],
+ },
+ )?;
+ assert!(
+ state.derive_type == DeriveType::Enum,
+ "Only enums can derive TryInto"
+ );
+
+ let mut variants_per_types = HashMap::default();
+
+ for variant_state in state.enabled_variant_data().variant_states {
+ let multi_field_data = variant_state.enabled_fields_data();
+ let MultiFieldData {
+ variant_info,
+ field_types,
+ ..
+ } = multi_field_data.clone();
+ for ref_type in variant_info.ref_types() {
+ variants_per_types
+ .entry((ref_type, field_types.clone()))
+ .or_insert_with(Vec::new)
+ .push(multi_field_data.clone());
+ }
+ }
+
+ let mut tokens = TokenStream::new();
+
+ for ((ref_type, ref original_types), ref multi_field_datas) in variants_per_types {
+ let input_type = &input.ident;
+
+ let pattern_ref = ref_type.pattern_ref();
+ let lifetime = ref_type.lifetime();
+ let reference_with_lifetime = ref_type.reference_with_lifetime();
+
+ let mut matchers = vec![];
+ let vars = &numbered_vars(original_types.len(), "");
+ for multi_field_data in multi_field_datas {
+ let patterns: Vec<_> = vars
+ .iter()
+ .map(|var| quote! { #pattern_ref #var })
+ .collect();
+ matchers.push(
+ multi_field_data.matcher(&multi_field_data.field_indexes, &patterns),
+ );
+ }
+
+ let vars = if vars.len() == 1 {
+ quote! { #(#vars)* }
+ } else {
+ quote! { (#(#vars),*) }
+ };
+
+ let output_type = if original_types.len() == 1 {
+ quote! { #(#original_types)* }.to_string()
+ } else {
+ let types = original_types
+ .iter()
+ .map(|t| quote! { #t }.to_string())
+ .collect::<Vec<_>>();
+ format!("({})", types.join(", "))
+ };
+ let variant_names = multi_field_datas
+ .iter()
+ .map(|d| {
+ d.variant_name
+ .expect("Somehow there was no variant name")
+ .to_string()
+ })
+ .collect::<Vec<_>>()
+ .join(", ");
+
+ let generics_impl;
+ let (_, ty_generics, where_clause) = input.generics.split_for_impl();
+ let (impl_generics, _, _) = if ref_type.is_ref() {
+ generics_impl = add_extra_generic_param(&input.generics, lifetime.clone());
+ generics_impl.split_for_impl()
+ } else {
+ input.generics.split_for_impl()
+ };
+
+ let try_from = quote! {
+ #[automatically_derived]
+ impl #impl_generics
+ ::core::convert::TryFrom<#reference_with_lifetime #input_type #ty_generics> for
+ (#(#reference_with_lifetime #original_types),*)
+ #where_clause
+ {
+ type Error = ::derive_more::TryIntoError<#reference_with_lifetime #input_type>;
+
+ #[inline]
+ fn try_from(value: #reference_with_lifetime #input_type #ty_generics) -> ::core::result::Result<Self, Self::Error> {
+ match value {
+ #(#matchers)|* => ::core::result::Result::Ok(#vars),
+ _ => ::core::result::Result::Err(::derive_more::TryIntoError::new(value, #variant_names, #output_type)),
+ }
+ }
+ }
+ };
+ try_from.to_tokens(&mut tokens)
+ }
+ Ok(tokens)
+}
diff --git a/third_party/rust/derive_more-impl/src/try_unwrap.rs b/third_party/rust/derive_more-impl/src/try_unwrap.rs
new file mode 100644
index 0000000000..67d3793d00
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/try_unwrap.rs
@@ -0,0 +1,166 @@
+use crate::utils::{AttrParams, DeriveType, State};
+use convert_case::{Case, Casing};
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote};
+use syn::{DeriveInput, Fields, Ident, Result, Type};
+
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let state = State::with_attr_params(
+ input,
+ trait_name,
+ "try_unwrap".into(),
+ AttrParams {
+ enum_: vec!["ignore", "owned", "ref", "ref_mut"],
+ variant: vec!["ignore", "owned", "ref", "ref_mut"],
+ struct_: vec!["ignore"],
+ field: vec!["ignore"],
+ },
+ )?;
+ assert!(
+ state.derive_type == DeriveType::Enum,
+ "TryUnwrap can only be derived for enums"
+ );
+
+ let enum_name = &input.ident;
+ let (imp_generics, type_generics, where_clause) = input.generics.split_for_impl();
+
+ let variant_data = state.enabled_variant_data();
+
+ let mut funcs = vec![];
+ for (variant_state, info) in
+ Iterator::zip(variant_data.variant_states.iter(), variant_data.infos)
+ {
+ let variant = variant_state.variant.unwrap();
+ let fn_name = format_ident!(
+ "try_unwrap_{ident}",
+ ident = variant.ident.to_string().to_case(Case::Snake),
+ span = variant.ident.span(),
+ );
+ let ref_fn_name = format_ident!(
+ "try_unwrap_{ident}_ref",
+ ident = variant.ident.to_string().to_case(Case::Snake),
+ span = variant.ident.span(),
+ );
+ let mut_fn_name = format_ident!(
+ "try_unwrap_{ident}_mut",
+ ident = variant.ident.to_string().to_case(Case::Snake),
+ span = variant.ident.span(),
+ );
+ let variant_ident = &variant.ident;
+ let (data_pattern, ret_value, data_types) = get_field_info(&variant.fields);
+ let pattern = quote! { #enum_name :: #variant_ident #data_pattern };
+
+ let (failed_block, failed_block_ref, failed_block_mut) = (
+ failed_block(&state, enum_name, &fn_name),
+ failed_block(&state, enum_name, &ref_fn_name),
+ failed_block(&state, enum_name, &mut_fn_name),
+ );
+
+ let doc_owned = format!(
+ "Attempts to unwrap this value to the `{enum_name}::{variant_ident}` variant.\n",
+ );
+ let doc_ref = format!(
+ "Attempts to unwrap this reference to the `{enum_name}::{variant_ident}` variant.\n",
+ );
+ let doc_mut = format!(
+ "Attempts to unwrap this mutable reference to the `{enum_name}::{variant_ident}` variant.\n",
+ );
+ let doc_else = "Returns a [TryUnwrapError] with the original value if this value is of any other type.";
+ let func = quote! {
+ #[inline]
+ #[track_caller]
+ #[doc = #doc_owned]
+ #[doc = #doc_else]
+ pub fn #fn_name(self) -> Result<(#(#data_types),*), ::derive_more::TryUnwrapError<Self>> {
+ match self {
+ #pattern => Ok(#ret_value),
+ val @ _ => #failed_block,
+ }
+ }
+ };
+
+ let ref_func = quote! {
+ #[inline]
+ #[track_caller]
+ #[doc = #doc_ref]
+ #[doc = #doc_else]
+ pub fn #ref_fn_name(&self) -> Result<(#(&#data_types),*), ::derive_more::TryUnwrapError<&Self>> {
+ match self {
+ #pattern => Ok(#ret_value),
+ val @ _ => #failed_block_ref,
+ }
+ }
+ };
+
+ let mut_func = quote! {
+ #[inline]
+ #[track_caller]
+ #[doc = #doc_mut]
+ #[doc = #doc_else]
+ pub fn #mut_fn_name(&mut self) -> Result<(#(&mut #data_types),*), ::derive_more::TryUnwrapError<&mut Self>> {
+ match self {
+ #pattern => Ok(#ret_value),
+ val @ _ => #failed_block_mut,
+ }
+ }
+ };
+
+ if info.owned && state.default_info.owned {
+ funcs.push(func);
+ }
+ if info.ref_ && state.default_info.ref_ {
+ funcs.push(ref_func);
+ }
+ if info.ref_mut && state.default_info.ref_mut {
+ funcs.push(mut_func);
+ }
+ }
+
+ let imp = quote! {
+ #[automatically_derived]
+ impl #imp_generics #enum_name #type_generics #where_clause {
+ #(#funcs)*
+ }
+ };
+
+ Ok(imp)
+}
+
+fn get_field_info(fields: &Fields) -> (TokenStream, TokenStream, Vec<&Type>) {
+ match fields {
+ Fields::Named(_) => panic!("cannot unwrap anonymous records"),
+ Fields::Unnamed(ref fields) => {
+ let (idents, types) = fields
+ .unnamed
+ .iter()
+ .enumerate()
+ .map(|(n, it)| (format_ident!("field_{n}"), &it.ty))
+ .unzip::<_, _, Vec<_>, Vec<_>>();
+ (quote! { (#(#idents),*) }, quote! { (#(#idents),*) }, types)
+ }
+ Fields::Unit => (quote! {}, quote! { () }, vec![]),
+ }
+}
+
+fn failed_block(state: &State, enum_name: &Ident, func_name: &Ident) -> TokenStream {
+ let arms = state
+ .variant_states
+ .iter()
+ .map(|it| it.variant.unwrap())
+ .map(|variant| {
+ let data_pattern = match variant.fields {
+ Fields::Named(_) => quote! { {..} },
+ Fields::Unnamed(_) => quote! { (..) },
+ Fields::Unit => quote! {},
+ };
+ let variant_ident = &variant.ident;
+ let error = quote! { ::derive_more::TryUnwrapError::<_>::new(val, stringify!(#enum_name), stringify!(#variant_ident), stringify!(#func_name)) };
+ quote! { val @ #enum_name :: #variant_ident #data_pattern => Err(#error) }
+ });
+
+ quote! {
+ match val {
+ #(#arms),*
+ }
+ }
+}
diff --git a/third_party/rust/derive_more-impl/src/unwrap.rs b/third_party/rust/derive_more-impl/src/unwrap.rs
new file mode 100644
index 0000000000..02a9010c4c
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/unwrap.rs
@@ -0,0 +1,169 @@
+use crate::utils::{AttrParams, DeriveType, State};
+use convert_case::{Case, Casing};
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote};
+use syn::{DeriveInput, Fields, Ident, Result, Type};
+
+pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
+ let state = State::with_attr_params(
+ input,
+ trait_name,
+ "unwrap".into(),
+ AttrParams {
+ enum_: vec!["ignore", "owned", "ref", "ref_mut"],
+ variant: vec!["ignore", "owned", "ref", "ref_mut"],
+ struct_: vec!["ignore"],
+ field: vec!["ignore"],
+ },
+ )?;
+ assert!(
+ state.derive_type == DeriveType::Enum,
+ "Unwrap can only be derived for enums",
+ );
+
+ let enum_name = &input.ident;
+ let (imp_generics, type_generics, where_clause) = input.generics.split_for_impl();
+
+ let variant_data = state.enabled_variant_data();
+
+ let mut funcs = vec![];
+ for (variant_state, info) in
+ Iterator::zip(variant_data.variant_states.iter(), variant_data.infos)
+ {
+ let variant = variant_state.variant.unwrap();
+ let fn_name = format_ident!(
+ "unwrap_{ident}",
+ ident = variant.ident.to_string().to_case(Case::Snake),
+ span = variant.ident.span(),
+ );
+ let ref_fn_name = format_ident!(
+ "unwrap_{ident}_ref",
+ ident = variant.ident.to_string().to_case(Case::Snake),
+ span = variant.ident.span(),
+ );
+ let mut_fn_name = format_ident!(
+ "unwrap_{ident}_mut",
+ ident = variant.ident.to_string().to_case(Case::Snake),
+ span = variant.ident.span(),
+ );
+ let variant_ident = &variant.ident;
+ let (data_pattern, ret_value, data_types) = get_field_info(&variant.fields);
+ let pattern = quote! { #enum_name :: #variant_ident #data_pattern };
+
+ let (failed_block, failed_block_ref, failed_block_mut) = (
+ failed_block(&state, enum_name, &fn_name),
+ failed_block(&state, enum_name, &ref_fn_name),
+ failed_block(&state, enum_name, &mut_fn_name),
+ );
+
+ let doc_owned = format!(
+ "Unwraps this value to the `{enum_name}::{variant_ident}` variant.\n",
+ );
+ let doc_ref = format!(
+ "Unwraps this reference to the `{enum_name}::{variant_ident}` variant.\n",
+ );
+ let doc_mut = format!(
+ "Unwraps this mutable reference to the `{enum_name}::{variant_ident}` variant.\n",
+ );
+ let doc_else = "Panics if this value is of any other type.";
+
+ let func = quote! {
+ #[inline]
+ #[track_caller]
+ #[doc = #doc_owned]
+ #[doc = #doc_else]
+ pub fn #fn_name(self) -> (#(#data_types),*) {
+ match self {
+ #pattern => #ret_value,
+ val @ _ => #failed_block,
+ }
+ }
+ };
+
+ let ref_func = quote! {
+ #[inline]
+ #[track_caller]
+ #[doc = #doc_ref]
+ #[doc = #doc_else]
+ pub fn #ref_fn_name(&self) -> (#(&#data_types),*) {
+ match self {
+ #pattern => #ret_value,
+ val @ _ => #failed_block_ref,
+ }
+ }
+ };
+
+ let mut_func = quote! {
+ #[inline]
+ #[track_caller]
+ #[doc = #doc_mut]
+ #[doc = #doc_else]
+ pub fn #mut_fn_name(&mut self) -> (#(&mut #data_types),*) {
+ match self {
+ #pattern => #ret_value,
+ val @ _ => #failed_block_mut,
+ }
+ }
+ };
+
+ if info.owned && state.default_info.owned {
+ funcs.push(func);
+ }
+ if info.ref_ && state.default_info.ref_ {
+ funcs.push(ref_func);
+ }
+ if info.ref_mut && state.default_info.ref_mut {
+ funcs.push(mut_func);
+ }
+ }
+
+ let imp = quote! {
+ #[automatically_derived]
+ impl #imp_generics #enum_name #type_generics #where_clause {
+ #(#funcs)*
+ }
+ };
+
+ Ok(imp)
+}
+
+fn get_field_info(fields: &Fields) -> (TokenStream, TokenStream, Vec<&Type>) {
+ match fields {
+ Fields::Named(_) => panic!("cannot unwrap anonymous records"),
+ Fields::Unnamed(ref fields) => {
+ let (idents, types) = fields
+ .unnamed
+ .iter()
+ .enumerate()
+ .map(|(n, it)| (format_ident!("field_{n}"), &it.ty))
+ .unzip::<_, _, Vec<_>, Vec<_>>();
+ (quote! { (#(#idents),*) }, quote! { (#(#idents),*) }, types)
+ }
+ Fields::Unit => (quote! {}, quote! { () }, vec![]),
+ }
+}
+
+fn failed_block(state: &State, enum_name: &Ident, fn_name: &Ident) -> TokenStream {
+ let arms = state
+ .variant_states
+ .iter()
+ .map(|it| it.variant.unwrap())
+ .map(|variant| {
+ let data_pattern = match variant.fields {
+ Fields::Named(_) => quote! { {..} },
+ Fields::Unnamed(_) => quote! { (..) },
+ Fields::Unit => quote! {},
+ };
+ let variant_ident = &variant.ident;
+ let panic_msg = format!(
+ "called `{enum_name}::{fn_name}()` on a `{enum_name}::{variant_ident}` value"
+ );
+ quote! { #enum_name :: #variant_ident #data_pattern => panic!(#panic_msg) }
+ });
+
+ quote! {
+ match val {
+ #(#arms),*
+ }
+ }
+}
diff --git a/third_party/rust/derive_more-impl/src/utils.rs b/third_party/rust/derive_more-impl/src/utils.rs
new file mode 100644
index 0000000000..9523591b26
--- /dev/null
+++ b/third_party/rust/derive_more-impl/src/utils.rs
@@ -0,0 +1,1514 @@
+#![cfg_attr(
+ not(all(feature = "add", feature = "mul")),
+ allow(dead_code),
+ allow(unused_mut)
+)]
+
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote, ToTokens};
+use syn::{
+ parse_quote, punctuated::Punctuated, spanned::Spanned, Attribute, Data,
+ DeriveInput, Error, Field, Fields, FieldsNamed, FieldsUnnamed, GenericParam,
+ Generics, Ident, ImplGenerics, Index, Result, Token, Type, TypeGenerics,
+ TypeParamBound, Variant, WhereClause,
+};
+
+#[cfg(any(feature = "from", feature = "into"))]
+pub(crate) use self::{either::Either, fields_ext::FieldsExt};
+
+#[derive(Clone, Copy, Default)]
+pub struct DeterministicState;
+
+impl std::hash::BuildHasher for DeterministicState {
+ type Hasher = std::collections::hash_map::DefaultHasher;
+
+ fn build_hasher(&self) -> Self::Hasher {
+ Self::Hasher::default()
+ }
+}
+
+pub type HashMap<K, V> = std::collections::HashMap<K, V, DeterministicState>;
+pub type HashSet<K> = std::collections::HashSet<K, DeterministicState>;
+
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
+pub enum RefType {
+ No,
+ Ref,
+ Mut,
+}
+
+impl RefType {
+ pub fn lifetime(self) -> TokenStream {
+ match self {
+ RefType::No => quote! {},
+ _ => quote! { '__deriveMoreLifetime },
+ }
+ }
+
+ pub fn reference(self) -> TokenStream {
+ match self {
+ RefType::No => quote! {},
+ RefType::Ref => quote! { & },
+ RefType::Mut => quote! { &mut },
+ }
+ }
+
+ pub fn mutability(self) -> TokenStream {
+ match self {
+ RefType::Mut => quote! { mut },
+ _ => quote! {},
+ }
+ }
+
+ pub fn pattern_ref(self) -> TokenStream {
+ match self {
+ RefType::Ref => quote! { ref },
+ RefType::Mut => quote! { ref mut },
+ RefType::No => quote! {},
+ }
+ }
+
+ pub fn reference_with_lifetime(self) -> TokenStream {
+ if !self.is_ref() {
+ return quote! {};
+ }
+ let lifetime = self.lifetime();
+ let mutability = self.mutability();
+ quote! { &#lifetime #mutability }
+ }
+
+ pub fn is_ref(self) -> bool {
+ !matches!(self, RefType::No)
+ }
+
+ pub fn from_attr_name(name: &str) -> Self {
+ match name {
+ "owned" => RefType::No,
+ "ref" => RefType::Ref,
+ "ref_mut" => RefType::Mut,
+ _ => panic!("`{name}` is not a `RefType`"),
+ }
+ }
+}
+
+pub fn numbered_vars(count: usize, prefix: &str) -> Vec<Ident> {
+ (0..count).map(|i| format_ident!("__{prefix}{i}")).collect()
+}
+
+pub fn field_idents<'a>(fields: &'a [&'a Field]) -> Vec<&'a Ident> {
+ fields
+ .iter()
+ .map(|f| {
+ f.ident
+ .as_ref()
+ .expect("Tried to get field names of a tuple struct")
+ })
+ .collect()
+}
+
+pub fn get_field_types_iter<'a>(
+ fields: &'a [&'a Field],
+) -> Box<dyn Iterator<Item = &'a Type> + 'a> {
+ Box::new(fields.iter().map(|f| &f.ty))
+}
+
+pub fn get_field_types<'a>(fields: &'a [&'a Field]) -> Vec<&'a Type> {
+ get_field_types_iter(fields).collect()
+}
+
+pub fn add_extra_type_param_bound_op_output<'a>(
+ generics: &'a Generics,
+ trait_ident: &'a Ident,
+) -> Generics {
+ let mut generics = generics.clone();
+ for type_param in &mut generics.type_params_mut() {
+ let type_ident = &type_param.ident;
+ let bound: TypeParamBound = parse_quote! {
+ ::core::ops::#trait_ident<Output=#type_ident>
+ };
+ type_param.bounds.push(bound)
+ }
+
+ generics
+}
+
+pub fn add_extra_ty_param_bound_op<'a>(
+ generics: &'a Generics,
+ trait_ident: &'a Ident,
+) -> Generics {
+ add_extra_ty_param_bound(generics, &quote! { ::core::ops::#trait_ident })
+}
+
+pub fn add_extra_ty_param_bound<'a>(
+ generics: &'a Generics,
+ bound: &'a TokenStream,
+) -> Generics {
+ let mut generics = generics.clone();
+ let bound: TypeParamBound = parse_quote! { #bound };
+ for type_param in &mut generics.type_params_mut() {
+ type_param.bounds.push(bound.clone())
+ }
+
+ generics
+}
+
+pub fn add_extra_ty_param_bound_ref<'a>(
+ generics: &'a Generics,
+ bound: &'a TokenStream,
+ ref_type: RefType,
+) -> Generics {
+ match ref_type {
+ RefType::No => add_extra_ty_param_bound(generics, bound),
+ _ => {
+ let generics = generics.clone();
+ let idents = generics.type_params().map(|x| &x.ident);
+ let ref_with_lifetime = ref_type.reference_with_lifetime();
+ add_extra_where_clauses(
+ &generics,
+ quote! {
+ where #(#ref_with_lifetime #idents: #bound),*
+ },
+ )
+ }
+ }
+}
+
+pub fn add_extra_generic_param(
+ generics: &Generics,
+ generic_param: TokenStream,
+) -> Generics {
+ let generic_param: GenericParam = parse_quote! { #generic_param };
+ let mut generics = generics.clone();
+ generics.params.push(generic_param);
+
+ generics
+}
+
+pub fn add_extra_generic_type_param(
+ generics: &Generics,
+ generic_param: TokenStream,
+) -> Generics {
+ let generic_param: GenericParam = parse_quote! { #generic_param };
+ let lifetimes: Vec<GenericParam> =
+ generics.lifetimes().map(|x| x.clone().into()).collect();
+ let type_params: Vec<GenericParam> =
+ generics.type_params().map(|x| x.clone().into()).collect();
+ let const_params: Vec<GenericParam> =
+ generics.const_params().map(|x| x.clone().into()).collect();
+ let mut generics = generics.clone();
+ generics.params = Default::default();
+ generics.params.extend(lifetimes);
+ generics.params.extend(type_params);
+ generics.params.push(generic_param);
+ generics.params.extend(const_params);
+
+ generics
+}
+
+pub fn add_extra_where_clauses(
+ generics: &Generics,
+ type_where_clauses: TokenStream,
+) -> Generics {
+ let mut type_where_clauses: WhereClause = parse_quote! { #type_where_clauses };
+ let mut new_generics = generics.clone();
+ if let Some(old_where) = new_generics.where_clause {
+ type_where_clauses.predicates.extend(old_where.predicates)
+ }
+ new_generics.where_clause = Some(type_where_clauses);
+
+ new_generics
+}
+
+pub fn add_where_clauses_for_new_ident<'a>(
+ generics: &'a Generics,
+ fields: &[&'a Field],
+ type_ident: &Ident,
+ type_where_clauses: TokenStream,
+ sized: bool,
+) -> Generics {
+ let generic_param = if fields.len() > 1 {
+ quote! { #type_ident: ::core::marker::Copy }
+ } else if sized {
+ quote! { #type_ident }
+ } else {
+ quote! { #type_ident: ?::core::marker::Sized }
+ };
+
+ let generics = add_extra_where_clauses(generics, type_where_clauses);
+ add_extra_generic_type_param(&generics, generic_param)
+}
+
+pub fn unnamed_to_vec(fields: &FieldsUnnamed) -> Vec<&Field> {
+ fields.unnamed.iter().collect()
+}
+
+pub fn named_to_vec(fields: &FieldsNamed) -> Vec<&Field> {
+ fields.named.iter().collect()
+}
+
+fn panic_one_field(trait_name: &str, trait_attr: &str) -> ! {
+ panic!(
+ "derive({trait_name}) only works when forwarding to a single field. \
+ Try putting #[{trait_attr}] or #[{trait_attr}(ignore)] on the fields in the struct",
+ )
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum DeriveType {
+ Unnamed,
+ Named,
+ Enum,
+}
+
+pub struct State<'input> {
+ pub input: &'input DeriveInput,
+ pub trait_name: &'static str,
+ pub trait_ident: Ident,
+ pub method_ident: Ident,
+ pub trait_path: TokenStream,
+ pub trait_path_params: Vec<TokenStream>,
+ pub trait_attr: String,
+ pub derive_type: DeriveType,
+ pub fields: Vec<&'input Field>,
+ pub variants: Vec<&'input Variant>,
+ pub variant_states: Vec<State<'input>>,
+ pub variant: Option<&'input Variant>,
+ pub generics: Generics,
+ pub default_info: FullMetaInfo,
+ full_meta_infos: Vec<FullMetaInfo>,
+}
+
+#[derive(Default, Clone)]
+pub struct AttrParams {
+ pub enum_: Vec<&'static str>,
+ pub variant: Vec<&'static str>,
+ pub struct_: Vec<&'static str>,
+ pub field: Vec<&'static str>,
+}
+
+impl AttrParams {
+ pub fn new(params: Vec<&'static str>) -> AttrParams {
+ AttrParams {
+ enum_: params.clone(),
+ struct_: params.clone(),
+ variant: params.clone(),
+ field: params,
+ }
+ }
+ pub fn struct_(params: Vec<&'static str>) -> AttrParams {
+ AttrParams {
+ enum_: vec![],
+ struct_: params,
+ variant: vec![],
+ field: vec![],
+ }
+ }
+
+ pub fn ignore_and_forward() -> AttrParams {
+ AttrParams::new(vec!["ignore", "forward"])
+ }
+}
+
+impl<'input> State<'input> {
+ pub fn new<'arg_input>(
+ input: &'arg_input DeriveInput,
+ trait_name: &'static str,
+ trait_attr: String,
+ ) -> Result<State<'arg_input>> {
+ State::new_impl(input, trait_name, trait_attr, AttrParams::default(), true)
+ }
+
+ pub fn with_field_ignore<'arg_input>(
+ input: &'arg_input DeriveInput,
+ trait_name: &'static str,
+ trait_attr: String,
+ ) -> Result<State<'arg_input>> {
+ State::new_impl(
+ input,
+ trait_name,
+ trait_attr,
+ AttrParams::new(vec!["ignore"]),
+ true,
+ )
+ }
+
+ pub fn with_field_ignore_and_forward<'arg_input>(
+ input: &'arg_input DeriveInput,
+ trait_name: &'static str,
+ trait_attr: String,
+ ) -> Result<State<'arg_input>> {
+ State::new_impl(
+ input,
+ trait_name,
+ trait_attr,
+ AttrParams::new(vec!["ignore", "forward"]),
+ true,
+ )
+ }
+
+ pub fn with_field_ignore_and_refs<'arg_input>(
+ input: &'arg_input DeriveInput,
+ trait_name: &'static str,
+ trait_attr: String,
+ ) -> Result<State<'arg_input>> {
+ State::new_impl(
+ input,
+ trait_name,
+ trait_attr,
+ AttrParams::new(vec!["ignore", "owned", "ref", "ref_mut"]),
+ true,
+ )
+ }
+
+ pub fn with_attr_params<'arg_input>(
+ input: &'arg_input DeriveInput,
+ trait_name: &'static str,
+ trait_attr: String,
+ allowed_attr_params: AttrParams,
+ ) -> Result<State<'arg_input>> {
+ State::new_impl(input, trait_name, trait_attr, allowed_attr_params, true)
+ }
+
+ pub fn with_type_bound<'arg_input>(
+ input: &'arg_input DeriveInput,
+ trait_name: &'static str,
+ trait_attr: String,
+ allowed_attr_params: AttrParams,
+ add_type_bound: bool,
+ ) -> Result<State<'arg_input>> {
+ Self::new_impl(
+ input,
+ trait_name,
+ trait_attr,
+ allowed_attr_params,
+ add_type_bound,
+ )
+ }
+
+ fn new_impl<'arg_input>(
+ input: &'arg_input DeriveInput,
+ trait_name: &'static str,
+ trait_attr: String,
+ allowed_attr_params: AttrParams,
+ add_type_bound: bool,
+ ) -> Result<State<'arg_input>> {
+ let trait_name = trait_name.trim_end_matches("ToInner");
+ let trait_ident = format_ident!("{trait_name}");
+ let method_ident = format_ident!("{trait_attr}");
+ let trait_path = quote! { ::derive_more::#trait_ident };
+ let (derive_type, fields, variants): (_, Vec<_>, Vec<_>) = match input.data {
+ Data::Struct(ref data_struct) => match data_struct.fields {
+ Fields::Unnamed(ref fields) => {
+ (DeriveType::Unnamed, unnamed_to_vec(fields), vec![])
+ }
+
+ Fields::Named(ref fields) => {
+ (DeriveType::Named, named_to_vec(fields), vec![])
+ }
+ Fields::Unit => (DeriveType::Named, vec![], vec![]),
+ },
+ Data::Enum(ref data_enum) => (
+ DeriveType::Enum,
+ vec![],
+ data_enum.variants.iter().collect(),
+ ),
+ Data::Union(_) => {
+ panic!("cannot derive({trait_name}) for union")
+ }
+ };
+ let attrs: Vec<_> = if derive_type == DeriveType::Enum {
+ variants.iter().map(|v| &v.attrs).collect()
+ } else {
+ fields.iter().map(|f| &f.attrs).collect()
+ };
+
+ let (allowed_attr_params_outer, allowed_attr_params_inner) =
+ if derive_type == DeriveType::Enum {
+ (&allowed_attr_params.enum_, &allowed_attr_params.variant)
+ } else {
+ (&allowed_attr_params.struct_, &allowed_attr_params.field)
+ };
+
+ let struct_meta_info =
+ get_meta_info(&trait_attr, &input.attrs, allowed_attr_params_outer)?;
+ let meta_infos: Result<Vec<_>> = attrs
+ .iter()
+ .map(|attrs| get_meta_info(&trait_attr, attrs, allowed_attr_params_inner))
+ .collect();
+ let meta_infos = meta_infos?;
+ let first_match = meta_infos
+ .iter()
+ .filter_map(|info| info.enabled.map(|_| info))
+ .next();
+
+ // Default to enabled true, except when first attribute has explicit
+ // enabling.
+ //
+ // Except for derive Error.
+ //
+ // The way `else` case works is that if any field have any valid
+ // attribute specified, then all fields without any attributes
+ // specified are filtered out from `State::enabled_fields`.
+ //
+ // However, derive Error *infers* fields and there are cases when
+ // one of the fields may have an attribute specified, but another field
+ // would be inferred. So, for derive Error macro we default enabled
+ // to true unconditionally (i.e., even if some fields have attributes
+ // specified).
+ let default_enabled = if trait_name == "Error" {
+ true
+ } else {
+ first_match.map_or(true, |info| !info.enabled.unwrap())
+ };
+
+ let defaults = struct_meta_info.into_full(FullMetaInfo {
+ enabled: default_enabled,
+ forward: false,
+ // Default to owned true, except when first attribute has one of owned,
+ // ref or ref_mut
+ // - not a single attribute means default true
+ // - an attribute, but non of owned, ref or ref_mut means default true
+ // - an attribute, and owned, ref or ref_mut means default false
+ owned: first_match.map_or(true, |info| {
+ info.owned.is_none() && info.ref_.is_none() || info.ref_mut.is_none()
+ }),
+ ref_: false,
+ ref_mut: false,
+ info: MetaInfo::default(),
+ });
+
+ let full_meta_infos: Vec<_> = meta_infos
+ .into_iter()
+ .map(|info| info.into_full(defaults.clone()))
+ .collect();
+
+ let variant_states: Result<Vec<_>> = if derive_type == DeriveType::Enum {
+ variants
+ .iter()
+ .zip(full_meta_infos.iter().cloned())
+ .map(|(variant, info)| {
+ State::from_variant(
+ input,
+ trait_name,
+ trait_attr.clone(),
+ allowed_attr_params.clone(),
+ variant,
+ info,
+ )
+ })
+ .collect()
+ } else {
+ Ok(vec![])
+ };
+
+ let generics = if add_type_bound {
+ add_extra_ty_param_bound(&input.generics, &trait_path)
+ } else {
+ input.generics.clone()
+ };
+
+ Ok(State {
+ input,
+ trait_name,
+ trait_ident,
+ method_ident,
+ trait_path,
+ trait_path_params: vec![],
+ trait_attr,
+ // input,
+ fields,
+ variants,
+ variant_states: variant_states?,
+ variant: None,
+ derive_type,
+ generics,
+ full_meta_infos,
+ default_info: defaults,
+ })
+ }
+
+ pub fn from_variant<'arg_input>(
+ input: &'arg_input DeriveInput,
+ trait_name: &'static str,
+ trait_attr: String,
+ allowed_attr_params: AttrParams,
+ variant: &'arg_input Variant,
+ default_info: FullMetaInfo,
+ ) -> Result<State<'arg_input>> {
+ let trait_name = trait_name.trim_end_matches("ToInner");
+ let trait_ident = format_ident!("{trait_name}");
+ let method_ident = format_ident!("{trait_attr}");
+ let trait_path = quote! { ::derive_more::#trait_ident };
+ let (derive_type, fields): (_, Vec<_>) = match variant.fields {
+ Fields::Unnamed(ref fields) => {
+ (DeriveType::Unnamed, unnamed_to_vec(fields))
+ }
+
+ Fields::Named(ref fields) => (DeriveType::Named, named_to_vec(fields)),
+ Fields::Unit => (DeriveType::Named, vec![]),
+ };
+
+ let meta_infos: Result<Vec<_>> = fields
+ .iter()
+ .map(|f| &f.attrs)
+ .map(|attrs| get_meta_info(&trait_attr, attrs, &allowed_attr_params.field))
+ .collect();
+ let meta_infos = meta_infos?;
+ let full_meta_infos: Vec<_> = meta_infos
+ .into_iter()
+ .map(|info| info.into_full(default_info.clone()))
+ .collect();
+
+ let generics = add_extra_ty_param_bound(&input.generics, &trait_path);
+
+ Ok(State {
+ input,
+ trait_name,
+ trait_path,
+ trait_path_params: vec![],
+ trait_attr,
+ trait_ident,
+ method_ident,
+ // input,
+ fields,
+ variants: vec![],
+ variant_states: vec![],
+ variant: Some(variant),
+ derive_type,
+ generics,
+ full_meta_infos,
+ default_info,
+ })
+ }
+ pub fn add_trait_path_type_param(&mut self, param: TokenStream) {
+ self.trait_path_params.push(param);
+ }
+
+ pub fn assert_single_enabled_field<'state>(
+ &'state self,
+ ) -> SingleFieldData<'input, 'state> {
+ if self.derive_type == DeriveType::Enum {
+ panic_one_field(self.trait_name, &self.trait_attr);
+ }
+ let data = self.enabled_fields_data();
+ if data.fields.len() != 1 {
+ panic_one_field(self.trait_name, &self.trait_attr);
+ };
+ SingleFieldData {
+ input_type: data.input_type,
+ field: data.fields[0],
+ field_type: data.field_types[0],
+ member: data.members[0].clone(),
+ info: data.infos[0].clone(),
+ field_ident: data.field_idents[0].clone(),
+ trait_path: data.trait_path,
+ trait_path_with_params: data.trait_path_with_params.clone(),
+ casted_trait: data.casted_traits[0].clone(),
+ impl_generics: data.impl_generics.clone(),
+ ty_generics: data.ty_generics.clone(),
+ where_clause: data.where_clause,
+ multi_field_data: data,
+ }
+ }
+
+ pub fn enabled_fields_data<'state>(&'state self) -> MultiFieldData<'input, 'state> {
+ if self.derive_type == DeriveType::Enum {
+ panic!("cannot derive({}) for enum", self.trait_name)
+ }
+ let fields = self.enabled_fields();
+ let field_idents = self.enabled_fields_idents();
+ let field_indexes = self.enabled_fields_indexes();
+ let field_types: Vec<_> = fields.iter().map(|f| &f.ty).collect();
+ let members: Vec<_> = field_idents
+ .iter()
+ .map(|ident| quote! { self.#ident })
+ .collect();
+ let trait_path = &self.trait_path;
+ let trait_path_with_params = if !self.trait_path_params.is_empty() {
+ let params = self.trait_path_params.iter();
+ quote! { #trait_path<#(#params),*> }
+ } else {
+ self.trait_path.clone()
+ };
+
+ let casted_traits: Vec<_> = field_types
+ .iter()
+ .map(|field_type| quote! { <#field_type as #trait_path_with_params> })
+ .collect();
+ let (impl_generics, ty_generics, where_clause) = self.generics.split_for_impl();
+ let input_type = &self.input.ident;
+ let (variant_name, variant_type) = self.variant.map_or_else(
+ || (None, quote! { #input_type }),
+ |v| {
+ let variant_name = &v.ident;
+ (Some(variant_name), quote! { #input_type::#variant_name })
+ },
+ );
+ MultiFieldData {
+ input_type,
+ variant_type,
+ variant_name,
+ variant_info: self.default_info.clone(),
+ fields,
+ field_types,
+ field_indexes,
+ members,
+ infos: self.enabled_infos(),
+ field_idents,
+ method_ident: &self.method_ident,
+ trait_path,
+ trait_path_with_params,
+ casted_traits,
+ impl_generics,
+ ty_generics,
+ where_clause,
+ state: self,
+ }
+ }
+
+ pub fn enabled_variant_data<'state>(
+ &'state self,
+ ) -> MultiVariantData<'input, 'state> {
+ if self.derive_type != DeriveType::Enum {
+ panic!("can only derive({}) for enum", self.trait_name)
+ }
+ let variants = self.enabled_variants();
+ let trait_path = &self.trait_path;
+ let (impl_generics, ty_generics, where_clause) = self.generics.split_for_impl();
+ MultiVariantData {
+ input_type: &self.input.ident,
+ variants,
+ variant_states: self.enabled_variant_states(),
+ infos: self.enabled_infos(),
+ trait_path,
+ impl_generics,
+ ty_generics,
+ where_clause,
+ }
+ }
+
+ fn enabled_variants(&self) -> Vec<&'input Variant> {
+ self.variants
+ .iter()
+ .zip(self.full_meta_infos.iter().map(|info| info.enabled))
+ .filter(|(_, ig)| *ig)
+ .map(|(v, _)| *v)
+ .collect()
+ }
+
+ fn enabled_variant_states(&self) -> Vec<&State<'input>> {
+ self.variant_states
+ .iter()
+ .zip(self.full_meta_infos.iter().map(|info| info.enabled))
+ .filter(|(_, ig)| *ig)
+ .map(|(v, _)| v)
+ .collect()
+ }
+
+ pub fn enabled_fields(&self) -> Vec<&'input Field> {
+ self.fields
+ .iter()
+ .zip(self.full_meta_infos.iter().map(|info| info.enabled))
+ .filter(|(_, ig)| *ig)
+ .map(|(f, _)| *f)
+ .collect()
+ }
+
+ fn field_idents(&self) -> Vec<TokenStream> {
+ if self.derive_type == DeriveType::Named {
+ self.fields
+ .iter()
+ .map(|f| {
+ f.ident
+ .as_ref()
+ .expect("Tried to get field names of a tuple struct")
+ .to_token_stream()
+ })
+ .collect()
+ } else {
+ let count = self.fields.len();
+ (0..count)
+ .map(|i| Index::from(i).to_token_stream())
+ .collect()
+ }
+ }
+
+ fn enabled_fields_idents(&self) -> Vec<TokenStream> {
+ self.field_idents()
+ .into_iter()
+ .zip(self.full_meta_infos.iter().map(|info| info.enabled))
+ .filter(|(_, ig)| *ig)
+ .map(|(f, _)| f)
+ .collect()
+ }
+
+ fn enabled_fields_indexes(&self) -> Vec<usize> {
+ self.full_meta_infos
+ .iter()
+ .map(|info| info.enabled)
+ .enumerate()
+ .filter(|(_, ig)| *ig)
+ .map(|(i, _)| i)
+ .collect()
+ }
+ fn enabled_infos(&self) -> Vec<FullMetaInfo> {
+ self.full_meta_infos
+ .iter()
+ .filter(|info| info.enabled)
+ .cloned()
+ .collect()
+ }
+}
+
+#[derive(Clone)]
+pub struct SingleFieldData<'input, 'state> {
+ pub input_type: &'input Ident,
+ pub field: &'input Field,
+ pub field_type: &'input Type,
+ pub field_ident: TokenStream,
+ pub member: TokenStream,
+ pub info: FullMetaInfo,
+ pub trait_path: &'state TokenStream,
+ pub trait_path_with_params: TokenStream,
+ pub casted_trait: TokenStream,
+ pub impl_generics: ImplGenerics<'state>,
+ pub ty_generics: TypeGenerics<'state>,
+ pub where_clause: Option<&'state WhereClause>,
+ multi_field_data: MultiFieldData<'input, 'state>,
+}
+
+#[derive(Clone)]
+pub struct MultiFieldData<'input, 'state> {
+ pub input_type: &'input Ident,
+ pub variant_type: TokenStream,
+ pub variant_name: Option<&'input Ident>,
+ pub variant_info: FullMetaInfo,
+ pub fields: Vec<&'input Field>,
+ pub field_types: Vec<&'input Type>,
+ pub field_idents: Vec<TokenStream>,
+ pub field_indexes: Vec<usize>,
+ pub members: Vec<TokenStream>,
+ pub infos: Vec<FullMetaInfo>,
+ pub method_ident: &'state Ident,
+ pub trait_path: &'state TokenStream,
+ pub trait_path_with_params: TokenStream,
+ pub casted_traits: Vec<TokenStream>,
+ pub impl_generics: ImplGenerics<'state>,
+ pub ty_generics: TypeGenerics<'state>,
+ pub where_clause: Option<&'state WhereClause>,
+ pub state: &'state State<'input>,
+}
+
+pub struct MultiVariantData<'input, 'state> {
+ pub input_type: &'input Ident,
+ pub variants: Vec<&'input Variant>,
+ pub variant_states: Vec<&'state State<'input>>,
+ pub infos: Vec<FullMetaInfo>,
+ pub trait_path: &'state TokenStream,
+ pub impl_generics: ImplGenerics<'state>,
+ pub ty_generics: TypeGenerics<'state>,
+ pub where_clause: Option<&'state WhereClause>,
+}
+
+impl<'input, 'state> MultiFieldData<'input, 'state> {
+ pub fn initializer<T: ToTokens>(&self, initializers: &[T]) -> TokenStream {
+ let MultiFieldData {
+ variant_type,
+ field_idents,
+ ..
+ } = self;
+ if self.state.derive_type == DeriveType::Named {
+ quote! { #variant_type{#(#field_idents: #initializers),*} }
+ } else {
+ quote! { #variant_type(#(#initializers),*) }
+ }
+ }
+ pub fn matcher<T: ToTokens>(
+ &self,
+ indexes: &[usize],
+ bindings: &[T],
+ ) -> TokenStream {
+ let MultiFieldData { variant_type, .. } = self;
+ let full_bindings = (0..self.state.fields.len()).map(|i| {
+ indexes.iter().position(|index| i == *index).map_or_else(
+ || quote! { _ },
+ |found_index| bindings[found_index].to_token_stream(),
+ )
+ });
+ if self.state.derive_type == DeriveType::Named {
+ let field_idents = self.state.field_idents();
+ quote! { #variant_type{#(#field_idents: #full_bindings),*} }
+ } else {
+ quote! { #variant_type(#(#full_bindings),*) }
+ }
+ }
+}
+
+impl<'input, 'state> SingleFieldData<'input, 'state> {
+ pub fn initializer<T: ToTokens>(&self, initializers: &[T]) -> TokenStream {
+ self.multi_field_data.initializer(initializers)
+ }
+}
+
+fn get_meta_info(
+ trait_attr: &str,
+ attrs: &[Attribute],
+ allowed_attr_params: &[&str],
+) -> Result<MetaInfo> {
+ let mut it = attrs.iter().filter(|a| {
+ a.meta
+ .path()
+ .segments
+ .first()
+ .map(|p| p.ident == trait_attr)
+ .unwrap_or_default()
+ });
+
+ let mut info = MetaInfo::default();
+
+ let Some(attr) = it.next() else {
+ return Ok(info);
+ };
+
+ if allowed_attr_params.is_empty() {
+ return Err(Error::new(attr.span(), "Attribute is not allowed here"));
+ }
+
+ info.enabled = Some(true);
+
+ if let Some(another_attr) = it.next() {
+ return Err(Error::new(
+ another_attr.span(),
+ "Only a single attribute is allowed",
+ ));
+ }
+
+ let list = match &attr.meta {
+ syn::Meta::Path(_) => {
+ if allowed_attr_params.contains(&"ignore") {
+ return Ok(info);
+ } else {
+ return Err(Error::new(
+ attr.span(),
+ format!(
+ "Empty attribute is not allowed, add one of the following parameters: {}",
+ allowed_attr_params.join(", "),
+ ),
+ ));
+ }
+ }
+ syn::Meta::List(list) => list,
+ syn::Meta::NameValue(val) => {
+ return Err(Error::new(
+ val.span(),
+ "Attribute doesn't support name-value format here",
+ ));
+ }
+ };
+
+ parse_punctuated_nested_meta(
+ &mut info,
+ &list.parse_args_with(Punctuated::parse_terminated)?,
+ allowed_attr_params,
+ None,
+ )?;
+
+ Ok(info)
+}
+
+fn parse_punctuated_nested_meta(
+ info: &mut MetaInfo,
+ meta: &Punctuated<polyfill::Meta, Token![,]>,
+ allowed_attr_params: &[&str],
+ wrapper_name: Option<&str>,
+) -> Result<()> {
+ for meta in meta.iter() {
+ match meta {
+ polyfill::Meta::List(list) if list.path.is_ident("not") => {
+ if wrapper_name.is_some() {
+ // Only single top-level `not` attribute is allowed.
+ return Err(Error::new(
+ list.span(),
+ "Attribute doesn't support multiple multiple or nested `not` parameters",
+ ));
+ }
+ parse_punctuated_nested_meta(
+ info,
+ &list.parse_args_with(Punctuated::parse_terminated)?,
+ allowed_attr_params,
+ Some("not"),
+ )?;
+ }
+
+ polyfill::Meta::List(list) => {
+ let path = &list.path;
+ if !allowed_attr_params.iter().any(|param| path.is_ident(param)) {
+ return Err(Error::new(
+ meta.span(),
+ format!(
+ "Attribute nested parameter not supported. \
+ Supported attribute parameters are: {}",
+ allowed_attr_params.join(", "),
+ ),
+ ));
+ }
+
+ let mut parse_nested = true;
+
+ let attr_name = path.get_ident().unwrap().to_string();
+ match (wrapper_name, attr_name.as_str()) {
+ (None, "owned") => info.owned = Some(true),
+ (None, "ref") => info.ref_ = Some(true),
+ (None, "ref_mut") => info.ref_mut = Some(true),
+
+ #[cfg(any(feature = "from", feature = "into"))]
+ (None, "types")
+ | (Some("owned"), "types")
+ | (Some("ref"), "types")
+ | (Some("ref_mut"), "types") => {
+ parse_nested = false;
+ for meta in &list.parse_args_with(
+ Punctuated::<polyfill::NestedMeta, syn::token::Comma>::parse_terminated,
+ )? {
+ let typ: syn::Type = match meta {
+ polyfill::NestedMeta::Meta(meta) => {
+ let polyfill::Meta::Path(path) = meta else {
+ return Err(Error::new(
+ meta.span(),
+ format!(
+ "Attribute doesn't support type {}",
+ quote! { #meta },
+ ),
+ ));
+ };
+ syn::TypePath {
+ qself: None,
+ path: path.clone().into(),
+ }
+ .into()
+ }
+ polyfill::NestedMeta::Lit(syn::Lit::Str(s)) => s.parse()?,
+ polyfill::NestedMeta::Lit(lit) => return Err(Error::new(
+ lit.span(),
+ "Attribute doesn't support nested literals here",
+ )),
+ };
+
+ for ref_type in wrapper_name
+ .map(|n| vec![RefType::from_attr_name(n)])
+ .unwrap_or_else(|| {
+ vec![RefType::No, RefType::Ref, RefType::Mut]
+ })
+ {
+ if info
+ .types
+ .entry(ref_type)
+ .or_default()
+ .replace(typ.clone())
+ .is_some()
+ {
+ return Err(Error::new(
+ typ.span(),
+ format!(
+ "Duplicate type `{}` specified",
+ quote! { #path },
+ ),
+ ));
+ }
+ }
+ }
+ }
+
+ _ => {
+ return Err(Error::new(
+ list.span(),
+ format!(
+ "Attribute doesn't support nested parameter `{}` here",
+ quote! { #path },
+ ),
+ ))
+ }
+ };
+
+ if parse_nested {
+ parse_punctuated_nested_meta(
+ info,
+ &list.parse_args_with(Punctuated::parse_terminated)?,
+ allowed_attr_params,
+ Some(&attr_name),
+ )?;
+ }
+ }
+
+ polyfill::Meta::Path(path) => {
+ if !allowed_attr_params.iter().any(|param| path.is_ident(param)) {
+ return Err(Error::new(
+ meta.span(),
+ format!(
+ "Attribute parameter not supported. \
+ Supported attribute parameters are: {}",
+ allowed_attr_params.join(", "),
+ ),
+ ));
+ }
+
+ let attr_name = path.get_ident().unwrap().to_string();
+ match (wrapper_name, attr_name.as_str()) {
+ (None, "ignore") => info.enabled = Some(false),
+ (None, "forward") => info.forward = Some(true),
+ (Some("not"), "forward") => info.forward = Some(false),
+ (None, "owned") => info.owned = Some(true),
+ (None, "ref") => info.ref_ = Some(true),
+ (None, "ref_mut") => info.ref_mut = Some(true),
+ (None, "source") => info.source = Some(true),
+ (Some("not"), "source") => info.source = Some(false),
+ (None, "backtrace") => info.backtrace = Some(true),
+ (Some("not"), "backtrace") => info.backtrace = Some(false),
+ _ => {
+ return Err(Error::new(
+ path.span(),
+ format!(
+ "Attribute doesn't support parameter `{}` here",
+ quote! { #path }
+ ),
+ ))
+ }
+ }
+ }
+ }
+ }
+
+ Ok(())
+}
+
+// TODO: Remove this eventually, once all macros migrate to
+// custom typed attributes parsing.
+/// Polyfill for [`syn`] 1.x AST.
+pub(crate) mod polyfill {
+ use proc_macro2::TokenStream;
+ use quote::ToTokens;
+ use syn::{
+ ext::IdentExt as _,
+ parse::{Parse, ParseStream, Parser},
+ token, Token,
+ };
+
+ #[derive(Clone)]
+ pub(crate) enum PathOrKeyword {
+ Path(syn::Path),
+ Keyword(syn::Ident),
+ }
+
+ impl Parse for PathOrKeyword {
+ fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
+ if input.fork().parse::<syn::Path>().is_ok() {
+ return input.parse().map(Self::Path);
+ }
+ syn::Ident::parse_any(input).map(Self::Keyword)
+ }
+ }
+
+ impl ToTokens for PathOrKeyword {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ match self {
+ Self::Path(p) => p.to_tokens(tokens),
+ Self::Keyword(i) => i.to_tokens(tokens),
+ }
+ }
+ }
+
+ impl PathOrKeyword {
+ pub(crate) fn is_ident<I: ?Sized>(&self, ident: &I) -> bool
+ where
+ syn::Ident: PartialEq<I>,
+ {
+ match self {
+ Self::Path(p) => p.is_ident(ident),
+ Self::Keyword(i) => i == ident,
+ }
+ }
+
+ pub fn get_ident(&self) -> Option<&syn::Ident> {
+ match self {
+ Self::Path(p) => p.get_ident(),
+ Self::Keyword(i) => Some(i),
+ }
+ }
+ }
+
+ impl From<PathOrKeyword> for syn::Path {
+ fn from(p: PathOrKeyword) -> Self {
+ match p {
+ PathOrKeyword::Path(p) => p,
+ PathOrKeyword::Keyword(i) => i.into(),
+ }
+ }
+ }
+
+ #[derive(Clone)]
+ pub(crate) struct MetaList {
+ pub(crate) path: PathOrKeyword,
+ pub(crate) tokens: TokenStream,
+ }
+
+ impl Parse for MetaList {
+ fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
+ let path = input.parse::<PathOrKeyword>()?;
+ let tokens;
+ _ = syn::parenthesized!(tokens in input);
+ Ok(Self {
+ path,
+ tokens: tokens.parse()?,
+ })
+ }
+ }
+
+ impl ToTokens for MetaList {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.path.to_tokens(tokens);
+ token::Paren::default()
+ .surround(tokens, |tokens| self.tokens.to_tokens(tokens))
+ }
+ }
+
+ impl MetaList {
+ pub fn parse_args_with<F: Parser>(&self, parser: F) -> syn::Result<F::Output> {
+ parser.parse2(self.tokens.clone())
+ }
+ }
+
+ #[derive(Clone)]
+ pub(crate) enum Meta {
+ Path(PathOrKeyword),
+ List(MetaList),
+ }
+
+ impl Parse for Meta {
+ fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
+ let path = input.parse::<PathOrKeyword>()?;
+ Ok(if input.peek(token::Paren) {
+ let tokens;
+ _ = syn::parenthesized!(tokens in input);
+ Self::List(MetaList {
+ path,
+ tokens: tokens.parse()?,
+ })
+ } else {
+ Self::Path(path)
+ })
+ }
+ }
+
+ impl ToTokens for Meta {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ match self {
+ Self::Path(p) => p.to_tokens(tokens),
+ Self::List(l) => l.to_tokens(tokens),
+ }
+ }
+ }
+
+ #[derive(Clone)]
+ pub(crate) enum NestedMeta {
+ Meta(Meta),
+ Lit(syn::Lit),
+ }
+
+ impl Parse for NestedMeta {
+ fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
+ if input.peek(syn::Lit)
+ && !(input.peek(syn::LitBool) && input.peek2(Token![=]))
+ {
+ input.parse().map(Self::Lit)
+ } else if input.peek(syn::Ident::peek_any)
+ || input.peek(Token![::]) && input.peek3(syn::Ident::peek_any)
+ {
+ input.parse().map(Self::Meta)
+ } else {
+ Err(input.error("expected identifier or literal"))
+ }
+ }
+ }
+
+ impl ToTokens for NestedMeta {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ match self {
+ Self::Meta(m) => m.to_tokens(tokens),
+ Self::Lit(l) => l.to_tokens(tokens),
+ }
+ }
+ }
+}
+
+#[derive(Clone, Debug, Default)]
+pub struct FullMetaInfo {
+ pub enabled: bool,
+ pub forward: bool,
+ pub owned: bool,
+ pub ref_: bool,
+ pub ref_mut: bool,
+ pub info: MetaInfo,
+}
+
+#[derive(Clone, Debug, Default)]
+pub struct MetaInfo {
+ pub enabled: Option<bool>,
+ pub forward: Option<bool>,
+ pub owned: Option<bool>,
+ pub ref_: Option<bool>,
+ pub ref_mut: Option<bool>,
+ pub source: Option<bool>,
+ pub backtrace: Option<bool>,
+ #[cfg(any(feature = "from", feature = "into"))]
+ pub types: HashMap<RefType, HashSet<syn::Type>>,
+}
+
+impl MetaInfo {
+ fn into_full(self, defaults: FullMetaInfo) -> FullMetaInfo {
+ FullMetaInfo {
+ enabled: self.enabled.unwrap_or(defaults.enabled),
+ forward: self.forward.unwrap_or(defaults.forward),
+ owned: self.owned.unwrap_or(defaults.owned),
+ ref_: self.ref_.unwrap_or(defaults.ref_),
+ ref_mut: self.ref_mut.unwrap_or(defaults.ref_mut),
+ info: self,
+ }
+ }
+}
+
+impl FullMetaInfo {
+ pub fn ref_types(&self) -> Vec<RefType> {
+ let mut ref_types = vec![];
+ if self.owned {
+ ref_types.push(RefType::No);
+ }
+ if self.ref_ {
+ ref_types.push(RefType::Ref);
+ }
+ if self.ref_mut {
+ ref_types.push(RefType::Mut);
+ }
+ ref_types
+ }
+}
+
+pub fn get_if_type_parameter_used_in_type(
+ type_parameters: &HashSet<syn::Ident>,
+ ty: &syn::Type,
+) -> Option<syn::Type> {
+ is_type_parameter_used_in_type(type_parameters, ty).then(|| match ty {
+ syn::Type::Reference(syn::TypeReference { elem: ty, .. }) => (**ty).clone(),
+ ty => ty.clone(),
+ })
+}
+
+pub fn is_type_parameter_used_in_type(
+ type_parameters: &HashSet<syn::Ident>,
+ ty: &syn::Type,
+) -> bool {
+ match ty {
+ syn::Type::Path(ty) => {
+ if let Some(qself) = &ty.qself {
+ if is_type_parameter_used_in_type(type_parameters, &qself.ty) {
+ return true;
+ }
+ }
+
+ if let Some(segment) = ty.path.segments.first() {
+ if type_parameters.contains(&segment.ident) {
+ return true;
+ }
+ }
+
+ ty.path.segments.iter().any(|segment| {
+ if let syn::PathArguments::AngleBracketed(arguments) =
+ &segment.arguments
+ {
+ arguments.args.iter().any(|argument| match argument {
+ syn::GenericArgument::Type(ty) => {
+ is_type_parameter_used_in_type(type_parameters, ty)
+ }
+ syn::GenericArgument::Constraint(constraint) => {
+ type_parameters.contains(&constraint.ident)
+ }
+ _ => false,
+ })
+ } else {
+ false
+ }
+ })
+ }
+
+ syn::Type::Reference(ty) => {
+ is_type_parameter_used_in_type(type_parameters, &ty.elem)
+ }
+
+ _ => false,
+ }
+}
+
+#[cfg(any(feature = "from", feature = "into"))]
+mod either {
+ use proc_macro2::TokenStream;
+ use quote::ToTokens;
+
+ /// Either [`Left`] or [`Right`].
+ ///
+ /// [`Left`]: Either::Left
+ /// [`Right`]: Either::Right
+ pub(crate) enum Either<L, R> {
+ /// Left variant.
+ Left(L),
+
+ /// Right variant.
+ Right(R),
+ }
+
+ impl<L, R, T> Iterator for Either<L, R>
+ where
+ L: Iterator<Item = T>,
+ R: Iterator<Item = T>,
+ {
+ type Item = T;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ match self {
+ Either::Left(left) => left.next(),
+ Either::Right(right) => right.next(),
+ }
+ }
+ }
+
+ impl<L, R> ToTokens for Either<L, R>
+ where
+ L: ToTokens,
+ R: ToTokens,
+ {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ match self {
+ Either::Left(l) => l.to_tokens(tokens),
+ Either::Right(r) => r.to_tokens(tokens),
+ }
+ }
+ }
+}
+
+#[cfg(any(feature = "from", feature = "into"))]
+mod fields_ext {
+ use std::{cmp, iter};
+
+ use proc_macro2::TokenStream;
+ use syn::{punctuated, spanned::Spanned as _};
+
+ use crate::parsing;
+
+ use super::Either;
+
+ /// Abstraction over `.len()` method to use it on type parameters.
+ pub(crate) trait Len {
+ /// Returns number of fields.
+ fn len(&self) -> usize;
+ }
+
+ impl Len for syn::Fields {
+ fn len(&self) -> usize {
+ self.len()
+ }
+ }
+
+ impl<T> Len for Vec<T> {
+ fn len(&self) -> usize {
+ self.len()
+ }
+ }
+
+ /// [`syn::Fields`] extension.
+ pub(crate) trait FieldsExt: Len {
+ /// Validates the provided [`parsing::Type`] against these [`syn::Fields`].
+ fn validate_type<'t>(
+ &self,
+ ty: &'t parsing::Type,
+ ) -> syn::Result<
+ Either<punctuated::Iter<'t, TokenStream>, iter::Once<&'t TokenStream>>,
+ > {
+ match ty {
+ parsing::Type::Tuple { items, .. } if self.len() > 1 => {
+ match self.len().cmp(&items.len()) {
+ cmp::Ordering::Greater => {
+ return Err(syn::Error::new(
+ ty.span(),
+ format!(
+ "wrong tuple length: expected {}, found {}. \
+ Consider adding {} more type{}: `({})`",
+ self.len(),
+ items.len(),
+ self.len() - items.len(),
+ if self.len() - items.len() > 1 {
+ "s"
+ } else {
+ ""
+ },
+ items
+ .iter()
+ .map(|item| item.to_string())
+ .chain(
+ (0..(self.len() - items.len()))
+ .map(|_| "_".to_string())
+ )
+ .collect::<Vec<_>>()
+ .join(", "),
+ ),
+ ));
+ }
+ cmp::Ordering::Less => {
+ return Err(syn::Error::new(
+ ty.span(),
+ format!(
+ "wrong tuple length: expected {}, found {}. \
+ Consider removing last {} type{}: `({})`",
+ self.len(),
+ items.len(),
+ items.len() - self.len(),
+ if items.len() - self.len() > 1 {
+ "s"
+ } else {
+ ""
+ },
+ items
+ .iter()
+ .take(self.len())
+ .map(ToString::to_string)
+ .collect::<Vec<_>>()
+ .join(", "),
+ ),
+ ));
+ }
+ cmp::Ordering::Equal => {}
+ }
+ }
+ parsing::Type::Other(other) if self.len() > 1 => {
+ if self.len() > 1 {
+ return Err(syn::Error::new(
+ other.span(),
+ format!(
+ "expected tuple: `({}, {})`",
+ other,
+ (0..(self.len() - 1))
+ .map(|_| "_")
+ .collect::<Vec<_>>()
+ .join(", "),
+ ),
+ ));
+ }
+ }
+ parsing::Type::Tuple { .. } | parsing::Type::Other(_) => {}
+ }
+ Ok(match ty {
+ parsing::Type::Tuple { items, .. } => Either::Left(items.iter()),
+ parsing::Type::Other(other) => Either::Right(iter::once(other)),
+ })
+ }
+ }
+
+ impl<T: Len + ?Sized> FieldsExt for T {}
+}