summaryrefslogtreecommitdiffstats
path: root/third_party/rust/darling
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/darling')
-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
31 files changed, 2035 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();
+}