summaryrefslogtreecommitdiff
path: root/vendor/prettyplease
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/prettyplease')
-rw-r--r--vendor/prettyplease/.cargo-checksum.json1
-rw-r--r--vendor/prettyplease/Cargo.lock54
-rw-r--r--vendor/prettyplease/Cargo.toml90
-rw-r--r--vendor/prettyplease/LICENSE-APACHE176
-rw-r--r--vendor/prettyplease/LICENSE-MIT23
-rw-r--r--vendor/prettyplease/README.md312
-rw-r--r--vendor/prettyplease/build.rs21
-rw-r--r--vendor/prettyplease/examples/input.rs1
-rw-r--r--vendor/prettyplease/examples/output.prettyplease.rs593
-rw-r--r--vendor/prettyplease/examples/output.rustc.rs506
-rw-r--r--vendor/prettyplease/examples/output.rustfmt.rs552
-rw-r--r--vendor/prettyplease/src/algorithm.rs386
-rw-r--r--vendor/prettyplease/src/attr.rs288
-rw-r--r--vendor/prettyplease/src/classify.rs324
-rw-r--r--vendor/prettyplease/src/convenience.rs98
-rw-r--r--vendor/prettyplease/src/data.rs79
-rw-r--r--vendor/prettyplease/src/expr.rs1533
-rw-r--r--vendor/prettyplease/src/file.rs17
-rw-r--r--vendor/prettyplease/src/fixup.rs676
-rw-r--r--vendor/prettyplease/src/generics.rs383
-rw-r--r--vendor/prettyplease/src/item.rs1812
-rw-r--r--vendor/prettyplease/src/iter.rs46
-rw-r--r--vendor/prettyplease/src/lib.rs385
-rw-r--r--vendor/prettyplease/src/lifetime.rs9
-rw-r--r--vendor/prettyplease/src/lit.rs57
-rw-r--r--vendor/prettyplease/src/mac.rs706
-rw-r--r--vendor/prettyplease/src/pat.rs254
-rw-r--r--vendor/prettyplease/src/path.rs194
-rw-r--r--vendor/prettyplease/src/precedence.rs148
-rw-r--r--vendor/prettyplease/src/ring.rs81
-rw-r--r--vendor/prettyplease/src/stmt.rs221
-rw-r--r--vendor/prettyplease/src/token.rs80
-rw-r--r--vendor/prettyplease/src/ty.rs339
-rw-r--r--vendor/prettyplease/tests/test.rs51
-rw-r--r--vendor/prettyplease/tests/test_precedence.rs900
35 files changed, 11396 insertions, 0 deletions
diff --git a/vendor/prettyplease/.cargo-checksum.json b/vendor/prettyplease/.cargo-checksum.json
new file mode 100644
index 00000000..9f67b4e1
--- /dev/null
+++ b/vendor/prettyplease/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.lock":"8cf7ad35d2a8f934f2c502eda7b1977ed87bd2bad0b3714fbb6b3a725dacfa27","Cargo.toml":"bf31ddfd1c5e933cde148be0b08937b8d965da3e2cd9422e0ff06e878b8e7ade","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"a7e6d152cdc6ea603077e50b8d55af374d9d21fd9f62d08a008588b17d785e6e","build.rs":"79a5b2d260aa97aeac7105fbfa00774982f825cd708c100ea96d01c39974bb88","examples/input.rs":"53350088f12a346a99034af41ef432dedcc9e5d581c5592d9aae3807c42656c1","examples/output.prettyplease.rs":"fa63c118daadb64c456ec5b8d5e46e5d7fabbbeb6a6e61a08eabc23360a18fbd","examples/output.rustc.rs":"04647e9b01f2aa85982f849c2d897acf3b6931121c1ef953de5fb6a67b80e05a","examples/output.rustfmt.rs":"914a9aea1c51e097bfd80c9af4011811e6126c9df5fb0eac3d40b1203fba7c58","src/algorithm.rs":"901c91416d7526038bfad30e0066295a03d2bb995830016ace49a41540079010","src/attr.rs":"0a5c64b1c1f6fe4944c1d805c528ee4a9a8c6223e875afe9f48371cba66732ee","src/classify.rs":"2ce2d63ad9071aac10b1037e6382703736e0147d96b3ccf32a53182d12883f1b","src/convenience.rs":"dd392b009b691d3587c7d8e3caeaacf450303c4223792b5f89c336358e371c39","src/data.rs":"5bc2dce1cfa1aa5c1324ccdc2d76a6bd5df2382530c7e863d2bb50dea60cc4bc","src/expr.rs":"c73157238a80b0fb9a1949c6250cbb01f2df9217770f263dffcf5e5fbb570296","src/file.rs":"5689efa3c5959a6a0d8cfc2c13bf8a37ab0669e2b81dbded3f3c28884a88fca0","src/fixup.rs":"ecf87543c342fffc79bae54e4fa174cbfd5c341817315caa3b95cce0d49ebf7c","src/generics.rs":"f10b95f4b011f5bf6510d3a77e38227716dccf0a8aeb8a8344e776be9f90f54e","src/item.rs":"4dc320bf73f4ca7d2c6741c31700b5150a02106bfe688969070aff53c2ce455a","src/iter.rs":"38b2cd3b38719c6024fb6b3aa739f6f8736c83193fd21e2365d4f6c27bc41666","src/lib.rs":"4ab10c35515b340eed4fbdfc901a20d8432a1fd19734124b392ce4b2011c4f63","src/lifetime.rs":"6d420430168185b2da3409bc38a45f63cced9443915f04e6aec71367fc070dcf","src/lit.rs":"9ea6d25533e64df4ff01c084fa1c31ddf64fb3b159409eec7d80dbf281e5171e","src/mac.rs":"c1f8f9d60a6d116a63a7aa86d3dafdc5279c030b7f6a3e9bf119df109a913c8e","src/pat.rs":"8e53fd1b5382bb068210162bfab9921246093cfdd80dd93cd8627fcfdae39940","src/path.rs":"e73d83dc38f5c6c0c82f824da7eb090a16027f32fc40446b185580ee5e99be58","src/precedence.rs":"a8ce97ba0a25f442b5f238c64f078d70f4114b4b0f9df82764d533dd39a47abb","src/ring.rs":"517b1a02f8e0a9c1316830117daad1e30d17e1fcf6428c6b438c626aa43286ae","src/stmt.rs":"e17ab9647fed9daa4f5b2fbd007015128f2a7fc65686a988593444a37242f885","src/token.rs":"c288b1d81f2a35673d4ca1dd10d3386670b067460121df3038303e1ed73b41a7","src/ty.rs":"a1e3e5a08124673826948f97e70c11800081d2bca7f3aec12d84d0d00837290f","tests/test.rs":"c6f8c7830b7491fca1d56e41aa4acc6256b683a3556a48982f57ae62d38aaaa2","tests/test_precedence.rs":"de0c770b9a72e5eba8a52dcac0614d6db8ff5041ba601e1e67f113d68c9afd50"},"package":"061c1221631e079b26479d25bbf2275bfe5917ae8419cd7e34f13bfc2aa7539a"} \ No newline at end of file
diff --git a/vendor/prettyplease/Cargo.lock b/vendor/prettyplease/Cargo.lock
new file mode 100644
index 00000000..e1d60638
--- /dev/null
+++ b/vendor/prettyplease/Cargo.lock
@@ -0,0 +1,54 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "indoc"
+version = "2.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd"
+
+[[package]]
+name = "prettyplease"
+version = "0.2.35"
+dependencies = [
+ "indoc",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.95"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.104"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
diff --git a/vendor/prettyplease/Cargo.toml b/vendor/prettyplease/Cargo.toml
new file mode 100644
index 00000000..721d34b2
--- /dev/null
+++ b/vendor/prettyplease/Cargo.toml
@@ -0,0 +1,90 @@
+# 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 are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2021"
+rust-version = "1.62"
+name = "prettyplease"
+version = "0.2.35"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+build = "build.rs"
+links = "prettyplease02"
+exclude = ["cargo-expand"]
+autolib = false
+autobins = false
+autoexamples = false
+autotests = false
+autobenches = false
+description = "A minimal `syn` syntax tree pretty-printer"
+documentation = "https://docs.rs/prettyplease"
+readme = "README.md"
+keywords = ["rustfmt"]
+categories = ["development-tools"]
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/dtolnay/prettyplease"
+
+[package.metadata.docs.rs]
+rustdoc-args = [
+ "--generate-link-to-definition",
+ "--extern-html-root-url=core=https://doc.rust-lang.org",
+ "--extern-html-root-url=alloc=https://doc.rust-lang.org",
+ "--extern-html-root-url=std=https://doc.rust-lang.org",
+]
+targets = ["x86_64-unknown-linux-gnu"]
+
+[package.metadata.playground]
+features = ["verbatim"]
+
+[features]
+verbatim = ["syn/parsing"]
+
+[lib]
+name = "prettyplease"
+path = "src/lib.rs"
+
+[[test]]
+name = "test"
+path = "tests/test.rs"
+
+[[test]]
+name = "test_precedence"
+path = "tests/test_precedence.rs"
+
+[dependencies.proc-macro2]
+version = "1.0.80"
+default-features = false
+
+[dependencies.syn]
+version = "2.0.104"
+features = ["full"]
+default-features = false
+
+[dev-dependencies.indoc]
+version = "2"
+
+[dev-dependencies.proc-macro2]
+version = "1.0.80"
+default-features = false
+
+[dev-dependencies.quote]
+version = "1.0.35"
+default-features = false
+
+[dev-dependencies.syn]
+version = "2.0.104"
+features = [
+ "clone-impls",
+ "extra-traits",
+ "parsing",
+ "printing",
+ "visit-mut",
+]
+default-features = false
diff --git a/vendor/prettyplease/LICENSE-APACHE b/vendor/prettyplease/LICENSE-APACHE
new file mode 100644
index 00000000..1b5ec8b7
--- /dev/null
+++ b/vendor/prettyplease/LICENSE-APACHE
@@ -0,0 +1,176 @@
+ 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
diff --git a/vendor/prettyplease/LICENSE-MIT b/vendor/prettyplease/LICENSE-MIT
new file mode 100644
index 00000000..31aa7938
--- /dev/null
+++ b/vendor/prettyplease/LICENSE-MIT
@@ -0,0 +1,23 @@
+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/vendor/prettyplease/README.md b/vendor/prettyplease/README.md
new file mode 100644
index 00000000..4584c485
--- /dev/null
+++ b/vendor/prettyplease/README.md
@@ -0,0 +1,312 @@
+prettyplease::unparse
+=====================
+
+[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/prettyplease-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/prettyplease)
+[<img alt="crates.io" src="https://img.shields.io/crates/v/prettyplease.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/prettyplease)
+[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-prettyplease-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/prettyplease)
+[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/prettyplease/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/dtolnay/prettyplease/actions?query=branch%3Amaster)
+
+A minimal `syn` syntax tree pretty-printer.
+
+<br>
+
+## Overview
+
+This is a pretty-printer to turn a `syn` syntax tree into a `String` of
+well-formatted source code. In contrast to rustfmt, this library is intended to
+be suitable for arbitrary generated code.
+
+Rustfmt prioritizes high-quality output that is impeccable enough that you'd be
+comfortable spending your career staring at its output &mdash; but that means
+some heavyweight algorithms, and it has a tendency to bail out on code that is
+hard to format (for example [rustfmt#3697], and there are dozens more issues
+like it). That's not necessarily a big deal for human-generated code because
+when code gets highly nested, the human will naturally be inclined to refactor
+into more easily formattable code. But for generated code, having the formatter
+just give up leaves it totally unreadable.
+
+[rustfmt#3697]: https://github.com/rust-lang/rustfmt/issues/3697
+
+This library is designed using the simplest possible algorithm and data
+structures that can deliver about 95% of the quality of rustfmt-formatted
+output. In my experience testing real-world code, approximately 97-98% of output
+lines come out identical between rustfmt's formatting and this crate's. The rest
+have slightly different linebreak decisions, but still clearly follow the
+dominant modern Rust style.
+
+The tradeoffs made by this crate are a good fit for generated code that you will
+*not* spend your career staring at. For example, the output of `bindgen`, or the
+output of `cargo-expand`. In those cases it's more important that the whole
+thing be formattable without the formatter giving up, than that it be flawless.
+
+<br>
+
+## Feature matrix
+
+Here are a few superficial comparisons of this crate against the AST
+pretty-printer built into rustc, and rustfmt. The sections below go into more
+detail comparing the output of each of these libraries.
+
+| | prettyplease | rustc | rustfmt |
+|:---|:---:|:---:|:---:|
+| non-pathological behavior on big or generated code | 💚 | ❌ | ❌ |
+| idiomatic modern formatting ("locally indistinguishable from rustfmt") | 💚 | ❌ | 💚 |
+| throughput | 60 MB/s | 39 MB/s | 2.8 MB/s |
+| number of dependencies | 3 | 72 | 66 |
+| compile time including dependencies | 2.4 sec | 23.1 sec | 29.8 sec |
+| buildable using a stable Rust compiler | 💚 | ❌ | ❌ |
+| published to crates.io | 💚 | ❌ | ❌ |
+| extensively configurable output | ❌ | ❌ | 💚 |
+| intended to accommodate hand-maintained source code | ❌ | ❌ | 💚 |
+
+<br>
+
+## Comparison to rustfmt
+
+- [input.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/input.rs)
+- [output.prettyplease.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/output.prettyplease.rs)
+- [output.rustfmt.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/output.rustfmt.rs)
+
+If you weren't told which output file is which, it would be practically
+impossible to tell &mdash; **except** for line 435 in the rustfmt output, which
+is more than 1000 characters long because rustfmt just gave up formatting that
+part of the file:
+
+```rust
+ match segments[5] {
+ 0 => write!(f, "::{}", ipv4),
+ 0xffff => write!(f, "::ffff:{}", ipv4),
+ _ => unreachable!(),
+ }
+ } else { # [derive (Copy , Clone , Default)] struct Span { start : usize , len : usize , } let zeroes = { let mut longest = Span :: default () ; let mut current = Span :: default () ; for (i , & segment) in segments . iter () . enumerate () { if segment == 0 { if current . len == 0 { current . start = i ; } current . len += 1 ; if current . len > longest . len { longest = current ; } } else { current = Span :: default () ; } } longest } ; # [doc = " Write a colon-separated part of the address"] # [inline] fn fmt_subslice (f : & mut fmt :: Formatter < '_ > , chunk : & [u16]) -> fmt :: Result { if let Some ((first , tail)) = chunk . split_first () { write ! (f , "{:x}" , first) ? ; for segment in tail { f . write_char (':') ? ; write ! (f , "{:x}" , segment) ? ; } } Ok (()) } if zeroes . len > 1 { fmt_subslice (f , & segments [.. zeroes . start]) ? ; f . write_str ("::") ? ; fmt_subslice (f , & segments [zeroes . start + zeroes . len ..]) } else { fmt_subslice (f , & segments) } }
+ } else {
+ const IPV6_BUF_LEN: usize = (4 * 8) + 7;
+ let mut buf = [0u8; IPV6_BUF_LEN];
+ let mut buf_slice = &mut buf[..];
+```
+
+This is a pretty typical manifestation of rustfmt bailing out in generated code
+&mdash; a chunk of the input ends up on one line. The other manifestation is
+that you're working on some code, running rustfmt on save like a conscientious
+developer, but after a while notice it isn't doing anything. You introduce an
+intentional formatting issue, like a stray indent or semicolon, and run rustfmt
+to check your suspicion. Nope, it doesn't get cleaned up &mdash; rustfmt is just
+not formatting the part of the file you are working on.
+
+The prettyplease library is designed to have no pathological cases that force a
+bail out; the entire input you give it will get formatted in some "good enough"
+form.
+
+Separately, rustfmt can be problematic to integrate into projects. It's written
+using rustc's internal syntax tree, so it can't be built by a stable compiler.
+Its releases are not regularly published to crates.io, so in Cargo builds you'd
+need to depend on it as a git dependency, which precludes publishing your crate
+to crates.io also. You can shell out to a `rustfmt` binary, but that'll be
+whatever rustfmt version is installed on each developer's system (if any), which
+can lead to spurious diffs in checked-in generated code formatted by different
+versions. In contrast prettyplease is designed to be easy to pull in as a
+library, and compiles fast.
+
+<br>
+
+## Comparison to rustc_ast_pretty
+
+- [input.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/input.rs)
+- [output.prettyplease.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/output.prettyplease.rs)
+- [output.rustc.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/output.rustc.rs)
+
+This is the pretty-printer that gets used when rustc prints source code, such as
+`rustc -Zunpretty=expanded`. It's used also by the standard library's
+`stringify!` when stringifying an interpolated macro_rules AST fragment, like an
+$:expr, and transitively by `dbg!` and many macros in the ecosystem.
+
+Rustc's formatting is mostly okay, but does not hew closely to the dominant
+contemporary style of Rust formatting. Some things wouldn't ever be written on
+one line, like this `match` expression, and certainly not with a comma in front
+of the closing brace:
+
+```rust
+fn eq(&self, other: &IpAddr) -> bool {
+ match other { IpAddr::V4(v4) => self == v4, IpAddr::V6(_) => false, }
+}
+```
+
+Some places use non-multiple-of-4 indentation, which is definitely not the norm:
+
+```rust
+pub const fn to_ipv6_mapped(&self) -> Ipv6Addr {
+ let [a, b, c, d] = self.octets();
+ Ipv6Addr{inner:
+ c::in6_addr{s6_addr:
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF,
+ 0xFF, a, b, c, d],},}
+}
+```
+
+And although there isn't an egregious example of it in the link because the
+input code is pretty tame, in general rustc_ast_pretty has pathological behavior
+on generated code. It has a tendency to use excessive horizontal indentation and
+rapidly run out of width:
+
+```rust
+::std::io::_print(::core::fmt::Arguments::new_v1(&[""],
+ &match (&msg,) {
+ _args =>
+ [::core::fmt::ArgumentV1::new(_args.0,
+ ::core::fmt::Display::fmt)],
+ }));
+```
+
+The snippets above are clearly different from modern rustfmt style. In contrast,
+prettyplease is designed to have output that is practically indistinguishable
+from rustfmt-formatted code.
+
+<br>
+
+## Example
+
+```rust
+// [dependencies]
+// prettyplease = "0.2"
+// syn = { version = "2", default-features = false, features = ["full", "parsing"] }
+
+const INPUT: &str = stringify! {
+ use crate::{
+ lazy::{Lazy, SyncLazy, SyncOnceCell}, panic,
+ sync::{ atomic::{AtomicUsize, Ordering::SeqCst},
+ mpsc::channel, Mutex, },
+ thread,
+ };
+ impl<T, U> Into<U> for T where U: From<T> {
+ fn into(self) -> U { U::from(self) }
+ }
+};
+
+fn main() {
+ let syntax_tree = syn::parse_file(INPUT).unwrap();
+ let formatted = prettyplease::unparse(&syntax_tree);
+ print!("{}", formatted);
+}
+```
+
+<br>
+
+## Algorithm notes
+
+The approach and terminology used in the implementation are derived from [*Derek
+C. Oppen, "Pretty Printing" (1979)*][paper], on which rustc_ast_pretty is also
+based, and from rustc_ast_pretty's implementation written by Graydon Hoare in
+2011 (and modernized over the years by dozens of volunteer maintainers).
+
+[paper]: http://i.stanford.edu/pub/cstr/reports/cs/tr/79/770/CS-TR-79-770.pdf
+
+The paper describes two language-agnostic interacting procedures `Scan()` and
+`Print()`. Language-specific code decomposes an input data structure into a
+stream of `string` and `break` tokens, and `begin` and `end` tokens for
+grouping. Each `begin`&ndash;`end` range may be identified as either "consistent
+breaking" or "inconsistent breaking". If a group is consistently breaking, then
+if the whole contents do not fit on the line, *every* `break` token in the group
+will receive a linebreak. This is appropriate, for example, for Rust struct
+literals, or arguments of a function call. If a group is inconsistently
+breaking, then the `string` tokens in the group are greedily placed on the line
+until out of space, and linebroken only at those `break` tokens for which the
+next string would not fit. For example, this is appropriate for the contents of
+a braced `use` statement in Rust.
+
+Scan's job is to efficiently accumulate sizing information about groups and
+breaks. For every `begin` token we compute the distance to the matched `end`
+token, and for every `break` we compute the distance to the next `break`. The
+algorithm uses a ringbuffer to hold tokens whose size is not yet ascertained.
+The maximum size of the ringbuffer is bounded by the target line length and does
+not grow indefinitely, regardless of deep nesting in the input stream. That's
+because once a group is sufficiently big, the precise size can no longer make a
+difference to linebreak decisions and we can effectively treat it as "infinity".
+
+Print's job is to use the sizing information to efficiently assign a "broken" or
+"not broken" status to every `begin` token. At that point the output is easily
+constructed by concatenating `string` tokens and breaking at `break` tokens
+contained within a broken group.
+
+Leveraging these primitives (i.e. cleverly placing the all-or-nothing consistent
+breaks and greedy inconsistent breaks) to yield rustfmt-compatible formatting
+for all of Rust's syntax tree nodes is a fun challenge.
+
+Here is a visualization of some Rust tokens fed into the pretty printing
+algorithm. Consistently breaking `begin`&mdash;`end` pairs are represented by
+`«`&#8288;`»`, inconsistently breaking by `‹`&#8288;`›`, `break` by `·`, and the
+rest of the non-whitespace are `string`.
+
+```text
+use crate::«{·
+‹ lazy::«{·‹Lazy,· SyncLazy,· SyncOnceCell›·}»,·
+ panic,·
+ sync::«{·
+‹ atomic::«{·‹AtomicUsize,· Ordering::SeqCst›·}»,·
+ mpsc::channel,· Mutex›,·
+ }»,·
+ thread›,·
+}»;·
+«‹«impl<«·T‹›,· U‹›·»>» Into<«·U·»>· for T›·
+where·
+ U:‹ From<«·T·»>›,·
+{·
+« fn into(·«·self·») -> U {·
+‹ U::from(«·self·»)›·
+» }·
+»}·
+```
+
+The algorithm described in the paper is not quite sufficient for producing
+well-formatted Rust code that is locally indistinguishable from rustfmt's style.
+The reason is that in the paper, the complete non-whitespace contents are
+assumed to be independent of linebreak decisions, with Scan and Print being only
+in control of the whitespace (spaces and line breaks). In Rust as idiomatically
+formatted by rustfmt, that is not the case. Trailing commas are one example; the
+punctuation is only known *after* the broken vs non-broken status of the
+surrounding group is known:
+
+```rust
+let _ = Struct { x: 0, y: true };
+
+let _ = Struct {
+ x: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
+ y: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, //<- trailing comma if the expression wrapped
+};
+```
+
+The formatting of `match` expressions is another case; we want small arms on the
+same line as the pattern, and big arms wrapped in a brace. The presence of the
+brace punctuation, comma, and semicolon are all dependent on whether the arm
+fits on the line:
+
+```rust
+match total_nanos.checked_add(entry.nanos as u64) {
+ Some(n) => tmp = n, //<- small arm, inline with comma
+ None => {
+ total_secs = total_secs
+ .checked_add(total_nanos / NANOS_PER_SEC as u64)
+ .expect("overflow in iter::sum over durations");
+ } //<- big arm, needs brace added, and also semicolon^
+}
+```
+
+The printing algorithm implementation in this crate accommodates all of these
+situations with conditional punctuation tokens whose selection can be deferred
+and populated after it's known that the group is or is not broken.
+
+<br>
+
+#### License
+
+<sup>
+Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
+2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
+</sup>
+
+<br>
+
+<sub>
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
+be dual licensed as above, without any additional terms or conditions.
+</sub>
diff --git a/vendor/prettyplease/build.rs b/vendor/prettyplease/build.rs
new file mode 100644
index 00000000..4fc36f74
--- /dev/null
+++ b/vendor/prettyplease/build.rs
@@ -0,0 +1,21 @@
+use std::env;
+use std::ffi::OsString;
+use std::process;
+
+fn main() {
+ println!("cargo:rerun-if-changed=build.rs");
+
+ println!("cargo:rustc-check-cfg=cfg(exhaustive)");
+ println!("cargo:rustc-check-cfg=cfg(prettyplease_debug)");
+ println!("cargo:rustc-check-cfg=cfg(prettyplease_debug_indent)");
+
+ let pkg_version = cargo_env_var("CARGO_PKG_VERSION");
+ println!("cargo:VERSION={}", pkg_version.to_str().unwrap());
+}
+
+fn cargo_env_var(key: &str) -> OsString {
+ env::var_os(key).unwrap_or_else(|| {
+ eprintln!("Environment variable ${key} is not set during execution of build script");
+ process::exit(1);
+ })
+}
diff --git a/vendor/prettyplease/examples/input.rs b/vendor/prettyplease/examples/input.rs
new file mode 100644
index 00000000..ca3d9803
--- /dev/null
+++ b/vendor/prettyplease/examples/input.rs
@@ -0,0 +1 @@
+use crate :: cmp :: Ordering ; use crate :: fmt :: { self , Write as FmtWrite } ; use crate :: hash ; use crate :: io :: Write as IoWrite ; use crate :: mem :: transmute ; use crate :: sys :: net :: netc as c ; use crate :: sys_common :: { AsInner , FromInner , IntoInner } ; # [derive (Copy , Clone , Eq , PartialEq , Hash , PartialOrd , Ord)] pub enum IpAddr { V4 (Ipv4Addr) , V6 (Ipv6Addr) , } # [derive (Copy)] pub struct Ipv4Addr { inner : c :: in_addr , } # [derive (Copy)] pub struct Ipv6Addr { inner : c :: in6_addr , } # [derive (Copy , PartialEq , Eq , Clone , Hash , Debug)] # [non_exhaustive] pub enum Ipv6MulticastScope { InterfaceLocal , LinkLocal , RealmLocal , AdminLocal , SiteLocal , OrganizationLocal , Global , } impl IpAddr { pub const fn is_unspecified (& self) -> bool { match self { IpAddr :: V4 (ip) => ip . is_unspecified () , IpAddr :: V6 (ip) => ip . is_unspecified () , } } pub const fn is_loopback (& self) -> bool { match self { IpAddr :: V4 (ip) => ip . is_loopback () , IpAddr :: V6 (ip) => ip . is_loopback () , } } pub const fn is_global (& self) -> bool { match self { IpAddr :: V4 (ip) => ip . is_global () , IpAddr :: V6 (ip) => ip . is_global () , } } pub const fn is_multicast (& self) -> bool { match self { IpAddr :: V4 (ip) => ip . is_multicast () , IpAddr :: V6 (ip) => ip . is_multicast () , } } pub const fn is_documentation (& self) -> bool { match self { IpAddr :: V4 (ip) => ip . is_documentation () , IpAddr :: V6 (ip) => ip . is_documentation () , } } pub const fn is_benchmarking (& self) -> bool { match self { IpAddr :: V4 (ip) => ip . is_benchmarking () , IpAddr :: V6 (ip) => ip . is_benchmarking () , } } pub const fn is_ipv4 (& self) -> bool { matches ! (self , IpAddr :: V4 (_)) } pub const fn is_ipv6 (& self) -> bool { matches ! (self , IpAddr :: V6 (_)) } pub const fn to_canonical (& self) -> IpAddr { match self { & v4 @ IpAddr :: V4 (_) => v4 , IpAddr :: V6 (v6) => v6 . to_canonical () , } } } impl Ipv4Addr { pub const fn new (a : u8 , b : u8 , c : u8 , d : u8) -> Ipv4Addr { Ipv4Addr { inner : c :: in_addr { s_addr : u32 :: from_ne_bytes ([a , b , c , d]) } } } pub const LOCALHOST : Self = Ipv4Addr :: new (127 , 0 , 0 , 1) ; # [doc (alias = "INADDR_ANY")] pub const UNSPECIFIED : Self = Ipv4Addr :: new (0 , 0 , 0 , 0) ; pub const BROADCAST : Self = Ipv4Addr :: new (255 , 255 , 255 , 255) ; pub const fn octets (& self) -> [u8 ; 4] { self . inner . s_addr . to_ne_bytes () } pub const fn is_unspecified (& self) -> bool { self . inner . s_addr == 0 } pub const fn is_loopback (& self) -> bool { self . octets () [0] == 127 } pub const fn is_private (& self) -> bool { match self . octets () { [10 , ..] => true , [172 , b , ..] if b >= 16 && b <= 31 => true , [192 , 168 , ..] => true , _ => false , } } pub const fn is_link_local (& self) -> bool { matches ! (self . octets () , [169 , 254 , ..]) } pub const fn is_global (& self) -> bool { if u32 :: from_be_bytes (self . octets ()) == 0xc0000009 || u32 :: from_be_bytes (self . octets ()) == 0xc000000a { return true ; } ! self . is_private () && ! self . is_loopback () && ! self . is_link_local () && ! self . is_broadcast () && ! self . is_documentation () && ! self . is_shared () && ! (self . octets () [0] == 192 && self . octets () [1] == 0 && self . octets () [2] == 0) && ! self . is_reserved () && ! self . is_benchmarking () && self . octets () [0] != 0 } pub const fn is_shared (& self) -> bool { self . octets () [0] == 100 && (self . octets () [1] & 0b1100_0000 == 0b0100_0000) } pub const fn is_benchmarking (& self) -> bool { self . octets () [0] == 198 && (self . octets () [1] & 0xfe) == 18 } pub const fn is_reserved (& self) -> bool { self . octets () [0] & 240 == 240 && ! self . is_broadcast () } pub const fn is_multicast (& self) -> bool { self . octets () [0] >= 224 && self . octets () [0] <= 239 } pub const fn is_broadcast (& self) -> bool { u32 :: from_be_bytes (self . octets ()) == u32 :: from_be_bytes (Self :: BROADCAST . octets ()) } pub const fn is_documentation (& self) -> bool { matches ! (self . octets () , [192 , 0 , 2 , _] | [198 , 51 , 100 , _] | [203 , 0 , 113 , _]) } pub const fn to_ipv6_compatible (& self) -> Ipv6Addr { let [a , b , c , d] = self . octets () ; Ipv6Addr { inner : c :: in6_addr { s6_addr : [0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , a , b , c , d] } , } } pub const fn to_ipv6_mapped (& self) -> Ipv6Addr { let [a , b , c , d] = self . octets () ; Ipv6Addr { inner : c :: in6_addr { s6_addr : [0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0xFF , 0xFF , a , b , c , d] } , } } } impl fmt :: Display for IpAddr { fn fmt (& self , fmt : & mut fmt :: Formatter < '_ >) -> fmt :: Result { match self { IpAddr :: V4 (ip) => ip . fmt (fmt) , IpAddr :: V6 (ip) => ip . fmt (fmt) , } } } impl fmt :: Debug for IpAddr { fn fmt (& self , fmt : & mut fmt :: Formatter < '_ >) -> fmt :: Result { fmt :: Display :: fmt (self , fmt) } } impl From < Ipv4Addr > for IpAddr { fn from (ipv4 : Ipv4Addr) -> IpAddr { IpAddr :: V4 (ipv4) } } impl From < Ipv6Addr > for IpAddr { fn from (ipv6 : Ipv6Addr) -> IpAddr { IpAddr :: V6 (ipv6) } } impl fmt :: Display for Ipv4Addr { fn fmt (& self , fmt : & mut fmt :: Formatter < '_ >) -> fmt :: Result { let octets = self . octets () ; if fmt . precision () . is_none () && fmt . width () . is_none () { write ! (fmt , "{}.{}.{}.{}" , octets [0] , octets [1] , octets [2] , octets [3]) } else { const IPV4_BUF_LEN : usize = 15 ; let mut buf = [0u8 ; IPV4_BUF_LEN] ; let mut buf_slice = & mut buf [..] ; write ! (buf_slice , "{}.{}.{}.{}" , octets [0] , octets [1] , octets [2] , octets [3]) . unwrap () ; let len = IPV4_BUF_LEN - buf_slice . len () ; let buf = unsafe { crate :: str :: from_utf8_unchecked (& buf [.. len]) } ; fmt . pad (buf) } } } impl fmt :: Debug for Ipv4Addr { fn fmt (& self , fmt : & mut fmt :: Formatter < '_ >) -> fmt :: Result { fmt :: Display :: fmt (self , fmt) } } impl Clone for Ipv4Addr { fn clone (& self) -> Ipv4Addr { * self } } impl PartialEq for Ipv4Addr { fn eq (& self , other : & Ipv4Addr) -> bool { self . inner . s_addr == other . inner . s_addr } } impl PartialEq < Ipv4Addr > for IpAddr { fn eq (& self , other : & Ipv4Addr) -> bool { match self { IpAddr :: V4 (v4) => v4 == other , IpAddr :: V6 (_) => false , } } } impl PartialEq < IpAddr > for Ipv4Addr { fn eq (& self , other : & IpAddr) -> bool { match other { IpAddr :: V4 (v4) => self == v4 , IpAddr :: V6 (_) => false , } } } impl Eq for Ipv4Addr { } impl hash :: Hash for Ipv4Addr { fn hash < H : hash :: Hasher > (& self , s : & mut H) { { self . inner . s_addr } . hash (s) } } impl PartialOrd for Ipv4Addr { fn partial_cmp (& self , other : & Ipv4Addr) -> Option < Ordering > { Some (self . cmp (other)) } } impl PartialOrd < Ipv4Addr > for IpAddr { fn partial_cmp (& self , other : & Ipv4Addr) -> Option < Ordering > { match self { IpAddr :: V4 (v4) => v4 . partial_cmp (other) , IpAddr :: V6 (_) => Some (Ordering :: Greater) , } } } impl PartialOrd < IpAddr > for Ipv4Addr { fn partial_cmp (& self , other : & IpAddr) -> Option < Ordering > { match other { IpAddr :: V4 (v4) => self . partial_cmp (v4) , IpAddr :: V6 (_) => Some (Ordering :: Less) , } } } impl Ord for Ipv4Addr { fn cmp (& self , other : & Ipv4Addr) -> Ordering { u32 :: from_be (self . inner . s_addr) . cmp (& u32 :: from_be (other . inner . s_addr)) } } impl IntoInner < c :: in_addr > for Ipv4Addr { fn into_inner (self) -> c :: in_addr { self . inner } } impl From < Ipv4Addr > for u32 { fn from (ip : Ipv4Addr) -> u32 { let ip = ip . octets () ; u32 :: from_be_bytes (ip) } } impl From < u32 > for Ipv4Addr { fn from (ip : u32) -> Ipv4Addr { Ipv4Addr :: from (ip . to_be_bytes ()) } } impl From < [u8 ; 4] > for Ipv4Addr { fn from (octets : [u8 ; 4]) -> Ipv4Addr { Ipv4Addr :: new (octets [0] , octets [1] , octets [2] , octets [3]) } } impl From < [u8 ; 4] > for IpAddr { fn from (octets : [u8 ; 4]) -> IpAddr { IpAddr :: V4 (Ipv4Addr :: from (octets)) } } impl Ipv6Addr { pub const fn new (a : u16 , b : u16 , c : u16 , d : u16 , e : u16 , f : u16 , g : u16 , h : u16) -> Ipv6Addr { let addr16 = [a . to_be () , b . to_be () , c . to_be () , d . to_be () , e . to_be () , f . to_be () , g . to_be () , h . to_be () ,] ; Ipv6Addr { inner : c :: in6_addr { s6_addr : unsafe { transmute :: < _ , [u8 ; 16] > (addr16) } , } , } } pub const LOCALHOST : Self = Ipv6Addr :: new (0 , 0 , 0 , 0 , 0 , 0 , 0 , 1) ; pub const UNSPECIFIED : Self = Ipv6Addr :: new (0 , 0 , 0 , 0 , 0 , 0 , 0 , 0) ; pub const fn segments (& self) -> [u16 ; 8] { let [a , b , c , d , e , f , g , h] = unsafe { transmute :: < _ , [u16 ; 8] > (self . inner . s6_addr) } ; [u16 :: from_be (a) , u16 :: from_be (b) , u16 :: from_be (c) , u16 :: from_be (d) , u16 :: from_be (e) , u16 :: from_be (f) , u16 :: from_be (g) , u16 :: from_be (h) ,] } pub const fn is_unspecified (& self) -> bool { u128 :: from_be_bytes (self . octets ()) == u128 :: from_be_bytes (Ipv6Addr :: UNSPECIFIED . octets ()) } pub const fn is_loopback (& self) -> bool { u128 :: from_be_bytes (self . octets ()) == u128 :: from_be_bytes (Ipv6Addr :: LOCALHOST . octets ()) } pub const fn is_global (& self) -> bool { match self . multicast_scope () { Some (Ipv6MulticastScope :: Global) => true , None => self . is_unicast_global () , _ => false , } } pub const fn is_unique_local (& self) -> bool { (self . segments () [0] & 0xfe00) == 0xfc00 } pub const fn is_unicast (& self) -> bool { ! self . is_multicast () } pub const fn is_unicast_link_local (& self) -> bool { (self . segments () [0] & 0xffc0) == 0xfe80 } pub const fn is_documentation (& self) -> bool { (self . segments () [0] == 0x2001) && (self . segments () [1] == 0xdb8) } pub const fn is_benchmarking (& self) -> bool { (self . segments () [0] == 0x2001) && (self . segments () [1] == 0x2) && (self . segments () [2] == 0) } pub const fn is_unicast_global (& self) -> bool { self . is_unicast () && ! self . is_loopback () && ! self . is_unicast_link_local () && ! self . is_unique_local () && ! self . is_unspecified () && ! self . is_documentation () } pub const fn multicast_scope (& self) -> Option < Ipv6MulticastScope > { if self . is_multicast () { match self . segments () [0] & 0x000f { 1 => Some (Ipv6MulticastScope :: InterfaceLocal) , 2 => Some (Ipv6MulticastScope :: LinkLocal) , 3 => Some (Ipv6MulticastScope :: RealmLocal) , 4 => Some (Ipv6MulticastScope :: AdminLocal) , 5 => Some (Ipv6MulticastScope :: SiteLocal) , 8 => Some (Ipv6MulticastScope :: OrganizationLocal) , 14 => Some (Ipv6MulticastScope :: Global) , _ => None , } } else { None } } pub const fn is_multicast (& self) -> bool { (self . segments () [0] & 0xff00) == 0xff00 } pub const fn to_ipv4_mapped (& self) -> Option < Ipv4Addr > { match self . octets () { [0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0xff , 0xff , a , b , c , d] => { Some (Ipv4Addr :: new (a , b , c , d)) } _ => None , } } pub const fn to_ipv4 (& self) -> Option < Ipv4Addr > { if let [0 , 0 , 0 , 0 , 0 , 0 | 0xffff , ab , cd] = self . segments () { let [a , b] = ab . to_be_bytes () ; let [c , d] = cd . to_be_bytes () ; Some (Ipv4Addr :: new (a , b , c , d)) } else { None } } pub const fn to_canonical (& self) -> IpAddr { if let Some (mapped) = self . to_ipv4_mapped () { return IpAddr :: V4 (mapped) ; } IpAddr :: V6 (* self) } pub const fn octets (& self) -> [u8 ; 16] { self . inner . s6_addr } } impl fmt :: Display for Ipv6Addr { fn fmt (& self , f : & mut fmt :: Formatter < '_ >) -> fmt :: Result { if f . precision () . is_none () && f . width () . is_none () { let segments = self . segments () ; if self . is_unspecified () { f . write_str ("::") } else if self . is_loopback () { f . write_str ("::1") } else if let Some (ipv4) = self . to_ipv4 () { match segments [5] { 0 => write ! (f , "::{}" , ipv4) , 0xffff => write ! (f , "::ffff:{}" , ipv4) , _ => unreachable ! () , } } else { # [derive (Copy , Clone , Default)] struct Span { start : usize , len : usize , } let zeroes = { let mut longest = Span :: default () ; let mut current = Span :: default () ; for (i , & segment) in segments . iter () . enumerate () { if segment == 0 { if current . len == 0 { current . start = i ; } current . len += 1 ; if current . len > longest . len { longest = current ; } } else { current = Span :: default () ; } } longest } ; # [doc = " Write a colon-separated part of the address"] # [inline] fn fmt_subslice (f : & mut fmt :: Formatter < '_ > , chunk : & [u16]) -> fmt :: Result { if let Some ((first , tail)) = chunk . split_first () { write ! (f , "{:x}" , first) ? ; for segment in tail { f . write_char (':') ? ; write ! (f , "{:x}" , segment) ? ; } } Ok (()) } if zeroes . len > 1 { fmt_subslice (f , & segments [.. zeroes . start]) ? ; f . write_str ("::") ? ; fmt_subslice (f , & segments [zeroes . start + zeroes . len ..]) } else { fmt_subslice (f , & segments) } } } else { const IPV6_BUF_LEN : usize = (4 * 8) + 7 ; let mut buf = [0u8 ; IPV6_BUF_LEN] ; let mut buf_slice = & mut buf [..] ; write ! (buf_slice , "{}" , self) . unwrap () ; let len = IPV6_BUF_LEN - buf_slice . len () ; let buf = unsafe { crate :: str :: from_utf8_unchecked (& buf [.. len]) } ; f . pad (buf) } } } impl fmt :: Debug for Ipv6Addr { fn fmt (& self , fmt : & mut fmt :: Formatter < '_ >) -> fmt :: Result { fmt :: Display :: fmt (self , fmt) } } impl Clone for Ipv6Addr { fn clone (& self) -> Ipv6Addr { * self } } impl PartialEq for Ipv6Addr { fn eq (& self , other : & Ipv6Addr) -> bool { self . inner . s6_addr == other . inner . s6_addr } } impl PartialEq < IpAddr > for Ipv6Addr { fn eq (& self , other : & IpAddr) -> bool { match other { IpAddr :: V4 (_) => false , IpAddr :: V6 (v6) => self == v6 , } } } impl PartialEq < Ipv6Addr > for IpAddr { fn eq (& self , other : & Ipv6Addr) -> bool { match self { IpAddr :: V4 (_) => false , IpAddr :: V6 (v6) => v6 == other , } } } impl Eq for Ipv6Addr { } impl hash :: Hash for Ipv6Addr { fn hash < H : hash :: Hasher > (& self , s : & mut H) { self . inner . s6_addr . hash (s) } } impl PartialOrd for Ipv6Addr { fn partial_cmp (& self , other : & Ipv6Addr) -> Option < Ordering > { Some (self . cmp (other)) } } impl PartialOrd < Ipv6Addr > for IpAddr { fn partial_cmp (& self , other : & Ipv6Addr) -> Option < Ordering > { match self { IpAddr :: V4 (_) => Some (Ordering :: Less) , IpAddr :: V6 (v6) => v6 . partial_cmp (other) , } } } impl PartialOrd < IpAddr > for Ipv6Addr { fn partial_cmp (& self , other : & IpAddr) -> Option < Ordering > { match other { IpAddr :: V4 (_) => Some (Ordering :: Greater) , IpAddr :: V6 (v6) => self . partial_cmp (v6) , } } } impl Ord for Ipv6Addr { fn cmp (& self , other : & Ipv6Addr) -> Ordering { self . segments () . cmp (& other . segments ()) } } impl AsInner < c :: in6_addr > for Ipv6Addr { fn as_inner (& self) -> & c :: in6_addr { & self . inner } } impl FromInner < c :: in6_addr > for Ipv6Addr { fn from_inner (addr : c :: in6_addr) -> Ipv6Addr { Ipv6Addr { inner : addr } } } impl From < Ipv6Addr > for u128 { fn from (ip : Ipv6Addr) -> u128 { let ip = ip . octets () ; u128 :: from_be_bytes (ip) } } impl From < u128 > for Ipv6Addr { fn from (ip : u128) -> Ipv6Addr { Ipv6Addr :: from (ip . to_be_bytes ()) } } impl From < [u8 ; 16] > for Ipv6Addr { fn from (octets : [u8 ; 16]) -> Ipv6Addr { let inner = c :: in6_addr { s6_addr : octets } ; Ipv6Addr :: from_inner (inner) } } impl From < [u16 ; 8] > for Ipv6Addr { fn from (segments : [u16 ; 8]) -> Ipv6Addr { let [a , b , c , d , e , f , g , h] = segments ; Ipv6Addr :: new (a , b , c , d , e , f , g , h) } } impl From < [u8 ; 16] > for IpAddr { fn from (octets : [u8 ; 16]) -> IpAddr { IpAddr :: V6 (Ipv6Addr :: from (octets)) } } impl From < [u16 ; 8] > for IpAddr { fn from (segments : [u16 ; 8]) -> IpAddr { IpAddr :: V6 (Ipv6Addr :: from (segments)) } }
diff --git a/vendor/prettyplease/examples/output.prettyplease.rs b/vendor/prettyplease/examples/output.prettyplease.rs
new file mode 100644
index 00000000..45b65d00
--- /dev/null
+++ b/vendor/prettyplease/examples/output.prettyplease.rs
@@ -0,0 +1,593 @@
+use crate::cmp::Ordering;
+use crate::fmt::{self, Write as FmtWrite};
+use crate::hash;
+use crate::io::Write as IoWrite;
+use crate::mem::transmute;
+use crate::sys::net::netc as c;
+use crate::sys_common::{AsInner, FromInner, IntoInner};
+#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
+pub enum IpAddr {
+ V4(Ipv4Addr),
+ V6(Ipv6Addr),
+}
+#[derive(Copy)]
+pub struct Ipv4Addr {
+ inner: c::in_addr,
+}
+#[derive(Copy)]
+pub struct Ipv6Addr {
+ inner: c::in6_addr,
+}
+#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)]
+#[non_exhaustive]
+pub enum Ipv6MulticastScope {
+ InterfaceLocal,
+ LinkLocal,
+ RealmLocal,
+ AdminLocal,
+ SiteLocal,
+ OrganizationLocal,
+ Global,
+}
+impl IpAddr {
+ pub const fn is_unspecified(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_unspecified(),
+ IpAddr::V6(ip) => ip.is_unspecified(),
+ }
+ }
+ pub const fn is_loopback(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_loopback(),
+ IpAddr::V6(ip) => ip.is_loopback(),
+ }
+ }
+ pub const fn is_global(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_global(),
+ IpAddr::V6(ip) => ip.is_global(),
+ }
+ }
+ pub const fn is_multicast(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_multicast(),
+ IpAddr::V6(ip) => ip.is_multicast(),
+ }
+ }
+ pub const fn is_documentation(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_documentation(),
+ IpAddr::V6(ip) => ip.is_documentation(),
+ }
+ }
+ pub const fn is_benchmarking(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_benchmarking(),
+ IpAddr::V6(ip) => ip.is_benchmarking(),
+ }
+ }
+ pub const fn is_ipv4(&self) -> bool {
+ matches!(self, IpAddr::V4(_))
+ }
+ pub const fn is_ipv6(&self) -> bool {
+ matches!(self, IpAddr::V6(_))
+ }
+ pub const fn to_canonical(&self) -> IpAddr {
+ match self {
+ &v4 @ IpAddr::V4(_) => v4,
+ IpAddr::V6(v6) => v6.to_canonical(),
+ }
+ }
+}
+impl Ipv4Addr {
+ pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
+ Ipv4Addr {
+ inner: c::in_addr {
+ s_addr: u32::from_ne_bytes([a, b, c, d]),
+ },
+ }
+ }
+ pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1);
+ #[doc(alias = "INADDR_ANY")]
+ pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0);
+ pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255);
+ pub const fn octets(&self) -> [u8; 4] {
+ self.inner.s_addr.to_ne_bytes()
+ }
+ pub const fn is_unspecified(&self) -> bool {
+ self.inner.s_addr == 0
+ }
+ pub const fn is_loopback(&self) -> bool {
+ self.octets()[0] == 127
+ }
+ pub const fn is_private(&self) -> bool {
+ match self.octets() {
+ [10, ..] => true,
+ [172, b, ..] if b >= 16 && b <= 31 => true,
+ [192, 168, ..] => true,
+ _ => false,
+ }
+ }
+ pub const fn is_link_local(&self) -> bool {
+ matches!(self.octets(), [169, 254, ..])
+ }
+ pub const fn is_global(&self) -> bool {
+ if u32::from_be_bytes(self.octets()) == 0xc0000009
+ || u32::from_be_bytes(self.octets()) == 0xc000000a
+ {
+ return true;
+ }
+ !self.is_private() && !self.is_loopback() && !self.is_link_local()
+ && !self.is_broadcast() && !self.is_documentation() && !self.is_shared()
+ && !(self.octets()[0] == 192 && self.octets()[1] == 0
+ && self.octets()[2] == 0) && !self.is_reserved()
+ && !self.is_benchmarking() && self.octets()[0] != 0
+ }
+ pub const fn is_shared(&self) -> bool {
+ self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000)
+ }
+ pub const fn is_benchmarking(&self) -> bool {
+ self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18
+ }
+ pub const fn is_reserved(&self) -> bool {
+ self.octets()[0] & 240 == 240 && !self.is_broadcast()
+ }
+ pub const fn is_multicast(&self) -> bool {
+ self.octets()[0] >= 224 && self.octets()[0] <= 239
+ }
+ pub const fn is_broadcast(&self) -> bool {
+ u32::from_be_bytes(self.octets()) == u32::from_be_bytes(Self::BROADCAST.octets())
+ }
+ pub const fn is_documentation(&self) -> bool {
+ matches!(self.octets(), [192, 0, 2, _] | [198, 51, 100, _] | [203, 0, 113, _])
+ }
+ pub const fn to_ipv6_compatible(&self) -> Ipv6Addr {
+ let [a, b, c, d] = self.octets();
+ Ipv6Addr {
+ inner: c::in6_addr {
+ s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d],
+ },
+ }
+ }
+ pub const fn to_ipv6_mapped(&self) -> Ipv6Addr {
+ let [a, b, c, d] = self.octets();
+ Ipv6Addr {
+ inner: c::in6_addr {
+ s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d],
+ },
+ }
+ }
+}
+impl fmt::Display for IpAddr {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ IpAddr::V4(ip) => ip.fmt(fmt),
+ IpAddr::V6(ip) => ip.fmt(fmt),
+ }
+ }
+}
+impl fmt::Debug for IpAddr {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(self, fmt)
+ }
+}
+impl From<Ipv4Addr> for IpAddr {
+ fn from(ipv4: Ipv4Addr) -> IpAddr {
+ IpAddr::V4(ipv4)
+ }
+}
+impl From<Ipv6Addr> for IpAddr {
+ fn from(ipv6: Ipv6Addr) -> IpAddr {
+ IpAddr::V6(ipv6)
+ }
+}
+impl fmt::Display for Ipv4Addr {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let octets = self.octets();
+ if fmt.precision().is_none() && fmt.width().is_none() {
+ write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
+ } else {
+ const IPV4_BUF_LEN: usize = 15;
+ let mut buf = [0u8; IPV4_BUF_LEN];
+ let mut buf_slice = &mut buf[..];
+ write!(buf_slice, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
+ .unwrap();
+ let len = IPV4_BUF_LEN - buf_slice.len();
+ let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
+ fmt.pad(buf)
+ }
+ }
+}
+impl fmt::Debug for Ipv4Addr {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(self, fmt)
+ }
+}
+impl Clone for Ipv4Addr {
+ fn clone(&self) -> Ipv4Addr {
+ *self
+ }
+}
+impl PartialEq for Ipv4Addr {
+ fn eq(&self, other: &Ipv4Addr) -> bool {
+ self.inner.s_addr == other.inner.s_addr
+ }
+}
+impl PartialEq<Ipv4Addr> for IpAddr {
+ fn eq(&self, other: &Ipv4Addr) -> bool {
+ match self {
+ IpAddr::V4(v4) => v4 == other,
+ IpAddr::V6(_) => false,
+ }
+ }
+}
+impl PartialEq<IpAddr> for Ipv4Addr {
+ fn eq(&self, other: &IpAddr) -> bool {
+ match other {
+ IpAddr::V4(v4) => self == v4,
+ IpAddr::V6(_) => false,
+ }
+ }
+}
+impl Eq for Ipv4Addr {}
+impl hash::Hash for Ipv4Addr {
+ fn hash<H: hash::Hasher>(&self, s: &mut H) {
+ { self.inner.s_addr }.hash(s)
+ }
+}
+impl PartialOrd for Ipv4Addr {
+ fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+impl PartialOrd<Ipv4Addr> for IpAddr {
+ fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
+ match self {
+ IpAddr::V4(v4) => v4.partial_cmp(other),
+ IpAddr::V6(_) => Some(Ordering::Greater),
+ }
+ }
+}
+impl PartialOrd<IpAddr> for Ipv4Addr {
+ fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
+ match other {
+ IpAddr::V4(v4) => self.partial_cmp(v4),
+ IpAddr::V6(_) => Some(Ordering::Less),
+ }
+ }
+}
+impl Ord for Ipv4Addr {
+ fn cmp(&self, other: &Ipv4Addr) -> Ordering {
+ u32::from_be(self.inner.s_addr).cmp(&u32::from_be(other.inner.s_addr))
+ }
+}
+impl IntoInner<c::in_addr> for Ipv4Addr {
+ fn into_inner(self) -> c::in_addr {
+ self.inner
+ }
+}
+impl From<Ipv4Addr> for u32 {
+ fn from(ip: Ipv4Addr) -> u32 {
+ let ip = ip.octets();
+ u32::from_be_bytes(ip)
+ }
+}
+impl From<u32> for Ipv4Addr {
+ fn from(ip: u32) -> Ipv4Addr {
+ Ipv4Addr::from(ip.to_be_bytes())
+ }
+}
+impl From<[u8; 4]> for Ipv4Addr {
+ fn from(octets: [u8; 4]) -> Ipv4Addr {
+ Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3])
+ }
+}
+impl From<[u8; 4]> for IpAddr {
+ fn from(octets: [u8; 4]) -> IpAddr {
+ IpAddr::V4(Ipv4Addr::from(octets))
+ }
+}
+impl Ipv6Addr {
+ pub const fn new(
+ a: u16,
+ b: u16,
+ c: u16,
+ d: u16,
+ e: u16,
+ f: u16,
+ g: u16,
+ h: u16,
+ ) -> Ipv6Addr {
+ let addr16 = [
+ a.to_be(),
+ b.to_be(),
+ c.to_be(),
+ d.to_be(),
+ e.to_be(),
+ f.to_be(),
+ g.to_be(),
+ h.to_be(),
+ ];
+ Ipv6Addr {
+ inner: c::in6_addr {
+ s6_addr: unsafe { transmute::<_, [u8; 16]>(addr16) },
+ },
+ }
+ }
+ pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
+ pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
+ pub const fn segments(&self) -> [u16; 8] {
+ let [a, b, c, d, e, f, g, h] = unsafe {
+ transmute::<_, [u16; 8]>(self.inner.s6_addr)
+ };
+ [
+ u16::from_be(a),
+ u16::from_be(b),
+ u16::from_be(c),
+ u16::from_be(d),
+ u16::from_be(e),
+ u16::from_be(f),
+ u16::from_be(g),
+ u16::from_be(h),
+ ]
+ }
+ pub const fn is_unspecified(&self) -> bool {
+ u128::from_be_bytes(self.octets())
+ == u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets())
+ }
+ pub const fn is_loopback(&self) -> bool {
+ u128::from_be_bytes(self.octets())
+ == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets())
+ }
+ pub const fn is_global(&self) -> bool {
+ match self.multicast_scope() {
+ Some(Ipv6MulticastScope::Global) => true,
+ None => self.is_unicast_global(),
+ _ => false,
+ }
+ }
+ pub const fn is_unique_local(&self) -> bool {
+ (self.segments()[0] & 0xfe00) == 0xfc00
+ }
+ pub const fn is_unicast(&self) -> bool {
+ !self.is_multicast()
+ }
+ pub const fn is_unicast_link_local(&self) -> bool {
+ (self.segments()[0] & 0xffc0) == 0xfe80
+ }
+ pub const fn is_documentation(&self) -> bool {
+ (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8)
+ }
+ pub const fn is_benchmarking(&self) -> bool {
+ (self.segments()[0] == 0x2001) && (self.segments()[1] == 0x2)
+ && (self.segments()[2] == 0)
+ }
+ pub const fn is_unicast_global(&self) -> bool {
+ self.is_unicast() && !self.is_loopback() && !self.is_unicast_link_local()
+ && !self.is_unique_local() && !self.is_unspecified()
+ && !self.is_documentation()
+ }
+ pub const fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
+ if self.is_multicast() {
+ match self.segments()[0] & 0x000f {
+ 1 => Some(Ipv6MulticastScope::InterfaceLocal),
+ 2 => Some(Ipv6MulticastScope::LinkLocal),
+ 3 => Some(Ipv6MulticastScope::RealmLocal),
+ 4 => Some(Ipv6MulticastScope::AdminLocal),
+ 5 => Some(Ipv6MulticastScope::SiteLocal),
+ 8 => Some(Ipv6MulticastScope::OrganizationLocal),
+ 14 => Some(Ipv6MulticastScope::Global),
+ _ => None,
+ }
+ } else {
+ None
+ }
+ }
+ pub const fn is_multicast(&self) -> bool {
+ (self.segments()[0] & 0xff00) == 0xff00
+ }
+ pub const fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
+ match self.octets() {
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
+ Some(Ipv4Addr::new(a, b, c, d))
+ }
+ _ => None,
+ }
+ }
+ pub const fn to_ipv4(&self) -> Option<Ipv4Addr> {
+ if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() {
+ let [a, b] = ab.to_be_bytes();
+ let [c, d] = cd.to_be_bytes();
+ Some(Ipv4Addr::new(a, b, c, d))
+ } else {
+ None
+ }
+ }
+ pub const fn to_canonical(&self) -> IpAddr {
+ if let Some(mapped) = self.to_ipv4_mapped() {
+ return IpAddr::V4(mapped);
+ }
+ IpAddr::V6(*self)
+ }
+ pub const fn octets(&self) -> [u8; 16] {
+ self.inner.s6_addr
+ }
+}
+impl fmt::Display for Ipv6Addr {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ if f.precision().is_none() && f.width().is_none() {
+ let segments = self.segments();
+ if self.is_unspecified() {
+ f.write_str("::")
+ } else if self.is_loopback() {
+ f.write_str("::1")
+ } else if let Some(ipv4) = self.to_ipv4() {
+ match segments[5] {
+ 0 => write!(f, "::{}", ipv4),
+ 0xffff => write!(f, "::ffff:{}", ipv4),
+ _ => unreachable!(),
+ }
+ } else {
+ #[derive(Copy, Clone, Default)]
+ struct Span {
+ start: usize,
+ len: usize,
+ }
+ let zeroes = {
+ let mut longest = Span::default();
+ let mut current = Span::default();
+ for (i, &segment) in segments.iter().enumerate() {
+ if segment == 0 {
+ if current.len == 0 {
+ current.start = i;
+ }
+ current.len += 1;
+ if current.len > longest.len {
+ longest = current;
+ }
+ } else {
+ current = Span::default();
+ }
+ }
+ longest
+ };
+ /// Write a colon-separated part of the address
+ #[inline]
+ fn fmt_subslice(
+ f: &mut fmt::Formatter<'_>,
+ chunk: &[u16],
+ ) -> fmt::Result {
+ if let Some((first, tail)) = chunk.split_first() {
+ write!(f, "{:x}", first)?;
+ for segment in tail {
+ f.write_char(':')?;
+ write!(f, "{:x}", segment)?;
+ }
+ }
+ Ok(())
+ }
+ if zeroes.len > 1 {
+ fmt_subslice(f, &segments[..zeroes.start])?;
+ f.write_str("::")?;
+ fmt_subslice(f, &segments[zeroes.start + zeroes.len..])
+ } else {
+ fmt_subslice(f, &segments)
+ }
+ }
+ } else {
+ const IPV6_BUF_LEN: usize = (4 * 8) + 7;
+ let mut buf = [0u8; IPV6_BUF_LEN];
+ let mut buf_slice = &mut buf[..];
+ write!(buf_slice, "{}", self).unwrap();
+ let len = IPV6_BUF_LEN - buf_slice.len();
+ let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
+ f.pad(buf)
+ }
+ }
+}
+impl fmt::Debug for Ipv6Addr {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(self, fmt)
+ }
+}
+impl Clone for Ipv6Addr {
+ fn clone(&self) -> Ipv6Addr {
+ *self
+ }
+}
+impl PartialEq for Ipv6Addr {
+ fn eq(&self, other: &Ipv6Addr) -> bool {
+ self.inner.s6_addr == other.inner.s6_addr
+ }
+}
+impl PartialEq<IpAddr> for Ipv6Addr {
+ fn eq(&self, other: &IpAddr) -> bool {
+ match other {
+ IpAddr::V4(_) => false,
+ IpAddr::V6(v6) => self == v6,
+ }
+ }
+}
+impl PartialEq<Ipv6Addr> for IpAddr {
+ fn eq(&self, other: &Ipv6Addr) -> bool {
+ match self {
+ IpAddr::V4(_) => false,
+ IpAddr::V6(v6) => v6 == other,
+ }
+ }
+}
+impl Eq for Ipv6Addr {}
+impl hash::Hash for Ipv6Addr {
+ fn hash<H: hash::Hasher>(&self, s: &mut H) {
+ self.inner.s6_addr.hash(s)
+ }
+}
+impl PartialOrd for Ipv6Addr {
+ fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+impl PartialOrd<Ipv6Addr> for IpAddr {
+ fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
+ match self {
+ IpAddr::V4(_) => Some(Ordering::Less),
+ IpAddr::V6(v6) => v6.partial_cmp(other),
+ }
+ }
+}
+impl PartialOrd<IpAddr> for Ipv6Addr {
+ fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
+ match other {
+ IpAddr::V4(_) => Some(Ordering::Greater),
+ IpAddr::V6(v6) => self.partial_cmp(v6),
+ }
+ }
+}
+impl Ord for Ipv6Addr {
+ fn cmp(&self, other: &Ipv6Addr) -> Ordering {
+ self.segments().cmp(&other.segments())
+ }
+}
+impl AsInner<c::in6_addr> for Ipv6Addr {
+ fn as_inner(&self) -> &c::in6_addr {
+ &self.inner
+ }
+}
+impl FromInner<c::in6_addr> for Ipv6Addr {
+ fn from_inner(addr: c::in6_addr) -> Ipv6Addr {
+ Ipv6Addr { inner: addr }
+ }
+}
+impl From<Ipv6Addr> for u128 {
+ fn from(ip: Ipv6Addr) -> u128 {
+ let ip = ip.octets();
+ u128::from_be_bytes(ip)
+ }
+}
+impl From<u128> for Ipv6Addr {
+ fn from(ip: u128) -> Ipv6Addr {
+ Ipv6Addr::from(ip.to_be_bytes())
+ }
+}
+impl From<[u8; 16]> for Ipv6Addr {
+ fn from(octets: [u8; 16]) -> Ipv6Addr {
+ let inner = c::in6_addr { s6_addr: octets };
+ Ipv6Addr::from_inner(inner)
+ }
+}
+impl From<[u16; 8]> for Ipv6Addr {
+ fn from(segments: [u16; 8]) -> Ipv6Addr {
+ let [a, b, c, d, e, f, g, h] = segments;
+ Ipv6Addr::new(a, b, c, d, e, f, g, h)
+ }
+}
+impl From<[u8; 16]> for IpAddr {
+ fn from(octets: [u8; 16]) -> IpAddr {
+ IpAddr::V6(Ipv6Addr::from(octets))
+ }
+}
+impl From<[u16; 8]> for IpAddr {
+ fn from(segments: [u16; 8]) -> IpAddr {
+ IpAddr::V6(Ipv6Addr::from(segments))
+ }
+}
diff --git a/vendor/prettyplease/examples/output.rustc.rs b/vendor/prettyplease/examples/output.rustc.rs
new file mode 100644
index 00000000..a77a14a8
--- /dev/null
+++ b/vendor/prettyplease/examples/output.rustc.rs
@@ -0,0 +1,506 @@
+use crate::cmp::Ordering;use crate::fmt::{self, Write as FmtWrite};
+use crate::hash;
+use crate::io::Write as IoWrite;
+use crate::mem::transmute;
+use crate::sys::net::netc as c;
+use crate::sys_common::{AsInner, FromInner, IntoInner};
+#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
+pub enum IpAddr { V4(Ipv4Addr), V6(Ipv6Addr), }
+#[derive(Copy)]
+pub struct Ipv4Addr {
+ inner: c::in_addr,
+}
+#[derive(Copy)]
+pub struct Ipv6Addr {
+ inner: c::in6_addr,
+}
+#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)]
+#[non_exhaustive]
+pub enum Ipv6MulticastScope {
+ InterfaceLocal,
+ LinkLocal,
+ RealmLocal,
+ AdminLocal,
+ SiteLocal,
+ OrganizationLocal,
+ Global,
+}
+impl IpAddr {
+ pub const fn is_unspecified(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_unspecified(),
+ IpAddr::V6(ip) => ip.is_unspecified(),
+ }
+ }
+ pub const fn is_loopback(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_loopback(),
+ IpAddr::V6(ip) => ip.is_loopback(),
+ }
+ }
+ pub const fn is_global(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_global(),
+ IpAddr::V6(ip) => ip.is_global(),
+ }
+ }
+ pub const fn is_multicast(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_multicast(),
+ IpAddr::V6(ip) => ip.is_multicast(),
+ }
+ }
+ pub const fn is_documentation(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_documentation(),
+ IpAddr::V6(ip) => ip.is_documentation(),
+ }
+ }
+ pub const fn is_benchmarking(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_benchmarking(),
+ IpAddr::V6(ip) => ip.is_benchmarking(),
+ }
+ }
+ pub const fn is_ipv4(&self) -> bool { matches!(self, IpAddr :: V4(_)) }
+ pub const fn is_ipv6(&self) -> bool { matches!(self, IpAddr :: V6(_)) }
+ pub const fn to_canonical(&self) -> IpAddr {
+ match self {
+ &v4 @ IpAddr::V4(_) => v4,
+ IpAddr::V6(v6) => v6.to_canonical(),
+ }
+ }
+}
+impl Ipv4Addr {
+ pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
+ Ipv4Addr {
+ inner: c::in_addr { s_addr: u32::from_ne_bytes([a, b, c, d]) },
+ }
+ }
+ pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1);
+ #[doc(alias = "INADDR_ANY")]
+ pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0);
+ pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255);
+ pub const fn octets(&self) -> [u8; 4] { self.inner.s_addr.to_ne_bytes() }
+ pub const fn is_unspecified(&self) -> bool { self.inner.s_addr == 0 }
+ pub const fn is_loopback(&self) -> bool { self.octets()[0] == 127 }
+ pub const fn is_private(&self) -> bool {
+ match self.octets() {
+ [10, ..] => true,
+ [172, b, ..] if b >= 16 && b <= 31 => true,
+ [192, 168, ..] => true,
+ _ => false,
+ }
+ }
+ pub const fn is_link_local(&self) -> bool {
+ matches!(self.octets(), [169, 254, ..])
+ }
+ pub const fn is_global(&self) -> bool {
+ if u32::from_be_bytes(self.octets()) == 0xc0000009 ||
+ u32::from_be_bytes(self.octets()) == 0xc000000a {
+ return true;
+ }
+ !self.is_private() && !self.is_loopback() && !self.is_link_local() &&
+ !self.is_broadcast() && !self.is_documentation() &&
+ !self.is_shared() &&
+ !(self.octets()[0] == 192 && self.octets()[1] == 0 &&
+ self.octets()[2] == 0) && !self.is_reserved() &&
+ !self.is_benchmarking() && self.octets()[0] != 0
+ }
+ pub const fn is_shared(&self) -> bool {
+ self.octets()[0] == 100 &&
+ (self.octets()[1] & 0b1100_0000 == 0b0100_0000)
+ }
+ pub const fn is_benchmarking(&self) -> bool {
+ self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18
+ }
+ pub const fn is_reserved(&self) -> bool {
+ self.octets()[0] & 240 == 240 && !self.is_broadcast()
+ }
+ pub const fn is_multicast(&self) -> bool {
+ self.octets()[0] >= 224 && self.octets()[0] <= 239
+ }
+ pub const fn is_broadcast(&self) -> bool {
+ u32::from_be_bytes(self.octets()) ==
+ u32::from_be_bytes(Self::BROADCAST.octets())
+ }
+ pub const fn is_documentation(&self) -> bool {
+ matches!(self.octets(), [192, 0, 2, _] | [198, 51, 100, _] |
+ [203, 0, 113, _])
+ }
+ pub const fn to_ipv6_compatible(&self) -> Ipv6Addr {
+ let [a, b, c, d] = self.octets();
+ Ipv6Addr {
+ inner: c::in6_addr {
+ s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d],
+ },
+ }
+ }
+ pub const fn to_ipv6_mapped(&self) -> Ipv6Addr {
+ let [a, b, c, d] = self.octets();
+ Ipv6Addr {
+ inner: c::in6_addr {
+ s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c,
+ d],
+ },
+ }
+ }
+}
+impl fmt::Display for IpAddr {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ IpAddr::V4(ip) => ip.fmt(fmt),
+ IpAddr::V6(ip) => ip.fmt(fmt),
+ }
+ }
+}
+impl fmt::Debug for IpAddr {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(self, fmt)
+ }
+}
+impl From<Ipv4Addr> for IpAddr {
+ fn from(ipv4: Ipv4Addr) -> IpAddr { IpAddr::V4(ipv4) }
+}
+impl From<Ipv6Addr> for IpAddr {
+ fn from(ipv6: Ipv6Addr) -> IpAddr { IpAddr::V6(ipv6) }
+}
+impl fmt::Display for Ipv4Addr {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let octets = self.octets();
+ if fmt.precision().is_none() && fmt.width().is_none() {
+ write!(fmt, "{}.{}.{}.{}", octets [0], octets [1], octets [2],
+ octets [3])
+ } else {
+ const IPV4_BUF_LEN: usize = 15;
+ let mut buf = [0u8; IPV4_BUF_LEN];
+ let mut buf_slice = &mut buf[..];
+ write!(buf_slice, "{}.{}.{}.{}", octets [0], octets [1], octets
+ [2], octets [3]).unwrap();
+ let len = IPV4_BUF_LEN - buf_slice.len();
+ let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
+ fmt.pad(buf)
+ }
+ }
+}
+impl fmt::Debug for Ipv4Addr {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(self, fmt)
+ }
+}
+impl Clone for Ipv4Addr {
+ fn clone(&self) -> Ipv4Addr { *self }
+}
+impl PartialEq for Ipv4Addr {
+ fn eq(&self, other: &Ipv4Addr) -> bool {
+ self.inner.s_addr == other.inner.s_addr
+ }
+}
+impl PartialEq<Ipv4Addr> for IpAddr {
+ fn eq(&self, other: &Ipv4Addr) -> bool {
+ match self { IpAddr::V4(v4) => v4 == other, IpAddr::V6(_) => false, }
+ }
+}
+impl PartialEq<IpAddr> for Ipv4Addr {
+ fn eq(&self, other: &IpAddr) -> bool {
+ match other { IpAddr::V4(v4) => self == v4, IpAddr::V6(_) => false, }
+ }
+}
+impl Eq for Ipv4Addr {}
+impl hash::Hash for Ipv4Addr {
+ fn hash<H: hash::Hasher>(&self, s: &mut H) {
+ { self.inner.s_addr }.hash(s)
+ }
+}
+impl PartialOrd for Ipv4Addr {
+ fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+impl PartialOrd<Ipv4Addr> for IpAddr {
+ fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
+ match self {
+ IpAddr::V4(v4) => v4.partial_cmp(other),
+ IpAddr::V6(_) => Some(Ordering::Greater),
+ }
+ }
+}
+impl PartialOrd<IpAddr> for Ipv4Addr {
+ fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
+ match other {
+ IpAddr::V4(v4) => self.partial_cmp(v4),
+ IpAddr::V6(_) => Some(Ordering::Less),
+ }
+ }
+}
+impl Ord for Ipv4Addr {
+ fn cmp(&self, other: &Ipv4Addr) -> Ordering {
+ u32::from_be(self.inner.s_addr).cmp(&u32::from_be(other.inner.s_addr))
+ }
+}
+impl IntoInner<c::in_addr> for Ipv4Addr {
+ fn into_inner(self) -> c::in_addr { self.inner }
+}
+impl From<Ipv4Addr> for u32 {
+ fn from(ip: Ipv4Addr) -> u32 {
+ let ip = ip.octets();
+ u32::from_be_bytes(ip)
+ }
+}
+impl From<u32> for Ipv4Addr {
+ fn from(ip: u32) -> Ipv4Addr { Ipv4Addr::from(ip.to_be_bytes()) }
+}
+impl From<[u8; 4]> for Ipv4Addr {
+ fn from(octets: [u8; 4]) -> Ipv4Addr {
+ Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3])
+ }
+}
+impl From<[u8; 4]> for IpAddr {
+ fn from(octets: [u8; 4]) -> IpAddr { IpAddr::V4(Ipv4Addr::from(octets)) }
+}
+impl Ipv6Addr {
+ pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16,
+ h: u16) -> Ipv6Addr {
+ let addr16 =
+ [a.to_be(), b.to_be(), c.to_be(), d.to_be(), e.to_be(), f.to_be(),
+ g.to_be(), h.to_be()];
+ Ipv6Addr {
+ inner: c::in6_addr {
+ s6_addr: unsafe { transmute::<_, [u8; 16]>(addr16) },
+ },
+ }
+ }
+ pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
+ pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
+ pub const fn segments(&self) -> [u16; 8] {
+ let [a, b, c, d, e, f, g, h] =
+ unsafe { transmute::<_, [u16; 8]>(self.inner.s6_addr) };
+ [u16::from_be(a), u16::from_be(b), u16::from_be(c), u16::from_be(d),
+ u16::from_be(e), u16::from_be(f), u16::from_be(g),
+ u16::from_be(h)]
+ }
+ pub const fn is_unspecified(&self) -> bool {
+ u128::from_be_bytes(self.octets()) ==
+ u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets())
+ }
+ pub const fn is_loopback(&self) -> bool {
+ u128::from_be_bytes(self.octets()) ==
+ u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets())
+ }
+ pub const fn is_global(&self) -> bool {
+ match self.multicast_scope() {
+ Some(Ipv6MulticastScope::Global) => true,
+ None => self.is_unicast_global(),
+ _ => false,
+ }
+ }
+ pub const fn is_unique_local(&self) -> bool {
+ (self.segments()[0] & 0xfe00) == 0xfc00
+ }
+ pub const fn is_unicast(&self) -> bool { !self.is_multicast() }
+ pub const fn is_unicast_link_local(&self) -> bool {
+ (self.segments()[0] & 0xffc0) == 0xfe80
+ }
+ pub const fn is_documentation(&self) -> bool {
+ (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8)
+ }
+ pub const fn is_benchmarking(&self) -> bool {
+ (self.segments()[0] == 0x2001) && (self.segments()[1] == 0x2) &&
+ (self.segments()[2] == 0)
+ }
+ pub const fn is_unicast_global(&self) -> bool {
+ self.is_unicast() && !self.is_loopback() &&
+ !self.is_unicast_link_local() && !self.is_unique_local() &&
+ !self.is_unspecified() && !self.is_documentation()
+ }
+ pub const fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
+ if self.is_multicast() {
+ match self.segments()[0] & 0x000f {
+ 1 => Some(Ipv6MulticastScope::InterfaceLocal),
+ 2 => Some(Ipv6MulticastScope::LinkLocal),
+ 3 => Some(Ipv6MulticastScope::RealmLocal),
+ 4 => Some(Ipv6MulticastScope::AdminLocal),
+ 5 => Some(Ipv6MulticastScope::SiteLocal),
+ 8 => Some(Ipv6MulticastScope::OrganizationLocal),
+ 14 => Some(Ipv6MulticastScope::Global),
+ _ => None,
+ }
+ } else { None }
+ }
+ pub const fn is_multicast(&self) -> bool {
+ (self.segments()[0] & 0xff00) == 0xff00
+ }
+ pub const fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
+ match self.octets() {
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
+ Some(Ipv4Addr::new(a, b, c, d))
+ }
+ _ => None,
+ }
+ }
+ pub const fn to_ipv4(&self) -> Option<Ipv4Addr> {
+ if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() {
+ let [a, b] = ab.to_be_bytes();
+ let [c, d] = cd.to_be_bytes();
+ Some(Ipv4Addr::new(a, b, c, d))
+ } else { None }
+ }
+ pub const fn to_canonical(&self) -> IpAddr {
+ if let Some(mapped) = self.to_ipv4_mapped() {
+ return IpAddr::V4(mapped);
+ }
+ IpAddr::V6(*self)
+ }
+ pub const fn octets(&self) -> [u8; 16] { self.inner.s6_addr }
+}
+impl fmt::Display for Ipv6Addr {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ if f.precision().is_none() && f.width().is_none() {
+ let segments = self.segments();
+ if self.is_unspecified() {
+ f.write_str("::")
+ } else if self.is_loopback() {
+ f.write_str("::1")
+ } else if let Some(ipv4) = self.to_ipv4() {
+ match segments[5] {
+ 0 => write!(f, "::{}", ipv4),
+ 0xffff => write!(f, "::ffff:{}", ipv4),
+ _ => unreachable!(),
+ }
+ } else {
+ #[derive(Copy, Clone, Default)]
+ struct Span {
+ start: usize,
+ len: usize,
+ }
+ let zeroes =
+ {
+ let mut longest = Span::default();
+ let mut current = Span::default();
+ for (i, &segment) in segments.iter().enumerate() {
+ if segment == 0 {
+ if current.len == 0 { current.start = i; }
+ current.len += 1;
+ if current.len > longest.len { longest = current; }
+ } else { current = Span::default(); }
+ }
+ longest
+ };
+ #[doc = " Write a colon-separated part of the address"]
+ #[inline]
+ fn fmt_subslice(f: &mut fmt::Formatter<'_>, chunk: &[u16])
+ -> fmt::Result {
+ if let Some((first, tail)) = chunk.split_first() {
+ write!(f, "{:x}", first)?;
+ for segment in tail {
+ f.write_char(':')?;
+ write!(f, "{:x}", segment)?;
+ }
+ }
+ Ok(())
+ }
+ if zeroes.len > 1 {
+ fmt_subslice(f, &segments[..zeroes.start])?;
+ f.write_str("::")?;
+ fmt_subslice(f, &segments[zeroes.start + zeroes.len..])
+ } else { fmt_subslice(f, &segments) }
+ }
+ } else {
+ const IPV6_BUF_LEN: usize = (4 * 8) + 7;
+ let mut buf = [0u8; IPV6_BUF_LEN];
+ let mut buf_slice = &mut buf[..];
+ write!(buf_slice, "{}", self).unwrap();
+ let len = IPV6_BUF_LEN - buf_slice.len();
+ let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
+ f.pad(buf)
+ }
+ }
+}
+impl fmt::Debug for Ipv6Addr {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(self, fmt)
+ }
+}
+impl Clone for Ipv6Addr {
+ fn clone(&self) -> Ipv6Addr { *self }
+}
+impl PartialEq for Ipv6Addr {
+ fn eq(&self, other: &Ipv6Addr) -> bool {
+ self.inner.s6_addr == other.inner.s6_addr
+ }
+}
+impl PartialEq<IpAddr> for Ipv6Addr {
+ fn eq(&self, other: &IpAddr) -> bool {
+ match other { IpAddr::V4(_) => false, IpAddr::V6(v6) => self == v6, }
+ }
+}
+impl PartialEq<Ipv6Addr> for IpAddr {
+ fn eq(&self, other: &Ipv6Addr) -> bool {
+ match self { IpAddr::V4(_) => false, IpAddr::V6(v6) => v6 == other, }
+ }
+}
+impl Eq for Ipv6Addr {}
+impl hash::Hash for Ipv6Addr {
+ fn hash<H: hash::Hasher>(&self, s: &mut H) { self.inner.s6_addr.hash(s) }
+}
+impl PartialOrd for Ipv6Addr {
+ fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+impl PartialOrd<Ipv6Addr> for IpAddr {
+ fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
+ match self {
+ IpAddr::V4(_) => Some(Ordering::Less),
+ IpAddr::V6(v6) => v6.partial_cmp(other),
+ }
+ }
+}
+impl PartialOrd<IpAddr> for Ipv6Addr {
+ fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
+ match other {
+ IpAddr::V4(_) => Some(Ordering::Greater),
+ IpAddr::V6(v6) => self.partial_cmp(v6),
+ }
+ }
+}
+impl Ord for Ipv6Addr {
+ fn cmp(&self, other: &Ipv6Addr) -> Ordering {
+ self.segments().cmp(&other.segments())
+ }
+}
+impl AsInner<c::in6_addr> for Ipv6Addr {
+ fn as_inner(&self) -> &c::in6_addr { &self.inner }
+}
+impl FromInner<c::in6_addr> for Ipv6Addr {
+ fn from_inner(addr: c::in6_addr) -> Ipv6Addr { Ipv6Addr { inner: addr } }
+}
+impl From<Ipv6Addr> for u128 {
+ fn from(ip: Ipv6Addr) -> u128 {
+ let ip = ip.octets();
+ u128::from_be_bytes(ip)
+ }
+}
+impl From<u128> for Ipv6Addr {
+ fn from(ip: u128) -> Ipv6Addr { Ipv6Addr::from(ip.to_be_bytes()) }
+}
+impl From<[u8; 16]> for Ipv6Addr {
+ fn from(octets: [u8; 16]) -> Ipv6Addr {
+ let inner = c::in6_addr { s6_addr: octets };
+ Ipv6Addr::from_inner(inner)
+ }
+}
+impl From<[u16; 8]> for Ipv6Addr {
+ fn from(segments: [u16; 8]) -> Ipv6Addr {
+ let [a, b, c, d, e, f, g, h] = segments;
+ Ipv6Addr::new(a, b, c, d, e, f, g, h)
+ }
+}
+impl From<[u8; 16]> for IpAddr {
+ fn from(octets: [u8; 16]) -> IpAddr { IpAddr::V6(Ipv6Addr::from(octets)) }
+}
+impl From<[u16; 8]> for IpAddr {
+ fn from(segments: [u16; 8]) -> IpAddr {
+ IpAddr::V6(Ipv6Addr::from(segments))
+ }
+}
diff --git a/vendor/prettyplease/examples/output.rustfmt.rs b/vendor/prettyplease/examples/output.rustfmt.rs
new file mode 100644
index 00000000..3c7181d8
--- /dev/null
+++ b/vendor/prettyplease/examples/output.rustfmt.rs
@@ -0,0 +1,552 @@
+use crate::cmp::Ordering;
+use crate::fmt::{self, Write as FmtWrite};
+use crate::hash;
+use crate::io::Write as IoWrite;
+use crate::mem::transmute;
+use crate::sys::net::netc as c;
+use crate::sys_common::{AsInner, FromInner, IntoInner};
+#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
+pub enum IpAddr {
+ V4(Ipv4Addr),
+ V6(Ipv6Addr),
+}
+#[derive(Copy)]
+pub struct Ipv4Addr {
+ inner: c::in_addr,
+}
+#[derive(Copy)]
+pub struct Ipv6Addr {
+ inner: c::in6_addr,
+}
+#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)]
+#[non_exhaustive]
+pub enum Ipv6MulticastScope {
+ InterfaceLocal,
+ LinkLocal,
+ RealmLocal,
+ AdminLocal,
+ SiteLocal,
+ OrganizationLocal,
+ Global,
+}
+impl IpAddr {
+ pub const fn is_unspecified(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_unspecified(),
+ IpAddr::V6(ip) => ip.is_unspecified(),
+ }
+ }
+ pub const fn is_loopback(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_loopback(),
+ IpAddr::V6(ip) => ip.is_loopback(),
+ }
+ }
+ pub const fn is_global(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_global(),
+ IpAddr::V6(ip) => ip.is_global(),
+ }
+ }
+ pub const fn is_multicast(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_multicast(),
+ IpAddr::V6(ip) => ip.is_multicast(),
+ }
+ }
+ pub const fn is_documentation(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_documentation(),
+ IpAddr::V6(ip) => ip.is_documentation(),
+ }
+ }
+ pub const fn is_benchmarking(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_benchmarking(),
+ IpAddr::V6(ip) => ip.is_benchmarking(),
+ }
+ }
+ pub const fn is_ipv4(&self) -> bool {
+ matches!(self, IpAddr::V4(_))
+ }
+ pub const fn is_ipv6(&self) -> bool {
+ matches!(self, IpAddr::V6(_))
+ }
+ pub const fn to_canonical(&self) -> IpAddr {
+ match self {
+ &v4 @ IpAddr::V4(_) => v4,
+ IpAddr::V6(v6) => v6.to_canonical(),
+ }
+ }
+}
+impl Ipv4Addr {
+ pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
+ Ipv4Addr {
+ inner: c::in_addr {
+ s_addr: u32::from_ne_bytes([a, b, c, d]),
+ },
+ }
+ }
+ pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1);
+ #[doc(alias = "INADDR_ANY")]
+ pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0);
+ pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255);
+ pub const fn octets(&self) -> [u8; 4] {
+ self.inner.s_addr.to_ne_bytes()
+ }
+ pub const fn is_unspecified(&self) -> bool {
+ self.inner.s_addr == 0
+ }
+ pub const fn is_loopback(&self) -> bool {
+ self.octets()[0] == 127
+ }
+ pub const fn is_private(&self) -> bool {
+ match self.octets() {
+ [10, ..] => true,
+ [172, b, ..] if b >= 16 && b <= 31 => true,
+ [192, 168, ..] => true,
+ _ => false,
+ }
+ }
+ pub const fn is_link_local(&self) -> bool {
+ matches!(self.octets(), [169, 254, ..])
+ }
+ pub const fn is_global(&self) -> bool {
+ if u32::from_be_bytes(self.octets()) == 0xc0000009
+ || u32::from_be_bytes(self.octets()) == 0xc000000a
+ {
+ return true;
+ }
+ !self.is_private()
+ && !self.is_loopback()
+ && !self.is_link_local()
+ && !self.is_broadcast()
+ && !self.is_documentation()
+ && !self.is_shared()
+ && !(self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0)
+ && !self.is_reserved()
+ && !self.is_benchmarking()
+ && self.octets()[0] != 0
+ }
+ pub const fn is_shared(&self) -> bool {
+ self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000)
+ }
+ pub const fn is_benchmarking(&self) -> bool {
+ self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18
+ }
+ pub const fn is_reserved(&self) -> bool {
+ self.octets()[0] & 240 == 240 && !self.is_broadcast()
+ }
+ pub const fn is_multicast(&self) -> bool {
+ self.octets()[0] >= 224 && self.octets()[0] <= 239
+ }
+ pub const fn is_broadcast(&self) -> bool {
+ u32::from_be_bytes(self.octets()) == u32::from_be_bytes(Self::BROADCAST.octets())
+ }
+ pub const fn is_documentation(&self) -> bool {
+ matches!(
+ self.octets(),
+ [192, 0, 2, _] | [198, 51, 100, _] | [203, 0, 113, _]
+ )
+ }
+ pub const fn to_ipv6_compatible(&self) -> Ipv6Addr {
+ let [a, b, c, d] = self.octets();
+ Ipv6Addr {
+ inner: c::in6_addr {
+ s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d],
+ },
+ }
+ }
+ pub const fn to_ipv6_mapped(&self) -> Ipv6Addr {
+ let [a, b, c, d] = self.octets();
+ Ipv6Addr {
+ inner: c::in6_addr {
+ s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d],
+ },
+ }
+ }
+}
+impl fmt::Display for IpAddr {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ IpAddr::V4(ip) => ip.fmt(fmt),
+ IpAddr::V6(ip) => ip.fmt(fmt),
+ }
+ }
+}
+impl fmt::Debug for IpAddr {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(self, fmt)
+ }
+}
+impl From<Ipv4Addr> for IpAddr {
+ fn from(ipv4: Ipv4Addr) -> IpAddr {
+ IpAddr::V4(ipv4)
+ }
+}
+impl From<Ipv6Addr> for IpAddr {
+ fn from(ipv6: Ipv6Addr) -> IpAddr {
+ IpAddr::V6(ipv6)
+ }
+}
+impl fmt::Display for Ipv4Addr {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let octets = self.octets();
+ if fmt.precision().is_none() && fmt.width().is_none() {
+ write!(
+ fmt,
+ "{}.{}.{}.{}",
+ octets[0], octets[1], octets[2], octets[3]
+ )
+ } else {
+ const IPV4_BUF_LEN: usize = 15;
+ let mut buf = [0u8; IPV4_BUF_LEN];
+ let mut buf_slice = &mut buf[..];
+ write!(
+ buf_slice,
+ "{}.{}.{}.{}",
+ octets[0], octets[1], octets[2], octets[3]
+ )
+ .unwrap();
+ let len = IPV4_BUF_LEN - buf_slice.len();
+ let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
+ fmt.pad(buf)
+ }
+ }
+}
+impl fmt::Debug for Ipv4Addr {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(self, fmt)
+ }
+}
+impl Clone for Ipv4Addr {
+ fn clone(&self) -> Ipv4Addr {
+ *self
+ }
+}
+impl PartialEq for Ipv4Addr {
+ fn eq(&self, other: &Ipv4Addr) -> bool {
+ self.inner.s_addr == other.inner.s_addr
+ }
+}
+impl PartialEq<Ipv4Addr> for IpAddr {
+ fn eq(&self, other: &Ipv4Addr) -> bool {
+ match self {
+ IpAddr::V4(v4) => v4 == other,
+ IpAddr::V6(_) => false,
+ }
+ }
+}
+impl PartialEq<IpAddr> for Ipv4Addr {
+ fn eq(&self, other: &IpAddr) -> bool {
+ match other {
+ IpAddr::V4(v4) => self == v4,
+ IpAddr::V6(_) => false,
+ }
+ }
+}
+impl Eq for Ipv4Addr {}
+impl hash::Hash for Ipv4Addr {
+ fn hash<H: hash::Hasher>(&self, s: &mut H) {
+ { self.inner.s_addr }.hash(s)
+ }
+}
+impl PartialOrd for Ipv4Addr {
+ fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+impl PartialOrd<Ipv4Addr> for IpAddr {
+ fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
+ match self {
+ IpAddr::V4(v4) => v4.partial_cmp(other),
+ IpAddr::V6(_) => Some(Ordering::Greater),
+ }
+ }
+}
+impl PartialOrd<IpAddr> for Ipv4Addr {
+ fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
+ match other {
+ IpAddr::V4(v4) => self.partial_cmp(v4),
+ IpAddr::V6(_) => Some(Ordering::Less),
+ }
+ }
+}
+impl Ord for Ipv4Addr {
+ fn cmp(&self, other: &Ipv4Addr) -> Ordering {
+ u32::from_be(self.inner.s_addr).cmp(&u32::from_be(other.inner.s_addr))
+ }
+}
+impl IntoInner<c::in_addr> for Ipv4Addr {
+ fn into_inner(self) -> c::in_addr {
+ self.inner
+ }
+}
+impl From<Ipv4Addr> for u32 {
+ fn from(ip: Ipv4Addr) -> u32 {
+ let ip = ip.octets();
+ u32::from_be_bytes(ip)
+ }
+}
+impl From<u32> for Ipv4Addr {
+ fn from(ip: u32) -> Ipv4Addr {
+ Ipv4Addr::from(ip.to_be_bytes())
+ }
+}
+impl From<[u8; 4]> for Ipv4Addr {
+ fn from(octets: [u8; 4]) -> Ipv4Addr {
+ Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3])
+ }
+}
+impl From<[u8; 4]> for IpAddr {
+ fn from(octets: [u8; 4]) -> IpAddr {
+ IpAddr::V4(Ipv4Addr::from(octets))
+ }
+}
+impl Ipv6Addr {
+ pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
+ let addr16 = [
+ a.to_be(),
+ b.to_be(),
+ c.to_be(),
+ d.to_be(),
+ e.to_be(),
+ f.to_be(),
+ g.to_be(),
+ h.to_be(),
+ ];
+ Ipv6Addr {
+ inner: c::in6_addr {
+ s6_addr: unsafe { transmute::<_, [u8; 16]>(addr16) },
+ },
+ }
+ }
+ pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
+ pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
+ pub const fn segments(&self) -> [u16; 8] {
+ let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.inner.s6_addr) };
+ [
+ u16::from_be(a),
+ u16::from_be(b),
+ u16::from_be(c),
+ u16::from_be(d),
+ u16::from_be(e),
+ u16::from_be(f),
+ u16::from_be(g),
+ u16::from_be(h),
+ ]
+ }
+ pub const fn is_unspecified(&self) -> bool {
+ u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets())
+ }
+ pub const fn is_loopback(&self) -> bool {
+ u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets())
+ }
+ pub const fn is_global(&self) -> bool {
+ match self.multicast_scope() {
+ Some(Ipv6MulticastScope::Global) => true,
+ None => self.is_unicast_global(),
+ _ => false,
+ }
+ }
+ pub const fn is_unique_local(&self) -> bool {
+ (self.segments()[0] & 0xfe00) == 0xfc00
+ }
+ pub const fn is_unicast(&self) -> bool {
+ !self.is_multicast()
+ }
+ pub const fn is_unicast_link_local(&self) -> bool {
+ (self.segments()[0] & 0xffc0) == 0xfe80
+ }
+ pub const fn is_documentation(&self) -> bool {
+ (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8)
+ }
+ pub const fn is_benchmarking(&self) -> bool {
+ (self.segments()[0] == 0x2001) && (self.segments()[1] == 0x2) && (self.segments()[2] == 0)
+ }
+ pub const fn is_unicast_global(&self) -> bool {
+ self.is_unicast()
+ && !self.is_loopback()
+ && !self.is_unicast_link_local()
+ && !self.is_unique_local()
+ && !self.is_unspecified()
+ && !self.is_documentation()
+ }
+ pub const fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
+ if self.is_multicast() {
+ match self.segments()[0] & 0x000f {
+ 1 => Some(Ipv6MulticastScope::InterfaceLocal),
+ 2 => Some(Ipv6MulticastScope::LinkLocal),
+ 3 => Some(Ipv6MulticastScope::RealmLocal),
+ 4 => Some(Ipv6MulticastScope::AdminLocal),
+ 5 => Some(Ipv6MulticastScope::SiteLocal),
+ 8 => Some(Ipv6MulticastScope::OrganizationLocal),
+ 14 => Some(Ipv6MulticastScope::Global),
+ _ => None,
+ }
+ } else {
+ None
+ }
+ }
+ pub const fn is_multicast(&self) -> bool {
+ (self.segments()[0] & 0xff00) == 0xff00
+ }
+ pub const fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
+ match self.octets() {
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
+ Some(Ipv4Addr::new(a, b, c, d))
+ }
+ _ => None,
+ }
+ }
+ pub const fn to_ipv4(&self) -> Option<Ipv4Addr> {
+ if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() {
+ let [a, b] = ab.to_be_bytes();
+ let [c, d] = cd.to_be_bytes();
+ Some(Ipv4Addr::new(a, b, c, d))
+ } else {
+ None
+ }
+ }
+ pub const fn to_canonical(&self) -> IpAddr {
+ if let Some(mapped) = self.to_ipv4_mapped() {
+ return IpAddr::V4(mapped);
+ }
+ IpAddr::V6(*self)
+ }
+ pub const fn octets(&self) -> [u8; 16] {
+ self.inner.s6_addr
+ }
+}
+impl fmt::Display for Ipv6Addr {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ if f.precision().is_none() && f.width().is_none() {
+ let segments = self.segments();
+ if self.is_unspecified() {
+ f.write_str("::")
+ } else if self.is_loopback() {
+ f.write_str("::1")
+ } else if let Some(ipv4) = self.to_ipv4() {
+ match segments[5] {
+ 0 => write!(f, "::{}", ipv4),
+ 0xffff => write!(f, "::ffff:{}", ipv4),
+ _ => unreachable!(),
+ }
+ } else { # [derive (Copy , Clone , Default)] struct Span { start : usize , len : usize , } let zeroes = { let mut longest = Span :: default () ; let mut current = Span :: default () ; for (i , & segment) in segments . iter () . enumerate () { if segment == 0 { if current . len == 0 { current . start = i ; } current . len += 1 ; if current . len > longest . len { longest = current ; } } else { current = Span :: default () ; } } longest } ; # [doc = " Write a colon-separated part of the address"] # [inline] fn fmt_subslice (f : & mut fmt :: Formatter < '_ > , chunk : & [u16]) -> fmt :: Result { if let Some ((first , tail)) = chunk . split_first () { write ! (f , "{:x}" , first) ? ; for segment in tail { f . write_char (':') ? ; write ! (f , "{:x}" , segment) ? ; } } Ok (()) } if zeroes . len > 1 { fmt_subslice (f , & segments [.. zeroes . start]) ? ; f . write_str ("::") ? ; fmt_subslice (f , & segments [zeroes . start + zeroes . len ..]) } else { fmt_subslice (f , & segments) } }
+ } else {
+ const IPV6_BUF_LEN: usize = (4 * 8) + 7;
+ let mut buf = [0u8; IPV6_BUF_LEN];
+ let mut buf_slice = &mut buf[..];
+ write!(buf_slice, "{}", self).unwrap();
+ let len = IPV6_BUF_LEN - buf_slice.len();
+ let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
+ f.pad(buf)
+ }
+ }
+}
+impl fmt::Debug for Ipv6Addr {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(self, fmt)
+ }
+}
+impl Clone for Ipv6Addr {
+ fn clone(&self) -> Ipv6Addr {
+ *self
+ }
+}
+impl PartialEq for Ipv6Addr {
+ fn eq(&self, other: &Ipv6Addr) -> bool {
+ self.inner.s6_addr == other.inner.s6_addr
+ }
+}
+impl PartialEq<IpAddr> for Ipv6Addr {
+ fn eq(&self, other: &IpAddr) -> bool {
+ match other {
+ IpAddr::V4(_) => false,
+ IpAddr::V6(v6) => self == v6,
+ }
+ }
+}
+impl PartialEq<Ipv6Addr> for IpAddr {
+ fn eq(&self, other: &Ipv6Addr) -> bool {
+ match self {
+ IpAddr::V4(_) => false,
+ IpAddr::V6(v6) => v6 == other,
+ }
+ }
+}
+impl Eq for Ipv6Addr {}
+impl hash::Hash for Ipv6Addr {
+ fn hash<H: hash::Hasher>(&self, s: &mut H) {
+ self.inner.s6_addr.hash(s)
+ }
+}
+impl PartialOrd for Ipv6Addr {
+ fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+impl PartialOrd<Ipv6Addr> for IpAddr {
+ fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
+ match self {
+ IpAddr::V4(_) => Some(Ordering::Less),
+ IpAddr::V6(v6) => v6.partial_cmp(other),
+ }
+ }
+}
+impl PartialOrd<IpAddr> for Ipv6Addr {
+ fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
+ match other {
+ IpAddr::V4(_) => Some(Ordering::Greater),
+ IpAddr::V6(v6) => self.partial_cmp(v6),
+ }
+ }
+}
+impl Ord for Ipv6Addr {
+ fn cmp(&self, other: &Ipv6Addr) -> Ordering {
+ self.segments().cmp(&other.segments())
+ }
+}
+impl AsInner<c::in6_addr> for Ipv6Addr {
+ fn as_inner(&self) -> &c::in6_addr {
+ &self.inner
+ }
+}
+impl FromInner<c::in6_addr> for Ipv6Addr {
+ fn from_inner(addr: c::in6_addr) -> Ipv6Addr {
+ Ipv6Addr { inner: addr }
+ }
+}
+impl From<Ipv6Addr> for u128 {
+ fn from(ip: Ipv6Addr) -> u128 {
+ let ip = ip.octets();
+ u128::from_be_bytes(ip)
+ }
+}
+impl From<u128> for Ipv6Addr {
+ fn from(ip: u128) -> Ipv6Addr {
+ Ipv6Addr::from(ip.to_be_bytes())
+ }
+}
+impl From<[u8; 16]> for Ipv6Addr {
+ fn from(octets: [u8; 16]) -> Ipv6Addr {
+ let inner = c::in6_addr { s6_addr: octets };
+ Ipv6Addr::from_inner(inner)
+ }
+}
+impl From<[u16; 8]> for Ipv6Addr {
+ fn from(segments: [u16; 8]) -> Ipv6Addr {
+ let [a, b, c, d, e, f, g, h] = segments;
+ Ipv6Addr::new(a, b, c, d, e, f, g, h)
+ }
+}
+impl From<[u8; 16]> for IpAddr {
+ fn from(octets: [u8; 16]) -> IpAddr {
+ IpAddr::V6(Ipv6Addr::from(octets))
+ }
+}
+impl From<[u16; 8]> for IpAddr {
+ fn from(segments: [u16; 8]) -> IpAddr {
+ IpAddr::V6(Ipv6Addr::from(segments))
+ }
+}
diff --git a/vendor/prettyplease/src/algorithm.rs b/vendor/prettyplease/src/algorithm.rs
new file mode 100644
index 00000000..482b3ad7
--- /dev/null
+++ b/vendor/prettyplease/src/algorithm.rs
@@ -0,0 +1,386 @@
+// Adapted from https://github.com/rust-lang/rust/blob/1.57.0/compiler/rustc_ast_pretty/src/pp.rs.
+// See "Algorithm notes" in the crate-level rustdoc.
+
+use crate::ring::RingBuffer;
+use crate::{MARGIN, MIN_SPACE};
+use std::borrow::Cow;
+use std::cmp;
+use std::collections::VecDeque;
+use std::iter;
+
+#[derive(Clone, Copy, PartialEq)]
+pub enum Breaks {
+ Consistent,
+ Inconsistent,
+}
+
+#[derive(Clone, Copy, Default)]
+pub struct BreakToken {
+ pub offset: isize,
+ pub blank_space: usize,
+ pub pre_break: Option<char>,
+ pub post_break: &'static str,
+ pub no_break: Option<char>,
+ pub if_nonempty: bool,
+ pub never_break: bool,
+}
+
+#[derive(Clone, Copy)]
+pub struct BeginToken {
+ pub offset: isize,
+ pub breaks: Breaks,
+}
+
+#[derive(Clone)]
+pub enum Token {
+ String(Cow<'static, str>),
+ Break(BreakToken),
+ Begin(BeginToken),
+ End,
+}
+
+#[derive(Copy, Clone)]
+enum PrintFrame {
+ Fits(Breaks),
+ Broken(usize, Breaks),
+}
+
+pub const SIZE_INFINITY: isize = 0xffff;
+
+pub struct Printer {
+ out: String,
+ // Number of spaces left on line
+ space: isize,
+ // Ring-buffer of tokens and calculated sizes
+ buf: RingBuffer<BufEntry>,
+ // Total size of tokens already printed
+ left_total: isize,
+ // Total size of tokens enqueued, including printed and not yet printed
+ right_total: isize,
+ // Holds the ring-buffer index of the Begin that started the current block,
+ // possibly with the most recent Break after that Begin (if there is any) on
+ // top of it. Values are pushed and popped on the back of the queue using it
+ // like stack, and elsewhere old values are popped from the front of the
+ // queue as they become irrelevant due to the primary ring-buffer advancing.
+ scan_stack: VecDeque<usize>,
+ // Stack of blocks-in-progress being flushed by print
+ print_stack: Vec<PrintFrame>,
+ // Level of indentation of current line
+ indent: usize,
+ // Buffered indentation to avoid writing trailing whitespace
+ pending_indentation: usize,
+}
+
+#[derive(Clone)]
+struct BufEntry {
+ token: Token,
+ size: isize,
+}
+
+impl Printer {
+ pub fn new() -> Self {
+ Printer {
+ out: String::new(),
+ space: MARGIN,
+ buf: RingBuffer::new(),
+ left_total: 0,
+ right_total: 0,
+ scan_stack: VecDeque::new(),
+ print_stack: Vec::new(),
+ indent: 0,
+ pending_indentation: 0,
+ }
+ }
+
+ pub fn eof(mut self) -> String {
+ if !self.scan_stack.is_empty() {
+ self.check_stack(0);
+ self.advance_left();
+ }
+ self.out
+ }
+
+ pub fn scan_begin(&mut self, token: BeginToken) {
+ if self.scan_stack.is_empty() {
+ self.left_total = 1;
+ self.right_total = 1;
+ self.buf.clear();
+ }
+ let right = self.buf.push(BufEntry {
+ token: Token::Begin(token),
+ size: -self.right_total,
+ });
+ self.scan_stack.push_back(right);
+ }
+
+ pub fn scan_end(&mut self) {
+ if self.scan_stack.is_empty() {
+ self.print_end();
+ } else {
+ if !self.buf.is_empty() {
+ if let Token::Break(break_token) = self.buf.last().token {
+ if self.buf.len() >= 2 {
+ if let Token::Begin(_) = self.buf.second_last().token {
+ self.buf.pop_last();
+ self.buf.pop_last();
+ self.scan_stack.pop_back();
+ self.scan_stack.pop_back();
+ self.right_total -= break_token.blank_space as isize;
+ return;
+ }
+ }
+ if break_token.if_nonempty {
+ self.buf.pop_last();
+ self.scan_stack.pop_back();
+ self.right_total -= break_token.blank_space as isize;
+ }
+ }
+ }
+ let right = self.buf.push(BufEntry {
+ token: Token::End,
+ size: -1,
+ });
+ self.scan_stack.push_back(right);
+ }
+ }
+
+ pub fn scan_break(&mut self, token: BreakToken) {
+ if self.scan_stack.is_empty() {
+ self.left_total = 1;
+ self.right_total = 1;
+ self.buf.clear();
+ } else {
+ self.check_stack(0);
+ }
+ let right = self.buf.push(BufEntry {
+ token: Token::Break(token),
+ size: -self.right_total,
+ });
+ self.scan_stack.push_back(right);
+ self.right_total += token.blank_space as isize;
+ }
+
+ pub fn scan_string(&mut self, string: Cow<'static, str>) {
+ if self.scan_stack.is_empty() {
+ self.print_string(string);
+ } else {
+ let len = string.len() as isize;
+ self.buf.push(BufEntry {
+ token: Token::String(string),
+ size: len,
+ });
+ self.right_total += len;
+ self.check_stream();
+ }
+ }
+
+ #[track_caller]
+ pub fn offset(&mut self, offset: isize) {
+ match &mut self.buf.last_mut().token {
+ Token::Break(token) => token.offset += offset,
+ Token::Begin(_) => {}
+ Token::String(_) | Token::End => unreachable!(),
+ }
+ }
+
+ pub fn end_with_max_width(&mut self, max: isize) {
+ let mut depth = 1;
+ for &index in self.scan_stack.iter().rev() {
+ let entry = &self.buf[index];
+ match entry.token {
+ Token::Begin(_) => {
+ depth -= 1;
+ if depth == 0 {
+ if entry.size < 0 {
+ let actual_width = entry.size + self.right_total;
+ if actual_width > max {
+ self.buf.push(BufEntry {
+ token: Token::String(Cow::Borrowed("")),
+ size: SIZE_INFINITY,
+ });
+ self.right_total += SIZE_INFINITY;
+ }
+ }
+ break;
+ }
+ }
+ Token::End => depth += 1,
+ Token::Break(_) => {}
+ Token::String(_) => unreachable!(),
+ }
+ }
+ self.scan_end();
+ }
+
+ pub fn ends_with(&self, ch: char) -> bool {
+ for i in self.buf.index_range().rev() {
+ if let Token::String(token) = &self.buf[i].token {
+ return token.ends_with(ch);
+ }
+ }
+ self.out.ends_with(ch)
+ }
+
+ fn check_stream(&mut self) {
+ while self.right_total - self.left_total > self.space {
+ if *self.scan_stack.front().unwrap() == self.buf.index_range().start {
+ self.scan_stack.pop_front().unwrap();
+ self.buf.first_mut().size = SIZE_INFINITY;
+ }
+
+ self.advance_left();
+
+ if self.buf.is_empty() {
+ break;
+ }
+ }
+ }
+
+ fn advance_left(&mut self) {
+ while self.buf.first().size >= 0 {
+ let left = self.buf.pop_first();
+
+ match left.token {
+ Token::String(string) => {
+ self.left_total += left.size;
+ self.print_string(string);
+ }
+ Token::Break(token) => {
+ self.left_total += token.blank_space as isize;
+ self.print_break(token, left.size);
+ }
+ Token::Begin(token) => self.print_begin(token, left.size),
+ Token::End => self.print_end(),
+ }
+
+ if self.buf.is_empty() {
+ break;
+ }
+ }
+ }
+
+ fn check_stack(&mut self, mut depth: usize) {
+ while let Some(&index) = self.scan_stack.back() {
+ let entry = &mut self.buf[index];
+ match entry.token {
+ Token::Begin(_) => {
+ if depth == 0 {
+ break;
+ }
+ self.scan_stack.pop_back().unwrap();
+ entry.size += self.right_total;
+ depth -= 1;
+ }
+ Token::End => {
+ self.scan_stack.pop_back().unwrap();
+ entry.size = 1;
+ depth += 1;
+ }
+ Token::Break(_) => {
+ self.scan_stack.pop_back().unwrap();
+ entry.size += self.right_total;
+ if depth == 0 {
+ break;
+ }
+ }
+ Token::String(_) => unreachable!(),
+ }
+ }
+ }
+
+ fn get_top(&self) -> PrintFrame {
+ const OUTER: PrintFrame = PrintFrame::Broken(0, Breaks::Inconsistent);
+ self.print_stack.last().map_or(OUTER, PrintFrame::clone)
+ }
+
+ fn print_begin(&mut self, token: BeginToken, size: isize) {
+ if cfg!(prettyplease_debug) {
+ self.out.push(match token.breaks {
+ Breaks::Consistent => '«',
+ Breaks::Inconsistent => '‹',
+ });
+ if cfg!(prettyplease_debug_indent) {
+ self.out
+ .extend(token.offset.to_string().chars().map(|ch| match ch {
+ '0'..='9' => ['₀', '₁', '₂', '₃', '₄', '₅', '₆', '₇', '₈', '₉']
+ [(ch as u8 - b'0') as usize],
+ '-' => '₋',
+ _ => unreachable!(),
+ }));
+ }
+ }
+ if size > self.space {
+ self.print_stack
+ .push(PrintFrame::Broken(self.indent, token.breaks));
+ self.indent = usize::try_from(self.indent as isize + token.offset).unwrap();
+ } else {
+ self.print_stack.push(PrintFrame::Fits(token.breaks));
+ }
+ }
+
+ fn print_end(&mut self) {
+ let breaks = match self.print_stack.pop().unwrap() {
+ PrintFrame::Broken(indent, breaks) => {
+ self.indent = indent;
+ breaks
+ }
+ PrintFrame::Fits(breaks) => breaks,
+ };
+ if cfg!(prettyplease_debug) {
+ self.out.push(match breaks {
+ Breaks::Consistent => '»',
+ Breaks::Inconsistent => '›',
+ });
+ }
+ }
+
+ fn print_break(&mut self, token: BreakToken, size: isize) {
+ let fits = token.never_break
+ || match self.get_top() {
+ PrintFrame::Fits(..) => true,
+ PrintFrame::Broken(.., Breaks::Consistent) => false,
+ PrintFrame::Broken(.., Breaks::Inconsistent) => size <= self.space,
+ };
+ if fits {
+ self.pending_indentation += token.blank_space;
+ self.space -= token.blank_space as isize;
+ if let Some(no_break) = token.no_break {
+ self.out.push(no_break);
+ self.space -= no_break.len_utf8() as isize;
+ }
+ if cfg!(prettyplease_debug) {
+ self.out.push('·');
+ }
+ } else {
+ if let Some(pre_break) = token.pre_break {
+ self.print_indent();
+ self.out.push(pre_break);
+ }
+ if cfg!(prettyplease_debug) {
+ self.out.push('·');
+ }
+ self.out.push('\n');
+ let indent = self.indent as isize + token.offset;
+ self.pending_indentation = usize::try_from(indent).unwrap();
+ self.space = cmp::max(MARGIN - indent, MIN_SPACE);
+ if !token.post_break.is_empty() {
+ self.print_indent();
+ self.out.push_str(token.post_break);
+ self.space -= token.post_break.len() as isize;
+ }
+ }
+ }
+
+ fn print_string(&mut self, string: Cow<'static, str>) {
+ self.print_indent();
+ self.out.push_str(&string);
+ self.space -= string.len() as isize;
+ }
+
+ fn print_indent(&mut self) {
+ self.out.reserve(self.pending_indentation);
+ self.out
+ .extend(iter::repeat(' ').take(self.pending_indentation));
+ self.pending_indentation = 0;
+ }
+}
diff --git a/vendor/prettyplease/src/attr.rs b/vendor/prettyplease/src/attr.rs
new file mode 100644
index 00000000..b436283f
--- /dev/null
+++ b/vendor/prettyplease/src/attr.rs
@@ -0,0 +1,288 @@
+use crate::algorithm::Printer;
+use crate::fixup::FixupContext;
+use crate::path::PathKind;
+use crate::INDENT;
+use proc_macro2::{Delimiter, Group, TokenStream, TokenTree};
+use syn::{AttrStyle, Attribute, Expr, Lit, MacroDelimiter, Meta, MetaList, MetaNameValue};
+
+impl Printer {
+ pub fn outer_attrs(&mut self, attrs: &[Attribute]) {
+ for attr in attrs {
+ if let AttrStyle::Outer = attr.style {
+ self.attr(attr);
+ }
+ }
+ }
+
+ pub fn inner_attrs(&mut self, attrs: &[Attribute]) {
+ for attr in attrs {
+ if let AttrStyle::Inner(_) = attr.style {
+ self.attr(attr);
+ }
+ }
+ }
+
+ fn attr(&mut self, attr: &Attribute) {
+ if let Some(mut doc) = value_of_attribute("doc", attr) {
+ if !doc.contains('\n')
+ && match attr.style {
+ AttrStyle::Outer => !doc.starts_with('/'),
+ AttrStyle::Inner(_) => true,
+ }
+ {
+ trim_trailing_spaces(&mut doc);
+ self.word(match attr.style {
+ AttrStyle::Outer => "///",
+ AttrStyle::Inner(_) => "//!",
+ });
+ self.word(doc);
+ self.hardbreak();
+ return;
+ } else if can_be_block_comment(&doc)
+ && match attr.style {
+ AttrStyle::Outer => !doc.starts_with(&['*', '/'][..]),
+ AttrStyle::Inner(_) => true,
+ }
+ {
+ trim_interior_trailing_spaces(&mut doc);
+ self.word(match attr.style {
+ AttrStyle::Outer => "/**",
+ AttrStyle::Inner(_) => "/*!",
+ });
+ self.word(doc);
+ self.word("*/");
+ self.hardbreak();
+ return;
+ }
+ } else if let Some(mut comment) = value_of_attribute("comment", attr) {
+ if !comment.contains('\n') {
+ trim_trailing_spaces(&mut comment);
+ self.word("//");
+ self.word(comment);
+ self.hardbreak();
+ return;
+ } else if can_be_block_comment(&comment) && !comment.starts_with(&['*', '!'][..]) {
+ trim_interior_trailing_spaces(&mut comment);
+ self.word("/*");
+ self.word(comment);
+ self.word("*/");
+ self.hardbreak();
+ return;
+ }
+ }
+
+ self.word(match attr.style {
+ AttrStyle::Outer => "#",
+ AttrStyle::Inner(_) => "#!",
+ });
+ self.word("[");
+ self.meta(&attr.meta);
+ self.word("]");
+ self.space();
+ }
+
+ fn meta(&mut self, meta: &Meta) {
+ match meta {
+ Meta::Path(path) => self.path(path, PathKind::Simple),
+ Meta::List(meta) => self.meta_list(meta),
+ Meta::NameValue(meta) => self.meta_name_value(meta),
+ }
+ }
+
+ fn meta_list(&mut self, meta: &MetaList) {
+ self.path(&meta.path, PathKind::Simple);
+ let delimiter = match meta.delimiter {
+ MacroDelimiter::Paren(_) => Delimiter::Parenthesis,
+ MacroDelimiter::Brace(_) => Delimiter::Brace,
+ MacroDelimiter::Bracket(_) => Delimiter::Bracket,
+ };
+ let group = Group::new(delimiter, meta.tokens.clone());
+ self.attr_tokens(TokenStream::from(TokenTree::Group(group)));
+ }
+
+ fn meta_name_value(&mut self, meta: &MetaNameValue) {
+ self.path(&meta.path, PathKind::Simple);
+ self.word(" = ");
+ self.expr(&meta.value, FixupContext::NONE);
+ }
+
+ fn attr_tokens(&mut self, tokens: TokenStream) {
+ let mut stack = Vec::new();
+ stack.push((tokens.into_iter().peekable(), Delimiter::None));
+ let mut space = Self::nbsp as fn(&mut Self);
+
+ #[derive(PartialEq)]
+ enum State {
+ Word,
+ Punct,
+ TrailingComma,
+ }
+
+ use State::*;
+ let mut state = Word;
+
+ while let Some((tokens, delimiter)) = stack.last_mut() {
+ match tokens.next() {
+ Some(TokenTree::Ident(ident)) => {
+ if let Word = state {
+ space(self);
+ }
+ self.ident(&ident);
+ state = Word;
+ }
+ Some(TokenTree::Punct(punct)) => {
+ let ch = punct.as_char();
+ if let (Word, '=') = (state, ch) {
+ self.nbsp();
+ }
+ if ch == ',' && tokens.peek().is_none() {
+ self.trailing_comma(true);
+ state = TrailingComma;
+ } else {
+ self.token_punct(ch);
+ if ch == '=' {
+ self.nbsp();
+ } else if ch == ',' {
+ space(self);
+ }
+ state = Punct;
+ }
+ }
+ Some(TokenTree::Literal(literal)) => {
+ if let Word = state {
+ space(self);
+ }
+ self.token_literal(&literal);
+ state = Word;
+ }
+ Some(TokenTree::Group(group)) => {
+ let delimiter = group.delimiter();
+ let stream = group.stream();
+ match delimiter {
+ Delimiter::Parenthesis => {
+ self.word("(");
+ self.cbox(INDENT);
+ self.zerobreak();
+ state = Punct;
+ }
+ Delimiter::Brace => {
+ self.word("{");
+ state = Punct;
+ }
+ Delimiter::Bracket => {
+ self.word("[");
+ state = Punct;
+ }
+ Delimiter::None => {}
+ }
+ stack.push((stream.into_iter().peekable(), delimiter));
+ space = Self::space;
+ }
+ None => {
+ match delimiter {
+ Delimiter::Parenthesis => {
+ if state != TrailingComma {
+ self.zerobreak();
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word(")");
+ state = Punct;
+ }
+ Delimiter::Brace => {
+ self.word("}");
+ state = Punct;
+ }
+ Delimiter::Bracket => {
+ self.word("]");
+ state = Punct;
+ }
+ Delimiter::None => {}
+ }
+ stack.pop();
+ if stack.is_empty() {
+ space = Self::nbsp;
+ }
+ }
+ }
+ }
+ }
+}
+
+fn value_of_attribute(requested: &str, attr: &Attribute) -> Option<String> {
+ let value = match &attr.meta {
+ Meta::NameValue(meta) if meta.path.is_ident(requested) => &meta.value,
+ _ => return None,
+ };
+ let lit = match value {
+ Expr::Lit(expr) if expr.attrs.is_empty() => &expr.lit,
+ _ => return None,
+ };
+ match lit {
+ Lit::Str(string) => Some(string.value()),
+ _ => None,
+ }
+}
+
+pub fn has_outer(attrs: &[Attribute]) -> bool {
+ for attr in attrs {
+ if let AttrStyle::Outer = attr.style {
+ return true;
+ }
+ }
+ false
+}
+
+pub fn has_inner(attrs: &[Attribute]) -> bool {
+ for attr in attrs {
+ if let AttrStyle::Inner(_) = attr.style {
+ return true;
+ }
+ }
+ false
+}
+
+fn trim_trailing_spaces(doc: &mut String) {
+ doc.truncate(doc.trim_end_matches(' ').len());
+}
+
+fn trim_interior_trailing_spaces(doc: &mut String) {
+ if !doc.contains(" \n") {
+ return;
+ }
+ let mut trimmed = String::with_capacity(doc.len());
+ let mut lines = doc.split('\n').peekable();
+ while let Some(line) = lines.next() {
+ if lines.peek().is_some() {
+ trimmed.push_str(line.trim_end_matches(' '));
+ trimmed.push('\n');
+ } else {
+ trimmed.push_str(line);
+ }
+ }
+ *doc = trimmed;
+}
+
+fn can_be_block_comment(value: &str) -> bool {
+ let mut depth = 0usize;
+ let bytes = value.as_bytes();
+ let mut i = 0usize;
+ let upper = bytes.len() - 1;
+
+ while i < upper {
+ if bytes[i] == b'/' && bytes[i + 1] == b'*' {
+ depth += 1;
+ i += 2;
+ } else if bytes[i] == b'*' && bytes[i + 1] == b'/' {
+ if depth == 0 {
+ return false;
+ }
+ depth -= 1;
+ i += 2;
+ } else {
+ i += 1;
+ }
+ }
+
+ depth == 0 && !value.ends_with('/')
+}
diff --git a/vendor/prettyplease/src/classify.rs b/vendor/prettyplease/src/classify.rs
new file mode 100644
index 00000000..17648f6c
--- /dev/null
+++ b/vendor/prettyplease/src/classify.rs
@@ -0,0 +1,324 @@
+use proc_macro2::{Delimiter, TokenStream, TokenTree};
+use std::ops::ControlFlow;
+use syn::punctuated::Punctuated;
+use syn::{Expr, MacroDelimiter, Path, PathArguments, ReturnType, Token, Type, TypeParamBound};
+
+pub(crate) fn requires_semi_to_be_stmt(expr: &Expr) -> bool {
+ match expr {
+ Expr::Macro(expr) => !matches!(expr.mac.delimiter, MacroDelimiter::Brace(_)),
+ _ => requires_comma_to_be_match_arm(expr),
+ }
+}
+
+pub(crate) fn requires_comma_to_be_match_arm(mut expr: &Expr) -> bool {
+ loop {
+ match expr {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ Expr::If(_)
+ | Expr::Match(_)
+ | Expr::Block(_) | Expr::Unsafe(_) // both under ExprKind::Block in rustc
+ | Expr::While(_)
+ | Expr::Loop(_)
+ | Expr::ForLoop(_)
+ | Expr::TryBlock(_)
+ | Expr::Const(_) => return false,
+
+ Expr::Array(_)
+ | Expr::Assign(_)
+ | Expr::Async(_)
+ | Expr::Await(_)
+ | Expr::Binary(_)
+ | Expr::Break(_)
+ | Expr::Call(_)
+ | Expr::Cast(_)
+ | Expr::Closure(_)
+ | Expr::Continue(_)
+ | Expr::Field(_)
+ | Expr::Index(_)
+ | Expr::Infer(_)
+ | Expr::Let(_)
+ | Expr::Lit(_)
+ | Expr::Macro(_)
+ | Expr::MethodCall(_)
+ | Expr::Paren(_)
+ | Expr::Path(_)
+ | Expr::Range(_)
+ | Expr::RawAddr(_)
+ | Expr::Reference(_)
+ | Expr::Repeat(_)
+ | Expr::Return(_)
+ | Expr::Struct(_)
+ | Expr::Try(_)
+ | Expr::Tuple(_)
+ | Expr::Unary(_)
+ | Expr::Yield(_)
+ | Expr::Verbatim(_) => return true,
+
+ Expr::Group(group) => expr = &group.expr,
+
+ _ => return true,
+ }
+ }
+}
+
+pub(crate) fn trailing_unparameterized_path(mut ty: &Type) -> bool {
+ loop {
+ match ty {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ Type::BareFn(t) => match &t.output {
+ ReturnType::Default => return false,
+ ReturnType::Type(_, ret) => ty = ret,
+ },
+ Type::ImplTrait(t) => match last_type_in_bounds(&t.bounds) {
+ ControlFlow::Break(trailing_path) => return trailing_path,
+ ControlFlow::Continue(t) => ty = t,
+ },
+ Type::Path(t) => match last_type_in_path(&t.path) {
+ ControlFlow::Break(trailing_path) => return trailing_path,
+ ControlFlow::Continue(t) => ty = t,
+ },
+ Type::Ptr(t) => ty = &t.elem,
+ Type::Reference(t) => ty = &t.elem,
+ Type::TraitObject(t) => match last_type_in_bounds(&t.bounds) {
+ ControlFlow::Break(trailing_path) => return trailing_path,
+ ControlFlow::Continue(t) => ty = t,
+ },
+
+ Type::Array(_)
+ | Type::Group(_)
+ | Type::Infer(_)
+ | Type::Macro(_)
+ | Type::Never(_)
+ | Type::Paren(_)
+ | Type::Slice(_)
+ | Type::Tuple(_)
+ | Type::Verbatim(_) => return false,
+
+ _ => return false,
+ }
+ }
+
+ fn last_type_in_path(path: &Path) -> ControlFlow<bool, &Type> {
+ match &path.segments.last().unwrap().arguments {
+ PathArguments::None => ControlFlow::Break(true),
+ PathArguments::AngleBracketed(_) => ControlFlow::Break(false),
+ PathArguments::Parenthesized(arg) => match &arg.output {
+ ReturnType::Default => ControlFlow::Break(false),
+ ReturnType::Type(_, ret) => ControlFlow::Continue(ret),
+ },
+ }
+ }
+
+ fn last_type_in_bounds(
+ bounds: &Punctuated<TypeParamBound, Token![+]>,
+ ) -> ControlFlow<bool, &Type> {
+ match bounds.last().unwrap() {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ TypeParamBound::Trait(t) => last_type_in_path(&t.path),
+ TypeParamBound::Lifetime(_)
+ | TypeParamBound::PreciseCapture(_)
+ | TypeParamBound::Verbatim(_) => ControlFlow::Break(false),
+ _ => ControlFlow::Break(false),
+ }
+ }
+}
+
+/// Whether the expression's first token is the label of a loop/block.
+pub(crate) fn expr_leading_label(mut expr: &Expr) -> bool {
+ loop {
+ match expr {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ Expr::Block(e) => return e.label.is_some(),
+ Expr::ForLoop(e) => return e.label.is_some(),
+ Expr::Loop(e) => return e.label.is_some(),
+ Expr::While(e) => return e.label.is_some(),
+
+ Expr::Assign(e) => expr = &e.left,
+ Expr::Await(e) => expr = &e.base,
+ Expr::Binary(e) => expr = &e.left,
+ Expr::Call(e) => expr = &e.func,
+ Expr::Cast(e) => expr = &e.expr,
+ Expr::Field(e) => expr = &e.base,
+ Expr::Index(e) => expr = &e.expr,
+ Expr::MethodCall(e) => expr = &e.receiver,
+ Expr::Range(e) => match &e.start {
+ Some(start) => expr = start,
+ None => return false,
+ },
+ Expr::Try(e) => expr = &e.expr,
+
+ Expr::Array(_)
+ | Expr::Async(_)
+ | Expr::Break(_)
+ | Expr::Closure(_)
+ | Expr::Const(_)
+ | Expr::Continue(_)
+ | Expr::If(_)
+ | Expr::Infer(_)
+ | Expr::Let(_)
+ | Expr::Lit(_)
+ | Expr::Macro(_)
+ | Expr::Match(_)
+ | Expr::Paren(_)
+ | Expr::Path(_)
+ | Expr::RawAddr(_)
+ | Expr::Reference(_)
+ | Expr::Repeat(_)
+ | Expr::Return(_)
+ | Expr::Struct(_)
+ | Expr::TryBlock(_)
+ | Expr::Tuple(_)
+ | Expr::Unary(_)
+ | Expr::Unsafe(_)
+ | Expr::Verbatim(_)
+ | Expr::Yield(_) => return false,
+
+ Expr::Group(e) => {
+ if !e.attrs.is_empty() {
+ return false;
+ }
+ expr = &e.expr;
+ }
+
+ _ => return false,
+ }
+ }
+}
+
+/// Whether the expression's last token is `}`.
+pub(crate) fn expr_trailing_brace(mut expr: &Expr) -> bool {
+ loop {
+ match expr {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ Expr::Async(_)
+ | Expr::Block(_)
+ | Expr::Const(_)
+ | Expr::ForLoop(_)
+ | Expr::If(_)
+ | Expr::Loop(_)
+ | Expr::Match(_)
+ | Expr::Struct(_)
+ | Expr::TryBlock(_)
+ | Expr::Unsafe(_)
+ | Expr::While(_) => return true,
+
+ Expr::Assign(e) => expr = &e.right,
+ Expr::Binary(e) => expr = &e.right,
+ Expr::Break(e) => match &e.expr {
+ Some(e) => expr = e,
+ None => return false,
+ },
+ Expr::Cast(e) => return type_trailing_brace(&e.ty),
+ Expr::Closure(e) => expr = &e.body,
+ Expr::Group(e) => expr = &e.expr,
+ Expr::Let(e) => expr = &e.expr,
+ Expr::Macro(e) => return matches!(e.mac.delimiter, MacroDelimiter::Brace(_)),
+ Expr::Range(e) => match &e.end {
+ Some(end) => expr = end,
+ None => return false,
+ },
+ Expr::RawAddr(e) => expr = &e.expr,
+ Expr::Reference(e) => expr = &e.expr,
+ Expr::Return(e) => match &e.expr {
+ Some(e) => expr = e,
+ None => return false,
+ },
+ Expr::Unary(e) => expr = &e.expr,
+ Expr::Verbatim(e) => return tokens_trailing_brace(e),
+ Expr::Yield(e) => match &e.expr {
+ Some(e) => expr = e,
+ None => return false,
+ },
+
+ Expr::Array(_)
+ | Expr::Await(_)
+ | Expr::Call(_)
+ | Expr::Continue(_)
+ | Expr::Field(_)
+ | Expr::Index(_)
+ | Expr::Infer(_)
+ | Expr::Lit(_)
+ | Expr::MethodCall(_)
+ | Expr::Paren(_)
+ | Expr::Path(_)
+ | Expr::Repeat(_)
+ | Expr::Try(_)
+ | Expr::Tuple(_) => return false,
+
+ _ => return false,
+ }
+ }
+
+ fn type_trailing_brace(mut ty: &Type) -> bool {
+ loop {
+ match ty {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ Type::BareFn(t) => match &t.output {
+ ReturnType::Default => return false,
+ ReturnType::Type(_, ret) => ty = ret,
+ },
+ Type::ImplTrait(t) => match last_type_in_bounds(&t.bounds) {
+ ControlFlow::Break(trailing_brace) => return trailing_brace,
+ ControlFlow::Continue(t) => ty = t,
+ },
+ Type::Macro(t) => return matches!(t.mac.delimiter, MacroDelimiter::Brace(_)),
+ Type::Path(t) => match last_type_in_path(&t.path) {
+ Some(t) => ty = t,
+ None => return false,
+ },
+ Type::Ptr(t) => ty = &t.elem,
+ Type::Reference(t) => ty = &t.elem,
+ Type::TraitObject(t) => match last_type_in_bounds(&t.bounds) {
+ ControlFlow::Break(trailing_brace) => return trailing_brace,
+ ControlFlow::Continue(t) => ty = t,
+ },
+ Type::Verbatim(t) => return tokens_trailing_brace(t),
+
+ Type::Array(_)
+ | Type::Group(_)
+ | Type::Infer(_)
+ | Type::Never(_)
+ | Type::Paren(_)
+ | Type::Slice(_)
+ | Type::Tuple(_) => return false,
+
+ _ => return false,
+ }
+ }
+ }
+
+ fn last_type_in_path(path: &Path) -> Option<&Type> {
+ match &path.segments.last().unwrap().arguments {
+ PathArguments::None | PathArguments::AngleBracketed(_) => None,
+ PathArguments::Parenthesized(arg) => match &arg.output {
+ ReturnType::Default => None,
+ ReturnType::Type(_, ret) => Some(ret),
+ },
+ }
+ }
+
+ fn last_type_in_bounds(
+ bounds: &Punctuated<TypeParamBound, Token![+]>,
+ ) -> ControlFlow<bool, &Type> {
+ match bounds.last().unwrap() {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ TypeParamBound::Trait(t) => match last_type_in_path(&t.path) {
+ Some(t) => ControlFlow::Continue(t),
+ None => ControlFlow::Break(false),
+ },
+ TypeParamBound::Lifetime(_) | TypeParamBound::PreciseCapture(_) => {
+ ControlFlow::Break(false)
+ }
+ TypeParamBound::Verbatim(t) => ControlFlow::Break(tokens_trailing_brace(t)),
+ _ => ControlFlow::Break(false),
+ }
+ }
+
+ fn tokens_trailing_brace(tokens: &TokenStream) -> bool {
+ if let Some(TokenTree::Group(last)) = tokens.clone().into_iter().last() {
+ last.delimiter() == Delimiter::Brace
+ } else {
+ false
+ }
+ }
+}
diff --git a/vendor/prettyplease/src/convenience.rs b/vendor/prettyplease/src/convenience.rs
new file mode 100644
index 00000000..bc4add6e
--- /dev/null
+++ b/vendor/prettyplease/src/convenience.rs
@@ -0,0 +1,98 @@
+use crate::algorithm::{self, BeginToken, BreakToken, Breaks, Printer};
+use std::borrow::Cow;
+
+impl Printer {
+ pub fn ibox(&mut self, indent: isize) {
+ self.scan_begin(BeginToken {
+ offset: indent,
+ breaks: Breaks::Inconsistent,
+ });
+ }
+
+ pub fn cbox(&mut self, indent: isize) {
+ self.scan_begin(BeginToken {
+ offset: indent,
+ breaks: Breaks::Consistent,
+ });
+ }
+
+ pub fn end(&mut self) {
+ self.scan_end();
+ }
+
+ pub fn word<S: Into<Cow<'static, str>>>(&mut self, wrd: S) {
+ let s = wrd.into();
+ self.scan_string(s);
+ }
+
+ fn spaces(&mut self, n: usize) {
+ self.scan_break(BreakToken {
+ blank_space: n,
+ ..BreakToken::default()
+ });
+ }
+
+ pub fn zerobreak(&mut self) {
+ self.spaces(0);
+ }
+
+ pub fn space(&mut self) {
+ self.spaces(1);
+ }
+
+ pub fn nbsp(&mut self) {
+ self.word(" ");
+ }
+
+ pub fn hardbreak(&mut self) {
+ self.spaces(algorithm::SIZE_INFINITY as usize);
+ }
+
+ pub fn space_if_nonempty(&mut self) {
+ self.scan_break(BreakToken {
+ blank_space: 1,
+ if_nonempty: true,
+ ..BreakToken::default()
+ });
+ }
+
+ pub fn hardbreak_if_nonempty(&mut self) {
+ self.scan_break(BreakToken {
+ blank_space: algorithm::SIZE_INFINITY as usize,
+ if_nonempty: true,
+ ..BreakToken::default()
+ });
+ }
+
+ pub fn trailing_comma(&mut self, is_last: bool) {
+ if is_last {
+ self.scan_break(BreakToken {
+ pre_break: Some(','),
+ ..BreakToken::default()
+ });
+ } else {
+ self.word(",");
+ self.space();
+ }
+ }
+
+ pub fn trailing_comma_or_space(&mut self, is_last: bool) {
+ if is_last {
+ self.scan_break(BreakToken {
+ blank_space: 1,
+ pre_break: Some(','),
+ ..BreakToken::default()
+ });
+ } else {
+ self.word(",");
+ self.space();
+ }
+ }
+
+ pub fn neverbreak(&mut self) {
+ self.scan_break(BreakToken {
+ never_break: true,
+ ..BreakToken::default()
+ });
+ }
+}
diff --git a/vendor/prettyplease/src/data.rs b/vendor/prettyplease/src/data.rs
new file mode 100644
index 00000000..3561a49b
--- /dev/null
+++ b/vendor/prettyplease/src/data.rs
@@ -0,0 +1,79 @@
+use crate::algorithm::Printer;
+use crate::fixup::FixupContext;
+use crate::iter::IterDelimited;
+use crate::path::PathKind;
+use crate::INDENT;
+use syn::{Field, Fields, FieldsUnnamed, Variant, VisRestricted, Visibility};
+
+impl Printer {
+ pub fn variant(&mut self, variant: &Variant) {
+ self.outer_attrs(&variant.attrs);
+ self.ident(&variant.ident);
+ match &variant.fields {
+ Fields::Named(fields) => {
+ self.nbsp();
+ self.word("{");
+ self.cbox(INDENT);
+ self.space();
+ for field in fields.named.iter().delimited() {
+ self.field(&field);
+ self.trailing_comma_or_space(field.is_last);
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word("}");
+ }
+ Fields::Unnamed(fields) => {
+ self.cbox(INDENT);
+ self.fields_unnamed(fields);
+ self.end();
+ }
+ Fields::Unit => {}
+ }
+ if let Some((_eq_token, discriminant)) = &variant.discriminant {
+ self.word(" = ");
+ self.expr(discriminant, FixupContext::NONE);
+ }
+ }
+
+ pub fn fields_unnamed(&mut self, fields: &FieldsUnnamed) {
+ self.word("(");
+ self.zerobreak();
+ for field in fields.unnamed.iter().delimited() {
+ self.field(&field);
+ self.trailing_comma(field.is_last);
+ }
+ self.offset(-INDENT);
+ self.word(")");
+ }
+
+ pub fn field(&mut self, field: &Field) {
+ self.outer_attrs(&field.attrs);
+ self.visibility(&field.vis);
+ if let Some(ident) = &field.ident {
+ self.ident(ident);
+ self.word(": ");
+ }
+ self.ty(&field.ty);
+ }
+
+ pub fn visibility(&mut self, vis: &Visibility) {
+ match vis {
+ Visibility::Public(_) => self.word("pub "),
+ Visibility::Restricted(vis) => self.vis_restricted(vis),
+ Visibility::Inherited => {}
+ }
+ }
+
+ fn vis_restricted(&mut self, vis: &VisRestricted) {
+ self.word("pub(");
+ let omit_in = vis.path.get_ident().map_or(false, |ident| {
+ matches!(ident.to_string().as_str(), "self" | "super" | "crate")
+ });
+ if !omit_in {
+ self.word("in ");
+ }
+ self.path(&vis.path, PathKind::Simple);
+ self.word(") ");
+ }
+}
diff --git a/vendor/prettyplease/src/expr.rs b/vendor/prettyplease/src/expr.rs
new file mode 100644
index 00000000..55b1b605
--- /dev/null
+++ b/vendor/prettyplease/src/expr.rs
@@ -0,0 +1,1533 @@
+use crate::algorithm::{BreakToken, Printer};
+use crate::attr;
+use crate::classify;
+use crate::fixup::FixupContext;
+use crate::iter::IterDelimited;
+use crate::path::PathKind;
+use crate::precedence::Precedence;
+use crate::stmt;
+use crate::INDENT;
+use proc_macro2::TokenStream;
+use syn::punctuated::Punctuated;
+use syn::{
+ token, Arm, Attribute, BinOp, Block, Expr, ExprArray, ExprAssign, ExprAsync, ExprAwait,
+ ExprBinary, ExprBlock, ExprBreak, ExprCall, ExprCast, ExprClosure, ExprConst, ExprContinue,
+ ExprField, ExprForLoop, ExprGroup, ExprIf, ExprIndex, ExprInfer, ExprLet, ExprLit, ExprLoop,
+ ExprMacro, ExprMatch, ExprMethodCall, ExprParen, ExprPath, ExprRange, ExprRawAddr,
+ ExprReference, ExprRepeat, ExprReturn, ExprStruct, ExprTry, ExprTryBlock, ExprTuple, ExprUnary,
+ ExprUnsafe, ExprWhile, ExprYield, FieldValue, Index, Label, Lit, Member, PointerMutability,
+ RangeLimits, ReturnType, Stmt, Token, UnOp,
+};
+
+impl Printer {
+ pub fn expr(&mut self, expr: &Expr, mut fixup: FixupContext) {
+ let needs_paren = fixup.parenthesize(expr);
+ if needs_paren {
+ self.word("(");
+ fixup = FixupContext::NONE;
+ }
+
+ let beginning_of_line = false;
+
+ match expr {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ Expr::Array(expr) => self.expr_array(expr),
+ Expr::Assign(expr) => self.expr_assign(expr, fixup),
+ Expr::Async(expr) => self.expr_async(expr),
+ Expr::Await(expr) => self.expr_await(expr, beginning_of_line, fixup),
+ Expr::Binary(expr) => self.expr_binary(expr, fixup),
+ Expr::Block(expr) => self.expr_block(expr),
+ Expr::Break(expr) => self.expr_break(expr, fixup),
+ Expr::Call(expr) => self.expr_call(expr, beginning_of_line, fixup),
+ Expr::Cast(expr) => self.expr_cast(expr, fixup),
+ Expr::Closure(expr) => self.expr_closure(expr, fixup),
+ Expr::Const(expr) => self.expr_const(expr),
+ Expr::Continue(expr) => self.expr_continue(expr),
+ Expr::Field(expr) => self.expr_field(expr, beginning_of_line, fixup),
+ Expr::ForLoop(expr) => self.expr_for_loop(expr),
+ Expr::Group(expr) => self.expr_group(expr, fixup),
+ Expr::If(expr) => self.expr_if(expr),
+ Expr::Index(expr) => self.expr_index(expr, beginning_of_line, fixup),
+ Expr::Infer(expr) => self.expr_infer(expr),
+ Expr::Let(expr) => self.expr_let(expr, fixup),
+ Expr::Lit(expr) => self.expr_lit(expr),
+ Expr::Loop(expr) => self.expr_loop(expr),
+ Expr::Macro(expr) => self.expr_macro(expr),
+ Expr::Match(expr) => self.expr_match(expr),
+ Expr::MethodCall(expr) => self.expr_method_call(expr, beginning_of_line, fixup),
+ Expr::Paren(expr) => self.expr_paren(expr),
+ Expr::Path(expr) => self.expr_path(expr),
+ Expr::Range(expr) => self.expr_range(expr, fixup),
+ Expr::RawAddr(expr) => self.expr_raw_addr(expr, fixup),
+ Expr::Reference(expr) => self.expr_reference(expr, fixup),
+ Expr::Repeat(expr) => self.expr_repeat(expr),
+ Expr::Return(expr) => self.expr_return(expr, fixup),
+ Expr::Struct(expr) => self.expr_struct(expr),
+ Expr::Try(expr) => self.expr_try(expr, beginning_of_line, fixup),
+ Expr::TryBlock(expr) => self.expr_try_block(expr),
+ Expr::Tuple(expr) => self.expr_tuple(expr),
+ Expr::Unary(expr) => self.expr_unary(expr, fixup),
+ Expr::Unsafe(expr) => self.expr_unsafe(expr),
+ Expr::Verbatim(expr) => self.expr_verbatim(expr, fixup),
+ Expr::While(expr) => self.expr_while(expr),
+ Expr::Yield(expr) => self.expr_yield(expr, fixup),
+ _ => unimplemented!("unknown Expr"),
+ }
+
+ if needs_paren {
+ self.word(")");
+ }
+ }
+
+ pub fn expr_beginning_of_line(
+ &mut self,
+ expr: &Expr,
+ mut needs_paren: bool,
+ beginning_of_line: bool,
+ mut fixup: FixupContext,
+ ) {
+ needs_paren |= fixup.parenthesize(expr);
+ if needs_paren {
+ self.word("(");
+ fixup = FixupContext::NONE;
+ }
+
+ match expr {
+ Expr::Await(expr) => self.expr_await(expr, beginning_of_line, fixup),
+ Expr::Field(expr) => self.expr_field(expr, beginning_of_line, fixup),
+ Expr::Index(expr) => self.expr_index(expr, beginning_of_line, fixup),
+ Expr::MethodCall(expr) => self.expr_method_call(expr, beginning_of_line, fixup),
+ Expr::Try(expr) => self.expr_try(expr, beginning_of_line, fixup),
+ _ => self.expr(expr, fixup),
+ }
+
+ if needs_paren {
+ self.word(")");
+ }
+ }
+
+ fn prefix_subexpr(
+ &mut self,
+ expr: &Expr,
+ mut needs_paren: bool,
+ beginning_of_line: bool,
+ mut fixup: FixupContext,
+ ) {
+ needs_paren |= fixup.parenthesize(expr);
+ if needs_paren {
+ self.word("(");
+ fixup = FixupContext::NONE;
+ }
+
+ match expr {
+ Expr::Await(expr) => self.prefix_subexpr_await(expr, beginning_of_line, fixup),
+ Expr::Call(expr) => self.prefix_subexpr_call(expr, fixup),
+ Expr::Field(expr) => self.prefix_subexpr_field(expr, beginning_of_line, fixup),
+ Expr::Index(expr) => self.prefix_subexpr_index(expr, beginning_of_line, fixup),
+ Expr::MethodCall(expr) => {
+ let unindent_call_args = false;
+ self.prefix_subexpr_method_call(expr, beginning_of_line, unindent_call_args, fixup);
+ }
+ Expr::Try(expr) => self.prefix_subexpr_try(expr, beginning_of_line, fixup),
+ _ => {
+ self.cbox(-INDENT);
+ self.expr(expr, fixup);
+ self.end();
+ }
+ }
+
+ if needs_paren {
+ self.word(")");
+ }
+ }
+
+ fn expr_condition(&mut self, expr: &Expr) {
+ self.cbox(0);
+ self.expr(expr, FixupContext::new_condition());
+ if needs_newline_if_wrap(expr) {
+ self.space();
+ } else {
+ self.nbsp();
+ }
+ self.end();
+ }
+
+ pub fn subexpr(&mut self, expr: &Expr, needs_paren: bool, mut fixup: FixupContext) {
+ if needs_paren {
+ self.word("(");
+ fixup = FixupContext::NONE;
+ }
+
+ self.expr(expr, fixup);
+
+ if needs_paren {
+ self.word(")");
+ }
+ }
+
+ fn expr_array(&mut self, expr: &ExprArray) {
+ self.outer_attrs(&expr.attrs);
+ if expr.elems.is_empty() {
+ self.word("[]");
+ } else if simple_array(&expr.elems) {
+ self.cbox(INDENT);
+ self.word("[");
+ self.zerobreak();
+ self.ibox(0);
+ for elem in expr.elems.iter().delimited() {
+ self.expr(&elem, FixupContext::NONE);
+ if !elem.is_last {
+ self.word(",");
+ self.space();
+ }
+ }
+ self.end();
+ self.trailing_comma(true);
+ self.offset(-INDENT);
+ self.word("]");
+ self.end();
+ } else {
+ self.word("[");
+ self.cbox(INDENT);
+ self.zerobreak();
+ for elem in expr.elems.iter().delimited() {
+ self.expr(&elem, FixupContext::NONE);
+ self.trailing_comma(elem.is_last);
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word("]");
+ }
+ }
+
+ fn expr_assign(&mut self, expr: &ExprAssign, fixup: FixupContext) {
+ let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
+ &expr.left,
+ false,
+ false,
+ Precedence::Assign,
+ );
+ let right_fixup = fixup.rightmost_subexpression_fixup(false, false, Precedence::Assign);
+
+ self.outer_attrs(&expr.attrs);
+ self.ibox(0);
+ if !expr.attrs.is_empty() {
+ self.word("(");
+ }
+ self.subexpr(&expr.left, left_prec <= Precedence::Range, left_fixup);
+ self.word(" = ");
+ self.neverbreak();
+ self.expr(&expr.right, right_fixup);
+ if !expr.attrs.is_empty() {
+ self.word(")");
+ }
+ self.end();
+ }
+
+ fn expr_async(&mut self, expr: &ExprAsync) {
+ self.outer_attrs(&expr.attrs);
+ self.word("async ");
+ if expr.capture.is_some() {
+ self.word("move ");
+ }
+ self.cbox(INDENT);
+ self.small_block(&expr.block, &expr.attrs);
+ self.end();
+ }
+
+ fn expr_await(&mut self, expr: &ExprAwait, beginning_of_line: bool, fixup: FixupContext) {
+ self.outer_attrs(&expr.attrs);
+ self.cbox(INDENT);
+ self.prefix_subexpr_await(expr, beginning_of_line, fixup);
+ self.end();
+ }
+
+ fn prefix_subexpr_await(
+ &mut self,
+ expr: &ExprAwait,
+ beginning_of_line: bool,
+ fixup: FixupContext,
+ ) {
+ let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&expr.base);
+
+ self.prefix_subexpr(
+ &expr.base,
+ left_prec < Precedence::Unambiguous,
+ beginning_of_line,
+ left_fixup,
+ );
+ if !(beginning_of_line && is_short_ident(&expr.base)) {
+ self.scan_break(BreakToken {
+ no_break: self.ends_with('.').then_some(' '),
+ ..BreakToken::default()
+ });
+ }
+ self.word(".await");
+ }
+
+ fn expr_binary(&mut self, expr: &ExprBinary, fixup: FixupContext) {
+ let binop_prec = Precedence::of_binop(&expr.op);
+ let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
+ &expr.left,
+ match &expr.op {
+ BinOp::Sub(_)
+ | BinOp::Mul(_)
+ | BinOp::And(_)
+ | BinOp::Or(_)
+ | BinOp::BitAnd(_)
+ | BinOp::BitOr(_)
+ | BinOp::Shl(_)
+ | BinOp::Lt(_) => true,
+ _ => false,
+ },
+ match &expr.op {
+ BinOp::Shl(_) | BinOp::Lt(_) => true,
+ _ => false,
+ },
+ binop_prec,
+ );
+ let left_needs_group = match binop_prec {
+ Precedence::Assign => left_prec <= Precedence::Range,
+ Precedence::Compare => left_prec <= binop_prec,
+ _ => left_prec < binop_prec,
+ };
+ let right_fixup = fixup.rightmost_subexpression_fixup(false, false, binop_prec);
+ let right_needs_group = binop_prec != Precedence::Assign
+ && right_fixup.rightmost_subexpression_precedence(&expr.right) <= binop_prec;
+
+ self.outer_attrs(&expr.attrs);
+ self.ibox(INDENT);
+ self.ibox(-INDENT);
+ if !expr.attrs.is_empty() {
+ self.word("(");
+ }
+ self.subexpr(&expr.left, left_needs_group, left_fixup);
+ self.end();
+ self.space();
+ self.binary_operator(&expr.op);
+ self.nbsp();
+ self.subexpr(&expr.right, right_needs_group, right_fixup);
+ if !expr.attrs.is_empty() {
+ self.word(")");
+ }
+ self.end();
+ }
+
+ pub fn expr_block(&mut self, expr: &ExprBlock) {
+ self.outer_attrs(&expr.attrs);
+ if let Some(label) = &expr.label {
+ self.label(label);
+ }
+ self.cbox(INDENT);
+ self.small_block(&expr.block, &expr.attrs);
+ self.end();
+ }
+
+ fn expr_break(&mut self, expr: &ExprBreak, fixup: FixupContext) {
+ self.outer_attrs(&expr.attrs);
+ self.word("break");
+ if let Some(lifetime) = &expr.label {
+ self.nbsp();
+ self.lifetime(lifetime);
+ }
+ if let Some(value) = &expr.expr {
+ self.nbsp();
+ self.subexpr(
+ value,
+ expr.label.is_none() && classify::expr_leading_label(value),
+ fixup.rightmost_subexpression_fixup(true, true, Precedence::Jump),
+ );
+ }
+ }
+
+ fn expr_call(&mut self, expr: &ExprCall, beginning_of_line: bool, fixup: FixupContext) {
+ let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
+ &expr.func,
+ true,
+ false,
+ Precedence::Unambiguous,
+ );
+ let needs_paren = if let Expr::Field(func) = &*expr.func {
+ matches!(func.member, Member::Named(_))
+ } else {
+ left_prec < Precedence::Unambiguous
+ };
+
+ self.outer_attrs(&expr.attrs);
+ self.expr_beginning_of_line(&expr.func, needs_paren, beginning_of_line, left_fixup);
+ self.word("(");
+ self.call_args(&expr.args);
+ self.word(")");
+ }
+
+ fn prefix_subexpr_call(&mut self, expr: &ExprCall, fixup: FixupContext) {
+ let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
+ &expr.func,
+ true,
+ false,
+ Precedence::Unambiguous,
+ );
+ let needs_paren = if let Expr::Field(func) = &*expr.func {
+ matches!(func.member, Member::Named(_))
+ } else {
+ left_prec < Precedence::Unambiguous
+ };
+
+ let beginning_of_line = false;
+ self.prefix_subexpr(&expr.func, needs_paren, beginning_of_line, left_fixup);
+ self.word("(");
+ self.call_args(&expr.args);
+ self.word(")");
+ }
+
+ fn expr_cast(&mut self, expr: &ExprCast, fixup: FixupContext) {
+ let (left_prec, left_fixup) =
+ fixup.leftmost_subexpression_with_operator(&expr.expr, false, false, Precedence::Cast);
+
+ self.outer_attrs(&expr.attrs);
+ self.ibox(INDENT);
+ self.ibox(-INDENT);
+ if !expr.attrs.is_empty() {
+ self.word("(");
+ }
+ self.subexpr(&expr.expr, left_prec < Precedence::Cast, left_fixup);
+ self.end();
+ self.space();
+ self.word("as ");
+ self.ty(&expr.ty);
+ if !expr.attrs.is_empty() {
+ self.word(")");
+ }
+ self.end();
+ }
+
+ fn expr_closure(&mut self, expr: &ExprClosure, fixup: FixupContext) {
+ self.outer_attrs(&expr.attrs);
+ self.ibox(0);
+ if let Some(bound_lifetimes) = &expr.lifetimes {
+ self.bound_lifetimes(bound_lifetimes);
+ }
+ if expr.constness.is_some() {
+ self.word("const ");
+ }
+ if expr.movability.is_some() {
+ self.word("static ");
+ }
+ if expr.asyncness.is_some() {
+ self.word("async ");
+ }
+ if expr.capture.is_some() {
+ self.word("move ");
+ }
+ self.cbox(INDENT);
+ self.word("|");
+ for pat in expr.inputs.iter().delimited() {
+ if pat.is_first {
+ self.zerobreak();
+ }
+ self.pat(&pat);
+ if !pat.is_last {
+ self.word(",");
+ self.space();
+ }
+ }
+ match &expr.output {
+ ReturnType::Default => {
+ self.word("|");
+ self.space();
+ self.offset(-INDENT);
+ self.end();
+ self.neverbreak();
+ let wrap_in_brace = match &*expr.body {
+ Expr::Match(ExprMatch { attrs, .. }) | Expr::Call(ExprCall { attrs, .. }) => {
+ attr::has_outer(attrs)
+ }
+ body => !is_blocklike(body),
+ };
+ if wrap_in_brace {
+ self.cbox(INDENT);
+ let okay_to_brace = parseable_as_stmt(&expr.body);
+ self.scan_break(BreakToken {
+ pre_break: Some(if okay_to_brace { '{' } else { '(' }),
+ ..BreakToken::default()
+ });
+ self.expr(
+ &expr.body,
+ fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump),
+ );
+ self.scan_break(BreakToken {
+ offset: -INDENT,
+ pre_break: (okay_to_brace && stmt::add_semi(&expr.body)).then_some(';'),
+ post_break: if okay_to_brace { "}" } else { ")" },
+ ..BreakToken::default()
+ });
+ self.end();
+ } else {
+ self.expr(
+ &expr.body,
+ fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump),
+ );
+ }
+ }
+ ReturnType::Type(_arrow, ty) => {
+ if !expr.inputs.is_empty() {
+ self.trailing_comma(true);
+ self.offset(-INDENT);
+ }
+ self.word("|");
+ self.end();
+ self.word(" -> ");
+ self.ty(ty);
+ self.nbsp();
+ self.neverbreak();
+ if matches!(&*expr.body, Expr::Block(body) if body.attrs.is_empty() && body.label.is_none())
+ {
+ self.expr(
+ &expr.body,
+ fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump),
+ );
+ } else {
+ self.cbox(INDENT);
+ self.expr_as_small_block(&expr.body, 0);
+ self.end();
+ }
+ }
+ }
+ self.end();
+ }
+
+ pub fn expr_const(&mut self, expr: &ExprConst) {
+ self.outer_attrs(&expr.attrs);
+ self.word("const ");
+ self.cbox(INDENT);
+ self.small_block(&expr.block, &expr.attrs);
+ self.end();
+ }
+
+ fn expr_continue(&mut self, expr: &ExprContinue) {
+ self.outer_attrs(&expr.attrs);
+ self.word("continue");
+ if let Some(lifetime) = &expr.label {
+ self.nbsp();
+ self.lifetime(lifetime);
+ }
+ }
+
+ fn expr_field(&mut self, expr: &ExprField, beginning_of_line: bool, fixup: FixupContext) {
+ self.outer_attrs(&expr.attrs);
+ self.cbox(INDENT);
+ self.prefix_subexpr_field(expr, beginning_of_line, fixup);
+ self.end();
+ }
+
+ fn prefix_subexpr_field(
+ &mut self,
+ expr: &ExprField,
+ beginning_of_line: bool,
+ fixup: FixupContext,
+ ) {
+ let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&expr.base);
+
+ self.prefix_subexpr(
+ &expr.base,
+ left_prec < Precedence::Unambiguous,
+ beginning_of_line,
+ left_fixup,
+ );
+ if !(beginning_of_line && is_short_ident(&expr.base)) {
+ self.scan_break(BreakToken {
+ no_break: self.ends_with('.').then_some(' '),
+ ..BreakToken::default()
+ });
+ }
+ self.word(".");
+ self.member(&expr.member);
+ }
+
+ fn expr_for_loop(&mut self, expr: &ExprForLoop) {
+ self.outer_attrs(&expr.attrs);
+ self.ibox(0);
+ if let Some(label) = &expr.label {
+ self.label(label);
+ }
+ self.word("for ");
+ self.pat(&expr.pat);
+ self.word(" in ");
+ self.neverbreak();
+ self.expr_condition(&expr.expr);
+ self.word("{");
+ self.neverbreak();
+ self.cbox(INDENT);
+ self.hardbreak_if_nonempty();
+ self.inner_attrs(&expr.attrs);
+ for stmt in expr.body.stmts.iter().delimited() {
+ self.stmt(&stmt, stmt.is_last);
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word("}");
+ self.end();
+ }
+
+ fn expr_group(&mut self, expr: &ExprGroup, fixup: FixupContext) {
+ self.outer_attrs(&expr.attrs);
+ self.expr(&expr.expr, fixup);
+ }
+
+ fn expr_if(&mut self, expr: &ExprIf) {
+ self.outer_attrs(&expr.attrs);
+ self.cbox(INDENT);
+ self.word("if ");
+ self.cbox(-INDENT);
+ self.expr_condition(&expr.cond);
+ self.end();
+ if let Some((_else_token, else_branch)) = &expr.else_branch {
+ let mut else_branch = &**else_branch;
+ self.small_block(&expr.then_branch, &[]);
+ loop {
+ self.word(" else ");
+ match else_branch {
+ Expr::If(expr) => {
+ self.word("if ");
+ self.cbox(-INDENT);
+ self.expr_condition(&expr.cond);
+ self.end();
+ self.small_block(&expr.then_branch, &[]);
+ if let Some((_else_token, next)) = &expr.else_branch {
+ else_branch = next;
+ continue;
+ }
+ }
+ Expr::Block(expr) => {
+ self.small_block(&expr.block, &[]);
+ }
+ // If not one of the valid expressions to exist in an else
+ // clause, wrap in a block.
+ other => self.expr_as_small_block(other, INDENT),
+ }
+ break;
+ }
+ } else if expr.then_branch.stmts.is_empty() {
+ self.word("{}");
+ } else {
+ self.word("{");
+ self.hardbreak();
+ for stmt in expr.then_branch.stmts.iter().delimited() {
+ self.stmt(&stmt, stmt.is_last);
+ }
+ self.offset(-INDENT);
+ self.word("}");
+ }
+ self.end();
+ }
+
+ fn expr_index(&mut self, expr: &ExprIndex, beginning_of_line: bool, fixup: FixupContext) {
+ let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
+ &expr.expr,
+ true,
+ false,
+ Precedence::Unambiguous,
+ );
+
+ self.outer_attrs(&expr.attrs);
+ self.expr_beginning_of_line(
+ &expr.expr,
+ left_prec < Precedence::Unambiguous,
+ beginning_of_line,
+ left_fixup,
+ );
+ self.word("[");
+ self.expr(&expr.index, FixupContext::NONE);
+ self.word("]");
+ }
+
+ fn prefix_subexpr_index(
+ &mut self,
+ expr: &ExprIndex,
+ beginning_of_line: bool,
+ fixup: FixupContext,
+ ) {
+ let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
+ &expr.expr,
+ true,
+ false,
+ Precedence::Unambiguous,
+ );
+
+ self.prefix_subexpr(
+ &expr.expr,
+ left_prec < Precedence::Unambiguous,
+ beginning_of_line,
+ left_fixup,
+ );
+ self.word("[");
+ self.expr(&expr.index, FixupContext::NONE);
+ self.word("]");
+ }
+
+ fn expr_infer(&mut self, expr: &ExprInfer) {
+ self.outer_attrs(&expr.attrs);
+ self.word("_");
+ }
+
+ fn expr_let(&mut self, expr: &ExprLet, fixup: FixupContext) {
+ let (right_prec, right_fixup) = fixup.rightmost_subexpression(&expr.expr, Precedence::Let);
+
+ self.outer_attrs(&expr.attrs);
+ self.ibox(0);
+ self.word("let ");
+ self.ibox(0);
+ self.pat(&expr.pat);
+ self.end();
+ self.word(" = ");
+ self.neverbreak();
+ self.ibox(0);
+ self.subexpr(&expr.expr, right_prec < Precedence::Let, right_fixup);
+ self.end();
+ self.end();
+ }
+
+ pub fn expr_lit(&mut self, expr: &ExprLit) {
+ self.outer_attrs(&expr.attrs);
+ self.lit(&expr.lit);
+ }
+
+ fn expr_loop(&mut self, expr: &ExprLoop) {
+ self.outer_attrs(&expr.attrs);
+ if let Some(label) = &expr.label {
+ self.label(label);
+ }
+ self.word("loop {");
+ self.cbox(INDENT);
+ self.hardbreak_if_nonempty();
+ self.inner_attrs(&expr.attrs);
+ for stmt in expr.body.stmts.iter().delimited() {
+ self.stmt(&stmt, stmt.is_last);
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word("}");
+ }
+
+ pub fn expr_macro(&mut self, expr: &ExprMacro) {
+ self.outer_attrs(&expr.attrs);
+ let semicolon = false;
+ self.mac(&expr.mac, None, semicolon);
+ }
+
+ fn expr_match(&mut self, expr: &ExprMatch) {
+ self.outer_attrs(&expr.attrs);
+ self.ibox(0);
+ self.word("match ");
+ self.expr_condition(&expr.expr);
+ self.word("{");
+ self.neverbreak();
+ self.cbox(INDENT);
+ self.hardbreak_if_nonempty();
+ self.inner_attrs(&expr.attrs);
+ for arm in &expr.arms {
+ self.arm(arm);
+ self.hardbreak();
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word("}");
+ self.end();
+ }
+
+ fn expr_method_call(
+ &mut self,
+ expr: &ExprMethodCall,
+ beginning_of_line: bool,
+ fixup: FixupContext,
+ ) {
+ self.outer_attrs(&expr.attrs);
+ self.cbox(INDENT);
+ let unindent_call_args = beginning_of_line && is_short_ident(&expr.receiver);
+ self.prefix_subexpr_method_call(expr, beginning_of_line, unindent_call_args, fixup);
+ self.end();
+ }
+
+ fn prefix_subexpr_method_call(
+ &mut self,
+ expr: &ExprMethodCall,
+ beginning_of_line: bool,
+ unindent_call_args: bool,
+ fixup: FixupContext,
+ ) {
+ let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&expr.receiver);
+
+ self.prefix_subexpr(
+ &expr.receiver,
+ left_prec < Precedence::Unambiguous,
+ beginning_of_line,
+ left_fixup,
+ );
+ if !(beginning_of_line && is_short_ident(&expr.receiver)) {
+ self.scan_break(BreakToken {
+ no_break: self.ends_with('.').then_some(' '),
+ ..BreakToken::default()
+ });
+ }
+ self.word(".");
+ self.ident(&expr.method);
+ if let Some(turbofish) = &expr.turbofish {
+ self.angle_bracketed_generic_arguments(turbofish, PathKind::Expr);
+ }
+ self.cbox(if unindent_call_args { -INDENT } else { 0 });
+ self.word("(");
+ self.call_args(&expr.args);
+ self.word(")");
+ self.end();
+ }
+
+ fn expr_paren(&mut self, expr: &ExprParen) {
+ self.outer_attrs(&expr.attrs);
+ self.word("(");
+ self.expr(&expr.expr, FixupContext::NONE);
+ self.word(")");
+ }
+
+ pub fn expr_path(&mut self, expr: &ExprPath) {
+ self.outer_attrs(&expr.attrs);
+ self.qpath(&expr.qself, &expr.path, PathKind::Expr);
+ }
+
+ pub fn expr_range(&mut self, expr: &ExprRange, fixup: FixupContext) {
+ self.outer_attrs(&expr.attrs);
+ if !expr.attrs.is_empty() {
+ self.word("(");
+ }
+ if let Some(start) = &expr.start {
+ let (left_prec, left_fixup) =
+ fixup.leftmost_subexpression_with_operator(start, true, false, Precedence::Range);
+ self.subexpr(start, left_prec <= Precedence::Range, left_fixup);
+ } else if self.ends_with('.') {
+ self.nbsp();
+ }
+ self.word(match expr.limits {
+ RangeLimits::HalfOpen(_) => "..",
+ RangeLimits::Closed(_) => "..=",
+ });
+ if let Some(end) = &expr.end {
+ let right_fixup = fixup.rightmost_subexpression_fixup(false, true, Precedence::Range);
+ let right_prec = right_fixup.rightmost_subexpression_precedence(end);
+ self.subexpr(end, right_prec <= Precedence::Range, right_fixup);
+ }
+ if !expr.attrs.is_empty() {
+ self.word(")");
+ }
+ }
+
+ fn expr_raw_addr(&mut self, expr: &ExprRawAddr, fixup: FixupContext) {
+ let (right_prec, right_fixup) =
+ fixup.rightmost_subexpression(&expr.expr, Precedence::Prefix);
+
+ self.outer_attrs(&expr.attrs);
+ self.word("&raw ");
+ self.pointer_mutability(&expr.mutability);
+ self.nbsp();
+ self.subexpr(&expr.expr, right_prec < Precedence::Prefix, right_fixup);
+ }
+
+ fn expr_reference(&mut self, expr: &ExprReference, fixup: FixupContext) {
+ let (right_prec, right_fixup) =
+ fixup.rightmost_subexpression(&expr.expr, Precedence::Prefix);
+
+ self.outer_attrs(&expr.attrs);
+ self.word("&");
+ if expr.mutability.is_some() {
+ self.word("mut ");
+ }
+ self.subexpr(&expr.expr, right_prec < Precedence::Prefix, right_fixup);
+ }
+
+ fn expr_repeat(&mut self, expr: &ExprRepeat) {
+ self.outer_attrs(&expr.attrs);
+ self.word("[");
+ self.expr(&expr.expr, FixupContext::NONE);
+ self.word("; ");
+ self.expr(&expr.len, FixupContext::NONE);
+ self.word("]");
+ }
+
+ fn expr_return(&mut self, expr: &ExprReturn, fixup: FixupContext) {
+ self.outer_attrs(&expr.attrs);
+ self.word("return");
+ if let Some(value) = &expr.expr {
+ self.nbsp();
+ self.expr(
+ value,
+ fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
+ );
+ }
+ }
+
+ fn expr_struct(&mut self, expr: &ExprStruct) {
+ self.outer_attrs(&expr.attrs);
+ self.cbox(INDENT);
+ self.ibox(-INDENT);
+ self.qpath(&expr.qself, &expr.path, PathKind::Expr);
+ self.end();
+ self.word(" {");
+ self.space_if_nonempty();
+ for field_value in expr.fields.iter().delimited() {
+ self.field_value(&field_value);
+ self.trailing_comma_or_space(field_value.is_last && expr.rest.is_none());
+ }
+ if let Some(rest) = &expr.rest {
+ self.word("..");
+ self.expr(rest, FixupContext::NONE);
+ self.space();
+ }
+ self.offset(-INDENT);
+ self.end_with_max_width(34);
+ self.word("}");
+ }
+
+ fn expr_try(&mut self, expr: &ExprTry, beginning_of_line: bool, fixup: FixupContext) {
+ let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&expr.expr);
+
+ self.outer_attrs(&expr.attrs);
+ self.expr_beginning_of_line(
+ &expr.expr,
+ left_prec < Precedence::Unambiguous,
+ beginning_of_line,
+ left_fixup,
+ );
+ self.word("?");
+ }
+
+ fn prefix_subexpr_try(&mut self, expr: &ExprTry, beginning_of_line: bool, fixup: FixupContext) {
+ let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&expr.expr);
+
+ self.prefix_subexpr(
+ &expr.expr,
+ left_prec < Precedence::Unambiguous,
+ beginning_of_line,
+ left_fixup,
+ );
+ self.word("?");
+ }
+
+ fn expr_try_block(&mut self, expr: &ExprTryBlock) {
+ self.outer_attrs(&expr.attrs);
+ self.word("try ");
+ self.cbox(INDENT);
+ self.small_block(&expr.block, &expr.attrs);
+ self.end();
+ }
+
+ fn expr_tuple(&mut self, expr: &ExprTuple) {
+ self.outer_attrs(&expr.attrs);
+ self.word("(");
+ self.cbox(INDENT);
+ self.zerobreak();
+ for elem in expr.elems.iter().delimited() {
+ self.expr(&elem, FixupContext::NONE);
+ if expr.elems.len() == 1 {
+ self.word(",");
+ self.zerobreak();
+ } else {
+ self.trailing_comma(elem.is_last);
+ }
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word(")");
+ }
+
+ fn expr_unary(&mut self, expr: &ExprUnary, fixup: FixupContext) {
+ let (right_prec, right_fixup) =
+ fixup.rightmost_subexpression(&expr.expr, Precedence::Prefix);
+
+ self.outer_attrs(&expr.attrs);
+ self.unary_operator(&expr.op);
+ self.subexpr(&expr.expr, right_prec < Precedence::Prefix, right_fixup);
+ }
+
+ fn expr_unsafe(&mut self, expr: &ExprUnsafe) {
+ self.outer_attrs(&expr.attrs);
+ self.word("unsafe ");
+ self.cbox(INDENT);
+ self.small_block(&expr.block, &expr.attrs);
+ self.end();
+ }
+
+ #[cfg(not(feature = "verbatim"))]
+ fn expr_verbatim(&mut self, expr: &TokenStream, _fixup: FixupContext) {
+ if !expr.is_empty() {
+ unimplemented!("Expr::Verbatim `{}`", expr);
+ }
+ }
+
+ #[cfg(feature = "verbatim")]
+ fn expr_verbatim(&mut self, tokens: &TokenStream, fixup: FixupContext) {
+ use syn::parse::discouraged::Speculative;
+ use syn::parse::{Parse, ParseStream, Result};
+ use syn::{parenthesized, Ident};
+
+ enum ExprVerbatim {
+ Empty,
+ Ellipsis,
+ Become(Become),
+ Builtin(Builtin),
+ }
+
+ struct Become {
+ attrs: Vec<Attribute>,
+ tail_call: Expr,
+ }
+
+ struct Builtin {
+ attrs: Vec<Attribute>,
+ name: Ident,
+ args: TokenStream,
+ }
+
+ mod kw {
+ syn::custom_keyword!(builtin);
+ syn::custom_keyword!(raw);
+ }
+
+ impl Parse for ExprVerbatim {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let ahead = input.fork();
+ let attrs = ahead.call(Attribute::parse_outer)?;
+ let lookahead = ahead.lookahead1();
+ if input.is_empty() {
+ Ok(ExprVerbatim::Empty)
+ } else if lookahead.peek(Token![become]) {
+ input.advance_to(&ahead);
+ input.parse::<Token![become]>()?;
+ let tail_call: Expr = input.parse()?;
+ Ok(ExprVerbatim::Become(Become { attrs, tail_call }))
+ } else if lookahead.peek(kw::builtin) {
+ input.advance_to(&ahead);
+ input.parse::<kw::builtin>()?;
+ input.parse::<Token![#]>()?;
+ let name: Ident = input.parse()?;
+ let args;
+ parenthesized!(args in input);
+ let args: TokenStream = args.parse()?;
+ Ok(ExprVerbatim::Builtin(Builtin { attrs, name, args }))
+ } else if lookahead.peek(Token![...]) {
+ input.parse::<Token![...]>()?;
+ Ok(ExprVerbatim::Ellipsis)
+ } else {
+ Err(lookahead.error())
+ }
+ }
+ }
+
+ let expr: ExprVerbatim = match syn::parse2(tokens.clone()) {
+ Ok(expr) => expr,
+ Err(_) => unimplemented!("Expr::Verbatim `{}`", tokens),
+ };
+
+ match expr {
+ ExprVerbatim::Empty => {}
+ ExprVerbatim::Ellipsis => {
+ self.word("...");
+ }
+ ExprVerbatim::Become(expr) => {
+ self.outer_attrs(&expr.attrs);
+ self.word("become");
+ self.nbsp();
+ self.expr(
+ &expr.tail_call,
+ fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
+ );
+ }
+ ExprVerbatim::Builtin(expr) => {
+ self.outer_attrs(&expr.attrs);
+ self.word("builtin # ");
+ self.ident(&expr.name);
+ self.word("(");
+ if !expr.args.is_empty() {
+ self.cbox(INDENT);
+ self.zerobreak();
+ self.ibox(0);
+ self.macro_rules_tokens(expr.args, false);
+ self.end();
+ self.zerobreak();
+ self.offset(-INDENT);
+ self.end();
+ }
+ self.word(")");
+ }
+ }
+ }
+
+ fn expr_while(&mut self, expr: &ExprWhile) {
+ self.outer_attrs(&expr.attrs);
+ if let Some(label) = &expr.label {
+ self.label(label);
+ }
+ self.word("while ");
+ self.expr_condition(&expr.cond);
+ self.word("{");
+ self.neverbreak();
+ self.cbox(INDENT);
+ self.hardbreak_if_nonempty();
+ self.inner_attrs(&expr.attrs);
+ for stmt in expr.body.stmts.iter().delimited() {
+ self.stmt(&stmt, stmt.is_last);
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word("}");
+ }
+
+ fn expr_yield(&mut self, expr: &ExprYield, fixup: FixupContext) {
+ self.outer_attrs(&expr.attrs);
+ self.word("yield");
+ if let Some(value) = &expr.expr {
+ self.nbsp();
+ self.expr(
+ value,
+ fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
+ );
+ }
+ }
+
+ fn label(&mut self, label: &Label) {
+ self.lifetime(&label.name);
+ self.word(": ");
+ }
+
+ fn field_value(&mut self, field_value: &FieldValue) {
+ self.outer_attrs(&field_value.attrs);
+ self.member(&field_value.member);
+ if field_value.colon_token.is_some() {
+ self.word(": ");
+ self.ibox(0);
+ self.expr(&field_value.expr, FixupContext::NONE);
+ self.end();
+ }
+ }
+
+ fn arm(&mut self, arm: &Arm) {
+ self.outer_attrs(&arm.attrs);
+ self.ibox(0);
+ self.pat(&arm.pat);
+ if let Some((_if_token, guard)) = &arm.guard {
+ self.word(" if ");
+ self.expr(guard, FixupContext::NONE);
+ }
+ self.word(" => ");
+ let empty_block;
+ let mut body = &*arm.body;
+ while let Expr::Block(expr) = body {
+ if expr.attrs.is_empty() && expr.label.is_none() {
+ let mut stmts = expr.block.stmts.iter();
+ if let (Some(Stmt::Expr(inner, None)), None) = (stmts.next(), stmts.next()) {
+ body = inner;
+ continue;
+ }
+ }
+ break;
+ }
+ if let Expr::Tuple(expr) = body {
+ if expr.elems.is_empty() && expr.attrs.is_empty() {
+ empty_block = Expr::Block(ExprBlock {
+ attrs: Vec::new(),
+ label: None,
+ block: Block {
+ brace_token: token::Brace::default(),
+ stmts: Vec::new(),
+ },
+ });
+ body = &empty_block;
+ }
+ }
+ if let Expr::Block(body) = body {
+ if let Some(label) = &body.label {
+ self.label(label);
+ }
+ self.word("{");
+ self.neverbreak();
+ self.cbox(INDENT);
+ self.hardbreak_if_nonempty();
+ self.inner_attrs(&body.attrs);
+ for stmt in body.block.stmts.iter().delimited() {
+ self.stmt(&stmt, stmt.is_last);
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word("}");
+ } else {
+ self.neverbreak();
+ self.cbox(INDENT);
+ let okay_to_brace = parseable_as_stmt(body);
+ self.scan_break(BreakToken {
+ pre_break: Some(if okay_to_brace { '{' } else { '(' }),
+ ..BreakToken::default()
+ });
+ self.expr_beginning_of_line(body, false, true, FixupContext::new_match_arm());
+ self.scan_break(BreakToken {
+ offset: -INDENT,
+ pre_break: (okay_to_brace && stmt::add_semi(body)).then_some(';'),
+ post_break: if okay_to_brace { "}" } else { ")," },
+ no_break: classify::requires_comma_to_be_match_arm(body).then_some(','),
+ ..BreakToken::default()
+ });
+ self.end();
+ }
+ self.end();
+ }
+
+ fn call_args(&mut self, args: &Punctuated<Expr, Token![,]>) {
+ let mut iter = args.iter();
+ match (iter.next(), iter.next()) {
+ (Some(expr), None) if is_blocklike(expr) => {
+ self.expr(expr, FixupContext::NONE);
+ }
+ _ => {
+ self.cbox(INDENT);
+ self.zerobreak();
+ for arg in args.iter().delimited() {
+ self.expr(&arg, FixupContext::NONE);
+ self.trailing_comma(arg.is_last);
+ }
+ self.offset(-INDENT);
+ self.end();
+ }
+ }
+ }
+
+ pub fn small_block(&mut self, block: &Block, attrs: &[Attribute]) {
+ self.word("{");
+ if attr::has_inner(attrs) || !block.stmts.is_empty() {
+ self.space();
+ self.inner_attrs(attrs);
+ match block.stmts.as_slice() {
+ [Stmt::Expr(expr, None)] if stmt::break_after(expr) => {
+ self.ibox(0);
+ self.expr_beginning_of_line(expr, false, true, FixupContext::new_stmt());
+ self.end();
+ self.space();
+ }
+ _ => {
+ for stmt in block.stmts.iter().delimited() {
+ self.stmt(&stmt, stmt.is_last);
+ }
+ }
+ }
+ self.offset(-INDENT);
+ }
+ self.word("}");
+ }
+
+ pub fn expr_as_small_block(&mut self, expr: &Expr, indent: isize) {
+ self.word("{");
+ self.space();
+ self.ibox(indent);
+ self.expr_beginning_of_line(expr, false, true, FixupContext::new_stmt());
+ self.end();
+ self.space();
+ self.offset(-INDENT);
+ self.word("}");
+ }
+
+ pub fn member(&mut self, member: &Member) {
+ match member {
+ Member::Named(ident) => self.ident(ident),
+ Member::Unnamed(index) => self.index(index),
+ }
+ }
+
+ fn index(&mut self, member: &Index) {
+ self.word(member.index.to_string());
+ }
+
+ fn binary_operator(&mut self, op: &BinOp) {
+ self.word(
+ match op {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ BinOp::Add(_) => "+",
+ BinOp::Sub(_) => "-",
+ BinOp::Mul(_) => "*",
+ BinOp::Div(_) => "/",
+ BinOp::Rem(_) => "%",
+ BinOp::And(_) => "&&",
+ BinOp::Or(_) => "||",
+ BinOp::BitXor(_) => "^",
+ BinOp::BitAnd(_) => "&",
+ BinOp::BitOr(_) => "|",
+ BinOp::Shl(_) => "<<",
+ BinOp::Shr(_) => ">>",
+ BinOp::Eq(_) => "==",
+ BinOp::Lt(_) => "<",
+ BinOp::Le(_) => "<=",
+ BinOp::Ne(_) => "!=",
+ BinOp::Ge(_) => ">=",
+ BinOp::Gt(_) => ">",
+ BinOp::AddAssign(_) => "+=",
+ BinOp::SubAssign(_) => "-=",
+ BinOp::MulAssign(_) => "*=",
+ BinOp::DivAssign(_) => "/=",
+ BinOp::RemAssign(_) => "%=",
+ BinOp::BitXorAssign(_) => "^=",
+ BinOp::BitAndAssign(_) => "&=",
+ BinOp::BitOrAssign(_) => "|=",
+ BinOp::ShlAssign(_) => "<<=",
+ BinOp::ShrAssign(_) => ">>=",
+ _ => unimplemented!("unknown BinOp"),
+ },
+ );
+ }
+
+ fn unary_operator(&mut self, op: &UnOp) {
+ self.word(
+ match op {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ UnOp::Deref(_) => "*",
+ UnOp::Not(_) => "!",
+ UnOp::Neg(_) => "-",
+ _ => unimplemented!("unknown UnOp"),
+ },
+ );
+ }
+
+ fn pointer_mutability(&mut self, mutability: &PointerMutability) {
+ match mutability {
+ PointerMutability::Const(_) => self.word("const"),
+ PointerMutability::Mut(_) => self.word("mut"),
+ }
+ }
+}
+
+fn needs_newline_if_wrap(expr: &Expr) -> bool {
+ match expr {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ Expr::Array(_)
+ | Expr::Async(_)
+ | Expr::Block(_)
+ | Expr::Break(ExprBreak { expr: None, .. })
+ | Expr::Closure(_)
+ | Expr::Const(_)
+ | Expr::Continue(_)
+ | Expr::ForLoop(_)
+ | Expr::If(_)
+ | Expr::Infer(_)
+ | Expr::Lit(_)
+ | Expr::Loop(_)
+ | Expr::Macro(_)
+ | Expr::Match(_)
+ | Expr::Path(_)
+ | Expr::Range(ExprRange { end: None, .. })
+ | Expr::Repeat(_)
+ | Expr::Return(ExprReturn { expr: None, .. })
+ | Expr::Struct(_)
+ | Expr::TryBlock(_)
+ | Expr::Tuple(_)
+ | Expr::Unsafe(_)
+ | Expr::Verbatim(_)
+ | Expr::While(_)
+ | Expr::Yield(ExprYield { expr: None, .. }) => false,
+
+ Expr::Assign(_)
+ | Expr::Await(_)
+ | Expr::Binary(_)
+ | Expr::Cast(_)
+ | Expr::Field(_)
+ | Expr::Index(_)
+ | Expr::MethodCall(_) => true,
+
+ Expr::Break(ExprBreak { expr: Some(e), .. })
+ | Expr::Call(ExprCall { func: e, .. })
+ | Expr::Group(ExprGroup { expr: e, .. })
+ | Expr::Let(ExprLet { expr: e, .. })
+ | Expr::Paren(ExprParen { expr: e, .. })
+ | Expr::Range(ExprRange { end: Some(e), .. })
+ | Expr::RawAddr(ExprRawAddr { expr: e, .. })
+ | Expr::Reference(ExprReference { expr: e, .. })
+ | Expr::Return(ExprReturn { expr: Some(e), .. })
+ | Expr::Try(ExprTry { expr: e, .. })
+ | Expr::Unary(ExprUnary { expr: e, .. })
+ | Expr::Yield(ExprYield { expr: Some(e), .. }) => needs_newline_if_wrap(e),
+
+ _ => false,
+ }
+}
+
+fn is_short_ident(expr: &Expr) -> bool {
+ if let Expr::Path(expr) = expr {
+ return expr.attrs.is_empty()
+ && expr.qself.is_none()
+ && expr
+ .path
+ .get_ident()
+ .map_or(false, |ident| ident.to_string().len() as isize <= INDENT);
+ }
+ false
+}
+
+fn is_blocklike(expr: &Expr) -> bool {
+ match expr {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ Expr::Array(ExprArray { attrs, .. })
+ | Expr::Async(ExprAsync { attrs, .. })
+ | Expr::Block(ExprBlock { attrs, .. })
+ | Expr::Closure(ExprClosure { attrs, .. })
+ | Expr::Const(ExprConst { attrs, .. })
+ | Expr::Struct(ExprStruct { attrs, .. })
+ | Expr::TryBlock(ExprTryBlock { attrs, .. })
+ | Expr::Tuple(ExprTuple { attrs, .. })
+ | Expr::Unsafe(ExprUnsafe { attrs, .. }) => !attr::has_outer(attrs),
+
+ Expr::Assign(_)
+ | Expr::Await(_)
+ | Expr::Binary(_)
+ | Expr::Break(_)
+ | Expr::Call(_)
+ | Expr::Cast(_)
+ | Expr::Continue(_)
+ | Expr::Field(_)
+ | Expr::ForLoop(_)
+ | Expr::If(_)
+ | Expr::Index(_)
+ | Expr::Infer(_)
+ | Expr::Let(_)
+ | Expr::Lit(_)
+ | Expr::Loop(_)
+ | Expr::Macro(_)
+ | Expr::Match(_)
+ | Expr::MethodCall(_)
+ | Expr::Paren(_)
+ | Expr::Path(_)
+ | Expr::Range(_)
+ | Expr::RawAddr(_)
+ | Expr::Reference(_)
+ | Expr::Repeat(_)
+ | Expr::Return(_)
+ | Expr::Try(_)
+ | Expr::Unary(_)
+ | Expr::Verbatim(_)
+ | Expr::While(_)
+ | Expr::Yield(_) => false,
+
+ Expr::Group(e) => is_blocklike(&e.expr),
+
+ _ => false,
+ }
+}
+
+pub fn simple_block(expr: &Expr) -> Option<&ExprBlock> {
+ if let Expr::Block(expr) = expr {
+ if expr.attrs.is_empty() && expr.label.is_none() {
+ return Some(expr);
+ }
+ }
+ None
+}
+
+pub fn simple_array(elements: &Punctuated<Expr, Token![,]>) -> bool {
+ for expr in elements {
+ if let Expr::Lit(expr) = expr {
+ match expr.lit {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ Lit::Byte(_) | Lit::Char(_) | Lit::Int(_) | Lit::Bool(_) => {}
+
+ Lit::Str(_) | Lit::ByteStr(_) | Lit::CStr(_) | Lit::Float(_) | Lit::Verbatim(_) => {
+ return false;
+ }
+
+ _ => return false,
+ }
+ } else {
+ return false;
+ }
+ }
+ true
+}
+
+// Expressions for which `$expr` and `{ $expr }` mean the same thing.
+//
+// This is not the case for all expressions. For example `{} | x | x` has some
+// bitwise OR operators while `{ {} |x| x }` has a block followed by a closure.
+fn parseable_as_stmt(mut expr: &Expr) -> bool {
+ loop {
+ match expr {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ Expr::Array(_)
+ | Expr::Async(_)
+ | Expr::Block(_)
+ | Expr::Break(_)
+ | Expr::Closure(_)
+ | Expr::Const(_)
+ | Expr::Continue(_)
+ | Expr::ForLoop(_)
+ | Expr::If(_)
+ | Expr::Infer(_)
+ | Expr::Lit(_)
+ | Expr::Loop(_)
+ | Expr::Macro(_)
+ | Expr::Match(_)
+ | Expr::Paren(_)
+ | Expr::Path(_)
+ | Expr::RawAddr(_)
+ | Expr::Reference(_)
+ | Expr::Repeat(_)
+ | Expr::Return(_)
+ | Expr::Struct(_)
+ | Expr::TryBlock(_)
+ | Expr::Tuple(_)
+ | Expr::Unary(_)
+ | Expr::Unsafe(_)
+ | Expr::Verbatim(_)
+ | Expr::While(_)
+ | Expr::Yield(_) => return true,
+
+ Expr::Let(_) => return false,
+
+ Expr::Assign(e) => {
+ if !classify::requires_semi_to_be_stmt(&e.left) {
+ return false;
+ }
+ expr = &e.left;
+ }
+ Expr::Await(e) => expr = &e.base,
+ Expr::Binary(e) => {
+ if !classify::requires_semi_to_be_stmt(&e.left) {
+ return false;
+ }
+ expr = &e.left;
+ }
+ Expr::Call(e) => {
+ if !classify::requires_semi_to_be_stmt(&e.func) {
+ return false;
+ }
+ expr = &e.func;
+ }
+ Expr::Cast(e) => {
+ if !classify::requires_semi_to_be_stmt(&e.expr) {
+ return false;
+ }
+ expr = &e.expr;
+ }
+ Expr::Field(e) => expr = &e.base,
+ Expr::Group(e) => expr = &e.expr,
+ Expr::Index(e) => {
+ if !classify::requires_semi_to_be_stmt(&e.expr) {
+ return false;
+ }
+ expr = &e.expr;
+ }
+ Expr::MethodCall(e) => expr = &e.receiver,
+ Expr::Range(e) => match &e.start {
+ None => return true,
+ Some(start) => {
+ if !classify::requires_semi_to_be_stmt(start) {
+ return false;
+ }
+ expr = start;
+ }
+ },
+ Expr::Try(e) => expr = &e.expr,
+
+ _ => return false,
+ }
+ }
+}
diff --git a/vendor/prettyplease/src/file.rs b/vendor/prettyplease/src/file.rs
new file mode 100644
index 00000000..e23bd120
--- /dev/null
+++ b/vendor/prettyplease/src/file.rs
@@ -0,0 +1,17 @@
+use crate::algorithm::Printer;
+use syn::File;
+
+impl Printer {
+ pub fn file(&mut self, file: &File) {
+ self.cbox(0);
+ if let Some(shebang) = &file.shebang {
+ self.word(shebang.clone());
+ self.hardbreak();
+ }
+ self.inner_attrs(&file.attrs);
+ for item in &file.items {
+ self.item(item);
+ }
+ self.end();
+ }
+}
diff --git a/vendor/prettyplease/src/fixup.rs b/vendor/prettyplease/src/fixup.rs
new file mode 100644
index 00000000..2355d490
--- /dev/null
+++ b/vendor/prettyplease/src/fixup.rs
@@ -0,0 +1,676 @@
+use crate::classify;
+use crate::precedence::Precedence;
+use syn::{
+ Expr, ExprBreak, ExprRange, ExprRawAddr, ExprReference, ExprReturn, ExprUnary, ExprYield,
+};
+
+#[derive(Copy, Clone)]
+pub struct FixupContext {
+ previous_operator: Precedence,
+ next_operator: Precedence,
+
+ // Print expression such that it can be parsed back as a statement
+ // consisting of the original expression.
+ //
+ // The effect of this is for binary operators in statement position to set
+ // `leftmost_subexpression_in_stmt` when printing their left-hand operand.
+ //
+ // (match x {}) - 1; // match needs parens when LHS of binary operator
+ //
+ // match x {}; // not when its own statement
+ //
+ stmt: bool,
+
+ // This is the difference between:
+ //
+ // (match x {}) - 1; // subexpression needs parens
+ //
+ // let _ = match x {} - 1; // no parens
+ //
+ // There are 3 distinguishable contexts in which `print_expr` might be
+ // called with the expression `$match` as its argument, where `$match`
+ // represents an expression of kind `ExprKind::Match`:
+ //
+ // - stmt=false leftmost_subexpression_in_stmt=false
+ //
+ // Example: `let _ = $match - 1;`
+ //
+ // No parentheses required.
+ //
+ // - stmt=false leftmost_subexpression_in_stmt=true
+ //
+ // Example: `$match - 1;`
+ //
+ // Must parenthesize `($match)`, otherwise parsing back the output as a
+ // statement would terminate the statement after the closing brace of
+ // the match, parsing `-1;` as a separate statement.
+ //
+ // - stmt=true leftmost_subexpression_in_stmt=false
+ //
+ // Example: `$match;`
+ //
+ // No parentheses required.
+ leftmost_subexpression_in_stmt: bool,
+
+ // Print expression such that it can be parsed as a match arm.
+ //
+ // This is almost equivalent to `stmt`, but the grammar diverges a tiny bit
+ // between statements and match arms when it comes to braced macro calls.
+ // Macro calls with brace delimiter terminate a statement without a
+ // semicolon, but do not terminate a match-arm without comma.
+ //
+ // m! {} - 1; // two statements: a macro call followed by -1 literal
+ //
+ // match () {
+ // _ => m! {} - 1, // binary subtraction operator
+ // }
+ //
+ match_arm: bool,
+
+ // This is almost equivalent to `leftmost_subexpression_in_stmt`, other than
+ // for braced macro calls.
+ //
+ // If we have `m! {} - 1` as an expression, the leftmost subexpression
+ // `m! {}` will need to be parenthesized in the statement case but not the
+ // match-arm case.
+ //
+ // (m! {}) - 1; // subexpression needs parens
+ //
+ // match () {
+ // _ => m! {} - 1, // no parens
+ // }
+ //
+ leftmost_subexpression_in_match_arm: bool,
+
+ // This is the difference between:
+ //
+ // if let _ = (Struct {}) {} // needs parens
+ //
+ // match () {
+ // () if let _ = Struct {} => {} // no parens
+ // }
+ //
+ condition: bool,
+
+ // This is the difference between:
+ //
+ // if break Struct {} == (break) {} // needs parens
+ //
+ // if break break == Struct {} {} // no parens
+ //
+ rightmost_subexpression_in_condition: bool,
+
+ // This is the difference between:
+ //
+ // if break ({ x }).field + 1 {} needs parens
+ //
+ // if break 1 + { x }.field {} // no parens
+ //
+ leftmost_subexpression_in_optional_operand: bool,
+
+ // This is the difference between:
+ //
+ // let _ = (return) - 1; // without paren, this would return -1
+ //
+ // let _ = return + 1; // no paren because '+' cannot begin expr
+ //
+ next_operator_can_begin_expr: bool,
+
+ // This is the difference between:
+ //
+ // let _ = 1 + return 1; // no parens if rightmost subexpression
+ //
+ // let _ = 1 + (return 1) + 1; // needs parens
+ //
+ next_operator_can_continue_expr: bool,
+
+ // This is the difference between:
+ //
+ // let _ = x as u8 + T;
+ //
+ // let _ = (x as u8) < T;
+ //
+ // Without parens, the latter would want to parse `u8<T...` as a type.
+ next_operator_can_begin_generics: bool,
+}
+
+impl FixupContext {
+ /// The default amount of fixing is minimal fixing. Fixups should be turned
+ /// on in a targeted fashion where needed.
+ pub const NONE: Self = FixupContext {
+ previous_operator: Precedence::MIN,
+ next_operator: Precedence::MIN,
+ stmt: false,
+ leftmost_subexpression_in_stmt: false,
+ match_arm: false,
+ leftmost_subexpression_in_match_arm: false,
+ condition: false,
+ rightmost_subexpression_in_condition: false,
+ leftmost_subexpression_in_optional_operand: false,
+ next_operator_can_begin_expr: false,
+ next_operator_can_continue_expr: false,
+ next_operator_can_begin_generics: false,
+ };
+
+ /// Create the initial fixup for printing an expression in statement
+ /// position.
+ pub fn new_stmt() -> Self {
+ FixupContext {
+ stmt: true,
+ ..FixupContext::NONE
+ }
+ }
+
+ /// Create the initial fixup for printing an expression as the right-hand
+ /// side of a match arm.
+ pub fn new_match_arm() -> Self {
+ FixupContext {
+ match_arm: true,
+ ..FixupContext::NONE
+ }
+ }
+
+ /// Create the initial fixup for printing an expression as the "condition"
+ /// of an `if` or `while`. There are a few other positions which are
+ /// grammatically equivalent and also use this, such as the iterator
+ /// expression in `for` and the scrutinee in `match`.
+ pub fn new_condition() -> Self {
+ FixupContext {
+ condition: true,
+ rightmost_subexpression_in_condition: true,
+ ..FixupContext::NONE
+ }
+ }
+
+ /// Transform this fixup into the one that should apply when printing the
+ /// leftmost subexpression of the current expression.
+ ///
+ /// The leftmost subexpression is any subexpression that has the same first
+ /// token as the current expression, but has a different last token.
+ ///
+ /// For example in `$a + $b` and `$a.method()`, the subexpression `$a` is a
+ /// leftmost subexpression.
+ ///
+ /// Not every expression has a leftmost subexpression. For example neither
+ /// `-$a` nor `[$a]` have one.
+ pub fn leftmost_subexpression_with_operator(
+ self,
+ expr: &Expr,
+ next_operator_can_begin_expr: bool,
+ next_operator_can_begin_generics: bool,
+ precedence: Precedence,
+ ) -> (Precedence, Self) {
+ let fixup = FixupContext {
+ next_operator: precedence,
+ stmt: false,
+ leftmost_subexpression_in_stmt: self.stmt || self.leftmost_subexpression_in_stmt,
+ match_arm: false,
+ leftmost_subexpression_in_match_arm: self.match_arm
+ || self.leftmost_subexpression_in_match_arm,
+ rightmost_subexpression_in_condition: false,
+ next_operator_can_begin_expr,
+ next_operator_can_continue_expr: true,
+ next_operator_can_begin_generics,
+ ..self
+ };
+
+ (fixup.leftmost_subexpression_precedence(expr), fixup)
+ }
+
+ /// Transform this fixup into the one that should apply when printing a
+ /// leftmost subexpression followed by a `.` or `?` token, which confer
+ /// different statement boundary rules compared to other leftmost
+ /// subexpressions.
+ pub fn leftmost_subexpression_with_dot(self, expr: &Expr) -> (Precedence, Self) {
+ let fixup = FixupContext {
+ next_operator: Precedence::Unambiguous,
+ stmt: self.stmt || self.leftmost_subexpression_in_stmt,
+ leftmost_subexpression_in_stmt: false,
+ match_arm: self.match_arm || self.leftmost_subexpression_in_match_arm,
+ leftmost_subexpression_in_match_arm: false,
+ rightmost_subexpression_in_condition: false,
+ next_operator_can_begin_expr: false,
+ next_operator_can_continue_expr: true,
+ next_operator_can_begin_generics: false,
+ ..self
+ };
+
+ (fixup.leftmost_subexpression_precedence(expr), fixup)
+ }
+
+ fn leftmost_subexpression_precedence(self, expr: &Expr) -> Precedence {
+ if !self.next_operator_can_begin_expr || self.next_operator == Precedence::Range {
+ if let Scan::Bailout = scan_right(expr, self, Precedence::MIN, 0, 0) {
+ if scan_left(expr, self) {
+ return Precedence::Unambiguous;
+ }
+ }
+ }
+
+ self.precedence(expr)
+ }
+
+ /// Transform this fixup into the one that should apply when printing the
+ /// rightmost subexpression of the current expression.
+ ///
+ /// The rightmost subexpression is any subexpression that has a different
+ /// first token than the current expression, but has the same last token.
+ ///
+ /// For example in `$a + $b` and `-$b`, the subexpression `$b` is a
+ /// rightmost subexpression.
+ ///
+ /// Not every expression has a rightmost subexpression. For example neither
+ /// `[$b]` nor `$a.f($b)` have one.
+ pub fn rightmost_subexpression(
+ self,
+ expr: &Expr,
+ precedence: Precedence,
+ ) -> (Precedence, Self) {
+ let fixup = self.rightmost_subexpression_fixup(false, false, precedence);
+ (fixup.rightmost_subexpression_precedence(expr), fixup)
+ }
+
+ pub fn rightmost_subexpression_fixup(
+ self,
+ reset_allow_struct: bool,
+ optional_operand: bool,
+ precedence: Precedence,
+ ) -> Self {
+ FixupContext {
+ previous_operator: precedence,
+ stmt: false,
+ leftmost_subexpression_in_stmt: false,
+ match_arm: false,
+ leftmost_subexpression_in_match_arm: false,
+ condition: self.condition && !reset_allow_struct,
+ leftmost_subexpression_in_optional_operand: self.condition && optional_operand,
+ ..self
+ }
+ }
+
+ pub fn rightmost_subexpression_precedence(self, expr: &Expr) -> Precedence {
+ let default_prec = self.precedence(expr);
+
+ if match self.previous_operator {
+ Precedence::Assign | Precedence::Let | Precedence::Prefix => {
+ default_prec < self.previous_operator
+ }
+ _ => default_prec <= self.previous_operator,
+ } && match self.next_operator {
+ Precedence::Range | Precedence::Or | Precedence::And => true,
+ _ => !self.next_operator_can_begin_expr,
+ } {
+ if let Scan::Bailout | Scan::Fail = scan_right(expr, self, self.previous_operator, 1, 0)
+ {
+ if scan_left(expr, self) {
+ return Precedence::Prefix;
+ }
+ }
+ }
+
+ default_prec
+ }
+
+ /// Determine whether parentheses are needed around the given expression to
+ /// head off the early termination of a statement or condition.
+ pub fn parenthesize(self, expr: &Expr) -> bool {
+ (self.leftmost_subexpression_in_stmt && !classify::requires_semi_to_be_stmt(expr))
+ || ((self.stmt || self.leftmost_subexpression_in_stmt) && matches!(expr, Expr::Let(_)))
+ || (self.leftmost_subexpression_in_match_arm
+ && !classify::requires_comma_to_be_match_arm(expr))
+ || (self.condition && matches!(expr, Expr::Struct(_)))
+ || (self.rightmost_subexpression_in_condition
+ && matches!(
+ expr,
+ Expr::Return(ExprReturn { expr: None, .. })
+ | Expr::Yield(ExprYield { expr: None, .. })
+ ))
+ || (self.rightmost_subexpression_in_condition
+ && !self.condition
+ && matches!(
+ expr,
+ Expr::Break(ExprBreak { expr: None, .. })
+ | Expr::Path(_)
+ | Expr::Range(ExprRange { end: None, .. })
+ ))
+ || (self.leftmost_subexpression_in_optional_operand
+ && matches!(expr, Expr::Block(expr) if expr.attrs.is_empty() && expr.label.is_none()))
+ }
+
+ /// Determines the effective precedence of a subexpression. Some expressions
+ /// have higher or lower precedence when adjacent to particular operators.
+ fn precedence(self, expr: &Expr) -> Precedence {
+ if self.next_operator_can_begin_expr {
+ // Decrease precedence of value-less jumps when followed by an
+ // operator that would otherwise get interpreted as beginning a
+ // value for the jump.
+ if let Expr::Break(ExprBreak { expr: None, .. })
+ | Expr::Return(ExprReturn { expr: None, .. })
+ | Expr::Yield(ExprYield { expr: None, .. }) = expr
+ {
+ return Precedence::Jump;
+ }
+ }
+
+ if !self.next_operator_can_continue_expr {
+ match expr {
+ // Increase precedence of expressions that extend to the end of
+ // current statement or group.
+ Expr::Break(_)
+ | Expr::Closure(_)
+ | Expr::Let(_)
+ | Expr::Return(_)
+ | Expr::Yield(_) => {
+ return Precedence::Prefix;
+ }
+ Expr::Range(e) if e.start.is_none() => return Precedence::Prefix,
+ _ => {}
+ }
+ }
+
+ if self.next_operator_can_begin_generics {
+ if let Expr::Cast(cast) = expr {
+ if classify::trailing_unparameterized_path(&cast.ty) {
+ return Precedence::MIN;
+ }
+ }
+ }
+
+ Precedence::of(expr)
+ }
+}
+
+#[derive(Copy, Clone, PartialEq)]
+enum Scan {
+ Fail,
+ Bailout,
+ Consume,
+}
+
+fn scan_left(expr: &Expr, fixup: FixupContext) -> bool {
+ match expr {
+ Expr::Assign(_) => fixup.previous_operator <= Precedence::Assign,
+ Expr::Binary(e) => match Precedence::of_binop(&e.op) {
+ Precedence::Assign => fixup.previous_operator <= Precedence::Assign,
+ binop_prec => fixup.previous_operator < binop_prec,
+ },
+ Expr::Cast(_) => fixup.previous_operator < Precedence::Cast,
+ Expr::Range(e) => e.start.is_none() || fixup.previous_operator < Precedence::Assign,
+ _ => true,
+ }
+}
+
+fn scan_right(
+ expr: &Expr,
+ fixup: FixupContext,
+ precedence: Precedence,
+ fail_offset: u8,
+ bailout_offset: u8,
+) -> Scan {
+ let consume_by_precedence = if match precedence {
+ Precedence::Assign | Precedence::Compare => precedence <= fixup.next_operator,
+ _ => precedence < fixup.next_operator,
+ } || fixup.next_operator == Precedence::MIN
+ {
+ Scan::Consume
+ } else {
+ Scan::Bailout
+ };
+ if fixup.parenthesize(expr) {
+ return consume_by_precedence;
+ }
+ match expr {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ Expr::Assign(e) if e.attrs.is_empty() => {
+ if match fixup.next_operator {
+ Precedence::Unambiguous => fail_offset >= 2,
+ _ => bailout_offset >= 1,
+ } {
+ return Scan::Consume;
+ }
+ let right_fixup = fixup.rightmost_subexpression_fixup(false, false, Precedence::Assign);
+ let scan = scan_right(
+ &e.right,
+ right_fixup,
+ Precedence::Assign,
+ match fixup.next_operator {
+ Precedence::Unambiguous => fail_offset,
+ _ => 1,
+ },
+ 1,
+ );
+ if let Scan::Bailout | Scan::Consume = scan {
+ Scan::Consume
+ } else if let Precedence::Unambiguous = fixup.next_operator {
+ Scan::Fail
+ } else {
+ Scan::Bailout
+ }
+ }
+ Expr::Binary(e) if e.attrs.is_empty() => {
+ if match fixup.next_operator {
+ Precedence::Unambiguous => {
+ fail_offset >= 2
+ && (consume_by_precedence == Scan::Consume || bailout_offset >= 1)
+ }
+ _ => bailout_offset >= 1,
+ } {
+ return Scan::Consume;
+ }
+ let binop_prec = Precedence::of_binop(&e.op);
+ if binop_prec == Precedence::Compare && fixup.next_operator == Precedence::Compare {
+ return Scan::Consume;
+ }
+ let right_fixup = fixup.rightmost_subexpression_fixup(false, false, binop_prec);
+ let scan = scan_right(
+ &e.right,
+ right_fixup,
+ binop_prec,
+ match fixup.next_operator {
+ Precedence::Unambiguous => fail_offset,
+ _ => 1,
+ },
+ consume_by_precedence as u8 - Scan::Bailout as u8,
+ );
+ match scan {
+ Scan::Fail => {}
+ Scan::Bailout => return consume_by_precedence,
+ Scan::Consume => return Scan::Consume,
+ }
+ let right_needs_group = binop_prec != Precedence::Assign
+ && right_fixup.rightmost_subexpression_precedence(&e.right) <= binop_prec;
+ if right_needs_group {
+ consume_by_precedence
+ } else if let (Scan::Fail, Precedence::Unambiguous) = (scan, fixup.next_operator) {
+ Scan::Fail
+ } else {
+ Scan::Bailout
+ }
+ }
+ Expr::RawAddr(ExprRawAddr { expr, .. })
+ | Expr::Reference(ExprReference { expr, .. })
+ | Expr::Unary(ExprUnary { expr, .. }) => {
+ if match fixup.next_operator {
+ Precedence::Unambiguous => {
+ fail_offset >= 2
+ && (consume_by_precedence == Scan::Consume || bailout_offset >= 1)
+ }
+ _ => bailout_offset >= 1,
+ } {
+ return Scan::Consume;
+ }
+ let right_fixup = fixup.rightmost_subexpression_fixup(false, false, Precedence::Prefix);
+ let scan = scan_right(
+ expr,
+ right_fixup,
+ precedence,
+ match fixup.next_operator {
+ Precedence::Unambiguous => fail_offset,
+ _ => 1,
+ },
+ consume_by_precedence as u8 - Scan::Bailout as u8,
+ );
+ match scan {
+ Scan::Fail => {}
+ Scan::Bailout => return consume_by_precedence,
+ Scan::Consume => return Scan::Consume,
+ }
+ if right_fixup.rightmost_subexpression_precedence(expr) < Precedence::Prefix {
+ consume_by_precedence
+ } else if let (Scan::Fail, Precedence::Unambiguous) = (scan, fixup.next_operator) {
+ Scan::Fail
+ } else {
+ Scan::Bailout
+ }
+ }
+ Expr::Range(e) if e.attrs.is_empty() => match &e.end {
+ Some(end) => {
+ if fail_offset >= 2 {
+ return Scan::Consume;
+ }
+ let right_fixup =
+ fixup.rightmost_subexpression_fixup(false, true, Precedence::Range);
+ let scan = scan_right(
+ end,
+ right_fixup,
+ Precedence::Range,
+ fail_offset,
+ match fixup.next_operator {
+ Precedence::Assign | Precedence::Range => 0,
+ _ => 1,
+ },
+ );
+ if match (scan, fixup.next_operator) {
+ (Scan::Fail, _) => false,
+ (Scan::Bailout, Precedence::Assign | Precedence::Range) => false,
+ (Scan::Bailout | Scan::Consume, _) => true,
+ } {
+ return Scan::Consume;
+ }
+ if right_fixup.rightmost_subexpression_precedence(end) <= Precedence::Range {
+ Scan::Consume
+ } else {
+ Scan::Fail
+ }
+ }
+ None => {
+ if fixup.next_operator_can_begin_expr {
+ Scan::Consume
+ } else {
+ Scan::Fail
+ }
+ }
+ },
+ Expr::Break(e) => match &e.expr {
+ Some(value) => {
+ if bailout_offset >= 1 || e.label.is_none() && classify::expr_leading_label(value) {
+ return Scan::Consume;
+ }
+ let right_fixup = fixup.rightmost_subexpression_fixup(true, true, Precedence::Jump);
+ match scan_right(value, right_fixup, Precedence::Jump, 1, 1) {
+ Scan::Fail => Scan::Bailout,
+ Scan::Bailout | Scan::Consume => Scan::Consume,
+ }
+ }
+ None => match fixup.next_operator {
+ Precedence::Assign if precedence > Precedence::Assign => Scan::Fail,
+ _ => Scan::Consume,
+ },
+ },
+ Expr::Return(ExprReturn { expr, .. }) | Expr::Yield(ExprYield { expr, .. }) => match expr {
+ Some(e) => {
+ if bailout_offset >= 1 {
+ return Scan::Consume;
+ }
+ let right_fixup =
+ fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump);
+ match scan_right(e, right_fixup, Precedence::Jump, 1, 1) {
+ Scan::Fail => Scan::Bailout,
+ Scan::Bailout | Scan::Consume => Scan::Consume,
+ }
+ }
+ None => match fixup.next_operator {
+ Precedence::Assign if precedence > Precedence::Assign => Scan::Fail,
+ _ => Scan::Consume,
+ },
+ },
+ Expr::Closure(_) => Scan::Consume,
+ Expr::Let(e) => {
+ if bailout_offset >= 1 {
+ return Scan::Consume;
+ }
+ let right_fixup = fixup.rightmost_subexpression_fixup(false, false, Precedence::Let);
+ let scan = scan_right(
+ &e.expr,
+ right_fixup,
+ Precedence::Let,
+ 1,
+ if fixup.next_operator < Precedence::Let {
+ 0
+ } else {
+ 1
+ },
+ );
+ match scan {
+ Scan::Fail | Scan::Bailout if fixup.next_operator < Precedence::Let => {
+ return Scan::Bailout;
+ }
+ Scan::Consume => return Scan::Consume,
+ _ => {}
+ }
+ if right_fixup.rightmost_subexpression_precedence(&e.expr) < Precedence::Let {
+ Scan::Consume
+ } else if let Scan::Fail = scan {
+ Scan::Bailout
+ } else {
+ Scan::Consume
+ }
+ }
+ Expr::Group(e) => scan_right(&e.expr, fixup, precedence, fail_offset, bailout_offset),
+ Expr::Array(_)
+ | Expr::Assign(_)
+ | Expr::Async(_)
+ | Expr::Await(_)
+ | Expr::Binary(_)
+ | Expr::Block(_)
+ | Expr::Call(_)
+ | Expr::Cast(_)
+ | Expr::Const(_)
+ | Expr::Continue(_)
+ | Expr::Field(_)
+ | Expr::ForLoop(_)
+ | Expr::If(_)
+ | Expr::Index(_)
+ | Expr::Infer(_)
+ | Expr::Lit(_)
+ | Expr::Loop(_)
+ | Expr::Macro(_)
+ | Expr::Match(_)
+ | Expr::MethodCall(_)
+ | Expr::Paren(_)
+ | Expr::Path(_)
+ | Expr::Range(_)
+ | Expr::Repeat(_)
+ | Expr::Struct(_)
+ | Expr::Try(_)
+ | Expr::TryBlock(_)
+ | Expr::Tuple(_)
+ | Expr::Unsafe(_)
+ | Expr::Verbatim(_)
+ | Expr::While(_) => match fixup.next_operator {
+ Precedence::Assign | Precedence::Range if precedence == Precedence::Range => Scan::Fail,
+ _ if precedence == Precedence::Let && fixup.next_operator < Precedence::Let => {
+ Scan::Fail
+ }
+ _ => consume_by_precedence,
+ },
+
+ _ => match fixup.next_operator {
+ Precedence::Assign | Precedence::Range if precedence == Precedence::Range => Scan::Fail,
+ _ if precedence == Precedence::Let && fixup.next_operator < Precedence::Let => {
+ Scan::Fail
+ }
+ _ => consume_by_precedence,
+ },
+ }
+}
diff --git a/vendor/prettyplease/src/generics.rs b/vendor/prettyplease/src/generics.rs
new file mode 100644
index 00000000..3f225b88
--- /dev/null
+++ b/vendor/prettyplease/src/generics.rs
@@ -0,0 +1,383 @@
+use crate::algorithm::Printer;
+use crate::iter::IterDelimited;
+use crate::path::PathKind;
+use crate::INDENT;
+use proc_macro2::TokenStream;
+use std::ptr;
+use syn::{
+ BoundLifetimes, CapturedParam, ConstParam, Expr, GenericParam, Generics, LifetimeParam,
+ PreciseCapture, PredicateLifetime, PredicateType, TraitBound, TraitBoundModifier, TypeParam,
+ TypeParamBound, WhereClause, WherePredicate,
+};
+
+impl Printer {
+ pub fn generics(&mut self, generics: &Generics) {
+ if generics.params.is_empty() {
+ return;
+ }
+
+ self.word("<");
+ self.cbox(0);
+ self.zerobreak();
+
+ // Print lifetimes before types and consts, regardless of their
+ // order in self.params.
+ #[derive(Ord, PartialOrd, Eq, PartialEq)]
+ enum Group {
+ First,
+ Second,
+ }
+ fn group(param: &GenericParam) -> Group {
+ match param {
+ GenericParam::Lifetime(_) => Group::First,
+ GenericParam::Type(_) | GenericParam::Const(_) => Group::Second,
+ }
+ }
+ let last = generics.params.iter().max_by_key(|param| group(param));
+ for current_group in [Group::First, Group::Second] {
+ for param in &generics.params {
+ if group(param) == current_group {
+ self.generic_param(param);
+ self.trailing_comma(ptr::eq(param, last.unwrap()));
+ }
+ }
+ }
+
+ self.offset(-INDENT);
+ self.end();
+ self.word(">");
+ }
+
+ fn generic_param(&mut self, generic_param: &GenericParam) {
+ match generic_param {
+ GenericParam::Type(type_param) => self.type_param(type_param),
+ GenericParam::Lifetime(lifetime_param) => self.lifetime_param(lifetime_param),
+ GenericParam::Const(const_param) => self.const_param(const_param),
+ }
+ }
+
+ pub fn bound_lifetimes(&mut self, bound_lifetimes: &BoundLifetimes) {
+ self.word("for<");
+ for param in bound_lifetimes.lifetimes.iter().delimited() {
+ self.generic_param(&param);
+ if !param.is_last {
+ self.word(", ");
+ }
+ }
+ self.word("> ");
+ }
+
+ fn lifetime_param(&mut self, lifetime_param: &LifetimeParam) {
+ self.outer_attrs(&lifetime_param.attrs);
+ self.lifetime(&lifetime_param.lifetime);
+ for lifetime in lifetime_param.bounds.iter().delimited() {
+ if lifetime.is_first {
+ self.word(": ");
+ } else {
+ self.word(" + ");
+ }
+ self.lifetime(&lifetime);
+ }
+ }
+
+ fn type_param(&mut self, type_param: &TypeParam) {
+ self.outer_attrs(&type_param.attrs);
+ self.ident(&type_param.ident);
+ self.ibox(INDENT);
+ for type_param_bound in type_param.bounds.iter().delimited() {
+ if type_param_bound.is_first {
+ self.word(": ");
+ } else {
+ self.space();
+ self.word("+ ");
+ }
+ self.type_param_bound(&type_param_bound);
+ }
+ if let Some(default) = &type_param.default {
+ self.space();
+ self.word("= ");
+ self.ty(default);
+ }
+ self.end();
+ }
+
+ pub fn type_param_bound(&mut self, type_param_bound: &TypeParamBound) {
+ match type_param_bound {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ TypeParamBound::Trait(trait_bound) => {
+ let tilde_const = false;
+ self.trait_bound(trait_bound, tilde_const);
+ }
+ TypeParamBound::Lifetime(lifetime) => self.lifetime(lifetime),
+ TypeParamBound::PreciseCapture(precise_capture) => {
+ self.precise_capture(precise_capture);
+ }
+ TypeParamBound::Verbatim(bound) => self.type_param_bound_verbatim(bound),
+ _ => unimplemented!("unknown TypeParamBound"),
+ }
+ }
+
+ fn trait_bound(&mut self, trait_bound: &TraitBound, tilde_const: bool) {
+ if trait_bound.paren_token.is_some() {
+ self.word("(");
+ }
+ if tilde_const {
+ self.word("~const ");
+ }
+ self.trait_bound_modifier(&trait_bound.modifier);
+ if let Some(bound_lifetimes) = &trait_bound.lifetimes {
+ self.bound_lifetimes(bound_lifetimes);
+ }
+ for segment in trait_bound.path.segments.iter().delimited() {
+ if !segment.is_first || trait_bound.path.leading_colon.is_some() {
+ self.word("::");
+ }
+ self.path_segment(&segment, PathKind::Type);
+ }
+ if trait_bound.paren_token.is_some() {
+ self.word(")");
+ }
+ }
+
+ fn trait_bound_modifier(&mut self, trait_bound_modifier: &TraitBoundModifier) {
+ match trait_bound_modifier {
+ TraitBoundModifier::None => {}
+ TraitBoundModifier::Maybe(_question_mark) => self.word("?"),
+ }
+ }
+
+ #[cfg(not(feature = "verbatim"))]
+ fn type_param_bound_verbatim(&mut self, bound: &TokenStream) {
+ unimplemented!("TypeParamBound::Verbatim `{}`", bound);
+ }
+
+ #[cfg(feature = "verbatim")]
+ fn type_param_bound_verbatim(&mut self, tokens: &TokenStream) {
+ use syn::parse::{Parse, ParseStream, Result};
+ use syn::{parenthesized, token, Token};
+
+ enum TypeParamBoundVerbatim {
+ Ellipsis,
+ TildeConst(TraitBound),
+ }
+
+ impl Parse for TypeParamBoundVerbatim {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let content;
+ let (paren_token, content) = if input.peek(token::Paren) {
+ (Some(parenthesized!(content in input)), &content)
+ } else {
+ (None, input)
+ };
+ let lookahead = content.lookahead1();
+ if lookahead.peek(Token![~]) {
+ content.parse::<Token![~]>()?;
+ content.parse::<Token![const]>()?;
+ let mut bound: TraitBound = content.parse()?;
+ bound.paren_token = paren_token;
+ Ok(TypeParamBoundVerbatim::TildeConst(bound))
+ } else if lookahead.peek(Token![...]) {
+ content.parse::<Token![...]>()?;
+ Ok(TypeParamBoundVerbatim::Ellipsis)
+ } else {
+ Err(lookahead.error())
+ }
+ }
+ }
+
+ let bound: TypeParamBoundVerbatim = match syn::parse2(tokens.clone()) {
+ Ok(bound) => bound,
+ Err(_) => unimplemented!("TypeParamBound::Verbatim `{}`", tokens),
+ };
+
+ match bound {
+ TypeParamBoundVerbatim::Ellipsis => {
+ self.word("...");
+ }
+ TypeParamBoundVerbatim::TildeConst(trait_bound) => {
+ let tilde_const = true;
+ self.trait_bound(&trait_bound, tilde_const);
+ }
+ }
+ }
+
+ fn const_param(&mut self, const_param: &ConstParam) {
+ self.outer_attrs(&const_param.attrs);
+ self.word("const ");
+ self.ident(&const_param.ident);
+ self.word(": ");
+ self.ty(&const_param.ty);
+ if let Some(default) = &const_param.default {
+ self.word(" = ");
+ self.const_argument(default);
+ }
+ }
+
+ pub fn where_clause_for_body(&mut self, where_clause: &Option<WhereClause>) {
+ let hardbreaks = true;
+ let semi = false;
+ self.where_clause_impl(where_clause, hardbreaks, semi);
+ }
+
+ pub fn where_clause_semi(&mut self, where_clause: &Option<WhereClause>) {
+ let hardbreaks = true;
+ let semi = true;
+ self.where_clause_impl(where_clause, hardbreaks, semi);
+ }
+
+ pub fn where_clause_oneline(&mut self, where_clause: &Option<WhereClause>) {
+ let hardbreaks = false;
+ let semi = false;
+ self.where_clause_impl(where_clause, hardbreaks, semi);
+ }
+
+ pub fn where_clause_oneline_semi(&mut self, where_clause: &Option<WhereClause>) {
+ let hardbreaks = false;
+ let semi = true;
+ self.where_clause_impl(where_clause, hardbreaks, semi);
+ }
+
+ fn where_clause_impl(
+ &mut self,
+ where_clause: &Option<WhereClause>,
+ hardbreaks: bool,
+ semi: bool,
+ ) {
+ let where_clause = match where_clause {
+ Some(where_clause) if !where_clause.predicates.is_empty() => where_clause,
+ _ => {
+ if semi {
+ self.word(";");
+ } else {
+ self.nbsp();
+ }
+ return;
+ }
+ };
+ if hardbreaks {
+ self.hardbreak();
+ self.offset(-INDENT);
+ self.word("where");
+ self.hardbreak();
+ for predicate in where_clause.predicates.iter().delimited() {
+ self.where_predicate(&predicate);
+ if predicate.is_last && semi {
+ self.word(";");
+ } else {
+ self.word(",");
+ self.hardbreak();
+ }
+ }
+ if !semi {
+ self.offset(-INDENT);
+ }
+ } else {
+ self.space();
+ self.offset(-INDENT);
+ self.word("where");
+ self.space();
+ for predicate in where_clause.predicates.iter().delimited() {
+ self.where_predicate(&predicate);
+ if predicate.is_last && semi {
+ self.word(";");
+ } else {
+ self.trailing_comma_or_space(predicate.is_last);
+ }
+ }
+ if !semi {
+ self.offset(-INDENT);
+ }
+ }
+ }
+
+ fn where_predicate(&mut self, predicate: &WherePredicate) {
+ match predicate {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ WherePredicate::Type(predicate) => self.predicate_type(predicate),
+ WherePredicate::Lifetime(predicate) => self.predicate_lifetime(predicate),
+ _ => unimplemented!("unknown WherePredicate"),
+ }
+ }
+
+ fn predicate_type(&mut self, predicate: &PredicateType) {
+ if let Some(bound_lifetimes) = &predicate.lifetimes {
+ self.bound_lifetimes(bound_lifetimes);
+ }
+ self.ty(&predicate.bounded_ty);
+ self.word(":");
+ if predicate.bounds.len() == 1 {
+ self.ibox(0);
+ } else {
+ self.ibox(INDENT);
+ }
+ for type_param_bound in predicate.bounds.iter().delimited() {
+ if type_param_bound.is_first {
+ self.nbsp();
+ } else {
+ self.space();
+ self.word("+ ");
+ }
+ self.type_param_bound(&type_param_bound);
+ }
+ self.end();
+ }
+
+ fn predicate_lifetime(&mut self, predicate: &PredicateLifetime) {
+ self.lifetime(&predicate.lifetime);
+ self.word(":");
+ self.ibox(INDENT);
+ for lifetime in predicate.bounds.iter().delimited() {
+ if lifetime.is_first {
+ self.nbsp();
+ } else {
+ self.space();
+ self.word("+ ");
+ }
+ self.lifetime(&lifetime);
+ }
+ self.end();
+ }
+
+ fn precise_capture(&mut self, precise_capture: &PreciseCapture) {
+ self.word("use<");
+ for capture in precise_capture.params.iter().delimited() {
+ self.captured_param(&capture);
+ if !capture.is_last {
+ self.word(", ");
+ }
+ }
+ self.word(">");
+ }
+
+ fn captured_param(&mut self, capture: &CapturedParam) {
+ match capture {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ CapturedParam::Lifetime(lifetime) => self.lifetime(lifetime),
+ CapturedParam::Ident(ident) => self.ident(ident),
+ _ => unimplemented!("unknown CapturedParam"),
+ }
+ }
+
+ pub fn const_argument(&mut self, expr: &Expr) {
+ match expr {
+ #![cfg_attr(all(test, exhaustive), allow(non_exhaustive_omitted_patterns))]
+ Expr::Lit(expr) => self.expr_lit(expr),
+
+ Expr::Path(expr)
+ if expr.attrs.is_empty()
+ && expr.qself.is_none()
+ && expr.path.get_ident().is_some() =>
+ {
+ self.expr_path(expr);
+ }
+
+ Expr::Block(expr) => self.expr_block(expr),
+
+ _ => {
+ self.cbox(INDENT);
+ self.expr_as_small_block(expr, 0);
+ self.end();
+ }
+ }
+ }
+}
diff --git a/vendor/prettyplease/src/item.rs b/vendor/prettyplease/src/item.rs
new file mode 100644
index 00000000..4e9d95d7
--- /dev/null
+++ b/vendor/prettyplease/src/item.rs
@@ -0,0 +1,1812 @@
+use crate::algorithm::Printer;
+use crate::fixup::FixupContext;
+use crate::iter::IterDelimited;
+use crate::mac;
+use crate::path::PathKind;
+use crate::INDENT;
+use proc_macro2::TokenStream;
+use syn::{
+ Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemMacro, ForeignItemStatic,
+ ForeignItemType, ImplItem, ImplItemConst, ImplItemFn, ImplItemMacro, ImplItemType, Item,
+ ItemConst, ItemEnum, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl, ItemMacro, ItemMod,
+ ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType, ItemUnion, ItemUse, Receiver,
+ Signature, StaticMutability, TraitItem, TraitItemConst, TraitItemFn, TraitItemMacro,
+ TraitItemType, Type, UseGlob, UseGroup, UseName, UsePath, UseRename, UseTree, Variadic,
+};
+
+impl Printer {
+ pub fn item(&mut self, item: &Item) {
+ match item {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ Item::Const(item) => self.item_const(item),
+ Item::Enum(item) => self.item_enum(item),
+ Item::ExternCrate(item) => self.item_extern_crate(item),
+ Item::Fn(item) => self.item_fn(item),
+ Item::ForeignMod(item) => self.item_foreign_mod(item),
+ Item::Impl(item) => self.item_impl(item),
+ Item::Macro(item) => self.item_macro(item),
+ Item::Mod(item) => self.item_mod(item),
+ Item::Static(item) => self.item_static(item),
+ Item::Struct(item) => self.item_struct(item),
+ Item::Trait(item) => self.item_trait(item),
+ Item::TraitAlias(item) => self.item_trait_alias(item),
+ Item::Type(item) => self.item_type(item),
+ Item::Union(item) => self.item_union(item),
+ Item::Use(item) => self.item_use(item),
+ Item::Verbatim(item) => self.item_verbatim(item),
+ _ => unimplemented!("unknown Item"),
+ }
+ }
+
+ fn item_const(&mut self, item: &ItemConst) {
+ self.outer_attrs(&item.attrs);
+ self.cbox(0);
+ self.visibility(&item.vis);
+ self.word("const ");
+ self.ident(&item.ident);
+ self.generics(&item.generics);
+ self.word(": ");
+ self.ty(&item.ty);
+ self.word(" = ");
+ self.neverbreak();
+ self.expr(&item.expr, FixupContext::NONE);
+ self.word(";");
+ self.end();
+ self.hardbreak();
+ }
+
+ fn item_enum(&mut self, item: &ItemEnum) {
+ self.outer_attrs(&item.attrs);
+ self.cbox(INDENT);
+ self.visibility(&item.vis);
+ self.word("enum ");
+ self.ident(&item.ident);
+ self.generics(&item.generics);
+ self.where_clause_for_body(&item.generics.where_clause);
+ self.word("{");
+ self.hardbreak_if_nonempty();
+ for variant in &item.variants {
+ self.variant(variant);
+ self.word(",");
+ self.hardbreak();
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word("}");
+ self.hardbreak();
+ }
+
+ fn item_extern_crate(&mut self, item: &ItemExternCrate) {
+ self.outer_attrs(&item.attrs);
+ self.visibility(&item.vis);
+ self.word("extern crate ");
+ self.ident(&item.ident);
+ if let Some((_as_token, rename)) = &item.rename {
+ self.word(" as ");
+ self.ident(rename);
+ }
+ self.word(";");
+ self.hardbreak();
+ }
+
+ fn item_fn(&mut self, item: &ItemFn) {
+ self.outer_attrs(&item.attrs);
+ self.cbox(INDENT);
+ self.visibility(&item.vis);
+ self.signature(
+ &item.sig,
+ #[cfg(feature = "verbatim")]
+ &verbatim::Safety::Disallowed,
+ );
+ self.where_clause_for_body(&item.sig.generics.where_clause);
+ self.word("{");
+ self.hardbreak_if_nonempty();
+ self.inner_attrs(&item.attrs);
+ for stmt in item.block.stmts.iter().delimited() {
+ self.stmt(&stmt, stmt.is_last);
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word("}");
+ self.hardbreak();
+ }
+
+ fn item_foreign_mod(&mut self, item: &ItemForeignMod) {
+ self.outer_attrs(&item.attrs);
+ self.cbox(INDENT);
+ if item.unsafety.is_some() {
+ self.word("unsafe ");
+ }
+ self.abi(&item.abi);
+ self.word("{");
+ self.hardbreak_if_nonempty();
+ self.inner_attrs(&item.attrs);
+ for foreign_item in &item.items {
+ self.foreign_item(foreign_item);
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word("}");
+ self.hardbreak();
+ }
+
+ fn item_impl(&mut self, item: &ItemImpl) {
+ self.outer_attrs(&item.attrs);
+ self.cbox(INDENT);
+ self.ibox(-INDENT);
+ self.cbox(INDENT);
+ if item.defaultness.is_some() {
+ self.word("default ");
+ }
+ if item.unsafety.is_some() {
+ self.word("unsafe ");
+ }
+ self.word("impl");
+ self.generics(&item.generics);
+ self.end();
+ self.nbsp();
+ if let Some((negative_polarity, path, _for_token)) = &item.trait_ {
+ if negative_polarity.is_some() {
+ self.word("!");
+ }
+ self.path(path, PathKind::Type);
+ self.space();
+ self.word("for ");
+ }
+ self.ty(&item.self_ty);
+ self.end();
+ self.where_clause_for_body(&item.generics.where_clause);
+ self.word("{");
+ self.hardbreak_if_nonempty();
+ self.inner_attrs(&item.attrs);
+ for impl_item in &item.items {
+ self.impl_item(impl_item);
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word("}");
+ self.hardbreak();
+ }
+
+ fn item_macro(&mut self, item: &ItemMacro) {
+ self.outer_attrs(&item.attrs);
+ let semicolon = mac::requires_semi(&item.mac.delimiter);
+ self.mac(&item.mac, item.ident.as_ref(), semicolon);
+ self.hardbreak();
+ }
+
+ fn item_mod(&mut self, item: &ItemMod) {
+ self.outer_attrs(&item.attrs);
+ self.cbox(INDENT);
+ self.visibility(&item.vis);
+ if item.unsafety.is_some() {
+ self.word("unsafe ");
+ }
+ self.word("mod ");
+ self.ident(&item.ident);
+ if let Some((_brace, items)) = &item.content {
+ self.word(" {");
+ self.hardbreak_if_nonempty();
+ self.inner_attrs(&item.attrs);
+ for item in items {
+ self.item(item);
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word("}");
+ } else {
+ self.word(";");
+ self.end();
+ }
+ self.hardbreak();
+ }
+
+ fn item_static(&mut self, item: &ItemStatic) {
+ self.outer_attrs(&item.attrs);
+ self.cbox(0);
+ self.visibility(&item.vis);
+ self.word("static ");
+ self.static_mutability(&item.mutability);
+ self.ident(&item.ident);
+ self.word(": ");
+ self.ty(&item.ty);
+ self.word(" = ");
+ self.neverbreak();
+ self.expr(&item.expr, FixupContext::NONE);
+ self.word(";");
+ self.end();
+ self.hardbreak();
+ }
+
+ fn item_struct(&mut self, item: &ItemStruct) {
+ self.outer_attrs(&item.attrs);
+ self.cbox(INDENT);
+ self.visibility(&item.vis);
+ self.word("struct ");
+ self.ident(&item.ident);
+ self.generics(&item.generics);
+ match &item.fields {
+ Fields::Named(fields) => {
+ self.where_clause_for_body(&item.generics.where_clause);
+ self.word("{");
+ self.hardbreak_if_nonempty();
+ for field in &fields.named {
+ self.field(field);
+ self.word(",");
+ self.hardbreak();
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word("}");
+ }
+ Fields::Unnamed(fields) => {
+ self.fields_unnamed(fields);
+ self.where_clause_semi(&item.generics.where_clause);
+ self.end();
+ }
+ Fields::Unit => {
+ self.where_clause_semi(&item.generics.where_clause);
+ self.end();
+ }
+ }
+ self.hardbreak();
+ }
+
+ fn item_trait(&mut self, item: &ItemTrait) {
+ self.outer_attrs(&item.attrs);
+ self.cbox(INDENT);
+ self.visibility(&item.vis);
+ if item.unsafety.is_some() {
+ self.word("unsafe ");
+ }
+ if item.auto_token.is_some() {
+ self.word("auto ");
+ }
+ self.word("trait ");
+ self.ident(&item.ident);
+ self.generics(&item.generics);
+ for supertrait in item.supertraits.iter().delimited() {
+ if supertrait.is_first {
+ self.word(": ");
+ } else {
+ self.word(" + ");
+ }
+ self.type_param_bound(&supertrait);
+ }
+ self.where_clause_for_body(&item.generics.where_clause);
+ self.word("{");
+ self.hardbreak_if_nonempty();
+ self.inner_attrs(&item.attrs);
+ for trait_item in &item.items {
+ self.trait_item(trait_item);
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word("}");
+ self.hardbreak();
+ }
+
+ fn item_trait_alias(&mut self, item: &ItemTraitAlias) {
+ self.outer_attrs(&item.attrs);
+ self.cbox(INDENT);
+ self.visibility(&item.vis);
+ self.word("trait ");
+ self.ident(&item.ident);
+ self.generics(&item.generics);
+ self.word(" = ");
+ self.neverbreak();
+ for bound in item.bounds.iter().delimited() {
+ if !bound.is_first {
+ self.space();
+ self.word("+ ");
+ }
+ self.type_param_bound(&bound);
+ }
+ self.where_clause_semi(&item.generics.where_clause);
+ self.end();
+ self.hardbreak();
+ }
+
+ fn item_type(&mut self, item: &ItemType) {
+ self.outer_attrs(&item.attrs);
+ self.cbox(INDENT);
+ self.visibility(&item.vis);
+ self.word("type ");
+ self.ident(&item.ident);
+ self.generics(&item.generics);
+ self.where_clause_oneline(&item.generics.where_clause);
+ self.word("= ");
+ self.neverbreak();
+ self.ibox(-INDENT);
+ self.ty(&item.ty);
+ self.end();
+ self.word(";");
+ self.end();
+ self.hardbreak();
+ }
+
+ fn item_union(&mut self, item: &ItemUnion) {
+ self.outer_attrs(&item.attrs);
+ self.cbox(INDENT);
+ self.visibility(&item.vis);
+ self.word("union ");
+ self.ident(&item.ident);
+ self.generics(&item.generics);
+ self.where_clause_for_body(&item.generics.where_clause);
+ self.word("{");
+ self.hardbreak_if_nonempty();
+ for field in &item.fields.named {
+ self.field(field);
+ self.word(",");
+ self.hardbreak();
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word("}");
+ self.hardbreak();
+ }
+
+ fn item_use(&mut self, item: &ItemUse) {
+ self.outer_attrs(&item.attrs);
+ self.visibility(&item.vis);
+ self.word("use ");
+ if item.leading_colon.is_some() {
+ self.word("::");
+ }
+ self.use_tree(&item.tree);
+ self.word(";");
+ self.hardbreak();
+ }
+
+ #[cfg(not(feature = "verbatim"))]
+ fn item_verbatim(&mut self, item: &TokenStream) {
+ if !item.is_empty() {
+ unimplemented!("Item::Verbatim `{}`", item);
+ }
+ self.hardbreak();
+ }
+
+ #[cfg(feature = "verbatim")]
+ fn item_verbatim(&mut self, tokens: &TokenStream) {
+ use syn::parse::{Parse, ParseStream, Result};
+ use syn::punctuated::Punctuated;
+ use syn::{
+ braced, parenthesized, token, Attribute, Generics, Ident, Lifetime, Token, Visibility,
+ };
+ use verbatim::{
+ FlexibleItemConst, FlexibleItemFn, FlexibleItemStatic, FlexibleItemType,
+ WhereClauseLocation,
+ };
+
+ enum ItemVerbatim {
+ Empty,
+ Ellipsis,
+ ConstFlexible(FlexibleItemConst),
+ FnFlexible(FlexibleItemFn),
+ ImplFlexible(ImplFlexible),
+ Macro2(Macro2),
+ StaticFlexible(FlexibleItemStatic),
+ TypeFlexible(FlexibleItemType),
+ UseBrace(UseBrace),
+ }
+
+ struct ImplFlexible {
+ attrs: Vec<Attribute>,
+ vis: Visibility,
+ defaultness: bool,
+ unsafety: bool,
+ generics: Generics,
+ constness: ImplConstness,
+ negative_impl: bool,
+ trait_: Option<Type>,
+ self_ty: Type,
+ items: Vec<ImplItem>,
+ }
+
+ enum ImplConstness {
+ None,
+ MaybeConst,
+ Const,
+ }
+
+ struct Macro2 {
+ attrs: Vec<Attribute>,
+ vis: Visibility,
+ ident: Ident,
+ args: Option<TokenStream>,
+ body: TokenStream,
+ }
+
+ struct UseBrace {
+ attrs: Vec<Attribute>,
+ vis: Visibility,
+ trees: Punctuated<RootUseTree, Token![,]>,
+ }
+
+ struct RootUseTree {
+ leading_colon: Option<Token![::]>,
+ inner: UseTree,
+ }
+
+ impl Parse for ImplConstness {
+ fn parse(input: ParseStream) -> Result<Self> {
+ if input.parse::<Option<Token![?]>>()?.is_some() {
+ input.parse::<Token![const]>()?;
+ Ok(ImplConstness::MaybeConst)
+ } else if input.parse::<Option<Token![const]>>()?.is_some() {
+ Ok(ImplConstness::Const)
+ } else {
+ Ok(ImplConstness::None)
+ }
+ }
+ }
+
+ impl Parse for RootUseTree {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(RootUseTree {
+ leading_colon: input.parse()?,
+ inner: input.parse()?,
+ })
+ }
+ }
+
+ impl Parse for ItemVerbatim {
+ fn parse(input: ParseStream) -> Result<Self> {
+ if input.is_empty() {
+ return Ok(ItemVerbatim::Empty);
+ } else if input.peek(Token![...]) {
+ input.parse::<Token![...]>()?;
+ return Ok(ItemVerbatim::Ellipsis);
+ }
+
+ let mut attrs = input.call(Attribute::parse_outer)?;
+ let vis: Visibility = input.parse()?;
+
+ let lookahead = input.lookahead1();
+ if lookahead.peek(Token![const]) && (input.peek2(Ident) || input.peek2(Token![_])) {
+ let defaultness = false;
+ let flexible_item = FlexibleItemConst::parse(attrs, vis, defaultness, input)?;
+ Ok(ItemVerbatim::ConstFlexible(flexible_item))
+ } else if input.peek(Token![const])
+ || lookahead.peek(Token![async])
+ || lookahead.peek(Token![unsafe]) && !input.peek2(Token![impl])
+ || lookahead.peek(Token![extern])
+ || lookahead.peek(Token![fn])
+ {
+ let defaultness = false;
+ let flexible_item = FlexibleItemFn::parse(attrs, vis, defaultness, input)?;
+ Ok(ItemVerbatim::FnFlexible(flexible_item))
+ } else if lookahead.peek(Token![default])
+ || input.peek(Token![unsafe])
+ || lookahead.peek(Token![impl])
+ {
+ let defaultness = input.parse::<Option<Token![default]>>()?.is_some();
+ let unsafety = input.parse::<Option<Token![unsafe]>>()?.is_some();
+ input.parse::<Token![impl]>()?;
+ let has_generics = input.peek(Token![<])
+ && (input.peek2(Token![>])
+ || input.peek2(Token![#])
+ || (input.peek2(Ident) || input.peek2(Lifetime))
+ && (input.peek3(Token![:])
+ || input.peek3(Token![,])
+ || input.peek3(Token![>])
+ || input.peek3(Token![=]))
+ || input.peek2(Token![const]));
+ let mut generics: Generics = if has_generics {
+ input.parse()?
+ } else {
+ Generics::default()
+ };
+ let constness: ImplConstness = input.parse()?;
+ let negative_impl =
+ !input.peek2(token::Brace) && input.parse::<Option<Token![!]>>()?.is_some();
+ let first_ty: Type = input.parse()?;
+ let (trait_, self_ty) = if input.parse::<Option<Token![for]>>()?.is_some() {
+ (Some(first_ty), input.parse()?)
+ } else {
+ (None, first_ty)
+ };
+ generics.where_clause = input.parse()?;
+ let content;
+ braced!(content in input);
+ let inner_attrs = content.call(Attribute::parse_inner)?;
+ attrs.extend(inner_attrs);
+ let mut items = Vec::new();
+ while !content.is_empty() {
+ items.push(content.parse()?);
+ }
+ Ok(ItemVerbatim::ImplFlexible(ImplFlexible {
+ attrs,
+ vis,
+ defaultness,
+ unsafety,
+ generics,
+ constness,
+ negative_impl,
+ trait_,
+ self_ty,
+ items,
+ }))
+ } else if lookahead.peek(Token![macro]) {
+ input.parse::<Token![macro]>()?;
+ let ident: Ident = input.parse()?;
+ let args = if input.peek(token::Paren) {
+ let paren_content;
+ parenthesized!(paren_content in input);
+ Some(paren_content.parse::<TokenStream>()?)
+ } else {
+ None
+ };
+ let brace_content;
+ braced!(brace_content in input);
+ let body: TokenStream = brace_content.parse()?;
+ Ok(ItemVerbatim::Macro2(Macro2 {
+ attrs,
+ vis,
+ ident,
+ args,
+ body,
+ }))
+ } else if lookahead.peek(Token![static]) {
+ let flexible_item = FlexibleItemStatic::parse(attrs, vis, input)?;
+ Ok(ItemVerbatim::StaticFlexible(flexible_item))
+ } else if lookahead.peek(Token![type]) {
+ let defaultness = false;
+ let flexible_item = FlexibleItemType::parse(
+ attrs,
+ vis,
+ defaultness,
+ input,
+ WhereClauseLocation::BeforeEq,
+ )?;
+ Ok(ItemVerbatim::TypeFlexible(flexible_item))
+ } else if lookahead.peek(Token![use]) {
+ input.parse::<Token![use]>()?;
+ let content;
+ braced!(content in input);
+ let trees = content.parse_terminated(RootUseTree::parse, Token![,])?;
+ input.parse::<Token![;]>()?;
+ Ok(ItemVerbatim::UseBrace(UseBrace { attrs, vis, trees }))
+ } else {
+ Err(lookahead.error())
+ }
+ }
+ }
+
+ let item: ItemVerbatim = match syn::parse2(tokens.clone()) {
+ Ok(item) => item,
+ Err(_) => unimplemented!("Item::Verbatim `{}`", tokens),
+ };
+
+ match item {
+ ItemVerbatim::Empty => {
+ self.hardbreak();
+ }
+ ItemVerbatim::Ellipsis => {
+ self.word("...");
+ self.hardbreak();
+ }
+ ItemVerbatim::ConstFlexible(item) => {
+ self.flexible_item_const(&item);
+ }
+ ItemVerbatim::FnFlexible(item) => {
+ self.flexible_item_fn(&item);
+ }
+ ItemVerbatim::ImplFlexible(item) => {
+ self.outer_attrs(&item.attrs);
+ self.cbox(INDENT);
+ self.ibox(-INDENT);
+ self.cbox(INDENT);
+ self.visibility(&item.vis);
+ if item.defaultness {
+ self.word("default ");
+ }
+ if item.unsafety {
+ self.word("unsafe ");
+ }
+ self.word("impl");
+ self.generics(&item.generics);
+ self.end();
+ self.nbsp();
+ match item.constness {
+ ImplConstness::None => {}
+ ImplConstness::MaybeConst => self.word("?const "),
+ ImplConstness::Const => self.word("const "),
+ }
+ if item.negative_impl {
+ self.word("!");
+ }
+ if let Some(trait_) = &item.trait_ {
+ self.ty(trait_);
+ self.space();
+ self.word("for ");
+ }
+ self.ty(&item.self_ty);
+ self.end();
+ self.where_clause_for_body(&item.generics.where_clause);
+ self.word("{");
+ self.hardbreak_if_nonempty();
+ self.inner_attrs(&item.attrs);
+ for impl_item in &item.items {
+ self.impl_item(impl_item);
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word("}");
+ self.hardbreak();
+ }
+ ItemVerbatim::Macro2(item) => {
+ self.outer_attrs(&item.attrs);
+ self.visibility(&item.vis);
+ self.word("macro ");
+ self.ident(&item.ident);
+ if let Some(args) = &item.args {
+ self.word("(");
+ self.cbox(INDENT);
+ self.zerobreak();
+ self.ibox(0);
+ self.macro_rules_tokens(args.clone(), true);
+ self.end();
+ self.zerobreak();
+ self.offset(-INDENT);
+ self.end();
+ self.word(")");
+ }
+ self.word(" {");
+ if !item.body.is_empty() {
+ self.neverbreak();
+ self.cbox(INDENT);
+ self.hardbreak();
+ self.ibox(0);
+ self.macro_rules_tokens(item.body.clone(), false);
+ self.end();
+ self.hardbreak();
+ self.offset(-INDENT);
+ self.end();
+ }
+ self.word("}");
+ self.hardbreak();
+ }
+ ItemVerbatim::StaticFlexible(item) => {
+ self.flexible_item_static(&item);
+ }
+ ItemVerbatim::TypeFlexible(item) => {
+ self.flexible_item_type(&item);
+ }
+ ItemVerbatim::UseBrace(item) => {
+ self.outer_attrs(&item.attrs);
+ self.visibility(&item.vis);
+ self.word("use ");
+ if item.trees.len() == 1 {
+ self.word("::");
+ self.use_tree(&item.trees[0].inner);
+ } else {
+ self.cbox(INDENT);
+ self.word("{");
+ self.zerobreak();
+ self.ibox(0);
+ for use_tree in item.trees.iter().delimited() {
+ if use_tree.leading_colon.is_some() {
+ self.word("::");
+ }
+ self.use_tree(&use_tree.inner);
+ if !use_tree.is_last {
+ self.word(",");
+ let mut use_tree = &use_tree.inner;
+ while let UseTree::Path(use_path) = use_tree {
+ use_tree = &use_path.tree;
+ }
+ if let UseTree::Group(_) = use_tree {
+ self.hardbreak();
+ } else {
+ self.space();
+ }
+ }
+ }
+ self.end();
+ self.trailing_comma(true);
+ self.offset(-INDENT);
+ self.word("}");
+ self.end();
+ }
+ self.word(";");
+ self.hardbreak();
+ }
+ }
+ }
+
+ fn use_tree(&mut self, use_tree: &UseTree) {
+ match use_tree {
+ UseTree::Path(use_path) => self.use_path(use_path),
+ UseTree::Name(use_name) => self.use_name(use_name),
+ UseTree::Rename(use_rename) => self.use_rename(use_rename),
+ UseTree::Glob(use_glob) => self.use_glob(use_glob),
+ UseTree::Group(use_group) => self.use_group(use_group),
+ }
+ }
+
+ fn use_path(&mut self, use_path: &UsePath) {
+ self.ident(&use_path.ident);
+ self.word("::");
+ self.use_tree(&use_path.tree);
+ }
+
+ fn use_name(&mut self, use_name: &UseName) {
+ self.ident(&use_name.ident);
+ }
+
+ fn use_rename(&mut self, use_rename: &UseRename) {
+ self.ident(&use_rename.ident);
+ self.word(" as ");
+ self.ident(&use_rename.rename);
+ }
+
+ fn use_glob(&mut self, use_glob: &UseGlob) {
+ let _ = use_glob;
+ self.word("*");
+ }
+
+ fn use_group(&mut self, use_group: &UseGroup) {
+ if use_group.items.is_empty() {
+ self.word("{}");
+ } else if use_group.items.len() == 1
+ && match &use_group.items[0] {
+ UseTree::Rename(use_rename) => use_rename.ident != "self",
+ _ => true,
+ }
+ {
+ self.use_tree(&use_group.items[0]);
+ } else {
+ self.cbox(INDENT);
+ self.word("{");
+ self.zerobreak();
+ self.ibox(0);
+ for use_tree in use_group.items.iter().delimited() {
+ self.use_tree(&use_tree);
+ if !use_tree.is_last {
+ self.word(",");
+ let mut use_tree = *use_tree;
+ while let UseTree::Path(use_path) = use_tree {
+ use_tree = &use_path.tree;
+ }
+ if let UseTree::Group(_) = use_tree {
+ self.hardbreak();
+ } else {
+ self.space();
+ }
+ }
+ }
+ self.end();
+ self.trailing_comma(true);
+ self.offset(-INDENT);
+ self.word("}");
+ self.end();
+ }
+ }
+
+ fn foreign_item(&mut self, foreign_item: &ForeignItem) {
+ match foreign_item {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ ForeignItem::Fn(item) => self.foreign_item_fn(item),
+ ForeignItem::Static(item) => self.foreign_item_static(item),
+ ForeignItem::Type(item) => self.foreign_item_type(item),
+ ForeignItem::Macro(item) => self.foreign_item_macro(item),
+ ForeignItem::Verbatim(item) => self.foreign_item_verbatim(item),
+ _ => unimplemented!("unknown ForeignItem"),
+ }
+ }
+
+ fn foreign_item_fn(&mut self, foreign_item: &ForeignItemFn) {
+ self.outer_attrs(&foreign_item.attrs);
+ self.cbox(INDENT);
+ self.visibility(&foreign_item.vis);
+ self.signature(
+ &foreign_item.sig,
+ #[cfg(feature = "verbatim")]
+ &verbatim::Safety::Disallowed,
+ );
+ self.where_clause_semi(&foreign_item.sig.generics.where_clause);
+ self.end();
+ self.hardbreak();
+ }
+
+ fn foreign_item_static(&mut self, foreign_item: &ForeignItemStatic) {
+ self.outer_attrs(&foreign_item.attrs);
+ self.cbox(0);
+ self.visibility(&foreign_item.vis);
+ self.word("static ");
+ self.static_mutability(&foreign_item.mutability);
+ self.ident(&foreign_item.ident);
+ self.word(": ");
+ self.ty(&foreign_item.ty);
+ self.word(";");
+ self.end();
+ self.hardbreak();
+ }
+
+ fn foreign_item_type(&mut self, foreign_item: &ForeignItemType) {
+ self.outer_attrs(&foreign_item.attrs);
+ self.cbox(0);
+ self.visibility(&foreign_item.vis);
+ self.word("type ");
+ self.ident(&foreign_item.ident);
+ self.generics(&foreign_item.generics);
+ self.word(";");
+ self.end();
+ self.hardbreak();
+ }
+
+ fn foreign_item_macro(&mut self, foreign_item: &ForeignItemMacro) {
+ self.outer_attrs(&foreign_item.attrs);
+ let semicolon = mac::requires_semi(&foreign_item.mac.delimiter);
+ self.mac(&foreign_item.mac, None, semicolon);
+ self.hardbreak();
+ }
+
+ #[cfg(not(feature = "verbatim"))]
+ fn foreign_item_verbatim(&mut self, foreign_item: &TokenStream) {
+ if !foreign_item.is_empty() {
+ unimplemented!("ForeignItem::Verbatim `{}`", foreign_item);
+ }
+ self.hardbreak();
+ }
+
+ #[cfg(feature = "verbatim")]
+ fn foreign_item_verbatim(&mut self, tokens: &TokenStream) {
+ use syn::parse::{Parse, ParseStream, Result};
+ use syn::{Abi, Attribute, Token, Visibility};
+ use verbatim::{
+ kw, FlexibleItemFn, FlexibleItemStatic, FlexibleItemType, WhereClauseLocation,
+ };
+
+ enum ForeignItemVerbatim {
+ Empty,
+ Ellipsis,
+ FnFlexible(FlexibleItemFn),
+ StaticFlexible(FlexibleItemStatic),
+ TypeFlexible(FlexibleItemType),
+ }
+
+ fn peek_signature(input: ParseStream) -> bool {
+ let fork = input.fork();
+ fork.parse::<Option<Token![const]>>().is_ok()
+ && fork.parse::<Option<Token![async]>>().is_ok()
+ && ((fork.peek(kw::safe) && fork.parse::<kw::safe>().is_ok())
+ || fork.parse::<Option<Token![unsafe]>>().is_ok())
+ && fork.parse::<Option<Abi>>().is_ok()
+ && fork.peek(Token![fn])
+ }
+
+ impl Parse for ForeignItemVerbatim {
+ fn parse(input: ParseStream) -> Result<Self> {
+ if input.is_empty() {
+ return Ok(ForeignItemVerbatim::Empty);
+ } else if input.peek(Token![...]) {
+ input.parse::<Token![...]>()?;
+ return Ok(ForeignItemVerbatim::Ellipsis);
+ }
+
+ let attrs = input.call(Attribute::parse_outer)?;
+ let vis: Visibility = input.parse()?;
+ let defaultness = false;
+
+ let lookahead = input.lookahead1();
+ if lookahead.peek(Token![fn]) || peek_signature(input) {
+ let flexible_item = FlexibleItemFn::parse(attrs, vis, defaultness, input)?;
+ Ok(ForeignItemVerbatim::FnFlexible(flexible_item))
+ } else if lookahead.peek(Token![static])
+ || ((input.peek(Token![unsafe]) || input.peek(kw::safe))
+ && input.peek2(Token![static]))
+ {
+ let flexible_item = FlexibleItemStatic::parse(attrs, vis, input)?;
+ Ok(ForeignItemVerbatim::StaticFlexible(flexible_item))
+ } else if lookahead.peek(Token![type]) {
+ let flexible_item = FlexibleItemType::parse(
+ attrs,
+ vis,
+ defaultness,
+ input,
+ WhereClauseLocation::Both,
+ )?;
+ Ok(ForeignItemVerbatim::TypeFlexible(flexible_item))
+ } else {
+ Err(lookahead.error())
+ }
+ }
+ }
+
+ let foreign_item: ForeignItemVerbatim = match syn::parse2(tokens.clone()) {
+ Ok(foreign_item) => foreign_item,
+ Err(_) => unimplemented!("ForeignItem::Verbatim `{}`", tokens),
+ };
+
+ match foreign_item {
+ ForeignItemVerbatim::Empty => {
+ self.hardbreak();
+ }
+ ForeignItemVerbatim::Ellipsis => {
+ self.word("...");
+ self.hardbreak();
+ }
+ ForeignItemVerbatim::FnFlexible(foreign_item) => {
+ self.flexible_item_fn(&foreign_item);
+ }
+ ForeignItemVerbatim::StaticFlexible(foreign_item) => {
+ self.flexible_item_static(&foreign_item);
+ }
+ ForeignItemVerbatim::TypeFlexible(foreign_item) => {
+ self.flexible_item_type(&foreign_item);
+ }
+ }
+ }
+
+ fn trait_item(&mut self, trait_item: &TraitItem) {
+ match trait_item {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ TraitItem::Const(item) => self.trait_item_const(item),
+ TraitItem::Fn(item) => self.trait_item_fn(item),
+ TraitItem::Type(item) => self.trait_item_type(item),
+ TraitItem::Macro(item) => self.trait_item_macro(item),
+ TraitItem::Verbatim(item) => self.trait_item_verbatim(item),
+ _ => unimplemented!("unknown TraitItem"),
+ }
+ }
+
+ fn trait_item_const(&mut self, trait_item: &TraitItemConst) {
+ self.outer_attrs(&trait_item.attrs);
+ self.cbox(0);
+ self.word("const ");
+ self.ident(&trait_item.ident);
+ self.generics(&trait_item.generics);
+ self.word(": ");
+ self.ty(&trait_item.ty);
+ if let Some((_eq_token, default)) = &trait_item.default {
+ self.word(" = ");
+ self.neverbreak();
+ self.expr(default, FixupContext::NONE);
+ }
+ self.word(";");
+ self.end();
+ self.hardbreak();
+ }
+
+ fn trait_item_fn(&mut self, trait_item: &TraitItemFn) {
+ self.outer_attrs(&trait_item.attrs);
+ self.cbox(INDENT);
+ self.signature(
+ &trait_item.sig,
+ #[cfg(feature = "verbatim")]
+ &verbatim::Safety::Disallowed,
+ );
+ if let Some(block) = &trait_item.default {
+ self.where_clause_for_body(&trait_item.sig.generics.where_clause);
+ self.word("{");
+ self.hardbreak_if_nonempty();
+ self.inner_attrs(&trait_item.attrs);
+ for stmt in block.stmts.iter().delimited() {
+ self.stmt(&stmt, stmt.is_last);
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word("}");
+ } else {
+ self.where_clause_semi(&trait_item.sig.generics.where_clause);
+ self.end();
+ }
+ self.hardbreak();
+ }
+
+ fn trait_item_type(&mut self, trait_item: &TraitItemType) {
+ self.outer_attrs(&trait_item.attrs);
+ self.cbox(INDENT);
+ self.word("type ");
+ self.ident(&trait_item.ident);
+ self.generics(&trait_item.generics);
+ for bound in trait_item.bounds.iter().delimited() {
+ if bound.is_first {
+ self.word(": ");
+ } else {
+ self.space();
+ self.word("+ ");
+ }
+ self.type_param_bound(&bound);
+ }
+ if let Some((_eq_token, default)) = &trait_item.default {
+ self.word(" = ");
+ self.neverbreak();
+ self.ibox(-INDENT);
+ self.ty(default);
+ self.end();
+ }
+ self.where_clause_oneline_semi(&trait_item.generics.where_clause);
+ self.end();
+ self.hardbreak();
+ }
+
+ fn trait_item_macro(&mut self, trait_item: &TraitItemMacro) {
+ self.outer_attrs(&trait_item.attrs);
+ let semicolon = mac::requires_semi(&trait_item.mac.delimiter);
+ self.mac(&trait_item.mac, None, semicolon);
+ self.hardbreak();
+ }
+
+ #[cfg(not(feature = "verbatim"))]
+ fn trait_item_verbatim(&mut self, trait_item: &TokenStream) {
+ if !trait_item.is_empty() {
+ unimplemented!("TraitItem::Verbatim `{}`", trait_item);
+ }
+ self.hardbreak();
+ }
+
+ #[cfg(feature = "verbatim")]
+ fn trait_item_verbatim(&mut self, tokens: &TokenStream) {
+ use syn::parse::{Parse, ParseStream, Result};
+ use syn::{Attribute, Ident, Token, Visibility};
+ use verbatim::{FlexibleItemConst, FlexibleItemType, WhereClauseLocation};
+
+ enum TraitItemVerbatim {
+ Empty,
+ Ellipsis,
+ ConstFlexible(FlexibleItemConst),
+ TypeFlexible(FlexibleItemType),
+ PubOrDefault(PubOrDefaultTraitItem),
+ }
+
+ struct PubOrDefaultTraitItem {
+ attrs: Vec<Attribute>,
+ vis: Visibility,
+ defaultness: bool,
+ trait_item: TraitItem,
+ }
+
+ impl Parse for TraitItemVerbatim {
+ fn parse(input: ParseStream) -> Result<Self> {
+ if input.is_empty() {
+ return Ok(TraitItemVerbatim::Empty);
+ } else if input.peek(Token![...]) {
+ input.parse::<Token![...]>()?;
+ return Ok(TraitItemVerbatim::Ellipsis);
+ }
+
+ let attrs = input.call(Attribute::parse_outer)?;
+ let vis: Visibility = input.parse()?;
+ let defaultness = input.parse::<Option<Token![default]>>()?.is_some();
+
+ let lookahead = input.lookahead1();
+ if lookahead.peek(Token![const]) && (input.peek2(Ident) || input.peek2(Token![_])) {
+ let flexible_item = FlexibleItemConst::parse(attrs, vis, defaultness, input)?;
+ Ok(TraitItemVerbatim::ConstFlexible(flexible_item))
+ } else if lookahead.peek(Token![type]) {
+ let flexible_item = FlexibleItemType::parse(
+ attrs,
+ vis,
+ defaultness,
+ input,
+ WhereClauseLocation::AfterEq,
+ )?;
+ Ok(TraitItemVerbatim::TypeFlexible(flexible_item))
+ } else if (input.peek(Token![const])
+ || lookahead.peek(Token![async])
+ || lookahead.peek(Token![unsafe])
+ || lookahead.peek(Token![extern])
+ || lookahead.peek(Token![fn]))
+ && (!matches!(vis, Visibility::Inherited) || defaultness)
+ {
+ Ok(TraitItemVerbatim::PubOrDefault(PubOrDefaultTraitItem {
+ attrs,
+ vis,
+ defaultness,
+ trait_item: input.parse()?,
+ }))
+ } else {
+ Err(lookahead.error())
+ }
+ }
+ }
+
+ let impl_item: TraitItemVerbatim = match syn::parse2(tokens.clone()) {
+ Ok(impl_item) => impl_item,
+ Err(_) => unimplemented!("TraitItem::Verbatim `{}`", tokens),
+ };
+
+ match impl_item {
+ TraitItemVerbatim::Empty => {
+ self.hardbreak();
+ }
+ TraitItemVerbatim::Ellipsis => {
+ self.word("...");
+ self.hardbreak();
+ }
+ TraitItemVerbatim::ConstFlexible(trait_item) => {
+ self.flexible_item_const(&trait_item);
+ }
+ TraitItemVerbatim::TypeFlexible(trait_item) => {
+ self.flexible_item_type(&trait_item);
+ }
+ TraitItemVerbatim::PubOrDefault(trait_item) => {
+ self.outer_attrs(&trait_item.attrs);
+ self.visibility(&trait_item.vis);
+ if trait_item.defaultness {
+ self.word("default ");
+ }
+ self.trait_item(&trait_item.trait_item);
+ }
+ }
+ }
+
+ fn impl_item(&mut self, impl_item: &ImplItem) {
+ match impl_item {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ ImplItem::Const(item) => self.impl_item_const(item),
+ ImplItem::Fn(item) => self.impl_item_fn(item),
+ ImplItem::Type(item) => self.impl_item_type(item),
+ ImplItem::Macro(item) => self.impl_item_macro(item),
+ ImplItem::Verbatim(item) => self.impl_item_verbatim(item),
+ _ => unimplemented!("unknown ImplItem"),
+ }
+ }
+
+ fn impl_item_const(&mut self, impl_item: &ImplItemConst) {
+ self.outer_attrs(&impl_item.attrs);
+ self.cbox(0);
+ self.visibility(&impl_item.vis);
+ if impl_item.defaultness.is_some() {
+ self.word("default ");
+ }
+ self.word("const ");
+ self.ident(&impl_item.ident);
+ self.generics(&impl_item.generics);
+ self.word(": ");
+ self.ty(&impl_item.ty);
+ self.word(" = ");
+ self.neverbreak();
+ self.expr(&impl_item.expr, FixupContext::NONE);
+ self.word(";");
+ self.end();
+ self.hardbreak();
+ }
+
+ fn impl_item_fn(&mut self, impl_item: &ImplItemFn) {
+ self.outer_attrs(&impl_item.attrs);
+ self.cbox(INDENT);
+ self.visibility(&impl_item.vis);
+ if impl_item.defaultness.is_some() {
+ self.word("default ");
+ }
+ self.signature(
+ &impl_item.sig,
+ #[cfg(feature = "verbatim")]
+ &verbatim::Safety::Disallowed,
+ );
+ self.where_clause_for_body(&impl_item.sig.generics.where_clause);
+ self.word("{");
+ self.hardbreak_if_nonempty();
+ self.inner_attrs(&impl_item.attrs);
+ for stmt in impl_item.block.stmts.iter().delimited() {
+ self.stmt(&stmt, stmt.is_last);
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word("}");
+ self.hardbreak();
+ }
+
+ fn impl_item_type(&mut self, impl_item: &ImplItemType) {
+ self.outer_attrs(&impl_item.attrs);
+ self.cbox(INDENT);
+ self.visibility(&impl_item.vis);
+ if impl_item.defaultness.is_some() {
+ self.word("default ");
+ }
+ self.word("type ");
+ self.ident(&impl_item.ident);
+ self.generics(&impl_item.generics);
+ self.word(" = ");
+ self.neverbreak();
+ self.ibox(-INDENT);
+ self.ty(&impl_item.ty);
+ self.end();
+ self.where_clause_oneline_semi(&impl_item.generics.where_clause);
+ self.end();
+ self.hardbreak();
+ }
+
+ fn impl_item_macro(&mut self, impl_item: &ImplItemMacro) {
+ self.outer_attrs(&impl_item.attrs);
+ let semicolon = mac::requires_semi(&impl_item.mac.delimiter);
+ self.mac(&impl_item.mac, None, semicolon);
+ self.hardbreak();
+ }
+
+ #[cfg(not(feature = "verbatim"))]
+ fn impl_item_verbatim(&mut self, impl_item: &TokenStream) {
+ if !impl_item.is_empty() {
+ unimplemented!("ImplItem::Verbatim `{}`", impl_item);
+ }
+ self.hardbreak();
+ }
+
+ #[cfg(feature = "verbatim")]
+ fn impl_item_verbatim(&mut self, tokens: &TokenStream) {
+ use syn::parse::{Parse, ParseStream, Result};
+ use syn::{Attribute, Ident, Token, Visibility};
+ use verbatim::{FlexibleItemConst, FlexibleItemFn, FlexibleItemType, WhereClauseLocation};
+
+ enum ImplItemVerbatim {
+ Empty,
+ Ellipsis,
+ ConstFlexible(FlexibleItemConst),
+ FnFlexible(FlexibleItemFn),
+ TypeFlexible(FlexibleItemType),
+ }
+
+ impl Parse for ImplItemVerbatim {
+ fn parse(input: ParseStream) -> Result<Self> {
+ if input.is_empty() {
+ return Ok(ImplItemVerbatim::Empty);
+ } else if input.peek(Token![...]) {
+ input.parse::<Token![...]>()?;
+ return Ok(ImplItemVerbatim::Ellipsis);
+ }
+
+ let attrs = input.call(Attribute::parse_outer)?;
+ let vis: Visibility = input.parse()?;
+ let defaultness = input.parse::<Option<Token![default]>>()?.is_some();
+
+ let lookahead = input.lookahead1();
+ if lookahead.peek(Token![const]) && (input.peek2(Ident) || input.peek2(Token![_])) {
+ let flexible_item = FlexibleItemConst::parse(attrs, vis, defaultness, input)?;
+ Ok(ImplItemVerbatim::ConstFlexible(flexible_item))
+ } else if input.peek(Token![const])
+ || lookahead.peek(Token![async])
+ || lookahead.peek(Token![unsafe])
+ || lookahead.peek(Token![extern])
+ || lookahead.peek(Token![fn])
+ {
+ let flexible_item = FlexibleItemFn::parse(attrs, vis, defaultness, input)?;
+ Ok(ImplItemVerbatim::FnFlexible(flexible_item))
+ } else if lookahead.peek(Token![type]) {
+ let flexible_item = FlexibleItemType::parse(
+ attrs,
+ vis,
+ defaultness,
+ input,
+ WhereClauseLocation::AfterEq,
+ )?;
+ Ok(ImplItemVerbatim::TypeFlexible(flexible_item))
+ } else {
+ Err(lookahead.error())
+ }
+ }
+ }
+
+ let impl_item: ImplItemVerbatim = match syn::parse2(tokens.clone()) {
+ Ok(impl_item) => impl_item,
+ Err(_) => unimplemented!("ImplItem::Verbatim `{}`", tokens),
+ };
+
+ match impl_item {
+ ImplItemVerbatim::Empty => {
+ self.hardbreak();
+ }
+ ImplItemVerbatim::Ellipsis => {
+ self.word("...");
+ self.hardbreak();
+ }
+ ImplItemVerbatim::ConstFlexible(impl_item) => {
+ self.flexible_item_const(&impl_item);
+ }
+ ImplItemVerbatim::FnFlexible(impl_item) => {
+ self.flexible_item_fn(&impl_item);
+ }
+ ImplItemVerbatim::TypeFlexible(impl_item) => {
+ self.flexible_item_type(&impl_item);
+ }
+ }
+ }
+
+ fn signature(
+ &mut self,
+ signature: &Signature,
+ #[cfg(feature = "verbatim")] safety: &verbatim::Safety,
+ ) {
+ if signature.constness.is_some() {
+ self.word("const ");
+ }
+ if signature.asyncness.is_some() {
+ self.word("async ");
+ }
+ #[cfg(feature = "verbatim")]
+ {
+ if let verbatim::Safety::Disallowed = safety {
+ if signature.unsafety.is_some() {
+ self.word("unsafe ");
+ }
+ } else {
+ self.safety(safety);
+ }
+ }
+ #[cfg(not(feature = "verbatim"))]
+ {
+ if signature.unsafety.is_some() {
+ self.word("unsafe ");
+ }
+ }
+ if let Some(abi) = &signature.abi {
+ self.abi(abi);
+ }
+ self.word("fn ");
+ self.ident(&signature.ident);
+ self.generics(&signature.generics);
+ self.word("(");
+ self.neverbreak();
+ self.cbox(0);
+ self.zerobreak();
+ for input in signature.inputs.iter().delimited() {
+ self.fn_arg(&input);
+ let is_last = input.is_last && signature.variadic.is_none();
+ self.trailing_comma(is_last);
+ }
+ if let Some(variadic) = &signature.variadic {
+ self.variadic(variadic);
+ self.zerobreak();
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word(")");
+ self.cbox(-INDENT);
+ self.return_type(&signature.output);
+ self.end();
+ }
+
+ fn fn_arg(&mut self, fn_arg: &FnArg) {
+ match fn_arg {
+ FnArg::Receiver(receiver) => self.receiver(receiver),
+ FnArg::Typed(pat_type) => self.pat_type(pat_type),
+ }
+ }
+
+ fn receiver(&mut self, receiver: &Receiver) {
+ self.outer_attrs(&receiver.attrs);
+ if let Some((_ampersand, lifetime)) = &receiver.reference {
+ self.word("&");
+ if let Some(lifetime) = lifetime {
+ self.lifetime(lifetime);
+ self.nbsp();
+ }
+ }
+ if receiver.mutability.is_some() {
+ self.word("mut ");
+ }
+ self.word("self");
+ if receiver.colon_token.is_some() {
+ self.word(": ");
+ self.ty(&receiver.ty);
+ } else {
+ let consistent = match (&receiver.reference, &receiver.mutability, &*receiver.ty) {
+ (Some(_), mutability, Type::Reference(ty)) => {
+ mutability.is_some() == ty.mutability.is_some()
+ && match &*ty.elem {
+ Type::Path(ty) => ty.qself.is_none() && ty.path.is_ident("Self"),
+ _ => false,
+ }
+ }
+ (None, _, Type::Path(ty)) => ty.qself.is_none() && ty.path.is_ident("Self"),
+ _ => false,
+ };
+ if !consistent {
+ self.word(": ");
+ self.ty(&receiver.ty);
+ }
+ }
+ }
+
+ fn variadic(&mut self, variadic: &Variadic) {
+ self.outer_attrs(&variadic.attrs);
+ if let Some((pat, _colon)) = &variadic.pat {
+ self.pat(pat);
+ self.word(": ");
+ }
+ self.word("...");
+ }
+
+ fn static_mutability(&mut self, mutability: &StaticMutability) {
+ match mutability {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ StaticMutability::Mut(_) => self.word("mut "),
+ StaticMutability::None => {}
+ _ => unimplemented!("unknown StaticMutability"),
+ }
+ }
+}
+
+#[cfg(feature = "verbatim")]
+mod verbatim {
+ use crate::algorithm::Printer;
+ use crate::fixup::FixupContext;
+ use crate::iter::IterDelimited;
+ use crate::INDENT;
+ use syn::ext::IdentExt;
+ use syn::parse::{Parse, ParseStream, Result};
+ use syn::{
+ braced, token, Attribute, Block, Expr, Generics, Ident, Signature, StaticMutability, Stmt,
+ Token, Type, TypeParamBound, Visibility, WhereClause,
+ };
+
+ pub mod kw {
+ syn::custom_keyword!(safe);
+ }
+
+ pub struct FlexibleItemConst {
+ pub attrs: Vec<Attribute>,
+ pub vis: Visibility,
+ pub defaultness: bool,
+ pub ident: Ident,
+ pub generics: Generics,
+ pub ty: Type,
+ pub value: Option<Expr>,
+ }
+
+ pub struct FlexibleItemFn {
+ pub attrs: Vec<Attribute>,
+ pub vis: Visibility,
+ pub defaultness: bool,
+ pub safety: Safety,
+ pub sig: Signature,
+ pub body: Option<Vec<Stmt>>,
+ }
+
+ pub struct FlexibleItemStatic {
+ pub attrs: Vec<Attribute>,
+ pub vis: Visibility,
+ pub safety: Safety,
+ pub mutability: StaticMutability,
+ pub ident: Ident,
+ pub ty: Option<Type>,
+ pub expr: Option<Expr>,
+ }
+
+ pub struct FlexibleItemType {
+ pub attrs: Vec<Attribute>,
+ pub vis: Visibility,
+ pub defaultness: bool,
+ pub ident: Ident,
+ pub generics: Generics,
+ pub bounds: Vec<TypeParamBound>,
+ pub definition: Option<Type>,
+ pub where_clause_after_eq: Option<WhereClause>,
+ }
+
+ pub enum Safety {
+ Unsafe,
+ Safe,
+ Default,
+ Disallowed,
+ }
+
+ pub enum WhereClauseLocation {
+ // type Ty<T> where T: 'static = T;
+ BeforeEq,
+ // type Ty<T> = T where T: 'static;
+ AfterEq,
+ // TODO: goes away once the migration period on rust-lang/rust#89122 is over
+ Both,
+ }
+
+ impl FlexibleItemConst {
+ pub fn parse(
+ attrs: Vec<Attribute>,
+ vis: Visibility,
+ defaultness: bool,
+ input: ParseStream,
+ ) -> Result<Self> {
+ input.parse::<Token![const]>()?;
+ let ident = input.call(Ident::parse_any)?;
+ let mut generics: Generics = input.parse()?;
+ input.parse::<Token![:]>()?;
+ let ty: Type = input.parse()?;
+ let value = if input.parse::<Option<Token![=]>>()?.is_some() {
+ let expr: Expr = input.parse()?;
+ Some(expr)
+ } else {
+ None
+ };
+ generics.where_clause = input.parse()?;
+ input.parse::<Token![;]>()?;
+
+ Ok(FlexibleItemConst {
+ attrs,
+ vis,
+ defaultness,
+ ident,
+ generics,
+ ty,
+ value,
+ })
+ }
+ }
+
+ impl FlexibleItemFn {
+ pub fn parse(
+ mut attrs: Vec<Attribute>,
+ vis: Visibility,
+ defaultness: bool,
+ input: ParseStream,
+ ) -> Result<Self> {
+ let constness: Option<Token![const]> = input.parse()?;
+ let asyncness: Option<Token![async]> = input.parse()?;
+ let safety: Safety = input.parse()?;
+
+ let lookahead = input.lookahead1();
+ let sig: Signature = if lookahead.peek(Token![extern]) || lookahead.peek(Token![fn]) {
+ input.parse()?
+ } else {
+ return Err(lookahead.error());
+ };
+
+ let lookahead = input.lookahead1();
+ let body = if lookahead.peek(Token![;]) {
+ input.parse::<Token![;]>()?;
+ None
+ } else if lookahead.peek(token::Brace) {
+ let content;
+ braced!(content in input);
+ attrs.extend(content.call(Attribute::parse_inner)?);
+ Some(content.call(Block::parse_within)?)
+ } else {
+ return Err(lookahead.error());
+ };
+
+ Ok(FlexibleItemFn {
+ attrs,
+ vis,
+ defaultness,
+ safety,
+ sig: Signature {
+ constness,
+ asyncness,
+ unsafety: None,
+ ..sig
+ },
+ body,
+ })
+ }
+ }
+
+ impl FlexibleItemStatic {
+ pub fn parse(attrs: Vec<Attribute>, vis: Visibility, input: ParseStream) -> Result<Self> {
+ let safety: Safety = input.parse()?;
+ input.parse::<Token![static]>()?;
+ let mutability: StaticMutability = input.parse()?;
+ let ident = input.parse()?;
+
+ let lookahead = input.lookahead1();
+ let has_type = lookahead.peek(Token![:]);
+ let has_expr = lookahead.peek(Token![=]);
+ if !has_type && !has_expr {
+ return Err(lookahead.error());
+ }
+
+ let ty: Option<Type> = if has_type {
+ input.parse::<Token![:]>()?;
+ input.parse().map(Some)?
+ } else {
+ None
+ };
+
+ let expr: Option<Expr> = if input.parse::<Option<Token![=]>>()?.is_some() {
+ input.parse().map(Some)?
+ } else {
+ None
+ };
+
+ input.parse::<Token![;]>()?;
+
+ Ok(FlexibleItemStatic {
+ attrs,
+ vis,
+ safety,
+ mutability,
+ ident,
+ ty,
+ expr,
+ })
+ }
+ }
+
+ impl FlexibleItemType {
+ pub fn parse(
+ attrs: Vec<Attribute>,
+ vis: Visibility,
+ defaultness: bool,
+ input: ParseStream,
+ where_clause_location: WhereClauseLocation,
+ ) -> Result<Self> {
+ input.parse::<Token![type]>()?;
+ let ident: Ident = input.parse()?;
+ let mut generics: Generics = input.parse()?;
+
+ let mut bounds = Vec::new();
+ if input.parse::<Option<Token![:]>>()?.is_some() {
+ loop {
+ if input.peek(Token![where]) || input.peek(Token![=]) || input.peek(Token![;]) {
+ break;
+ }
+ bounds.push(input.parse::<TypeParamBound>()?);
+ if input.peek(Token![where]) || input.peek(Token![=]) || input.peek(Token![;]) {
+ break;
+ }
+ input.parse::<Token![+]>()?;
+ }
+ }
+
+ match where_clause_location {
+ WhereClauseLocation::BeforeEq | WhereClauseLocation::Both => {
+ generics.where_clause = input.parse()?;
+ }
+ WhereClauseLocation::AfterEq => {}
+ }
+
+ let definition = if input.parse::<Option<Token![=]>>()?.is_some() {
+ Some(input.parse()?)
+ } else {
+ None
+ };
+
+ let where_clause_after_eq = match where_clause_location {
+ WhereClauseLocation::AfterEq | WhereClauseLocation::Both
+ if generics.where_clause.is_none() =>
+ {
+ input.parse()?
+ }
+ _ => None,
+ };
+
+ input.parse::<Token![;]>()?;
+
+ Ok(FlexibleItemType {
+ attrs,
+ vis,
+ defaultness,
+ ident,
+ generics,
+ bounds,
+ definition,
+ where_clause_after_eq,
+ })
+ }
+ }
+
+ impl Parse for Safety {
+ fn parse(input: ParseStream) -> Result<Self> {
+ if input.peek(Token![unsafe]) {
+ input.parse::<Token![unsafe]>()?;
+ Ok(Safety::Unsafe)
+ } else if input.peek(kw::safe) {
+ input.parse::<kw::safe>()?;
+ Ok(Safety::Safe)
+ } else {
+ Ok(Safety::Default)
+ }
+ }
+ }
+
+ impl Printer {
+ pub fn flexible_item_const(&mut self, item: &FlexibleItemConst) {
+ self.outer_attrs(&item.attrs);
+ self.cbox(INDENT);
+ self.visibility(&item.vis);
+ if item.defaultness {
+ self.word("default ");
+ }
+ self.word("const ");
+ self.ident(&item.ident);
+ self.generics(&item.generics);
+ self.word(": ");
+ self.cbox(-INDENT);
+ self.ty(&item.ty);
+ self.end();
+ if let Some(value) = &item.value {
+ self.word(" = ");
+ self.neverbreak();
+ self.ibox(-INDENT);
+ self.expr(value, FixupContext::NONE);
+ self.end();
+ }
+ self.where_clause_oneline_semi(&item.generics.where_clause);
+ self.end();
+ self.hardbreak();
+ }
+
+ pub fn flexible_item_fn(&mut self, item: &FlexibleItemFn) {
+ self.outer_attrs(&item.attrs);
+ self.cbox(INDENT);
+ self.visibility(&item.vis);
+ if item.defaultness {
+ self.word("default ");
+ }
+ self.signature(&item.sig, &item.safety);
+ if let Some(body) = &item.body {
+ self.where_clause_for_body(&item.sig.generics.where_clause);
+ self.word("{");
+ self.hardbreak_if_nonempty();
+ self.inner_attrs(&item.attrs);
+ for stmt in body.iter().delimited() {
+ self.stmt(&stmt, stmt.is_last);
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word("}");
+ } else {
+ self.where_clause_semi(&item.sig.generics.where_clause);
+ self.end();
+ }
+ self.hardbreak();
+ }
+
+ pub fn flexible_item_static(&mut self, item: &FlexibleItemStatic) {
+ self.outer_attrs(&item.attrs);
+ self.cbox(0);
+ self.visibility(&item.vis);
+ self.safety(&item.safety);
+ self.word("static ");
+ self.static_mutability(&item.mutability);
+ self.ident(&item.ident);
+ if let Some(ty) = &item.ty {
+ self.word(": ");
+ self.ty(ty);
+ }
+ if let Some(expr) = &item.expr {
+ self.word(" = ");
+ self.neverbreak();
+ self.expr(expr, FixupContext::NONE);
+ }
+ self.word(";");
+ self.end();
+ self.hardbreak();
+ }
+
+ pub fn flexible_item_type(&mut self, item: &FlexibleItemType) {
+ self.outer_attrs(&item.attrs);
+ self.cbox(INDENT);
+ self.visibility(&item.vis);
+ if item.defaultness {
+ self.word("default ");
+ }
+ self.word("type ");
+ self.ident(&item.ident);
+ self.generics(&item.generics);
+ for bound in item.bounds.iter().delimited() {
+ if bound.is_first {
+ self.word(": ");
+ } else {
+ self.space();
+ self.word("+ ");
+ }
+ self.type_param_bound(&bound);
+ }
+ if let Some(definition) = &item.definition {
+ self.where_clause_oneline(&item.generics.where_clause);
+ self.word("= ");
+ self.neverbreak();
+ self.ibox(-INDENT);
+ self.ty(definition);
+ self.end();
+ self.where_clause_oneline_semi(&item.where_clause_after_eq);
+ } else {
+ self.where_clause_oneline_semi(&item.generics.where_clause);
+ }
+ self.end();
+ self.hardbreak();
+ }
+
+ pub fn safety(&mut self, safety: &Safety) {
+ match safety {
+ Safety::Unsafe => self.word("unsafe "),
+ Safety::Safe => self.word("safe "),
+ Safety::Default => {}
+ Safety::Disallowed => unreachable!(),
+ }
+ }
+ }
+}
diff --git a/vendor/prettyplease/src/iter.rs b/vendor/prettyplease/src/iter.rs
new file mode 100644
index 00000000..702c653f
--- /dev/null
+++ b/vendor/prettyplease/src/iter.rs
@@ -0,0 +1,46 @@
+use std::iter::Peekable;
+use std::ops::Deref;
+
+pub struct Delimited<I: Iterator> {
+ is_first: bool,
+ iter: Peekable<I>,
+}
+
+pub trait IterDelimited: Iterator + Sized {
+ fn delimited(self) -> Delimited<Self> {
+ Delimited {
+ is_first: true,
+ iter: self.peekable(),
+ }
+ }
+}
+
+impl<I: Iterator> IterDelimited for I {}
+
+pub struct IteratorItem<T> {
+ value: T,
+ pub is_first: bool,
+ pub is_last: bool,
+}
+
+impl<I: Iterator> Iterator for Delimited<I> {
+ type Item = IteratorItem<I::Item>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let item = IteratorItem {
+ value: self.iter.next()?,
+ is_first: self.is_first,
+ is_last: self.iter.peek().is_none(),
+ };
+ self.is_first = false;
+ Some(item)
+ }
+}
+
+impl<T> Deref for IteratorItem<T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ &self.value
+ }
+}
diff --git a/vendor/prettyplease/src/lib.rs b/vendor/prettyplease/src/lib.rs
new file mode 100644
index 00000000..ee2b048d
--- /dev/null
+++ b/vendor/prettyplease/src/lib.rs
@@ -0,0 +1,385 @@
+//! [![github]](https://github.com/dtolnay/prettyplease)&ensp;[![crates-io]](https://crates.io/crates/prettyplease)&ensp;[![docs-rs]](https://docs.rs/prettyplease)
+//!
+//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
+//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
+//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
+//!
+//! <br>
+//!
+//! **prettyplease::unparse** &mdash; a minimal `syn` syntax tree pretty-printer
+//!
+//! <br>
+//!
+//! # Overview
+//!
+//! This is a pretty-printer to turn a `syn` syntax tree into a `String` of
+//! well-formatted source code. In contrast to rustfmt, this library is intended
+//! to be suitable for arbitrary generated code.
+//!
+//! Rustfmt prioritizes high-quality output that is impeccable enough that you'd
+//! be comfortable spending your career staring at its output &mdash; but that
+//! means some heavyweight algorithms, and it has a tendency to bail out on code
+//! that is hard to format (for example [rustfmt#3697], and there are dozens
+//! more issues like it). That's not necessarily a big deal for human-generated
+//! code because when code gets highly nested, the human will naturally be
+//! inclined to refactor into more easily formattable code. But for generated
+//! code, having the formatter just give up leaves it totally unreadable.
+//!
+//! [rustfmt#3697]: https://github.com/rust-lang/rustfmt/issues/3697
+//!
+//! This library is designed using the simplest possible algorithm and data
+//! structures that can deliver about 95% of the quality of rustfmt-formatted
+//! output. In my experience testing real-world code, approximately 97-98% of
+//! output lines come out identical between rustfmt's formatting and this
+//! crate's. The rest have slightly different linebreak decisions, but still
+//! clearly follow the dominant modern Rust style.
+//!
+//! The tradeoffs made by this crate are a good fit for generated code that you
+//! will *not* spend your career staring at. For example, the output of
+//! `bindgen`, or the output of `cargo-expand`. In those cases it's more
+//! important that the whole thing be formattable without the formatter giving
+//! up, than that it be flawless.
+//!
+//! <br>
+//!
+//! # Feature matrix
+//!
+//! Here are a few superficial comparisons of this crate against the AST
+//! pretty-printer built into rustc, and rustfmt. The sections below go into
+//! more detail comparing the output of each of these libraries.
+//!
+//! | | prettyplease | rustc | rustfmt |
+//! |:---|:---:|:---:|:---:|
+//! | non-pathological behavior on big or generated code | 💚 | ❌ | ❌ |
+//! | idiomatic modern formatting ("locally indistinguishable from rustfmt") | 💚 | ❌ | 💚 |
+//! | throughput | 60 MB/s | 39 MB/s | 2.8 MB/s |
+//! | number of dependencies | 3 | 72 | 66 |
+//! | compile time including dependencies | 2.4 sec | 23.1 sec | 29.8 sec |
+//! | buildable using a stable Rust compiler | 💚 | ❌ | ❌ |
+//! | published to crates.io | 💚 | ❌ | ❌ |
+//! | extensively configurable output | ❌ | ❌ | 💚 |
+//! | intended to accommodate hand-maintained source code | ❌ | ❌ | 💚 |
+//!
+//! <br>
+//!
+//! # Comparison to rustfmt
+//!
+//! - [input.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/input.rs)
+//! - [output.prettyplease.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/output.prettyplease.rs)
+//! - [output.rustfmt.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/output.rustfmt.rs)
+//!
+//! If you weren't told which output file is which, it would be practically
+//! impossible to tell &mdash; **except** for line 435 in the rustfmt output,
+//! which is more than 1000 characters long because rustfmt just gave up
+//! formatting that part of the file:
+//!
+//! ```
+//! # const _: &str = stringify! {{{
+//! match segments[5] {
+//! 0 => write!(f, "::{}", ipv4),
+//! 0xffff => write!(f, "::ffff:{}", ipv4),
+//! _ => unreachable!(),
+//! }
+//! } else { # [derive (Copy , Clone , Default)] struct Span { start : usize , len : usize , } let zeroes = { let mut longest = Span :: default () ; let mut current = Span :: default () ; for (i , & segment) in segments . iter () . enumerate () { if segment == 0 { if current . len == 0 { current . start = i ; } current . len += 1 ; if current . len > longest . len { longest = current ; } } else { current = Span :: default () ; } } longest } ; # [doc = " Write a colon-separated part of the address"] # [inline] fn fmt_subslice (f : & mut fmt :: Formatter < '_ > , chunk : & [u16]) -> fmt :: Result { if let Some ((first , tail)) = chunk . split_first () { write ! (f , "{:x}" , first) ? ; for segment in tail { f . write_char (':') ? ; write ! (f , "{:x}" , segment) ? ; } } Ok (()) } if zeroes . len > 1 { fmt_subslice (f , & segments [.. zeroes . start]) ? ; f . write_str ("::") ? ; fmt_subslice (f , & segments [zeroes . start + zeroes . len ..]) } else { fmt_subslice (f , & segments) } }
+//! } else {
+//! const IPV6_BUF_LEN: usize = (4 * 8) + 7;
+//! let mut buf = [0u8; IPV6_BUF_LEN];
+//! let mut buf_slice = &mut buf[..];
+//! # }};
+//! ```
+//!
+//! This is a pretty typical manifestation of rustfmt bailing out in generated
+//! code &mdash; a chunk of the input ends up on one line. The other
+//! manifestation is that you're working on some code, running rustfmt on save
+//! like a conscientious developer, but after a while notice it isn't doing
+//! anything. You introduce an intentional formatting issue, like a stray indent
+//! or semicolon, and run rustfmt to check your suspicion. Nope, it doesn't get
+//! cleaned up &mdash; rustfmt is just not formatting the part of the file you
+//! are working on.
+//!
+//! The prettyplease library is designed to have no pathological cases that
+//! force a bail out; the entire input you give it will get formatted in some
+//! "good enough" form.
+//!
+//! Separately, rustfmt can be problematic to integrate into projects. It's
+//! written using rustc's internal syntax tree, so it can't be built by a stable
+//! compiler. Its releases are not regularly published to crates.io, so in Cargo
+//! builds you'd need to depend on it as a git dependency, which precludes
+//! publishing your crate to crates.io also. You can shell out to a `rustfmt`
+//! binary, but that'll be whatever rustfmt version is installed on each
+//! developer's system (if any), which can lead to spurious diffs in checked-in
+//! generated code formatted by different versions. In contrast prettyplease is
+//! designed to be easy to pull in as a library, and compiles fast.
+//!
+//! <br>
+//!
+//! # Comparison to rustc_ast_pretty
+//!
+//! - [input.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/input.rs)
+//! - [output.prettyplease.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/output.prettyplease.rs)
+//! - [output.rustc.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/output.rustc.rs)
+//!
+//! This is the pretty-printer that gets used when rustc prints source code,
+//! such as `rustc -Zunpretty=expanded`. It's used also by the standard
+//! library's `stringify!` when stringifying an interpolated macro_rules AST
+//! fragment, like an $:expr, and transitively by `dbg!` and many macros in the
+//! ecosystem.
+//!
+//! Rustc's formatting is mostly okay, but does not hew closely to the dominant
+//! contemporary style of Rust formatting. Some things wouldn't ever be written
+//! on one line, like this `match` expression, and certainly not with a comma in
+//! front of the closing brace:
+//!
+//! ```
+//! # const _: &str = stringify! {
+//! fn eq(&self, other: &IpAddr) -> bool {
+//! match other { IpAddr::V4(v4) => self == v4, IpAddr::V6(_) => false, }
+//! }
+//! # };
+//! ```
+//!
+//! Some places use non-multiple-of-4 indentation, which is definitely not the
+//! norm:
+//!
+//! ```
+//! # const _: &str = stringify! {
+//! pub const fn to_ipv6_mapped(&self) -> Ipv6Addr {
+//! let [a, b, c, d] = self.octets();
+//! Ipv6Addr{inner:
+//! c::in6_addr{s6_addr:
+//! [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF,
+//! 0xFF, a, b, c, d],},}
+//! }
+//! # };
+//! ```
+//!
+//! And although there isn't an egregious example of it in the link because the
+//! input code is pretty tame, in general rustc_ast_pretty has pathological
+//! behavior on generated code. It has a tendency to use excessive horizontal
+//! indentation and rapidly run out of width:
+//!
+//! ```
+//! # const _: &str = stringify! {
+//! ::std::io::_print(::core::fmt::Arguments::new_v1(&[""],
+//! &match (&msg,) {
+//! _args =>
+//! [::core::fmt::ArgumentV1::new(_args.0,
+//! ::core::fmt::Display::fmt)],
+//! }));
+//! # };
+//! ```
+//!
+//! The snippets above are clearly different from modern rustfmt style. In
+//! contrast, prettyplease is designed to have output that is practically
+//! indistinguishable from rustfmt-formatted code.
+//!
+//! <br>
+//!
+//! # Example
+//!
+//! ```
+//! // [dependencies]
+//! // prettyplease = "0.2"
+//! // syn = { version = "2", default-features = false, features = ["full", "parsing"] }
+//!
+//! const INPUT: &str = stringify! {
+//! use crate::{
+//! lazy::{Lazy, SyncLazy, SyncOnceCell}, panic,
+//! sync::{ atomic::{AtomicUsize, Ordering::SeqCst},
+//! mpsc::channel, Mutex, },
+//! thread,
+//! };
+//! impl<T, U> Into<U> for T where U: From<T> {
+//! fn into(self) -> U { U::from(self) }
+//! }
+//! };
+//!
+//! fn main() {
+//! let syntax_tree = syn::parse_file(INPUT).unwrap();
+//! let formatted = prettyplease::unparse(&syntax_tree);
+//! print!("{}", formatted);
+//! }
+//! ```
+//!
+//! <br>
+//!
+//! # Algorithm notes
+//!
+//! The approach and terminology used in the implementation are derived from
+//! [*Derek C. Oppen, "Pretty Printing" (1979)*][paper], on which
+//! rustc_ast_pretty is also based, and from rustc_ast_pretty's implementation
+//! written by Graydon Hoare in 2011 (and modernized over the years by dozens of
+//! volunteer maintainers).
+//!
+//! [paper]: http://i.stanford.edu/pub/cstr/reports/cs/tr/79/770/CS-TR-79-770.pdf
+//!
+//! The paper describes two language-agnostic interacting procedures `Scan()`
+//! and `Print()`. Language-specific code decomposes an input data structure
+//! into a stream of `string` and `break` tokens, and `begin` and `end` tokens
+//! for grouping. Each `begin`&ndash;`end` range may be identified as either
+//! "consistent breaking" or "inconsistent breaking". If a group is consistently
+//! breaking, then if the whole contents do not fit on the line, *every* `break`
+//! token in the group will receive a linebreak. This is appropriate, for
+//! example, for Rust struct literals, or arguments of a function call. If a
+//! group is inconsistently breaking, then the `string` tokens in the group are
+//! greedily placed on the line until out of space, and linebroken only at those
+//! `break` tokens for which the next string would not fit. For example, this is
+//! appropriate for the contents of a braced `use` statement in Rust.
+//!
+//! Scan's job is to efficiently accumulate sizing information about groups and
+//! breaks. For every `begin` token we compute the distance to the matched `end`
+//! token, and for every `break` we compute the distance to the next `break`.
+//! The algorithm uses a ringbuffer to hold tokens whose size is not yet
+//! ascertained. The maximum size of the ringbuffer is bounded by the target
+//! line length and does not grow indefinitely, regardless of deep nesting in
+//! the input stream. That's because once a group is sufficiently big, the
+//! precise size can no longer make a difference to linebreak decisions and we
+//! can effectively treat it as "infinity".
+//!
+//! Print's job is to use the sizing information to efficiently assign a
+//! "broken" or "not broken" status to every `begin` token. At that point the
+//! output is easily constructed by concatenating `string` tokens and breaking
+//! at `break` tokens contained within a broken group.
+//!
+//! Leveraging these primitives (i.e. cleverly placing the all-or-nothing
+//! consistent breaks and greedy inconsistent breaks) to yield
+//! rustfmt-compatible formatting for all of Rust's syntax tree nodes is a fun
+//! challenge.
+//!
+//! Here is a visualization of some Rust tokens fed into the pretty printing
+//! algorithm. Consistently breaking `begin`&mdash;`end` pairs are represented
+//! by `«`&#8288;`»`, inconsistently breaking by `‹`&#8288;`›`, `break` by `·`,
+//! and the rest of the non-whitespace are `string`.
+//!
+//! ```text
+//! use crate::«{·
+//! ‹ lazy::«{·‹Lazy,· SyncLazy,· SyncOnceCell›·}»,·
+//! panic,·
+//! sync::«{·
+//! ‹ atomic::«{·‹AtomicUsize,· Ordering::SeqCst›·}»,·
+//! mpsc::channel,· Mutex›,·
+//! }»,·
+//! thread›,·
+//! }»;·
+//! «‹«impl<«·T‹›,· U‹›·»>» Into<«·U·»>· for T›·
+//! where·
+//! U:‹ From<«·T·»>›,·
+//! {·
+//! « fn into(·«·self·») -> U {·
+//! ‹ U::from(«·self·»)›·
+//! » }·
+//! »}·
+//! ```
+//!
+//! The algorithm described in the paper is not quite sufficient for producing
+//! well-formatted Rust code that is locally indistinguishable from rustfmt's
+//! style. The reason is that in the paper, the complete non-whitespace contents
+//! are assumed to be independent of linebreak decisions, with Scan and Print
+//! being only in control of the whitespace (spaces and line breaks). In Rust as
+//! idiomatically formatted by rustfmt, that is not the case. Trailing commas
+//! are one example; the punctuation is only known *after* the broken vs
+//! non-broken status of the surrounding group is known:
+//!
+//! ```
+//! # struct Struct { x: u64, y: bool }
+//! # let xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = 0;
+//! # let yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy = true;
+//! #
+//! let _ = Struct { x: 0, y: true };
+//!
+//! let _ = Struct {
+//! x: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
+//! y: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, //<- trailing comma if the expression wrapped
+//! };
+//! ```
+//!
+//! The formatting of `match` expressions is another case; we want small arms on
+//! the same line as the pattern, and big arms wrapped in a brace. The presence
+//! of the brace punctuation, comma, and semicolon are all dependent on whether
+//! the arm fits on the line:
+//!
+//! ```
+//! # struct Entry { nanos: u32 }
+//! # let total_nanos = 0u64;
+//! # let mut total_secs = 0u64;
+//! # let tmp;
+//! # let entry = Entry { nanos: 0 };
+//! # const NANOS_PER_SEC: u32 = 1_000_000_000;
+//! #
+//! match total_nanos.checked_add(entry.nanos as u64) {
+//! Some(n) => tmp = n, //<- small arm, inline with comma
+//! None => {
+//! total_secs = total_secs
+//! .checked_add(total_nanos / NANOS_PER_SEC as u64)
+//! .expect("overflow in iter::sum over durations");
+//! } //<- big arm, needs brace added, and also semicolon^
+//! }
+//! ```
+//!
+//! The printing algorithm implementation in this crate accommodates all of
+//! these situations with conditional punctuation tokens whose selection can be
+//! deferred and populated after it's known that the group is or is not broken.
+
+#![doc(html_root_url = "https://docs.rs/prettyplease/0.2.35")]
+#![allow(
+ clippy::bool_to_int_with_if,
+ clippy::cast_possible_wrap,
+ clippy::cast_sign_loss,
+ clippy::derive_partial_eq_without_eq,
+ clippy::doc_markdown,
+ clippy::enum_glob_use,
+ clippy::items_after_statements,
+ clippy::let_underscore_untyped,
+ clippy::match_like_matches_macro,
+ clippy::match_same_arms,
+ clippy::module_name_repetitions,
+ clippy::must_use_candidate,
+ clippy::needless_pass_by_value,
+ clippy::ref_option,
+ clippy::similar_names,
+ clippy::struct_excessive_bools,
+ clippy::too_many_lines,
+ clippy::unused_self,
+ clippy::vec_init_then_push
+)]
+#![cfg_attr(all(test, exhaustive), feature(non_exhaustive_omitted_patterns_lint))]
+
+mod algorithm;
+mod attr;
+mod classify;
+mod convenience;
+mod data;
+mod expr;
+mod file;
+mod fixup;
+mod generics;
+mod item;
+mod iter;
+mod lifetime;
+mod lit;
+mod mac;
+mod pat;
+mod path;
+mod precedence;
+mod ring;
+mod stmt;
+mod token;
+mod ty;
+
+use crate::algorithm::Printer;
+use syn::File;
+
+// Target line width.
+const MARGIN: isize = 89;
+
+// Number of spaces increment at each level of block indentation.
+const INDENT: isize = 4;
+
+// Every line is allowed at least this much space, even if highly indented.
+const MIN_SPACE: isize = 60;
+
+pub fn unparse(file: &File) -> String {
+ let mut p = Printer::new();
+ p.file(file);
+ p.eof()
+}
diff --git a/vendor/prettyplease/src/lifetime.rs b/vendor/prettyplease/src/lifetime.rs
new file mode 100644
index 00000000..665caa32
--- /dev/null
+++ b/vendor/prettyplease/src/lifetime.rs
@@ -0,0 +1,9 @@
+use crate::algorithm::Printer;
+use syn::Lifetime;
+
+impl Printer {
+ pub fn lifetime(&mut self, lifetime: &Lifetime) {
+ self.word("'");
+ self.ident(&lifetime.ident);
+ }
+}
diff --git a/vendor/prettyplease/src/lit.rs b/vendor/prettyplease/src/lit.rs
new file mode 100644
index 00000000..10a86e4b
--- /dev/null
+++ b/vendor/prettyplease/src/lit.rs
@@ -0,0 +1,57 @@
+use crate::algorithm::Printer;
+use proc_macro2::Literal;
+use syn::{Lit, LitBool, LitByte, LitByteStr, LitCStr, LitChar, LitFloat, LitInt, LitStr};
+
+impl Printer {
+ pub fn lit(&mut self, lit: &Lit) {
+ match lit {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ Lit::Str(lit) => self.lit_str(lit),
+ Lit::ByteStr(lit) => self.lit_byte_str(lit),
+ Lit::CStr(lit) => self.lit_c_str(lit),
+ Lit::Byte(lit) => self.lit_byte(lit),
+ Lit::Char(lit) => self.lit_char(lit),
+ Lit::Int(lit) => self.lit_int(lit),
+ Lit::Float(lit) => self.lit_float(lit),
+ Lit::Bool(lit) => self.lit_bool(lit),
+ Lit::Verbatim(lit) => self.lit_verbatim(lit),
+ _ => unimplemented!("unknown Lit"),
+ }
+ }
+
+ pub fn lit_str(&mut self, lit: &LitStr) {
+ self.word(lit.token().to_string());
+ }
+
+ fn lit_byte_str(&mut self, lit: &LitByteStr) {
+ self.word(lit.token().to_string());
+ }
+
+ fn lit_c_str(&mut self, lit: &LitCStr) {
+ self.word(lit.token().to_string());
+ }
+
+ fn lit_byte(&mut self, lit: &LitByte) {
+ self.word(lit.token().to_string());
+ }
+
+ fn lit_char(&mut self, lit: &LitChar) {
+ self.word(lit.token().to_string());
+ }
+
+ fn lit_int(&mut self, lit: &LitInt) {
+ self.word(lit.token().to_string());
+ }
+
+ fn lit_float(&mut self, lit: &LitFloat) {
+ self.word(lit.token().to_string());
+ }
+
+ fn lit_bool(&mut self, lit: &LitBool) {
+ self.word(if lit.value { "true" } else { "false" });
+ }
+
+ fn lit_verbatim(&mut self, token: &Literal) {
+ self.word(token.to_string());
+ }
+}
diff --git a/vendor/prettyplease/src/mac.rs b/vendor/prettyplease/src/mac.rs
new file mode 100644
index 00000000..ddb2b5fe
--- /dev/null
+++ b/vendor/prettyplease/src/mac.rs
@@ -0,0 +1,706 @@
+use crate::algorithm::Printer;
+use crate::path::PathKind;
+use crate::token::Token;
+use crate::INDENT;
+use proc_macro2::{Delimiter, Spacing, TokenStream};
+use syn::{Ident, Macro, MacroDelimiter};
+
+impl Printer {
+ pub fn mac(&mut self, mac: &Macro, ident: Option<&Ident>, semicolon: bool) {
+ if mac.path.is_ident("macro_rules") {
+ if let Some(ident) = ident {
+ self.macro_rules(ident, &mac.tokens);
+ return;
+ }
+ }
+ #[cfg(feature = "verbatim")]
+ if ident.is_none() && self.standard_library_macro(mac, semicolon) {
+ return;
+ }
+ self.path(&mac.path, PathKind::Simple);
+ self.word("!");
+ if let Some(ident) = ident {
+ self.nbsp();
+ self.ident(ident);
+ }
+ let (open, close, delimiter_break) = match mac.delimiter {
+ MacroDelimiter::Paren(_) => ("(", ")", Self::zerobreak as fn(&mut Self)),
+ MacroDelimiter::Brace(_) => (" {", "}", Self::hardbreak as fn(&mut Self)),
+ MacroDelimiter::Bracket(_) => ("[", "]", Self::zerobreak as fn(&mut Self)),
+ };
+ self.word(open);
+ if !mac.tokens.is_empty() {
+ self.cbox(INDENT);
+ delimiter_break(self);
+ self.ibox(0);
+ self.macro_rules_tokens(mac.tokens.clone(), false);
+ self.end();
+ delimiter_break(self);
+ self.offset(-INDENT);
+ self.end();
+ }
+ self.word(close);
+ if semicolon {
+ self.word(";");
+ }
+ }
+
+ fn macro_rules(&mut self, name: &Ident, rules: &TokenStream) {
+ enum State {
+ Start,
+ Matcher,
+ Equal,
+ Greater,
+ Expander,
+ }
+
+ use State::*;
+
+ self.word("macro_rules! ");
+ self.ident(name);
+ self.word(" {");
+ self.cbox(INDENT);
+ self.hardbreak_if_nonempty();
+ let mut state = State::Start;
+ for tt in rules.clone() {
+ let token = Token::from(tt);
+ match (state, token) {
+ (Start, Token::Group(delimiter, stream)) => {
+ self.delimiter_open(delimiter);
+ if !stream.is_empty() {
+ self.cbox(INDENT);
+ self.zerobreak();
+ self.ibox(0);
+ self.macro_rules_tokens(stream, true);
+ self.end();
+ self.zerobreak();
+ self.offset(-INDENT);
+ self.end();
+ }
+ self.delimiter_close(delimiter);
+ state = Matcher;
+ }
+ (Matcher, Token::Punct('=', Spacing::Joint)) => {
+ self.word(" =");
+ state = Equal;
+ }
+ (Equal, Token::Punct('>', Spacing::Alone)) => {
+ self.word(">");
+ state = Greater;
+ }
+ (Greater, Token::Group(_delimiter, stream)) => {
+ self.word(" {");
+ self.neverbreak();
+ if !stream.is_empty() {
+ self.cbox(INDENT);
+ self.hardbreak();
+ self.ibox(0);
+ self.macro_rules_tokens(stream, false);
+ self.end();
+ self.hardbreak();
+ self.offset(-INDENT);
+ self.end();
+ }
+ self.word("}");
+ state = Expander;
+ }
+ (Expander, Token::Punct(';', Spacing::Alone)) => {
+ self.word(";");
+ self.hardbreak();
+ state = Start;
+ }
+ _ => unimplemented!("bad macro_rules syntax"),
+ }
+ }
+ match state {
+ Start => {}
+ Expander => {
+ self.word(";");
+ self.hardbreak();
+ }
+ _ => self.hardbreak(),
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word("}");
+ }
+
+ pub fn macro_rules_tokens(&mut self, stream: TokenStream, matcher: bool) {
+ #[derive(PartialEq)]
+ enum State {
+ Start,
+ Dollar,
+ DollarCrate,
+ DollarIdent,
+ DollarIdentColon,
+ DollarParen,
+ DollarParenSep,
+ Pound,
+ PoundBang,
+ Dot,
+ Colon,
+ Colon2,
+ Ident,
+ IdentBang,
+ Delim,
+ Other,
+ }
+
+ use State::*;
+
+ let mut state = Start;
+ let mut previous_is_joint = true;
+ for tt in stream {
+ let token = Token::from(tt);
+ let (needs_space, next_state) = match (&state, &token) {
+ (Dollar, Token::Ident(_)) if matcher => (false, DollarIdent),
+ (Dollar, Token::Ident(ident)) if ident == "crate" => (false, DollarCrate),
+ (Dollar, Token::Ident(_)) => (false, Other),
+ (DollarIdent, Token::Punct(':', Spacing::Alone)) => (false, DollarIdentColon),
+ (DollarIdentColon, Token::Ident(_)) => (false, Other),
+ (DollarParen, Token::Punct('+' | '*' | '?', Spacing::Alone)) => (false, Other),
+ (DollarParen, Token::Ident(_) | Token::Literal(_)) => (false, DollarParenSep),
+ (DollarParen, Token::Punct(_, Spacing::Joint)) => (false, DollarParen),
+ (DollarParen, Token::Punct(_, Spacing::Alone)) => (false, DollarParenSep),
+ (DollarParenSep, Token::Punct('+' | '*', _)) => (false, Other),
+ (Pound, Token::Punct('!', _)) => (false, PoundBang),
+ (Dollar, Token::Group(Delimiter::Parenthesis, _)) => (false, DollarParen),
+ (Pound | PoundBang, Token::Group(Delimiter::Bracket, _)) => (false, Other),
+ (Ident, Token::Group(Delimiter::Parenthesis | Delimiter::Bracket, _)) => {
+ (false, Delim)
+ }
+ (Ident, Token::Punct('!', Spacing::Alone)) => (false, IdentBang),
+ (IdentBang, Token::Group(Delimiter::Parenthesis | Delimiter::Bracket, _)) => {
+ (false, Other)
+ }
+ (Colon, Token::Punct(':', _)) => (false, Colon2),
+ (_, Token::Group(Delimiter::Parenthesis | Delimiter::Bracket, _)) => (true, Delim),
+ (_, Token::Group(Delimiter::Brace | Delimiter::None, _)) => (true, Other),
+ (_, Token::Ident(ident)) if !is_keyword(ident) => {
+ (state != Dot && state != Colon2, Ident)
+ }
+ (_, Token::Literal(lit)) if lit.to_string().ends_with('.') => (state != Dot, Other),
+ (_, Token::Literal(_)) => (state != Dot, Ident),
+ (_, Token::Punct(',' | ';', _)) => (false, Other),
+ (_, Token::Punct('.', _)) if !matcher => (state != Ident && state != Delim, Dot),
+ (_, Token::Punct(':', Spacing::Joint)) => {
+ (state != Ident && state != DollarCrate, Colon)
+ }
+ (_, Token::Punct('$', _)) => (true, Dollar),
+ (_, Token::Punct('#', _)) => (true, Pound),
+ (_, _) => (true, Other),
+ };
+ if !previous_is_joint {
+ if needs_space {
+ self.space();
+ } else if let Token::Punct('.', _) = token {
+ self.zerobreak();
+ }
+ }
+ previous_is_joint = match token {
+ Token::Punct(_, Spacing::Joint) | Token::Punct('$', _) => true,
+ _ => false,
+ };
+ self.single_token(
+ token,
+ if matcher {
+ |printer, stream| printer.macro_rules_tokens(stream, true)
+ } else {
+ |printer, stream| printer.macro_rules_tokens(stream, false)
+ },
+ );
+ state = next_state;
+ }
+ }
+}
+
+pub(crate) fn requires_semi(delimiter: &MacroDelimiter) -> bool {
+ match delimiter {
+ MacroDelimiter::Paren(_) | MacroDelimiter::Bracket(_) => true,
+ MacroDelimiter::Brace(_) => false,
+ }
+}
+
+fn is_keyword(ident: &Ident) -> bool {
+ match ident.to_string().as_str() {
+ "as" | "async" | "await" | "box" | "break" | "const" | "continue" | "crate" | "dyn"
+ | "else" | "enum" | "extern" | "fn" | "for" | "if" | "impl" | "in" | "let" | "loop"
+ | "macro" | "match" | "mod" | "move" | "mut" | "pub" | "ref" | "return" | "static"
+ | "struct" | "trait" | "type" | "unsafe" | "use" | "where" | "while" | "yield" => true,
+ _ => false,
+ }
+}
+
+#[cfg(feature = "verbatim")]
+mod standard_library {
+ use crate::algorithm::Printer;
+ use crate::expr;
+ use crate::fixup::FixupContext;
+ use crate::iter::IterDelimited;
+ use crate::path::PathKind;
+ use crate::INDENT;
+ use syn::ext::IdentExt;
+ use syn::parse::{Parse, ParseStream, Parser, Result};
+ use syn::punctuated::Punctuated;
+ use syn::{
+ parenthesized, token, Attribute, Expr, ExprAssign, ExprPath, Ident, Lit, Macro, Pat, Path,
+ Token, Type, Visibility,
+ };
+
+ enum KnownMacro {
+ Expr(Expr),
+ Exprs(Vec<Expr>),
+ Cfg(Cfg),
+ Matches(Matches),
+ ThreadLocal(Vec<ThreadLocal>),
+ VecArray(Punctuated<Expr, Token![,]>),
+ VecRepeat { elem: Expr, n: Expr },
+ }
+
+ enum Cfg {
+ Eq(Ident, Option<Lit>),
+ Call(Ident, Vec<Cfg>),
+ }
+
+ struct Matches {
+ expression: Expr,
+ pattern: Pat,
+ guard: Option<Expr>,
+ }
+
+ struct ThreadLocal {
+ attrs: Vec<Attribute>,
+ vis: Visibility,
+ name: Ident,
+ ty: Type,
+ init: Expr,
+ }
+
+ struct FormatArgs {
+ format_string: Expr,
+ args: Vec<Expr>,
+ }
+
+ impl Parse for FormatArgs {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let format_string: Expr = input.parse()?;
+
+ let mut args = Vec::new();
+ while !input.is_empty() {
+ input.parse::<Token![,]>()?;
+ if input.is_empty() {
+ break;
+ }
+ let arg = if input.peek(Ident::peek_any)
+ && input.peek2(Token![=])
+ && !input.peek2(Token![==])
+ {
+ let key = input.call(Ident::parse_any)?;
+ let eq_token: Token![=] = input.parse()?;
+ let value: Expr = input.parse()?;
+ Expr::Assign(ExprAssign {
+ attrs: Vec::new(),
+ left: Box::new(Expr::Path(ExprPath {
+ attrs: Vec::new(),
+ qself: None,
+ path: Path::from(key),
+ })),
+ eq_token,
+ right: Box::new(value),
+ })
+ } else {
+ input.parse()?
+ };
+ args.push(arg);
+ }
+
+ Ok(FormatArgs {
+ format_string,
+ args,
+ })
+ }
+ }
+
+ impl KnownMacro {
+ fn parse_expr(input: ParseStream) -> Result<Self> {
+ let expr: Expr = input.parse()?;
+ Ok(KnownMacro::Expr(expr))
+ }
+
+ fn parse_expr_comma(input: ParseStream) -> Result<Self> {
+ let expr: Expr = input.parse()?;
+ input.parse::<Option<Token![,]>>()?;
+ Ok(KnownMacro::Exprs(vec![expr]))
+ }
+
+ fn parse_exprs(input: ParseStream) -> Result<Self> {
+ let exprs = input.parse_terminated(Expr::parse, Token![,])?;
+ Ok(KnownMacro::Exprs(Vec::from_iter(exprs)))
+ }
+
+ fn parse_assert(input: ParseStream) -> Result<Self> {
+ let mut exprs = Vec::new();
+ let cond: Expr = input.parse()?;
+ exprs.push(cond);
+ if input.parse::<Option<Token![,]>>()?.is_some() && !input.is_empty() {
+ let format_args: FormatArgs = input.parse()?;
+ exprs.push(format_args.format_string);
+ exprs.extend(format_args.args);
+ }
+ Ok(KnownMacro::Exprs(exprs))
+ }
+
+ fn parse_assert_cmp(input: ParseStream) -> Result<Self> {
+ let mut exprs = Vec::new();
+ let left: Expr = input.parse()?;
+ exprs.push(left);
+ input.parse::<Token![,]>()?;
+ let right: Expr = input.parse()?;
+ exprs.push(right);
+ if input.parse::<Option<Token![,]>>()?.is_some() && !input.is_empty() {
+ let format_args: FormatArgs = input.parse()?;
+ exprs.push(format_args.format_string);
+ exprs.extend(format_args.args);
+ }
+ Ok(KnownMacro::Exprs(exprs))
+ }
+
+ fn parse_cfg(input: ParseStream) -> Result<Self> {
+ fn parse_single(input: ParseStream) -> Result<Cfg> {
+ let ident: Ident = input.parse()?;
+ if input.peek(token::Paren) && (ident == "all" || ident == "any") {
+ let content;
+ parenthesized!(content in input);
+ let list = content.call(parse_multiple)?;
+ Ok(Cfg::Call(ident, list))
+ } else if input.peek(token::Paren) && ident == "not" {
+ let content;
+ parenthesized!(content in input);
+ let cfg = content.call(parse_single)?;
+ content.parse::<Option<Token![,]>>()?;
+ Ok(Cfg::Call(ident, vec![cfg]))
+ } else if input.peek(Token![=]) {
+ input.parse::<Token![=]>()?;
+ let string: Lit = input.parse()?;
+ Ok(Cfg::Eq(ident, Some(string)))
+ } else {
+ Ok(Cfg::Eq(ident, None))
+ }
+ }
+
+ fn parse_multiple(input: ParseStream) -> Result<Vec<Cfg>> {
+ let mut vec = Vec::new();
+ while !input.is_empty() {
+ let cfg = input.call(parse_single)?;
+ vec.push(cfg);
+ if input.is_empty() {
+ break;
+ }
+ input.parse::<Token![,]>()?;
+ }
+ Ok(vec)
+ }
+
+ let cfg = input.call(parse_single)?;
+ input.parse::<Option<Token![,]>>()?;
+ Ok(KnownMacro::Cfg(cfg))
+ }
+
+ fn parse_env(input: ParseStream) -> Result<Self> {
+ let mut exprs = Vec::new();
+ let name: Expr = input.parse()?;
+ exprs.push(name);
+ if input.parse::<Option<Token![,]>>()?.is_some() && !input.is_empty() {
+ let error_msg: Expr = input.parse()?;
+ exprs.push(error_msg);
+ input.parse::<Option<Token![,]>>()?;
+ }
+ Ok(KnownMacro::Exprs(exprs))
+ }
+
+ fn parse_format_args(input: ParseStream) -> Result<Self> {
+ let format_args: FormatArgs = input.parse()?;
+ let mut exprs = format_args.args;
+ exprs.insert(0, format_args.format_string);
+ Ok(KnownMacro::Exprs(exprs))
+ }
+
+ fn parse_matches(input: ParseStream) -> Result<Self> {
+ let expression: Expr = input.parse()?;
+ input.parse::<Token![,]>()?;
+ let pattern = input.call(Pat::parse_multi_with_leading_vert)?;
+ let guard = if input.parse::<Option<Token![if]>>()?.is_some() {
+ Some(input.parse()?)
+ } else {
+ None
+ };
+ input.parse::<Option<Token![,]>>()?;
+ Ok(KnownMacro::Matches(Matches {
+ expression,
+ pattern,
+ guard,
+ }))
+ }
+
+ fn parse_thread_local(input: ParseStream) -> Result<Self> {
+ let mut items = Vec::new();
+ while !input.is_empty() {
+ let attrs = input.call(Attribute::parse_outer)?;
+ let vis: Visibility = input.parse()?;
+ input.parse::<Token![static]>()?;
+ let name: Ident = input.parse()?;
+ input.parse::<Token![:]>()?;
+ let ty: Type = input.parse()?;
+ input.parse::<Token![=]>()?;
+ let init: Expr = input.parse()?;
+ if input.is_empty() {
+ break;
+ }
+ input.parse::<Token![;]>()?;
+ items.push(ThreadLocal {
+ attrs,
+ vis,
+ name,
+ ty,
+ init,
+ });
+ }
+ Ok(KnownMacro::ThreadLocal(items))
+ }
+
+ fn parse_vec(input: ParseStream) -> Result<Self> {
+ if input.is_empty() {
+ return Ok(KnownMacro::VecArray(Punctuated::new()));
+ }
+ let first: Expr = input.parse()?;
+ if input.parse::<Option<Token![;]>>()?.is_some() {
+ let len: Expr = input.parse()?;
+ Ok(KnownMacro::VecRepeat {
+ elem: first,
+ n: len,
+ })
+ } else {
+ let mut vec = Punctuated::new();
+ vec.push_value(first);
+ while !input.is_empty() {
+ let comma: Token![,] = input.parse()?;
+ vec.push_punct(comma);
+ if input.is_empty() {
+ break;
+ }
+ let next: Expr = input.parse()?;
+ vec.push_value(next);
+ }
+ Ok(KnownMacro::VecArray(vec))
+ }
+ }
+
+ fn parse_write(input: ParseStream) -> Result<Self> {
+ let mut exprs = Vec::new();
+ let dst: Expr = input.parse()?;
+ exprs.push(dst);
+ input.parse::<Token![,]>()?;
+ let format_args: FormatArgs = input.parse()?;
+ exprs.push(format_args.format_string);
+ exprs.extend(format_args.args);
+ Ok(KnownMacro::Exprs(exprs))
+ }
+
+ fn parse_writeln(input: ParseStream) -> Result<Self> {
+ let mut exprs = Vec::new();
+ let dst: Expr = input.parse()?;
+ exprs.push(dst);
+ if input.parse::<Option<Token![,]>>()?.is_some() && !input.is_empty() {
+ let format_args: FormatArgs = input.parse()?;
+ exprs.push(format_args.format_string);
+ exprs.extend(format_args.args);
+ }
+ Ok(KnownMacro::Exprs(exprs))
+ }
+ }
+
+ impl Printer {
+ pub fn standard_library_macro(&mut self, mac: &Macro, mut semicolon: bool) -> bool {
+ let name = mac.path.segments.last().unwrap().ident.to_string();
+ let parser = match name.as_str() {
+ "addr_of" | "addr_of_mut" => KnownMacro::parse_expr,
+ "assert" | "debug_assert" => KnownMacro::parse_assert,
+ "assert_eq" | "assert_ne" | "debug_assert_eq" | "debug_assert_ne" => {
+ KnownMacro::parse_assert_cmp
+ }
+ "cfg" => KnownMacro::parse_cfg,
+ "compile_error" | "include" | "include_bytes" | "include_str" | "option_env" => {
+ KnownMacro::parse_expr_comma
+ }
+ "concat" | "concat_bytes" | "dbg" => KnownMacro::parse_exprs,
+ "const_format_args" | "eprint" | "eprintln" | "format" | "format_args"
+ | "format_args_nl" | "panic" | "print" | "println" | "todo" | "unimplemented"
+ | "unreachable" => KnownMacro::parse_format_args,
+ "env" => KnownMacro::parse_env,
+ "matches" => KnownMacro::parse_matches,
+ "thread_local" => KnownMacro::parse_thread_local,
+ "vec" => KnownMacro::parse_vec,
+ "write" => KnownMacro::parse_write,
+ "writeln" => KnownMacro::parse_writeln,
+ _ => return false,
+ };
+
+ let known_macro = match parser.parse2(mac.tokens.clone()) {
+ Ok(known_macro) => known_macro,
+ Err(_) => return false,
+ };
+
+ self.path(&mac.path, PathKind::Simple);
+ self.word("!");
+
+ match &known_macro {
+ KnownMacro::Expr(expr) => {
+ self.word("(");
+ self.cbox(INDENT);
+ self.zerobreak();
+ self.expr(expr, FixupContext::NONE);
+ self.zerobreak();
+ self.offset(-INDENT);
+ self.end();
+ self.word(")");
+ }
+ KnownMacro::Exprs(exprs) => {
+ self.word("(");
+ self.cbox(INDENT);
+ self.zerobreak();
+ for elem in exprs.iter().delimited() {
+ self.expr(&elem, FixupContext::NONE);
+ self.trailing_comma(elem.is_last);
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word(")");
+ }
+ KnownMacro::Cfg(cfg) => {
+ self.word("(");
+ self.cfg(cfg);
+ self.word(")");
+ }
+ KnownMacro::Matches(matches) => {
+ self.word("(");
+ self.cbox(INDENT);
+ self.zerobreak();
+ self.expr(&matches.expression, FixupContext::NONE);
+ self.word(",");
+ self.space();
+ self.pat(&matches.pattern);
+ if let Some(guard) = &matches.guard {
+ self.space();
+ self.word("if ");
+ self.expr(guard, FixupContext::NONE);
+ }
+ self.zerobreak();
+ self.offset(-INDENT);
+ self.end();
+ self.word(")");
+ }
+ KnownMacro::ThreadLocal(items) => {
+ self.word(" {");
+ self.cbox(INDENT);
+ self.hardbreak_if_nonempty();
+ for item in items {
+ self.outer_attrs(&item.attrs);
+ self.cbox(0);
+ self.visibility(&item.vis);
+ self.word("static ");
+ self.ident(&item.name);
+ self.word(": ");
+ self.ty(&item.ty);
+ self.word(" = ");
+ self.neverbreak();
+ self.expr(&item.init, FixupContext::NONE);
+ self.word(";");
+ self.end();
+ self.hardbreak();
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word("}");
+ semicolon = false;
+ }
+ KnownMacro::VecArray(vec) => {
+ if vec.is_empty() {
+ self.word("[]");
+ } else if expr::simple_array(vec) {
+ self.cbox(INDENT);
+ self.word("[");
+ self.zerobreak();
+ self.ibox(0);
+ for elem in vec.iter().delimited() {
+ self.expr(&elem, FixupContext::NONE);
+ if !elem.is_last {
+ self.word(",");
+ self.space();
+ }
+ }
+ self.end();
+ self.trailing_comma(true);
+ self.offset(-INDENT);
+ self.word("]");
+ self.end();
+ } else {
+ self.word("[");
+ self.cbox(INDENT);
+ self.zerobreak();
+ for elem in vec.iter().delimited() {
+ self.expr(&elem, FixupContext::NONE);
+ self.trailing_comma(elem.is_last);
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word("]");
+ }
+ }
+ KnownMacro::VecRepeat { elem, n } => {
+ self.word("[");
+ self.cbox(INDENT);
+ self.zerobreak();
+ self.expr(elem, FixupContext::NONE);
+ self.word(";");
+ self.space();
+ self.expr(n, FixupContext::NONE);
+ self.zerobreak();
+ self.offset(-INDENT);
+ self.end();
+ self.word("]");
+ }
+ }
+
+ if semicolon {
+ self.word(";");
+ }
+
+ true
+ }
+
+ fn cfg(&mut self, cfg: &Cfg) {
+ match cfg {
+ Cfg::Eq(ident, value) => {
+ self.ident(ident);
+ if let Some(value) = value {
+ self.word(" = ");
+ self.lit(value);
+ }
+ }
+ Cfg::Call(ident, args) => {
+ self.ident(ident);
+ self.word("(");
+ self.cbox(INDENT);
+ self.zerobreak();
+ for arg in args.iter().delimited() {
+ self.cfg(&arg);
+ self.trailing_comma(arg.is_last);
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word(")");
+ }
+ }
+ }
+ }
+}
diff --git a/vendor/prettyplease/src/pat.rs b/vendor/prettyplease/src/pat.rs
new file mode 100644
index 00000000..23a38cbb
--- /dev/null
+++ b/vendor/prettyplease/src/pat.rs
@@ -0,0 +1,254 @@
+use crate::algorithm::Printer;
+use crate::fixup::FixupContext;
+use crate::iter::IterDelimited;
+use crate::path::PathKind;
+use crate::INDENT;
+use proc_macro2::TokenStream;
+use syn::{
+ FieldPat, Pat, PatIdent, PatOr, PatParen, PatReference, PatRest, PatSlice, PatStruct, PatTuple,
+ PatTupleStruct, PatType, PatWild,
+};
+
+impl Printer {
+ pub fn pat(&mut self, pat: &Pat) {
+ match pat {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ Pat::Const(pat) => self.expr_const(pat),
+ Pat::Ident(pat) => self.pat_ident(pat),
+ Pat::Lit(pat) => self.expr_lit(pat),
+ Pat::Macro(pat) => self.expr_macro(pat),
+ Pat::Or(pat) => self.pat_or(pat),
+ Pat::Paren(pat) => self.pat_paren(pat),
+ Pat::Path(pat) => self.expr_path(pat),
+ Pat::Range(pat) => self.expr_range(pat, FixupContext::NONE),
+ Pat::Reference(pat) => self.pat_reference(pat),
+ Pat::Rest(pat) => self.pat_rest(pat),
+ Pat::Slice(pat) => self.pat_slice(pat),
+ Pat::Struct(pat) => self.pat_struct(pat),
+ Pat::Tuple(pat) => self.pat_tuple(pat),
+ Pat::TupleStruct(pat) => self.pat_tuple_struct(pat),
+ Pat::Type(pat) => self.pat_type(pat),
+ Pat::Verbatim(pat) => self.pat_verbatim(pat),
+ Pat::Wild(pat) => self.pat_wild(pat),
+ _ => unimplemented!("unknown Pat"),
+ }
+ }
+
+ fn pat_ident(&mut self, pat: &PatIdent) {
+ self.outer_attrs(&pat.attrs);
+ if pat.by_ref.is_some() {
+ self.word("ref ");
+ }
+ if pat.mutability.is_some() {
+ self.word("mut ");
+ }
+ self.ident(&pat.ident);
+ if let Some((_at_token, subpat)) = &pat.subpat {
+ self.word(" @ ");
+ self.pat(subpat);
+ }
+ }
+
+ fn pat_or(&mut self, pat: &PatOr) {
+ self.outer_attrs(&pat.attrs);
+ let mut consistent_break = false;
+ for case in &pat.cases {
+ match case {
+ Pat::Lit(_) | Pat::Wild(_) => {}
+ _ => {
+ consistent_break = true;
+ break;
+ }
+ }
+ }
+ if consistent_break {
+ self.cbox(0);
+ } else {
+ self.ibox(0);
+ }
+ for case in pat.cases.iter().delimited() {
+ if !case.is_first {
+ self.space();
+ self.word("| ");
+ }
+ self.pat(&case);
+ }
+ self.end();
+ }
+
+ fn pat_paren(&mut self, pat: &PatParen) {
+ self.outer_attrs(&pat.attrs);
+ self.word("(");
+ self.pat(&pat.pat);
+ self.word(")");
+ }
+
+ fn pat_reference(&mut self, pat: &PatReference) {
+ self.outer_attrs(&pat.attrs);
+ self.word("&");
+ if pat.mutability.is_some() {
+ self.word("mut ");
+ }
+ self.pat(&pat.pat);
+ }
+
+ fn pat_rest(&mut self, pat: &PatRest) {
+ self.outer_attrs(&pat.attrs);
+ self.word("..");
+ }
+
+ fn pat_slice(&mut self, pat: &PatSlice) {
+ self.outer_attrs(&pat.attrs);
+ self.word("[");
+ for elem in pat.elems.iter().delimited() {
+ self.pat(&elem);
+ self.trailing_comma(elem.is_last);
+ }
+ self.word("]");
+ }
+
+ fn pat_struct(&mut self, pat: &PatStruct) {
+ self.outer_attrs(&pat.attrs);
+ self.cbox(INDENT);
+ self.path(&pat.path, PathKind::Expr);
+ self.word(" {");
+ self.space_if_nonempty();
+ for field in pat.fields.iter().delimited() {
+ self.field_pat(&field);
+ self.trailing_comma_or_space(field.is_last && pat.rest.is_none());
+ }
+ if let Some(rest) = &pat.rest {
+ self.pat_rest(rest);
+ self.space();
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word("}");
+ }
+
+ fn pat_tuple(&mut self, pat: &PatTuple) {
+ self.outer_attrs(&pat.attrs);
+ self.word("(");
+ self.cbox(INDENT);
+ self.zerobreak();
+ for elem in pat.elems.iter().delimited() {
+ self.pat(&elem);
+ if pat.elems.len() == 1 {
+ if pat.elems.trailing_punct() {
+ self.word(",");
+ }
+ self.zerobreak();
+ } else {
+ self.trailing_comma(elem.is_last);
+ }
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word(")");
+ }
+
+ fn pat_tuple_struct(&mut self, pat: &PatTupleStruct) {
+ self.outer_attrs(&pat.attrs);
+ self.path(&pat.path, PathKind::Expr);
+ self.word("(");
+ self.cbox(INDENT);
+ self.zerobreak();
+ for elem in pat.elems.iter().delimited() {
+ self.pat(&elem);
+ self.trailing_comma(elem.is_last);
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word(")");
+ }
+
+ pub fn pat_type(&mut self, pat: &PatType) {
+ self.outer_attrs(&pat.attrs);
+ self.pat(&pat.pat);
+ self.word(": ");
+ self.ty(&pat.ty);
+ }
+
+ #[cfg(not(feature = "verbatim"))]
+ fn pat_verbatim(&mut self, pat: &TokenStream) {
+ unimplemented!("Pat::Verbatim `{}`", pat);
+ }
+
+ #[cfg(feature = "verbatim")]
+ fn pat_verbatim(&mut self, tokens: &TokenStream) {
+ use syn::parse::{Parse, ParseStream, Result};
+ use syn::{braced, Attribute, Block, Token};
+
+ enum PatVerbatim {
+ Ellipsis,
+ Box(Pat),
+ Const(PatConst),
+ }
+
+ struct PatConst {
+ attrs: Vec<Attribute>,
+ block: Block,
+ }
+
+ impl Parse for PatVerbatim {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let lookahead = input.lookahead1();
+ if lookahead.peek(Token![box]) {
+ input.parse::<Token![box]>()?;
+ let inner = Pat::parse_single(input)?;
+ Ok(PatVerbatim::Box(inner))
+ } else if lookahead.peek(Token![const]) {
+ input.parse::<Token![const]>()?;
+ let content;
+ let brace_token = braced!(content in input);
+ let attrs = content.call(Attribute::parse_inner)?;
+ let stmts = content.call(Block::parse_within)?;
+ Ok(PatVerbatim::Const(PatConst {
+ attrs,
+ block: Block { brace_token, stmts },
+ }))
+ } else if lookahead.peek(Token![...]) {
+ input.parse::<Token![...]>()?;
+ Ok(PatVerbatim::Ellipsis)
+ } else {
+ Err(lookahead.error())
+ }
+ }
+ }
+
+ let pat: PatVerbatim = match syn::parse2(tokens.clone()) {
+ Ok(pat) => pat,
+ Err(_) => unimplemented!("Pat::Verbatim `{}`", tokens),
+ };
+
+ match pat {
+ PatVerbatim::Ellipsis => {
+ self.word("...");
+ }
+ PatVerbatim::Box(pat) => {
+ self.word("box ");
+ self.pat(&pat);
+ }
+ PatVerbatim::Const(pat) => {
+ self.word("const ");
+ self.cbox(INDENT);
+ self.small_block(&pat.block, &pat.attrs);
+ self.end();
+ }
+ }
+ }
+
+ fn pat_wild(&mut self, pat: &PatWild) {
+ self.outer_attrs(&pat.attrs);
+ self.word("_");
+ }
+
+ fn field_pat(&mut self, field_pat: &FieldPat) {
+ self.outer_attrs(&field_pat.attrs);
+ if field_pat.colon_token.is_some() {
+ self.member(&field_pat.member);
+ self.word(": ");
+ }
+ self.pat(&field_pat.pat);
+ }
+}
diff --git a/vendor/prettyplease/src/path.rs b/vendor/prettyplease/src/path.rs
new file mode 100644
index 00000000..44428cc6
--- /dev/null
+++ b/vendor/prettyplease/src/path.rs
@@ -0,0 +1,194 @@
+use crate::algorithm::Printer;
+use crate::iter::IterDelimited;
+use crate::INDENT;
+use std::ptr;
+use syn::{
+ AngleBracketedGenericArguments, AssocConst, AssocType, Constraint, GenericArgument,
+ ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf,
+};
+
+#[derive(Copy, Clone, PartialEq)]
+pub enum PathKind {
+ // a::B
+ Simple,
+ // a::B<T>
+ Type,
+ // a::B::<T>
+ Expr,
+}
+
+impl Printer {
+ pub fn path(&mut self, path: &Path, kind: PathKind) {
+ assert!(!path.segments.is_empty());
+ for segment in path.segments.iter().delimited() {
+ if !segment.is_first || path.leading_colon.is_some() {
+ self.word("::");
+ }
+ self.path_segment(&segment, kind);
+ }
+ }
+
+ pub fn path_segment(&mut self, segment: &PathSegment, kind: PathKind) {
+ self.ident(&segment.ident);
+ self.path_arguments(&segment.arguments, kind);
+ }
+
+ fn path_arguments(&mut self, arguments: &PathArguments, kind: PathKind) {
+ match arguments {
+ PathArguments::None => {}
+ PathArguments::AngleBracketed(arguments) => {
+ self.angle_bracketed_generic_arguments(arguments, kind);
+ }
+ PathArguments::Parenthesized(arguments) => {
+ self.parenthesized_generic_arguments(arguments);
+ }
+ }
+ }
+
+ fn generic_argument(&mut self, arg: &GenericArgument) {
+ match arg {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ GenericArgument::Lifetime(lifetime) => self.lifetime(lifetime),
+ GenericArgument::Type(ty) => self.ty(ty),
+ GenericArgument::Const(expr) => self.const_argument(expr),
+ GenericArgument::AssocType(assoc) => self.assoc_type(assoc),
+ GenericArgument::AssocConst(assoc) => self.assoc_const(assoc),
+ GenericArgument::Constraint(constraint) => self.constraint(constraint),
+ _ => unimplemented!("unknown GenericArgument"),
+ }
+ }
+
+ pub fn angle_bracketed_generic_arguments(
+ &mut self,
+ generic: &AngleBracketedGenericArguments,
+ path_kind: PathKind,
+ ) {
+ if generic.args.is_empty() || path_kind == PathKind::Simple {
+ return;
+ }
+
+ if path_kind == PathKind::Expr {
+ self.word("::");
+ }
+ self.word("<");
+ self.cbox(INDENT);
+ self.zerobreak();
+
+ // Print lifetimes before types/consts/bindings, regardless of their
+ // order in self.args.
+ #[derive(Ord, PartialOrd, Eq, PartialEq)]
+ enum Group {
+ First,
+ Second,
+ }
+ fn group(arg: &GenericArgument) -> Group {
+ match arg {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ GenericArgument::Lifetime(_) => Group::First,
+ GenericArgument::Type(_)
+ | GenericArgument::Const(_)
+ | GenericArgument::AssocType(_)
+ | GenericArgument::AssocConst(_)
+ | GenericArgument::Constraint(_) => Group::Second,
+ _ => Group::Second,
+ }
+ }
+ let last = generic.args.iter().max_by_key(|param| group(param));
+ for current_group in [Group::First, Group::Second] {
+ for arg in &generic.args {
+ if group(arg) == current_group {
+ self.generic_argument(arg);
+ self.trailing_comma(ptr::eq(arg, last.unwrap()));
+ }
+ }
+ }
+
+ self.offset(-INDENT);
+ self.end();
+ self.word(">");
+ }
+
+ fn assoc_type(&mut self, assoc: &AssocType) {
+ self.ident(&assoc.ident);
+ if let Some(generics) = &assoc.generics {
+ self.angle_bracketed_generic_arguments(generics, PathKind::Type);
+ }
+ self.word(" = ");
+ self.ty(&assoc.ty);
+ }
+
+ fn assoc_const(&mut self, assoc: &AssocConst) {
+ self.ident(&assoc.ident);
+ if let Some(generics) = &assoc.generics {
+ self.angle_bracketed_generic_arguments(generics, PathKind::Type);
+ }
+ self.word(" = ");
+ self.const_argument(&assoc.value);
+ }
+
+ fn constraint(&mut self, constraint: &Constraint) {
+ self.ident(&constraint.ident);
+ if let Some(generics) = &constraint.generics {
+ self.angle_bracketed_generic_arguments(generics, PathKind::Type);
+ }
+ self.ibox(INDENT);
+ for bound in constraint.bounds.iter().delimited() {
+ if bound.is_first {
+ self.word(": ");
+ } else {
+ self.space();
+ self.word("+ ");
+ }
+ self.type_param_bound(&bound);
+ }
+ self.end();
+ }
+
+ fn parenthesized_generic_arguments(&mut self, arguments: &ParenthesizedGenericArguments) {
+ self.cbox(INDENT);
+ self.word("(");
+ self.zerobreak();
+ for ty in arguments.inputs.iter().delimited() {
+ self.ty(&ty);
+ self.trailing_comma(ty.is_last);
+ }
+ self.offset(-INDENT);
+ self.word(")");
+ self.return_type(&arguments.output);
+ self.end();
+ }
+
+ pub fn qpath(&mut self, qself: &Option<QSelf>, path: &Path, kind: PathKind) {
+ let qself = if let Some(qself) = qself {
+ qself
+ } else {
+ self.path(path, kind);
+ return;
+ };
+
+ assert!(qself.position < path.segments.len());
+
+ self.word("<");
+ self.ty(&qself.ty);
+
+ let mut segments = path.segments.iter();
+ if qself.position > 0 {
+ self.word(" as ");
+ for segment in segments.by_ref().take(qself.position).delimited() {
+ if !segment.is_first || path.leading_colon.is_some() {
+ self.word("::");
+ }
+ self.path_segment(&segment, PathKind::Type);
+ if segment.is_last {
+ self.word(">");
+ }
+ }
+ } else {
+ self.word(">");
+ }
+ for segment in segments {
+ self.word("::");
+ self.path_segment(segment, kind);
+ }
+ }
+}
diff --git a/vendor/prettyplease/src/precedence.rs b/vendor/prettyplease/src/precedence.rs
new file mode 100644
index 00000000..03117d56
--- /dev/null
+++ b/vendor/prettyplease/src/precedence.rs
@@ -0,0 +1,148 @@
+use syn::{
+ AttrStyle, Attribute, BinOp, Expr, ExprArray, ExprAsync, ExprAwait, ExprBlock, ExprBreak,
+ ExprCall, ExprConst, ExprContinue, ExprField, ExprForLoop, ExprIf, ExprIndex, ExprInfer,
+ ExprLit, ExprLoop, ExprMacro, ExprMatch, ExprMethodCall, ExprParen, ExprPath, ExprRepeat,
+ ExprReturn, ExprStruct, ExprTry, ExprTryBlock, ExprTuple, ExprUnsafe, ExprWhile, ExprYield,
+ ReturnType,
+};
+
+// Reference: https://doc.rust-lang.org/reference/expressions.html#expression-precedence
+#[derive(Copy, Clone, PartialEq, PartialOrd)]
+pub enum Precedence {
+ // return, break, closures
+ Jump,
+ // = += -= *= /= %= &= |= ^= <<= >>=
+ Assign,
+ // .. ..=
+ Range,
+ // ||
+ Or,
+ // &&
+ And,
+ // let
+ Let,
+ // == != < > <= >=
+ Compare,
+ // |
+ BitOr,
+ // ^
+ BitXor,
+ // &
+ BitAnd,
+ // << >>
+ Shift,
+ // + -
+ Sum,
+ // * / %
+ Product,
+ // as
+ Cast,
+ // unary - * ! & &mut
+ Prefix,
+ // paths, loops, function calls, array indexing, field expressions, method calls
+ Unambiguous,
+}
+
+impl Precedence {
+ pub(crate) const MIN: Self = Precedence::Jump;
+
+ pub(crate) fn of_binop(op: &BinOp) -> Self {
+ match op {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ BinOp::Add(_) | BinOp::Sub(_) => Precedence::Sum,
+ BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Product,
+ BinOp::And(_) => Precedence::And,
+ BinOp::Or(_) => Precedence::Or,
+ BinOp::BitXor(_) => Precedence::BitXor,
+ BinOp::BitAnd(_) => Precedence::BitAnd,
+ BinOp::BitOr(_) => Precedence::BitOr,
+ BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
+
+ BinOp::Eq(_)
+ | BinOp::Lt(_)
+ | BinOp::Le(_)
+ | BinOp::Ne(_)
+ | BinOp::Ge(_)
+ | BinOp::Gt(_) => Precedence::Compare,
+
+ BinOp::AddAssign(_)
+ | BinOp::SubAssign(_)
+ | BinOp::MulAssign(_)
+ | BinOp::DivAssign(_)
+ | BinOp::RemAssign(_)
+ | BinOp::BitXorAssign(_)
+ | BinOp::BitAndAssign(_)
+ | BinOp::BitOrAssign(_)
+ | BinOp::ShlAssign(_)
+ | BinOp::ShrAssign(_) => Precedence::Assign,
+
+ _ => Precedence::MIN,
+ }
+ }
+
+ pub(crate) fn of(e: &Expr) -> Self {
+ fn prefix_attrs(attrs: &[Attribute]) -> Precedence {
+ for attr in attrs {
+ if let AttrStyle::Outer = attr.style {
+ return Precedence::Prefix;
+ }
+ }
+ Precedence::Unambiguous
+ }
+
+ match e {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ Expr::Closure(e) => match e.output {
+ ReturnType::Default => Precedence::Jump,
+ ReturnType::Type(..) => prefix_attrs(&e.attrs),
+ },
+
+ Expr::Break(ExprBreak { expr, .. })
+ | Expr::Return(ExprReturn { expr, .. })
+ | Expr::Yield(ExprYield { expr, .. }) => match expr {
+ Some(_) => Precedence::Jump,
+ None => Precedence::Unambiguous,
+ },
+
+ Expr::Assign(_) => Precedence::Assign,
+ Expr::Range(_) => Precedence::Range,
+ Expr::Binary(e) => Precedence::of_binop(&e.op),
+ Expr::Let(_) => Precedence::Let,
+ Expr::Cast(_) => Precedence::Cast,
+ Expr::RawAddr(_) | Expr::Reference(_) | Expr::Unary(_) => Precedence::Prefix,
+
+ Expr::Array(ExprArray { attrs, .. })
+ | Expr::Async(ExprAsync { attrs, .. })
+ | Expr::Await(ExprAwait { attrs, .. })
+ | Expr::Block(ExprBlock { attrs, .. })
+ | Expr::Call(ExprCall { attrs, .. })
+ | Expr::Const(ExprConst { attrs, .. })
+ | Expr::Continue(ExprContinue { attrs, .. })
+ | Expr::Field(ExprField { attrs, .. })
+ | Expr::ForLoop(ExprForLoop { attrs, .. })
+ | Expr::If(ExprIf { attrs, .. })
+ | Expr::Index(ExprIndex { attrs, .. })
+ | Expr::Infer(ExprInfer { attrs, .. })
+ | Expr::Lit(ExprLit { attrs, .. })
+ | Expr::Loop(ExprLoop { attrs, .. })
+ | Expr::Macro(ExprMacro { attrs, .. })
+ | Expr::Match(ExprMatch { attrs, .. })
+ | Expr::MethodCall(ExprMethodCall { attrs, .. })
+ | Expr::Paren(ExprParen { attrs, .. })
+ | Expr::Path(ExprPath { attrs, .. })
+ | Expr::Repeat(ExprRepeat { attrs, .. })
+ | Expr::Struct(ExprStruct { attrs, .. })
+ | Expr::Try(ExprTry { attrs, .. })
+ | Expr::TryBlock(ExprTryBlock { attrs, .. })
+ | Expr::Tuple(ExprTuple { attrs, .. })
+ | Expr::Unsafe(ExprUnsafe { attrs, .. })
+ | Expr::While(ExprWhile { attrs, .. }) => prefix_attrs(attrs),
+
+ Expr::Group(e) => Precedence::of(&e.expr),
+
+ Expr::Verbatim(_) => Precedence::Unambiguous,
+
+ _ => Precedence::Unambiguous,
+ }
+ }
+}
diff --git a/vendor/prettyplease/src/ring.rs b/vendor/prettyplease/src/ring.rs
new file mode 100644
index 00000000..882a988e
--- /dev/null
+++ b/vendor/prettyplease/src/ring.rs
@@ -0,0 +1,81 @@
+use std::collections::VecDeque;
+use std::ops::{Index, IndexMut, Range};
+
+pub struct RingBuffer<T> {
+ data: VecDeque<T>,
+ // Abstract index of data[0] in infinitely sized queue
+ offset: usize,
+}
+
+impl<T> RingBuffer<T> {
+ pub fn new() -> Self {
+ RingBuffer {
+ data: VecDeque::new(),
+ offset: 0,
+ }
+ }
+
+ pub fn is_empty(&self) -> bool {
+ self.data.is_empty()
+ }
+
+ pub fn len(&self) -> usize {
+ self.data.len()
+ }
+
+ pub fn push(&mut self, value: T) -> usize {
+ let index = self.offset + self.data.len();
+ self.data.push_back(value);
+ index
+ }
+
+ pub fn clear(&mut self) {
+ self.data.clear();
+ }
+
+ pub fn index_range(&self) -> Range<usize> {
+ self.offset..self.offset + self.data.len()
+ }
+
+ pub fn first(&self) -> &T {
+ &self.data[0]
+ }
+
+ pub fn first_mut(&mut self) -> &mut T {
+ &mut self.data[0]
+ }
+
+ pub fn pop_first(&mut self) -> T {
+ self.offset += 1;
+ self.data.pop_front().unwrap()
+ }
+
+ pub fn last(&self) -> &T {
+ self.data.back().unwrap()
+ }
+
+ pub fn last_mut(&mut self) -> &mut T {
+ self.data.back_mut().unwrap()
+ }
+
+ pub fn second_last(&self) -> &T {
+ &self.data[self.data.len() - 2]
+ }
+
+ pub fn pop_last(&mut self) {
+ self.data.pop_back().unwrap();
+ }
+}
+
+impl<T> Index<usize> for RingBuffer<T> {
+ type Output = T;
+ fn index(&self, index: usize) -> &Self::Output {
+ &self.data[index.checked_sub(self.offset).unwrap()]
+ }
+}
+
+impl<T> IndexMut<usize> for RingBuffer<T> {
+ fn index_mut(&mut self, index: usize) -> &mut Self::Output {
+ &mut self.data[index.checked_sub(self.offset).unwrap()]
+ }
+}
diff --git a/vendor/prettyplease/src/stmt.rs b/vendor/prettyplease/src/stmt.rs
new file mode 100644
index 00000000..ce58200e
--- /dev/null
+++ b/vendor/prettyplease/src/stmt.rs
@@ -0,0 +1,221 @@
+use crate::algorithm::Printer;
+use crate::classify;
+use crate::expr;
+use crate::fixup::FixupContext;
+use crate::mac;
+use crate::INDENT;
+use syn::{BinOp, Expr, Stmt};
+
+impl Printer {
+ pub fn stmt(&mut self, stmt: &Stmt, is_last: bool) {
+ match stmt {
+ Stmt::Local(local) => {
+ self.outer_attrs(&local.attrs);
+ self.ibox(0);
+ self.word("let ");
+ self.pat(&local.pat);
+ if let Some(local_init) = &local.init {
+ self.word(" = ");
+ self.neverbreak();
+ self.subexpr(
+ &local_init.expr,
+ local_init.diverge.is_some()
+ && classify::expr_trailing_brace(&local_init.expr),
+ FixupContext::NONE,
+ );
+ if let Some((_else, diverge)) = &local_init.diverge {
+ self.space();
+ self.word("else ");
+ self.end();
+ self.neverbreak();
+ self.cbox(INDENT);
+ if let Some(expr) = expr::simple_block(diverge) {
+ self.small_block(&expr.block, &[]);
+ } else {
+ self.expr_as_small_block(diverge, INDENT);
+ }
+ }
+ }
+ self.end();
+ self.word(";");
+ self.hardbreak();
+ }
+ Stmt::Item(item) => self.item(item),
+ Stmt::Expr(expr, None) => {
+ if break_after(expr) {
+ self.ibox(0);
+ self.expr_beginning_of_line(expr, false, true, FixupContext::new_stmt());
+ if add_semi(expr) {
+ self.word(";");
+ }
+ self.end();
+ self.hardbreak();
+ } else {
+ self.expr_beginning_of_line(expr, false, true, FixupContext::new_stmt());
+ }
+ }
+ Stmt::Expr(expr, Some(_semi)) => {
+ if let Expr::Verbatim(tokens) = expr {
+ if tokens.is_empty() {
+ return;
+ }
+ }
+ self.ibox(0);
+ self.expr_beginning_of_line(expr, false, true, FixupContext::new_stmt());
+ if !remove_semi(expr) {
+ self.word(";");
+ }
+ self.end();
+ self.hardbreak();
+ }
+ Stmt::Macro(stmt) => {
+ self.outer_attrs(&stmt.attrs);
+ let semicolon = stmt.semi_token.is_some()
+ || !is_last && mac::requires_semi(&stmt.mac.delimiter);
+ self.mac(&stmt.mac, None, semicolon);
+ self.hardbreak();
+ }
+ }
+ }
+}
+
+pub fn add_semi(expr: &Expr) -> bool {
+ match expr {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ Expr::Assign(_) | Expr::Break(_) | Expr::Continue(_) | Expr::Return(_) | Expr::Yield(_) => {
+ true
+ }
+ Expr::Binary(expr) =>
+ {
+ match expr.op {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ BinOp::AddAssign(_)
+ | BinOp::SubAssign(_)
+ | BinOp::MulAssign(_)
+ | BinOp::DivAssign(_)
+ | BinOp::RemAssign(_)
+ | BinOp::BitXorAssign(_)
+ | BinOp::BitAndAssign(_)
+ | BinOp::BitOrAssign(_)
+ | BinOp::ShlAssign(_)
+ | BinOp::ShrAssign(_) => true,
+ BinOp::Add(_)
+ | BinOp::Sub(_)
+ | BinOp::Mul(_)
+ | BinOp::Div(_)
+ | BinOp::Rem(_)
+ | BinOp::And(_)
+ | BinOp::Or(_)
+ | BinOp::BitXor(_)
+ | BinOp::BitAnd(_)
+ | BinOp::BitOr(_)
+ | BinOp::Shl(_)
+ | BinOp::Shr(_)
+ | BinOp::Eq(_)
+ | BinOp::Lt(_)
+ | BinOp::Le(_)
+ | BinOp::Ne(_)
+ | BinOp::Ge(_)
+ | BinOp::Gt(_) => false,
+ _ => unimplemented!("unknown BinOp"),
+ }
+ }
+ Expr::Group(group) => add_semi(&group.expr),
+
+ Expr::Array(_)
+ | Expr::Async(_)
+ | Expr::Await(_)
+ | Expr::Block(_)
+ | Expr::Call(_)
+ | Expr::Cast(_)
+ | Expr::Closure(_)
+ | Expr::Const(_)
+ | Expr::Field(_)
+ | Expr::ForLoop(_)
+ | Expr::If(_)
+ | Expr::Index(_)
+ | Expr::Infer(_)
+ | Expr::Let(_)
+ | Expr::Lit(_)
+ | Expr::Loop(_)
+ | Expr::Macro(_)
+ | Expr::Match(_)
+ | Expr::MethodCall(_)
+ | Expr::Paren(_)
+ | Expr::Path(_)
+ | Expr::Range(_)
+ | Expr::RawAddr(_)
+ | Expr::Reference(_)
+ | Expr::Repeat(_)
+ | Expr::Struct(_)
+ | Expr::Try(_)
+ | Expr::TryBlock(_)
+ | Expr::Tuple(_)
+ | Expr::Unary(_)
+ | Expr::Unsafe(_)
+ | Expr::Verbatim(_)
+ | Expr::While(_) => false,
+
+ _ => false,
+ }
+}
+
+pub fn break_after(expr: &Expr) -> bool {
+ if let Expr::Group(group) = expr {
+ if let Expr::Verbatim(verbatim) = group.expr.as_ref() {
+ return !verbatim.is_empty();
+ }
+ }
+ true
+}
+
+fn remove_semi(expr: &Expr) -> bool {
+ match expr {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ Expr::ForLoop(_) | Expr::While(_) => true,
+ Expr::Group(group) => remove_semi(&group.expr),
+ Expr::If(expr) => match &expr.else_branch {
+ Some((_else_token, else_branch)) => remove_semi(else_branch),
+ None => true,
+ },
+
+ Expr::Array(_)
+ | Expr::Assign(_)
+ | Expr::Async(_)
+ | Expr::Await(_)
+ | Expr::Binary(_)
+ | Expr::Block(_)
+ | Expr::Break(_)
+ | Expr::Call(_)
+ | Expr::Cast(_)
+ | Expr::Closure(_)
+ | Expr::Continue(_)
+ | Expr::Const(_)
+ | Expr::Field(_)
+ | Expr::Index(_)
+ | Expr::Infer(_)
+ | Expr::Let(_)
+ | Expr::Lit(_)
+ | Expr::Loop(_)
+ | Expr::Macro(_)
+ | Expr::Match(_)
+ | Expr::MethodCall(_)
+ | Expr::Paren(_)
+ | Expr::Path(_)
+ | Expr::Range(_)
+ | Expr::RawAddr(_)
+ | Expr::Reference(_)
+ | Expr::Repeat(_)
+ | Expr::Return(_)
+ | Expr::Struct(_)
+ | Expr::Try(_)
+ | Expr::TryBlock(_)
+ | Expr::Tuple(_)
+ | Expr::Unary(_)
+ | Expr::Unsafe(_)
+ | Expr::Verbatim(_)
+ | Expr::Yield(_) => false,
+
+ _ => false,
+ }
+}
diff --git a/vendor/prettyplease/src/token.rs b/vendor/prettyplease/src/token.rs
new file mode 100644
index 00000000..e41fd728
--- /dev/null
+++ b/vendor/prettyplease/src/token.rs
@@ -0,0 +1,80 @@
+use crate::algorithm::Printer;
+use proc_macro2::{Delimiter, Ident, Literal, Spacing, TokenStream, TokenTree};
+
+impl Printer {
+ pub fn single_token(&mut self, token: Token, group_contents: fn(&mut Self, TokenStream)) {
+ match token {
+ Token::Group(delimiter, stream) => self.token_group(delimiter, stream, group_contents),
+ Token::Ident(ident) => self.ident(&ident),
+ Token::Punct(ch, _spacing) => self.token_punct(ch),
+ Token::Literal(literal) => self.token_literal(&literal),
+ }
+ }
+
+ fn token_group(
+ &mut self,
+ delimiter: Delimiter,
+ stream: TokenStream,
+ group_contents: fn(&mut Self, TokenStream),
+ ) {
+ self.delimiter_open(delimiter);
+ if !stream.is_empty() {
+ if delimiter == Delimiter::Brace {
+ self.space();
+ }
+ group_contents(self, stream);
+ if delimiter == Delimiter::Brace {
+ self.space();
+ }
+ }
+ self.delimiter_close(delimiter);
+ }
+
+ pub fn ident(&mut self, ident: &Ident) {
+ self.word(ident.to_string());
+ }
+
+ pub fn token_punct(&mut self, ch: char) {
+ self.word(ch.to_string());
+ }
+
+ pub fn token_literal(&mut self, literal: &Literal) {
+ self.word(literal.to_string());
+ }
+
+ pub fn delimiter_open(&mut self, delimiter: Delimiter) {
+ self.word(match delimiter {
+ Delimiter::Parenthesis => "(",
+ Delimiter::Brace => "{",
+ Delimiter::Bracket => "[",
+ Delimiter::None => return,
+ });
+ }
+
+ pub fn delimiter_close(&mut self, delimiter: Delimiter) {
+ self.word(match delimiter {
+ Delimiter::Parenthesis => ")",
+ Delimiter::Brace => "}",
+ Delimiter::Bracket => "]",
+ Delimiter::None => return,
+ });
+ }
+}
+
+pub enum Token {
+ Group(Delimiter, TokenStream),
+ Ident(Ident),
+ Punct(char, Spacing),
+ Literal(Literal),
+}
+
+impl From<TokenTree> for Token {
+ fn from(tt: TokenTree) -> Self {
+ match tt {
+ TokenTree::Group(group) => Token::Group(group.delimiter(), group.stream()),
+ TokenTree::Ident(ident) => Token::Ident(ident),
+ TokenTree::Punct(punct) => Token::Punct(punct.as_char(), punct.spacing()),
+ TokenTree::Literal(literal) => Token::Literal(literal),
+ }
+ }
+}
diff --git a/vendor/prettyplease/src/ty.rs b/vendor/prettyplease/src/ty.rs
new file mode 100644
index 00000000..7f92821a
--- /dev/null
+++ b/vendor/prettyplease/src/ty.rs
@@ -0,0 +1,339 @@
+use crate::algorithm::Printer;
+use crate::fixup::FixupContext;
+use crate::iter::IterDelimited;
+use crate::path::PathKind;
+use crate::INDENT;
+use proc_macro2::TokenStream;
+use syn::{
+ Abi, BareFnArg, BareVariadic, ReturnType, Type, TypeArray, TypeBareFn, TypeGroup,
+ TypeImplTrait, TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr, TypeReference,
+ TypeSlice, TypeTraitObject, TypeTuple,
+};
+
+impl Printer {
+ pub fn ty(&mut self, ty: &Type) {
+ match ty {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ Type::Array(ty) => self.type_array(ty),
+ Type::BareFn(ty) => self.type_bare_fn(ty),
+ Type::Group(ty) => self.type_group(ty),
+ Type::ImplTrait(ty) => self.type_impl_trait(ty),
+ Type::Infer(ty) => self.type_infer(ty),
+ Type::Macro(ty) => self.type_macro(ty),
+ Type::Never(ty) => self.type_never(ty),
+ Type::Paren(ty) => self.type_paren(ty),
+ Type::Path(ty) => self.type_path(ty),
+ Type::Ptr(ty) => self.type_ptr(ty),
+ Type::Reference(ty) => self.type_reference(ty),
+ Type::Slice(ty) => self.type_slice(ty),
+ Type::TraitObject(ty) => self.type_trait_object(ty),
+ Type::Tuple(ty) => self.type_tuple(ty),
+ Type::Verbatim(ty) => self.type_verbatim(ty),
+ _ => unimplemented!("unknown Type"),
+ }
+ }
+
+ fn type_array(&mut self, ty: &TypeArray) {
+ self.word("[");
+ self.ty(&ty.elem);
+ self.word("; ");
+ self.expr(&ty.len, FixupContext::NONE);
+ self.word("]");
+ }
+
+ fn type_bare_fn(&mut self, ty: &TypeBareFn) {
+ if let Some(bound_lifetimes) = &ty.lifetimes {
+ self.bound_lifetimes(bound_lifetimes);
+ }
+ if ty.unsafety.is_some() {
+ self.word("unsafe ");
+ }
+ if let Some(abi) = &ty.abi {
+ self.abi(abi);
+ }
+ self.word("fn(");
+ self.cbox(INDENT);
+ self.zerobreak();
+ for bare_fn_arg in ty.inputs.iter().delimited() {
+ self.bare_fn_arg(&bare_fn_arg);
+ self.trailing_comma(bare_fn_arg.is_last && ty.variadic.is_none());
+ }
+ if let Some(variadic) = &ty.variadic {
+ self.bare_variadic(variadic);
+ self.zerobreak();
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word(")");
+ self.return_type(&ty.output);
+ }
+
+ fn type_group(&mut self, ty: &TypeGroup) {
+ self.ty(&ty.elem);
+ }
+
+ fn type_impl_trait(&mut self, ty: &TypeImplTrait) {
+ self.word("impl ");
+ for type_param_bound in ty.bounds.iter().delimited() {
+ if !type_param_bound.is_first {
+ self.word(" + ");
+ }
+ self.type_param_bound(&type_param_bound);
+ }
+ }
+
+ fn type_infer(&mut self, ty: &TypeInfer) {
+ let _ = ty;
+ self.word("_");
+ }
+
+ fn type_macro(&mut self, ty: &TypeMacro) {
+ let semicolon = false;
+ self.mac(&ty.mac, None, semicolon);
+ }
+
+ fn type_never(&mut self, ty: &TypeNever) {
+ let _ = ty;
+ self.word("!");
+ }
+
+ fn type_paren(&mut self, ty: &TypeParen) {
+ self.word("(");
+ self.ty(&ty.elem);
+ self.word(")");
+ }
+
+ fn type_path(&mut self, ty: &TypePath) {
+ self.qpath(&ty.qself, &ty.path, PathKind::Type);
+ }
+
+ fn type_ptr(&mut self, ty: &TypePtr) {
+ self.word("*");
+ if ty.mutability.is_some() {
+ self.word("mut ");
+ } else {
+ self.word("const ");
+ }
+ self.ty(&ty.elem);
+ }
+
+ fn type_reference(&mut self, ty: &TypeReference) {
+ self.word("&");
+ if let Some(lifetime) = &ty.lifetime {
+ self.lifetime(lifetime);
+ self.nbsp();
+ }
+ if ty.mutability.is_some() {
+ self.word("mut ");
+ }
+ self.ty(&ty.elem);
+ }
+
+ fn type_slice(&mut self, ty: &TypeSlice) {
+ self.word("[");
+ self.ty(&ty.elem);
+ self.word("]");
+ }
+
+ fn type_trait_object(&mut self, ty: &TypeTraitObject) {
+ self.word("dyn ");
+ for type_param_bound in ty.bounds.iter().delimited() {
+ if !type_param_bound.is_first {
+ self.word(" + ");
+ }
+ self.type_param_bound(&type_param_bound);
+ }
+ }
+
+ fn type_tuple(&mut self, ty: &TypeTuple) {
+ self.word("(");
+ self.cbox(INDENT);
+ self.zerobreak();
+ for elem in ty.elems.iter().delimited() {
+ self.ty(&elem);
+ if ty.elems.len() == 1 {
+ self.word(",");
+ self.zerobreak();
+ } else {
+ self.trailing_comma(elem.is_last);
+ }
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word(")");
+ }
+
+ #[cfg(not(feature = "verbatim"))]
+ fn type_verbatim(&mut self, ty: &TokenStream) {
+ unimplemented!("Type::Verbatim `{}`", ty);
+ }
+
+ #[cfg(feature = "verbatim")]
+ fn type_verbatim(&mut self, tokens: &TokenStream) {
+ use syn::parse::{Parse, ParseStream, Result};
+ use syn::punctuated::Punctuated;
+ use syn::{token, FieldsNamed, Token, TypeParamBound};
+
+ enum TypeVerbatim {
+ Ellipsis,
+ AnonStruct(AnonStruct),
+ AnonUnion(AnonUnion),
+ DynStar(DynStar),
+ MutSelf(MutSelf),
+ NotType(NotType),
+ }
+
+ struct AnonStruct {
+ fields: FieldsNamed,
+ }
+
+ struct AnonUnion {
+ fields: FieldsNamed,
+ }
+
+ struct DynStar {
+ bounds: Punctuated<TypeParamBound, Token![+]>,
+ }
+
+ struct MutSelf {
+ ty: Option<Type>,
+ }
+
+ struct NotType {
+ inner: Type,
+ }
+
+ impl Parse for TypeVerbatim {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let lookahead = input.lookahead1();
+ if lookahead.peek(Token![struct]) {
+ input.parse::<Token![struct]>()?;
+ let fields: FieldsNamed = input.parse()?;
+ Ok(TypeVerbatim::AnonStruct(AnonStruct { fields }))
+ } else if lookahead.peek(Token![union]) && input.peek2(token::Brace) {
+ input.parse::<Token![union]>()?;
+ let fields: FieldsNamed = input.parse()?;
+ Ok(TypeVerbatim::AnonUnion(AnonUnion { fields }))
+ } else if lookahead.peek(Token![dyn]) {
+ input.parse::<Token![dyn]>()?;
+ input.parse::<Token![*]>()?;
+ let bounds = input.parse_terminated(TypeParamBound::parse, Token![+])?;
+ Ok(TypeVerbatim::DynStar(DynStar { bounds }))
+ } else if lookahead.peek(Token![mut]) {
+ input.parse::<Token![mut]>()?;
+ input.parse::<Token![self]>()?;
+ let ty = if input.is_empty() {
+ None
+ } else {
+ input.parse::<Token![:]>()?;
+ let ty: Type = input.parse()?;
+ Some(ty)
+ };
+ Ok(TypeVerbatim::MutSelf(MutSelf { ty }))
+ } else if lookahead.peek(Token![!]) {
+ input.parse::<Token![!]>()?;
+ let inner: Type = input.parse()?;
+ Ok(TypeVerbatim::NotType(NotType { inner }))
+ } else if lookahead.peek(Token![...]) {
+ input.parse::<Token![...]>()?;
+ Ok(TypeVerbatim::Ellipsis)
+ } else {
+ Err(lookahead.error())
+ }
+ }
+ }
+
+ let ty: TypeVerbatim = match syn::parse2(tokens.clone()) {
+ Ok(ty) => ty,
+ Err(_) => unimplemented!("Type::Verbatim `{}`", tokens),
+ };
+
+ match ty {
+ TypeVerbatim::Ellipsis => {
+ self.word("...");
+ }
+ TypeVerbatim::AnonStruct(ty) => {
+ self.cbox(INDENT);
+ self.word("struct {");
+ self.hardbreak_if_nonempty();
+ for field in &ty.fields.named {
+ self.field(field);
+ self.word(",");
+ self.hardbreak();
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word("}");
+ }
+ TypeVerbatim::AnonUnion(ty) => {
+ self.cbox(INDENT);
+ self.word("union {");
+ self.hardbreak_if_nonempty();
+ for field in &ty.fields.named {
+ self.field(field);
+ self.word(",");
+ self.hardbreak();
+ }
+ self.offset(-INDENT);
+ self.end();
+ self.word("}");
+ }
+ TypeVerbatim::DynStar(ty) => {
+ self.word("dyn* ");
+ for type_param_bound in ty.bounds.iter().delimited() {
+ if !type_param_bound.is_first {
+ self.word(" + ");
+ }
+ self.type_param_bound(&type_param_bound);
+ }
+ }
+ TypeVerbatim::MutSelf(bare_fn_arg) => {
+ self.word("mut self");
+ if let Some(ty) = &bare_fn_arg.ty {
+ self.word(": ");
+ self.ty(ty);
+ }
+ }
+ TypeVerbatim::NotType(ty) => {
+ self.word("!");
+ self.ty(&ty.inner);
+ }
+ }
+ }
+
+ pub fn return_type(&mut self, ty: &ReturnType) {
+ match ty {
+ ReturnType::Default => {}
+ ReturnType::Type(_arrow, ty) => {
+ self.word(" -> ");
+ self.ty(ty);
+ }
+ }
+ }
+
+ fn bare_fn_arg(&mut self, bare_fn_arg: &BareFnArg) {
+ self.outer_attrs(&bare_fn_arg.attrs);
+ if let Some((name, _colon)) = &bare_fn_arg.name {
+ self.ident(name);
+ self.word(": ");
+ }
+ self.ty(&bare_fn_arg.ty);
+ }
+
+ fn bare_variadic(&mut self, variadic: &BareVariadic) {
+ self.outer_attrs(&variadic.attrs);
+ if let Some((name, _colon)) = &variadic.name {
+ self.ident(name);
+ self.word(": ");
+ }
+ self.word("...");
+ }
+
+ pub fn abi(&mut self, abi: &Abi) {
+ self.word("extern ");
+ if let Some(name) = &abi.name {
+ self.lit_str(name);
+ self.nbsp();
+ }
+ }
+}
diff --git a/vendor/prettyplease/tests/test.rs b/vendor/prettyplease/tests/test.rs
new file mode 100644
index 00000000..aa6b849f
--- /dev/null
+++ b/vendor/prettyplease/tests/test.rs
@@ -0,0 +1,51 @@
+use indoc::indoc;
+use proc_macro2::{Delimiter, Group, TokenStream};
+use quote::quote;
+
+#[track_caller]
+fn test(tokens: TokenStream, expected: &str) {
+ let syntax_tree: syn::File = syn::parse2(tokens).unwrap();
+ let pretty = prettyplease::unparse(&syntax_tree);
+ assert_eq!(pretty, expected);
+}
+
+#[test]
+fn test_parenthesize_cond() {
+ let s = Group::new(Delimiter::None, quote!(Struct {}));
+ test(
+ quote! {
+ fn main() {
+ if #s == #s {}
+ }
+ },
+ indoc! {"
+ fn main() {
+ if (Struct {}) == (Struct {}) {}
+ }
+ "},
+ );
+}
+
+#[test]
+fn test_parenthesize_match_guard() {
+ let expr_struct = Group::new(Delimiter::None, quote!(Struct {}));
+ let expr_binary = Group::new(Delimiter::None, quote!(true && false));
+ test(
+ quote! {
+ fn main() {
+ match () {
+ () if let _ = #expr_struct => {}
+ () if let _ = #expr_binary => {}
+ }
+ }
+ },
+ indoc! {"
+ fn main() {
+ match () {
+ () if let _ = Struct {} => {}
+ () if let _ = (true && false) => {}
+ }
+ }
+ "},
+ );
+}
diff --git a/vendor/prettyplease/tests/test_precedence.rs b/vendor/prettyplease/tests/test_precedence.rs
new file mode 100644
index 00000000..f1eec232
--- /dev/null
+++ b/vendor/prettyplease/tests/test_precedence.rs
@@ -0,0 +1,900 @@
+use proc_macro2::{Ident, Span, TokenStream};
+use quote::ToTokens as _;
+use std::mem;
+use std::process::ExitCode;
+use syn::punctuated::Punctuated;
+use syn::visit_mut::{self, VisitMut};
+use syn::{
+ token, AngleBracketedGenericArguments, Arm, BinOp, Block, Expr, ExprArray, ExprAssign,
+ ExprAsync, ExprAwait, ExprBinary, ExprBlock, ExprBreak, ExprCall, ExprCast, ExprClosure,
+ ExprConst, ExprContinue, ExprField, ExprForLoop, ExprIf, ExprIndex, ExprLet, ExprLit, ExprLoop,
+ ExprMacro, ExprMatch, ExprMethodCall, ExprPath, ExprRange, ExprRawAddr, ExprReference,
+ ExprReturn, ExprStruct, ExprTry, ExprTryBlock, ExprUnary, ExprUnsafe, ExprWhile, ExprYield,
+ File, GenericArgument, Generics, Item, ItemConst, Label, Lifetime, LifetimeParam, Lit, LitInt,
+ Macro, MacroDelimiter, Member, Pat, PatWild, Path, PathArguments, PathSegment,
+ PointerMutability, QSelf, RangeLimits, ReturnType, Stmt, StmtMacro, Token, Type, TypeInfer,
+ TypeParam, TypePath, UnOp, Visibility,
+};
+
+struct FlattenParens;
+
+impl VisitMut for FlattenParens {
+ fn visit_expr_mut(&mut self, e: &mut Expr) {
+ while let Expr::Paren(paren) = e {
+ *e = mem::replace(&mut *paren.expr, Expr::PLACEHOLDER);
+ }
+ visit_mut::visit_expr_mut(self, e);
+ }
+}
+
+struct AsIfPrinted;
+
+impl VisitMut for AsIfPrinted {
+ fn visit_generics_mut(&mut self, generics: &mut Generics) {
+ if generics.params.is_empty() {
+ generics.lt_token = None;
+ generics.gt_token = None;
+ }
+ if let Some(where_clause) = &generics.where_clause {
+ if where_clause.predicates.is_empty() {
+ generics.where_clause = None;
+ }
+ }
+ visit_mut::visit_generics_mut(self, generics);
+ }
+
+ fn visit_lifetime_param_mut(&mut self, param: &mut LifetimeParam) {
+ if param.bounds.is_empty() {
+ param.colon_token = None;
+ }
+ visit_mut::visit_lifetime_param_mut(self, param);
+ }
+
+ fn visit_stmt_mut(&mut self, stmt: &mut Stmt) {
+ if let Stmt::Expr(expr, semi) = stmt {
+ if let Expr::Macro(e) = expr {
+ if match e.mac.delimiter {
+ MacroDelimiter::Brace(_) => true,
+ MacroDelimiter::Paren(_) | MacroDelimiter::Bracket(_) => semi.is_some(),
+ } {
+ let expr = match mem::replace(expr, Expr::PLACEHOLDER) {
+ Expr::Macro(expr) => expr,
+ _ => unreachable!(),
+ };
+ *stmt = Stmt::Macro(StmtMacro {
+ attrs: expr.attrs,
+ mac: expr.mac,
+ semi_token: *semi,
+ });
+ }
+ }
+ }
+ visit_mut::visit_stmt_mut(self, stmt);
+ }
+
+ fn visit_type_param_mut(&mut self, param: &mut TypeParam) {
+ if param.bounds.is_empty() {
+ param.colon_token = None;
+ }
+ visit_mut::visit_type_param_mut(self, param);
+ }
+}
+
+#[test]
+fn test_permutations() -> ExitCode {
+ fn iter(depth: usize, f: &mut dyn FnMut(Expr)) {
+ let span = Span::call_site();
+
+ // Expr::Path
+ f(Expr::Path(ExprPath {
+ // `x`
+ attrs: Vec::new(),
+ qself: None,
+ path: Path::from(Ident::new("x", span)),
+ }));
+ if false {
+ f(Expr::Path(ExprPath {
+ // `x::<T>`
+ attrs: Vec::new(),
+ qself: None,
+ path: Path {
+ leading_colon: None,
+ segments: Punctuated::from_iter([PathSegment {
+ ident: Ident::new("x", span),
+ arguments: PathArguments::AngleBracketed(AngleBracketedGenericArguments {
+ colon2_token: Some(Token![::](span)),
+ lt_token: Token![<](span),
+ args: Punctuated::from_iter([GenericArgument::Type(Type::Path(
+ TypePath {
+ qself: None,
+ path: Path::from(Ident::new("T", span)),
+ },
+ ))]),
+ gt_token: Token![>](span),
+ }),
+ }]),
+ },
+ }));
+ f(Expr::Path(ExprPath {
+ // `<T as Trait>::CONST`
+ attrs: Vec::new(),
+ qself: Some(QSelf {
+ lt_token: Token![<](span),
+ ty: Box::new(Type::Path(TypePath {
+ qself: None,
+ path: Path::from(Ident::new("T", span)),
+ })),
+ position: 1,
+ as_token: Some(Token![as](span)),
+ gt_token: Token![>](span),
+ }),
+ path: Path {
+ leading_colon: None,
+ segments: Punctuated::from_iter([
+ PathSegment::from(Ident::new("Trait", span)),
+ PathSegment::from(Ident::new("CONST", span)),
+ ]),
+ },
+ }));
+ }
+
+ let depth = match depth.checked_sub(1) {
+ Some(depth) => depth,
+ None => return,
+ };
+
+ // Expr::Assign
+ iter(depth, &mut |expr| {
+ iter(0, &mut |simple| {
+ f(Expr::Assign(ExprAssign {
+ // `x = $expr`
+ attrs: Vec::new(),
+ left: Box::new(simple.clone()),
+ eq_token: Token![=](span),
+ right: Box::new(expr.clone()),
+ }));
+ f(Expr::Assign(ExprAssign {
+ // `$expr = x`
+ attrs: Vec::new(),
+ left: Box::new(expr.clone()),
+ eq_token: Token![=](span),
+ right: Box::new(simple),
+ }));
+ });
+ });
+
+ // Expr::Binary
+ iter(depth, &mut |expr| {
+ iter(0, &mut |simple| {
+ for op in [
+ BinOp::Add(Token![+](span)),
+ //BinOp::Sub(Token![-](span)),
+ //BinOp::Mul(Token![*](span)),
+ //BinOp::Div(Token![/](span)),
+ //BinOp::Rem(Token![%](span)),
+ //BinOp::And(Token![&&](span)),
+ //BinOp::Or(Token![||](span)),
+ //BinOp::BitXor(Token![^](span)),
+ //BinOp::BitAnd(Token![&](span)),
+ //BinOp::BitOr(Token![|](span)),
+ //BinOp::Shl(Token![<<](span)),
+ //BinOp::Shr(Token![>>](span)),
+ //BinOp::Eq(Token![==](span)),
+ BinOp::Lt(Token![<](span)),
+ //BinOp::Le(Token![<=](span)),
+ //BinOp::Ne(Token![!=](span)),
+ //BinOp::Ge(Token![>=](span)),
+ //BinOp::Gt(Token![>](span)),
+ BinOp::ShlAssign(Token![<<=](span)),
+ ] {
+ f(Expr::Binary(ExprBinary {
+ // `x + $expr`
+ attrs: Vec::new(),
+ left: Box::new(simple.clone()),
+ op,
+ right: Box::new(expr.clone()),
+ }));
+ f(Expr::Binary(ExprBinary {
+ // `$expr + x`
+ attrs: Vec::new(),
+ left: Box::new(expr.clone()),
+ op,
+ right: Box::new(simple.clone()),
+ }));
+ }
+ });
+ });
+
+ // Expr::Block
+ f(Expr::Block(ExprBlock {
+ // `{}`
+ attrs: Vec::new(),
+ label: None,
+ block: Block {
+ brace_token: token::Brace(span),
+ stmts: Vec::new(),
+ },
+ }));
+
+ // Expr::Break
+ f(Expr::Break(ExprBreak {
+ // `break`
+ attrs: Vec::new(),
+ break_token: Token![break](span),
+ label: None,
+ expr: None,
+ }));
+ iter(depth, &mut |expr| {
+ f(Expr::Break(ExprBreak {
+ // `break $expr`
+ attrs: Vec::new(),
+ break_token: Token![break](span),
+ label: None,
+ expr: Some(Box::new(expr)),
+ }));
+ });
+
+ // Expr::Call
+ iter(depth, &mut |expr| {
+ f(Expr::Call(ExprCall {
+ // `$expr()`
+ attrs: Vec::new(),
+ func: Box::new(expr),
+ paren_token: token::Paren(span),
+ args: Punctuated::new(),
+ }));
+ });
+
+ // Expr::Cast
+ iter(depth, &mut |expr| {
+ f(Expr::Cast(ExprCast {
+ // `$expr as T`
+ attrs: Vec::new(),
+ expr: Box::new(expr),
+ as_token: Token![as](span),
+ ty: Box::new(Type::Path(TypePath {
+ qself: None,
+ path: Path::from(Ident::new("T", span)),
+ })),
+ }));
+ });
+
+ // Expr::Closure
+ iter(depth, &mut |expr| {
+ f(Expr::Closure(ExprClosure {
+ // `|| $expr`
+ attrs: Vec::new(),
+ lifetimes: None,
+ constness: None,
+ movability: None,
+ asyncness: None,
+ capture: None,
+ or1_token: Token![|](span),
+ inputs: Punctuated::new(),
+ or2_token: Token![|](span),
+ output: ReturnType::Default,
+ body: Box::new(expr),
+ }));
+ });
+
+ // Expr::Field
+ iter(depth, &mut |expr| {
+ f(Expr::Field(ExprField {
+ // `$expr.field`
+ attrs: Vec::new(),
+ base: Box::new(expr),
+ dot_token: Token![.](span),
+ member: Member::Named(Ident::new("field", span)),
+ }));
+ });
+
+ // Expr::If
+ iter(depth, &mut |expr| {
+ f(Expr::If(ExprIf {
+ // `if $expr {}`
+ attrs: Vec::new(),
+ if_token: Token![if](span),
+ cond: Box::new(expr),
+ then_branch: Block {
+ brace_token: token::Brace(span),
+ stmts: Vec::new(),
+ },
+ else_branch: None,
+ }));
+ });
+
+ // Expr::Let
+ iter(depth, &mut |expr| {
+ f(Expr::Let(ExprLet {
+ attrs: Vec::new(),
+ let_token: Token![let](span),
+ pat: Box::new(Pat::Wild(PatWild {
+ attrs: Vec::new(),
+ underscore_token: Token![_](span),
+ })),
+ eq_token: Token![=](span),
+ expr: Box::new(expr),
+ }));
+ });
+
+ // Expr::Range
+ f(Expr::Range(ExprRange {
+ // `..`
+ attrs: Vec::new(),
+ start: None,
+ limits: RangeLimits::HalfOpen(Token![..](span)),
+ end: None,
+ }));
+ iter(depth, &mut |expr| {
+ f(Expr::Range(ExprRange {
+ // `..$expr`
+ attrs: Vec::new(),
+ start: None,
+ limits: RangeLimits::HalfOpen(Token![..](span)),
+ end: Some(Box::new(expr.clone())),
+ }));
+ f(Expr::Range(ExprRange {
+ // `$expr..`
+ attrs: Vec::new(),
+ start: Some(Box::new(expr)),
+ limits: RangeLimits::HalfOpen(Token![..](span)),
+ end: None,
+ }));
+ });
+
+ // Expr::Reference
+ iter(depth, &mut |expr| {
+ f(Expr::Reference(ExprReference {
+ // `&$expr`
+ attrs: Vec::new(),
+ and_token: Token![&](span),
+ mutability: None,
+ expr: Box::new(expr),
+ }));
+ });
+
+ // Expr::Return
+ f(Expr::Return(ExprReturn {
+ // `return`
+ attrs: Vec::new(),
+ return_token: Token![return](span),
+ expr: None,
+ }));
+ iter(depth, &mut |expr| {
+ f(Expr::Return(ExprReturn {
+ // `return $expr`
+ attrs: Vec::new(),
+ return_token: Token![return](span),
+ expr: Some(Box::new(expr)),
+ }));
+ });
+
+ // Expr::Try
+ iter(depth, &mut |expr| {
+ f(Expr::Try(ExprTry {
+ // `$expr?`
+ attrs: Vec::new(),
+ expr: Box::new(expr),
+ question_token: Token![?](span),
+ }));
+ });
+
+ // Expr::Unary
+ iter(depth, &mut |expr| {
+ for op in [
+ UnOp::Deref(Token![*](span)),
+ //UnOp::Not(Token![!](span)),
+ //UnOp::Neg(Token![-](span)),
+ ] {
+ f(Expr::Unary(ExprUnary {
+ // `*$expr`
+ attrs: Vec::new(),
+ op,
+ expr: Box::new(expr.clone()),
+ }));
+ }
+ });
+
+ if false {
+ // Expr::Array
+ f(Expr::Array(ExprArray {
+ // `[]`
+ attrs: Vec::new(),
+ bracket_token: token::Bracket(span),
+ elems: Punctuated::new(),
+ }));
+
+ // Expr::Async
+ f(Expr::Async(ExprAsync {
+ // `async {}`
+ attrs: Vec::new(),
+ async_token: Token![async](span),
+ capture: None,
+ block: Block {
+ brace_token: token::Brace(span),
+ stmts: Vec::new(),
+ },
+ }));
+
+ // Expr::Await
+ iter(depth, &mut |expr| {
+ f(Expr::Await(ExprAwait {
+ // `$expr.await`
+ attrs: Vec::new(),
+ base: Box::new(expr),
+ dot_token: Token![.](span),
+ await_token: Token![await](span),
+ }));
+ });
+
+ // Expr::Block
+ f(Expr::Block(ExprBlock {
+ // `'a: {}`
+ attrs: Vec::new(),
+ label: Some(Label {
+ name: Lifetime::new("'a", span),
+ colon_token: Token![:](span),
+ }),
+ block: Block {
+ brace_token: token::Brace(span),
+ stmts: Vec::new(),
+ },
+ }));
+ iter(depth, &mut |expr| {
+ f(Expr::Block(ExprBlock {
+ // `{ $expr }`
+ attrs: Vec::new(),
+ label: None,
+ block: Block {
+ brace_token: token::Brace(span),
+ stmts: Vec::from([Stmt::Expr(expr.clone(), None)]),
+ },
+ }));
+ f(Expr::Block(ExprBlock {
+ // `{ $expr; }`
+ attrs: Vec::new(),
+ label: None,
+ block: Block {
+ brace_token: token::Brace(span),
+ stmts: Vec::from([Stmt::Expr(expr, Some(Token![;](span)))]),
+ },
+ }));
+ });
+
+ // Expr::Break
+ f(Expr::Break(ExprBreak {
+ // `break 'a`
+ attrs: Vec::new(),
+ break_token: Token![break](span),
+ label: Some(Lifetime::new("'a", span)),
+ expr: None,
+ }));
+ iter(depth, &mut |expr| {
+ f(Expr::Break(ExprBreak {
+ // `break 'a $expr`
+ attrs: Vec::new(),
+ break_token: Token![break](span),
+ label: Some(Lifetime::new("'a", span)),
+ expr: Some(Box::new(expr)),
+ }));
+ });
+
+ // Expr::Closure
+ f(Expr::Closure(ExprClosure {
+ // `|| -> T {}`
+ attrs: Vec::new(),
+ lifetimes: None,
+ constness: None,
+ movability: None,
+ asyncness: None,
+ capture: None,
+ or1_token: Token![|](span),
+ inputs: Punctuated::new(),
+ or2_token: Token![|](span),
+ output: ReturnType::Type(
+ Token![->](span),
+ Box::new(Type::Path(TypePath {
+ qself: None,
+ path: Path::from(Ident::new("T", span)),
+ })),
+ ),
+ body: Box::new(Expr::Block(ExprBlock {
+ attrs: Vec::new(),
+ label: None,
+ block: Block {
+ brace_token: token::Brace(span),
+ stmts: Vec::new(),
+ },
+ })),
+ }));
+
+ // Expr::Const
+ f(Expr::Const(ExprConst {
+ // `const {}`
+ attrs: Vec::new(),
+ const_token: Token![const](span),
+ block: Block {
+ brace_token: token::Brace(span),
+ stmts: Vec::new(),
+ },
+ }));
+
+ // Expr::Continue
+ f(Expr::Continue(ExprContinue {
+ // `continue`
+ attrs: Vec::new(),
+ continue_token: Token![continue](span),
+ label: None,
+ }));
+ f(Expr::Continue(ExprContinue {
+ // `continue 'a`
+ attrs: Vec::new(),
+ continue_token: Token![continue](span),
+ label: Some(Lifetime::new("'a", span)),
+ }));
+
+ // Expr::ForLoop
+ iter(depth, &mut |expr| {
+ f(Expr::ForLoop(ExprForLoop {
+ // `for _ in $expr {}`
+ attrs: Vec::new(),
+ label: None,
+ for_token: Token![for](span),
+ pat: Box::new(Pat::Wild(PatWild {
+ attrs: Vec::new(),
+ underscore_token: Token![_](span),
+ })),
+ in_token: Token![in](span),
+ expr: Box::new(expr.clone()),
+ body: Block {
+ brace_token: token::Brace(span),
+ stmts: Vec::new(),
+ },
+ }));
+ f(Expr::ForLoop(ExprForLoop {
+ // `'a: for _ in $expr {}`
+ attrs: Vec::new(),
+ label: Some(Label {
+ name: Lifetime::new("'a", span),
+ colon_token: Token![:](span),
+ }),
+ for_token: Token![for](span),
+ pat: Box::new(Pat::Wild(PatWild {
+ attrs: Vec::new(),
+ underscore_token: Token![_](span),
+ })),
+ in_token: Token![in](span),
+ expr: Box::new(expr),
+ body: Block {
+ brace_token: token::Brace(span),
+ stmts: Vec::new(),
+ },
+ }));
+ });
+
+ // Expr::Index
+ iter(depth, &mut |expr| {
+ f(Expr::Index(ExprIndex {
+ // `$expr[0]`
+ attrs: Vec::new(),
+ expr: Box::new(expr),
+ bracket_token: token::Bracket(span),
+ index: Box::new(Expr::Lit(ExprLit {
+ attrs: Vec::new(),
+ lit: Lit::Int(LitInt::new("0", span)),
+ })),
+ }));
+ });
+
+ // Expr::Loop
+ f(Expr::Loop(ExprLoop {
+ // `loop {}`
+ attrs: Vec::new(),
+ label: None,
+ loop_token: Token![loop](span),
+ body: Block {
+ brace_token: token::Brace(span),
+ stmts: Vec::new(),
+ },
+ }));
+ f(Expr::Loop(ExprLoop {
+ // `'a: loop {}`
+ attrs: Vec::new(),
+ label: Some(Label {
+ name: Lifetime::new("'a", span),
+ colon_token: Token![:](span),
+ }),
+ loop_token: Token![loop](span),
+ body: Block {
+ brace_token: token::Brace(span),
+ stmts: Vec::new(),
+ },
+ }));
+
+ // Expr::Macro
+ f(Expr::Macro(ExprMacro {
+ // `m!()`
+ attrs: Vec::new(),
+ mac: Macro {
+ path: Path::from(Ident::new("m", span)),
+ bang_token: Token![!](span),
+ delimiter: MacroDelimiter::Paren(token::Paren(span)),
+ tokens: TokenStream::new(),
+ },
+ }));
+ f(Expr::Macro(ExprMacro {
+ // `m! {}`
+ attrs: Vec::new(),
+ mac: Macro {
+ path: Path::from(Ident::new("m", span)),
+ bang_token: Token![!](span),
+ delimiter: MacroDelimiter::Brace(token::Brace(span)),
+ tokens: TokenStream::new(),
+ },
+ }));
+
+ // Expr::Match
+ iter(depth, &mut |expr| {
+ f(Expr::Match(ExprMatch {
+ // `match $expr {}`
+ attrs: Vec::new(),
+ match_token: Token![match](span),
+ expr: Box::new(expr.clone()),
+ brace_token: token::Brace(span),
+ arms: Vec::new(),
+ }));
+ f(Expr::Match(ExprMatch {
+ // `match x { _ => $expr }`
+ attrs: Vec::new(),
+ match_token: Token![match](span),
+ expr: Box::new(Expr::Path(ExprPath {
+ attrs: Vec::new(),
+ qself: None,
+ path: Path::from(Ident::new("x", span)),
+ })),
+ brace_token: token::Brace(span),
+ arms: Vec::from([Arm {
+ attrs: Vec::new(),
+ pat: Pat::Wild(PatWild {
+ attrs: Vec::new(),
+ underscore_token: Token![_](span),
+ }),
+ guard: None,
+ fat_arrow_token: Token![=>](span),
+ body: Box::new(expr.clone()),
+ comma: None,
+ }]),
+ }));
+ f(Expr::Match(ExprMatch {
+ // `match x { _ if $expr => {} }`
+ attrs: Vec::new(),
+ match_token: Token![match](span),
+ expr: Box::new(Expr::Path(ExprPath {
+ attrs: Vec::new(),
+ qself: None,
+ path: Path::from(Ident::new("x", span)),
+ })),
+ brace_token: token::Brace(span),
+ arms: Vec::from([Arm {
+ attrs: Vec::new(),
+ pat: Pat::Wild(PatWild {
+ attrs: Vec::new(),
+ underscore_token: Token![_](span),
+ }),
+ guard: Some((Token![if](span), Box::new(expr))),
+ fat_arrow_token: Token![=>](span),
+ body: Box::new(Expr::Block(ExprBlock {
+ attrs: Vec::new(),
+ label: None,
+ block: Block {
+ brace_token: token::Brace(span),
+ stmts: Vec::new(),
+ },
+ })),
+ comma: None,
+ }]),
+ }));
+ });
+
+ // Expr::MethodCall
+ iter(depth, &mut |expr| {
+ f(Expr::MethodCall(ExprMethodCall {
+ // `$expr.method()`
+ attrs: Vec::new(),
+ receiver: Box::new(expr.clone()),
+ dot_token: Token![.](span),
+ method: Ident::new("method", span),
+ turbofish: None,
+ paren_token: token::Paren(span),
+ args: Punctuated::new(),
+ }));
+ f(Expr::MethodCall(ExprMethodCall {
+ // `$expr.method::<T>()`
+ attrs: Vec::new(),
+ receiver: Box::new(expr),
+ dot_token: Token![.](span),
+ method: Ident::new("method", span),
+ turbofish: Some(AngleBracketedGenericArguments {
+ colon2_token: Some(Token![::](span)),
+ lt_token: Token![<](span),
+ args: Punctuated::from_iter([GenericArgument::Type(Type::Path(
+ TypePath {
+ qself: None,
+ path: Path::from(Ident::new("T", span)),
+ },
+ ))]),
+ gt_token: Token![>](span),
+ }),
+ paren_token: token::Paren(span),
+ args: Punctuated::new(),
+ }));
+ });
+
+ // Expr::RawAddr
+ iter(depth, &mut |expr| {
+ f(Expr::RawAddr(ExprRawAddr {
+ // `&raw const $expr`
+ attrs: Vec::new(),
+ and_token: Token![&](span),
+ raw: Token![raw](span),
+ mutability: PointerMutability::Const(Token![const](span)),
+ expr: Box::new(expr),
+ }));
+ });
+
+ // Expr::Struct
+ f(Expr::Struct(ExprStruct {
+ // `Struct {}`
+ attrs: Vec::new(),
+ qself: None,
+ path: Path::from(Ident::new("Struct", span)),
+ brace_token: token::Brace(span),
+ fields: Punctuated::new(),
+ dot2_token: None,
+ rest: None,
+ }));
+
+ // Expr::TryBlock
+ f(Expr::TryBlock(ExprTryBlock {
+ // `try {}`
+ attrs: Vec::new(),
+ try_token: Token![try](span),
+ block: Block {
+ brace_token: token::Brace(span),
+ stmts: Vec::new(),
+ },
+ }));
+
+ // Expr::Unsafe
+ f(Expr::Unsafe(ExprUnsafe {
+ // `unsafe {}`
+ attrs: Vec::new(),
+ unsafe_token: Token![unsafe](span),
+ block: Block {
+ brace_token: token::Brace(span),
+ stmts: Vec::new(),
+ },
+ }));
+
+ // Expr::While
+ iter(depth, &mut |expr| {
+ f(Expr::While(ExprWhile {
+ // `while $expr {}`
+ attrs: Vec::new(),
+ label: None,
+ while_token: Token![while](span),
+ cond: Box::new(expr.clone()),
+ body: Block {
+ brace_token: token::Brace(span),
+ stmts: Vec::new(),
+ },
+ }));
+ f(Expr::While(ExprWhile {
+ // `'a: while $expr {}`
+ attrs: Vec::new(),
+ label: Some(Label {
+ name: Lifetime::new("'a", span),
+ colon_token: Token![:](span),
+ }),
+ while_token: Token![while](span),
+ cond: Box::new(expr),
+ body: Block {
+ brace_token: token::Brace(span),
+ stmts: Vec::new(),
+ },
+ }));
+ });
+
+ // Expr::Yield
+ f(Expr::Yield(ExprYield {
+ // `yield`
+ attrs: Vec::new(),
+ yield_token: Token![yield](span),
+ expr: None,
+ }));
+ iter(depth, &mut |expr| {
+ f(Expr::Yield(ExprYield {
+ // `yield $expr`
+ attrs: Vec::new(),
+ yield_token: Token![yield](span),
+ expr: Some(Box::new(expr)),
+ }));
+ });
+ }
+ }
+
+ let mut failures = 0;
+ macro_rules! fail {
+ ($($message:tt)*) => {{
+ eprintln!($($message)*);
+ failures += 1;
+ return;
+ }};
+ }
+ let mut assert = |mut original: Expr| {
+ let span = Span::call_site();
+ // `const _: () = $expr;`
+ let pretty = prettyplease::unparse(&File {
+ shebang: None,
+ attrs: Vec::new(),
+ items: Vec::from([Item::Const(ItemConst {
+ attrs: Vec::new(),
+ vis: Visibility::Inherited,
+ const_token: Token![const](span),
+ ident: Ident::from(Token![_](span)),
+ generics: Generics::default(),
+ colon_token: Token![:](span),
+ ty: Box::new(Type::Infer(TypeInfer {
+ underscore_token: Token![_](span),
+ })),
+ eq_token: Token![=](span),
+ expr: Box::new(original.clone()),
+ semi_token: Token![;](span),
+ })]),
+ });
+ let mut parsed = match syn::parse_file(&pretty) {
+ Ok(parsed) => parsed,
+ _ => fail!("failed to parse: {pretty}{original:#?}"),
+ };
+ let item = match parsed.items.as_mut_slice() {
+ [Item::Const(item)] => item,
+ _ => unreachable!(),
+ };
+ let mut parsed = mem::replace(&mut *item.expr, Expr::PLACEHOLDER);
+ AsIfPrinted.visit_expr_mut(&mut original);
+ FlattenParens.visit_expr_mut(&mut parsed);
+ if original != parsed {
+ fail!(
+ "before: {}\n{:#?}\nafter: {}\n{:#?}",
+ original.to_token_stream(),
+ original,
+ parsed.to_token_stream(),
+ parsed,
+ );
+ }
+ if pretty.contains("(||") {
+ // https://github.com/dtolnay/prettyplease/issues/99
+ return;
+ }
+ let no_paren = pretty.replace(['(', ')'], "");
+ if pretty != no_paren {
+ if let Ok(mut parsed2) = syn::parse_file(&no_paren) {
+ let item = match parsed2.items.as_mut_slice() {
+ [Item::Const(item)] => item,
+ _ => unreachable!(),
+ };
+ if original == *item.expr {
+ fail!("redundant parens: {}", pretty);
+ }
+ }
+ }
+ };
+
+ iter(if cfg!(debug_assertions) { 3 } else { 4 }, &mut assert);
+ if failures > 0 {
+ eprintln!("FAILURES: {failures}");
+ ExitCode::FAILURE
+ } else {
+ ExitCode::SUCCESS
+ }
+}