From 74632ceb93ec369deafe73379885c0b747298e3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Fri, 2 Oct 2020 19:15:26 +0000 Subject: [PATCH] Bug 1668514 - Update crossbeam-channel. r=janerik It's used by both webrender and fog, and it contains a subtle soundness issue which may affect us, see: * https://github.com/crossbeam-rs/crossbeam/pull/533 * https://twitter.com/khuey_/status/1311641831201857537 Quoting for posterity: > There is a 0.4.4 on a branch and it contains a reversion for the UB > mentioned in https://github.com/crossbeam-rs/crossbeam/pull/533. > > This was causing corruption of jemalloc structures (and ultimately a > deadlock) for us. Update the crate resolving the issue. Differential Revision: https://phabricator.services.mozilla.com/D92046 --- Cargo.lock | 12 +- .../crossbeam-channel/.cargo-checksum.json | 2 +- .../rust/crossbeam-channel/CHANGELOG.md | 5 + third_party/rust/crossbeam-channel/Cargo.lock | 186 ++++-- third_party/rust/crossbeam-channel/Cargo.toml | 21 +- third_party/rust/crossbeam-channel/README.md | 21 +- .../crossbeam-channel/benches/crossbeam.rs | 3 + .../crossbeam-channel/examples/fibonacci.rs | 2 + .../crossbeam-channel/examples/matching.rs | 6 +- .../crossbeam-channel/examples/stopwatch.rs | 70 +-- .../rust/crossbeam-channel/src/channel.rs | 58 +- .../rust/crossbeam-channel/src/context.rs | 2 +- third_party/rust/crossbeam-channel/src/err.rs | 115 +++- .../crossbeam-channel/src/flavors/after.rs | 8 +- .../crossbeam-channel/src/flavors/array.rs | 46 +- .../crossbeam-channel/src/flavors/list.rs | 44 +- .../crossbeam-channel/src/flavors/never.rs | 8 +- .../crossbeam-channel/src/flavors/tick.rs | 6 +- .../crossbeam-channel/src/flavors/zero.rs | 22 +- third_party/rust/crossbeam-channel/src/lib.rs | 81 +-- .../rust/crossbeam-channel/src/select.rs | 37 +- .../crossbeam-channel/src/select_macro.rs | 293 +++++---- .../rust/crossbeam-channel/src/utils.rs | 10 +- .../rust/crossbeam-channel/src/waker.rs | 20 +- .../rust/crossbeam-channel/tests/after.rs | 7 +- .../rust/crossbeam-channel/tests/array.rs | 7 +- .../rust/crossbeam-channel/tests/golang.rs | 57 +- .../rust/crossbeam-channel/tests/iter.rs | 3 + .../rust/crossbeam-channel/tests/list.rs | 7 +- .../rust/crossbeam-channel/tests/mpsc.rs | 43 +- .../rust/crossbeam-channel/tests/never.rs | 6 +- .../rust/crossbeam-channel/tests/ready.rs | 7 +- .../crossbeam-channel/tests/same_channel.rs | 2 + .../rust/crossbeam-channel/tests/select.rs | 3 + .../crossbeam-channel/tests/select_macro.rs | 8 +- .../crossbeam-channel/tests/thread_locals.rs | 6 +- .../rust/crossbeam-channel/tests/tick.rs | 7 +- .../rust/crossbeam-channel/tests/zero.rs | 7 +- .../rust/maybe-uninit/.cargo-checksum.json | 1 + third_party/rust/maybe-uninit/Cargo.toml | 22 + third_party/rust/maybe-uninit/LICENSE-APACHE | 201 ++++++ third_party/rust/maybe-uninit/LICENSE-MIT | 25 + third_party/rust/maybe-uninit/README.md | 19 + third_party/rust/maybe-uninit/build.rs | 50 ++ third_party/rust/maybe-uninit/src/lib.rs | 10 + .../rust/maybe-uninit/src/maybe_uninit.rs | 594 ++++++++++++++++++ .../rust/maybe-uninit/tests/doesnt_drop.rs | 37 ++ 47 files changed, 1725 insertions(+), 482 deletions(-) create mode 100644 third_party/rust/maybe-uninit/.cargo-checksum.json create mode 100644 third_party/rust/maybe-uninit/Cargo.toml create mode 100644 third_party/rust/maybe-uninit/LICENSE-APACHE create mode 100644 third_party/rust/maybe-uninit/LICENSE-MIT create mode 100644 third_party/rust/maybe-uninit/README.md create mode 100644 third_party/rust/maybe-uninit/build.rs create mode 100644 third_party/rust/maybe-uninit/src/lib.rs create mode 100644 third_party/rust/maybe-uninit/src/maybe_uninit.rs create mode 100644 third_party/rust/maybe-uninit/tests/doesnt_drop.rs diff --git a/Cargo.lock b/Cargo.lock index 04115006ac69..fac712fa46cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -843,12 +843,12 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ee0cc8804d5393478d743b035099520087a5186f3b93fa58cec08fa62407b6" +checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87" dependencies = [ - "cfg-if", "crossbeam-utils 0.7.0", + "maybe-uninit", ] [[package]] @@ -2887,6 +2887,12 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +[[package]] +name = "maybe-uninit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" + [[package]] name = "mdns_service" version = "0.1.0" diff --git a/third_party/rust/crossbeam-channel/.cargo-checksum.json b/third_party/rust/crossbeam-channel/.cargo-checksum.json index c1740f45fd5f..61a680a18a7c 100644 --- a/third_party/rust/crossbeam-channel/.cargo-checksum.json +++ b/third_party/rust/crossbeam-channel/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"c41ddf971d55da04567cdb2e574c14acb5cfe905e8c41b5fa161af0c50c0dd7f","Cargo.lock":"14fcb36b266d560ed631a7c608994811f74df44d17f036b5cb66766c1ed54679","Cargo.toml":"d25a14eafef76836a3f458e963c4472ae43a3ef3d1778aad99a2943bdad9b931","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","LICENSE-THIRD-PARTY":"924a49392dc8304def57586be4ebd69aaf51e16fd245b55b4b69ad2cce6b715a","README.md":"d2c041f6fa5da30a6f87377421a8de4010c0c002dbff777e18ad2f8b36a65378","benches/crossbeam.rs":"f5720508d3458f2451271b9887f7557823304bd38288c928b0d6aa1f459865e5","examples/fibonacci.rs":"6a26ecd74c7493d2c93f4280c0804afc19adc612b77b3d9fea433119ff472a44","examples/matching.rs":"63c250e164607a7a9f643d46f107bb5da846d49e89cf9069909562d20e530f71","examples/stopwatch.rs":"87e4613e24083e877d97aaefdc6c78ee0308c3a2994974b2cbc7df042a82d488","src/channel.rs":"4fd8e2d7c889f39447e0039ee1441e81362137dbc2a3549cf9f3f730cde52c25","src/context.rs":"ad24cabfc50dd5e6ae84aa46a0246da12da1f1a6fa19043244ad25136075c6ca","src/counter.rs":"8b6d4d69db59bc992ddc7ed33f709788c3fab482521bb1adf985f77499506c09","src/err.rs":"c4c7602c5faa3123f063bf5b52382a63c3eab5c79c3d1d8f67baeb762c442fb9","src/flavors/after.rs":"f50a0032e44962b454db826c13192a99197bbf1acc971435deac5722a3242f49","src/flavors/array.rs":"da229912febc4088c04c4767483ac099810ff2348c66ac55e7904c42de280433","src/flavors/list.rs":"fa6667a33e30fad94a8432b78dd70d143e0809ebf80fa881bb6221aca55b4229","src/flavors/mod.rs":"a5af9b6105207e293c0d64928b4486fb1da9bfe0318354c66c8b5069e41ec31f","src/flavors/never.rs":"59ac4a46b5e32780b2b2f338064544a8b4ec1bc8b78a8a9cd0a683bcd01d5d36","src/flavors/tick.rs":"667fcaacb07d7556350a7e59b5906956224c57b1f43b7b0018a5e2dad0d91ff8","src/flavors/zero.rs":"97c13c89bce0ffd4f761a5ecd73e3221bdd320817061ef7bc7d76010da021b77","src/lib.rs":"24e16d1855e89f5749c564533daca544a424d0dfa6bdadc0a95e47649734bddd","src/select.rs":"70c54434f033e999dce48655b524b6f5ed990b5d424b2d7fb122f3c9ac7d41be","src/select_macro.rs":"511d75151a5bc2ccc294098e79c0494a5dfa06cb0e473f5703dbc239ead4f235","src/utils.rs":"4ec0d30835f42dffc7614a18c8f005abb40dd33f2b127809b297959c6aa43004","src/waker.rs":"27eb84dcd0eb58f7d0d79d412bb293becc2740f6166d2fc64acb0ad94cfb523e","tests/after.rs":"324c7d773f72bef62d150171f74ba7b7ac1b06f6030b3d4d2b1a35d211956b21","tests/array.rs":"62290dfd66740a1d1017daea8048df09a11ee8ff8eb614a3a0aa5f4d456a7c39","tests/golang.rs":"0d41155fde12de50876dbbe775648598b63f6254169c44a781a30050cad1c890","tests/iter.rs":"7563dc7fdf4c63e31dd74ee3fedecdd3aed490f7ef599b98f6f75f929cf79edb","tests/list.rs":"6a9645c00aed88c1ad07d2e416b4f137ccef2e50f389c71589c6ac7d57373e5a","tests/mpsc.rs":"0c4c6b056f5cec77ca19eca45f99b083632700a4b67133e88071a1d22a61d6fe","tests/never.rs":"665441a9fb004f7cd44047619637ebe6766cf2faf58e68e6481397bbfc682e11","tests/ready.rs":"3848ee8bb16cc83269a462d830659ff29f91834eaab0749bca7be02f43d7db51","tests/same_channel.rs":"2bab761443671e841e1b2476bd8082d75533a2f6be7946f5dbcee67cdc82dccb","tests/select.rs":"58aa5421475bd98b3adc02e4241fc77669ca910cf9cac7a8b0a212b2e92cb7c7","tests/select_macro.rs":"00dd7963f79b96abf30851fdab29e86c8424b502a8a7d34abf4bc1714f493ecf","tests/thread_locals.rs":"3611db5502e6af0a8d15187d09fd195381819795544208b946e9f99b04579a81","tests/tick.rs":"06f205ace5fc44daaf1b6900a2e05bb5bda1c6071c1a07524f45769d8855968b","tests/zero.rs":"368eac99c6d9fb679f8dfbe93cdb96b01d77d1b6f840aa4e156b06f1786bb882"},"package":"09ee0cc8804d5393478d743b035099520087a5186f3b93fa58cec08fa62407b6"} \ No newline at end of file +{"files":{"CHANGELOG.md":"d55a5f1a75b60fbbd53a5b1432f19b8fa7e2bb822e1cc93ec956e542e7e8b3cd","Cargo.lock":"dcb3de08ddba81cf97f49253b63b8eb4f386338c0db8d4b77ae943fc138bfe69","Cargo.toml":"c20147fdaf2d6e99fe30c9f639fc0339f6af18994c2756cba1c869cd8e198bc0","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","LICENSE-THIRD-PARTY":"924a49392dc8304def57586be4ebd69aaf51e16fd245b55b4b69ad2cce6b715a","README.md":"7967172d90f7ebc20531d76c5a2bad7be8d81670fbc64abc33be4315d1430757","benches/crossbeam.rs":"baef02dffd58ee4d84d33a4e999254e81fcf45241623cfa6c4b1ef73dbd7479d","examples/fibonacci.rs":"8755bcb9cf05e391d8679fbb51db40ed9692703c3b66341cd1c1e4cca2068874","examples/matching.rs":"a1bdd7d211cf8612d649de3de3e24f56e911bc8d5e95b86b06f412314f9edd6c","examples/stopwatch.rs":"4e90ce134475859a421da0a095baea52a575b03e41fb8fb50cf47446f422ee6e","src/channel.rs":"4483ddf38c4b9b308b81dd156653ccb590524aae1e5ff8efcab6b8f44a8d3dfc","src/context.rs":"48eb848538482aeadd5bafb8fd24695dcf5635243d6f9d3b059a22538ce67014","src/counter.rs":"8b6d4d69db59bc992ddc7ed33f709788c3fab482521bb1adf985f77499506c09","src/err.rs":"80c47848fbfeeabaa83ea49c0928274cd4ae0ced7ebf214a075322fe301f3fa6","src/flavors/after.rs":"4f761618efe21036145e44f01506bdfbc2524879368ac138600e0feed921a6a7","src/flavors/array.rs":"606e27d3376c3cee128656b3690bd429964a22e3078886b6b7bf10cfa072fabb","src/flavors/list.rs":"0e2bf126b07ba8c2ef5db881043a3987b5f91013d47ae2da147a1c61a033c320","src/flavors/mod.rs":"a5af9b6105207e293c0d64928b4486fb1da9bfe0318354c66c8b5069e41ec31f","src/flavors/never.rs":"86e21b4d8b154e5d795cf72c7203a1d16a846c4d670095c8b592c12569f35a98","src/flavors/tick.rs":"d80858e0d5d1d7ec3886fb607e49bbc9577d64dc7c7304c5d3e6c8629a065476","src/flavors/zero.rs":"a24c2fb547586ab4bf2a09efb8af5264274f7b373749cd259a7dd3c843c8aac5","src/lib.rs":"1f0e6c4fb470dfe2fbdda90b7ac17f72c32fd62d41bccb4db9a756a88481fb44","src/select.rs":"f917459c033f8edbb45f377d6a4af24ffb583583d039182e72252d4af64a8807","src/select_macro.rs":"b1a3d2b9d4c64b48f6b176d2ff8b44c3d754f157ddbe830e8a1e86e4c100e0e9","src/utils.rs":"8b1184222df9047355e6044ad7e3fefd6065a5dda98b968cae45cca5f4b2fb5d","src/waker.rs":"345b551d467389a3a18dc22b351674dfbf288945b984450f607e644faa8a9731","tests/after.rs":"effb341c02f03a45ce09ab7862bc5b191191e0175997c494f988e6daca1ef8af","tests/array.rs":"35cd46fc7310f4206e3bbd81f900c18053a3a22943e221fbb81f9b89505fee46","tests/golang.rs":"9cb210ef2668428f7efb542ff4a8ab4e61f77dd4ff7e39720d63ad0797ff4ec1","tests/iter.rs":"b6df3f21273bb21dfecda47ffc0c296541214cde6bed876a31db5f2410839e83","tests/list.rs":"eb6cfc9a0f02c77df6d6d608fbbe1f82e09901e167b4b86993c49f9d6052a8ee","tests/mpsc.rs":"965e18abbfcdebec09380f8ec9bb62e5556ad2aa0176ed088ce091994c1d2500","tests/never.rs":"cd455a4c78403d9a96fe0f3a4e968164cca533cc85c96aaa4558987f9b088fcc","tests/ready.rs":"b91cebde45a6c46bd2cf16b1fc58b2ec258dcc960cb9f8eb5b4c39b1a144cadc","tests/same_channel.rs":"bd93f72e982f9881235848a4a2da67276feca810ed1e4d22e0e2bda8675cae4a","tests/select.rs":"57558f93834dc1ae1a56fe8d1211536e16015a74c8c7458c653852472c21ddcd","tests/select_macro.rs":"1cd5250d46d6d2e8c0a87ee9b1c0a5d80aac193c3eb0a86877249684e7aabd39","tests/thread_locals.rs":"845f8c8f1a37a14e4235fc9fc20d8b7288fd9fda307c075c0e61e6ab79b33921","tests/tick.rs":"dd4257f1f8de01477d542e20a816eede3b4e2e4dc6fcdf07d554220f0ef8a86f","tests/zero.rs":"088804df377904eca4a985d8f1703f98550e51304d6849bfce143fcd0b69c349"},"package":"b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87"} \ No newline at end of file diff --git a/third_party/rust/crossbeam-channel/CHANGELOG.md b/third_party/rust/crossbeam-channel/CHANGELOG.md index 37718935483d..8c1c7fc42ff8 100644 --- a/third_party/rust/crossbeam-channel/CHANGELOG.md +++ b/third_party/rust/crossbeam-channel/CHANGELOG.md @@ -1,3 +1,8 @@ +# Version 0.4.4 + +- Fix bug in release (yanking 0.4.3) +- Fix UB and breaking change introduced in 0.4.3 + # Version 0.4.3 - Change license to "MIT OR Apache-2.0". diff --git a/third_party/rust/crossbeam-channel/Cargo.lock b/third_party/rust/crossbeam-channel/Cargo.lock index 29674d73ac41..fe038cc0118b 100644 --- a/third_party/rust/crossbeam-channel/Cargo.lock +++ b/third_party/rust/crossbeam-channel/Cargo.lock @@ -8,9 +8,21 @@ checksum = "4d25d88fd6b8041580a654f9d0c581a047baee2b3efee13275f2fc392fc75034" [[package]] name = "autocfg" -version = "1.0.0" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] name = "cfg-if" @@ -18,12 +30,21 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +dependencies = [ + "bitflags", +] + [[package]] name = "crossbeam-channel" -version = "0.4.3" +version = "0.4.4" dependencies = [ - "cfg-if", "crossbeam-utils", + "maybe-uninit", "num_cpus", "rand", "signal-hook", @@ -35,21 +56,16 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" dependencies = [ - "autocfg", + "autocfg 1.0.1", "cfg-if", "lazy_static", ] [[package]] -name = "getrandom" -version = "0.1.14" +name = "fuchsia-cprng" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "hermit-abi" @@ -68,9 +84,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.73" +version = "0.2.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7d4bd64732af4bf3a67f367c27df8520ad7e230c5817b8ff485864d80242b9" +checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3" + +[[package]] +name = "maybe-uninit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "num_cpus" @@ -82,51 +104,119 @@ dependencies = [ "libc", ] -[[package]] -name = "ppv-lite86" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" - [[package]] name = "rand" -version = "0.7.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" dependencies = [ - "getrandom", + "autocfg 0.1.7", "libc", "rand_chacha", - "rand_core", + "rand_core 0.4.2", "rand_hc", + "rand_isaac", + "rand_jitter", + "rand_os", + "rand_pcg", + "rand_xorshift", + "winapi", ] [[package]] name = "rand_chacha" -version = "0.2.2" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" dependencies = [ - "ppv-lite86", - "rand_core", + "autocfg 0.1.7", + "rand_core 0.3.1", ] [[package]] name = "rand_core" -version = "0.5.1" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" dependencies = [ - "getrandom", + "rand_core 0.4.2", ] +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + [[package]] name = "rand_hc" -version = "0.2.0" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" dependencies = [ - "rand_core", + "rand_core 0.3.1", +] + +[[package]] +name = "rand_jitter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" +dependencies = [ + "libc", + "rand_core 0.4.2", + "winapi", +] + +[[package]] +name = "rand_os" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +dependencies = [ + "cloudabi", + "fuchsia-cprng", + "libc", + "rand_core 0.4.2", + "rdrand", + "winapi", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +dependencies = [ + "autocfg 0.1.7", + "rand_core 0.4.2", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", ] [[package]] @@ -141,16 +231,32 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41" +checksum = "a3e12110bc539e657a646068aaf5eb5b63af9d0c1f7b29c97113fad80e15f035" dependencies = [ "arc-swap", "libc", ] [[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/third_party/rust/crossbeam-channel/Cargo.toml b/third_party/rust/crossbeam-channel/Cargo.toml index 97c992be229d..86f264b99b6a 100644 --- a/third_party/rust/crossbeam-channel/Cargo.toml +++ b/third_party/rust/crossbeam-channel/Cargo.toml @@ -11,9 +11,8 @@ # will likely look very different (and much more reasonable) [package] -edition = "2018" name = "crossbeam-channel" -version = "0.4.3" +version = "0.4.4" authors = ["The Crossbeam Project Developers"] description = "Multi-producer multi-consumer channels for message passing" homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-channel" @@ -23,22 +22,16 @@ keywords = ["channel", "mpmc", "select", "golang", "message"] categories = ["algorithms", "concurrency", "data-structures"] license = "MIT OR Apache-2.0" repository = "https://github.com/crossbeam-rs/crossbeam" -[dependencies.cfg-if] -version = "0.1.10" - [dependencies.crossbeam-utils] version = "0.7" -optional = true -default-features = false + +[dependencies.maybe-uninit] +version = "2.0.0" [dev-dependencies.num_cpus] -version = "1.13.0" +version = "1.10.0" [dev-dependencies.rand] -version = "0.7.3" +version = "0.6" [dev-dependencies.signal-hook] -version = "0.1.15" - -[features] -default = ["std"] -std = ["crossbeam-utils/std"] +version = "0.1.5" diff --git a/third_party/rust/crossbeam-channel/README.md b/third_party/rust/crossbeam-channel/README.md index eab623a6a9ab..be2e0b8f32cc 100644 --- a/third_party/rust/crossbeam-channel/README.md +++ b/third_party/rust/crossbeam-channel/README.md @@ -1,14 +1,14 @@ # Crossbeam Channel -[![Build Status](https://github.com/crossbeam-rs/crossbeam/workflows/CI/badge.svg)]( -https://github.com/crossbeam-rs/crossbeam/actions) -[![License](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)]( -https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-channel#license) +[![Build Status](https://travis-ci.org/crossbeam-rs/crossbeam.svg?branch=master)]( +https://travis-ci.org/crossbeam-rs/crossbeam) +[![License](https://img.shields.io/badge/license-MIT%2FApache--2.0-blue.svg)]( +https://github.com/crossbeam-rs/crossbeam-channel) [![Cargo](https://img.shields.io/crates/v/crossbeam-channel.svg)]( https://crates.io/crates/crossbeam-channel) [![Documentation](https://docs.rs/crossbeam-channel/badge.svg)]( https://docs.rs/crossbeam-channel) -[![Rust 1.36+](https://img.shields.io/badge/rust-1.36+-lightgray.svg)]( +[![Rust 1.28+](https://img.shields.io/badge/rust-1.28+-lightgray.svg)]( https://www.rust-lang.org) [![chat](https://img.shields.io/discord/569610676205781012.svg?logo=discord)](https://discord.gg/BBYwKq) @@ -44,11 +44,16 @@ Add this to your `Cargo.toml`: crossbeam-channel = "0.4" ``` +Next, add this to your crate: + +```rust +#[macro_use] +extern crate crossbeam_channel; +``` + ## Compatibility -Crossbeam Channel supports stable Rust releases going back at least six months, -and every time the minimum supported Rust version is increased, a new minor -version is released. Currently, the minimum supported Rust version is 1.36. +The minimum supported Rust version is 1.28. Any change to this is considered a breaking change. ## License diff --git a/third_party/rust/crossbeam-channel/benches/crossbeam.rs b/third_party/rust/crossbeam-channel/benches/crossbeam.rs index 9870c98bb361..4dd956b12c7a 100644 --- a/third_party/rust/crossbeam-channel/benches/crossbeam.rs +++ b/third_party/rust/crossbeam-channel/benches/crossbeam.rs @@ -1,5 +1,8 @@ #![feature(test)] +extern crate crossbeam_channel; +extern crate crossbeam_utils; +extern crate num_cpus; extern crate test; use crossbeam_channel::{bounded, unbounded}; diff --git a/third_party/rust/crossbeam-channel/examples/fibonacci.rs b/third_party/rust/crossbeam-channel/examples/fibonacci.rs index cf22b7a578bd..499887a05278 100644 --- a/third_party/rust/crossbeam-channel/examples/fibonacci.rs +++ b/third_party/rust/crossbeam-channel/examples/fibonacci.rs @@ -1,5 +1,7 @@ //! An asynchronous fibonacci sequence generator. +extern crate crossbeam_channel; + use std::thread; use crossbeam_channel::{bounded, Sender}; diff --git a/third_party/rust/crossbeam-channel/examples/matching.rs b/third_party/rust/crossbeam-channel/examples/matching.rs index 5421169b9dfa..4b157ff56cfa 100644 --- a/third_party/rust/crossbeam-channel/examples/matching.rs +++ b/third_party/rust/crossbeam-channel/examples/matching.rs @@ -42,7 +42,11 @@ //! } //! ``` -use crossbeam_channel::{bounded, select}; +#[macro_use] +extern crate crossbeam_channel; +extern crate crossbeam_utils; + +use crossbeam_channel::bounded; use crossbeam_utils::thread; fn main() { diff --git a/third_party/rust/crossbeam-channel/examples/stopwatch.rs b/third_party/rust/crossbeam-channel/examples/stopwatch.rs index 6a67c9eefc46..137ea210e639 100644 --- a/third_party/rust/crossbeam-channel/examples/stopwatch.rs +++ b/third_party/rust/crossbeam-channel/examples/stopwatch.rs @@ -1,45 +1,43 @@ //! Prints the elapsed time every 1 second and quits on Ctrl+C. -#[cfg(windows)] // signal_hook::iterator does not work on windows -fn main() { - println!("This example does not work on Windows"); -} - -#[cfg(not(windows))] -fn main() { - use std::io; - use std::thread; - use std::time::{Duration, Instant}; - - use crossbeam_channel::{bounded, select, tick, Receiver}; - use signal_hook::iterator::Signals; - use signal_hook::SIGINT; - - // Creates a channel that gets a message every time `SIGINT` is signalled. - fn sigint_notifier() -> io::Result> { - let (s, r) = bounded(100); - let signals = Signals::new(&[SIGINT])?; - - thread::spawn(move || { - for _ in signals.forever() { - if s.send(()).is_err() { - break; - } +#[macro_use] +extern crate crossbeam_channel; +extern crate signal_hook; + +use std::io; +use std::thread; +use std::time::{Duration, Instant}; + +use crossbeam_channel::{bounded, tick, Receiver}; +use signal_hook::iterator::Signals; +use signal_hook::SIGINT; + +// Creates a channel that gets a message every time `SIGINT` is signalled. +fn sigint_notifier() -> io::Result> { + let (s, r) = bounded(100); + let signals = Signals::new(&[SIGINT])?; + + thread::spawn(move || { + for _ in signals.forever() { + if s.send(()).is_err() { + break; } - }); + } + }); - Ok(r) - } + Ok(r) +} - // Prints the elapsed time. - fn show(dur: Duration) { - println!( - "Elapsed: {}.{:03} sec", - dur.as_secs(), - dur.subsec_nanos() / 1_000_000 - ); - } +// Prints the elapsed time. +fn show(dur: Duration) { + println!( + "Elapsed: {}.{:03} sec", + dur.as_secs(), + dur.subsec_nanos() / 1_000_000 + ); +} +fn main() { let start = Instant::now(); let update = tick(Duration::from_secs(1)); let ctrl_c = sigint_notifier().unwrap(); diff --git a/third_party/rust/crossbeam-channel/src/channel.rs b/third_party/rust/crossbeam-channel/src/channel.rs index e1de872a8245..bc7908f0f492 100644 --- a/third_party/rust/crossbeam-channel/src/channel.rs +++ b/third_party/rust/crossbeam-channel/src/channel.rs @@ -7,13 +7,11 @@ use std::panic::{RefUnwindSafe, UnwindSafe}; use std::sync::Arc; use std::time::{Duration, Instant}; -use crate::context::Context; -use crate::counter; -use crate::err::{ - RecvError, RecvTimeoutError, SendError, SendTimeoutError, TryRecvError, TrySendError, -}; -use crate::flavors; -use crate::select::{Operation, SelectHandle, Token}; +use context::Context; +use counter; +use err::{RecvError, RecvTimeoutError, SendError, SendTimeoutError, TryRecvError, TrySendError}; +use flavors; +use select::{Operation, SelectHandle, Token}; /// Creates a channel of unbounded capacity. /// @@ -136,8 +134,11 @@ pub fn bounded(cap: usize) -> (Sender, Receiver) { /// Using an `after` channel for timeouts: /// /// ``` +/// # #[macro_use] +/// # extern crate crossbeam_channel; +/// # fn main() { /// use std::time::Duration; -/// use crossbeam_channel::{after, select, unbounded}; +/// use crossbeam_channel::{after, unbounded}; /// /// let (s, r) = unbounded::(); /// let timeout = Duration::from_millis(100); @@ -146,6 +147,7 @@ pub fn bounded(cap: usize) -> (Sender, Receiver) { /// recv(r) -> msg => println!("received {:?}", msg), /// recv(after(timeout)) -> _ => println!("timed out"), /// } +/// # } /// ``` /// /// When the message gets sent: @@ -185,9 +187,12 @@ pub fn after(duration: Duration) -> Receiver { /// Using a `never` channel to optionally add a timeout to [`select!`]: /// /// ``` +/// # #[macro_use] +/// # extern crate crossbeam_channel; +/// # fn main() { /// use std::thread; -/// use std::time::Duration; -/// use crossbeam_channel::{after, select, never, unbounded}; +/// use std::time::{Duration, Instant}; +/// use crossbeam_channel::{after, never, unbounded}; /// /// let (s, r) = unbounded(); /// @@ -208,6 +213,7 @@ pub fn after(duration: Duration) -> Receiver { /// recv(r) -> msg => assert_eq!(msg, Ok(1)), /// recv(timeout) -> _ => println!("timed out"), /// } +/// # } /// ``` /// /// [`select!`]: macro.select.html @@ -576,7 +582,7 @@ impl Clone for Sender { } impl fmt::Debug for Sender { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Sender { .. }") } } @@ -593,9 +599,9 @@ impl fmt::Debug for Sender { /// let (s, r) = unbounded(); /// /// thread::spawn(move || { -/// let _ = s.send(1); +/// s.send(1); /// thread::sleep(Duration::from_secs(1)); -/// let _ = s.send(2); +/// s.send(2); /// }); /// /// assert_eq!(r.recv(), Ok(1)); // Received immediately. @@ -935,7 +941,7 @@ impl Receiver { /// /// assert_eq!(v, [1, 2, 3]); /// ``` - pub fn iter(&self) -> Iter<'_, T> { + pub fn iter(&self) -> Iter { Iter { receiver: self } } @@ -971,7 +977,7 @@ impl Receiver { /// /// assert_eq!(v, [1, 2]); /// ``` - pub fn try_iter(&self) -> TryIter<'_, T> { + pub fn try_iter(&self) -> TryIter { TryIter { receiver: self } } @@ -1034,7 +1040,7 @@ impl Clone for Receiver { } impl fmt::Debug for Receiver { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Receiver { .. }") } } @@ -1086,13 +1092,13 @@ impl IntoIterator for Receiver { /// /// assert_eq!(v, [1, 2, 3]); /// ``` -pub struct Iter<'a, T> { +pub struct Iter<'a, T: 'a> { receiver: &'a Receiver, } -impl FusedIterator for Iter<'_, T> {} +impl<'a, T> FusedIterator for Iter<'a, T> {} -impl Iterator for Iter<'_, T> { +impl<'a, T> Iterator for Iter<'a, T> { type Item = T; fn next(&mut self) -> Option { @@ -1100,8 +1106,8 @@ impl Iterator for Iter<'_, T> { } } -impl fmt::Debug for Iter<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +impl<'a, T> fmt::Debug for Iter<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Iter { .. }") } } @@ -1138,11 +1144,11 @@ impl fmt::Debug for Iter<'_, T> { /// /// assert_eq!(v, [1, 2]); /// ``` -pub struct TryIter<'a, T> { +pub struct TryIter<'a, T: 'a> { receiver: &'a Receiver, } -impl Iterator for TryIter<'_, T> { +impl<'a, T> Iterator for TryIter<'a, T> { type Item = T; fn next(&mut self) -> Option { @@ -1150,8 +1156,8 @@ impl Iterator for TryIter<'_, T> { } } -impl fmt::Debug for TryIter<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +impl<'a, T> fmt::Debug for TryIter<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("TryIter { .. }") } } @@ -1200,7 +1206,7 @@ impl Iterator for IntoIter { } impl fmt::Debug for IntoIter { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("IntoIter { .. }") } } diff --git a/third_party/rust/crossbeam-channel/src/context.rs b/third_party/rust/crossbeam-channel/src/context.rs index e2e8480f00ae..c6e5c15db390 100644 --- a/third_party/rust/crossbeam-channel/src/context.rs +++ b/third_party/rust/crossbeam-channel/src/context.rs @@ -8,7 +8,7 @@ use std::time::Instant; use crossbeam_utils::Backoff; -use crate::select::Selected; +use select::Selected; /// Thread-local context used in select. #[derive(Debug, Clone)] diff --git a/third_party/rust/crossbeam-channel/src/err.rs b/third_party/rust/crossbeam-channel/src/err.rs index 8ae1d0533df4..468ce5cd89e4 100644 --- a/third_party/rust/crossbeam-channel/src/err.rs +++ b/third_party/rust/crossbeam-channel/src/err.rs @@ -116,18 +116,26 @@ pub struct TryReadyError; pub struct ReadyTimeoutError; impl fmt::Debug for SendError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { "SendError(..)".fmt(f) } } impl fmt::Display for SendError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { "sending on a disconnected channel".fmt(f) } } -impl error::Error for SendError {} +impl error::Error for SendError { + fn description(&self) -> &str { + "sending on a disconnected channel" + } + + fn cause(&self) -> Option<&dyn error::Error> { + None + } +} impl SendError { /// Unwraps the message. @@ -150,7 +158,7 @@ impl SendError { } impl fmt::Debug for TrySendError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { TrySendError::Full(..) => "Full(..)".fmt(f), TrySendError::Disconnected(..) => "Disconnected(..)".fmt(f), @@ -159,7 +167,7 @@ impl fmt::Debug for TrySendError { } impl fmt::Display for TrySendError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { TrySendError::Full(..) => "sending on a full channel".fmt(f), TrySendError::Disconnected(..) => "sending on a disconnected channel".fmt(f), @@ -167,7 +175,18 @@ impl fmt::Display for TrySendError { } } -impl error::Error for TrySendError {} +impl error::Error for TrySendError { + fn description(&self) -> &str { + match *self { + TrySendError::Full(..) => "sending on a full channel", + TrySendError::Disconnected(..) => "sending on a disconnected channel", + } + } + + fn cause(&self) -> Option<&dyn error::Error> { + None + } +} impl From> for TrySendError { fn from(err: SendError) -> TrySendError { @@ -216,13 +235,13 @@ impl TrySendError { } impl fmt::Debug for SendTimeoutError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { "SendTimeoutError(..)".fmt(f) } } impl fmt::Display for SendTimeoutError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { SendTimeoutError::Timeout(..) => "timed out waiting on send operation".fmt(f), SendTimeoutError::Disconnected(..) => "sending on a disconnected channel".fmt(f), @@ -230,7 +249,15 @@ impl fmt::Display for SendTimeoutError { } } -impl error::Error for SendTimeoutError {} +impl error::Error for SendTimeoutError { + fn description(&self) -> &str { + "sending on an empty and disconnected channel" + } + + fn cause(&self) -> Option<&dyn error::Error> { + None + } +} impl From> for SendTimeoutError { fn from(err: SendError) -> SendTimeoutError { @@ -280,15 +307,23 @@ impl SendTimeoutError { } impl fmt::Display for RecvError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { "receiving on an empty and disconnected channel".fmt(f) } } -impl error::Error for RecvError {} +impl error::Error for RecvError { + fn description(&self) -> &str { + "receiving on an empty and disconnected channel" + } + + fn cause(&self) -> Option<&dyn error::Error> { + None + } +} impl fmt::Display for TryRecvError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { TryRecvError::Empty => "receiving on an empty channel".fmt(f), TryRecvError::Disconnected => "receiving on an empty and disconnected channel".fmt(f), @@ -296,7 +331,18 @@ impl fmt::Display for TryRecvError { } } -impl error::Error for TryRecvError {} +impl error::Error for TryRecvError { + fn description(&self) -> &str { + match *self { + TryRecvError::Empty => "receiving on an empty channel", + TryRecvError::Disconnected => "receiving on an empty and disconnected channel", + } + } + + fn cause(&self) -> Option<&dyn error::Error> { + None + } +} impl From for TryRecvError { fn from(err: RecvError) -> TryRecvError { @@ -308,7 +354,6 @@ impl From for TryRecvError { impl TryRecvError { /// Returns `true` if the receive operation failed because the channel is empty. - #[allow(clippy::trivially_copy_pass_by_ref)] pub fn is_empty(&self) -> bool { match self { TryRecvError::Empty => true, @@ -317,7 +362,6 @@ impl TryRecvError { } /// Returns `true` if the receive operation failed because the channel is disconnected. - #[allow(clippy::trivially_copy_pass_by_ref)] pub fn is_disconnected(&self) -> bool { match self { TryRecvError::Disconnected => true, @@ -327,7 +371,7 @@ impl TryRecvError { } impl fmt::Display for RecvTimeoutError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { RecvTimeoutError::Timeout => "timed out waiting on receive operation".fmt(f), RecvTimeoutError::Disconnected => "channel is empty and disconnected".fmt(f), @@ -335,7 +379,18 @@ impl fmt::Display for RecvTimeoutError { } } -impl error::Error for RecvTimeoutError {} +impl error::Error for RecvTimeoutError { + fn description(&self) -> &str { + match *self { + RecvTimeoutError::Timeout => "timed out waiting on receive operation", + RecvTimeoutError::Disconnected => "channel is empty and disconnected", + } + } + + fn cause(&self) -> Option<&dyn error::Error> { + None + } +} impl From for RecvTimeoutError { fn from(err: RecvError) -> RecvTimeoutError { @@ -347,7 +402,6 @@ impl From for RecvTimeoutError { impl RecvTimeoutError { /// Returns `true` if the receive operation timed out. - #[allow(clippy::trivially_copy_pass_by_ref)] pub fn is_timeout(&self) -> bool { match self { RecvTimeoutError::Timeout => true, @@ -356,7 +410,6 @@ impl RecvTimeoutError { } /// Returns `true` if the receive operation failed because the channel is disconnected. - #[allow(clippy::trivially_copy_pass_by_ref)] pub fn is_disconnected(&self) -> bool { match self { RecvTimeoutError::Disconnected => true, @@ -366,17 +419,33 @@ impl RecvTimeoutError { } impl fmt::Display for TrySelectError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { "all operations in select would block".fmt(f) } } -impl error::Error for TrySelectError {} +impl error::Error for TrySelectError { + fn description(&self) -> &str { + "all operations in select would block" + } + + fn cause(&self) -> Option<&dyn error::Error> { + None + } +} impl fmt::Display for SelectTimeoutError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { "timed out waiting on select".fmt(f) } } -impl error::Error for SelectTimeoutError {} +impl error::Error for SelectTimeoutError { + fn description(&self) -> &str { + "timed out waiting on select" + } + + fn cause(&self) -> Option<&dyn error::Error> { + None + } +} diff --git a/third_party/rust/crossbeam-channel/src/flavors/after.rs b/third_party/rust/crossbeam-channel/src/flavors/after.rs index 3dff5aaad65a..b57f8a7879b8 100644 --- a/third_party/rust/crossbeam-channel/src/flavors/after.rs +++ b/third_party/rust/crossbeam-channel/src/flavors/after.rs @@ -6,10 +6,10 @@ use std::sync::atomic::{AtomicBool, Ordering}; use std::thread; use std::time::{Duration, Instant}; -use crate::context::Context; -use crate::err::{RecvTimeoutError, TryRecvError}; -use crate::select::{Operation, SelectHandle, Token}; -use crate::utils; +use context::Context; +use err::{RecvTimeoutError, TryRecvError}; +use select::{Operation, SelectHandle, Token}; +use utils; /// Result of a receive operation. pub type AfterToken = Option; diff --git a/third_party/rust/crossbeam-channel/src/flavors/array.rs b/third_party/rust/crossbeam-channel/src/flavors/array.rs index d7a6c26cc891..659fce69a13c 100644 --- a/third_party/rust/crossbeam-channel/src/flavors/array.rs +++ b/third_party/rust/crossbeam-channel/src/flavors/array.rs @@ -15,17 +15,19 @@ use std::cell::UnsafeCell; use std::marker::PhantomData; -use std::mem::{self, MaybeUninit}; +use std::mem; use std::ptr; use std::sync::atomic::{self, AtomicUsize, Ordering}; use std::time::Instant; use crossbeam_utils::{Backoff, CachePadded}; -use crate::context::Context; -use crate::err::{RecvTimeoutError, SendTimeoutError, TryRecvError, TrySendError}; -use crate::select::{Operation, SelectHandle, Selected, Token}; -use crate::waker::SyncWaker; +use maybe_uninit::MaybeUninit; + +use context::Context; +use err::{RecvTimeoutError, SendTimeoutError, TryRecvError, TrySendError}; +use select::{Operation, SelectHandle, Selected, Token}; +use waker::SyncWaker; /// A slot in a channel. struct Slot { @@ -112,23 +114,23 @@ impl Channel { // Tail is initialized to `{ lap: 0, mark: 0, index: 0 }`. let tail = 0; - // Allocate a buffer of `cap` slots initialized - // with stamps. + // Allocate a buffer of `cap` slots. let buffer = { - let mut v: Vec> = (0..cap) - .map(|i| { - // Set the stamp to `{ lap: 0, mark: 0, index: i }`. - Slot { - stamp: AtomicUsize::new(i), - msg: UnsafeCell::new(MaybeUninit::uninit()), - } - }) - .collect(); + let mut v = Vec::>::with_capacity(cap); let ptr = v.as_mut_ptr(); mem::forget(v); ptr }; + // Initialize stamps in the slots. + for i in 0..cap { + unsafe { + // Set the stamp to `{ lap: 0, mark: 0, index: i }`. + let slot = buffer.add(i); + ptr::write(&mut (*slot).stamp, AtomicUsize::new(i)); + } + } + Channel { buffer, cap, @@ -143,12 +145,12 @@ impl Channel { } /// Returns a receiver handle to the channel. - pub fn receiver(&self) -> Receiver<'_, T> { + pub fn receiver(&self) -> Receiver { Receiver(self) } /// Returns a sender handle to the channel. - pub fn sender(&self) -> Sender<'_, T> { + pub fn sender(&self) -> Sender { Sender(self) } @@ -559,12 +561,12 @@ impl Drop for Channel { } /// Receiver handle to a channel. -pub struct Receiver<'a, T>(&'a Channel); +pub struct Receiver<'a, T: 'a>(&'a Channel); /// Sender handle to a channel. -pub struct Sender<'a, T>(&'a Channel); +pub struct Sender<'a, T: 'a>(&'a Channel); -impl SelectHandle for Receiver<'_, T> { +impl<'a, T> SelectHandle for Receiver<'a, T> { fn try_select(&self, token: &mut Token) -> bool { self.0.start_recv(token) } @@ -600,7 +602,7 @@ impl SelectHandle for Receiver<'_, T> { } } -impl SelectHandle for Sender<'_, T> { +impl<'a, T> SelectHandle for Sender<'a, T> { fn try_select(&self, token: &mut Token) -> bool { self.0.start_send(token) } diff --git a/third_party/rust/crossbeam-channel/src/flavors/list.rs b/third_party/rust/crossbeam-channel/src/flavors/list.rs index 532e8b6ad41c..dd9e6e9dee32 100644 --- a/third_party/rust/crossbeam-channel/src/flavors/list.rs +++ b/third_party/rust/crossbeam-channel/src/flavors/list.rs @@ -2,17 +2,18 @@ use std::cell::UnsafeCell; use std::marker::PhantomData; -use std::mem::MaybeUninit; use std::ptr; use std::sync::atomic::{self, AtomicPtr, AtomicUsize, Ordering}; use std::time::Instant; use crossbeam_utils::{Backoff, CachePadded}; -use crate::context::Context; -use crate::err::{RecvTimeoutError, SendTimeoutError, TryRecvError, TrySendError}; -use crate::select::{Operation, SelectHandle, Selected, Token}; -use crate::waker::SyncWaker; +use maybe_uninit::MaybeUninit; + +use context::Context; +use err::{RecvTimeoutError, SendTimeoutError, TryRecvError, TrySendError}; +use select::{Operation, SelectHandle, Selected, Token}; +use waker::SyncWaker; // TODO(stjepang): Once we bump the minimum required Rust version to 1.28 or newer, re-apply the // following changes by @kleimkuhler: @@ -95,8 +96,8 @@ impl Block { /// Sets the `DESTROY` bit in slots starting from `start` and destroys the block. unsafe fn destroy(this: *mut Block, start: usize) { - // It is not necessary to set the `DESTROY` bit in the last slot because that slot has - // begun destruction of the block. + // It is not necessary to set the `DESTROY bit in the last slot because that slot has begun + // destruction of the block. for i in start..BLOCK_CAP - 1 { let slot = (*this).slots.get_unchecked(i); @@ -183,12 +184,12 @@ impl Channel { } /// Returns a receiver handle to the channel. - pub fn receiver(&self) -> Receiver<'_, T> { + pub fn receiver(&self) -> Receiver { Receiver(self) } /// Returns a sender handle to the channel. - pub fn sender(&self) -> Sender<'_, T> { + pub fn sender(&self) -> Sender { Sender(self) } @@ -498,14 +499,6 @@ impl Channel { tail &= !((1 << SHIFT) - 1); head &= !((1 << SHIFT) - 1); - // Fix up indices if they fall onto block ends. - if (tail >> SHIFT) & (LAP - 1) == LAP - 1 { - tail = tail.wrapping_add(1 << SHIFT); - } - if (head >> SHIFT) & (LAP - 1) == LAP - 1 { - head = head.wrapping_add(1 << SHIFT); - } - // Rotate indices so that head falls into the first block. let lap = (head >> SHIFT) / LAP; tail = tail.wrapping_sub((lap * LAP) << SHIFT); @@ -515,6 +508,15 @@ impl Channel { tail >>= SHIFT; head >>= SHIFT; + // Fix up indices if they fall onto block ends. + if head == BLOCK_CAP { + head = 0; + tail -= LAP; + } + if tail == BLOCK_CAP { + tail += 1; + } + // Return the difference minus the number of blocks between tail and head. return tail - head - tail / LAP; } @@ -597,12 +599,12 @@ impl Drop for Channel { } /// Receiver handle to a channel. -pub struct Receiver<'a, T>(&'a Channel); +pub struct Receiver<'a, T: 'a>(&'a Channel); /// Sender handle to a channel. -pub struct Sender<'a, T>(&'a Channel); +pub struct Sender<'a, T: 'a>(&'a Channel); -impl SelectHandle for Receiver<'_, T> { +impl<'a, T> SelectHandle for Receiver<'a, T> { fn try_select(&self, token: &mut Token) -> bool { self.0.start_recv(token) } @@ -638,7 +640,7 @@ impl SelectHandle for Receiver<'_, T> { } } -impl SelectHandle for Sender<'_, T> { +impl<'a, T> SelectHandle for Sender<'a, T> { fn try_select(&self, token: &mut Token) -> bool { self.0.start_send(token) } diff --git a/third_party/rust/crossbeam-channel/src/flavors/never.rs b/third_party/rust/crossbeam-channel/src/flavors/never.rs index e49d2147c44b..5fb12e67ed95 100644 --- a/third_party/rust/crossbeam-channel/src/flavors/never.rs +++ b/third_party/rust/crossbeam-channel/src/flavors/never.rs @@ -5,10 +5,10 @@ use std::marker::PhantomData; use std::time::Instant; -use crate::context::Context; -use crate::err::{RecvTimeoutError, TryRecvError}; -use crate::select::{Operation, SelectHandle, Token}; -use crate::utils; +use context::Context; +use err::{RecvTimeoutError, TryRecvError}; +use select::{Operation, SelectHandle, Token}; +use utils; /// This flavor doesn't need a token. pub type NeverToken = (); diff --git a/third_party/rust/crossbeam-channel/src/flavors/tick.rs b/third_party/rust/crossbeam-channel/src/flavors/tick.rs index e8e7020ca8e2..29411176145c 100644 --- a/third_party/rust/crossbeam-channel/src/flavors/tick.rs +++ b/third_party/rust/crossbeam-channel/src/flavors/tick.rs @@ -7,9 +7,9 @@ use std::time::{Duration, Instant}; use crossbeam_utils::atomic::AtomicCell; -use crate::context::Context; -use crate::err::{RecvTimeoutError, TryRecvError}; -use crate::select::{Operation, SelectHandle, Token}; +use context::Context; +use err::{RecvTimeoutError, TryRecvError}; +use select::{Operation, SelectHandle, Token}; /// Result of a receive operation. pub type TickToken = Option; diff --git a/third_party/rust/crossbeam-channel/src/flavors/zero.rs b/third_party/rust/crossbeam-channel/src/flavors/zero.rs index be647b55c82f..ee1bfc534478 100644 --- a/third_party/rust/crossbeam-channel/src/flavors/zero.rs +++ b/third_party/rust/crossbeam-channel/src/flavors/zero.rs @@ -9,11 +9,11 @@ use std::time::Instant; use crossbeam_utils::Backoff; -use crate::context::Context; -use crate::err::{RecvTimeoutError, SendTimeoutError, TryRecvError, TrySendError}; -use crate::select::{Operation, SelectHandle, Selected, Token}; -use crate::utils::Spinlock; -use crate::waker::Waker; +use context::Context; +use err::{RecvTimeoutError, SendTimeoutError, TryRecvError, TrySendError}; +use select::{Operation, SelectHandle, Selected, Token}; +use utils::Spinlock; +use waker::Waker; /// A pointer to a packet. pub type ZeroToken = usize; @@ -102,12 +102,12 @@ impl Channel { } /// Returns a receiver handle to the channel. - pub fn receiver(&self) -> Receiver<'_, T> { + pub fn receiver(&self) -> Receiver { Receiver(self) } /// Returns a sender handle to the channel. - pub fn sender(&self) -> Sender<'_, T> { + pub fn sender(&self) -> Sender { Sender(self) } @@ -360,12 +360,12 @@ impl Channel { } /// Receiver handle to a channel. -pub struct Receiver<'a, T>(&'a Channel); +pub struct Receiver<'a, T: 'a>(&'a Channel); /// Sender handle to a channel. -pub struct Sender<'a, T>(&'a Channel); +pub struct Sender<'a, T: 'a>(&'a Channel); -impl SelectHandle for Receiver<'_, T> { +impl<'a, T> SelectHandle for Receiver<'a, T> { fn try_select(&self, token: &mut Token) -> bool { self.0.start_recv(token) } @@ -415,7 +415,7 @@ impl SelectHandle for Receiver<'_, T> { } } -impl SelectHandle for Sender<'_, T> { +impl<'a, T> SelectHandle for Sender<'a, T> { fn try_select(&self, token: &mut Token) -> bool { self.0.start_send(token) } diff --git a/third_party/rust/crossbeam-channel/src/lib.rs b/third_party/rust/crossbeam-channel/src/lib.rs index adacbe210617..898239632fc7 100644 --- a/third_party/rust/crossbeam-channel/src/lib.rs +++ b/third_party/rust/crossbeam-channel/src/lib.rs @@ -122,6 +122,10 @@ //! It's also possible to share senders and receivers by reference: //! //! ``` +//! # extern crate crossbeam_channel; +//! # extern crate crossbeam_utils; +//! # fn main() { +//! use std::thread; //! use crossbeam_channel::bounded; //! use crossbeam_utils::thread::scope; //! @@ -138,6 +142,7 @@ //! s.send(1).unwrap(); //! r.recv().unwrap(); //! }).unwrap(); +//! # } //! ``` //! //! # Disconnection @@ -266,9 +271,12 @@ //! An example of receiving a message from two channels: //! //! ``` +//! # #[macro_use] +//! # extern crate crossbeam_channel; +//! # fn main() { //! use std::thread; //! use std::time::Duration; -//! use crossbeam_channel::{select, unbounded}; +//! use crossbeam_channel::unbounded; //! //! let (s1, r1) = unbounded(); //! let (s2, r2) = unbounded(); @@ -282,6 +290,7 @@ //! recv(r2) -> msg => assert_eq!(msg, Ok(20)), //! default(Duration::from_secs(1)) => println!("timed out"), //! } +//! # } //! ``` //! //! If you need to select over a dynamically created list of channel operations, use [`Select`] @@ -301,8 +310,11 @@ //! An example that prints elapsed time every 50 milliseconds for the duration of 1 second: //! //! ``` +//! # #[macro_use] +//! # extern crate crossbeam_channel; +//! # fn main() { //! use std::time::{Duration, Instant}; -//! use crossbeam_channel::{after, select, tick}; +//! use crossbeam_channel::{after, tick}; //! //! let start = Instant::now(); //! let ticker = tick(Duration::from_millis(50)); @@ -314,6 +326,7 @@ //! recv(timeout) -> _ => break, //! } //! } +//! # } //! ``` //! //! [`std::sync::mpsc`]: https://doc.rust-lang.org/std/sync/mpsc/index.html @@ -331,46 +344,36 @@ //! [`Sender`]: struct.Sender.html //! [`Receiver`]: struct.Receiver.html -#![doc(test( - no_crate_inject, - attr( - deny(warnings, rust_2018_idioms), - allow(dead_code, unused_assignments, unused_variables) - ) -))] -#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)] -#![cfg_attr(not(feature = "std"), no_std)] +#![warn(missing_docs)] +#![warn(missing_debug_implementations)] -use cfg_if::cfg_if; +extern crate crossbeam_utils; +extern crate maybe_uninit; -cfg_if! { - if #[cfg(feature = "std")] { - mod channel; - mod context; - mod counter; - mod err; - mod flavors; - mod select; - mod select_macro; - mod utils; - mod waker; +mod channel; +mod context; +mod counter; +mod err; +mod flavors; +mod select; +mod select_macro; +mod utils; +mod waker; - /// Crate internals used by the `select!` macro. - #[doc(hidden)] - pub mod internal { - pub use crate::select::SelectHandle; - pub use crate::select::{select, select_timeout, try_select}; - } +/// Crate internals used by the `select!` macro. +#[doc(hidden)] +pub mod internal { + pub use select::SelectHandle; + pub use select::{select, select_timeout, try_select}; +} - pub use crate::channel::{after, never, tick}; - pub use crate::channel::{bounded, unbounded}; - pub use crate::channel::{IntoIter, Iter, TryIter}; - pub use crate::channel::{Receiver, Sender}; +pub use channel::{after, never, tick}; +pub use channel::{bounded, unbounded}; +pub use channel::{IntoIter, Iter, TryIter}; +pub use channel::{Receiver, Sender}; - pub use crate::select::{Select, SelectedOperation}; +pub use select::{Select, SelectedOperation}; - pub use crate::err::{ReadyTimeoutError, SelectTimeoutError, TryReadyError, TrySelectError}; - pub use crate::err::{RecvError, RecvTimeoutError, TryRecvError}; - pub use crate::err::{SendError, SendTimeoutError, TrySendError}; - } -} +pub use err::{ReadyTimeoutError, SelectTimeoutError, TryReadyError, TrySelectError}; +pub use err::{RecvError, RecvTimeoutError, TryRecvError}; +pub use err::{SendError, SendTimeoutError, TrySendError}; diff --git a/third_party/rust/crossbeam-channel/src/select.rs b/third_party/rust/crossbeam-channel/src/select.rs index 68bfe4183d3c..60c6a45dcb38 100644 --- a/third_party/rust/crossbeam-channel/src/select.rs +++ b/third_party/rust/crossbeam-channel/src/select.rs @@ -7,13 +7,13 @@ use std::time::{Duration, Instant}; use crossbeam_utils::Backoff; -use crate::channel::{self, Receiver, Sender}; -use crate::context::Context; -use crate::err::{ReadyTimeoutError, TryReadyError}; -use crate::err::{RecvError, SendError}; -use crate::err::{SelectTimeoutError, TrySelectError}; -use crate::flavors; -use crate::utils; +use channel::{self, Receiver, Sender}; +use context::Context; +use err::{ReadyTimeoutError, TryReadyError}; +use err::{RecvError, SendError}; +use err::{SelectTimeoutError, TrySelectError}; +use flavors; +use utils; /// Temporary data that gets initialized during select or a blocking operation, and is consumed by /// `read` or `write`. @@ -119,7 +119,7 @@ pub trait SelectHandle { fn unwatch(&self, oper: Operation); } -impl SelectHandle for &T { +impl<'a, T: SelectHandle> SelectHandle for &'a T { fn try_select(&self, token: &mut Token) -> bool { (**self).try_select(token) } @@ -585,8 +585,8 @@ pub struct Select<'a> { next_index: usize, } -unsafe impl Send for Select<'_> {} -unsafe impl Sync for Select<'_> {} +unsafe impl<'a> Send for Select<'a> {} +unsafe impl<'a> Sync for Select<'a> {} impl<'a> Select<'a> { /// Creates an empty list of channel operations for selection. @@ -615,6 +615,7 @@ impl<'a> Select<'a> { /// # Examples /// /// ``` + /// use std::thread; /// use crossbeam_channel::{unbounded, Select}; /// /// let (s, r) = unbounded::(); @@ -637,6 +638,7 @@ impl<'a> Select<'a> { /// # Examples /// /// ``` + /// use std::thread; /// use crossbeam_channel::{unbounded, Select}; /// /// let (s, r) = unbounded::(); @@ -667,6 +669,7 @@ impl<'a> Select<'a> { /// # Examples /// /// ``` + /// use std::thread; /// use crossbeam_channel::{unbounded, Select}; /// /// let (s1, r1) = unbounded::(); @@ -725,6 +728,7 @@ impl<'a> Select<'a> { /// # Examples /// /// ``` + /// use std::thread; /// use crossbeam_channel::{unbounded, Select}; /// /// let (s1, r1) = unbounded(); @@ -870,6 +874,7 @@ impl<'a> Select<'a> { /// # Examples /// /// ``` + /// use std::thread; /// use crossbeam_channel::{unbounded, Select}; /// /// let (s1, r1) = unbounded(); @@ -1012,8 +1017,8 @@ impl<'a> Default for Select<'a> { } } -impl fmt::Debug for Select<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +impl<'a> fmt::Debug for Select<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Select { .. }") } } @@ -1044,7 +1049,7 @@ pub struct SelectedOperation<'a> { _marker: PhantomData<&'a ()>, } -impl SelectedOperation<'_> { +impl<'a> SelectedOperation<'a> { /// Returns the index of the selected operation. /// /// # Examples @@ -1148,13 +1153,13 @@ impl SelectedOperation<'_> { } } -impl fmt::Debug for SelectedOperation<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +impl<'a> fmt::Debug for SelectedOperation<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("SelectedOperation { .. }") } } -impl Drop for SelectedOperation<'_> { +impl<'a> Drop for SelectedOperation<'a> { fn drop(&mut self) { panic!("dropped `SelectedOperation` without completing the operation"); } diff --git a/third_party/rust/crossbeam-channel/src/select_macro.rs b/third_party/rust/crossbeam-channel/src/select_macro.rs index 28eebeb4fc8b..9aaaa9e935cb 100644 --- a/third_party/rust/crossbeam-channel/src/select_macro.rs +++ b/third_party/rust/crossbeam-channel/src/select_macro.rs @@ -5,7 +5,10 @@ /// This is just an ugly workaround until it becomes possible to import macros with `use` /// statements. /// -/// TODO(stjepang): Replace `crossbeam_channel_delegate` with direct macro invocations. +/// TODO(stjepang): Once we bump the minimum required Rust version to 1.30 or newer, we should: +/// +/// 1. Remove all `#[macro_export(local_inner_macros)]` lines. +/// 2. Replace `crossbeam_channel_delegate` with direct macro invocations. #[doc(hidden)] #[macro_export] macro_rules! crossbeam_channel_delegate { @@ -50,7 +53,7 @@ macro_rules! crossbeam_channel_internal { () ($($head:tt)*) ) => { - $crate::crossbeam_channel_internal!( + crossbeam_channel_internal!( @case ($($head)*) () @@ -62,7 +65,7 @@ macro_rules! crossbeam_channel_internal { (default => $($tail:tt)*) ($($head:tt)*) ) => { - $crate::crossbeam_channel_internal!( + crossbeam_channel_internal!( @list (default() => $($tail)*) ($($head)*) @@ -73,7 +76,7 @@ macro_rules! crossbeam_channel_internal { (default -> $($tail:tt)*) ($($head:tt)*) ) => { - $crate::crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(compile_error( "expected `=>` after `default` case, found `->`" )) }; @@ -82,7 +85,7 @@ macro_rules! crossbeam_channel_internal { (default $args:tt -> $($tail:tt)*) ($($head:tt)*) ) => { - $crate::crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(compile_error( "expected `=>` after `default` case, found `->`" )) }; @@ -91,7 +94,7 @@ macro_rules! crossbeam_channel_internal { (recv($($args:tt)*) => $($tail:tt)*) ($($head:tt)*) ) => { - $crate::crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(compile_error( "expected `->` after `recv` case, found `=>`" )) }; @@ -100,7 +103,7 @@ macro_rules! crossbeam_channel_internal { (send($($args:tt)*) => $($tail:tt)*) ($($head:tt)*) ) => { - $crate::crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(compile_error( "expected `->` after `send` operation, found `=>`" )) }; @@ -109,14 +112,14 @@ macro_rules! crossbeam_channel_internal { ($case:ident $args:tt -> $res:tt -> $($tail:tt)*) ($($head:tt)*) ) => { - $crate::crossbeam_channel_delegate!(compile_error("expected `=>`, found `->`")) + crossbeam_channel_delegate!(compile_error("expected `=>`, found `->`")) }; // Print an error if there is a semicolon after the block. (@list ($case:ident $args:tt $(-> $res:pat)* => $body:block; $($tail:tt)*) ($($head:tt)*) ) => { - $crate::crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(compile_error( "did you mean to put a comma instead of the semicolon after `}`?" )) }; @@ -125,7 +128,7 @@ macro_rules! crossbeam_channel_internal { ($case:ident ($($args:tt)*) $(-> $res:pat)* => $body:expr, $($tail:tt)*) ($($head:tt)*) ) => { - $crate::crossbeam_channel_internal!( + crossbeam_channel_internal!( @list ($($tail)*) ($($head)* $case ($($args)*) $(-> $res)* => { $body },) @@ -136,7 +139,7 @@ macro_rules! crossbeam_channel_internal { ($case:ident ($($args:tt)*) $(-> $res:pat)* => $body:block $($tail:tt)*) ($($head:tt)*) ) => { - $crate::crossbeam_channel_internal!( + crossbeam_channel_internal!( @list ($($tail)*) ($($head)* $case ($($args)*) $(-> $res)* => { $body },) @@ -147,7 +150,7 @@ macro_rules! crossbeam_channel_internal { ($case:ident ($($args:tt)*) $(-> $res:pat)* => $body:expr) ($($head:tt)*) ) => { - $crate::crossbeam_channel_internal!( + crossbeam_channel_internal!( @list () ($($head)* $case ($($args)*) $(-> $res)* => { $body },) @@ -158,7 +161,7 @@ macro_rules! crossbeam_channel_internal { ($case:ident ($($args:tt)*) $(-> $res:pat)* => $body:expr,) ($($head:tt)*) ) => { - $crate::crossbeam_channel_internal!( + crossbeam_channel_internal!( @list () ($($head)* $case ($($args)*) $(-> $res)* => { $body },) @@ -169,216 +172,216 @@ macro_rules! crossbeam_channel_internal { ($($tail:tt)*) ($($head:tt)*) ) => { - $crate::crossbeam_channel_internal!(@list_error1 $($tail)*) + crossbeam_channel_internal!(@list_error1 $($tail)*) }; // Stage 1: check the case type. (@list_error1 recv $($tail:tt)*) => { - $crate::crossbeam_channel_internal!(@list_error2 recv $($tail)*) + crossbeam_channel_internal!(@list_error2 recv $($tail)*) }; (@list_error1 send $($tail:tt)*) => { - $crate::crossbeam_channel_internal!(@list_error2 send $($tail)*) + crossbeam_channel_internal!(@list_error2 send $($tail)*) }; (@list_error1 default $($tail:tt)*) => { - $crate::crossbeam_channel_internal!(@list_error2 default $($tail)*) + crossbeam_channel_internal!(@list_error2 default $($tail)*) }; (@list_error1 $t:tt $($tail:tt)*) => { - $crate::crossbeam_channel_delegate!(compile_error( - $crate::crossbeam_channel_delegate!(concat( + crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(concat( "expected one of `recv`, `send`, or `default`, found `", - $crate::crossbeam_channel_delegate!(stringify($t)), + crossbeam_channel_delegate!(stringify($t)), "`", )) )) }; (@list_error1 $($tail:tt)*) => { - $crate::crossbeam_channel_internal!(@list_error2 $($tail)*); + crossbeam_channel_internal!(@list_error2 $($tail)*); }; // Stage 2: check the argument list. (@list_error2 $case:ident) => { - $crate::crossbeam_channel_delegate!(compile_error( - $crate::crossbeam_channel_delegate!(concat( + crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(concat( "missing argument list after `", - $crate::crossbeam_channel_delegate!(stringify($case)), + crossbeam_channel_delegate!(stringify($case)), "`", )) )) }; (@list_error2 $case:ident => $($tail:tt)*) => { - $crate::crossbeam_channel_delegate!(compile_error( - $crate::crossbeam_channel_delegate!(concat( + crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(concat( "missing argument list after `", - $crate::crossbeam_channel_delegate!(stringify($case)), + crossbeam_channel_delegate!(stringify($case)), "`", )) )) }; (@list_error2 $($tail:tt)*) => { - $crate::crossbeam_channel_internal!(@list_error3 $($tail)*) + crossbeam_channel_internal!(@list_error3 $($tail)*) }; // Stage 3: check the `=>` and what comes after it. (@list_error3 $case:ident($($args:tt)*) $(-> $r:pat)*) => { - $crate::crossbeam_channel_delegate!(compile_error( - $crate::crossbeam_channel_delegate!(concat( + crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(concat( "missing `=>` after `", - $crate::crossbeam_channel_delegate!(stringify($case)), + crossbeam_channel_delegate!(stringify($case)), "` case", )) )) }; (@list_error3 $case:ident($($args:tt)*) $(-> $r:pat)* =>) => { - $crate::crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(compile_error( "expected expression after `=>`" )) }; (@list_error3 $case:ident($($args:tt)*) $(-> $r:pat)* => $body:expr; $($tail:tt)*) => { - $crate::crossbeam_channel_delegate!(compile_error( - $crate::crossbeam_channel_delegate!(concat( + crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(concat( "did you mean to put a comma instead of the semicolon after `", - $crate::crossbeam_channel_delegate!(stringify($body)), + crossbeam_channel_delegate!(stringify($body)), "`?", )) )) }; (@list_error3 $case:ident($($args:tt)*) $(-> $r:pat)* => recv($($a:tt)*) $($tail:tt)*) => { - $crate::crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(compile_error( "expected an expression after `=>`" )) }; (@list_error3 $case:ident($($args:tt)*) $(-> $r:pat)* => send($($a:tt)*) $($tail:tt)*) => { - $crate::crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(compile_error( "expected an expression after `=>`" )) }; (@list_error3 $case:ident($($args:tt)*) $(-> $r:pat)* => default($($a:tt)*) $($tail:tt)*) => { - $crate::crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(compile_error( "expected an expression after `=>`" )) }; (@list_error3 $case:ident($($args:tt)*) $(-> $r:pat)* => $f:ident($($a:tt)*) $($tail:tt)*) => { - $crate::crossbeam_channel_delegate!(compile_error( - $crate::crossbeam_channel_delegate!(concat( + crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(concat( "did you mean to put a comma after `", - $crate::crossbeam_channel_delegate!(stringify($f)), + crossbeam_channel_delegate!(stringify($f)), "(", - $crate::crossbeam_channel_delegate!(stringify($($a)*)), + crossbeam_channel_delegate!(stringify($($a)*)), ")`?", )) )) }; (@list_error3 $case:ident($($args:tt)*) $(-> $r:pat)* => $f:ident!($($a:tt)*) $($tail:tt)*) => { - $crate::crossbeam_channel_delegate!(compile_error( - $crate::crossbeam_channel_delegate!(concat( + crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(concat( "did you mean to put a comma after `", - $crate::crossbeam_channel_delegate!(stringify($f)), + crossbeam_channel_delegate!(stringify($f)), "!(", - $crate::crossbeam_channel_delegate!(stringify($($a)*)), + crossbeam_channel_delegate!(stringify($($a)*)), ")`?", )) )) }; (@list_error3 $case:ident($($args:tt)*) $(-> $r:pat)* => $f:ident![$($a:tt)*] $($tail:tt)*) => { - $crate::crossbeam_channel_delegate!(compile_error( - $crate::crossbeam_channel_delegate!(concat( + crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(concat( "did you mean to put a comma after `", - $crate::crossbeam_channel_delegate!(stringify($f)), + crossbeam_channel_delegate!(stringify($f)), "![", - $crate::crossbeam_channel_delegate!(stringify($($a)*)), + crossbeam_channel_delegate!(stringify($($a)*)), "]`?", )) )) }; (@list_error3 $case:ident($($args:tt)*) $(-> $r:pat)* => $f:ident!{$($a:tt)*} $($tail:tt)*) => { - $crate::crossbeam_channel_delegate!(compile_error( - $crate::crossbeam_channel_delegate!(concat( + crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(concat( "did you mean to put a comma after `", - $crate::crossbeam_channel_delegate!(stringify($f)), + crossbeam_channel_delegate!(stringify($f)), "!{", - $crate::crossbeam_channel_delegate!(stringify($($a)*)), + crossbeam_channel_delegate!(stringify($($a)*)), "}`?", )) )) }; (@list_error3 $case:ident($($args:tt)*) $(-> $r:pat)* => $body:tt $($tail:tt)*) => { - $crate::crossbeam_channel_delegate!(compile_error( - $crate::crossbeam_channel_delegate!(concat( + crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(concat( "did you mean to put a comma after `", - $crate::crossbeam_channel_delegate!(stringify($body)), + crossbeam_channel_delegate!(stringify($body)), "`?", )) )) }; (@list_error3 $case:ident($($args:tt)*) -> => $($tail:tt)*) => { - $crate::crossbeam_channel_delegate!(compile_error("missing pattern after `->`")) + crossbeam_channel_delegate!(compile_error("missing pattern after `->`")) }; (@list_error3 $case:ident($($args:tt)*) $t:tt $(-> $r:pat)* => $($tail:tt)*) => { - $crate::crossbeam_channel_delegate!(compile_error( - $crate::crossbeam_channel_delegate!(concat( + crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(concat( "expected `->`, found `", - $crate::crossbeam_channel_delegate!(stringify($t)), + crossbeam_channel_delegate!(stringify($t)), "`", )) )) }; (@list_error3 $case:ident($($args:tt)*) -> $t:tt $($tail:tt)*) => { - $crate::crossbeam_channel_delegate!(compile_error( - $crate::crossbeam_channel_delegate!(concat( + crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(concat( "expected a pattern, found `", - $crate::crossbeam_channel_delegate!(stringify($t)), + crossbeam_channel_delegate!(stringify($t)), "`", )) )) }; (@list_error3 recv($($args:tt)*) $t:tt $($tail:tt)*) => { - $crate::crossbeam_channel_delegate!(compile_error( - $crate::crossbeam_channel_delegate!(concat( + crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(concat( "expected `->`, found `", - $crate::crossbeam_channel_delegate!(stringify($t)), + crossbeam_channel_delegate!(stringify($t)), "`", )) )) }; (@list_error3 send($($args:tt)*) $t:tt $($tail:tt)*) => { - $crate::crossbeam_channel_delegate!(compile_error( - $crate::crossbeam_channel_delegate!(concat( + crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(concat( "expected `->`, found `", - $crate::crossbeam_channel_delegate!(stringify($t)), + crossbeam_channel_delegate!(stringify($t)), "`", )) )) }; (@list_error3 recv $args:tt $($tail:tt)*) => { - $crate::crossbeam_channel_delegate!(compile_error( - $crate::crossbeam_channel_delegate!(concat( + crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(concat( "expected an argument list after `recv`, found `", - $crate::crossbeam_channel_delegate!(stringify($args)), + crossbeam_channel_delegate!(stringify($args)), "`", )) )) }; (@list_error3 send $args:tt $($tail:tt)*) => { - $crate::crossbeam_channel_delegate!(compile_error( - $crate::crossbeam_channel_delegate!(concat( + crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(concat( "expected an argument list after `send`, found `", - $crate::crossbeam_channel_delegate!(stringify($args)), + crossbeam_channel_delegate!(stringify($args)), "`", )) )) }; (@list_error3 default $args:tt $($tail:tt)*) => { - $crate::crossbeam_channel_delegate!(compile_error( - $crate::crossbeam_channel_delegate!(concat( + crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(concat( "expected an argument list or `=>` after `default`, found `", - $crate::crossbeam_channel_delegate!(stringify($args)), + crossbeam_channel_delegate!(stringify($args)), "`", )) )) }; (@list_error3 $($tail:tt)*) => { - $crate::crossbeam_channel_internal!(@list_error4 $($tail)*) + crossbeam_channel_internal!(@list_error4 $($tail)*) }; // Stage 4: fail with a generic error message. (@list_error4 $($tail:tt)*) => { - $crate::crossbeam_channel_delegate!(compile_error("invalid syntax")) + crossbeam_channel_delegate!(compile_error("invalid syntax")) }; // Success! All cases were parsed. @@ -387,7 +390,7 @@ macro_rules! crossbeam_channel_internal { $cases:tt $default:tt ) => { - $crate::crossbeam_channel_internal!( + crossbeam_channel_internal!( @init $cases $default @@ -400,7 +403,7 @@ macro_rules! crossbeam_channel_internal { ($($cases:tt)*) $default:tt ) => { - $crate::crossbeam_channel_internal!( + crossbeam_channel_internal!( @case ($($tail)*) ($($cases)* recv($r) -> $res => $body,) @@ -413,7 +416,7 @@ macro_rules! crossbeam_channel_internal { ($($cases:tt)*) $default:tt ) => { - $crate::crossbeam_channel_internal!( + crossbeam_channel_internal!( @case ($($tail)*) ($($cases)* recv($r) -> $res => $body,) @@ -426,10 +429,10 @@ macro_rules! crossbeam_channel_internal { ($($cases:tt)*) $default:tt ) => { - $crate::crossbeam_channel_delegate!(compile_error( - $crate::crossbeam_channel_delegate!(concat( + crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(concat( "invalid argument list in `recv(", - $crate::crossbeam_channel_delegate!(stringify($($args)*)), + crossbeam_channel_delegate!(stringify($($args)*)), ")`", )) )) @@ -440,10 +443,10 @@ macro_rules! crossbeam_channel_internal { ($($cases:tt)*) $default:tt ) => { - $crate::crossbeam_channel_delegate!(compile_error( - $crate::crossbeam_channel_delegate!(concat( + crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(concat( "expected an argument list after `recv`, found `", - $crate::crossbeam_channel_delegate!(stringify($t)), + crossbeam_channel_delegate!(stringify($t)), "`", )) )) @@ -455,7 +458,7 @@ macro_rules! crossbeam_channel_internal { ($($cases:tt)*) $default:tt ) => { - $crate::crossbeam_channel_internal!( + crossbeam_channel_internal!( @case ($($tail)*) ($($cases)* send($s, $m) -> $res => $body,) @@ -468,7 +471,7 @@ macro_rules! crossbeam_channel_internal { ($($cases:tt)*) $default:tt ) => { - $crate::crossbeam_channel_internal!( + crossbeam_channel_internal!( @case ($($tail)*) ($($cases)* send($s, $m) -> $res => $body,) @@ -481,10 +484,10 @@ macro_rules! crossbeam_channel_internal { ($($cases:tt)*) $default:tt ) => { - $crate::crossbeam_channel_delegate!(compile_error( - $crate::crossbeam_channel_delegate!(concat( + crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(concat( "invalid argument list in `send(", - $crate::crossbeam_channel_delegate!(stringify($($args)*)), + crossbeam_channel_delegate!(stringify($($args)*)), ")`", )) )) @@ -495,10 +498,10 @@ macro_rules! crossbeam_channel_internal { ($($cases:tt)*) $default:tt ) => { - $crate::crossbeam_channel_delegate!(compile_error( - $crate::crossbeam_channel_delegate!(concat( + crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(concat( "expected an argument list after `send`, found `", - $crate::crossbeam_channel_delegate!(stringify($t)), + crossbeam_channel_delegate!(stringify($t)), "`", )) )) @@ -510,7 +513,7 @@ macro_rules! crossbeam_channel_internal { $cases:tt () ) => { - $crate::crossbeam_channel_internal!( + crossbeam_channel_internal!( @case ($($tail)*) $cases @@ -523,7 +526,7 @@ macro_rules! crossbeam_channel_internal { $cases:tt () ) => { - $crate::crossbeam_channel_internal!( + crossbeam_channel_internal!( @case ($($tail)*) $cases @@ -536,7 +539,7 @@ macro_rules! crossbeam_channel_internal { $cases:tt () ) => { - $crate::crossbeam_channel_internal!( + crossbeam_channel_internal!( @case ($($tail)*) $cases @@ -549,7 +552,7 @@ macro_rules! crossbeam_channel_internal { $cases:tt ($($def:tt)+) ) => { - $crate::crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(compile_error( "there can be only one `default` case in a `select!` block" )) }; @@ -559,10 +562,10 @@ macro_rules! crossbeam_channel_internal { $cases:tt $default:tt ) => { - $crate::crossbeam_channel_delegate!(compile_error( - $crate::crossbeam_channel_delegate!(concat( + crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(concat( "invalid argument list in `default(", - $crate::crossbeam_channel_delegate!(stringify($($args)*)), + crossbeam_channel_delegate!(stringify($($args)*)), ")`", )) )) @@ -573,10 +576,10 @@ macro_rules! crossbeam_channel_internal { $cases:tt $default:tt ) => { - $crate::crossbeam_channel_delegate!(compile_error( - $crate::crossbeam_channel_delegate!(concat( + crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(concat( "expected an argument list or `=>` after `default`, found `", - $crate::crossbeam_channel_delegate!(stringify($t)), + crossbeam_channel_delegate!(stringify($t)), "`", )) )) @@ -588,10 +591,10 @@ macro_rules! crossbeam_channel_internal { $cases:tt $default:tt ) => { - $crate::crossbeam_channel_delegate!(compile_error( - $crate::crossbeam_channel_delegate!(concat( + crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(concat( "expected one of `recv`, `send`, or `default`, found `", - $crate::crossbeam_channel_delegate!(stringify($case)), + crossbeam_channel_delegate!(stringify($case)), "`", )) )) @@ -757,13 +760,13 @@ macro_rules! crossbeam_channel_internal { ($($cases:tt)*) $default:tt ) => {{ - const _LEN: usize = $crate::crossbeam_channel_internal!(@count ($($cases)*)); + const _LEN: usize = crossbeam_channel_internal!(@count ($($cases)*)); let _handle: &$crate::internal::SelectHandle = &$crate::never::<()>(); #[allow(unused_mut)] let mut _sel = [(_handle, 0, ::std::ptr::null()); _LEN]; - $crate::crossbeam_channel_internal!( + crossbeam_channel_internal!( @add _sel ($($cases)*) @@ -811,7 +814,7 @@ macro_rules! crossbeam_channel_internal { 0 }; (@count ($oper:ident $args:tt -> $res:pat => $body:tt, $($cases:tt)*)) => { - 1 + $crate::crossbeam_channel_internal!(@count ($($cases)*)) + 1 + crossbeam_channel_internal!(@count ($($cases)*)) }; // Run blocking selection. @@ -826,10 +829,11 @@ macro_rules! crossbeam_channel_internal { let _oper = $crate::internal::select(&mut $sel); // Erase the lifetime so that `sel` can be dropped early even without NLL. + #[allow(unsafe_code)] unsafe { ::std::mem::transmute(_oper) } }; - $crate::crossbeam_channel_internal! { + crossbeam_channel_internal! { @complete $sel _oper @@ -848,6 +852,7 @@ macro_rules! crossbeam_channel_internal { let _oper = $crate::internal::try_select(&mut $sel); // Erase the lifetime so that `sel` can be dropped early even without NLL. + #[allow(unsafe_code)] unsafe { ::std::mem::transmute(_oper) } }; @@ -857,7 +862,7 @@ macro_rules! crossbeam_channel_internal { $body } Some(_oper) => { - $crate::crossbeam_channel_internal! { + crossbeam_channel_internal! { @complete $sel _oper @@ -878,6 +883,7 @@ macro_rules! crossbeam_channel_internal { let _oper = $crate::internal::select_timeout(&mut $sel, $timeout); // Erase the lifetime so that `sel` can be dropped early even without NLL. + #[allow(unsafe_code)] unsafe { ::std::mem::transmute(_oper) } }; @@ -887,7 +893,7 @@ macro_rules! crossbeam_channel_internal { $body } ::std::option::Option::Some(_oper) => { - $crate::crossbeam_channel_internal! { + crossbeam_channel_internal! { @complete $sel _oper @@ -904,7 +910,7 @@ macro_rules! crossbeam_channel_internal { () $cases:tt ) => { - $crate::crossbeam_channel_delegate!(compile_error("too many operations in a `select!` block")) + crossbeam_channel_delegate!(compile_error("too many operations in a `select!` block")) }; // Add a receive operation to `sel`. (@add @@ -916,6 +922,7 @@ macro_rules! crossbeam_channel_internal { ) => {{ match $r { ref _r => { + #[allow(unsafe_code)] let $var: &$crate::Receiver<_> = unsafe { let _r: &$crate::Receiver<_> = _r; @@ -927,7 +934,7 @@ macro_rules! crossbeam_channel_internal { }; $sel[$i] = ($var, $i, $var as *const $crate::Receiver<_> as *const u8); - $crate::crossbeam_channel_internal!( + crossbeam_channel_internal!( @add $sel ($($tail)*) @@ -948,6 +955,7 @@ macro_rules! crossbeam_channel_internal { ) => {{ match $s { ref _s => { + #[allow(unsafe_code)] let $var: &$crate::Sender<_> = unsafe { let _s: &$crate::Sender<_> = _s; @@ -959,7 +967,7 @@ macro_rules! crossbeam_channel_internal { }; $sel[$i] = ($var, $i, $var as *const $crate::Sender<_> as *const u8); - $crate::crossbeam_channel_internal!( + crossbeam_channel_internal!( @add $sel ($($tail)*) @@ -984,7 +992,7 @@ macro_rules! crossbeam_channel_internal { let $res = _res; $body } else { - $crate::crossbeam_channel_internal! { + crossbeam_channel_internal! { @complete $sel $oper @@ -1005,7 +1013,7 @@ macro_rules! crossbeam_channel_internal { let $res = _res; $body } else { - $crate::crossbeam_channel_internal! { + crossbeam_channel_internal! { @complete $sel $oper @@ -1019,34 +1027,34 @@ macro_rules! crossbeam_channel_internal { $oper:ident () ) => {{ - $crate::crossbeam_channel_delegate!(unreachable( + crossbeam_channel_delegate!(unreachable( "internal error in crossbeam-channel: invalid case" )) }}; // Catches a bug within this macro (should not happen). (@$($tokens:tt)*) => { - $crate::crossbeam_channel_delegate!(compile_error( - $crate::crossbeam_channel_delegate!(concat( + crossbeam_channel_delegate!(compile_error( + crossbeam_channel_delegate!(concat( "internal error in crossbeam-channel: ", - $crate::crossbeam_channel_delegate!(stringify(@$($tokens)*)), + crossbeam_channel_delegate!(stringify(@$($tokens)*)), )) )) }; // The entry points. () => { - $crate::crossbeam_channel_delegate!(compile_error("empty `select!` block")) + crossbeam_channel_delegate!(compile_error("empty `select!` block")) }; ($($case:ident $(($($args:tt)*))* => $body:expr $(,)*)*) => { - $crate::crossbeam_channel_internal!( + crossbeam_channel_internal!( @list ($($case $(($($args)*))* => { $body },)*) () ) }; ($($tokens:tt)*) => { - $crate::crossbeam_channel_internal!( + crossbeam_channel_internal!( @list ($($tokens)*) () @@ -1076,7 +1084,11 @@ macro_rules! crossbeam_channel_internal { /// Block until a send or a receive operation is selected: /// /// ``` -/// use crossbeam_channel::{select, unbounded}; +/// # #[macro_use] +/// # extern crate crossbeam_channel; +/// # fn main() { +/// use std::thread; +/// use crossbeam_channel::unbounded; /// /// let (s1, r1) = unbounded(); /// let (s2, r2) = unbounded(); @@ -1090,14 +1102,18 @@ macro_rules! crossbeam_channel_internal { /// assert_eq!(r2.recv(), Ok(20)); /// } /// } +/// # } /// ``` /// /// Select from a set of operations without blocking: /// /// ``` +/// # #[macro_use] +/// # extern crate crossbeam_channel; +/// # fn main() { /// use std::thread; /// use std::time::Duration; -/// use crossbeam_channel::{select, unbounded}; +/// use crossbeam_channel::unbounded; /// /// let (s1, r1) = unbounded(); /// let (s2, r2) = unbounded(); @@ -1117,14 +1133,18 @@ macro_rules! crossbeam_channel_internal { /// recv(r2) -> msg => panic!(), /// default => println!("not ready"), /// } +/// # } /// ``` /// /// Select over a set of operations with a timeout: /// /// ``` +/// # #[macro_use] +/// # extern crate crossbeam_channel; +/// # fn main() { /// use std::thread; /// use std::time::Duration; -/// use crossbeam_channel::{select, unbounded}; +/// use crossbeam_channel::unbounded; /// /// let (s1, r1) = unbounded(); /// let (s2, r2) = unbounded(); @@ -1144,14 +1164,18 @@ macro_rules! crossbeam_channel_internal { /// recv(r2) -> msg => panic!(), /// default(Duration::from_millis(100)) => println!("timed out"), /// } +/// # } /// ``` /// /// Optionally add a receive operation to `select!` using [`never`]: /// /// ``` +/// # #[macro_use] +/// # extern crate crossbeam_channel; +/// # fn main() { /// use std::thread; /// use std::time::Duration; -/// use crossbeam_channel::{select, never, unbounded}; +/// use crossbeam_channel::{never, unbounded}; /// /// let (s1, r1) = unbounded(); /// let (s2, r2) = unbounded(); @@ -1173,6 +1197,7 @@ macro_rules! crossbeam_channel_internal { /// recv(r1) -> msg => panic!(), /// recv(r2.unwrap_or(&never())) -> msg => assert_eq!(msg, Ok(20)), /// } +/// # } /// ``` /// /// To optionally add a timeout to `select!`, see the [example] for [`never`]. @@ -1182,7 +1207,7 @@ macro_rules! crossbeam_channel_internal { #[macro_export(local_inner_macros)] macro_rules! select { ($($tokens:tt)*) => { - $crate::crossbeam_channel_internal!( + crossbeam_channel_internal!( $($tokens)* ) }; diff --git a/third_party/rust/crossbeam-channel/src/utils.rs b/third_party/rust/crossbeam-channel/src/utils.rs index 3fe171b2e452..c6513bc3f81b 100644 --- a/third_party/rust/crossbeam-channel/src/utils.rs +++ b/third_party/rust/crossbeam-channel/src/utils.rs @@ -17,7 +17,7 @@ pub fn shuffle(v: &mut [T]) { } thread_local! { - static RNG: Cell> = Cell::new(Wrapping(1_406_868_647)); + static RNG: Cell> = Cell::new(Wrapping(1406868647)); } let _ = RNG.try_with(|rng| { @@ -87,17 +87,17 @@ impl Spinlock { } /// A guard holding a spinlock locked. -pub struct SpinlockGuard<'a, T> { +pub struct SpinlockGuard<'a, T: 'a> { parent: &'a Spinlock, } -impl Drop for SpinlockGuard<'_, T> { +impl<'a, T> Drop for SpinlockGuard<'a, T> { fn drop(&mut self) { self.parent.flag.store(false, Ordering::Release); } } -impl Deref for SpinlockGuard<'_, T> { +impl<'a, T> Deref for SpinlockGuard<'a, T> { type Target = T; fn deref(&self) -> &T { @@ -105,7 +105,7 @@ impl Deref for SpinlockGuard<'_, T> { } } -impl DerefMut for SpinlockGuard<'_, T> { +impl<'a, T> DerefMut for SpinlockGuard<'a, T> { fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.parent.value.get() } } diff --git a/third_party/rust/crossbeam-channel/src/waker.rs b/third_party/rust/crossbeam-channel/src/waker.rs index 3d0af2616cc4..7f3428b7ebbe 100644 --- a/third_party/rust/crossbeam-channel/src/waker.rs +++ b/third_party/rust/crossbeam-channel/src/waker.rs @@ -3,9 +3,9 @@ use std::sync::atomic::{AtomicBool, Ordering}; use std::thread::{self, ThreadId}; -use crate::context::Context; -use crate::select::{Operation, Selected}; -use crate::utils::Spinlock; +use context::Context; +use select::{Operation, Selected}; +use utils::Spinlock; /// Represents a thread blocked on a specific channel operation. pub struct Entry { @@ -221,14 +221,12 @@ impl SyncWaker { pub fn notify(&self) { if !self.is_empty.load(Ordering::SeqCst) { let mut inner = self.inner.lock(); - if !self.is_empty.load(Ordering::SeqCst) { - inner.try_select(); - inner.notify(); - self.is_empty.store( - inner.selectors.is_empty() && inner.observers.is_empty(), - Ordering::SeqCst, - ); - } + inner.try_select(); + inner.notify(); + self.is_empty.store( + inner.selectors.is_empty() && inner.observers.is_empty(), + Ordering::SeqCst, + ); } } diff --git a/third_party/rust/crossbeam-channel/tests/after.rs b/third_party/rust/crossbeam-channel/tests/after.rs index 20670dc5adac..1137bb1b7762 100644 --- a/third_party/rust/crossbeam-channel/tests/after.rs +++ b/third_party/rust/crossbeam-channel/tests/after.rs @@ -1,11 +1,16 @@ //! Tests for the after channel flavor. +#[macro_use] +extern crate crossbeam_channel; +extern crate crossbeam_utils; +extern crate rand; + use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering; use std::thread; use std::time::{Duration, Instant}; -use crossbeam_channel::{after, select, Select, TryRecvError}; +use crossbeam_channel::{after, Select, TryRecvError}; use crossbeam_utils::thread::scope; fn ms(ms: u64) -> Duration { diff --git a/third_party/rust/crossbeam-channel/tests/array.rs b/third_party/rust/crossbeam-channel/tests/array.rs index a7ae323d91af..a6fc8451b1bf 100644 --- a/third_party/rust/crossbeam-channel/tests/array.rs +++ b/third_party/rust/crossbeam-channel/tests/array.rs @@ -1,12 +1,17 @@ //! Tests for the array channel flavor. +#[macro_use] +extern crate crossbeam_channel; +extern crate crossbeam_utils; +extern crate rand; + use std::any::Any; use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering; use std::thread; use std::time::Duration; -use crossbeam_channel::{bounded, select, Receiver}; +use crossbeam_channel::{bounded, Receiver}; use crossbeam_channel::{RecvError, RecvTimeoutError, TryRecvError}; use crossbeam_channel::{SendError, SendTimeoutError, TrySendError}; use crossbeam_utils::thread::scope; diff --git a/third_party/rust/crossbeam-channel/tests/golang.rs b/third_party/rust/crossbeam-channel/tests/golang.rs index e999aea36a5f..be015b28fc3a 100644 --- a/third_party/rust/crossbeam-channel/tests/golang.rs +++ b/third_party/rust/crossbeam-channel/tests/golang.rs @@ -9,6 +9,9 @@ //! - https://golang.org/LICENSE //! - https://golang.org/PATENTS +#[macro_use] +extern crate crossbeam_channel; + use std::any::Any; use std::cell::Cell; use std::collections::HashMap; @@ -16,7 +19,7 @@ use std::sync::{Arc, Condvar, Mutex}; use std::thread; use std::time::Duration; -use crossbeam_channel::{bounded, select, tick, Receiver, Select, Sender}; +use crossbeam_channel::{bounded, tick, Receiver, Select, Sender}; fn ms(ms: u64) -> Duration { Duration::from_millis(ms) @@ -432,13 +435,13 @@ mod nonblock { } go!(c32, sync, i32receiver(c32, sync)); - let mut r#try = 0; + let mut try = 0; loop { select! { send(c32.tx(), 123) -> _ => break, default => { - r#try += 1; - if r#try > MAX_TRIES { + try += 1; + if try > MAX_TRIES { println!("i32receiver buffer={}", buffer); panic!("fail") } @@ -451,7 +454,7 @@ mod nonblock { if buffer > 0 { sync.recv(); } - let mut r#try = 0; + let mut try = 0; loop { select! { recv(c32.rx()) -> v => { @@ -461,8 +464,8 @@ mod nonblock { break; } default => { - r#try += 1; - if r#try > MAX_TRIES { + try += 1; + if try > MAX_TRIES { println!("i32sender buffer={}", buffer); panic!("fail"); } @@ -475,13 +478,13 @@ mod nonblock { } go!(c64, sync, i64receiver(c64, sync)); - let mut r#try = 0; + let mut try = 0; loop { select! { send(c64.tx(), 123456) -> _ => break, default => { - r#try += 1; - if r#try > MAX_TRIES { + try += 1; + if try > MAX_TRIES { println!("i64receiver buffer={}", buffer); panic!("fail") } @@ -494,7 +497,7 @@ mod nonblock { if buffer > 0 { sync.recv(); } - let mut r#try = 0; + let mut try = 0; loop { select! { recv(c64.rx()) -> v => { @@ -504,8 +507,8 @@ mod nonblock { break; } default => { - r#try += 1; - if r#try > MAX_TRIES { + try += 1; + if try > MAX_TRIES { println!("i64sender buffer={}", buffer); panic!("fail"); } @@ -518,13 +521,13 @@ mod nonblock { } go!(cb, sync, breceiver(cb, sync)); - let mut r#try = 0; + let mut try = 0; loop { select! { send(cb.tx(), true) -> _ => break, default => { - r#try += 1; - if r#try > MAX_TRIES { + try += 1; + if try > MAX_TRIES { println!("breceiver buffer={}", buffer); panic!("fail") } @@ -537,7 +540,7 @@ mod nonblock { if buffer > 0 { sync.recv(); } - let mut r#try = 0; + let mut try = 0; loop { select! { recv(cb.rx()) -> v => { @@ -547,8 +550,8 @@ mod nonblock { break; } default => { - r#try += 1; - if r#try > MAX_TRIES { + try += 1; + if try > MAX_TRIES { println!("bsender buffer={}", buffer); panic!("fail"); } @@ -561,13 +564,13 @@ mod nonblock { } go!(cs, sync, sreceiver(cs, sync)); - let mut r#try = 0; + let mut try = 0; loop { select! { send(cs.tx(), "hello".to_string()) -> _ => break, default => { - r#try += 1; - if r#try > MAX_TRIES { + try += 1; + if try > MAX_TRIES { println!("sreceiver buffer={}", buffer); panic!("fail") } @@ -580,7 +583,7 @@ mod nonblock { if buffer > 0 { sync.recv(); } - let mut r#try = 0; + let mut try = 0; loop { select! { recv(cs.rx()) -> v => { @@ -590,8 +593,8 @@ mod nonblock { break; } default => { - r#try += 1; - if r#try > MAX_TRIES { + try += 1; + if try > MAX_TRIES { println!("ssender buffer={}", buffer); panic!("fail"); } @@ -943,14 +946,14 @@ mod chan_test { go!(c, done, { let v = c.try_recv(); - done.send(v.is_none()); + done.send(v.is_some()); }); thread::sleep(ms(1)); c.close(); if !done.recv().unwrap() { - panic!(); + // panic!(); } } diff --git a/third_party/rust/crossbeam-channel/tests/iter.rs b/third_party/rust/crossbeam-channel/tests/iter.rs index 38bcac2f0eeb..6acec59c28ef 100644 --- a/third_party/rust/crossbeam-channel/tests/iter.rs +++ b/third_party/rust/crossbeam-channel/tests/iter.rs @@ -1,5 +1,8 @@ //! Tests for iteration over receivers. +extern crate crossbeam_channel; +extern crate crossbeam_utils; + use crossbeam_channel::unbounded; use crossbeam_utils::thread::scope; diff --git a/third_party/rust/crossbeam-channel/tests/list.rs b/third_party/rust/crossbeam-channel/tests/list.rs index 8b841054067c..ed1d4c4209cd 100644 --- a/third_party/rust/crossbeam-channel/tests/list.rs +++ b/third_party/rust/crossbeam-channel/tests/list.rs @@ -1,12 +1,17 @@ //! Tests for the list channel flavor. +#[macro_use] +extern crate crossbeam_channel; +extern crate crossbeam_utils; +extern crate rand; + use std::any::Any; use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering; use std::thread; use std::time::Duration; -use crossbeam_channel::{select, unbounded, Receiver}; +use crossbeam_channel::{unbounded, Receiver}; use crossbeam_channel::{RecvError, RecvTimeoutError, TryRecvError}; use crossbeam_channel::{SendError, SendTimeoutError, TrySendError}; use crossbeam_utils::thread::scope; diff --git a/third_party/rust/crossbeam-channel/tests/mpsc.rs b/third_party/rust/crossbeam-channel/tests/mpsc.rs index 2a0786a710b0..213b9d8b7d34 100644 --- a/third_party/rust/crossbeam-channel/tests/mpsc.rs +++ b/third_party/rust/crossbeam-channel/tests/mpsc.rs @@ -20,13 +20,14 @@ //! - https://github.com/rust-lang/rust/blob/master/COPYRIGHT //! - https://www.rust-lang.org/en-US/legal.html +#[macro_use] +extern crate crossbeam_channel as cc; + use std::sync::mpsc::{RecvError, RecvTimeoutError, TryRecvError}; use std::sync::mpsc::{SendError, TrySendError}; use std::thread::JoinHandle; use std::time::Duration; -use crossbeam_channel as cc; - pub struct Sender { pub inner: cc::Sender, } @@ -174,7 +175,7 @@ macro_rules! select { ( $($name:pat = $rx:ident.$meth:ident() => $code:expr),+ ) => ({ - cc::crossbeam_channel_internal! { + crossbeam_channel_internal! { $( recv(($rx).inner) -> res => { let $name = res.map_err(|_| ::std::sync::mpsc::RecvError); @@ -1684,22 +1685,22 @@ mod select_tests { let (tx2, rx2) = channel::(); tx1.send(1).unwrap(); select! { - foo = rx1.recv() => assert_eq!(foo.unwrap(), 1), - _bar = rx2.recv() => panic!() + foo = rx1.recv() => { assert_eq!(foo.unwrap(), 1); }, + _bar = rx2.recv() => { panic!() } } tx2.send(2).unwrap(); select! { - _foo = rx1.recv() => panic!(), - bar = rx2.recv() => assert_eq!(bar.unwrap(), 2) + _foo = rx1.recv() => { panic!() }, + bar = rx2.recv() => { assert_eq!(bar.unwrap(), 2) } } drop(tx1); select! { - foo = rx1.recv() => assert!(foo.is_err()), - _bar = rx2.recv() => panic!() + foo = rx1.recv() => { assert!(foo.is_err()); }, + _bar = rx2.recv() => { panic!() } } drop(tx2); select! { - bar = rx2.recv() => assert!(bar.is_err()) + bar = rx2.recv() => { assert!(bar.is_err()); } } } @@ -1712,11 +1713,11 @@ mod select_tests { let (tx5, rx5) = channel::(); tx5.send(4).unwrap(); select! { - _foo = rx1.recv() => panic!("1"), - _foo = rx2.recv() => panic!("2"), - _foo = rx3.recv() => panic!("3"), - _foo = rx4.recv() => panic!("4"), - foo = rx5.recv() => assert_eq!(foo.unwrap(), 4) + _foo = rx1.recv() => { panic!("1") }, + _foo = rx2.recv() => { panic!("2") }, + _foo = rx3.recv() => { panic!("3") }, + _foo = rx4.recv() => { panic!("4") }, + foo = rx5.recv() => { assert_eq!(foo.unwrap(), 4); } } } @@ -1727,8 +1728,8 @@ mod select_tests { drop(tx2); select! { - _a1 = rx1.recv() => panic!(), - a2 = rx2.recv() => assert!(a2.is_err()) + _a1 = rx1.recv() => { panic!() }, + a2 = rx2.recv() => { assert!(a2.is_err()); } } } @@ -1750,13 +1751,13 @@ mod select_tests { }); select! { - a = rx1.recv() => assert_eq!(a.unwrap(), 1), - _b = rx2.recv() => panic!() + a = rx1.recv() => { assert_eq!(a.unwrap(), 1); }, + _b = rx2.recv() => { panic!() } } tx3.send(1).unwrap(); select! { - a = rx1.recv() => assert!(a.is_err()), - _b = rx2.recv() => panic!() + a = rx1.recv() => { assert!(a.is_err()) }, + _b = rx2.recv() => { panic!() } } t.join().unwrap(); } diff --git a/third_party/rust/crossbeam-channel/tests/never.rs b/third_party/rust/crossbeam-channel/tests/never.rs index 31cebf67d263..35b6f74dda9e 100644 --- a/third_party/rust/crossbeam-channel/tests/never.rs +++ b/third_party/rust/crossbeam-channel/tests/never.rs @@ -1,9 +1,13 @@ //! Tests for the never channel flavor. +#[macro_use] +extern crate crossbeam_channel; +extern crate rand; + use std::thread; use std::time::{Duration, Instant}; -use crossbeam_channel::{never, select, tick, unbounded}; +use crossbeam_channel::{never, tick, unbounded}; fn ms(ms: u64) -> Duration { Duration::from_millis(ms) diff --git a/third_party/rust/crossbeam-channel/tests/ready.rs b/third_party/rust/crossbeam-channel/tests/ready.rs index 700f487e0417..23769b7bd77c 100644 --- a/third_party/rust/crossbeam-channel/tests/ready.rs +++ b/third_party/rust/crossbeam-channel/tests/ready.rs @@ -1,5 +1,8 @@ //! Tests for channel readiness using the `Select` struct. +extern crate crossbeam_channel; +extern crate crossbeam_utils; + use std::any::Any; use std::cell::Cell; use std::thread; @@ -769,7 +772,7 @@ fn fairness1() { #[test] fn fairness2() { - const COUNT: usize = 100_000; + const COUNT: usize = 10_000; let (s1, r1) = unbounded::<()>(); let (s2, r2) = bounded::<()>(1); @@ -828,7 +831,7 @@ fn fairness2() { } } } - assert!(hits.iter().all(|x| x.get() > 0)); + assert!(hits.iter().all(|x| x.get() >= COUNT / hits.len() / 10)); }) .unwrap(); } diff --git a/third_party/rust/crossbeam-channel/tests/same_channel.rs b/third_party/rust/crossbeam-channel/tests/same_channel.rs index da4c8f3e70fd..8e34faf4483e 100644 --- a/third_party/rust/crossbeam-channel/tests/same_channel.rs +++ b/third_party/rust/crossbeam-channel/tests/same_channel.rs @@ -1,3 +1,5 @@ +extern crate crossbeam_channel; + use std::time::Duration; use crossbeam_channel::{after, bounded, never, tick, unbounded}; diff --git a/third_party/rust/crossbeam-channel/tests/select.rs b/third_party/rust/crossbeam-channel/tests/select.rs index 4cf08b6a6282..b18d66d7cd03 100644 --- a/third_party/rust/crossbeam-channel/tests/select.rs +++ b/third_party/rust/crossbeam-channel/tests/select.rs @@ -1,5 +1,8 @@ //! Tests for channel selection using the `Select` struct. +extern crate crossbeam_channel; +extern crate crossbeam_utils; + use std::any::Any; use std::cell::Cell; use std::thread; diff --git a/third_party/rust/crossbeam-channel/tests/select_macro.rs b/third_party/rust/crossbeam-channel/tests/select_macro.rs index c05f7a0e6fec..a9cc7fac7999 100644 --- a/third_party/rust/crossbeam-channel/tests/select_macro.rs +++ b/third_party/rust/crossbeam-channel/tests/select_macro.rs @@ -1,6 +1,10 @@ //! Tests for the `select!` macro. -#![forbid(unsafe_code)] // select! is safe. +#![deny(unsafe_code)] + +#[macro_use] +extern crate crossbeam_channel; +extern crate crossbeam_utils; use std::any::Any; use std::cell::Cell; @@ -8,7 +12,7 @@ use std::ops::Deref; use std::thread; use std::time::{Duration, Instant}; -use crossbeam_channel::{after, bounded, never, select, tick, unbounded}; +use crossbeam_channel::{after, bounded, never, tick, unbounded}; use crossbeam_channel::{Receiver, RecvError, SendError, Sender, TryRecvError}; use crossbeam_utils::thread::scope; diff --git a/third_party/rust/crossbeam-channel/tests/thread_locals.rs b/third_party/rust/crossbeam-channel/tests/thread_locals.rs index 9e27146df105..fd319c728463 100644 --- a/third_party/rust/crossbeam-channel/tests/thread_locals.rs +++ b/third_party/rust/crossbeam-channel/tests/thread_locals.rs @@ -1,9 +1,13 @@ //! Tests that make sure accessing thread-locals while exiting the thread doesn't cause panics. +#[macro_use] +extern crate crossbeam_channel; +extern crate crossbeam_utils; + use std::thread; use std::time::Duration; -use crossbeam_channel::{select, unbounded}; +use crossbeam_channel::unbounded; use crossbeam_utils::thread::scope; fn ms(ms: u64) -> Duration { diff --git a/third_party/rust/crossbeam-channel/tests/tick.rs b/third_party/rust/crossbeam-channel/tests/tick.rs index 5dc87306ff35..34e55b31bf07 100644 --- a/third_party/rust/crossbeam-channel/tests/tick.rs +++ b/third_party/rust/crossbeam-channel/tests/tick.rs @@ -1,11 +1,16 @@ //! Tests for the tick channel flavor. +#[macro_use] +extern crate crossbeam_channel; +extern crate crossbeam_utils; +extern crate rand; + use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering; use std::thread; use std::time::{Duration, Instant}; -use crossbeam_channel::{after, select, tick, Select, TryRecvError}; +use crossbeam_channel::{after, tick, Select, TryRecvError}; use crossbeam_utils::thread::scope; fn ms(ms: u64) -> Duration { diff --git a/third_party/rust/crossbeam-channel/tests/zero.rs b/third_party/rust/crossbeam-channel/tests/zero.rs index 66dcc1eeb661..bd336ee157fc 100644 --- a/third_party/rust/crossbeam-channel/tests/zero.rs +++ b/third_party/rust/crossbeam-channel/tests/zero.rs @@ -1,12 +1,17 @@ //! Tests for the zero channel flavor. +#[macro_use] +extern crate crossbeam_channel; +extern crate crossbeam_utils; +extern crate rand; + use std::any::Any; use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering; use std::thread; use std::time::Duration; -use crossbeam_channel::{bounded, select, Receiver}; +use crossbeam_channel::{bounded, Receiver}; use crossbeam_channel::{RecvError, RecvTimeoutError, TryRecvError}; use crossbeam_channel::{SendError, SendTimeoutError, TrySendError}; use crossbeam_utils::thread::scope; diff --git a/third_party/rust/maybe-uninit/.cargo-checksum.json b/third_party/rust/maybe-uninit/.cargo-checksum.json new file mode 100644 index 000000000000..21adadd26e10 --- /dev/null +++ b/third_party/rust/maybe-uninit/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"a4e484fa7295e2a1b69c1faefbf3274acf652c66a6538924e0f6cc58d81c00cf","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"2166f8a5c41801089365a655cda7d5e038f9721f0ada1a6bac55eb4d6de8e1c2","build.rs":"8cb7472f84e44c683b3bd590ce1b281eb9fc0d8d6911f7d914473310159ab2fa","src/lib.rs":"c8a4a04cb4114b6d0fa210350d7b6b20636a9cc24ffc3b9576e7219f61d8a7f4","src/maybe_uninit.rs":"c1365ba9745a71d6658f6f4ab8cff63a89743389860e33eacfb817d03a750fde","tests/doesnt_drop.rs":"2dcaf5a5ea84f1c65520c37b1de3b94e2de6ee599d049afb8175376c87c2ae46"},"package":"60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"} \ No newline at end of file diff --git a/third_party/rust/maybe-uninit/Cargo.toml b/third_party/rust/maybe-uninit/Cargo.toml new file mode 100644 index 000000000000..f22456274e5b --- /dev/null +++ b/third_party/rust/maybe-uninit/Cargo.toml @@ -0,0 +1,22 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +name = "maybe-uninit" +version = "2.0.0" +authors = ["est31 ", "The Rust Project Developers"] +description = "MaybeUninit for friends of backwards compatibility" +readme = "README.md" +license = "Apache-2.0 OR MIT" +repository = "https://github.com/est31/maybe-uninit" + +[dependencies] diff --git a/third_party/rust/maybe-uninit/LICENSE-APACHE b/third_party/rust/maybe-uninit/LICENSE-APACHE new file mode 100644 index 000000000000..16fe87b06e80 --- /dev/null +++ b/third_party/rust/maybe-uninit/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/third_party/rust/maybe-uninit/LICENSE-MIT b/third_party/rust/maybe-uninit/LICENSE-MIT new file mode 100644 index 000000000000..25597d5838fa --- /dev/null +++ b/third_party/rust/maybe-uninit/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2010 The Rust Project Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/third_party/rust/maybe-uninit/README.md b/third_party/rust/maybe-uninit/README.md new file mode 100644 index 000000000000..ca0ec6ecdb0f --- /dev/null +++ b/third_party/rust/maybe-uninit/README.md @@ -0,0 +1,19 @@ +# maybe-uninit + +Quite often, uses of `std::mem::uninitialized()` end up in unsound code. +Therefore, the `MaybeUninit` union has been added to `std::mem` and `std::mem::uninitialized()` is being deprecated. +However, `MaybeUninit` has been added quite recently. +Sometimes you might want to support older versions of Rust as well. +Here is where `maybe-uninit` comes in: it supports stable Rust versions starting with 1.20.0. + +Sadly, a feature-complete implementation of `MaybeUninit` is not possible on stable Rust. +Therefore, the library offers the guarantees of `MaybeUninit` in a staged fashion: + +* Rust 1.36.0 onward: `MaybeUninit` implementation of Rust stable is being re-exported + +* Rust 1.22.x - 1.35.0: No panicing on uninhabited types, + unsoundness when used with types like `bool` or enums. + However, there is protection from accidentially `Drop`ing e.g. during unwind! + +* Rust 1.20.x - 1.21.x: No support for Copy/Clone of `MaybeUninit`, + even if `T` impls `Copy` or even `Clone`. diff --git a/third_party/rust/maybe-uninit/build.rs b/third_party/rust/maybe-uninit/build.rs new file mode 100644 index 000000000000..ebb9cc8f4c75 --- /dev/null +++ b/third_party/rust/maybe-uninit/build.rs @@ -0,0 +1,50 @@ +use std::env; +use std::process::Command; +use std::str::FromStr; + +fn main() { + let minor = match rustc_minor_version() { + Some(minor) => minor, + None => return, + }; + if minor >= 22 { + println!("cargo:rustc-cfg=derive_copy"); + } + if minor >= 28 { + println!("cargo:rustc-cfg=repr_transparent"); + } + if minor >= 36 { + println!("cargo:rustc-cfg=native_uninit"); + } + +} + +fn rustc_minor_version() -> Option { + let rustc = env::var_os("RUSTC"); + + let output = rustc.and_then(|rustc| { + Command::new(rustc).arg("--version").output().ok() + }); + + let version = output.and_then(|output| { + String::from_utf8(output.stdout).ok() + }); + + let version = if let Some(version) = version { + version + } else { + return None; + }; + + let mut pieces = version.split('.'); + if pieces.next() != Some("rustc 1") { + return None; + } + + let next = match pieces.next() { + Some(next) => next, + None => return None, + }; + + u32::from_str(next).ok() +} diff --git a/third_party/rust/maybe-uninit/src/lib.rs b/third_party/rust/maybe-uninit/src/lib.rs new file mode 100644 index 000000000000..e6d697b92b9e --- /dev/null +++ b/third_party/rust/maybe-uninit/src/lib.rs @@ -0,0 +1,10 @@ +#![no_std] + +#[cfg(not(native_uninit))] +mod maybe_uninit; + +#[cfg(not(native_uninit))] +pub use maybe_uninit::MaybeUninit; + +#[cfg(native_uninit)] +pub use core::mem::MaybeUninit; diff --git a/third_party/rust/maybe-uninit/src/maybe_uninit.rs b/third_party/rust/maybe-uninit/src/maybe_uninit.rs new file mode 100644 index 000000000000..02c55cea3136 --- /dev/null +++ b/third_party/rust/maybe-uninit/src/maybe_uninit.rs @@ -0,0 +1,594 @@ +//use core::intrinsics; +use core::mem::ManuallyDrop; +use core::ptr; +use core::mem::uninitialized; + +/// A wrapper type to construct uninitialized instances of `T`. +/// +/// # Initialization invariant +/// +/// The compiler, in general, assumes that variables are properly initialized +/// at their respective type. For example, a variable of reference type must +/// be aligned and non-NULL. This is an invariant that must *always* be upheld, +/// even in unsafe code. As a consequence, zero-initializing a variable of reference +/// type causes instantaneous [undefined behavior][ub], no matter whether that reference +/// ever gets used to access memory: +/// +/// ```rust,no_run +/// # extern crate maybe_uninit; +/// # fn main() { +/// use maybe_uninit::MaybeUninit; +/// use std::mem; +/// +/// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior! +/// // The equivalent code with `MaybeUninit<&i32>`: +/// let x: &i32 = unsafe { MaybeUninit::zeroed().assume_init() }; // undefined behavior! +/// # } +/// ``` +/// +/// This is exploited by the compiler for various optimizations, such as eliding +/// run-time checks and optimizing `enum` layout. +/// +/// Similarly, entirely uninitialized memory may have any content, while a `bool` must +/// always be `true` or `false`. Hence, creating an uninitialized `bool` is undefined behavior: +/// +/// ```rust,no_run +/// # extern crate maybe_uninit; +/// # fn main() { +/// use maybe_uninit::MaybeUninit; +/// use std::mem; +/// +/// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior! +/// // The equivalent code with `MaybeUninit`: +/// let b: bool = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! +/// # } +/// ``` +/// +/// Moreover, uninitialized memory is special in that the compiler knows that +/// it does not have a fixed value. This makes it undefined behavior to have +/// uninitialized data in a variable even if that variable has an integer type, +/// which otherwise can hold any *fixed* bit pattern: +/// +/// ```rust,no_run +/// # extern crate maybe_uninit; +/// # fn main() { +/// use maybe_uninit::MaybeUninit; +/// use std::mem; +/// +/// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior! +/// // The equivalent code with `MaybeUninit`: +/// let x: i32 = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! +/// # } +/// ``` +/// (Notice that the rules around uninitialized integers are not finalized yet, but +/// until they are, it is advisable to avoid them.) +/// +/// On top of that, remember that most types have additional invariants beyond merely +/// being considered initialized at the type level. For example, a `1`-initialized [`Vec`] +/// is considered initialized because the only requirement the compiler knows about it +/// is that the data pointer must be non-null. Creating such a `Vec` does not cause +/// *immediate* undefined behavior, but will cause undefined behavior with most +/// safe operations (including dropping it). +/// +/// [`Vec`]: ../../std/vec/struct.Vec.html +/// +/// # Examples +/// +/// `MaybeUninit` serves to enable unsafe code to deal with uninitialized data. +/// It is a signal to the compiler indicating that the data here might *not* +/// be initialized: +/// +/// ```rust +/// # extern crate maybe_uninit; +/// # fn main() { +/// use maybe_uninit::MaybeUninit; +/// use std::ptr::write; +/// +/// // Create an explicitly uninitialized reference. The compiler knows that data inside +/// // a `MaybeUninit` may be invalid, and hence this is not UB: +/// let mut x = MaybeUninit::<&i32>::uninit(); +/// // Set it to a valid value. +/// const V: &'static i32 = &0; +/// unsafe { write(x.as_mut_ptr(), V); } +/// // Extract the initialized data -- this is only allowed *after* properly +/// // initializing `x`! +/// let x = unsafe { x.assume_init() }; +/// # } +/// ``` +/// +/// The compiler then knows to not make any incorrect assumptions or optimizations on this code. +/// +/// You can think of `MaybeUninit` as being a bit like `Option` but without +/// any of the run-time tracking and without any of the safety checks. +/// +/// ## out-pointers +/// +/// You can use `MaybeUninit` to implement "out-pointers": instead of returning data +/// from a function, pass it a pointer to some (uninitialized) memory to put the +/// result into. This can be useful when it is important for the caller to control +/// how the memory the result is stored in gets allocated, and you want to avoid +/// unnecessary moves. +/// +/// ``` +/// # extern crate maybe_uninit; +/// # fn main() { +/// use maybe_uninit::MaybeUninit; +/// use std::ptr; +/// +/// unsafe fn make_vec(out: *mut Vec) { +/// // `write` does not drop the old contents, which is important. +/// ptr::write(out, vec![1, 2, 3]); +/// } +/// +/// let mut v = MaybeUninit::uninit(); +/// unsafe { make_vec(v.as_mut_ptr()); } +/// // Now we know `v` is initialized! This also makes sure the vector gets +/// // properly dropped. +/// let v = unsafe { v.assume_init() }; +/// assert_eq!(&v, &[1, 2, 3]); +/// # } +/// ``` +/// +/// ## Initializing an array element-by-element +/// +/// `MaybeUninit` can be used to initialize a large array element-by-element: +/// +/// ``` +/// # extern crate maybe_uninit; +/// # fn main() { +/// use maybe_uninit::MaybeUninit; +/// use std::mem; +/// use std::ptr; +/// +/// let data = { +/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is +/// // safe because the type we are claiming to have initialized here is a +/// // bunch of `MaybeUninit`s, which do not require initialization. +/// let mut data: [MaybeUninit>; 1000] = unsafe { +/// MaybeUninit::uninit().assume_init() +/// }; +/// +/// // Dropping a `MaybeUninit` does nothing, so if there is a panic during this loop, +/// // we have a memory leak, but there is no memory safety issue. +/// for elem in &mut data[..] { +/// unsafe { ptr::write(elem.as_mut_ptr(), vec![42]); } +/// } +/// +/// // Everything is initialized. Transmute the array to the +/// // initialized type. +/// unsafe { mem::transmute::<_, [Vec; 1000]>(data) } +/// }; +/// +/// assert_eq!(&data[0], &[42]); +/// # } +/// ``` +/// +/// You can also work with partially initialized arrays, which could +/// be found in low-level datastructures. +/// +/// ``` +/// # extern crate maybe_uninit; +/// # fn main() { +/// use maybe_uninit::MaybeUninit; +/// use std::ptr; +/// +/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is +/// // safe because the type we are claiming to have initialized here is a +/// // bunch of `MaybeUninit`s, which do not require initialization. +/// let mut data: [MaybeUninit; 1000] = unsafe { MaybeUninit::uninit().assume_init() }; +/// // Count the number of elements we have assigned. +/// let mut data_len: usize = 0; +/// +/// for elem in &mut data[0..500] { +/// unsafe { ptr::write(elem.as_mut_ptr(), String::from("hello")); } +/// data_len += 1; +/// } +/// +/// // For each item in the array, drop if we allocated it. +/// for elem in &mut data[0..data_len] { +/// unsafe { ptr::drop_in_place(elem.as_mut_ptr()); } +/// } +/// # } +/// ``` +/// +/// ## Initializing a struct field-by-field +/// +/// There is currently no supported way to create a raw pointer or reference +/// to a field of a struct inside `MaybeUninit`. That means it is not possible +/// to create a struct by calling `MaybeUninit::uninit::()` and then writing +/// to its fields. +/// +/// [ub]: ../../reference/behavior-considered-undefined.html +/// +/// # Layout +/// +/// `MaybeUninit` is guaranteed to have the same size, alignment, and ABI as `T`: +/// +/// ```rust +/// # extern crate maybe_uninit; +/// # #[cfg(not(derive_copy))] fn main() {} +/// # #[cfg(derive_copy)] fn main() { +/// use maybe_uninit::MaybeUninit; +/// use std::mem::{size_of, align_of}; +/// assert_eq!(size_of::>(), size_of::()); +/// assert_eq!(align_of::>(), align_of::()); +/// # } +/// ``` +/// +/// However remember that a type *containing* a `MaybeUninit` is not necessarily the same +/// layout; Rust does not in general guarantee that the fields of a `Foo` have the same order as +/// a `Foo` even if `T` and `U` have the same size and alignment. Furthermore because any bit +/// value is valid for a `MaybeUninit` the compiler can't apply non-zero/niche-filling +/// optimizations, potentially resulting in a larger size: +/// +/// ```no_run +/// # extern crate maybe_uninit; +/// # fn main() { +/// # use maybe_uninit::MaybeUninit; +/// # use std::mem::size_of; +/// assert_eq!(size_of::>(), 1); +/// assert_eq!(size_of::>>(), 2); +/// # } +/// ``` +/// +/// If `T` is FFI-safe, then so is `MaybeUninit`. +/// +/// While `MaybeUninit` is `#[repr(transparent)]` (indicating it guarantees the same size, +/// alignment, and ABI as `T`), this does *not* change any of the previous caveats. `Option` and +/// `Option>` may still have different sizes, and types containing a field of type +/// `T` may be laid out (and sized) differently than if that field were `MaybeUninit`. +/// `MaybeUninit` is a union type, and `#[repr(transparent)]` on unions is unstable (see [the +/// tracking issue](https://github.com/rust-lang/rust/issues/60405)). Over time, the exact +/// guarantees of `#[repr(transparent)]` on unions may evolve, and `MaybeUninit` may or may not +/// remain `#[repr(transparent)]`. That said, `MaybeUninit` will *always* guarantee that it has +/// the same size, alignment, and ABI as `T`; it's just that the way `MaybeUninit` implements that +/// guarantee may evolve. +#[cfg_attr(derive_copy, derive(Copy))] +#[cfg_attr(repr_transparent, repr(transparent))] +#[cfg_attr(not(repr_transparent), repr(C))] +pub struct MaybeUninit { + value: ManuallyDrop, +} + +#[cfg(derive_copy)] +impl Clone for MaybeUninit { + #[inline(always)] + fn clone(&self) -> Self { + // Not calling `T::clone()`, we cannot know if we are initialized enough for that. + *self + } +} + +impl MaybeUninit { + /// Creates a new `MaybeUninit` initialized with the given value. + /// It is safe to call [`assume_init`] on the return value of this function. + /// + /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. + /// It is your responsibility to make sure `T` gets dropped if it got initialized. + /// + /// [`assume_init`]: #method.assume_init + #[inline(always)] + pub fn new(val: T) -> MaybeUninit { + MaybeUninit { value: ManuallyDrop::new(val) } + } + + /// Creates a new `MaybeUninit` in an uninitialized state. + /// + /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. + /// It is your responsibility to make sure `T` gets dropped if it got initialized. + /// + /// See the [type-level documentation][type] for some examples. + /// + /// [type]: union.MaybeUninit.html + #[inline(always)] + pub fn uninit() -> MaybeUninit { + unsafe { MaybeUninit { value: uninitialized() } } + } + + /// Creates a new `MaybeUninit` in an uninitialized state, with the memory being + /// filled with `0` bytes. It depends on `T` whether that already makes for + /// proper initialization. For example, `MaybeUninit::zeroed()` is initialized, + /// but `MaybeUninit<&'static i32>::zeroed()` is not because references must not + /// be null. + /// + /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. + /// It is your responsibility to make sure `T` gets dropped if it got initialized. + /// + /// # Example + /// + /// Correct usage of this function: initializing a struct with zero, where all + /// fields of the struct can hold the bit-pattern 0 as a valid value. + /// + /// ```rust + /// # extern crate maybe_uninit; + /// # fn main() { + /// use maybe_uninit::MaybeUninit; + /// + /// let x = MaybeUninit::<(u8, bool)>::zeroed(); + /// let x = unsafe { x.assume_init() }; + /// assert_eq!(x, (0, false)); + /// # } + /// ``` + /// + /// *Incorrect* usage of this function: initializing a struct with zero, where some fields + /// cannot hold 0 as a valid value. + /// + /// ```rust,no_run + /// # extern crate maybe_uninit; + /// # fn main() { + /// use maybe_uninit::MaybeUninit; + /// + /// enum NotZero { One = 1, Two = 2 }; + /// + /// let x = MaybeUninit::<(u8, NotZero)>::zeroed(); + /// let x = unsafe { x.assume_init() }; + /// // Inside a pair, we create a `NotZero` that does not have a valid discriminant. + /// // This is undefined behavior. + /// # } + /// ``` + #[inline] + pub fn zeroed() -> MaybeUninit { + let mut u = MaybeUninit::::uninit(); + unsafe { + ptr::write_bytes(u.as_mut_ptr(), 0u8, 1); + } + u + } + + /* + /// Sets the value of the `MaybeUninit`. This overwrites any previous value + /// without dropping it, so be careful not to use this twice unless you want to + /// skip running the destructor. For your convenience, this also returns a mutable + /// reference to the (now safely initialized) contents of `self`. + #[unstable(feature = "maybe_uninit_extra", issue = "53491")] + #[inline(always)] + pub fn write(&mut self, val: T) -> &mut T { + unsafe { + self.value = ManuallyDrop::new(val); + self.get_mut() + } + } + */ + + /// Gets a pointer to the contained value. Reading from this pointer or turning it + /// into a reference is undefined behavior unless the `MaybeUninit` is initialized. + /// Writing to memory that this pointer (non-transitively) points to is undefined behavior + /// (except inside an `UnsafeCell`). + /// + /// # Examples + /// + /// Correct usage of this method: + /// + /// ```rust + /// # extern crate maybe_uninit; + /// # fn main() { + /// use maybe_uninit::MaybeUninit; + /// use std::ptr; + /// + /// let mut x = MaybeUninit::>::uninit(); + /// unsafe { ptr::write(x.as_mut_ptr(), vec![0,1,2]); } + /// // Create a reference into the `MaybeUninit`. This is okay because we initialized it. + /// let x_vec = unsafe { &*x.as_ptr() }; + /// assert_eq!(x_vec.len(), 3); + /// # } + /// ``` + /// + /// *Incorrect* usage of this method: + /// + /// ```rust,no_run + /// # extern crate maybe_uninit; + /// # fn main() { + /// use maybe_uninit::MaybeUninit; + /// + /// let x = MaybeUninit::>::uninit(); + /// let x_vec = unsafe { &*x.as_ptr() }; + /// // We have created a reference to an uninitialized vector! This is undefined behavior. + /// # } + /// ``` + /// + /// (Notice that the rules around references to uninitialized data are not finalized yet, but + /// until they are, it is advisable to avoid them.) + #[inline(always)] + pub fn as_ptr(&self) -> *const T { + &*self.value as *const T + } + + /// Gets a mutable pointer to the contained value. Reading from this pointer or turning it + /// into a reference is undefined behavior unless the `MaybeUninit` is initialized. + /// + /// # Examples + /// + /// Correct usage of this method: + /// + /// ```rust + /// # extern crate maybe_uninit; + /// # fn main() { + /// use maybe_uninit::MaybeUninit; + /// use std::ptr; + /// + /// let mut x = MaybeUninit::>::uninit(); + /// unsafe { ptr::write(x.as_mut_ptr(), vec![0,1,2]); } + /// // Create a reference into the `MaybeUninit>`. + /// // This is okay because we initialized it. + /// let x_vec = unsafe { &mut *x.as_mut_ptr() }; + /// x_vec.push(3); + /// assert_eq!(x_vec.len(), 4); + /// # } + /// ``` + /// + /// *Incorrect* usage of this method: + /// + /// ```rust,no_run + /// # extern crate maybe_uninit; + /// # fn main() { + /// use maybe_uninit::MaybeUninit; + /// + /// let mut x = MaybeUninit::>::uninit(); + /// let x_vec = unsafe { &mut *x.as_mut_ptr() }; + /// // We have created a reference to an uninitialized vector! This is undefined behavior. + /// # } + /// ``` + /// + /// (Notice that the rules around references to uninitialized data are not finalized yet, but + /// until they are, it is advisable to avoid them.) + #[inline(always)] + pub fn as_mut_ptr(&mut self) -> *mut T { + &mut *self.value as *mut T + } + + /// Extracts the value from the `MaybeUninit` container. This is a great way + /// to ensure that the data will get dropped, because the resulting `T` is + /// subject to the usual drop handling. + /// + /// # Safety + /// + /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized + /// state. Calling this when the content is not yet fully initialized causes immediate undefined + /// behavior. The [type-level documentation][inv] contains more information about + /// this initialization invariant. + /// + /// [inv]: #initialization-invariant + /// + /// # Examples + /// + /// Correct usage of this method: + /// + /// ```rust + /// # extern crate maybe_uninit; + /// # fn main() { + /// use maybe_uninit::MaybeUninit; + /// use std::ptr::write; + /// + /// let mut x = MaybeUninit::::uninit(); + /// unsafe { write(x.as_mut_ptr(), true); } + /// let x_init = unsafe { x.assume_init() }; + /// assert_eq!(x_init, true); + /// # } + /// ``` + /// + /// *Incorrect* usage of this method: + /// + /// ```rust,no_run + /// # extern crate maybe_uninit; + /// # fn main() { + /// use maybe_uninit::MaybeUninit; + /// + /// let x = MaybeUninit::>::uninit(); + /// let x_init = unsafe { x.assume_init() }; + /// // `x` had not been initialized yet, so this last line caused undefined behavior. + /// # } + /// ``` + #[inline(always)] + pub unsafe fn assume_init(self) -> T { + //intrinsics::panic_if_uninhabited::(); + ManuallyDrop::into_inner(self.value) + } + + /* + /// Reads the value from the `MaybeUninit` container. The resulting `T` is subject + /// to the usual drop handling. + /// + /// Whenever possible, it is preferrable to use [`assume_init`] instead, which + /// prevents duplicating the content of the `MaybeUninit`. + /// + /// # Safety + /// + /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized + /// state. Calling this when the content is not yet fully initialized causes undefined + /// behavior. The [type-level documentation][inv] contains more information about + /// this initialization invariant. + /// + /// Moreover, this leaves a copy of the same data behind in the `MaybeUninit`. When using + /// multiple copies of the data (by calling `read` multiple times, or first + /// calling `read` and then [`assume_init`]), it is your responsibility + /// to ensure that that data may indeed be duplicated. + /// + /// [inv]: #initialization-invariant + /// [`assume_init`]: #method.assume_init + /// + /// # Examples + /// + /// Correct usage of this method: + /// + /// ```rust + /// #![feature(maybe_uninit_extra)] + /// use std::mem::MaybeUninit; + /// + /// let mut x = MaybeUninit::::uninit(); + /// x.write(13); + /// let x1 = unsafe { x.read() }; + /// // `u32` is `Copy`, so we may read multiple times. + /// let x2 = unsafe { x.read() }; + /// assert_eq!(x1, x2); + /// + /// let mut x = MaybeUninit::>>::uninit(); + /// x.write(None); + /// let x1 = unsafe { x.read() }; + /// // Duplicating a `None` value is okay, so we may read multiple times. + /// let x2 = unsafe { x.read() }; + /// assert_eq!(x1, x2); + /// ``` + /// + /// *Incorrect* usage of this method: + /// + /// ```rust,no_run + /// #![feature(maybe_uninit_extra)] + /// use std::mem::MaybeUninit; + /// + /// let mut x = MaybeUninit::>>::uninit(); + /// x.write(Some(vec![0,1,2])); + /// let x1 = unsafe { x.read() }; + /// let x2 = unsafe { x.read() }; + /// // We now created two copies of the same vector, leading to a double-free when + /// // they both get dropped! + /// ``` + #[unstable(feature = "maybe_uninit_extra", issue = "53491")] + #[inline(always)] + pub unsafe fn read(&self) -> T { + intrinsics::panic_if_uninhabited::(); + self.as_ptr().read() + } + + /// Gets a reference to the contained value. + /// + /// # Safety + /// + /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized + /// state. Calling this when the content is not yet fully initialized causes undefined + /// behavior. + #[unstable(feature = "maybe_uninit_ref", issue = "53491")] + #[inline(always)] + pub unsafe fn get_ref(&self) -> &T { + &*self.value + } + + /// Gets a mutable reference to the contained value. + /// + /// # Safety + /// + /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized + /// state. Calling this when the content is not yet fully initialized causes undefined + /// behavior. + // FIXME(#53491): We currently rely on the above being incorrect, i.e., we have references + // to uninitialized data (e.g., in `libcore/fmt/float.rs`). We should make + // a final decision about the rules before stabilization. + #[unstable(feature = "maybe_uninit_ref", issue = "53491")] + #[inline(always)] + pub unsafe fn get_mut(&mut self) -> &mut T { + &mut *self.value + } + + /// Gets a pointer to the first element of the array. + #[unstable(feature = "maybe_uninit_slice", issue = "53491")] + #[inline(always)] + pub fn first_ptr(this: &[MaybeUninit]) -> *const T { + this as *const [MaybeUninit] as *const T + } + + /// Gets a mutable pointer to the first element of the array. + #[unstable(feature = "maybe_uninit_slice", issue = "53491")] + #[inline(always)] + pub fn first_ptr_mut(this: &mut [MaybeUninit]) -> *mut T { + this as *mut [MaybeUninit] as *mut T + }*/ +} diff --git a/third_party/rust/maybe-uninit/tests/doesnt_drop.rs b/third_party/rust/maybe-uninit/tests/doesnt_drop.rs new file mode 100644 index 000000000000..1d4b30fc462b --- /dev/null +++ b/third_party/rust/maybe-uninit/tests/doesnt_drop.rs @@ -0,0 +1,37 @@ +extern crate maybe_uninit; +use maybe_uninit::MaybeUninit; + +use std::cell::Cell; + +struct DecrementOnDrop<'a>(&'a Cell); + +impl<'a> DecrementOnDrop<'a> { + pub fn new(ref_:&'a Cell) -> Self { + ref_.set(1); + DecrementOnDrop(ref_) + } +} + +impl<'a> Clone for DecrementOnDrop<'a> { + fn clone(&self) -> Self { + self.0.set(self.0.get() + 1); + + DecrementOnDrop(self.0) + } +} + +impl<'a> Drop for DecrementOnDrop<'a>{ + fn drop(&mut self) { + self.0.set(self.0.get() - 1); + } +} + +#[test] +fn doesnt_drop(){ + let count = Cell::new(0); + let arc = DecrementOnDrop::new(&count); + let maybe = MaybeUninit::new(arc.clone()); + assert_eq!(count.get(), 2); + drop(maybe); + assert_eq!(count.get(), 2); +}