From 5b5bf2110c2c8be9a1bdd50e3c9611477523923e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Fri, 7 Dec 2018 09:00:57 -0500 Subject: [PATCH] Bug 1511811 - Revendor rust dependencies. --HG-- rename : third_party/rust/darling_core/src/macros.rs => third_party/rust/darling_core/src/macros_private.rs --- Cargo.lock | 66 +- third_party/rust/darling/.cargo-checksum.json | 2 +- third_party/rust/darling/CHANGELOG.md | 36 +- third_party/rust/darling/Cargo.toml | 15 +- third_party/rust/darling/README.md | 4 +- .../rust/darling/examples/automatic_bounds.rs | 77 + .../rust/darling/examples/consume_fields.rs | 34 +- .../rust/darling/examples/fallible_read.rs | 17 +- .../rust/darling/examples/supports_struct.rs | 63 + third_party/rust/darling/src/lib.rs | 56 +- third_party/rust/darling/src/macros_public.rs | 98 + .../rust/darling/tests/accrue_errors.rs | 37 +- .../rust/darling/tests/computed_bound.rs | 46 + .../rust/darling/tests/custom_bound.rs | 6 +- third_party/rust/darling/tests/defaults.rs | 32 + .../rust/darling/tests/enums_newtype.rs | 47 +- .../rust/darling/tests/enums_struct.rs | 17 +- third_party/rust/darling/tests/enums_unit.rs | 10 +- third_party/rust/darling/tests/error.rs | 14 +- .../rust/darling/tests/from_generics.rs | 186 ++ .../rust/darling/tests/from_type_param.rs | 63 + .../darling/tests/from_type_param_default.rs | 58 + .../rust/darling/tests/from_variant.rs | 4 +- third_party/rust/darling/tests/generics.rs | 9 +- third_party/rust/darling/tests/happy_path.rs | 52 +- third_party/rust/darling/tests/multiple.rs | 13 +- third_party/rust/darling/tests/newtype.rs | 12 +- third_party/rust/darling/tests/skip.rs | 23 +- .../rust/darling/tests/split_declaration.rs | 44 +- third_party/rust/darling/tests/supports.rs | 69 +- .../rust/darling_core/.cargo-checksum.json | 2 +- third_party/rust/darling_core/Cargo.toml | 11 +- .../darling_core/src/{ast.rs => ast/data.rs} | 94 +- .../rust/darling_core/src/ast/generics.rs | 194 ++ third_party/rust/darling_core/src/ast/mod.rs | 7 + .../src/codegen/attr_extractor.rs | 109 + .../darling_core/src/codegen/default_expr.rs | 9 +- .../rust/darling_core/src/codegen/error.rs | 17 +- .../rust/darling_core/src/codegen/field.rs | 28 +- .../src/codegen/from_derive_impl.rs | 104 +- .../darling_core/src/codegen/from_field.rs | 65 +- .../{fmi_impl.rs => from_meta_impl.rs} | 36 +- .../src/codegen/from_type_param.rs | 114 + .../src/codegen/from_variant_impl.rs | 50 +- .../rust/darling_core/src/codegen/mod.rs | 107 +- .../src/codegen/outer_from_impl.rs | 29 +- .../darling_core/src/codegen/trait_impl.rs | 89 +- .../rust/darling_core/src/codegen/variant.rs | 33 +- .../darling_core/src/codegen/variant_data.rs | 24 +- third_party/rust/darling_core/src/error.rs | 36 +- .../darling_core/src/from_derive_input.rs | 2 +- .../rust/darling_core/src/from_field.rs | 2 +- .../darling_core/src/from_generic_param.rs | 21 + .../rust/darling_core/src/from_generics.rs | 27 + .../src/{from_meta_item.rs => from_meta.rs} | 206 +- .../rust/darling_core/src/from_type_param.rs | 32 + .../rust/darling_core/src/from_variant.rs | 2 +- third_party/rust/darling_core/src/lib.rs | 27 +- .../src/{macros.rs => macros_private.rs} | 0 .../rust/darling_core/src/macros_public.rs | 98 + .../rust/darling_core/src/options/core.rs | 33 +- .../darling_core/src/options/forward_attrs.rs | 4 +- .../darling_core/src/options/from_derive.rs | 45 +- .../darling_core/src/options/from_field.rs | 29 +- .../{from_meta_item.rs => from_meta.rs} | 23 +- .../src/options/from_type_param.rs | 70 + .../darling_core/src/options/from_variant.rs | 35 +- .../darling_core/src/options/input_field.rs | 58 +- .../darling_core/src/options/input_variant.rs | 17 +- .../rust/darling_core/src/options/mod.rs | 54 +- .../darling_core/src/options/outer_from.rs | 36 +- .../rust/darling_core/src/options/shape.rs | 49 +- .../darling_core/src/usage/generics_ext.rs | 24 + .../rust/darling_core/src/usage/ident_set.rs | 8 + .../rust/darling_core/src/usage/lifetimes.rs | 322 +++ .../rust/darling_core/src/usage/mod.rs | 111 + .../rust/darling_core/src/usage/options.rs | 58 + .../darling_core/src/usage/type_params.rs | 362 +++ .../rust/darling_core/src/util/ident_list.rs | 19 +- .../darling_core/src/util/ident_string.rs | 148 ++ .../rust/darling_core/src/util/ignored.rs | 62 +- third_party/rust/darling_core/src/util/mod.rs | 22 +- .../rust/darling_core/src/util/over_ride.rs | 25 +- .../darling_core/src/util/with_original.rs | 35 + .../rust/darling_macro/.cargo-checksum.json | 2 +- third_party/rust/darling_macro/Cargo.toml | 8 +- third_party/rust/darling_macro/src/lib.rs | 37 +- third_party/rust/fnv/.cargo-checksum.json | 2 +- third_party/rust/fnv/Cargo.toml | 20 +- third_party/rust/fnv/LICENSE-APACHE | 201 ++ third_party/rust/fnv/LICENSE-MIT | 25 + third_party/rust/fnv/README.md | 2 +- third_party/rust/fnv/lib.rs | 2 +- .../synstructure-0.8.1/.cargo-checksum.json | 1 - .../rust/synstructure-0.8.1/Cargo.toml | 40 - third_party/rust/synstructure-0.8.1/LICENSE | 7 - third_party/rust/synstructure-0.8.1/README.md | 157 -- .../rust/synstructure-0.8.1/src/lib.rs | 2226 ----------------- .../rust/synstructure-0.8.1/src/macros.rs | 411 --- 99 files changed, 3873 insertions(+), 3702 deletions(-) create mode 100644 third_party/rust/darling/examples/automatic_bounds.rs create mode 100644 third_party/rust/darling/examples/supports_struct.rs create mode 100644 third_party/rust/darling/src/macros_public.rs create mode 100644 third_party/rust/darling/tests/computed_bound.rs create mode 100644 third_party/rust/darling/tests/defaults.rs create mode 100644 third_party/rust/darling/tests/from_generics.rs create mode 100644 third_party/rust/darling/tests/from_type_param.rs create mode 100644 third_party/rust/darling/tests/from_type_param_default.rs rename third_party/rust/darling_core/src/{ast.rs => ast/data.rs} (76%) create mode 100644 third_party/rust/darling_core/src/ast/generics.rs create mode 100644 third_party/rust/darling_core/src/ast/mod.rs create mode 100644 third_party/rust/darling_core/src/codegen/attr_extractor.rs rename third_party/rust/darling_core/src/codegen/{fmi_impl.rs => from_meta_impl.rs} (80%) create mode 100644 third_party/rust/darling_core/src/codegen/from_type_param.rs create mode 100644 third_party/rust/darling_core/src/from_generic_param.rs create mode 100644 third_party/rust/darling_core/src/from_generics.rs rename third_party/rust/darling_core/src/{from_meta_item.rs => from_meta.rs} (56%) create mode 100644 third_party/rust/darling_core/src/from_type_param.rs rename third_party/rust/darling_core/src/{macros.rs => macros_private.rs} (100%) create mode 100644 third_party/rust/darling_core/src/macros_public.rs rename third_party/rust/darling_core/src/options/{from_meta_item.rs => from_meta.rs} (59%) create mode 100644 third_party/rust/darling_core/src/options/from_type_param.rs create mode 100644 third_party/rust/darling_core/src/usage/generics_ext.rs create mode 100644 third_party/rust/darling_core/src/usage/ident_set.rs create mode 100644 third_party/rust/darling_core/src/usage/lifetimes.rs create mode 100644 third_party/rust/darling_core/src/usage/mod.rs create mode 100644 third_party/rust/darling_core/src/usage/options.rs create mode 100644 third_party/rust/darling_core/src/usage/type_params.rs create mode 100644 third_party/rust/darling_core/src/util/ident_string.rs create mode 100644 third_party/rust/darling_core/src/util/with_original.rs create mode 100644 third_party/rust/fnv/LICENSE-APACHE create mode 100644 third_party/rust/fnv/LICENSE-MIT delete mode 100644 third_party/rust/synstructure-0.8.1/.cargo-checksum.json delete mode 100644 third_party/rust/synstructure-0.8.1/Cargo.toml delete mode 100644 third_party/rust/synstructure-0.8.1/LICENSE delete mode 100644 third_party/rust/synstructure-0.8.1/README.md delete mode 100644 third_party/rust/synstructure-0.8.1/src/lib.rs delete mode 100644 third_party/rust/synstructure-0.8.1/src/macros.rs diff --git a/Cargo.lock b/Cargo.lock index 858204d6aeca..1db7eea552e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -181,7 +181,7 @@ dependencies = [ name = "bench-collections-gtest" version = "0.1.0" dependencies = [ - "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -677,32 +677,33 @@ dependencies = [ [[package]] name = "darling" -version = "0.4.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "darling_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "darling_macro 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "darling_core 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "darling_macro 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "darling_core" -version = "0.4.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "ident_case 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "darling_macro" -version = "0.4.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "darling_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "darling_core 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -895,7 +896,7 @@ dependencies = [ [[package]] name = "fnv" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1102,7 +1103,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1125,7 +1126,7 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1432,9 +1433,9 @@ dependencies = [ name = "malloc_size_of_derive" version = "0.0.1" dependencies = [ - "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.7 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2408,10 +2409,11 @@ dependencies = [ name = "style_derive" version = "0.0.1" dependencies = [ - "darling 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "darling 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.7 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2479,17 +2481,6 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "synstructure" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "synstructure" version = "0.10.1" @@ -3182,9 +3173,9 @@ dependencies = [ "checksum cubeb-backend 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcac95519416d9ec814db2dc40e6293e7da25b906023d93f48b87f0587ab138" "checksum cubeb-core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37f7b20f757a4e4b6aa28863236551bff77682dc6db192eba15af615492b5445" "checksum cubeb-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "653b9e245d35dbe2a2da7c4586275cee75ff656ddeb02d4a73b4afdfa6d67502" -"checksum darling 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2a78af487e4eb8f4421a1770687b328af6bb4494ca93435210678c6eea875c11" -"checksum darling_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b315f49c7b6db3708bca6e6913c194581a44ec619b7a39e131d4dd63733a3698" -"checksum darling_macro 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eb69a38fdeaeaf3db712e1df170de67ee9dfc24fb88ca3e9d21e703ec25a4d8e" +"checksum darling 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f000e7b03a0083a30e1f10b1428a530849c21e72b338fa76869b5dbc4b045bf" +"checksum darling_core 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "86bc5ce438f4b703755d12f59bbf0a16c642766d4534e922db47569dbdd0b998" +"checksum darling_macro 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9973050ba46be2a2935a7b316147f41a808ac604b8f0fef6eba77fd47a89daeb" "checksum devd-rs 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7c9ac481c38baf400d3b732e4a06850dfaa491d1b6379a249d9d40d14c2434c" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" "checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" @@ -3205,7 +3196,7 @@ dependencies = [ "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum fixedbitset 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "85cb8fec437468d86dc7c83ca7cfc933341d561873275f22dd5eedefa63a6478" "checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909" -"checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344" +"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ebc04f19019fff1f2d627b5581574ead502f80c48c88900575a46e0840fe5d0" "checksum freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b659e75b7a7338fe75afd7f909fc2b71937845cffb6ebe54ba2e50f13d8e903d" "checksum fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" @@ -3346,7 +3337,6 @@ dependencies = [ "checksum syn 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4e4b5274d4a0a3d2749d5c158dc64d3403e60554dc61194648787ada5212473d" "checksum syn 0.15.7 (registry+https://github.com/rust-lang/crates.io-index)" = "455a6ec9b368f8c479b0ae5494d13b22dc00990d2f00d68c9dc6a2dc4f17f210" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" -"checksum synstructure 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "98cad891cd238c98e1f0aec9f7c0f620aa696e4e5f7daba56ac67b5e86a6b049" "checksum target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4af5e2227f0b887d591d3724b796a96eff04226104d872f5b3883fcd427d64b9" "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" diff --git a/third_party/rust/darling/.cargo-checksum.json b/third_party/rust/darling/.cargo-checksum.json index 7ae00179dc54..7f95c847382a 100644 --- a/third_party/rust/darling/.cargo-checksum.json +++ b/third_party/rust/darling/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"d7322023ffc58d041c542f8de0f43167f34ba4fdacc9a5014308d97055f7b729","Cargo.toml":"c1d8f7f99c24eb373e5aefaf3c678eea57d72552fdbb3547872b62b0d28aa07f","LICENSE":"8ea93490d74a5a1b1af3ff71d786271b3f1e5f0bea79ac16e02ec533cef040d6","README.md":"7e05868f02bae698ee3193b86e86f25faa4dbc63661062e1d3f7bff590cfb313","examples/consume_fields.rs":"f32d3873b61e22b1ded500571ec7120420b4825ee7f807d07409e3a257407add","examples/fallible_read.rs":"4e2d558f8a77c4fffa79bde5a6c48df3dbc932822e7bc7cf0a903d1ea38b8d6f","publish.sh":"42795a155247c69402f8c4c917c9874a06dfde5a7606c8b59fc4e9ccd34233dd","src/lib.rs":"c13e19cd0363784d9ec3605bafcaf74648594fb419162143c4ecc3308a8ec695","tests/accrue_errors.rs":"7a995118cfa75ac90accf9a35e17b07a00e8528c8ccc5dd8700ba7b4c59393c1","tests/custom_bound.rs":"cca7c557ac0a2efd9554d31f0df9a98c4f6f01b9f211107846732cc1fe9f7856","tests/enums_newtype.rs":"328ebbbb4aa540f06f13158dff22cf9d98d45dba2331f75e4aa169d348397b76","tests/enums_struct.rs":"560a8bfdea9eca7f8c2024bc8740e71ef1a0681cea36b098ceadba520fad8640","tests/enums_unit.rs":"5e9458af9d695706e181b6622dcbc8b80b9eae33dcc1f15da7eecfd3e7037777","tests/error.rs":"69d12e969555fc1d72990d7596b54adcb469da95f1f257d0273f31bc9c855db5","tests/from_variant.rs":"af60c9dec64e80e2ac3beafb942d8edc1100a1342bb97378e6a35f878dd1fb50","tests/generics.rs":"3d884d65cb6b57d4bc4b3f7c39f321b2df3cd339fa15db5b66dc7c97ef84df17","tests/happy_path.rs":"5143dbf33b59fcab94be61affefddf485857f1a5cb3d45d5583463423d417cdf","tests/multiple.rs":"20e1c5110449db46df68c5a4cdb6e0c4c0e9a6b47451fe73f1523a1cf730196d","tests/newtype.rs":"a8709857e2067bc01b388a11230db5764c9e5fe2341c98d6c819adc01472b988","tests/skip.rs":"e34034c6b5fae80c8cf2caa762a41ab3d971f8af50f1022e68ba299218477892","tests/split_declaration.rs":"d55219ec0dce001ccd1975f0b4fbe0f5e8c5792a1ddf2de5a210d380bc6761e0","tests/supports.rs":"1131c2afd42e20e4a39f922758cbb8d7c5a0167ae41f9cd1cd14b40db055cd10"},"package":"2a78af487e4eb8f4421a1770687b328af6bb4494ca93435210678c6eea875c11"} \ No newline at end of file +{"files":{"CHANGELOG.md":"06091817afa317ff86efb9aee3fa8d165358150a92c6369e4ab2958765c14af8","Cargo.toml":"82b023db972c6554f198cc926eaca456f945d6ac2cdc4df65cdeb5b186a1ced0","LICENSE":"8ea93490d74a5a1b1af3ff71d786271b3f1e5f0bea79ac16e02ec533cef040d6","README.md":"f70d772dd28cd14fc817c71d343b07ec8bfbe02dfe8d3e999a0185c6ef8731ec","examples/automatic_bounds.rs":"2716da31a5beed954da77866779ef77600686688a8890fefa7e23db628358104","examples/consume_fields.rs":"abcdd6a919a95a5c295e8d362db0367ab171fe3c8a80b23d83701765cd902d2d","examples/fallible_read.rs":"e06d5c045d3a47c0e00d3c77ed3aa1a1d5173d2c3f462dc1967379db3094af4c","examples/supports_struct.rs":"f2d84a4377e555ed7535e563c9593bd6a398a63b42f7da72381eea2fccec229f","publish.sh":"42795a155247c69402f8c4c917c9874a06dfde5a7606c8b59fc4e9ccd34233dd","src/lib.rs":"07da20edb52c4aba30f2b680b28ca96cf995859566b0db3b1d2e0ee967249a18","src/macros_public.rs":"3ed7eb99f309d9cd600d3a09ff4dcf5cc5d787fb49e8e5ead6bb00e31e5e6793","tests/accrue_errors.rs":"f873acf2a13dba88f508c3eb118d14e36515bf94b7ee914ddec2ae1eb55e381f","tests/computed_bound.rs":"2313da96a250b5948ca06bf86cb7158b55a59eba75334aa8ba27a46b28ede6b5","tests/custom_bound.rs":"4dd3e8fd76734d8f262e857773f53a820229ad6e10fe6fbbbe1f636c7da9eab0","tests/defaults.rs":"b544be90d18be26305a757e8468bf8735356889b59c167294d118e32ee7f82ea","tests/enums_newtype.rs":"723c761eab356f577e804a5e07f5efa244f70fb7525d20fceb1bc3852c8d742e","tests/enums_struct.rs":"e0097d7f947cf9e4612c9450c55ea5075c7f6fcbbf8cac7176449d92eebc9343","tests/enums_unit.rs":"8c075d5897b60b58cb71d6306e7fdd80851f5a147ae3010ba70ea100007364a3","tests/error.rs":"f989a43fad47d61d75da2bc78af6c51bac549f39f14f87a804eea226308ece32","tests/from_generics.rs":"79230ad21e8482cf6e6ceb0c74303bc0cdf77fbb951f46a6ba1006ecf1248fd5","tests/from_type_param.rs":"4369737a9d4c21cfa8595a9159cd5d98d02af3445d8b4085654ad4ce8e8bba3f","tests/from_type_param_default.rs":"a5ee72f22540004e755445c37dd4c425ef12beef496896d608695bae964afe7f","tests/from_variant.rs":"2e804326302a62b979eae963e88f0a2cdb6a21ee9667407c361d178f8c0aadba","tests/generics.rs":"3c0f43b39a8f319b8318e409d3836c7235892ae4f50f5986ea80f69b80a4080b","tests/happy_path.rs":"13cf6cd5f87920d90762fd08e45d9f0bb378563e1c92cf5ffb3ba78decdc4969","tests/multiple.rs":"b76172c396a89414b1669eec2bf854c79a7215fd3b6977123b81591ac6761670","tests/newtype.rs":"c45842fd764174a6a8177851e15445d344ab93bf2124b5f77213780d1306adea","tests/skip.rs":"fd936a5eff92c0a49b0a900e6fcda6b7a10a83dd4096ae2000201ccb3f66a738","tests/split_declaration.rs":"b191ed446bf7b8fdf1d41059354adb4b155523507f37b0d36aed3347617a2492","tests/supports.rs":"acb53d4d810dcd3e46763db13234e4fb42e425cfde2516d9bf5d7b690be72dcc"},"package":"7f000e7b03a0083a30e1f10b1428a530849c21e72b338fa76869b5dbc4b045bf"} \ No newline at end of file diff --git a/third_party/rust/darling/CHANGELOG.md b/third_party/rust/darling/CHANGELOG.md index 3cd7c3832a47..2ec5d8675b2b 100644 --- a/third_party/rust/darling/CHANGELOG.md +++ b/third_party/rust/darling/CHANGELOG.md @@ -1,7 +1,37 @@ # Changelog -## Unreleased Features -_None_ +## 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 @@ -36,4 +66,4 @@ _None_ - 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) \ No newline at end of file +- 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 index 32fd8074e97f..287c833195e9 100644 --- a/third_party/rust/darling/Cargo.toml +++ b/third_party/rust/darling/Cargo.toml @@ -12,22 +12,25 @@ [package] name = "darling" -version = "0.4.0" +version = "0.8.0" authors = ["Ted Driggs "] description = "A proc-macro library for reading attributes into structs when\nimplementing custom derives.\n" -documentation = "https://docs.rs/darling/0.4.0" +documentation = "https://docs.rs/darling/0.8.0" readme = "README.md" license = "MIT" repository = "https://github.com/TedDriggs/darling" [dependencies.darling_core] -version = "=0.4.0" +version = "=0.8.0" [dependencies.darling_macro] -version = "=0.4.0" +version = "=0.8.0" +[dev-dependencies.proc-macro2] +version = "0.4" + [dev-dependencies.quote] -version = "0.5" +version = "0.6" [dev-dependencies.syn] -version = "0.13" +version = "0.15" [badges.travis-ci] repository = "TedDriggs/darling" diff --git a/third_party/rust/darling/README.md b/third_party/rust/darling/README.md index 4a8779a51f63..9919e722236b 100644 --- a/third_party/rust/darling/README.md +++ b/third_party/rust/darling/README.md @@ -9,7 +9,7 @@ Darling # Usage `darling` provides a set of traits which can be derived or manually implemented. -1. `FromMetaItem` 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. +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. 1. `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. 1. `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. @@ -20,7 +20,7 @@ Darling extern crate darling; extern crate syn; -#[derive(Default, FromMetaItem)] +#[derive(Default, FromMeta)] #[darling(default)] pub struct Lorem { #[darling(rename = "sit")] 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 000000000000..06263f147f71 --- /dev/null +++ b/third_party/rust/darling/examples/automatic_bounds.rs @@ -0,0 +1,77 @@ +#[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 { + Constant(Volume), + Variable(darling::util::IdentList), + #[darling(skip)] + PerPhoneme(Option), + Strided { + #[darling(skip)] + step: Vec, + #[darling(multiple)] + volume: Vec, + }, +} + +#[derive(FromDeriveInput)] +#[darling(attributes(speak))] +struct SpeakingOptions { + max_volume: U, + #[darling(skip, default)] + additional_data: Vec, +} + +#[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 Default for SpeakingOptions +where + Vec: 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 = + 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 index 46dcbdcbccba..d5602f303fec 100644 --- a/third_party/rust/darling/examples/consume_fields.rs +++ b/third_party/rust/darling/examples/consume_fields.rs @@ -2,19 +2,20 @@ #[macro_use] extern crate darling; - +extern crate proc_macro2; #[macro_use] extern crate quote; extern crate syn; use darling::ast; use darling::FromDeriveInput; -use quote::{Tokens, ToTokens}; +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, FromMetaItem)] +#[derive(Debug, Clone, Copy, FromMeta)] #[darling(default)] enum Volume { Normal, @@ -28,7 +29,7 @@ impl Default for Volume { } } -/// Support parsing from a full derive input. Unlike FromMetaItem, this isn't +/// 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)] @@ -54,7 +55,7 @@ struct MyInputReceiver { } impl ToTokens for MyInputReceiver { - fn to_tokens(&self, tokens: &mut Tokens) { + fn to_tokens(&self, tokens: &mut TokenStream) { let MyInputReceiver { ref ident, ref generics, @@ -78,11 +79,10 @@ impl ToTokens for MyInputReceiver { // unfortunately. format!( "{} = {{}}", - f.ident.as_ref().map(|v| format!("{}", v)).unwrap_or_else( - || { - format!("{}", i) - }, - ) + f.ident + .as_ref() + .map(|v| format!("{}", v)) + .unwrap_or_else(|| format!("{}", i)) ) }) .collect::>() @@ -97,7 +97,10 @@ impl ToTokens for MyInputReceiver { // 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)); + 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), @@ -111,7 +114,7 @@ impl ToTokens for MyInputReceiver { }) .collect::>(); - tokens.append_all(quote! { + 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),*) @@ -152,7 +155,8 @@ pub struct Foo { let receiver = MyInputReceiver::from_derive_input(&parsed).unwrap(); let tokens = quote!(#receiver); - println!(r#" + println!( + r#" INPUT: {} @@ -164,5 +168,7 @@ PARSED AS: EMITS: {} - "#, input, receiver, tokens); + "#, + input, receiver, tokens + ); } diff --git a/third_party/rust/darling/examples/fallible_read.rs b/third_party/rust/darling/examples/fallible_read.rs index e0149e4403f3..04d573cefa2f 100644 --- a/third_party/rust/darling/examples/fallible_read.rs +++ b/third_party/rust/darling/examples/fallible_read.rs @@ -10,7 +10,7 @@ extern crate darling; extern crate syn; -use darling::{FromDeriveInput, FromMetaItem}; +use darling::{FromDeriveInput, FromMeta}; use syn::parse_str; #[derive(Debug, FromDeriveInput)] @@ -36,14 +36,18 @@ impl MyInputReceiver { /// 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; + 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) = FromMetaItem::from_meta_item(&mi) { + let val: i64 = if let Ok(v) = FromMeta::from_meta(&mi) { v } else { panic!(format!("amplitude should have been an integer")) @@ -69,7 +73,8 @@ pub struct Foo;"#; let parsed = parse_str(input).unwrap(); let receiver = MyInputReceiver::from_derive_input(&parsed).unwrap(); - println!(r#" + println!( + r#" INPUT: {} @@ -77,5 +82,7 @@ INPUT: PARSED AS: {:?} - "#, input, receiver); + "#, + 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 000000000000..b76b4b707dab --- /dev/null +++ b/third_party/rust/darling/examples/supports_struct.rs @@ -0,0 +1,63 @@ +#[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, + ty: Type, + #[darling(default)] + skip: bool, +} + +#[derive(Debug, FromDeriveInput)] +#[darling(attributes(lorem), supports(struct_named))] +pub struct Lorem { + ident: Ident, + data: ast::Data, +} + +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 index 322f791c198e..70035be9d54d 100644 --- a/third_party/rust/darling/src/lib.rs +++ b/third_party/rust/darling/src/lib.rs @@ -4,12 +4,12 @@ //! //! ## Design //! Darling takes considerable design inspiration from [`serde`]. A data structure that can be -//! read from any attribute implements `FromMetaItem` (or has an implementation automatically -//! generated using `derive`). Any crate can provide `FromMetaItem` implementations, even one not +//! 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` and -//! `FromField` to gather settings relevant to their operation. +//! 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 @@ -24,10 +24,10 @@ //! `Default::default()` for their value, but you can override that with an explicit default or a value from the type-level default. //! //! ## Forwarded Fields -//! The traits `FromDeriveInput` and `FromField` support forwarding fields from the input AST directly -//! to the derived struct. These fields are matched up by identifier **before** `rename` attribute values are -//! considered. The deriving struct is responsible for making sure the types of fields it does declare match this -//! table. +//! 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. //! @@ -36,8 +36,8 @@ //! |---|---|---| //! |`ident`|`syn::Ident`|The identifier of the passed-in type| //! |`vis`|`syn::Visibility`|The visibility of the passed-in type| -//! |`generics`|`syn::Generics`|The generics of the passed-in type| -//! |`body`|`darling::ast::Data`|The body 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`|The forwarded attributes from the passed in type. These are controlled using the `forward_attrs` attribute.| //! //! ### `FromField` @@ -47,6 +47,14 @@ //! |`vis`|`syn::Visibility`|The visibility of the passed-in field| //! |`ty`|`syn::Type`|The type of the passed-in field| //! |`attrs`|`Vec`|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`|The bounds applied to the type param| +//! |`default`|`Option`|The default type of the parameter, if one exists| +//! |`attrs`|`Vec`|The forwarded attributes from the passed in type param. These are controlled using the `forward_attrs` attribute.| extern crate core; extern crate darling_core; @@ -59,22 +67,32 @@ extern crate darling_macro; pub use darling_macro::*; #[doc(inline)] -pub use darling_core::{FromMetaItem, FromDeriveInput, FromField, FromVariant}; +pub use darling_core::{FromDeriveInput, FromField, FromGenericParam, FromGenerics, FromMeta, + FromTypeParam, FromVariant}; #[doc(inline)] -pub use darling_core::{Result, Error}; +pub use darling_core::{Error, Result}; #[doc(inline)] -pub use darling_core::{ast, error, util}; +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::option::Option::{self, Some, None}; - pub use ::core::result::Result::{self, Ok, Err}; - pub use ::core::default::Default; - pub use ::std::vec::Vec; +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 000000000000..a3c5cac98d57 --- /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 index db94e3b3c5f5..44ba7d908ddb 100644 --- a/third_party/rust/darling/tests/accrue_errors.rs +++ b/third_party/rust/darling/tests/accrue_errors.rs @@ -16,9 +16,9 @@ struct Lorem { data: ast::Data<(), LoremField>, } -#[derive(Debug, FromMetaItem)] +#[derive(Debug, FromMeta)] struct Dolor { - sit: bool + sit: bool, } #[derive(Debug, FromField)] @@ -30,12 +30,14 @@ struct LoremField { #[test] fn bad_type_and_missing_fields() { - let input = syn::parse_str(r#" + let input = syn::parse_str( + r#" #[accrue(ipsum = true, dolor(amet = "Hi"))] pub struct NonConforming { foo: () } - "#).unwrap(); + "#, + ).unwrap(); let s_result: ::darling::Error = Lorem::from_derive_input(&input).unwrap_err(); //assert_eq!(3, s_result.len()); @@ -46,44 +48,45 @@ fn bad_type_and_missing_fields() { #[test] fn body_only_issues() { - let input = syn::parse_str(r#" + let input = syn::parse_str( + r#" #[accrue(ipsum = "Hello", dolor(sit))] pub struct NonConforming { foo: (), bar: bool, } - "#).unwrap(); + "#, + ).unwrap(); let s_err: ::darling::Error = Lorem::from_derive_input(&input).unwrap_err(); println!("{:?}", s_err); assert_eq!(2, s_err.len()); } -#[derive(Debug, FromMetaItem)] +#[derive(Debug, FromMeta)] enum Week { Monday, - Tuesday { - morning: bool, - afternoon: String, - }, + Tuesday { morning: bool, afternoon: String }, Wednesday(Dolor), } #[derive(Debug, FromDeriveInput)] #[darling(attributes(accrue))] struct Month { - schedule: Week + schedule: Week, } #[test] fn error_in_enum_fields() { - let input = syn::parse_str(r#" + let input = syn::parse_str( + r#" #[accrue(schedule(tuesday(morning = "yes")))] pub struct NonConforming { foo: (), bar: bool, } - "#).unwrap(); + "#, + ).unwrap(); let s_err: ::darling::Error = Month::from_derive_input(&input).unwrap_err(); assert_eq!(2, s_err.len()); @@ -94,13 +97,15 @@ fn error_in_enum_fields() { #[test] fn error_in_newtype_variant() { - let input = syn::parse_str(r#" + let input = syn::parse_str( + r#" #[accrue(schedule(wednesday(sit = "yes")))] pub struct NonConforming { foo: (), bar: bool, } - "#).unwrap(); + "#, + ).unwrap(); let s_err: ::darling::Error = Month::from_derive_input(&input).unwrap_err(); assert_eq!(1, s_err.len()); 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 000000000000..94fd307b685d --- /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(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 { + 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 = 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 index bcab2424bdae..4266a740e1c6 100644 --- a/third_party/rust/darling/tests/custom_bound.rs +++ b/third_party/rust/darling/tests/custom_bound.rs @@ -4,8 +4,8 @@ extern crate syn; use std::ops::Add; -#[derive(Debug, Clone, FromMetaItem)] -#[darling(bound = "T: FromMetaItem + Add")] +#[derive(Debug, Clone, FromMeta)] +#[darling(bound = "T: FromMeta + Add")] struct Wrapper(pub T); impl Add for Wrapper { @@ -16,7 +16,7 @@ impl Add for Wrapper { } #[derive(Debug, FromDeriveInput)] -#[darling(attributes(hello), bound = "Wrapper: Add, T: FromMetaItem")] +#[darling(attributes(hello), bound = "Wrapper: Add, T: FromMeta")] struct Foo { lorem: Wrapper, } diff --git a/third_party/rust/darling/tests/defaults.rs b/third_party/rust/darling/tests/defaults.rs new file mode 100644 index 000000000000..c6003ec4ba22 --- /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 index a4d1b3e1689c..f17d33e5654b 100644 --- a/third_party/rust/darling/tests/enums_newtype.rs +++ b/third_party/rust/darling/tests/enums_newtype.rs @@ -5,15 +5,15 @@ use darling::FromDeriveInput; extern crate syn; -#[derive(Debug, Default, PartialEq, Eq, FromMetaItem)] +#[derive(Debug, Default, PartialEq, Eq, FromMeta)] #[darling(default)] pub struct Amet { hello: bool, world: String, } -#[derive(Debug, PartialEq, Eq, FromMetaItem)] -#[darling(rename_all="snake_case")] +#[derive(Debug, PartialEq, Eq, FromMeta)] +#[darling(rename_all = "snake_case")] pub enum Lorem { Ipsum(bool), Dolor(String), @@ -34,10 +34,12 @@ impl PartialEq for Holder { #[test] fn bool_word() { - let di = syn::parse_str(r#" + let di = syn::parse_str( + r#" #[hello(lorem(ipsum))] pub struct Bar; - "#).unwrap(); + "#, + ).unwrap(); let pr = Holder::from_derive_input(&di).unwrap(); assert_eq!(pr, Lorem::Ipsum(true)); @@ -45,10 +47,12 @@ fn bool_word() { #[test] fn bool_literal() { - let di = syn::parse_str(r#" + let di = syn::parse_str( + r#" #[hello(lorem(ipsum = false))] pub struct Bar; - "#).unwrap(); + "#, + ).unwrap(); let pr = Holder::from_derive_input(&di).unwrap(); assert_eq!(pr, Lorem::Ipsum(false)); @@ -56,10 +60,12 @@ fn bool_literal() { #[test] fn string_literal() { - let di = syn::parse_str(r#" + let di = syn::parse_str( + r#" #[hello(lorem(dolor = "Hello"))] pub struct Bar; - "#).unwrap(); + "#, + ).unwrap(); let pr = Holder::from_derive_input(&di).unwrap(); assert_eq!(pr, Lorem::Dolor("Hello".to_string())); @@ -67,25 +73,32 @@ fn string_literal() { #[test] fn struct_nested() { - let di = syn::parse_str(r#" + let di = syn::parse_str( + r#" #[hello(lorem(sit(world = "Hello", hello = false)))] pub struct Bar; - "#).unwrap(); + "#, + ).unwrap(); let pr = Holder::from_derive_input(&di).unwrap(); - assert_eq!(pr, Lorem::Sit(Amet { - hello: false, - world: "Hello".to_string(), - })); + assert_eq!( + pr, + Lorem::Sit(Amet { + hello: false, + world: "Hello".to_string(), + }) + ); } #[test] #[should_panic] fn format_mismatch() { - let di = syn::parse_str(r#" + let di = syn::parse_str( + r#" #[hello(lorem(dolor(world = "Hello", hello = false)))] pub struct Bar; - "#).unwrap(); + "#, + ).unwrap(); 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 index 81db457f365b..63ce69058d81 100644 --- a/third_party/rust/darling/tests/enums_struct.rs +++ b/third_party/rust/darling/tests/enums_struct.rs @@ -4,20 +4,13 @@ extern crate darling; extern crate syn; -#[derive(Debug, FromMetaItem)] -#[darling(rename_all="snake_case")] +#[derive(Debug, FromMeta)] +#[darling(rename_all = "snake_case")] enum Message { - Hello { - user: String, - silent: bool - }, + Hello { user: String, silent: bool }, Ping, - Goodbye { - user: String, - } + Goodbye { user: String }, } #[test] -fn expansion() { - -} \ No newline at end of file +fn expansion() {} diff --git a/third_party/rust/darling/tests/enums_unit.rs b/third_party/rust/darling/tests/enums_unit.rs index 458593bdd858..f9eb23f24571 100644 --- a/third_party/rust/darling/tests/enums_unit.rs +++ b/third_party/rust/darling/tests/enums_unit.rs @@ -4,15 +4,13 @@ extern crate darling; extern crate syn; -#[derive(Debug, FromMetaItem)] -#[darling(rename_all="snake_case")] +#[derive(Debug, FromMeta)] +#[darling(rename_all = "snake_case")] enum Pattern { Owned, Immutable, - Mutable + Mutable, } #[test] -fn expansion() { - -} \ No newline at end of file +fn expansion() {} diff --git a/third_party/rust/darling/tests/error.rs b/third_party/rust/darling/tests/error.rs index 259e7a3319b2..6da666951fb7 100644 --- a/third_party/rust/darling/tests/error.rs +++ b/third_party/rust/darling/tests/error.rs @@ -5,7 +5,7 @@ extern crate syn; use darling::FromDeriveInput; -#[derive(Debug, FromMetaItem)] +#[derive(Debug, FromMeta)] struct Dolor { #[darling(rename = "amet")] sit: bool, @@ -33,20 +33,24 @@ impl From for Lorem { #[test] fn parsing_fail() { - let di = syn::parse_str(r#" + let di = syn::parse_str( + r#" #[hello(ipsum(amet = "yes", world = false))] pub struct Foo; - "#).unwrap(); + "#, + ).unwrap(); println!("{}", Lorem::from_derive_input(&di).unwrap_err()); } #[test] fn missing_field() { - let di = syn::parse_str(r#" + let di = syn::parse_str( + r#" #[hello(ipsum(amet = true))] pub struct Foo; - "#).unwrap(); + "#, + ).unwrap(); 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 000000000000..2c259ec280f8 --- /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>, +} + +#[derive(FromTypeParam)] +#[darling(attributes(lorem))] +struct MyTypeParam { + pub ident: syn::Ident, + #[darling(default)] + pub foo: bool, + #[darling(default)] + pub bar: Option, +} + +fn fdi(src: &str) -> Result { + 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; + "#) + .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>, 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; + "#) + .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::>() + .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; + "#) + .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 000000000000..ebd7e3e269ba --- /dev/null +++ b/third_party/rust/darling/tests/from_type_param.rs @@ -0,0 +1,63 @@ +#[macro_use] +extern crate darling; +extern crate syn; + +use darling::FromTypeParam; +use syn::{DeriveInput, GenericParam, Ident, TypeParam}; + +#[darling(attributes(lorem), from_ident)] +#[derive(FromTypeParam)] +struct Lorem { + ident: Ident, + bounds: Vec, + foo: bool, + bar: Option, +} + +impl From 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 = syn::parse_str( + r#" + struct Baz< + #[lorem(foo)] T, + #[lorem(bar = "x")] U: Eq + ?Sized + >(T, U); + "#, + ).unwrap(); + let params = di.generics.params; + + { + let ty = extract_type(¶ms[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(¶ms[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 000000000000..df24de08892a --- /dev/null +++ b/third_party/rust/darling/tests/from_type_param_default.rs @@ -0,0 +1,58 @@ +#[macro_use] +extern crate darling; +extern crate syn; + +use darling::FromTypeParam; +use syn::{DeriveInput, GenericParam, TypeParam}; + +#[darling(attributes(lorem), default)] +#[derive(Default, FromTypeParam)] +struct Lorem { + foo: bool, + bar: Option, + default: Option, +} + +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 = syn::parse_str( + r#" + struct Baz< + #[lorem(foo)] T, + #[lorem(bar = "x")] U: Eq + ?Sized, + #[lorem(foo = false)] V = (), + >(T, U, V); + "#, + ).unwrap(); + let params = di.generics.params; + + { + let ty = extract_type(¶ms[0]); + let lorem = Lorem::from_type_param(ty).unwrap(); + assert_eq!(lorem.foo, true); + assert_eq!(lorem.bar, None); + } + + { + let ty = extract_type(¶ms[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(¶ms[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 index bba50688db24..be216cbe5217 100644 --- a/third_party/rust/darling/tests/from_variant.rs +++ b/third_party/rust/darling/tests/from_variant.rs @@ -24,6 +24,4 @@ impl From for Lorem { } #[test] -fn expansion() { - -} \ No newline at end of file +fn expansion() {} diff --git a/third_party/rust/darling/tests/generics.rs b/third_party/rust/darling/tests/generics.rs index 33c1fe019edc..c268f56c0f6b 100644 --- a/third_party/rust/darling/tests/generics.rs +++ b/third_party/rust/darling/tests/generics.rs @@ -4,7 +4,7 @@ extern crate syn; use darling::FromDeriveInput; -#[derive(Debug, Clone, FromMetaItem)] +#[derive(Debug, Clone, FromMeta)] struct Wrapper(pub T); #[derive(Debug, FromDeriveInput)] @@ -15,11 +15,12 @@ struct Foo { #[test] fn expansion() { - let di = syn::parse_str(r#" + let di = syn::parse_str( + r#" #[hello(lorem = "Hello")] pub struct Foo; - "#) - .unwrap(); + "#, + ).unwrap(); let _parsed = Foo::::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 index 37f295d9e54e..d5d7b54fb9fa 100644 --- a/third_party/rust/darling/tests/happy_path.rs +++ b/third_party/rust/darling/tests/happy_path.rs @@ -8,7 +8,7 @@ extern crate quote; use darling::FromDeriveInput; -#[derive(Default, FromMetaItem, PartialEq, Debug)] +#[derive(Default, FromMeta, PartialEq, Debug)] #[darling(default)] struct Lorem { ipsum: bool, @@ -21,7 +21,7 @@ struct Core { ident: syn::Ident, vis: syn::Visibility, generics: syn::Generics, - lorem: Lorem + lorem: Lorem, } #[derive(FromDeriveInput, PartialEq, Debug)] @@ -34,37 +34,47 @@ struct TraitCore { #[test] fn simple() { - let di = syn::parse_str(r#" + let di = syn::parse_str( + r#" #[derive(Foo)] #[darling_demo(lorem(ipsum))] pub struct Bar; - "#).unwrap(); + "#, + ).unwrap(); - assert_eq!(Core::from_derive_input(&di).unwrap(), Core { - ident: syn::Ident::from("Bar"), - vis: parse_quote!(pub), - generics: Default::default(), - lorem: Lorem { - ipsum: true, - dolor: None, + 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 = syn::parse_str(r#" + let di = syn::parse_str( + r#" #[derive(Foo)] #[darling_demo(lorem(dolor = "hello"))] pub struct Bar; - "#).unwrap(); + "#, + ).unwrap(); - assert_eq!(TraitCore::from_derive_input(&di).unwrap(), TraitCore { - ident: syn::Ident::from("Bar"), - generics: Default::default(), - lorem: Lorem { - ipsum: false, - dolor: Some("hello".to_owned()), + 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 index 8e64d89938b9..111c1f402a6b 100644 --- a/third_party/rust/darling/tests/multiple.rs +++ b/third_party/rust/darling/tests/multiple.rs @@ -12,7 +12,7 @@ struct Lorem { ipsum: Ipsum, } -#[derive(FromMetaItem)] +#[derive(FromMeta)] struct Ipsum { #[darling(multiple)] dolor: Vec, @@ -20,11 +20,16 @@ struct Ipsum { #[test] fn expand_many() { - let di = syn::parse_str(r#" + let di = syn::parse_str( + r#" #[hello(ipsum(dolor = "Hello", dolor = "World"))] pub struct Baz; - "#).unwrap(); + "#, + ).unwrap(); let lorem: Lorem = Lorem::from_derive_input(&di).unwrap(); - assert_eq!(lorem.ipsum.dolor, vec!["Hello".to_string(), "World".to_string()]); + 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 index b78829fc2b1a..16cb95994b0f 100644 --- a/third_party/rust/darling/tests/newtype.rs +++ b/third_party/rust/darling/tests/newtype.rs @@ -1,4 +1,4 @@ -//! A newtype struct should be able to derive `FromMetaItem` if its member implements it. +//! A newtype struct should be able to derive `FromMeta` if its member implements it. #[macro_use] extern crate darling; @@ -7,22 +7,24 @@ extern crate syn; use darling::FromDeriveInput; -#[derive(Debug, FromMetaItem, PartialEq, Eq)] +#[derive(Debug, FromMeta, PartialEq, Eq)] struct Lorem(bool); #[derive(Debug, FromDeriveInput)] #[darling(attributes(newtype))] struct DemoContainer { - lorem: Lorem + lorem: Lorem, } #[test] fn generated() { - let di = syn::parse_str(r#" + let di = syn::parse_str( + r#" #[derive(Baz)] #[newtype(lorem = false)] pub struct Foo; - "#).unwrap(); + "#, + ).unwrap(); let c = DemoContainer::from_derive_input(&di).unwrap(); diff --git a/third_party/rust/darling/tests/skip.rs b/third_party/rust/darling/tests/skip.rs index 809fcafc04cf..a46dbfdda21b 100644 --- a/third_party/rust/darling/tests/skip.rs +++ b/third_party/rust/darling/tests/skip.rs @@ -16,7 +16,7 @@ pub struct Lorem { } /// Verify variant-level and field-level skip work correctly for enums. -#[derive(Debug, FromMetaItem)] +#[derive(Debug, FromMeta)] pub enum Sit { Amet(bool), @@ -28,19 +28,24 @@ pub enum Sit { Bar { hello: bool, #[darling(skip)] - world: u8 - } + world: u8, + }, } #[test] fn verify_skipped_field_not_required() { - let di = syn::parse_str(r#" + let di = syn::parse_str( + r#" #[skip_test(ipsum = "Hello")] struct Baz; - "#).unwrap(); + "#, + ).unwrap(); - assert_eq!(Lorem::from_derive_input(&di).unwrap(), Lorem { - ipsum: "Hello".to_string(), - dolor: 0, - }); + 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 index fedc88a2e741..5eb492a34aae 100644 --- a/third_party/rust/darling/tests/split_declaration.rs +++ b/third_party/rust/darling/tests/split_declaration.rs @@ -18,44 +18,62 @@ struct Lorem { #[test] fn split_attributes_accrue_to_instance() { - let di = syn::parse_str(r#" + let di = syn::parse_str( + r#" #[split(foo = "Hello")] #[split(bar)] pub struct Foo; - "#).unwrap(); + "#, + ).unwrap(); let parsed = Lorem::from_derive_input(&di).unwrap(); - assert_eq!(parsed, Lorem { - foo: "Hello".to_string(), - bar: true, - }); + assert_eq!( + parsed, + Lorem { + foo: "Hello".to_string(), + bar: true, + } + ); } #[test] fn duplicates_across_split_attrs_error() { - let di = syn::parse_str(r#" + let di = syn::parse_str( + r#" #[split(foo = "Hello")] #[split(foo = "World", bar)] pub struct Foo; - "#).unwrap(); + "#, + ).unwrap(); let pr = Lorem::from_derive_input(&di); - assert_eq!(pr.unwrap_err().to_string(), Error::duplicate_field("foo").to_string()); + assert_eq!( + pr.unwrap_err().to_string(), + Error::duplicate_field("foo").to_string() + ); } #[test] fn multiple_errors_accrue_to_instance() { - let di = syn::parse_str(r#" + let di = syn::parse_str( + r#" #[split(foo = "Hello")] #[split(foo = "World")] pub struct Foo; - "#).unwrap(); + "#, + ).unwrap(); let pr = Lorem::from_derive_input(&di); let err: Error = pr.unwrap_err(); assert_eq!(2, err.len()); let mut errs = err.into_iter(); - assert_eq!(errs.next().unwrap().to_string(), Error::duplicate_field("foo").to_string()); - assert_eq!(errs.next().unwrap().to_string(), Error::missing_field("bar").to_string()); + assert_eq!( + errs.next().unwrap().to_string(), + Error::duplicate_field("foo").to_string() + ); + 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/supports.rs b/third_party/rust/darling/tests/supports.rs index 3e36063a60bf..0681a5f7b42a 100644 --- a/third_party/rust/darling/tests/supports.rs +++ b/third_party/rust/darling/tests/supports.rs @@ -5,7 +5,7 @@ extern crate syn; use darling::ast; use darling::FromDeriveInput; -#[derive(Debug,FromDeriveInput)] +#[derive(Debug, FromDeriveInput)] #[darling(attributes(from_variants), supports(enum_any))] pub struct Container { data: ast::Data, @@ -18,28 +18,71 @@ pub struct Variant { skip: Option, } -#[test] -fn expansion() { - let di = syn::parse_str(r#" +#[derive(Debug, FromDeriveInput)] +#[darling(attributes(from_struct), supports(struct_named))] +pub struct StructContainer { + data: ast::Data<(), syn::Field>, +} + +mod source { + use syn::{self, DeriveInput}; + + pub fn newtype_enum() -> DeriveInput { + syn::parse_str( + r#" enum Hello { World(bool), String(String), } - "#).unwrap(); + "#, + ).unwrap() + } - Container::from_derive_input(&di).unwrap(); -} - -#[test] -fn unsupported_shape() { - let di = syn::parse_str(r#" + pub fn named_field_enum() -> DeriveInput { + syn::parse_str( + r#" enum Hello { Foo(u16), World { name: String }, } - "#).unwrap(); + "#, + ).unwrap() + } - Container::from_derive_input(&di).unwrap_err(); + pub fn named_struct() -> DeriveInput { + syn::parse_str( + r#" + struct Hello { + world: bool, + } + "#, + ).unwrap() + } + + pub fn tuple_struct() -> DeriveInput { + syn::parse_str("struct Hello(String, bool);").unwrap() + } +} + +#[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 index 0f9dcee3f5da..cb18371e768c 100644 --- a/third_party/rust/darling_core/.cargo-checksum.json +++ b/third_party/rust/darling_core/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"06561e115990be3f278ed12704d0eb575c971242cbdfe8ebb32a8132280e054e","src/ast.rs":"2538b41e2a579c0a5a49e02f911120ffff39d48dfc0d80570a5fcfe95c971794","src/codegen/default_expr.rs":"28d750fb5ed3a6344007bf545c48e4d9a15c175209903d4009efc0de257adf2e","src/codegen/error.rs":"2a1bde9a20c664f26c6a0017e35ddf82885a31b8be42a628ea5549013b1eab44","src/codegen/field.rs":"ad8355c7bb87269c7dcc1d27695b0f8de410b546625d33d5a219fbadf85f8230","src/codegen/fmi_impl.rs":"89a66b24d7527989dd90ca71d9409fd8cdcf3a659fa1a670448032a4b384e83c","src/codegen/from_derive_impl.rs":"36507c9eddd354a50f96cd28e737c914be494c83ae61202b533524a9d90a2ca9","src/codegen/from_field.rs":"586866442f6628fd055f139b018a8c5c13e3aea20954ec741517aa9ab731c163","src/codegen/from_variant_impl.rs":"d42ecd82d3159aa7ee89ed81ed355c927dea9df2a298cf1db0c486699b77eac2","src/codegen/mod.rs":"46cdb1b4a76eb2e56f01e2c9e2879aed9b1c21ecbed42575a2eeccabf446a27a","src/codegen/outer_from_impl.rs":"2314c1594bd63e682ebd4a4b4954b2b9f16aa50b1422c05568bce97ae29f9727","src/codegen/trait_impl.rs":"715ce9dcb82d855e9dd8f2a70599bc3c5328acde70c92b7db5bd4c276598a7d0","src/codegen/variant.rs":"294045aefcfcb54e8b9536d6d91251a46115271869578b3212ae36ae76883b18","src/codegen/variant_data.rs":"efdee90d7e9acce39672024502ceb0616bc162d11e59d255fcbcd23f00f80806","src/error.rs":"55f33c960123799e1ccb27676d780751c0b62d1f52ccb9a2ac69cea4acfe55db","src/from_derive_input.rs":"ea55cc1b2bc17495d36fb616f7cd7aa78e4b74ea7c8554eed9d392ee853700c3","src/from_field.rs":"b42c2fc037aebdd55f195d722ba20075d3e095f03e89890a0d37d406d6419d87","src/from_meta_item.rs":"996ccec9dca998ff41f65bb346e5cc75952af5d61339c6951bebdbf8db1212c5","src/from_variant.rs":"2baeb09c8a95ff606d9d5ca8992f10bbad9c4925590332af1a8b5bdae54ebae8","src/lib.rs":"58b910cecc1f1962c2d6059db384f065099547c34631d9ddcc35099db8e16405","src/macros.rs":"ef249cd9ca593aac423b4242df1c39c31610438da094c21562d74a7e5823c700","src/options/core.rs":"689067ee0901714e53caeef5d5634c4bc02f52ff06e3ff286410eecaca665734","src/options/forward_attrs.rs":"35a83a4ae695872413d964d9050e35a0075c8386c286d291b1ecf1779f9ba8a3","src/options/from_derive.rs":"502e18c3d9f90d7a4cebc8c6b60181ab6068958a0ba2e70fe645528dee34b231","src/options/from_field.rs":"7222be5e62026184169f12adb08403abc89d66c53e678f8d8b43afaeceed9e4f","src/options/from_meta_item.rs":"cbc2d747e9e35e0d68b26c9f1592914bb4924cac01a6cdaf9137f643a72b551a","src/options/from_variant.rs":"6f8538da3fb61e614552839ee32bc479d33b5227d7f9d9b357d8d05146b96dac","src/options/input_field.rs":"6d43c2907694c4187e9f182f7945fc769ce210cde8eb1b4a336dea2a7fce3710","src/options/input_variant.rs":"2fc064fb87a73542a012a31aa5fd9702cf58b52a1bf37dabbfa7fb2e758ff9cc","src/options/mod.rs":"ceefde4d1dba9b5f3822f667c34a6eb963e5a899973475456bfe7939177f0e19","src/options/outer_from.rs":"3125aad9f8c033727fd3ef4ef1e1881c77fa52463f78342c408bf135e8533037","src/options/shape.rs":"118af560da80a46d6e3f8980c3d9b4863319d224a8b2985520901bfea0eba531","src/util/ident_list.rs":"11b5008380ace89d5745cdd83b73a2841c5382f05d3a8942ba998a7e4d6abb31","src/util/ignored.rs":"66e2e3201e17e8fffe2f249a4327b8178a20304624a47c0149fe8dd5e05d187c","src/util/mod.rs":"0c9ee0ba8ec03ca654fd298bd0d82588f224e3743227e6cba2beba4ab2f4dee4","src/util/over_ride.rs":"f63637ff73b3f377a4b1c38714a0f108b98ff40a96dd3ffbebb1e4ecc7523813"},"package":"b315f49c7b6db3708bca6e6913c194581a44ec619b7a39e131d4dd63733a3698"} \ No newline at end of file +{"files":{"Cargo.toml":"f7061460abe53907c290c7975f49077a6c698e4acc9034d3e904c63a224dbd21","src/ast/data.rs":"c95e469d870f7918e77707da0e9e5e945e205e640bf34637355ef863b6efb28f","src/ast/generics.rs":"3bdfe1abdbee64f5aaa9b189dc5c58e222568f196ed206e9d6d91ea5f29673e7","src/ast/mod.rs":"58a58eeb1db7682e5994732cc8eb04088f6ca662805460ef443cf089e5c24e2c","src/codegen/attr_extractor.rs":"d13a3ba16f3a93f4a540421bb9df54a8f74cc6ee0e9e769b78b6c8045f285408","src/codegen/default_expr.rs":"60f23b77ddf80da70ec92fd0d8cb5a97143535df85eafa0e47943ac797ec46d2","src/codegen/error.rs":"50d0a1a2a392560ca10d3eb622ba745612761bf18846404742bd30caf2436228","src/codegen/field.rs":"d8b20dd1dda2c5591f5dcd4a2e5b8442ffae3daa23378323a81a682637080ea1","src/codegen/from_derive_impl.rs":"2a1e331d205db9334218b800760afcb64539fa2b25b0b2b014586b49b5b25882","src/codegen/from_field.rs":"af6f848ed7c6d2274e15d6307b011a1b8bcba66172ef68b0e665c9b4ae85157d","src/codegen/from_meta_impl.rs":"a937808b081e5d8bd16020fea8da0461e7e45872516cc0ee9e8a8cc957858a76","src/codegen/from_type_param.rs":"48493227f4a81fe1a533bd958b89207d56b1c70f754a2a28fb0e9eb9114a9aeb","src/codegen/from_variant_impl.rs":"3d9b10d60e3eb969946bbd210ce93a43375b9c8d3ffa827c7e87ab9235e2c3f3","src/codegen/mod.rs":"2dc3ee7f18177b2ef9c27c4f0cabc5bbd49f970abdba28a0539d81c70d81b6e2","src/codegen/outer_from_impl.rs":"059c3c05e4d6c7ba3876d23855ccbffa9e6158e7af7f6dc619b4d9770587f161","src/codegen/trait_impl.rs":"0e479f9e5b7253a3da2f77fd0bd63ea44a08a27dba2bd7dd992f05dc40b1d2a2","src/codegen/variant.rs":"3bc37ceb0e3dbf7eb02d7b66178adb3b165a24e92afa3295c012cf2f091d7328","src/codegen/variant_data.rs":"2467651663bfbb0ab35370b421d456948b053c26d0a23581a6c91ae7789b2db3","src/error.rs":"77436dc9a30172e94c434bdb61e3620ce37b2d64848a4fa19daba6e9c9329c95","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":"daa3d9a82b2f659147572f7d0e7fdef38139583e61e8319986098a4a73106453","src/from_type_param.rs":"9b611f276871002ade78146266fde3b6f9101b360082681a2fa2dafc16431f84","src/from_variant.rs":"70a23b5b4cb93c7e5a498fe9d16420b9b93bd69c1376d7703bc7cefd9417d159","src/lib.rs":"ea8f2d28793e4c0e367c4905e55e405417fbee9eb7ef0577f883b91aee1b5a57","src/macros_private.rs":"ef249cd9ca593aac423b4242df1c39c31610438da094c21562d74a7e5823c700","src/macros_public.rs":"3ed7eb99f309d9cd600d3a09ff4dcf5cc5d787fb49e8e5ead6bb00e31e5e6793","src/options/core.rs":"2dfb29a85a68d5ed6dccc46fe521c46ea8483bcd5d73cf21dbf21a7163ec318a","src/options/forward_attrs.rs":"89d8294a2204d6c32e5f58b797c23f4b035a8ff424bcf1b1c7db973ada89a4bc","src/options/from_derive.rs":"c8e41d2779e570dadd76c28b9cc9dd9cee57d8ef027766b4b5f39460a29df5d1","src/options/from_field.rs":"0b06590092a5c13d5c8eedf4e2d0518d869206813f828a06c65605d6cb8decc4","src/options/from_meta.rs":"ef268f78480f1d3df4e56cbc630aa4013ab5128cbb4471c4e85e9ff5a3980e7b","src/options/from_type_param.rs":"80d1fa60bac5bb31d0895e321faf1b8af99e407d9594028a01704b424be1dd4c","src/options/from_variant.rs":"99d4b60e48f8feef9c1fc2414ac0a420e66551c14e40c4a718668cca8e1f8cb5","src/options/input_field.rs":"08a5c584ccbb96ca11d2e58572ee654c269672f81cd76f9e2f29c3c23577c998","src/options/input_variant.rs":"29c39072f250dae92acf362185f81ea3ceac210e556f861e6cc0c87b043764dd","src/options/mod.rs":"30aefb531716954bad2b484c321baa333ef1d7d07ca55a0430df26bf4c1afb15","src/options/outer_from.rs":"e60196f2b9ea3ae014eaf3444607c6cf2a227c8d8aa4a5d64f59454602a0a5e6","src/options/shape.rs":"f6c110134954c62377e81d17e3fe623a9750ca7eb99eab853add114180f55904","src/usage/generics_ext.rs":"340774fe43033680e6b494c76dd4f558ada7ca4f09e91f9e4d076f125a729fc2","src/usage/ident_set.rs":"30edb2f0a599284967e3c6b579da31e5f9b15f3dd67bc9a82d6335eb44133df0","src/usage/lifetimes.rs":"19a63490660eb416bbccd4be9c060079a630dd15d5fd23c39e3c6c8c5498e369","src/usage/mod.rs":"bcf0ffb2257aed3b7b2cdad91c0136743384f39ff8f61f25c195c73b8fcdf144","src/usage/options.rs":"0491c995aad0d55783b24cce8a4e40f0f4435988c54ce2ded34763ac9b199fcf","src/usage/type_params.rs":"5aecf7f89c4b0623010e4717f5b32388b06d15e8511fde7b72f1d72e88fd3cb0","src/util/ident_list.rs":"fb6314436435547c111539213b209abd8d2593c28331560b84468a03b52d7c44","src/util/ident_string.rs":"06441e502d3bad342e292e42d083aff9070735a93d45f204aee5ef5f0144fdd0","src/util/ignored.rs":"7c979fbef880498ff64efda7396e759d80bf77fb1c7df0313bed8e533a16c0e0","src/util/mod.rs":"027793775e7079ea425f45b9bdad8b8fa309defcee02bf8ee6b6c556ec016342","src/util/over_ride.rs":"e90b3aeb41dd3364753f3ee6f8c6bbd85bf51d51569bf048396ec6e7735c569f","src/util/with_original.rs":"a545b38ba9d624fdc939eb844f001b7fc4102717b1d3683b4cbd0aae00fa7ef2"},"package":"86bc5ce438f4b703755d12f59bbf0a16c642766d4534e922db47569dbdd0b998"} \ No newline at end of file diff --git a/third_party/rust/darling_core/Cargo.toml b/third_party/rust/darling_core/Cargo.toml index 362e41db0c38..e4555e9411fa 100644 --- a/third_party/rust/darling_core/Cargo.toml +++ b/third_party/rust/darling_core/Cargo.toml @@ -12,22 +12,25 @@ [package] name = "darling_core" -version = "0.4.0" +version = "0.8.0" authors = ["Ted Driggs "] 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 = "0.3" +version = "0.4.2" [dependencies.quote] -version = "0.5" +version = "0.6" [dependencies.syn] -version = "0.13" +version = "0.15" features = ["extra-traits"] [features] diff --git a/third_party/rust/darling_core/src/ast.rs b/third_party/rust/darling_core/src/ast/data.rs similarity index 76% rename from third_party/rust/darling_core/src/ast.rs rename to third_party/rust/darling_core/src/ast/data.rs index a0b68fab5afd..1c2cd798fbcf 100644 --- a/third_party/rust/darling_core/src/ast.rs +++ b/third_party/rust/darling_core/src/ast/data.rs @@ -1,10 +1,13 @@ -//! Utility types for working with the AST. +use std::slice; use syn; +use usage::{ + self, IdentRefSet, IdentSet, LifetimeRefSet, LifetimeSet, UsesLifetimes, UsesTypeParams, +}; use {Error, FromField, FromVariant, Result}; -/// A struct or enum body. +/// A struct or enum body. /// /// `V` is the type which receives any encountered variants, and `F` receives struct fields. #[derive(Debug, Clone, PartialEq, Eq)] @@ -13,7 +16,7 @@ pub enum Data { Struct(Fields), } -#[deprecated(since="0.3", note="this has been renamed to Data")] +#[deprecated(since = "0.3", note = "this has been renamed to Data")] pub type Body = Data; impl Data { @@ -36,7 +39,8 @@ impl Data { /// Applies a function `V -> U` on enum variants, if this is an enum. pub fn map_enum_variants(self, map: T) -> Data - where T: FnMut(V) -> U + where + T: FnMut(V) -> U, { match self { Data::Enum(v) => Data::Enum(v.into_iter().map(map).collect()), @@ -46,7 +50,8 @@ impl Data { /// Applies a function `F -> U` on struct fields, if this is a struct. pub fn map_struct_fields(self, map: T) -> Data - where T: FnMut(F) -> U + where + T: FnMut(F) -> U, { match self { Data::Enum(v) => Data::Enum(v), @@ -56,7 +61,8 @@ impl Data { /// Applies a function to the `Fields` if this is a struct. pub fn map_struct(self, mut map: T) -> Data - where T: FnMut(Fields) -> Fields + where + T: FnMut(Fields) -> Fields, { match self { Data::Enum(v) => Data::Enum(v), @@ -101,10 +107,14 @@ impl Data { 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.clone().into_iter().map(|v| FromVariant::from_variant(&v)) { + for v_result in data.variants + .clone() + .into_iter() + .map(|v| FromVariant::from_variant(&v)) + { match v_result { Ok(val) => items.push(val), - Err(err) => errors.push(err) + Err(err) => errors.push(err), } } @@ -120,13 +130,39 @@ impl Data { } } +impl UsesTypeParams for Data { + 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 UsesLifetimes for Data { + 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), + } + } +} + #[derive(Debug, Clone, PartialEq, Eq)] pub struct Fields { pub style: Style, pub fields: Vec, } -#[deprecated(since="0.3", note="this has been renamed to Fields")] +#[deprecated(since = "0.3", note = "this has been renamed to Fields")] pub type VariantData = Fields; impl Fields { @@ -167,12 +203,19 @@ impl Fields { } } - pub fn map(self, map: F) -> Fields where F: FnMut(T) -> U { + pub fn map(self, map: F) -> Fields + where + F: FnMut(T) -> U, + { Fields { style: self.style, - fields: self.fields.into_iter().map(map).collect() + fields: self.fields.into_iter().map(map).collect(), } } + + pub fn iter(&self) -> slice::Iter { + self.fields.iter() + } } impl Fields { @@ -187,10 +230,10 @@ impl Fields { match f_result { Ok(val) => items.push(val), Err(err) => errors.push(if let Some(ref ident) = field.ident { - err.at(ident.as_ref()) + err.at(ident) } else { err - }) + }), } } @@ -205,10 +248,10 @@ impl Fields { match f_result { Ok(val) => items.push(val), Err(err) => errors.push(if let Some(ref ident) = field.ident { - err.at(ident.as_ref()) + err.at(ident) } else { err - }) + }), } } @@ -217,7 +260,6 @@ impl Fields { syn::Fields::Unit => (vec![], vec![]), }; - if !errors.is_empty() { Err(Error::multiple(errors)) } else { @@ -244,6 +286,26 @@ impl>> From<(Style, U)> for Fields { } } +impl UsesTypeParams for Fields { + fn uses_type_params<'a>( + &self, + options: &usage::Options, + type_set: &'a IdentSet, + ) -> IdentRefSet<'a> { + self.fields.uses_type_params(options, type_set) + } +} + +impl UsesLifetimes for Fields { + 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, 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 000000000000..2619993036ef --- /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 { + Type(T), + Lifetime(L), + Const(C), +} + +impl FromTypeParam for GenericParam { + fn from_type_param(type_param: &syn::TypeParam) -> Result { + Ok(GenericParam::Type(FromTypeParam::from_type_param( + type_param, + )?)) + } +} + +impl FromGenericParam for GenericParam { + fn from_generic_param(param: &syn::GenericParam) -> Result { + 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 GenericParamExt for GenericParam { + 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 { + pub params: Vec

, + pub where_clause: Option, +} + +impl Generics { + pub fn type_params<'a>(&'a self) -> TypeParams<'a, P> { + TypeParams(self.params.iter()) + } +} + +impl FromGenerics for Generics

{ + fn from_generics(generics: &syn::Generics) -> Result { + Ok(Generics { + params: generics + .params + .iter() + .map(FromGenericParam::from_generic_param) + .collect::>>()?, + 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

::TypeParam; + + fn next(&mut self) -> Option { + 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!(); + let deified: Generics> = 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 000000000000..492b26f18253 --- /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 000000000000..0b610044cb7d --- /dev/null +++ b/third_party/rust/darling_core/src/codegen/attr_extractor.rs @@ -0,0 +1,109 @@ +use proc_macro2::TokenStream; + +use options::ForwardAttrs; +use util::IdentList; + +/// 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) -> &IdentList; + + 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 Some(::syn::Meta::List(ref __data)) = __attr.interpret_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, + ) + } + } +} \ No newline at end of file diff --git a/third_party/rust/darling_core/src/codegen/default_expr.rs b/third_party/rust/darling_core/src/codegen/default_expr.rs index 3f5a92d45d8e..3bafca09d7e7 100644 --- a/third_party/rust/darling_core/src/codegen/default_expr.rs +++ b/third_party/rust/darling_core/src/codegen/default_expr.rs @@ -1,4 +1,5 @@ -use quote::{Tokens, ToTokens}; +use proc_macro2::TokenStream; +use quote::{TokenStreamExt, ToTokens}; use syn::{Ident, Path}; /// This will be in scope during struct initialization after option parsing. @@ -21,12 +22,12 @@ impl<'a> DefaultExpression<'a> { } impl<'a> ToTokens for DefaultExpression<'a> { - fn to_tokens(&self, tokens: &mut Tokens) { + 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()), }); @@ -37,7 +38,7 @@ impl<'a> ToTokens for DefaultExpression<'a> { pub struct DefaultDeclaration<'a>(&'a DefaultExpression<'a>); impl<'a> ToTokens for DefaultDeclaration<'a> { - fn to_tokens(&self, tokens: &mut Tokens) { + 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 index cc6e69339dbe..9c36d96eff42 100644 --- a/third_party/rust/darling_core/src/codegen/error.rs +++ b/third_party/rust/darling_core/src/codegen/error.rs @@ -1,20 +1,19 @@ -use quote::{Tokens, ToTokens}; +use proc_macro2::TokenStream; +use quote::{TokenStreamExt, ToTokens}; /// Declares the local variable into which errors will be accumulated. pub struct ErrorDeclaration { - __hidden: () + __hidden: (), } impl ErrorDeclaration { pub fn new() -> Self { - ErrorDeclaration { - __hidden: () - } + ErrorDeclaration { __hidden: () } } } impl ToTokens for ErrorDeclaration { - fn to_tokens(&self, tokens: &mut Tokens) { + fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(quote! { let mut __errors = Vec::new(); }) @@ -24,14 +23,14 @@ impl ToTokens for ErrorDeclaration { /// Returns early if attribute or body parsing has caused any errors. pub struct ErrorCheck<'a> { location: Option<&'a str>, - __hidden: () + __hidden: (), } impl<'a> ErrorCheck<'a> { pub fn new() -> Self { ErrorCheck { location: None, - __hidden: () + __hidden: (), } } @@ -44,7 +43,7 @@ impl<'a> ErrorCheck<'a> { } impl<'a> ToTokens for ErrorCheck<'a> { - fn to_tokens(&self, tokens: &mut Tokens) { + fn to_tokens(&self, tokens: &mut TokenStream) { let at_call = if let Some(ref s) = self.location { quote!(.at(#s)) } else { diff --git a/third_party/rust/darling_core/src/codegen/field.rs b/third_party/rust/darling_core/src/codegen/field.rs index b6c6f1b8b9c8..d80cfa56a95f 100644 --- a/third_party/rust/darling_core/src/codegen/field.rs +++ b/third_party/rust/darling_core/src/codegen/field.rs @@ -1,7 +1,9 @@ -use quote::{Tokens, ToTokens}; +use proc_macro2::TokenStream; +use quote::{TokenStreamExt, ToTokens}; 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. @@ -9,7 +11,7 @@ use codegen::DefaultExpression; 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: &'a str, + pub name_in_attr: String, /// The name presented to the author of the library. This will appear /// in the setters or temporary variables which contain the values. @@ -42,6 +44,16 @@ impl<'a> Field<'a> { } } +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); @@ -53,7 +65,7 @@ impl<'a> Declaration<'a> { } impl<'a> ToTokens for Declaration<'a> { - fn to_tokens(&self, tokens: &mut Tokens) { + fn to_tokens(&self, tokens: &mut TokenStream) { let field: &Field = self.0; let ident = field.ident; let ty = field.ty; @@ -73,10 +85,10 @@ impl<'a> ToTokens for Declaration<'a> { pub struct MatchArm<'a>(&'a Field<'a>); impl<'a> ToTokens for MatchArm<'a> { - fn to_tokens(&self, tokens: &mut Tokens) { + fn to_tokens(&self, tokens: &mut TokenStream) { let field: &Field = self.0; if !field.skip { - let name_str = field.name_in_attr; + let name_str = &field.name_in_attr; let ident = field.ident; let with_path = &field.with_path; @@ -140,7 +152,7 @@ impl<'a> ToTokens for MatchArm<'a> { pub struct Initializer<'a>(&'a Field<'a>); impl<'a> ToTokens for Initializer<'a> { - fn to_tokens(&self, tokens: &mut Tokens) { + fn to_tokens(&self, tokens: &mut TokenStream) { let field: &Field = self.0; let ident = field.ident; tokens.append_all(if field.multiple { @@ -170,10 +182,10 @@ impl<'a> ToTokens for Initializer<'a> { pub struct CheckMissing<'a>(&'a Field<'a>); impl<'a> ToTokens for CheckMissing<'a> { - fn to_tokens(&self, tokens: &mut Tokens) { + 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; + let name_in_attr = &self.0.name_in_attr; tokens.append_all(quote! { if !#ident.0 { 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 index f0b6b42f205a..e1536b2f59ac 100644 --- a/third_party/rust/darling_core/src/codegen/from_derive_impl.rs +++ b/third_party/rust/darling_core/src/codegen/from_derive_impl.rs @@ -1,9 +1,11 @@ -use quote::{Tokens, ToTokens}; +use proc_macro2::TokenStream; +use quote::ToTokens; use syn::{self, Ident}; use ast::Data; -use codegen::{TraitImpl, ExtractAttribute, OuterFromImpl}; +use codegen::{ExtractAttribute, OuterFromImpl, TraitImpl}; use options::{ForwardAttrs, Shape}; +use util::IdentList; pub struct FromDeriveInputImpl<'a> { pub ident: Option<&'a Ident>, @@ -12,45 +14,56 @@ pub struct FromDeriveInputImpl<'a> { pub attrs: Option<&'a Ident>, pub data: Option<&'a Ident>, pub base: TraitImpl<'a>, - pub attr_names: Vec<&'a str>, + pub attr_names: &'a IdentList, pub forward_attrs: Option<&'a ForwardAttrs>, - pub from_ident: Option, + pub from_ident: bool, pub supports: Option<&'a Shape>, } impl<'a> ToTokens for FromDeriveInputImpl<'a> { - fn to_tokens(&self, tokens: &mut Tokens) { + 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 { - ::darling::export::Ok( - #ty_ident(::darling::FromDeriveInput::from_derive_input(#input)?) - ) #map - } - }, tokens); + self.wrap( + quote!{ + fn from_derive_input(#input: &::syn::DeriveInput) -> ::darling::Result { + ::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_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: #input.generics.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 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 supports = self.supports.map(|i| { + quote!{ + #i + __validate_body(&#input.data)?; + } }); let inits = self.base.initializers(); - let default = if let Some(true) = self.from_ident { + let default = if self.from_ident { quote!(let __default: Self = ::darling::export::From::from(#input.ident.clone());) } else { self.base.fallback_decl() @@ -62,55 +75,58 @@ impl<'a> ToTokens for FromDeriveInputImpl<'a> { 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 { - #declare_errors + self.wrap( + quote! { + fn from_derive_input(#input: &::syn::DeriveInput) -> ::darling::Result { + #declare_errors - #grab_attrs + #grab_attrs - #supports + #supports - #require_fields + #require_fields - #check_errors + #check_errors - #default + #default - ::darling::export::Ok(#ty_ident { - #passed_ident - #passed_generics - #passed_vis - #passed_attrs - #passed_body - #inits - }) #map - } - }, tokens); + ::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) -> &[&str] { - self.attr_names.as_slice() + fn attr_names(&self) -> &IdentList { + &self.attr_names } fn forwarded_attrs(&self) -> Option<&ForwardAttrs> { self.forward_attrs } - fn param_name(&self) -> Tokens { + fn param_name(&self) -> TokenStream { quote!(__di) } - fn core_loop(&self) -> Tokens { + fn core_loop(&self) -> TokenStream { self.base.core_loop() } - fn local_declarations(&self) -> Tokens { + fn local_declarations(&self) -> TokenStream { self.base.local_declarations() } - fn immutable_declarations(&self) -> Tokens { + fn immutable_declarations(&self) -> TokenStream { self.base.immutable_declarations() } } @@ -121,7 +137,7 @@ impl<'a> OuterFromImpl<'a> for FromDeriveInputImpl<'a> { } fn trait_bound(&self) -> syn::Path { - path!(::darling::FromMetaItem) + path!(::darling::FromMeta) } fn base(&'a self) -> &'a TraitImpl<'a> { diff --git a/third_party/rust/darling_core/src/codegen/from_field.rs b/third_party/rust/darling_core/src/codegen/from_field.rs index b7e5cf84853f..1a2b62581657 100644 --- a/third_party/rust/darling_core/src/codegen/from_field.rs +++ b/third_party/rust/darling_core/src/codegen/from_field.rs @@ -1,8 +1,10 @@ -use quote::{Tokens, ToTokens}; +use proc_macro2::TokenStream; +use quote::ToTokens; use syn::{self, Ident}; -use codegen::{TraitImpl, ExtractAttribute, OuterFromImpl}; +use codegen::{ExtractAttribute, OuterFromImpl, TraitImpl}; use options::ForwardAttrs; +use util::IdentList; /// `impl FromField` generator. This is used for parsing an individual /// field and its attributes. @@ -12,13 +14,13 @@ pub struct FromFieldImpl<'a> { pub ty: Option<&'a Ident>, pub attrs: Option<&'a Ident>, pub base: TraitImpl<'a>, - pub attr_names: Vec<&'a str>, + pub attr_names: &'a IdentList, pub forward_attrs: Option<&'a ForwardAttrs>, pub from_ident: bool, } impl<'a> ToTokens for FromFieldImpl<'a> { - fn to_tokens(&self, tokens: &mut Tokens) { + fn to_tokens(&self, tokens: &mut TokenStream) { let input = self.param_name(); let error_declaration = self.base.declare_errors(); @@ -33,7 +35,9 @@ impl<'a> ToTokens for FromFieldImpl<'a> { self.base.fallback_decl() }; - let passed_ident = self.ident.as_ref().map(|i| quote!(#i: #input.ident.clone(),)); + 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,)); @@ -42,53 +46,56 @@ impl<'a> ToTokens for FromFieldImpl<'a> { let grab_attrs = self.extractor(); let map = self.base.map_fn(); - self.wrap(quote!{ - fn from_field(#input: &::syn::Field) -> ::darling::Result { - #error_declaration + self.wrap( + quote!{ + fn from_field(#input: &::syn::Field) -> ::darling::Result { + #error_declaration - #grab_attrs + #grab_attrs - #require_fields + #require_fields - #error_check + #error_check - #default + #default - ::darling::export::Ok(Self { - #passed_ident - #passed_ty - #passed_vis - #passed_attrs - #initializers - }) #map + ::darling::export::Ok(Self { + #passed_ident + #passed_ty + #passed_vis + #passed_attrs + #initializers + }) #map - } - }, tokens); + } + }, + tokens, + ); } } impl<'a> ExtractAttribute for FromFieldImpl<'a> { - fn attr_names(&self) -> &[&str] { - self.attr_names.as_slice() + fn attr_names(&self) -> &IdentList { + &self.attr_names } fn forwarded_attrs(&self) -> Option<&ForwardAttrs> { self.forward_attrs } - fn param_name(&self) -> Tokens { + fn param_name(&self) -> TokenStream { quote!(__field) } - fn core_loop(&self) -> Tokens { + fn core_loop(&self) -> TokenStream { self.base.core_loop() } - fn local_declarations(&self) -> Tokens { + fn local_declarations(&self) -> TokenStream { self.base.local_declarations() } - fn immutable_declarations(&self) -> Tokens { + fn immutable_declarations(&self) -> TokenStream { self.base.immutable_declarations() } } @@ -99,10 +106,10 @@ impl<'a> OuterFromImpl<'a> for FromFieldImpl<'a> { } fn trait_bound(&self) -> syn::Path { - path!(::darling::FromMetaItem) + path!(::darling::FromMeta) } fn base(&'a self) -> &'a TraitImpl<'a> { &self.base } -} \ No newline at end of file +} diff --git a/third_party/rust/darling_core/src/codegen/fmi_impl.rs b/third_party/rust/darling_core/src/codegen/from_meta_impl.rs similarity index 80% rename from third_party/rust/darling_core/src/codegen/fmi_impl.rs rename to third_party/rust/darling_core/src/codegen/from_meta_impl.rs index 4697da5862db..3744d4fd076e 100644 --- a/third_party/rust/darling_core/src/codegen/fmi_impl.rs +++ b/third_party/rust/darling_core/src/codegen/from_meta_impl.rs @@ -1,15 +1,16 @@ -use quote::{Tokens, ToTokens}; +use proc_macro2::TokenStream; +use quote::ToTokens; use syn; -use ast::{Data, Style, Fields}; -use codegen::{Field, TraitImpl, OuterFromImpl, Variant}; +use ast::{Data, Fields, Style}; +use codegen::{Field, OuterFromImpl, TraitImpl, Variant}; -pub struct FmiImpl<'a> { +pub struct FromMetaImpl<'a> { pub base: TraitImpl<'a>, } -impl<'a> ToTokens for FmiImpl<'a> { - fn to_tokens(&self, tokens: &mut Tokens) { +impl<'a> ToTokens for FromMetaImpl<'a> { + fn to_tokens(&self, tokens: &mut TokenStream) { let base = &self.base; let impl_block = match base.data { @@ -24,15 +25,23 @@ impl<'a> ToTokens for FmiImpl<'a> { } // Newtype structs proxy to the sole value they contain. - Data::Struct(Fields { ref fields, style: Style::Tuple, .. }) if fields.len() == 1 => { + Data::Struct(Fields { + ref fields, + style: Style::Tuple, + .. + }) if fields.len() == 1 => + { let ty_ident = base.ident; quote!( - fn from_meta_item(__item: &::syn::Meta) -> ::darling::Result { - Ok(#ty_ident(::darling::FromMetaItem::from_meta_item(__item)?)) + fn from_meta(__item: &::syn::Meta) -> ::darling::Result { + Ok(#ty_ident(::darling::FromMeta::from_meta(__item)?)) } ) } - Data::Struct(Fields { style: Style::Tuple, .. }) => { + Data::Struct(Fields { + style: Style::Tuple, + .. + }) => { panic!("Multi-field tuples are not supported"); } Data::Struct(ref data) => { @@ -45,7 +54,6 @@ impl<'a> ToTokens for FmiImpl<'a> { let default = base.fallback_decl(); let map = base.map_fn(); - quote!( fn from_list(__items: &[::syn::NestedMeta]) -> ::darling::Result { @@ -79,7 +87,7 @@ impl<'a> ToTokens for FmiImpl<'a> { 0 => ::darling::export::Err(::darling::Error::too_few_items(1)), 1 => { if let ::syn::NestedMeta::Meta(ref __nested) = __outer[0] { - match __nested.name().as_ref() { + match __nested.name().to_string().as_ref() { #(#struct_arms)* __other => ::darling::export::Err(::darling::Error::unknown_value(__other)) } @@ -105,9 +113,9 @@ impl<'a> ToTokens for FmiImpl<'a> { } } -impl<'a> OuterFromImpl<'a> for FmiImpl<'a> { +impl<'a> OuterFromImpl<'a> for FromMetaImpl<'a> { fn trait_path(&self) -> syn::Path { - path!(::darling::FromMetaItem) + path!(::darling::FromMeta) } fn base(&'a self) -> &'a TraitImpl<'a> { 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 000000000000..41df3ddd5f99 --- /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::IdentList; + +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 IdentList, + 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::>(),)); + 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 { + #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) -> &IdentList { + &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 index 4a0a7966a1f6..3b92a9501393 100644 --- a/third_party/rust/darling_core/src/codegen/from_variant_impl.rs +++ b/third_party/rust/darling_core/src/codegen/from_variant_impl.rs @@ -1,47 +1,56 @@ -use quote::{Tokens, ToTokens}; +use proc_macro2::TokenStream; +use quote::ToTokens; use syn::{self, Ident}; use codegen::{ExtractAttribute, OuterFromImpl, TraitImpl}; use options::{DataShape, ForwardAttrs}; +use util::IdentList; 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: Vec<&'a str>, + pub attr_names: &'a IdentList, pub forward_attrs: Option<&'a ForwardAttrs>, - pub from_ident: Option, + pub from_ident: bool, pub supports: Option<&'a DataShape>, } impl<'a> ToTokens for FromVariantImpl<'a> { - fn to_tokens(&self, tokens: &mut Tokens) { + 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_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 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 let Some(true) = self.from_ident { + 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 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!( + self.wrap( + quote!( fn from_variant(#input: &::syn::Variant) -> ::darling::Result { #error_declaration @@ -62,44 +71,45 @@ impl<'a> ToTokens for FromVariantImpl<'a> { #inits }) #map } - ), tokens); + ), + tokens, + ); } } impl<'a> ExtractAttribute for FromVariantImpl<'a> { - fn local_declarations(&self) -> Tokens { + fn local_declarations(&self) -> TokenStream { self.base.local_declarations() } - fn immutable_declarations(&self) -> Tokens { + fn immutable_declarations(&self) -> TokenStream { self.base.immutable_declarations() } - fn attr_names(&self) -> &[&str] { - self.attr_names.as_slice() + fn attr_names(&self) -> &IdentList { + &self.attr_names } fn forwarded_attrs(&self) -> Option<&ForwardAttrs> { self.forward_attrs } - fn param_name(&self) -> Tokens { + fn param_name(&self) -> TokenStream { quote!(__variant) } - fn core_loop(&self) -> Tokens { + 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::FromMetaItem) + path!(::darling::FromMeta) } fn base(&'a self) -> &'a TraitImpl<'a> { diff --git a/third_party/rust/darling_core/src/codegen/mod.rs b/third_party/rust/darling_core/src/codegen/mod.rs index f76572a592f2..40b8d68a755d 100644 --- a/third_party/rust/darling_core/src/codegen/mod.rs +++ b/third_party/rust/darling_core/src/codegen/mod.rs @@ -1,124 +1,29 @@ -use quote::Tokens; +mod attr_extractor; mod default_expr; mod error; mod field; -mod fmi_impl; +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::fmi_impl::FmiImpl; +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; -use options::ForwardAttrs; -/// Infrastructure for generating an attribute extractor. -pub trait ExtractAttribute { - fn local_declarations(&self) -> Tokens; - - fn immutable_declarations(&self) -> Tokens; - - /// Gets the list of attribute names that should be parsed by the extractor. - fn attr_names(&self) -> &[&str]; - - 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) -> Tokens; - - /// Gets the core from-meta-item loop that should be used on matching attributes. - fn core_loop(&self) -> Tokens; - - fn declarations(&self) -> Tokens { - if !self.attr_names().is_empty() { - self.local_declarations() - } else { - self.immutable_declarations() - } - } - - /// Generates the main extraction loop. - fn extractor(&self) -> Tokens { - 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(); - let core_loop = self.core_loop(); - quote!( - #(#attr_names)|* => { - if let Some(::syn::Meta::List(ref __data)) = __attr.interpret_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 - let mut __fwd_attrs: ::darling::export::Vec<::syn::Attribute> = vec![]; - - for __attr in &#input.attrs { - // Filter attributes based on name - match __attr.path.segments.iter().map(|s| s.ident.as_ref()).collect::>().join("::").as_str() { - #parse_handled - #forward_unhandled - } - } - ) - } -} - -fn forwards_to_local(behavior: &ForwardAttrs) -> Tokens { - let push_command = quote!(__fwd_attrs.push(__attr.clone())); - match *behavior { - ForwardAttrs::All => quote!(_ => #push_command), - ForwardAttrs::Only(ref idents) => { - let names = idents.as_strs(); - quote!( - #(#names)|* => #push_command, - _ => continue, - ) - } - } -} 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 index 5717dc652a8f..13ea8af30521 100644 --- a/third_party/rust/darling_core/src/codegen/outer_from_impl.rs +++ b/third_party/rust/darling_core/src/codegen/outer_from_impl.rs @@ -1,7 +1,9 @@ -use syn::{Generics, Path, TraitBound, TraitBoundModifier, TypeParamBound, GenericParam}; -use quote::{Tokens, ToTokens}; +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> { @@ -14,11 +16,14 @@ pub trait OuterFromImpl<'a> { self.trait_path() } - fn wrap(&'a self, body: T, tokens: &mut Tokens) { + fn wrap(&'a self, body: T, tokens: &mut TokenStream) { let base = self.base(); let trayt = self.trait_path(); let ty_ident = base.ident; - let generics = compute_impl_bounds(self.trait_bound(), base.generics.clone()); + // 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!( @@ -31,21 +36,23 @@ pub trait OuterFromImpl<'a> { } } -fn compute_impl_bounds(bound: Path, mut generics: Generics) -> Generics { +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, - }); + paren_token: None, + modifier: TraitBoundModifier::None, + lifetimes: None, + path: bound, + }); for mut param in generics.params.iter_mut() { if let &mut GenericParam::Type(ref mut typ) = param { - typ.bounds.push(added_bound.clone()); + if applies_to.contains(&typ.ident) { + typ.bounds.push(added_bound.clone()); + } } } diff --git a/third_party/rust/darling_core/src/codegen/trait_impl.rs b/third_party/rust/darling_core/src/codegen/trait_impl.rs index d870a8bcea71..601a6daf018b 100644 --- a/third_party/rust/darling_core/src/codegen/trait_impl.rs +++ b/third_party/rust/darling_core/src/codegen/trait_impl.rs @@ -1,10 +1,11 @@ -use quote::Tokens; +use proc_macro2::TokenStream; use syn::{Generics, Ident, Path, WherePredicate}; -use codegen::{DefaultExpression, Field, Variant, FieldsGen}; -use codegen::field; +use ast::{Data, Fields}; use codegen::error::{ErrorCheck, ErrorDeclaration}; -use ast::Data; +use codegen::field; +use codegen::{DefaultExpression, Field, FieldsGen, Variant}; +use usage::{CollectTypeParams, IdentSet, Purpose}; #[derive(Debug)] pub struct TraitImpl<'a> { @@ -16,6 +17,64 @@ pub struct TraitImpl<'a> { pub bound: Option<&'a [WherePredicate]>, } +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 fields. + pub fn used_type_params(&self) -> IdentSet { + self.type_params_matching(|f| !f.skip, |v| !v.skip) + } + + /// Get the type parameters which are used by skipped fields. + pub fn skipped_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_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 { @@ -28,7 +87,7 @@ impl<'a> TraitImpl<'a> { } /// Generate local variable declarations for all fields. - pub(in codegen) fn local_declarations(&self) -> Tokens { + 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(); @@ -39,7 +98,7 @@ impl<'a> TraitImpl<'a> { } /// Generate immutable variable declarations for all fields. - pub(in codegen) fn immutable_declarations(&self) -> Tokens { + 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(); @@ -49,17 +108,17 @@ impl<'a> TraitImpl<'a> { } } - pub(in codegen) fn map_fn(&self) -> Option { + pub(in codegen) fn map_fn(&self) -> Option { 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) -> Tokens { + 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) -> Tokens { + 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(); @@ -69,24 +128,20 @@ impl<'a> TraitImpl<'a> { } } - pub(in codegen) fn initializers(&self) -> Tokens { + pub(in codegen) fn initializers(&self) -> TokenStream { let foo = match self.data { Data::Enum(_) => panic!("Core loop on enums isn't supported"), - Data::Struct(ref data) => { - FieldsGen(data) - } + Data::Struct(ref data) => FieldsGen(data), }; foo.initializers() } /// Generate the loop which walks meta items looking for property matches. - pub(in codegen) fn core_loop(&self) -> Tokens { + pub(in codegen) fn core_loop(&self) -> TokenStream { let foo = match self.data { Data::Enum(_) => panic!("Core loop on enums isn't supported"), - Data::Struct(ref data) => { - FieldsGen(data) - } + Data::Struct(ref data) => FieldsGen(data), }; foo.core_loop() diff --git a/third_party/rust/darling_core/src/codegen/variant.rs b/third_party/rust/darling_core/src/codegen/variant.rs index 9c50a0579989..d4ab868a0507 100644 --- a/third_party/rust/darling_core/src/codegen/variant.rs +++ b/third_party/rust/darling_core/src/codegen/variant.rs @@ -1,15 +1,17 @@ -use quote::{Tokens, ToTokens}; +use proc_macro2::TokenStream; +use quote::{TokenStreamExt, ToTokens}; use syn::Ident; use ast::Fields; -use codegen::{Field, FieldsGen}; use codegen::error::{ErrorCheck, ErrorDeclaration}; +use codegen::{Field, FieldsGen}; +use usage::{self, IdentRefSet, IdentSet, UsesTypeParams}; /// An enum variant. #[derive(Debug, Clone, PartialEq, Eq)] pub struct Variant<'a> { - /// The name which will appear in code passed to the `FromMetaItem` input. - pub name_in_attr: &'a str, + /// The name which will appear in code passed to the `FromMeta` input. + pub name_in_attr: String, /// The name of the variant which will be returned for a given `name_in_attr`. pub variant_ident: &'a Ident, @@ -33,17 +35,27 @@ impl<'a> Variant<'a> { } } +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) + } +} + pub struct UnitMatchArm<'a>(&'a Variant<'a>); impl<'a> ToTokens for UnitMatchArm<'a> { - fn to_tokens(&self, tokens: &mut Tokens) { + 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 name_in_attr = &val.name_in_attr; if val.data.is_unit() { let variant_ident = val.variant_ident; @@ -63,14 +75,14 @@ impl<'a> ToTokens for UnitMatchArm<'a> { pub struct DataMatchArm<'a>(&'a Variant<'a>); impl<'a> ToTokens for DataMatchArm<'a> { - fn to_tokens(&self, tokens: &mut Tokens) { + 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 name_in_attr = &val.name_in_attr; let variant_ident = val.variant_ident; let ty_ident = val.ty_ident; @@ -82,12 +94,11 @@ impl<'a> ToTokens for DataMatchArm<'a> { return; } - let vdg = FieldsGen(&val.data); if val.data.is_struct() { let declare_errors = ErrorDeclaration::new(); - let check_errors = ErrorCheck::with_location(name_in_attr); + 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(); @@ -121,7 +132,7 @@ impl<'a> ToTokens for DataMatchArm<'a> { #name_in_attr => { ::darling::export::Ok( #ty_ident::#variant_ident( - ::darling::FromMetaItem::from_meta_item(__nested) + ::darling::FromMeta::from_meta(__nested) .map_err(|e| e.at(#name_in_attr))?) ) } diff --git a/third_party/rust/darling_core/src/codegen/variant_data.rs b/third_party/rust/darling_core/src/codegen/variant_data.rs index d1a817e1ed8c..250e4c63c73e 100644 --- a/third_party/rust/darling_core/src/codegen/variant_data.rs +++ b/third_party/rust/darling_core/src/codegen/variant_data.rs @@ -1,16 +1,19 @@ -use quote::Tokens; +use proc_macro2::TokenStream; +use ast::Fields; use ast::Style; use codegen::field; use codegen::Field; -use ast::Fields; pub struct FieldsGen<'a>(pub &'a Fields>); impl<'a> FieldsGen<'a> { - pub(in codegen) fn declarations(&self) -> Tokens { + pub(in codegen) fn declarations(&self) -> TokenStream { match *self.0 { - Fields { style: Style::Struct, ref fields } => { + Fields { + style: Style::Struct, + ref fields, + } => { let vdr = fields.into_iter().map(Field::as_declaration); quote!(#(#vdr)*) } @@ -19,7 +22,7 @@ impl<'a> FieldsGen<'a> { } /// Generate the loop which walks meta items looking for property matches. - pub(in codegen) fn core_loop(&self) -> Tokens { + pub(in codegen) fn core_loop(&self) -> TokenStream { let arms: Vec = self.0.as_ref().map(Field::as_match).fields; quote!( @@ -35,17 +38,20 @@ impl<'a> FieldsGen<'a> { ) } - pub fn require_fields(&self) -> Tokens { + pub fn require_fields(&self) -> TokenStream { match *self.0 { - Fields { style: Style::Struct, ref fields } => { + Fields { + style: Style::Struct, + ref fields, + } => { let checks = fields.into_iter().map(Field::as_presence_check); quote!(#(#checks)*) } - _ => panic!("FieldsGen doesn't support tuples for requirement checks") + _ => panic!("FieldsGen doesn't support tuples for requirement checks"), } } - pub(in codegen) fn initializers(&self) -> Tokens { + pub(in codegen) fn initializers(&self) -> TokenStream { let inits: Vec<_> = self.0.as_ref().map(Field::as_initializer).fields; quote!(#(#inits),*) diff --git a/third_party/rust/darling_core/src/error.rs b/third_party/rust/darling_core/src/error.rs index f8e875d82efb..73bda734d3c0 100644 --- a/third_party/rust/darling_core/src/error.rs +++ b/third_party/rust/darling_core/src/error.rs @@ -51,6 +51,11 @@ impl Error { Error::new(ErrorKind::UnknownField(name.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())) } @@ -84,7 +89,9 @@ impl Error { 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") + errors + .pop() + .expect("Error array of length 1 has a first item") } else { panic!("Can't deal with 0 errors") } @@ -168,11 +175,11 @@ impl IntoIterator for Error { fn into_iter(self) -> IntoIter { if let ErrorKind::Multiple(errors) = self.kind { IntoIter { - inner: IntoIterEnum::Multiple(errors.into_iter()) + inner: IntoIterEnum::Multiple(errors.into_iter()), } } else { IntoIter { - inner: IntoIterEnum::Single(iter::once(self)) + inner: IntoIterEnum::Single(iter::once(self)), } } } @@ -196,7 +203,7 @@ impl Iterator for IntoIterEnum { /// An iterator that moves out of an `Error`. pub struct IntoIter { - inner: IntoIterEnum + inner: IntoIterEnum, } impl Iterator for IntoIter { @@ -207,6 +214,7 @@ impl Iterator for IntoIter { } } +type DeriveInputShape = String; type FieldName = String; type MetaFormat = String; @@ -219,6 +227,7 @@ enum ErrorKind { Custom(String), DuplicateField(FieldName), MissingField(FieldName), + UnsupportedShape(DeriveInputShape), UnknownField(FieldName), UnexpectedFormat(MetaFormat), UnexpectedType(String), @@ -230,7 +239,7 @@ enum ErrorKind { // TODO make this variant take `!` so it can't exist #[doc(hidden)] - __NonExhaustive + __NonExhaustive, } impl ErrorKind { @@ -242,6 +251,7 @@ impl ErrorKind { 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", @@ -271,6 +281,7 @@ impl fmt::Display for ErrorKind { DuplicateField(ref field) => write!(f, "Duplicate field `{}`", field), MissingField(ref field) => write!(f, "Missing field `{}`", field), UnknownField(ref field) => write!(f, "Unexpected field `{}`", field), + 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), @@ -291,7 +302,7 @@ impl fmt::Display for ErrorKind { } write!(f, ")") - }, + } __NonExhaustive => unreachable!(), } } @@ -311,8 +322,9 @@ mod tests { fn flatten_simple() { let err = Error::multiple(vec![ Error::unknown_field("hello").at("world"), - Error::missing_field("hell_no").at("world") - ]).at("foo").flatten(); + Error::missing_field("hell_no").at("world"), + ]).at("foo") + .flatten(); assert!(err.location().is_empty()); @@ -340,7 +352,7 @@ mod tests { fn len_multiple() { let err = Error::multiple(vec![ Error::duplicate_field("hello"), - Error::missing_field("hell_no") + Error::missing_field("hell_no"), ]); assert_eq!(2, err.len()); } @@ -352,10 +364,8 @@ mod tests { Error::multiple(vec![ Error::duplicate_field("hi"), Error::missing_field("bye"), - Error::multiple(vec![ - Error::duplicate_field("whatsup") - ]) - ]) + 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 index a5e525a8d460..740dd08284fc 100644 --- a/third_party/rust/darling_core/src/from_derive_input.rs +++ b/third_party/rust/darling_core/src/from_derive_input.rs @@ -23,4 +23,4 @@ impl FromDeriveInput for DeriveInput { fn from_derive_input(input: &DeriveInput) -> Result { Ok(input.clone()) } -} \ No newline at end of file +} diff --git a/third_party/rust/darling_core/src/from_field.rs b/third_party/rust/darling_core/src/from_field.rs index b4a2978e03dd..074bdc07afc4 100644 --- a/third_party/rust/darling_core/src/from_field.rs +++ b/third_party/rust/darling_core/src/from_field.rs @@ -35,4 +35,4 @@ impl FromField for Vec { fn from_field(field: &Field) -> Result { Ok(field.attrs.clone()) } -} \ No newline at end of file +} 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 000000000000..168600c4c4ff --- /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; +} + +impl FromGenericParam for () { + fn from_generic_param(_param: &syn::GenericParam) -> Result { + Ok(()) + } +} + +impl FromGenericParam for syn::GenericParam { + fn from_generic_param(param: &syn::GenericParam) -> Result { + 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 000000000000..eb6e5c97e044 --- /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; +} + +impl FromGenerics for () { + fn from_generics(_generics: &Generics) -> Result { + Ok(()) + } +} + +impl FromGenerics for Generics { + fn from_generics(generics: &Generics) -> Result { + Ok(generics.clone()) + } +} + +impl FromGenerics for Result { + fn from_generics(generics: &Generics) -> Result { + Ok(FromGenerics::from_generics(generics)) + } +} diff --git a/third_party/rust/darling_core/src/from_meta_item.rs b/third_party/rust/darling_core/src/from_meta.rs similarity index 56% rename from third_party/rust/darling_core/src/from_meta_item.rs rename to third_party/rust/darling_core/src/from_meta.rs index 0efaa270c914..dc03f993b5c3 100644 --- a/third_party/rust/darling_core/src/from_meta_item.rs +++ b/third_party/rust/darling_core/src/from_meta.rs @@ -1,8 +1,8 @@ use std::cell::RefCell; use std::collections::hash_map::{Entry, HashMap}; use std::rc::Rc; -use std::sync::Arc; use std::sync::atomic::AtomicBool; +use std::sync::Arc; use ident_case; use syn::{self, Lit, Meta, NestedMeta}; @@ -11,7 +11,7 @@ use {Error, Result}; /// Create an instance from an item in an attribute declaration. /// -/// # Implementing `FromMetaItem` +/// # 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. /// @@ -36,20 +36,26 @@ use {Error, Result}; /// ## `Result` /// * Allows for fallible parsing; will populate the target field with the result of the /// parse attempt. -pub trait FromMetaItem: Sized { - fn from_nested_meta_item(item: &NestedMeta) -> Result { +pub trait FromMeta: Sized { + fn from_nested_meta(item: &NestedMeta) -> Result { match *item { NestedMeta::Literal(ref lit) => Self::from_value(lit), - NestedMeta::Meta(ref mi) => Self::from_meta_item(mi), + NestedMeta::Meta(ref mi) => Self::from_meta(mi), } } /// Create an instance from a `syn::Meta` by dispatching to the format-appropriate /// trait function. This generally should not be overridden by implementers. - fn from_meta_item(item: &Meta) -> Result { + fn from_meta(item: &Meta) -> Result { match *item { Meta::Word(_) => Self::from_word(), - Meta::List(ref value) => Self::from_list(&value.nested.clone().into_iter().collect::>()[..]), + Meta::List(ref value) => Self::from_list( + &value + .nested + .clone() + .into_iter() + .collect::>()[..], + ), Meta::NameValue(ref value) => Self::from_value(&value.lit), } } @@ -73,7 +79,7 @@ pub trait FromMetaItem: Sized { match *value { Lit::Bool(ref b) => Self::from_bool(b.value), Lit::Str(ref s) => Self::from_string(&s.value()), - ref _other => Err(Error::unexpected_type("other")) + ref _other => Err(Error::unexpected_type("other")), } } @@ -96,15 +102,15 @@ pub trait FromMetaItem: Sized { } } -// FromMetaItem impls for std and syn types. +// FromMeta impls for std and syn types. -impl FromMetaItem for () { +impl FromMeta for () { fn from_word() -> Result { Ok(()) } } -impl FromMetaItem for bool { +impl FromMeta for bool { fn from_word() -> Result { Ok(true) } @@ -114,181 +120,181 @@ impl FromMetaItem for bool { } fn from_string(value: &str) -> Result { - value.parse().or_else(|_| Err(Error::unknown_value(value))) + value.parse().map_err(|_| Error::unknown_value(value)) } } -impl FromMetaItem for AtomicBool { - fn from_meta_item(mi: &Meta) -> Result { - Ok(AtomicBool::new(FromMetaItem::from_meta_item(mi)?)) +impl FromMeta for AtomicBool { + fn from_meta(mi: &Meta) -> Result { + FromMeta::from_meta(mi).map(AtomicBool::new) } } -impl FromMetaItem for String { +impl FromMeta for String { fn from_string(s: &str) -> Result { Ok(s.to_string()) } } -impl FromMetaItem for u8 { +impl FromMeta for u8 { fn from_string(s: &str) -> Result { - s.parse().or_else(|_| Err(Error::unknown_value(s))) + s.parse().map_err(|_| Error::unknown_value(s)) } } -impl FromMetaItem for u16 { +impl FromMeta for u16 { fn from_string(s: &str) -> Result { - s.parse().or_else(|_| Err(Error::unknown_value(s))) + s.parse().map_err(|_| Error::unknown_value(s)) } } -impl FromMetaItem for u32 { +impl FromMeta for u32 { fn from_string(s: &str) -> Result { - s.parse().or_else(|_| Err(Error::unknown_value(s))) + s.parse().map_err(|_| Error::unknown_value(s)) } } -impl FromMetaItem for u64 { +impl FromMeta for u64 { fn from_string(s: &str) -> Result { - s.parse().or_else(|_| Err(Error::unknown_value(s))) + s.parse().map_err(|_| Error::unknown_value(s)) } } -impl FromMetaItem for usize { +impl FromMeta for usize { fn from_string(s: &str) -> Result { - s.parse().or_else(|_| Err(Error::unknown_value(s))) + s.parse().map_err(|_| Error::unknown_value(s)) } } -impl FromMetaItem for i8 { +impl FromMeta for i8 { fn from_string(s: &str) -> Result { - s.parse().or_else(|_| Err(Error::unknown_value(s))) + s.parse().map_err(|_| Error::unknown_value(s)) } } -impl FromMetaItem for i16 { +impl FromMeta for i16 { fn from_string(s: &str) -> Result { - s.parse().or_else(|_| Err(Error::unknown_value(s))) + s.parse().map_err(|_| Error::unknown_value(s)) } } -impl FromMetaItem for i32 { +impl FromMeta for i32 { fn from_string(s: &str) -> Result { - s.parse().or_else(|_| Err(Error::unknown_value(s))) + s.parse().map_err(|_| Error::unknown_value(s)) } } -impl FromMetaItem for i64 { +impl FromMeta for i64 { fn from_string(s: &str) -> Result { - s.parse().or_else(|_| Err(Error::unknown_value(s))) + s.parse().map_err(|_| Error::unknown_value(s)) } } -impl FromMetaItem for isize { +impl FromMeta for isize { fn from_string(s: &str) -> Result { - s.parse().or_else(|_| Err(Error::unknown_value(s))) + s.parse().map_err(|_| Error::unknown_value(s)) } } -impl FromMetaItem for syn::Ident { +impl FromMeta for syn::Ident { fn from_string(value: &str) -> Result { Ok(syn::Ident::new(value, ::proc_macro2::Span::call_site())) } } -impl FromMetaItem for syn::Path { +impl FromMeta for syn::Path { fn from_string(value: &str) -> Result { - Ok(syn::parse_str::(value).unwrap()) + syn::parse_str(value).map_err(|_| Error::unknown_value(value)) } } /* -impl FromMetaItem for syn::TypeParamBound { +impl FromMeta for syn::TypeParamBound { fn from_string(value: &str) -> Result { Ok(syn::TypeParamBound::from(value)) } } */ -impl FromMetaItem for syn::Meta { - fn from_meta_item(value: &syn::Meta) -> Result { +impl FromMeta for syn::Meta { + fn from_meta(value: &syn::Meta) -> Result { Ok(value.clone()) } } -impl FromMetaItem for syn::WhereClause { +impl FromMeta for syn::WhereClause { fn from_string(value: &str) -> Result { - let ret: syn::WhereClause = syn::parse_str(value).unwrap(); - Ok(ret) + syn::parse_str(value).map_err(|_| Error::unknown_value(value)) } } -impl FromMetaItem for Vec { +impl FromMeta for Vec { fn from_string(value: &str) -> Result { - syn::WhereClause::from_string(&format!("where {}", value)).map(|c| c.predicates.into_iter().collect()) + syn::WhereClause::from_string(&format!("where {}", value)) + .map(|c| c.predicates.into_iter().collect()) } } -impl FromMetaItem for ident_case::RenameRule { +impl FromMeta for ident_case::RenameRule { fn from_string(value: &str) -> Result { - value.parse().or_else(|_| Err(Error::unknown_value(value))) + value.parse().map_err(|_| Error::unknown_value(value)) } } -impl FromMetaItem for Option { - fn from_meta_item(item: &Meta) -> Result { - Ok(Some(FromMetaItem::from_meta_item(item)?)) +impl FromMeta for Option { + fn from_meta(item: &Meta) -> Result { + FromMeta::from_meta(item).map(Some) } } -impl FromMetaItem for Box { - fn from_meta_item(item: &Meta) -> Result { - Ok(Box::new(FromMetaItem::from_meta_item(item)?)) +impl FromMeta for Box { + fn from_meta(item: &Meta) -> Result { + FromMeta::from_meta(item).map(Box::new) } } -impl FromMetaItem for Result { - fn from_meta_item(item: &Meta) -> Result { - Ok(FromMetaItem::from_meta_item(item)) +impl FromMeta for Result { + fn from_meta(item: &Meta) -> Result { + Ok(FromMeta::from_meta(item)) } } /// Parses the meta-item, and in case of error preserves a copy of the input for /// later analysis. -impl FromMetaItem for ::std::result::Result { - fn from_meta_item(item: &Meta) -> Result { - T::from_meta_item(item).map(Ok).or_else(|_| Ok(Err(item.clone()))) +impl FromMeta for ::std::result::Result { + fn from_meta(item: &Meta) -> Result { + T::from_meta(item) + .map(Ok) + .or_else(|_| Ok(Err(item.clone()))) } } -impl FromMetaItem for Rc { - fn from_meta_item(item: &Meta) -> Result { - Ok(Rc::new(FromMetaItem::from_meta_item(item)?)) +impl FromMeta for Rc { + fn from_meta(item: &Meta) -> Result { + FromMeta::from_meta(item).map(Rc::new) } } -impl FromMetaItem for Arc { - fn from_meta_item(item: &Meta) -> Result { - Ok(Arc::new(FromMetaItem::from_meta_item(item)?)) +impl FromMeta for Arc { + fn from_meta(item: &Meta) -> Result { + FromMeta::from_meta(item).map(Arc::new) } } -impl FromMetaItem for RefCell { - fn from_meta_item(item: &Meta) -> Result { - Ok(RefCell::new(FromMetaItem::from_meta_item(item)?)) +impl FromMeta for RefCell { + fn from_meta(item: &Meta) -> Result { + FromMeta::from_meta(item).map(RefCell::new) } } -impl FromMetaItem for HashMap { +impl FromMeta for HashMap { fn from_list(nested: &[syn::NestedMeta]) -> Result { let mut map = HashMap::with_capacity(nested.len()); for item in nested { if let syn::NestedMeta::Meta(ref inner) = *item { match map.entry(inner.name().to_string()) { - Entry::Occupied(_) => return Err(Error::duplicate_field(inner.name().as_ref())), + Entry::Occupied(_) => return Err(Error::duplicate_field(&inner.name().to_string())), Entry::Vacant(entry) => { - entry.insert( - FromMetaItem::from_meta_item(inner).map_err(|e| e.at(inner.name()))? - ); + entry.insert(FromMeta::from_meta(inner).map_err(|e| e.at(inner.name()))?); } } } @@ -298,65 +304,68 @@ impl FromMetaItem for HashMap { } } -/// Tests for `FromMetaItem` implementations. Wherever the word `ignore` appears in test input, +/// 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 quote::Tokens; - use {FromMetaItem, Result}; + use {FromMeta, Result}; /// parse a string as a syn::Meta instance. - fn pmi(tokens: Tokens) -> ::std::result::Result { + fn pm(tokens: TokenStream) -> ::std::result::Result { let attribute: syn::Attribute = parse_quote!(#[#tokens]); attribute.interpret_meta().ok_or("Unable to parse".into()) } - fn fmi(tokens: Tokens) -> T { - FromMetaItem::from_meta_item(&pmi(tokens).expect("Tests should pass well-formed input")) + fn fm(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!(fmi::<()>(quote!(ignore)), ()); + assert_eq!(fm::<()>(quote!(ignore)), ()); } #[test] fn bool_succeeds() { // word format - assert_eq!(fmi::(quote!(ignore)), true); + assert_eq!(fm::(quote!(ignore)), true); // bool literal - assert_eq!(fmi::(quote!(ignore = true)), true); - assert_eq!(fmi::(quote!(ignore = false)), false); + assert_eq!(fm::(quote!(ignore = true)), true); + assert_eq!(fm::(quote!(ignore = false)), false); // string literals - assert_eq!(fmi::(quote!(ignore = "true")), true); - assert_eq!(fmi::(quote!(ignore = "false")), false); + assert_eq!(fm::(quote!(ignore = "true")), true); + assert_eq!(fm::(quote!(ignore = "false")), false); } #[test] fn string_succeeds() { // cooked form - assert_eq!(&fmi::(quote!(ignore = "world")), "world"); + assert_eq!(&fm::(quote!(ignore = "world")), "world"); // raw form - assert_eq!(&fmi::(quote!(ignore = r#"world"#)), "world"); + assert_eq!(&fm::(quote!(ignore = r#"world"#)), "world"); } #[test] fn number_succeeds() { - assert_eq!(fmi::(quote!(ignore = "2")), 2u8); - assert_eq!(fmi::(quote!(ignore="-25")), -25i16); + assert_eq!(fm::(quote!(ignore = "2")), 2u8); + assert_eq!(fm::(quote!(ignore = "-25")), -25i16); } #[test] - fn meta_item_succeeds() { + fn meta_succeeds() { use syn::Meta; - assert_eq!(fmi::(quote!(hello(world,today))), pmi(quote!(hello(world,today))).unwrap()); + assert_eq!( + fm::(quote!(hello(world, today))), + pm(quote!(hello(world, today))).unwrap() + ); } #[test] @@ -371,14 +380,17 @@ mod tests { c }; - assert_eq!(fmi::>(quote!(ignore(hello, world = false, there = "true"))), comparison); + assert_eq!( + fm::>(quote!(ignore(hello, world = false, there = "true"))), + comparison + ); } - /// Tests that fallible parsing will always produce an outer `Ok` (from `fmi`), + /// Tests that fallible parsing will always produce an outer `Ok` (from `fm`), /// and will accurately preserve the inner contents. #[test] fn darling_result_succeeds() { - fmi::>(quote!(ignore)).unwrap(); - fmi::>(quote!(ignore(world))).unwrap_err(); + fm::>(quote!(ignore)).unwrap(); + fm::>(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 000000000000..cc9c5dac0003 --- /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; +} + +impl FromTypeParam for () { + fn from_type_param(_: &TypeParam) -> Result { + Ok(()) + } +} + +impl FromTypeParam for TypeParam { + fn from_type_param(type_param: &TypeParam) -> Result { + Ok(type_param.clone()) + } +} + +impl FromTypeParam for Vec { + fn from_type_param(type_param: &TypeParam) -> Result { + Ok(type_param.attrs.clone()) + } +} + +impl FromTypeParam for syn::Ident { + fn from_type_param(type_param: &TypeParam) -> Result { + 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 index 3c0c1774fcd5..d4dd5f2ac948 100644 --- a/third_party/rust/darling_core/src/from_variant.rs +++ b/third_party/rust/darling_core/src/from_variant.rs @@ -30,4 +30,4 @@ impl FromVariant for Vec { fn from_variant(variant: &Variant) -> Result { Ok(variant.attrs.clone()) } -} \ No newline at end of file +} diff --git a/third_party/rust/darling_core/src/lib.rs b/third_party/rust/darling_core/src/lib.rs index 50ac06a31d9f..5a45bae321da 100644 --- a/third_party/rust/darling_core/src/lib.rs +++ b/third_party/rust/darling_core/src/lib.rs @@ -7,28 +7,37 @@ extern crate quote; extern crate syn; extern crate proc_macro2; +extern crate fnv; extern crate ident_case; #[macro_use] -mod macros; +mod macros_private; +#[macro_use] +mod macros_public; pub mod ast; pub mod codegen; pub mod error; -mod from_field; mod from_derive_input; -mod from_meta_item; +mod from_field; +mod from_generic_param; +mod from_generics; +mod from_meta; +mod from_type_param; mod from_variant; pub mod options; +pub mod usage; pub mod util; -pub use error::{Result, Error}; +pub use error::{Error, Result}; pub use from_derive_input::FromDeriveInput; pub use from_field::FromField; -pub use from_meta_item::{FromMetaItem}; +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; -#[cfg(test)] -mod tests { - -} +// Re-export tokenizer +#[doc(hidden)] +pub use quote::ToTokens; \ No newline at end of file diff --git a/third_party/rust/darling_core/src/macros.rs b/third_party/rust/darling_core/src/macros_private.rs similarity index 100% rename from third_party/rust/darling_core/src/macros.rs rename to third_party/rust/darling_core/src/macros_private.rs 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 000000000000..a3c5cac98d57 --- /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 index a9a9ad11a788..adce7513c291 100644 --- a/third_party/rust/darling_core/src/options/core.rs +++ b/third_party/rust/darling_core/src/options/core.rs @@ -1,12 +1,12 @@ use ident_case::RenameRule; use syn; -use {Result, Error, FromMetaItem}; -use ast::{Data, Style, Fields}; +use ast::{Data, Fields, Style}; use codegen; use options::{DefaultExpression, InputField, InputVariant, ParseAttribute, ParseData}; +use {Error, FromMeta, Result}; -/// A struct or enum which should have `FromMetaItem` or `FromDeriveInput` implementations +/// A struct or enum which should have `FromMeta` or `FromDeriveInput` implementations /// generated. #[derive(Debug, Clone, PartialEq, Eq)] pub struct Core { @@ -45,7 +45,7 @@ impl Core { 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{ + rename_rule: if let syn::Data::Enum(_) = di.data { RenameRule::SnakeCase } else { Default::default() @@ -56,11 +56,10 @@ impl Core { } fn as_codegen_default<'a>(&'a self) -> Option> { - self.default.as_ref().map(|expr| { - match *expr { - DefaultExpression::Explicit(ref path) => codegen::DefaultExpression::Explicit(path), - DefaultExpression::Inherit | - DefaultExpression::Trait => codegen::DefaultExpression::Trait, + self.default.as_ref().map(|expr| match *expr { + DefaultExpression::Explicit(ref path) => codegen::DefaultExpression::Explicit(path), + DefaultExpression::Inherit | DefaultExpression::Trait => { + codegen::DefaultExpression::Trait } }) } @@ -68,31 +67,31 @@ impl Core { impl ParseAttribute for Core { fn parse_nested(&mut self, mi: &syn::Meta) -> Result<()> { - match mi.name().as_ref() { + match mi.name().to_string().as_str() { "default" => { if self.default.is_some() { Err(Error::duplicate_field("default")) } else { - self.default = FromMetaItem::from_meta_item(mi)?; + self.default = FromMeta::from_meta(mi)?; Ok(()) } } "rename_all" => { // WARNING: This may have been set based on body shape previously, // so an overwrite may be permissible. - self.rename_rule = FromMetaItem::from_meta_item(mi)?; + self.rename_rule = FromMeta::from_meta(mi)?; Ok(()) } "map" => { if self.map.is_some() { Err(Error::duplicate_field("map")) } else { - self.map = FromMetaItem::from_meta_item(mi)?; + self.map = FromMeta::from_meta(mi)?; Ok(()) } } "bound" => { - self.bound = FromMetaItem::from_meta_item(mi)?; + self.bound = FromMeta::from_meta(mi)?; Ok(()) } n => Err(Error::unknown_field(n.as_ref())), @@ -117,9 +116,9 @@ impl ParseData for Core { 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 { + style: Style::Unit, .. + }) => panic!("Core::parse_field should not be called on unit"), Data::Struct(Fields { ref mut fields, .. }) => { fields.push(f); Ok(()) diff --git a/third_party/rust/darling_core/src/options/forward_attrs.rs b/third_party/rust/darling_core/src/options/forward_attrs.rs index d1ee2424c840..51cb84097c9a 100644 --- a/third_party/rust/darling_core/src/options/forward_attrs.rs +++ b/third_party/rust/darling_core/src/options/forward_attrs.rs @@ -1,7 +1,7 @@ use syn::NestedMeta; -use {FromMetaItem, Result}; use util::IdentList; +use {FromMeta, Result}; /// A rule about which attributes to forward to the generated struct. #[derive(Debug, Clone, PartialEq, Eq)] @@ -20,7 +20,7 @@ impl ForwardAttrs { } } -impl FromMetaItem for ForwardAttrs { +impl FromMeta for ForwardAttrs { fn from_word() -> Result { Ok(ForwardAttrs::All) } diff --git a/third_party/rust/darling_core/src/options/from_derive.rs b/third_party/rust/darling_core/src/options/from_derive.rs index 9a6d1381332a..23664bd12dec 100644 --- a/third_party/rust/darling_core/src/options/from_derive.rs +++ b/third_party/rust/darling_core/src/options/from_derive.rs @@ -1,8 +1,8 @@ use syn::{self, Ident}; -use {FromMetaItem, Result}; use codegen; -use options::{ParseAttribute, ParseData, OuterFrom, Shape}; +use options::{OuterFrom, ParseAttribute, ParseData, Shape}; +use {FromMeta, Result}; #[derive(Debug)] pub struct FdiOptions { @@ -27,15 +27,19 @@ impl FdiOptions { generics: Default::default(), data: Default::default(), supports: Default::default(), - }).parse_attributes(&di.attrs)?.parse_body(&di.data) + }).parse_attributes(&di.attrs)? + .parse_body(&di.data) } } impl ParseAttribute for FdiOptions { fn parse_nested(&mut self, mi: &syn::Meta) -> Result<()> { - match mi.name().as_ref() { - "supports" => { self.supports = FromMetaItem::from_meta_item(mi)?; Ok(()) }, - _ => self.base.parse_nested(mi) + match mi.name().to_string().as_str() { + "supports" => { + self.supports = FromMeta::from_meta(mi)?; + Ok(()) + } + _ => self.base.parse_nested(mi), } } } @@ -46,11 +50,26 @@ impl ParseData for FdiOptions { } fn parse_field(&mut self, field: &syn::Field) -> Result<()> { - match field.ident.as_ref().map(|v| v.as_ref()) { - 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) + 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), } } } @@ -59,8 +78,8 @@ impl<'a> From<&'a FdiOptions> for codegen::FromDeriveInputImpl<'a> { fn from(v: &'a FdiOptions) -> Self { codegen::FromDeriveInputImpl { base: (&v.base.container).into(), - attr_names: v.base.attr_names.as_strs(), - from_ident: Some(v.base.from_ident), + 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(), diff --git a/third_party/rust/darling_core/src/options/from_field.rs b/third_party/rust/darling_core/src/options/from_field.rs index ca26d5fa089d..215bdb0f925f 100644 --- a/third_party/rust/darling_core/src/options/from_field.rs +++ b/third_party/rust/darling_core/src/options/from_field.rs @@ -1,8 +1,8 @@ use syn::{self, Ident}; -use {Result}; use codegen::FromFieldImpl; -use options::{ParseAttribute, ParseData, OuterFrom}; +use options::{OuterFrom, ParseAttribute, ParseData}; +use Result; #[derive(Debug)] pub struct FromFieldOptions { @@ -17,7 +17,8 @@ impl FromFieldOptions { base: OuterFrom::start(di), vis: Default::default(), ty: Default::default(), - }).parse_attributes(&di.attrs)?.parse_body(&di.data) + }).parse_attributes(&di.attrs)? + .parse_body(&di.data) } } @@ -33,10 +34,22 @@ impl ParseData for FromFieldOptions { } fn parse_field(&mut self, field: &syn::Field) -> Result<()> { - match field.ident.as_ref().map(|v| v.as_ref()) { - Some("vis") => { self.vis = field.ident.clone(); Ok(()) }, - Some("ty") => { self.ty = field.ident.clone(); Ok(()) } - _ => self.base.parse_field(field) + 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), } } } @@ -49,7 +62,7 @@ impl<'a> From<&'a FromFieldOptions> for FromFieldImpl<'a> { ty: v.ty.as_ref(), attrs: v.base.attrs.as_ref(), base: (&v.base.container).into(), - attr_names: v.base.attr_names.as_strs(), + attr_names: &v.base.attr_names, forward_attrs: v.base.forward_attrs.as_ref(), from_ident: v.base.from_ident, } diff --git a/third_party/rust/darling_core/src/options/from_meta_item.rs b/third_party/rust/darling_core/src/options/from_meta.rs similarity index 59% rename from third_party/rust/darling_core/src/options/from_meta_item.rs rename to third_party/rust/darling_core/src/options/from_meta.rs index 7efdcd490e10..c8d40c48ce64 100644 --- a/third_party/rust/darling_core/src/options/from_meta_item.rs +++ b/third_party/rust/darling_core/src/options/from_meta.rs @@ -1,28 +1,29 @@ use syn; -use Result; use codegen; use options::{Core, ParseAttribute, ParseData}; +use Result; -pub struct FmiOptions { - base: Core +pub struct FromMetaOptions { + base: Core, } -impl FmiOptions { +impl FromMetaOptions { pub fn new(di: &syn::DeriveInput) -> Result { - (FmiOptions { + (FromMetaOptions { base: Core::start(di), - }).parse_attributes(&di.attrs)?.parse_body(&di.data) + }).parse_attributes(&di.attrs)? + .parse_body(&di.data) } } -impl ParseAttribute for FmiOptions { +impl ParseAttribute for FromMetaOptions { fn parse_nested(&mut self, mi: &syn::Meta) -> Result<()> { self.base.parse_nested(mi) } } -impl ParseData for FmiOptions { +impl ParseData for FromMetaOptions { fn parse_variant(&mut self, variant: &syn::Variant) -> Result<()> { self.base.parse_variant(variant) } @@ -32,9 +33,9 @@ impl ParseData for FmiOptions { } } -impl<'a> From<&'a FmiOptions> for codegen::FmiImpl<'a> { - fn from(v: &'a FmiOptions) -> Self { - codegen::FmiImpl { +impl<'a> From<&'a FromMetaOptions> for codegen::FromMetaImpl<'a> { + fn from(v: &'a FromMetaOptions) -> Self { + codegen::FromMetaImpl { base: (&v.base).into(), } } 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 000000000000..e6735efa95f3 --- /dev/null +++ b/third_party/rust/darling_core/src/options/from_type_param.rs @@ -0,0 +1,70 @@ +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, + pub default: Option, +} + +impl FromTypeParamOptions { + pub fn new(di: &syn::DeriveInput) -> Result { + (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, + } + } +} diff --git a/third_party/rust/darling_core/src/options/from_variant.rs b/third_party/rust/darling_core/src/options/from_variant.rs index 0ee4c40777fe..bc1cf781781e 100644 --- a/third_party/rust/darling_core/src/options/from_variant.rs +++ b/third_party/rust/darling_core/src/options/from_variant.rs @@ -1,8 +1,8 @@ use syn::{DeriveInput, Field, Ident, Meta}; -use {FromMetaItem, Result}; use codegen::FromVariantImpl; -use options::{OuterFrom, ParseAttribute, ParseData, DataShape}; +use options::{DataShape, OuterFrom, ParseAttribute, ParseData}; +use {FromMeta, Result}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct FromVariantOptions { @@ -17,7 +17,8 @@ impl FromVariantOptions { base: OuterFrom::start(di), fields: Default::default(), supports: Default::default(), - }).parse_attributes(&di.attrs)?.parse_body(&di.data) + }).parse_attributes(&di.attrs)? + .parse_body(&di.data) } } @@ -28,9 +29,9 @@ impl<'a> From<&'a FromVariantOptions> for FromVariantImpl<'a> { ident: v.base.ident.as_ref(), fields: v.fields.as_ref(), attrs: v.base.attrs.as_ref(), - attr_names: v.base.attr_names.as_strs(), + attr_names: &v.base.attr_names, forward_attrs: v.base.forward_attrs.as_ref(), - from_ident: Some(v.base.from_ident), + from_ident: v.base.from_ident, supports: v.supports.as_ref(), } } @@ -38,18 +39,30 @@ impl<'a> From<&'a FromVariantOptions> for FromVariantImpl<'a> { impl ParseAttribute for FromVariantOptions { fn parse_nested(&mut self, mi: &Meta) -> Result<()> { - match mi.name().as_ref() { - "supports" => { self.supports = FromMetaItem::from_meta_item(mi)?; Ok(()) } - _ => self.base.parse_nested(mi) + match mi.name().to_string().as_str() { + "supports" => { + self.supports = FromMeta::from_meta(mi)?; + Ok(()) + } + _ => self.base.parse_nested(mi), } } } impl ParseData for FromVariantOptions { fn parse_field(&mut self, field: &Field) -> Result<()> { - match field.ident.as_ref().map(|i| i.as_ref()) { - Some("fields") => { self.fields = field.ident.clone(); Ok(()) } - _ => self.base.parse_field(field) + 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), } } } diff --git a/third_party/rust/darling_core/src/options/input_field.rs b/third_party/rust/darling_core/src/options/input_field.rs index 34b7f3adeb9e..b437f670fe0b 100644 --- a/third_party/rust/darling_core/src/options/input_field.rs +++ b/third_party/rust/darling_core/src/options/input_field.rs @@ -1,9 +1,8 @@ use syn; -use ::{FromMetaItem, Error, Result}; use codegen; use options::{Core, DefaultExpression, ParseAttribute}; - +use {Error, FromMeta, Result}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct InputField { @@ -25,10 +24,14 @@ impl InputField { 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(|n| n.as_str()).unwrap_or(self.ident.as_ref()), + name_in_attr: self.attr_name + .clone() + .unwrap_or(self.ident.to_string()), ty: &self.ty, default_expression: self.as_codegen_default(), - with_path: self.with.clone().unwrap_or(parse_quote!(::darling::FromMetaItem::from_meta_item)), + with_path: self.with + .clone() + .unwrap_or(parse_quote!(::darling::FromMeta::from_meta)), skip: self.skip, map: self.map.as_ref(), multiple: self.multiple, @@ -38,12 +41,10 @@ impl InputField { /// Generate a codegen::DefaultExpression for this field. This requires the field name /// in the `Inherit` case. fn as_codegen_default<'a>(&'a self) -> Option> { - 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, - } + 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, }) } @@ -61,7 +62,10 @@ impl InputField { } pub fn from_field(f: &syn::Field, parent: Option<&Core>) -> Result { - let ident = f.ident.clone().unwrap_or(syn::Ident::new("__unnamed", ::proc_macro2::Span::call_site())); + let ident = f.ident.clone().unwrap_or(syn::Ident::new( + "__unnamed", + ::proc_macro2::Span::call_site(), + )); let ty = f.ty.clone(); let base = Self::new(ident, ty).parse_attributes(&f.attrs)?; @@ -78,7 +82,7 @@ impl InputField { // 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)); + 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: @@ -109,12 +113,30 @@ impl ParseAttribute for InputField { fn parse_nested(&mut self, mi: &syn::Meta) -> Result<()> { let name = mi.name().to_string(); match name.as_str() { - "rename" => { self.attr_name = FromMetaItem::from_meta_item(mi)?; Ok(()) } - "default" => { self.default = FromMetaItem::from_meta_item(mi)?; Ok(()) } - "with" => { self.with = Some(FromMetaItem::from_meta_item(mi)?); Ok(()) } - "skip" => { self.skip = FromMetaItem::from_meta_item(mi)?; Ok(()) } - "map" => { self.map = Some(FromMetaItem::from_meta_item(mi)?); Ok(()) } - "multiple" => { self.multiple = FromMetaItem::from_meta_item(mi)?; Ok(()) } + "rename" => { + self.attr_name = FromMeta::from_meta(mi)?; + Ok(()) + } + "default" => { + self.default = FromMeta::from_meta(mi)?; + Ok(()) + } + "with" => { + self.with = Some(FromMeta::from_meta(mi)?); + Ok(()) + } + "skip" => { + self.skip = FromMeta::from_meta(mi)?; + Ok(()) + } + "map" => { + self.map = Some(FromMeta::from_meta(mi)?); + Ok(()) + } + "multiple" => { + self.multiple = FromMeta::from_meta(mi)?; + Ok(()) + } n => Err(Error::unknown_field(n)), } } diff --git a/third_party/rust/darling_core/src/options/input_variant.rs b/third_party/rust/darling_core/src/options/input_variant.rs index 31c1438beb21..8fdcf38335cf 100644 --- a/third_party/rust/darling_core/src/options/input_variant.rs +++ b/third_party/rust/darling_core/src/options/input_variant.rs @@ -1,9 +1,9 @@ use syn; -use {FromMetaItem, Error, Result}; -use ast::{Style, Fields}; +use ast::{Fields, Style}; use codegen; use options::{Core, InputField, ParseAttribute}; +use {Error, FromMeta, Result}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct InputVariant { @@ -18,7 +18,9 @@ impl InputVariant { codegen::Variant { ty_ident, variant_ident: &self.ident, - name_in_attr: self.attr_name.as_ref().map(|s| s.as_str()).unwrap_or(self.ident.as_ref()), + name_in_attr: self.attr_name + .clone() + .unwrap_or(self.ident.to_string()), data: self.data.as_ref().map(InputField::as_codegen_field), skip: self.skip, } @@ -44,7 +46,7 @@ impl InputVariant { style: v.fields.clone().into(), fields: items, } - }, + } syn::Fields::Named(ref fields) => { let mut items = Vec::with_capacity(fields.named.len()); for item in &fields.named { @@ -67,24 +69,23 @@ impl InputVariant { 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)); + self.attr_name = Some(parent.rename_rule.apply_to_variant(self.ident.to_string())); } self } } - impl ParseAttribute for InputVariant { fn parse_nested(&mut self, mi: &syn::Meta) -> Result<()> { let name = mi.name().to_string(); match name.as_str() { "rename" => { - self.attr_name = FromMetaItem::from_meta_item(mi)?; + self.attr_name = FromMeta::from_meta(mi)?; Ok(()) } "skip" => { - self.skip = FromMetaItem::from_meta_item(mi)?; + self.skip = FromMeta::from_meta(mi)?; Ok(()) } n => Err(Error::unknown_field(n)), diff --git a/third_party/rust/darling_core/src/options/mod.rs b/third_party/rust/darling_core/src/options/mod.rs index e2d58c01d799..f8ea7d651073 100644 --- a/third_party/rust/darling_core/src/options/mod.rs +++ b/third_party/rust/darling_core/src/options/mod.rs @@ -1,15 +1,16 @@ use syn; -use {FromMetaItem, Result, Error}; +use {Error, FromMeta, Result}; mod core; mod forward_attrs; mod from_derive; mod from_field; -mod from_meta_item; +mod from_meta; +mod from_type_param; mod from_variant; -mod input_variant; mod input_field; +mod input_variant; mod outer_from; mod shape; @@ -17,10 +18,11 @@ 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_item::FmiOptions; +pub use self::from_meta::FromMetaOptions; +pub use self::from_type_param::FromTypeParamOptions; pub use self::from_variant::FromVariantOptions; -pub use self::input_variant::InputVariant; pub use self::input_field::InputField; +pub use self::input_variant::InputVariant; pub use self::outer_from::OuterFrom; pub use self::shape::{DataShape, Shape}; @@ -35,13 +37,15 @@ pub enum DefaultExpression { } #[doc(hidden)] -impl FromMetaItem for DefaultExpression { +impl FromMeta for DefaultExpression { fn from_word() -> Result { Ok(DefaultExpression::Trait) } fn from_string(lit: &str) -> Result { - Ok(DefaultExpression::Explicit(syn::Path::from(lit))) + Ok(DefaultExpression::Explicit( + syn::parse_str(lit).map_err(|_| Error::unknown_value(lit))? + )) } } @@ -62,10 +66,6 @@ pub trait ParseAttribute: Sized { } fn parse_attr(attr: &syn::Attribute, target: &mut T) -> Result<()> { - if attr.is_sugared_doc { - return Ok(()) - } - match attr.interpret_meta() { Some(syn::Meta::List(data)) => { for item in data.nested { @@ -77,7 +77,7 @@ fn parse_attr(attr: &syn::Attribute, target: &mut T) -> Resul } Ok(()) - }, + } Some(ref item) => panic!("Wasn't able to parse: `{:?}`", item), None => panic!("Unable to parse {:?}", attr), } @@ -88,24 +88,22 @@ pub trait ParseData: Sized { use syn::{Data, Fields}; match *body { - Data::Struct(ref data) => { - match data.fields { - Fields::Unit => Ok(self), - Fields::Named(ref fields) => { - for field in &fields.named { - self.parse_field(field)?; - } - Ok(self) - } - Fields::Unnamed(ref fields) => { - for field in &fields.unnamed { - self.parse_field(field)?; - } - - Ok(self) + Data::Struct(ref data) => match data.fields { + Fields::Unit => Ok(self), + Fields::Named(ref fields) => { + for field in &fields.named { + self.parse_field(field)?; } + Ok(self) } - } + Fields::Unnamed(ref fields) => { + for field in &fields.unnamed { + self.parse_field(field)?; + } + + Ok(self) + } + }, Data::Enum(ref data) => { for variant in &data.variants { self.parse_variant(variant)?; diff --git a/third_party/rust/darling_core/src/options/outer_from.rs b/third_party/rust/darling_core/src/options/outer_from.rs index 82d860fd4b84..dac1435160a4 100644 --- a/third_party/rust/darling_core/src/options/outer_from.rs +++ b/third_party/rust/darling_core/src/options/outer_from.rs @@ -1,8 +1,8 @@ use syn::{self, Field, Ident, Meta}; -use {FromMetaItem, Result}; use options::{Core, DefaultExpression, ForwardAttrs, ParseAttribute, ParseData}; use util::IdentList; +use {FromMeta, Result}; /// Reusable base for `FromDeriveInput`, `FromVariant`, `FromField`, and other top-level /// `From*` traits. @@ -42,9 +42,15 @@ impl OuterFrom { impl ParseAttribute for OuterFrom { fn parse_nested(&mut self, mi: &Meta) -> Result<()> { - match mi.name().as_ref() { - "attributes" => { self.attr_names = FromMetaItem::from_meta_item(mi)?; Ok(()) } - "forward_attrs" => { self.forward_attrs = FromMetaItem::from_meta_item(mi)?; Ok(()) }, + match mi.name().to_string().as_str() { + "attributes" => { + self.attr_names = FromMeta::from_meta(mi)?; + Ok(()) + } + "forward_attrs" => { + self.forward_attrs = FromMeta::from_meta(mi)?; + Ok(()) + } "from_ident" => { // HACK: Declaring that a default is present will cause fields to // generate correct code, but control flow isn't that obvious. @@ -52,17 +58,29 @@ impl ParseAttribute for OuterFrom { self.from_ident = true; Ok(()) } - _ => self.container.parse_nested(mi) + _ => self.container.parse_nested(mi), } } } impl ParseData for OuterFrom { fn parse_field(&mut self, field: &Field) -> Result<()> { - match field.ident.as_ref().map(|v| v.as_ref()) { - Some("ident") => { self.ident = field.ident.clone(); Ok(()) } - Some("attrs") => { self.attrs = field.ident.clone(); Ok(()) } - _ => self.container.parse_field(field) + 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 index 3bafd37bd880..11f175a437d8 100644 --- a/third_party/rust/darling_core/src/options/shape.rs +++ b/third_party/rust/darling_core/src/options/shape.rs @@ -1,7 +1,8 @@ -use quote::{Tokens, ToTokens}; +use proc_macro2::TokenStream; +use quote::{TokenStreamExt, ToTokens}; use syn::{Meta, NestedMeta}; -use {Error, FromMetaItem, Result}; +use {Error, FromMeta, Result}; #[derive(Debug, Clone)] pub struct Shape { @@ -29,16 +30,16 @@ impl Default for Shape { } } -impl FromMetaItem for Shape { +impl FromMeta for Shape { fn from_list(items: &[NestedMeta]) -> Result { let mut new = Shape::default(); for item in items { if let NestedMeta::Meta(Meta::Word(ref ident)) = *item { - let word = ident.as_ref(); + let word = ident.to_string(); + let word = word.as_str(); if word == "any" { new.any = true; - } - else if word.starts_with("enum_") { + } else if word.starts_with("enum_") { new.enum_values.set_word(word)?; } else if word.starts_with("struct_") { new.struct_values.set_word(word)?; @@ -55,11 +56,10 @@ impl FromMetaItem for Shape { } impl ToTokens for Shape { - fn to_tokens(&self, tokens: &mut Tokens) { + fn to_tokens(&self, tokens: &mut TokenStream) { let fn_body = if self.any == true { quote!(::darling::export::Ok(())) - } - else { + } else { let en = &self.enum_values; let st = &self.struct_values; quote! { @@ -75,7 +75,8 @@ impl ToTokens for Shape { Ok(()) } - ::syn::Data::Struct(ref data) => { + ::syn::Data::Struct(ref struct_data) => { + let data = &struct_data.fields; #st } ::syn::Data::Union(_) => unreachable!(), @@ -144,12 +145,12 @@ impl DataShape { } } -impl FromMetaItem for DataShape { +impl FromMeta for DataShape { fn from_list(items: &[NestedMeta]) -> Result { let mut new = DataShape::default(); for item in items { if let NestedMeta::Meta(Meta::Word(ref ident)) = *item { - new.set_word(ident.as_ref())?; + new.set_word(ident.to_string().as_str())?; } else { return Err(Error::unsupported_format("non-word")); } @@ -160,12 +161,12 @@ impl FromMetaItem for DataShape { } impl ToTokens for DataShape { - fn to_tokens(&self, tokens: &mut Tokens) { + 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_format(#ty))) + quote!(::darling::export::Err(::darling::Error::unsupported_shape(#ty))) } else { let unit = match_arm("unit", self.unit); let newtype = match_arm("newtype", self.newtype); @@ -195,49 +196,49 @@ impl ToTokens for DataShape { } } -fn match_arm(name: &'static str, is_supported: bool) -> Tokens { +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_format(#name))) + quote!(::darling::export::Err(::darling::Error::unsupported_shape(#name))) } } #[cfg(test)] mod tests { + use proc_macro2::TokenStream; use syn; - use quote::Tokens; use super::Shape; - use {FromMetaItem}; + use FromMeta; /// parse a string as a syn::Meta instance. - fn pmi(tokens: Tokens) -> ::std::result::Result { + fn pm(tokens: TokenStream) -> ::std::result::Result { let attribute: syn::Attribute = parse_quote!(#[#tokens]); attribute.interpret_meta().ok_or("Unable to parse".into()) } - fn fmi(tokens: Tokens) -> T { - FromMetaItem::from_meta_item(&pmi(tokens).expect("Tests should pass well-formed input")) + fn fm(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 = fmi::(quote!(ignore(any))); + let decl = fm::(quote!(ignore(any))); assert_eq!(decl.any, true); } #[test] fn supports_struct() { - let decl = fmi::(quote!(ignore(struct_any, struct_newtype))); + let decl = fm::(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 = fmi::(quote!(ignore(struct_newtype, enum_newtype, enum_tuple))); + let decl = fm::(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); 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 000000000000..82af2f576209 --- /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 000000000000..e38d332dd071 --- /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; + +/// 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 000000000000..eed944d89993 --- /dev/null +++ b/third_party/rust/darling_core/src/usage/lifetimes.rs @@ -0,0 +1,322 @@ +use fnv::FnvHashSet; +use syn::punctuated::Punctuated; +use syn::{self, Lifetime, Type}; + +use usage::Options; + +/// A set of lifetimes. +pub type LifetimeSet = FnvHashSet; + +/// 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, + 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 UsesLifetimes for Vec { + fn uses_lifetimes<'a>( + &self, + options: &Options, + lifetimes: &'a LifetimeSet, + ) -> LifetimeRefSet<'a> { + self.collect_lifetimes(options, lifetimes) + } +} + +impl UsesLifetimes for Punctuated { + fn uses_lifetimes<'a>( + &self, + options: &Options, + lifetimes: &'a LifetimeSet, + ) -> LifetimeRefSet<'a> { + self.collect_lifetimes(options, lifetimes) + } +} + +impl UsesLifetimes for Option { + fn uses_lifetimes<'a>( + &self, + options: &Options, + lifetimes: &'a LifetimeSet, + ) -> LifetimeRefSet<'a> { + self.as_ref().map_or_else( + || Default::default(), + |v| v.uses_lifetimes(options, lifetimes), + ) + } +} + +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() + } + } + } +} + +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::*; + + fn parse(src: &str) -> DeriveInput { + syn::parse_str(src).unwrap() + } + + #[test] + fn struct_named() { + let input = parse("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 = parse( + "struct Foo<'a, 'b: 'a> { parent: &'b Bar, child: 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 000000000000..bc1d1e08d41a --- /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::>(); +//! +//! 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(<.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, +//! ty: syn::Type, +//! #[darling(default)] +//! volume: Option, +//! } +//! +//! uses_type_params!(SpeakerField, ty); +//! uses_lifetimes!(SpeakerField, ty); +//! +//! #[derive(FromDeriveInput)] +//! struct SpeakerOptions { +//! generics: syn::Generics, +//! data: darling::ast::Data, +//! } +//! ``` +//! +//! 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 000000000000..f154881be9c7 --- /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 ` 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` 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 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 000000000000..310b381eaf4b --- /dev/null +++ b/third_party/rust/darling_core/src/usage/type_params.rs @@ -0,0 +1,362 @@ +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, + 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 UsesTypeParams for Option { + 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 UsesTypeParams for Vec { + fn uses_type_params<'a>(&self, options: &Options, type_set: &'a IdentSet) -> IdentRefSet<'a> { + self.collect_type_params(options, type_set) + } +} + +impl UsesTypeParams for Punctuated { + 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() + } + } + } +} + +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::{self, Ident}; + + use super::UsesTypeParams; + use usage::IdentSet; + use usage::Purpose::*; + + fn given_src(src: &str) -> syn::DeriveInput { + syn::parse_str(src).unwrap() + } + + 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 = given_src("struct Foo(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::(&parse_quote!(T))); + assert!(matches.contains::(&parse_quote!(U))); + assert!(!matches.contains::(&parse_quote!(X))); + assert!(!matches.contains::(&parse_quote!(A))); + } + + #[test] + fn finds_named() { + let input = given_src( + r#" + struct Foo { + 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::(&parse_quote!(T))); + assert!(matches.contains::(&parse_quote!(U))); + assert!(!matches.contains::(&parse_quote!(X))); + assert!(!matches.contains::(&parse_quote!(A))); + } + + #[test] + fn finds_as_type_arg() { + let input = given_src( + r#" + struct Foo { + bar: T, + world: Vec, + } + "#, + ); + + 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::(&parse_quote!(T))); + assert!(matches.contains::(&parse_quote!(U))); + assert!(!matches.contains::(&parse_quote!(X))); + assert!(!matches.contains::(&parse_quote!(A))); + } + + #[test] + fn associated_type() { + let input = given_src("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 = given_src("struct Foo(Box 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::(&parse_quote!(T))); + } + + #[test] + fn box_fn_input() { + let input = given_src("struct Foo(Box ()>);"); + let generics = ident_set(vec!["T"]); + let matches = input.data.uses_type_params(&BoundImpl.into(), &generics); + assert_eq!(matches.len(), 1); + assert!(matches.contains::(&parse_quote!(T))); + } + + /// Test that `syn::TypePath` is correctly honoring the different modes a + /// search can execute in. + #[test] + fn qself_vec() { + let input = given_src("struct Foo( 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::(&parse_quote!(T))); + } +} diff --git a/third_party/rust/darling_core/src/util/ident_list.rs b/third_party/rust/darling_core/src/util/ident_list.rs index 7641cd36efaa..d81697cfccb6 100644 --- a/third_party/rust/darling_core/src/util/ident_list.rs +++ b/third_party/rust/darling_core/src/util/ident_list.rs @@ -1,14 +1,15 @@ use std::ops::Deref; +use std::string::ToString; -use syn::{Ident, NestedMeta, Meta}; +use syn::{Ident, Meta, NestedMeta}; -use {FromMetaItem, Result, Error}; +use {Error, FromMeta, Result}; -/// A list of `syn::Ident` instances. This type is used to extract a list of words from an +/// A list of `syn::Ident` instances. This type is used to extract a list of words from an /// attribute. /// /// # Usage -/// An `IdentList` field on a struct implementing `FromMetaItem` will turn `#[builder(derive(Debug, Clone))]` into: +/// An `IdentList` field on a struct implementing `FromMeta` will turn `#[builder(derive(Debug, Clone))]` into: /// /// ```rust,ignore /// StructOptions { @@ -24,9 +25,9 @@ impl IdentList { IdentList(vals.into_iter().map(T::into).collect()) } - /// Creates a view of the contained identifiers as `&str`s. - pub fn as_strs<'a>(&'a self) -> Vec<&'a str> { - self.iter().map(|i| i.as_ref()).collect() + /// Create a new `Vec` containing the string representation of each ident. + pub fn to_strings(&self) -> Vec { + self.0.iter().map(ToString::to_string).collect() } } @@ -44,14 +45,14 @@ impl From> for IdentList { } } -impl FromMetaItem for IdentList { +impl FromMeta for IdentList { fn from_list(v: &[NestedMeta]) -> Result { let mut idents = Vec::with_capacity(v.len()); for nmi in v { if let NestedMeta::Meta(Meta::Word(ref ident)) = *nmi { idents.push(ident.clone()); } else { - return Err(Error::unexpected_type("non-word")) + return Err(Error::unexpected_type("non-word")); } } 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 000000000000..529891f71fd9 --- /dev/null +++ b/third_party/rust/darling_core/src/util/ident_string.rs @@ -0,0 +1,148 @@ +use std::fmt; + +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, Hash, 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(self, map_fn: F) -> Self + where + F: FnOnce(String) -> S, + S: AsRef, + { + let span = self.span(); + let string = map_fn(self.string); + Ident::new(string.as_ref(), span).into() + } +} + +impl AsRef for IdentString { + fn as_ref(&self) -> &Ident { + self.as_ident() + } +} + +impl AsRef for IdentString { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl From for IdentString { + fn from(ident: Ident) -> Self { + IdentString::new(ident) + } +} + +impl From for Ident { + fn from(v: IdentString) -> Ident { + v.ident + } +} + +impl From 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 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 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 { + 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 index 8edf58a3d71f..9347fb433172 100644 --- a/third_party/rust/darling_core/src/util/ignored.rs +++ b/third_party/rust/darling_core/src/util/ignored.rs @@ -1,38 +1,52 @@ use syn; -use {FromMetaItem, FromDeriveInput, FromField, FromVariant, Result}; +use usage::{self, UsesLifetimes, UsesTypeParams}; +use { + FromDeriveInput, FromField, FromGenericParam, FromGenerics, FromMeta, FromTypeParam, + FromVariant, Result, +}; -/// An efficient way of discarding data from an attribute. +/// An efficient way of discarding data from a syntax element. /// -/// All meta-items, fields, and variants will be successfully read into +/// 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; -impl FromMetaItem for Ignored { - fn from_meta_item(_: &syn::Meta) -> Result { - Ok(Ignored) - } +macro_rules! ignored { + ($trayt:ident, $method:ident, $syn:path) => { + impl $trayt for Ignored { + fn $method(_: &$syn) -> Result { + Ok(Ignored) + } + } + }; +} - fn from_nested_meta_item(_: &syn::NestedMeta) -> Result { - 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 FromDeriveInput for Ignored { - fn from_derive_input(_: &syn::DeriveInput) -> Result { - Ok(Ignored) +impl UsesLifetimes for Ignored { + fn uses_lifetimes<'a>( + &self, + _opts: &usage::Options, + _: &'a usage::LifetimeSet, + ) -> usage::LifetimeRefSet<'a> { + Default::default() } } - -impl FromField for Ignored { - fn from_field(_: &syn::Field) -> Result { - Ok(Ignored) - } -} - -impl FromVariant for Ignored { - fn from_variant(_: &syn::Variant) -> Result { - Ok(Ignored) - } -} \ No newline at end of file diff --git a/third_party/rust/darling_core/src/util/mod.rs b/third_party/rust/darling_core/src/util/mod.rs index 8ee6e072f81b..f3f58d8293b7 100644 --- a/third_party/rust/darling_core/src/util/mod.rs +++ b/third_party/rust/darling_core/src/util/mod.rs @@ -1,17 +1,21 @@ //! Utility types for attribute parsing. -use std::ops::{Deref, Not, BitAnd, BitOr}; +use std::ops::{BitAnd, BitOr, Deref, Not}; use syn; -use {FromMetaItem, Result}; +use {FromMeta, Result}; mod ident_list; +mod ident_string; mod ignored; mod over_ride; +mod with_original; pub use self::ident_list::IdentList; +pub use self::ident_string::IdentString; pub use self::ignored::Ignored; pub use self::over_ride::Override; +pub use self::with_original::WithOriginal; /// Marker type equivalent to `Option<()>` for use in attribute parsing. #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] @@ -31,9 +35,9 @@ impl Deref for Flag { } } -impl FromMetaItem for Flag { - fn from_meta_item(mi: &syn::Meta) -> Result { - FromMetaItem::from_meta_item(mi).map(Flag) +impl FromMeta for Flag { + fn from_meta(mi: &syn::Meta) -> Result { + FromMeta::from_meta(mi).map(Flag) } } @@ -45,7 +49,11 @@ impl From for bool { impl From for Flag { fn from(v: bool) -> Self { - if v { Flag::present() } else { Flag(None) } + if v { + Flag::present() + } else { + Flag(None) + } } } @@ -99,4 +107,4 @@ impl BitOr for Flag { fn bitor(self, rhs: Self) -> Self { (self.into() || rhs.into()).into() } -} \ No newline at end of file +} diff --git a/third_party/rust/darling_core/src/util/over_ride.rs b/third_party/rust/darling_core/src/util/over_ride.rs index c83414fdfb2e..668676cc72e4 100644 --- a/third_party/rust/darling_core/src/util/over_ride.rs +++ b/third_party/rust/darling_core/src/util/over_ride.rs @@ -2,7 +2,7 @@ use std::fmt; use syn::{Lit, NestedMeta}; -use {Result, FromMetaItem}; +use {FromMeta, Result}; use self::Override::*; @@ -42,7 +42,7 @@ pub enum Override { Inherit, /// Explicitly set the value. - Explicit(T) + Explicit(T), } impl Override { @@ -52,7 +52,7 @@ impl Override { pub fn as_ref<'a>(&'a self) -> Override<&'a T> { match *self { Inherit => Inherit, - Explicit(ref val) => Explicit(val) + Explicit(ref val) => Explicit(val), } } @@ -62,7 +62,7 @@ impl Override { pub fn as_mut<'a>(&'a mut self) -> Override<&'a T> { match *self { Inherit => Inherit, - Explicit(ref mut val) => Explicit(val) + Explicit(ref mut val) => Explicit(val), } } @@ -78,7 +78,7 @@ impl Override { pub fn explicit(self) -> Option { match self { Inherit => None, - Explicit(val) => Some(val) + Explicit(val) => Some(val), } } @@ -91,7 +91,10 @@ impl Override { } /// Unwraps an override, yielding the content of an `Explicit`. Otherwise, it calls `op`. - pub fn unwrap_or_else(self, op: F) -> T where F: FnOnce() -> T { + pub fn unwrap_or_else(self, op: F) -> T + where + F: FnOnce() -> T, + { match self { Inherit => op(), Explicit(val) => val, @@ -131,17 +134,17 @@ impl fmt::Display for Override { } /// Parses a `Meta`. A bare word will produce `Override::Inherit`, while -/// any value will be forwarded to `T::from_meta_item`. -impl FromMetaItem for Override { +/// any value will be forwarded to `T::from_meta`. +impl FromMeta for Override { fn from_word() -> Result { Ok(Inherit) } fn from_list(items: &[NestedMeta]) -> Result { - Ok(Explicit(FromMetaItem::from_list(items)?)) + Ok(Explicit(FromMeta::from_list(items)?)) } fn from_value(lit: &Lit) -> Result { - Ok(Explicit(FromMetaItem::from_value(lit)?)) + Ok(Explicit(FromMeta::from_value(lit)?)) } -} \ No newline at end of file +} 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 000000000000..e53264bb4571 --- /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 { + pub parsed: T, + pub original: O, +} + +impl WithOriginal { + pub fn new(parsed: T, original: O) -> Self { + WithOriginal { parsed, original } + } +} + +macro_rules! with_original { + ($trayt:ident, $func:ident, $syn:path) => { + impl $trayt for WithOriginal { + fn $func(value: &$syn) -> Result { + 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 index e953c6311ff2..5995fa8ed8e4 100644 --- a/third_party/rust/darling_macro/.cargo-checksum.json +++ b/third_party/rust/darling_macro/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"cf9d579ee6af881a7aa52d43d637b4afa9cf589bfda3fa63159538d681855330","src/lib.rs":"d900da894985945215cb4494ebd4e8b5f697c19bf9e624a1bb03d22a0a5367a5"},"package":"eb69a38fdeaeaf3db712e1df170de67ee9dfc24fb88ca3e9d21e703ec25a4d8e"} \ No newline at end of file +{"files":{"Cargo.toml":"2603037629b2df2d1ce38ee7a163f745d4f08cd5a8c4c39efc828cd718445fbe","src/lib.rs":"8343bf4500faeaf72e0cafb9e2c378be176bfe41529ba8f0d5e315336de422bf"},"package":"9973050ba46be2a2935a7b316147f41a808ac604b8f0fef6eba77fd47a89daeb"} \ No newline at end of file diff --git a/third_party/rust/darling_macro/Cargo.toml b/third_party/rust/darling_macro/Cargo.toml index 1045edebaa48..16681a764f2f 100644 --- a/third_party/rust/darling_macro/Cargo.toml +++ b/third_party/rust/darling_macro/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "darling_macro" -version = "0.4.0" +version = "0.8.0" authors = ["Ted Driggs "] 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" @@ -21,10 +21,10 @@ repository = "https://github.com/TedDriggs/darling" [lib] proc-macro = true [dependencies.darling_core] -version = "=0.4.0" +version = "=0.8.0" [dependencies.quote] -version = "0.5" +version = "0.6" [dependencies.syn] -version = "0.13" +version = "0.15" diff --git a/third_party/rust/darling_macro/src/lib.rs b/third_party/rust/darling_macro/src/lib.rs index 9f68872cf72f..0553ef97377c 100644 --- a/third_party/rust/darling_macro/src/lib.rs +++ b/third_party/rust/darling_macro/src/lib.rs @@ -1,27 +1,35 @@ extern crate proc_macro; #[macro_use] extern crate quote; +#[macro_use] extern crate syn; extern crate darling_core; use proc_macro::TokenStream; -use darling_core::{options, codegen}; +use darling_core::{codegen, options}; -#[proc_macro_derive(FromMetaItem, attributes(darling))] -pub fn derive_from_meta_item(input: TokenStream) -> TokenStream { - let ast: syn::DeriveInput = syn::parse(input).unwrap(); - let container = options::FmiOptions::new(&ast).unwrap(); - let trait_impl = codegen::FmiImpl::from(&container); +#[proc_macro_derive(FromMeta, attributes(darling))] +pub fn derive_from_meta(input: TokenStream) -> TokenStream { + let ast = parse_macro_input!(input as syn::DeriveInput); + + let container = options::FromMetaOptions::new(&ast).unwrap(); + let trait_impl = codegen::FromMetaImpl::from(&container); let result = quote!(#trait_impl); result.into() } +#[proc_macro_derive(FromMetaItem, attributes(darling))] +pub fn derive_from_meta_item(_input: TokenStream) -> TokenStream { + panic!("darling::FromMetaItem has been replaced by darling::FromMeta"); +} + + #[proc_macro_derive(FromDeriveInput, attributes(darling))] pub fn derive_from_input(input: TokenStream) -> TokenStream { - let ast: syn::DeriveInput = syn::parse(input).unwrap(); + let ast = parse_macro_input!(input as syn::DeriveInput); let container = options::FdiOptions::new(&ast).unwrap(); let trait_impl = codegen::FromDeriveInputImpl::from(&container); @@ -32,7 +40,7 @@ pub fn derive_from_input(input: TokenStream) -> TokenStream { #[proc_macro_derive(FromField, attributes(darling))] pub fn derive_field(input: TokenStream) -> TokenStream { - let ast: syn::DeriveInput = syn::parse(input).unwrap(); + let ast = parse_macro_input!(input as syn::DeriveInput); let fdic = options::FromFieldOptions::new(&ast).unwrap(); let trait_impl = codegen::FromFieldImpl::from(&fdic); @@ -41,9 +49,20 @@ pub fn derive_field(input: TokenStream) -> TokenStream { result.into() } +#[proc_macro_derive(FromTypeParam, attributes(darling))] +pub fn derive_type_param(input: TokenStream) -> TokenStream { + let ast = parse_macro_input!(input as syn::DeriveInput); + + let fdic = options::FromTypeParamOptions::new(&ast).unwrap(); + let trait_impl = codegen::FromTypeParamImpl::from(&fdic); + let result = quote!(#trait_impl); + + result.into() +} + #[proc_macro_derive(FromVariant, attributes(darling))] pub fn derive_variant(input: TokenStream) -> TokenStream { - let ast: syn::DeriveInput = syn::parse(input).unwrap(); + let ast = parse_macro_input!(input as syn::DeriveInput); let fdic = options::FromVariantOptions::new(&ast).unwrap(); let trait_impl = codegen::FromVariantImpl::from(&fdic); diff --git a/third_party/rust/fnv/.cargo-checksum.json b/third_party/rust/fnv/.cargo-checksum.json index cd66f35daf94..b1fb191253dc 100644 --- a/third_party/rust/fnv/.cargo-checksum.json +++ b/third_party/rust/fnv/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"19864ecb948c0e7be14ead11068a2c689a4d31a684c85b6ad1bdf4a26d893516","README.md":"772c547b8e78764f07cc22f2294cb7c691cb20f30d459ed45a65c2434b1ca8a9","lib.rs":"2e2be31e9c90c9b2b0fe223f64f4b4bb24487e370e1cd2fbcce70d30f50fc452"},"package":"6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344"} \ No newline at end of file +{"files":{"Cargo.toml":"8a89e16dc6b373aa151fb2d1221c699b39b1dd5599aa616897fa85511b71104f","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"65fdb6c76cd61612070c066eec9ecdb30ee74fb27859d0d9af58b9f499fd0c3e","README.md":"9398b0785fdaf32fe61dca3d6f16e69cf53ab2911c9435053d1ec962cd92b8fa","lib.rs":"0303c8c75e9cf35f5379f67cfc003ba0b51e9643dc8f3bd346322595d7685d97"},"package":"2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"} \ No newline at end of file diff --git a/third_party/rust/fnv/Cargo.toml b/third_party/rust/fnv/Cargo.toml index c4011504898c..115779985819 100644 --- a/third_party/rust/fnv/Cargo.toml +++ b/third_party/rust/fnv/Cargo.toml @@ -1,12 +1,24 @@ +# 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 = "fnv" -version = "1.0.5" +version = "1.0.6" authors = ["Alex Crichton "] description = "Fowler–Noll–Vo hash function" -license = "Apache-2.0 / MIT" -readme = "README.md" -repository = "https://github.com/servo/rust-fnv" documentation = "https://doc.servo.org/fnv/" +readme = "README.md" +license = "Apache-2.0 / MIT" +repository = "https://github.com/servo/rust-fnv" [lib] name = "fnv" diff --git a/third_party/rust/fnv/LICENSE-APACHE b/third_party/rust/fnv/LICENSE-APACHE new file mode 100644 index 000000000000..16fe87b06e80 --- /dev/null +++ b/third_party/rust/fnv/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/third_party/rust/fnv/LICENSE-MIT b/third_party/rust/fnv/LICENSE-MIT new file mode 100644 index 000000000000..bc976a272ced --- /dev/null +++ b/third_party/rust/fnv/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2017 Contributors + +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/fnv/README.md b/third_party/rust/fnv/README.md index 96001e22deb3..6a4c4aeebbe8 100644 --- a/third_party/rust/fnv/README.md +++ b/third_party/rust/fnv/README.md @@ -77,5 +77,5 @@ set.insert(2); ``` [chongo]: http://www.isthe.com/chongo/tech/comp/fnv/index.html -[faq]: https://www.rust-lang.org/faq.html#why-are-rusts-hashmaps-slow +[faq]: https://www.rust-lang.org/en-US/faq.html#why-are-rusts-hashmaps-slow [graphs]: http://cglab.ca/~abeinges/blah/hash-rs/ diff --git a/third_party/rust/fnv/lib.rs b/third_party/rust/fnv/lib.rs index 1fc5d28c2000..eaf3d44a324a 100644 --- a/third_party/rust/fnv/lib.rs +++ b/third_party/rust/fnv/lib.rs @@ -61,7 +61,7 @@ //! ``` //! //! [chongo]: http://www.isthe.com/chongo/tech/comp/fnv/index.html -//! [faq]: https://www.rust-lang.org/faq.html#why-are-rusts-hashmaps-slow +//! [faq]: https://www.rust-lang.org/en-US/faq.html#why-are-rusts-hashmaps-slow //! [graphs]: http://cglab.ca/~abeinges/blah/hash-rs/ diff --git a/third_party/rust/synstructure-0.8.1/.cargo-checksum.json b/third_party/rust/synstructure-0.8.1/.cargo-checksum.json deleted file mode 100644 index 5cf0e3a36b09..000000000000 --- a/third_party/rust/synstructure-0.8.1/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.toml":"936c905633b5e43ea48d8a7f34cfe32741e2cabfc5b71541e1e1fa214c9afbe2","LICENSE":"219920e865eee70b7dcfc948a86b099e7f4fe2de01bcca2ca9a20c0a033f2b59","README.md":"16135f8089978a256141f3ffedfeb60df584bbd3f4dd928437cf839fc6920ff9","src/lib.rs":"7bcbf539b948ebb5a77cd636f496598662ad440416c265be1b6bda43ed3f19fb","src/macros.rs":"d9a58b66620003e7500cf53699410639f104c36146fe612d48128f293210a524"},"package":"98cad891cd238c98e1f0aec9f7c0f620aa696e4e5f7daba56ac67b5e86a6b049"} \ No newline at end of file diff --git a/third_party/rust/synstructure-0.8.1/Cargo.toml b/third_party/rust/synstructure-0.8.1/Cargo.toml deleted file mode 100644 index 76b0aab83557..000000000000 --- a/third_party/rust/synstructure-0.8.1/Cargo.toml +++ /dev/null @@ -1,40 +0,0 @@ -# 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 = "synstructure" -version = "0.8.1" -authors = ["Nika Layzell "] -include = ["src/**/*", "Cargo.toml", "README.md", "LICENSE"] -description = "Helper methods and macros for custom derives" -documentation = "https://docs.rs/synstructure" -readme = "README.md" -keywords = ["syn", "macros", "derive", "expand_substructure", "enum"] -license = "MIT" -repository = "https://github.com/mystor/synstructure" -[dependencies.proc-macro2] -version = "0.3" - -[dependencies.quote] -version = "0.5" - -[dependencies.syn] -version = "0.13" -features = ["visit", "extra-traits"] - -[dependencies.unicode-xid] -version = "0.1" -[dev-dependencies.synstructure_test_traits] -version = "0.1" - -[features] -simple-derive = [] diff --git a/third_party/rust/synstructure-0.8.1/LICENSE b/third_party/rust/synstructure-0.8.1/LICENSE deleted file mode 100644 index f78f1c15d129..000000000000 --- a/third_party/rust/synstructure-0.8.1/LICENSE +++ /dev/null @@ -1,7 +0,0 @@ -Copyright 2016 Nika Layzell - -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/synstructure-0.8.1/README.md b/third_party/rust/synstructure-0.8.1/README.md deleted file mode 100644 index 3ec46d21b596..000000000000 --- a/third_party/rust/synstructure-0.8.1/README.md +++ /dev/null @@ -1,157 +0,0 @@ -# synstructure - -[![Latest Version](https://img.shields.io/crates/v/synstructure.svg)](https://crates.io/crates/synstructure) -[![Documentation](https://docs.rs/synstructure/badge.svg)](https://docs.rs/synstructure) -[![Build Status](https://travis-ci.org/mystor/synstructure.svg?branch=master)](https://travis-ci.org/mystor/synstructure) -[![Rustc Version 1.15+](https://img.shields.io/badge/rustc-1.15+-lightgray.svg)](https://blog.rust-lang.org/2017/02/02/Rust-1.15.html) - -> NOTE: What follows is an exerpt from the module level documentation. For full -> details read the docs on [docs.rs](https://docs.rs/synstructure/) - -This crate provides helper types for matching against enum variants, and -extracting bindings to each of the fields in the deriving Struct or Enum in -a generic way. - -If you are writing a `#[derive]` which needs to perform some operation on -every field, then you have come to the right place! - -# Example: `WalkFields` -### Trait Implementation -```rust -pub trait WalkFields: std::any::Any { - fn walk_fields(&self, walk: &mut FnMut(&WalkFields)); -} -impl WalkFields for i32 { - fn walk_fields(&self, _walk: &mut FnMut(&WalkFields)) {} -} -``` - -### Custom Derive -```rust -#[macro_use] -extern crate synstructure; -#[macro_use] -extern crate quote; - -fn walkfields_derive(s: synstructure::Structure) -> quote::Tokens { - let body = s.each(|bi| quote!{ - walk(#bi) - }); - - s.bound_impl(quote!(example_traits::WalkFields), quote!{ - fn walk_fields(&self, walk: &mut FnMut(&example_traits::WalkFields)) { - match *self { #body } - } - }) -} -decl_derive!([WalkFields] => walkfields_derive); - -/* - * Test Case - */ -fn main() { - test_derive! { - walkfields_derive { - enum A { - B(i32, T), - C(i32), - } - } - expands to { - #[allow(non_upper_case_globals)] - const _DERIVE_example_traits_WalkFields_FOR_A: () = { - extern crate example_traits; - impl example_traits::WalkFields for A - where T: example_traits::WalkFields - { - fn walk_fields(&self, walk: &mut FnMut(&example_traits::WalkFields)) { - match *self { - A::B(ref __binding_0, ref __binding_1,) => { - { walk(__binding_0) } - { walk(__binding_1) } - } - A::C(ref __binding_0,) => { - { walk(__binding_0) } - } - } - } - } - }; - } - } -} -``` - -# Example: `Interest` -### Trait Implementation -```rust -pub trait Interest { - fn interesting(&self) -> bool; -} -impl Interest for i32 { - fn interesting(&self) -> bool { *self > 0 } -} -``` - -### Custom Derive -```rust -#[macro_use] -extern crate synstructure; -#[macro_use] -extern crate quote; - -fn interest_derive(mut s: synstructure::Structure) -> quote::Tokens { - let body = s.fold(false, |acc, bi| quote!{ - #acc || example_traits::Interest::interesting(#bi) - }); - - s.bound_impl(quote!(example_traits::Interest), quote!{ - fn interesting(&self) -> bool { - match *self { - #body - } - } - }) -} -decl_derive!([Interest] => interest_derive); - -/* - * Test Case - */ -fn main() { - test_derive!{ - interest_derive { - enum A { - B(i32, T), - C(i32), - } - } - expands to { - #[allow(non_upper_case_globals)] - const _DERIVE_example_traits_Interest_FOR_A: () = { - extern crate example_traits; - impl example_traits::Interest for A - where T: example_traits::Interest - { - fn interesting(&self) -> bool { - match *self { - A::B(ref __binding_0, ref __binding_1,) => { - false || - example_traits::Interest::interesting(__binding_0) || - example_traits::Interest::interesting(__binding_1) - } - A::C(ref __binding_0,) => { - false || - example_traits::Interest::interesting(__binding_0) - } - } - } - } - }; - } - } -} -``` - -For more example usage, consider investigating the `abomonation_derive` crate, -which makes use of this crate, and is fairly simple. diff --git a/third_party/rust/synstructure-0.8.1/src/lib.rs b/third_party/rust/synstructure-0.8.1/src/lib.rs deleted file mode 100644 index 09626c21f206..000000000000 --- a/third_party/rust/synstructure-0.8.1/src/lib.rs +++ /dev/null @@ -1,2226 +0,0 @@ -//! This crate provides helper types for matching against enum variants, and -//! extracting bindings to each of the fields in the deriving Struct or Enum in -//! a generic way. -//! -//! If you are writing a `#[derive]` which needs to perform some operation on -//! every field, then you have come to the right place! -//! -//! # Example: `WalkFields` -//! ### Trait Implementation -//! ``` -//! pub trait WalkFields: std::any::Any { -//! fn walk_fields(&self, walk: &mut FnMut(&WalkFields)); -//! } -//! impl WalkFields for i32 { -//! fn walk_fields(&self, _walk: &mut FnMut(&WalkFields)) {} -//! } -//! ``` -//! -//! ### Custom Derive -//! ``` -//! #[macro_use] -//! extern crate synstructure; -//! #[macro_use] -//! extern crate quote; -//! -//! fn walkfields_derive(s: synstructure::Structure) -> quote::Tokens { -//! let body = s.each(|bi| quote!{ -//! walk(#bi) -//! }); -//! -//! s.gen_impl(quote! { -//! extern crate synstructure_test_traits; -//! -//! gen impl synstructure_test_traits::WalkFields for @Self { -//! fn walk_fields(&self, walk: &mut FnMut(&synstructure_test_traits::WalkFields)) { -//! match *self { #body } -//! } -//! } -//! }) -//! } -//! # const _IGNORE: &'static str = stringify!( -//! decl_derive!([WalkFields] => walkfields_derive); -//! # ); -//! -//! /* -//! * Test Case -//! */ -//! fn main() { -//! test_derive! { -//! walkfields_derive { -//! enum A { -//! B(i32, T), -//! C(i32), -//! } -//! } -//! expands to { -//! #[allow(non_upper_case_globals)] -//! const _DERIVE_synstructure_test_traits_WalkFields_FOR_A: () = { -//! extern crate synstructure_test_traits; -//! impl synstructure_test_traits::WalkFields for A -//! where T: synstructure_test_traits::WalkFields -//! { -//! fn walk_fields(&self, walk: &mut FnMut(&synstructure_test_traits::WalkFields)) { -//! match *self { -//! A::B(ref __binding_0, ref __binding_1,) => { -//! { walk(__binding_0) } -//! { walk(__binding_1) } -//! } -//! A::C(ref __binding_0,) => { -//! { walk(__binding_0) } -//! } -//! } -//! } -//! } -//! }; -//! } -//! } -//! } -//! ``` -//! -//! # Example: `Interest` -//! ### Trait Implementation -//! ``` -//! pub trait Interest { -//! fn interesting(&self) -> bool; -//! } -//! impl Interest for i32 { -//! fn interesting(&self) -> bool { *self > 0 } -//! } -//! ``` -//! -//! ### Custom Derive -//! ``` -//! #[macro_use] -//! extern crate synstructure; -//! #[macro_use] -//! extern crate quote; -//! -//! fn interest_derive(mut s: synstructure::Structure) -> quote::Tokens { -//! let body = s.fold(false, |acc, bi| quote!{ -//! #acc || synstructure_test_traits::Interest::interesting(#bi) -//! }); -//! -//! s.gen_impl(quote! { -//! extern crate synstructure_test_traits; -//! gen impl synstructure_test_traits::Interest for @Self { -//! fn interesting(&self) -> bool { -//! match *self { -//! #body -//! } -//! } -//! } -//! }) -//! } -//! # const _IGNORE: &'static str = stringify!( -//! decl_derive!([Interest] => interest_derive); -//! # ); -//! -//! /* -//! * Test Case -//! */ -//! fn main() { -//! test_derive!{ -//! interest_derive { -//! enum A { -//! B(i32, T), -//! C(i32), -//! } -//! } -//! expands to { -//! #[allow(non_upper_case_globals)] -//! const _DERIVE_synstructure_test_traits_Interest_FOR_A: () = { -//! extern crate synstructure_test_traits; -//! impl synstructure_test_traits::Interest for A -//! where T: synstructure_test_traits::Interest -//! { -//! fn interesting(&self) -> bool { -//! match *self { -//! A::B(ref __binding_0, ref __binding_1,) => { -//! false || -//! synstructure_test_traits::Interest::interesting(__binding_0) || -//! synstructure_test_traits::Interest::interesting(__binding_1) -//! } -//! A::C(ref __binding_0,) => { -//! false || -//! synstructure_test_traits::Interest::interesting(__binding_0) -//! } -//! } -//! } -//! } -//! }; -//! } -//! } -//! } -//! ``` -//! -//! For more example usage, consider investigating the `abomonation_derive` crate, -//! which makes use of this crate, and is fairly simple. - -extern crate proc_macro; -extern crate proc_macro2; -#[macro_use] -extern crate quote; -#[macro_use] -extern crate syn; -extern crate unicode_xid; - -use std::collections::HashSet; - -use syn::{ - Generics, Ident, Attribute, Field, Fields, Expr, DeriveInput, - TraitBound, WhereClause, GenericParam, Data, WherePredicate, - TypeParamBound, Type, TypeMacro, FieldsUnnamed, FieldsNamed, - PredicateType, TypePath, token, punctuated, -}; -use syn::visit::{self, Visit}; - -// re-export the quote! macro so we can depend on it being around in our macro's -// implementations. -#[doc(hidden)] -pub use quote::*; - -use unicode_xid::UnicodeXID; - -use proc_macro2::Span; - -// NOTE: This module has documentation hidden, as it only exports macros (which -// always appear in the root of the crate) and helper methods / re-exports used -// in the implementation of those macros. -#[doc(hidden)] -pub mod macros; - -/// The type of binding to use when generating a pattern. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum BindStyle { - /// `x` - Move, - /// `mut x` - MoveMut, - /// `ref x` - Ref, - /// `ref mut x` - RefMut, -} - -impl ToTokens for BindStyle { - fn to_tokens(&self, tokens: &mut Tokens) { - match *self { - BindStyle::Move => {} - BindStyle::MoveMut => quote_spanned!(Span::call_site() => mut).to_tokens(tokens), - BindStyle::Ref => quote_spanned!(Span::call_site() => ref).to_tokens(tokens), - BindStyle::RefMut => quote_spanned!(Span::call_site() => ref mut).to_tokens(tokens), - } - } -} - -// Internal method for merging seen_generics arrays together. -fn generics_fuse(res: &mut Vec, new: &[bool]) { - for (i, &flag) in new.iter().enumerate() { - if i == res.len() { - res.push(false); - } - if flag { - res[i] = true; - } - } -} - -// Internal method for extracting the set of generics which have been matched. -fn fetch_generics<'a>(set: &[bool], generics: &'a Generics) -> Vec<&'a Ident> { - let mut tys = vec![]; - for (&seen, param) in set.iter().zip(generics.params.iter()) { - if seen { - match *param { - GenericParam::Type(ref tparam) => tys.push(&tparam.ident), - _ => {} - } - } - } - tys -} - -// Internal method for sanitizing an identifier for hygiene purposes. -fn sanitize_ident(s: &str) -> Ident { - let mut res = String::with_capacity(s.len()); - for mut c in s.chars() { - if ! UnicodeXID::is_xid_continue(c) { c = '_' } - // Deduplicate consecutive _ characters. - if res.ends_with('_') && c == '_' { continue } - res.push(c); - } - Ident::from(res) -} - -// Internal method to merge two Generics objects together intelligently. -fn merge_generics(into: &mut Generics, from: &Generics) { - // Try to add the param into `into`, and merge parmas with identical names. - 'outer: for p in &from.params { - for op in &into.params { - match (op, p) { - (&GenericParam::Type(ref otp), &GenericParam::Type(ref tp)) => { - // NOTE: This is only OK because syn ignores the span for equality purposes. - if otp.ident == tp.ident { - panic!("Attempted to merge conflicting generic params: {} and {}", quote!{#op}, quote!{#p}); - } - } - (&GenericParam::Lifetime(ref olp), &GenericParam::Lifetime(ref lp)) => { - // NOTE: This is only OK because syn ignores the span for equality purposes. - if olp.lifetime == lp.lifetime { - panic!("Attempted to merge conflicting generic params: {} and {}", quote!{#op}, quote!{#p}); - } - } - // We don't support merging Const parameters, because that wouldn't make much sense. - _ => (), - } - } - into.params.push(p.clone()); - } - - // Add any where clauses from the input generics object. - if let Some(ref from_clause) = from.where_clause { - into.make_where_clause() - .predicates - .extend(from_clause.predicates.iter().cloned()); - } -} - -/// Information about a specific binding. This contains both an `Ident` -/// reference to the given field, and the syn `&'a Field` descriptor for that -/// field. -/// -/// This type supports `quote::ToTokens`, so can be directly used within the -/// `quote!` macro. It expands to a reference to the matched field. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct BindingInfo<'a> { - /// The name which this BindingInfo will bind to. - pub binding: Ident, - - /// The type of binding which this BindingInfo will create. - pub style: BindStyle, - - field: &'a Field, - - // These are used to determine which type parameters are avaliable. - generics: &'a Generics, - seen_generics: Vec, -} - -impl<'a> ToTokens for BindingInfo<'a> { - fn to_tokens(&self, tokens: &mut Tokens) { - self.binding.to_tokens(tokens); - } -} - -impl<'a> BindingInfo<'a> { - /// Returns a reference to the underlying `syn` AST node which this - /// `BindingInfo` references - pub fn ast(&self) -> &'a Field { - self.field - } - - /// Generates the pattern fragment for this field binding. - /// - /// # Example - /// ``` - /// # #[macro_use] extern crate quote; - /// # extern crate synstructure; - /// # #[macro_use] extern crate syn; - /// # use synstructure::*; - /// # fn main() { - /// let di: syn::DeriveInput = parse_quote! { - /// enum A { - /// B{ a: i32, b: i32 }, - /// C(u32), - /// } - /// }; - /// let s = Structure::new(&di); - /// - /// assert_eq!( - /// s.variants()[0].bindings()[0].pat(), - /// quote! { - /// ref __binding_0 - /// } - /// ); - /// # } - /// ``` - pub fn pat(&self) -> Tokens { - let BindingInfo { - ref binding, - ref style, - .. - } = *self; - quote!(#style #binding) - } - - /// Returns a list of the type parameters which are referenced in this - /// field's type. - /// - /// # Caveat - /// - /// If the field contains any macros in type position, all parameters will - /// be considered bound. This is because we cannot determine which type - /// parameters are bound by type macros. - /// - /// # Example - /// ``` - /// # #[macro_use] extern crate quote; - /// # extern crate synstructure; - /// # #[macro_use] extern crate syn; - /// # use synstructure::*; - /// # fn main() { - /// let di: syn::DeriveInput = parse_quote! { - /// struct A { - /// a: Option, - /// b: U, - /// } - /// }; - /// let mut s = Structure::new(&di); - /// - /// assert_eq!( - /// s.variants()[0].bindings()[0].referenced_ty_params(), - /// &[&(syn::Ident::from("T"))] - /// ); - /// # } - /// ``` - pub fn referenced_ty_params(&self) -> Vec<&'a Ident> { - fetch_generics(&self.seen_generics, self.generics) - } -} - -/// This type is similar to `syn`'s `Variant` type, however each of the fields -/// are references rather than owned. When this is used as the AST for a real -/// variant, this struct simply borrows the fields of the `syn::Variant`, -/// however this type may also be used as the sole variant for a struct. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct VariantAst<'a> { - pub attrs: &'a [Attribute], - pub ident: &'a Ident, - pub fields: &'a Fields, - pub discriminant: &'a Option<(token::Eq, Expr)>, -} - -/// A wrapper around a `syn::DeriveInput`'s variant which provides utilities -/// for destructuring `Variant`s with `match` expressions. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct VariantInfo<'a> { - pub prefix: Option<&'a Ident>, - bindings: Vec>, - omitted_fields: bool, - ast: VariantAst<'a>, - generics: &'a Generics, -} - -/// Helper function used by the VariantInfo constructor. Walks all of the types -/// in `field` and returns a list of the type parameters from `ty_params` which -/// are referenced in the field. -fn get_ty_params<'a>(field: &Field, generics: &Generics) -> Vec { - // Helper type. Discovers all identifiers inside of the visited type, - // and calls a callback with them. - struct BoundTypeLocator<'a> { - result: Vec, - generics: &'a Generics, - } - - impl<'a> Visit<'a> for BoundTypeLocator<'a> { - // XXX: This also (intentionally) captures paths like T::SomeType. Is - // this desirable? - fn visit_ident(&mut self, id: &Ident) { - for (idx, i) in self.generics.params.iter().enumerate() { - if let GenericParam::Type(ref tparam) = *i { - if tparam.ident == id { - self.result[idx] = true; - } - } - } - } - - fn visit_type_macro(&mut self, x: &'a TypeMacro) { - // If we see a type_mac declaration, then we can't know what type parameters - // it might be binding, so we presume it binds all of them. - for r in &mut self.result { - *r = true; - } - visit::visit_type_macro(self, x) - } - } - - let mut btl = BoundTypeLocator { - result: vec![false; generics.params.len()], - generics: generics, - }; - - btl.visit_type(&field.ty); - - btl.result -} - -impl<'a> VariantInfo<'a> { - fn new(ast: VariantAst<'a>, prefix: Option<&'a Ident>, generics: &'a Generics) -> Self { - let bindings = match *ast.fields { - Fields::Unit => vec![], - Fields::Unnamed(FieldsUnnamed { unnamed: ref fields, .. }) | - Fields::Named(FieldsNamed { named: ref fields, .. }) => { - fields.into_iter() - .enumerate() - .map(|(i, field)| { - BindingInfo { - // XXX: This has to be call_site to avoid privacy - // when deriving on private fields. - binding: Ident::new( - &format!("__binding_{}", i), - Span::call_site(), - ), - style: BindStyle::Ref, - field: field, - generics: generics, - seen_generics: get_ty_params(field, generics), - } - }) - .collect::>() - } - }; - - VariantInfo { - prefix: prefix, - bindings: bindings, - omitted_fields: false, - ast: ast, - generics: generics, - } - } - - /// Returns a slice of the bindings in this Variant. - pub fn bindings(&self) -> &[BindingInfo<'a>] { - &self.bindings - } - - /// Returns a mut slice of the bindings in this Variant. - pub fn bindings_mut(&mut self) -> &mut [BindingInfo<'a>] { - &mut self.bindings - } - - /// Returns a `VariantAst` object which contains references to the - /// underlying `syn` AST node which this `Variant` was created from. - pub fn ast(&self) -> VariantAst<'a> { - self.ast - } - - /// True if any bindings were omitted due to a `filter` call. - pub fn omitted_bindings(&self) -> bool { - self.omitted_fields - } - - /// Generates the match-arm pattern which could be used to match against this Variant. - /// - /// # Example - /// ``` - /// # #[macro_use] extern crate quote; - /// # extern crate synstructure; - /// # #[macro_use] extern crate syn; - /// # use synstructure::*; - /// # fn main() { - /// let di: syn::DeriveInput = parse_quote! { - /// enum A { - /// B(i32, i32), - /// C(u32), - /// } - /// }; - /// let s = Structure::new(&di); - /// - /// assert_eq!( - /// s.variants()[0].pat(), - /// quote!{ - /// A::B(ref __binding_0, ref __binding_1,) - /// } - /// ); - /// # } - /// ``` - pub fn pat(&self) -> Tokens { - let mut t = Tokens::new(); - if let Some(prefix) = self.prefix { - prefix.to_tokens(&mut t); - quote!(::).to_tokens(&mut t); - } - self.ast.ident.to_tokens(&mut t); - match *self.ast.fields { - Fields::Unit => { - assert!(self.bindings.len() == 0); - } - Fields::Unnamed(..) => { - token::Paren(Span::call_site()).surround(&mut t, |t| { - for binding in &self.bindings { - binding.pat().to_tokens(t); - quote!(,).to_tokens(t); - } - if self.omitted_fields { - quote!(..).to_tokens(t); - } - }) - } - Fields::Named(..) => { - token::Brace(Span::call_site()).surround(&mut t, |t| { - for binding in &self.bindings { - binding.field.ident.to_tokens(t); - quote!(:).to_tokens(t); - binding.pat().to_tokens(t); - quote!(,).to_tokens(t); - } - if self.omitted_fields { - quote!(..).to_tokens(t); - } - }) - } - } - t - } - - /// Generates the token stream required to construct the current variant. - /// - /// The init array initializes each of the fields in the order they are - /// written in `variant.ast().fields`. - /// - /// # Example - /// ``` - /// # #[macro_use] extern crate quote; - /// # extern crate synstructure; - /// # #[macro_use] extern crate syn; - /// # use synstructure::*; - /// # fn main() { - /// let di: syn::DeriveInput = parse_quote! { - /// enum A { - /// B(usize, usize), - /// C{ v: usize }, - /// } - /// }; - /// let s = Structure::new(&di); - /// - /// assert_eq!( - /// s.variants()[0].construct(|_, i| quote!(#i)), - /// - /// quote!{ - /// A::B(0usize, 1usize,) - /// } - /// ); - /// - /// assert_eq!( - /// s.variants()[1].construct(|_, i| quote!(#i)), - /// - /// quote!{ - /// A::C{ v: 0usize, } - /// } - /// ); - /// # } - /// ``` - pub fn construct(&self, mut func: F) -> Tokens - where - F: FnMut(&Field, usize) -> T, - T: ToTokens, - { - let mut t = Tokens::new(); - if let Some(prefix) = self.prefix { - quote!(#prefix ::).to_tokens(&mut t); - } - self.ast.ident.to_tokens(&mut t); - - match *self.ast.fields { - Fields::Unit => (), - Fields::Unnamed(FieldsUnnamed { ref unnamed, .. }) => { - token::Paren::default().surround(&mut t, |t| { - for (i, field) in unnamed.into_iter().enumerate() { - func(field, i).to_tokens(t); - quote!(,).to_tokens(t); - } - }) - } - Fields::Named(FieldsNamed { ref named, .. }) => { - token::Brace::default().surround(&mut t, |t| { - for (i, field) in named.into_iter().enumerate() { - field.ident.to_tokens(t); - quote!(:).to_tokens(t); - func(field, i).to_tokens(t); - quote!(,).to_tokens(t); - } - }) - } - } - t - } - - /// Runs the passed-in function once for each bound field, passing in a `BindingInfo`. - /// and generating a `match` arm which evaluates the returned tokens. - /// - /// This method will ignore fields which are ignored through the `filter` - /// method. - /// - /// # Example - /// ``` - /// # #[macro_use] extern crate quote; - /// # extern crate synstructure; - /// # #[macro_use] extern crate syn; - /// # use synstructure::*; - /// # fn main() { - /// let di: syn::DeriveInput = parse_quote! { - /// enum A { - /// B(i32, i32), - /// C(u32), - /// } - /// }; - /// let s = Structure::new(&di); - /// - /// assert_eq!( - /// s.variants()[0].each(|bi| quote!(println!("{:?}", #bi))), - /// - /// quote!{ - /// A::B(ref __binding_0, ref __binding_1,) => { - /// { println!("{:?}", __binding_0) } - /// { println!("{:?}", __binding_1) } - /// } - /// } - /// ); - /// # } - /// ``` - pub fn each(&self, mut f: F) -> Tokens - where - F: FnMut(&BindingInfo) -> R, - R: ToTokens, - { - let pat = self.pat(); - let mut body = Tokens::new(); - for binding in &self.bindings { - token::Brace::default().surround(&mut body, |body| { - f(binding).to_tokens(body); - }); - } - quote!(#pat => { #body }) - } - - /// Runs the passed-in function once for each bound field, passing in the - /// result of the previous call, and a `BindingInfo`. generating a `match` - /// arm which evaluates to the resulting tokens. - /// - /// This method will ignore fields which are ignored through the `filter` - /// method. - /// - /// # Example - /// ``` - /// # #[macro_use] extern crate quote; - /// # extern crate synstructure; - /// # #[macro_use] extern crate syn; - /// # use synstructure::*; - /// # fn main() { - /// let di: syn::DeriveInput = parse_quote! { - /// enum A { - /// B(i32, i32), - /// C(u32), - /// } - /// }; - /// let s = Structure::new(&di); - /// - /// assert_eq!( - /// s.variants()[0].fold(quote!(0), |acc, bi| quote!(#acc + #bi)), - /// - /// quote!{ - /// A::B(ref __binding_0, ref __binding_1,) => { - /// 0 + __binding_0 + __binding_1 - /// } - /// } - /// ); - /// # } - /// ``` - pub fn fold(&self, init: I, mut f: F) -> Tokens - where - F: FnMut(Tokens, &BindingInfo) -> R, - I: ToTokens, - R: ToTokens, - { - let pat = self.pat(); - let body = self.bindings.iter().fold(quote!(#init), |i, bi| { - let r = f(i, bi); - quote!(#r) - }); - quote!(#pat => { #body }) - } - - /// Filter the bindings created by this `Variant` object. This has 2 effects: - /// - /// * The bindings will no longer appear in match arms generated by methods - /// on this `Variant` or its subobjects. - /// - /// * Impl blocks created with the `bound_impl` or `unsafe_bound_impl` - /// method only consider type parameters referenced in the types of - /// non-filtered fields. - /// - /// # Example - /// ``` - /// # #[macro_use] extern crate quote; - /// # extern crate synstructure; - /// # #[macro_use] extern crate syn; - /// # use synstructure::*; - /// # fn main() { - /// let di: syn::DeriveInput = parse_quote! { - /// enum A { - /// B{ a: i32, b: i32 }, - /// C{ a: u32 }, - /// } - /// }; - /// let mut s = Structure::new(&di); - /// - /// s.variants_mut()[0].filter(|bi| { - /// bi.ast().ident == Some("b".into()) - /// }); - /// - /// assert_eq!( - /// s.each(|bi| quote!(println!("{:?}", #bi))), - /// - /// quote!{ - /// A::B{ b: ref __binding_1, .. } => { - /// { println!("{:?}", __binding_1) } - /// } - /// A::C{ a: ref __binding_0, } => { - /// { println!("{:?}", __binding_0) } - /// } - /// } - /// ); - /// # } - /// ``` - pub fn filter(&mut self, f: F) -> &mut Self - where - F: FnMut(&BindingInfo) -> bool, - { - let before_len = self.bindings.len(); - self.bindings.retain(f); - if self.bindings.len() != before_len { - self.omitted_fields = true; - } - self - } - - /// Remove the binding at the given index. - /// - /// # Panics - /// - /// Panics if the index is out of range. - pub fn remove_binding(&mut self, idx: usize) -> &mut Self { - self.bindings.remove(idx); - self.omitted_fields = true; - self - } - - /// Updates the `BindStyle` for each of the passed-in fields by calling the - /// passed-in function for each `BindingInfo`. - /// - /// # Example - /// ``` - /// # #[macro_use] extern crate quote; - /// # extern crate synstructure; - /// # #[macro_use] extern crate syn; - /// # use synstructure::*; - /// # fn main() { - /// let di: syn::DeriveInput = parse_quote! { - /// enum A { - /// B(i32, i32), - /// C(u32), - /// } - /// }; - /// let mut s = Structure::new(&di); - /// - /// s.variants_mut()[0].bind_with(|bi| BindStyle::RefMut); - /// - /// assert_eq!( - /// s.each(|bi| quote!(println!("{:?}", #bi))), - /// - /// quote!{ - /// A::B(ref mut __binding_0, ref mut __binding_1,) => { - /// { println!("{:?}", __binding_0) } - /// { println!("{:?}", __binding_1) } - /// } - /// A::C(ref __binding_0,) => { - /// { println!("{:?}", __binding_0) } - /// } - /// } - /// ); - /// # } - /// ``` - pub fn bind_with(&mut self, mut f: F) -> &mut Self - where - F: FnMut(&BindingInfo) -> BindStyle, - { - for binding in &mut self.bindings { - binding.style = f(&binding); - } - self - } - - /// Updates the binding name for each fo the passed-in fields by calling the - /// passed-in function for each `BindingInfo`. - /// - /// The function will be called with the `BindingInfo` and its index in the - /// enclosing variant. - /// - /// The default name is `__binding_{}` where `{}` is replaced with an - /// increasing number. - /// - /// # Example - /// ``` - /// # #[macro_use] extern crate quote; - /// # extern crate synstructure; - /// # #[macro_use] extern crate syn; - /// # use synstructure::*; - /// # fn main() { - /// let di: syn::DeriveInput = parse_quote! { - /// enum A { - /// B{ a: i32, b: i32 }, - /// C{ a: u32 }, - /// } - /// }; - /// let mut s = Structure::new(&di); - /// - /// s.variants_mut()[0].binding_name(|bi, i| bi.ident.clone().unwrap()); - /// - /// assert_eq!( - /// s.each(|bi| quote!(println!("{:?}", #bi))), - /// - /// quote!{ - /// A::B{ a: ref a, b: ref b, } => { - /// { println!("{:?}", a) } - /// { println!("{:?}", b) } - /// } - /// A::C{ a: ref __binding_0, } => { - /// { println!("{:?}", __binding_0) } - /// } - /// } - /// ); - /// # } - /// ``` - pub fn binding_name(&mut self, mut f: F) -> &mut Self - where - F: FnMut(&Field, usize) -> Ident, - { - for (it, binding) in self.bindings.iter_mut().enumerate() { - binding.binding = f(binding.field, it); - } - self - } - - /// Returns a list of the type parameters which are referenced in this - /// field's type. - /// - /// # Caveat - /// - /// If the field contains any macros in type position, all parameters will - /// be considered bound. This is because we cannot determine which type - /// parameters are bound by type macros. - /// - /// # Example - /// ``` - /// # #[macro_use] extern crate quote; - /// # extern crate synstructure; - /// # #[macro_use] extern crate syn; - /// # use synstructure::*; - /// # fn main() { - /// let di: syn::DeriveInput = parse_quote! { - /// struct A { - /// a: Option, - /// b: U, - /// } - /// }; - /// let mut s = Structure::new(&di); - /// - /// assert_eq!( - /// s.variants()[0].bindings()[0].referenced_ty_params(), - /// &[&(syn::Ident::from("T"))] - /// ); - /// # } - /// ``` - pub fn referenced_ty_params(&self) -> Vec<&'a Ident> { - let mut flags = Vec::new(); - for binding in &self.bindings { - generics_fuse(&mut flags, &binding.seen_generics); - } - fetch_generics(&flags, self.generics) - } -} - -/// A wrapper around a `syn::DeriveInput` which provides utilities for creating -/// custom derive trait implementations. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct Structure<'a> { - variants: Vec>, - omitted_variants: bool, - ast: &'a DeriveInput, - extra_impl: Vec, -} - -impl<'a> Structure<'a> { - /// Create a new `Structure` with the variants and fields from the passed-in - /// `DeriveInput`. - pub fn new(ast: &'a DeriveInput) -> Self { - let variants = match ast.data { - Data::Enum(ref data) => { - (&data.variants).into_iter() - .map(|v| { - VariantInfo::new( - VariantAst { - attrs: &v.attrs, - ident: &v.ident, - fields: &v.fields, - discriminant: &v.discriminant - }, - Some(&ast.ident), - &ast.generics, - ) - }) - .collect::>() - } - Data::Struct(ref data) => { - // SAFETY NOTE: Normally putting an `Expr` in static storage - // wouldn't be safe, because it could contain `Term` objects - // which use thread-local interning. However, this static always - // contains the value `None`. Thus, it will never contain any - // unsafe values. - struct UnsafeMakeSync(Option<(token::Eq, Expr)>); - unsafe impl Sync for UnsafeMakeSync {} - static NONE_DISCRIMINANT: UnsafeMakeSync = UnsafeMakeSync(None); - - vec![ - VariantInfo::new( - VariantAst { - attrs: &ast.attrs, - ident: &ast.ident, - fields: &data.fields, - discriminant: &NONE_DISCRIMINANT.0, - }, - None, - &ast.generics, - ), - ] - } - Data::Union(_) => { - panic!("synstructure does not handle untagged unions \ - (https://github.com/mystor/synstructure/issues/6)"); - } - }; - - Structure { - variants: variants, - omitted_variants: false, - ast: ast, - extra_impl: vec![], - } - } - - /// Returns a slice of the variants in this Structure. - pub fn variants(&self) -> &[VariantInfo<'a>] { - &self.variants - } - - /// Returns a mut slice of the variants in this Structure. - pub fn variants_mut(&mut self) -> &mut [VariantInfo<'a>] { - &mut self.variants - } - - /// Returns a reference to the underlying `syn` AST node which this - /// `Structure` was created from. - pub fn ast(&self) -> &'a DeriveInput { - self.ast - } - - /// True if any variants were omitted due to a `filter_variants` call. - pub fn omitted_variants(&self) -> bool { - self.omitted_variants - } - - /// Runs the passed-in function once for each bound field, passing in a `BindingInfo`. - /// and generating `match` arms which evaluate the returned tokens. - /// - /// This method will ignore variants or fields which are ignored through the - /// `filter` and `filter_variant` methods. - /// - /// # Example - /// ``` - /// # #[macro_use] extern crate quote; - /// # extern crate synstructure; - /// # #[macro_use] extern crate syn; - /// # use synstructure::*; - /// # fn main() { - /// let di: syn::DeriveInput = parse_quote! { - /// enum A { - /// B(i32, i32), - /// C(u32), - /// } - /// }; - /// let s = Structure::new(&di); - /// - /// assert_eq!( - /// s.each(|bi| quote!(println!("{:?}", #bi))), - /// - /// quote!{ - /// A::B(ref __binding_0, ref __binding_1,) => { - /// { println!("{:?}", __binding_0) } - /// { println!("{:?}", __binding_1) } - /// } - /// A::C(ref __binding_0,) => { - /// { println!("{:?}", __binding_0) } - /// } - /// } - /// ); - /// # } - /// ``` - pub fn each(&self, mut f: F) -> Tokens - where - F: FnMut(&BindingInfo) -> R, - R: ToTokens, - { - let mut t = Tokens::new(); - for variant in &self.variants { - variant.each(&mut f).to_tokens(&mut t); - } - if self.omitted_variants { - quote!(_ => {}).to_tokens(&mut t); - } - t - } - - /// Runs the passed-in function once for each bound field, passing in the - /// result of the previous call, and a `BindingInfo`. generating `match` - /// arms which evaluate to the resulting tokens. - /// - /// This method will ignore variants or fields which are ignored through the - /// `filter` and `filter_variant` methods. - /// - /// If a variant has been ignored, it will return the `init` value. - /// - /// # Example - /// ``` - /// # #[macro_use] extern crate quote; - /// # extern crate synstructure; - /// # #[macro_use] extern crate syn; - /// # use synstructure::*; - /// # fn main() { - /// let di: syn::DeriveInput = parse_quote! { - /// enum A { - /// B(i32, i32), - /// C(u32), - /// } - /// }; - /// let s = Structure::new(&di); - /// - /// assert_eq!( - /// s.fold(quote!(0), |acc, bi| quote!(#acc + #bi)), - /// - /// quote!{ - /// A::B(ref __binding_0, ref __binding_1,) => { - /// 0 + __binding_0 + __binding_1 - /// } - /// A::C(ref __binding_0,) => { - /// 0 + __binding_0 - /// } - /// } - /// ); - /// # } - /// ``` - pub fn fold(&self, init: I, mut f: F) -> Tokens - where - F: FnMut(Tokens, &BindingInfo) -> R, - I: ToTokens, - R: ToTokens, - { - let mut t = Tokens::new(); - for variant in &self.variants { - variant.fold(&init, &mut f).to_tokens(&mut t); - } - if self.omitted_variants { - quote!(_ => { #init }).to_tokens(&mut t); - } - t - } - - /// Runs the passed-in function once for each variant, passing in a - /// `VariantInfo`. and generating `match` arms which evaluate the returned - /// tokens. - /// - /// This method will ignore variants and not bind fields which are ignored - /// through the `filter` and `filter_variant` methods. - /// - /// # Example - /// ``` - /// # #[macro_use] extern crate quote; - /// # extern crate synstructure; - /// # #[macro_use] extern crate syn; - /// # use synstructure::*; - /// # fn main() { - /// let di: syn::DeriveInput = parse_quote! { - /// enum A { - /// B(i32, i32), - /// C(u32), - /// } - /// }; - /// let s = Structure::new(&di); - /// - /// assert_eq!( - /// s.each_variant(|v| { - /// let name = &v.ast().ident; - /// quote!(println!(stringify!(#name))) - /// }), - /// - /// quote!{ - /// A::B(ref __binding_0, ref __binding_1,) => { - /// println!(stringify!(B)) - /// } - /// A::C(ref __binding_0,) => { - /// println!(stringify!(C)) - /// } - /// } - /// ); - /// # } - /// ``` - pub fn each_variant(&self, mut f: F) -> Tokens - where - F: FnMut(&VariantInfo) -> R, - R: ToTokens, - { - let mut t = Tokens::new(); - for variant in &self.variants { - let pat = variant.pat(); - let body = f(variant); - quote!(#pat => { #body }).to_tokens(&mut t); - } - if self.omitted_variants { - quote!(_ => {}).to_tokens(&mut t); - } - t - } - - /// Filter the bindings created by this `Structure` object. This has 2 effects: - /// - /// * The bindings will no longer appear in match arms generated by methods - /// on this `Structure` or its subobjects. - /// - /// * Impl blocks created with the `bound_impl` or `unsafe_bound_impl` - /// method only consider type parameters referenced in the types of - /// non-filtered fields. - /// - /// # Example - /// ``` - /// # #[macro_use] extern crate quote; - /// # extern crate synstructure; - /// # #[macro_use] extern crate syn; - /// # use synstructure::*; - /// # fn main() { - /// let di: syn::DeriveInput = parse_quote! { - /// enum A { - /// B{ a: i32, b: i32 }, - /// C{ a: u32 }, - /// } - /// }; - /// let mut s = Structure::new(&di); - /// - /// s.filter(|bi| { bi.ast().ident == Some("a".into()) }); - /// - /// assert_eq!( - /// s.each(|bi| quote!(println!("{:?}", #bi))), - /// - /// quote!{ - /// A::B{ a: ref __binding_0, .. } => { - /// { println!("{:?}", __binding_0) } - /// } - /// A::C{ a: ref __binding_0, } => { - /// { println!("{:?}", __binding_0) } - /// } - /// } - /// ); - /// # } - /// ``` - pub fn filter(&mut self, mut f: F) -> &mut Self - where - F: FnMut(&BindingInfo) -> bool, - { - for variant in &mut self.variants { - variant.filter(&mut f); - } - self - } - - /// Filter the variants matched by this `Structure` object. This has 2 effects: - /// - /// * Match arms destructuring these variants will no longer be generated by - /// methods on this `Structure` - /// - /// * Impl blocks created with the `bound_impl` or `unsafe_bound_impl` - /// method only consider type parameters referenced in the types of - /// fields in non-fitered variants. - /// - /// # Example - /// ``` - /// # #[macro_use] extern crate quote; - /// # extern crate synstructure; - /// # #[macro_use] extern crate syn; - /// # use synstructure::*; - /// # fn main() { - /// let di: syn::DeriveInput = parse_quote! { - /// enum A { - /// B(i32, i32), - /// C(u32), - /// } - /// }; - /// - /// let mut s = Structure::new(&di); - /// - /// s.filter_variants(|v| v.ast().ident != "B"); - /// - /// assert_eq!( - /// s.each(|bi| quote!(println!("{:?}", #bi))), - /// - /// quote!{ - /// A::C(ref __binding_0,) => { - /// { println!("{:?}", __binding_0) } - /// } - /// _ => {} - /// } - /// ); - /// # } - /// ``` - pub fn filter_variants(&mut self, f: F) -> &mut Self - where - F: FnMut(&VariantInfo) -> bool, - { - let before_len = self.variants.len(); - self.variants.retain(f); - if self.variants.len() != before_len { - self.omitted_variants = true; - } - self - } - - /// Remove the variant at the given index. - /// - /// # Panics - /// - /// Panics if the index is out of range. - pub fn remove_variant(&mut self, idx: usize) -> &mut Self { - self.variants.remove(idx); - self.omitted_variants = true; - self - } - - /// Updates the `BindStyle` for each of the passed-in fields by calling the - /// passed-in function for each `BindingInfo`. - /// - /// # Example - /// ``` - /// # #[macro_use] extern crate quote; - /// # extern crate synstructure; - /// # #[macro_use] extern crate syn; - /// # use synstructure::*; - /// # fn main() { - /// let di: syn::DeriveInput = parse_quote! { - /// enum A { - /// B(i32, i32), - /// C(u32), - /// } - /// }; - /// let mut s = Structure::new(&di); - /// - /// s.bind_with(|bi| BindStyle::RefMut); - /// - /// assert_eq!( - /// s.each(|bi| quote!(println!("{:?}", #bi))), - /// - /// quote!{ - /// A::B(ref mut __binding_0, ref mut __binding_1,) => { - /// { println!("{:?}", __binding_0) } - /// { println!("{:?}", __binding_1) } - /// } - /// A::C(ref mut __binding_0,) => { - /// { println!("{:?}", __binding_0) } - /// } - /// } - /// ); - /// # } - /// ``` - pub fn bind_with(&mut self, mut f: F) -> &mut Self - where - F: FnMut(&BindingInfo) -> BindStyle, - { - for variant in &mut self.variants { - variant.bind_with(&mut f); - } - self - } - - /// Updates the binding name for each fo the passed-in fields by calling the - /// passed-in function for each `BindingInfo`. - /// - /// The function will be called with the `BindingInfo` and its index in the - /// enclosing variant. - /// - /// The default name is `__binding_{}` where `{}` is replaced with an - /// increasing number. - /// - /// # Example - /// ``` - /// # #[macro_use] extern crate quote; - /// # extern crate synstructure; - /// # #[macro_use] extern crate syn; - /// # use synstructure::*; - /// # fn main() { - /// let di: syn::DeriveInput = parse_quote! { - /// enum A { - /// B{ a: i32, b: i32 }, - /// C{ a: u32 }, - /// } - /// }; - /// let mut s = Structure::new(&di); - /// - /// s.binding_name(|bi, i| bi.ident.clone().unwrap()); - /// - /// assert_eq!( - /// s.each(|bi| quote!(println!("{:?}", #bi))), - /// - /// quote!{ - /// A::B{ a: ref a, b: ref b, } => { - /// { println!("{:?}", a) } - /// { println!("{:?}", b) } - /// } - /// A::C{ a: ref a, } => { - /// { println!("{:?}", a) } - /// } - /// } - /// ); - /// # } - /// ``` - pub fn binding_name(&mut self, mut f: F) -> &mut Self - where - F: FnMut(&Field, usize) -> Ident, - { - for variant in &mut self.variants { - variant.binding_name(&mut f); - } - self - } - - /// Returns a list of the type parameters which are refrenced in the types - /// of non-filtered fields / variants. - /// - /// # Caveat - /// - /// If the struct contains any macros in type position, all parameters will - /// be considered bound. This is because we cannot determine which type - /// parameters are bound by type macros. - /// - /// # Example - /// ``` - /// # #[macro_use] extern crate quote; - /// # extern crate synstructure; - /// # #[macro_use] extern crate syn; - /// # use synstructure::*; - /// # fn main() { - /// let di: syn::DeriveInput = parse_quote! { - /// enum A { - /// B(T, i32), - /// C(Option), - /// } - /// }; - /// let mut s = Structure::new(&di); - /// - /// s.filter_variants(|v| v.ast().ident != "C"); - /// - /// assert_eq!( - /// s.referenced_ty_params(), - /// &[&(syn::Ident::from("T"))] - /// ); - /// # } - /// ``` - pub fn referenced_ty_params(&self) -> Vec<&'a Ident> { - let mut flags = Vec::new(); - for variant in &self.variants { - for binding in &variant.bindings { - generics_fuse(&mut flags, &binding.seen_generics); - } - } - fetch_generics(&flags, &self.ast.generics) - } - - /// Adds an `impl<>` generic parameter. - /// This can be used when the trait to be derived needs some extra generic parameters. - /// - /// # Example - /// ``` - /// # #![recursion_limit="128"] - /// # #[macro_use] extern crate quote; - /// # extern crate synstructure; - /// # #[macro_use] extern crate syn; - /// # use synstructure::*; - /// # fn main() { - /// let di: syn::DeriveInput = parse_quote! { - /// enum A { - /// B(T), - /// C(Option), - /// } - /// }; - /// let mut s = Structure::new(&di); - /// let generic: syn::GenericParam = parse_quote!(X: krate::AnotherTrait); - /// - /// assert_eq!( - /// s.add_impl_generic(generic) - /// .bound_impl(quote!(krate::Trait), - /// quote!{ - /// fn a() {} - /// } - /// ), - /// quote!{ - /// #[allow(non_upper_case_globals)] - /// const _DERIVE_krate_Trait_X_FOR_A: () = { - /// extern crate krate; - /// impl krate::Trait for A - /// where T : krate :: Trait < X >, - /// Option: krate::Trait, - /// U: krate::Trait - /// { - /// fn a() {} - /// } - /// }; - /// } - /// ); - /// # } - /// ``` - pub fn add_impl_generic(&mut self, param: GenericParam) -> &mut Self { - self.extra_impl.push(param); - self - } - - /// Add trait bounds for a trait with the given path for each type parmaeter - /// referenced in the types of non-filtered fields. - /// - /// # Caveat - /// - /// If the method contains any macros in type position, all parameters will - /// be considered bound. This is because we cannot determine which type - /// parameters are bound by type macros. - pub fn add_trait_bounds(&self, bound: &TraitBound, where_clause: &mut Option) { - let mut seen = HashSet::new(); - let mut pred = |ty: Type| if !seen.contains(&ty) { - seen.insert(ty.clone()); - - // Ensure we have a where clause, because we need to use it. We - // can't use `get_or_insert_with`, because it isn't supported on all - // rustc versions we support (this is a Rust 1.20+ feature). - if where_clause.is_none() { - *where_clause = Some(WhereClause { - where_token: Default::default(), - predicates: punctuated::Punctuated::new(), - }); - } - let clause = where_clause.as_mut().unwrap(); - - // Add a predicate. - clause.predicates.push(WherePredicate::Type(PredicateType { - lifetimes: None, - bounded_ty: ty, - colon_token: Default::default(), - bounds: Some(punctuated::Pair::End(TypeParamBound::Trait(bound.clone()))) - .into_iter() - .collect(), - })); - }; - - for variant in &self.variants { - for binding in &variant.bindings { - for &seen in &binding.seen_generics { - if seen { - pred(binding.ast().ty.clone()); - break; - } - } - - for param in binding.referenced_ty_params() { - pred(Type::Path(TypePath { - qself: None, - path: (*param).clone().into(), - })); - } - } - } - } - - /// > NOTE: This methods' features are superceded by `Structure::gen_impl`. - /// - /// Creates an `impl` block with the required generic type fields filled in - /// to implement the trait `path`. - /// - /// This method also adds where clauses to the impl requiring that all - /// referenced type parmaeters implement the trait `path`. - /// - /// # Hygiene and Paths - /// - /// This method wraps the impl block inside of a `const` (see the example - /// below). In this scope, the first segment of the passed-in path is - /// `extern crate`-ed in. If you don't want to generate that `extern crate` - /// item, use a global path. - /// - /// This means that if you are implementing `my_crate::Trait`, you simply - /// write `s.bound_impl(quote!(my_crate::Trait), quote!(...))`, and for the - /// entirety of the definition, you can refer to your crate as `my_crate`. - /// - /// # Caveat - /// - /// If the method contains any macros in type position, all parameters will - /// be considered bound. This is because we cannot determine which type - /// parameters are bound by type macros. - /// - /// # Panics - /// - /// Panics if the path string parameter is not a valid `TraitBound`. - /// - /// # Example - /// ``` - /// # #[macro_use] extern crate quote; - /// # extern crate synstructure; - /// # #[macro_use] extern crate syn; - /// # use synstructure::*; - /// # fn main() { - /// let di: syn::DeriveInput = parse_quote! { - /// enum A { - /// B(T), - /// C(Option), - /// } - /// }; - /// let mut s = Structure::new(&di); - /// - /// s.filter_variants(|v| v.ast().ident != "B"); - /// - /// assert_eq!( - /// s.bound_impl(quote!(krate::Trait), quote!{ - /// fn a() {} - /// }), - /// quote!{ - /// #[allow(non_upper_case_globals)] - /// const _DERIVE_krate_Trait_FOR_A: () = { - /// extern crate krate; - /// impl krate::Trait for A - /// where Option: krate::Trait, - /// U: krate::Trait - /// { - /// fn a() {} - /// } - /// }; - /// } - /// ); - /// # } - /// ``` - pub fn bound_impl(&self, path: P, body: B) -> Tokens { - self.impl_internal( - path.into_tokens(), - body.into_tokens(), - quote!(), - true, - ) - } - - /// > NOTE: This methods' features are superceded by `Structure::gen_impl`. - /// - /// Creates an `impl` block with the required generic type fields filled in - /// to implement the unsafe trait `path`. - /// - /// This method also adds where clauses to the impl requiring that all - /// referenced type parmaeters implement the trait `path`. - /// - /// # Hygiene and Paths - /// - /// This method wraps the impl block inside of a `const` (see the example - /// below). In this scope, the first segment of the passed-in path is - /// `extern crate`-ed in. If you don't want to generate that `extern crate` - /// item, use a global path. - /// - /// This means that if you are implementing `my_crate::Trait`, you simply - /// write `s.bound_impl(quote!(my_crate::Trait), quote!(...))`, and for the - /// entirety of the definition, you can refer to your crate as `my_crate`. - /// - /// # Caveat - /// - /// If the method contains any macros in type position, all parameters will - /// be considered bound. This is because we cannot determine which type - /// parameters are bound by type macros. - /// - /// # Panics - /// - /// Panics if the path string parameter is not a valid `TraitBound`. - /// - /// # Example - /// ``` - /// # #[macro_use] extern crate quote; - /// # extern crate synstructure; - /// # #[macro_use] extern crate syn; - /// # use synstructure::*; - /// # fn main() { - /// let di: syn::DeriveInput = parse_quote! { - /// enum A { - /// B(T), - /// C(Option), - /// } - /// }; - /// let mut s = Structure::new(&di); - /// - /// s.filter_variants(|v| v.ast().ident != "B"); - /// - /// assert_eq!( - /// s.unsafe_bound_impl(quote!(krate::Trait), quote!{ - /// fn a() {} - /// }), - /// quote!{ - /// #[allow(non_upper_case_globals)] - /// const _DERIVE_krate_Trait_FOR_A: () = { - /// extern crate krate; - /// unsafe impl krate::Trait for A - /// where Option: krate::Trait, - /// U: krate::Trait - /// { - /// fn a() {} - /// } - /// }; - /// } - /// ); - /// # } - /// ``` - pub fn unsafe_bound_impl(&self, path: P, body: B) -> Tokens { - self.impl_internal( - path.into_tokens(), - body.into_tokens(), - quote!(unsafe), - true, - ) - } - - /// > NOTE: This methods' features are superceded by `Structure::gen_impl`. - /// - /// Creates an `impl` block with the required generic type fields filled in - /// to implement the trait `path`. - /// - /// This method will not add any where clauses to the impl. - /// - /// # Hygiene and Paths - /// - /// This method wraps the impl block inside of a `const` (see the example - /// below). In this scope, the first segment of the passed-in path is - /// `extern crate`-ed in. If you don't want to generate that `extern crate` - /// item, use a global path. - /// - /// This means that if you are implementing `my_crate::Trait`, you simply - /// write `s.bound_impl(quote!(my_crate::Trait), quote!(...))`, and for the - /// entirety of the definition, you can refer to your crate as `my_crate`. - /// - /// # Panics - /// - /// Panics if the path string parameter is not a valid `TraitBound`. - /// - /// # Example - /// ``` - /// # #[macro_use] extern crate quote; - /// # extern crate synstructure; - /// # #[macro_use] extern crate syn; - /// # use synstructure::*; - /// # fn main() { - /// let di: syn::DeriveInput = parse_quote! { - /// enum A { - /// B(T), - /// C(Option), - /// } - /// }; - /// let mut s = Structure::new(&di); - /// - /// s.filter_variants(|v| v.ast().ident != "B"); - /// - /// assert_eq!( - /// s.unbound_impl(quote!(krate::Trait), quote!{ - /// fn a() {} - /// }), - /// quote!{ - /// #[allow(non_upper_case_globals)] - /// const _DERIVE_krate_Trait_FOR_A: () = { - /// extern crate krate; - /// impl krate::Trait for A { - /// fn a() {} - /// } - /// }; - /// } - /// ); - /// # } - /// ``` - pub fn unbound_impl(&self, path: P, body: B) -> Tokens { - self.impl_internal( - path.into_tokens(), - body.into_tokens(), - quote!(), - false, - ) - } - - /// > NOTE: This methods' features are superceded by `Structure::gen_impl`. - /// - /// Creates an `impl` block with the required generic type fields filled in - /// to implement the unsafe trait `path`. - /// - /// This method will not add any where clauses to the impl. - /// - /// # Hygiene and Paths - /// - /// This method wraps the impl block inside of a `const` (see the example - /// below). In this scope, the first segment of the passed-in path is - /// `extern crate`-ed in. If you don't want to generate that `extern crate` - /// item, use a global path. - /// - /// This means that if you are implementing `my_crate::Trait`, you simply - /// write `s.bound_impl(quote!(my_crate::Trait), quote!(...))`, and for the - /// entirety of the definition, you can refer to your crate as `my_crate`. - /// - /// # Panics - /// - /// Panics if the path string parameter is not a valid `TraitBound`. - /// - /// # Example - /// ``` - /// # #[macro_use] extern crate quote; - /// # extern crate synstructure; - /// # #[macro_use] extern crate syn; - /// # use synstructure::*; - /// # fn main() { - /// let di: syn::DeriveInput = parse_quote! { - /// enum A { - /// B(T), - /// C(Option), - /// } - /// }; - /// let mut s = Structure::new(&di); - /// - /// s.filter_variants(|v| v.ast().ident != "B"); - /// - /// assert_eq!( - /// s.unsafe_unbound_impl(quote!(krate::Trait), quote!{ - /// fn a() {} - /// }), - /// quote!{ - /// #[allow(non_upper_case_globals)] - /// const _DERIVE_krate_Trait_FOR_A: () = { - /// extern crate krate; - /// unsafe impl krate::Trait for A { - /// fn a() {} - /// } - /// }; - /// } - /// ); - /// # } - /// ``` - #[deprecated] - pub fn unsafe_unbound_impl(&self, path: P, body: B) -> Tokens { - self.impl_internal( - path.into_tokens(), - body.into_tokens(), - quote!(unsafe), - false, - ) - } - - fn impl_internal( - &self, - path: Tokens, - body: Tokens, - safety: Tokens, - add_bounds: bool, - ) -> Tokens { - let name = &self.ast.ident; - let mut gen_clone = self.ast.generics.clone(); - gen_clone.params.extend(self.extra_impl.clone().into_iter()); - let (impl_generics, _, _) = gen_clone.split_for_impl(); - let (_, ty_generics, where_clause) = self.ast.generics.split_for_impl(); - - let bound = syn::parse2::(path.into()) - .expect("`path` argument must be a valid rust trait bound"); - - let mut where_clause = where_clause.cloned(); - if add_bounds { - self.add_trait_bounds(&bound, &mut where_clause); - } - - let dummy_const: Ident = sanitize_ident(&format!( - "_DERIVE_{}_FOR_{}", - (&bound).into_tokens(), - name.into_tokens(), - )); - - // This function is smart. If a global path is passed, no extern crate - // statement will be generated, however, a relative path will cause the - // crate which it is relative to to be imported within the current - // scope. - let mut extern_crate = quote!(); - if bound.path.leading_colon.is_none() { - if let Some(ref seg) = bound.path.segments.first() { - let seg = seg.value(); - extern_crate = quote! { extern crate #seg; }; - } - } - - quote! { - #[allow(non_upper_case_globals)] - const #dummy_const: () = { - #extern_crate - #safety impl #impl_generics #bound for #name #ty_generics #where_clause { - #body - } - }; - } - } - - /// Generate an impl block for the given struct. This impl block will - /// automatically use hygiene tricks to avoid polluting the caller's - /// namespace, and will automatically add trait bounds for generic type - /// parameters. - /// - /// # Syntax - /// - /// This function accepts its arguments as a `Tokens`. The recommended way - /// to call this function is passing the result of invoking the `quote!` - /// macro to it. - /// - /// ```ignore - /// s.gen_impl(quote! { - /// // You can write any items which you want to import into scope here. - /// // For example, you may want to include an `extern crate` for the - /// // crate which implements your trait. These items will only be - /// // visible to the code you generate, and won't be exposed to the - /// // consuming crate - /// extern crate krate; - /// - /// // You can also add `use` statements here to bring types or traits - /// // into scope. - /// // - /// // WARNING: Try not to use common names here, because the stable - /// // version of syn does not support hygiene and you could accidentally - /// // shadow types from the caller crate. - /// use krate::Trait as MyTrait; - /// - /// // The actual impl block is a `gen impl` or `gen unsafe impl` block. - /// // You can use `@Self` to refer to the structure's type. - /// gen impl MyTrait for @Self { - /// fn f(&self) { ... } - /// } - /// }) - /// ``` - /// - /// The most common usage of this trait involves loading the crate the - /// target trait comes from with `extern crate`, and then invoking a `gen - /// impl` block. - /// - /// # Hygiene - /// - /// This method tries to handle hygiene intelligenly for both stable and - /// unstable proc-macro implementations, however there are visible - /// differences. - /// - /// The output of every `gen_impl` function is wrapped in a dummy `const` - /// value, to ensure that it is given its own scope, and any values brought - /// into scope are not leaked to the calling crate. For example, the above - /// invocation may generate an output like the following: - /// - /// ```ignore - /// const _DERIVE_krate_Trait_FOR_Struct: () = { - /// extern crate krate; - /// use krate::Trait as MyTrait; - /// impl MyTrait for Struct where T: MyTrait { - /// fn f(&self) { ... } - /// } - /// }; - /// ``` - /// - /// ### Using the `std` crate - /// - /// If you are using `quote!()` to implement your trait, with the - /// `proc-macro2/nightly` feature, `std` isn't considered to be in scope for - /// your macro. This means that if you use types from `std` in your - /// procedural macro, you'll want to explicitly load it with an `extern - /// crate std;`. - /// - /// ### Absolute paths - /// - /// You should generally avoid using absolute paths in your generated code, - /// as they will resolve very differently when using the stable and nightly - /// versions of `proc-macro2`. Instead, load the crates you need to use - /// explictly with `extern crate` and - /// - /// # Trait Bounds - /// - /// This method will automatically add trait bounds for any type parameters - /// which are referenced within the types of non-ignored fields. - /// - /// Additional type parameters may be added with the generics syntax after - /// the `impl` keyword. - /// - /// ### Type Macro Caveat - /// - /// If the method contains any macros in type position, all parameters will - /// be considered bound. This is because we cannot determine which type - /// parameters are bound by type macros. - /// - /// # Panics - /// - /// This function will panic if the input `Tokens` is not well-formed, or - /// if additional type parameters added by `impl<..>` conflict with generic - /// type parameters on the original struct. - /// - /// # Example Usage - /// - /// ``` - /// # #![recursion_limit="128"] - /// # #[macro_use] extern crate quote; - /// # extern crate synstructure; - /// # #[macro_use] extern crate syn; - /// # use synstructure::*; - /// # fn main() { - /// let di: syn::DeriveInput = parse_quote! { - /// enum A { - /// B(T), - /// C(Option), - /// } - /// }; - /// let mut s = Structure::new(&di); - /// - /// s.filter_variants(|v| v.ast().ident != "B"); - /// - /// assert_eq!( - /// s.gen_impl(quote! { - /// extern crate krate; - /// gen impl krate::Trait for @Self { - /// fn a() {} - /// } - /// }), - /// quote!{ - /// #[allow(non_upper_case_globals)] - /// const _DERIVE_krate_Trait_FOR_A: () = { - /// extern crate krate; - /// impl krate::Trait for A - /// where - /// Option: krate::Trait, - /// U: krate::Trait - /// { - /// fn a() {} - /// } - /// }; - /// } - /// ); - /// - /// // NOTE: You can also add extra generics after the impl - /// assert_eq!( - /// s.gen_impl(quote! { - /// extern crate krate; - /// gen impl krate::Trait for @Self - /// where - /// X: Send + Sync, - /// { - /// fn a() {} - /// } - /// }), - /// quote!{ - /// #[allow(non_upper_case_globals)] - /// const _DERIVE_krate_Trait_X_FOR_A: () = { - /// extern crate krate; - /// impl krate::Trait for A - /// where - /// X: Send + Sync, - /// Option: krate::Trait, - /// U: krate::Trait - /// { - /// fn a() {} - /// } - /// }; - /// } - /// ); - /// # } - /// ``` - pub fn gen_impl(&self, cfg: Tokens) -> Tokens { - use syn::buffer::{TokenBuffer, Cursor}; - use syn::synom::PResult; - use proc_macro2::TokenStream; - - /* Parsing Logic */ - fn parse_gen_impl( - c: Cursor, - ) -> PResult< - ( - Option, - TraitBound, - TokenStream, - syn::Generics, - ), - > { - // `gen` - let (id, c) = syn!(c, Ident)?; - if id.as_ref() != "gen" { - let ((), _) = reject!(c,)?; - unreachable!() - } - - // `impl` or unsafe impl` - let (unsafe_kw, c) = option!(c, keyword!(unsafe))?; - let (_, c) = syn!(c, token::Impl)?; - - // NOTE: After this point we assume they meant to write a gen impl, - // so we panic if we run into an error. - - // optional `<>` - let (mut generics, c) = syn!(c, Generics) - .expect("Expected an optional `<>` with generics after `gen impl`"); - - // @bound - let (bound, c) = syn!(c, TraitBound) - .expect("Expected a trait bound after `gen impl`"); - - // `for @Self` - let (_, c) = keyword!(c, for) - .expect("Expected `for` after trait bound"); - let (_, c) = do_parse!(c, syn!(Token![@]) >> keyword!(Self) >> (())) - .expect("Expected `@Self` after `for`"); - - // optional `where ...` - // XXX: We have to do this awkward if let because option!() doesn't - // provide enough type information to call expect(). - let c = if let Ok((where_clause, c)) = syn!(c, WhereClause) { - generics.where_clause = Some(where_clause); - c - } else { c }; - - let ((_, body), c) = braces!(c, syn!(TokenStream)) - .expect("Expected an impl body after `@Self`"); - - Ok(((unsafe_kw, bound, body, generics), c)) - } - - let buf = TokenBuffer::new2(cfg.into()); - let mut c = buf.begin(); - let mut before = vec![]; - - // Use uninitialized variables here to avoid using the "break with value" - // language feature, which requires Rust 1.19+. - let ((unsafe_kw, bound, body, mut generics), after) = { - let gen_impl; - let cursor; - - loop { - if let Ok((gi, c2)) = parse_gen_impl(c) { - gen_impl = gi; - cursor = c2; - break; - } else if let Some((tt, c2)) = c.token_tree() { - c = c2; - before.push(tt); - } else { - panic!("Expected a gen impl block"); - } - } - - (gen_impl, cursor.token_stream()) - }; - - /* Codegen Logic */ - let name = &self.ast.ident; - - // Add the generics from the original struct in, and then add any - // additional trait bounds which we need on the type. - merge_generics(&mut generics, &self.ast.generics); - self.add_trait_bounds(&bound, &mut generics.where_clause); - let (impl_generics, _, where_clause) = generics.split_for_impl(); - let (_, ty_generics, _) = self.ast.generics.split_for_impl(); - - let dummy_const: Ident = sanitize_ident(&format!( - "_DERIVE_{}_FOR_{}", - (&bound).into_tokens(), - name.into_tokens(), - )); - - quote! { - #[allow(non_upper_case_globals)] - const #dummy_const: () = { - #(#before)* - #unsafe_kw impl #impl_generics #bound for #name #ty_generics #where_clause { - #body - } - #after - }; - } - } -} - -/// Dumps an unpretty version of a tokenstream. Takes any type which implements -/// `Display`. -/// -/// This is mostly useful for visualizing the output of a procedural macro, as -/// it makes it marginally more readable. It is used in the implementation of -/// `test_derive!` to unprettily print the output. -/// -/// # Stability -/// -/// The stability of the output of this function is not guaranteed. Do not -/// assert that the output of this function does not change between minor -/// versions. -/// -/// # Example -/// -/// ``` -/// # extern crate synstructure; -/// # #[macro_use] extern crate quote; -/// # fn main() { -/// assert_eq!( -/// synstructure::unpretty_print(quote! { -/// #[allow(non_upper_case_globals)] -/// const _DERIVE_krate_Trait_FOR_A: () = { -/// extern crate krate; -/// impl krate::Trait for A -/// where -/// Option: krate::Trait, -/// U: krate::Trait -/// { -/// fn a() {} -/// } -/// }; -/// }), -/// "# [ -/// allow ( -/// non_upper_case_globals ) -/// ] -/// const _DERIVE_krate_Trait_FOR_A : ( -/// ) -/// = { -/// extern crate krate ; -/// impl < T , U > krate :: Trait for A < T , U > where Option < U > : krate :: Trait , U : krate :: Trait { -/// fn a ( -/// ) -/// { -/// } -/// } -/// } -/// ; -/// " -/// ) -/// # } -/// ``` -pub fn unpretty_print(ts: T) -> String { - let mut res = String::new(); - - let raw_s = ts.to_string(); - let mut s = &raw_s[..]; - let mut indent = 0; - while let Some(i) = s.find(&['(', '{', '[', ')', '}', ']', ';'][..]) { - match &s[i..i + 1] { - "(" | "{" | "[" => indent += 1, - ")" | "}" | "]" => indent -= 1, - _ => {} - } - res.push_str(&s[..i + 1]); - res.push('\n'); - for _ in 0..indent { - res.push_str(" "); - } - s = s[i + 1..].trim_left_matches(' '); - } - res.push_str(s); - res -} diff --git a/third_party/rust/synstructure-0.8.1/src/macros.rs b/third_party/rust/synstructure-0.8.1/src/macros.rs deleted file mode 100644 index 94e46c2f63c2..000000000000 --- a/third_party/rust/synstructure-0.8.1/src/macros.rs +++ /dev/null @@ -1,411 +0,0 @@ -//! This module provides two utility macros for testing custom derives. They can -//! be used together to eliminate some of the boilerplate required in order to -//! declare and test custom derive implementations. - -// Re-exports used by the decl_derive! and test_derive! -pub use syn::{parse_str, parse, DeriveInput}; -pub use quote::Tokens; -pub use proc_macro::TokenStream as TokenStream; -pub use proc_macro2::TokenStream as TokenStream2; - -/// The `decl_derive!` macro declares a custom derive wrapper. It will parse the -/// incoming `TokenStream` into a `synstructure::Structure` object, and pass it -/// into the inner function. -/// -/// Your inner function should have the following type: -/// -/// ``` -/// # extern crate quote; -/// # extern crate synstructure; -/// fn derive(input: synstructure::Structure) -> quote::Tokens { -/// unimplemented!() -/// } -/// ``` -/// -/// # Usage -/// -/// ### Without Attributes -/// ``` -/// # #[macro_use] extern crate quote; -/// # extern crate synstructure; -/// # fn main() {} -/// fn derive_interesting(_input: synstructure::Structure) -> quote::Tokens { -/// quote! { ... } -/// } -/// -/// # const _IGNORE: &'static str = stringify! { -/// decl_derive!([Interesting] => derive_interesting); -/// # }; -/// ``` -/// -/// ### With Attributes -/// ``` -/// # #[macro_use] extern crate quote; -/// # extern crate synstructure; -/// # fn main() {} -/// fn derive_interesting(_input: synstructure::Structure) -> quote::Tokens { -/// quote! { ... } -/// } -/// -/// # const _IGNORE: &'static str = stringify! { -/// decl_derive!([Interesting, attributes(interesting_ignore)] => derive_interesting); -/// # }; -/// ``` -#[macro_export] -macro_rules! decl_derive { - // XXX: Switch to using this variant everywhere? - ([$derives:ident $($derive_t:tt)*] => $inner:path) => { - #[proc_macro_derive($derives $($derive_t)*)] - #[allow(non_snake_case)] - pub fn $derives( - i: $crate::macros::TokenStream - ) -> $crate::macros::TokenStream - { - let parsed = $crate::macros::parse::<$crate::macros::DeriveInput>(i) - .expect(concat!("Failed to parse input to `#[derive(", - stringify!($derives), - ")]`")); - $inner($crate::Structure::new(&parsed)).into() - } - }; -} - -/// Run a test on a custom derive. This macro expands both the original struct -/// and the expansion to ensure that they compile correctly, and confirms that -/// feeding the original struct into the named derive will produce the written -/// output. -/// -/// You can add `no_build` to the end of the macro invocation to disable -/// checking that the written code compiles. This is useful in contexts where -/// the procedural macro cannot depend on the crate where it is used during -/// tests. -/// -/// # Usage -/// -/// ``` -/// # #[macro_use] extern crate quote; -/// # #[macro_use] extern crate synstructure; -/// fn test_derive_example(_s: synstructure::Structure) -> quote::Tokens { -/// quote! { const YOUR_OUTPUT: &'static str = "here"; } -/// } -/// -/// fn main() { -/// test_derive!{ -/// test_derive_example { -/// struct A; -/// } -/// expands to { -/// const YOUR_OUTPUT: &'static str = "here"; -/// } -/// } -/// } -/// ``` -#[macro_export] -macro_rules! test_derive { - ($name:path { $($i:tt)* } expands to { $($o:tt)* }) => { - { - #[allow(dead_code)] - fn ensure_compiles() { - $($i)* - $($o)* - } - - test_derive!($name { $($i)* } expands to { $($o)* } no_build); - } - }; - - ($name:path { $($i:tt)* } expands to { $($o:tt)* } no_build) => { - { - let i = stringify!( $($i)* ); - let parsed = $crate::macros::parse_str::<$crate::macros::DeriveInput>(i) - .expect(concat!("Failed to parse input to `#[derive(", - stringify!($name), - ")]`")); - - let res = $name($crate::Structure::new(&parsed)); - let expected = stringify!( $($o)* ) - .parse::<$crate::macros::TokenStream2>() - .expect("output should be a valid TokenStream"); - let mut expected_toks = $crate::macros::Tokens::new(); - expected_toks.append_all(expected); - - if res != expected_toks { - panic!("\ -test_derive failed: -expected: -``` -{} -``` - -got: -``` -{} -```\n", - $crate::unpretty_print(&expected_toks), - $crate::unpretty_print(&res), - ); - } - // assert_eq!(res, expected_toks) - } - }; -} - -/// A helper macro for declaring relatively straightforward derive -/// implementations. It provides mechanisms for operating over structures -/// performing modifications on each field etc. -/// -/// This macro doesn't define the actual derive, but rather the implementation -/// method. Use `decl_derive!` to generate the implementation wrapper. -/// -/// # Stability Warning -/// -/// This is an unstable experimental macro API, which may be changed or removed -/// in a future version. I'm not yet confident enough that this API is useful -/// enough to warrant its complexity and inclusion in `synstructure`. -/// -/// # Caveat -/// -/// The `quote!` macro from `quote` must be imported in the calling crate, as -/// this macro depends on it. -/// -/// # Note -/// -/// This feature is implemented behind the `simple-derive` feature, and is only -/// avaliable when that feature is enabled. -/// -/// # Example -/// -/// ``` -/// #[macro_use] -/// extern crate quote; -/// #[macro_use] -/// extern crate synstructure; -/// # const _IGNORE: &'static str = stringify! { -/// decl_derive!([Interest] => derive_interest); -/// # }; -/// -/// simple_derive! { -/// // This macro implements the `Interesting` method exported by the `aa` -/// // crate. It will explicitly add an `extern crate` invocation to import the -/// // crate into the expanded context. -/// derive_interest impl synstructure_test_traits::Interest { -/// // A "filter" block can be added. It evaluates its body with the (s) -/// // variable bound to a mutable reference to the input `Structure` -/// // object. -/// // -/// // This block can be used to perform general transformations, such as -/// // filtering out fields which should be ignored by all methods and for -/// // the purposes of binding type parameters. -/// filter(s) { -/// s.filter(|bi| bi.ast().ident != Some("a".into())); -/// } -/// -/// // This is an implementation of a method in the implemented crate. The -/// // return value should be the series of match patterns to destructure -/// // the `self` argument with. -/// fn interesting(&self as s) -> bool { -/// s.fold(false, |acc, bi| { -/// quote!(#acc || synstructure_test_traits::Interest::interesting(#bi)) -/// }) -/// } -/// } -/// } -/// -/// fn main() { -/// test_derive!{ -/// derive_interest { -/// struct A { -/// x: i32, -/// a: bool, // Will be ignored by filter -/// c: T, -/// } -/// } -/// expands to { -/// #[allow(non_upper_case_globals)] -/// const _DERIVE_synstructure_test_traits_Interest_FOR_A: () = { -/// extern crate synstructure_test_traits; -/// impl synstructure_test_traits::Interest for A -/// where T: synstructure_test_traits::Interest -/// { -/// fn interesting(&self) -> bool { -/// match *self { -/// A { -/// x: ref __binding_0, -/// c: ref __binding_2, -/// .. -/// } => { -/// false || -/// synstructure_test_traits::Interest::interesting(__binding_0) || -/// synstructure_test_traits::Interest::interesting(__binding_2) -/// } -/// } -/// } -/// } -/// }; -/// } -/// } -/// } -/// ``` -#[cfg(feature = "simple-derive")] -#[macro_export] -macro_rules! simple_derive { - // entry point - ( - $iname:ident impl $path:path { $($rest:tt)* } - ) => { - simple_derive!(__I [$iname, $path] { $($rest)* } [] []); - }; - - // Adding a filter block - ( - __I $opt:tt { - filter($s:ident) { - $($body:tt)* - } - $($rest:tt)* - } [$($done:tt)*] [$($filter:tt)*] - ) => { - simple_derive!( - __I $opt { $($rest)* } [$($done)*] [ - $($filter)* - [ - st_name = $s, - body = { - $($body)* - }, - ] - ] - ); - }; - - // &self bound method - ( - __I $opt:tt { - fn $fn_name:ident (&self as $s:ident $($params:tt)*) $(-> $t:ty)* { - $($body:tt)* - } - $($rest:tt)* - } [$($done:tt)*] [$($filter:tt)*] - ) => { - simple_derive!( - __I $opt { $($rest)* } [ - $($done)* - [ - st_name = $s, - bind_style = Ref, - body = { $($body)* }, - result = result, - expanded = { - fn $fn_name(&self $($params)*) $(-> $t)* { - match *self { #result } - } - }, - ] - ] [$($filter)*] - ); - }; - - // &mut self bound method - ( - __I $opt:tt { - fn $fn_name:ident (&mut self as $s:ident $($params:tt)*) $(-> $t:ty)* { - $($body:tt)* - } - $($rest:tt)* - } [$($done:tt)*] [$($filter:tt)*] - ) => { - simple_derive!( - __I $opt { $($rest)* } [ - $($done)* - [ - st_name = $s, - bind_style = RefMut, - body = { $($body)* }, - result = result, - expanded = { - fn $fn_name(&mut self $($params)*) $(-> $t)* { - match *self { #result } - } - }, - ] - ] [$($filter)*] - ); - }; - - // self bound method - ( - __I $opt:tt { - fn $fn_name:ident (self as $s:ident $($params:tt)*) $(-> $t:ty)* { - $($body:tt)* - } - $($rest:tt)* - } [$($done:tt)*] [$($filter:tt)*] - ) => { - simple_derive!( - __I $opt { $($rest)* } [ - $($done)* - [ - st_name = $s, - bind_style = Move, - body = { $($body)* }, - result = result, - expanded = { - fn $fn_name(self $($params)*) $(-> $t)* { - match self { #result } - } - }, - ] - ] [$($filter)*] - ); - }; - - // XXX: Static methods? - - // codegen after data collection - ( - __I [$iname:ident, $path:path] {} [$( - [ - st_name = $st_name:ident, - bind_style = $bind_style:ident, - body = $body:tt, - result = $result:ident, - expanded = { $($expanded:tt)* }, - ] - )*] [$( - [ - st_name = $filter_st_name:ident, - body = $filter_body:tt, - ] - )*] - ) => { - fn $iname(mut st: $crate::Structure) -> $crate::macros::Tokens { - let _ = &mut st; // Silence the unused mut warning - - // Filter/transform the `Structure` object before cloning it for - // individual methods. - $( - { - let $filter_st_name = &mut st; - $filter_body - } - )* - - // Clone the `Structure` object and set the correct binding style, - // then perform method specific expansion. - $( - let $result = { - let mut $st_name = st.clone(); - $st_name.bind_with(|_| ::synstructure::BindStyle::$bind_style); - let $result = { - $body - }; - quote!{ $($expanded)* } - }; - )* - - st.bound_impl(quote!($path), quote!{ - $(#$result)* - }) - } - } -}