From 7b2c7f4f51056c095e67006f7c0134b7c6c74ab0 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Tue, 15 Jun 2021 21:00:57 +0000 Subject: [PATCH] Bug 1716518 - Upgrade derive_more to v0.99.11. r=emilio Latest version is v0.99.14 but it adds new dependencies. Differential Revision: https://phabricator.services.mozilla.com/D117780 --- Cargo.lock | 4 +- .../rust/derive_more/.cargo-checksum.json | 2 +- third_party/rust/derive_more/CHANGELOG.md | 60 ++- third_party/rust/derive_more/Cargo.lock | 27 +- third_party/rust/derive_more/Cargo.toml | 32 +- third_party/rust/derive_more/README.md | 7 + third_party/rust/derive_more/src/as_mut.rs | 8 +- third_party/rust/derive_more/src/as_ref.rs | 12 +- third_party/rust/derive_more/src/deref.rs | 19 +- third_party/rust/derive_more/src/deref_mut.rs | 20 +- third_party/rust/derive_more/src/display.rs | 152 ++---- third_party/rust/derive_more/src/error.rs | 437 +++++++++++++++ third_party/rust/derive_more/src/from.rs | 93 ++-- third_party/rust/derive_more/src/into.rs | 49 +- third_party/rust/derive_more/src/lib.rs | 16 +- .../rust/derive_more/src/mul_assign_like.rs | 2 +- third_party/rust/derive_more/src/parsing.rs | 9 +- third_party/rust/derive_more/src/try_into.rs | 5 +- third_party/rust/derive_more/src/utils.rs | 510 ++++++++++++++---- third_party/rust/derive_more/tests/add.rs | 23 + .../rust/derive_more/tests/add_assign.rs | 12 + third_party/rust/derive_more/tests/as_mut.rs | 108 ++++ third_party/rust/derive_more/tests/as_ref.rs | 108 ++++ .../derive_more/tests/boats_display_derive.rs | 57 ++ .../rust/derive_more/tests/constructor.rs | 21 + third_party/rust/derive_more/tests/deref.rs | 68 +++ .../rust/derive_more/tests/deref_mut.rs | 124 +++++ third_party/rust/derive_more/tests/display.rs | 405 ++++++++++++++ .../error/derives_for_enums_with_source.rs | 249 +++++++++ .../derives_for_generic_enums_with_source.rs | 248 +++++++++ ...derives_for_generic_structs_with_source.rs | 245 +++++++++ .../error/derives_for_structs_with_source.rs | 249 +++++++++ .../rust/derive_more/tests/error/mod.rs | 56 ++ .../derives_for_enums_with_backtrace.rs | 272 ++++++++++ ...erives_for_generic_enums_with_backtrace.rs | 272 ++++++++++ ...ives_for_generic_structs_with_backtrace.rs | 275 ++++++++++ .../derives_for_structs_with_backtrace.rs | 280 ++++++++++ .../derive_more/tests/error/nightly/mod.rs | 85 +++ .../rust/derive_more/tests/error_tests.rs | 6 + third_party/rust/derive_more/tests/from.rs | 171 ++++++ .../rust/derive_more/tests/from_str.rs | 11 + .../rust/derive_more/tests/generics.rs | 103 ++++ third_party/rust/derive_more/tests/index.rs | 13 + .../rust/derive_more/tests/index_mut.rs | 36 ++ third_party/rust/derive_more/tests/into.rs | 126 +++++ .../rust/derive_more/tests/into_iterator.rs | 39 ++ third_party/rust/derive_more/tests/lib.rs | 275 ++++++++++ third_party/rust/derive_more/tests/mul.rs | 20 + .../rust/derive_more/tests/mul_assign.rs | 32 ++ third_party/rust/derive_more/tests/no_std.rs | 74 +++ third_party/rust/derive_more/tests/not.rs | 28 + third_party/rust/derive_more/tests/sum.rs | 31 ++ .../rust/derive_more/tests/try_into.rs | 199 +++++++ 53 files changed, 5480 insertions(+), 305 deletions(-) create mode 100644 third_party/rust/derive_more/src/error.rs create mode 100644 third_party/rust/derive_more/tests/add.rs create mode 100644 third_party/rust/derive_more/tests/add_assign.rs create mode 100644 third_party/rust/derive_more/tests/as_mut.rs create mode 100644 third_party/rust/derive_more/tests/as_ref.rs create mode 100644 third_party/rust/derive_more/tests/boats_display_derive.rs create mode 100644 third_party/rust/derive_more/tests/constructor.rs create mode 100644 third_party/rust/derive_more/tests/deref.rs create mode 100644 third_party/rust/derive_more/tests/deref_mut.rs create mode 100644 third_party/rust/derive_more/tests/display.rs create mode 100644 third_party/rust/derive_more/tests/error/derives_for_enums_with_source.rs create mode 100644 third_party/rust/derive_more/tests/error/derives_for_generic_enums_with_source.rs create mode 100644 third_party/rust/derive_more/tests/error/derives_for_generic_structs_with_source.rs create mode 100644 third_party/rust/derive_more/tests/error/derives_for_structs_with_source.rs create mode 100644 third_party/rust/derive_more/tests/error/mod.rs create mode 100644 third_party/rust/derive_more/tests/error/nightly/derives_for_enums_with_backtrace.rs create mode 100644 third_party/rust/derive_more/tests/error/nightly/derives_for_generic_enums_with_backtrace.rs create mode 100644 third_party/rust/derive_more/tests/error/nightly/derives_for_generic_structs_with_backtrace.rs create mode 100644 third_party/rust/derive_more/tests/error/nightly/derives_for_structs_with_backtrace.rs create mode 100644 third_party/rust/derive_more/tests/error/nightly/mod.rs create mode 100644 third_party/rust/derive_more/tests/error_tests.rs create mode 100644 third_party/rust/derive_more/tests/from.rs create mode 100644 third_party/rust/derive_more/tests/from_str.rs create mode 100644 third_party/rust/derive_more/tests/generics.rs create mode 100644 third_party/rust/derive_more/tests/index.rs create mode 100644 third_party/rust/derive_more/tests/index_mut.rs create mode 100644 third_party/rust/derive_more/tests/into.rs create mode 100644 third_party/rust/derive_more/tests/into_iterator.rs create mode 100644 third_party/rust/derive_more/tests/lib.rs create mode 100644 third_party/rust/derive_more/tests/mul.rs create mode 100644 third_party/rust/derive_more/tests/mul_assign.rs create mode 100644 third_party/rust/derive_more/tests/no_std.rs create mode 100644 third_party/rust/derive_more/tests/not.rs create mode 100644 third_party/rust/derive_more/tests/sum.rs create mode 100644 third_party/rust/derive_more/tests/try_into.rs diff --git a/Cargo.lock b/Cargo.lock index 6c9e59b943a5..c88403e312d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1136,9 +1136,9 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.2" +version = "0.99.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2159be042979966de68315bce7034bb000c775f22e3e834e1c52ff78f041cae8" +checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c" dependencies = [ "proc-macro2", "quote", diff --git a/third_party/rust/derive_more/.cargo-checksum.json b/third_party/rust/derive_more/.cargo-checksum.json index a1075a1d19cb..1d6c08274f24 100644 --- a/third_party/rust/derive_more/.cargo-checksum.json +++ b/third_party/rust/derive_more/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"d2567aaf31209eed254c6245f9dbb7b1c8dbe96dc7c4eefc4e5e4e30f3fef16f","Cargo.lock":"524047afe2b1422b2841449d75d16d715e52a437b6ec8a0a5b6b0c340bf9ec79","Cargo.toml":"5a906a9bd1c9350f0af97c65936d2128f01d5640afab607e1c43629b75455ffc","LICENSE":"8a35369f3ca263b3c62fbb5032947e53b6bfebc6c8a4d1bb982de1c069f6fba5","README.md":"618e76cc65717577a15fa156f8ec4aba1c751b2098b61f42aac404eaf4e3ad29","src/add_assign_like.rs":"d71056331208161cfc985ca66425cb0b162381d64edbfaec39efeae77f5b5731","src/add_helpers.rs":"bbd4544b57091ac40bf0a6920fc85e0c90ce750bc4fc2bae3b7656808bc31324","src/add_like.rs":"130adfe79da699c10cc1c480036e84360eaac2aea1bd5667a2be51757803e14f","src/as_mut.rs":"1467c45a4e04c3c1138adcb04412a1e8e56615c9f8eea3ee5be28006f3bec598","src/as_ref.rs":"a018ce133009c19626d5913db947b913e3c834737c0242e2551f8de6be915929","src/constructor.rs":"c34f5eeaf51a3990fa783826ff1b2669a47e1876ce47eed6891a359db684d37d","src/deref.rs":"872145c99fa2850f4adc25169d455ee4e4cffab9e7bdec1495b0eb65c405504a","src/deref_mut.rs":"0272b00dcc59685673b79013ea4b50aa76291b95920987e5f445ac04825e5552","src/display.rs":"ff8502782100d3e3bc4c2dab718084a04457e101d8799e9e1f84f29ecc95ff6c","src/from.rs":"41e7cbbd908277bdb8586809c8f2cb740560e1c7b9a2bb2314d6ef43f0700190","src/from_str.rs":"077a09809bcb466ff801e1a6e75b034b8c46562e3b1665f068a313e1d2dabe95","src/index.rs":"64bdb5f51034b0e7d0962a6c4e7781453d08767d693adb7f474f638e2b9c6179","src/index_mut.rs":"035095e24b7a7c11fb6c4951e5fbb094e045435bbfe9fe36ebc78fe28e6cc802","src/into.rs":"89848fc814ace46b2f65649171e8aaedd805ec0d68150cc04eec811d095cbea3","src/into_iterator.rs":"1a89f60f635ed1f0dda2f740631ca564391cbc9cc20789d0be0f6181d80aaee5","src/lib.rs":"e032f313fd5e42d8cbd077bf38229b9015b3dc7e4e9a9fea8ee11eb5fd34ca2f","src/mul_assign_like.rs":"7f91514b34885304c846c9d41ce7b6519702ee3a6dfa3b0590069c3b1150e292","src/mul_helpers.rs":"7bb577b8866a87bafb8f79843d54416fb0e6eca6bbe22b1523c9eb7347f84b30","src/mul_like.rs":"25fdf3a26909a5f88ec392f00bcf7eeec247dd05a9c6307426383fac133a5e69","src/not_like.rs":"484a7d300a6a3306cb6423d706b570c4c9ca1bcdf26852556a6e7bbcfd51ad09","src/parsing.rs":"53190b5cd3302777b0f7cf4f9bdccb26e4b552598502c98109e5692c34cc21b8","src/sum_like.rs":"c566c6d94d92efb46396ac8673cceeb074e3dc7c1a234a388d40c0946567a2ef","src/try_into.rs":"23fd745717e7d3b60ba23ea985eefe2c460a3ff9ddd74f11ef752a4eaf52ed7c","src/utils.rs":"e044b9bc93245a6c3d4fc0b5663abb23c924d2ef1f8c823ae15364c145664077"},"package":"2159be042979966de68315bce7034bb000c775f22e3e834e1c52ff78f041cae8"} \ No newline at end of file +{"files":{"CHANGELOG.md":"99993087689dc50095d26a01835cb9def2c1cc61fa7bdc3c9bee4b7a6d803547","Cargo.lock":"2e83d0b5e0945e393121a950c894e32237105e101bbb474871ef4b3c76873181","Cargo.toml":"e1428d0d712672a672c4d802fa0de36e7d87183045f21bab7cebfd7559dcecb6","LICENSE":"8a35369f3ca263b3c62fbb5032947e53b6bfebc6c8a4d1bb982de1c069f6fba5","README.md":"16a0e23ebad9efed56d920694ccb3f6b333f9af83f482cf7dec408e9717c972a","src/add_assign_like.rs":"d71056331208161cfc985ca66425cb0b162381d64edbfaec39efeae77f5b5731","src/add_helpers.rs":"bbd4544b57091ac40bf0a6920fc85e0c90ce750bc4fc2bae3b7656808bc31324","src/add_like.rs":"130adfe79da699c10cc1c480036e84360eaac2aea1bd5667a2be51757803e14f","src/as_mut.rs":"0feebd28cd53f2eab9feb0807a1203359811a6718afd80fa86fe34210dcbd17c","src/as_ref.rs":"0dddd9a8e4671d5bf546c2ab662fbf5e5dcf43657c6445aee84acf1bf0570efc","src/constructor.rs":"c34f5eeaf51a3990fa783826ff1b2669a47e1876ce47eed6891a359db684d37d","src/deref.rs":"a58b91ea3a92c0d51289b2f38a4605c46b3307439eb8a3edc595659de229f37c","src/deref_mut.rs":"6e32cf2ebb3aacff2e88fae8511b1ac09de0c450f2b7b8d87d2c48bd4aceb937","src/display.rs":"db7eb9312cd0a4180bedc5d469f591af42abaabb2cbd01e927530b8af5df0a53","src/error.rs":"5c291464fc356af2cd15ff877c34accf83225ba05ab34d7ba5df15538439c0cf","src/from.rs":"cdc16582137aba976044716ebe33b6885fe716ea7fdba87bd748b7678dd587b5","src/from_str.rs":"077a09809bcb466ff801e1a6e75b034b8c46562e3b1665f068a313e1d2dabe95","src/index.rs":"64bdb5f51034b0e7d0962a6c4e7781453d08767d693adb7f474f638e2b9c6179","src/index_mut.rs":"035095e24b7a7c11fb6c4951e5fbb094e045435bbfe9fe36ebc78fe28e6cc802","src/into.rs":"07bfbab252096360ae6fbeb76a5b04106caebf4a779e6d7cfc096cb92d2bb275","src/into_iterator.rs":"1a89f60f635ed1f0dda2f740631ca564391cbc9cc20789d0be0f6181d80aaee5","src/lib.rs":"25de27962959d76a643ad0a5029e104577d99885e49ad81d8a262cb28af0b0b2","src/mul_assign_like.rs":"6c530daebeb72a0df366ea5921bcf75f5aa9723dc0326b5035fe71fd9348cc9a","src/mul_helpers.rs":"7bb577b8866a87bafb8f79843d54416fb0e6eca6bbe22b1523c9eb7347f84b30","src/mul_like.rs":"25fdf3a26909a5f88ec392f00bcf7eeec247dd05a9c6307426383fac133a5e69","src/not_like.rs":"484a7d300a6a3306cb6423d706b570c4c9ca1bcdf26852556a6e7bbcfd51ad09","src/parsing.rs":"90b101b680add5e33b069ca3df89958e2ee7f45fdd7dd1012fc8001fa6e7a743","src/sum_like.rs":"c566c6d94d92efb46396ac8673cceeb074e3dc7c1a234a388d40c0946567a2ef","src/try_into.rs":"32facc30af83c79dbd47c7f21d888c2739ba207413bf67b917bca5001baa6f0c","src/utils.rs":"dd0612d6e1aef9c83705e0742c5b9fa9b1ccca079f620b447f1565a3210a47e9","tests/add.rs":"2c4eda40cd46fb57e9e5502dad61f930ac5f8bd672d6aacf2e35124b20034518","tests/add_assign.rs":"e59d94a1b76afdbeacc869f13e1c296a7939a660bfc23b331811248f2320d944","tests/as_mut.rs":"c9cc54e0d5b434c720cbd44e5def4f11cd28abc807675b96fe30a4b43bdbacd3","tests/as_ref.rs":"7c3caf32cedfd3ff9423c3b3ae4d6479a3df6d1b04ee7d3e8db822d20f226394","tests/boats_display_derive.rs":"23d00ad64b1a16a4e6119424f2e274729282a5acef8e72351fe87c23dcf85b47","tests/constructor.rs":"ca619975d6205cd2817b531373d61a3c2077f6673733ba945496cc33e9fb2299","tests/deref.rs":"936e20c2e3d8a32b5d8531fa462d279ccfaabaa422148790c9db174f3cc190f6","tests/deref_mut.rs":"5d55950e2541b5da33c8ba1351240f3d09d9d63d37a424655d8cc5674a0342ad","tests/display.rs":"aa03fdf40ba7282a7e7550f88eddc48c371d0dc020fceff171e61a382c228c9e","tests/error/derives_for_enums_with_source.rs":"b6d4c49cc888ec92cfeb24caab1cc3e23ee0d8ff99e098340584f2ef77ec060a","tests/error/derives_for_generic_enums_with_source.rs":"70de37458473bfb158ff6adf4131dd4b2beb259d44c3741b63d1a35652220baf","tests/error/derives_for_generic_structs_with_source.rs":"f017e45e72ad7e95544c95a92257253b3a61cc497180e1a224c4e5dc977fc627","tests/error/derives_for_structs_with_source.rs":"6fc1d1b4a3a6ba5d77837af6ef171f05fca50ab98b3d71351b649a0e689afd5f","tests/error/mod.rs":"b0599240c34d819986202a079b1d628c2f56c8ccd8206e89f7220cc1752a04d7","tests/error/nightly/derives_for_enums_with_backtrace.rs":"106459fb7873e5c38a35f68f6e026abe6d6a67edaed0b8c8106485bb8e67ee4c","tests/error/nightly/derives_for_generic_enums_with_backtrace.rs":"073184bcdb6051d8f8b1651f42c3636f066c80710f53ecfef32436b579c3297b","tests/error/nightly/derives_for_generic_structs_with_backtrace.rs":"5b78ff9c2d5f58c529d591e84b3eaeddc4f945da7508a5c97f3e5e025032abb8","tests/error/nightly/derives_for_structs_with_backtrace.rs":"320d95ba58786b065591807da96d5cfa09c73836d0d2a7dd2ae328abdb348724","tests/error/nightly/mod.rs":"aa12d7075bdbe222a89cf6492e10f59cfadf3658718d3226942b8230eac7f8b3","tests/error_tests.rs":"f37167b7d22f9d98593e8ed66e1c46c17548d7fb6cd125b3adf2409435e4935c","tests/from.rs":"de0943ed566d15ca15d0ec9cd946b4c77e4b2057d192b0d5165c29877b303be1","tests/from_str.rs":"ce1aeb1fca38b5d7b05c2229efe5865c0ac57454dcfec657a2645c5472694b25","tests/generics.rs":"c7c762453cde679ede4c6246906dd19c3016c8b0dc4a7b8e4e33005d0a573ea5","tests/index.rs":"e05053cd9f13651a8e00fcd63c85d068f029d9b7a3377ac4bb1ac540c99d06d5","tests/index_mut.rs":"bde985198352a3489c038d92bdff30119901e38db054f95fb582ed85b5e2768f","tests/into.rs":"d581a27d32f11207c1775fb631e64bdbcb4c711a6be669c265fe4f757b7442b6","tests/into_iterator.rs":"7ae73a51d5ceef8a0e3f97a64e71b85cba64ec857fc02248f33a97a3fc358f84","tests/lib.rs":"471f15f790c1a040652d8833094e96e185d4e9c8a9e945b4c7c9a29b2aed025c","tests/mul.rs":"0b07081d99a7bf64113a9d8fac98e9679e9aa58c67c9ff73b43d78a432c52b80","tests/mul_assign.rs":"77d18aad3715dfdae990ae585fa507f6fc9341aba8eb22d72c85ec98be614abc","tests/no_std.rs":"541ad39e31adc570bff4fe9dc520d29faed48d8af74656bcf4456705994a7b01","tests/not.rs":"cb5f9c259abc19905f0fd088f2694d86945c9319b03c347c045c6c3b632f4b64","tests/sum.rs":"4c9bb7487aa323ee9a56eef7c1283b137d43f8f424854c3efc94e01aea18bdb8","tests/try_into.rs":"458feca7461f33ba3aa6cf1c4d6848693ae0acafcf95feec0ea48c9c36c3a167"},"package":"41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c"} \ No newline at end of file diff --git a/third_party/rust/derive_more/CHANGELOG.md b/third_party/rust/derive_more/CHANGELOG.md index 8dd88f5098b2..a04b013f655b 100644 --- a/third_party/rust/derive_more/CHANGELOG.md +++ b/third_party/rust/derive_more/CHANGELOG.md @@ -5,12 +5,70 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). + +## 0.99.10 - 2020-??-?? + +### Improvements + +- `From` supports additional types for conversion: `#[from(types(u8, u16))]`. + + +## 0.99.7 - 2020-05-16 + +### Fixes + +- Fix generic derives for `MulAssign` + +### Improvements + +- When specifying specific features of the crate to only enable specific + derives, the `extra-traits` feature of `syn` is not always enabled + when those the specified features do not require it. This should speed up + compile time of `syn` when this feature is not needed. + + +## 0.99.6 - 2020-05-13 + +### Improvements + +- Make sure output of derives is deterministic, for better support in + rust-analyzer + + +## 0.99.5 - 2020-03-28 + +### New features + +- Support for deriving `Error`!!! (many thanks to @ffuugoo and @tyranron) + +### Fixes + +- Fix generic bounds for `Deref` and `DerefMut` with `forward`, i.e. put `Deref` + bound on whole type, so on `where Box: Deref` instead of on `T: Deref`. + ([#107](https://github.com/JelteF/derive_more/issues/114)) + +- The `tests` directory is now correctly included in the crate (requested by + Debian package maintainers) + +## 0.99.4 - 2020-03-28 + +Note: This version is yanked, because quickly after release it was found out +tests did not run in CI. + +## 0.99.3 - 2020-02-19 + +### Fixes + +- Fix generic bounds for `Deref` and `DerefMut` with no `forward`, i.e. no bounds + are necessary. ([#107](https://github.com/JelteF/derive_more/issues/114)) + + ## 0.99.2 - 2019-11-17 ### Fixes - Hotfix for a regression in allowed `Display` derives using `#` flag, such as - `{:#b}` ([#107](https://github.com/JelteF/derive_more/issues/105)) + `{:#b}` ([#107](https://github.com/JelteF/derive_more/issues/107)) ## 0.99.1 - 2019-11-12 diff --git a/third_party/rust/derive_more/Cargo.lock b/third_party/rust/derive_more/Cargo.lock index a6fcb562cd36..5d594c8ec548 100644 --- a/third_party/rust/derive_more/Cargo.lock +++ b/third_party/rust/derive_more/Cargo.lock @@ -2,11 +2,12 @@ # It is not intended for manual editing. [[package]] name = "derive_more" -version = "0.99.2" +version = "0.99.11" dependencies = [ "peg 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -39,6 +40,27 @@ dependencies = [ "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "syn" version = "1.0.3" @@ -59,5 +81,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5c2380ae88876faae57698be9e9775e3544decad214599c3a6266cca6ac802" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum quote 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "49d77c41ca8767f2f41394c11a4eebccab83da25e7cc035387a3125f02be90a3" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum syn 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "158521e6f544e7e3dcfc370ac180794aa38cb34a1b1e07609376d4adcf429b93" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" diff --git a/third_party/rust/derive_more/Cargo.toml b/third_party/rust/derive_more/Cargo.toml index 1b9e5b4358ce..b496f9f9d9e5 100644 --- a/third_party/rust/derive_more/Cargo.toml +++ b/third_party/rust/derive_more/Cargo.toml @@ -13,9 +13,9 @@ [package] edition = "2018" name = "derive_more" -version = "0.99.2" +version = "0.99.11" authors = ["Jelte Fennema "] -include = ["src/**/*.rs", "Cargo.toml", "LICENSE", "README.md", "CHANGELOG.md", "test/**/*.rs"] +include = ["src/**/*.rs", "Cargo.toml", "LICENSE", "README.md", "CHANGELOG.md", "tests/**/*.rs"] autotests = true description = "Adds #[derive(x)] macros for more traits" documentation = "https://jeltef.github.io/derive_more/derive_more/" @@ -79,6 +79,11 @@ name = "display" path = "tests/display.rs" required-features = ["display"] +[[test]] +name = "error" +path = "tests/error_tests.rs" +required-features = ["error"] + [[test]] name = "from" path = "tests/from.rs" @@ -156,35 +161,40 @@ version = "1" [dependencies.syn] version = "1" -features = ["extra-traits"] [build-dependencies.peg] version = "0.5" optional = true +[build-dependencies.rustc_version] +version = "0.2" +optional = true + [features] add = [] add_assign = [] as_mut = [] as_ref = [] constructor = [] -default = ["add_assign", "add", "as_mut", "as_ref", "constructor", "deref", "deref_mut", "display", "from", "from_str", "index", "index_mut", "into", "into_iterator", "iterator", "mul_assign", "mul", "not", "sum", "try_into"] +default = ["add_assign", "add", "as_mut", "as_ref", "constructor", "deref", "deref_mut", "display", "error", "from", "from_str", "index", "index_mut", "into", "into_iterator", "iterator", "mul_assign", "mul", "not", "sum", "try_into"] deref = [] deref_mut = [] -display = [] -from = [] +display = ["syn/extra-traits"] +error = ["syn/extra-traits"] +from = ["syn/extra-traits"] from_str = [] generate-parsing-rs = ["peg"] index = [] index_mut = [] -into = [] +into = ["syn/extra-traits"] into_iterator = [] iterator = [] -mul = [] -mul_assign = [] +mul = ["syn/extra-traits"] +mul_assign = ["syn/extra-traits"] nightly = [] -not = [] +not = ["syn/extra-traits"] sum = [] -try_into = [] +testing-helpers = ["rustc_version"] +try_into = ["syn/extra-traits"] [badges.github] repository = "JelteF/derive_more" workflow = "CI" diff --git a/third_party/rust/derive_more/README.md b/third_party/rust/derive_more/README.md index 106f07cd7de7..862d4b7173c4 100644 --- a/third_party/rust/derive_more/README.md +++ b/third_party/rust/derive_more/README.md @@ -90,6 +90,11 @@ These traits are used for converting a struct to a string in different ways. 1. [`Display`-like], contains `Display`, `Binary`, `Octal`, `LowerHex`, `UpperHex`, `LowerExp`, `UpperExp`, `Pointer` +### Error-handling traits +These traits are used to define error-types. + +1. [`Error`] + ### Operators These are traits that can be used for operator overloading. @@ -159,6 +164,8 @@ extern crate derive_more; [`Display`-like]: https://jeltef.github.io/derive_more/derive_more/display.html +[`Error`]: https://jeltef.github.io/derive_more/derive_more/error.html + [`Index`]: https://jeltef.github.io/derive_more/derive_more/index_op.html [`Deref`]: https://jeltef.github.io/derive_more/derive_more/deref.html [`Not`-like]: https://jeltef.github.io/derive_more/derive_more/not.html diff --git a/third_party/rust/derive_more/src/as_mut.rs b/third_party/rust/derive_more/src/as_mut.rs index 544407aef856..83944648f58f 100644 --- a/third_party/rust/derive_more/src/as_mut.rs +++ b/third_party/rust/derive_more/src/as_mut.rs @@ -1,15 +1,19 @@ -use crate::utils::{add_where_clauses_for_new_ident, MultiFieldData, State}; +use crate::utils::{ + add_where_clauses_for_new_ident, AttrParams, MultiFieldData, State, +}; use proc_macro2::{Span, TokenStream}; use quote::quote; use syn::{parse::Result, DeriveInput, Ident}; pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result { let as_mut_type = &Ident::new("__AsMutT", Span::call_site()); - let state = State::with_field_ignore_and_forward( + let state = State::with_type_bound( input, trait_name, quote!(::core::convert), String::from("as_mut"), + AttrParams::ignore_and_forward(), + false, )?; let MultiFieldData { fields, diff --git a/third_party/rust/derive_more/src/as_ref.rs b/third_party/rust/derive_more/src/as_ref.rs index ed5bb34eea3d..4b8ba851d5b6 100644 --- a/third_party/rust/derive_more/src/as_ref.rs +++ b/third_party/rust/derive_more/src/as_ref.rs @@ -1,15 +1,19 @@ -use crate::utils::{add_where_clauses_for_new_ident, MultiFieldData, State}; +use crate::utils::{ + add_where_clauses_for_new_ident, AttrParams, MultiFieldData, State, +}; use proc_macro2::{Span, TokenStream}; use quote::quote; use syn::{parse::Result, DeriveInput, Ident}; pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result { let as_ref_type = &Ident::new("__AsRefT", Span::call_site()); - let state = State::with_field_ignore_and_forward( + let state = State::with_type_bound( input, trait_name, quote!(::core::convert), String::from("as_ref"), + AttrParams::ignore_and_forward(), + false, )?; let MultiFieldData { fields, @@ -61,13 +65,13 @@ pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result Result Result Result { let trait_name = trait_name.trim_end_matches("Custom"); let trait_ident = syn::Ident::new(trait_name, Span::call_site()); @@ -51,7 +45,7 @@ pub fn expand(input: &syn::DeriveInput, trait_name: &str) -> Result }) .collect(); let where_clause = quote_spanned!(input.span()=> where #(#bounds),*); - add_extra_where_clauses(&input.generics, where_clause) + utils::add_extra_where_clauses(&input.generics, where_clause) } else { input.generics.clone() }; @@ -278,7 +272,7 @@ impl<'a, 'b> State<'a, 'b> { return Err(Error::new(span, "No bounds specified")); } - let mut bounds = HashMap::new(); + let mut bounds = HashMap::default(); for generic_param in generic_params { let type_param = match generic_param { @@ -303,7 +297,7 @@ impl<'a, 'b> State<'a, 'b> { qself: None, path: type_param.ident.into(), }); - let bounds = bounds.entry(ty).or_insert_with(HashSet::new); + let bounds = bounds.entry(ty).or_insert_with(HashSet::default); for bound in type_param.bounds { let bound = match bound { @@ -352,11 +346,12 @@ impl<'a, 'b> State<'a, 'b> { op if op.segments.first().expect("path shouldn't be empty").ident == "fmt" => { + let expected_affix_usage = "outer `enum` `fmt` is an affix spec that expects no args and at most 1 placeholder for inner variant display"; if outer_enum { if list.nested.iter().skip(1).count() != 0 { return Err(Error::new( list.nested[1].span(), - "`fmt` formatting requires a single `fmt` argument", + expected_affix_usage, )); } // TODO: Check for a single `Display` group? @@ -385,7 +380,7 @@ impl<'a, 'b> State<'a, 'b> { if num_placeholders > 1 { return Err(Error::new( list.nested[1].span(), - "fmt string for enum should have at at most 1 placeholder", + expected_affix_usage, )); } if num_placeholders == 1 { @@ -447,7 +442,7 @@ impl<'a, 'b> State<'a, 'b> { } else if fields.len() > 1 { return Err(Error::new( fields.span(), - "Can not automatically infer format for types with more than 1 field", + "Cannot automatically infer format for types with more than 1 field", )); } @@ -480,7 +475,7 @@ impl<'a, 'b> State<'a, 'b> { Ok(ParseResult { arms: quote_spanned!(self.input.span()=> _ => #fmt,), - bounds: HashMap::new(), + bounds: HashMap::default(), requires_helper: false, }) } @@ -504,7 +499,7 @@ impl<'a, 'b> State<'a, 'b> { let fmt = fmt?; Ok(ParseResult { arms: quote_spanned!(self.input.span()=> #fmt), - bounds: HashMap::new(), + bounds: HashMap::default(), requires_helper: true, }) } @@ -558,14 +553,14 @@ impl<'a, 'b> State<'a, 'b> { self.find_meta(&self.input.attrs, "fmt")?.ok_or_else(|| { Error::new( self.input.span(), - "Can not automatically infer format for unions", + "Cannot automatically infer format for unions", ) })?; let fmt = self.parse_meta_fmt(&meta, false)?.0; Ok(ParseResult { arms: quote_spanned!(self.input.span()=> _ => #fmt,), - bounds: HashMap::new(), + bounds: HashMap::default(), requires_helper: false, }) } @@ -613,29 +608,30 @@ impl<'a, 'b> State<'a, 'b> { meta: &syn::Meta, ) -> HashMap> { if self.type_params.is_empty() { - return HashMap::new(); + return HashMap::default(); } let fields_type_params: HashMap = fields .iter() .enumerate() .filter_map(|(i, field)| { - self.get_type_param(&field.ty).map(|ty| { - ( - field - .ident - .clone() - .unwrap_or_else(|| { - Ident::new(&format!("_{}", i), Span::call_site()) - }) - .into(), - ty, - ) - }) + utils::get_if_type_parameter_used_in_type(&self.type_params, &field.ty) + .map(|ty| { + ( + field + .ident + .clone() + .unwrap_or_else(|| { + Ident::new(&format!("_{}", i), Span::call_site()) + }) + .into(), + ty, + ) + }) }) .collect(); if fields_type_params.is_empty() { - return HashMap::new(); + return HashMap::default(); } let list = match meta { @@ -658,7 +654,7 @@ impl<'a, 'b> State<'a, 'b> { }) .collect(); if fmt_args.is_empty() { - return HashMap::new(); + return HashMap::default(); } let fmt_string = match &list.nested[0] { syn::NestedMeta::Meta(syn::Meta::NameValue(syn::MetaNameValue { @@ -679,13 +675,13 @@ impl<'a, 'b> State<'a, 'b> { }; Placeholder::parse_fmt_string(&fmt_string).into_iter().fold( - HashMap::new(), + HashMap::default(), |mut bounds, pl| { if let Some(arg) = fmt_args.get(&pl.position) { if fields_type_params.contains_key(arg) { bounds .entry(fields_type_params[arg].clone()) - .or_insert_with(HashSet::new) + .or_insert_with(HashSet::default) .insert(trait_name_to_trait_bound(pl.trait_name)); } } @@ -698,81 +694,31 @@ impl<'a, 'b> State<'a, 'b> { fields: &syn::Fields, ) -> HashMap> { if self.type_params.is_empty() { - return HashMap::new(); + return HashMap::default(); } if let syn::Fields::Unit = fields { - return HashMap::new(); + return HashMap::default(); } // infer_fmt() uses only first field. fields .iter() .take(1) .filter_map(|field| { - self.get_type_param(&field.ty).map(|ty| { - ( - ty, - [trait_name_to_trait_bound(attribute_name_to_trait_name( - self.trait_attr, - ))] - .iter() - .cloned() - .collect(), - ) - }) + utils::get_if_type_parameter_used_in_type(&self.type_params, &field.ty) + .map(|ty| { + ( + ty, + [trait_name_to_trait_bound(attribute_name_to_trait_name( + self.trait_attr, + ))] + .iter() + .cloned() + .collect(), + ) + }) }) .collect() } - fn get_type_param(&self, ty: &syn::Type) -> Option { - if self.has_type_param_in(ty) { - match ty { - syn::Type::Reference(syn::TypeReference { elem: ty, .. }) => { - Some(ty.deref().clone()) - } - ty => Some(ty.clone()), - } - } else { - None - } - } - fn has_type_param_in(&self, ty: &syn::Type) -> bool { - match ty { - syn::Type::Path(ty) => { - if let Some(qself) = &ty.qself { - if self.has_type_param_in(&qself.ty) { - return true; - } - } - - if let Some(segment) = ty.path.segments.first() { - if self.type_params.contains(&segment.ident) { - return true; - } - } - - ty.path.segments.iter().any(|segment| { - if let syn::PathArguments::AngleBracketed(arguments) = - &segment.arguments - { - arguments.args.iter().any(|argument| match argument { - syn::GenericArgument::Type(ty) => { - self.has_type_param_in(ty) - } - syn::GenericArgument::Constraint(constraint) => { - self.type_params.contains(&constraint.ident) - } - _ => false, - }) - } else { - false - } - }) - } - - syn::Type::Reference(ty) => self.has_type_param_in(&ty.elem), - - _ => false, - } - } } /// Representation of formatting placeholder. diff --git a/third_party/rust/derive_more/src/error.rs b/third_party/rust/derive_more/src/error.rs new file mode 100644 index 000000000000..5235af8bac82 --- /dev/null +++ b/third_party/rust/derive_more/src/error.rs @@ -0,0 +1,437 @@ +use proc_macro2::TokenStream; +use quote::quote; +use syn::{spanned::Spanned as _, Error, Result}; + +use crate::utils::{ + self, AttrParams, DeriveType, FullMetaInfo, HashSet, MetaInfo, MultiFieldData, + State, +}; + +pub fn expand( + input: &syn::DeriveInput, + trait_name: &'static str, +) -> Result { + let syn::DeriveInput { + ident, generics, .. + } = input; + + let state = State::with_attr_params( + input, + trait_name, + quote!(::std::error), + trait_name.to_lowercase(), + allowed_attr_params(), + )?; + + let type_params: HashSet<_> = generics + .params + .iter() + .filter_map(|generic| match generic { + syn::GenericParam::Type(ty) => Some(ty.ident.clone()), + _ => None, + }) + .collect(); + + let (bounds, source, backtrace) = match state.derive_type { + DeriveType::Named | DeriveType::Unnamed => render_struct(&type_params, &state)?, + DeriveType::Enum => render_enum(&type_params, &state)?, + }; + + let source = source.map(|source| { + quote! { + fn source(&self) -> Option<&(dyn ::std::error::Error + 'static)> { + #source + } + } + }); + + let backtrace = backtrace.map(|backtrace| { + quote! { + fn backtrace(&self) -> Option<&::std::backtrace::Backtrace> { + #backtrace + } + } + }); + + let mut generics = generics.clone(); + + if !type_params.is_empty() { + let generic_parameters = generics.params.iter(); + generics = utils::add_extra_where_clauses( + &generics, + quote! { + where + #ident<#(#generic_parameters),*>: ::std::fmt::Debug + ::std::fmt::Display + }, + ); + } + + if !bounds.is_empty() { + let bounds = bounds.iter(); + generics = utils::add_extra_where_clauses( + &generics, + quote! { + where + #(#bounds: ::std::fmt::Debug + ::std::fmt::Display + ::std::error::Error + 'static),* + }, + ); + } + + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + let render = quote! { + impl#impl_generics ::std::error::Error for #ident#ty_generics #where_clause { + #source + #backtrace + } + }; + + Ok(render) +} + +fn render_struct( + type_params: &HashSet, + state: &State, +) -> Result<(HashSet, Option, Option)> { + let parsed_fields = parse_fields(&type_params, &state)?; + + let source = parsed_fields.render_source_as_struct(); + let backtrace = parsed_fields.render_backtrace_as_struct(); + + Ok((parsed_fields.bounds, source, backtrace)) +} + +fn render_enum( + type_params: &HashSet, + state: &State, +) -> Result<(HashSet, Option, Option)> { + let mut bounds = HashSet::default(); + let mut source_match_arms = Vec::new(); + let mut backtrace_match_arms = Vec::new(); + + for variant in state.enabled_variant_data().variants { + let mut default_info = FullMetaInfo::default(); + default_info.enabled = true; + + let state = State::from_variant( + state.input, + state.trait_name, + state.trait_module.clone(), + state.trait_attr.clone(), + allowed_attr_params(), + variant, + default_info, + )?; + + let parsed_fields = parse_fields(&type_params, &state)?; + + if let Some(expr) = parsed_fields.render_source_as_enum_variant_match_arm() { + source_match_arms.push(expr); + } + + if let Some(expr) = parsed_fields.render_backtrace_as_enum_variant_match_arm() { + backtrace_match_arms.push(expr); + } + + bounds.extend(parsed_fields.bounds.into_iter()); + } + + let render = |match_arms: &mut Vec| { + if !match_arms.is_empty() && match_arms.len() < state.variants.len() { + match_arms.push(quote!(_ => None)); + } + + if !match_arms.is_empty() { + let expr = quote! { + match self { + #(#match_arms),* + } + }; + + Some(expr) + } else { + None + } + }; + + let source = render(&mut source_match_arms); + let backtrace = render(&mut backtrace_match_arms); + + Ok((bounds, source, backtrace)) +} + +fn allowed_attr_params() -> AttrParams { + AttrParams { + enum_: vec!["ignore"], + struct_: vec!["ignore"], + variant: vec!["ignore"], + field: vec!["ignore", "source", "backtrace"], + } +} + +struct ParsedFields<'input, 'state> { + data: MultiFieldData<'input, 'state>, + source: Option, + backtrace: Option, + bounds: HashSet, +} + +impl<'input, 'state> ParsedFields<'input, 'state> { + fn new(data: MultiFieldData<'input, 'state>) -> Self { + Self { + data, + source: None, + backtrace: None, + bounds: HashSet::default(), + } + } +} + +impl<'input, 'state> ParsedFields<'input, 'state> { + fn render_source_as_struct(&self) -> Option { + let source = self.source?; + let ident = &self.data.members[source]; + Some(render_some(quote!(&#ident))) + } + + fn render_source_as_enum_variant_match_arm(&self) -> Option { + let source = self.source?; + let pattern = self.data.matcher(&[source], &[quote!(source)]); + let expr = render_some(quote!(source)); + Some(quote!(#pattern => #expr)) + } + + fn render_backtrace_as_struct(&self) -> Option { + let backtrace = self.backtrace?; + let backtrace_expr = &self.data.members[backtrace]; + Some(quote!(Some(&#backtrace_expr))) + } + + fn render_backtrace_as_enum_variant_match_arm(&self) -> Option { + let backtrace = self.backtrace?; + let pattern = self.data.matcher(&[backtrace], &[quote!(backtrace)]); + Some(quote!(#pattern => Some(backtrace))) + } +} + +fn render_some(expr: T) -> TokenStream +where + T: quote::ToTokens, +{ + quote!(Some(#expr as &(dyn ::std::error::Error + 'static))) +} + +fn parse_fields<'input, 'state>( + type_params: &HashSet, + state: &'state State<'input>, +) -> Result> { + let mut parsed_fields = match state.derive_type { + DeriveType::Named => { + parse_fields_impl(state, |attr, field, _| { + // Unwrapping is safe, cause fields in named struct + // always have an ident + let ident = field.ident.as_ref().unwrap(); + + match attr { + "source" => ident == "source", + "backtrace" => { + ident == "backtrace" + || is_type_path_ends_with_segment(&field.ty, "Backtrace") + } + _ => unreachable!(), + } + }) + } + + DeriveType::Unnamed => { + let mut parsed_fields = + parse_fields_impl(state, |attr, field, len| match attr { + "source" => { + len == 1 + && !is_type_path_ends_with_segment(&field.ty, "Backtrace") + } + "backtrace" => { + is_type_path_ends_with_segment(&field.ty, "Backtrace") + } + _ => unreachable!(), + })?; + + parsed_fields.source = parsed_fields + .source + .or_else(|| infer_source_field(&state.fields, &parsed_fields)); + + Ok(parsed_fields) + } + + _ => unreachable!(), + }?; + + if let Some(source) = parsed_fields.source { + add_bound_if_type_parameter_used_in_type( + &mut parsed_fields.bounds, + type_params, + &state.fields[source].ty, + ); + } + + Ok(parsed_fields) +} + +/// Checks if `ty` is [`syn::Type::Path`] and ends with segment matching `tail` +/// and doesn't contain any generic parameters. +fn is_type_path_ends_with_segment(ty: &syn::Type, tail: &str) -> bool { + let ty = match ty { + syn::Type::Path(ty) => ty, + _ => return false, + }; + + // Unwrapping is safe, cause 'syn::TypePath.path.segments' + // have to have at least one segment + let segment = ty.path.segments.last().unwrap(); + + match segment.arguments { + syn::PathArguments::None => (), + _ => return false, + }; + + segment.ident == tail +} + +fn infer_source_field( + fields: &[&syn::Field], + parsed_fields: &ParsedFields, +) -> Option { + // if we have exactly two fields + if fields.len() != 2 { + return None; + } + + // no source field was specified/inferred + if parsed_fields.source.is_some() { + return None; + } + + // but one of the fields was specified/inferred as backtrace field + if let Some(backtrace) = parsed_fields.backtrace { + // then infer *other field* as source field + let source = (backtrace + 1) % 2; + // unless it was explicitly marked as non-source + if parsed_fields.data.infos[source].info.source != Some(false) { + return Some(source); + } + } + + None +} + +fn parse_fields_impl<'input, 'state, P>( + state: &'state State<'input>, + is_valid_default_field_for_attr: P, +) -> Result> +where + P: Fn(&str, &syn::Field, usize) -> bool, +{ + let MultiFieldData { fields, infos, .. } = state.enabled_fields_data(); + + let iter = fields + .iter() + .zip(infos.iter().map(|info| &info.info)) + .enumerate() + .map(|(index, (field, info))| (index, *field, info)); + + let source = parse_field_impl( + &is_valid_default_field_for_attr, + state.fields.len(), + iter.clone(), + "source", + |info| info.source, + )?; + + let backtrace = parse_field_impl( + &is_valid_default_field_for_attr, + state.fields.len(), + iter.clone(), + "backtrace", + |info| info.backtrace, + )?; + + let mut parsed_fields = ParsedFields::new(state.enabled_fields_data()); + + if let Some((index, _, _)) = source { + parsed_fields.source = Some(index); + } + + if let Some((index, _, _)) = backtrace { + parsed_fields.backtrace = Some(index); + } + + Ok(parsed_fields) +} + +fn parse_field_impl<'a, P, V>( + is_valid_default_field_for_attr: &P, + len: usize, + iter: impl Iterator + Clone, + attr: &str, + value: V, +) -> Result> +where + P: Fn(&str, &syn::Field, usize) -> bool, + V: Fn(&MetaInfo) -> Option, +{ + let explicit_fields = iter.clone().filter(|(_, _, info)| match value(info) { + Some(true) => true, + _ => false, + }); + + let inferred_fields = iter.filter(|(_, field, info)| match value(info) { + None => is_valid_default_field_for_attr(attr, field, len), + _ => false, + }); + + let field = assert_iter_contains_zero_or_one_item( + explicit_fields, + &format!( + "Multiple `{}` attributes specified. \ + Single attribute per struct/enum variant allowed.", + attr + ), + )?; + + let field = match field { + field @ Some(_) => field, + None => assert_iter_contains_zero_or_one_item( + inferred_fields, + "Conflicting fields found. Consider specifying some \ + `#[error(...)]` attributes to resolve conflict.", + )?, + }; + + Ok(field) +} + +fn assert_iter_contains_zero_or_one_item<'a>( + mut iter: impl Iterator, + error_msg: &str, +) -> Result> { + let item = match iter.next() { + Some(item) => item, + None => return Ok(None), + }; + + if let Some((_, field, _)) = iter.next() { + return Err(Error::new(field.span(), error_msg)); + } + + Ok(Some(item)) +} + +fn add_bound_if_type_parameter_used_in_type( + bounds: &mut HashSet, + type_params: &HashSet, + ty: &syn::Type, +) { + if let Some(ty) = utils::get_if_type_parameter_used_in_type(type_params, ty) { + bounds.insert(ty); + } +} diff --git a/third_party/rust/derive_more/src/from.rs b/third_party/rust/derive_more/src/from.rs index 84cf619e3ddc..56ff5bcf9116 100644 --- a/third_party/rust/derive_more/src/from.rs +++ b/third_party/rust/derive_more/src/from.rs @@ -1,11 +1,14 @@ -use crate::utils::{ - add_where_clauses_for_new_ident, AttrParams, DeriveType, MultiFieldData, State, -}; +use std::iter; + use proc_macro2::{Span, TokenStream}; use quote::{quote, ToTokens}; -use std::collections::HashMap; use syn::{parse::Result, DeriveInput, Ident, Index}; +use crate::utils::{ + add_where_clauses_for_new_ident, AttrParams, DeriveType, HashMap, MultiFieldData, + RefType, State, +}; + /// Provides the hook to expand `#[derive(From)]` into an implementation of `From` pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result { let state = State::with_attr_params( @@ -15,8 +18,8 @@ pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result TokenStream { let multi_field_data = state.enabled_fields_data(); let MultiFieldData { fields, + variant_info, infos, input_type, trait_path, .. } = multi_field_data.clone(); - let mut new_generics = input.generics.clone(); - let sub_items: Vec<_> = infos - .iter() - .zip(fields.iter()) - .enumerate() - .map(|(i, (info, field))| { + let additional_types = variant_info.additional_types(RefType::No); + let mut impls = Vec::with_capacity(additional_types.len() + 1); + for explicit_type in iter::once(None).chain(additional_types.iter().map(Some)) { + let mut new_generics = input.generics.clone(); + + let mut initializers = Vec::with_capacity(infos.len()); + let mut from_types = Vec::with_capacity(infos.len()); + for (i, (info, field)) in infos.iter().zip(fields.iter()).enumerate() { let field_type = &field.ty; let variable = if fields.len() == 1 { - quote!(original) + quote! { original } } else { let tuple_index = Index::from(i); - quote!(original.#tuple_index) + quote! { original.#tuple_index } }; - if info.forward { + if let Some(type_) = explicit_type { + initializers.push(quote! { + <#field_type as #trait_path<#type_>>::from(#variable) + }); + from_types.push(quote! { #type_ }); + } else if info.forward { let type_param = &Ident::new(&format!("__FromT{}", i), Span::call_site()); - let sub_trait_path = quote!(#trait_path<#type_param>); + let sub_trait_path = quote! { #trait_path<#type_param> }; let type_where_clauses = quote! { where #field_type: #sub_trait_path }; new_generics = add_where_clauses_for_new_ident( - &input.generics, + &new_generics, &[field], type_param, type_where_clauses, true, ); - let casted_trait = quote!(<#field_type as #sub_trait_path>); - (quote!(#casted_trait::from(#variable)), quote!(#type_param)) + let casted_trait = quote! { <#field_type as #sub_trait_path> }; + initializers.push(quote! { #casted_trait::from(#variable) }); + from_types.push(quote! { #type_param }); } else { - (variable, quote!(#field_type)) - } - }) - .collect(); - let initializers: Vec<_> = sub_items.iter().map(|i| &i.0).collect(); - let from_types: Vec<_> = sub_items.iter().map(|i| &i.1).collect(); - - let body = multi_field_data.initializer(&initializers); - let (impl_generics, _, where_clause) = new_generics.split_for_impl(); - let (_, ty_generics, _) = input.generics.split_for_impl(); - - quote! { - impl#impl_generics #trait_path<(#(#from_types),*)> for - #input_type#ty_generics #where_clause { - - #[allow(unused_variables)] - #[inline] - fn from(original: (#(#from_types),*)) -> #input_type#ty_generics { - #body + initializers.push(variable); + from_types.push(quote! { #field_type }); } } + + let body = multi_field_data.initializer(&initializers); + let (impl_generics, _, where_clause) = new_generics.split_for_impl(); + let (_, ty_generics, _) = input.generics.split_for_impl(); + + impls.push(quote! { + #[automatically_derived] + impl#impl_generics #trait_path<(#(#from_types),*)> for + #input_type#ty_generics #where_clause { + + #[inline] + fn from(original: (#(#from_types),*)) -> #input_type#ty_generics { + #body + } + } + }); } + + quote! { #( #impls )* } } fn enum_from(input: &DeriveInput, state: State) -> TokenStream { let mut tokens = TokenStream::new(); - let mut variants_per_types = HashMap::new(); + let mut variants_per_types = HashMap::default(); for variant_state in state.enabled_variant_data().variant_states { let multi_field_data = variant_state.enabled_fields_data(); let MultiFieldData { field_types, .. } = multi_field_data.clone(); @@ -112,7 +125,7 @@ fn enum_from(input: &DeriveInput, state: State) -> TokenStream { .. } = multi_field_data.clone(); // If there would be a conflict on a empty tuple derive, ignore the - // variants that are not explicitely enabled or have explicitely enabled + // variants that are not explicitly enabled or have explicitly enabled // or disabled fields if field_types.is_empty() && variant_states.len() > 1 diff --git a/third_party/rust/derive_more/src/into.rs b/third_party/rust/derive_more/src/into.rs index bb77e2336a4e..239a438de0df 100644 --- a/third_party/rust/derive_more/src/into.rs +++ b/third_party/rust/derive_more/src/into.rs @@ -1,8 +1,11 @@ -use crate::utils::{add_extra_generic_param, AttrParams, MultiFieldData, State}; +use std::iter; + use proc_macro2::TokenStream; use quote::{quote, ToTokens}; use syn::{parse::Result, DeriveInput}; +use crate::utils::{add_extra_generic_param, AttrParams, MultiFieldData, State}; + /// Provides the hook to expand `#[derive(Into)]` into an implementation of `Into` pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result { let state = State::with_attr_params( @@ -13,7 +16,7 @@ pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result Result for - (#(#reference_with_lifetime #field_types),*) #where_clause { + let additional_types = variant_info.additional_types(ref_type); + for explicit_type in iter::once(None).chain(additional_types.iter().map(Some)) { + let into_types: Vec<_> = field_types + .iter() + .map(|field_type| { + // No, `.unwrap_or()` won't work here, because we use different types. + if let Some(type_) = explicit_type { + quote! { #reference_with_lifetime #type_ } + } else { + quote! { #reference_with_lifetime #field_type } + } + }) + .collect(); - #[allow(unused_variables)] - #[inline] - fn from(original: #reference_with_lifetime #input_type#ty_generics) -> (#(#reference_with_lifetime #field_types),*) { - (#(#reference original.#field_idents),*) + let initializers = field_idents.iter().map(|field_ident| { + if let Some(type_) = explicit_type { + quote! { <#reference #type_>::from(#reference original.#field_ident) } + } else { + quote! { #reference original.#field_ident } } - } - }; - into.to_tokens(&mut tokens); + }); + + (quote! { + #[automatically_derived] + impl#impl_generics ::core::convert::From<#reference_with_lifetime #input_type#ty_generics> for + (#(#into_types),*) #where_clause { + + #[inline] + fn from(original: #reference_with_lifetime #input_type#ty_generics) -> (#(#into_types),*) { + (#(#initializers),*) + } + } + }).to_tokens(&mut tokens); + } } Ok(tokens) } diff --git a/third_party/rust/derive_more/src/lib.rs b/third_party/rust/derive_more/src/lib.rs index 8ea93aa406c2..f9843a0db8a2 100644 --- a/third_party/rust/derive_more/src/lib.rs +++ b/third_party/rust/derive_more/src/lib.rs @@ -90,6 +90,11 @@ //! 1. [`Display`-like], contains `Display`, `Binary`, `Octal`, `LowerHex`, //! `UpperHex`, `LowerExp`, `UpperExp`, `Pointer` //! +//! ### Error-handling traits +//! These traits are used to define error-types. +//! +//! 1. [`Error`] +//! //! ### Operators //! //! These are traits that can be used for operator overloading. @@ -160,6 +165,8 @@ //! //! [`Display`-like]: https://jeltef.github.io/derive_more/derive_more/display.html //! +//! [`Error`]: https://jeltef.github.io/derive_more/derive_more/error.html +//! //! [`Index`]: https://jeltef.github.io/derive_more/derive_more/index_op.html //! [`Deref`]: https://jeltef.github.io/derive_more/derive_more/deref.html //! [`Not`-like]: https://jeltef.github.io/derive_more/derive_more/not.html @@ -173,11 +180,12 @@ //! //! [`Constructor`]: https://jeltef.github.io/derive_more/derive_more/constructor.html +// Suppress Clippy tips to use `matches!` macro, because minimal supported Rust version is 1.36.0. +// Remove this suppression once minimal supported Rust version is bumped up to 1.42.0 or above. +#![cfg_attr(nightly, allow(clippy::match_like_matches_macro))] #![recursion_limit = "128"] extern crate proc_macro; -use proc_macro2; -use syn; use proc_macro::TokenStream; use syn::parse::Error as ParseError; @@ -207,6 +215,8 @@ mod deref; mod deref_mut; #[cfg(feature = "display")] mod display; +#[cfg(feature = "error")] +mod error; #[cfg(feature = "from")] mod from; #[cfg(feature = "from_str")] @@ -352,6 +362,8 @@ create_derive!( create_derive!("sum", sum_like, Sum, sum_derive); create_derive!("sum", sum_like, Product, product_derive); +create_derive!("error", error, Error, error_derive, error); + create_derive!("from_str", from_str, FromStr, from_str_derive); create_derive!("display", display, Display, display_derive, display); diff --git a/third_party/rust/derive_more/src/mul_assign_like.rs b/third_party/rust/derive_more/src/mul_assign_like.rs index 544e4b75263c..eaba70daaf6b 100644 --- a/third_party/rust/derive_more/src/mul_assign_like.rs +++ b/third_party/rust/derive_more/src/mul_assign_like.rs @@ -56,7 +56,7 @@ pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result for #input_type#ty_generics #where_clause{ #[inline] - fn #method_ident(&mut self, rhs: #scalar_ident#ty_generics) { + fn #method_ident(&mut self, rhs: #scalar_ident) { #(#exprs; )* } diff --git a/third_party/rust/derive_more/src/parsing.rs b/third_party/rust/derive_more/src/parsing.rs index c3d09d162404..936293f5ff2c 100644 --- a/third_party/rust/derive_more/src/parsing.rs +++ b/third_party/rust/derive_more/src/parsing.rs @@ -654,9 +654,11 @@ fn __parse_format_spec<'input>( Matched(__pos, _) => { let __choice_res = { let __seq_res = { - let mut __repeat_pos = + let mut + __repeat_pos = __pos; - let mut __repeat_value = + let mut + __repeat_value = vec![]; loop { let __pos = @@ -717,7 +719,8 @@ fn __parse_format_spec<'input>( let __choice_res = { let mut __repeat_pos = __pos; - let mut __repeat_value = vec![]; + let mut + __repeat_value = vec![]; loop { let __pos = __repeat_pos ; let __step_res = diff --git a/third_party/rust/derive_more/src/try_into.rs b/third_party/rust/derive_more/src/try_into.rs index 66ff7a26e6fe..219337db5982 100644 --- a/third_party/rust/derive_more/src/try_into.rs +++ b/third_party/rust/derive_more/src/try_into.rs @@ -4,9 +4,10 @@ use crate::utils::{ }; use proc_macro2::TokenStream; use quote::{quote, ToTokens}; -use std::collections::HashMap; use syn::{DeriveInput, Result}; +use crate::utils::HashMap; + /// Provides the hook to expand `#[derive(TryInto)]` into an implementation of `TryInto` #[allow(clippy::cognitive_complexity)] pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result { @@ -26,7 +27,7 @@ pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result Self::Hasher { + Self::Hasher::default() + } +} + +pub type HashMap = std::collections::HashMap; +pub type HashSet = std::collections::HashSet; + +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] pub enum RefType { No, Ref, @@ -63,6 +76,15 @@ impl RefType { _ => true, } } + + pub fn from_attr_name(name: &str) -> Self { + match name { + "owned" => RefType::No, + "ref" => RefType::Ref, + "ref_mut" => RefType::Mut, + _ => panic!("'{}' is not a RefType", name), + } + } } pub fn numbered_vars(count: usize, prefix: &str) -> Vec { @@ -99,10 +121,9 @@ pub fn add_extra_type_param_bound_op_output<'a>( let mut generics = generics.clone(); for type_param in &mut generics.type_params_mut() { let type_ident = &type_param.ident; - let bound: TypeParamBound = parse_str( - "e!(::core::ops::#trait_ident).to_string(), - ) - .unwrap(); + let bound: TypeParamBound = parse_quote! { + ::core::ops::#trait_ident + }; type_param.bounds.push(bound) } @@ -121,7 +142,7 @@ pub fn add_extra_ty_param_bound<'a>( bound: &'a TokenStream, ) -> Generics { let mut generics = generics.clone(); - let bound: TypeParamBound = parse_str(&bound.to_string()).unwrap(); + let bound: TypeParamBound = parse_quote! { #bound }; for type_param in &mut generics.type_params_mut() { type_param.bounds.push(bound.clone()) } @@ -154,7 +175,7 @@ pub fn add_extra_generic_param( generics: &Generics, generic_param: TokenStream, ) -> Generics { - let generic_param: GenericParam = parse_str(&generic_param.to_string()).unwrap(); + let generic_param: GenericParam = parse_quote! { #generic_param }; let mut generics = generics.clone(); generics.params.push(generic_param); @@ -165,8 +186,7 @@ pub fn add_extra_where_clauses( generics: &Generics, type_where_clauses: TokenStream, ) -> Generics { - let mut type_where_clauses: WhereClause = - parse_str(&type_where_clauses.to_string()).unwrap(); + let mut type_where_clauses: WhereClause = parse_quote! { #type_where_clauses }; let mut new_generics = generics.clone(); if let Some(old_where) = new_generics.where_clause { type_where_clauses.predicates.extend(old_where.predicates) @@ -210,7 +230,7 @@ fn panic_one_field(trait_name: &str, trait_attr: &str) -> ! { )) } -#[derive(PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum DeriveType { Unnamed, Named, @@ -261,6 +281,10 @@ impl AttrParams { field: vec![], } } + + pub fn ignore_and_forward() -> AttrParams { + AttrParams::new(vec!["ignore", "forward"]) + } } impl<'input> State<'input> { @@ -270,12 +294,13 @@ impl<'input> State<'input> { trait_module: TokenStream, trait_attr: String, ) -> Result> { - State::with_attr_params( + State::new_impl( input, trait_name, trait_module, trait_attr, AttrParams::default(), + true, ) } @@ -285,12 +310,13 @@ impl<'input> State<'input> { trait_module: TokenStream, trait_attr: String, ) -> Result> { - State::with_attr_params( + State::new_impl( input, trait_name, trait_module, trait_attr, AttrParams::new(vec!["ignore"]), + true, ) } @@ -300,12 +326,13 @@ impl<'input> State<'input> { trait_module: TokenStream, trait_attr: String, ) -> Result> { - State::with_attr_params( + State::new_impl( input, trait_name, trait_module, trait_attr, AttrParams::new(vec!["ignore", "forward"]), + true, ) } @@ -315,12 +342,13 @@ impl<'input> State<'input> { trait_module: TokenStream, trait_attr: String, ) -> Result> { - State::with_attr_params( + State::new_impl( input, trait_name, trait_module, trait_attr, AttrParams::new(vec!["ignore", "owned", "ref", "ref_mut"]), + true, ) } @@ -330,6 +358,42 @@ impl<'input> State<'input> { trait_module: TokenStream, trait_attr: String, allowed_attr_params: AttrParams, + ) -> Result> { + State::new_impl( + input, + trait_name, + trait_module, + trait_attr, + allowed_attr_params, + true, + ) + } + + pub fn with_type_bound<'arg_input>( + input: &'arg_input DeriveInput, + trait_name: &'static str, + trait_module: TokenStream, + trait_attr: String, + allowed_attr_params: AttrParams, + add_type_bound: bool, + ) -> Result> { + Self::new_impl( + input, + trait_name, + trait_module, + trait_attr, + allowed_attr_params, + add_type_bound, + ) + } + + fn new_impl<'arg_input>( + input: &'arg_input DeriveInput, + trait_name: &'static str, + trait_module: TokenStream, + trait_attr: String, + allowed_attr_params: AttrParams, + add_type_bound: bool, ) -> Result> { let trait_name = trait_name.trim_end_matches("ToInner"); let trait_ident = Ident::new(trait_name, Span::call_site()); @@ -352,7 +416,7 @@ impl<'input> State<'input> { data_enum.variants.iter().collect(), ), Data::Union(_) => { - panic!(format!("can not derive({}) for union", trait_name)) + panic!(format!("cannot derive({}) for union", trait_name)) } }; let attrs: Vec<_> = if derive_type == DeriveType::Enum { @@ -380,14 +444,32 @@ impl<'input> State<'input> { .filter_map(|info| info.enabled.map(|_| info)) .next(); - let defaults = struct_meta_info.to_full(FullMetaInfo { - // Default to enabled true, except when first attribute has explicit - // enabling - enabled: first_match.map_or(true, |info| !info.enabled.unwrap()), + // Default to enabled true, except when first attribute has explicit + // enabling. + // + // Except for derive Error. + // + // The way `else` case works is that if any field have any valid + // attribute specified, then all fields without any attributes + // specified are filtered out from `State::enabled_fields`. + // + // However, derive Error *infers* fields and there are cases when + // one of the fields may have an attribute specified, but another field + // would be inferred. So, for derive Error macro we default enabled + // to true unconditionally (i.e., even if some fields have attributes + // specified). + let default_enabled = if trait_name == "Error" { + true + } else { + first_match.map_or(true, |info| !info.enabled.unwrap()) + }; + + let defaults = struct_meta_info.into_full(FullMetaInfo { + enabled: default_enabled, forward: false, // Default to owned true, except when first attribute has one of owned, // ref or ref_mut - // - not a single attibute means default true + // - not a single attribute means default true // - an attribute, but non of owned, ref or ref_mut means default true // - an attribute, and owned, ref or ref_mut means default false owned: first_match.map_or(true, |info| { @@ -399,14 +481,14 @@ impl<'input> State<'input> { }); let full_meta_infos: Vec<_> = meta_infos - .iter() - .map(|info| info.to_full(defaults)) + .into_iter() + .map(|info| info.into_full(defaults.clone())) .collect(); let variant_states: Result> = if derive_type == DeriveType::Enum { variants .iter() - .zip(full_meta_infos.iter().copied()) + .zip(full_meta_infos.iter().cloned()) .map(|(variant, info)| { State::from_variant( input, @@ -422,7 +504,12 @@ impl<'input> State<'input> { } else { Ok(vec![]) }; - let generics = add_extra_ty_param_bound(&input.generics, &trait_path); + + let generics = if add_type_bound { + add_extra_ty_param_bound(&input.generics, &trait_path) + } else { + input.generics.clone() + }; Ok(State { input, @@ -474,8 +561,8 @@ impl<'input> State<'input> { .collect(); let meta_infos = meta_infos?; let full_meta_infos: Vec<_> = meta_infos - .iter() - .map(|info| info.to_full(default_info)) + .into_iter() + .map(|info| info.into_full(default_info.clone())) .collect(); let generics = add_extra_ty_param_bound(&input.generics, &trait_path); @@ -519,7 +606,7 @@ impl<'input> State<'input> { field: data.fields[0], field_type: data.field_types[0], member: data.members[0].clone(), - info: data.infos[0], + info: data.infos[0].clone(), field_ident: data.field_idents[0].clone(), trait_path: data.trait_path, trait_path_with_params: data.trait_path_with_params.clone(), @@ -533,7 +620,7 @@ impl<'input> State<'input> { pub fn enabled_fields_data<'state>(&'state self) -> MultiFieldData<'input, 'state> { if self.derive_type == DeriveType::Enum { - panic!(format!("can not derive({}) for enum", self.trait_name)) + panic!(format!("cannot derive({}) for enum", self.trait_name)) } let fields = self.enabled_fields(); let field_idents = self.enabled_fields_idents(); @@ -568,7 +655,7 @@ impl<'input> State<'input> { input_type, variant_type, variant_name, - variant_info: self.default_info, + variant_info: self.default_info.clone(), fields, field_types, field_indexes, @@ -675,7 +762,7 @@ impl<'input> State<'input> { self.full_meta_infos .iter() .filter(|info| info.enabled) - .copied() + .cloned() .collect() } } @@ -773,25 +860,20 @@ impl<'input, 'state> SingleFieldData<'input, 'state> { fn get_meta_info( trait_attr: &str, attrs: &[Attribute], - allowed_attr_params: &[&'static str], + allowed_attr_params: &[&str], ) -> Result { let mut it = attrs .iter() .filter_map(|m| m.parse_meta().ok()) .filter(|m| { - if let Some(ident) = m.path().segments.first().map(|p| &p.ident) { - ident == trait_attr - } else { - false - } + m.path() + .segments + .first() + .map(|p| p.ident == trait_attr) + .unwrap_or_default() }); - let mut info = MetaInfo { - enabled: None, - forward: None, - owned: None, - ref_: None, - ref_mut: None, - }; + + let mut info = MetaInfo::default(); let meta = if let Some(meta) = it.next() { meta @@ -805,81 +887,222 @@ fn get_meta_info( info.enabled = Some(true); - if let Some(meta2) = it.next() { + if let Some(another_meta) = it.next() { return Err(Error::new( - meta2.span(), + another_meta.span(), "Only a single attribute is allowed", )); } + let list = match meta.clone() { Meta::Path(_) => { if allowed_attr_params.contains(&"ignore") { return Ok(info); } else { - return Err(Error::new(meta.span(), format!("Empty attribute is not allowed, add one of the following parameters: {}", - allowed_attr_params.join(", ") - ))); + return Err(Error::new( + meta.span(), + format!( + "Empty attribute is not allowed, add one of the following parameters: {}", + allowed_attr_params.join(", "), + ), + )); } } Meta::List(list) => list, - _ => { - return Err(Error::new(meta.span(), "Attribute format not supported1")); - } - }; - for element in list.nested.into_iter() { - let nested_meta = if let NestedMeta::Meta(meta) = element { - meta - } else { - return Err(Error::new(meta.span(), "Attribute format not supported3")); - }; - if let Meta::Path(_) = nested_meta { - } else { - return Err(Error::new(meta.span(), "Attribute format not supported4")); - } - let ident = if let Some(ident) = - nested_meta.path().segments.first().map(|p| &p.ident) - { - ident - } else { - return Err(Error::new(meta.span(), "Attribute format not supported5")); - }; - - let str_ident: &str = &ident.to_string(); - if !allowed_attr_params.contains(&str_ident) { + Meta::NameValue(val) => { return Err(Error::new( - ident.span(), - format!( - "Attribute parameter not supported. Supported attribute parameters are: {}", - allowed_attr_params.join(", ") - ), + val.span(), + "Attribute doesn't support name-value format here", )); } + }; + + parse_punctuated_nested_meta(&mut info, &list.nested, allowed_attr_params, None)?; - match str_ident { - "ignore" => { - info.enabled = Some(false); - } - "forward" => { - info.forward = Some(true); - } - "owned" => { - info.owned = Some(true); - } - "ref" => { - info.ref_ = Some(true); - } - "ref_mut" => { - info.ref_mut = Some(true); - } - _ => { - return Err(Error::new(meta.span(), "Attribute format not supported7")); - } - } - } Ok(info) } -#[derive(Copy, Clone, Debug, Default)] +fn parse_punctuated_nested_meta( + info: &mut MetaInfo, + meta: &Punctuated, + allowed_attr_params: &[&str], + wrapper_name: Option<&str>, +) -> Result<()> { + for meta in meta.iter() { + let meta = match meta { + NestedMeta::Meta(meta) => meta, + NestedMeta::Lit(lit) => { + return Err(Error::new( + lit.span(), + "Attribute doesn't support literals here", + )) + } + }; + + match meta { + Meta::List(list) if list.path.is_ident("not") => { + if wrapper_name.is_some() { + // Only single top-level `not` attribute is allowed. + return Err(Error::new( + list.span(), + "Attribute doesn't support multiple multiple or nested `not` parameters", + )); + } + parse_punctuated_nested_meta( + info, + &list.nested, + allowed_attr_params, + Some("not"), + )?; + } + + Meta::List(list) => { + let path = &list.path; + if !allowed_attr_params.iter().any(|param| path.is_ident(param)) { + return Err(Error::new( + meta.span(), + format!( + "Attribute nested parameter not supported. \ + Supported attribute parameters are: {}", + allowed_attr_params.join(", "), + ), + )); + } + + let mut parse_nested = true; + + let attr_name = path.get_ident().unwrap().to_string(); + match (wrapper_name, attr_name.as_str()) { + (None, "owned") => info.owned = Some(true), + (None, "ref") => info.ref_ = Some(true), + (None, "ref_mut") => info.ref_mut = Some(true), + + #[cfg(any(feature = "from", feature = "into"))] + (None, "types") + | (Some("owned"), "types") + | (Some("ref"), "types") + | (Some("ref_mut"), "types") => { + parse_nested = false; + for meta in &list.nested { + match meta { + NestedMeta::Meta(meta) => { + let path = if let Meta::Path(p) = meta { + p + } else { + return Err(Error::new( + meta.span(), + format!( + "Attribute doesn't support type {}", + quote! { #meta }, + ), + )); + }; + + for ref_type in wrapper_name + .map(|n| vec![RefType::from_attr_name(n)]) + .unwrap_or_else(|| { + vec![ + RefType::No, + RefType::Ref, + RefType::Mut, + ] + }) + { + if info + .types + .entry(ref_type) + .or_default() + .replace(path.clone()) + .is_some() + { + return Err(Error::new( + path.span(), + format!( + "Duplicate type `{}` specified", + quote! { #path }, + ), + )); + } + } + } + NestedMeta::Lit(lit) => return Err(Error::new( + lit.span(), + "Attribute doesn't support nested literals here", + )), + } + } + } + + _ => { + return Err(Error::new( + list.span(), + format!( + "Attribute doesn't support nested parameter `{}` here", + quote! { #path }, + ), + )) + } + }; + + if parse_nested { + parse_punctuated_nested_meta( + info, + &list.nested, + allowed_attr_params, + Some(&attr_name), + )?; + } + } + + Meta::Path(path) => { + if !allowed_attr_params.iter().any(|param| path.is_ident(param)) { + return Err(Error::new( + meta.span(), + format!( + "Attribute parameter not supported. \ + Supported attribute parameters are: {}", + allowed_attr_params.join(", "), + ), + )); + } + + let attr_name = path.get_ident().unwrap().to_string(); + match (wrapper_name, attr_name.as_str()) { + (None, "ignore") => info.enabled = Some(false), + (None, "forward") => info.forward = Some(true), + (Some("not"), "forward") => info.forward = Some(false), + (None, "owned") => info.owned = Some(true), + (None, "ref") => info.ref_ = Some(true), + (None, "ref_mut") => info.ref_mut = Some(true), + (None, "source") => info.source = Some(true), + (Some("not"), "source") => info.source = Some(false), + (None, "backtrace") => info.backtrace = Some(true), + (Some("not"), "backtrace") => info.backtrace = Some(false), + _ => { + return Err(Error::new( + path.span(), + format!( + "Attribute doesn't support parameter `{}` here", + quote! { #path } + ), + )) + } + } + } + + Meta::NameValue(val) => { + return Err(Error::new( + val.span(), + "Attribute doesn't support name-value parameters here", + )) + } + } + } + + Ok(()) +} + +#[derive(Clone, Debug, Default)] pub struct FullMetaInfo { pub enabled: bool, pub forward: bool, @@ -889,31 +1112,34 @@ pub struct FullMetaInfo { pub info: MetaInfo, } -#[derive(Copy, Clone, Debug, Default)] +#[derive(Clone, Debug, Default)] pub struct MetaInfo { pub enabled: Option, pub forward: Option, pub owned: Option, pub ref_: Option, pub ref_mut: Option, + pub source: Option, + pub backtrace: Option, + #[cfg(any(feature = "from", feature = "into"))] + pub types: HashMap>, } impl MetaInfo { - fn to_full(self, defaults: FullMetaInfo) -> FullMetaInfo { - let info = self; + fn into_full(self, defaults: FullMetaInfo) -> FullMetaInfo { FullMetaInfo { enabled: self.enabled.unwrap_or(defaults.enabled), forward: self.forward.unwrap_or(defaults.forward), owned: self.owned.unwrap_or(defaults.owned), ref_: self.ref_.unwrap_or(defaults.ref_), ref_mut: self.ref_mut.unwrap_or(defaults.ref_mut), - info, + info: self, } } } impl FullMetaInfo { - pub fn ref_types(self) -> Vec { + pub fn ref_types(&self) -> Vec { let mut ref_types = vec![]; if self.owned { ref_types.push(RefType::No); @@ -926,4 +1152,70 @@ impl FullMetaInfo { } ref_types } + + #[cfg(any(feature = "from", feature = "into"))] + pub fn additional_types(&self, ref_type: RefType) -> HashSet { + self.info.types.get(&ref_type).cloned().unwrap_or_default() + } +} + +pub fn get_if_type_parameter_used_in_type( + type_parameters: &HashSet, + ty: &syn::Type, +) -> Option { + if is_type_parameter_used_in_type(type_parameters, ty) { + match ty { + syn::Type::Reference(syn::TypeReference { elem: ty, .. }) => { + Some((&**ty).clone()) + } + ty => Some(ty.clone()), + } + } else { + None + } +} + +pub fn is_type_parameter_used_in_type( + type_parameters: &HashSet, + ty: &syn::Type, +) -> bool { + match ty { + syn::Type::Path(ty) => { + if let Some(qself) = &ty.qself { + if is_type_parameter_used_in_type(type_parameters, &qself.ty) { + return true; + } + } + + if let Some(segment) = ty.path.segments.first() { + if type_parameters.contains(&segment.ident) { + return true; + } + } + + ty.path.segments.iter().any(|segment| { + if let syn::PathArguments::AngleBracketed(arguments) = + &segment.arguments + { + arguments.args.iter().any(|argument| match argument { + syn::GenericArgument::Type(ty) => { + is_type_parameter_used_in_type(type_parameters, ty) + } + syn::GenericArgument::Constraint(constraint) => { + type_parameters.contains(&constraint.ident) + } + _ => false, + }) + } else { + false + } + }) + } + + syn::Type::Reference(ty) => { + is_type_parameter_used_in_type(type_parameters, &ty.elem) + } + + _ => false, + } } diff --git a/third_party/rust/derive_more/tests/add.rs b/third_party/rust/derive_more/tests/add.rs new file mode 100644 index 000000000000..f9ec5a77f39e --- /dev/null +++ b/third_party/rust/derive_more/tests/add.rs @@ -0,0 +1,23 @@ +#![allow(dead_code)] +#[macro_use] +extern crate derive_more; + +#[derive(Add)] +struct MyInts(i32, i32); + +#[derive(Add)] +struct Point2D { + x: i32, + y: i32, +} + +#[derive(Add)] +enum MixedInts { + SmallInt(i32), + BigInt(i64), + TwoSmallInts(i32, i32), + NamedSmallInts { x: i32, y: i32 }, + UnsignedOne(u32), + UnsignedTwo(u32), + Unit, +} diff --git a/third_party/rust/derive_more/tests/add_assign.rs b/third_party/rust/derive_more/tests/add_assign.rs new file mode 100644 index 000000000000..32681787ce14 --- /dev/null +++ b/third_party/rust/derive_more/tests/add_assign.rs @@ -0,0 +1,12 @@ +#![allow(dead_code)] +#[macro_use] +extern crate derive_more; + +#[derive(AddAssign)] +struct MyInts(i32, i32); + +#[derive(AddAssign)] +struct Point2D { + x: i32, + y: i32, +} diff --git a/third_party/rust/derive_more/tests/as_mut.rs b/third_party/rust/derive_more/tests/as_mut.rs new file mode 100644 index 000000000000..e074f8b02f90 --- /dev/null +++ b/third_party/rust/derive_more/tests/as_mut.rs @@ -0,0 +1,108 @@ +#![allow(dead_code)] + +#[macro_use] +extern crate derive_more; + +use std::path::PathBuf; +use std::ptr; + +#[derive(AsMut)] +struct SingleFieldTuple(String); + +#[test] +fn single_field_tuple() { + let mut item = SingleFieldTuple(String::from("test")); + + assert!(ptr::eq(&mut item.0, item.as_mut())); +} + +#[derive(AsMut)] +#[as_mut(forward)] +struct SingleFieldForward(Vec); + +#[test] +fn single_field_forward() { + let mut item = SingleFieldForward(vec![]); + let _: &mut [i32] = (&mut item).as_mut(); +} + +#[derive(AsMut)] +struct SingleFieldStruct { + first: String, +} + +#[test] +fn single_field_struct() { + let mut item = SingleFieldStruct { + first: String::from("test"), + }; + + assert!(ptr::eq(&mut item.first, item.as_mut())); +} + +#[derive(AsMut)] +struct MultiFieldTuple(#[as_mut] String, #[as_mut] PathBuf, Vec); + +#[test] +fn multi_field_tuple() { + let mut item = MultiFieldTuple(String::from("test"), PathBuf::new(), vec![]); + + assert!(ptr::eq(&mut item.0, item.as_mut())); + assert!(ptr::eq(&mut item.1, item.as_mut())); +} + +#[derive(AsMut)] +struct MultiFieldStruct { + #[as_mut] + first: String, + #[as_mut] + second: PathBuf, + third: Vec, +} + +#[test] +fn multi_field_struct() { + let mut item = MultiFieldStruct { + first: String::from("test"), + second: PathBuf::new(), + third: vec![], + }; + + assert!(ptr::eq(&mut item.first, item.as_mut())); + assert!(ptr::eq(&mut item.second, item.as_mut())); +} + +#[derive(AsMut)] +struct SingleFieldGenericStruct { + first: T, +} + +#[test] +fn single_field_generic_struct() { + let mut item = SingleFieldGenericStruct { + first: String::from("test"), + }; + + assert!(ptr::eq(&mut item.first, item.as_mut())); +} + +#[derive(AsMut)] +struct MultiFieldGenericStruct { + #[as_mut] + first: Vec, + #[as_mut] + second: PathBuf, + third: Vec, +} + +#[test] +fn multi_field_generic_struct() { + let mut item = MultiFieldGenericStruct { + first: b"test".to_vec(), + second: PathBuf::new(), + third: vec![], + }; + + assert!(ptr::eq(&mut item.first, item.as_mut())); + assert!(ptr::eq(&mut item.second, item.as_mut())); +} diff --git a/third_party/rust/derive_more/tests/as_ref.rs b/third_party/rust/derive_more/tests/as_ref.rs new file mode 100644 index 000000000000..1e355d28fb48 --- /dev/null +++ b/third_party/rust/derive_more/tests/as_ref.rs @@ -0,0 +1,108 @@ +#![allow(dead_code)] + +#[macro_use] +extern crate derive_more; + +use std::path::PathBuf; +use std::ptr; + +#[derive(AsRef)] +struct SingleFieldTuple(String); + +#[test] +fn single_field_tuple() { + let item = SingleFieldTuple(String::from("test")); + + assert!(ptr::eq(&item.0, item.as_ref())); +} + +#[derive(AsRef)] +#[as_ref(forward)] +struct SingleFieldForward(Vec); + +#[test] +fn single_field_forward() { + let item = SingleFieldForward(vec![]); + let _: &[i32] = (&item).as_ref(); +} + +#[derive(AsRef)] +struct SingleFieldStruct { + first: String, +} + +#[test] +fn single_field_struct() { + let item = SingleFieldStruct { + first: String::from("test"), + }; + + assert!(ptr::eq(&item.first, item.as_ref())); +} + +#[derive(AsRef)] +struct MultiFieldTuple(#[as_ref] String, #[as_ref] PathBuf, Vec); + +#[test] +fn multi_field_tuple() { + let item = MultiFieldTuple(String::from("test"), PathBuf::new(), vec![]); + + assert!(ptr::eq(&item.0, item.as_ref())); + assert!(ptr::eq(&item.1, item.as_ref())); +} + +#[derive(AsRef)] +struct MultiFieldStruct { + #[as_ref] + first: String, + #[as_ref] + second: PathBuf, + third: Vec, +} + +#[test] +fn multi_field_struct() { + let item = MultiFieldStruct { + first: String::from("test"), + second: PathBuf::new(), + third: vec![], + }; + + assert!(ptr::eq(&item.first, item.as_ref())); + assert!(ptr::eq(&item.second, item.as_ref())); +} + +#[derive(AsRef)] +struct SingleFieldGenericStruct { + first: T, +} + +#[test] +fn single_field_generic_struct() { + let item = SingleFieldGenericStruct { + first: String::from("test"), + }; + + assert!(ptr::eq(&item.first, item.as_ref())); +} + +#[derive(AsRef)] +struct MultiFieldGenericStruct { + #[as_ref] + first: Vec, + #[as_ref] + second: [U; 2], + third: Vec, +} + +#[test] +fn multi_field_generic_struct() { + let item = MultiFieldGenericStruct { + first: b"test".to_vec(), + second: [0i32, 1i32], + third: vec![], + }; + + assert!(ptr::eq(&item.first, item.as_ref())); + assert!(ptr::eq(&item.second, item.as_ref())); +} diff --git a/third_party/rust/derive_more/tests/boats_display_derive.rs b/third_party/rust/derive_more/tests/boats_display_derive.rs new file mode 100644 index 000000000000..b64f75df84c9 --- /dev/null +++ b/third_party/rust/derive_more/tests/boats_display_derive.rs @@ -0,0 +1,57 @@ +// The following code is from https://github.com/withoutboats/display_derive/blob/232a32ee19e262aacbd2c93be5b4ce9e89a5fc30/tests/tests.rs +// Written by without boats originally + +#[macro_use] +extern crate derive_more; + +#[derive(Display)] +#[display(fmt = "An error has occurred.")] +struct UnitError; + +#[test] +fn unit_struct() { + let s = format!("{}", UnitError); + assert_eq!(&s[..], "An error has occurred."); +} + +#[derive(Display)] +#[display(fmt = "Error code: {}", code)] +struct RecordError { + code: u32, +} + +#[test] +fn record_struct() { + let s = format!("{}", RecordError { code: 0 }); + assert_eq!(&s[..], "Error code: 0"); +} + +#[derive(Display)] +#[display(fmt = "Error code: {}", _0)] +struct TupleError(i32); + +#[test] +fn tuple_struct() { + let s = format!("{}", TupleError(2)); + assert_eq!(&s[..], "Error code: 2"); +} + +#[derive(Display)] +enum EnumError { + #[display(fmt = "Error code: {}", code)] + StructVariant { code: i32 }, + #[display(fmt = "Error: {}", _0)] + TupleVariant(&'static str), + #[display(fmt = "An error has occurred.")] + UnitVariant, +} + +#[test] +fn enum_error() { + let s = format!("{}", EnumError::StructVariant { code: 2 }); + assert_eq!(&s[..], "Error code: 2"); + let s = format!("{}", EnumError::TupleVariant("foobar")); + assert_eq!(&s[..], "Error: foobar"); + let s = format!("{}", EnumError::UnitVariant); + assert_eq!(&s[..], "An error has occurred."); +} diff --git a/third_party/rust/derive_more/tests/constructor.rs b/third_party/rust/derive_more/tests/constructor.rs new file mode 100644 index 000000000000..07fddb88386d --- /dev/null +++ b/third_party/rust/derive_more/tests/constructor.rs @@ -0,0 +1,21 @@ +#![allow(dead_code)] +#[macro_use] +extern crate derive_more; + +#[derive(Constructor)] +struct EmptyTuple(); + +#[derive(Constructor)] +struct EmptyStruct {} + +#[derive(Constructor)] +struct EmptyUnit; + +#[derive(Constructor)] +struct MyInts(i32, i32); + +#[derive(Constructor)] +struct Point2D { + x: i32, + y: i32, +} diff --git a/third_party/rust/derive_more/tests/deref.rs b/third_party/rust/derive_more/tests/deref.rs new file mode 100644 index 000000000000..8227f88f9813 --- /dev/null +++ b/third_party/rust/derive_more/tests/deref.rs @@ -0,0 +1,68 @@ +#![allow(dead_code, unused_imports)] +#[macro_use] +extern crate derive_more; + +#[derive(Deref)] +#[deref(forward)] +struct MyBoxedInt(Box); + +#[derive(Deref)] +#[deref(forward)] +struct NumRef<'a> { + num: &'a i32, +} + +#[derive(Deref)] +struct NumRef2<'a> { + #[deref(forward)] + num: &'a i32, + useless: bool, +} + +#[derive(Deref)] +#[deref(forward)] +struct NumRef3<'a> { + num: &'a i32, + #[deref(ignore)] + useless: bool, +} + +#[derive(Deref)] +struct MyInt(i32); + +#[derive(Deref)] +struct Point1D { + x: i32, +} + +#[derive(Deref)] +struct Point1D2 { + x: i32, + #[deref(ignore)] + useless: bool, +} + +#[derive(Deref)] +struct CoolVec { + cool: bool, + #[deref] + vec: Vec, +} + +#[derive(Deref)] +struct GenericVec(Vec); + +#[test] +fn deref_generic() { + let gv = GenericVec(Vec::::new()); + assert!(gv.is_empty()) +} + +#[derive(Deref)] +struct GenericBox(#[deref(forward)] Box); + +#[test] +fn deref_generic_forward() { + let boxed = GenericBox(Box::new(1i32)); + assert_eq!(*boxed, 1i32); +} diff --git a/third_party/rust/derive_more/tests/deref_mut.rs b/third_party/rust/derive_more/tests/deref_mut.rs new file mode 100644 index 000000000000..51a95e4f2956 --- /dev/null +++ b/third_party/rust/derive_more/tests/deref_mut.rs @@ -0,0 +1,124 @@ +#![allow(dead_code, unused_imports)] +#[macro_use] +extern crate derive_more; + +#[derive(DerefMut)] +#[deref_mut(forward)] +struct MyBoxedInt(Box); +// Deref implementation is needed for DerefMut +impl ::core::ops::Deref for MyBoxedInt { + type Target = as ::core::ops::Deref>::Target; + #[inline] + fn deref(&self) -> &Self::Target { + as ::core::ops::Deref>::deref(&self.0) + } +} + +#[derive(DerefMut)] +struct NumRef<'a> { + #[deref_mut(forward)] + num: &'a mut i32, +} +// Deref implementation is needed for DerefMut +impl<'a> ::core::ops::Deref for NumRef<'a> { + type Target = <&'a mut i32 as ::core::ops::Deref>::Target; + #[inline] + fn deref(&self) -> &Self::Target { + <&'a mut i32 as ::core::ops::Deref>::deref(&self.num) + } +} + +#[derive(DerefMut)] +#[deref_mut(forward)] +struct NumRef2<'a> { + num: &'a mut i32, + #[deref_mut(ignore)] + useless: bool, +} + +// Deref implementation is needed for DerefMut +impl<'a> ::core::ops::Deref for NumRef2<'a> { + type Target = <&'a mut i32 as ::core::ops::Deref>::Target; + #[inline] + fn deref(&self) -> &Self::Target { + <&'a mut i32 as ::core::ops::Deref>::deref(&self.num) + } +} + +#[derive(DerefMut)] +struct MyInt(i32); + +// Deref implementation is needed for DerefMutToInner +impl ::core::ops::Deref for MyInt { + type Target = i32; + #[inline] + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +#[derive(DerefMut)] +struct Point1D { + x: i32, +} + +// Deref implementation is needed for DerefMutToInner +impl ::core::ops::Deref for Point1D { + type Target = i32; + #[inline] + fn deref(&self) -> &Self::Target { + &self.x + } +} + +#[derive(DerefMut)] +struct CoolVec { + cool: bool, + #[deref_mut] + vec: Vec, +} +impl ::core::ops::Deref for CoolVec { + type Target = Vec; + #[inline] + fn deref(&self) -> &Self::Target { + &self.vec + } +} + +#[derive(DerefMut)] +struct GenericVec(Vec); + +impl ::core::ops::Deref for GenericVec { + type Target = Vec; + #[inline] + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +#[test] +fn deref_mut_generic() { + let mut gv = GenericVec::(vec![42]); + assert!(gv.get_mut(0).is_some()); +} + +#[derive(DerefMut)] +struct GenericBox(#[deref_mut(forward)] Box); + +impl ::core::ops::Deref for GenericBox +where + Box: ::core::ops::Deref, +{ + type Target = as ::core::ops::Deref>::Target; + #[inline] + fn deref(&self) -> &Self::Target { + as ::core::ops::Deref>::deref(&self.0) + } +} + +#[test] +fn deref_mut_generic_forward() { + let mut boxed = GenericBox(Box::new(1i32)); + *boxed = 3; + assert_eq!(*boxed, 3i32); +} diff --git a/third_party/rust/derive_more/tests/display.rs b/third_party/rust/derive_more/tests/display.rs new file mode 100644 index 000000000000..119b42c29e63 --- /dev/null +++ b/third_party/rust/derive_more/tests/display.rs @@ -0,0 +1,405 @@ +#![allow(dead_code, unused_imports)] +#[macro_use] +extern crate derive_more; + +use std::path::PathBuf; + +// Here just to make sure that this doesn't conflict with +// the derives in some way +use std::fmt::Binary; + +#[derive(Display, Octal, Binary)] +struct MyInt(i32); + +#[derive(UpperHex)] +enum IntEnum { + U8(u8), + I8(i8), +} + +#[derive(Display)] +#[display(fmt = "({}, {})", x, y)] +struct Point2D { + x: i32, + y: i32, +} + +#[derive(Display)] +#[display(fmt = "{}", message)] +struct Error { + message: &'static str, + backtrace: (), +} + +impl Error { + fn new(message: &'static str) -> Self { + Self { + message, + backtrace: (), + } + } +} + +#[derive(Display)] +enum E { + Uint(u32), + #[display(fmt = "I am B {:b}", i)] + Binary { + i: i8, + }, + #[display(fmt = "I am C {}", "_0.display()")] + Path(PathBuf), +} + +#[derive(Display)] +#[display(fmt = "Java EE")] +enum EE { + A, + B, +} + +#[derive(Display)] +#[display(fmt = "Hello there!")] +union U { + i: u32, +} + +#[derive(Octal)] +#[octal(fmt = "7")] +struct S; + +#[derive(UpperHex)] +#[upper_hex(fmt = "UpperHex")] +struct UH; + +#[derive(DebugCustom)] +#[debug(fmt = "MyDebug")] +struct D; + +#[derive(Display)] +struct Unit; + +#[derive(Display)] +struct UnitStruct {} + +#[derive(Display)] +enum EmptyEnum {} + +#[derive(Display)] +#[display(fmt = "Generic")] +struct Generic(T); + +#[derive(Display)] +#[display(fmt = "Here's a prefix for {} and a suffix")] +enum Affix { + A(u32), + #[display(fmt = "{} -- {}", wat, stuff)] + B { + wat: String, + stuff: bool, + }, +} + +#[test] +fn check_display() { + assert_eq!(MyInt(-2).to_string(), "-2"); + assert_eq!(format!("{:b}", MyInt(9)), "1001"); + assert_eq!(format!("{:#b}", MyInt(9)), "0b1001"); + assert_eq!(format!("{:o}", MyInt(9)), "11"); + assert_eq!(format!("{:X}", IntEnum::I8(-1)), "FF"); + assert_eq!(format!("{:#X}", IntEnum::U8(255)), "0xFF"); + assert_eq!(Point2D { x: 3, y: 4 }.to_string(), "(3, 4)"); + assert_eq!(Error::new("Error").to_string(), "Error"); + assert_eq!(E::Uint(2).to_string(), "2"); + assert_eq!(E::Binary { i: -2 }.to_string(), "I am B 11111110"); + assert_eq!(E::Path("abc".into()).to_string(), "I am C abc"); + assert_eq!(EE::A.to_string(), "Java EE"); + assert_eq!(EE::B.to_string(), "Java EE"); + assert_eq!(U { i: 2 }.to_string(), "Hello there!"); + assert_eq!(format!("{:o}", S), "7"); + assert_eq!(format!("{:X}", UH), "UpperHex"); + assert_eq!(format!("{:?}", D), "MyDebug"); + assert_eq!(Unit.to_string(), "Unit"); + assert_eq!(UnitStruct {}.to_string(), "UnitStruct"); + assert_eq!(Generic(()).to_string(), "Generic"); + assert_eq!( + Affix::A(2).to_string(), + "Here's a prefix for 2 and a suffix" + ); + assert_eq!( + Affix::B { + wat: "things".to_owned(), + stuff: false, + } + .to_string(), + "Here's a prefix for things -- false and a suffix" + ); +} + +mod generic { + #[derive(Display)] + #[display(fmt = "Generic {}", field)] + struct NamedGenericStruct { + field: T, + } + #[test] + fn named_generic_struct() { + assert_eq!(NamedGenericStruct { field: 1 }.to_string(), "Generic 1"); + } + + #[derive(Display)] + struct AutoNamedGenericStruct { + field: T, + } + #[test] + fn auto_named_generic_struct() { + assert_eq!(AutoNamedGenericStruct { field: 1 }.to_string(), "1"); + } + + #[derive(Display)] + #[display(fmt = "Generic {}", "_0")] + struct UnnamedGenericStruct(T); + #[test] + fn unnamed_generic_struct() { + assert_eq!(UnnamedGenericStruct(2).to_string(), "Generic 2"); + } + + #[derive(Display)] + struct AutoUnnamedGenericStruct(T); + #[test] + fn auto_unnamed_generic_struct() { + assert_eq!(AutoUnnamedGenericStruct(2).to_string(), "2"); + } + + #[derive(Display)] + enum GenericEnum { + #[display(fmt = "Gen::A {}", field)] + A { field: A }, + #[display(fmt = "Gen::B {}", "_0")] + B(B), + } + #[test] + fn generic_enum() { + assert_eq!(GenericEnum::A::<_, u8> { field: 1 }.to_string(), "Gen::A 1"); + assert_eq!(GenericEnum::B::(2).to_string(), "Gen::B 2"); + } + + #[derive(Display)] + enum AutoGenericEnum { + A { field: A }, + B(B), + } + #[test] + fn auto_generic_enum() { + assert_eq!(AutoGenericEnum::A::<_, u8> { field: 1 }.to_string(), "1"); + assert_eq!(AutoGenericEnum::B::(2).to_string(), "2"); + } + + #[derive(Display)] + #[display(fmt = "{} {} <-> {0:o} {1:#x} <-> {0:?} {1:X?}", a, b)] + struct MultiTraitNamedGenericStruct { + a: A, + b: B, + } + #[test] + fn multi_trait_named_generic_struct() { + let s = MultiTraitNamedGenericStruct { a: 8u8, b: 255 }; + assert_eq!(s.to_string(), "8 255 <-> 10 0xff <-> 8 FF"); + } + + #[derive(Display)] + #[display(fmt = "{} {} {{}} {0:o} {1:#x} - {0:>4?} {1:^4X?}", "_0", "_1")] + struct MultiTraitUnnamedGenericStruct(A, B); + #[test] + fn multi_trait_unnamed_generic_struct() { + let s = MultiTraitUnnamedGenericStruct(8u8, 255); + assert_eq!(s.to_string(), "8 255 {} 10 0xff - 8 FF "); + } + + #[derive(Display)] + #[display(fmt = "{}", "3 * 4")] + struct UnusedGenericStruct(T); + #[test] + fn unused_generic_struct() { + let s = UnusedGenericStruct(()); + assert_eq!(s.to_string(), "12"); + } + + mod associated_type_field_enumerator { + use super::*; + + trait Trait { + type Type; + } + + struct Struct; + + impl Trait for Struct { + type Type = i32; + } + + #[test] + fn auto_generic_named_struct_associated() { + #[derive(Display)] + struct AutoGenericNamedStructAssociated { + field: ::Type, + } + + let s = AutoGenericNamedStructAssociated:: { field: 10 }; + assert_eq!(s.to_string(), "10"); + } + + #[test] + fn auto_generic_unnamed_struct_associated() { + #[derive(Display)] + struct AutoGenericUnnamedStructAssociated(::Type); + + let s = AutoGenericUnnamedStructAssociated::(10); + assert_eq!(s.to_string(), "10"); + } + + #[test] + fn auto_generic_enum_associated() { + #[derive(Display)] + enum AutoGenericEnumAssociated { + Enumerator(::Type), + } + + let e = AutoGenericEnumAssociated::::Enumerator(10); + assert_eq!(e.to_string(), "10"); + } + } + + mod complex_type_field_enumerator { + use super::*; + + #[derive(Display)] + struct Struct(T); + + #[test] + fn auto_generic_named_struct_complex() { + #[derive(Display)] + struct AutoGenericNamedStructComplex { + field: Struct, + } + + let s = AutoGenericNamedStructComplex { field: Struct(10) }; + assert_eq!(s.to_string(), "10"); + } + + #[test] + fn auto_generic_unnamed_struct_complex() { + #[derive(Display)] + struct AutoGenericUnnamedStructComplex(Struct); + + let s = AutoGenericUnnamedStructComplex(Struct(10)); + assert_eq!(s.to_string(), "10"); + } + + #[test] + fn auto_generic_enum_complex() { + #[derive(Display)] + enum AutoGenericEnumComplex { + Enumerator(Struct), + } + + let e = AutoGenericEnumComplex::Enumerator(Struct(10)); + assert_eq!(e.to_string(), "10") + } + } + + mod reference { + use super::*; + + #[test] + fn auto_generic_reference() { + #[derive(Display)] + struct AutoGenericReference<'a, T>(&'a T); + + let s = AutoGenericReference(&10); + assert_eq!(s.to_string(), "10"); + } + + #[test] + fn auto_generic_static_reference() { + #[derive(Display)] + struct AutoGenericStaticReference(&'static T); + + let s = AutoGenericStaticReference(&10); + assert_eq!(s.to_string(), "10"); + } + } + + mod indirect { + use super::*; + + #[derive(Display)] + struct Struct(T); + + #[test] + fn auto_generic_indirect() { + #[derive(Display)] + struct AutoGenericIndirect(Struct<&'static T>); + + const V: i32 = 10; + let s = AutoGenericIndirect(Struct(&V)); + assert_eq!(s.to_string(), "10"); + } + } + + mod bound { + use super::*; + + #[test] + fn simple() { + #[derive(Display)] + #[display(fmt = "{} {}", _0, _1)] + struct Struct(T1, T2); + + let s = Struct(10, 20); + assert_eq!(s.to_string(), "10 20"); + } + + #[test] + fn redundant() { + #[derive(Display)] + #[display(bound = "T1: ::core::fmt::Display, T2: ::core::fmt::Display")] + #[display(fmt = "{} {}", _0, _1)] + struct Struct(T1, T2); + + let s = Struct(10, 20); + assert_eq!(s.to_string(), "10 20"); + } + + #[test] + fn complex() { + trait Trait1 { + fn function1(&self) -> &'static str; + } + + trait Trait2 { + fn function2(&self) -> &'static str; + } + + impl Trait1 for i32 { + fn function1(&self) -> &'static str { + "WHAT" + } + } + + impl Trait2 for i32 { + fn function2(&self) -> &'static str { + "EVER" + } + } + + #[derive(Display)] + #[display(bound = "T1: Trait1 + Trait2, T2: Trait1 + Trait2")] + #[display(fmt = "{} {} {} {}", "_0.function1()", _0, "_1.function2()", _1)] + struct Struct(T1, T2); + + let s = Struct(10, 20); + assert_eq!(s.to_string(), "WHAT 10 EVER 20"); + } + } +} diff --git a/third_party/rust/derive_more/tests/error/derives_for_enums_with_source.rs b/third_party/rust/derive_more/tests/error/derives_for_enums_with_source.rs new file mode 100644 index 000000000000..2513ab60cd83 --- /dev/null +++ b/third_party/rust/derive_more/tests/error/derives_for_enums_with_source.rs @@ -0,0 +1,249 @@ +use super::*; + +derive_display!(TestErr); +#[derive(Debug, Error)] +enum TestErr { + Unit, + NamedImplicitNoSource { + field: i32, + }, + NamedImplicitSource { + source: SimpleErr, + field: i32, + }, + NamedExplicitNoSource { + #[error(not(source))] + source: SimpleErr, + field: i32, + }, + NamedExplicitSource { + #[error(source)] + explicit_source: SimpleErr, + field: i32, + }, + NamedExplicitNoSourceRedundant { + #[error(not(source))] + field: i32, + }, + NamedExplicitSourceRedundant { + #[error(source)] + source: SimpleErr, + field: i32, + }, + NamedExplicitSuppressesImplicit { + source: i32, + #[error(source)] + field: SimpleErr, + }, + UnnamedImplicitNoSource(i32, i32), + UnnamedImplicitSource(SimpleErr), + UnnamedExplicitNoSource(#[error(not(source))] SimpleErr), + UnnamedExplicitSource(#[error(source)] SimpleErr, i32), + UnnamedExplicitNoSourceRedundant( + #[error(not(source))] i32, + #[error(not(source))] i32, + ), + UnnamedExplicitSourceRedundant(#[error(source)] SimpleErr), + NamedIgnore { + #[error(ignore)] + source: SimpleErr, + field: i32, + }, + UnnamedIgnore(#[error(ignore)] SimpleErr), + NamedIgnoreRedundant { + #[error(ignore)] + field: i32, + }, + UnnamedIgnoreRedundant(#[error(ignore)] i32, #[error(ignore)] i32), + #[error(ignore)] + NamedVariantIgnore { + source: SimpleErr, + field: i32, + }, + #[error(ignore)] + UnnamedVariantIgnore(SimpleErr), + #[error(ignore)] + NamedVariantIgnoreRedundant { + field: i32, + }, + #[error(ignore)] + UnnamedVariantIgnoreRedundant(i32, i32), +} + +#[test] +fn unit() { + assert!(TestErr::Unit.source().is_none()); +} + +#[test] +fn named_implicit_no_source() { + let err = TestErr::NamedImplicitNoSource { field: 0 }; + + assert!(err.source().is_none()); +} + +#[test] +fn named_implicit_source() { + let err = TestErr::NamedImplicitSource { + source: SimpleErr, + field: 0, + }; + + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn named_explicit_no_source() { + let err = TestErr::NamedExplicitNoSource { + source: SimpleErr, + field: 0, + }; + + assert!(err.source().is_none()); +} + +#[test] +fn named_explicit_source() { + let err = TestErr::NamedExplicitSource { + explicit_source: SimpleErr, + field: 0, + }; + + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn named_explicit_no_source_redundant() { + let err = TestErr::NamedExplicitNoSourceRedundant { field: 0 }; + + assert!(err.source().is_none()); +} + +#[test] +fn named_explicit_source_redundant() { + let err = TestErr::NamedExplicitSourceRedundant { + source: SimpleErr, + field: 0, + }; + + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn named_explicit_suppresses_implicit() { + let err = TestErr::NamedExplicitSuppressesImplicit { + source: 0, + field: SimpleErr, + }; + + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn unnamed_implicit_no_source() { + assert!(TestErr::UnnamedImplicitNoSource(0, 0).source().is_none()); +} + +#[test] +fn unnamed_implicit_source() { + let err = TestErr::UnnamedImplicitSource(SimpleErr); + + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn unnamed_explicit_no_source() { + let err = TestErr::UnnamedExplicitNoSource(SimpleErr); + + assert!(err.source().is_none()); +} + +#[test] +fn unnamed_explicit_source() { + let err = TestErr::UnnamedExplicitSource(SimpleErr, 0); + + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn unnamed_explicit_no_source_redundant() { + let err = TestErr::UnnamedExplicitNoSourceRedundant(0, 0); + + assert!(err.source().is_none()); +} + +#[test] +fn unnamed_explicit_source_redundant() { + let err = TestErr::UnnamedExplicitSourceRedundant(SimpleErr); + + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn named_ignore() { + let err = TestErr::NamedIgnore { + source: SimpleErr, + field: 0, + }; + + assert!(err.source().is_none()); +} + +#[test] +fn unnamed_ignore() { + let err = TestErr::UnnamedIgnore(SimpleErr); + + assert!(err.source().is_none()); +} + +#[test] +fn named_ignore_redundant() { + let err = TestErr::NamedIgnoreRedundant { field: 0 }; + + assert!(err.source().is_none()); +} + +#[test] +fn unnamed_ignore_redundant() { + let err = TestErr::UnnamedIgnoreRedundant(0, 0); + + assert!(err.source().is_none()); +} + +#[test] +fn named_variant_ignore() { + let err = TestErr::NamedVariantIgnore { + source: SimpleErr, + field: 0, + }; + + assert!(err.source().is_none()); +} + +#[test] +fn unnamed_variant_ignore() { + let err = TestErr::UnnamedVariantIgnore(SimpleErr); + + assert!(err.source().is_none()) +} + +#[test] +fn named_variant_ignore_redundant() { + let err = TestErr::NamedVariantIgnoreRedundant { field: 0 }; + + assert!(err.source().is_none()); +} + +#[test] +fn unnamed_variant_ignore_redundant() { + let err = TestErr::UnnamedVariantIgnoreRedundant(0, 0); + + assert!(err.source().is_none()) +} diff --git a/third_party/rust/derive_more/tests/error/derives_for_generic_enums_with_source.rs b/third_party/rust/derive_more/tests/error/derives_for_generic_enums_with_source.rs new file mode 100644 index 000000000000..92f3b3ae9e6c --- /dev/null +++ b/third_party/rust/derive_more/tests/error/derives_for_generic_enums_with_source.rs @@ -0,0 +1,248 @@ +use super::*; + +derive_display!(TestErr, T, E); +#[derive(Debug, Error)] +enum TestErr { + Unit, + NamedImplicitNoSource { + field: T, + }, + NamedImplicitSource { + source: E, + field: T, + }, + NamedExplicitNoSource { + #[error(not(source))] + source: E, + field: T, + }, + NamedExplicitSource { + #[error(source)] + explicit_source: E, + field: T, + }, + NamedExplicitNoSourceRedundant { + #[error(not(source))] + field: T, + }, + NamedExplicitSourceRedundant { + #[error(source)] + source: E, + field: T, + }, + NamedExplicitSuppressesImplicit { + source: T, + #[error(source)] + field: E, + }, + UnnamedImplicitNoSource(T, T), + UnnamedImplicitSource(E), + UnnamedExplicitNoSource(#[error(not(source))] E), + UnnamedExplicitSource(#[error(source)] E, T), + UnnamedExplicitNoSourceRedundant(#[error(not(source))] T, #[error(not(source))] T), + UnnamedExplicitSourceRedundant(#[error(source)] E), + NamedIgnore { + #[error(ignore)] + source: E, + field: T, + }, + UnnamedIgnore(#[error(ignore)] E), + NamedIgnoreRedundant { + #[error(ignore)] + field: T, + }, + UnnamedIgnoreRedundant(#[error(ignore)] T, #[error(ignore)] T), + #[error(ignore)] + NamedVariantIgnore { + source: E, + field: T, + }, + #[error(ignore)] + UnnamedVariantIgnore(E), + #[error(ignore)] + NamedVariantIgnoreRedundant { + field: T, + }, + #[error(ignore)] + UnnamedVariantIgnoreRedundant(T, T), +} + +#[test] +fn unit() { + assert!(TestErr::::Unit.source().is_none()); +} + +#[test] +fn named_implicit_no_source() { + let err = TestErr::::NamedImplicitNoSource { field: 0 }; + + assert!(err.source().is_none()); +} + +#[test] +fn named_implicit_source() { + let err = TestErr::NamedImplicitSource { + source: SimpleErr, + field: 0, + }; + + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn named_explicit_no_source() { + let err = TestErr::NamedExplicitNoSource { + source: SimpleErr, + field: 0, + }; + + assert!(err.source().is_none()); +} + +#[test] +fn named_explicit_source() { + let err = TestErr::NamedExplicitSource { + explicit_source: SimpleErr, + field: 0, + }; + + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn named_explicit_no_source_redundant() { + let err = TestErr::::NamedExplicitNoSourceRedundant { field: 0 }; + + assert!(err.source().is_none()); +} + +#[test] +fn named_explicit_source_redundant() { + let err = TestErr::NamedExplicitSourceRedundant { + source: SimpleErr, + field: 0, + }; + + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn named_explicit_suppresses_implicit() { + let err = TestErr::NamedExplicitSuppressesImplicit { + source: 0, + field: SimpleErr, + }; + + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn unnamed_implicit_no_source() { + let err = TestErr::::UnnamedImplicitNoSource(0, 0); + + assert!(err.source().is_none()); +} + +#[test] +fn unnamed_implicit_source() { + let err = TestErr::<_, i32>::UnnamedImplicitSource(SimpleErr); + + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn unnamed_explicit_no_source() { + let err = TestErr::<_, i32>::UnnamedExplicitNoSource(SimpleErr); + + assert!(err.source().is_none()); +} + +#[test] +fn unnamed_explicit_source() { + let err = TestErr::UnnamedExplicitSource(SimpleErr, 0); + + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn unnamed_explicit_no_source_redundant() { + let err = TestErr::::UnnamedExplicitNoSourceRedundant(0, 0); + + assert!(err.source().is_none()); +} + +#[test] +fn unnamed_explicit_source_redundant() { + let err = TestErr::<_, i32>::UnnamedExplicitSourceRedundant(SimpleErr); + + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn named_ignore() { + let err = TestErr::NamedIgnore { + source: SimpleErr, + field: 0, + }; + + assert!(err.source().is_none()); +} + +#[test] +fn unnamed_ignore() { + let err = TestErr::<_, i32>::UnnamedIgnore(SimpleErr); + + assert!(err.source().is_none()); +} + +#[test] +fn named_ignore_redundant() { + let err = TestErr::::NamedIgnoreRedundant { field: 0 }; + + assert!(err.source().is_none()); +} + +#[test] +fn unnamed_ignore_redundant() { + let err = TestErr::::UnnamedIgnoreRedundant(0, 0); + + assert!(err.source().is_none()); +} + +#[test] +fn named_variant_ignore() { + let err = TestErr::NamedVariantIgnore { + source: SimpleErr, + field: 0, + }; + + assert!(err.source().is_none()); +} + +#[test] +fn unnamed_variant_ignore() { + let err = TestErr::<_, i32>::UnnamedVariantIgnore(SimpleErr); + + assert!(err.source().is_none()) +} + +#[test] +fn named_variant_ignore_redundant() { + let err = TestErr::::NamedVariantIgnoreRedundant { field: 0 }; + + assert!(err.source().is_none()); +} + +#[test] +fn unnamed_variant_ignore_redundant() { + let err = TestErr::::UnnamedVariantIgnoreRedundant(0, 0); + + assert!(err.source().is_none()) +} diff --git a/third_party/rust/derive_more/tests/error/derives_for_generic_structs_with_source.rs b/third_party/rust/derive_more/tests/error/derives_for_generic_structs_with_source.rs new file mode 100644 index 000000000000..248e3c97ff30 --- /dev/null +++ b/third_party/rust/derive_more/tests/error/derives_for_generic_structs_with_source.rs @@ -0,0 +1,245 @@ +use super::*; + +#[test] +fn named_implicit_no_source() { + derive_display!(TestErr, T); + #[derive(Default, Debug, Error)] + struct TestErr { + field: T, + } + + assert!(TestErr::::default().source().is_none()); +} + +#[test] +fn named_implicit_source() { + derive_display!(TestErr, E, T); + #[derive(Default, Debug, Error)] + struct TestErr { + source: E, + field: T, + } + + let err = TestErr::::default(); + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn named_explicit_no_source() { + derive_display!(TestErr, E, T); + #[derive(Default, Debug, Error)] + struct TestErr { + #[error(not(source))] + source: E, + field: T, + } + + let err = TestErr::::default(); + assert!(err.source().is_none()); +} + +#[test] +fn named_explicit_source() { + derive_display!(TestErr, E, T); + #[derive(Default, Debug, Error)] + struct TestErr { + #[error(source)] + explicit_source: E, + field: T, + } + + let err = TestErr::::default(); + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn named_explicit_no_source_redundant() { + derive_display!(TestErr, T); + #[derive(Default, Debug, Error)] + struct TestErr { + #[error(not(source))] + field: T, + } + + assert!(TestErr::::default().source().is_none()); +} + +#[test] +fn named_explicit_source_redundant() { + derive_display!(TestErr, E, T); + #[derive(Default, Debug, Error)] + struct TestErr { + #[error(source)] + source: E, + field: T, + } + + let err = TestErr::::default(); + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn named_explicit_suppresses_implicit() { + derive_display!(TestErr, E, T); + #[derive(Default, Debug, Error)] + struct TestErr { + source: E, + #[error(source)] + field: T, + } + + let err = TestErr::::default(); + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn unnamed_implicit_no_source() { + derive_display!(TestErr, T); + #[derive(Default, Debug, Error)] + struct TestErr(T, T); + + assert!(TestErr::::default().source().is_none()); +} + +#[test] +fn unnamed_implicit_source() { + derive_display!(TestErr, E); + #[derive(Default, Debug, Error)] + struct TestErr(E); + + let err = TestErr::::default(); + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn unnamed_explicit_no_source() { + derive_display!(TestErr, E); + #[derive(Default, Debug, Error)] + struct TestErr(#[error(not(source))] E); + + assert!(TestErr::::default().source().is_none()); +} + +#[test] +fn unnamed_explicit_source() { + derive_display!(TestErr, E, T); + #[derive(Default, Debug, Error)] + struct TestErr(#[error(source)] E, T); + + let err = TestErr::::default(); + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn unnamed_explicit_no_source_redundant() { + derive_display!(TestErr, T); + #[derive(Default, Debug, Error)] + struct TestErr(#[error(not(source))] T, #[error(not(source))] T); + + assert!(TestErr::::default().source().is_none()); +} + +#[test] +fn unnamed_explicit_source_redundant() { + derive_display!(TestErr, E); + #[derive(Default, Debug, Error)] + struct TestErr(#[error(source)] E); + + let err = TestErr::::default(); + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn named_ignore() { + derive_display!(TestErr, E, T); + #[derive(Default, Debug, Error)] + struct TestErr { + #[error(ignore)] + source: E, + field: T, + } + + assert!(TestErr::::default().source().is_none()); +} + +#[test] +fn unnamed_ignore() { + derive_display!(TestErr, E); + #[derive(Default, Debug, Error)] + struct TestErr(#[error(ignore)] E); + + assert!(TestErr::::default().source().is_none()); +} + +#[test] +fn named_ignore_redundant() { + derive_display!(TestErr, T); + #[derive(Default, Debug, Error)] + struct TestErr { + #[error(ignore)] + field: T, + } + + assert!(TestErr::::default().source().is_none()); +} + +#[test] +fn unnamed_ignore_redundant() { + derive_display!(TestErr, T); + #[derive(Default, Debug, Error)] + struct TestErr(#[error(ignore)] T, #[error(ignore)] T); + + assert!(TestErr::::default().source().is_none()); +} + +#[test] +fn named_struct_ignore() { + derive_display!(TestErr, E, T); + #[derive(Default, Debug, Error)] + #[error(ignore)] + struct TestErr { + source: E, + field: T, + } + + assert!(TestErr::::default().source().is_none()) +} + +#[test] +fn unnamed_struct_ignore() { + derive_display!(TestErr, E); + #[derive(Default, Debug, Error)] + #[error(ignore)] + struct TestErr(E); + + assert!(TestErr::::default().source().is_none()) +} + +#[test] +fn named_struct_ignore_redundant() { + derive_display!(TestErr, T); + #[derive(Default, Debug, Error)] + #[error(ignore)] + struct TestErr { + field: T, + } + + assert!(TestErr::::default().source().is_none()) +} + +#[test] +fn unnamed_struct_ignore_redundant() { + derive_display!(TestErr, T); + #[derive(Default, Debug, Error)] + #[error(ignore)] + struct TestErr(T, T); + + assert!(TestErr::::default().source().is_none()) +} diff --git a/third_party/rust/derive_more/tests/error/derives_for_structs_with_source.rs b/third_party/rust/derive_more/tests/error/derives_for_structs_with_source.rs new file mode 100644 index 000000000000..d46bd5ad588b --- /dev/null +++ b/third_party/rust/derive_more/tests/error/derives_for_structs_with_source.rs @@ -0,0 +1,249 @@ +use super::*; + +#[test] +fn unit() { + assert!(SimpleErr.source().is_none()); +} + +#[test] +fn named_implicit_no_source() { + derive_display!(TestErr); + #[derive(Default, Debug, Error)] + struct TestErr { + field: i32, + } + + assert!(TestErr::default().source().is_none()); +} + +#[test] +fn named_implicit_source() { + derive_display!(TestErr); + #[derive(Default, Debug, Error)] + struct TestErr { + source: SimpleErr, + field: i32, + } + + let err = TestErr::default(); + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn named_explicit_no_source() { + derive_display!(TestErr); + #[derive(Default, Debug, Error)] + struct TestErr { + #[error(not(source))] + source: SimpleErr, + field: i32, + } + + assert!(TestErr::default().source().is_none()); +} + +#[test] +fn named_explicit_source() { + derive_display!(TestErr); + #[derive(Default, Debug, Error)] + struct TestErr { + #[error(source)] + explicit_source: SimpleErr, + field: i32, + } + + let err = TestErr::default(); + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn named_explicit_no_source_redundant() { + derive_display!(TestErr); + #[derive(Default, Debug, Error)] + struct TestErr { + #[error(not(source))] + field: i32, + } + + assert!(TestErr::default().source().is_none()); +} + +#[test] +fn named_explicit_source_redundant() { + derive_display!(TestErr); + #[derive(Default, Debug, Error)] + struct TestErr { + #[error(source)] + source: SimpleErr, + field: i32, + } + + let err = TestErr::default(); + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn named_explicit_suppresses_implicit() { + derive_display!(TestErr); + #[derive(Default, Debug, Error)] + struct TestErr { + source: i32, + #[error(source)] + field: SimpleErr, + } + + let err = TestErr::default(); + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn unnamed_implicit_no_source() { + derive_display!(TestErr); + #[derive(Default, Debug, Error)] + struct TestErr(i32, i32); + + assert!(TestErr::default().source().is_none()); +} + +#[test] +fn unnamed_implicit_source() { + derive_display!(TestErr); + #[derive(Default, Debug, Error)] + struct TestErr(SimpleErr); + + let err = TestErr::default(); + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn unnamed_explicit_no_source() { + derive_display!(TestErr); + #[derive(Default, Debug, Error)] + struct TestErr(#[error(not(source))] SimpleErr); + + assert!(TestErr::default().source().is_none()); +} + +#[test] +fn unnamed_explicit_source() { + derive_display!(TestErr); + #[derive(Default, Debug, Error)] + struct TestErr(#[error(source)] SimpleErr, i32); + + let err = TestErr::default(); + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn unnamed_explicit_no_source_redundant() { + derive_display!(TestErr); + #[derive(Default, Debug, Error)] + struct TestErr(#[error(not(source))] i32, #[error(not(source))] i32); + + assert!(TestErr::default().source().is_none()); +} + +#[test] +fn unnamed_explicit_source_redundant() { + derive_display!(TestErr); + #[derive(Default, Debug, Error)] + struct TestErr(#[error(source)] SimpleErr); + + let err = TestErr::default(); + assert!(err.source().is_some()); + assert!(err.source().unwrap().is::()); +} + +#[test] +fn named_ignore() { + derive_display!(TestErr); + #[derive(Default, Debug, Error)] + struct TestErr { + #[error(ignore)] + source: SimpleErr, + field: i32, + } + + assert!(TestErr::default().source().is_none()); +} + +#[test] +fn unnamed_ignore() { + derive_display!(TestErr); + #[derive(Default, Debug, Error)] + struct TestErr(#[error(ignore)] SimpleErr); + + assert!(TestErr::default().source().is_none()); +} + +#[test] +fn named_ignore_redundant() { + derive_display!(TestErr); + #[derive(Default, Debug, Error)] + struct TestErr { + #[error(ignore)] + field: i32, + } + + assert!(TestErr::default().source().is_none()); +} + +#[test] +fn unnamed_ignore_redundant() { + derive_display!(TestErr); + #[derive(Default, Debug, Error)] + struct TestErr(#[error(ignore)] i32, #[error(ignore)] i32); + + assert!(TestErr::default().source().is_none()); +} + +#[test] +fn named_struct_ignore() { + derive_display!(TestErr); + #[derive(Default, Debug, Error)] + #[error(ignore)] + struct TestErr { + source: SimpleErr, + field: i32, + } + + assert!(TestErr::default().source().is_none()) +} + +#[test] +fn unnamed_struct_ignore() { + derive_display!(TestErr); + #[derive(Default, Debug, Error)] + #[error(ignore)] + struct TestErr(SimpleErr); + + assert!(TestErr::default().source().is_none()) +} + +#[test] +fn named_struct_ignore_redundant() { + derive_display!(TestErr); + #[derive(Default, Debug, Error)] + #[error(ignore)] + struct TestErr { + field: i32, + } + + assert!(TestErr::default().source().is_none()) +} + +#[test] +fn unnamed_struct_ignore_redundant() { + derive_display!(TestErr); + #[derive(Default, Debug, Error)] + #[error(ignore)] + struct TestErr(i32, i32); + + assert!(TestErr::default().source().is_none()) +} diff --git a/third_party/rust/derive_more/tests/error/mod.rs b/third_party/rust/derive_more/tests/error/mod.rs new file mode 100644 index 000000000000..5d7190d8f75b --- /dev/null +++ b/third_party/rust/derive_more/tests/error/mod.rs @@ -0,0 +1,56 @@ +use std::error::Error; + +/// Derives `std::fmt::Display` for structs/enums. +/// Derived implementation outputs empty string. +/// Useful, as a way to formally satisfy `Display` trait bound. +/// +/// ## Syntax: +/// +/// For regular structs/enums: +/// +/// ``` +/// enum MyEnum { +/// ... +/// } +/// +/// derive_display!(MyEnum); +/// ``` +/// +/// For generic structs/enums: +/// +/// ``` +/// struct MyGenericStruct { +/// ... +/// } +/// +/// derive_display!(MyGenericStruct, T, U); +/// ``` +macro_rules! derive_display { + (@fmt) => { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + write!(f, "") + } + }; + ($type:ident) => { + impl ::std::fmt::Display for $type { + derive_display!(@fmt); + } + }; + ($type:ident, $($type_parameters:ident),*) => { + impl<$($type_parameters),*> ::std::fmt::Display for $type<$($type_parameters),*> { + derive_display!(@fmt); + } + }; +} + +mod derives_for_enums_with_source; +mod derives_for_generic_enums_with_source; +mod derives_for_generic_structs_with_source; +mod derives_for_structs_with_source; + +#[cfg(feature = "nightly")] +mod nightly; + +derive_display!(SimpleErr); +#[derive(Default, Debug, Error)] +struct SimpleErr; diff --git a/third_party/rust/derive_more/tests/error/nightly/derives_for_enums_with_backtrace.rs b/third_party/rust/derive_more/tests/error/nightly/derives_for_enums_with_backtrace.rs new file mode 100644 index 000000000000..c4ff4817d696 --- /dev/null +++ b/third_party/rust/derive_more/tests/error/nightly/derives_for_enums_with_backtrace.rs @@ -0,0 +1,272 @@ +use super::*; + +derive_display!(TestErr); +#[derive(Debug, Error)] +enum TestErr { + Unit, + NamedImplicitNoBacktrace { + field: i32, + }, + NamedImplicitBacktraceByFieldName { + backtrace: MyBacktrace, + field: i32, + }, + NamedImplicitBacktraceByFieldType { + implicit_backtrace: Backtrace, + field: i32, + }, + NamedExplicitNoBacktraceByFieldName { + #[error(not(backtrace))] + backtrace: MyBacktrace, + field: i32, + }, + NamedExplicitNoBacktraceByFieldType { + #[error(not(backtrace))] + implicit_backtrace: Backtrace, + field: i32, + }, + NamedExplicitBacktrace { + #[error(backtrace)] + explicit_backtrace: MyBacktrace, + field: i32, + }, + NamedExplicitNoBacktraceRedundant { + #[error(not(backtrace))] + not_backtrace: MyBacktrace, + #[error(not(backtrace))] + field: i32, + }, + NamedExplicitBacktraceByFieldNameRedundant { + #[error(backtrace)] + backtrace: MyBacktrace, + field: i32, + }, + NamedExplicitBacktraceByFieldTypeRedundant { + #[error(backtrace)] + implicit_backtrace: Backtrace, + field: i32, + }, + NamedExplicitSupressesImplicit { + #[error(backtrace)] + not_backtrace: MyBacktrace, + backtrace: Backtrace, + field: i32, + }, + UnnamedImplicitNoBacktrace(i32, i32), + UnnamedImplicitBacktrace(Backtrace, i32, i32), + UnnamedExplicitNoBacktrace(#[error(not(backtrace))] Backtrace, i32), + UnnamedExplicitBacktrace(#[error(backtrace)] MyBacktrace, i32, i32), + UnnamedExplicitNoBacktraceRedundant( + #[error(not(backtrace))] MyBacktrace, + #[error(not(backtrace))] i32, + ), + UnnamedExplicitBacktraceRedundant(#[error(backtrace)] Backtrace, i32, i32), + UnnamedExplicitSupressesImplicit(#[error(backtrace)] MyBacktrace, Backtrace, i32), +} + +impl TestErr { + fn get_stored_backtrace(&self) -> &Backtrace { + match self { + Self::NamedImplicitBacktraceByFieldName { backtrace, .. } => backtrace, + Self::NamedImplicitBacktraceByFieldType { + implicit_backtrace, .. + } => implicit_backtrace, + Self::NamedExplicitBacktrace { + explicit_backtrace, .. + } => explicit_backtrace, + Self::NamedExplicitBacktraceByFieldNameRedundant { backtrace, .. } => { + backtrace + } + Self::NamedExplicitBacktraceByFieldTypeRedundant { + implicit_backtrace, + .. + } => implicit_backtrace, + Self::NamedExplicitSupressesImplicit { not_backtrace, .. } => not_backtrace, + Self::UnnamedImplicitBacktrace(backtrace, _, _) => backtrace, + Self::UnnamedExplicitBacktrace(backtrace, _, _) => backtrace, + Self::UnnamedExplicitBacktraceRedundant(backtrace, _, _) => backtrace, + Self::UnnamedExplicitSupressesImplicit(backtrace, _, _) => backtrace, + _ => panic!("ERROR IN TEST IMPLEMENTATION"), + } + } + + fn get_unused_backtrace(&self) -> &Backtrace { + match self { + Self::NamedExplicitSupressesImplicit { backtrace, .. } => backtrace, + Self::UnnamedExplicitSupressesImplicit(_, backtrace, _) => backtrace, + _ => panic!("ERROR IN TEST IMPLEMENTATION"), + } + } +} + +type MyBacktrace = Backtrace; + +#[test] +fn unit() { + assert!(TestErr::Unit.backtrace().is_none()); +} + +#[test] +fn named_implicit_no_backtrace() { + let err = TestErr::NamedImplicitNoBacktrace { field: 0 }; + + assert!(err.backtrace().is_none()); +} + +#[test] +fn named_implicit_backtrace_by_field_name() { + let err = TestErr::NamedImplicitBacktraceByFieldName { + backtrace: Backtrace::force_capture(), + field: 0, + }; + + assert!(err.backtrace().is_some()); + assert_bt!(==, err, .get_stored_backtrace); +} + +#[test] +fn named_implicit_backtrace_by_field_type() { + let err = TestErr::NamedImplicitBacktraceByFieldType { + implicit_backtrace: Backtrace::force_capture(), + field: 0, + }; + + assert!(err.backtrace().is_some()); + assert_bt!(==, err, .get_stored_backtrace); +} + +#[test] +fn named_explicit_no_backtrace_by_field_name() { + let err = TestErr::NamedExplicitNoBacktraceByFieldName { + backtrace: Backtrace::force_capture(), + field: 0, + }; + + assert!(err.backtrace().is_none()); +} + +#[test] +fn named_explicit_no_backtrace_by_field_type() { + let err = TestErr::NamedExplicitNoBacktraceByFieldType { + implicit_backtrace: Backtrace::force_capture(), + field: 0, + }; + + assert!(err.backtrace().is_none()); +} + +#[test] +fn named_explicit_backtrace() { + let err = TestErr::NamedExplicitBacktrace { + explicit_backtrace: Backtrace::force_capture(), + field: 0, + }; + + assert!(err.backtrace().is_some()); + assert_bt!(==, err, .get_stored_backtrace); +} + +#[test] +fn named_explicit_no_backtrace_redundant() { + let err = TestErr::NamedExplicitNoBacktraceRedundant { + not_backtrace: Backtrace::force_capture(), + field: 0, + }; + + assert!(err.backtrace().is_none()); +} + +#[test] +fn named_explicit_backtrace_by_field_name_redundant() { + let err = TestErr::NamedExplicitBacktraceByFieldNameRedundant { + backtrace: Backtrace::force_capture(), + field: 0, + }; + + assert!(err.backtrace().is_some()); + assert_bt!(==, err, .get_stored_backtrace); +} + +#[test] +fn named_explicit_backtrace_by_field_type_redundant() { + let err = TestErr::NamedExplicitBacktraceByFieldTypeRedundant { + implicit_backtrace: Backtrace::force_capture(), + field: 0, + }; + + assert!(err.backtrace().is_some()); + assert_bt!(==, err, .get_stored_backtrace); +} + +#[test] +fn named_explicit_supresses_implicit() { + let err = TestErr::NamedExplicitSupressesImplicit { + not_backtrace: Backtrace::force_capture(), + backtrace: (|| Backtrace::force_capture())(), // ensure backtraces are different + field: 0, + }; + + assert!(err.backtrace().is_some()); + assert_bt!(==, err, .get_stored_backtrace); + assert_bt!(!=, err, .get_unused_backtrace); +} + +#[test] +fn unnamed_implicit_no_backtrace() { + let err = TestErr::UnnamedImplicitNoBacktrace(0, 0); + + assert!(err.backtrace().is_none()); +} + +#[test] +fn unnamed_implicit_backtrace() { + let err = TestErr::UnnamedImplicitBacktrace(Backtrace::force_capture(), 0, 0); + + assert!(err.backtrace().is_some()); + assert_bt!(==, err, .get_stored_backtrace); +} + +#[test] +fn unnamed_explicit_no_backtrace() { + let err = TestErr::UnnamedExplicitNoBacktrace(Backtrace::force_capture(), 0); + + assert!(err.backtrace().is_none()); +} + +#[test] +fn unnamed_explicit_backtrace() { + let err = TestErr::UnnamedExplicitBacktrace(Backtrace::force_capture(), 0, 0); + + assert!(err.backtrace().is_some()); + assert_bt!(==, err, .get_stored_backtrace); +} + +#[test] +fn unnamed_explicit_no_backtrace_redundant() { + let err = + TestErr::UnnamedExplicitNoBacktraceRedundant(Backtrace::force_capture(), 0); + + assert!(err.backtrace().is_none()); +} + +#[test] +fn unnamed_explicit_backtrace_redundant() { + let err = + TestErr::UnnamedExplicitBacktraceRedundant(Backtrace::force_capture(), 0, 0); + + assert!(err.backtrace().is_some()); + assert_bt!(==, err, .get_stored_backtrace); +} + +#[test] +fn unnamed_explicit_supresses_implicit() { + let err = TestErr::UnnamedExplicitSupressesImplicit( + Backtrace::force_capture(), + (|| Backtrace::force_capture())(), // ensure backtraces are different + 0, + ); + + assert!(err.backtrace().is_some()); + assert_bt!(==, err, .get_stored_backtrace); + assert_bt!(!=, err, .get_unused_backtrace); +} diff --git a/third_party/rust/derive_more/tests/error/nightly/derives_for_generic_enums_with_backtrace.rs b/third_party/rust/derive_more/tests/error/nightly/derives_for_generic_enums_with_backtrace.rs new file mode 100644 index 000000000000..8574751d0277 --- /dev/null +++ b/third_party/rust/derive_more/tests/error/nightly/derives_for_generic_enums_with_backtrace.rs @@ -0,0 +1,272 @@ +use super::*; + +derive_display!(TestErr, T); +#[derive(Debug, Error)] +enum TestErr { + Unit, + NamedImplicitNoBacktrace { + field: T, + }, + NamedImplicitBacktraceByFieldName { + backtrace: MyBacktrace, + field: T, + }, + NamedImplicitBacktraceByFieldType { + implicit_backtrace: Backtrace, + field: T, + }, + NamedExplicitNoBacktraceByFieldName { + #[error(not(backtrace))] + backtrace: MyBacktrace, + field: T, + }, + NamedExplicitNoBacktraceByFieldType { + #[error(not(backtrace))] + implicit_backtrace: Backtrace, + field: T, + }, + NamedExplicitBacktrace { + #[error(backtrace)] + explicit_backtrace: MyBacktrace, + field: T, + }, + NamedExplicitNoBacktraceRedundant { + #[error(not(backtrace))] + not_backtrace: MyBacktrace, + #[error(not(backtrace))] + field: T, + }, + NamedExplicitBacktraceByFieldNameRedundant { + #[error(backtrace)] + backtrace: MyBacktrace, + field: T, + }, + NamedExplicitBacktraceByFieldTypeRedundant { + #[error(backtrace)] + implicit_backtrace: Backtrace, + field: T, + }, + NamedExplicitSupressesImplicit { + #[error(backtrace)] + not_backtrace: MyBacktrace, + backtrace: Backtrace, + field: T, + }, + UnnamedImplicitNoBacktrace(T, T), + UnnamedImplicitBacktrace(Backtrace, T, T), + UnnamedExplicitNoBacktrace(#[error(not(backtrace))] Backtrace, T), + UnnamedExplicitBacktrace(#[error(backtrace)] MyBacktrace, T, T), + UnnamedExplicitNoBacktraceRedundant( + #[error(not(backtrace))] MyBacktrace, + #[error(not(backtrace))] T, + ), + UnnamedExplicitBacktraceRedundant(#[error(backtrace)] Backtrace, T, T), + UnnamedExplicitSupressesImplicit(#[error(backtrace)] MyBacktrace, Backtrace, T), +} + +impl TestErr { + fn get_stored_backtrace(&self) -> &Backtrace { + match self { + Self::NamedImplicitBacktraceByFieldName { backtrace, .. } => backtrace, + Self::NamedImplicitBacktraceByFieldType { + implicit_backtrace, .. + } => implicit_backtrace, + Self::NamedExplicitBacktrace { + explicit_backtrace, .. + } => explicit_backtrace, + Self::NamedExplicitBacktraceByFieldNameRedundant { backtrace, .. } => { + backtrace + } + Self::NamedExplicitBacktraceByFieldTypeRedundant { + implicit_backtrace, + .. + } => implicit_backtrace, + Self::NamedExplicitSupressesImplicit { not_backtrace, .. } => not_backtrace, + Self::UnnamedImplicitBacktrace(backtrace, _, _) => backtrace, + Self::UnnamedExplicitBacktrace(backtrace, _, _) => backtrace, + Self::UnnamedExplicitBacktraceRedundant(backtrace, _, _) => backtrace, + Self::UnnamedExplicitSupressesImplicit(backtrace, _, _) => backtrace, + _ => panic!("ERROR IN TEST IMPLEMENTATION"), + } + } + + fn get_unused_backtrace(&self) -> &Backtrace { + match self { + Self::NamedExplicitSupressesImplicit { backtrace, .. } => backtrace, + Self::UnnamedExplicitSupressesImplicit(_, backtrace, _) => backtrace, + _ => panic!("ERROR IN TEST IMPLEMENTATION"), + } + } +} + +type MyBacktrace = Backtrace; + +#[test] +fn unit() { + assert!(TestErr::::Unit.backtrace().is_none()); +} + +#[test] +fn named_implicit_no_backtrace() { + let err = TestErr::NamedImplicitNoBacktrace { field: 0 }; + + assert!(err.backtrace().is_none()); +} + +#[test] +fn named_implicit_backtrace_by_field_name() { + let err = TestErr::NamedImplicitBacktraceByFieldName { + backtrace: Backtrace::force_capture(), + field: 0, + }; + + assert!(err.backtrace().is_some()); + assert_bt!(==, err, .get_stored_backtrace); +} + +#[test] +fn named_implicit_backtrace_by_field_type() { + let err = TestErr::NamedImplicitBacktraceByFieldType { + implicit_backtrace: Backtrace::force_capture(), + field: 0, + }; + + assert!(err.backtrace().is_some()); + assert_bt!(==, err, .get_stored_backtrace); +} + +#[test] +fn named_explicit_no_backtrace_by_field_name() { + let err = TestErr::NamedExplicitNoBacktraceByFieldName { + backtrace: Backtrace::force_capture(), + field: 0, + }; + + assert!(err.backtrace().is_none()); +} + +#[test] +fn named_explicit_no_backtrace_by_field_type() { + let err = TestErr::NamedExplicitNoBacktraceByFieldType { + implicit_backtrace: Backtrace::force_capture(), + field: 0, + }; + + assert!(err.backtrace().is_none()); +} + +#[test] +fn named_explicit_backtrace() { + let err = TestErr::NamedExplicitBacktrace { + explicit_backtrace: Backtrace::force_capture(), + field: 0, + }; + + assert!(err.backtrace().is_some()); + assert_bt!(==, err, .get_stored_backtrace); +} + +#[test] +fn named_explicit_no_backtrace_redundant() { + let err = TestErr::NamedExplicitNoBacktraceRedundant { + not_backtrace: Backtrace::force_capture(), + field: 0, + }; + + assert!(err.backtrace().is_none()); +} + +#[test] +fn named_explicit_backtrace_by_field_name_redundant() { + let err = TestErr::NamedExplicitBacktraceByFieldNameRedundant { + backtrace: Backtrace::force_capture(), + field: 0, + }; + + assert!(err.backtrace().is_some()); + assert_bt!(==, err, .get_stored_backtrace); +} + +#[test] +fn named_explicit_backtrace_by_field_type_redundant() { + let err = TestErr::NamedExplicitBacktraceByFieldTypeRedundant { + implicit_backtrace: Backtrace::force_capture(), + field: 0, + }; + + assert!(err.backtrace().is_some()); + assert_bt!(==, err, .get_stored_backtrace); +} + +#[test] +fn named_explicit_supresses_implicit() { + let err = TestErr::NamedExplicitSupressesImplicit { + not_backtrace: Backtrace::force_capture(), + backtrace: (|| Backtrace::force_capture())(), // ensure backtraces are different + field: 0, + }; + + assert!(err.backtrace().is_some()); + assert_bt!(==, err, .get_stored_backtrace); + assert_bt!(!=, err, .get_unused_backtrace); +} + +#[test] +fn unnamed_implicit_no_backtrace() { + let err = TestErr::UnnamedImplicitNoBacktrace(0, 0); + + assert!(err.backtrace().is_none()); +} + +#[test] +fn unnamed_implicit_backtrace() { + let err = TestErr::UnnamedImplicitBacktrace(Backtrace::force_capture(), 0, 0); + + assert!(err.backtrace().is_some()); + assert_bt!(==, err, .get_stored_backtrace); +} + +#[test] +fn unnamed_explicit_no_backtrace() { + let err = TestErr::UnnamedExplicitNoBacktrace(Backtrace::force_capture(), 0); + + assert!(err.backtrace().is_none()); +} + +#[test] +fn unnamed_explicit_backtrace() { + let err = TestErr::UnnamedExplicitBacktrace(Backtrace::force_capture(), 0, 0); + + assert!(err.backtrace().is_some()); + assert_bt!(==, err, .get_stored_backtrace); +} + +#[test] +fn unnamed_explicit_no_backtrace_redundant() { + let err = + TestErr::UnnamedExplicitNoBacktraceRedundant(Backtrace::force_capture(), 0); + + assert!(err.backtrace().is_none()); +} + +#[test] +fn unnamed_explicit_backtrace_redundant() { + let err = + TestErr::UnnamedExplicitBacktraceRedundant(Backtrace::force_capture(), 0, 0); + + assert!(err.backtrace().is_some()); + assert_bt!(==, err, .get_stored_backtrace); +} + +#[test] +fn unnamed_explicit_supresses_implicit() { + let err = TestErr::UnnamedExplicitSupressesImplicit( + Backtrace::force_capture(), + (|| Backtrace::force_capture())(), // ensure backtraces are different + 0, + ); + + assert!(err.backtrace().is_some()); + assert_bt!(==, err, .get_stored_backtrace); + assert_bt!(!=, err, .get_unused_backtrace); +} diff --git a/third_party/rust/derive_more/tests/error/nightly/derives_for_generic_structs_with_backtrace.rs b/third_party/rust/derive_more/tests/error/nightly/derives_for_generic_structs_with_backtrace.rs new file mode 100644 index 000000000000..91df87c82a45 --- /dev/null +++ b/third_party/rust/derive_more/tests/error/nightly/derives_for_generic_structs_with_backtrace.rs @@ -0,0 +1,275 @@ +use super::*; + +#[test] +fn named_implicit_no_backtrace() { + derive_display!(TestErr, T); + #[derive(Default, Debug, Error)] + struct TestErr { + field: T, + } + + assert!(TestErr::::default().backtrace().is_none()); +} + +#[test] +fn named_implicit_backtrace_by_field_name() { + derive_display!(TestErr, T); + #[derive(Debug, Error)] + struct TestErr { + backtrace: MyBacktrace, + field: T, + } + + type MyBacktrace = Backtrace; + + let err = TestErr { + backtrace: Backtrace::force_capture(), + field: 0, + }; + assert!(err.backtrace().is_some()); + assert_bt!(==, err); +} + +#[test] +fn named_implicit_backtrace_by_field_type() { + derive_display!(TestErr, T); + #[derive(Debug, Error)] + struct TestErr { + implicit_backtrace: Backtrace, + field: T, + } + + let err = TestErr { + implicit_backtrace: Backtrace::force_capture(), + field: 0, + }; + assert!(err.backtrace().is_some()); + assert_bt!(==, err, implicit_backtrace); +} + +#[test] +fn named_explicit_no_backtrace_by_field_name() { + derive_display!(TestErr, T); + #[derive(Debug, Error)] + struct TestErr { + #[error(not(backtrace))] + backtrace: MyBacktrace, + field: T, + } + + type MyBacktrace = Backtrace; + + assert!(TestErr { + backtrace: Backtrace::force_capture(), + field: 0 + } + .backtrace() + .is_none()); +} + +#[test] +fn named_explicit_no_backtrace_by_field_type() { + derive_display!(TestErr, T); + #[derive(Debug, Error)] + struct TestErr { + #[error(not(backtrace))] + implicit_backtrace: Backtrace, + field: T, + } + + assert!(TestErr { + implicit_backtrace: Backtrace::force_capture(), + field: 0 + } + .backtrace() + .is_none()); +} + +#[test] +fn named_explicit_backtrace() { + derive_display!(TestErr, T); + #[derive(Debug, Error)] + struct TestErr { + #[error(backtrace)] + explicit_backtrace: MyBacktrace, + field: T, + } + + type MyBacktrace = Backtrace; + + let err = TestErr { + explicit_backtrace: Backtrace::force_capture(), + field: 0, + }; + assert!(err.backtrace().is_some()); + assert_bt!(==, err, explicit_backtrace); +} + +#[test] +fn named_explicit_no_backtrace_redundant() { + derive_display!(TestErr, T); + #[derive(Debug, Error)] + struct TestErr { + #[error(not(backtrace))] + not_backtrace: MyBacktrace, + #[error(not(backtrace))] + field: T, + } + + type MyBacktrace = Backtrace; + + assert!(TestErr { + not_backtrace: Backtrace::force_capture(), + field: 0 + } + .backtrace() + .is_none()); +} + +#[test] +fn named_explicit_backtrace_by_field_name_redundant() { + derive_display!(TestErr, T); + #[derive(Debug, Error)] + struct TestErr { + #[error(backtrace)] + backtrace: MyBacktrace, + field: T, + } + + type MyBacktrace = Backtrace; + + let err = TestErr { + backtrace: Backtrace::force_capture(), + field: 0, + }; + assert!(err.backtrace().is_some()); + assert_bt!(==, err); +} + +#[test] +fn named_explicit_backtrace_by_field_type_redundant() { + derive_display!(TestErr, T); + #[derive(Debug, Error)] + struct TestErr { + #[error(backtrace)] + implicit_backtrace: Backtrace, + field: T, + } + + let err = TestErr { + implicit_backtrace: Backtrace::force_capture(), + field: 0, + }; + assert!(err.backtrace().is_some()); + assert_bt!(==, err, implicit_backtrace); +} + +#[test] +fn named_explicit_supresses_implicit() { + derive_display!(TestErr, T); + #[derive(Debug, Error)] + struct TestErr { + #[error(backtrace)] + not_backtrace: MyBacktrace, + backtrace: Backtrace, + field: T, + } + + type MyBacktrace = Backtrace; + + let err = TestErr { + not_backtrace: Backtrace::force_capture(), + backtrace: (|| Backtrace::force_capture())(), // ensure backtraces are different + field: 0, + }; + + assert!(err.backtrace().is_some()); + assert_bt!(==, err, not_backtrace); + assert_bt!(!=, err); +} + +#[test] +fn unnamed_implicit_no_backtrace() { + derive_display!(TestErr, T); + #[derive(Default, Debug, Error)] + struct TestErr(T, T); + + assert!(TestErr::::default().backtrace().is_none()); +} + +#[test] +fn unnamed_implicit_backtrace() { + derive_display!(TestErr, T); + #[derive(Debug, Error)] + struct TestErr(Backtrace, T, T); + + let err = TestErr(Backtrace::force_capture(), 0, 0); + assert!(err.backtrace().is_some()); + assert_bt!(==, err, 0); +} + +#[test] +fn unnamed_explicit_no_backtrace() { + derive_display!(TestErr, T); + #[derive(Debug, Error)] + struct TestErr(#[error(not(backtrace))] Backtrace, T); + + assert!(TestErr(Backtrace::force_capture(), 0).backtrace().is_none()); +} + +#[test] +fn unnamed_explicit_backtrace() { + derive_display!(TestErr, T); + #[derive(Debug, Error)] + struct TestErr(#[error(backtrace)] MyBacktrace, T, T); + + type MyBacktrace = Backtrace; + + let err = TestErr(Backtrace::force_capture(), 0, 0); + assert!(err.backtrace().is_some()); + assert_bt!(==, err, 0); +} + +#[test] +fn unnamed_explicit_no_backtrace_redundant() { + derive_display!(TestErr, T); + #[derive(Debug, Error)] + struct TestErr( + #[error(not(backtrace))] MyBacktrace, + #[error(not(backtrace))] T, + ); + + type MyBacktrace = Backtrace; + + assert!(TestErr(Backtrace::force_capture(), 0).backtrace().is_none()); +} + +#[test] +fn unnamed_explicit_backtrace_redundant() { + derive_display!(TestErr, T); + #[derive(Debug, Error)] + struct TestErr(#[error(backtrace)] Backtrace, T, T); + + let err = TestErr(Backtrace::force_capture(), 0, 0); + assert!(err.backtrace().is_some()); + assert_bt!(==, err, 0); +} + +#[test] +fn unnamed_explicit_supresses_implicit() { + derive_display!(TestErr, T); + #[derive(Debug, Error)] + struct TestErr(#[error(backtrace)] MyBacktrace, Backtrace, T); + + type MyBacktrace = Backtrace; + + let err = TestErr( + Backtrace::force_capture(), + (|| Backtrace::force_capture())(), // ensure backtraces are different + 0, + ); + + assert!(err.backtrace().is_some()); + assert_bt!(==, err, 0); + assert_bt!(!=, err, 1); +} diff --git a/third_party/rust/derive_more/tests/error/nightly/derives_for_structs_with_backtrace.rs b/third_party/rust/derive_more/tests/error/nightly/derives_for_structs_with_backtrace.rs new file mode 100644 index 000000000000..18e268f841b2 --- /dev/null +++ b/third_party/rust/derive_more/tests/error/nightly/derives_for_structs_with_backtrace.rs @@ -0,0 +1,280 @@ +use super::*; + +#[test] +fn unit() { + assert!(SimpleErr.backtrace().is_none()); +} + +#[test] +fn named_implicit_no_backtrace() { + derive_display!(TestErr); + #[derive(Default, Debug, Error)] + struct TestErr { + field: i32, + } + + assert!(TestErr::default().backtrace().is_none()); +} + +#[test] +fn named_implicit_backtrace_by_field_name() { + derive_display!(TestErr); + #[derive(Debug, Error)] + struct TestErr { + backtrace: MyBacktrace, + field: i32, + } + + type MyBacktrace = Backtrace; + + let err = TestErr { + backtrace: Backtrace::force_capture(), + field: 0, + }; + assert!(err.backtrace().is_some()); + assert_bt!(==, err); +} + +#[test] +fn named_implicit_backtrace_by_field_type() { + derive_display!(TestErr); + #[derive(Debug, Error)] + struct TestErr { + implicit_backtrace: Backtrace, + field: i32, + } + + let err = TestErr { + implicit_backtrace: Backtrace::force_capture(), + field: 0, + }; + assert!(err.backtrace().is_some()); + assert_bt!(==, err, implicit_backtrace); +} + +#[test] +fn named_explicit_no_backtrace_by_field_name() { + derive_display!(TestErr); + #[derive(Debug, Error)] + struct TestErr { + #[error(not(backtrace))] + backtrace: MyBacktrace, + field: i32, + } + + type MyBacktrace = Backtrace; + + assert!(TestErr { + backtrace: Backtrace::force_capture(), + field: 0 + } + .backtrace() + .is_none()); +} + +#[test] +fn named_explicit_no_backtrace_by_field_type() { + derive_display!(TestErr); + #[derive(Debug, Error)] + struct TestErr { + #[error(not(backtrace))] + implicit_backtrace: Backtrace, + field: i32, + } + + assert!(TestErr { + implicit_backtrace: Backtrace::force_capture(), + field: 0 + } + .backtrace() + .is_none()); +} + +#[test] +fn named_explicit_backtrace() { + derive_display!(TestErr); + #[derive(Debug, Error)] + struct TestErr { + #[error(backtrace)] + explicit_backtrace: MyBacktrace, + field: i32, + } + + type MyBacktrace = Backtrace; + + let err = TestErr { + explicit_backtrace: Backtrace::force_capture(), + field: 0, + }; + assert!(err.backtrace().is_some()); + assert_bt!(==, err, explicit_backtrace); +} + +#[test] +fn named_explicit_no_backtrace_redundant() { + derive_display!(TestErr); + #[derive(Debug, Error)] + struct TestErr { + #[error(not(backtrace))] + not_backtrace: MyBacktrace, + #[error(not(backtrace))] + field: i32, + } + + type MyBacktrace = Backtrace; + + assert!(TestErr { + not_backtrace: Backtrace::force_capture(), + field: 0 + } + .backtrace() + .is_none()); +} + +#[test] +fn named_explicit_backtrace_by_field_name_redundant() { + derive_display!(TestErr); + #[derive(Debug, Error)] + struct TestErr { + #[error(backtrace)] + backtrace: MyBacktrace, + field: i32, + } + + type MyBacktrace = Backtrace; + + let err = TestErr { + backtrace: Backtrace::force_capture(), + field: 0, + }; + assert!(err.backtrace().is_some()); + assert_bt!(==, err); +} + +#[test] +fn named_explicit_backtrace_by_field_type_redundant() { + derive_display!(TestErr); + #[derive(Debug, Error)] + struct TestErr { + #[error(backtrace)] + implicit_backtrace: Backtrace, + field: i32, + } + + let err = TestErr { + implicit_backtrace: Backtrace::force_capture(), + field: 0, + }; + assert!(err.backtrace().is_some()); + assert_bt!(==, err, implicit_backtrace); +} + +#[test] +fn named_explicit_supresses_implicit() { + derive_display!(TestErr); + #[derive(Debug, Error)] + struct TestErr { + #[error(backtrace)] + not_backtrace: MyBacktrace, + backtrace: Backtrace, + field: i32, + } + + type MyBacktrace = Backtrace; + + let err = TestErr { + not_backtrace: Backtrace::force_capture(), + backtrace: (|| Backtrace::force_capture())(), // ensure backtraces are different + field: 0, + }; + + assert!(err.backtrace().is_some()); + assert_bt!(==, err, not_backtrace); + assert_bt!(!=, err); +} + +#[test] +fn unnamed_implicit_no_backtrace() { + derive_display!(TestErr); + #[derive(Default, Debug, Error)] + struct TestErr(i32, i32); + + assert!(TestErr::default().backtrace().is_none()); +} + +#[test] +fn unnamed_implicit_backtrace() { + derive_display!(TestErr); + #[derive(Debug, Error)] + struct TestErr(Backtrace, i32, i32); + + let err = TestErr(Backtrace::force_capture(), 0, 0); + assert!(err.backtrace().is_some()); + assert_bt!(==, err, 0); +} + +#[test] +fn unnamed_explicit_no_backtrace() { + derive_display!(TestErr); + #[derive(Debug, Error)] + struct TestErr(#[error(not(backtrace))] Backtrace, i32); + + assert!(TestErr(Backtrace::force_capture(), 0).backtrace().is_none()); +} + +#[test] +fn unnamed_explicit_backtrace() { + derive_display!(TestErr); + #[derive(Debug, Error)] + struct TestErr(#[error(backtrace)] MyBacktrace, i32, i32); + + type MyBacktrace = Backtrace; + + let err = TestErr(Backtrace::force_capture(), 0, 0); + assert!(err.backtrace().is_some()); + assert_bt!(==, err, 0); +} + +#[test] +fn unnamed_explicit_no_backtrace_redundant() { + derive_display!(TestErr); + #[derive(Debug, Error)] + struct TestErr( + #[error(not(backtrace))] MyBacktrace, + #[error(not(backtrace))] i32, + ); + + type MyBacktrace = Backtrace; + + assert!(TestErr(Backtrace::force_capture(), 0).backtrace().is_none()); +} + +#[test] +fn unnamed_explicit_backtrace_redundant() { + derive_display!(TestErr); + #[derive(Debug, Error)] + struct TestErr(#[error(backtrace)] Backtrace, i32, i32); + + let err = TestErr(Backtrace::force_capture(), 0, 0); + assert!(err.backtrace().is_some()); + assert_bt!(==, err, 0); +} + +#[test] +fn unnamed_explicit_supresses_implicit() { + derive_display!(TestErr); + #[derive(Debug, Error)] + struct TestErr(#[error(backtrace)] MyBacktrace, Backtrace, i32); + + type MyBacktrace = Backtrace; + + let err = TestErr( + Backtrace::force_capture(), + (|| Backtrace::force_capture())(), // ensure backtraces are different + 0, + ); + + assert!(err.backtrace().is_some()); + assert_bt!(==, err, 0); + assert_bt!(!=, err, 1); +} diff --git a/third_party/rust/derive_more/tests/error/nightly/mod.rs b/third_party/rust/derive_more/tests/error/nightly/mod.rs new file mode 100644 index 000000000000..57de7ba2abe9 --- /dev/null +++ b/third_party/rust/derive_more/tests/error/nightly/mod.rs @@ -0,0 +1,85 @@ +use std::backtrace::Backtrace; + +use super::*; + +/// Asserts that backtrace returned by `Error::backtrace` method equals/not-equals +/// backtrace stored in object itself. +/// +/// Comparison is done by converting backtraces to strings +/// and then comparing these strings. +/// +/// ## Syntax +/// +/// * Equals: `assert_bt!(==, ...)` +/// * Not-equals: `assert_bt!(!=, ...)` +/// +/// ### Backtrace Access +/// +/// Shortcut for named-structs with `backtrace` field. +/// Access backtrace as `error.backtrace`. +/// +/// ``` +/// assert_bt!(==, error); +/// ``` +/// +/// Full form for named- and tuple-structs. +/// Access backtrace as `error.some_other_field` and `error.1` respectively. +/// +/// ``` +/// assert_bt!(!=, error, some_other_field); +/// assert_bt!(==, error, 1); +/// ``` +/// +/// Access as a method call. +/// Useful for enums (i.e., you can define a method that will match on enum variants +/// and return backtrace for each variant). +/// Access backtrace as `error.get_stored_backtrace_method()`. +/// +/// ``` +/// assert_bt!(!=, error, .get_stored_backtrace_method); +/// ``` +macro_rules! assert_bt { + (@impl $macro:ident, $error:expr, $backtrace:expr) => { + $macro!($error.backtrace().unwrap().to_string(), $backtrace.to_string()); + }; + (@expand $macro:ident, $error:expr, .$backtrace:ident) => { + assert_bt!(@impl $macro, $error, $error.$backtrace()) + }; + (@expand $macro:ident, $error:expr, $backtrace:tt) => { + assert_bt!(@impl $macro, $error, $error.$backtrace) + }; + (@expand $macro:ident, $error:expr) => { + assert_bt!(@expand $macro, $error, backtrace) + }; + (==, $($args:tt)*) => { + assert_bt!(@expand assert_eq, $($args)*) + }; + (!=, $($args:tt)*) => { + assert_bt!(@expand assert_ne, $($args)*) + }; +} + +mod derives_for_enums_with_backtrace; +mod derives_for_generic_enums_with_backtrace; +mod derives_for_generic_structs_with_backtrace; +mod derives_for_structs_with_backtrace; + +derive_display!(BacktraceErr); +#[derive(Debug)] +struct BacktraceErr { + backtrace: Backtrace, +} + +impl Default for BacktraceErr { + fn default() -> Self { + Self { + backtrace: Backtrace::force_capture(), + } + } +} + +impl Error for BacktraceErr { + fn backtrace(&self) -> Option<&Backtrace> { + Some(&self.backtrace) + } +} diff --git a/third_party/rust/derive_more/tests/error_tests.rs b/third_party/rust/derive_more/tests/error_tests.rs new file mode 100644 index 000000000000..c2798bd148c5 --- /dev/null +++ b/third_party/rust/derive_more/tests/error_tests.rs @@ -0,0 +1,6 @@ +#![cfg_attr(feature = "nightly", feature(backtrace))] + +#[macro_use] +extern crate derive_more; + +mod error; diff --git a/third_party/rust/derive_more/tests/from.rs b/third_party/rust/derive_more/tests/from.rs new file mode 100644 index 000000000000..69836454f6db --- /dev/null +++ b/third_party/rust/derive_more/tests/from.rs @@ -0,0 +1,171 @@ +#![allow(dead_code)] +#[macro_use] +extern crate derive_more; + +#[derive(From)] +struct EmptyTuple(); + +#[derive(From)] +struct EmptyStruct {} + +#[derive(From)] +struct EmptyUnit; + +#[derive(From)] +struct MyInt(i32); + +#[derive(From)] +struct MyInts(i32, i32); + +#[derive(From)] +struct Point1D { + x: i32, +} + +#[derive(From)] +struct Point2D { + x: i32, + y: i32, +} + +#[derive(From)] +enum MixedInts { + SmallInt(i32), + NamedBigInt { + int: i64, + }, + TwoSmallInts(i32, i32), + NamedBigInts { + x: i64, + y: i64, + }, + #[from(ignore)] + Unsigned(u32), + NamedUnsigned { + x: u32, + }, +} + +#[derive(PartialEq, Eq, Debug)] +#[derive(From)] +#[from(forward)] +struct MyIntForward(u64); + +#[test] +fn forward_struct() { + assert_eq!(MyIntForward(42), 42u32.into()); + assert_eq!(MyIntForward(42), 42u16.into()); + assert_eq!(MyIntForward(42), 42u64.into()); +} + +#[derive(PartialEq, Eq, Debug)] +#[derive(From)] +enum MixedIntsForward { + #[from(forward)] + SmallInt(i32), + NamedBigInt { + int: i64, + }, +} + +#[test] +fn forward_enum() { + assert_eq!(MixedIntsForward::SmallInt(42), 42i32.into()); + assert_eq!(MixedIntsForward::SmallInt(42), 42i16.into()); +} + +#[derive(From, PartialEq)] +enum AutoIgnore { + SmallInt(i32), + Uninteresting, + Uninteresting2, +} + +#[test] +fn auto_ignore_variants() { + assert!(AutoIgnore::SmallInt(42) == 42i32.into()); +} + +#[derive(From, PartialEq)] +enum AutoIgnoreWithDefaultTrue { + #[from(ignore)] + SmallInt(i32), + Uninteresting, + Uninteresting2, +} + +#[derive(From, PartialEq)] +enum AutoIgnoreWithForwardFields2 { + #[from(forward)] + SmallInt(i32), + SmallIntIgnore(i32), +} + +#[test] +fn auto_ignore_with_forward_field2() { + assert!(AutoIgnoreWithForwardFields2::SmallInt(42) == 42i32.into()); + assert!(AutoIgnoreWithForwardFields2::SmallInt(42) == 42i16.into()); +} + +#[derive(Debug, Eq, PartialEq)] +#[derive(From)] +#[from(types(u8, u16, u32))] +struct MyIntExplicit(u64); + +#[test] +fn explicit_types_struct() { + assert_eq!(MyIntExplicit(42), 42u8.into()); + assert_eq!(MyIntExplicit(42), 42u16.into()); + assert_eq!(MyIntExplicit(42), 42u32.into()); + assert_eq!(MyIntExplicit(42), 42u64.into()); +} + +#[derive(Debug, Eq, PartialEq)] +#[derive(From)] +#[from(types(i8, i16))] +struct MyIntsExplicit(i32, i32); + +#[test] +fn explicit_types_struct_tupled() { + assert_eq!(MyIntsExplicit(42, 42), (42i32, 42i32).into()); + assert_eq!(MyIntsExplicit(42, 42), (42i8, 42i8).into()); + assert_eq!(MyIntsExplicit(42, 42), (42i16, 42i16).into()); +} + +#[derive(Debug, Eq, PartialEq)] +#[derive(From)] +enum MixedIntsExplicit { + #[from(types(i8))] + SmallInt(i32), + #[from(types(i16, i64))] + AnotherInt(i128), + NamedBigInt { + int: i64, + }, +} + +#[test] +fn explicit_types_enum() { + assert_eq!(MixedIntsExplicit::SmallInt(42), 42i32.into()); + assert_eq!(MixedIntsExplicit::SmallInt(42), 42i8.into()); + + assert_eq!(MixedIntsExplicit::AnotherInt(42), 42i128.into()); + assert_eq!(MixedIntsExplicit::AnotherInt(42), 42i64.into()); + assert_eq!(MixedIntsExplicit::AnotherInt(42), 42i16.into()); +} + +#[derive(Debug, Eq, PartialEq)] +#[derive(From)] +#[from(types(i8, i16))] +struct Point2DExplicit { + x: i32, + y: i32, +} + +#[test] +fn explicit_types_point_2d() { + let expected = Point2DExplicit { x: 42, y: 42 }; + assert_eq!(expected, (42i32, 42i32).into()); + assert_eq!(expected, (42i8, 42i8).into()); + assert_eq!(expected, (42i16, 42i16).into()); +} diff --git a/third_party/rust/derive_more/tests/from_str.rs b/third_party/rust/derive_more/tests/from_str.rs new file mode 100644 index 000000000000..4bb0eca636ca --- /dev/null +++ b/third_party/rust/derive_more/tests/from_str.rs @@ -0,0 +1,11 @@ +#![allow(dead_code)] +#[macro_use] +extern crate derive_more; + +#[derive(FromStr)] +struct MyInt(i32); + +#[derive(FromStr)] +struct Point1D { + x: i32, +} diff --git a/third_party/rust/derive_more/tests/generics.rs b/third_party/rust/derive_more/tests/generics.rs new file mode 100644 index 000000000000..8f22cd50597e --- /dev/null +++ b/third_party/rust/derive_more/tests/generics.rs @@ -0,0 +1,103 @@ +#![allow(dead_code, non_camel_case_types)] +#[macro_use] +extern crate derive_more; + +#[derive( + From, + FromStr, + Display, + Index, + Not, + Add, + Mul, + Sum, + IndexMut, + AddAssign, + MulAssign, + Deref, + DerefMut, + IntoIterator, + Constructor +)] +#[deref(forward)] +#[deref_mut(forward)] +#[into_iterator(owned, ref, ref_mut)] +struct Wrapped(T); + +#[derive(Deref, DerefMut)] +struct Wrapped2(T); + +#[derive(From, Not, Add, Mul, AddAssign, MulAssign, Constructor, Sum)] +struct WrappedDouble(T, U); + +#[derive(From)] +#[from(forward)] +struct WrappedDouble2(T, U); + +#[derive( + From, + FromStr, + Display, + Index, + Not, + Add, + Mul, + IndexMut, + AddAssign, + MulAssign, + Deref, + DerefMut, + IntoIterator, + Constructor, + Sum +)] +#[deref(forward)] +#[deref_mut(forward)] +#[into_iterator(owned, ref, ref_mut)] +struct Struct { + t: T, +} + +#[derive(Deref, DerefMut)] +struct Struct2 { + t: T, +} + +#[derive(From, Not, Add, Mul, AddAssign, MulAssign, Constructor, Sum)] +struct DoubleStruct { + t: T, + u: U, +} + +#[derive(From)] +#[from(forward)] +struct DoubleStruct2 { + t: T, + u: U, +} + +#[derive(From, Not, Add)] +enum TupleEnum { + Tuple(T), + DoubleTuple(T, U), +} + +#[derive(From)] +#[from(forward)] +enum TupleEnum2 { + DoubleTuple(T, U), + TripleTuple(T, U, X), +} + +#[derive(From, Not, Add)] +enum StructEnum { + Struct { t: T }, + DoubleStruct { t: T, u: U }, +} + +#[derive(From)] +#[from(forward)] +enum StructEnum2 { + DoubleStruct { t: T, u: U }, + TripleStruct { t: T, u: U, x: X }, +} diff --git a/third_party/rust/derive_more/tests/index.rs b/third_party/rust/derive_more/tests/index.rs new file mode 100644 index 000000000000..952223c09b9e --- /dev/null +++ b/third_party/rust/derive_more/tests/index.rs @@ -0,0 +1,13 @@ +#![allow(dead_code, unused_imports)] +#[macro_use] +extern crate derive_more; + +#[derive(Index)] +struct MyVec(Vec); + +#[derive(Index)] +struct Numbers { + #[index] + numbers: Vec, + useless: bool, +} diff --git a/third_party/rust/derive_more/tests/index_mut.rs b/third_party/rust/derive_more/tests/index_mut.rs new file mode 100644 index 000000000000..a053fd332b43 --- /dev/null +++ b/third_party/rust/derive_more/tests/index_mut.rs @@ -0,0 +1,36 @@ +#![allow(dead_code, unused_imports)] +#[macro_use] +extern crate derive_more; + +#[derive(IndexMut)] +struct MyVec(Vec); +//Index implementation is required for IndexMut +impl<__IdxT> ::core::ops::Index<__IdxT> for MyVec +where + Vec: ::core::ops::Index<__IdxT>, +{ + type Output = as ::core::ops::Index<__IdxT>>::Output; + #[inline] + fn index(&self, idx: __IdxT) -> &Self::Output { + as ::core::ops::Index<__IdxT>>::index(&self.0, idx) + } +} + +#[derive(IndexMut)] +struct Numbers { + #[index_mut] + numbers: Vec, + useless: bool, +} + +//Index implementation is required for IndexMut +impl<__IdxT> ::core::ops::Index<__IdxT> for Numbers +where + Vec: ::core::ops::Index<__IdxT>, +{ + type Output = as ::core::ops::Index<__IdxT>>::Output; + #[inline] + fn index(&self, idx: __IdxT) -> &Self::Output { + as ::core::ops::Index<__IdxT>>::index(&self.numbers, idx) + } +} diff --git a/third_party/rust/derive_more/tests/into.rs b/third_party/rust/derive_more/tests/into.rs new file mode 100644 index 000000000000..f94b88f82ed9 --- /dev/null +++ b/third_party/rust/derive_more/tests/into.rs @@ -0,0 +1,126 @@ +#![allow(dead_code)] +#[macro_use] +extern crate derive_more; + +#[derive(Into)] +#[into(owned, ref, ref_mut)] +struct EmptyTuple(); + +#[derive(Into)] +#[into(owned, ref, ref_mut)] +struct EmptyStruct {} + +#[derive(Into)] +#[into(owned, ref, ref_mut)] +struct EmptyUnit; + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[derive(Into)] +#[into(owned(types(i64, i128)), ref, ref_mut)] +struct MyInt(i32); + +#[test] +fn explicit_types_struct_owned_only() { + assert_eq!(i32::from(MyInt(42)), 42i32); + assert_eq!(<&i32>::from(&MyInt(42)), &42i32); + assert_eq!(<&mut i32>::from(&mut MyInt(42)), &mut 42i32); + assert_eq!(i64::from(MyInt(42)), 42i64); + assert_eq!(i128::from(MyInt(42)), 42i128); +} + +#[derive(Into)] +#[into(owned, ref, ref_mut)] +struct MyInts(i32, i32); + +#[derive(Into)] +#[into(owned, ref, ref_mut)] +struct Point1D { + x: i32, +} + +#[derive(Debug, Eq, PartialEq)] +#[derive(Into)] +#[into(owned, ref, ref_mut)] +struct Point2D { + x: i32, + y: i32, +} + +#[derive(Into)] +#[into(owned, ref, ref_mut)] +struct Point2DWithIgnored { + x: i32, + y: i32, + #[into(ignore)] + useless: bool, +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[derive(Into)] +#[into(owned(types(i64, i128)), ref, ref_mut, types(i32))] +struct MyIntExplicit(MyInt); + +#[test] +fn explicit_types_struct_all() { + let mut input = MyIntExplicit(MyInt(42)); + assert_eq!(MyInt::from(input), MyInt(42)); + assert_eq!(<&MyInt>::from(&input), &MyInt(42)); + assert_eq!(<&mut MyInt>::from(&mut input), &mut MyInt(42)); + assert_eq!(i32::from(input), 42i32); + assert_eq!(<&i32>::from(&input), &42i32); + assert_eq!(<&mut i32>::from(&mut input), &mut 42i32); + assert_eq!(i64::from(input), 42i64); + assert_eq!(i128::from(input), 42i128); +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[derive(Into)] +#[into(owned(types(i32, i64, i128)), ref(types(i32)), ref_mut(types(i32)))] +struct MyIntsExplicit(i32, MyInt, MyIntExplicit); + +#[test] +fn explicit_types_struct_tupled() { + let mut input = MyIntsExplicit(42i32, MyInt(42), MyIntExplicit(MyInt(42))); + assert_eq!( + <(i32, MyInt, MyIntExplicit)>::from(input), + (42i32, MyInt(42), MyIntExplicit(MyInt(42))), + ); + assert_eq!( + <(&i32, &MyInt, &MyIntExplicit)>::from(&input), + (&42i32, &MyInt(42), &MyIntExplicit(MyInt(42))), + ); + assert_eq!( + <(&mut i32, &mut MyInt, &mut MyIntExplicit)>::from(&mut input), + (&mut 42i32, &mut MyInt(42), &mut MyIntExplicit(MyInt(42))), + ); + assert_eq!(<(i32, i32, i32)>::from(input), (42i32, 42i32, 42i32)); + assert_eq!(<(&i32, &i32, &i32)>::from(&input), (&42i32, &42i32, &42i32)); + assert_eq!( + <(&mut i32, &mut i32, &mut i32)>::from(&mut input), + (&mut 42i32, &mut 42i32, &mut 42i32), + ); + assert_eq!(<(i64, i64, i64)>::from(input), (42i64, 42i64, 42i64)); + assert_eq!(<(i128, i128, i128)>::from(input), (42i128, 42i128, 42i128)); +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[derive(Into)] +#[into(owned, ref, ref_mut, types(i32))] +struct Point2DExplicit { + x: MyInt, + y: MyInt, +} + +#[test] +fn explicit_types_point_2d() { + let mut input = Point2DExplicit { + x: MyInt(42), + y: MyInt(42), + }; + assert_eq!(<(i32, i32)>::from(input), (42i32, 42i32)); + assert_eq!(<(&i32, &i32)>::from(&input), (&42i32, &42i32)); + assert_eq!( + <(&mut i32, &mut i32)>::from(&mut input), + (&mut 42i32, &mut 42i32) + ); +} diff --git a/third_party/rust/derive_more/tests/into_iterator.rs b/third_party/rust/derive_more/tests/into_iterator.rs new file mode 100644 index 000000000000..8c0e48f57157 --- /dev/null +++ b/third_party/rust/derive_more/tests/into_iterator.rs @@ -0,0 +1,39 @@ +#![allow(dead_code, unused_imports)] +#[macro_use] +extern crate derive_more; + +#[derive(IntoIterator)] +#[into_iterator(owned, ref, ref_mut)] +struct MyVec(Vec); + +#[derive(IntoIterator)] +#[into_iterator(owned, ref, ref_mut)] +struct Numbers { + numbers: Vec, +} + +#[derive(IntoIterator)] +struct Numbers2 { + #[into_iterator(owned, ref, ref_mut)] + numbers: Vec, + useless: bool, + useless2: bool, +} + +#[derive(IntoIterator)] +struct Numbers3 { + #[into_iterator(ref, ref_mut)] + numbers: Vec, + useless: bool, + useless2: bool, +} + +// Test that owned is not enabled when ref/ref_mut are enabled without owned +impl ::core::iter::IntoIterator for Numbers3 { + type Item = as ::core::iter::IntoIterator>::Item; + type IntoIter = as ::core::iter::IntoIterator>::IntoIter; + #[inline] + fn into_iter(self) -> Self::IntoIter { + as ::core::iter::IntoIterator>::into_iter(self.numbers) + } +} diff --git a/third_party/rust/derive_more/tests/lib.rs b/third_party/rust/derive_more/tests/lib.rs new file mode 100644 index 000000000000..27fd53d3314e --- /dev/null +++ b/third_party/rust/derive_more/tests/lib.rs @@ -0,0 +1,275 @@ +#[macro_use] +extern crate derive_more; + +#[derive(From)] +#[derive(Into)] +#[derive(Constructor)] +#[derive(Eq, PartialEq, Debug, Clone)] +#[derive(Add)] +#[derive(Mul)] +#[derive(Neg)] +#[derive(AddAssign)] +#[derive(MulAssign)] +#[derive(FromStr)] +#[derive(Display)] +#[derive(Octal)] +#[derive(Binary)] +#[derive(Deref, DerefMut)] +#[into(owned, ref, ref_mut)] +struct MyInt(i32); + +#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Add)] +#[derive(Sum)] +#[derive(Mul)] +#[derive(MulAssign)] +#[derive(Product)] +#[mul(forward)] +#[mul_assign(forward)] +struct MyInt2(i32); + +#[derive(Eq, PartialEq, Debug)] +#[derive(Index, IndexMut)] +#[derive(Deref, DerefMut)] +#[derive(IntoIterator)] +#[deref(forward)] +#[deref_mut(forward)] +#[into_iterator(owned, ref, ref_mut)] +struct MyVec(Vec); + +#[derive(Eq, PartialEq, Debug)] +#[derive(Deref, DerefMut)] +#[deref(forward)] +#[deref_mut(forward)] +struct MyBoxedInt(Box); + +#[derive(Eq, PartialEq, Debug)] +#[derive(Not)] +#[derive(From)] +struct MyBool(bool); + +#[derive(From)] +#[derive(Into)] +#[derive(Constructor)] +#[derive(Add)] +#[derive(Eq, PartialEq, Debug)] +#[derive(Mul)] +#[derive(AddAssign)] +struct MyUInt(u64, u64); + +#[derive(From)] +#[derive(Into)] +#[derive(Constructor)] +#[derive(FromStr)] +#[derive(Eq, PartialEq, Debug)] +#[derive(Display)] +struct SimpleStruct { + int1: u64, +} + +#[derive(From)] +#[derive(Constructor)] +#[derive(Add, Sub, Mul, Div, Rem, BitAnd, BitOr, BitXor, Shr, Shl)] +#[derive(Eq, PartialEq, Debug, Clone, Copy)] +#[derive(Into)] +#[derive(AddAssign)] +#[into(owned, ref, ref_mut)] +struct NormalStruct { + int1: u64, + int2: u64, +} + +#[derive(From)] +#[derive(Eq, PartialEq, Debug)] +struct NestedInt(MyInt); + +#[derive(Eq, PartialEq, Debug)] +#[derive(From)] +#[derive(Add, Sub)] +enum SimpleMyIntEnum { + Int(i32), + #[from(ignore)] + _UnsignedOne(u32), + _UnsignedTwo(u32), +} +#[derive(Eq, PartialEq, Debug)] +#[derive(From)] +#[derive(Neg)] +enum SimpleSignedIntEnum { + Int(i32), + Int2(i16), +} + +#[derive(Eq, PartialEq, Debug)] +#[derive(From)] +#[derive(Add, Sub)] +#[derive(Neg)] +enum SimpleEnum { + Int(i32), + #[from(ignore)] + _Ints(i32, i32), + LabeledInts { + a: i32, + b: i32, + }, + _SomeUnit, +} + +#[derive(Eq, PartialEq, Debug)] +#[derive(From)] +#[derive(Add, Sub)] +enum MyIntEnum { + SmallInt(i32), + BigInt(i64), + TwoInts(i32, i32), + Point2D { + x: i64, + y: i64, + }, + #[from(ignore)] + _UnsignedOne(u32), + _UnsignedTwo(u32), + #[from(ignore)] + _Uints1(u64, u64), + _Uints2 { + x: u64, + y: u64, + }, + Nothing, +} + +#[derive(Eq, PartialEq, Debug)] +#[derive(Add, Mul)] +struct DoubleUInt(u32, u32); + +#[derive(Eq, PartialEq, Debug)] +#[derive(Add, Mul)] +struct DoubleUIntStruct { + x: u32, + y: u32, +} + +#[derive(Eq, PartialEq, Debug)] +#[derive(From, Into, Constructor)] +struct Unit; + +// Tests that we can forward to a path +// containing `$crate` +macro_rules! use_dollar_crate { + () => { + struct Foo; + #[derive(From)] + enum Bar { + First(#[from(forward)] $crate::Foo), + } + }; +} + +use_dollar_crate!(); + +#[test] +fn main() { + let mut myint: MyInt = 5.into(); + let _: SimpleMyIntEnum = 5i32.into(); + let _: MyIntEnum = 5i32.into(); + let _: MyIntEnum = 6i64.into(); + let _: MyIntEnum = (5i32, 8i32).into(); + let _: MyIntEnum = (5i64, 8i64).into(); + let _: MyIntEnum = ().into(); + + let int_ref: &i32 = (&myint).into(); + assert_eq!(int_ref, &5); + + let int_ref_mut: &mut i32 = (&mut myint).into(); + assert_eq!(int_ref_mut, &mut 5); + + let mut myint: MyInt = 5.into(); + let _: Unit = ().into(); + assert_eq!((), Unit.into()); + assert_eq!(Unit, Unit::new()); + assert_eq!(MyInt(5), 5.into()); + assert_eq!(Ok(MyInt(5)), "5".parse()); + assert_eq!(5, MyInt(5).into()); + assert_eq!(MyInt(5), MyInt::new(5)); + assert_eq!(-MyInt(5), (-5).into()); + assert_eq!("30", format!("{}", MyInt(30))); + assert_eq!("36", format!("{:o}", MyInt(30))); + assert_eq!("100", format!("{:b}", MyInt(4))); + assert_eq!(!MyBool(true), false.into()); + assert_eq!(MyIntEnum::SmallInt(5), 5.into()); + + assert_eq!(SimpleStruct { int1: 5 }, 5.into()); + assert_eq!(5u64, SimpleStruct { int1: 5 }.into()); + assert_eq!(Ok(SimpleStruct { int1: 5 }), "5".parse()); + assert_eq!("5", format!("{}", SimpleStruct { int1: 5 })); + assert_eq!(NormalStruct { int1: 5, int2: 6 }, (5, 6).into()); + assert_eq!(SimpleStruct { int1: 5 }, SimpleStruct::new(5)); + assert_eq!(NormalStruct { int1: 5, int2: 6 }, NormalStruct::new(5, 6)); + assert_eq!((5, 6), NormalStruct::new(5, 6).into()); + let mut norm_struct = NormalStruct::new(5, 6); + let uints_ref: (&u64, &u64) = (&norm_struct).into(); + assert_eq!((&5, &6), uints_ref); + let uints_ref_mut: (&mut u64, &mut u64) = (&mut norm_struct).into(); + assert_eq!((&mut 5, &mut 6), uints_ref_mut); + + assert_eq!(MyInt(4) + MyInt(1), 5.into()); + myint += MyInt(3); + assert_eq!(myint, 8.into()); + myint *= 5; + assert_eq!(myint, 40.into()); + assert_eq!(MyInt(4) + MyInt(1), 5.into()); + assert_eq!(MyUInt(4, 5) + MyUInt(1, 2), MyUInt(5, 7)); + assert_eq!(MyUInt(4, 5), MyUInt::new(4, 5)); + assert_eq!((4, 5), MyUInt(4, 5).into()); + let mut s1 = NormalStruct { int1: 1, int2: 2 }; + let s2 = NormalStruct { int1: 2, int2: 3 }; + let s3 = NormalStruct { int1: 3, int2: 5 }; + assert_eq!(s1 + s2, s3); + assert_eq!(s3 - s2, s1); + s1 += s2; + assert_eq!(s1, s3); + + assert_eq!((SimpleMyIntEnum::Int(6) + 5.into()).unwrap(), 11.into()); + assert_eq!((SimpleMyIntEnum::Int(6) - 5.into()).unwrap(), 1.into()); + assert_eq!((SimpleMyIntEnum::Int(6) - 5.into()).unwrap(), 1.into()); + assert_eq!(-SimpleSignedIntEnum::Int(6), (-6i32).into()); + assert_eq!( + (SimpleEnum::LabeledInts { a: 6, b: 5 } + + SimpleEnum::LabeledInts { a: 1, b: 4 }) + .unwrap(), + SimpleEnum::LabeledInts { a: 7, b: 9 } + ); + + let _ = (MyIntEnum::SmallInt(5) + 6.into()).unwrap(); + assert_eq!((-SimpleEnum::Int(5)).unwrap(), (-5).into()); + + assert_eq!(MyInt(50), MyInt(5) * 10); + assert_eq!(DoubleUInt(5, 6) * 10, DoubleUInt(50, 60)); + // assert_eq!(DoubleUIntStruct{x:5, y:6} * 10, DoubleUIntStruct{x:50, y:60}); + + let mut myint = MyInt(5); + assert_eq!(5, *myint); + *myint = 7; + assert_eq!(MyInt(7), myint); + + let mut my_vec = MyVec(vec![5, 8]); + assert_eq!(5, my_vec[0]); + assert_eq!(8, my_vec[1]); + my_vec[0] = 20; + assert_eq!(20, my_vec[0]); + assert_eq!((&my_vec).into_iter().next(), Some(&20)); + assert_eq!((&mut my_vec).into_iter().next(), Some(&mut 20)); + assert_eq!(my_vec.into_iter().next(), Some(20)); + + let int_vec = vec![MyInt2(2), MyInt2(3)]; + assert_eq!(MyInt2(5), int_vec.clone().into_iter().sum()); + assert_eq!(MyInt2(6), int_vec.clone().into_iter().product()); + let mut myint2 = MyInt2(8); + myint2 *= MyInt2(4); + assert_eq!(MyInt2(32), myint2); + + let mut boxed = MyBoxedInt(Box::new(5)); + assert_eq!(5, *boxed); + *boxed = 7; + assert_eq!(MyBoxedInt(Box::new(7)), boxed) +} diff --git a/third_party/rust/derive_more/tests/mul.rs b/third_party/rust/derive_more/tests/mul.rs new file mode 100644 index 000000000000..192806032d2d --- /dev/null +++ b/third_party/rust/derive_more/tests/mul.rs @@ -0,0 +1,20 @@ +#![allow(dead_code)] +#[macro_use] +extern crate derive_more; + +#[derive(Mul)] +struct MyInt(i32); + +#[derive(Mul)] +struct MyInts(i32, i32); + +#[derive(Mul)] +struct Point1D { + x: i32, +} + +#[derive(Mul)] +struct Point2D { + x: i32, + y: i32, +} diff --git a/third_party/rust/derive_more/tests/mul_assign.rs b/third_party/rust/derive_more/tests/mul_assign.rs new file mode 100644 index 000000000000..f8aee3e18969 --- /dev/null +++ b/third_party/rust/derive_more/tests/mul_assign.rs @@ -0,0 +1,32 @@ +#![allow(dead_code)] +use std::marker::PhantomData; + +#[macro_use] +extern crate derive_more; + +#[derive(MulAssign)] +struct MyInt(i32); + +#[derive(MulAssign)] +struct MyInts(i32, i32); + +#[derive(MulAssign)] +#[mul_assign(forward)] +struct MyIntForward(i32); + +#[derive(MulAssign)] +struct Point1D { + x: i32, +} + +#[derive(MulAssign)] +struct Point2D { + x: i32, + y: i32, +} + +#[derive(MulAssign)] +struct MyInt2 { + x: i32, + ph: PhantomData, +} diff --git a/third_party/rust/derive_more/tests/no_std.rs b/third_party/rust/derive_more/tests/no_std.rs new file mode 100644 index 000000000000..a6680c38c238 --- /dev/null +++ b/third_party/rust/derive_more/tests/no_std.rs @@ -0,0 +1,74 @@ +#![no_std] +#![allow(dead_code)] + +#[macro_use] +extern crate derive_more; + +#[derive( + AddAssign, + MulAssign, + Add, + Mul, + Not, + Index, + Display, + FromStr, + Into, + From, + IndexMut, + Sum, + Deref, + DerefMut, + Constructor +)] +#[into(owned, ref, ref_mut)] +struct MyInts(u64); + +#[derive(Deref, DerefMut)] +#[deref(forward)] +#[deref_mut(forward)] +struct MyBoxedInt<'a>(&'a mut u64); + +#[derive( + From, + FromStr, + Display, + Index, + Not, + Add, + Mul, + Sum, + IndexMut, + AddAssign, + Deref, + DerefMut, + IntoIterator, + Constructor +)] +#[deref(forward)] +#[deref_mut(forward)] +#[into_iterator(owned, ref, ref_mut)] +struct Wrapped(T); + +#[derive(Deref, DerefMut)] +struct Wrapped2(T); + +#[derive(From, Not, Add, Mul, AddAssign, Constructor, Sum)] +struct WrappedDouble(T, U); + +#[derive(Add, Not, TryInto)] +#[try_into(owned, ref, ref_mut)] +enum MixedInts { + SmallInt(i32), + BigInt(i64), + TwoSmallInts(i32, i32), + NamedSmallInts { x: i32, y: i32 }, + UnsignedOne(u32), + UnsignedTwo(u32), +} + +#[derive(Not, Add)] +enum EnumWithUnit { + SmallInt(i32), + Unit, +} diff --git a/third_party/rust/derive_more/tests/not.rs b/third_party/rust/derive_more/tests/not.rs new file mode 100644 index 000000000000..7e3ad8d01e48 --- /dev/null +++ b/third_party/rust/derive_more/tests/not.rs @@ -0,0 +1,28 @@ +#![allow(dead_code)] +#[macro_use] +extern crate derive_more; + +#[derive(Not)] +struct MyInts(i32, i32); + +#[derive(Not)] +struct Point2D { + x: i32, + y: i32, +} + +#[derive(Not)] +enum MixedInts { + SmallInt(i32), + BigInt(i64), + TwoSmallInts(i32, i32), + NamedSmallInts { x: i32, y: i32 }, + UnsignedOne(u32), + UnsignedTwo(u32), +} + +#[derive(Not)] +enum EnumWithUnit { + SmallInt(i32), + Unit, +} diff --git a/third_party/rust/derive_more/tests/sum.rs b/third_party/rust/derive_more/tests/sum.rs new file mode 100644 index 000000000000..a0b0967bd91d --- /dev/null +++ b/third_party/rust/derive_more/tests/sum.rs @@ -0,0 +1,31 @@ +#[macro_use] +extern crate derive_more; + +#[derive(Sum)] +struct MyInts(i32, i64); + +// Add implementation is needed for Sum +impl ::core::ops::Add for MyInts { + type Output = MyInts; + #[inline] + fn add(self, rhs: MyInts) -> MyInts { + MyInts(self.0.add(rhs.0), self.1.add(rhs.1)) + } +} + +#[derive(Sum)] +struct Point2D { + x: i32, + y: i32, +} + +impl ::core::ops::Add for Point2D { + type Output = Point2D; + #[inline] + fn add(self, rhs: Point2D) -> Point2D { + Point2D { + x: self.x.add(rhs.x), + y: self.y.add(rhs.y), + } + } +} diff --git a/third_party/rust/derive_more/tests/try_into.rs b/third_party/rust/derive_more/tests/try_into.rs new file mode 100644 index 000000000000..837c8e991315 --- /dev/null +++ b/third_party/rust/derive_more/tests/try_into.rs @@ -0,0 +1,199 @@ +#![allow(dead_code)] + +#[macro_use] +extern crate derive_more; + +use std::convert::{TryFrom, TryInto}; + +// Ensure that the TryFrom macro is hygenic and doesn't break when `Result` has +// been redefined. +type Result = (); + +#[derive(Clone, Copy, TryInto)] +#[try_into(owned, ref, ref_mut)] +enum MixedInts { + SmallInt(i32), + NamedBigInt { + int: i64, + }, + UnsignedWithIgnoredField(#[try_into(ignore)] bool, i64), + NamedUnsignedWithIgnnoredField { + #[try_into(ignore)] + useless: bool, + x: i64, + }, + TwoSmallInts(i32, i32), + NamedBigInts { + x: i64, + y: i64, + }, + Unsigned(u32), + NamedUnsigned { + x: u32, + }, + Unit, + #[try_into(ignore)] + Unit2, +} + +#[test] +fn test_try_into() { + let mut i = MixedInts::SmallInt(42); + assert_eq!(Ok(42i32), i.try_into()); + assert_eq!(Ok(&42i32), (&i).try_into()); + assert_eq!(Ok(&mut 42i32), (&mut i).try_into()); + assert_eq!( + i64::try_from(i), + Err("Only NamedBigInt, UnsignedWithIgnoredField, NamedUnsignedWithIgnnoredField can be converted to i64") + ); + assert_eq!( + <(i32, i32)>::try_from(i), + Err("Only TwoSmallInts can be converted to (i32, i32)") + ); + assert_eq!( + <(i64, i64)>::try_from(i), + Err("Only NamedBigInts can be converted to (i64, i64)") + ); + assert_eq!( + u32::try_from(i), + Err("Only Unsigned, NamedUnsigned can be converted to u32") + ); + assert_eq!(<()>::try_from(i), Err("Only Unit can be converted to ()")); + + let mut i = MixedInts::NamedBigInt { int: 42 }; + assert_eq!( + i32::try_from(i), + Err("Only SmallInt can be converted to i32") + ); + assert_eq!(Ok(42i64), i.try_into()); + assert_eq!(Ok(&42i64), (&i).try_into()); + assert_eq!(Ok(&mut 42i64), (&mut i).try_into()); + assert_eq!( + <(i32, i32)>::try_from(i), + Err("Only TwoSmallInts can be converted to (i32, i32)") + ); + assert_eq!( + <(i64, i64)>::try_from(i), + Err("Only NamedBigInts can be converted to (i64, i64)") + ); + assert_eq!( + u32::try_from(i), + Err("Only Unsigned, NamedUnsigned can be converted to u32") + ); + assert_eq!(<()>::try_from(i), Err("Only Unit can be converted to ()")); + + let mut i = MixedInts::TwoSmallInts(42, 64); + assert_eq!( + i32::try_from(i), + Err("Only SmallInt can be converted to i32") + ); + assert_eq!( + i64::try_from(i), + Err("Only NamedBigInt, UnsignedWithIgnoredField, NamedUnsignedWithIgnnoredField can be converted to i64") + ); + assert_eq!(Ok((42i32, 64i32)), i.try_into()); + assert_eq!(Ok((&42i32, &64i32)), (&i).try_into()); + assert_eq!(Ok((&mut 42i32, &mut 64i32)), (&mut i).try_into()); + assert_eq!( + <(i64, i64)>::try_from(i), + Err("Only NamedBigInts can be converted to (i64, i64)") + ); + assert_eq!( + u32::try_from(i), + Err("Only Unsigned, NamedUnsigned can be converted to u32") + ); + assert_eq!(<()>::try_from(i), Err("Only Unit can be converted to ()")); + + let mut i = MixedInts::NamedBigInts { x: 42, y: 64 }; + assert_eq!( + i32::try_from(i), + Err("Only SmallInt can be converted to i32") + ); + assert_eq!( + i64::try_from(i), + Err("Only NamedBigInt, UnsignedWithIgnoredField, NamedUnsignedWithIgnnoredField can be converted to i64") + ); + assert_eq!( + <(i32, i32)>::try_from(i), + Err("Only TwoSmallInts can be converted to (i32, i32)") + ); + assert_eq!(Ok((42i64, 64i64)), i.try_into()); + assert_eq!(Ok((&42i64, &64i64)), (&i).try_into()); + assert_eq!(Ok((&mut 42i64, &mut 64i64)), (&mut i).try_into()); + assert_eq!( + u32::try_from(i), + Err("Only Unsigned, NamedUnsigned can be converted to u32") + ); + assert_eq!(<()>::try_from(i), Err("Only Unit can be converted to ()")); + + let mut i = MixedInts::Unsigned(42); + assert_eq!( + i32::try_from(i), + Err("Only SmallInt can be converted to i32") + ); + assert_eq!( + i64::try_from(i), + Err("Only NamedBigInt, UnsignedWithIgnoredField, NamedUnsignedWithIgnnoredField can be converted to i64") + ); + assert_eq!( + <(i32, i32)>::try_from(i), + Err("Only TwoSmallInts can be converted to (i32, i32)") + ); + assert_eq!( + <(i64, i64)>::try_from(i), + Err("Only NamedBigInts can be converted to (i64, i64)") + ); + assert_eq!(Ok(42u32), i.try_into()); + assert_eq!(Ok(&42u32), (&i).try_into()); + assert_eq!(Ok(&mut 42u32), (&mut i).try_into()); + assert_eq!(<()>::try_from(i), Err("Only Unit can be converted to ()")); + + let mut i = MixedInts::NamedUnsigned { x: 42 }; + assert_eq!( + i32::try_from(i), + Err("Only SmallInt can be converted to i32") + ); + assert_eq!( + i64::try_from(i), + Err("Only NamedBigInt, UnsignedWithIgnoredField, NamedUnsignedWithIgnnoredField can be converted to i64") + ); + assert_eq!( + i64::try_from(i), + Err("Only NamedBigInt, UnsignedWithIgnoredField, NamedUnsignedWithIgnnoredField can be converted to i64") + ); + assert_eq!( + <(i32, i32)>::try_from(i), + Err("Only TwoSmallInts can be converted to (i32, i32)") + ); + assert_eq!( + <(i64, i64)>::try_from(i), + Err("Only NamedBigInts can be converted to (i64, i64)") + ); + assert_eq!(Ok(42u32), i.try_into()); + assert_eq!(Ok(&42u32), (&i).try_into()); + assert_eq!(Ok(&mut 42u32), (&mut i).try_into()); + assert_eq!(<()>::try_from(i), Err("Only Unit can be converted to ()")); + + let i = MixedInts::Unit; + assert_eq!( + i32::try_from(i), + Err("Only SmallInt can be converted to i32") + ); + assert_eq!( + i64::try_from(i), + Err("Only NamedBigInt, UnsignedWithIgnoredField, NamedUnsignedWithIgnnoredField can be converted to i64") + ); + assert_eq!( + <(i32, i32)>::try_from(i), + Err("Only TwoSmallInts can be converted to (i32, i32)") + ); + assert_eq!( + <(i64, i64)>::try_from(i), + Err("Only NamedBigInts can be converted to (i64, i64)") + ); + assert_eq!( + u32::try_from(i), + Err("Only Unsigned, NamedUnsigned can be converted to u32") + ); + assert_eq!(Ok(()), i.try_into()); +}