diff options
Diffstat (limited to 'third_party/rust/static_assertions')
16 files changed, 1765 insertions, 0 deletions
diff --git a/third_party/rust/static_assertions/.cargo-checksum.json b/third_party/rust/static_assertions/.cargo-checksum.json new file mode 100644 index 0000000000..eb917cb985 --- /dev/null +++ b/third_party/rust/static_assertions/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"750f74f3b520672a81dd2ede5c097cfe972c0da181dd8fd010e7131a3526d4fd","Cargo.toml":"6531dbe3d557e427f9e3510e50cdf3de751a319eece11c9a937b35cfab8744c4","LICENSE-APACHE":"cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30","LICENSE-MIT":"ea084a2373ebc1f0902c09266e7bf25a05ab3814c1805bb017ffa7308f90c061","README.md":"88cc779ada8c6e1362c2d095c179284ec2755797729946ebccfe8264fcff0f8e","src/assert_cfg.rs":"ce9230bcc055d8df21ceefbed4233df5e73ecb832829ba23ac8d7f54ec457522","src/assert_eq_align.rs":"f09c4ec30e476446ab337a4a9ed950edf21c780a42ece7613f0ffc20225331ae","src/assert_eq_size.rs":"c06d2ff44e1f7af8a57b7c2fe5a9c69aa2a90d12cd41614c9d4f3ae551cdb64c","src/assert_fields.rs":"9c5baeac0215be557213eec9e80fc00de10a721d9b2c369fece743fcc6ccdc8e","src/assert_impl.rs":"fe5a2fffcbb78f60991bbc590481e74fd0d5f7ed8fa75718644599e1fae117ce","src/assert_obj_safe.rs":"88584809f3aa2dfce966b0adbeb6128191229465d653e57b68f968be001eff03","src/assert_trait.rs":"87b2d4dbd4334d9ace9880b81f3a1fbf91725c5e152b34a74c86457ca40ece30","src/assert_type.rs":"7cd942341efa7ed0b89b5e4fe1faa62bafb537ec6cf72ee6866115daee931885","src/const_assert.rs":"e0dcfe9016e34455f5efcb23500f716386d42b9fb09c6d08566d03dce8249e51","src/lib.rs":"4cbaaff38a6ac16631e774ab5a349056cbd2335ac570aeb46c5616eaf9700c3b"},"package":"a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"}
\ No newline at end of file diff --git a/third_party/rust/static_assertions/CHANGELOG.md b/third_party/rust/static_assertions/CHANGELOG.md new file mode 100644 index 0000000000..80d55075fc --- /dev/null +++ b/third_party/rust/static_assertions/CHANGELOG.md @@ -0,0 +1,181 @@ +# Changelog [![Crates.io][crate-badge]][crate] +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog] and this project adheres to +[Semantic Versioning]. + +## [Unreleased] + +## [1.1.0] - 2019-11-03 +### Added +- `assert_impl_any!` macro +- `assert_impl_one!` macro +- `assert_trait_sub_all!` macro +- `assert_trait_super_all!` macro +- Frequently asked questions to `README.md` + +### Fixed +- `assert_eq_size_val!`, `const_assert_eq!`, and `const_assert_ne!` to export + their local inner macros. Not having this prevented them from working when + `use`d or called directly via `static_assertions::macro!(...)` + +### Removed +- Unused `_assert_obj_safe!` from pre-1.0 + +## [1.0.0] - 2019-10-02 +### Added +- `assert_eq_align!` macro + +### Removed +- **[breaking]** Labels from macros that needed them 🎉 + - Made possible by [`const _`] in Rust 1.37 +- **[breaking]** `assert_impl!` macro + +### Fixed +- `assert_fields!` now works for `enum` types with multiple variants + +### Changed +- **[breaking]** `const_assert!` macro to only take one expression + - Reasoning: when custom error messages are added in the future (via + [`assert!`]), having the macro allow for multiple comma-separated + expressions may lead to ambiguity +- **[breaking]** Trait assertions to use `Type: Trait` syntax +- **[breaking]** Field assertions to use `Type: field1, field2` syntax +- **[breaking]** Renamed `assert_{ne,eq}_type!` to `assert_type_{ne,eq}_all!` + +## [0.3.4] - 2019-06-12 +### Changed +- Aliased `assert_impl!` to `assert_impl_all!` and deprecated `assert_impl!` + +### Added +- `assert_impl_all!` as replacement to `assert_impl!` +- `assert_not_impl_all!` and `assert_not_impl_any!` macro counterparts to + `assert_impl_all!` + +### Fixed +- `assert_eq_type!` now works with types involving lifetimes + +## [0.3.3] - 2019-06-12 +### Added +- `const_assert_ne!` macro counterpart to `const_assert_eq!` + +### Fixed +- `assert_eq_type!` would pass when types can coerce via `Deref`, such as with + `str` and `String` + +## [0.3.2] - 2019-05-15 +### Added +- A `assert_eq_type!` macro that allows for checking whether inputs are the same + concrete type +- A `assert_ne_type!` macro for checking whether inputs all refer to different + types + +### Fixed +- `const_assert!` now only takes `bool` values whereas integer (or other type) + values could previously be passed + +## [0.3.1] - 2018-11-15 +### Fixed +- Macros that refer to other internal macros can now be imported when compiling + for Rust 2018 ([issue + #10](https://github.com/nvzqz/static-assertions-rs/issues/10)) + +## [0.3.0] - 2018-11-14 +### Changed +- Bumped minimum supported (automatically tested) Rust version to 1.24.0 +- Moved message parameter for `assert_cfg!()` to last argument position, making + it consistent with other macros + +### Removed +- No need to use `macro!(label; ...)` syntax when compiling on nightly Rust and + enabling the `nightly` feature flag + +## [0.2.5] - 2017-12-12 +### Changed +- `assert_eq_size_ptr` wraps its code inside of a closure, ensuring that the + unsafe code inside never runs +- Clippy no longer warns about `unneeded_field_pattern` within `assert_fields` + +### Added +- Much better documentation with test examples that are guaranteed to fail at + compile-time + +### Removed +- Removed testing features; compile failure tests are now done via doc tests + +## [0.2.4] - 2017-12-11 +### Removed +- Removed the actual call to `mem::transmute` while still utilizing it for size + verification ([Simon Sapin], [#5]) + +### Added +- `assert_cfg` macro that asserts that the given configuration is set +- `assert_fields` macro to assert that a struct type or enum variant has a given + field + +### Fixed +- Allow more generics flexibility in `assert_impl` + +## [0.2.3] - 2017-08-24 +### Fixed +- Trailing commas are now allowed + +### Removed +- Removed clippy warnings + +## [0.2.2] - 2017-08-13 +### Added +- Added `assert_impl` macro to ensure a type implements a given set of traits + +## [0.2.1] - 2017-08-13 +### Added +- Added `assert_obj_safe` macro for ensuring that a trait is object-safe + +## [0.2.0] - 2017-08-12 +### Added +- Added `assert_eq_size_ptr` macro + +### Fixed +- Allow `assert_eq_size`, `const_assert`, and `const_assert_eq` in non-function + contexts via providing a unique label [#1] + +### Removed +- **[Breaking]** Semicolon-separated `assert_eq_size` is no longer allowed + +## [0.1.1] - 2017-08-12 +### Added +- Added `const_assert_eq` macro + +## 0.1.0 - 2017-08-12 + +Initial release + +[Simon Sapin]: https://github.com/SimonSapin + +[`assert!`]: https://doc.rust-lang.org/stable/std/macro.assert.html +[`const _`]: https://github.com/rust-lang/rfcs/blob/master/text/2526-const-wildcard.md + +[#1]: https://github.com/nvzqz/static-assertions-rs/issues/1 +[#5]: https://github.com/nvzqz/static-assertions-rs/pull/5 + +[crate]: https://crates.io/crates/static_assertions +[crate-badge]: https://img.shields.io/crates/v/static_assertions.svg + +[Keep a Changelog]: http://keepachangelog.com/en/1.0.0/ +[Semantic Versioning]: http://semver.org/spec/v2.0.0.html + +[Unreleased]: https://github.com/nvzqz/static-assertions-rs/compare/v1.1.0...HEAD +[1.1.0]: https://github.com/nvzqz/static-assertions-rs/compare/v1.0.0...v1.1.0 +[1.0.0]: https://github.com/nvzqz/static-assertions-rs/compare/v0.3.4...v1.0.0 +[0.3.4]: https://github.com/nvzqz/static-assertions-rs/compare/v0.3.3...v0.3.4 +[0.3.3]: https://github.com/nvzqz/static-assertions-rs/compare/v0.3.2...v0.3.3 +[0.3.2]: https://github.com/nvzqz/static-assertions-rs/compare/v0.3.1...v0.3.2 +[0.3.1]: https://github.com/nvzqz/static-assertions-rs/compare/v0.3.0...v0.3.1 +[0.3.0]: https://github.com/nvzqz/static-assertions-rs/compare/v0.2.5...v0.3.0 +[0.2.5]: https://github.com/nvzqz/static-assertions-rs/compare/v0.2.4...v0.2.5 +[0.2.4]: https://github.com/nvzqz/static-assertions-rs/compare/v0.2.3...v0.2.4 +[0.2.3]: https://github.com/nvzqz/static-assertions-rs/compare/v0.2.2...v0.2.3 +[0.2.2]: https://github.com/nvzqz/static-assertions-rs/compare/v0.2.1...v0.2.2 +[0.2.1]: https://github.com/nvzqz/static-assertions-rs/compare/v0.2.0...v0.2.1 +[0.2.0]: https://github.com/nvzqz/static-assertions-rs/compare/v0.1.1...v0.2.0 +[0.1.1]: https://github.com/nvzqz/static-assertions-rs/compare/v0.1.0...v0.1.1 diff --git a/third_party/rust/static_assertions/Cargo.toml b/third_party/rust/static_assertions/Cargo.toml new file mode 100644 index 0000000000..8651ce1ee3 --- /dev/null +++ b/third_party/rust/static_assertions/Cargo.toml @@ -0,0 +1,39 @@ +# 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 = "static_assertions" +version = "1.1.0" +authors = ["Nikolai Vazquez"] +include = ["Cargo.toml", "src/**/*.rs", "README.md", "CHANGELOG.md", "LICENSE*"] +description = "Compile-time assertions to ensure that invariants are met." +homepage = "https://github.com/nvzqz/static-assertions-rs" +documentation = "https://docs.rs/static_assertions/" +readme = "README.md" +keywords = ["assert", "static", "testing"] +categories = ["no-std", "rust-patterns", "development-tools::testing"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/nvzqz/static-assertions-rs" + +[features] +nightly = [] +[badges.is-it-maintained-issue-resolution] +repository = "nvzqz/static-assertions-rs" + +[badges.is-it-maintained-open-issues] +repository = "nvzqz/static-assertions-rs" + +[badges.maintenance] +status = "passively-maintained" + +[badges.travis-ci] +repository = "nvzqz/static-assertions-rs" diff --git a/third_party/rust/static_assertions/LICENSE-APACHE b/third_party/rust/static_assertions/LICENSE-APACHE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/third_party/rust/static_assertions/LICENSE-APACHE @@ -0,0 +1,202 @@ + + 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/static_assertions/LICENSE-MIT b/third_party/rust/static_assertions/LICENSE-MIT new file mode 100644 index 0000000000..ccc94459f8 --- /dev/null +++ b/third_party/rust/static_assertions/LICENSE-MIT @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Nikolai Vazquez + +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/static_assertions/README.md b/third_party/rust/static_assertions/README.md new file mode 100644 index 0000000000..bca222ed55 --- /dev/null +++ b/third_party/rust/static_assertions/README.md @@ -0,0 +1,188 @@ +[![Banner](https://raw.githubusercontent.com/nvzqz/static-assertions-rs/assets/Banner.png)](https://github.com/nvzqz/static-assertions-rs) + +<div align="center"> + <a href="https://crates.io/crates/static_assertions"> + <img src="https://img.shields.io/crates/v/static_assertions.svg" alt="Crates.io"> + <img src="https://img.shields.io/crates/d/static_assertions.svg" alt="Downloads"> + </a> + <a href="https://travis-ci.org/nvzqz/static-assertions-rs"> + <img src="https://travis-ci.org/nvzqz/static-assertions-rs.svg?branch=master" alt="Build Status"> + </a> + <img src="https://img.shields.io/badge/rustc-^1.37.0-blue.svg" alt="rustc ^1.37.0"> + <br> + <a href="https://www.patreon.com/nvzqz"> + <img src="https://c5.patreon.com/external/logo/become_a_patron_button.png" alt="Become a Patron!" height="35"> + </a> + <a href="https://www.paypal.me/nvzqz"> + <img src="https://buymecoffee.intm.org/img/button-paypal-white.png" alt="Buy me a coffee" height="35"> + </a> +</div> + +Compile-time assertions for Rust, brought to you by +[Nikolai Vazquez](https://twitter.com/NikolaiVazquez). + +This library lets you ensure correct assumptions about constants, types, and +more. See the [docs] and [FAQ](#faq) for more info! + +## Installation + +This crate is available +[on crates.io](https://crates.io/crates/static_assertions) and can be used by +adding the following to your project's +[`Cargo.toml`](https://doc.rust-lang.org/cargo/reference/manifest.html): + +```toml +[dependencies] +static_assertions = "1.1.0" +``` + +and this to your crate root (`main.rs` or `lib.rs`): + +```rust +#[macro_use] +extern crate static_assertions; +``` + +## Usage + +This crate exposes the following macros: +- [`assert_cfg!`] +- [`assert_eq_align!`] +- [`assert_eq_size!`] +- [`assert_eq_size_ptr!`] +- [`assert_eq_size_val!`] +- [`assert_fields!`] +- [`assert_impl_all!`] +- [`assert_impl_any!`] +- [`assert_impl_one!`] +- [`assert_not_impl_all!`] +- [`assert_not_impl_any!`] +- [`assert_obj_safe!`] +- [`assert_trait_sub_all!`] +- [`assert_trait_super_all!`] +- [`assert_type_eq_all!`] +- [`assert_type_ne_all!`] +- [`const_assert!`] +- [`const_assert_eq!`] +- [`const_assert_ne!`] + +## FAQ + +- **Q:** When would I want to use this? + + **A:** This library is useful for when wanting to ensure properties of + constants, types, and traits. + + Basic examples: + + - With the release of 1.39, `str::len` can be called in a `const` + context. Using [`const_assert!`], one can check that a string generated from + elsewhere is of a given size: + + ```rust + const DATA: &str = include_str!("path/to/string.txt"); + + const_assert!(DATA.len() < 512); + ``` + + - Have a type that absolutely must implement certain traits? With + [`assert_impl_all!`], one can ensure this: + + ```rust + struct Foo { + value: // ... + } + + assert_impl_all!(Foo: Send, Sync); + ``` + +- **Q:** How can I contribute? + + **A:** A couple of ways! You can: + + - Attempt coming up with some form of static analysis that you'd like to see + implemented. Create a [new issue] and describe how you'd imagine your + assertion to work, with example code to demonstrate. + + - Implement your own static assertion and create a [pull request]. + + - Give feedback. What are some pain points? Where is it unpleasant? + + - Write docs. If you're familiar with how this library works, sharing your + knowledge with the rest its users would be great! + +- **Q:** Will this affect my compiled binary? + + **A:** Nope! There is zero runtime cost to using this because all checks are + at compile-time, and so no code is emitted to run. + +- **Q:** Will this affect my compile times? + + **A:** Likely not by anything perceivable. If this is a concern, this library + can be put in `dev-dependencies`: + + ```toml + [dev-dependencies] + static_assertions = "1.1.0" + ``` + + and then assertions can be conditionally run behind `#[cfg(test)]`: + + ```rust + #[cfg(test)] + const_assert_eq!(MEANING_OF_LIFE, 42); + ``` + + However, the assertions will only be checked when running `cargo test`. This + somewhat defeats the purpose of catching false static conditions up-front with + a compilation failure. + +- **Q:** What is `const _`? + + **A:** It's a way of creating an unnamed constant. This is used so that macros + can be called from a global scope without requiring a scope-unique label. This + library makes use of the side effects of evaluating the `const` expression. + See the feature's + [tracking issue](https://github.com/rust-lang/rust/issues/54912) + and + [issue #1](https://github.com/nvzqz/static-assertions-rs/issues/1) + for more info. + +## Changes + +See [`CHANGELOG.md`](https://github.com/nvzqz/static-assertions-rs/blob/master/CHANGELOG.md) +for a complete list of what has changed from one version to another. + +## License + +This project is released under either: + +- [MIT License](https://github.com/nvzqz/static-assertions-rs/blob/master/LICENSE-MIT) + +- [Apache License (Version 2.0)](https://github.com/nvzqz/static-assertions-rs/blob/master/LICENSE-APACHE) + +at your choosing. + +[new issue]: https://github.com/nvzqz/static-assertions-rs/issues/new +[pull request]: https://github.com/nvzqz/static-assertions-rs/pulls +[docs]: https://docs.rs/static_assertions + +[`assert_cfg!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_cfg.html +[`assert_eq_align!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_eq_align.html +[`assert_eq_size!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_eq_size.html +[`assert_eq_size_ptr!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_eq_size_ptr.html +[`assert_eq_size_val!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_eq_size_val.html +[`assert_fields!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_fields.html +[`assert_impl_all!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_impl_all.html +[`assert_impl_any!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_impl_any.html +[`assert_impl_one!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_impl_one.html +[`assert_not_impl_all!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_not_impl_all.html +[`assert_not_impl_any!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_not_impl_any.html +[`assert_obj_safe!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_obj_safe.html +[`assert_trait_sub_all!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_trait_sub_all.html +[`assert_trait_super_all!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_trait_super_all.html +[`assert_type_eq_all!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_type_eq_all.html +[`assert_type_ne_all!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_type_ne_all.html +[`const_assert!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.const_assert.html +[`const_assert_eq!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.const_assert_eq.html +[`const_assert_ne!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.const_assert_ne.html diff --git a/third_party/rust/static_assertions/src/assert_cfg.rs b/third_party/rust/static_assertions/src/assert_cfg.rs new file mode 100644 index 0000000000..24282c1f32 --- /dev/null +++ b/third_party/rust/static_assertions/src/assert_cfg.rs @@ -0,0 +1,49 @@ +/// Asserts that a given configuration is set. +/// +/// # Examples +/// +/// A project will simply fail to compile if the given configuration is not set. +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// // We're not masochists +/// # #[cfg(not(target_pointer_width = "16"))] // Just in case +/// assert_cfg!(not(target_pointer_width = "16")); +/// ``` +/// +/// If a project does not support a set of configurations, you may want to +/// report why. There is the option of providing a compile error message string: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// # #[cfg(any(unix, windows))] +/// assert_cfg!(any(unix, windows), "There is only support for Unix or Windows"); +/// +/// // User needs to specify a database back-end +/// # #[cfg(target_pointer_width = "0")] // Impossible +/// assert_cfg!(all(not(all(feature = "mysql", feature = "mongodb")), +/// any( feature = "mysql", feature = "mongodb")), +/// "Must exclusively use MySQL or MongoDB as database back-end"); +/// ``` +/// +/// Some configurations are impossible. For example, we can't be compiling for +/// both macOS _and_ Windows simultaneously: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_cfg!(all(target_os = "macos", +/// target_os = "windows"), +/// "No, that's not how it works! ಠ_ಠ"); +/// ``` +#[macro_export] +macro_rules! assert_cfg { + () => {}; + ($($cfg:meta)+, $msg:expr $(,)?) => { + #[cfg(not($($cfg)+))] + compile_error!($msg); + }; + ($($cfg:tt)*) => { + #[cfg(not($($cfg)*))] + compile_error!(concat!("Cfg does not pass: ", stringify!($($cfg)*))); + }; +} diff --git a/third_party/rust/static_assertions/src/assert_eq_align.rs b/third_party/rust/static_assertions/src/assert_eq_align.rs new file mode 100644 index 0000000000..69412daefb --- /dev/null +++ b/third_party/rust/static_assertions/src/assert_eq_align.rs @@ -0,0 +1,45 @@ +/// Asserts that types are equal in alignment. +/// +/// This is useful when ensuring that pointer arithmetic is done correctly, or +/// when [FFI] requires a type to have the same alignment as some foreign type. +/// +/// # Examples +/// +/// A `usize` has the same alignment as any pointer type: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_eq_align!(usize, *const u8, *mut u8); +/// ``` +/// +/// The following passes because `[i32; 4]` has the same alignment as `i32`: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_eq_align!([i32; 4], i32); +/// ``` +/// +/// The following example fails to compile because `i32x4` explicitly has 4 +/// times the alignment as `[i32; 4]`: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// # #[allow(non_camel_case_types)] +/// #[repr(align(16))] +/// struct i32x4([i32; 4]); +/// +/// assert_eq_align!(i32x4, [i32; 4]); +/// ``` +/// +/// [FFI]: https://en.wikipedia.org/wiki/Foreign_function_interface +#[macro_export] +macro_rules! assert_eq_align { + ($x:ty, $($xs:ty),+ $(,)?) => { + const _: fn() = || { + // Assigned instance must match the annotated type or else it will + // fail to compile + use $crate::_core::mem::align_of; + $(let _: [(); align_of::<$x>()] = [(); align_of::<$xs>()];)+ + }; + }; +} diff --git a/third_party/rust/static_assertions/src/assert_eq_size.rs b/third_party/rust/static_assertions/src/assert_eq_size.rs new file mode 100644 index 0000000000..9c3c4901c7 --- /dev/null +++ b/third_party/rust/static_assertions/src/assert_eq_size.rs @@ -0,0 +1,123 @@ +/// Asserts that types are equal in size. +/// +/// When performing operations such as pointer casts or dealing with [`usize`] +/// versus [`u64`] versus [`u32`], the size of your types matter. That is where +/// this macro comes into play. +/// +/// # Alternatives +/// +/// There also exists [`assert_eq_size_val`](macro.assert_eq_size_val.html) and +/// [`assert_eq_size_ptr`](macro.assert_eq_size_ptr.html). Instead of specifying +/// types to compare, values' sizes can be directly compared against each other. +/// +/// # Examples +/// +/// These three types, despite being very different, all have the same size: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_eq_size!([u8; 4], (u16, u16), u32); +/// ``` +/// +/// The following example fails to compile because `u32` has 4 times the size of +/// `u8`: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_eq_size!(u32, u8); +/// ``` +/// +/// [`usize`]: https://doc.rust-lang.org/std/primitive.usize.html +/// [`u64`]: https://doc.rust-lang.org/std/primitive.u64.html +/// [`u32`]: https://doc.rust-lang.org/std/primitive.u32.html +#[macro_export] +macro_rules! assert_eq_size { + ($x:ty, $($xs:ty),+ $(,)?) => { + const _: fn() = || { + $(let _ = $crate::_core::mem::transmute::<$x, $xs>;)+ + }; + }; +} + +/// Asserts that values pointed to are equal in size. +/// +/// # Examples +/// +/// This especially is useful for when coercing pointers between different types +/// and ensuring the underlying values are the same size. +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// fn operation(x: &(u32, u32), y: &[u16; 4]) { +/// assert_eq_size_ptr!(x, y); +/// // ... +/// } +/// ``` +/// +/// The following example fails to compile because byte arrays of different +/// lengths have different sizes: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; +/// # fn main() { +/// static BYTES: &[u8; 4] = &[ +/// /* ... */ +/// # 0; 4 +/// ]; +/// +/// static TABLE: &[u8; 16] = &[ +/// /* ... */ +/// # 0; 16 +/// ]; +/// +/// assert_eq_size_ptr!(BYTES, TABLE); +/// ``` +#[macro_export] +macro_rules! assert_eq_size_ptr { + ($x:expr, $($xs:expr),+ $(,)?) => { + #[allow(unknown_lints, unsafe_code, forget_copy, useless_transmute)] + let _ = || unsafe { + use $crate::_core::{mem, ptr}; + let mut copy = ptr::read($x); + $(ptr::write(&mut copy, mem::transmute(ptr::read($xs)));)+ + mem::forget(copy); + }; + } +} + +/// Asserts that values are equal in size. +/// +/// This macro doesn't consume its arguments and thus works for +/// non-[`Clone`]able values. +/// +/// # Examples +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; +/// # fn main() { +/// struct Byte(u8); +/// +/// let x = 10u8; +/// let y = Byte(42); // Works for non-cloneable types +/// +/// assert_eq_size_val!(x, y); +/// assert_eq_size_val!(x, y, 0u8); +/// # } +/// ``` +/// +/// Even though both values are 0, they are of types with different sizes: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; +/// # fn main() { +/// assert_eq_size_val!(0u8, 0u32); +/// # } +/// ``` +/// +/// [`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html +#[macro_export(local_inner_macros)] +macro_rules! assert_eq_size_val { + ($x:expr, $($xs:expr),+ $(,)?) => { + assert_eq_size_ptr!(&$x, $(&$xs),+); + } +} diff --git a/third_party/rust/static_assertions/src/assert_fields.rs b/third_party/rust/static_assertions/src/assert_fields.rs new file mode 100644 index 0000000000..00f6242775 --- /dev/null +++ b/third_party/rust/static_assertions/src/assert_fields.rs @@ -0,0 +1,72 @@ +/// Asserts that the type has the given fields. +/// +/// # Examples +/// +/// One common use case is when types have fields defined multiple times as a +/// result of `#[cfg]`. This can be an issue when exposing a public API. +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; +/// pub struct Ty { +/// #[cfg(windows)] +/// pub val1: u8, +/// #[cfg(not(windows))] +/// pub val1: usize, +/// +/// #[cfg(unix)] +/// pub val2: u32, +/// #[cfg(not(unix))] +/// pub val2: usize, +/// } +/// +/// // Always have `val2` regardless of OS +/// assert_fields!(Ty: val2); +/// ``` +/// +/// This macro even works with `enum` variants: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// enum Data { +/// Val { +/// id: i32, +/// name: String, +/// bytes: [u8; 128], +/// }, +/// Ptr(*const u8), +/// } +/// +/// assert_fields!(Data::Val: id, bytes); +/// ``` +/// +/// The following example fails to compile because [`Range`] does not have a field named `middle`: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// use std::ops::Range; +/// +/// assert_fields!(Range<u32>: middle); +/// ``` +/// +/// [`Range`]: https://doc.rust-lang.org/std/ops/struct.Range.html +#[macro_export] +macro_rules! assert_fields { + ($t:ident::$v:ident: $($f:ident),+) => { + #[allow(unknown_lints, unneeded_field_pattern)] + const _: fn() = || { + #[allow(dead_code, unreachable_patterns)] + fn assert(value: $t) { + match value { + $($t::$v { $f: _, .. } => {},)+ + _ => {} + } + } + }; + }; + ($t:path: $($f:ident),+) => { + #[allow(unknown_lints, unneeded_field_pattern)] + const _: fn() = || { + $(let $t { $f: _, .. };)+ + }; + }; +} diff --git a/third_party/rust/static_assertions/src/assert_impl.rs b/third_party/rust/static_assertions/src/assert_impl.rs new file mode 100644 index 0000000000..480b6b6c61 --- /dev/null +++ b/third_party/rust/static_assertions/src/assert_impl.rs @@ -0,0 +1,356 @@ +/// Asserts that the type implements exactly one in a set of traits. +/// +/// Related: +/// - [`assert_impl_any!`] +/// - [`assert_impl_all!`] +/// - [`assert_not_impl_all!`] +/// - [`assert_not_impl_any!`] +/// +/// # Examples +/// +/// Given some type `Foo`, it is expected to implement either `Snap`, `Crackle`, +/// or `Pop`: +/// +/// ```compile_fail +/// # use static_assertions::assert_impl_one; fn main() {} +/// struct Foo; +/// +/// trait Snap {} +/// trait Crackle {} +/// trait Pop {} +/// +/// assert_impl_one!(Foo: Snap, Crackle, Pop); +/// ``` +/// +/// If _only_ `Crackle` is implemented, the assertion passes: +/// +/// ``` +/// # use static_assertions::assert_impl_one; fn main() {} +/// # struct Foo; +/// # trait Snap {} +/// # trait Crackle {} +/// # trait Pop {} +/// impl Crackle for Foo {} +/// +/// assert_impl_one!(Foo: Snap, Crackle, Pop); +/// ``` +/// +/// If `Snap` or `Pop` is _also_ implemented, the assertion fails: +/// +/// ```compile_fail +/// # use static_assertions::assert_impl_one; fn main() {} +/// # struct Foo; +/// # trait Snap {} +/// # trait Crackle {} +/// # trait Pop {} +/// # impl Crackle for Foo {} +/// impl Pop for Foo {} +/// +/// assert_impl_one!(Foo: Snap, Crackle, Pop); +/// ``` +/// +/// [`assert_impl_any!`]: macro.assert_impl_any.html +/// [`assert_impl_all!`]: macro.assert_impl_all.html +/// [`assert_not_impl_all!`]: macro.assert_not_impl_all.html +/// [`assert_not_impl_any!`]: macro.assert_not_impl_any.html +#[macro_export] +macro_rules! assert_impl_one { + ($x:ty: $($t:path),+ $(,)?) => { + const _: fn() = || { + // Generic trait that must be implemented for `$x` exactly once. + trait AmbiguousIfMoreThanOne<A> { + // Required for actually being able to reference the trait. + fn some_item() {} + } + + // Creates multiple scoped `Token` types for each trait `$t`, over + // which a specialized `AmbiguousIfMoreThanOne<Token>` is + // implemented for every type that implements `$t`. + $({ + #[allow(dead_code)] + struct Token; + + impl<T: ?Sized + $t> AmbiguousIfMoreThanOne<Token> for T {} + })+ + + // If there is only one specialized trait impl, type inference with + // `_` can be resolved and this can compile. Fails to compile if + // `$x` implements more than one `AmbiguousIfMoreThanOne<Token>` or + // does not implement any at all. + let _ = <$x as AmbiguousIfMoreThanOne<_>>::some_item; + }; + }; +} + +/// Asserts that the type implements _all_ of the given traits. +/// +/// See [`assert_not_impl_all!`] for achieving the opposite effect. +/// +/// # Examples +/// +/// This can be used to ensure types implement auto traits such as [`Send`] and +/// [`Sync`], as well as traits with [blanket `impl`s][blanket]. +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_impl_all!(u32: Copy, Send); +/// assert_impl_all!(&str: Into<String>); +/// ``` +/// +/// The following example fails to compile because raw pointers do not implement +/// [`Send`] since they cannot be moved between threads safely: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_impl_all!(*const u8: Send); +/// ``` +/// +/// [`assert_not_impl_all!`]: macro.assert_not_impl_all.html +/// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html +/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html +/// [blanket]: https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods +#[macro_export] +macro_rules! assert_impl_all { + ($type:ty: $($trait:path),+ $(,)?) => { + const _: fn() = || { + // Only callable when `$type` implements all traits in `$($trait)+`. + fn assert_impl_all<T: ?Sized $(+ $trait)+>() {} + assert_impl_all::<$type>(); + }; + }; +} + +/// Asserts that the type implements _any_ of the given traits. +/// +/// See [`assert_not_impl_any!`] for achieving the opposite effect. +/// +/// # Examples +/// +/// `u8` cannot be converted from `u16`, but it can be converted into `u16`: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_impl_any!(u8: From<u16>, Into<u16>); +/// ``` +/// +/// The unit type cannot be converted from `u8` or `u16`, but it does implement +/// [`Send`]: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_impl_any!((): From<u8>, From<u16>, Send); +/// ``` +/// +/// The following example fails to compile because raw pointers do not implement +/// [`Send`] or [`Sync`] since they cannot be moved or shared between threads +/// safely: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_impl_any!(*const u8: Send, Sync); +/// ``` +/// +/// [`assert_not_impl_any!`]: macro.assert_not_impl_any.html +/// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html +/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html +#[macro_export] +macro_rules! assert_impl_any { + ($x:ty: $($t:path),+ $(,)?) => { + const _: fn() = || { + use $crate::_core::marker::PhantomData; + use $crate::_core::ops::Deref; + + // Fallback to use as the first iterative assignment to `previous`. + let previous = AssertImplAnyFallback; + struct AssertImplAnyFallback; + + // Ensures that blanket traits can't impersonate the method. This + // prevents a false positive attack where---if a blanket trait is in + // scope that has `_static_assertions_impl_any`---the macro will + // compile when it shouldn't. + // + // See https://github.com/nvzqz/static-assertions-rs/issues/19 for + // more info. + struct ActualAssertImplAnyToken; + trait AssertImplAnyToken {} + impl AssertImplAnyToken for ActualAssertImplAnyToken {} + fn assert_impl_any_token<T: AssertImplAnyToken>(_: T) {} + + $(let previous = { + struct Wrapper<T, N>(PhantomData<T>, N); + + // If the method for this wrapper can't be called then the + // compiler will insert a deref and try again. This forwards the + // compiler's next attempt to the previous wrapper. + impl<T, N> Deref for Wrapper<T, N> { + type Target = N; + + fn deref(&self) -> &Self::Target { + &self.1 + } + } + + // This impl is bounded on the `$t` trait, so the method can + // only be called if `$x` implements `$t`. This is why a new + // `Wrapper` is defined for each `previous`. + impl<T: $t, N> Wrapper<T, N> { + fn _static_assertions_impl_any(&self) -> ActualAssertImplAnyToken { + ActualAssertImplAnyToken + } + } + + Wrapper::<$x, _>(PhantomData, previous) + };)+ + + // Attempt to find the method that can actually be called. The found + // method must return a type that implements the sealed `Token` + // trait, this ensures that blanket trait methods can't cause this + // macro to compile. + assert_impl_any_token(previous._static_assertions_impl_any()); + }; + }; +} + +/// Asserts that the type does **not** implement _all_ of the given traits. +/// +/// This can be used to ensure types do not implement auto traits such as +/// [`Send`] and [`Sync`], as well as traits with [blanket `impl`s][blanket]. +/// +/// Note that the combination of all provided traits is required to not be +/// implemented. If you want to check that none of multiple traits are +/// implemented you should invoke [`assert_not_impl_any!`] instead. +/// +/// # Examples +/// +/// Although `u32` implements `From<u16>`, it does not implement `Into<usize>`: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_not_impl_all!(u32: From<u16>, Into<usize>); +/// ``` +/// +/// The following example fails to compile since `u32` can be converted into +/// `u64`. +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_not_impl_all!(u32: Into<u64>); +/// ``` +/// +/// The following compiles because [`Cell`] is not both [`Sync`] _and_ [`Send`]: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// use std::cell::Cell; +/// +/// assert_not_impl_all!(Cell<u32>: Sync, Send); +/// ``` +/// +/// But it is [`Send`], so this fails to compile: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// # std::cell::Cell; +/// assert_not_impl_all!(Cell<u32>: Send); +/// ``` +/// +/// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html +/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html +/// [`assert_not_impl_any!`]: macro.assert_not_impl_any.html +/// [`Cell`]: https://doc.rust-lang.org/std/cell/struct.Cell.html +/// [blanket]: https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods +#[macro_export] +macro_rules! assert_not_impl_all { + ($x:ty: $($t:path),+ $(,)?) => { + const _: fn() = || { + // Generic trait with a blanket impl over `()` for all types. + trait AmbiguousIfImpl<A> { + // Required for actually being able to reference the trait. + fn some_item() {} + } + + impl<T: ?Sized> AmbiguousIfImpl<()> for T {} + + // Used for the specialized impl when *all* traits in + // `$($t)+` are implemented. + #[allow(dead_code)] + struct Invalid; + + impl<T: ?Sized $(+ $t)+> AmbiguousIfImpl<Invalid> for T {} + + // If there is only one specialized trait impl, type inference with + // `_` can be resolved and this can compile. Fails to compile if + // `$x` implements `AmbiguousIfImpl<Invalid>`. + let _ = <$x as AmbiguousIfImpl<_>>::some_item; + }; + }; +} + +/// Asserts that the type does **not** implement _any_ of the given traits. +/// +/// This can be used to ensure types do not implement auto traits such as +/// [`Send`] and [`Sync`], as well as traits with [blanket `impl`s][blanket]. +/// +/// This macro causes a compilation failure if any of the provided individual +/// traits are implemented for the type. If you want to check that a combination +/// of traits is not implemented you should invoke [`assert_not_impl_all!`] +/// instead. For single traits both macros behave the same. +/// +/// # Examples +/// +/// If `u32` were to implement `Into` conversions for `usize` _and_ for `u8`, +/// the following would fail to compile: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_not_impl_any!(u32: Into<usize>, Into<u8>); +/// ``` +/// +/// This is also good for simple one-off cases: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_not_impl_any!(&'static mut u8: Copy); +/// ``` +/// +/// The following example fails to compile since `u32` can be converted into +/// `u64` even though it can not be converted into a `u16`: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_not_impl_any!(u32: Into<u64>, Into<u16>); +/// ``` +/// +/// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html +/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html +/// [`assert_not_impl_all!`]: macro.assert_not_impl_all.html +/// [blanket]: https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods +#[macro_export] +macro_rules! assert_not_impl_any { + ($x:ty: $($t:path),+ $(,)?) => { + const _: fn() = || { + // Generic trait with a blanket impl over `()` for all types. + trait AmbiguousIfImpl<A> { + // Required for actually being able to reference the trait. + fn some_item() {} + } + + impl<T: ?Sized> AmbiguousIfImpl<()> for T {} + + // Creates multiple scoped `Invalid` types for each trait `$t`, over + // which a specialized `AmbiguousIfImpl<Invalid>` is implemented for + // every type that implements `$t`. + $({ + #[allow(dead_code)] + struct Invalid; + + impl<T: ?Sized + $t> AmbiguousIfImpl<Invalid> for T {} + })+ + + // If there is only one specialized trait impl, type inference with + // `_` can be resolved and this can compile. Fails to compile if + // `$x` implements any `AmbiguousIfImpl<Invalid>`. + let _ = <$x as AmbiguousIfImpl<_>>::some_item; + }; + }; +} diff --git a/third_party/rust/static_assertions/src/assert_obj_safe.rs b/third_party/rust/static_assertions/src/assert_obj_safe.rs new file mode 100644 index 0000000000..ecbba96475 --- /dev/null +++ b/third_party/rust/static_assertions/src/assert_obj_safe.rs @@ -0,0 +1,76 @@ +// FIXME: Link below is required to render in index +/// Asserts that the traits support dynamic dispatch +/// ([object-safety](https://doc.rust-lang.org/book/ch17-02-trait-objects.html#object-safety-is-required-for-trait-objects)). +/// +/// This is useful for when changes are made to a trait that accidentally +/// prevent it from being used as an [object]. Such a case would be adding a +/// generic method and forgetting to add `where Self: Sized` after it. If left +/// unnoticed, that mistake will affect crate users and break both forward and +/// backward compatibility. +/// +/// # Examples +/// +/// When exposing a public API, it's important that traits that could previously +/// use dynamic dispatch can still do so in future compatible crate versions. +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// trait MySafeTrait { +/// fn foo(&self) -> u32; +/// } +/// +/// assert_obj_safe!(std::fmt::Write, MySafeTrait); +/// ``` +/// +/// Works with traits that are not in the calling module: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// mod inner { +/// pub trait BasicTrait { +/// fn bar(&self); +/// } +/// assert_obj_safe!(BasicTrait); +/// } +/// +/// assert_obj_safe!(inner::BasicTrait); +/// ``` +/// +/// The following example fails to compile because raw pointers cannot be sent +/// between threads safely: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_impl!(*const u8, Send); +/// ``` +/// +/// The following example fails to compile because generics without +/// `where Self: Sized` are not allowed in [object-safe][object] trait methods: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// trait MyUnsafeTrait { +/// fn baz<T>(&self) -> T; +/// } +/// +/// assert_obj_safe!(MyUnsafeTrait); +/// ``` +/// +/// When we fix that, the previous code will compile: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// trait MyUnsafeTrait { +/// fn baz<T>(&self) -> T where Self: Sized; +/// } +/// +/// assert_obj_safe!(MyUnsafeTrait); +/// ``` +/// +/// [object]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html#object-safety-is-required-for-trait-objects +#[macro_export] +macro_rules! assert_obj_safe { + ($($xs:path),+ $(,)?) => { + $(const _: Option<&$xs> = None;)+ + }; +} diff --git a/third_party/rust/static_assertions/src/assert_trait.rs b/third_party/rust/static_assertions/src/assert_trait.rs new file mode 100644 index 0000000000..c231492fda --- /dev/null +++ b/third_party/rust/static_assertions/src/assert_trait.rs @@ -0,0 +1,105 @@ +/// Asserts that the trait is a child of all of the other traits. +/// +/// Related: +/// - [`assert_trait_super_all!`] +/// +/// # Examples +/// +/// All types that implement [`Copy`] must implement [`Clone`]: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_trait_sub_all!(Copy: Clone); +/// ``` +/// +/// All types that implement [`Ord`] must implement [`PartialEq`], [`Eq`], and +/// [`PartialOrd`]: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_trait_sub_all!(Ord: PartialEq, Eq, PartialOrd); +/// ``` +/// +/// The following example fails to compile because [`Eq`] is not required for +/// [`PartialOrd`]: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_trait_sub_all!(PartialOrd: Eq); +/// ``` +/// +/// [`assert_trait_super_all!`]: macro.assert_trait_super_all.html +/// +/// [`Copy`]: https://doc.rust-lang.org/std/marker/trait.Copy.html +/// [`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html +/// [`Ord`]: https://doc.rust-lang.org/std/cmp/trait.Ord.html +/// [`PartialOrd`]: https://doc.rust-lang.org/std/cmp/trait.PartialOrd.html +/// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html +/// [`PartialEq`]: https://doc.rust-lang.org/std/cmp/trait.PartialEq.html +#[macro_export] +macro_rules! assert_trait_sub_all { + ($sub:path: $($super:path),+ $(,)?) => { + const _: () = { + // One scope per super-trait. + $({ + #[allow(non_camel_case_types)] + trait __Impl_Implication: $super {} + + // Can only be implemented for `$sub` types if `$super` is + // also implemented. + impl<T: $sub> __Impl_Implication for T {} + })+ + }; + }; +} + +/// Asserts that the trait is a parent of all of the other traits. +/// +/// Related: +/// - [`assert_trait_sub_all!`] +/// +/// # Examples +/// +/// With this, traits `A` and `B` can both be tested to require [`Copy`] on a +/// single line: +/// +/// ``` +/// # use static_assertions::assert_trait_super_all; +/// trait A: Copy {} +/// trait B: Copy {} +/// +/// assert_trait_super_all!(Copy: A, B); +/// ``` +/// +/// Otherwise, each sub-trait would require its own call to +/// [`assert_trait_sub_all!`]: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// # trait A: Copy {} +/// # trait B: Copy {} +/// assert_trait_sub_all!(A: Copy); +/// assert_trait_sub_all!(B: Copy); +/// ``` +/// +/// The following example fails to compile because trait `C` does not require +/// [`Copy`]: +/// +/// ```compile_fail +/// # use static_assertions::assert_trait_super_all; +/// # trait A: Copy {} +/// # trait B: Copy {} +/// trait C {} +/// +/// assert_trait_super_all!(Copy: A, B, C); +/// ``` +/// +/// [`assert_trait_sub_all!`]: macro.assert_trait_sub_all.html +/// +/// [`Copy`]: https://doc.rust-lang.org/std/marker/trait.Copy.html +#[macro_export(local_inner_macros)] +macro_rules! assert_trait_super_all { + ($super:path: $($sub:path),+ $(,)?) => { + $(assert_trait_sub_all!($sub: $super);)+ + }; +} diff --git a/third_party/rust/static_assertions/src/assert_type.rs b/third_party/rust/static_assertions/src/assert_type.rs new file mode 100644 index 0000000000..dd2dc2a6f7 --- /dev/null +++ b/third_party/rust/static_assertions/src/assert_type.rs @@ -0,0 +1,101 @@ +/// Asserts that _all_ types in a list are equal to each other. +/// +/// # Examples +/// +/// Often times, type aliases are used to express usage semantics via naming. In +/// some cases, the underlying type may differ based on platform. However, other +/// types like [`c_float`] will always alias the same type. +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// use std::os::raw::c_float; +/// +/// assert_type_eq_all!(c_float, f32); +/// ``` +/// +/// This macro can also be used to compare types that involve lifetimes! Just +/// use `'static` in that case: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; +/// # fn main() { +/// type Buf<'a> = &'a [u8]; +/// +/// assert_type_eq_all!(Buf<'static>, &'static [u8]); +/// # } +/// ``` +/// +/// The following example fails to compile because `String` and `str` do not +/// refer to the same type: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_type_eq_all!(String, str); +/// ``` +/// +/// This should also work the other way around, regardless of [`Deref`] +/// implementations. +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_type_eq_all!(str, String); +/// ``` +/// +/// [`c_float`]: https://doc.rust-lang.org/std/os/raw/type.c_float.html +/// [`Deref`]: https://doc.rust-lang.org/std/ops/trait.Deref.html +#[macro_export] +macro_rules! assert_type_eq_all { + ($x:ty, $($xs:ty),+ $(,)*) => { + const _: fn() = || { $({ + trait TypeEq { + type This: ?Sized; + } + + impl<T: ?Sized> TypeEq for T { + type This = Self; + } + + fn assert_type_eq_all<T, U>() + where + T: ?Sized + TypeEq<This = U>, + U: ?Sized, + {} + + assert_type_eq_all::<$x, $xs>(); + })+ }; + }; +} + +/// Asserts that _all_ types are **not** equal to each other. +/// +/// # Examples +/// +/// Rust has all sorts of slices, but they represent different types of data: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// assert_type_ne_all!([u8], [u16], str); +/// ``` +/// +/// The following example fails to compile because [`c_uchar`] is a type alias +/// for [`u8`]: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// use std::os::raw::c_uchar; +/// +/// assert_type_ne_all!(c_uchar, u8, u32); +/// ``` +/// +/// [`c_uchar`]: https://doc.rust-lang.org/std/os/raw/type.c_uchar.html +/// [`u8`]: https://doc.rust-lang.org/std/primitive.u8.html +#[macro_export] +macro_rules! assert_type_ne_all { + ($x:ty, $($y:ty),+ $(,)?) => { + const _: fn() = || { + trait MutuallyExclusive {} + impl MutuallyExclusive for $x {} + $(impl MutuallyExclusive for $y {})+ + }; + }; +} diff --git a/third_party/rust/static_assertions/src/const_assert.rs b/third_party/rust/static_assertions/src/const_assert.rs new file mode 100644 index 0000000000..16ae4a6b42 --- /dev/null +++ b/third_party/rust/static_assertions/src/const_assert.rs @@ -0,0 +1,109 @@ +/// Asserts that constant expressions evaluate to `true`. +/// +/// Constant expressions can be ensured to have certain properties via this +/// macro If the expression evaluates to `false`, the file will fail to compile. +/// This is synonymous to [`static_assert` in C++][static_assert]. +/// +/// # Alternatives +/// +/// There also exists [`const_assert_eq`](macro.const_assert_eq.html) for +/// validating whether a sequence of expressions are equal to one another. +/// +/// # Examples +/// +/// A common use case is to guarantee properties about a constant value that's +/// generated via meta-programming. +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// const VALUE: i32 = // ... +/// # 3; +/// +/// const_assert!(VALUE >= 2); +/// ``` +/// +/// Inputs are type-checked as booleans: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// const_assert!(!0); +/// ``` +/// +/// Despite this being a macro, we see this produces a type error: +/// +/// ```txt +/// | const_assert!(!0); +/// | ^^ expected bool, found integral variable +/// | +/// = note: expected type `bool` +/// found type `{integer}` +/// ``` +/// +/// The following fails to compile because multiplying by 5 does not have an +/// identity property: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// const_assert!(5 * 5 == 5); +/// ``` +/// +/// [static_assert]: http://en.cppreference.com/w/cpp/language/static_assert +#[macro_export] +macro_rules! const_assert { + ($x:expr $(,)?) => { + #[allow(unknown_lints, eq_op)] + const _: [(); 0 - !{ const ASSERT: bool = $x; ASSERT } as usize] = []; + }; +} + +/// Asserts that constants are equal in value. +/// +/// # Examples +/// +/// This works as a shorthand for `const_assert!(a == b)`: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// const TWO: usize = 2; +/// +/// const_assert_eq!(TWO * TWO, TWO + TWO); +/// ``` +/// +/// Just because 2 × 2 = 2 + 2 doesn't mean it holds true for other numbers: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// const_assert_eq!(4 + 4, 4 * 4); +/// ``` +#[macro_export(local_inner_macros)] +macro_rules! const_assert_eq { + ($x:expr, $y:expr $(,)?) => { + const_assert!($x == $y); + }; +} + +/// Asserts that constants are **not** equal in value. +/// +/// # Examples +/// +/// This works as a shorthand for `const_assert!(a != b)`: +/// +/// ``` +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// const NUM: usize = 32; +/// +/// const_assert_ne!(NUM * NUM, 64); +/// ``` +/// +/// The following example fails to compile because 2 is magic and 2 × 2 = 2 + 2: +/// +/// ```compile_fail +/// # #[macro_use] extern crate static_assertions; fn main() {} +/// const_assert_ne!(2 + 2, 2 * 2); +/// ``` +#[macro_export(local_inner_macros)] +macro_rules! const_assert_ne { + ($x:expr, $y:expr $(,)?) => { + const_assert!($x != $y); + }; +} diff --git a/third_party/rust/static_assertions/src/lib.rs b/third_party/rust/static_assertions/src/lib.rs new file mode 100644 index 0000000000..a43cc1f56d --- /dev/null +++ b/third_party/rust/static_assertions/src/lib.rs @@ -0,0 +1,97 @@ +//! [![Banner](https://raw.githubusercontent.com/nvzqz/static-assertions-rs/assets/Banner.png)](https://github.com/nvzqz/static-assertions-rs) +//! +//! <div align="center"> +//! <a href="https://crates.io/crates/static_assertions"> +//! <img src="https://img.shields.io/crates/d/static_assertions.svg" alt="Downloads"> +//! </a> +//! <a href="https://travis-ci.org/nvzqz/static-assertions-rs"> +//! <img src="https://travis-ci.org/nvzqz/static-assertions-rs.svg?branch=master" alt="Build Status"> +//! </a> +//! <img src="https://img.shields.io/badge/rustc-^1.37.0-blue.svg" alt="rustc ^1.37.0"> +//! <br><br> +//! </div> +//! +//! Assertions to ensure correct assumptions about constants, types, and more. +//! +//! _All_ checks provided by this crate are performed at [compile-time]. This +//! allows for finding errors quickly and early when it comes to ensuring +//! certain features or aspects of a codebase. These macros are especially +//! important when exposing a public API that requires types to be the same size +//! or implement certain traits. +//! +//! # Usage +//! +//! This crate is available [on crates.io][crate] and can be used by adding the +//! following to your project's [`Cargo.toml`]: +//! +//! ```toml +//! [dependencies] +//! static_assertions = "1.1.0" +//! ``` +//! +//! and this to your crate root (`main.rs` or `lib.rs`): +//! +//! ``` +//! #[macro_use] +//! extern crate static_assertions; +//! # fn main() {} +//! ``` +//! +//! When using [Rust 2018 edition][2018], the following shorthand can help if +//! having `#[macro_use]` is undesirable. +//! +//! ```edition2018 +//! extern crate static_assertions as sa; +//! +//! sa::const_assert!(true); +//! ``` +//! +//! # Examples +//! +//! Very thorough examples are provided in the docs for +//! [each individual macro](#macros). Failure case examples are also documented. +//! +//! # Changes +//! +//! See [`CHANGELOG.md`](https://github.com/nvzqz/static-assertions-rs/blob/master/CHANGELOG.md) +//! for an exhaustive list of what has changed from one version to another. +//! +//! # Donate +//! +//! This project is made freely available (as in free beer), but unfortunately +//! not all beer is free! So, if you would like to buy me a beer (or coffee or +//! *more*), then consider supporting my work that's benefited your project +//! and thousands of others. +//! +//! <a href="https://www.patreon.com/nvzqz"> +//! <img src="https://c5.patreon.com/external/logo/become_a_patron_button.png" alt="Become a Patron!" height="35"> +//! </a> +//! <a href="https://www.paypal.me/nvzqz"> +//! <img src="https://buymecoffee.intm.org/img/button-paypal-white.png" alt="Buy me a coffee" height="35"> +//! </a> +//! +//! [Rust 1.37]: https://blog.rust-lang.org/2019/08/15/Rust-1.37.0.html +//! [2018]: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html#rust-2018 +//! [crate]: https://crates.io/crates/static_assertions +//! [compile-time]: https://en.wikipedia.org/wiki/Compile_time +//! [`Cargo.toml`]: https://doc.rust-lang.org/cargo/reference/manifest.html + +#![doc(html_root_url = "https://docs.rs/static_assertions/1.1.0")] +#![doc(html_logo_url = "https://raw.githubusercontent.com/nvzqz/static-assertions-rs/assets/Icon.png")] + +#![no_std] + +#![deny(unused_macros)] + +#[doc(hidden)] +pub extern crate core as _core; + +mod assert_cfg; +mod assert_eq_align; +mod assert_eq_size; +mod assert_fields; +mod assert_impl; +mod assert_obj_safe; +mod assert_trait; +mod assert_type; +mod const_assert; |