summaryrefslogtreecommitdiffstats
path: root/third_party/rust/darling
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/darling
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--third_party/rust/darling/.cargo-checksum.json1
-rw-r--r--third_party/rust/darling/CHANGELOG.md107
-rw-r--r--third_party/rust/darling/Cargo.toml45
-rw-r--r--third_party/rust/darling/LICENSE21
-rw-r--r--third_party/rust/darling/README.md113
-rw-r--r--third_party/rust/darling/examples/automatic_bounds.rs78
-rw-r--r--third_party/rust/darling/examples/consume_fields.rs175
-rw-r--r--third_party/rust/darling/examples/fallible_read.rs87
-rw-r--r--third_party/rust/darling/examples/supports_struct.rs62
-rw-r--r--third_party/rust/darling/src/lib.rs98
-rw-r--r--third_party/rust/darling/src/macros_public.rs98
-rw-r--r--third_party/rust/darling/tests/accrue_errors.rs108
-rw-r--r--third_party/rust/darling/tests/computed_bound.rs46
-rw-r--r--third_party/rust/darling/tests/custom_bound.rs25
-rw-r--r--third_party/rust/darling/tests/defaults.rs32
-rw-r--r--third_party/rust/darling/tests/enums_newtype.rs96
-rw-r--r--third_party/rust/darling/tests/enums_struct.rs16
-rw-r--r--third_party/rust/darling/tests/enums_unit.rs16
-rw-r--r--third_party/rust/darling/tests/error.rs55
-rw-r--r--third_party/rust/darling/tests/from_generics.rs186
-rw-r--r--third_party/rust/darling/tests/from_type_param.rs65
-rw-r--r--third_party/rust/darling/tests/from_type_param_default.rs59
-rw-r--r--third_party/rust/darling/tests/from_variant.rs27
-rw-r--r--third_party/rust/darling/tests/generics.rs27
-rw-r--r--third_party/rust/darling/tests/happy_path.rs75
-rw-r--r--third_party/rust/darling/tests/multiple.rs36
-rw-r--r--third_party/rust/darling/tests/newtype.rs32
-rw-r--r--third_party/rust/darling/tests/skip.rs52
-rw-r--r--third_party/rust/darling/tests/split_declaration.rs78
-rw-r--r--third_party/rust/darling/tests/suggestions.rs34
-rw-r--r--third_party/rust/darling/tests/supports.rs85
-rw-r--r--third_party/rust/darling_core/.cargo-checksum.json1
-rw-r--r--third_party/rust/darling_core/Cargo.toml42
-rw-r--r--third_party/rust/darling_core/LICENSE21
-rw-r--r--third_party/rust/darling_core/src/ast/data.rs360
-rw-r--r--third_party/rust/darling_core/src/ast/generics.rs194
-rw-r--r--third_party/rust/darling_core/src/ast/mod.rs7
-rw-r--r--third_party/rust/darling_core/src/codegen/attr_extractor.rs110
-rw-r--r--third_party/rust/darling_core/src/codegen/default_expr.rs46
-rw-r--r--third_party/rust/darling_core/src/codegen/error.rs48
-rw-r--r--third_party/rust/darling_core/src/codegen/field.rs206
-rw-r--r--third_party/rust/darling_core/src/codegen/from_derive_impl.rs146
-rw-r--r--third_party/rust/darling_core/src/codegen/from_field.rs115
-rw-r--r--third_party/rust/darling_core/src/codegen/from_meta_impl.rs136
-rw-r--r--third_party/rust/darling_core/src/codegen/from_type_param.rs114
-rw-r--r--third_party/rust/darling_core/src/codegen/from_variant_impl.rs118
-rw-r--r--third_party/rust/darling_core/src/codegen/mod.rs29
-rw-r--r--third_party/rust/darling_core/src/codegen/outer_from_impl.rs60
-rw-r--r--third_party/rust/darling_core/src/codegen/trait_impl.rs145
-rw-r--r--third_party/rust/darling_core/src/codegen/variant.rs158
-rw-r--r--third_party/rust/darling_core/src/codegen/variant_data.rs91
-rw-r--r--third_party/rust/darling_core/src/derive.rs54
-rw-r--r--third_party/rust/darling_core/src/error/kind.rs201
-rw-r--r--third_party/rust/darling_core/src/error/mod.rs520
-rw-r--r--third_party/rust/darling_core/src/from_derive_input.rs26
-rw-r--r--third_party/rust/darling_core/src/from_field.rs38
-rw-r--r--third_party/rust/darling_core/src/from_generic_param.rs21
-rw-r--r--third_party/rust/darling_core/src/from_generics.rs27
-rw-r--r--third_party/rust/darling_core/src/from_meta.rs500
-rw-r--r--third_party/rust/darling_core/src/from_type_param.rs32
-rw-r--r--third_party/rust/darling_core/src/from_variant.rs33
-rw-r--r--third_party/rust/darling_core/src/lib.rs47
-rw-r--r--third_party/rust/darling_core/src/macros_private.rs12
-rw-r--r--third_party/rust/darling_core/src/macros_public.rs98
-rw-r--r--third_party/rust/darling_core/src/options/core.rs154
-rw-r--r--third_party/rust/darling_core/src/options/forward_attrs.rs31
-rw-r--r--third_party/rust/darling_core/src/options/from_derive.rs100
-rw-r--r--third_party/rust/darling_core/src/options/from_field.rs79
-rw-r--r--third_party/rust/darling_core/src/options/from_meta.rs51
-rw-r--r--third_party/rust/darling_core/src/options/from_type_param.rs79
-rw-r--r--third_party/rust/darling_core/src/options/from_variant.rs76
-rw-r--r--third_party/rust/darling_core/src/options/input_field.rs138
-rw-r--r--third_party/rust/darling_core/src/options/input_variant.rs98
-rw-r--r--third_party/rust/darling_core/src/options/mod.rs154
-rw-r--r--third_party/rust/darling_core/src/options/outer_from.rs82
-rw-r--r--third_party/rust/darling_core/src/options/shape.rs268
-rw-r--r--third_party/rust/darling_core/src/usage/generics_ext.rs24
-rw-r--r--third_party/rust/darling_core/src/usage/ident_set.rs8
-rw-r--r--third_party/rust/darling_core/src/usage/lifetimes.rs326
-rw-r--r--third_party/rust/darling_core/src/usage/mod.rs111
-rw-r--r--third_party/rust/darling_core/src/usage/options.rs58
-rw-r--r--third_party/rust/darling_core/src/usage/type_params.rs357
-rw-r--r--third_party/rust/darling_core/src/util/ident_string.rs155
-rw-r--r--third_party/rust/darling_core/src/util/ignored.rs52
-rw-r--r--third_party/rust/darling_core/src/util/mod.rs112
-rw-r--r--third_party/rust/darling_core/src/util/over_ride.rs150
-rw-r--r--third_party/rust/darling_core/src/util/path_list.rs102
-rw-r--r--third_party/rust/darling_core/src/util/spanned_value.rs104
-rw-r--r--third_party/rust/darling_core/src/util/with_original.rs35
-rw-r--r--third_party/rust/darling_macro/.cargo-checksum.json1
-rw-r--r--third_party/rust/darling_macro/Cargo.toml30
-rw-r--r--third_party/rust/darling_macro/LICENSE21
-rw-r--r--third_party/rust/darling_macro/src/lib.rs41
93 files changed, 8788 insertions, 0 deletions
diff --git a/third_party/rust/darling/.cargo-checksum.json b/third_party/rust/darling/.cargo-checksum.json
new file mode 100644
index 0000000000..2392782177
--- /dev/null
+++ b/third_party/rust/darling/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"CHANGELOG.md":"9a83b921a832799b871634e4cca8a5c92cb9b901626009fc46c2f480db9e20f2","Cargo.toml":"6fa2ba78e86577539ad3ff71cb44109bf5b500d7b3b1c59f9484b61288546da7","LICENSE":"8ea93490d74a5a1b1af3ff71d786271b3f1e5f0bea79ac16e02ec533cef040d6","README.md":"5b591026cb7c3ed964d46779f323a2b45f89aa18d2bc5f63519126cb3b7efed9","examples/automatic_bounds.rs":"2540e6eb0761755737927a0e01d94956a1e9db04db67ae1aba3110415759fac4","examples/consume_fields.rs":"ebf4bd8baf4e54ccaa926f910957183d6a5b1decaa87ab5ebcca6c8d38b6c6b3","examples/fallible_read.rs":"aa9d1e0aaba8f3eb4580e94e133839f7eb77fca61beed254f3d5e0f6d6981f00","examples/supports_struct.rs":"d69124e09d3d6b8e04a3af07a6af96c5df7cbd3d6953a51657b39088cc2c2de7","src/lib.rs":"07da20edb52c4aba30f2b680b28ca96cf995859566b0db3b1d2e0ee967249a18","src/macros_public.rs":"3ed7eb99f309d9cd600d3a09ff4dcf5cc5d787fb49e8e5ead6bb00e31e5e6793","tests/accrue_errors.rs":"f5ac2d8cb0a12284a845d25b9472c4605aa5e8c1cd66a6dd6ad64f1c749b2caf","tests/computed_bound.rs":"2313da96a250b5948ca06bf86cb7158b55a59eba75334aa8ba27a46b28ede6b5","tests/custom_bound.rs":"4dd3e8fd76734d8f262e857773f53a820229ad6e10fe6fbbbe1f636c7da9eab0","tests/defaults.rs":"b544be90d18be26305a757e8468bf8735356889b59c167294d118e32ee7f82ea","tests/enums_newtype.rs":"a09af70072e566bee1f6cad91675f3553c47333e51a0e389ebb47ae82de776a8","tests/enums_struct.rs":"e0097d7f947cf9e4612c9450c55ea5075c7f6fcbbf8cac7176449d92eebc9343","tests/enums_unit.rs":"8c075d5897b60b58cb71d6306e7fdd80851f5a147ae3010ba70ea100007364a3","tests/error.rs":"465f7634fa23f0076c93a9c5fc16ccde16119b874d64c8dabaf275b6b7ae61f2","tests/from_generics.rs":"79230ad21e8482cf6e6ceb0c74303bc0cdf77fbb951f46a6ba1006ecf1248fd5","tests/from_type_param.rs":"7c97745cdcea18a2d6f51e4da7426055a078287bf9f2c93d487057195efa2b30","tests/from_type_param_default.rs":"80787ef6527e7f76c2aac93b1f35a006a9c5e0df8deed61698eaac1127278021","tests/from_variant.rs":"2e804326302a62b979eae963e88f0a2cdb6a21ee9667407c361d178f8c0aadba","tests/generics.rs":"e08aea8a8de8f03e3c243bde650e250defbe340cef3e4c06935b2b3e46d2a376","tests/happy_path.rs":"c32daa68e2becdc2d6204985a19b437cfb49d7f1680e890578f0760dc9749b77","tests/multiple.rs":"0391be49bab07771d7e37d35fe17f6d9bf1aa6dc57e2c0e5c0912ab8e043128f","tests/newtype.rs":"3f029724467abc7a33aaf7b6a1feb7b6898eba578576afff338e73deb9fd2b3b","tests/skip.rs":"604861aa4d1dfdc4e5f38f8261be19b7240c650eb493b64ce0178f54c24a8d2d","tests/split_declaration.rs":"f509390f88549164af9218f1e5b07564b169a4481a20b738432ffb03c517b599","tests/suggestions.rs":"0afb756949be876aaae76974f119be811c783fb134a54978ff0453c537ff3174","tests/supports.rs":"8564709d7e63b124cda91f7e21c890037200e533d0403ffd7eb075403cf58926"},"package":"3fe629a532efad5526454efb0700f86d5ad7ff001acb37e431c8bf017a432a8e"} \ No newline at end of file
diff --git a/third_party/rust/darling/CHANGELOG.md b/third_party/rust/darling/CHANGELOG.md
new file mode 100644
index 0000000000..7698ba05ee
--- /dev/null
+++ b/third_party/rust/darling/CHANGELOG.md
@@ -0,0 +1,107 @@
+# Changelog
+
+## v0.10.1 (September 25, 2019)
+- Fix test compilation errors [#81](https://github.com/TedDriggs/darling/pull/81)
+
+## v0.10.0 (August 15, 2019)
+- Bump syn and quote to 1.0 [#79](https://github.com/TedDriggs/darling/pull/79)
+- Increase rust version to 1.31
+
+## v0.9.0 (March 20, 2019)
+- Enable "did you mean" suggestions by default
+- Make `darling_core::{codegen, options}` private [#58](https://github.com/TedDriggs/darling/issues/58)
+- Fix `Override::as_mut`: [#66](https://github.com/TedDriggs/darling/issues/66)
+
+## v0.8.6 (March 18, 2019)
+- Added "did you mean" suggestions for unknown fields behind the `suggestions` flag [#60](https://github.com/TedDriggs/issues/60)
+- Added `Error::unknown_field_with_alts` to support the suggestion use-case.
+- Added `ast::Fields::len` and `ast::Fields::is_empty` methods.
+
+## v0.8.5 (February 4, 2019)
+- Accept unquoted positive numeric literals [#52](https://github.com/TedDriggs/issues/52)
+- Add `FromMeta` to the `syn::Lit` enum and its variants
+- Improve error message for unexpected literal formats to not say "other"
+
+## v0.8.4 (February 4, 2019)
+- Use `syn::Error` to provide precise errors before `proc_macro::Diagnostic` is available
+- Add `diagnostics` feature flag to toggle between stable and unstable error backends
+- Attach error information in more contexts
+- Add `allow_unknown_fields` to support parsing the same attribute multiple times for different macros [#51](https://github.com/darling/issues/51)
+- Proc-macro authors will now see better errors in `darling` attributes
+
+## v0.8.3 (January 21, 2019)
+- Attach spans to errors in generated trait impls [#37](https://github.com/darling/issues/37)
+- Attach spans to errors for types with provided bespoke implementations
+- Deprecate `set_span` from 0.8.2, as spans should never be broadened after being initially set
+
+## v0.8.2 (January 17, 2019)
+- Add spans to errors to make quality warnings and errors easy in darling. This is blocked on diagnostics stabilizing.
+- Add `darling::util::SpannedValue` so proc-macro authors can remember position information alongside parsed values.
+
+## v0.8.0
+- Update dependency on `syn` to 0.15 [#44](https://github.com/darling/pull/44). Thanks to @hcpl
+
+## v0.7.0 (July 24, 2018)
+- Update dependencies on `syn` and `proc-macro2`
+- Add `util::IdentString`, which acts as an Ident or its string equivalent
+
+## v0.6.3 (May 22, 2018)
+- Add support for `Uses*` traits in where predicates
+
+## v0.6.2 (May 22, 2018)
+- Add `usage` module for tracking type param and lifetime usage in generic declarations
+ - Add `UsesTypeParams` and `CollectsTypeParams` traits [#37](https://github.com/darling/issues/37)
+ - Add `UsesLifetimes` and `CollectLifetimes` traits [#41](https://github.com/darling/pull/41)
+- Don't add `FromMeta` bounds to type parameters only used by skipped fields [#40](https://github.com/darling/pull/40)
+
+## v0.6.1 (May 17, 2018)
+- Fix an issue where the `syn` update broke shape validation [#36](https://github.com/TedDriggs/darling/issues/36)
+
+## v0.6.0 (May 15, 2018)
+
+### Breaking Changes
+- Renamed `FromMetaItem` to `FromMeta`, and renamed `from_meta_item` method to `from_meta`
+- Added dedicated `derive(FromMetaItem)` which panics and redirects users to `FromMeta`
+
+## v0.5.0 (May 10, 2018)
+- Add `ast::Generics` and `ast::GenericParam` to work with generics in a manner similar to `ast::Data`
+- Add `ast::GenericParamExt` to support alternate representations of generic parameters
+- Add `util::WithOriginal` to get a parsed representation and syn's own struct for a syntax block
+- Add `FromGenerics` and `FromGenericParam` traits (without derive support)
+- Change generated code for `generics` magic field to invoke `FromGenerics` trait during parsing
+- Add `FromTypeParam` trait [#30](https://github.com/TedDriggs/darling/pull/30). Thanks to @upsuper
+
+## v0.4.0 (April 5, 2018)
+- Update dependencies on `proc-macro`, `quote`, and `syn` [#26](https://github.com/TedDriggs/darling/pull/26). Thanks to @hcpl
+
+## v0.3.3 (April 2, 2018)
+**YANKED**
+
+## v0.3.2 (March 13, 2018)
+- Derive `Default` on `darling::Ignored` (fixes [#25](https://github.com/TedDriggs/darling/issues/25)).
+
+## v0.3.1 (March 7, 2018)
+- Support proc-macro2/nightly [#24](https://github.com/TedDriggs/darling/pull/24). Thanks to @kdy1
+
+## v0.3.0 (January 26, 2018)
+
+### Breaking Changes
+- Update `syn` to 0.12 [#20](https://github.com/TedDriggs/darling/pull/20). Thanks to @Eijebong
+- Update `quote` to 0.4 [#20](https://github.com/TedDriggs/darling/pull/20). Thanks to @Eijebong
+- Rename magic field `body` in derived `FromDeriveInput` structs to `data` to stay in sync with `syn`
+- Rename magic field `data` in derived `FromVariant` structs to `fields` to stay in sync with `syn`
+
+## v0.2.2 (December 5, 2017)
+
+- Update `lazy_static` to 1.0 [#15](https://github.com/TedDriggs/darling/pull/16). Thanks to @Eijebong
+
+## v0.2.1 (November 28, 2017)
+
+- Add `impl FromMetaItem` for integer types [#15](https://github.com/TedDriggs/darling/pull/15)
+
+## v0.2.0 (June 18, 2017)
+
+- Added support for returning multiple errors from parsing [#5](https://github.com/TedDriggs/darling/pull/5)
+- Derived impls no longer return on first error [#5](https://github.com/TedDriggs/darling/pull/5)
+- Removed default types for `V` and `F` from `ast::Body`
+- Enum variants are automatically converted to snake_case [#12](https://github.com/TedDriggs/darling/pull/12)
diff --git a/third_party/rust/darling/Cargo.toml b/third_party/rust/darling/Cargo.toml
new file mode 100644
index 0000000000..0fd6008b56
--- /dev/null
+++ b/third_party/rust/darling/Cargo.toml
@@ -0,0 +1,45 @@
+# 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 believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "darling"
+version = "0.10.1"
+authors = ["Ted Driggs <ted.driggs@outlook.com>"]
+exclude = ["/.travis.yml", "/publish.sh"]
+description = "A proc-macro library for reading attributes into structs when\nimplementing custom derives.\n"
+documentation = "https://docs.rs/darling/0.10.1"
+readme = "README.md"
+license = "MIT"
+repository = "https://github.com/TedDriggs/darling"
+[dependencies.darling_core]
+version = "=0.10.1"
+
+[dependencies.darling_macro]
+version = "=0.10.1"
+[dev-dependencies.proc-macro2]
+version = "1"
+
+[dev-dependencies.quote]
+version = "1"
+
+[dev-dependencies.syn]
+version = "1"
+
+[features]
+default = ["suggestions"]
+diagnostics = ["darling_core/diagnostics"]
+suggestions = ["darling_core/suggestions"]
+[badges.maintenance]
+status = "actively-developed"
+
+[badges.travis-ci]
+repository = "TedDriggs/darling"
diff --git a/third_party/rust/darling/LICENSE b/third_party/rust/darling/LICENSE
new file mode 100644
index 0000000000..0b48eadc9d
--- /dev/null
+++ b/third_party/rust/darling/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017 Ted Driggs
+
+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/darling/README.md b/third_party/rust/darling/README.md
new file mode 100644
index 0000000000..24e46d93cd
--- /dev/null
+++ b/third_party/rust/darling/README.md
@@ -0,0 +1,113 @@
+Darling
+=======
+
+[![Build Status](https://travis-ci.org/TedDriggs/darling.svg?branch=master)](https://travis-ci.org/TedDriggs/darling)
+[![Latest Version](https://img.shields.io/crates/v/darling.svg)](https://crates.io/crates/darling)
+[![Rustc Version 1.31+](https://img.shields.io/badge/rustc-1.31+-lightgray.svg)](https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html)
+
+`darling` is a crate for proc macro authors, which enables parsing attributes into structs. It is heavily inspired by `serde` both in its internals and in its API.
+
+# Benefits
+* Easy and declarative parsing of macro input - make your proc-macros highly controllable with minimal time investment.
+* Great validation and errors, no work required. When users of your proc-macro make a mistake, `darling` makes sure they get error markers at the right place in their source, and provides "did you mean" suggestions for misspelled fields.
+
+# Usage
+`darling` provides a set of traits which can be derived or manually implemented.
+
+1. `FromMeta` is used to extract values from a meta-item in an attribute. Implementations are likely reusable for many libraries, much like `FromStr` or `serde::Deserialize`. Trait implementations are provided for primitives, some std types, and some `syn` types.
+2. `FromDeriveInput` is implemented or derived by each proc-macro crate which depends on `darling`. This is the root for input parsing; it gets access to the identity, generics, and visibility of the target type, and can specify which attribute names should be parsed or forwarded from the input AST.
+3. `FromField` is implemented or derived by each proc-macro crate which depends on `darling`. Structs deriving this trait will get access to the identity (if it exists), type, and visibility of the field.
+4. `FromVariant` is implemented or derived by each proc-macro crate which depends on `darling`. Structs deriving this trait will get access to the identity and contents of the variant, which can be transformed the same as any other `darling` input.
+
+## Additional Modules
+* `darling::ast` provides generic types for representing the AST.
+* `darling::usage` provides traits and functions for determining where type parameters and lifetimes are used in a struct or enum.
+* `darling::util` provides helper types with special `FromMeta` implementations, such as `IdentList`.
+
+# Example
+
+```rust,ignore
+#[macro_use]
+extern crate darling;
+extern crate syn;
+
+#[derive(Default, FromMeta)]
+#[darling(default)]
+pub struct Lorem {
+ #[darling(rename = "sit")]
+ ipsum: bool,
+ dolor: Option<String>,
+}
+
+#[derive(FromDeriveInput)]
+#[darling(from_ident, attributes(my_crate), forward_attrs(allow, doc, cfg))]
+pub struct MyTraitOpts {
+ ident: syn::Ident,
+ attrs: Vec<syn::Attribute>,
+ lorem: Lorem,
+}
+```
+
+The above code will then be able to parse this input:
+
+```rust,ignore
+/// A doc comment which will be available in `MyTraitOpts::attrs`.
+#[derive(MyTrait)]
+#[my_crate(lorem(dolor = "Hello", ipsum))]
+pub struct ConsumingType;
+```
+
+# Attribute Macros
+Non-derive attribute macros are supported.
+To parse arguments for attribute macros, derive `FromMeta` on the argument receiver type, then pass `&syn::AttributeArgs` to the `from_list` method.
+This will produce a normal `darling::Result<T>` that can be used the same as a result from parsing a `DeriveInput`.
+
+## Macro Code
+```rust,ignore
+use darling::FromMeta;
+use syn::{AttributeArgs, ItemFn};
+use proc_macro::TokenStream;
+
+#[derive(Debug, FromMeta)]
+pub struct MacroArgs {
+ #[darling(default)]
+ timeout_ms: Option<u16>,
+ path: String,
+}
+
+#[proc_macro_attribute]
+fn your_attr(args: TokenStream, input: TokenStream) -> TokenStream {
+ let attr_args = parse_macro_input!(args as AttributeArgs);
+ let _input = parse_macro_input!(input as ItemFn);
+
+ let _args = match MacroArgs::from_list(&attr_args) {
+ Ok(v) => v,
+ Err(e) => { return e.write_errors(); }
+ };
+
+ // do things with `args`
+ unimplemented!()
+}
+```
+
+## Consuming Code
+```rust,ignore
+use your_crate::your_attr;
+
+#[your_attr(path = "hello", timeout_ms = 15)]
+fn do_stuff() {
+ println!("Hello");
+}
+```
+
+# Features
+Darling's features are built to work well for real-world projects.
+
+* **Defaults**: Supports struct- and field-level defaults, using the same path syntax as `serde`.
+* **Field Renaming**: Fields can have different names in usage vs. the backing code.
+* **Auto-populated fields**: Structs deriving `FromDeriveInput` and `FromField` can declare properties named `ident`, `vis`, `ty`, `attrs`, and `generics` to automatically get copies of the matching values from the input AST. `FromDeriveInput` additionally exposes `data` to get access to the body of the deriving type, and `FromVariant` exposes `fields`.
+* **Mapping function**: Use `#[darling(map="path")]` to specify a function that runs on the result of parsing a meta-item field. This can change the return type, which enables you to parse to an intermediate form and convert that to the type you need in your struct.
+* **Skip fields**: Use `#[darling(skip)]` to mark a field that shouldn't be read from attribute meta-items.
+* **Multiple-occurrence fields**: Use `#[darling(multiple)]` on a `Vec` field to allow that field to appear multiple times in the meta-item. Each occurrence will be pushed into the `Vec`.
+* **Span access**: Use `darling::util::SpannedValue` in a struct to get access to that meta item's source code span. This can be used to emit warnings that point at a specific field from your proc macro. In addition, you can use `darling::Error::write_errors` to automatically get precise error location details in most cases.
+* **"Did you mean" suggestions**: Compile errors from derived darling trait impls include suggestions for misspelled fields. \ No newline at end of file
diff --git a/third_party/rust/darling/examples/automatic_bounds.rs b/third_party/rust/darling/examples/automatic_bounds.rs
new file mode 100644
index 0000000000..73e236bda4
--- /dev/null
+++ b/third_party/rust/darling/examples/automatic_bounds.rs
@@ -0,0 +1,78 @@
+#[macro_use]
+extern crate darling;
+
+extern crate syn;
+
+use darling::FromDeriveInput;
+
+#[derive(FromMeta, PartialEq, Eq, Debug)]
+enum Volume {
+ Whisper,
+ Talk,
+ Shout,
+}
+
+/// A more complex example showing the ability to skip at a field or struct
+/// level while still tracking which type parameters need to be bounded.
+/// This can be seen by expanding this example using `cargo expand`.
+#[derive(FromMeta)]
+#[allow(dead_code)]
+enum Emphasis<T> {
+ Constant(Volume),
+ Variable(darling::util::PathList),
+ #[darling(skip)]
+ PerPhoneme(Option<T>),
+ Strided {
+ #[darling(skip)]
+ step: Vec<T>,
+ #[darling(multiple)]
+ volume: Vec<Volume>,
+ },
+}
+
+#[derive(FromDeriveInput)]
+#[darling(attributes(speak))]
+struct SpeakingOptions<T, U> {
+ max_volume: U,
+ #[darling(skip, default)]
+ additional_data: Vec<T>,
+}
+
+#[derive(Default)]
+struct Phoneme {
+ #[allow(dead_code)]
+ first: String,
+}
+
+// This is probably the holy grail for `darling`'s own internal use-case:
+// Auto-apply `Default` bound to skipped *field* types in `where` clause.
+impl<T, U> Default for SpeakingOptions<T, U>
+where
+ Vec<T>: Default,
+ U: Default,
+{
+ fn default() -> Self {
+ Self {
+ max_volume: Default::default(),
+ additional_data: Default::default(),
+ }
+ }
+}
+
+fn main() {
+ let derive_input = syn::parse_str(
+ r#"
+ #[derive(Speak)]
+ #[speak(max_volume = "shout")]
+ enum HtmlElement {
+ Div(String)
+ }
+ "#,
+ )
+ .unwrap();
+
+ let parsed: SpeakingOptions<Phoneme, Volume> =
+ FromDeriveInput::from_derive_input(&derive_input).unwrap();
+ assert_eq!(parsed.max_volume, Volume::Shout);
+ assert_eq!(parsed.additional_data.len(), 0);
+}
diff --git a/third_party/rust/darling/examples/consume_fields.rs b/third_party/rust/darling/examples/consume_fields.rs
new file mode 100644
index 0000000000..4b0703f507
--- /dev/null
+++ b/third_party/rust/darling/examples/consume_fields.rs
@@ -0,0 +1,175 @@
+//! This example shows how to do struct and field parsing using darling.
+
+#[macro_use]
+extern crate darling;
+extern crate proc_macro2;
+#[macro_use]
+extern crate quote;
+extern crate syn;
+
+use darling::ast;
+use darling::FromDeriveInput;
+use proc_macro2::TokenStream;
+use quote::ToTokens;
+use syn::parse_str;
+
+/// A speaking volume. Deriving `FromMeta` will cause this to be usable
+/// as a string value for a meta-item key.
+#[derive(Debug, Clone, Copy, FromMeta)]
+#[darling(default)]
+enum Volume {
+ Normal,
+ Whisper,
+ Shout,
+}
+
+impl Default for Volume {
+ fn default() -> Self {
+ Volume::Normal
+ }
+}
+
+/// Support parsing from a full derive input. Unlike FromMeta, this isn't
+/// composable; each darling-dependent crate should have its own struct to handle
+/// when its trait is derived.
+#[derive(Debug, FromDeriveInput)]
+// This line says that we want to process all attributes declared with `my_trait`,
+// and that darling should panic if this receiver is given an enum.
+#[darling(attributes(my_trait), supports(struct_any))]
+struct MyInputReceiver {
+ /// The struct ident.
+ ident: syn::Ident,
+
+ /// The type's generics. You'll need these any time your trait is expected
+ /// to work with types that declare generics.
+ generics: syn::Generics,
+
+ /// Receives the body of the struct or enum. We don't care about
+ /// struct fields because we previously told darling we only accept structs.
+ data: ast::Data<(), MyFieldReceiver>,
+
+ /// The Input Receiver demands a volume, so use `Volume::Normal` if the
+ /// caller doesn't provide one.
+ #[darling(default)]
+ volume: Volume,
+}
+
+impl ToTokens for MyInputReceiver {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ let MyInputReceiver {
+ ref ident,
+ ref generics,
+ ref data,
+ volume,
+ } = *self;
+
+ let (imp, ty, wher) = generics.split_for_impl();
+ let fields = data
+ .as_ref()
+ .take_struct()
+ .expect("Should never be enum")
+ .fields;
+
+ // Generate the format string which shows each field and its name
+ let fmt_string = fields
+ .iter()
+ .enumerate()
+ .map(|(i, f)| {
+ // We have to preformat the ident in this case so we can fall back
+ // to the field index for unnamed fields. It's not easy to read,
+ // unfortunately.
+ format!(
+ "{} = {{}}",
+ f.ident
+ .as_ref()
+ .map(|v| format!("{}", v))
+ .unwrap_or_else(|| format!("{}", i))
+ )
+ })
+ .collect::<Vec<_>>()
+ .join(", ");
+
+ // Generate the actual values to fill the format string.
+ let field_list = fields
+ .into_iter()
+ .enumerate()
+ .map(|(i, f)| {
+ let field_volume = f.volume.unwrap_or(volume);
+
+ // This works with named or indexed fields, so we'll fall back to the index so we can
+ // write the output as a key-value pair.
+ let field_ident = f.ident
+ .as_ref()
+ .map(|v| quote!(#v))
+ .unwrap_or_else(|| quote!(#i));
+
+ match field_volume {
+ Volume::Normal => quote!(self.#field_ident),
+ Volume::Shout => {
+ quote!(::std::string::ToString::to_string(&self.#field_ident).to_uppercase())
+ }
+ Volume::Whisper => {
+ quote!(::std::string::ToString::to_string(&self.#field_ident).to_lowercase())
+ }
+ }
+ })
+ .collect::<Vec<_>>();
+
+ tokens.extend(quote! {
+ impl #imp Speak for #ident #ty #wher {
+ fn speak(&self, writer: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+ write!(#fmt_string, #(#field_list),*)
+ }
+ }
+ });
+ }
+}
+
+#[derive(Debug, FromField)]
+#[darling(attributes(my_trait))]
+struct MyFieldReceiver {
+ /// Get the ident of the field. For fields in tuple or newtype structs or
+ /// enum bodies, this can be `None`.
+ ident: Option<syn::Ident>,
+
+ /// This magic field name pulls the type from the input.
+ ty: syn::Type,
+
+ /// We declare this as an `Option` so that during tokenization we can write
+ /// `field.volume.unwrap_or(derive_input.volume)` to facilitate field-level
+ /// overrides of struct-level settings.
+ #[darling(default)]
+ volume: Option<Volume>,
+}
+
+fn main() {
+ let input = r#"#[derive(MyTrait)]
+#[my_trait(volume = "shout")]
+pub struct Foo {
+ #[my_trait(volume = "whisper")]
+ bar: bool,
+
+ baz: i64,
+}"#;
+
+ let parsed = parse_str(input).unwrap();
+ let receiver = MyInputReceiver::from_derive_input(&parsed).unwrap();
+ let tokens = quote!(#receiver);
+
+ println!(
+ r#"
+INPUT:
+
+{}
+
+PARSED AS:
+
+{:?}
+
+EMITS:
+
+{}
+ "#,
+ input, receiver, tokens
+ );
+}
diff --git a/third_party/rust/darling/examples/fallible_read.rs b/third_party/rust/darling/examples/fallible_read.rs
new file mode 100644
index 0000000000..c487854336
--- /dev/null
+++ b/third_party/rust/darling/examples/fallible_read.rs
@@ -0,0 +1,87 @@
+//! This example demonstrates techniques for performing custom error handling
+//! in a derive-input receiver.
+//!
+//! 1. Using `darling::Result` as a carrier to preserve the error for later display
+//! 1. Using `Result<T, syn::Meta>` to attempt a recovery in imperative code
+//! 1. Using the `map` darling meta-item to post-process the receiver before returning.
+#[macro_use]
+extern crate darling;
+
+extern crate syn;
+
+use darling::{FromDeriveInput, FromMeta};
+use syn::parse_str;
+
+#[derive(Debug, FromDeriveInput)]
+#[darling(attributes(my_trait), map = "MyInputReceiver::autocorrect")]
+pub struct MyInputReceiver {
+ /// This field must be present and a string or else parsing will panic.
+ name: String,
+
+ /// If this field fails to parse, the struct can still be built; the field
+ /// will contain the error. The consuming struct can then decide if this
+ /// blocks code generation. If so, panic. Otherwise, recover and proceed.
+ frequency: darling::Result<i64>,
+
+ /// If this field fails to parse, the struct can still be built; the field
+ /// will contain an `Err` with the original `syn::Meta`. This can be used
+ /// for alternate parsing attempts before panicking.
+ amplitude: Result<u64, syn::Meta>,
+}
+
+impl MyInputReceiver {
+ /// This function will be called by `darling` _after_ it's finished parsing the
+ /// input but before returning to the caller. This is a good place to initialize
+ /// skipped fields or to perform corrections that don't lend themselves to being
+ /// done elsewhere.
+ fn autocorrect(self) -> Self {
+ let Self {
+ name,
+ frequency,
+ amplitude,
+ } = self;
+
+ // Amplitude doesn't have a sign, so if we received a negative number then
+ // we'll go ahead and make it positive.
+ let amplitude = match amplitude {
+ Ok(amp) => amp,
+ Err(mi) => {
+ let val: i64 = if let Ok(v) = FromMeta::from_meta(&mi) {
+ v
+ } else {
+ panic!(format!("amplitude should have been an integer"))
+ };
+
+ val.abs() as u64
+ }
+ };
+
+ Self {
+ name,
+ frequency,
+ amplitude: Ok(amplitude),
+ }
+ }
+}
+
+fn main() {
+ let input = r#"#[derive(MyTrait)]
+#[my_trait(name="Jon", amplitude = "-1", frequency = "1")]
+pub struct Foo;"#;
+
+ let parsed = parse_str(input).unwrap();
+ let receiver = MyInputReceiver::from_derive_input(&parsed).unwrap();
+
+ println!(
+ r#"
+INPUT:
+
+{}
+
+PARSED AS:
+
+{:?}
+ "#,
+ input, receiver
+ );
+}
diff --git a/third_party/rust/darling/examples/supports_struct.rs b/third_party/rust/darling/examples/supports_struct.rs
new file mode 100644
index 0000000000..dbf8238a9d
--- /dev/null
+++ b/third_party/rust/darling/examples/supports_struct.rs
@@ -0,0 +1,62 @@
+#[macro_use]
+extern crate darling;
+
+extern crate syn;
+
+use darling::{ast, util, FromDeriveInput};
+use syn::{Ident, Type};
+
+#[derive(Debug, FromField)]
+#[darling(attributes(lorem))]
+pub struct LoremField {
+ ident: Option<Ident>,
+ ty: Type,
+ #[darling(default)]
+ skip: bool,
+}
+
+#[derive(Debug, FromDeriveInput)]
+#[darling(attributes(lorem), supports(struct_named))]
+pub struct Lorem {
+ ident: Ident,
+ data: ast::Data<util::Ignored, LoremField>,
+}
+
+fn main() {
+ let good_input = r#"#[derive(Lorem)]
+pub struct Foo {
+ #[lorem(skip)]
+ bar: bool,
+
+ baz: i64,
+}"#;
+
+ let bad_input = r#"#[derive(Lorem)]
+ pub struct BadFoo(String, u32);"#;
+
+ let parsed = syn::parse_str(good_input).unwrap();
+ let receiver = Lorem::from_derive_input(&parsed).unwrap();
+ let wrong_shape_parsed = syn::parse_str(bad_input).unwrap();
+ let wrong_shape = Lorem::from_derive_input(&wrong_shape_parsed).expect_err("Shape was wrong");
+
+ println!(
+ r#"
+INPUT:
+
+{}
+
+PARSED AS:
+
+{:?}
+
+BAD INPUT:
+
+{}
+
+PRODUCED ERROR:
+
+{}
+ "#,
+ good_input, receiver, bad_input, wrong_shape
+ );
+}
diff --git a/third_party/rust/darling/src/lib.rs b/third_party/rust/darling/src/lib.rs
new file mode 100644
index 0000000000..70035be9d5
--- /dev/null
+++ b/third_party/rust/darling/src/lib.rs
@@ -0,0 +1,98 @@
+//! # Darling
+//! Darling is a tool for declarative attribute parsing in proc macro implementations.
+//!
+//!
+//! ## Design
+//! Darling takes considerable design inspiration from [`serde`]. A data structure that can be
+//! read from any attribute implements `FromMeta` (or has an implementation automatically
+//! generated using `derive`). Any crate can provide `FromMeta` implementations, even one not
+//! specifically geared towards proc-macro authors.
+//!
+//! Proc-macro crates should provide their own structs which implement or derive `FromDeriveInput`,
+//! `FromField`, `FromVariant`, `FromGenerics`, _et alia_ to gather settings relevant to their operation.
+//!
+//! ## Attributes
+//! There are a number of attributes that `darling` exposes to enable finer-grained control over the code
+//! it generates.
+//!
+//! * **Field renaming**: You can use `#[darling(rename="new_name")]` on a field to change the name Darling looks for.
+//! You can also use `#[darling(rename_all="...")]` at the struct or enum level to apply a casing rule to all fields or variants.
+//! * **Map function**: You can use `#[darling(map="path::to::function")]` to run code on a field before its stored in the struct.
+//! * **Default values**: You can use `#[darling(default)]` at the type or field level to use that type's default value to fill
+//! in values not specified by the caller.
+//! * **Skipped fields**: You can skip a variant or field using `#[darling(skip)]`. Fields marked with this will fall back to
+//! `Default::default()` for their value, but you can override that with an explicit default or a value from the type-level default.
+//!
+//! ## Forwarded Fields
+//! All derivable traits except `FromMeta` support forwarding some fields from the input AST to the derived struct.
+//! These fields are matched up by identifier **before** `rename` attribute values are considered,
+//! allowing you to use their names for your own properties.
+//! The deriving struct is responsible for making sure the types of fields it chooses to declare are compatible with this table.
+//!
+//! A deriving struct is free to include or exclude any of the fields below.
+//!
+//! ### `FromDeriveInput`
+//! |Field name|Type|Meaning|
+//! |---|---|---|
+//! |`ident`|`syn::Ident`|The identifier of the passed-in type|
+//! |`vis`|`syn::Visibility`|The visibility of the passed-in type|
+//! |`generics`|`T: darling::FromGenerics`|The generics of the passed-in type. This can be `syn::Generics`, `darling::ast::Generics`, or any compatible type.|
+//! |`data`|`darling::ast::Data`|The body of the passed-in type|
+//! |`attrs`|`Vec<syn::Attribute>`|The forwarded attributes from the passed in type. These are controlled using the `forward_attrs` attribute.|
+//!
+//! ### `FromField`
+//! |Field name|Type|Meaning|
+//! |---|---|---|
+//! |`ident`|`syn::Ident`|The identifier of the passed-in field|
+//! |`vis`|`syn::Visibility`|The visibility of the passed-in field|
+//! |`ty`|`syn::Type`|The type of the passed-in field|
+//! |`attrs`|`Vec<syn::Attribute>`|The forwarded attributes from the passed in field. These are controlled using the `forward_attrs` attribute.|
+//!
+//! ### `FromTypeParam`
+//! |Field name|Type|Meaning|
+//! |---|---|---|
+//! |`ident`|`syn::Ident`|The identifier of the passed-in type param|
+//! |`bounds`|`Vec<syn::TypeParamBound>`|The bounds applied to the type param|
+//! |`default`|`Option<syn::Type>`|The default type of the parameter, if one exists|
+//! |`attrs`|`Vec<syn::Attribute>`|The forwarded attributes from the passed in type param. These are controlled using the `forward_attrs` attribute.|
+
+extern crate core;
+extern crate darling_core;
+
+#[allow(unused_imports)]
+#[macro_use]
+extern crate darling_macro;
+
+#[doc(hidden)]
+pub use darling_macro::*;
+
+#[doc(inline)]
+pub use darling_core::{FromDeriveInput, FromField, FromGenericParam, FromGenerics, FromMeta,
+ FromTypeParam, FromVariant};
+
+#[doc(inline)]
+pub use darling_core::{Error, Result};
+
+#[doc(inline)]
+pub use darling_core::{ast, error, usage, util};
+
+// XXX exported so that `ExtractAttribute::extractor` can convert a path into tokens.
+// This is likely to change in the future, so only generated code should depend on this export.
+#[doc(hidden)]
+pub use darling_core::ToTokens;
+
+/// Core/std trait re-exports. This should help produce generated code which doesn't
+/// depend on `std` unnecessarily, and avoids problems caused by aliasing `std` or any
+/// of the referenced types.
+#[doc(hidden)]
+pub mod export {
+ pub use core::convert::From;
+ pub use core::default::Default;
+ pub use core::option::Option::{self, None, Some};
+ pub use core::result::Result::{self, Err, Ok};
+ pub use std::vec::Vec;
+ pub use std::string::ToString;
+}
+
+#[macro_use]
+mod macros_public;
diff --git a/third_party/rust/darling/src/macros_public.rs b/third_party/rust/darling/src/macros_public.rs
new file mode 100644
index 0000000000..a3c5cac98d
--- /dev/null
+++ b/third_party/rust/darling/src/macros_public.rs
@@ -0,0 +1,98 @@
+//! Macros that should be exported from both `darling_core` and `darling`.
+//! Note that these are **sym-linked** into the main code, and so cannot declare on items that are exported differently
+//! in `darling_core` vs. `darling`.
+
+/// Generator for `UsesTypeParam` impls that unions the used type parameters of the selected fields.
+///
+/// # Usage
+/// The macro takes the type implementing the trait as the first argument, then a comma-separated list of
+/// fields for the rest of its arguments.
+///
+/// The type of each passed-in field must implement `UsesTypeParams`, or the resulting code won't compile.
+///
+/// ```rust
+/// # extern crate syn;
+/// #
+/// # #[macro_use]
+/// # extern crate darling_core;
+/// #
+/// struct MyField {
+/// ty: syn::Type,
+/// }
+///
+/// uses_type_params!(MyField, ty);
+///
+/// fn main() {
+/// // no test run
+/// }
+/// ```
+///
+/// `darling` cannot derive this trait automatically, as it doesn't know which information extracted from
+/// proc-macro input is meant to constitute "using" the type parameter, but crate consumers should
+/// implement it by hand or using the macro.
+#[macro_export]
+macro_rules! uses_type_params {
+ ($impl_type:ty, $accessor:ident) => {
+ impl $crate::usage::UsesTypeParams for $impl_type {
+ fn uses_type_params<'gen>(
+ &self,
+ options: &$crate::usage::Options,
+ type_set: &'gen $crate::usage::IdentSet
+ ) -> $crate::usage::IdentRefSet<'gen> {
+ self.$accessor.uses_type_params(options, type_set)
+ }
+ }
+ };
+ ($impl_type:ty, $first:ident, $($field:ident),+) => {
+ impl $crate::usage::UsesTypeParams for $impl_type {
+ fn uses_type_params<'gen>(
+ &self,
+ options: &$crate::usage::Options,
+ type_set: &'gen $crate::usage::IdentSet
+ ) -> $crate::usage::IdentRefSet<'gen> {
+ let mut hits = self.$first.uses_type_params(options, type_set);
+ $(
+ hits.extend(self.$field.uses_type_params(options, type_set));
+ )*
+ hits
+ }
+ }
+ };
+}
+
+/// Generator for `UsesLifetimes` impls that unions the used lifetimes of the selected fields.
+///
+/// # Usage
+/// The macro takes the type implementing the trait as the first argument, then a comma-separated list of
+/// fields for the rest of its arguments.
+///
+/// The type of each passed-in field must implement `UsesLifetimes`, or the resulting code won't compile.
+#[macro_export]
+macro_rules! uses_lifetimes {
+ ($impl_type:ty, $accessor:ident) => {
+ impl $crate::usage::UsesLifetimes for $impl_type {
+ fn uses_lifetimes<'gen>(
+ &self,
+ options: &$crate::usage::Options,
+ type_set: &'gen $crate::usage::LifetimeSet
+ ) -> $crate::usage::LifetimeRefSet<'gen> {
+ self.$accessor.uses_lifetimes(options, type_set)
+ }
+ }
+ };
+ ($impl_type:ty, $first:ident, $($field:ident),+) => {
+ impl $crate::usage::UsesLifetimes for $impl_type {
+ fn uses_lifetimes<'gen>(
+ &self,
+ options: &$crate::usage::Options,
+ type_set: &'gen $crate::usage::LifetimeSet
+ ) -> $crate::usage::LifetimeRefSet<'gen> {
+ let mut hits = self.$first.uses_lifetimes(options, type_set);
+ $(
+ hits.extend(self.$field.uses_lifetimes(options, type_set));
+ )*
+ hits
+ }
+ }
+ };
+}
diff --git a/third_party/rust/darling/tests/accrue_errors.rs b/third_party/rust/darling/tests/accrue_errors.rs
new file mode 100644
index 0000000000..9ae8212765
--- /dev/null
+++ b/third_party/rust/darling/tests/accrue_errors.rs
@@ -0,0 +1,108 @@
+//! These tests verify that multiple errors will be collected up from throughout
+//! the parsing process and returned correctly to the caller.
+
+#[macro_use]
+extern crate darling;
+#[macro_use]
+extern crate syn;
+#[macro_use]
+extern crate quote;
+
+use darling::ast;
+use darling::FromDeriveInput;
+
+#[derive(Debug, FromDeriveInput)]
+#[darling(attributes(accrue))]
+struct Lorem {
+ ipsum: String,
+ dolor: Dolor,
+ data: ast::Data<(), LoremField>,
+}
+
+#[derive(Debug, FromMeta)]
+struct Dolor {
+ sit: bool,
+}
+
+#[derive(Debug, FromField)]
+#[darling(attributes(accrue))]
+struct LoremField {
+ ident: Option<syn::Ident>,
+ aliased_as: syn::Ident,
+}
+
+#[test]
+fn bad_type_and_missing_fields() {
+ let input = parse_quote! {
+ #[accrue(ipsum = true, dolor(amet = "Hi"))]
+ pub struct NonConforming {
+ foo: ()
+ }
+ };
+
+ let s_result: ::darling::Error = Lorem::from_derive_input(&input).unwrap_err();
+ let err = s_result.flatten();
+ println!("{}", err);
+ assert_eq!(3, err.len());
+}
+
+#[test]
+fn body_only_issues() {
+ let input = parse_quote! {
+ #[accrue(ipsum = "Hello", dolor(sit))]
+ pub struct NonConforming {
+ foo: (),
+ bar: bool,
+ }
+ };
+
+ let s_err = Lorem::from_derive_input(&input).unwrap_err();
+ println!("{:?}", s_err);
+ assert_eq!(2, s_err.len());
+}
+
+#[derive(Debug, FromMeta)]
+enum Week {
+ Monday,
+ Tuesday { morning: bool, afternoon: String },
+ Wednesday(Dolor),
+}
+
+#[derive(Debug, FromDeriveInput)]
+#[darling(attributes(accrue))]
+struct Month {
+ schedule: Week,
+}
+
+#[test]
+fn error_in_enum_fields() {
+ let input = parse_quote! {
+ #[accrue(schedule(tuesday(morning = "yes")))]
+ pub struct NonConforming {
+ foo: (),
+ bar: bool,
+ }
+ };
+
+ let s_err = Month::from_derive_input(&input).unwrap_err();
+ assert_eq!(2, s_err.len());
+ let err = s_err.flatten();
+ // TODO add tests to check location path is correct
+ println!("{}", err);
+}
+
+#[test]
+fn error_in_newtype_variant() {
+ let input = parse_quote! {
+ #[accrue(schedule(wednesday(sit = "yes")))]
+ pub struct NonConforming {
+ foo: (),
+ bar: bool,
+ }
+ };
+
+ let s_err = Month::from_derive_input(&input).unwrap_err();
+ assert_eq!(1, s_err.len());
+ println!("{}", s_err);
+ println!("{}", s_err.flatten());
+}
diff --git a/third_party/rust/darling/tests/computed_bound.rs b/third_party/rust/darling/tests/computed_bound.rs
new file mode 100644
index 0000000000..94fd307b68
--- /dev/null
+++ b/third_party/rust/darling/tests/computed_bound.rs
@@ -0,0 +1,46 @@
+#[macro_use]
+extern crate darling;
+extern crate syn;
+
+use darling::FromDeriveInput;
+
+fn parse<T: FromDeriveInput>(src: &str) -> T {
+ let ast = syn::parse_str(src).unwrap();
+ FromDeriveInput::from_derive_input(&ast).unwrap()
+}
+
+#[derive(FromMeta, PartialEq, Eq, Debug)]
+enum Volume {
+ Whisper,
+ Talk,
+ Shout,
+}
+
+#[derive(FromDeriveInput)]
+#[darling(attributes(speak))]
+struct SpeakingOptions<T: Default, U> {
+ max_volume: U,
+ #[darling(skip)]
+ #[allow(dead_code)]
+ additional_data: T,
+}
+
+#[derive(Default)]
+struct Phoneme {
+ #[allow(dead_code)]
+ first: String,
+}
+
+#[test]
+fn skipped_field() {
+ let parsed: SpeakingOptions<Phoneme, Volume> = parse(
+ r#"
+ #[derive(Speak)]
+ #[speak(max_volume = "shout")]
+ enum HtmlElement {
+ Div(String)
+ }
+ "#,
+ );
+ assert_eq!(parsed.max_volume, Volume::Shout);
+}
diff --git a/third_party/rust/darling/tests/custom_bound.rs b/third_party/rust/darling/tests/custom_bound.rs
new file mode 100644
index 0000000000..4266a740e1
--- /dev/null
+++ b/third_party/rust/darling/tests/custom_bound.rs
@@ -0,0 +1,25 @@
+#[macro_use]
+extern crate darling;
+extern crate syn;
+
+use std::ops::Add;
+
+#[derive(Debug, Clone, FromMeta)]
+#[darling(bound = "T: FromMeta + Add")]
+struct Wrapper<T>(pub T);
+
+impl<T: Add> Add for Wrapper<T> {
+ type Output = Wrapper<<T as Add>::Output>;
+ fn add(self, rhs: Self) -> Wrapper<<T as Add>::Output> {
+ Wrapper(self.0 + rhs.0)
+ }
+}
+
+#[derive(Debug, FromDeriveInput)]
+#[darling(attributes(hello), bound = "Wrapper<T>: Add, T: FromMeta")]
+struct Foo<T> {
+ lorem: Wrapper<T>,
+}
+
+#[test]
+fn expansion() {}
diff --git a/third_party/rust/darling/tests/defaults.rs b/third_party/rust/darling/tests/defaults.rs
new file mode 100644
index 0000000000..c6003ec4ba
--- /dev/null
+++ b/third_party/rust/darling/tests/defaults.rs
@@ -0,0 +1,32 @@
+#[macro_use]
+extern crate darling;
+#[macro_use]
+extern crate quote;
+#[macro_use]
+extern crate syn;
+
+use darling::FromDeriveInput;
+
+mod foo {
+ pub mod bar {
+ pub fn init() -> String {
+ String::from("hello")
+ }
+ }
+}
+
+#[derive(FromDeriveInput)]
+#[darling(attributes(speak))]
+pub struct SpeakerOpts {
+ #[darling(default="foo::bar::init")]
+ first_word: String,
+}
+
+#[test]
+fn path_default() {
+ let speaker: SpeakerOpts = FromDeriveInput::from_derive_input(&parse_quote! {
+ struct Foo;
+ }).expect("Unit struct with no attrs should parse");
+
+ assert_eq!(speaker.first_word, "hello");
+} \ No newline at end of file
diff --git a/third_party/rust/darling/tests/enums_newtype.rs b/third_party/rust/darling/tests/enums_newtype.rs
new file mode 100644
index 0000000000..0fd12f03fc
--- /dev/null
+++ b/third_party/rust/darling/tests/enums_newtype.rs
@@ -0,0 +1,96 @@
+#[macro_use]
+extern crate darling;
+#[macro_use]
+extern crate syn;
+#[macro_use]
+extern crate quote;
+
+use darling::FromDeriveInput;
+
+#[derive(Debug, Default, PartialEq, Eq, FromMeta)]
+#[darling(default)]
+pub struct Amet {
+ hello: bool,
+ world: String,
+}
+
+#[derive(Debug, PartialEq, Eq, FromMeta)]
+#[darling(rename_all = "snake_case")]
+pub enum Lorem {
+ Ipsum(bool),
+ Dolor(String),
+ Sit(Amet),
+}
+
+#[derive(Debug, PartialEq, Eq, FromDeriveInput)]
+#[darling(attributes(hello))]
+pub struct Holder {
+ lorem: Lorem,
+}
+
+impl PartialEq<Lorem> for Holder {
+ fn eq(&self, other: &Lorem) -> bool {
+ self.lorem == *other
+ }
+}
+
+#[test]
+fn bool_word() {
+ let di = parse_quote! {
+ #[hello(lorem(ipsum))]
+ pub struct Bar;
+ };
+
+ let pr = Holder::from_derive_input(&di).unwrap();
+ assert_eq!(pr, Lorem::Ipsum(true));
+}
+
+#[test]
+fn bool_literal() {
+ let di = parse_quote! {
+ #[hello(lorem(ipsum = false))]
+ pub struct Bar;
+ };
+
+ let pr = Holder::from_derive_input(&di).unwrap();
+ assert_eq!(pr, Lorem::Ipsum(false));
+}
+
+#[test]
+fn string_literal() {
+ let di = parse_quote! {
+ #[hello(lorem(dolor = "Hello"))]
+ pub struct Bar;
+ };
+
+ let pr = Holder::from_derive_input(&di).unwrap();
+ assert_eq!(pr, Lorem::Dolor("Hello".to_string()));
+}
+
+#[test]
+fn struct_nested() {
+ let di = parse_quote! {
+ #[hello(lorem(sit(world = "Hello", hello = false)))]
+ pub struct Bar;
+ };
+
+ let pr = Holder::from_derive_input(&di).unwrap();
+ assert_eq!(
+ pr,
+ Lorem::Sit(Amet {
+ hello: false,
+ world: "Hello".to_string(),
+ })
+ );
+}
+
+#[test]
+#[should_panic]
+fn format_mismatch() {
+ let di = parse_quote! {
+ #[hello(lorem(dolor(world = "Hello", hello = false)))]
+ pub struct Bar;
+ };
+
+ Holder::from_derive_input(&di).unwrap();
+}
diff --git a/third_party/rust/darling/tests/enums_struct.rs b/third_party/rust/darling/tests/enums_struct.rs
new file mode 100644
index 0000000000..63ce69058d
--- /dev/null
+++ b/third_party/rust/darling/tests/enums_struct.rs
@@ -0,0 +1,16 @@
+//! Test expansion of enums which have struct variants.
+
+#[macro_use]
+extern crate darling;
+extern crate syn;
+
+#[derive(Debug, FromMeta)]
+#[darling(rename_all = "snake_case")]
+enum Message {
+ Hello { user: String, silent: bool },
+ Ping,
+ Goodbye { user: String },
+}
+
+#[test]
+fn expansion() {}
diff --git a/third_party/rust/darling/tests/enums_unit.rs b/third_party/rust/darling/tests/enums_unit.rs
new file mode 100644
index 0000000000..f9eb23f245
--- /dev/null
+++ b/third_party/rust/darling/tests/enums_unit.rs
@@ -0,0 +1,16 @@
+//! Test expansion of enum variants which have no associated data.
+
+#[macro_use]
+extern crate darling;
+extern crate syn;
+
+#[derive(Debug, FromMeta)]
+#[darling(rename_all = "snake_case")]
+enum Pattern {
+ Owned,
+ Immutable,
+ Mutable,
+}
+
+#[test]
+fn expansion() {}
diff --git a/third_party/rust/darling/tests/error.rs b/third_party/rust/darling/tests/error.rs
new file mode 100644
index 0000000000..edd72eb1dd
--- /dev/null
+++ b/third_party/rust/darling/tests/error.rs
@@ -0,0 +1,55 @@
+//! In case of bad input, parsing should fail. The error should have locations set in derived implementations.
+#[macro_use]
+extern crate darling;
+#[macro_use]
+extern crate syn;
+#[macro_use]
+extern crate quote;
+
+use darling::FromDeriveInput;
+
+#[derive(Debug, FromMeta)]
+struct Dolor {
+ #[darling(rename = "amet")]
+ sit: bool,
+ world: bool,
+}
+
+#[derive(Debug, FromDeriveInput)]
+#[darling(from_ident, attributes(hello))]
+struct Lorem {
+ ident: syn::Ident,
+ ipsum: Dolor,
+}
+
+impl From<syn::Ident> for Lorem {
+ fn from(ident: syn::Ident) -> Self {
+ Lorem {
+ ident,
+ ipsum: Dolor {
+ sit: false,
+ world: true,
+ },
+ }
+ }
+}
+
+#[test]
+fn parsing_fail() {
+ let di = parse_quote! {
+ #[hello(ipsum(amet = "yes", world = false))]
+ pub struct Foo;
+ };
+
+ println!("{}", Lorem::from_derive_input(&di).unwrap_err());
+}
+
+#[test]
+fn missing_field() {
+ let di = parse_quote! {
+ #[hello(ipsum(amet = true))]
+ pub struct Foo;
+ };
+
+ println!("{}", Lorem::from_derive_input(&di).unwrap_err());
+}
diff --git a/third_party/rust/darling/tests/from_generics.rs b/third_party/rust/darling/tests/from_generics.rs
new file mode 100644
index 0000000000..2c259ec280
--- /dev/null
+++ b/third_party/rust/darling/tests/from_generics.rs
@@ -0,0 +1,186 @@
+//! Tests for `FromGenerics`, and - indirectly - `FromGenericParam`.
+//! These tests assume `FromTypeParam` is working and only look at whether the wrappers for magic
+//! fields are working as expected.
+
+#[macro_use]
+extern crate darling;
+extern crate syn;
+
+use darling::ast::{self, GenericParamExt};
+use darling::util::{Ignored, WithOriginal};
+use darling::{FromDeriveInput, Result};
+
+#[derive(FromDeriveInput)]
+#[darling(attributes(lorem))]
+struct MyReceiver {
+ pub ident: syn::Ident,
+ pub generics: ast::Generics<ast::GenericParam<MyTypeParam>>,
+}
+
+#[derive(FromTypeParam)]
+#[darling(attributes(lorem))]
+struct MyTypeParam {
+ pub ident: syn::Ident,
+ #[darling(default)]
+ pub foo: bool,
+ #[darling(default)]
+ pub bar: Option<String>,
+}
+
+fn fdi<T: FromDeriveInput>(src: &str) -> Result<T> {
+ FromDeriveInput::from_derive_input(&syn::parse_str(src).expect("Source parses"))
+}
+
+/// Verify that `ast::Generics` is populated correctly when there is no generics declaration
+#[test]
+fn no_generics() {
+ let rec: MyReceiver = fdi("struct Baz;").expect("Input is well-formed");
+ assert!(rec.generics.where_clause.is_none());
+ assert_eq!(rec.generics.params.len(), 0);
+}
+
+#[test]
+fn expand_some() {
+ let rec: MyReceiver = fdi(r#"
+ struct Baz<
+ 'a,
+ #[lorem(foo)] T,
+ #[lorem(bar = "x")] U: Eq + ?Sized
+ >(&'a T, U);
+ "#)
+ .expect("Input is well-formed");
+ assert!(rec.generics.where_clause.is_none());
+
+ // Make sure we've preserved the lifetime def, though we don't do anything with it.
+ assert!(rec.generics.params[0].as_lifetime_def().is_some());
+
+ let mut ty_param_iter = rec.generics.type_params();
+
+ let first = ty_param_iter
+ .next()
+ .expect("type_params should not be empty");
+ assert!(first.bar.is_none());
+ assert!(first.foo);
+ assert_eq!(first.ident, "T");
+
+ let second = ty_param_iter
+ .next()
+ .expect("type_params should have a second value");
+ assert_eq!(
+ second
+ .bar
+ .as_ref()
+ .expect("Second type param should set bar"),
+ "x"
+ );
+ assert_eq!(second.foo, false);
+ assert_eq!(second.ident, "U");
+}
+
+/// Verify ≤0.4.1 behavior - where `generics` had to be `syn::Generics` - keeps working.
+#[test]
+fn passthrough() {
+ #[derive(FromDeriveInput)]
+ struct PassthroughReceiver {
+ pub generics: syn::Generics,
+ }
+
+ let rec: PassthroughReceiver = fdi(r#"
+ struct Baz<
+ 'a,
+ #[lorem(foo)] T,
+ #[lorem(bar = "x")] U: Eq + ?Sized
+ >(&'a T, U);
+ "#)
+ .expect("Input is well-formed");
+
+ let mut type_param_iter = rec.generics.type_params();
+ assert!(type_param_iter.next().is_some());
+}
+
+/// Verify that `where_clause` is passed through when it exists.
+/// As of 0.4.1, there is no `FromWhereClause` trait, so other types aren't supported
+/// for that field.
+#[test]
+fn where_clause() {
+ let rec: MyReceiver = fdi(r#"
+ struct Baz<
+ 'a,
+ #[lorem(foo)] T,
+ #[lorem(bar = "x")] U: Eq + ?Sized
+ >(&'a T, U) where T: Into<String>;
+ "#)
+ .expect("Input is well-formed");
+
+ assert!(rec.generics.where_clause.is_some());
+}
+
+/// Test that `WithOriginal` works for generics.
+#[test]
+fn with_original() {
+ #[derive(FromDeriveInput)]
+ struct WorigReceiver {
+ generics: WithOriginal<ast::Generics<ast::GenericParam<MyTypeParam>>, syn::Generics>,
+ }
+
+ let rec: WorigReceiver = fdi(r#"
+ struct Baz<
+ 'a,
+ #[lorem(foo)] T,
+ #[lorem(bar = "x")] U: Eq + ?Sized
+ >(&'a T, U) where T: Into<String>;
+ "#)
+ .expect("Input is well-formed");
+
+ // Make sure we haven't lost anything in the conversion
+ assert_eq!(rec.generics.parsed.params.len(), 3);
+ assert_eq!(
+ rec.generics
+ .original
+ .params
+ .iter()
+ .collect::<Vec<_>>()
+ .len(),
+ 3
+ );
+
+ let parsed_t: &MyTypeParam = rec.generics.parsed.params[1]
+ .as_type_param()
+ .expect("Second argument should be type param");
+
+ // Make sure the first type param in each case is T
+ assert_eq!(parsed_t.ident, "T");
+ assert_eq!(
+ rec.generics
+ .original
+ .type_params()
+ .next()
+ .expect("First type param should exist")
+ .ident,
+ "T"
+ );
+
+ // Make sure we actually parsed the first type param
+ assert!(parsed_t.foo);
+ assert!(parsed_t.bar.is_none());
+}
+
+/// Make sure generics can be ignored
+#[test]
+fn ignored() {
+ #[derive(FromDeriveInput)]
+ struct IgnoredReceiver {
+ generics: Ignored,
+ }
+
+ let rec: IgnoredReceiver = fdi(r#"
+ struct Baz<
+ 'a,
+ #[lorem(foo)] T,
+ #[lorem(bar = "x")] U: Eq + ?Sized
+ >(&'a T, U) where T: Into<String>;
+ "#)
+ .expect("Input is well-formed");
+
+ assert_eq!(Ignored, rec.generics);
+}
diff --git a/third_party/rust/darling/tests/from_type_param.rs b/third_party/rust/darling/tests/from_type_param.rs
new file mode 100644
index 0000000000..adaf34dd38
--- /dev/null
+++ b/third_party/rust/darling/tests/from_type_param.rs
@@ -0,0 +1,65 @@
+#[macro_use]
+extern crate darling;
+#[macro_use]
+extern crate syn;
+#[macro_use]
+extern crate quote;
+
+use darling::FromTypeParam;
+use syn::{DeriveInput, GenericParam, Ident, TypeParam};
+
+#[darling(attributes(lorem), from_ident)]
+#[derive(FromTypeParam)]
+struct Lorem {
+ ident: Ident,
+ bounds: Vec<syn::TypeParamBound>,
+ foo: bool,
+ bar: Option<String>,
+}
+
+impl From<Ident> for Lorem {
+ fn from(ident: Ident) -> Self {
+ Lorem {
+ ident,
+ foo: false,
+ bar: None,
+ bounds: Default::default(),
+ }
+ }
+}
+
+fn extract_type(param: &GenericParam) -> &TypeParam {
+ match *param {
+ GenericParam::Type(ref ty) => ty,
+ _ => unreachable!("Not a type param"),
+ }
+}
+
+#[test]
+fn expand_many() {
+ let di: DeriveInput = parse_quote! {
+ struct Baz<
+ #[lorem(foo)] T,
+ #[lorem(bar = "x")] U: Eq + ?Sized
+ >(T, U);
+ };
+
+ let params = di.generics.params;
+
+ {
+ let ty = extract_type(&params[0]);
+ let lorem = Lorem::from_type_param(ty).unwrap();
+ assert_eq!(lorem.ident, "T");
+ assert_eq!(lorem.foo, true);
+ assert_eq!(lorem.bar, None);
+ }
+
+ {
+ let ty = extract_type(&params[1]);
+ let lorem = Lorem::from_type_param(ty).unwrap();
+ assert_eq!(lorem.ident, "U");
+ assert_eq!(lorem.foo, false);
+ assert_eq!(lorem.bar, Some("x".to_string()));
+ assert_eq!(lorem.bounds.len(), 2);
+ }
+}
diff --git a/third_party/rust/darling/tests/from_type_param_default.rs b/third_party/rust/darling/tests/from_type_param_default.rs
new file mode 100644
index 0000000000..eb0ecc766c
--- /dev/null
+++ b/third_party/rust/darling/tests/from_type_param_default.rs
@@ -0,0 +1,59 @@
+#[macro_use]
+extern crate darling;
+#[macro_use]
+extern crate syn;
+#[macro_use]
+extern crate quote;
+
+use darling::FromTypeParam;
+use syn::{DeriveInput, GenericParam, TypeParam};
+
+#[darling(attributes(lorem), default)]
+#[derive(Default, FromTypeParam)]
+struct Lorem {
+ foo: bool,
+ bar: Option<String>,
+ default: Option<syn::Type>,
+}
+
+fn extract_type(param: &GenericParam) -> &TypeParam {
+ match *param {
+ GenericParam::Type(ref ty) => ty,
+ _ => unreachable!("Not a type param"),
+ }
+}
+
+#[test]
+fn expand_many() {
+ let di: DeriveInput = parse_quote! {
+ struct Baz<
+ #[lorem(foo)] T,
+ #[lorem(bar = "x")] U: Eq + ?Sized,
+ #[lorem(foo = false)] V = (),
+ >(T, U, V);
+ };
+ let params = di.generics.params;
+
+ {
+ let ty = extract_type(&params[0]);
+ let lorem = Lorem::from_type_param(ty).unwrap();
+ assert_eq!(lorem.foo, true);
+ assert_eq!(lorem.bar, None);
+ }
+
+ {
+ let ty = extract_type(&params[1]);
+ let lorem = Lorem::from_type_param(ty).unwrap();
+ assert_eq!(lorem.foo, false);
+ assert_eq!(lorem.bar, Some("x".to_string()));
+ assert!(lorem.default.is_none());
+ }
+
+ {
+ let ty = extract_type(&params[2]);
+ let lorem = Lorem::from_type_param(ty).unwrap();
+ assert_eq!(lorem.foo, false);
+ assert_eq!(lorem.bar, None);
+ assert!(lorem.default.is_some());
+ }
+}
diff --git a/third_party/rust/darling/tests/from_variant.rs b/third_party/rust/darling/tests/from_variant.rs
new file mode 100644
index 0000000000..be216cbe52
--- /dev/null
+++ b/third_party/rust/darling/tests/from_variant.rs
@@ -0,0 +1,27 @@
+#[macro_use]
+extern crate darling;
+extern crate syn;
+
+#[derive(FromVariant)]
+#[darling(from_ident, attributes(hello))]
+#[allow(dead_code)]
+pub struct Lorem {
+ ident: syn::Ident,
+ into: Option<bool>,
+ skip: Option<bool>,
+ fields: darling::ast::Fields<syn::Type>,
+}
+
+impl From<syn::Ident> for Lorem {
+ fn from(ident: syn::Ident) -> Self {
+ Lorem {
+ ident,
+ into: Default::default(),
+ skip: Default::default(),
+ fields: darling::ast::Style::Unit.into(),
+ }
+ }
+}
+
+#[test]
+fn expansion() {}
diff --git a/third_party/rust/darling/tests/generics.rs b/third_party/rust/darling/tests/generics.rs
new file mode 100644
index 0000000000..a83d03e284
--- /dev/null
+++ b/third_party/rust/darling/tests/generics.rs
@@ -0,0 +1,27 @@
+#[macro_use]
+extern crate darling;
+#[macro_use]
+extern crate syn;
+#[macro_use]
+extern crate quote;
+
+use darling::FromDeriveInput;
+
+#[derive(Debug, Clone, FromMeta)]
+struct Wrapper<T>(pub T);
+
+#[derive(Debug, FromDeriveInput)]
+#[darling(attributes(hello))]
+struct Foo<T> {
+ lorem: Wrapper<T>,
+}
+
+#[test]
+fn expansion() {
+ let di = parse_quote! {
+ #[hello(lorem = "Hello")]
+ pub struct Foo;
+ };
+
+ Foo::<String>::from_derive_input(&di).unwrap();
+}
diff --git a/third_party/rust/darling/tests/happy_path.rs b/third_party/rust/darling/tests/happy_path.rs
new file mode 100644
index 0000000000..df1bfadd75
--- /dev/null
+++ b/third_party/rust/darling/tests/happy_path.rs
@@ -0,0 +1,75 @@
+#[macro_use]
+extern crate darling;
+#[macro_use]
+extern crate syn;
+#[macro_use]
+extern crate quote;
+
+use darling::FromDeriveInput;
+
+#[derive(Default, FromMeta, PartialEq, Debug)]
+#[darling(default)]
+struct Lorem {
+ ipsum: bool,
+ dolor: Option<String>,
+}
+
+#[derive(FromDeriveInput, PartialEq, Debug)]
+#[darling(attributes(darling_demo))]
+struct Core {
+ ident: syn::Ident,
+ vis: syn::Visibility,
+ generics: syn::Generics,
+ lorem: Lorem,
+}
+
+#[derive(FromDeriveInput, PartialEq, Debug)]
+#[darling(attributes(darling_demo))]
+struct TraitCore {
+ ident: syn::Ident,
+ generics: syn::Generics,
+ lorem: Lorem,
+}
+
+#[test]
+fn simple() {
+ let di = parse_quote! {
+ #[derive(Foo)]
+ #[darling_demo(lorem(ipsum))]
+ pub struct Bar;
+ };
+
+ assert_eq!(
+ Core::from_derive_input(&di).unwrap(),
+ Core {
+ ident: parse_quote!(Bar),
+ vis: parse_quote!(pub),
+ generics: Default::default(),
+ lorem: Lorem {
+ ipsum: true,
+ dolor: None,
+ },
+ }
+ );
+}
+
+#[test]
+fn trait_type() {
+ let di = parse_quote! {
+ #[derive(Foo)]
+ #[darling_demo(lorem(dolor = "hello"))]
+ pub struct Bar;
+ };
+
+ assert_eq!(
+ TraitCore::from_derive_input(&di).unwrap(),
+ TraitCore {
+ ident: parse_quote!(Bar),
+ generics: Default::default(),
+ lorem: Lorem {
+ ipsum: false,
+ dolor: Some("hello".to_owned()),
+ }
+ }
+ );
+}
diff --git a/third_party/rust/darling/tests/multiple.rs b/third_party/rust/darling/tests/multiple.rs
new file mode 100644
index 0000000000..e705280633
--- /dev/null
+++ b/third_party/rust/darling/tests/multiple.rs
@@ -0,0 +1,36 @@
+#[macro_use]
+extern crate darling;
+#[macro_use]
+extern crate syn;
+#[macro_use]
+extern crate quote;
+
+use darling::FromDeriveInput;
+
+#[derive(FromDeriveInput)]
+#[darling(attributes(hello))]
+#[allow(dead_code)]
+struct Lorem {
+ ident: syn::Ident,
+ ipsum: Ipsum,
+}
+
+#[derive(FromMeta)]
+struct Ipsum {
+ #[darling(multiple)]
+ dolor: Vec<String>,
+}
+
+#[test]
+fn expand_many() {
+ let di = parse_quote! {
+ #[hello(ipsum(dolor = "Hello", dolor = "World"))]
+ pub struct Baz;
+ };
+
+ let lorem: Lorem = Lorem::from_derive_input(&di).unwrap();
+ assert_eq!(
+ lorem.ipsum.dolor,
+ vec!["Hello".to_string(), "World".to_string()]
+ );
+}
diff --git a/third_party/rust/darling/tests/newtype.rs b/third_party/rust/darling/tests/newtype.rs
new file mode 100644
index 0000000000..5219d9ad93
--- /dev/null
+++ b/third_party/rust/darling/tests/newtype.rs
@@ -0,0 +1,32 @@
+//! A newtype struct should be able to derive `FromMeta` if its member implements it.
+
+#[macro_use]
+extern crate darling;
+#[macro_use]
+extern crate syn;
+#[macro_use]
+extern crate quote;
+
+use darling::FromDeriveInput;
+
+#[derive(Debug, FromMeta, PartialEq, Eq)]
+struct Lorem(bool);
+
+#[derive(Debug, FromDeriveInput)]
+#[darling(attributes(newtype))]
+struct DemoContainer {
+ lorem: Lorem,
+}
+
+#[test]
+fn generated() {
+ let di = parse_quote! {
+ #[derive(Baz)]
+ #[newtype(lorem = false)]
+ pub struct Foo;
+ };
+
+ let c = DemoContainer::from_derive_input(&di).unwrap();
+
+ assert_eq!(c.lorem, Lorem(false));
+}
diff --git a/third_party/rust/darling/tests/skip.rs b/third_party/rust/darling/tests/skip.rs
new file mode 100644
index 0000000000..b4e0f64dc1
--- /dev/null
+++ b/third_party/rust/darling/tests/skip.rs
@@ -0,0 +1,52 @@
+//! Test that skipped fields are not read into structs when they appear in input.
+
+#[macro_use]
+extern crate darling;
+#[macro_use]
+extern crate syn;
+#[macro_use]
+extern crate quote;
+
+use darling::FromDeriveInput;
+
+#[derive(Debug, PartialEq, Eq, FromDeriveInput)]
+#[darling(attributes(skip_test))]
+pub struct Lorem {
+ ipsum: String,
+
+ #[darling(skip)]
+ dolor: u8,
+}
+
+/// Verify variant-level and field-level skip work correctly for enums.
+#[derive(Debug, FromMeta)]
+pub enum Sit {
+ Amet(bool),
+
+ #[darling(skip)]
+ Foo {
+ hello: bool,
+ },
+
+ Bar {
+ hello: bool,
+ #[darling(skip)]
+ world: u8,
+ },
+}
+
+#[test]
+fn verify_skipped_field_not_required() {
+ let di = parse_quote! {
+ #[skip_test(ipsum = "Hello")]
+ struct Baz;
+ };
+
+ assert_eq!(
+ Lorem::from_derive_input(&di).unwrap(),
+ Lorem {
+ ipsum: "Hello".to_string(),
+ dolor: 0,
+ }
+ );
+}
diff --git a/third_party/rust/darling/tests/split_declaration.rs b/third_party/rust/darling/tests/split_declaration.rs
new file mode 100644
index 0000000000..23d458d173
--- /dev/null
+++ b/third_party/rust/darling/tests/split_declaration.rs
@@ -0,0 +1,78 @@
+//! When input is split across multiple attributes on one element,
+//! darling should collapse that into one struct.
+
+#[macro_use]
+extern crate darling;
+#[macro_use]
+extern crate syn;
+#[macro_use]
+extern crate quote;
+
+use std::string::ToString;
+
+use darling::{Error, FromDeriveInput};
+
+#[derive(Debug, FromDeriveInput, PartialEq, Eq)]
+#[darling(attributes(split))]
+struct Lorem {
+ foo: String,
+ bar: bool,
+}
+
+#[test]
+fn split_attributes_accrue_to_instance() {
+ let di = parse_quote! {
+ #[split(foo = "Hello")]
+ #[split(bar)]
+ pub struct Foo;
+ };
+
+ let parsed = Lorem::from_derive_input(&di).unwrap();
+ assert_eq!(
+ parsed,
+ Lorem {
+ foo: "Hello".to_string(),
+ bar: true,
+ }
+ );
+}
+
+#[test]
+fn duplicates_across_split_attrs_error() {
+ let di = parse_quote! {
+ #[split(foo = "Hello")]
+ #[split(foo = "World", bar)]
+ pub struct Foo;
+ };
+
+ let pr = Lorem::from_derive_input(&di).unwrap_err();
+ assert!(pr.has_span());
+ assert_eq!(
+ pr.to_string(),
+ Error::duplicate_field("foo").to_string()
+ );
+}
+
+#[test]
+fn multiple_errors_accrue_to_instance() {
+ let di = parse_quote! {
+ #[split(foo = "Hello")]
+ #[split(foo = "World")]
+ pub struct Foo;
+ };
+
+ let pr = Lorem::from_derive_input(&di);
+ let err: Error = pr.unwrap_err();
+ assert_eq!(2, err.len());
+ let mut errs = err.into_iter().peekable();
+ assert_eq!(
+ errs.peek().unwrap().to_string(),
+ Error::duplicate_field("foo").to_string()
+ );
+ assert!(errs.next().unwrap().has_span());
+ assert_eq!(
+ errs.next().unwrap().to_string(),
+ Error::missing_field("bar").to_string()
+ );
+ assert!(errs.next().is_none());
+}
diff --git a/third_party/rust/darling/tests/suggestions.rs b/third_party/rust/darling/tests/suggestions.rs
new file mode 100644
index 0000000000..3499e9ed9a
--- /dev/null
+++ b/third_party/rust/darling/tests/suggestions.rs
@@ -0,0 +1,34 @@
+#![cfg(feature = "suggestions")]
+
+#[macro_use]
+extern crate darling;
+#[macro_use]
+extern crate syn;
+#[macro_use]
+extern crate quote;
+
+use darling::FromDeriveInput;
+
+#[derive(Debug, FromDeriveInput)]
+#[darling(attributes(suggest))]
+struct Lorem {
+ ipsum: String,
+ dolor: Dolor,
+}
+
+#[derive(Debug, FromMeta)]
+struct Dolor {
+ sit: bool,
+}
+
+#[test]
+fn suggest_dolor() {
+ let input: syn::DeriveInput = parse_quote! {
+ #[suggest(ipsum = "Hello", dolorr(sit))]
+ pub struct Foo;
+ };
+
+ let result = Lorem::from_derive_input(&input).unwrap_err();
+ assert_eq!(2, result.len());
+ assert!(format!("{}", result).contains("Did you mean"));
+}
diff --git a/third_party/rust/darling/tests/supports.rs b/third_party/rust/darling/tests/supports.rs
new file mode 100644
index 0000000000..ead3bad3b5
--- /dev/null
+++ b/third_party/rust/darling/tests/supports.rs
@@ -0,0 +1,85 @@
+#[macro_use]
+extern crate darling;
+#[macro_use]
+extern crate syn;
+#[macro_use]
+extern crate quote;
+
+use darling::ast;
+use darling::FromDeriveInput;
+
+#[derive(Debug, FromDeriveInput)]
+#[darling(attributes(from_variants), supports(enum_any))]
+pub struct Container {
+ data: ast::Data<Variant, ()>,
+}
+
+#[derive(Default, Debug, FromVariant)]
+#[darling(default, attributes(from_variants), supports(newtype, unit))]
+pub struct Variant {
+ into: Option<bool>,
+ skip: Option<bool>,
+}
+
+#[derive(Debug, FromDeriveInput)]
+#[darling(attributes(from_struct), supports(struct_named))]
+pub struct StructContainer {
+ data: ast::Data<(), syn::Field>,
+}
+
+mod source {
+ use syn::DeriveInput;
+
+ pub fn newtype_enum() -> DeriveInput {
+ parse_quote!{
+ enum Hello {
+ World(bool),
+ String(String),
+ }
+ }
+ }
+
+ pub fn named_field_enum() -> DeriveInput {
+ parse_quote! {
+ enum Hello {
+ Foo(u16),
+ World {
+ name: String
+ },
+ }
+ }
+ }
+
+ pub fn named_struct() -> DeriveInput {
+ parse_quote! {
+ struct Hello {
+ world: bool,
+ }
+ }
+ }
+
+ pub fn tuple_struct() -> DeriveInput {
+ parse_quote! { struct Hello(String, bool); }
+ }
+}
+
+#[test]
+fn enum_newtype_or_unit() {
+ // Should pass
+ Container::from_derive_input(&source::newtype_enum()).unwrap();
+
+ // Should error
+ Container::from_derive_input(&source::named_field_enum()).unwrap_err();
+ Container::from_derive_input(&source::named_struct()).unwrap_err();
+}
+
+#[test]
+fn struct_named() {
+ // Should pass
+ StructContainer::from_derive_input(&source::named_struct()).unwrap();
+
+ // Should fail
+ StructContainer::from_derive_input(&source::tuple_struct()).unwrap_err();
+ StructContainer::from_derive_input(&source::named_field_enum()).unwrap_err();
+ StructContainer::from_derive_input(&source::newtype_enum()).unwrap_err();
+}
diff --git a/third_party/rust/darling_core/.cargo-checksum.json b/third_party/rust/darling_core/.cargo-checksum.json
new file mode 100644
index 0000000000..828d6ce066
--- /dev/null
+++ b/third_party/rust/darling_core/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"550d5451a115c7cb8118c0a038e12b1b97ddcefeee0303438296b86aacbe84e5","LICENSE":"8ea93490d74a5a1b1af3ff71d786271b3f1e5f0bea79ac16e02ec533cef040d6","src/ast/data.rs":"73a6b7a679011135dfee25af462163b3fe3f3effdf028c440aa6e3e4b5ff079f","src/ast/generics.rs":"3bdfe1abdbee64f5aaa9b189dc5c58e222568f196ed206e9d6d91ea5f29673e7","src/ast/mod.rs":"58a58eeb1db7682e5994732cc8eb04088f6ca662805460ef443cf089e5c24e2c","src/codegen/attr_extractor.rs":"d49605dbea8e95d64a9859a8beef5cf678390ffc5ba76ec77d69913f650ba974","src/codegen/default_expr.rs":"60f23b77ddf80da70ec92fd0d8cb5a97143535df85eafa0e47943ac797ec46d2","src/codegen/error.rs":"1a415136f93adde7458e39cab91413adc9a64243b718c7b74fdeba748959b5af","src/codegen/field.rs":"82104df8f3e733b23764fd6683e60d24ce62912b8b29a22dadbbc55d6a42f158","src/codegen/from_derive_impl.rs":"7cc03ffcc65e8e06dbf9d469502dc4ddd8772a2177dbf6404ad32d306379f777","src/codegen/from_field.rs":"a77abdb024b9a884dcdfda758ab072f26d5fae12eb67a3deb3dc47c6be2f2390","src/codegen/from_meta_impl.rs":"8fc08e65736efaf82b7aa2ce7e20c1a4235a94840353b860d6e782606c92ce18","src/codegen/from_type_param.rs":"c9cdb902d72f2ec047aeaa5217c2cda551d6cfc570f51ae4420907d6b398d9e7","src/codegen/from_variant_impl.rs":"1b44e10d8a0c43b1dcb7d66d1ced74ffab7f7beaa680031c11cfd4ab1abb39bf","src/codegen/mod.rs":"2dc3ee7f18177b2ef9c27c4f0cabc5bbd49f970abdba28a0539d81c70d81b6e2","src/codegen/outer_from_impl.rs":"41f5b6b4fb9185f88eaab3fbeed8b07e5791d04f265ee3c77e874a869fac7e1a","src/codegen/trait_impl.rs":"94c6f8a190ab2957ddae55745184e056ec5e43e9c552f492a3cb2f387dfb4a6a","src/codegen/variant.rs":"69ee861a63e31feb158611e93d0a355fdd94d6c8f3adc6c550864b7f5906d0ba","src/codegen/variant_data.rs":"bf17078e1bfeb35fae88b6ba124d730a27028ab75a422b247bbe09022c5f84d1","src/derive.rs":"89180c13798b61510a6d266781e065114b75ca0be27e172a24656347b9baf1d3","src/error/kind.rs":"877f025ff72839ede46b8c7460331dac32ec56a7539816820179110381f8d0fb","src/error/mod.rs":"a440321a7d7d76ecdbd100a8a4ac94d231fdf4e58a8758d09c115d6d7e297601","src/from_derive_input.rs":"b2a04fefa4e14684061c819387ea0384297c67c7f50d5d0959aa69ab19075e76","src/from_field.rs":"f667924422ab4ab8d8b16ebfd42f61e74864cfaa80e96b49de5d1e1287e3d1d3","src/from_generic_param.rs":"49c5a8335eb0a9010998c5600c95c89440f7febe03265afb625d818dbc883d92","src/from_generics.rs":"7285b0fd213507e87c1da413cd1bc9eeada485d4a8f9d19630848d02a4d41c4a","src/from_meta.rs":"11cd84155ab7ac2f20eb5eb6b297be3606871bf5ee10fa529cbb6e370fe9ab68","src/from_type_param.rs":"9b611f276871002ade78146266fde3b6f9101b360082681a2fa2dafc16431f84","src/from_variant.rs":"70a23b5b4cb93c7e5a498fe9d16420b9b93bd69c1376d7703bc7cefd9417d159","src/lib.rs":"337ce983fd49548c60bc0d8662f6d279daec1964c79b123453340158d55d39ab","src/macros_private.rs":"ef249cd9ca593aac423b4242df1c39c31610438da094c21562d74a7e5823c700","src/macros_public.rs":"3ed7eb99f309d9cd600d3a09ff4dcf5cc5d787fb49e8e5ead6bb00e31e5e6793","src/options/core.rs":"02659124b387437daf3b7d6c841a07478dc39a5a626e8ac4b7703e48c6675f6d","src/options/forward_attrs.rs":"a8bb729d8096dd467f23d55c5b4f09e1b8f329181b7d63c75b10fb51518277fd","src/options/from_derive.rs":"e3e13549d327169a64e831612c370662d09465e11690a3e8a6d029591dba3c8b","src/options/from_field.rs":"67f338df3ffc270b3baf08b35cbe985802a65c1360c4e540cc5b937f6f08f915","src/options/from_meta.rs":"81a2ae765d390f64fbcbb1d30d40e895d77f8cd4f4c5f7167b1eacb48e066195","src/options/from_type_param.rs":"d3c8add6c8f5f7ee3d4a487c53e1f85002a2da43b943c03d4ce856fa6e7c8453","src/options/from_variant.rs":"6b2d0b37c9f66ff59b2ac74c51bc7c968a44c2f4812baf428ed2f6801a474704","src/options/input_field.rs":"6e09c3432c63130a7def5cd1c4ba2d9ae2f692e58f82224e96f1212f09d2adb5","src/options/input_variant.rs":"94050b9185838296b7eb6ffacf41472cbff63461162b0005ca07c9a792c749ac","src/options/mod.rs":"8fe5c94c3999d210cb024c6f6b181da92a0cc1a4a862e5d46ec49904c6692e11","src/options/outer_from.rs":"648e3005f19b38299284df954b371fba9cea2fab39a6cfd6b54b5437b4200599","src/options/shape.rs":"03ca937d0c158e96337731517b8cfbc839f536e691f2f31713222bd228b49e07","src/usage/generics_ext.rs":"340774fe43033680e6b494c76dd4f558ada7ca4f09e91f9e4d076f125a729fc2","src/usage/ident_set.rs":"30edb2f0a599284967e3c6b579da31e5f9b15f3dd67bc9a82d6335eb44133df0","src/usage/lifetimes.rs":"35546bd524c38cbae2366e59ac2d836fe09af8e59aa99c7992d1e4d725364db7","src/usage/mod.rs":"e49adadfa8ffed27299d5bbf3c33e68e2c8c7411f89aef655f77e158be9dd642","src/usage/options.rs":"0491c995aad0d55783b24cce8a4e40f0f4435988c54ce2ded34763ac9b199fcf","src/usage/type_params.rs":"c46323838a5e1e87a1a75878314a8b1217e8d63d27a5067961c3b908842d248b","src/util/ident_string.rs":"2b7fdbe9664c2e306114ffa830fde9710d849a0240029636cbb244457795b13f","src/util/ignored.rs":"7c979fbef880498ff64efda7396e759d80bf77fb1c7df0313bed8e533a16c0e0","src/util/mod.rs":"9d8fef190513b6ab675a6ea3cf7e2841d2204fd38d8d55b10cc915d583491982","src/util/over_ride.rs":"5750d284d46c6a51522e908b642c8f09cd6e48c91fd25077f24ce75989525560","src/util/path_list.rs":"4d14eef07b6e3a3e69a539c49b3f25d477e79bd55594cd7324fda3b86784b0f5","src/util/spanned_value.rs":"3938cfc5169237cde1f19d65b653e1da8699663d1abfcf005359d48bbcee7d0b","src/util/with_original.rs":"a545b38ba9d624fdc939eb844f001b7fc4102717b1d3683b4cbd0aae00fa7ef2"},"package":"ee54512bec54b41cf2337a22ddfadb53c7d4c738494dc2a186d7b037ad683b85"} \ No newline at end of file
diff --git a/third_party/rust/darling_core/Cargo.toml b/third_party/rust/darling_core/Cargo.toml
new file mode 100644
index 0000000000..c457f1eaa7
--- /dev/null
+++ b/third_party/rust/darling_core/Cargo.toml
@@ -0,0 +1,42 @@
+# 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 believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "darling_core"
+version = "0.10.1"
+authors = ["Ted Driggs <ted.driggs@outlook.com>"]
+description = "Helper crate for proc-macro library for reading attributes into structs when\nimplementing custom derives. Use https://crates.io/crates/darling in your code.\n"
+license = "MIT"
+repository = "https://github.com/TedDriggs/darling"
+[dependencies.fnv]
+version = "1.0.6"
+
+[dependencies.ident_case]
+version = "1.0.0"
+
+[dependencies.proc-macro2]
+version = "1"
+
+[dependencies.quote]
+version = "1"
+
+[dependencies.strsim]
+version = "0.9.0"
+optional = true
+
+[dependencies.syn]
+version = "1"
+features = ["full", "extra-traits"]
+
+[features]
+diagnostics = []
+suggestions = ["strsim"]
diff --git a/third_party/rust/darling_core/LICENSE b/third_party/rust/darling_core/LICENSE
new file mode 100644
index 0000000000..0b48eadc9d
--- /dev/null
+++ b/third_party/rust/darling_core/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017 Ted Driggs
+
+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/darling_core/src/ast/data.rs b/third_party/rust/darling_core/src/ast/data.rs
new file mode 100644
index 0000000000..a0c765c56f
--- /dev/null
+++ b/third_party/rust/darling_core/src/ast/data.rs
@@ -0,0 +1,360 @@
+use std::{slice, vec};
+
+use syn;
+
+use usage::{
+ self, IdentRefSet, IdentSet, LifetimeRefSet, LifetimeSet, UsesLifetimes, UsesTypeParams,
+};
+use {Error, FromField, FromVariant, Result};
+
+/// A struct or enum body.
+///
+/// `V` is the type which receives any encountered variants, and `F` receives struct fields.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum Data<V, F> {
+ Enum(Vec<V>),
+ Struct(Fields<F>),
+}
+
+impl<V, F> Data<V, F> {
+ /// Creates an empty body of the same shape as the passed-in body.
+ pub fn empty_from(src: &syn::Data) -> Self {
+ match *src {
+ syn::Data::Enum(_) => Data::Enum(vec![]),
+ syn::Data::Struct(ref vd) => Data::Struct(Fields::empty_from(&vd.fields)),
+ syn::Data::Union(_) => unreachable!(),
+ }
+ }
+
+ /// Creates a new `Data<&'a V, &'a F>` instance from `Data<V, F>`.
+ pub fn as_ref<'a>(&'a self) -> Data<&'a V, &'a F> {
+ match *self {
+ Data::Enum(ref variants) => Data::Enum(variants.iter().collect()),
+ Data::Struct(ref data) => Data::Struct(data.as_ref()),
+ }
+ }
+
+ /// Applies a function `V -> U` on enum variants, if this is an enum.
+ pub fn map_enum_variants<T, U>(self, map: T) -> Data<U, F>
+ where
+ T: FnMut(V) -> U,
+ {
+ match self {
+ Data::Enum(v) => Data::Enum(v.into_iter().map(map).collect()),
+ Data::Struct(f) => Data::Struct(f),
+ }
+ }
+
+ /// Applies a function `F -> U` on struct fields, if this is a struct.
+ pub fn map_struct_fields<T, U>(self, map: T) -> Data<V, U>
+ where
+ T: FnMut(F) -> U,
+ {
+ match self {
+ Data::Enum(v) => Data::Enum(v),
+ Data::Struct(f) => Data::Struct(f.map(map)),
+ }
+ }
+
+ /// Applies a function to the `Fields` if this is a struct.
+ pub fn map_struct<T, U>(self, mut map: T) -> Data<V, U>
+ where
+ T: FnMut(Fields<F>) -> Fields<U>,
+ {
+ match self {
+ Data::Enum(v) => Data::Enum(v),
+ Data::Struct(f) => Data::Struct(map(f)),
+ }
+ }
+
+ /// Consumes the `Data`, returning `Fields<F>` if it was a struct.
+ pub fn take_struct(self) -> Option<Fields<F>> {
+ match self {
+ Data::Enum(_) => None,
+ Data::Struct(f) => Some(f),
+ }
+ }
+
+ /// Consumes the `Data`, returning `Vec<V>` if it was an enum.
+ pub fn take_enum(self) -> Option<Vec<V>> {
+ match self {
+ Data::Enum(v) => Some(v),
+ Data::Struct(_) => None,
+ }
+ }
+
+ /// Returns `true` if this instance is `Data::Enum`.
+ pub fn is_enum(&self) -> bool {
+ match *self {
+ Data::Enum(_) => true,
+ Data::Struct(_) => false,
+ }
+ }
+
+ /// Returns `true` if this instance is `Data::Struct`.
+ pub fn is_struct(&self) -> bool {
+ !self.is_enum()
+ }
+}
+
+impl<V: FromVariant, F: FromField> Data<V, F> {
+ /// Attempt to convert from a `syn::Data` instance.
+ pub fn try_from(body: &syn::Data) -> Result<Self> {
+ match *body {
+ syn::Data::Enum(ref data) => {
+ let mut items = Vec::with_capacity(data.variants.len());
+ let mut errors = Vec::new();
+ for v_result in data.variants.iter().map(FromVariant::from_variant) {
+ match v_result {
+ Ok(val) => items.push(val),
+ Err(err) => errors.push(err),
+ }
+ }
+
+ if !errors.is_empty() {
+ Err(Error::multiple(errors))
+ } else {
+ Ok(Data::Enum(items))
+ }
+ }
+ syn::Data::Struct(ref data) => Ok(Data::Struct(Fields::try_from(&data.fields)?)),
+ syn::Data::Union(_) => unreachable!(),
+ }
+ }
+}
+
+impl<V: UsesTypeParams, F: UsesTypeParams> UsesTypeParams for Data<V, F> {
+ fn uses_type_params<'a>(
+ &self,
+ options: &usage::Options,
+ type_set: &'a IdentSet,
+ ) -> IdentRefSet<'a> {
+ match *self {
+ Data::Struct(ref v) => v.uses_type_params(options, type_set),
+ Data::Enum(ref v) => v.uses_type_params(options, type_set),
+ }
+ }
+}
+
+impl<V: UsesLifetimes, F: UsesLifetimes> UsesLifetimes for Data<V, F> {
+ fn uses_lifetimes<'a>(
+ &self,
+ options: &usage::Options,
+ lifetimes: &'a LifetimeSet,
+ ) -> LifetimeRefSet<'a> {
+ match *self {
+ Data::Struct(ref v) => v.uses_lifetimes(options, lifetimes),
+ Data::Enum(ref v) => v.uses_lifetimes(options, lifetimes),
+ }
+ }
+}
+
+/// Equivalent to `syn::Fields`, but replaces the AST element with a generic.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Fields<T> {
+ pub style: Style,
+ pub fields: Vec<T>,
+}
+
+impl<T> Fields<T> {
+ pub fn empty_from(vd: &syn::Fields) -> Self {
+ Fields {
+ style: vd.into(),
+ fields: Vec::new(),
+ }
+ }
+
+ /// Splits the `Fields` into its style and fields for further processing.
+ /// Returns an empty `Vec` for `Unit` data.
+ pub fn split(self) -> (Style, Vec<T>) {
+ (self.style, self.fields)
+ }
+
+ /// Returns true if this variant's data makes it a newtype.
+ pub fn is_newtype(&self) -> bool {
+ self.style == Style::Tuple && self.len() == 1
+ }
+
+ pub fn is_unit(&self) -> bool {
+ self.style.is_unit()
+ }
+
+ pub fn is_tuple(&self) -> bool {
+ self.style.is_tuple()
+ }
+
+ pub fn is_struct(&self) -> bool {
+ self.style.is_struct()
+ }
+
+ pub fn as_ref<'a>(&'a self) -> Fields<&'a T> {
+ Fields {
+ style: self.style,
+ fields: self.fields.iter().collect(),
+ }
+ }
+
+ pub fn map<F, U>(self, map: F) -> Fields<U>
+ where
+ F: FnMut(T) -> U,
+ {
+ Fields {
+ style: self.style,
+ fields: self.fields.into_iter().map(map).collect(),
+ }
+ }
+
+ pub fn iter(&self) -> slice::Iter<T> {
+ self.fields.iter()
+ }
+
+ /// Returns the number of fields in the structure.
+ pub fn len(&self) -> usize {
+ self.fields.len()
+ }
+
+ /// Returns `true` if the `Fields` contains no fields.
+ pub fn is_empty(&self) -> bool {
+ self.fields.is_empty()
+ }
+}
+
+impl<F: FromField> Fields<F> {
+ pub fn try_from(fields: &syn::Fields) -> Result<Self> {
+ let (items, errors) = match *fields {
+ syn::Fields::Named(ref fields) => {
+ let mut items = Vec::with_capacity(fields.named.len());
+ let mut errors = Vec::new();
+
+ for field in &fields.named {
+ match FromField::from_field(field) {
+ Ok(val) => items.push(val),
+ Err(err) => errors.push(if let Some(ref ident) = field.ident {
+ err.at(ident)
+ } else {
+ err
+ }),
+ }
+ }
+
+ (items, errors)
+ }
+ syn::Fields::Unnamed(ref fields) => {
+ let mut items = Vec::with_capacity(fields.unnamed.len());
+ let mut errors = Vec::new();
+
+ for field in &fields.unnamed {
+ match FromField::from_field(field) {
+ Ok(val) => items.push(val),
+ Err(err) => errors.push(if let Some(ref ident) = field.ident {
+ err.at(ident)
+ } else {
+ err
+ }),
+ }
+ }
+
+ (items, errors)
+ }
+ syn::Fields::Unit => (vec![], vec![]),
+ };
+
+ if !errors.is_empty() {
+ Err(Error::multiple(errors))
+ } else {
+ Ok(Fields {
+ style: fields.into(),
+ fields: items,
+ })
+ }
+ }
+}
+
+impl<T> IntoIterator for Fields<T> {
+ type Item = T;
+ type IntoIter = vec::IntoIter<T>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.fields.into_iter()
+ }
+}
+
+impl<T> From<Style> for Fields<T> {
+ fn from(style: Style) -> Self {
+ Fields {
+ style,
+ fields: Vec::new(),
+ }
+ }
+}
+
+impl<T, U: Into<Vec<T>>> From<(Style, U)> for Fields<T> {
+ fn from((style, fields): (Style, U)) -> Self {
+ style.with_fields(fields)
+ }
+}
+
+impl<T: UsesTypeParams> UsesTypeParams for Fields<T> {
+ fn uses_type_params<'a>(
+ &self,
+ options: &usage::Options,
+ type_set: &'a IdentSet,
+ ) -> IdentRefSet<'a> {
+ self.fields.uses_type_params(options, type_set)
+ }
+}
+
+impl<T: UsesLifetimes> UsesLifetimes for Fields<T> {
+ fn uses_lifetimes<'a>(
+ &self,
+ options: &usage::Options,
+ lifetimes: &'a LifetimeSet,
+ ) -> LifetimeRefSet<'a> {
+ self.fields.uses_lifetimes(options, lifetimes)
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum Style {
+ Tuple,
+ Struct,
+ Unit,
+}
+
+impl Style {
+ pub fn is_unit(self) -> bool {
+ self == Style::Unit
+ }
+
+ pub fn is_tuple(self) -> bool {
+ self == Style::Tuple
+ }
+
+ pub fn is_struct(self) -> bool {
+ self == Style::Struct
+ }
+
+ /// Creates a new `Fields` of the specified style with the passed-in fields.
+ fn with_fields<T, U: Into<Vec<T>>>(self, fields: U) -> Fields<T> {
+ Fields {
+ style: self,
+ fields: fields.into(),
+ }
+ }
+}
+
+impl From<syn::Fields> for Style {
+ fn from(vd: syn::Fields) -> Self {
+ (&vd).into()
+ }
+}
+
+impl<'a> From<&'a syn::Fields> for Style {
+ fn from(vd: &syn::Fields) -> Self {
+ match *vd {
+ syn::Fields::Named(_) => Style::Struct,
+ syn::Fields::Unnamed(_) => Style::Tuple,
+ syn::Fields::Unit => Style::Unit,
+ }
+ }
+}
diff --git a/third_party/rust/darling_core/src/ast/generics.rs b/third_party/rust/darling_core/src/ast/generics.rs
new file mode 100644
index 0000000000..2619993036
--- /dev/null
+++ b/third_party/rust/darling_core/src/ast/generics.rs
@@ -0,0 +1,194 @@
+//! Types for working with generics
+
+use std::iter::Iterator;
+use std::slice::Iter;
+
+use syn;
+
+use {FromGenericParam, FromGenerics, FromTypeParam, Result};
+
+/// Extension trait for `GenericParam` to support getting values by variant.
+///
+/// # Usage
+/// `darling::ast::Generics` needs a way to test its params array in order to iterate over type params.
+/// Rather than require callers to use `darling::ast::GenericParam` in all cases, this trait makes that
+/// polymorphic.
+pub trait GenericParamExt {
+ /// The type this GenericParam uses to represent type params and their bounds
+ type TypeParam;
+ type LifetimeDef;
+ type ConstParam;
+
+ /// If this GenericParam is a type param, get the underlying value.
+ fn as_type_param(&self) -> Option<&Self::TypeParam> {
+ None
+ }
+
+ /// If this GenericParam is a lifetime, get the underlying value.
+ fn as_lifetime_def(&self) -> Option<&Self::LifetimeDef> {
+ None
+ }
+
+ /// If this GenericParam is a const param, get the underlying value.
+ fn as_const_param(&self) -> Option<&Self::ConstParam> {
+ None
+ }
+}
+
+impl GenericParamExt for syn::GenericParam {
+ type TypeParam = syn::TypeParam;
+ type LifetimeDef = syn::LifetimeDef;
+ type ConstParam = syn::ConstParam;
+
+ fn as_type_param(&self) -> Option<&Self::TypeParam> {
+ if let syn::GenericParam::Type(ref val) = *self {
+ Some(val)
+ } else {
+ None
+ }
+ }
+
+ fn as_lifetime_def(&self) -> Option<&Self::LifetimeDef> {
+ if let syn::GenericParam::Lifetime(ref val) = *self {
+ Some(val)
+ } else {
+ None
+ }
+ }
+
+ fn as_const_param(&self) -> Option<&Self::ConstParam> {
+ if let syn::GenericParam::Const(ref val) = *self {
+ Some(val)
+ } else {
+ None
+ }
+ }
+}
+
+impl GenericParamExt for syn::TypeParam {
+ type TypeParam = syn::TypeParam;
+ type LifetimeDef = ();
+ type ConstParam = ();
+
+ fn as_type_param(&self) -> Option<&Self::TypeParam> {
+ Some(self)
+ }
+}
+
+/// A mirror of `syn::GenericParam` which is generic over all its contents.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum GenericParam<T = syn::TypeParam, L = syn::LifetimeDef, C = syn::ConstParam> {
+ Type(T),
+ Lifetime(L),
+ Const(C),
+}
+
+impl<T: FromTypeParam> FromTypeParam for GenericParam<T> {
+ fn from_type_param(type_param: &syn::TypeParam) -> Result<Self> {
+ Ok(GenericParam::Type(FromTypeParam::from_type_param(
+ type_param,
+ )?))
+ }
+}
+
+impl<T: FromTypeParam> FromGenericParam for GenericParam<T> {
+ fn from_generic_param(param: &syn::GenericParam) -> Result<Self> {
+ Ok(match *param {
+ syn::GenericParam::Type(ref ty) => {
+ GenericParam::Type(FromTypeParam::from_type_param(ty)?)
+ }
+ syn::GenericParam::Lifetime(ref val) => GenericParam::Lifetime(val.clone()),
+ syn::GenericParam::Const(ref val) => GenericParam::Const(val.clone()),
+ })
+ }
+}
+
+impl<T, L, C> GenericParamExt for GenericParam<T, L, C> {
+ type TypeParam = T;
+ type LifetimeDef = L;
+ type ConstParam = C;
+
+ fn as_type_param(&self) -> Option<&T> {
+ if let GenericParam::Type(ref val) = *self {
+ Some(val)
+ } else {
+ None
+ }
+ }
+
+ fn as_lifetime_def(&self) -> Option<&L> {
+ if let GenericParam::Lifetime(ref val) = *self {
+ Some(val)
+ } else {
+ None
+ }
+ }
+
+ fn as_const_param(&self) -> Option<&C> {
+ if let GenericParam::Const(ref val) = *self {
+ Some(val)
+ } else {
+ None
+ }
+ }
+}
+
+/// A mirror of the `syn::Generics` type which can contain arbitrary representations
+/// of params and where clauses.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Generics<P, W = syn::WhereClause> {
+ pub params: Vec<P>,
+ pub where_clause: Option<W>,
+}
+
+impl<P, W> Generics<P, W> {
+ pub fn type_params<'a>(&'a self) -> TypeParams<'a, P> {
+ TypeParams(self.params.iter())
+ }
+}
+
+impl<P: FromGenericParam> FromGenerics for Generics<P> {
+ fn from_generics(generics: &syn::Generics) -> Result<Self> {
+ Ok(Generics {
+ params: generics
+ .params
+ .iter()
+ .map(FromGenericParam::from_generic_param)
+ .collect::<Result<Vec<P>>>()?,
+ where_clause: generics.where_clause.clone(),
+ })
+ }
+}
+
+pub struct TypeParams<'a, P: 'a>(Iter<'a, P>);
+
+impl<'a, P: GenericParamExt> Iterator for TypeParams<'a, P> {
+ type Item = &'a <P as GenericParamExt>::TypeParam;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let next = self.0.next();
+ match next {
+ None => None,
+ Some(v) => match v.as_type_param() {
+ Some(val) => Some(val),
+ None => self.next(),
+ },
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use syn;
+
+ use super::{GenericParam, Generics};
+ use FromGenerics;
+
+ #[test]
+ fn generics() {
+ let g: syn::Generics = parse_quote!(<T>);
+ let deified: Generics<GenericParam<syn::Ident>> = FromGenerics::from_generics(&g).unwrap();
+ assert!(deified.params.len() == 1);
+ assert!(deified.where_clause.is_none());
+ }
+}
diff --git a/third_party/rust/darling_core/src/ast/mod.rs b/third_party/rust/darling_core/src/ast/mod.rs
new file mode 100644
index 0000000000..492b26f182
--- /dev/null
+++ b/third_party/rust/darling_core/src/ast/mod.rs
@@ -0,0 +1,7 @@
+//! Utility types for working with the AST.
+
+mod data;
+mod generics;
+
+pub use self::data::*;
+pub use self::generics::{GenericParam, GenericParamExt, Generics};
diff --git a/third_party/rust/darling_core/src/codegen/attr_extractor.rs b/third_party/rust/darling_core/src/codegen/attr_extractor.rs
new file mode 100644
index 0000000000..6d128bd97b
--- /dev/null
+++ b/third_party/rust/darling_core/src/codegen/attr_extractor.rs
@@ -0,0 +1,110 @@
+use proc_macro2::TokenStream;
+
+use options::ForwardAttrs;
+use util::PathList;
+
+/// Infrastructure for generating an attribute extractor.
+pub trait ExtractAttribute {
+ /// A set of mutable declarations for all members of the implementing type.
+ fn local_declarations(&self) -> TokenStream;
+
+ /// A set of immutable declarations for all members of the implementing type.
+ /// This is used in the case where a deriving struct handles no attributes and therefore can
+ /// never change its default state.
+ fn immutable_declarations(&self) -> TokenStream;
+
+ /// Gets the list of attribute names that should be parsed by the extractor.
+ fn attr_names(&self) -> &PathList;
+
+ fn forwarded_attrs(&self) -> Option<&ForwardAttrs>;
+
+ /// Gets the name used by the generated impl to return to the `syn` item passed as input.
+ fn param_name(&self) -> TokenStream;
+
+ /// Gets the core from-meta-item loop that should be used on matching attributes.
+ fn core_loop(&self) -> TokenStream;
+
+ fn declarations(&self) -> TokenStream {
+ if !self.attr_names().is_empty() {
+ self.local_declarations()
+ } else {
+ self.immutable_declarations()
+ }
+ }
+
+ /// Generates the main extraction loop.
+ fn extractor(&self) -> TokenStream {
+ let declarations = self.declarations();
+
+ let will_parse_any = !self.attr_names().is_empty();
+ let will_fwd_any = self
+ .forwarded_attrs()
+ .map(|fa| !fa.is_empty())
+ .unwrap_or_default();
+
+ if !(will_parse_any || will_fwd_any) {
+ return quote! {
+ #declarations
+ };
+ }
+
+ let input = self.param_name();
+
+ // The block for parsing attributes whose names have been claimed by the target
+ // struct. If no attributes were claimed, this is a pass-through.
+ let parse_handled = if will_parse_any {
+ let attr_names = self.attr_names().to_strings();
+ let core_loop = self.core_loop();
+ quote!(
+ #(#attr_names)|* => {
+ if let ::darling::export::Ok(::syn::Meta::List(ref __data)) = __attr.parse_meta() {
+ let __items = &__data.nested;
+
+ #core_loop
+ } else {
+ // darling currently only supports list-style
+ continue
+ }
+ }
+ )
+ } else {
+ quote!()
+ };
+
+ // Specifies the behavior for unhandled attributes. They will either be silently ignored or
+ // forwarded to the inner struct for later analysis.
+ let forward_unhandled = if will_fwd_any {
+ forwards_to_local(self.forwarded_attrs().unwrap())
+ } else {
+ quote!(_ => continue)
+ };
+
+ quote!(
+ #declarations
+ use ::darling::ToTokens;
+ let mut __fwd_attrs: ::darling::export::Vec<::syn::Attribute> = vec![];
+
+ for __attr in &#input.attrs {
+ // Filter attributes based on name
+ match ::darling::export::ToString::to_string(&__attr.path.clone().into_token_stream()).as_str() {
+ #parse_handled
+ #forward_unhandled
+ }
+ }
+ )
+ }
+}
+
+fn forwards_to_local(behavior: &ForwardAttrs) -> TokenStream {
+ let push_command = quote!(__fwd_attrs.push(__attr.clone()));
+ match *behavior {
+ ForwardAttrs::All => quote!(_ => #push_command),
+ ForwardAttrs::Only(ref idents) => {
+ let names = idents.to_strings();
+ quote!(
+ #(#names)|* => #push_command,
+ _ => continue,
+ )
+ }
+ }
+}
diff --git a/third_party/rust/darling_core/src/codegen/default_expr.rs b/third_party/rust/darling_core/src/codegen/default_expr.rs
new file mode 100644
index 0000000000..3bafca09d7
--- /dev/null
+++ b/third_party/rust/darling_core/src/codegen/default_expr.rs
@@ -0,0 +1,46 @@
+use proc_macro2::TokenStream;
+use quote::{TokenStreamExt, ToTokens};
+use syn::{Ident, Path};
+
+/// This will be in scope during struct initialization after option parsing.
+const DEFAULT_STRUCT_NAME: &str = "__default";
+
+/// The fallback value for a field or container.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum DefaultExpression<'a> {
+ /// Only valid on fields, `Inherit` indicates that the value should be taken from a pre-constructed
+ /// fallback object. The value in the variant is the ident of the field.
+ Inherit(&'a Ident),
+ Explicit(&'a Path),
+ Trait,
+}
+
+impl<'a> DefaultExpression<'a> {
+ pub fn as_declaration(&'a self) -> DefaultDeclaration<'a> {
+ DefaultDeclaration(self)
+ }
+}
+
+impl<'a> ToTokens for DefaultExpression<'a> {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(match *self {
+ DefaultExpression::Inherit(ident) => {
+ let dsn = Ident::new(DEFAULT_STRUCT_NAME, ::proc_macro2::Span::call_site());
+ quote!(#dsn.#ident)
+ }
+ DefaultExpression::Explicit(path) => quote!(#path()),
+ DefaultExpression::Trait => quote!(::darling::export::Default::default()),
+ });
+ }
+}
+
+/// Used only by containers, this wrapper type generates code to declare the fallback instance.
+pub struct DefaultDeclaration<'a>(&'a DefaultExpression<'a>);
+
+impl<'a> ToTokens for DefaultDeclaration<'a> {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ let name = Ident::new(DEFAULT_STRUCT_NAME, ::proc_macro2::Span::call_site());
+ let expr = self.0;
+ tokens.append_all(quote!(let #name: Self = #expr;));
+ }
+}
diff --git a/third_party/rust/darling_core/src/codegen/error.rs b/third_party/rust/darling_core/src/codegen/error.rs
new file mode 100644
index 0000000000..bfa18d2d33
--- /dev/null
+++ b/third_party/rust/darling_core/src/codegen/error.rs
@@ -0,0 +1,48 @@
+use proc_macro2::TokenStream;
+use quote::{TokenStreamExt, ToTokens};
+
+/// Declares the local variable into which errors will be accumulated.
+#[derive(Default)]
+pub struct ErrorDeclaration {
+ __hidden: (),
+}
+
+impl ToTokens for ErrorDeclaration {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(quote! {
+ let mut __errors = ::darling::export::Vec::new();
+ })
+ }
+}
+
+/// Returns early if attribute or body parsing has caused any errors.
+#[derive(Default)]
+pub struct ErrorCheck<'a> {
+ location: Option<&'a str>,
+ __hidden: (),
+}
+
+impl<'a> ErrorCheck<'a> {
+ pub fn with_location(location: &'a str) -> Self {
+ ErrorCheck {
+ location: Some(location),
+ __hidden: (),
+ }
+ }
+}
+
+impl<'a> ToTokens for ErrorCheck<'a> {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ let at_call = if let Some(ref s) = self.location {
+ quote!(.at(#s))
+ } else {
+ quote!()
+ };
+
+ tokens.append_all(quote! {
+ if !__errors.is_empty() {
+ return ::darling::export::Err(::darling::Error::multiple(__errors) #at_call);
+ }
+ })
+ }
+}
diff --git a/third_party/rust/darling_core/src/codegen/field.rs b/third_party/rust/darling_core/src/codegen/field.rs
new file mode 100644
index 0000000000..ae32f88d5c
--- /dev/null
+++ b/third_party/rust/darling_core/src/codegen/field.rs
@@ -0,0 +1,206 @@
+use std::borrow::Cow;
+
+use proc_macro2::TokenStream;
+use quote::{ToTokens, TokenStreamExt};
+use syn::{Ident, Path, Type};
+
+use codegen::DefaultExpression;
+use usage::{self, IdentRefSet, IdentSet, UsesTypeParams};
+
+/// Properties needed to generate code for a field in all the contexts
+/// where one may appear.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Field<'a> {
+ /// The name presented to the user of the library. This will appear
+ /// in error messages and will be looked when parsing names.
+ pub name_in_attr: Cow<'a, String>,
+
+ /// The name presented to the author of the library. This will appear
+ /// in the setters or temporary variables which contain the values.
+ pub ident: &'a Ident,
+
+ /// The type of the field in the input.
+ pub ty: &'a Type,
+ pub default_expression: Option<DefaultExpression<'a>>,
+ pub with_path: Cow<'a, Path>,
+ pub map: Option<&'a Path>,
+ pub skip: bool,
+ pub multiple: bool,
+}
+
+impl<'a> Field<'a> {
+ pub fn as_name(&'a self) -> &'a str {
+ &self.name_in_attr
+ }
+
+ pub fn as_declaration(&'a self) -> Declaration<'a> {
+ Declaration(self, !self.skip)
+ }
+
+ pub fn as_match(&'a self) -> MatchArm<'a> {
+ MatchArm(self)
+ }
+
+ pub fn as_initializer(&'a self) -> Initializer<'a> {
+ Initializer(self)
+ }
+
+ pub fn as_presence_check(&'a self) -> CheckMissing<'a> {
+ CheckMissing(self)
+ }
+}
+
+impl<'a> UsesTypeParams for Field<'a> {
+ fn uses_type_params<'b>(
+ &self,
+ options: &usage::Options,
+ type_set: &'b IdentSet,
+ ) -> IdentRefSet<'b> {
+ self.ty.uses_type_params(options, type_set)
+ }
+}
+
+/// An individual field during variable declaration in the generated parsing method.
+pub struct Declaration<'a>(&'a Field<'a>, bool);
+
+impl<'a> Declaration<'a> {
+ /// Creates a new declaration with the given field and mutability.
+ pub fn new(field: &'a Field<'a>, mutable: bool) -> Self {
+ Declaration(field, mutable)
+ }
+}
+
+impl<'a> ToTokens for Declaration<'a> {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ let field: &Field = self.0;
+ let ident = field.ident;
+ let ty = field.ty;
+
+ let mutable = if self.1 { quote!(mut) } else { quote!() };
+
+ tokens.append_all(if field.multiple {
+ // This is NOT mutable, as it will be declared mutable only temporarily.
+ quote!(let #mutable #ident: #ty = ::darling::export::Default::default();)
+ } else {
+ quote!(let #mutable #ident: (bool, ::darling::export::Option<#ty>) = (false, None);)
+ });
+ }
+}
+
+/// Represents an individual field in the match.
+pub struct MatchArm<'a>(&'a Field<'a>);
+
+impl<'a> ToTokens for MatchArm<'a> {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ let field: &Field = self.0;
+ if !field.skip {
+ let name_str = &field.name_in_attr;
+ let ident = field.ident;
+ let with_path = &field.with_path;
+
+ // Errors include the location of the bad input, so we compute that here.
+ // Fields that take multiple values add the index of the error for convenience,
+ // while single-value fields only expose the name in the input attribute.
+ let location = if field.multiple {
+ // we use the local variable `len` here because location is accessed via
+ // a closure, and the borrow checker gets very unhappy if we try to immutably
+ // borrow `#ident` in that closure when it was declared `mut` outside.
+ quote!(&format!("{}[{}]", #name_str, __len))
+ } else {
+ quote!(#name_str)
+ };
+
+ // Add the span immediately on extraction failure, so that it's as specific as possible.
+ // The behavior of `with_span` makes this safe to do; if the child applied an
+ // even-more-specific span, our attempt here will not overwrite that and will only cost
+ // us one `if` check.
+ let mut extractor =
+ quote!(#with_path(__inner).map_err(|e| e.with_span(&__inner).at(#location)));
+ if let Some(ref map) = field.map {
+ extractor = quote!(#extractor.map(#map))
+ }
+
+ tokens.append_all(if field.multiple {
+ quote!(
+ #name_str => {
+ // Store the index of the name we're assessing in case we need
+ // it for error reporting.
+ let __len = #ident.len();
+ match #extractor {
+ ::darling::export::Ok(__val) => {
+ #ident.push(__val)
+ }
+ ::darling::export::Err(__err) => {
+ __errors.push(__err)
+ }
+ }
+ }
+ )
+ } else {
+ quote!(
+ #name_str => {
+ if !#ident.0 {
+ match #extractor {
+ ::darling::export::Ok(__val) => {
+ #ident = (true, ::darling::export::Some(__val));
+ }
+ ::darling::export::Err(__err) => {
+ #ident = (true, None);
+ __errors.push(__err);
+ }
+ }
+ } else {
+ __errors.push(::darling::Error::duplicate_field(#name_str).with_span(&__inner));
+ }
+ }
+ )
+ });
+ }
+ }
+}
+
+/// Wrapper to generate initialization code for a field.
+pub struct Initializer<'a>(&'a Field<'a>);
+
+impl<'a> ToTokens for Initializer<'a> {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ let field: &Field = self.0;
+ let ident = field.ident;
+ tokens.append_all(if field.multiple {
+ if let Some(ref expr) = field.default_expression {
+ quote!(#ident: if !#ident.is_empty() {
+ #ident
+ } else {
+ #expr
+ })
+ } else {
+ quote!(#ident: #ident)
+ }
+ } else if let Some(ref expr) = field.default_expression {
+ quote!(#ident: match #ident.1 {
+ ::darling::export::Some(__val) => __val,
+ ::darling::export::None => #expr,
+ })
+ } else {
+ quote!(#ident: #ident.1.expect("Uninitialized fields without defaults were already checked"))
+ });
+ }
+}
+
+/// Creates an error if a field has no value and no default.
+pub struct CheckMissing<'a>(&'a Field<'a>);
+
+impl<'a> ToTokens for CheckMissing<'a> {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ if !self.0.multiple && self.0.default_expression.is_none() {
+ let ident = self.0.ident;
+ let name_in_attr = &self.0.name_in_attr;
+
+ tokens.append_all(quote! {
+ if !#ident.0 {
+ __errors.push(::darling::Error::missing_field(#name_in_attr));
+ }
+ })
+ }
+ }
+}
diff --git a/third_party/rust/darling_core/src/codegen/from_derive_impl.rs b/third_party/rust/darling_core/src/codegen/from_derive_impl.rs
new file mode 100644
index 0000000000..2c0a3a162b
--- /dev/null
+++ b/third_party/rust/darling_core/src/codegen/from_derive_impl.rs
@@ -0,0 +1,146 @@
+use proc_macro2::TokenStream;
+use quote::ToTokens;
+use syn::{self, Ident};
+
+use ast::Data;
+use codegen::{ExtractAttribute, OuterFromImpl, TraitImpl};
+use options::{ForwardAttrs, Shape};
+use util::PathList;
+
+pub struct FromDeriveInputImpl<'a> {
+ pub ident: Option<&'a Ident>,
+ pub generics: Option<&'a Ident>,
+ pub vis: Option<&'a Ident>,
+ pub attrs: Option<&'a Ident>,
+ pub data: Option<&'a Ident>,
+ pub base: TraitImpl<'a>,
+ pub attr_names: &'a PathList,
+ pub forward_attrs: Option<&'a ForwardAttrs>,
+ pub from_ident: bool,
+ pub supports: Option<&'a Shape>,
+}
+
+impl<'a> ToTokens for FromDeriveInputImpl<'a> {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ let ty_ident = self.base.ident;
+ let input = self.param_name();
+ let map = self.base.map_fn();
+
+ if let Data::Struct(ref data) = self.base.data {
+ if data.is_newtype() {
+ self.wrap(
+ quote!{
+ fn from_derive_input(#input: &::syn::DeriveInput) -> ::darling::Result<Self> {
+ ::darling::export::Ok(
+ #ty_ident(::darling::FromDeriveInput::from_derive_input(#input)?)
+ ) #map
+ }
+ },
+ tokens,
+ );
+
+ return;
+ }
+ }
+
+ let passed_ident = self.ident
+ .as_ref()
+ .map(|i| quote!(#i: #input.ident.clone(),));
+ let passed_vis = self.vis.as_ref().map(|i| quote!(#i: #input.vis.clone(),));
+ let passed_generics = self.generics
+ .as_ref()
+ .map(|i| quote!(#i: ::darling::FromGenerics::from_generics(&#input.generics)?,));
+ let passed_attrs = self.attrs.as_ref().map(|i| quote!(#i: __fwd_attrs,));
+ let passed_body = self.data
+ .as_ref()
+ .map(|i| quote!(#i: ::darling::ast::Data::try_from(&#input.data)?,));
+
+ let supports = self.supports.map(|i| {
+ quote!{
+ #i
+ __validate_body(&#input.data)?;
+ }
+ });
+
+ let inits = self.base.initializers();
+ let default = if self.from_ident {
+ quote!(let __default: Self = ::darling::export::From::from(#input.ident.clone());)
+ } else {
+ self.base.fallback_decl()
+ };
+
+ let grab_attrs = self.extractor();
+
+ let declare_errors = self.base.declare_errors();
+ let require_fields = self.base.require_fields();
+ let check_errors = self.base.check_errors();
+
+ self.wrap(
+ quote! {
+ fn from_derive_input(#input: &::syn::DeriveInput) -> ::darling::Result<Self> {
+ #declare_errors
+
+ #grab_attrs
+
+ #supports
+
+ #require_fields
+
+ #check_errors
+
+ #default
+
+ ::darling::export::Ok(#ty_ident {
+ #passed_ident
+ #passed_generics
+ #passed_vis
+ #passed_attrs
+ #passed_body
+ #inits
+ }) #map
+ }
+ },
+ tokens,
+ );
+ }
+}
+
+impl<'a> ExtractAttribute for FromDeriveInputImpl<'a> {
+ fn attr_names(&self) -> &PathList {
+ &self.attr_names
+ }
+
+ fn forwarded_attrs(&self) -> Option<&ForwardAttrs> {
+ self.forward_attrs
+ }
+
+ fn param_name(&self) -> TokenStream {
+ quote!(__di)
+ }
+
+ fn core_loop(&self) -> TokenStream {
+ self.base.core_loop()
+ }
+
+ fn local_declarations(&self) -> TokenStream {
+ self.base.local_declarations()
+ }
+
+ fn immutable_declarations(&self) -> TokenStream {
+ self.base.immutable_declarations()
+ }
+}
+
+impl<'a> OuterFromImpl<'a> for FromDeriveInputImpl<'a> {
+ fn trait_path(&self) -> syn::Path {
+ path!(::darling::FromDeriveInput)
+ }
+
+ fn trait_bound(&self) -> syn::Path {
+ path!(::darling::FromMeta)
+ }
+
+ fn base(&'a self) -> &'a TraitImpl<'a> {
+ &self.base
+ }
+}
diff --git a/third_party/rust/darling_core/src/codegen/from_field.rs b/third_party/rust/darling_core/src/codegen/from_field.rs
new file mode 100644
index 0000000000..b714211871
--- /dev/null
+++ b/third_party/rust/darling_core/src/codegen/from_field.rs
@@ -0,0 +1,115 @@
+use proc_macro2::TokenStream;
+use quote::ToTokens;
+use syn::{self, Ident};
+
+use codegen::{ExtractAttribute, OuterFromImpl, TraitImpl};
+use options::ForwardAttrs;
+use util::PathList;
+
+/// `impl FromField` generator. This is used for parsing an individual
+/// field and its attributes.
+pub struct FromFieldImpl<'a> {
+ pub ident: Option<&'a Ident>,
+ pub vis: Option<&'a Ident>,
+ pub ty: Option<&'a Ident>,
+ pub attrs: Option<&'a Ident>,
+ pub base: TraitImpl<'a>,
+ pub attr_names: &'a PathList,
+ pub forward_attrs: Option<&'a ForwardAttrs>,
+ pub from_ident: bool,
+}
+
+impl<'a> ToTokens for FromFieldImpl<'a> {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ let input = self.param_name();
+
+ let error_declaration = self.base.declare_errors();
+ let require_fields = self.base.require_fields();
+ let error_check = self.base.check_errors();
+
+ let initializers = self.base.initializers();
+
+ let default = if self.from_ident {
+ quote!(let __default: Self = ::darling::export::From::from(#input.ident.clone());)
+ } else {
+ self.base.fallback_decl()
+ };
+
+ let passed_ident = self.ident
+ .as_ref()
+ .map(|i| quote!(#i: #input.ident.clone(),));
+ let passed_vis = self.vis.as_ref().map(|i| quote!(#i: #input.vis.clone(),));
+ let passed_ty = self.ty.as_ref().map(|i| quote!(#i: #input.ty.clone(),));
+ let passed_attrs = self.attrs.as_ref().map(|i| quote!(#i: __fwd_attrs,));
+
+ // Determine which attributes to forward (if any).
+ let grab_attrs = self.extractor();
+ let map = self.base.map_fn();
+
+ self.wrap(
+ quote!{
+ fn from_field(#input: &::syn::Field) -> ::darling::Result<Self> {
+ #error_declaration
+
+ #grab_attrs
+
+ #require_fields
+
+ #error_check
+
+ #default
+
+ ::darling::export::Ok(Self {
+ #passed_ident
+ #passed_ty
+ #passed_vis
+ #passed_attrs
+ #initializers
+ }) #map
+
+ }
+ },
+ tokens,
+ );
+ }
+}
+
+impl<'a> ExtractAttribute for FromFieldImpl<'a> {
+ fn attr_names(&self) -> &PathList {
+ &self.attr_names
+ }
+
+ fn forwarded_attrs(&self) -> Option<&ForwardAttrs> {
+ self.forward_attrs
+ }
+
+ fn param_name(&self) -> TokenStream {
+ quote!(__field)
+ }
+
+ fn core_loop(&self) -> TokenStream {
+ self.base.core_loop()
+ }
+
+ fn local_declarations(&self) -> TokenStream {
+ self.base.local_declarations()
+ }
+
+ fn immutable_declarations(&self) -> TokenStream {
+ self.base.immutable_declarations()
+ }
+}
+
+impl<'a> OuterFromImpl<'a> for FromFieldImpl<'a> {
+ fn trait_path(&self) -> syn::Path {
+ path!(::darling::FromField)
+ }
+
+ fn trait_bound(&self) -> syn::Path {
+ path!(::darling::FromMeta)
+ }
+
+ fn base(&'a self) -> &'a TraitImpl<'a> {
+ &self.base
+ }
+}
diff --git a/third_party/rust/darling_core/src/codegen/from_meta_impl.rs b/third_party/rust/darling_core/src/codegen/from_meta_impl.rs
new file mode 100644
index 0000000000..dbc5056e6d
--- /dev/null
+++ b/third_party/rust/darling_core/src/codegen/from_meta_impl.rs
@@ -0,0 +1,136 @@
+use proc_macro2::TokenStream;
+use quote::ToTokens;
+use syn;
+
+use ast::{Data, Fields, Style};
+use codegen::{Field, OuterFromImpl, TraitImpl, Variant};
+
+pub struct FromMetaImpl<'a> {
+ pub base: TraitImpl<'a>,
+}
+
+impl<'a> ToTokens for FromMetaImpl<'a> {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ let base = &self.base;
+
+ let impl_block = match base.data {
+ // Unit structs allow empty bodies only.
+ Data::Struct(ref vd) if vd.style.is_unit() => {
+ let ty_ident = base.ident;
+ quote!(
+ fn from_word() -> ::darling::Result<Self> {
+ ::darling::export::Ok(#ty_ident)
+ }
+ )
+ }
+
+ // Newtype structs proxy to the sole value they contain.
+ Data::Struct(Fields {
+ ref fields,
+ style: Style::Tuple,
+ ..
+ }) if fields.len() == 1 => {
+ let ty_ident = base.ident;
+ quote!(
+ fn from_meta(__item: &::syn::Meta) -> ::darling::Result<Self> {
+ ::darling::FromMeta::from_meta(__item)
+ .map_err(|e| e.with_span(&__item))
+ .map(#ty_ident)
+ }
+ )
+ }
+ Data::Struct(Fields {
+ style: Style::Tuple,
+ ..
+ }) => {
+ panic!("Multi-field tuples are not supported");
+ }
+ Data::Struct(ref data) => {
+ let inits = data.fields.iter().map(Field::as_initializer);
+ let declare_errors = base.declare_errors();
+ let require_fields = base.require_fields();
+ let check_errors = base.check_errors();
+ let decls = base.local_declarations();
+ let core_loop = base.core_loop();
+ let default = base.fallback_decl();
+ let map = base.map_fn();
+
+ quote!(
+ fn from_list(__items: &[::syn::NestedMeta]) -> ::darling::Result<Self> {
+
+ #decls
+
+ #declare_errors
+
+ #core_loop
+
+ #require_fields
+
+ #check_errors
+
+ #default
+
+ ::darling::export::Ok(Self {
+ #(#inits),*
+ }) #map
+ }
+ )
+ }
+ Data::Enum(ref variants) => {
+ let unit_arms = variants.iter().map(Variant::as_unit_match_arm);
+ let struct_arms = variants.iter().map(Variant::as_data_match_arm);
+
+ let unknown_variant_err = if !variants.is_empty() {
+ let names = variants.iter().map(Variant::as_name);
+ quote! {
+ unknown_field_with_alts(__other, &[#(#names),*])
+ }
+ } else {
+ quote! {
+ unknown_field(__other)
+ }
+ };
+
+ quote!(
+ fn from_list(__outer: &[::syn::NestedMeta]) -> ::darling::Result<Self> {
+ // An enum must have exactly one value inside the parentheses if it's not a unit
+ // match arm
+ match __outer.len() {
+ 0 => ::darling::export::Err(::darling::Error::too_few_items(1)),
+ 1 => {
+ if let ::syn::NestedMeta::Meta(ref __nested) = __outer[0] {
+ match __nested.path().segments.iter().map(|s| s.ident.to_string()).collect::<Vec<String>>().join("::").as_ref() {
+ #(#struct_arms)*
+ __other => ::darling::export::Err(::darling::Error::#unknown_variant_err.with_span(__nested))
+ }
+ } else {
+ ::darling::export::Err(::darling::Error::unsupported_format("literal"))
+ }
+ }
+ _ => ::darling::export::Err(::darling::Error::too_many_items(1)),
+ }
+ }
+
+ fn from_string(lit: &str) -> ::darling::Result<Self> {
+ match lit {
+ #(#unit_arms)*
+ __other => ::darling::export::Err(::darling::Error::unknown_value(__other))
+ }
+ }
+ )
+ }
+ };
+
+ self.wrap(impl_block, tokens);
+ }
+}
+
+impl<'a> OuterFromImpl<'a> for FromMetaImpl<'a> {
+ fn trait_path(&self) -> syn::Path {
+ path!(::darling::FromMeta)
+ }
+
+ fn base(&'a self) -> &'a TraitImpl<'a> {
+ &self.base
+ }
+}
diff --git a/third_party/rust/darling_core/src/codegen/from_type_param.rs b/third_party/rust/darling_core/src/codegen/from_type_param.rs
new file mode 100644
index 0000000000..4936378dfb
--- /dev/null
+++ b/third_party/rust/darling_core/src/codegen/from_type_param.rs
@@ -0,0 +1,114 @@
+use proc_macro2::TokenStream;
+use quote::ToTokens;
+use syn::{self, Ident};
+
+use codegen::{ExtractAttribute, OuterFromImpl, TraitImpl};
+use options::ForwardAttrs;
+use util::PathList;
+
+pub struct FromTypeParamImpl<'a> {
+ pub base: TraitImpl<'a>,
+ pub ident: Option<&'a Ident>,
+ pub attrs: Option<&'a Ident>,
+ pub bounds: Option<&'a Ident>,
+ pub default: Option<&'a Ident>,
+ pub attr_names: &'a PathList,
+ pub forward_attrs: Option<&'a ForwardAttrs>,
+ pub from_ident: bool,
+}
+
+impl<'a> ToTokens for FromTypeParamImpl<'a> {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ let input = self.param_name();
+
+ let error_declaration = self.base.declare_errors();
+ let grab_attrs = self.extractor();
+ let require_fields = self.base.require_fields();
+ let error_check = self.base.check_errors();
+
+ let default = if self.from_ident {
+ quote!(let __default: Self = ::darling::export::From::from(#input.ident.clone());)
+ } else {
+ self.base.fallback_decl()
+ };
+
+ let passed_ident = self.ident
+ .as_ref()
+ .map(|i| quote!(#i: #input.ident.clone(),));
+ let passed_attrs = self.attrs.as_ref().map(|i| quote!(#i: __fwd_attrs,));
+ let passed_bounds = self.bounds
+ .as_ref()
+ .map(|i| quote!(#i: #input.bounds.clone().into_iter().collect::<Vec<_>>(),));
+ let passed_default = self.default
+ .as_ref()
+ .map(|i| quote!(#i: #input.default.clone(),));
+ let initializers = self.base.initializers();
+
+ let map = self.base.map_fn();
+
+ self.wrap(
+ quote! {
+ fn from_type_param(#input: &::syn::TypeParam) -> ::darling::Result<Self> {
+ #error_declaration
+
+ #grab_attrs
+
+ #require_fields
+
+ #error_check
+
+ #default
+
+ ::darling::export::Ok(Self {
+ #passed_ident
+ #passed_bounds
+ #passed_default
+ #passed_attrs
+ #initializers
+ }) #map
+ }
+ },
+ tokens,
+ );
+ }
+}
+
+impl<'a> ExtractAttribute for FromTypeParamImpl<'a> {
+ fn attr_names(&self) -> &PathList {
+ &self.attr_names
+ }
+
+ fn forwarded_attrs(&self) -> Option<&ForwardAttrs> {
+ self.forward_attrs
+ }
+
+ fn param_name(&self) -> TokenStream {
+ quote!(__type_param)
+ }
+
+ fn core_loop(&self) -> TokenStream {
+ self.base.core_loop()
+ }
+
+ fn local_declarations(&self) -> TokenStream {
+ self.base.local_declarations()
+ }
+
+ fn immutable_declarations(&self) -> TokenStream {
+ self.base.immutable_declarations()
+ }
+}
+
+impl<'a> OuterFromImpl<'a> for FromTypeParamImpl<'a> {
+ fn trait_path(&self) -> syn::Path {
+ path!(::darling::FromTypeParam)
+ }
+
+ fn trait_bound(&self) -> syn::Path {
+ path!(::darling::FromMeta)
+ }
+
+ fn base(&'a self) -> &'a TraitImpl<'a> {
+ &self.base
+ }
+}
diff --git a/third_party/rust/darling_core/src/codegen/from_variant_impl.rs b/third_party/rust/darling_core/src/codegen/from_variant_impl.rs
new file mode 100644
index 0000000000..bbe5a9a12e
--- /dev/null
+++ b/third_party/rust/darling_core/src/codegen/from_variant_impl.rs
@@ -0,0 +1,118 @@
+use proc_macro2::TokenStream;
+use quote::ToTokens;
+use syn::{self, Ident};
+
+use codegen::{ExtractAttribute, OuterFromImpl, TraitImpl};
+use options::{DataShape, ForwardAttrs};
+use util::PathList;
+
+pub struct FromVariantImpl<'a> {
+ pub base: TraitImpl<'a>,
+ pub ident: Option<&'a Ident>,
+ pub fields: Option<&'a Ident>,
+ pub attrs: Option<&'a Ident>,
+ pub attr_names: &'a PathList,
+ pub forward_attrs: Option<&'a ForwardAttrs>,
+ pub from_ident: bool,
+ pub supports: Option<&'a DataShape>,
+}
+
+impl<'a> ToTokens for FromVariantImpl<'a> {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ let input = self.param_name();
+ let extractor = self.extractor();
+ let passed_ident = self.ident
+ .as_ref()
+ .map(|i| quote!(#i: #input.ident.clone(),));
+ let passed_attrs = self.attrs.as_ref().map(|i| quote!(#i: __fwd_attrs,));
+ let passed_fields = self.fields
+ .as_ref()
+ .map(|i| quote!(#i: ::darling::ast::Fields::try_from(&#input.fields)?,));
+
+ let inits = self.base.initializers();
+ let map = self.base.map_fn();
+
+ let default = if self.from_ident {
+ quote!(let __default: Self = ::darling::export::From::from(#input.ident.clone());)
+ } else {
+ self.base.fallback_decl()
+ };
+
+ let supports = self.supports.map(|i| {
+ quote! {
+ #i
+ __validate_data(&#input.fields)?;
+ }
+ });
+
+ let error_declaration = self.base.declare_errors();
+ let require_fields = self.base.require_fields();
+ let error_check = self.base.check_errors();
+
+ self.wrap(
+ quote!(
+ fn from_variant(#input: &::syn::Variant) -> ::darling::Result<Self> {
+ #error_declaration
+
+ #extractor
+
+ #supports
+
+ #require_fields
+
+ #error_check
+
+ #default
+
+ ::darling::export::Ok(Self {
+ #passed_ident
+ #passed_attrs
+ #passed_fields
+ #inits
+ }) #map
+ }
+ ),
+ tokens,
+ );
+ }
+}
+
+impl<'a> ExtractAttribute for FromVariantImpl<'a> {
+ fn local_declarations(&self) -> TokenStream {
+ self.base.local_declarations()
+ }
+
+ fn immutable_declarations(&self) -> TokenStream {
+ self.base.immutable_declarations()
+ }
+
+ fn attr_names(&self) -> &PathList {
+ &self.attr_names
+ }
+
+ fn forwarded_attrs(&self) -> Option<&ForwardAttrs> {
+ self.forward_attrs
+ }
+
+ fn param_name(&self) -> TokenStream {
+ quote!(__variant)
+ }
+
+ fn core_loop(&self) -> TokenStream {
+ self.base.core_loop()
+ }
+}
+
+impl<'a> OuterFromImpl<'a> for FromVariantImpl<'a> {
+ fn trait_path(&self) -> syn::Path {
+ path!(::darling::FromVariant)
+ }
+
+ fn trait_bound(&self) -> syn::Path {
+ path!(::darling::FromMeta)
+ }
+
+ fn base(&'a self) -> &'a TraitImpl<'a> {
+ &self.base
+ }
+}
diff --git a/third_party/rust/darling_core/src/codegen/mod.rs b/third_party/rust/darling_core/src/codegen/mod.rs
new file mode 100644
index 0000000000..40b8d68a75
--- /dev/null
+++ b/third_party/rust/darling_core/src/codegen/mod.rs
@@ -0,0 +1,29 @@
+
+mod attr_extractor;
+mod default_expr;
+mod error;
+mod field;
+mod from_meta_impl;
+mod from_derive_impl;
+mod from_field;
+mod from_type_param;
+mod from_variant_impl;
+mod outer_from_impl;
+mod trait_impl;
+mod variant;
+mod variant_data;
+
+pub(in codegen) use self::attr_extractor::ExtractAttribute;
+pub use self::default_expr::DefaultExpression;
+pub use self::field::Field;
+pub use self::from_meta_impl::FromMetaImpl;
+pub use self::from_derive_impl::FromDeriveInputImpl;
+pub use self::from_field::FromFieldImpl;
+pub use self::from_type_param::FromTypeParamImpl;
+pub use self::from_variant_impl::FromVariantImpl;
+pub use self::outer_from_impl::OuterFromImpl;
+pub use self::trait_impl::TraitImpl;
+pub use self::variant::Variant;
+pub use self::variant_data::FieldsGen;
+
+
diff --git a/third_party/rust/darling_core/src/codegen/outer_from_impl.rs b/third_party/rust/darling_core/src/codegen/outer_from_impl.rs
new file mode 100644
index 0000000000..e99c4e1526
--- /dev/null
+++ b/third_party/rust/darling_core/src/codegen/outer_from_impl.rs
@@ -0,0 +1,60 @@
+use proc_macro2::TokenStream;
+use quote::{TokenStreamExt, ToTokens};
+use syn::{GenericParam, Generics, Path, TraitBound, TraitBoundModifier, TypeParamBound};
+
+use codegen::TraitImpl;
+use usage::IdentSet;
+
+/// Wrapper for "outer From" traits, such as `FromDeriveInput`, `FromVariant`, and `FromField`.
+pub trait OuterFromImpl<'a> {
+ /// Gets the path of the trait being implemented.
+ fn trait_path(&self) -> Path;
+
+ fn base(&'a self) -> &'a TraitImpl<'a>;
+
+ fn trait_bound(&self) -> Path {
+ self.trait_path()
+ }
+
+ fn wrap<T: ToTokens>(&'a self, body: T, tokens: &mut TokenStream) {
+ let base = self.base();
+ let trayt = self.trait_path();
+ let ty_ident = base.ident;
+ // The type parameters used in non-skipped, non-magic fields.
+ // These must impl `FromMeta` unless they have custom bounds.
+ let used = base.used_type_params();
+ let generics = compute_impl_bounds(self.trait_bound(), base.generics.clone(), &used);
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ tokens.append_all(quote!(
+ impl #impl_generics #trayt for #ty_ident #ty_generics
+ #where_clause
+ {
+ #body
+ }
+ ));
+ }
+}
+
+fn compute_impl_bounds(bound: Path, mut generics: Generics, applies_to: &IdentSet) -> Generics {
+ if generics.params.is_empty() {
+ return generics;
+ }
+
+ let added_bound = TypeParamBound::Trait(TraitBound {
+ paren_token: None,
+ modifier: TraitBoundModifier::None,
+ lifetimes: None,
+ path: bound,
+ });
+
+ for param in generics.params.iter_mut() {
+ if let GenericParam::Type(ref mut typ) = *param {
+ if applies_to.contains(&typ.ident) {
+ typ.bounds.push(added_bound.clone());
+ }
+ }
+ }
+
+ generics
+}
diff --git a/third_party/rust/darling_core/src/codegen/trait_impl.rs b/third_party/rust/darling_core/src/codegen/trait_impl.rs
new file mode 100644
index 0000000000..2f4f4aec63
--- /dev/null
+++ b/third_party/rust/darling_core/src/codegen/trait_impl.rs
@@ -0,0 +1,145 @@
+use proc_macro2::TokenStream;
+use syn::{Generics, Ident, Path, WherePredicate};
+
+use ast::{Data, Fields};
+use codegen::error::{ErrorCheck, ErrorDeclaration};
+use codegen::field;
+use codegen::{DefaultExpression, Field, FieldsGen, Variant};
+use usage::{CollectTypeParams, IdentSet, Purpose};
+
+#[derive(Debug)]
+pub struct TraitImpl<'a> {
+ pub ident: &'a Ident,
+ pub generics: &'a Generics,
+ pub data: Data<Variant<'a>, Field<'a>>,
+ pub default: Option<DefaultExpression<'a>>,
+ pub map: Option<&'a Path>,
+ pub bound: Option<&'a [WherePredicate]>,
+ pub allow_unknown_fields: bool,
+}
+
+impl<'a> TraitImpl<'a> {
+ /// Get all declared type parameters.
+ pub fn declared_type_params(&self) -> IdentSet {
+ self.generics
+ .type_params()
+ .map(|tp| tp.ident.clone())
+ .collect()
+ }
+
+ /// Get the type parameters which are used by non-skipped, non-magic fields.
+ /// These type parameters will have a `FromMeta` bound applied to them in emitted
+ /// code.
+ pub fn used_type_params(&self) -> IdentSet {
+ self.type_params_matching(|f| !f.skip, |v| !v.skip)
+ }
+
+ fn type_params_matching<'b, F, V>(&'b self, field_filter: F, variant_filter: V) -> IdentSet
+ where
+ F: Fn(&&Field) -> bool,
+ V: Fn(&&Variant) -> bool,
+ {
+ let declared = self.declared_type_params();
+ match self.data {
+ Data::Struct(ref v) => self.type_params_in_fields(v, &field_filter, &declared),
+ Data::Enum(ref v) => {
+ v.iter()
+ .filter(variant_filter)
+ .fold(Default::default(), |mut state, variant| {
+ state.extend(self.type_params_in_fields(
+ &variant.data,
+ &field_filter,
+ &declared,
+ ));
+ state
+ })
+ }
+ }
+ }
+
+ /// Get the type parameters of all fields in a set matching some filter
+ fn type_params_in_fields<'b, F>(
+ &'b self,
+ fields: &'b Fields<Field<'a>>,
+ field_filter: F,
+ declared: &IdentSet,
+ ) -> IdentSet
+ where
+ F: Fn(&&'b Field) -> bool,
+ {
+ fields
+ .iter()
+ .filter(field_filter)
+ .collect_type_params_cloned(&Purpose::BoundImpl.into(), declared)
+ }
+}
+
+impl<'a> TraitImpl<'a> {
+ /// Gets the `let` declaration for errors accumulated during parsing.
+ pub fn declare_errors(&self) -> ErrorDeclaration {
+ ErrorDeclaration::default()
+ }
+
+ /// Gets the check which performs an early return if errors occurred during parsing.
+ pub fn check_errors(&self) -> ErrorCheck {
+ ErrorCheck::default()
+ }
+
+ /// Generate local variable declarations for all fields.
+ pub(in codegen) fn local_declarations(&self) -> TokenStream {
+ if let Data::Struct(ref vd) = self.data {
+ let vdr = vd.as_ref().map(Field::as_declaration);
+ let decls = vdr.fields.as_slice();
+ quote!(#(#decls)*)
+ } else {
+ quote!()
+ }
+ }
+
+ /// Generate immutable variable declarations for all fields.
+ pub(in codegen) fn immutable_declarations(&self) -> TokenStream {
+ if let Data::Struct(ref vd) = self.data {
+ let vdr = vd.as_ref().map(|f| field::Declaration::new(f, false));
+ let decls = vdr.fields.as_slice();
+ quote!(#(#decls)*)
+ } else {
+ quote!()
+ }
+ }
+
+ pub(in codegen) fn map_fn(&self) -> Option<TokenStream> {
+ self.map.as_ref().map(|path| quote!(.map(#path)))
+ }
+
+ /// Generate local variable declaration and initialization for instance from which missing fields will be taken.
+ pub(in codegen) fn fallback_decl(&self) -> TokenStream {
+ let default = self.default.as_ref().map(DefaultExpression::as_declaration);
+ quote!(#default)
+ }
+
+ pub fn require_fields(&self) -> TokenStream {
+ if let Data::Struct(ref vd) = self.data {
+ let check_nones = vd.as_ref().map(Field::as_presence_check);
+ let checks = check_nones.fields.as_slice();
+ quote!(#(#checks)*)
+ } else {
+ quote!()
+ }
+ }
+
+ pub(in codegen) fn initializers(&self) -> TokenStream {
+ self.make_field_ctx().initializers()
+ }
+
+ /// Generate the loop which walks meta items looking for property matches.
+ pub(in codegen) fn core_loop(&self) -> TokenStream {
+ self.make_field_ctx().core_loop()
+ }
+
+ fn make_field_ctx(&'a self) -> FieldsGen<'a> {
+ match self.data {
+ Data::Enum(_) => panic!("Core loop on enums isn't supported"),
+ Data::Struct(ref data) => FieldsGen::new(data, self.allow_unknown_fields),
+ }
+ }
+}
diff --git a/third_party/rust/darling_core/src/codegen/variant.rs b/third_party/rust/darling_core/src/codegen/variant.rs
new file mode 100644
index 0000000000..e982a2e815
--- /dev/null
+++ b/third_party/rust/darling_core/src/codegen/variant.rs
@@ -0,0 +1,158 @@
+use std::borrow::Cow;
+
+use proc_macro2::TokenStream;
+use quote::{ToTokens, TokenStreamExt};
+use syn::Ident;
+
+use ast::Fields;
+use codegen::error::{ErrorCheck, ErrorDeclaration};
+use codegen::{Field, FieldsGen};
+use usage::{self, IdentRefSet, IdentSet, UsesTypeParams};
+
+/// A variant of the enum which is deriving `FromMeta`.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Variant<'a> {
+ /// The name which will appear in code passed to the `FromMeta` input.
+ pub name_in_attr: Cow<'a, String>,
+
+ /// The name of the variant which will be returned for a given `name_in_attr`.
+ pub variant_ident: &'a Ident,
+
+ /// The name of the parent enum type.
+ pub ty_ident: &'a Ident,
+
+ pub data: Fields<Field<'a>>,
+
+ /// Whether or not the variant should be skipped in the generated code.
+ pub skip: bool,
+
+ pub allow_unknown_fields: bool,
+}
+
+impl<'a> Variant<'a> {
+ pub fn as_name(&'a self) -> &'a str {
+ &self.name_in_attr
+ }
+
+ pub fn as_unit_match_arm(&'a self) -> UnitMatchArm<'a> {
+ UnitMatchArm(self)
+ }
+
+ pub fn as_data_match_arm(&'a self) -> DataMatchArm<'a> {
+ DataMatchArm(self)
+ }
+}
+
+impl<'a> UsesTypeParams for Variant<'a> {
+ fn uses_type_params<'b>(
+ &self,
+ options: &usage::Options,
+ type_set: &'b IdentSet,
+ ) -> IdentRefSet<'b> {
+ self.data.uses_type_params(options, type_set)
+ }
+}
+
+/// Code generator for an enum variant in a unit match position.
+/// This is placed in generated `from_string` calls for the parent enum.
+/// Value-carrying variants wrapped in this type will emit code to produce an "unsupported format" error.
+pub struct UnitMatchArm<'a>(&'a Variant<'a>);
+
+impl<'a> ToTokens for UnitMatchArm<'a> {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ let val: &Variant<'a> = self.0;
+
+ if val.skip {
+ return;
+ }
+
+ let name_in_attr = &val.name_in_attr;
+
+ if val.data.is_unit() {
+ let variant_ident = val.variant_ident;
+ let ty_ident = val.ty_ident;
+
+ tokens.append_all(quote!(
+ #name_in_attr => ::darling::export::Ok(#ty_ident::#variant_ident),
+ ));
+ } else {
+ tokens.append_all(quote!(
+ #name_in_attr => ::darling::export::Err(::darling::Error::unsupported_format("literal")),
+ ));
+ }
+ }
+}
+
+/// Code generator for an enum variant in a data-carrying match position.
+/// This is placed in generated `from_list` calls for the parent enum.
+/// Unit variants wrapped in this type will emit code to produce an "unsupported format" error.
+pub struct DataMatchArm<'a>(&'a Variant<'a>);
+
+impl<'a> ToTokens for DataMatchArm<'a> {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ let val: &Variant<'a> = self.0;
+
+ if val.skip {
+ return;
+ }
+
+ let name_in_attr = &val.name_in_attr;
+ let variant_ident = val.variant_ident;
+ let ty_ident = val.ty_ident;
+
+ if val.data.is_unit() {
+ tokens.append_all(quote!(
+ #name_in_attr => ::darling::export::Err(::darling::Error::unsupported_format("list")),
+ ));
+
+ return;
+ }
+
+ let vdg = FieldsGen::new(&val.data, val.allow_unknown_fields);
+
+ if val.data.is_struct() {
+ let declare_errors = ErrorDeclaration::default();
+ let check_errors = ErrorCheck::with_location(&name_in_attr);
+ let require_fields = vdg.require_fields();
+ let decls = vdg.declarations();
+ let core_loop = vdg.core_loop();
+ let inits = vdg.initializers();
+
+ tokens.append_all(quote!(
+ #name_in_attr => {
+ if let ::syn::Meta::List(ref __data) = *__nested {
+ let __items = &__data.nested;
+
+ #declare_errors
+
+ #decls
+
+ #core_loop
+
+ #require_fields
+
+ #check_errors
+
+ ::darling::export::Ok(#ty_ident::#variant_ident {
+ #inits
+ })
+ } else {
+ ::darling::export::Err(::darling::Error::unsupported_format("non-list"))
+ }
+ }
+ ));
+ } else if val.data.is_newtype() {
+ tokens.append_all(quote!(
+ #name_in_attr => {
+ ::darling::export::Ok(
+ #ty_ident::#variant_ident(
+ ::darling::FromMeta::from_meta(__nested)
+ .map_err(|e| e.at(#name_in_attr))?)
+ )
+ }
+ ));
+ } else {
+ panic!("Match arms aren't supported for tuple variants yet");
+ }
+ }
+}
diff --git a/third_party/rust/darling_core/src/codegen/variant_data.rs b/third_party/rust/darling_core/src/codegen/variant_data.rs
new file mode 100644
index 0000000000..392242b266
--- /dev/null
+++ b/third_party/rust/darling_core/src/codegen/variant_data.rs
@@ -0,0 +1,91 @@
+use proc_macro2::TokenStream;
+
+use ast::Fields;
+use ast::Style;
+use codegen::Field;
+
+pub struct FieldsGen<'a> {
+ fields: &'a Fields<Field<'a>>,
+ allow_unknown_fields: bool,
+}
+
+impl<'a> FieldsGen<'a> {
+ pub fn new(fields: &'a Fields<Field<'a>>, allow_unknown_fields: bool) -> Self {
+ Self {
+ fields,
+ allow_unknown_fields,
+ }
+ }
+
+ /// Create declarations for all the fields in the struct.
+ pub(in codegen) fn declarations(&self) -> TokenStream {
+ match *self.fields {
+ Fields {
+ style: Style::Struct,
+ ref fields,
+ } => {
+ let vdr = fields.iter().map(Field::as_declaration);
+ quote!(#(#vdr)*)
+ }
+ _ => panic!("FieldsGen doesn't support tuples yet"),
+ }
+ }
+
+ /// Generate the loop which walks meta items looking for property matches.
+ pub(in codegen) fn core_loop(&self) -> TokenStream {
+ let arms = self.fields.as_ref().map(Field::as_match);
+
+ // If we're allowing unknown fields, then handling one is a no-op.
+ // Otherwise, we're going to push a new spanned error pointing at the field.
+ let handle_unknown = if self.allow_unknown_fields {
+ quote!()
+ } else {
+ // We can't call `unknown_field_with_alts` with an empty slice, or else it fails to
+ // infer the type of the slice item.
+ let err_fn = if arms.is_empty() {
+ quote!(unknown_field(__other))
+ } else {
+ let names = self.fields.as_ref().map(Field::as_name);
+ let names = names.iter();
+ quote!(unknown_field_with_alts(__other, &[#(#names),*]))
+ };
+
+ quote! {
+ __errors.push(::darling::Error::#err_fn.with_span(__inner));
+ }
+ };
+ let arms = arms.iter();
+
+ quote!(
+ for __item in __items {
+ if let ::syn::NestedMeta::Meta(ref __inner) = *__item {
+ let __name = __inner.path().segments.iter().map(|s| s.ident.to_string()).collect::<Vec<String>>().join("::");
+ match __name.as_str() {
+ #(#arms)*
+ __other => { #handle_unknown }
+ }
+ }
+ }
+ )
+ }
+
+ pub fn require_fields(&self) -> TokenStream {
+ match *self.fields {
+ Fields {
+ style: Style::Struct,
+ ref fields,
+ } => {
+ let checks = fields.iter().map(Field::as_presence_check);
+ quote!(#(#checks)*)
+ }
+ _ => panic!("FieldsGen doesn't support tuples for requirement checks"),
+ }
+ }
+
+ pub(in codegen) fn initializers(&self) -> TokenStream {
+ let inits = self.fields.as_ref().map(Field::as_initializer);
+ let inits = inits.iter();
+
+ quote!(#(#inits),*)
+ }
+}
diff --git a/third_party/rust/darling_core/src/derive.rs b/third_party/rust/darling_core/src/derive.rs
new file mode 100644
index 0000000000..92dce8e1a9
--- /dev/null
+++ b/third_party/rust/darling_core/src/derive.rs
@@ -0,0 +1,54 @@
+//! Functions to derive `darling`'s traits from well-formed input, without directly depending
+//! on `proc_macro`.
+
+use proc_macro2::TokenStream;
+use quote::ToTokens;
+use syn::DeriveInput;
+
+use options;
+
+/// Run an expression which returns a `darling::Result`, then either return the tokenized
+/// representation of the `Ok` value, or the tokens of the compiler errors in the `Err` case.
+macro_rules! emit_impl_or_error {
+ ($e:expr) => {
+ match $e {
+ Ok(val) => val.into_token_stream(),
+ Err(err) => err.write_errors(),
+ }
+ };
+}
+
+/// Create tokens for a `darling::FromMeta` impl from a `DeriveInput`. If
+/// the input cannot produce a valid impl, the returned tokens will contain
+/// compile errors instead.
+pub fn from_meta(input: &DeriveInput) -> TokenStream {
+ emit_impl_or_error!(options::FromMetaOptions::new(input))
+}
+
+/// Create tokens for a `darling::FromDeriveInput` impl from a `DeriveInput`. If
+/// the input cannot produce a valid impl, the returned tokens will contain
+/// compile errors instead.
+pub fn from_derive_input(input: &DeriveInput) -> TokenStream {
+ emit_impl_or_error!(options::FdiOptions::new(&input))
+}
+
+/// Create tokens for a `darling::FromField` impl from a `DeriveInput`. If
+/// the input cannot produce a valid impl, the returned tokens will contain
+/// compile errors instead.
+pub fn from_field(input: &DeriveInput) -> TokenStream {
+ emit_impl_or_error!(options::FromFieldOptions::new(input))
+}
+
+/// Create tokens for a `darling::FromTypeParam` impl from a `DeriveInput`. If
+/// the input cannot produce a valid impl, the returned tokens will contain
+/// compile errors instead.
+pub fn from_type_param(input: &DeriveInput) -> TokenStream {
+ emit_impl_or_error!(options::FromTypeParamOptions::new(input))
+}
+
+/// Create tokens for a `darling::FromVariant` impl from a `DeriveInput`. If
+/// the input cannot produce a valid impl, the returned tokens will contain
+/// compile errors instead.
+pub fn from_variant(input: &DeriveInput) -> TokenStream {
+ emit_impl_or_error!(options::FromVariantOptions::new(input))
+}
diff --git a/third_party/rust/darling_core/src/error/kind.rs b/third_party/rust/darling_core/src/error/kind.rs
new file mode 100644
index 0000000000..92d4afeb37
--- /dev/null
+++ b/third_party/rust/darling_core/src/error/kind.rs
@@ -0,0 +1,201 @@
+use std::fmt;
+
+use error::Error;
+
+type DeriveInputShape = String;
+type FieldName = String;
+type MetaFormat = String;
+
+#[derive(Debug)]
+// Don't want to publicly commit to ErrorKind supporting equality yet, but
+// not having it makes testing very difficult.
+#[cfg_attr(test, derive(Clone, PartialEq, Eq))]
+pub(in error) enum ErrorKind {
+ /// An arbitrary error message.
+ Custom(String),
+ DuplicateField(FieldName),
+ MissingField(FieldName),
+ UnsupportedShape(DeriveInputShape),
+ UnknownField(ErrorUnknownField),
+ UnexpectedFormat(MetaFormat),
+ UnexpectedType(String),
+ UnknownValue(String),
+ TooFewItems(usize),
+ TooManyItems(usize),
+ /// A set of errors.
+ Multiple(Vec<Error>),
+
+ // TODO make this variant take `!` so it can't exist
+ #[doc(hidden)]
+ __NonExhaustive,
+}
+
+impl ErrorKind {
+ pub fn description(&self) -> &str {
+ use self::ErrorKind::*;
+
+ match *self {
+ Custom(ref s) => s,
+ DuplicateField(_) => "Duplicate field",
+ MissingField(_) => "Missing field",
+ UnknownField(_) => "Unexpected field",
+ UnsupportedShape(_) => "Unsupported shape",
+ UnexpectedFormat(_) => "Unexpected meta-item format",
+ UnexpectedType(_) => "Unexpected literal type",
+ UnknownValue(_) => "Unknown literal value",
+ TooFewItems(_) => "Too few items",
+ TooManyItems(_) => "Too many items",
+ Multiple(_) => "Multiple errors",
+ __NonExhaustive => unreachable!(),
+ }
+ }
+
+ /// Deeply counts the number of errors this item represents.
+ pub fn len(&self) -> usize {
+ if let ErrorKind::Multiple(ref items) = *self {
+ items.iter().map(Error::len).sum()
+ } else {
+ 1
+ }
+ }
+}
+
+impl fmt::Display for ErrorKind {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ use self::ErrorKind::*;
+
+ match *self {
+ Custom(ref s) => s.fmt(f),
+ DuplicateField(ref field) => write!(f, "Duplicate field `{}`", field),
+ MissingField(ref field) => write!(f, "Missing field `{}`", field),
+ UnknownField(ref field) => field.fmt(f),
+ UnsupportedShape(ref shape) => write!(f, "Unsupported shape `{}`", shape),
+ UnexpectedFormat(ref format) => write!(f, "Unexpected meta-item format `{}`", format),
+ UnexpectedType(ref ty) => write!(f, "Unexpected literal type `{}`", ty),
+ UnknownValue(ref val) => write!(f, "Unknown literal value `{}`", val),
+ TooFewItems(ref min) => write!(f, "Too few items: Expected at least {}", min),
+ TooManyItems(ref max) => write!(f, "Too many items: Expected no more than {}", max),
+ Multiple(ref items) if items.len() == 1 => items[0].fmt(f),
+ Multiple(ref items) => {
+ write!(f, "Multiple errors: (")?;
+ let mut first = true;
+ for item in items {
+ if !first {
+ write!(f, ", ")?;
+ } else {
+ first = false;
+ }
+
+ item.fmt(f)?;
+ }
+
+ write!(f, ")")
+ }
+ __NonExhaustive => unreachable!(),
+ }
+ }
+}
+
+impl From<ErrorUnknownField> for ErrorKind {
+ fn from(err: ErrorUnknownField) -> Self {
+ ErrorKind::UnknownField(err)
+ }
+}
+
+/// An error for an unknown field, with a possible "did-you-mean" suggestion to get
+/// the user back on the right track.
+#[derive(Debug)]
+// Don't want to publicly commit to ErrorKind supporting equality yet, but
+// not having it makes testing very difficult.
+#[cfg_attr(test, derive(Clone, PartialEq, Eq))]
+pub(in error) struct ErrorUnknownField {
+ name: String,
+ did_you_mean: Option<String>,
+}
+
+impl ErrorUnknownField {
+ pub fn new<I: Into<String>>(name: I, did_you_mean: Option<String>) -> Self {
+ ErrorUnknownField {
+ name: name.into(),
+ did_you_mean,
+ }
+ }
+
+ pub fn with_alts<'a, T, I>(field: &str, alternates: I) -> Self
+ where
+ T: AsRef<str> + 'a,
+ I: IntoIterator<Item = &'a T>,
+ {
+ ErrorUnknownField::new(field, did_you_mean(field, alternates))
+ }
+
+ #[cfg(feature = "diagnostics")]
+ pub fn to_diagnostic(self, span: Option<::proc_macro2::Span>) -> ::proc_macro::Diagnostic {
+ let base = span
+ .unwrap_or_else(::proc_macro2::Span::call_site)
+ .unwrap()
+ .error(self.top_line());
+ match self.did_you_mean {
+ Some(alt_name) => base.help(format!("did you mean `{}`?", alt_name)),
+ None => base,
+ }
+ }
+
+ #[cfg(feature = "diagnostics")]
+ fn top_line(&self) -> String {
+ format!("Unknown field: `{}`", self.name)
+ }
+}
+
+impl From<String> for ErrorUnknownField {
+ fn from(name: String) -> Self {
+ ErrorUnknownField::new(name, None)
+ }
+}
+
+impl<'a> From<&'a str> for ErrorUnknownField {
+ fn from(name: &'a str) -> Self {
+ ErrorUnknownField::new(name, None)
+ }
+}
+
+impl fmt::Display for ErrorUnknownField {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "Unknown field: `{}`", self.name)?;
+
+ if let Some(ref did_you_mean) = self.did_you_mean {
+ write!(f, ". Did you mean `{}`?", did_you_mean)?;
+ }
+
+ Ok(())
+ }
+}
+
+#[cfg(feature = "suggestions")]
+fn did_you_mean<'a, T, I>(field: &str, alternates: I) -> Option<String>
+where
+ T: AsRef<str> + 'a,
+ I: IntoIterator<Item = &'a T>,
+{
+ let mut candidate: Option<(f64, &str)> = None;
+ for pv in alternates {
+ let confidence = ::strsim::jaro_winkler(field, pv.as_ref());
+ if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence))
+ {
+ candidate = Some((confidence, pv.as_ref()));
+ }
+ }
+ match candidate {
+ None => None,
+ Some((_, candidate)) => Some(candidate.into()),
+ }
+}
+
+#[cfg(not(feature = "suggestions"))]
+fn did_you_mean<'a, T, I>(_field: &str, _alternates: I) -> Option<String>
+where
+ T: AsRef<str> + 'a,
+ I: IntoIterator<Item = &'a T>,
+{
+ None
+}
diff --git a/third_party/rust/darling_core/src/error/mod.rs b/third_party/rust/darling_core/src/error/mod.rs
new file mode 100644
index 0000000000..28102a8aca
--- /dev/null
+++ b/third_party/rust/darling_core/src/error/mod.rs
@@ -0,0 +1,520 @@
+//! The `darling::Error` type and its internals.
+//!
+//! Error handling is one of the core values of `darling`; creating great errors is hard and
+//! never the reason that a proc-macro author started writing their crate. As a result, the
+//! `Error` type in `darling` tries to make adding span information, suggestions, and other
+//! help content easy when manually implementing `darling` traits, and automatic when deriving
+//! them.
+
+use proc_macro2::{Span, TokenStream};
+use std::error::Error as StdError;
+use std::fmt;
+use std::iter::{self, Iterator};
+use std::string::ToString;
+use std::vec;
+use syn::spanned::Spanned;
+use syn::{Lit, LitStr, Path};
+
+mod kind;
+
+use self::kind::{ErrorKind, ErrorUnknownField};
+
+/// An alias of `Result` specific to attribute parsing.
+pub type Result<T> = ::std::result::Result<T, Error>;
+
+/// An error encountered during attribute parsing.
+///
+/// Given that most errors darling encounters represent code bugs in dependent crates,
+/// the internal structure of the error is deliberately opaque.
+#[derive(Debug)]
+#[cfg_attr(test, derive(Clone))]
+pub struct Error {
+ kind: ErrorKind,
+ locations: Vec<String>,
+ /// The span to highlight in the emitted diagnostic.
+ span: Option<Span>,
+}
+
+/// Transform a syn::Path to a readable String
+fn path_to_string(path: &syn::Path) -> String {
+ path.segments.iter().map(|s| s.ident.to_string()).collect::<Vec<String>>().join("::")
+}
+
+/// Error creation functions
+impl Error {
+ pub(in error) fn new(kind: ErrorKind) -> Self {
+ Error {
+ kind,
+ locations: Vec::new(),
+ span: None,
+ }
+ }
+
+ /// Creates a new error with a custom message.
+ pub fn custom<T: fmt::Display>(msg: T) -> Self {
+ Error::new(ErrorKind::Custom(msg.to_string()))
+ }
+
+ /// Creates a new error for a field that appears twice in the input.
+ pub fn duplicate_field(name: &str) -> Self {
+ Error::new(ErrorKind::DuplicateField(name.into()))
+ }
+
+ /// Creates a new error for a field that appears twice in the input. Helper to avoid repeating
+ /// the syn::Path to String conversion.
+ pub fn duplicate_field_path(path: &Path) -> Self {
+ Error::duplicate_field(&path_to_string(path))
+ }
+
+ /// Creates a new error for a non-optional field that does not appear in the input.
+ pub fn missing_field(name: &str) -> Self {
+ Error::new(ErrorKind::MissingField(name.into()))
+ }
+
+ /// Creates a new error for a field name that appears in the input but does not correspond
+ /// to a known field.
+ pub fn unknown_field(name: &str) -> Self {
+ Error::new(ErrorKind::UnknownField(name.into()))
+ }
+
+ /// Creates a new error for a field name that appears in the input but does not correspond
+ /// to a known field. Helper to avoid repeating the syn::Path to String conversion.
+ pub fn unknown_field_path(path: &Path) -> Self {
+ Error::unknown_field(&path_to_string(path))
+ }
+
+ /// Creates a new error for a field name that appears in the input but does not correspond to
+ /// a known attribute. The second argument is the list of known attributes; if a similar name
+ /// is found that will be shown in the emitted error message.
+ pub fn unknown_field_with_alts<'a, T, I>(field: &str, alternates: I) -> Self
+ where
+ T: AsRef<str> + 'a,
+ I: IntoIterator<Item = &'a T>,
+ {
+ Error::new(ErrorUnknownField::with_alts(field, alternates).into())
+ }
+
+ /// Creates a new error for a struct or variant that does not adhere to the supported shape.
+ pub fn unsupported_shape(shape: &str) -> Self {
+ Error::new(ErrorKind::UnsupportedShape(shape.into()))
+ }
+
+ pub fn unsupported_format(format: &str) -> Self {
+ Error::new(ErrorKind::UnexpectedFormat(format.into()))
+ }
+
+ /// Creates a new error for a field which has an unexpected literal type.
+ pub fn unexpected_type(ty: &str) -> Self {
+ Error::new(ErrorKind::UnexpectedType(ty.into()))
+ }
+
+ /// Creates a new error for a field which has an unexpected literal type. This will automatically
+ /// extract the literal type name from the passed-in `Lit` and set the span to encompass only the
+ /// literal value.
+ ///
+ /// # Usage
+ /// This is most frequently used in overrides of the `FromMeta::from_value` method.
+ ///
+ /// ```rust
+ /// # // pretend darling_core is darling so the doc example looks correct.
+ /// # extern crate darling_core as darling;
+ /// # extern crate syn;
+ ///
+ /// use darling::{FromMeta, Error, Result};
+ /// use syn::{Lit, LitStr};
+ ///
+ /// pub struct Foo(String);
+ ///
+ /// impl FromMeta for Foo {
+ /// fn from_value(value: &Lit) -> Result<Self> {
+ /// if let Lit::Str(ref lit_str) = *value {
+ /// Ok(Foo(lit_str.value()))
+ /// } else {
+ /// Err(Error::unexpected_lit_type(value))
+ /// }
+ /// }
+ /// }
+ ///
+ /// # fn main() {}
+ /// ```
+ pub fn unexpected_lit_type(lit: &Lit) -> Self {
+ Error::unexpected_type(match *lit {
+ Lit::Str(_) => "string",
+ Lit::ByteStr(_) => "byte string",
+ Lit::Byte(_) => "byte",
+ Lit::Char(_) => "char",
+ Lit::Int(_) => "int",
+ Lit::Float(_) => "float",
+ Lit::Bool(_) => "bool",
+ Lit::Verbatim(_) => "verbatim",
+ })
+ .with_span(lit)
+ }
+
+ /// Creates a new error for a value which doesn't match a set of expected literals.
+ pub fn unknown_value(value: &str) -> Self {
+ Error::new(ErrorKind::UnknownValue(value.into()))
+ }
+
+ /// Creates a new error for a list which did not get enough items to proceed.
+ pub fn too_few_items(min: usize) -> Self {
+ Error::new(ErrorKind::TooFewItems(min))
+ }
+
+ /// Creates a new error when a list got more items than it supports. The `max` argument
+ /// is the largest number of items the receiver could accept.
+ pub fn too_many_items(max: usize) -> Self {
+ Error::new(ErrorKind::TooManyItems(max))
+ }
+
+ /// Bundle a set of multiple errors into a single `Error` instance.
+ ///
+ /// # Panics
+ /// This function will panic if `errors.is_empty() == true`.
+ pub fn multiple(mut errors: Vec<Error>) -> Self {
+ if errors.len() > 1 {
+ Error::new(ErrorKind::Multiple(errors))
+ } else if errors.len() == 1 {
+ errors
+ .pop()
+ .expect("Error array of length 1 has a first item")
+ } else {
+ panic!("Can't deal with 0 errors")
+ }
+ }
+}
+
+impl Error {
+ /// Create a new error about a literal string that doesn't match a set of known
+ /// or permissible values. This function can be made public if the API proves useful
+ /// beyond impls for `syn` types.
+ pub(crate) fn unknown_lit_str_value(value: &LitStr) -> Self {
+ Error::unknown_value(&value.value()).with_span(value)
+ }
+}
+
+/// Error instance methods
+impl Error {
+ /// Check if this error is associated with a span in the token stream.
+ pub fn has_span(&self) -> bool {
+ self.span.is_some()
+ }
+
+ /// Tie a span to the error if none is already present. This is used in `darling::FromMeta`
+ /// and other traits to attach errors to the most specific possible location in the input
+ /// source code.
+ ///
+ /// All `darling`-built impls, either from the crate or from the proc macro, will call this
+ /// when appropriate during parsing, so it should not be necessary to call this unless you have
+ /// overridden:
+ ///
+ /// * `FromMeta::from_meta`
+ /// * `FromMeta::from_nested_meta`
+ /// * `FromMeta::from_value`
+ pub fn with_span<T: Spanned>(mut self, node: &T) -> Self {
+ if !self.has_span() {
+ self.span = Some(node.span());
+ }
+
+ self
+ }
+
+ /// Recursively converts a tree of errors to a flattened list.
+ pub fn flatten(self) -> Self {
+ Error::multiple(self.into_vec())
+ }
+
+ fn into_vec(self) -> Vec<Self> {
+ if let ErrorKind::Multiple(errors) = self.kind {
+ let mut flat = Vec::new();
+ for error in errors {
+ flat.extend(error.prepend_at(self.locations.clone()).into_vec());
+ }
+
+ flat
+ } else {
+ vec![self]
+ }
+ }
+
+ /// Adds a location to the error, such as a field or variant.
+ /// Locations must be added in reverse order of specificity.
+ pub fn at<T: fmt::Display>(mut self, location: T) -> Self {
+ self.locations.insert(0, location.to_string());
+ self
+ }
+
+ /// Adds a location to the error, such as a field or variant.
+ /// Locations must be added in reverse order of specificity. This is a helper function to avoid
+ /// repeating path to string logic.
+ pub fn at_path(self, path: &Path) -> Self {
+ self.at(path_to_string(path))
+ }
+
+ /// Gets the number of individual errors in this error.
+ ///
+ /// This function never returns `0`, as it's impossible to construct
+ /// a multi-error from an empty `Vec`.
+ pub fn len(&self) -> usize {
+ self.kind.len()
+ }
+
+ /// Adds a location chain to the head of the error's existing locations.
+ fn prepend_at(mut self, mut locations: Vec<String>) -> Self {
+ if !locations.is_empty() {
+ locations.extend(self.locations);
+ self.locations = locations;
+ }
+
+ self
+ }
+
+ /// Gets the location slice.
+ #[cfg(test)]
+ pub(crate) fn location(&self) -> Vec<&str> {
+ self.locations.iter().map(|i| i.as_str()).collect()
+ }
+
+ /// Write this error and any children as compile errors into a `TokenStream` to
+ /// be returned by the proc-macro.
+ ///
+ /// The behavior of this method will be slightly different if the `diagnostics` feature
+ /// is enabled: In that case, the diagnostics will be emitted immediately by this call,
+ /// and an empty `TokenStream` will be returned.
+ ///
+ /// Return these tokens unmodified to avoid disturbing the attached span information.
+ ///
+ /// # Usage
+ /// ```rust,ignore
+ /// // in your proc-macro function
+ /// let opts = match MyOptions::from_derive_input(&ast) {
+ /// Ok(val) => val,
+ /// Err(err) => {
+ /// return err.write_errors();
+ /// }
+ /// }
+ /// ```
+ pub fn write_errors(self) -> TokenStream {
+ #[cfg(feature = "diagnostics")]
+ {
+ self.emit();
+ quote!()
+ }
+
+ #[cfg(not(feature = "diagnostics"))]
+ {
+ self.flatten()
+ .into_iter()
+ .map(|e| e.single_to_syn_error().to_compile_error())
+ .collect()
+ }
+ }
+
+ #[cfg(not(feature = "diagnostics"))]
+ fn single_to_syn_error(self) -> ::syn::Error {
+ match self.span {
+ Some(span) => ::syn::Error::new(span, self.kind),
+ None => ::syn::Error::new(Span::call_site(), self),
+ }
+ }
+
+ #[cfg(feature = "diagnostics")]
+ fn single_to_diagnostic(self) -> ::proc_macro::Diagnostic {
+ use proc_macro::{Diagnostic, Level};
+
+ // Delegate to dedicated error formatters when applicable.
+ //
+ // If span information is available, don't include the error property path
+ // since it's redundant and not consistent with native compiler diagnostics.
+ match self.kind {
+ ErrorKind::UnknownField(euf) => euf.to_diagnostic(self.span),
+ _ => match self.span {
+ Some(span) => span.unwrap().error(self.kind.to_string()),
+ None => Diagnostic::new(Level::Error, self.to_string()),
+ },
+ }
+ }
+
+ /// Transform this error and its children into a list of compiler diagnostics
+ /// and emit them. If the `Error` has associated span information, the diagnostics
+ /// will identify the correct location in source code automatically.
+ ///
+ /// # Stability
+ /// This is only available on `nightly` until the compiler `proc_macro_diagnostic`
+ /// feature stabilizes. Until then, it may break at any time.
+ #[cfg(feature = "diagnostics")]
+ pub fn emit(self) {
+ for error in self.flatten() {
+ error.single_to_diagnostic().emit()
+ }
+ }
+
+ /// Transform the error into a compiler diagnostic and - if the diagnostic points to
+ /// a specific code location - add a spanned help child diagnostic that points to the
+ /// parent derived trait.
+ ///
+ /// This is experimental and therefore not exposed outside the crate.
+ #[cfg(feature = "diagnostics")]
+ #[allow(dead_code)]
+ fn emit_with_macro_help_span(self) {
+ use proc_macro::Diagnostic;
+
+ for error in self.flatten() {
+ let needs_help = error.has_span();
+ let diagnostic = error.single_to_diagnostic();
+ Diagnostic::emit(if needs_help {
+ diagnostic.span_help(
+ Span::call_site().unwrap(),
+ "Encountered as part of this derive-mode-macro",
+ )
+ } else {
+ diagnostic
+ })
+ }
+ }
+}
+
+impl StdError for Error {
+ fn description(&self) -> &str {
+ &self.kind.description()
+ }
+
+ fn cause(&self) -> Option<&StdError> {
+ None
+ }
+}
+
+impl fmt::Display for Error {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.kind)?;
+ if !self.locations.is_empty() {
+ write!(f, " at {}", self.locations.join("/"))?;
+ }
+
+ Ok(())
+ }
+}
+
+// Don't want to publicly commit to Error supporting equality yet, but
+// not having it makes testing very difficult. Note that spans are not
+// considered for equality since that would break testing in most cases.
+#[cfg(test)]
+impl PartialEq for Error {
+ fn eq(&self, other: &Self) -> bool {
+ self.kind == other.kind && self.locations == other.locations
+ }
+}
+
+#[cfg(test)]
+impl Eq for Error {}
+
+impl IntoIterator for Error {
+ type Item = Error;
+ type IntoIter = IntoIter;
+
+ fn into_iter(self) -> IntoIter {
+ if let ErrorKind::Multiple(errors) = self.kind {
+ IntoIter {
+ inner: IntoIterEnum::Multiple(errors.into_iter()),
+ }
+ } else {
+ IntoIter {
+ inner: IntoIterEnum::Single(iter::once(self)),
+ }
+ }
+ }
+}
+
+enum IntoIterEnum {
+ Single(iter::Once<Error>),
+ Multiple(vec::IntoIter<Error>),
+}
+
+impl Iterator for IntoIterEnum {
+ type Item = Error;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ match *self {
+ IntoIterEnum::Single(ref mut content) => content.next(),
+ IntoIterEnum::Multiple(ref mut content) => content.next(),
+ }
+ }
+}
+
+/// An iterator that moves out of an `Error`.
+pub struct IntoIter {
+ inner: IntoIterEnum,
+}
+
+impl Iterator for IntoIter {
+ type Item = Error;
+
+ fn next(&mut self) -> Option<Error> {
+ self.inner.next()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::Error;
+
+ #[test]
+ fn flatten_noop() {
+ let err = Error::duplicate_field("hello").at("world");
+ assert_eq!(err.clone().flatten(), err);
+ }
+
+ #[test]
+ fn flatten_simple() {
+ let err = Error::multiple(vec![
+ Error::unknown_field("hello").at("world"),
+ Error::missing_field("hell_no").at("world"),
+ ])
+ .at("foo")
+ .flatten();
+
+ assert!(err.location().is_empty());
+
+ let mut err_iter = err.into_iter();
+
+ let first = err_iter.next();
+ assert!(first.is_some());
+ assert_eq!(first.unwrap().location(), vec!["foo", "world"]);
+
+ let second = err_iter.next();
+ assert!(second.is_some());
+
+ assert_eq!(second.unwrap().location(), vec!["foo", "world"]);
+
+ assert!(err_iter.next().is_none());
+ }
+
+ #[test]
+ fn len_single() {
+ let err = Error::duplicate_field("hello");
+ assert_eq!(1, err.len());
+ }
+
+ #[test]
+ fn len_multiple() {
+ let err = Error::multiple(vec![
+ Error::duplicate_field("hello"),
+ Error::missing_field("hell_no"),
+ ]);
+ assert_eq!(2, err.len());
+ }
+
+ #[test]
+ fn len_nested() {
+ let err = Error::multiple(vec![
+ Error::duplicate_field("hello"),
+ Error::multiple(vec![
+ Error::duplicate_field("hi"),
+ Error::missing_field("bye"),
+ Error::multiple(vec![Error::duplicate_field("whatsup")]),
+ ]),
+ ]);
+
+ assert_eq!(4, err.len());
+ }
+}
diff --git a/third_party/rust/darling_core/src/from_derive_input.rs b/third_party/rust/darling_core/src/from_derive_input.rs
new file mode 100644
index 0000000000..740dd08284
--- /dev/null
+++ b/third_party/rust/darling_core/src/from_derive_input.rs
@@ -0,0 +1,26 @@
+use syn::DeriveInput;
+
+use Result;
+
+/// Creates an instance by parsing an entire proc-macro `derive` input,
+/// including the, identity, generics, and visibility of the type.
+///
+/// This trait should either be derived or manually implemented by a type
+/// in the proc macro crate which is directly using `darling`. It is unlikely
+/// that these implementations will be reusable across crates.
+pub trait FromDeriveInput: Sized {
+ /// Create an instance from `syn::DeriveInput`, or return an error.
+ fn from_derive_input(input: &DeriveInput) -> Result<Self>;
+}
+
+impl FromDeriveInput for () {
+ fn from_derive_input(_: &DeriveInput) -> Result<Self> {
+ Ok(())
+ }
+}
+
+impl FromDeriveInput for DeriveInput {
+ fn from_derive_input(input: &DeriveInput) -> Result<Self> {
+ Ok(input.clone())
+ }
+}
diff --git a/third_party/rust/darling_core/src/from_field.rs b/third_party/rust/darling_core/src/from_field.rs
new file mode 100644
index 0000000000..074bdc07af
--- /dev/null
+++ b/third_party/rust/darling_core/src/from_field.rs
@@ -0,0 +1,38 @@
+use syn::{self, Field};
+
+use Result;
+
+/// Creates an instance by parsing an individual field and its attributes.
+pub trait FromField: Sized {
+ fn from_field(field: &Field) -> Result<Self>;
+}
+
+impl FromField for () {
+ fn from_field(_: &Field) -> Result<Self> {
+ Ok(())
+ }
+}
+
+impl FromField for Field {
+ fn from_field(field: &Field) -> Result<Self> {
+ Ok(field.clone())
+ }
+}
+
+impl FromField for syn::Type {
+ fn from_field(field: &Field) -> Result<Self> {
+ Ok(field.ty.clone())
+ }
+}
+
+impl FromField for syn::Visibility {
+ fn from_field(field: &Field) -> Result<Self> {
+ Ok(field.vis.clone())
+ }
+}
+
+impl FromField for Vec<syn::Attribute> {
+ fn from_field(field: &Field) -> Result<Self> {
+ Ok(field.attrs.clone())
+ }
+}
diff --git a/third_party/rust/darling_core/src/from_generic_param.rs b/third_party/rust/darling_core/src/from_generic_param.rs
new file mode 100644
index 0000000000..168600c4c4
--- /dev/null
+++ b/third_party/rust/darling_core/src/from_generic_param.rs
@@ -0,0 +1,21 @@
+use syn;
+
+use Result;
+
+/// Creates an instance by parsing a specific `syn::GenericParam`.
+/// This can be a type param, a lifetime, or a const param.
+pub trait FromGenericParam: Sized {
+ fn from_generic_param(param: &syn::GenericParam) -> Result<Self>;
+}
+
+impl FromGenericParam for () {
+ fn from_generic_param(_param: &syn::GenericParam) -> Result<Self> {
+ Ok(())
+ }
+}
+
+impl FromGenericParam for syn::GenericParam {
+ fn from_generic_param(param: &syn::GenericParam) -> Result<Self> {
+ Ok(param.clone())
+ }
+}
diff --git a/third_party/rust/darling_core/src/from_generics.rs b/third_party/rust/darling_core/src/from_generics.rs
new file mode 100644
index 0000000000..eb6e5c97e0
--- /dev/null
+++ b/third_party/rust/darling_core/src/from_generics.rs
@@ -0,0 +1,27 @@
+use syn::Generics;
+
+use Result;
+
+/// Creates an instance by parsing an entire generics declaration, including the
+/// `where` clause.
+pub trait FromGenerics: Sized {
+ fn from_generics(generics: &Generics) -> Result<Self>;
+}
+
+impl FromGenerics for () {
+ fn from_generics(_generics: &Generics) -> Result<Self> {
+ Ok(())
+ }
+}
+
+impl FromGenerics for Generics {
+ fn from_generics(generics: &Generics) -> Result<Self> {
+ Ok(generics.clone())
+ }
+}
+
+impl<T: FromGenerics> FromGenerics for Result<T> {
+ fn from_generics(generics: &Generics) -> Result<Self> {
+ Ok(FromGenerics::from_generics(generics))
+ }
+}
diff --git a/third_party/rust/darling_core/src/from_meta.rs b/third_party/rust/darling_core/src/from_meta.rs
new file mode 100644
index 0000000000..5c805393b5
--- /dev/null
+++ b/third_party/rust/darling_core/src/from_meta.rs
@@ -0,0 +1,500 @@
+use std::cell::RefCell;
+use std::collections::hash_map::{Entry, HashMap};
+use std::hash::BuildHasher;
+use std::rc::Rc;
+use std::sync::atomic::AtomicBool;
+use std::sync::Arc;
+
+use ident_case;
+use syn::{self, Lit, Meta, NestedMeta};
+
+use {Error, Result};
+
+/// Create an instance from an item in an attribute declaration.
+///
+/// # Implementing `FromMeta`
+/// * Do not take a dependency on the `ident` of the passed-in meta item. The ident will be set by the field name of the containing struct.
+/// * Implement only the `from_*` methods that you intend to support. The default implementations will return useful errors.
+///
+/// # Provided Implementations
+/// ## bool
+///
+/// * Word with no value specified - becomes `true`.
+/// * As a boolean literal, e.g. `foo = true`.
+/// * As a string literal, e.g. `foo = "true"`.
+///
+/// ## String
+/// * As a string literal, e.g. `foo = "hello"`.
+/// * As a raw string literal, e.g. `foo = r#"hello "world""#`.
+///
+/// ## Number
+/// * As a string literal, e.g. `foo = "-25"`.
+/// * As an unquoted positive value, e.g. `foo = 404`. Negative numbers must be in quotation marks.
+///
+/// ## ()
+/// * Word with no value specified, e.g. `foo`. This is best used with `Option`.
+/// See `darling::util::Flag` for a more strongly-typed alternative.
+///
+/// ## Option
+/// * Any format produces `Some`.
+///
+/// ## `Result<T, darling::Error>`
+/// * Allows for fallible parsing; will populate the target field with the result of the
+/// parse attempt.
+pub trait FromMeta: Sized {
+ fn from_nested_meta(item: &NestedMeta) -> Result<Self> {
+ (match *item {
+ NestedMeta::Lit(ref lit) => Self::from_value(lit),
+ NestedMeta::Meta(ref mi) => Self::from_meta(mi),
+ })
+ .map_err(|e| e.with_span(item))
+ }
+
+ /// Create an instance from a `syn::Meta` by dispatching to the format-appropriate
+ /// trait function. This generally should not be overridden by implementers.
+ ///
+ /// # Error Spans
+ /// If this method is overridden and can introduce errors that weren't passed up from
+ /// other `from_meta` calls, the override must call `with_span` on the error using the
+ /// `item` to make sure that the emitted diagnostic points to the correct location in
+ /// source code.
+ fn from_meta(item: &Meta) -> Result<Self> {
+ (match *item {
+ Meta::Path(_) => Self::from_word(),
+ Meta::List(ref value) => Self::from_list(
+ &value
+ .nested
+ .iter()
+ .cloned()
+ .collect::<Vec<syn::NestedMeta>>()[..],
+ ),
+ Meta::NameValue(ref value) => Self::from_value(&value.lit),
+ })
+ .map_err(|e| e.with_span(item))
+ }
+
+ /// Create an instance from the presence of the word in the attribute with no
+ /// additional options specified.
+ fn from_word() -> Result<Self> {
+ Err(Error::unsupported_format("word"))
+ }
+
+ /// Create an instance from a list of nested meta items.
+ #[allow(unused_variables)]
+ fn from_list(items: &[NestedMeta]) -> Result<Self> {
+ Err(Error::unsupported_format("list"))
+ }
+
+ /// Create an instance from a literal value of either `foo = "bar"` or `foo("bar")`.
+ /// This dispatches to the appropriate method based on the type of literal encountered,
+ /// and generally should not be overridden by implementers.
+ ///
+ /// # Error Spans
+ /// If this method is overridden, the override must make sure to add `value`'s span
+ /// information to the returned error by calling `with_span(value)` on the `Error` instance.
+ fn from_value(value: &Lit) -> Result<Self> {
+ (match *value {
+ Lit::Bool(ref b) => Self::from_bool(b.value),
+ Lit::Str(ref s) => Self::from_string(&s.value()),
+ _ => Err(Error::unexpected_lit_type(value)),
+ })
+ .map_err(|e| e.with_span(value))
+ }
+
+ /// Create an instance from a char literal in a value position.
+ #[allow(unused_variables)]
+ fn from_char(value: char) -> Result<Self> {
+ Err(Error::unexpected_type("char"))
+ }
+
+ /// Create an instance from a string literal in a value position.
+ #[allow(unused_variables)]
+ fn from_string(value: &str) -> Result<Self> {
+ Err(Error::unexpected_type("string"))
+ }
+
+ /// Create an instance from a bool literal in a value position.
+ #[allow(unused_variables)]
+ fn from_bool(value: bool) -> Result<Self> {
+ Err(Error::unexpected_type("bool"))
+ }
+}
+
+// FromMeta impls for std and syn types.
+
+impl FromMeta for () {
+ fn from_word() -> Result<Self> {
+ Ok(())
+ }
+}
+
+impl FromMeta for bool {
+ fn from_word() -> Result<Self> {
+ Ok(true)
+ }
+
+ fn from_bool(value: bool) -> Result<Self> {
+ Ok(value)
+ }
+
+ fn from_string(value: &str) -> Result<Self> {
+ value.parse().map_err(|_| Error::unknown_value(value))
+ }
+}
+
+impl FromMeta for AtomicBool {
+ fn from_meta(mi: &Meta) -> Result<Self> {
+ FromMeta::from_meta(mi)
+ .map(AtomicBool::new)
+ .map_err(|e| e.with_span(mi))
+ }
+}
+
+impl FromMeta for String {
+ fn from_string(s: &str) -> Result<Self> {
+ Ok(s.to_string())
+ }
+}
+
+/// Generate an impl of `FromMeta` that will accept strings which parse to numbers or
+/// integer literals.
+macro_rules! from_meta_num {
+ ($ty:ident) => {
+ impl FromMeta for $ty {
+ fn from_string(s: &str) -> Result<Self> {
+ s.parse().map_err(|_| Error::unknown_value(s))
+ }
+
+ fn from_value(value: &Lit) -> Result<Self> {
+ (match *value {
+ Lit::Str(ref s) => Self::from_string(&s.value()),
+ Lit::Int(ref s) => Ok(s.base10_parse::<$ty>().unwrap()),
+ _ => Err(Error::unexpected_lit_type(value)),
+ })
+ .map_err(|e| e.with_span(value))
+ }
+ }
+ };
+}
+
+from_meta_num!(u8);
+from_meta_num!(u16);
+from_meta_num!(u32);
+from_meta_num!(u64);
+from_meta_num!(usize);
+from_meta_num!(i8);
+from_meta_num!(i16);
+from_meta_num!(i32);
+from_meta_num!(i64);
+from_meta_num!(isize);
+
+/// Generate an impl of `FromMeta` that will accept strings which parse to floats or
+/// float literals.
+macro_rules! from_meta_float {
+ ($ty:ident) => {
+ impl FromMeta for $ty {
+ fn from_string(s: &str) -> Result<Self> {
+ s.parse().map_err(|_| Error::unknown_value(s))
+ }
+
+ fn from_value(value: &Lit) -> Result<Self> {
+ (match *value {
+ Lit::Str(ref s) => Self::from_string(&s.value()),
+ Lit::Float(ref s) => Ok(s.base10_parse::<$ty>().unwrap()),
+ _ => Err(Error::unexpected_lit_type(value)),
+ })
+ .map_err(|e| e.with_span(value))
+ }
+ }
+ };
+}
+
+from_meta_float!(f32);
+from_meta_float!(f64);
+
+/// Parsing support for identifiers. This attempts to preserve span information
+/// when available, but also supports parsing strings with the call site as the
+/// emitted span.
+impl FromMeta for syn::Ident {
+ fn from_string(value: &str) -> Result<Self> {
+ Ok(syn::Ident::new(value, ::proc_macro2::Span::call_site()))
+ }
+
+ fn from_value(value: &Lit) -> Result<Self> {
+ if let Lit::Str(ref ident) = *value {
+ ident
+ .parse()
+ .map_err(|_| Error::unknown_lit_str_value(ident))
+ } else {
+ Err(Error::unexpected_lit_type(value))
+ }
+ }
+}
+
+/// Parsing support for paths. This attempts to preserve span information when available,
+/// but also supports parsing strings with the call site as the emitted span.
+impl FromMeta for syn::Path {
+ fn from_string(value: &str) -> Result<Self> {
+ syn::parse_str(value).map_err(|_| Error::unknown_value(value))
+ }
+
+ fn from_value(value: &Lit) -> Result<Self> {
+ if let Lit::Str(ref path_str) = *value {
+ path_str
+ .parse()
+ .map_err(|_| Error::unknown_lit_str_value(path_str))
+ } else {
+ Err(Error::unexpected_lit_type(value))
+ }
+ }
+}
+
+impl FromMeta for syn::Lit {
+ fn from_value(value: &Lit) -> Result<Self> {
+ Ok(value.clone())
+ }
+}
+
+macro_rules! from_meta_lit {
+ ($impl_ty:path, $lit_variant:path) => {
+ impl FromMeta for $impl_ty {
+ fn from_value(value: &Lit) -> Result<Self> {
+ if let $lit_variant(ref value) = *value {
+ Ok(value.clone())
+ } else {
+ Err(Error::unexpected_lit_type(value))
+ }
+ }
+ }
+ };
+}
+
+from_meta_lit!(syn::LitInt, Lit::Int);
+from_meta_lit!(syn::LitFloat, Lit::Float);
+from_meta_lit!(syn::LitStr, Lit::Str);
+from_meta_lit!(syn::LitByte, Lit::Byte);
+from_meta_lit!(syn::LitByteStr, Lit::ByteStr);
+from_meta_lit!(syn::LitChar, Lit::Char);
+from_meta_lit!(syn::LitBool, Lit::Bool);
+from_meta_lit!(proc_macro2::Literal, Lit::Verbatim);
+
+impl FromMeta for syn::Meta {
+ fn from_meta(value: &syn::Meta) -> Result<Self> {
+ Ok(value.clone())
+ }
+}
+
+impl FromMeta for syn::WhereClause {
+ fn from_string(value: &str) -> Result<Self> {
+ syn::parse_str(value).map_err(|_| Error::unknown_value(value))
+ }
+}
+
+impl FromMeta for Vec<syn::WherePredicate> {
+ fn from_string(value: &str) -> Result<Self> {
+ syn::WhereClause::from_string(&format!("where {}", value))
+ .map(|c| c.predicates.into_iter().collect())
+ }
+}
+
+impl FromMeta for ident_case::RenameRule {
+ fn from_string(value: &str) -> Result<Self> {
+ value.parse().map_err(|_| Error::unknown_value(value))
+ }
+}
+
+impl<T: FromMeta> FromMeta for Option<T> {
+ fn from_meta(item: &Meta) -> Result<Self> {
+ FromMeta::from_meta(item).map(Some)
+ }
+}
+
+impl<T: FromMeta> FromMeta for Box<T> {
+ fn from_meta(item: &Meta) -> Result<Self> {
+ FromMeta::from_meta(item).map(Box::new)
+ }
+}
+
+impl<T: FromMeta> FromMeta for Result<T> {
+ fn from_meta(item: &Meta) -> Result<Self> {
+ Ok(FromMeta::from_meta(item))
+ }
+}
+
+/// Parses the meta-item, and in case of error preserves a copy of the input for
+/// later analysis.
+impl<T: FromMeta> FromMeta for ::std::result::Result<T, Meta> {
+ fn from_meta(item: &Meta) -> Result<Self> {
+ T::from_meta(item)
+ .map(Ok)
+ .or_else(|_| Ok(Err(item.clone())))
+ }
+}
+
+impl<T: FromMeta> FromMeta for Rc<T> {
+ fn from_meta(item: &Meta) -> Result<Self> {
+ FromMeta::from_meta(item).map(Rc::new)
+ }
+}
+
+impl<T: FromMeta> FromMeta for Arc<T> {
+ fn from_meta(item: &Meta) -> Result<Self> {
+ FromMeta::from_meta(item).map(Arc::new)
+ }
+}
+
+impl<T: FromMeta> FromMeta for RefCell<T> {
+ fn from_meta(item: &Meta) -> Result<Self> {
+ FromMeta::from_meta(item).map(RefCell::new)
+ }
+}
+
+impl<V: FromMeta, S: BuildHasher + Default> FromMeta for HashMap<String, V, S> {
+ fn from_list(nested: &[syn::NestedMeta]) -> Result<Self> {
+ let mut map = HashMap::with_capacity_and_hasher(nested.len(), Default::default());
+ for item in nested {
+ if let syn::NestedMeta::Meta(ref inner) = *item {
+ let path = inner.path();
+ let name = path.segments.iter().map(|s| s.ident.to_string()).collect::<Vec<String>>().join("::");
+ match map.entry(name) {
+ Entry::Occupied(_) => {
+ return Err(
+ Error::duplicate_field_path(&path).with_span(inner)
+ );
+ }
+ Entry::Vacant(entry) => {
+ // In the error case, extend the error's path, but assume the inner `from_meta`
+ // set the span, and that subsequently we don't have to.
+ entry.insert(FromMeta::from_meta(inner).map_err(|e| e.at_path(&path))?);
+ }
+ }
+ }
+ }
+
+ Ok(map)
+ }
+}
+
+/// Tests for `FromMeta` implementations. Wherever the word `ignore` appears in test input,
+/// it should not be considered by the parsing.
+#[cfg(test)]
+mod tests {
+ use proc_macro2::TokenStream;
+ use syn;
+
+ use {Error, FromMeta, Result};
+
+ /// parse a string as a syn::Meta instance.
+ fn pm(tokens: TokenStream) -> ::std::result::Result<syn::Meta, String> {
+ let attribute: syn::Attribute = parse_quote!(#[#tokens]);
+ attribute.parse_meta().map_err(|_| "Unable to parse".into())
+ }
+
+ fn fm<T: FromMeta>(tokens: TokenStream) -> T {
+ FromMeta::from_meta(&pm(tokens).expect("Tests should pass well-formed input"))
+ .expect("Tests should pass valid input")
+ }
+
+ #[test]
+ fn unit_succeeds() {
+ assert_eq!(fm::<()>(quote!(ignore)), ());
+ }
+
+ #[test]
+ fn bool_succeeds() {
+ // word format
+ assert_eq!(fm::<bool>(quote!(ignore)), true);
+
+ // bool literal
+ assert_eq!(fm::<bool>(quote!(ignore = true)), true);
+ assert_eq!(fm::<bool>(quote!(ignore = false)), false);
+
+ // string literals
+ assert_eq!(fm::<bool>(quote!(ignore = "true")), true);
+ assert_eq!(fm::<bool>(quote!(ignore = "false")), false);
+ }
+
+ #[test]
+ fn string_succeeds() {
+ // cooked form
+ assert_eq!(&fm::<String>(quote!(ignore = "world")), "world");
+
+ // raw form
+ assert_eq!(&fm::<String>(quote!(ignore = r#"world"#)), "world");
+ }
+
+ #[test]
+ fn number_succeeds() {
+ assert_eq!(fm::<u8>(quote!(ignore = "2")), 2u8);
+ assert_eq!(fm::<i16>(quote!(ignore = "-25")), -25i16);
+ assert_eq!(fm::<f64>(quote!(ignore = "1.4e10")), 1.4e10);
+ }
+
+ #[test]
+ fn int_without_quotes() {
+ assert_eq!(fm::<u8>(quote!(ignore = 2)), 2u8);
+ assert_eq!(fm::<u16>(quote!(ignore = 255)), 255u16);
+ assert_eq!(fm::<u32>(quote!(ignore = 5000)), 5000u32);
+
+ // Check that we aren't tripped up by incorrect suffixes
+ assert_eq!(fm::<u32>(quote!(ignore = 5000i32)), 5000u32);
+ }
+
+ #[test]
+ fn float_without_quotes() {
+ assert_eq!(fm::<f32>(quote!(ignore = 2.)), 2.0f32);
+ assert_eq!(fm::<f32>(quote!(ignore = 2.0)), 2.0f32);
+ assert_eq!(fm::<f64>(quote!(ignore = 1.4e10)), 1.4e10f64);
+ }
+
+ #[test]
+ fn meta_succeeds() {
+ use syn::Meta;
+
+ assert_eq!(
+ fm::<Meta>(quote!(hello(world, today))),
+ pm(quote!(hello(world, today))).unwrap()
+ );
+ }
+
+ #[test]
+ fn hash_map_succeeds() {
+ use std::collections::HashMap;
+
+ let comparison = {
+ let mut c = HashMap::new();
+ c.insert("hello".to_string(), true);
+ c.insert("world".to_string(), false);
+ c.insert("there".to_string(), true);
+ c
+ };
+
+ assert_eq!(
+ fm::<HashMap<String, bool>>(quote!(ignore(hello, world = false, there = "true"))),
+ comparison
+ );
+ }
+
+ /// Check that a `HashMap` cannot have duplicate keys, and that the generated error
+ /// is assigned a span to correctly target the diagnostic message.
+ #[test]
+ fn hash_map_duplicate() {
+ use std::collections::HashMap;
+
+ let err: Result<HashMap<String, bool>> =
+ FromMeta::from_meta(&pm(quote!(ignore(hello, hello = false))).unwrap());
+
+ let err = err.expect_err("Duplicate keys in HashMap should error");
+
+ assert!(err.has_span());
+ assert_eq!(err.to_string(), Error::duplicate_field("hello").to_string());
+ }
+
+ /// Tests that fallible parsing will always produce an outer `Ok` (from `fm`),
+ /// and will accurately preserve the inner contents.
+ #[test]
+ fn darling_result_succeeds() {
+ fm::<Result<()>>(quote!(ignore)).unwrap();
+ fm::<Result<()>>(quote!(ignore(world))).unwrap_err();
+ }
+}
diff --git a/third_party/rust/darling_core/src/from_type_param.rs b/third_party/rust/darling_core/src/from_type_param.rs
new file mode 100644
index 0000000000..cc9c5dac00
--- /dev/null
+++ b/third_party/rust/darling_core/src/from_type_param.rs
@@ -0,0 +1,32 @@
+use syn::{self, TypeParam};
+
+use Result;
+
+/// Creates an instance by parsing an individual type_param and its attributes.
+pub trait FromTypeParam: Sized {
+ fn from_type_param(type_param: &TypeParam) -> Result<Self>;
+}
+
+impl FromTypeParam for () {
+ fn from_type_param(_: &TypeParam) -> Result<Self> {
+ Ok(())
+ }
+}
+
+impl FromTypeParam for TypeParam {
+ fn from_type_param(type_param: &TypeParam) -> Result<Self> {
+ Ok(type_param.clone())
+ }
+}
+
+impl FromTypeParam for Vec<syn::Attribute> {
+ fn from_type_param(type_param: &TypeParam) -> Result<Self> {
+ Ok(type_param.attrs.clone())
+ }
+}
+
+impl FromTypeParam for syn::Ident {
+ fn from_type_param(type_param: &TypeParam) -> Result<Self> {
+ Ok(type_param.ident.clone())
+ }
+}
diff --git a/third_party/rust/darling_core/src/from_variant.rs b/third_party/rust/darling_core/src/from_variant.rs
new file mode 100644
index 0000000000..d4dd5f2ac9
--- /dev/null
+++ b/third_party/rust/darling_core/src/from_variant.rs
@@ -0,0 +1,33 @@
+use syn::{self, Variant};
+
+use Result;
+
+/// Creates an instance from a specified `syn::Variant`.
+pub trait FromVariant: Sized {
+ /// Create an instance from `syn::Variant`, or return an error.
+ fn from_variant(variant: &Variant) -> Result<Self>;
+}
+
+impl FromVariant for () {
+ fn from_variant(_: &Variant) -> Result<Self> {
+ Ok(())
+ }
+}
+
+impl FromVariant for Variant {
+ fn from_variant(variant: &Variant) -> Result<Self> {
+ Ok(variant.clone())
+ }
+}
+
+impl FromVariant for syn::Ident {
+ fn from_variant(variant: &Variant) -> Result<Self> {
+ Ok(variant.ident.clone())
+ }
+}
+
+impl FromVariant for Vec<syn::Attribute> {
+ fn from_variant(variant: &Variant) -> Result<Self> {
+ Ok(variant.attrs.clone())
+ }
+}
diff --git a/third_party/rust/darling_core/src/lib.rs b/third_party/rust/darling_core/src/lib.rs
new file mode 100644
index 0000000000..6ce361b481
--- /dev/null
+++ b/third_party/rust/darling_core/src/lib.rs
@@ -0,0 +1,47 @@
+#![recursion_limit = "256"]
+#![cfg_attr(feature = "diagnostics", feature(proc_macro_diagnostic))]
+
+#[macro_use]
+extern crate quote;
+#[macro_use]
+extern crate syn;
+extern crate fnv;
+extern crate ident_case;
+#[cfg(feature = "diagnostics")]
+extern crate proc_macro;
+extern crate proc_macro2;
+#[cfg(feature = "suggestions")]
+extern crate strsim;
+
+#[macro_use]
+mod macros_private;
+#[macro_use]
+mod macros_public;
+
+pub mod ast;
+pub(crate) mod codegen;
+pub mod derive;
+pub mod error;
+mod from_derive_input;
+mod from_field;
+mod from_generic_param;
+mod from_generics;
+mod from_meta;
+mod from_type_param;
+mod from_variant;
+pub(crate) mod options;
+pub mod usage;
+pub mod util;
+
+pub use error::{Error, Result};
+pub use from_derive_input::FromDeriveInput;
+pub use from_field::FromField;
+pub use from_generic_param::FromGenericParam;
+pub use from_generics::FromGenerics;
+pub use from_meta::FromMeta;
+pub use from_type_param::FromTypeParam;
+pub use from_variant::FromVariant;
+
+// Re-export tokenizer
+#[doc(hidden)]
+pub use quote::ToTokens;
diff --git a/third_party/rust/darling_core/src/macros_private.rs b/third_party/rust/darling_core/src/macros_private.rs
new file mode 100644
index 0000000000..65a3cd5750
--- /dev/null
+++ b/third_party/rust/darling_core/src/macros_private.rs
@@ -0,0 +1,12 @@
+macro_rules! quote {
+ ($($tt:tt)*) => {
+ quote_spanned!(::proc_macro2::Span::call_site() => $($tt)*)
+ };
+}
+
+macro_rules! path {
+ ($($path:tt)+) => {
+ parse_quote!($($path)+)
+ //stringify!($($path)+).parse().unwrap()
+ };
+}
diff --git a/third_party/rust/darling_core/src/macros_public.rs b/third_party/rust/darling_core/src/macros_public.rs
new file mode 100644
index 0000000000..a3c5cac98d
--- /dev/null
+++ b/third_party/rust/darling_core/src/macros_public.rs
@@ -0,0 +1,98 @@
+//! Macros that should be exported from both `darling_core` and `darling`.
+//! Note that these are **sym-linked** into the main code, and so cannot declare on items that are exported differently
+//! in `darling_core` vs. `darling`.
+
+/// Generator for `UsesTypeParam` impls that unions the used type parameters of the selected fields.
+///
+/// # Usage
+/// The macro takes the type implementing the trait as the first argument, then a comma-separated list of
+/// fields for the rest of its arguments.
+///
+/// The type of each passed-in field must implement `UsesTypeParams`, or the resulting code won't compile.
+///
+/// ```rust
+/// # extern crate syn;
+/// #
+/// # #[macro_use]
+/// # extern crate darling_core;
+/// #
+/// struct MyField {
+/// ty: syn::Type,
+/// }
+///
+/// uses_type_params!(MyField, ty);
+///
+/// fn main() {
+/// // no test run
+/// }
+/// ```
+///
+/// `darling` cannot derive this trait automatically, as it doesn't know which information extracted from
+/// proc-macro input is meant to constitute "using" the type parameter, but crate consumers should
+/// implement it by hand or using the macro.
+#[macro_export]
+macro_rules! uses_type_params {
+ ($impl_type:ty, $accessor:ident) => {
+ impl $crate::usage::UsesTypeParams for $impl_type {
+ fn uses_type_params<'gen>(
+ &self,
+ options: &$crate::usage::Options,
+ type_set: &'gen $crate::usage::IdentSet
+ ) -> $crate::usage::IdentRefSet<'gen> {
+ self.$accessor.uses_type_params(options, type_set)
+ }
+ }
+ };
+ ($impl_type:ty, $first:ident, $($field:ident),+) => {
+ impl $crate::usage::UsesTypeParams for $impl_type {
+ fn uses_type_params<'gen>(
+ &self,
+ options: &$crate::usage::Options,
+ type_set: &'gen $crate::usage::IdentSet
+ ) -> $crate::usage::IdentRefSet<'gen> {
+ let mut hits = self.$first.uses_type_params(options, type_set);
+ $(
+ hits.extend(self.$field.uses_type_params(options, type_set));
+ )*
+ hits
+ }
+ }
+ };
+}
+
+/// Generator for `UsesLifetimes` impls that unions the used lifetimes of the selected fields.
+///
+/// # Usage
+/// The macro takes the type implementing the trait as the first argument, then a comma-separated list of
+/// fields for the rest of its arguments.
+///
+/// The type of each passed-in field must implement `UsesLifetimes`, or the resulting code won't compile.
+#[macro_export]
+macro_rules! uses_lifetimes {
+ ($impl_type:ty, $accessor:ident) => {
+ impl $crate::usage::UsesLifetimes for $impl_type {
+ fn uses_lifetimes<'gen>(
+ &self,
+ options: &$crate::usage::Options,
+ type_set: &'gen $crate::usage::LifetimeSet
+ ) -> $crate::usage::LifetimeRefSet<'gen> {
+ self.$accessor.uses_lifetimes(options, type_set)
+ }
+ }
+ };
+ ($impl_type:ty, $first:ident, $($field:ident),+) => {
+ impl $crate::usage::UsesLifetimes for $impl_type {
+ fn uses_lifetimes<'gen>(
+ &self,
+ options: &$crate::usage::Options,
+ type_set: &'gen $crate::usage::LifetimeSet
+ ) -> $crate::usage::LifetimeRefSet<'gen> {
+ let mut hits = self.$first.uses_lifetimes(options, type_set);
+ $(
+ hits.extend(self.$field.uses_lifetimes(options, type_set));
+ )*
+ hits
+ }
+ }
+ };
+}
diff --git a/third_party/rust/darling_core/src/options/core.rs b/third_party/rust/darling_core/src/options/core.rs
new file mode 100644
index 0000000000..2e59071a99
--- /dev/null
+++ b/third_party/rust/darling_core/src/options/core.rs
@@ -0,0 +1,154 @@
+use ident_case::RenameRule;
+use syn;
+
+use ast::{Data, Fields, Style};
+use codegen;
+use options::{DefaultExpression, InputField, InputVariant, ParseAttribute, ParseData};
+use util::Flag;
+use {Error, FromMeta, Result};
+
+/// A struct or enum which should have `FromMeta` or `FromDeriveInput` implementations
+/// generated.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Core {
+ /// The type identifier.
+ pub ident: syn::Ident,
+
+ /// The type's generics. If the type does not use any generics, this will
+ /// be an empty instance.
+ pub generics: syn::Generics,
+
+ /// Controls whether missing properties should cause errors or should be filled by
+ /// the result of a function call. This can be overridden at the field level.
+ pub default: Option<DefaultExpression>,
+
+ /// The rule that should be used to rename all fields/variants in the container.
+ pub rename_rule: RenameRule,
+
+ /// An infallible function with the signature `FnOnce(T) -> T` which will be called after the
+ /// target instance is successfully constructed.
+ pub map: Option<syn::Path>,
+
+ /// The body of the _deriving_ type.
+ pub data: Data<InputVariant, InputField>,
+
+ /// The custom bound to apply to the generated impl
+ pub bound: Option<Vec<syn::WherePredicate>>,
+
+ /// Whether or not unknown fields should produce an error at compilation time.
+ pub allow_unknown_fields: Flag,
+}
+
+impl Core {
+ /// Partially initializes `Core` by reading the identity, generics, and body shape.
+ pub fn start(di: &syn::DeriveInput) -> Self {
+ Core {
+ ident: di.ident.clone(),
+ generics: di.generics.clone(),
+ data: Data::empty_from(&di.data),
+ default: Default::default(),
+ // See https://github.com/TedDriggs/darling/issues/10: We default to snake_case
+ // for enums to help authors produce more idiomatic APIs.
+ rename_rule: if let syn::Data::Enum(_) = di.data {
+ RenameRule::SnakeCase
+ } else {
+ Default::default()
+ },
+ map: Default::default(),
+ bound: Default::default(),
+ allow_unknown_fields: Default::default(),
+ }
+ }
+
+ fn as_codegen_default<'a>(&'a self) -> Option<codegen::DefaultExpression<'a>> {
+ self.default.as_ref().map(|expr| match *expr {
+ DefaultExpression::Explicit(ref path) => codegen::DefaultExpression::Explicit(path),
+ DefaultExpression::Inherit | DefaultExpression::Trait => {
+ codegen::DefaultExpression::Trait
+ }
+ })
+ }
+}
+
+impl ParseAttribute for Core {
+ fn parse_nested(&mut self, mi: &syn::Meta) -> Result<()> {
+ let path = mi.path();
+
+ if path.is_ident("default") {
+ if self.default.is_some() {
+ return Err(Error::duplicate_field("default").with_span(mi))
+ }
+
+ self.default = FromMeta::from_meta(mi)?;
+ } else if path.is_ident("rename_all") {
+ // WARNING: This may have been set based on body shape previously,
+ // so an overwrite may be permissible.
+ self.rename_rule = FromMeta::from_meta(mi)?;
+ } else if path.is_ident("map") {
+ if self.map.is_some() {
+ return Err(Error::duplicate_field("map").with_span(mi))
+ }
+
+ self.map = FromMeta::from_meta(mi)?;
+ } else if path.is_ident("bound") {
+ self.bound = FromMeta::from_meta(mi)?;
+ } else if path.is_ident("allow_unknown_fields") {
+ if self.allow_unknown_fields.is_some() {
+ return Err(Error::duplicate_field("allow_unknown_fields").with_span(mi))
+ }
+
+ self.allow_unknown_fields = FromMeta::from_meta(mi)?;
+ } else {
+ return Err(Error::unknown_field_path(&path).with_span(mi))
+ }
+
+ Ok(())
+ }
+}
+
+impl ParseData for Core {
+ fn parse_variant(&mut self, variant: &syn::Variant) -> Result<()> {
+ let v = InputVariant::from_variant(variant, Some(&self))?;
+
+ match self.data {
+ Data::Enum(ref mut variants) => {
+ variants.push(v);
+ Ok(())
+ }
+ Data::Struct(_) => panic!("Core::parse_variant should never be called for a struct"),
+ }
+ }
+
+ fn parse_field(&mut self, field: &syn::Field) -> Result<()> {
+ let f = InputField::from_field(field, Some(&self))?;
+
+ match self.data {
+ Data::Struct(Fields {
+ style: Style::Unit, ..
+ }) => panic!("Core::parse_field should not be called on unit"),
+ Data::Struct(Fields { ref mut fields, .. }) => {
+ fields.push(f);
+ Ok(())
+ }
+ Data::Enum(_) => panic!("Core::parse_field should never be called for an enum"),
+ }
+ }
+}
+
+impl<'a> From<&'a Core> for codegen::TraitImpl<'a> {
+ fn from(v: &'a Core) -> Self {
+ codegen::TraitImpl {
+ ident: &v.ident,
+ generics: &v.generics,
+ data: v
+ .data
+ .as_ref()
+ .map_struct_fields(InputField::as_codegen_field)
+ .map_enum_variants(|variant| variant.as_codegen_variant(&v.ident)),
+ default: v.as_codegen_default(),
+ map: v.map.as_ref(),
+ bound: v.bound.as_ref().map(|i| i.as_slice()),
+ allow_unknown_fields: v.allow_unknown_fields.into(),
+ }
+ }
+}
diff --git a/third_party/rust/darling_core/src/options/forward_attrs.rs b/third_party/rust/darling_core/src/options/forward_attrs.rs
new file mode 100644
index 0000000000..eccdb78102
--- /dev/null
+++ b/third_party/rust/darling_core/src/options/forward_attrs.rs
@@ -0,0 +1,31 @@
+use syn::NestedMeta;
+
+use util::PathList;
+use {FromMeta, Result};
+
+/// A rule about which attributes to forward to the generated struct.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum ForwardAttrs {
+ All,
+ Only(PathList),
+}
+
+impl ForwardAttrs {
+ /// Returns `true` if this will not forward any attributes.
+ pub fn is_empty(&self) -> bool {
+ match *self {
+ ForwardAttrs::All => false,
+ ForwardAttrs::Only(ref list) => list.is_empty(),
+ }
+ }
+}
+
+impl FromMeta for ForwardAttrs {
+ fn from_word() -> Result<Self> {
+ Ok(ForwardAttrs::All)
+ }
+
+ fn from_list(nested: &[NestedMeta]) -> Result<Self> {
+ Ok(ForwardAttrs::Only(PathList::from_list(nested)?))
+ }
+}
diff --git a/third_party/rust/darling_core/src/options/from_derive.rs b/third_party/rust/darling_core/src/options/from_derive.rs
new file mode 100644
index 0000000000..6c252e68a4
--- /dev/null
+++ b/third_party/rust/darling_core/src/options/from_derive.rs
@@ -0,0 +1,100 @@
+use proc_macro2::TokenStream;
+use quote::ToTokens;
+use syn::{self, Ident};
+
+use codegen::FromDeriveInputImpl;
+use options::{OuterFrom, ParseAttribute, ParseData, Shape};
+use {FromMeta, Result};
+
+#[derive(Debug)]
+pub struct FdiOptions {
+ pub base: OuterFrom,
+
+ /// The field on the target struct which should receive the type visibility, if any.
+ pub vis: Option<Ident>,
+
+ /// The field on the target struct which should receive the type generics, if any.
+ pub generics: Option<Ident>,
+
+ pub data: Option<Ident>,
+
+ pub supports: Option<Shape>,
+}
+
+impl FdiOptions {
+ pub fn new(di: &syn::DeriveInput) -> Result<Self> {
+ (FdiOptions {
+ base: OuterFrom::start(di),
+ vis: Default::default(),
+ generics: Default::default(),
+ data: Default::default(),
+ supports: Default::default(),
+ })
+ .parse_attributes(&di.attrs)?
+ .parse_body(&di.data)
+ }
+}
+
+impl ParseAttribute for FdiOptions {
+ fn parse_nested(&mut self, mi: &syn::Meta) -> Result<()> {
+ if mi.path().is_ident("supports") {
+ self.supports = FromMeta::from_meta(mi)?;
+ Ok(())
+ } else {
+ self.base.parse_nested(mi)
+ }
+ }
+}
+
+impl ParseData for FdiOptions {
+ fn parse_variant(&mut self, variant: &syn::Variant) -> Result<()> {
+ self.base.parse_variant(variant)
+ }
+
+ fn parse_field(&mut self, field: &syn::Field) -> Result<()> {
+ match field
+ .ident
+ .as_ref()
+ .map(|v| v.to_string())
+ .as_ref()
+ .map(|v| v.as_str())
+ {
+ Some("vis") => {
+ self.vis = field.ident.clone();
+ Ok(())
+ }
+ Some("data") => {
+ self.data = field.ident.clone();
+ Ok(())
+ }
+ Some("generics") => {
+ self.generics = field.ident.clone();
+ Ok(())
+ }
+ _ => self.base.parse_field(field),
+ }
+ }
+}
+
+impl<'a> From<&'a FdiOptions> for FromDeriveInputImpl<'a> {
+ fn from(v: &'a FdiOptions) -> Self {
+ FromDeriveInputImpl {
+ base: (&v.base.container).into(),
+ attr_names: &v.base.attr_names,
+ from_ident: v.base.from_ident,
+ ident: v.base.ident.as_ref(),
+ vis: v.vis.as_ref(),
+ data: v.data.as_ref(),
+ generics: v.generics.as_ref(),
+ attrs: v.base.attrs.as_ref(),
+ forward_attrs: v.base.forward_attrs.as_ref(),
+ supports: v.supports.as_ref(),
+ }
+ }
+}
+
+impl ToTokens for FdiOptions {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ FromDeriveInputImpl::from(self).to_tokens(tokens)
+ }
+}
diff --git a/third_party/rust/darling_core/src/options/from_field.rs b/third_party/rust/darling_core/src/options/from_field.rs
new file mode 100644
index 0000000000..266d1fa043
--- /dev/null
+++ b/third_party/rust/darling_core/src/options/from_field.rs
@@ -0,0 +1,79 @@
+use proc_macro2::TokenStream;
+use quote::ToTokens;
+use syn::{self, Ident};
+
+use codegen::FromFieldImpl;
+use options::{OuterFrom, ParseAttribute, ParseData};
+use Result;
+
+#[derive(Debug)]
+pub struct FromFieldOptions {
+ pub base: OuterFrom,
+ pub vis: Option<Ident>,
+ pub ty: Option<Ident>,
+}
+
+impl FromFieldOptions {
+ pub fn new(di: &syn::DeriveInput) -> Result<Self> {
+ (FromFieldOptions {
+ base: OuterFrom::start(di),
+ vis: Default::default(),
+ ty: Default::default(),
+ })
+ .parse_attributes(&di.attrs)?
+ .parse_body(&di.data)
+ }
+}
+
+impl ParseAttribute for FromFieldOptions {
+ fn parse_nested(&mut self, mi: &syn::Meta) -> Result<()> {
+ self.base.parse_nested(mi)
+ }
+}
+
+impl ParseData for FromFieldOptions {
+ fn parse_variant(&mut self, variant: &syn::Variant) -> Result<()> {
+ self.base.parse_variant(variant)
+ }
+
+ fn parse_field(&mut self, field: &syn::Field) -> Result<()> {
+ match field
+ .ident
+ .as_ref()
+ .map(|v| v.to_string())
+ .as_ref()
+ .map(|v| v.as_str())
+ {
+ Some("vis") => {
+ self.vis = field.ident.clone();
+ Ok(())
+ }
+ Some("ty") => {
+ self.ty = field.ident.clone();
+ Ok(())
+ }
+ _ => self.base.parse_field(field),
+ }
+ }
+}
+
+impl<'a> From<&'a FromFieldOptions> for FromFieldImpl<'a> {
+ fn from(v: &'a FromFieldOptions) -> Self {
+ FromFieldImpl {
+ ident: v.base.ident.as_ref(),
+ vis: v.vis.as_ref(),
+ ty: v.ty.as_ref(),
+ attrs: v.base.attrs.as_ref(),
+ base: (&v.base.container).into(),
+ attr_names: &v.base.attr_names,
+ forward_attrs: v.base.forward_attrs.as_ref(),
+ from_ident: v.base.from_ident,
+ }
+ }
+}
+
+impl ToTokens for FromFieldOptions {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ FromFieldImpl::from(self).to_tokens(tokens)
+ }
+}
diff --git a/third_party/rust/darling_core/src/options/from_meta.rs b/third_party/rust/darling_core/src/options/from_meta.rs
new file mode 100644
index 0000000000..d9088562a5
--- /dev/null
+++ b/third_party/rust/darling_core/src/options/from_meta.rs
@@ -0,0 +1,51 @@
+use proc_macro2::TokenStream;
+use quote::ToTokens;
+use syn;
+
+use codegen::FromMetaImpl;
+use options::{Core, ParseAttribute, ParseData};
+use Result;
+
+pub struct FromMetaOptions {
+ base: Core,
+}
+
+impl FromMetaOptions {
+ pub fn new(di: &syn::DeriveInput) -> Result<Self> {
+ (FromMetaOptions {
+ base: Core::start(di),
+ })
+ .parse_attributes(&di.attrs)?
+ .parse_body(&di.data)
+ }
+}
+
+impl ParseAttribute for FromMetaOptions {
+ fn parse_nested(&mut self, mi: &syn::Meta) -> Result<()> {
+ self.base.parse_nested(mi)
+ }
+}
+
+impl ParseData for FromMetaOptions {
+ fn parse_variant(&mut self, variant: &syn::Variant) -> Result<()> {
+ self.base.parse_variant(variant)
+ }
+
+ fn parse_field(&mut self, field: &syn::Field) -> Result<()> {
+ self.base.parse_field(field)
+ }
+}
+
+impl<'a> From<&'a FromMetaOptions> for FromMetaImpl<'a> {
+ fn from(v: &'a FromMetaOptions) -> Self {
+ FromMetaImpl {
+ base: (&v.base).into(),
+ }
+ }
+}
+
+impl ToTokens for FromMetaOptions {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ FromMetaImpl::from(self).to_tokens(tokens)
+ }
+}
diff --git a/third_party/rust/darling_core/src/options/from_type_param.rs b/third_party/rust/darling_core/src/options/from_type_param.rs
new file mode 100644
index 0000000000..701ca1b83e
--- /dev/null
+++ b/third_party/rust/darling_core/src/options/from_type_param.rs
@@ -0,0 +1,79 @@
+use proc_macro2::TokenStream;
+use quote::ToTokens;
+use syn::{self, Ident};
+
+use codegen::FromTypeParamImpl;
+use options::{OuterFrom, ParseAttribute, ParseData};
+use Result;
+
+#[derive(Debug)]
+pub struct FromTypeParamOptions {
+ pub base: OuterFrom,
+ pub bounds: Option<Ident>,
+ pub default: Option<Ident>,
+}
+
+impl FromTypeParamOptions {
+ pub fn new(di: &syn::DeriveInput) -> Result<Self> {
+ (FromTypeParamOptions {
+ base: OuterFrom::start(di),
+ bounds: None,
+ default: None,
+ })
+ .parse_attributes(&di.attrs)?
+ .parse_body(&di.data)
+ }
+}
+
+impl ParseAttribute for FromTypeParamOptions {
+ fn parse_nested(&mut self, mi: &syn::Meta) -> Result<()> {
+ self.base.parse_nested(mi)
+ }
+}
+
+impl ParseData for FromTypeParamOptions {
+ fn parse_variant(&mut self, variant: &syn::Variant) -> Result<()> {
+ self.base.parse_variant(variant)
+ }
+
+ fn parse_field(&mut self, field: &syn::Field) -> Result<()> {
+ match field
+ .ident
+ .as_ref()
+ .map(|v| v.to_string())
+ .as_ref()
+ .map(|v| v.as_str())
+ {
+ Some("bounds") => {
+ self.bounds = field.ident.clone();
+ Ok(())
+ }
+ Some("default") => {
+ self.default = field.ident.clone();
+ Ok(())
+ }
+ _ => self.base.parse_field(field),
+ }
+ }
+}
+
+impl<'a> From<&'a FromTypeParamOptions> for FromTypeParamImpl<'a> {
+ fn from(v: &'a FromTypeParamOptions) -> Self {
+ FromTypeParamImpl {
+ base: (&v.base.container).into(),
+ ident: v.base.ident.as_ref(),
+ attrs: v.base.attrs.as_ref(),
+ bounds: v.bounds.as_ref(),
+ default: v.default.as_ref(),
+ attr_names: &v.base.attr_names,
+ forward_attrs: v.base.forward_attrs.as_ref(),
+ from_ident: v.base.from_ident,
+ }
+ }
+}
+
+impl ToTokens for FromTypeParamOptions {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ FromTypeParamImpl::from(self).to_tokens(tokens)
+ }
+}
diff --git a/third_party/rust/darling_core/src/options/from_variant.rs b/third_party/rust/darling_core/src/options/from_variant.rs
new file mode 100644
index 0000000000..c5ffe5d0e3
--- /dev/null
+++ b/third_party/rust/darling_core/src/options/from_variant.rs
@@ -0,0 +1,76 @@
+use proc_macro2::TokenStream;
+use quote::ToTokens;
+use syn::{DeriveInput, Field, Ident, Meta};
+
+use codegen::FromVariantImpl;
+use options::{DataShape, OuterFrom, ParseAttribute, ParseData};
+use {FromMeta, Result};
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct FromVariantOptions {
+ pub base: OuterFrom,
+ pub fields: Option<Ident>,
+ pub supports: Option<DataShape>,
+}
+
+impl FromVariantOptions {
+ pub fn new(di: &DeriveInput) -> Result<Self> {
+ (FromVariantOptions {
+ base: OuterFrom::start(di),
+ fields: Default::default(),
+ supports: Default::default(),
+ })
+ .parse_attributes(&di.attrs)?
+ .parse_body(&di.data)
+ }
+}
+
+impl<'a> From<&'a FromVariantOptions> for FromVariantImpl<'a> {
+ fn from(v: &'a FromVariantOptions) -> Self {
+ FromVariantImpl {
+ base: (&v.base.container).into(),
+ ident: v.base.ident.as_ref(),
+ fields: v.fields.as_ref(),
+ attrs: v.base.attrs.as_ref(),
+ attr_names: &v.base.attr_names,
+ forward_attrs: v.base.forward_attrs.as_ref(),
+ from_ident: v.base.from_ident,
+ supports: v.supports.as_ref(),
+ }
+ }
+}
+
+impl ParseAttribute for FromVariantOptions {
+ fn parse_nested(&mut self, mi: &Meta) -> Result<()> {
+ if mi.path().is_ident("supports") {
+ self.supports = FromMeta::from_meta(mi)?;
+ Ok(())
+ } else {
+ self.base.parse_nested(mi)
+ }
+ }
+}
+
+impl ParseData for FromVariantOptions {
+ fn parse_field(&mut self, field: &Field) -> Result<()> {
+ match field
+ .ident
+ .as_ref()
+ .map(|v| v.to_string())
+ .as_ref()
+ .map(|v| v.as_str())
+ {
+ Some("fields") => {
+ self.fields = field.ident.clone();
+ Ok(())
+ }
+ _ => self.base.parse_field(field),
+ }
+ }
+}
+
+impl ToTokens for FromVariantOptions {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ FromVariantImpl::from(self).to_tokens(tokens)
+ }
+}
diff --git a/third_party/rust/darling_core/src/options/input_field.rs b/third_party/rust/darling_core/src/options/input_field.rs
new file mode 100644
index 0000000000..1b1905a6f3
--- /dev/null
+++ b/third_party/rust/darling_core/src/options/input_field.rs
@@ -0,0 +1,138 @@
+use std::borrow::Cow;
+
+use syn;
+
+use codegen;
+use options::{Core, DefaultExpression, ParseAttribute};
+use {Error, FromMeta, Result};
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct InputField {
+ pub ident: syn::Ident,
+ pub attr_name: Option<String>,
+ pub ty: syn::Type,
+ pub default: Option<DefaultExpression>,
+ pub with: Option<syn::Path>,
+
+ /// If `true`, generated code will not look for this field in the input meta item,
+ /// instead always falling back to either `InputField::default` or `Default::default`.
+ pub skip: bool,
+ pub map: Option<syn::Path>,
+ pub multiple: bool,
+}
+
+impl InputField {
+ /// Generate a view into this field that can be used for code generation.
+ pub fn as_codegen_field<'a>(&'a self) -> codegen::Field<'a> {
+ codegen::Field {
+ ident: &self.ident,
+ name_in_attr: self
+ .attr_name
+ .as_ref()
+ .map_or_else(|| Cow::Owned(self.ident.to_string()), Cow::Borrowed),
+ ty: &self.ty,
+ default_expression: self.as_codegen_default(),
+ with_path: self.with.as_ref().map_or_else(
+ || Cow::Owned(parse_quote!(::darling::FromMeta::from_meta)),
+ Cow::Borrowed,
+ ),
+ skip: self.skip,
+ map: self.map.as_ref(),
+ multiple: self.multiple,
+ }
+ }
+
+ /// Generate a codegen::DefaultExpression for this field. This requires the field name
+ /// in the `Inherit` case.
+ fn as_codegen_default<'a>(&'a self) -> Option<codegen::DefaultExpression<'a>> {
+ self.default.as_ref().map(|expr| match *expr {
+ DefaultExpression::Explicit(ref path) => codegen::DefaultExpression::Explicit(path),
+ DefaultExpression::Inherit => codegen::DefaultExpression::Inherit(&self.ident),
+ DefaultExpression::Trait => codegen::DefaultExpression::Trait,
+ })
+ }
+
+ fn new(ident: syn::Ident, ty: syn::Type) -> Self {
+ InputField {
+ ident,
+ ty,
+ attr_name: None,
+ default: None,
+ with: None,
+ skip: false,
+ map: Default::default(),
+ multiple: false,
+ }
+ }
+
+ pub fn from_field(f: &syn::Field, parent: Option<&Core>) -> Result<Self> {
+ let ident = f
+ .ident
+ .clone()
+ .unwrap_or_else(|| syn::Ident::new("__unnamed", ::proc_macro2::Span::call_site()));
+ let ty = f.ty.clone();
+ let base = Self::new(ident, ty).parse_attributes(&f.attrs)?;
+
+ if let Some(container) = parent {
+ base.with_inherited(container)
+ } else {
+ Ok(base)
+ }
+ }
+
+ /// Apply inherited settings from the container. This is done _after_ parsing
+ /// to ensure deference to explicit field-level settings.
+ fn with_inherited(mut self, parent: &Core) -> Result<Self> {
+ // explicit renamings take precedence over rename rules on the container,
+ // but in the absence of an explicit name we apply the rule.
+ if self.attr_name.is_none() {
+ self.attr_name = Some(parent.rename_rule.apply_to_field(self.ident.to_string()));
+ }
+
+ // Determine the default expression for this field, based on three pieces of information:
+ // 1. Will we look for this field in the attribute?
+ // 1. Is there a locally-defined default?
+ // 1. Did the parent define a default?
+ self.default = match (self.skip, self.default.is_some(), parent.default.is_some()) {
+ // If we have a default, use it.
+ (_, true, _) => self.default,
+
+ // If there isn't an explicit default but the struct sets a default, we'll
+ // inherit from that.
+ (_, false, true) => Some(DefaultExpression::Inherit),
+
+ // If we're skipping the field and no defaults have been expressed then we should
+ // use the ::darling::export::Default trait.
+ (true, false, false) => Some(DefaultExpression::Trait),
+
+ // If we don't have or need a default, then leave it blank.
+ (false, false, false) => None,
+ };
+
+ Ok(self)
+ }
+}
+
+impl ParseAttribute for InputField {
+ fn parse_nested(&mut self, mi: &syn::Meta) -> Result<()> {
+ let path = mi.path();
+
+ if path.is_ident("rename") {
+ self.attr_name = FromMeta::from_meta(mi)?;
+ } else if path.is_ident("default") {
+ self.default = FromMeta::from_meta(mi)?;
+ } else if path.is_ident("with") {
+ self.with = Some(FromMeta::from_meta(mi)?);
+ } else if path.is_ident("skip") {
+ self.skip = FromMeta::from_meta(mi)?;
+ } else if path.is_ident("map") {
+ self.map = Some(FromMeta::from_meta(mi)?);
+ } else if path.is_ident("multiple") {
+ self.multiple = FromMeta::from_meta(mi)?;
+ } else {
+ return Err(Error::unknown_field_path(path).with_span(mi))
+ }
+
+ Ok(())
+ }
+}
diff --git a/third_party/rust/darling_core/src/options/input_variant.rs b/third_party/rust/darling_core/src/options/input_variant.rs
new file mode 100644
index 0000000000..08398fe687
--- /dev/null
+++ b/third_party/rust/darling_core/src/options/input_variant.rs
@@ -0,0 +1,98 @@
+use std::borrow::Cow;
+
+use syn;
+
+use ast::Fields;
+use codegen;
+use options::{Core, InputField, ParseAttribute};
+use {Error, FromMeta, Result};
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct InputVariant {
+ ident: syn::Ident,
+ attr_name: Option<String>,
+ data: Fields<InputField>,
+ skip: bool,
+ /// Whether or not unknown fields are acceptable in this
+ allow_unknown_fields: Option<bool>,
+}
+
+impl InputVariant {
+ pub fn as_codegen_variant<'a>(&'a self, ty_ident: &'a syn::Ident) -> codegen::Variant<'a> {
+ codegen::Variant {
+ ty_ident,
+ variant_ident: &self.ident,
+ name_in_attr: self
+ .attr_name
+ .as_ref()
+ .map_or_else(|| Cow::Owned(self.ident.to_string()), Cow::Borrowed),
+ data: self.data.as_ref().map(InputField::as_codegen_field),
+ skip: self.skip,
+ allow_unknown_fields: self.allow_unknown_fields.unwrap_or_default(),
+ }
+ }
+
+ pub fn from_variant(v: &syn::Variant, parent: Option<&Core>) -> Result<Self> {
+ let mut starter = (InputVariant {
+ ident: v.ident.clone(),
+ attr_name: Default::default(),
+ data: Fields::empty_from(&v.fields),
+ skip: Default::default(),
+ allow_unknown_fields: None,
+ })
+ .parse_attributes(&v.attrs)?;
+
+ starter.data.fields = match v.fields {
+ syn::Fields::Unit => vec![],
+ syn::Fields::Unnamed(ref fields) => {
+ let mut items = Vec::with_capacity(fields.unnamed.len());
+ for item in &fields.unnamed {
+ items.push(InputField::from_field(item, parent)?);
+ }
+
+ items
+ }
+ syn::Fields::Named(ref fields) => {
+ let mut items = Vec::with_capacity(fields.named.len());
+ for item in &fields.named {
+ items.push(InputField::from_field(item, parent)?);
+ }
+
+ items
+ }
+ };
+
+ Ok(if let Some(p) = parent {
+ starter.with_inherited(p)
+ } else {
+ starter
+ })
+ }
+
+ fn with_inherited(mut self, parent: &Core) -> Self {
+ if self.attr_name.is_none() {
+ self.attr_name = Some(parent.rename_rule.apply_to_variant(self.ident.to_string()));
+ }
+
+ if self.allow_unknown_fields.is_none() {
+ self.allow_unknown_fields = Some(parent.allow_unknown_fields.is_some());
+ }
+
+ self
+ }
+}
+
+impl ParseAttribute for InputVariant {
+ fn parse_nested(&mut self, mi: &syn::Meta) -> Result<()> {
+ let path = mi.path();
+ if path.is_ident("rename") {
+ self.attr_name = FromMeta::from_meta(mi)?;
+ Ok(())
+ } else if path.is_ident("skip") {
+ self.skip = FromMeta::from_meta(mi)?;
+ Ok(())
+ } else {
+ Err(Error::unknown_field_path(&path).with_span(mi))
+ }
+ }
+}
diff --git a/third_party/rust/darling_core/src/options/mod.rs b/third_party/rust/darling_core/src/options/mod.rs
new file mode 100644
index 0000000000..a884f5afba
--- /dev/null
+++ b/third_party/rust/darling_core/src/options/mod.rs
@@ -0,0 +1,154 @@
+use syn;
+
+use {Error, FromMeta, Result};
+
+mod core;
+mod forward_attrs;
+mod from_derive;
+mod from_field;
+mod from_meta;
+mod from_type_param;
+mod from_variant;
+mod input_field;
+mod input_variant;
+mod outer_from;
+mod shape;
+
+pub use self::core::Core;
+pub use self::forward_attrs::ForwardAttrs;
+pub use self::from_derive::FdiOptions;
+pub use self::from_field::FromFieldOptions;
+pub use self::from_meta::FromMetaOptions;
+pub use self::from_type_param::FromTypeParamOptions;
+pub use self::from_variant::FromVariantOptions;
+pub use self::input_field::InputField;
+pub use self::input_variant::InputVariant;
+pub use self::outer_from::OuterFrom;
+pub use self::shape::{DataShape, Shape};
+
+/// A default/fallback expression encountered in attributes during parsing.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum DefaultExpression {
+ /// The value should be taken from the `default` instance of the containing struct.
+ /// This is not valid in container options.
+ Inherit,
+ Explicit(syn::Path),
+ Trait,
+}
+
+#[doc(hidden)]
+impl FromMeta for DefaultExpression {
+ fn from_word() -> Result<Self> {
+ Ok(DefaultExpression::Trait)
+ }
+
+ fn from_value(value: &syn::Lit) -> Result<Self> {
+ syn::Path::from_value(value).map(DefaultExpression::Explicit)
+ }
+}
+
+/// Run a parsing task, and if it produces an error push it into `$errors`
+macro_rules! collect_error {
+ ($errors:ident, $task:expr) => {
+ if let Err(e) = $task {
+ $errors.push(e);
+ }
+ };
+}
+
+/// Middleware for extracting attribute values. Implementers are expected to override
+/// `parse_nested` so they can apply individual items to themselves, while `parse_attributes`
+/// is responsible for looping through distinct outer attributes and collecting errors.
+pub trait ParseAttribute: Sized {
+ fn parse_attributes(mut self, attrs: &[syn::Attribute]) -> Result<Self> {
+ let mut errors = Vec::new();
+ for attr in attrs {
+ if attr.path == parse_quote!(darling) {
+ collect_error!(errors, parse_attr(attr, &mut self));
+ }
+ }
+
+ if !errors.is_empty() {
+ Err(Error::multiple(errors))
+ } else {
+ Ok(self)
+ }
+ }
+
+ /// Read a meta-item, and apply its values to the current instance.
+ fn parse_nested(&mut self, mi: &syn::Meta) -> Result<()>;
+}
+
+fn parse_attr<T: ParseAttribute>(attr: &syn::Attribute, target: &mut T) -> Result<()> {
+ let mut errors = Vec::new();
+ match attr.parse_meta().ok() {
+ Some(syn::Meta::List(data)) => {
+ for item in data.nested {
+ if let syn::NestedMeta::Meta(ref mi) = item {
+ collect_error!(errors, target.parse_nested(mi));
+ } else {
+ panic!("Wasn't able to parse: `{:?}`", item);
+ }
+ }
+
+ if !errors.is_empty() {
+ Err(Error::multiple(errors))
+ } else {
+ Ok(())
+ }
+ }
+ Some(ref item) => panic!("Wasn't able to parse: `{:?}`", item),
+ None => panic!("Unable to parse {:?}", attr),
+ }
+}
+
+/// Middleware for extracting values from the body of the derive input. Implementers are
+/// expected to override `parse_field` or `parse_variant` as appropriate for their use-case,
+/// while `parse_body` dispatches to the appropriate methods and handles error collection.
+pub trait ParseData: Sized {
+ fn parse_body(mut self, body: &syn::Data) -> Result<Self> {
+ use syn::{Data, Fields};
+
+ let mut errors = Vec::new();
+
+ match *body {
+ Data::Struct(ref data) => match data.fields {
+ Fields::Unit => {}
+ Fields::Named(ref fields) => {
+ for field in &fields.named {
+ collect_error!(errors, self.parse_field(field));
+ }
+ }
+ Fields::Unnamed(ref fields) => {
+ for field in &fields.unnamed {
+ collect_error!(errors, self.parse_field(field));
+ }
+ }
+ },
+ Data::Enum(ref data) => {
+ for variant in &data.variants {
+ collect_error!(errors, self.parse_variant(variant));
+ }
+ }
+ Data::Union(_) => unreachable!(),
+ };
+
+ if !errors.is_empty() {
+ Err(Error::multiple(errors))
+ } else {
+ Ok(self)
+ }
+ }
+
+ /// Apply the next found variant to the object, returning an error
+ /// if parsing goes wrong.
+ fn parse_variant(&mut self, variant: &syn::Variant) -> Result<()> {
+ Err(Error::unsupported_format("enum variant").with_span(variant))
+ }
+
+ /// Apply the next found struct field to the object, returning an error
+ /// if parsing goes wrong.
+ fn parse_field(&mut self, field: &syn::Field) -> Result<()> {
+ Err(Error::unsupported_format("struct field").with_span(field))
+ }
+}
diff --git a/third_party/rust/darling_core/src/options/outer_from.rs b/third_party/rust/darling_core/src/options/outer_from.rs
new file mode 100644
index 0000000000..ca8f1de684
--- /dev/null
+++ b/third_party/rust/darling_core/src/options/outer_from.rs
@@ -0,0 +1,82 @@
+use syn::{self, Field, Ident, Meta};
+
+use options::{Core, DefaultExpression, ForwardAttrs, ParseAttribute, ParseData};
+use util::PathList;
+use {FromMeta, Result};
+
+/// Reusable base for `FromDeriveInput`, `FromVariant`, `FromField`, and other top-level
+/// `From*` traits.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct OuterFrom {
+ /// The field on the target struct which should receive the type identifier, if any.
+ pub ident: Option<Ident>,
+
+ /// The field on the target struct which should receive the type attributes, if any.
+ pub attrs: Option<Ident>,
+
+ pub container: Core,
+
+ /// The attribute names that should be searched.
+ pub attr_names: PathList,
+
+ /// The attribute names that should be forwarded. The presence of the word with no additional
+ /// filtering will cause _all_ attributes to be cloned and exposed to the struct after parsing.
+ pub forward_attrs: Option<ForwardAttrs>,
+
+ /// Whether or not the container can be made through conversion from the type `Ident`.
+ pub from_ident: bool,
+}
+
+impl OuterFrom {
+ pub fn start(di: &syn::DeriveInput) -> Self {
+ OuterFrom {
+ container: Core::start(di),
+ attrs: Default::default(),
+ ident: Default::default(),
+ attr_names: Default::default(),
+ forward_attrs: Default::default(),
+ from_ident: Default::default(),
+ }
+ }
+}
+
+impl ParseAttribute for OuterFrom {
+ fn parse_nested(&mut self, mi: &Meta) -> Result<()> {
+ let path = mi.path();
+ if path.is_ident("attributes") {
+ self.attr_names = FromMeta::from_meta(mi)?;
+ } else if path.is_ident("forward_attrs") {
+ self.forward_attrs = FromMeta::from_meta(mi)?;
+ } else if path.is_ident("from_ident") {
+ // HACK: Declaring that a default is present will cause fields to
+ // generate correct code, but control flow isn't that obvious.
+ self.container.default = Some(DefaultExpression::Trait);
+ self.from_ident = true;
+ } else {
+ return self.container.parse_nested(mi)
+ }
+ Ok(())
+ }
+}
+
+impl ParseData for OuterFrom {
+ fn parse_field(&mut self, field: &Field) -> Result<()> {
+ match field
+ .ident
+ .as_ref()
+ .map(|v| v.to_string())
+ .as_ref()
+ .map(|v| v.as_str())
+ {
+ Some("ident") => {
+ self.ident = field.ident.clone();
+ Ok(())
+ }
+ Some("attrs") => {
+ self.attrs = field.ident.clone();
+ Ok(())
+ }
+ _ => self.container.parse_field(field),
+ }
+ }
+}
diff --git a/third_party/rust/darling_core/src/options/shape.rs b/third_party/rust/darling_core/src/options/shape.rs
new file mode 100644
index 0000000000..4cb3f7a9ed
--- /dev/null
+++ b/third_party/rust/darling_core/src/options/shape.rs
@@ -0,0 +1,268 @@
+//! Types for "shape" validation. This allows types deriving `FromDeriveInput` etc. to declare
+//! that they only work on - for example - structs with named fields, or newtype enum variants.
+
+use proc_macro2::TokenStream;
+use quote::{ToTokens, TokenStreamExt};
+use syn::{Meta, NestedMeta};
+
+use {Error, FromMeta, Result};
+
+/// Receiver struct for shape validation. Shape validation allows a deriving type
+/// to declare that it only accepts - for example - named structs, or newtype enum
+/// variants.
+///
+/// # Usage
+/// Because `Shape` implements `FromMeta`, the name of the field where it appears is
+/// controlled by the struct that declares `Shape` as a member. That field name is
+/// shown as `ignore` below.
+///
+/// ```rust,ignore
+/// #[ignore(any, struct_named, enum_newtype)]
+/// ```
+#[derive(Debug, Clone)]
+pub struct Shape {
+ enum_values: DataShape,
+ struct_values: DataShape,
+ any: bool,
+}
+
+impl Default for Shape {
+ fn default() -> Self {
+ Shape {
+ enum_values: DataShape::new("enum_"),
+ struct_values: DataShape::new("struct_"),
+ any: Default::default(),
+ }
+ }
+}
+
+impl FromMeta for Shape {
+ fn from_list(items: &[NestedMeta]) -> Result<Self> {
+ let mut new = Shape::default();
+ for item in items {
+ if let NestedMeta::Meta(Meta::Path(ref path)) = *item {
+ let ident = &path.segments.first().unwrap().ident;
+ let word = ident.to_string();
+ if word == "any" {
+ new.any = true;
+ } else if word.starts_with("enum_") {
+ new.enum_values
+ .set_word(&word)
+ .map_err(|e| e.with_span(&ident))?;
+ } else if word.starts_with("struct_") {
+ new.struct_values
+ .set_word(&word)
+ .map_err(|e| e.with_span(&ident))?;
+ } else {
+ return Err(Error::unknown_value(&word).with_span(&ident));
+ }
+ } else {
+ return Err(Error::unsupported_format("non-word").with_span(item));
+ }
+ }
+
+ Ok(new)
+ }
+}
+
+impl ToTokens for Shape {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ let fn_body = if self.any {
+ quote!(::darling::export::Ok(()))
+ } else {
+ let en = &self.enum_values;
+ let st = &self.struct_values;
+ quote! {
+ match *__body {
+ ::syn::Data::Enum(ref data) => {
+ fn validate_variant(data: &::syn::Fields) -> ::darling::Result<()> {
+ #en
+ }
+
+ for variant in &data.variants {
+ validate_variant(&variant.fields)?;
+ }
+
+ Ok(())
+ }
+ ::syn::Data::Struct(ref struct_data) => {
+ let data = &struct_data.fields;
+ #st
+ }
+ ::syn::Data::Union(_) => unreachable!(),
+ }
+ }
+ };
+
+ tokens.append_all(quote! {
+ #[allow(unused_variables)]
+ fn __validate_body(__body: &::syn::Data) -> ::darling::Result<()> {
+ #fn_body
+ }
+ });
+ }
+}
+
+/// Receiver for shape information within a struct or enum context. See `Shape` for more information
+/// on valid uses of shape validation.
+#[derive(Debug, Clone, Default, PartialEq, Eq)]
+pub struct DataShape {
+ /// The kind of shape being described. This can be `struct_` or `enum_`.
+ prefix: &'static str,
+ newtype: bool,
+ named: bool,
+ tuple: bool,
+ unit: bool,
+ any: bool,
+ /// Control whether the emitted code should be inside a function or not.
+ /// This is `true` when creating a `Shape` for `FromDeriveInput`, but false
+ /// when deriving `FromVariant`.
+ embedded: bool,
+}
+
+impl DataShape {
+ fn new(prefix: &'static str) -> Self {
+ DataShape {
+ prefix,
+ embedded: true,
+ ..Default::default()
+ }
+ }
+
+ fn supports_none(&self) -> bool {
+ !(self.any || self.newtype || self.named || self.tuple || self.unit)
+ }
+
+ fn set_word(&mut self, word: &str) -> Result<()> {
+ match word.trim_left_matches(self.prefix) {
+ "newtype" => {
+ self.newtype = true;
+ Ok(())
+ }
+ "named" => {
+ self.named = true;
+ Ok(())
+ }
+ "tuple" => {
+ self.tuple = true;
+ Ok(())
+ }
+ "unit" => {
+ self.unit = true;
+ Ok(())
+ }
+ "any" => {
+ self.any = true;
+ Ok(())
+ }
+ _ => Err(Error::unknown_value(word)),
+ }
+ }
+}
+
+impl FromMeta for DataShape {
+ fn from_list(items: &[NestedMeta]) -> Result<Self> {
+ let mut errors = Vec::new();
+ let mut new = DataShape::default();
+
+ for item in items {
+ if let NestedMeta::Meta(Meta::Path(ref path)) = *item {
+ if let Err(e) = new.set_word(&path.segments.first().unwrap().ident.to_string()) {
+ errors.push(e.with_span(&path));
+ }
+ } else {
+ errors.push(Error::unsupported_format("non-word").with_span(item));
+ }
+ }
+
+ if !errors.is_empty() {
+ Err(Error::multiple(errors))
+ } else {
+ Ok(new)
+ }
+ }
+}
+
+impl ToTokens for DataShape {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ let body = if self.any {
+ quote!(::darling::export::Ok(()))
+ } else if self.supports_none() {
+ let ty = self.prefix.trim_right_matches('_');
+ quote!(::darling::export::Err(::darling::Error::unsupported_shape(#ty)))
+ } else {
+ let unit = match_arm("unit", self.unit);
+ let newtype = match_arm("newtype", self.newtype);
+ let named = match_arm("named", self.named);
+ let tuple = match_arm("tuple", self.tuple);
+ quote! {
+ match *data {
+ ::syn::Fields::Unit => #unit,
+ ::syn::Fields::Unnamed(ref fields) if fields.unnamed.len() == 1 => #newtype,
+ ::syn::Fields::Unnamed(_) => #tuple,
+ ::syn::Fields::Named(_) => #named,
+ }
+ }
+ };
+
+ if self.embedded {
+ body.to_tokens(tokens);
+ } else {
+ tokens.append_all(quote! {
+ fn __validate_data(data: &::syn::Fields) -> ::darling::Result<()> {
+ #body
+ }
+ });
+ }
+ }
+}
+
+fn match_arm(name: &'static str, is_supported: bool) -> TokenStream {
+ if is_supported {
+ quote!(::darling::export::Ok(()))
+ } else {
+ quote!(::darling::export::Err(::darling::Error::unsupported_shape(#name)))
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use proc_macro2::TokenStream;
+ use syn;
+
+ use super::Shape;
+ use FromMeta;
+
+ /// parse a string as a syn::Meta instance.
+ fn pm(tokens: TokenStream) -> ::std::result::Result<syn::Meta, String> {
+ let attribute: syn::Attribute = parse_quote!(#[#tokens]);
+ attribute.parse_meta().or(Err("Unable to parse".into()))
+ }
+
+ fn fm<T: FromMeta>(tokens: TokenStream) -> T {
+ FromMeta::from_meta(&pm(tokens).expect("Tests should pass well-formed input"))
+ .expect("Tests should pass valid input")
+ }
+
+ #[test]
+ fn supports_any() {
+ let decl = fm::<Shape>(quote!(ignore(any)));
+ assert_eq!(decl.any, true);
+ }
+
+ #[test]
+ fn supports_struct() {
+ let decl = fm::<Shape>(quote!(ignore(struct_any, struct_newtype)));
+ assert_eq!(decl.struct_values.any, true);
+ assert_eq!(decl.struct_values.newtype, true);
+ }
+
+ #[test]
+ fn supports_mixed() {
+ let decl = fm::<Shape>(quote!(ignore(struct_newtype, enum_newtype, enum_tuple)));
+ assert_eq!(decl.struct_values.newtype, true);
+ assert_eq!(decl.enum_values.newtype, true);
+ assert_eq!(decl.enum_values.tuple, true);
+ assert_eq!(decl.struct_values.any, false);
+ }
+}
diff --git a/third_party/rust/darling_core/src/usage/generics_ext.rs b/third_party/rust/darling_core/src/usage/generics_ext.rs
new file mode 100644
index 0000000000..82af2f5762
--- /dev/null
+++ b/third_party/rust/darling_core/src/usage/generics_ext.rs
@@ -0,0 +1,24 @@
+use syn::Generics;
+
+use usage::{IdentSet, LifetimeSet};
+
+/// Extension trait for pulling specific generics data from a generics AST representation.
+pub trait GenericsExt {
+ /// Get the set of all lifetimes declared by the syntax element.
+ /// This does not look for usage of the lifetime; see `UsesLifetimes` for that.
+ fn declared_lifetimes(&self) -> LifetimeSet;
+
+ /// Get the set of all type parameters declared by the syntax element.
+ /// This does not look for usage of the type parameter; see `UsesTypeParams` for that.
+ fn declared_type_params(&self) -> IdentSet;
+}
+
+impl GenericsExt for Generics {
+ fn declared_lifetimes(&self) -> LifetimeSet {
+ self.lifetimes().map(|lt| lt.lifetime.clone()).collect()
+ }
+
+ fn declared_type_params(&self) -> IdentSet {
+ self.type_params().map(|tp| tp.ident.clone()).collect()
+ }
+}
diff --git a/third_party/rust/darling_core/src/usage/ident_set.rs b/third_party/rust/darling_core/src/usage/ident_set.rs
new file mode 100644
index 0000000000..e38d332dd0
--- /dev/null
+++ b/third_party/rust/darling_core/src/usage/ident_set.rs
@@ -0,0 +1,8 @@
+use fnv::FnvHashSet;
+use syn::Ident;
+
+/// A set of idents.
+pub type IdentSet = FnvHashSet<Ident>;
+
+/// A set of references to idents.
+pub type IdentRefSet<'a> = FnvHashSet<&'a Ident>;
diff --git a/third_party/rust/darling_core/src/usage/lifetimes.rs b/third_party/rust/darling_core/src/usage/lifetimes.rs
new file mode 100644
index 0000000000..ef76bc6798
--- /dev/null
+++ b/third_party/rust/darling_core/src/usage/lifetimes.rs
@@ -0,0 +1,326 @@
+use fnv::FnvHashSet;
+use syn::punctuated::Punctuated;
+use syn::{self, Lifetime, Type};
+
+use usage::Options;
+
+/// A set of lifetimes.
+pub type LifetimeSet = FnvHashSet<Lifetime>;
+
+/// A set of references to lifetimes.
+pub type LifetimeRefSet<'a> = FnvHashSet<&'a Lifetime>;
+
+/// Searcher for finding lifetimes in a syntax tree.
+/// This can be used to determine which lifetimes must be emitted in generated code.
+pub trait UsesLifetimes {
+ /// Returns the subset of the queried lifetimes that are used by the implementing syntax element.
+ ///
+ /// This method only accounts for direct usage by the element; indirect usage via bounds or `where`
+ /// predicates are not detected.
+ fn uses_lifetimes<'a>(
+ &self,
+ options: &Options,
+ lifetimes: &'a LifetimeSet,
+ ) -> LifetimeRefSet<'a>;
+
+ /// Find all used lifetimes, then clone them and return that set.
+ fn uses_lifetimes_cloned(&self, options: &Options, lifetimes: &LifetimeSet) -> LifetimeSet {
+ self.uses_lifetimes(options, lifetimes)
+ .into_iter()
+ .cloned()
+ .collect()
+ }
+}
+
+/// Searcher for finding lifetimes in an iterator.
+///
+/// This trait extends iterators, providing a way to turn a filtered list of fields or variants into a set
+/// of lifetimes.
+pub trait CollectLifetimes {
+ /// Consume an iterator, accumulating all lifetimes in the elements which occur in `lifetimes`.
+ fn collect_lifetimes<'a>(
+ self,
+ options: &Options,
+ lifetimes: &'a LifetimeSet,
+ ) -> LifetimeRefSet<'a>;
+
+ /// Consume an iterator using `collect_lifetimes`, then clone all found lifetimes and return that set.
+ fn collect_lifetimes_cloned(self, options: &Options, lifetimes: &LifetimeSet) -> LifetimeSet;
+}
+
+impl<'i, I, T> CollectLifetimes for T
+where
+ T: IntoIterator<Item = &'i I>,
+ I: 'i + UsesLifetimes,
+{
+ fn collect_lifetimes<'a>(
+ self,
+ options: &Options,
+ lifetimes: &'a LifetimeSet,
+ ) -> LifetimeRefSet<'a> {
+ self.into_iter()
+ .fold(Default::default(), |mut state, value| {
+ state.extend(value.uses_lifetimes(options, lifetimes));
+ state
+ })
+ }
+
+ fn collect_lifetimes_cloned(self, options: &Options, lifetimes: &LifetimeSet) -> LifetimeSet {
+ self.collect_lifetimes(options, lifetimes)
+ .into_iter()
+ .cloned()
+ .collect()
+ }
+}
+
+impl<T: UsesLifetimes> UsesLifetimes for Vec<T> {
+ fn uses_lifetimes<'a>(
+ &self,
+ options: &Options,
+ lifetimes: &'a LifetimeSet,
+ ) -> LifetimeRefSet<'a> {
+ self.collect_lifetimes(options, lifetimes)
+ }
+}
+
+impl<T: UsesLifetimes, U> UsesLifetimes for Punctuated<T, U> {
+ fn uses_lifetimes<'a>(
+ &self,
+ options: &Options,
+ lifetimes: &'a LifetimeSet,
+ ) -> LifetimeRefSet<'a> {
+ self.collect_lifetimes(options, lifetimes)
+ }
+}
+
+impl<T: UsesLifetimes> UsesLifetimes for Option<T> {
+ fn uses_lifetimes<'a>(
+ &self,
+ options: &Options,
+ lifetimes: &'a LifetimeSet,
+ ) -> LifetimeRefSet<'a> {
+ self.as_ref()
+ .map(|v| v.uses_lifetimes(options, lifetimes))
+ .unwrap_or_default()
+ }
+}
+
+impl UsesLifetimes for Lifetime {
+ fn uses_lifetimes<'a>(&self, _: &Options, lifetimes: &'a LifetimeSet) -> LifetimeRefSet<'a> {
+ lifetimes.iter().filter(|lt| *lt == self).collect()
+ }
+}
+
+uses_lifetimes!(syn::AngleBracketedGenericArguments, args);
+uses_lifetimes!(syn::BareFnArg, ty);
+uses_lifetimes!(syn::Binding, ty);
+uses_lifetimes!(syn::BoundLifetimes, lifetimes);
+uses_lifetimes!(syn::Constraint, bounds);
+uses_lifetimes!(syn::DataEnum, variants);
+uses_lifetimes!(syn::DataStruct, fields);
+uses_lifetimes!(syn::DataUnion, fields);
+uses_lifetimes!(syn::Field, ty);
+uses_lifetimes!(syn::FieldsNamed, named);
+uses_lifetimes!(syn::LifetimeDef, lifetime, bounds);
+uses_lifetimes!(syn::ParenthesizedGenericArguments, inputs, output);
+uses_lifetimes!(syn::Path, segments);
+uses_lifetimes!(syn::PathSegment, arguments);
+uses_lifetimes!(syn::PredicateEq, lhs_ty, rhs_ty);
+uses_lifetimes!(syn::PredicateLifetime, lifetime, bounds);
+uses_lifetimes!(syn::PredicateType, lifetimes, bounded_ty, bounds);
+uses_lifetimes!(syn::QSelf, ty);
+uses_lifetimes!(syn::TraitBound, path, lifetimes);
+uses_lifetimes!(syn::TypeArray, elem);
+uses_lifetimes!(syn::TypeBareFn, inputs, output);
+uses_lifetimes!(syn::TypeGroup, elem);
+uses_lifetimes!(syn::TypeImplTrait, bounds);
+uses_lifetimes!(syn::TypeParen, elem);
+uses_lifetimes!(syn::TypePtr, elem);
+uses_lifetimes!(syn::TypeReference, lifetime, elem);
+uses_lifetimes!(syn::TypeSlice, elem);
+uses_lifetimes!(syn::TypeTuple, elems);
+uses_lifetimes!(syn::TypeTraitObject, bounds);
+uses_lifetimes!(syn::Variant, fields);
+
+impl UsesLifetimes for syn::Data {
+ fn uses_lifetimes<'a>(
+ &self,
+ options: &Options,
+ lifetimes: &'a LifetimeSet,
+ ) -> LifetimeRefSet<'a> {
+ match *self {
+ syn::Data::Struct(ref v) => v.uses_lifetimes(options, lifetimes),
+ syn::Data::Enum(ref v) => v.uses_lifetimes(options, lifetimes),
+ syn::Data::Union(ref v) => v.uses_lifetimes(options, lifetimes),
+ }
+ }
+}
+
+impl UsesLifetimes for Type {
+ fn uses_lifetimes<'a>(
+ &self,
+ options: &Options,
+ lifetimes: &'a LifetimeSet,
+ ) -> LifetimeRefSet<'a> {
+ match *self {
+ Type::Slice(ref v) => v.uses_lifetimes(options, lifetimes),
+ Type::Array(ref v) => v.uses_lifetimes(options, lifetimes),
+ Type::Ptr(ref v) => v.uses_lifetimes(options, lifetimes),
+ Type::Reference(ref v) => v.uses_lifetimes(options, lifetimes),
+ Type::BareFn(ref v) => v.uses_lifetimes(options, lifetimes),
+ Type::Tuple(ref v) => v.uses_lifetimes(options, lifetimes),
+ Type::Path(ref v) => v.uses_lifetimes(options, lifetimes),
+ Type::Paren(ref v) => v.uses_lifetimes(options, lifetimes),
+ Type::Group(ref v) => v.uses_lifetimes(options, lifetimes),
+ Type::TraitObject(ref v) => v.uses_lifetimes(options, lifetimes),
+ Type::ImplTrait(ref v) => v.uses_lifetimes(options, lifetimes),
+ Type::Macro(_) | Type::Verbatim(_) | Type::Infer(_) | Type::Never(_) => {
+ Default::default()
+ },
+ _ => panic!("Unknown syn::Type: {:?}", self)
+ }
+ }
+}
+
+impl UsesLifetimes for syn::Fields {
+ fn uses_lifetimes<'a>(
+ &self,
+ options: &Options,
+ lifetimes: &'a LifetimeSet,
+ ) -> LifetimeRefSet<'a> {
+ self.collect_lifetimes(options, lifetimes)
+ }
+}
+
+impl UsesLifetimes for syn::TypePath {
+ fn uses_lifetimes<'a>(
+ &self,
+ options: &Options,
+ lifetimes: &'a LifetimeSet,
+ ) -> LifetimeRefSet<'a> {
+ let mut hits = self.path.uses_lifetimes(options, lifetimes);
+
+ if options.include_type_path_qself() {
+ hits.extend(self.qself.uses_lifetimes(options, lifetimes));
+ }
+
+ hits
+ }
+}
+
+impl UsesLifetimes for syn::ReturnType {
+ fn uses_lifetimes<'a>(
+ &self,
+ options: &Options,
+ lifetimes: &'a LifetimeSet,
+ ) -> LifetimeRefSet<'a> {
+ if let syn::ReturnType::Type(_, ref ty) = *self {
+ ty.uses_lifetimes(options, lifetimes)
+ } else {
+ Default::default()
+ }
+ }
+}
+
+impl UsesLifetimes for syn::PathArguments {
+ fn uses_lifetimes<'a>(
+ &self,
+ options: &Options,
+ lifetimes: &'a LifetimeSet,
+ ) -> LifetimeRefSet<'a> {
+ match *self {
+ syn::PathArguments::None => Default::default(),
+ syn::PathArguments::AngleBracketed(ref v) => v.uses_lifetimes(options, lifetimes),
+ syn::PathArguments::Parenthesized(ref v) => v.uses_lifetimes(options, lifetimes),
+ }
+ }
+}
+
+impl UsesLifetimes for syn::WherePredicate {
+ fn uses_lifetimes<'a>(
+ &self,
+ options: &Options,
+ lifetimes: &'a LifetimeSet,
+ ) -> LifetimeRefSet<'a> {
+ match *self {
+ syn::WherePredicate::Type(ref v) => v.uses_lifetimes(options, lifetimes),
+ syn::WherePredicate::Lifetime(ref v) => v.uses_lifetimes(options, lifetimes),
+ syn::WherePredicate::Eq(ref v) => v.uses_lifetimes(options, lifetimes),
+ }
+ }
+}
+
+impl UsesLifetimes for syn::GenericArgument {
+ fn uses_lifetimes<'a>(
+ &self,
+ options: &Options,
+ lifetimes: &'a LifetimeSet,
+ ) -> LifetimeRefSet<'a> {
+ match *self {
+ syn::GenericArgument::Type(ref v) => v.uses_lifetimes(options, lifetimes),
+ syn::GenericArgument::Binding(ref v) => v.uses_lifetimes(options, lifetimes),
+ syn::GenericArgument::Lifetime(ref v) => v.uses_lifetimes(options, lifetimes),
+ syn::GenericArgument::Constraint(ref v) => v.uses_lifetimes(options, lifetimes),
+ syn::GenericArgument::Const(_) => Default::default(),
+ }
+ }
+}
+
+impl UsesLifetimes for syn::TypeParamBound {
+ fn uses_lifetimes<'a>(
+ &self,
+ options: &Options,
+ lifetimes: &'a LifetimeSet,
+ ) -> LifetimeRefSet<'a> {
+ match *self {
+ syn::TypeParamBound::Trait(ref v) => v.uses_lifetimes(options, lifetimes),
+ syn::TypeParamBound::Lifetime(ref v) => v.uses_lifetimes(options, lifetimes),
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use proc_macro2::Span;
+ use syn::{self, DeriveInput};
+
+ use super::UsesLifetimes;
+ use usage::GenericsExt;
+ use usage::Purpose::*;
+
+ #[test]
+ fn struct_named() {
+ let input: DeriveInput = parse_quote! {
+ struct Foo<'a, 'b: 'a> {
+ parent: &'b Bar,
+ child: &'a Baz,
+ }
+ };
+ let omitted = syn::Lifetime::new("'c", Span::call_site());
+
+ let lifetimes = {
+ let mut lt = input.generics.declared_lifetimes();
+ lt.insert(omitted);
+ lt
+ };
+
+ let matches = input.data.uses_lifetimes(&BoundImpl.into(), &lifetimes);
+ assert_eq!(matches.len(), 2);
+ }
+
+ #[test]
+ fn qself() {
+ let input: DeriveInput = parse_quote! {
+ struct Foo<'a, 'b: 'a> {
+ parent: &'b Bar,
+ child: <Bar<'a> as MyIterator>::Item,
+ }
+ };
+ let lifetimes = input.generics.declared_lifetimes();
+ let matches = input.data.uses_lifetimes(&BoundImpl.into(), &lifetimes);
+ assert_eq!(matches.len(), 1);
+
+ let decl_matches = input.data.uses_lifetimes(&Declare.into(), &lifetimes);
+ assert_eq!(decl_matches.len(), 2);
+ }
+}
diff --git a/third_party/rust/darling_core/src/usage/mod.rs b/third_party/rust/darling_core/src/usage/mod.rs
new file mode 100644
index 0000000000..fe8f12fb98
--- /dev/null
+++ b/third_party/rust/darling_core/src/usage/mod.rs
@@ -0,0 +1,111 @@
+//! Traits and types used for tracking the usage of generic parameters through a proc-macro input.
+//!
+//! When generating trait impls, libraries often want to automatically figure out which type parameters
+//! are used in which fields, and then emit bounds that will produce the most permissive compilable
+//! code.
+//!
+//! # Usage
+//!
+//! ## Example 1: Filtering
+//! This example accepts a proc-macro input, then finds all lifetimes and type parameters used
+//! by private fields.
+//!
+//! ```rust
+//! # extern crate darling_core;
+//! # extern crate syn;
+//! #
+//! # // in real-world usage, import from `darling`
+//! # use darling_core::usage::{self, CollectLifetimes, CollectTypeParams, GenericsExt, Purpose};
+//! # use syn::{Data, DeriveInput, GenericParam, Generics, Visibility};
+//! #
+//! # #[allow(dead_code)]
+//! fn process(input: &DeriveInput) -> Generics {
+//! let type_params = input.generics.declared_type_params();
+//! let lifetimes = input.generics.declared_lifetimes();
+//!
+//! let mut ret_generics = input.generics.clone();
+//!
+//! if let Data::Struct(ref body) = input.data {
+//! let internal_fields = body
+//! .fields
+//! .iter()
+//! .filter(|field| field.vis == Visibility::Inherited)
+//! .collect::<Vec<_>>();
+//!
+//! let int_type_params = internal_fields
+//! .collect_type_params(&Purpose::BoundImpl.into(), &type_params);
+//!
+//! // We could reuse the vec from above, but here we'll instead
+//! // directly consume the chained iterator.
+//! let int_lifetimes = body
+//! .fields
+//! .iter()
+//! .filter(|field| field.vis == Visibility::Inherited)
+//! .collect_lifetimes(&Purpose::BoundImpl.into(), &lifetimes);
+//!
+//!
+//! ret_generics.params = ret_generics
+//! .params
+//! .into_iter()
+//! .filter(|gp| {
+//! match *gp {
+//! GenericParam::Type(ref ty) => int_type_params.contains(&ty.ident),
+//! GenericParam::Lifetime(ref lt) => int_lifetimes.contains(&lt.lifetime),
+//! _ => true,
+//! }
+//! })
+//! .collect();
+//! }
+//!
+//! ret_generics
+//! }
+//!
+//! # fn main() {}
+//! ```
+//!
+//! ## Example 2: Integrating with `FromDeriveInput`
+//! It is possible to use `darling`'s magic fields feature in tandem with the `usage` feature set.
+//! While there is no custom derive for `UsesTypeParams` or `UsesLifetimes`, there are macros to
+//! generate impls.
+//!
+//! ```rust,ignore
+//! #![allow(dead_code)]
+//!
+//! #[derive(FromField)]
+//! #[darling(attributes(speak))]
+//! struct SpeakerField {
+//! ident: Option<syn::Ident>,
+//! ty: syn::Type,
+//! #[darling(default)]
+//! volume: Option<u32>,
+//! }
+//!
+//! uses_type_params!(SpeakerField, ty);
+//! uses_lifetimes!(SpeakerField, ty);
+//!
+//! #[derive(FromDeriveInput)]
+//! struct SpeakerOptions {
+//! generics: syn::Generics,
+//! data: darling::ast::Data<darling::util::Ignored, SpeakerField>,
+//! }
+//! ```
+//!
+//! At this point, you are able to call `uses_type_params` on `SpeakerOptions.data`, or any filtered
+//! view of it. `darling` internally uses this in conjunction with the `skip` meta-item to determine
+//! which type parameters don't require the `FromMeta` bound in generated impls.
+//!
+//! **Note:** If you are performing operations referencing generic params in meta-items parsed by `darling`,
+//! you should determine if those impact the emitted code and wire up `UsesTypeParams` accordingly for
+//! your field/variant.
+
+mod generics_ext;
+mod ident_set;
+mod lifetimes;
+mod options;
+mod type_params;
+
+pub use self::generics_ext::GenericsExt;
+pub use self::ident_set::{IdentRefSet, IdentSet};
+pub use self::lifetimes::{CollectLifetimes, LifetimeRefSet, LifetimeSet, UsesLifetimes};
+pub use self::options::{Options, Purpose};
+pub use self::type_params::{CollectTypeParams, UsesTypeParams};
diff --git a/third_party/rust/darling_core/src/usage/options.rs b/third_party/rust/darling_core/src/usage/options.rs
new file mode 100644
index 0000000000..f154881be9
--- /dev/null
+++ b/third_party/rust/darling_core/src/usage/options.rs
@@ -0,0 +1,58 @@
+/// The goal of tracing generic parameter usage.
+///
+/// Not all uses of type parameters imply a need to add bounds to a generated trait impl.
+/// For example, a field of type `<Vec<T> as a::b::Trait>::Associated` does not need a
+/// `where T: Serialize` bound in `serde`.
+/// However, a proc macro that is attempting to generate a helper struct _would_ need to
+/// know about this usage, or else the generated code would reference an unknown type `T`
+/// and fail to compile.
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub enum Purpose {
+ /// The tracing is being used to generate an `impl` block.
+ ///
+ /// Uses such as `syn::TypePath.qself` will _not_ be returned.
+ BoundImpl,
+ /// The tracing is being used to generate a new struct or enum.
+ ///
+ /// All uses will be returned.
+ Declare,
+}
+
+/// Control struct for searching type parameters.
+///
+/// This acts as the search context, preserving information that might have been
+/// kept on a visitor in a different implementation.
+/// Trait implementers are required to pass this through on any invocations they make.
+///
+/// # Usage
+/// For extensibility, `Options` hides all of its fields from consumers.
+/// To create an instance, use the `From<Purpose>` trait implementation:
+///
+/// ```rust
+/// # use darling_core::usage::{Options, Purpose};
+/// let opts: Options = Purpose::BoundImpl.into();
+/// assert!(!opts.include_type_path_qself());
+/// ```
+#[derive(Debug, Clone)]
+pub struct Options {
+ purpose: Purpose,
+ #[doc(hidden)]
+ __nonexhaustive: (),
+}
+
+impl From<Purpose> for Options {
+ fn from(purpose: Purpose) -> Self {
+ Self {
+ purpose,
+ __nonexhaustive: (),
+ }
+ }
+}
+
+impl Options {
+ /// Returns `true` if the implementer of `UseTypeParams` should search
+ /// `<___ as ...>::...` when looking for type parameter uses.
+ pub fn include_type_path_qself(&self) -> bool {
+ self.purpose == Purpose::Declare
+ }
+}
diff --git a/third_party/rust/darling_core/src/usage/type_params.rs b/third_party/rust/darling_core/src/usage/type_params.rs
new file mode 100644
index 0000000000..770f4954fb
--- /dev/null
+++ b/third_party/rust/darling_core/src/usage/type_params.rs
@@ -0,0 +1,357 @@
+use syn::punctuated::Punctuated;
+use syn::{self, Ident, Type};
+
+use usage::{IdentRefSet, IdentSet, Options};
+
+/// Searcher for finding type params in a syntax tree.
+/// This can be used to determine if a given type parameter needs to be bounded in a generated impl.
+pub trait UsesTypeParams {
+ /// Returns the subset of the queried type parameters that are used by the implementing syntax element.
+ ///
+ /// This method only accounts for direct usage by the element; indirect usage via bounds or `where`
+ /// predicates are not detected.
+ fn uses_type_params<'a>(&self, options: &Options, type_set: &'a IdentSet) -> IdentRefSet<'a>;
+
+ /// Find all type params using `uses_type_params`, then clone the found values and return the set.
+ fn uses_type_params_cloned(&self, options: &Options, type_set: &IdentSet) -> IdentSet {
+ self.uses_type_params(options, type_set)
+ .into_iter()
+ .cloned()
+ .collect()
+ }
+}
+
+/// Searcher for finding type params in an iterator.
+///
+/// This trait extends iterators, providing a way to turn a filtered list of fields or variants into a set
+/// of type parameter idents.
+pub trait CollectTypeParams {
+ /// Consume an iterator, accumulating all type parameters in the elements which occur in `type_set`.
+ fn collect_type_params<'a>(self, options: &Options, type_set: &'a IdentSet) -> IdentRefSet<'a>;
+
+ /// Consume an iterator using `collect_type_params`, then clone all found type params and return that set.
+ fn collect_type_params_cloned(self, options: &Options, type_set: &IdentSet) -> IdentSet;
+}
+
+impl<'i, T, I> CollectTypeParams for T
+where
+ T: IntoIterator<Item = &'i I>,
+ I: 'i + UsesTypeParams,
+{
+ fn collect_type_params<'a>(self, options: &Options, type_set: &'a IdentSet) -> IdentRefSet<'a> {
+ self.into_iter().fold(
+ IdentRefSet::with_capacity_and_hasher(type_set.len(), Default::default()),
+ |state, value| union_in_place(state, value.uses_type_params(options, type_set)),
+ )
+ }
+
+ fn collect_type_params_cloned(self, options: &Options, type_set: &IdentSet) -> IdentSet {
+ self.collect_type_params(options, type_set)
+ .into_iter()
+ .cloned()
+ .collect()
+ }
+}
+
+/// Insert the contents of `right` into `left`.
+fn union_in_place<'a>(mut left: IdentRefSet<'a>, right: IdentRefSet<'a>) -> IdentRefSet<'a> {
+ left.extend(right);
+
+ left
+}
+
+impl UsesTypeParams for () {
+ fn uses_type_params<'a>(&self, _options: &Options, _type_set: &'a IdentSet) -> IdentRefSet<'a> {
+ Default::default()
+ }
+}
+
+impl<T: UsesTypeParams> UsesTypeParams for Option<T> {
+ fn uses_type_params<'a>(&self, options: &Options, type_set: &'a IdentSet) -> IdentRefSet<'a> {
+ self.as_ref()
+ .map(|v| v.uses_type_params(options, type_set))
+ .unwrap_or_default()
+ }
+}
+
+impl<T: UsesTypeParams> UsesTypeParams for Vec<T> {
+ fn uses_type_params<'a>(&self, options: &Options, type_set: &'a IdentSet) -> IdentRefSet<'a> {
+ self.collect_type_params(options, type_set)
+ }
+}
+
+impl<T: UsesTypeParams, U> UsesTypeParams for Punctuated<T, U> {
+ fn uses_type_params<'a>(&self, options: &Options, type_set: &'a IdentSet) -> IdentRefSet<'a> {
+ self.collect_type_params(options, type_set)
+ }
+}
+
+uses_type_params!(syn::AngleBracketedGenericArguments, args);
+uses_type_params!(syn::BareFnArg, ty);
+uses_type_params!(syn::Binding, ty);
+uses_type_params!(syn::Constraint, bounds);
+uses_type_params!(syn::DataEnum, variants);
+uses_type_params!(syn::DataStruct, fields);
+uses_type_params!(syn::DataUnion, fields);
+uses_type_params!(syn::Field, ty);
+uses_type_params!(syn::FieldsNamed, named);
+uses_type_params!(syn::ParenthesizedGenericArguments, inputs, output);
+uses_type_params!(syn::PredicateEq, lhs_ty, rhs_ty);
+uses_type_params!(syn::PredicateType, bounded_ty, bounds);
+uses_type_params!(syn::QSelf, ty);
+uses_type_params!(syn::TraitBound, path);
+uses_type_params!(syn::TypeArray, elem);
+uses_type_params!(syn::TypeBareFn, inputs, output);
+uses_type_params!(syn::TypeGroup, elem);
+uses_type_params!(syn::TypeImplTrait, bounds);
+uses_type_params!(syn::TypeParen, elem);
+uses_type_params!(syn::TypePtr, elem);
+uses_type_params!(syn::TypeReference, elem);
+uses_type_params!(syn::TypeSlice, elem);
+uses_type_params!(syn::TypeTuple, elems);
+uses_type_params!(syn::TypeTraitObject, bounds);
+uses_type_params!(syn::Variant, fields);
+
+impl UsesTypeParams for syn::Data {
+ fn uses_type_params<'a>(&self, options: &Options, type_set: &'a IdentSet) -> IdentRefSet<'a> {
+ match *self {
+ syn::Data::Struct(ref v) => v.uses_type_params(options, type_set),
+ syn::Data::Enum(ref v) => v.uses_type_params(options, type_set),
+ syn::Data::Union(ref v) => v.uses_type_params(options, type_set),
+ }
+ }
+}
+
+impl UsesTypeParams for syn::Fields {
+ fn uses_type_params<'a>(&self, options: &Options, type_set: &'a IdentSet) -> IdentRefSet<'a> {
+ self.collect_type_params(options, type_set)
+ }
+}
+
+/// Check if an Ident exactly matches one of the sought-after type parameters.
+impl UsesTypeParams for Ident {
+ fn uses_type_params<'a>(&self, _options: &Options, type_set: &'a IdentSet) -> IdentRefSet<'a> {
+ type_set.iter().filter(|v| *v == self).collect()
+ }
+}
+
+impl UsesTypeParams for syn::ReturnType {
+ fn uses_type_params<'a>(&self, options: &Options, type_set: &'a IdentSet) -> IdentRefSet<'a> {
+ if let syn::ReturnType::Type(_, ref ty) = *self {
+ ty.uses_type_params(options, type_set)
+ } else {
+ Default::default()
+ }
+ }
+}
+
+impl UsesTypeParams for Type {
+ fn uses_type_params<'a>(&self, options: &Options, type_set: &'a IdentSet) -> IdentRefSet<'a> {
+ match *self {
+ Type::Slice(ref v) => v.uses_type_params(options, type_set),
+ Type::Array(ref v) => v.uses_type_params(options, type_set),
+ Type::Ptr(ref v) => v.uses_type_params(options, type_set),
+ Type::Reference(ref v) => v.uses_type_params(options, type_set),
+ Type::BareFn(ref v) => v.uses_type_params(options, type_set),
+ Type::Tuple(ref v) => v.uses_type_params(options, type_set),
+ Type::Path(ref v) => v.uses_type_params(options, type_set),
+ Type::Paren(ref v) => v.uses_type_params(options, type_set),
+ Type::Group(ref v) => v.uses_type_params(options, type_set),
+ Type::TraitObject(ref v) => v.uses_type_params(options, type_set),
+ Type::ImplTrait(ref v) => v.uses_type_params(options, type_set),
+ Type::Macro(_) | Type::Verbatim(_) | Type::Infer(_) | Type::Never(_) => {
+ Default::default()
+ },
+ _ => panic!("Unknown syn::Type: {:?}", self)
+ }
+ }
+}
+
+impl UsesTypeParams for syn::TypePath {
+ fn uses_type_params<'a>(&self, options: &Options, type_set: &'a IdentSet) -> IdentRefSet<'a> {
+ let hits = self.path.uses_type_params(options, type_set);
+
+ if options.include_type_path_qself() {
+ union_in_place(hits, self.qself.uses_type_params(options, type_set))
+ } else {
+ hits
+ }
+ }
+}
+
+impl UsesTypeParams for syn::Path {
+ fn uses_type_params<'a>(&self, options: &Options, type_set: &'a IdentSet) -> IdentRefSet<'a> {
+ // Not sure if this is even possible, but a path with no segments definitely
+ // can't use type parameters.
+ if self.segments.is_empty() {
+ return Default::default();
+ }
+
+ // A path segment ident can only match if it is not global and it is the first segment
+ // in the path.
+ let ident_hits = if self.leading_colon.is_none() {
+ self.segments[0].ident.uses_type_params(options, type_set)
+ } else {
+ Default::default()
+ };
+
+ // Merge ident hit, if any, with all hits from path arguments
+ self.segments.iter().fold(ident_hits, |state, segment| {
+ union_in_place(state, segment.arguments.uses_type_params(options, type_set))
+ })
+ }
+}
+
+impl UsesTypeParams for syn::PathArguments {
+ fn uses_type_params<'a>(&self, options: &Options, type_set: &'a IdentSet) -> IdentRefSet<'a> {
+ match *self {
+ syn::PathArguments::None => Default::default(),
+ syn::PathArguments::AngleBracketed(ref v) => v.uses_type_params(options, type_set),
+ syn::PathArguments::Parenthesized(ref v) => v.uses_type_params(options, type_set),
+ }
+ }
+}
+
+impl UsesTypeParams for syn::WherePredicate {
+ fn uses_type_params<'a>(&self, options: &Options, type_set: &'a IdentSet) -> IdentRefSet<'a> {
+ match *self {
+ syn::WherePredicate::Lifetime(_) => Default::default(),
+ syn::WherePredicate::Type(ref v) => v.uses_type_params(options, type_set),
+ syn::WherePredicate::Eq(ref v) => v.uses_type_params(options, type_set),
+ }
+ }
+}
+
+impl UsesTypeParams for syn::GenericArgument {
+ fn uses_type_params<'a>(&self, options: &Options, type_set: &'a IdentSet) -> IdentRefSet<'a> {
+ match *self {
+ syn::GenericArgument::Type(ref v) => v.uses_type_params(options, type_set),
+ syn::GenericArgument::Binding(ref v) => v.uses_type_params(options, type_set),
+ syn::GenericArgument::Constraint(ref v) => v.uses_type_params(options, type_set),
+ syn::GenericArgument::Const(_) | syn::GenericArgument::Lifetime(_) => {
+ Default::default()
+ }
+ }
+ }
+}
+
+impl UsesTypeParams for syn::TypeParamBound {
+ fn uses_type_params<'a>(&self, options: &Options, type_set: &'a IdentSet) -> IdentRefSet<'a> {
+ match *self {
+ syn::TypeParamBound::Trait(ref v) => v.uses_type_params(options, type_set),
+ syn::TypeParamBound::Lifetime(_) => Default::default(),
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use proc_macro2::Span;
+ use syn::{DeriveInput, Ident};
+
+ use super::UsesTypeParams;
+ use usage::IdentSet;
+ use usage::Purpose::*;
+
+ fn ident_set(idents: Vec<&str>) -> IdentSet {
+ idents
+ .into_iter()
+ .map(|s| Ident::new(s, Span::call_site()))
+ .collect()
+ }
+
+ #[test]
+ fn finds_simple() {
+ let input: DeriveInput = parse_quote! { struct Foo<T, U>(T, i32, A, U); };
+ let generics = ident_set(vec!["T", "U", "X"]);
+ let matches = input.data.uses_type_params(&BoundImpl.into(), &generics);
+ assert_eq!(matches.len(), 2);
+ assert!(matches.contains::<Ident>(&parse_quote!(T)));
+ assert!(matches.contains::<Ident>(&parse_quote!(U)));
+ assert!(!matches.contains::<Ident>(&parse_quote!(X)));
+ assert!(!matches.contains::<Ident>(&parse_quote!(A)));
+ }
+
+ #[test]
+ fn finds_named() {
+ let input: DeriveInput = parse_quote! {
+ struct Foo<T, U = usize> {
+ bar: T,
+ world: U,
+ }
+ };
+
+ let generics = ident_set(vec!["T", "U", "X"]);
+
+ let matches = input.data.uses_type_params(&BoundImpl.into(), &generics);
+
+ assert_eq!(matches.len(), 2);
+ assert!(matches.contains::<Ident>(&parse_quote!(T)));
+ assert!(matches.contains::<Ident>(&parse_quote!(U)));
+ assert!(!matches.contains::<Ident>(&parse_quote!(X)));
+ assert!(!matches.contains::<Ident>(&parse_quote!(A)));
+ }
+
+ #[test]
+ fn finds_as_type_arg() {
+ let input: DeriveInput = parse_quote! {
+ struct Foo<T, U> {
+ bar: T,
+ world: Vec<U>,
+ }
+ };
+
+ let generics = ident_set(vec!["T", "U", "X"]);
+
+ let matches = input.data.uses_type_params(&BoundImpl.into(), &generics);
+
+ assert_eq!(matches.len(), 2);
+ assert!(matches.contains::<Ident>(&parse_quote!(T)));
+ assert!(matches.contains::<Ident>(&parse_quote!(U)));
+ assert!(!matches.contains::<Ident>(&parse_quote!(X)));
+ assert!(!matches.contains::<Ident>(&parse_quote!(A)));
+ }
+
+ #[test]
+ fn associated_type() {
+ let input: DeriveInput =
+ parse_quote! { struct Foo<'a, T> where T: Iterator { peek: T::Item } };
+ let generics = ident_set(vec!["T", "INTO"]);
+ let matches = input.data.uses_type_params(&BoundImpl.into(), &generics);
+ assert_eq!(matches.len(), 1);
+ }
+
+ #[test]
+ fn box_fn_output() {
+ let input: DeriveInput = parse_quote! { struct Foo<T>(Box<Fn() -> T>); };
+ let generics = ident_set(vec!["T"]);
+ let matches = input.data.uses_type_params(&BoundImpl.into(), &generics);
+ assert_eq!(matches.len(), 1);
+ assert!(matches.contains::<Ident>(&parse_quote!(T)));
+ }
+
+ #[test]
+ fn box_fn_input() {
+ let input: DeriveInput = parse_quote! { struct Foo<T>(Box<Fn(&T) -> ()>); };
+ let generics = ident_set(vec!["T"]);
+ let matches = input.data.uses_type_params(&BoundImpl.into(), &generics);
+ assert_eq!(matches.len(), 1);
+ assert!(matches.contains::<Ident>(&parse_quote!(T)));
+ }
+
+ /// Test that `syn::TypePath` is correctly honoring the different modes a
+ /// search can execute in.
+ #[test]
+ fn qself_vec() {
+ let input: DeriveInput =
+ parse_quote! { struct Foo<T>(<Vec<T> as a::b::Trait>::AssociatedItem); };
+ let generics = ident_set(vec!["T", "U"]);
+
+ let bound_matches = input.data.uses_type_params(&BoundImpl.into(), &generics);
+ assert_eq!(bound_matches.len(), 0);
+
+ let declare_matches = input.data.uses_type_params(&Declare.into(), &generics);
+ assert_eq!(declare_matches.len(), 1);
+ assert!(declare_matches.contains::<Ident>(&parse_quote!(T)));
+ }
+}
diff --git a/third_party/rust/darling_core/src/util/ident_string.rs b/third_party/rust/darling_core/src/util/ident_string.rs
new file mode 100644
index 0000000000..293610e2f6
--- /dev/null
+++ b/third_party/rust/darling_core/src/util/ident_string.rs
@@ -0,0 +1,155 @@
+use std::fmt;
+use std::hash::{Hash, Hasher};
+
+use proc_macro2::{Span, TokenStream};
+use quote::ToTokens;
+use syn::{Ident, Meta};
+
+use {FromMeta, Result};
+
+/// A wrapper for an `Ident` which also keeps the value as a string.
+///
+/// This struct can be used to perform string comparisons and operations.
+#[derive(Clone, PartialOrd, Ord)]
+pub struct IdentString {
+ ident: Ident,
+ string: String,
+}
+
+impl IdentString {
+ /// Create a new `IdentString`.
+ pub fn new(ident: Ident) -> Self {
+ IdentString {
+ string: ident.to_string(),
+ ident,
+ }
+ }
+
+ /// Get the ident as a `proc_macro2::Ident`.
+ pub fn as_ident(&self) -> &Ident {
+ &self.ident
+ }
+
+ /// Get the ident as a string.
+ pub fn as_str(&self) -> &str {
+ &self.string
+ }
+
+ /// Get the location of this `Ident` in source.
+ pub fn span(&self) -> Span {
+ self.ident.span()
+ }
+
+ /// Apply some transform to the ident's string representation.
+ ///
+ /// # Panics
+ /// This will panic if the transform produces an invalid ident.
+ pub fn map<F, S>(self, map_fn: F) -> Self
+ where
+ F: FnOnce(String) -> S,
+ S: AsRef<str>,
+ {
+ let span = self.span();
+ let string = map_fn(self.string);
+ Ident::new(string.as_ref(), span).into()
+ }
+}
+
+impl AsRef<Ident> for IdentString {
+ fn as_ref(&self) -> &Ident {
+ self.as_ident()
+ }
+}
+
+impl AsRef<str> for IdentString {
+ fn as_ref(&self) -> &str {
+ self.as_str()
+ }
+}
+
+impl From<Ident> for IdentString {
+ fn from(ident: Ident) -> Self {
+ IdentString::new(ident)
+ }
+}
+
+impl From<IdentString> for Ident {
+ fn from(v: IdentString) -> Ident {
+ v.ident
+ }
+}
+
+impl From<IdentString> for String {
+ fn from(v: IdentString) -> String {
+ v.string
+ }
+}
+
+impl Eq for IdentString {}
+
+impl PartialEq for IdentString {
+ fn eq(&self, rhs: &Self) -> bool {
+ self.ident == rhs.ident
+ }
+}
+
+impl PartialEq<String> for IdentString {
+ fn eq(&self, rhs: &String) -> bool {
+ self.as_str() == rhs
+ }
+}
+
+impl<'a> PartialEq<&'a str> for IdentString {
+ fn eq(&self, rhs: &&str) -> bool {
+ self.as_str() == *rhs
+ }
+}
+
+impl Hash for IdentString {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.ident.hash(state);
+ }
+}
+
+impl ToTokens for IdentString {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.ident.to_tokens(tokens);
+ }
+}
+
+impl fmt::Debug for IdentString {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{:?}", self.ident)
+ }
+}
+
+impl fmt::Display for IdentString {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.ident)
+ }
+}
+
+impl FromMeta for IdentString {
+ fn from_meta(item: &Meta) -> Result<Self> {
+ Ident::from_meta(item).map(IdentString::from)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::IdentString;
+
+ #[test]
+ fn convert() {
+ let i_str = IdentString::new(parse_quote!(t));
+ assert_eq!(i_str.as_str(), "t");
+ }
+
+ #[test]
+ fn map_transform() {
+ let i = IdentString::new(parse_quote!(my));
+ let after = i.map(|v| format!("var_{}", v));
+ assert_eq!(after, "var_my");
+ assert_eq!(after, String::from("var_my"));
+ }
+}
diff --git a/third_party/rust/darling_core/src/util/ignored.rs b/third_party/rust/darling_core/src/util/ignored.rs
new file mode 100644
index 0000000000..9347fb4331
--- /dev/null
+++ b/third_party/rust/darling_core/src/util/ignored.rs
@@ -0,0 +1,52 @@
+use syn;
+
+use usage::{self, UsesLifetimes, UsesTypeParams};
+use {
+ FromDeriveInput, FromField, FromGenericParam, FromGenerics, FromMeta, FromTypeParam,
+ FromVariant, Result,
+};
+
+/// An efficient way of discarding data from a syntax element.
+///
+/// All syntax elements will be successfully read into
+/// the `Ignored` struct, with all properties discarded.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
+pub struct Ignored;
+
+macro_rules! ignored {
+ ($trayt:ident, $method:ident, $syn:path) => {
+ impl $trayt for Ignored {
+ fn $method(_: &$syn) -> Result<Self> {
+ Ok(Ignored)
+ }
+ }
+ };
+}
+
+ignored!(FromGenericParam, from_generic_param, syn::GenericParam);
+ignored!(FromGenerics, from_generics, syn::Generics);
+ignored!(FromTypeParam, from_type_param, syn::TypeParam);
+ignored!(FromMeta, from_meta, syn::Meta);
+ignored!(FromDeriveInput, from_derive_input, syn::DeriveInput);
+ignored!(FromField, from_field, syn::Field);
+ignored!(FromVariant, from_variant, syn::Variant);
+
+impl UsesTypeParams for Ignored {
+ fn uses_type_params<'a>(
+ &self,
+ _opts: &usage::Options,
+ _: &'a usage::IdentSet,
+ ) -> usage::IdentRefSet<'a> {
+ Default::default()
+ }
+}
+
+impl UsesLifetimes for Ignored {
+ fn uses_lifetimes<'a>(
+ &self,
+ _opts: &usage::Options,
+ _: &'a usage::LifetimeSet,
+ ) -> usage::LifetimeRefSet<'a> {
+ Default::default()
+ }
+}
diff --git a/third_party/rust/darling_core/src/util/mod.rs b/third_party/rust/darling_core/src/util/mod.rs
new file mode 100644
index 0000000000..1058381cdc
--- /dev/null
+++ b/third_party/rust/darling_core/src/util/mod.rs
@@ -0,0 +1,112 @@
+//! Utility types for attribute parsing.
+
+use std::ops::{BitAnd, BitOr, Deref, Not};
+
+use syn;
+use {FromMeta, Result};
+
+mod ident_string;
+mod ignored;
+mod over_ride;
+mod path_list;
+mod with_original;
+mod spanned_value;
+
+pub use self::ident_string::IdentString;
+pub use self::ignored::Ignored;
+pub use self::over_ride::Override;
+pub use self::path_list::PathList;
+pub use self::spanned_value::SpannedValue;
+pub use self::with_original::WithOriginal;
+
+/// Marker type equivalent to `Option<()>` for use in attribute parsing.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
+pub struct Flag(Option<()>);
+
+impl Flag {
+ /// Creates a new `Flag` which corresponds to the presence of a value.
+ pub fn present() -> Self {
+ Flag(Some(()))
+ }
+}
+
+impl Deref for Flag {
+ type Target = Option<()>;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl FromMeta for Flag {
+ fn from_meta(mi: &syn::Meta) -> Result<Self> {
+ FromMeta::from_meta(mi).map(Flag)
+ }
+}
+
+impl From<Flag> for bool {
+ fn from(flag: Flag) -> Self {
+ flag.is_some()
+ }
+}
+
+impl From<bool> for Flag {
+ fn from(v: bool) -> Self {
+ if v {
+ Flag::present()
+ } else {
+ Flag(None)
+ }
+ }
+}
+
+impl From<Option<()>> for Flag {
+ fn from(v: Option<()>) -> Self {
+ Flag::from(v.is_some())
+ }
+}
+
+impl PartialEq<Option<()>> for Flag {
+ fn eq(&self, rhs: &Option<()>) -> bool {
+ self.0 == *rhs
+ }
+}
+
+impl PartialEq<Flag> for Option<()> {
+ fn eq(&self, rhs: &Flag) -> bool {
+ *self == rhs.0
+ }
+}
+
+impl PartialEq<bool> for Flag {
+ fn eq(&self, rhs: &bool) -> bool {
+ self.is_some() == *rhs
+ }
+}
+
+impl Not for Flag {
+ type Output = Self;
+
+ fn not(self) -> Self {
+ if self.is_some() {
+ Flag(None)
+ } else {
+ Flag::present()
+ }
+ }
+}
+
+impl BitAnd for Flag {
+ type Output = Self;
+
+ fn bitand(self, rhs: Self) -> Self {
+ (self.into() && rhs.into()).into()
+ }
+}
+
+impl BitOr for Flag {
+ type Output = Self;
+
+ fn bitor(self, rhs: Self) -> Self {
+ (self.into() || rhs.into()).into()
+ }
+}
diff --git a/third_party/rust/darling_core/src/util/over_ride.rs b/third_party/rust/darling_core/src/util/over_ride.rs
new file mode 100644
index 0000000000..5223a023d0
--- /dev/null
+++ b/third_party/rust/darling_core/src/util/over_ride.rs
@@ -0,0 +1,150 @@
+use std::fmt;
+
+use syn::{Lit, NestedMeta};
+
+use {FromMeta, Result};
+
+use self::Override::*;
+
+/// A value which can inherit a default value or have an explicit value specified.
+///
+/// # Usage
+/// This type is meant for attributes like `default` in `darling`, which can take the following forms:
+///
+/// * `#[darling(default)]`
+/// * `#[darling(default="path::to::fn")]`
+///
+/// In a struct collecting input for this attribute, that would be written as:
+///
+/// ```rust,ignore
+/// # #[macro_use]
+/// # extern crate darling;
+/// # extern crate syn;
+/// use darling::util::Override;
+/// #[derive(FromField)]
+/// #[darling(attributes(darling))]
+/// pub struct Options {
+/// default: Option<Override<syn::Path>>,
+/// }
+///
+/// impl Options {
+/// fn hydrate(self) -> Option<syn::Path> {
+/// self.default.map(|ov| ov.unwrap_or(syn::parse_path("::Default::default").unwrap()))
+/// }
+/// }
+/// ```
+///
+/// The `word` format (with no associated value), would produce `Override::Inherit`, while a list
+/// or value format would produce `Override::Explicit`.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum Override<T> {
+ /// Inherit the eventual value from an external source.
+ Inherit,
+
+ /// Explicitly set the value.
+ Explicit(T),
+}
+
+impl<T> Override<T> {
+ /// Converts from `Override<T>` to `Override<&T>`.
+ ///
+ /// Produces a new `Override`, containing a reference into the original, leaving the original in place.
+ pub fn as_ref<'a>(&'a self) -> Override<&'a T> {
+ match *self {
+ Inherit => Inherit,
+ Explicit(ref val) => Explicit(val),
+ }
+ }
+
+ /// Converts from `Override<T>` to `Override<&mut T>`.
+ ///
+ /// Produces a new `Override`, containing a mutable reference into the original.
+ pub fn as_mut<'a>(&'a mut self) -> Override<&'a mut T> {
+ match *self {
+ Inherit => Inherit,
+ Explicit(ref mut val) => Explicit(val),
+ }
+ }
+
+ /// Returns `true` if the override is an `Explicit` value.
+ pub fn is_explicit(&self) -> bool {
+ match *self {
+ Inherit => false,
+ Explicit(_) => true,
+ }
+ }
+
+ /// Converts from `Override<T>` to `Option<T>`.
+ pub fn explicit(self) -> Option<T> {
+ match self {
+ Inherit => None,
+ Explicit(val) => Some(val),
+ }
+ }
+
+ /// Unwraps an override, yielding the content of an `Explicit`. Otherwise, it returns `optb`.
+ pub fn unwrap_or(self, optb: T) -> T {
+ match self {
+ Inherit => optb,
+ Explicit(val) => val,
+ }
+ }
+
+ /// Unwraps an override, yielding the content of an `Explicit`. Otherwise, it calls `op`.
+ pub fn unwrap_or_else<F>(self, op: F) -> T
+ where
+ F: FnOnce() -> T,
+ {
+ match self {
+ Inherit => op(),
+ Explicit(val) => val,
+ }
+ }
+}
+
+impl<T: Default> Override<T> {
+ /// Returns the contained value or the default value of `T`.
+ pub fn unwrap_or_default(self) -> T {
+ self.unwrap_or_else(Default::default)
+ }
+}
+
+impl<T> Default for Override<T> {
+ fn default() -> Self {
+ Inherit
+ }
+}
+
+impl<T> From<Option<T>> for Override<T> {
+ fn from(v: Option<T>) -> Self {
+ match v {
+ None => Inherit,
+ Some(val) => Explicit(val),
+ }
+ }
+}
+
+impl<T: fmt::Display> fmt::Display for Override<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ Inherit => write!(f, "Inherit"),
+ Explicit(ref val) => write!(f, "Explicit `{}`", val),
+ }
+ }
+}
+
+/// Parses a `Meta`. A bare word will produce `Override::Inherit`, while
+/// any value will be forwarded to `T::from_meta`.
+impl<T: FromMeta> FromMeta for Override<T> {
+ fn from_word() -> Result<Self> {
+ Ok(Inherit)
+ }
+
+ fn from_list(items: &[NestedMeta]) -> Result<Self> {
+ Ok(Explicit(FromMeta::from_list(items)?))
+ }
+
+ fn from_value(lit: &Lit) -> Result<Self> {
+ Ok(Explicit(FromMeta::from_value(lit)?))
+ }
+}
diff --git a/third_party/rust/darling_core/src/util/path_list.rs b/third_party/rust/darling_core/src/util/path_list.rs
new file mode 100644
index 0000000000..069aa6a177
--- /dev/null
+++ b/third_party/rust/darling_core/src/util/path_list.rs
@@ -0,0 +1,102 @@
+use std::ops::Deref;
+use std::string::ToString;
+
+use syn::{Meta, NestedMeta, Path};
+
+use {Error, FromMeta, Result};
+
+/// A list of `syn::Path` instances. This type is used to extract a list of paths from an
+/// attribute.
+///
+/// # Usage
+/// An `PathList` field on a struct implementing `FromMeta` will turn `#[builder(derive(serde::Debug, Clone))]` into:
+///
+/// ```rust,ignore
+/// StructOptions {
+/// derive: PathList(vec![syn::Path::new("serde::Debug"), syn::Path::new("Clone")])
+/// }
+/// ```
+#[derive(Debug, Default, Clone, PartialEq, Eq)]
+pub struct PathList(Vec<Path>);
+
+impl PathList {
+ /// Create a new list.
+ pub fn new<T: Into<Path>>(vals: Vec<T>) -> Self {
+ PathList(vals.into_iter().map(T::into).collect())
+ }
+
+ /// Create a new `Vec` containing the string representation of each path.
+ pub fn to_strings(&self) -> Vec<String> {
+ self.0.iter().map(|p| p.segments.iter().map(|s| s.ident.to_string()).collect::<Vec<String>>().join("::")).collect()
+ }
+}
+
+impl Deref for PathList {
+ type Target = Vec<Path>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl From<Vec<Path>> for PathList {
+ fn from(v: Vec<Path>) -> Self {
+ PathList(v)
+ }
+}
+
+impl FromMeta for PathList {
+ fn from_list(v: &[NestedMeta]) -> Result<Self> {
+ let mut paths = Vec::with_capacity(v.len());
+ for nmi in v {
+ if let NestedMeta::Meta(Meta::Path(ref path)) = *nmi {
+ paths.push(path.clone());
+ } else {
+ return Err(Error::unexpected_type("non-word").with_span(nmi));
+ }
+ }
+
+ Ok(PathList(paths))
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::PathList;
+ use proc_macro2::TokenStream;
+ use syn::{Attribute, Meta};
+ use FromMeta;
+
+ /// parse a string as a syn::Meta instance.
+ fn pm(tokens: TokenStream) -> ::std::result::Result<Meta, String> {
+ let attribute: Attribute = parse_quote!(#[#tokens]);
+ attribute.parse_meta().map_err(|_| "Unable to parse".into())
+ }
+
+ fn fm<T: FromMeta>(tokens: TokenStream) -> T {
+ FromMeta::from_meta(&pm(tokens).expect("Tests should pass well-formed input"))
+ .expect("Tests should pass valid input")
+ }
+
+ #[test]
+ fn succeeds() {
+ let paths = fm::<PathList>(quote!(ignore(Debug, Clone, Eq)));
+ assert_eq!(
+ paths.to_strings(),
+ vec![
+ String::from("Debug"),
+ String::from("Clone"),
+ String::from("Eq")
+ ]
+ );
+ }
+
+ /// Check that the parser rejects non-word members of the list, and that the error
+ /// has an associated span.
+ #[test]
+ fn fails_non_word() {
+ let input = PathList::from_meta(&pm(quote!(ignore(Debug, Clone = false))).unwrap());
+ let err = input.unwrap_err();
+ assert!(err.has_span());
+ }
+}
diff --git a/third_party/rust/darling_core/src/util/spanned_value.rs b/third_party/rust/darling_core/src/util/spanned_value.rs
new file mode 100644
index 0000000000..1ea3dfc703
--- /dev/null
+++ b/third_party/rust/darling_core/src/util/spanned_value.rs
@@ -0,0 +1,104 @@
+use proc_macro2::Span;
+use std::ops::{Deref, DerefMut};
+use syn;
+use syn::spanned::Spanned;
+use {
+ FromDeriveInput, FromField, FromGenericParam, FromGenerics, FromMeta, FromTypeParam,
+ FromVariant, Result,
+};
+
+/// A value and an associated position in source code. The main use case for this is
+/// to preserve position information to emit warnings from proc macros. You can use
+/// a `SpannedValue<T>` as a field in any struct that implements or derives any of
+/// `darling`'s core traits.
+///
+/// To access the underlying value, use the struct's `Deref` implementation.
+///
+/// # Defaulting
+/// This type is meant to be used in conjunction with attribute-extracted options,
+/// but the user may not always explicitly set those options in their source code.
+/// In this case, using `Default::default()` will create an instance which points
+/// to `Span::call_site()`.
+#[derive(Debug, Clone)]
+pub struct SpannedValue<T> {
+ value: T,
+ span: Span,
+}
+
+impl<T> SpannedValue<T> {
+ pub fn new(value: T, span: Span) -> Self {
+ SpannedValue { value, span }
+ }
+
+ /// Get the source code location referenced by this struct.
+ pub fn span(&self) -> Span {
+ self.span
+ }
+}
+
+impl<T: Default> Default for SpannedValue<T> {
+ fn default() -> Self {
+ SpannedValue::new(Default::default(), Span::call_site())
+ }
+}
+
+impl<T> Deref for SpannedValue<T> {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ &self.value
+ }
+}
+
+impl<T> DerefMut for SpannedValue<T> {
+ fn deref_mut(&mut self) -> &mut T {
+ &mut self.value
+ }
+}
+
+impl<T> AsRef<T> for SpannedValue<T> {
+ fn as_ref(&self) -> &T {
+ &self.value
+ }
+}
+
+macro_rules! spanned {
+ ($trayt:ident, $method:ident, $syn:path) => {
+ impl<T: $trayt> $trayt for SpannedValue<T> {
+ fn $method(value: &$syn) -> Result<Self> {
+ Ok(SpannedValue::new(
+ $trayt::$method(value).map_err(|e| e.with_span(value))?,
+ value.span(),
+ ))
+ }
+ }
+ };
+}
+
+spanned!(FromGenericParam, from_generic_param, syn::GenericParam);
+spanned!(FromGenerics, from_generics, syn::Generics);
+spanned!(FromTypeParam, from_type_param, syn::TypeParam);
+spanned!(FromMeta, from_meta, syn::Meta);
+spanned!(FromDeriveInput, from_derive_input, syn::DeriveInput);
+spanned!(FromField, from_field, syn::Field);
+spanned!(FromVariant, from_variant, syn::Variant);
+
+impl<T: Spanned> From<T> for SpannedValue<T> {
+ fn from(value: T) -> Self {
+ let span = value.span();
+ SpannedValue::new(value, span)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use proc_macro2::Span;
+
+ /// Make sure that `SpannedValue` can be seamlessly used as its underlying type.
+ #[test]
+ fn deref() {
+ let test = SpannedValue::new("hello", Span::call_site());
+ assert_eq!("hello", test.trim());
+ }
+}
diff --git a/third_party/rust/darling_core/src/util/with_original.rs b/third_party/rust/darling_core/src/util/with_original.rs
new file mode 100644
index 0000000000..e53264bb45
--- /dev/null
+++ b/third_party/rust/darling_core/src/util/with_original.rs
@@ -0,0 +1,35 @@
+use syn;
+
+use {FromDeriveInput, FromField, FromGenericParam, FromGenerics, FromMeta, FromTypeParam,
+ FromVariant, Result};
+
+/// A container to parse some syntax and retain access to the original.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct WithOriginal<T, O> {
+ pub parsed: T,
+ pub original: O,
+}
+
+impl<T, O> WithOriginal<T, O> {
+ pub fn new(parsed: T, original: O) -> Self {
+ WithOriginal { parsed, original }
+ }
+}
+
+macro_rules! with_original {
+ ($trayt:ident, $func:ident, $syn:path) => {
+ impl<T: $trayt> $trayt for WithOriginal<T, $syn> {
+ fn $func(value: &$syn) -> Result<Self> {
+ Ok(WithOriginal::new($trayt::$func(value)?, value.clone()))
+ }
+ }
+ };
+}
+
+with_original!(FromDeriveInput, from_derive_input, syn::DeriveInput);
+with_original!(FromField, from_field, syn::Field);
+with_original!(FromGenerics, from_generics, syn::Generics);
+with_original!(FromGenericParam, from_generic_param, syn::GenericParam);
+with_original!(FromMeta, from_meta, syn::Meta);
+with_original!(FromTypeParam, from_type_param, syn::TypeParam);
+with_original!(FromVariant, from_variant, syn::Variant);
diff --git a/third_party/rust/darling_macro/.cargo-checksum.json b/third_party/rust/darling_macro/.cargo-checksum.json
new file mode 100644
index 0000000000..2f56ee886e
--- /dev/null
+++ b/third_party/rust/darling_macro/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"772583c440b7413dfc8fe74b455978310f5a9b321733c973bdaeb1cd21cfb2ca","LICENSE":"8ea93490d74a5a1b1af3ff71d786271b3f1e5f0bea79ac16e02ec533cef040d6","src/lib.rs":"88141a58dc13b9001a83ca7559b6213ab44641510b6d642a3280c244ad735cec"},"package":"0cd3e432e52c0810b72898296a69d66b1d78d1517dff6cde7a130557a55a62c1"} \ No newline at end of file
diff --git a/third_party/rust/darling_macro/Cargo.toml b/third_party/rust/darling_macro/Cargo.toml
new file mode 100644
index 0000000000..61f76a70c3
--- /dev/null
+++ b/third_party/rust/darling_macro/Cargo.toml
@@ -0,0 +1,30 @@
+# 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 believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "darling_macro"
+version = "0.10.1"
+authors = ["Ted Driggs <ted.driggs@outlook.com>"]
+description = "Internal support for a proc-macro library for reading attributes into structs when\nimplementing custom derives. Use https://crates.io/crates/darling in your code.\n"
+license = "MIT"
+repository = "https://github.com/TedDriggs/darling"
+
+[lib]
+proc-macro = true
+[dependencies.darling_core]
+version = "=0.10.1"
+
+[dependencies.quote]
+version = "1"
+
+[dependencies.syn]
+version = "1"
diff --git a/third_party/rust/darling_macro/LICENSE b/third_party/rust/darling_macro/LICENSE
new file mode 100644
index 0000000000..0b48eadc9d
--- /dev/null
+++ b/third_party/rust/darling_macro/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017 Ted Driggs
+
+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/darling_macro/src/lib.rs b/third_party/rust/darling_macro/src/lib.rs
new file mode 100644
index 0000000000..629526c553
--- /dev/null
+++ b/third_party/rust/darling_macro/src/lib.rs
@@ -0,0 +1,41 @@
+extern crate proc_macro;
+#[macro_use]
+extern crate syn;
+
+extern crate darling_core;
+
+use proc_macro::TokenStream;
+
+use darling_core::{derive, Error};
+
+#[proc_macro_derive(FromMeta, attributes(darling))]
+pub fn derive_from_meta(input: TokenStream) -> TokenStream {
+ derive::from_meta(&parse_macro_input!(input)).into()
+}
+
+#[proc_macro_derive(FromMetaItem, attributes(darling))]
+pub fn derive_from_meta_item(_input: TokenStream) -> TokenStream {
+ Error::custom("darling::FromMetaItem has been replaced by darling::FromMeta")
+ .write_errors()
+ .into()
+}
+
+#[proc_macro_derive(FromDeriveInput, attributes(darling))]
+pub fn derive_from_input(input: TokenStream) -> TokenStream {
+ derive::from_derive_input(&parse_macro_input!(input)).into()
+}
+
+#[proc_macro_derive(FromField, attributes(darling))]
+pub fn derive_field(input: TokenStream) -> TokenStream {
+ derive::from_field(&parse_macro_input!(input)).into()
+}
+
+#[proc_macro_derive(FromTypeParam, attributes(darling))]
+pub fn derive_type_param(input: TokenStream) -> TokenStream {
+ derive::from_type_param(&parse_macro_input!(input)).into()
+}
+
+#[proc_macro_derive(FromVariant, attributes(darling))]
+pub fn derive_variant(input: TokenStream) -> TokenStream {
+ derive::from_variant(&parse_macro_input!(input)).into()
+}