summaryrefslogtreecommitdiffstats
path: root/third_party/rust/proc-macro-error
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/proc-macro-error')
-rw-r--r--third_party/rust/proc-macro-error/.cargo-checksum.json1
-rw-r--r--third_party/rust/proc-macro-error/CHANGELOG.md162
-rw-r--r--third_party/rust/proc-macro-error/Cargo.toml56
-rw-r--r--third_party/rust/proc-macro-error/LICENSE-APACHE201
-rw-r--r--third_party/rust/proc-macro-error/LICENSE-MIT21
-rw-r--r--third_party/rust/proc-macro-error/README.md258
-rw-r--r--third_party/rust/proc-macro-error/build.rs11
-rw-r--r--third_party/rust/proc-macro-error/src/diagnostic.rs349
-rw-r--r--third_party/rust/proc-macro-error/src/dummy.rs150
-rw-r--r--third_party/rust/proc-macro-error/src/imp/delegate.rs69
-rw-r--r--third_party/rust/proc-macro-error/src/imp/fallback.rs30
-rw-r--r--third_party/rust/proc-macro-error/src/lib.rs560
-rw-r--r--third_party/rust/proc-macro-error/src/macros.rs288
-rw-r--r--third_party/rust/proc-macro-error/src/sealed.rs3
-rw-r--r--third_party/rust/proc-macro-error/tests/macro-errors.rs8
-rw-r--r--third_party/rust/proc-macro-error/tests/ok.rs10
-rw-r--r--third_party/rust/proc-macro-error/tests/runtime-errors.rs13
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/abort.rs11
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/abort.stderr48
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/append_dummy.rs13
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/append_dummy.stderr5
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/children_messages.rs6
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/children_messages.stderr23
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/dummy.rs13
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/dummy.stderr5
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/emit.rs7
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/emit.stderr48
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/explicit_span_range.rs6
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/explicit_span_range.stderr5
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/misuse.rs11
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/misuse.stderr13
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/multiple_tokens.rs6
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/multiple_tokens.stderr5
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/not_proc_macro.rs4
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/not_proc_macro.stderr10
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/option_ext.rs6
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/option_ext.stderr7
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/proc_macro_hack.rs10
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/proc_macro_hack.stderr26
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/result_ext.rs7
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/result_ext.stderr11
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/to_tokens_span.rs6
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/to_tokens_span.stderr11
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/unknown_setting.rs4
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/unknown_setting.stderr5
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/unrelated_panic.rs6
-rw-r--r--third_party/rust/proc-macro-error/tests/ui/unrelated_panic.stderr7
47 files changed, 2535 insertions, 0 deletions
diff --git a/third_party/rust/proc-macro-error/.cargo-checksum.json b/third_party/rust/proc-macro-error/.cargo-checksum.json
new file mode 100644
index 0000000000..79bcfa696f
--- /dev/null
+++ b/third_party/rust/proc-macro-error/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"CHANGELOG.md":"b84c4baa5fb093c6aaca44b98f9f28ef54d399ef6dd43c91f1dca618ab366b45","Cargo.toml":"50db093e1a4617606939dfb1f098cb59babbea0d7b390e973a3ed6bb1406170d","LICENSE-APACHE":"4665f973ccb9393807a7fb1264add6b3513d19abc6b357e4cb52c6fe59cc6a3b","LICENSE-MIT":"544b3aed1fd723d0cadea567affdcfe0431e43e18d997a718f9d67256b814fde","README.md":"72d59787d0a1f7bf161e292d0bc1bc25fdfb08cd6ad379a34cc3ed1b388d11fa","build.rs":"6238a0ad4f1146fbf55112419609e6449986154cf7ded1b5fdc978b06f4413b3","src/diagnostic.rs":"cb8724bb0bf9d2eee2f7119d0960fd5349edaa80e147abdef060ebf4572eca01","src/dummy.rs":"b44728091ddcdf9786523c01178efcedd83462bfe8bac6b97b1c2ffb19c96d09","src/imp/delegate.rs":"81da3a602a883240161dd98deb52b3b4ae29e626bfd2e1e07ef5e38d1be00679","src/imp/fallback.rs":"c3d333aba1122ac7e26f038f69750aa02e6a1222433a7cffd1c2f961befedd93","src/lib.rs":"e563d5dceaeb81551a5cb2610c1a3ad1a46200a6cbf8c3c3b394d8ac307b8cfa","src/macros.rs":"3be6feccd343cd9dc4bf03780f3107909bf70e02c6c7c72912e4b160dc6a68fc","src/sealed.rs":"dcf569c4c7ce1d372ff51b0fa73fa67f995bdca8e520cb225cde789c71276439","tests/macro-errors.rs":"7f793921dfbec692bfb2bbb067faf0480c0e7eeec83982b5e9fcddd817817616","tests/ok.rs":"a8c1925ac8647d185c7490ed1e33e3ce3203f5945bd3db4dcaf50ea55078df29","tests/runtime-errors.rs":"e53aa7d8e6c0e5128a90e856105eb05e4e7e72ea6db1bd580f3fe439bff62f24","tests/ui/abort.rs":"e209c8dd9dde6bde7440f8795624ad84b0f8486f563c8fe838238818f459bb67","tests/ui/abort.stderr":"dd0605e79be0309f92b251d055f087b0375c48ec60da978df354b48e8563fa10","tests/ui/append_dummy.rs":"ecaf939c8aabd94eef2dd1c10e9515489ba78e4db5b25195e19833b020d2483c","tests/ui/append_dummy.stderr":"ef03b01fc823aba8cfb9eb6d116640ca953fec569e61ed6ed6b7b7fa3bbad686","tests/ui/children_messages.rs":"32299679804133cb5295ed7a9341bf1ab86a4f1277679ee9738a83115c6b1d2b","tests/ui/children_messages.stderr":"dadeb86e1c7094d5fb38664b1766212b3d083fbe04962c137f8281fb3f5d162e","tests/ui/dummy.rs":"ba51c9158cef88ff2ddf0185be26fcd35a641d73c7124fab9ace0bbd546de847","tests/ui/dummy.stderr":"0635fd563d26691d07a2a875111f0b5e155caa45c37ad9cbaefe5fe617eac703","tests/ui/emit.rs":"82aaf06bcee56b7e139bbcba3a92c29448af14974d6806a28c9961aa764026e5","tests/ui/emit.stderr":"d3daa6d304453d436317495b7fc1d9d36bbebb7705bef75a5260d6d8fcfad5b1","tests/ui/explicit_span_range.rs":"3c37d5fc75b2bd460a091acd97a19acc80a40ba8d1d4ac7f36cd2f0e171bf5e7","tests/ui/explicit_span_range.stderr":"d7562847c326badbce2df8546e6f625eef0725b1dd2c786a037cc46357e4d2e8","tests/ui/misuse.rs":"0d66c61ab5c9723cf2f85cd12216751ab09722e9386cc27928034ee17f1c34e3","tests/ui/misuse.stderr":"52568a2208423e8e4050774559f269e79181a350f0805a34880bfa208e08c6bb","tests/ui/multiple_tokens.rs":"74997da1fdd3bce88a04ab42866c651723861fba4f59e826ee602d905398dcca","tests/ui/multiple_tokens.stderr":"e347ef1c18949711ce41957848e255095132f855c94db1e7e28d32e7d2c79a74","tests/ui/not_proc_macro.rs":"ca448d832ccf0cfdcda6f04281d8134a76c61b3ad96437e972b2cb5c6e0844c4","tests/ui/not_proc_macro.stderr":"a22c53a7dd5a03ddfaee5a7fb7fe5d61cb588b2d81a30c1e935b789baf0d2676","tests/ui/option_ext.rs":"1db81c17172f155c0ca8bcf92d55b5852b92107a3ba1d4b2ae6d14020df67f96","tests/ui/option_ext.stderr":"3b363759db60ee4f249dfde4d4571963032d5f0043249de40bd3b38eecc65404","tests/ui/proc_macro_hack.rs":"1d08c3e2c4c331e230c7cdaa2635ca1e43077252f90d3a430dcd091c646a842c","tests/ui/proc_macro_hack.stderr":"65e887dc208b92bfcd44405e76d5d05e315c3c5c5f637070954b7d593c723731","tests/ui/result_ext.rs":"ef398e76aab82a574ca5a988a91353e1a87fcfcb459d30314eceed3cbcf6fcd8","tests/ui/result_ext.stderr":"9e1e387b1378d9ec40ccb29be9f8cdaa5b42060c3f4f9b3c09fb307d5dcf7d85","tests/ui/to_tokens_span.rs":"d017a3c4cd583defe9806cdc51220bde89ced871ddd4d65b7cd089882feb1f61","tests/ui/to_tokens_span.stderr":"0b88e659ab214d6c7dfcd99274d327fe72da4b9bd009477e0e65165ddde65e02","tests/ui/unknown_setting.rs":"16fe9631b51023909497e857a6c674cd216ba9802fbdba360bb8273d6e00fa31","tests/ui/unknown_setting.stderr":"d605f151ce8eba5b2f867667394bd2d2adf0a233145516a9d6b801817521e587","tests/ui/unrelated_panic.rs":"438db25f8f14f1263152545a1c5135e20b3f5063dc4ab223fd8145b891039b24","tests/ui/unrelated_panic.stderr":"04cd814f2bd57d5271f93f90f0dd078b09ee3fd73137245a914d698e4a33ed57"},"package":"da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"} \ No newline at end of file
diff --git a/third_party/rust/proc-macro-error/CHANGELOG.md b/third_party/rust/proc-macro-error/CHANGELOG.md
new file mode 100644
index 0000000000..3c422f1c45
--- /dev/null
+++ b/third_party/rust/proc-macro-error/CHANGELOG.md
@@ -0,0 +1,162 @@
+# v1.0.4 (2020-7-31)
+
+* `SpanRange` facility is now public.
+* Docs have been improved.
+* Introduced the `syn-error` feature so you can opt-out from the `syn` dependency.
+
+# v1.0.3 (2020-6-26)
+
+* Corrected a few typos.
+* Fixed the `emit_call_site_warning` macro.
+
+# v1.0.2 (2020-4-9)
+
+* An obsolete note was removed from documentation.
+
+# v1.0.1 (2020-4-9)
+
+* `proc-macro-hack` is now well tested and supported. Not sure about `proc-macro-nested`,
+ please fill a request if you need it.
+* Fixed `emit_call_site_error`.
+* Documentation improvements.
+
+# v1.0.0 (2020-3-25)
+
+I believe the API can be considered stable because it's been a few months without
+breaking changes, and I also don't think this crate will receive much further evolution.
+It's perfect, admit it.
+
+Hence, meet the new, stable release!
+
+### Improvements
+
+* Supported nested `#[proc_macro_error]` attributes. Well, you aren't supposed to do that,
+ but I caught myself doing it by accident on one occasion and the behavior was... surprising.
+ Better to handle this smooth.
+
+# v0.4.12 (2020-3-23)
+
+* Error message on macros' misuse is now a bit more understandable.
+
+# v0.4.11 (2020-3-02)
+
+* `build.rs` no longer fails when `rustc` date could not be determined,
+ (thanks to [`Fabian Möller`](https://gitlab.com/CreepySkeleton/proc-macro-error/issues/8)
+ for noticing and to [`Igor Gnatenko`](https://gitlab.com/CreepySkeleton/proc-macro-error/-/merge_requests/25)
+ for fixing).
+
+# v0.4.10 (2020-2-29)
+
+* `proc-macro-error` doesn't depend on syn\[full\] anymore, the compilation
+ is \~30secs faster.
+
+# v0.4.9 (2020-2-13)
+
+* New function: `append_dummy`.
+
+# v0.4.8 (2020-2-01)
+
+* Support for children messages
+
+# v0.4.7 (2020-1-31)
+
+* Now any type that implements `quote::ToTokens` can be used instead of spans.
+ This allows for high quality error messages.
+
+# v0.4.6 (2020-1-31)
+
+* `From<syn::Error>` implementation doesn't lose span info anymore, see
+ [#6](https://gitlab.com/CreepySkeleton/proc-macro-error/issues/6).
+
+# v0.4.5 (2020-1-20)
+Just a small intermediate release.
+
+* Fix some bugs.
+* Populate license files into subfolders.
+
+# v0.4.4 (2019-11-13)
+* Fix `abort_if_dirty` + warnings bug
+* Allow trailing commas in macros
+
+# v0.4.2 (2019-11-7)
+* FINALLY fixed `__pme__suggestions not found` bug
+
+# v0.4.1 (2019-11-7) YANKED
+* Fixed `__pme__suggestions not found` bug
+* Documentation improvements, links checked
+
+# v0.4.0 (2019-11-6) YANKED
+
+## New features
+* "help" messages that can have their own span on nightly, they
+ inherit parent span on stable.
+ ```rust
+ let cond_help = if condition { Some("some help message") else { None } };
+ abort!(
+ span, // parent span
+ "something's wrong, {} wrongs in total", 10; // main message
+ help = "here's a help for you, {}", "take it"; // unconditional help message
+ help =? cond_help; // conditional help message, must be Option
+ note = note_span => "don't forget the note, {}", "would you?" // notes can have their own span but it's effective only on nightly
+ )
+ ```
+* Warnings via `emit_warning` and `emit_warning_call_site`. Nightly only, they're ignored on stable.
+* Now `proc-macro-error` delegates to `proc_macro::Diagnostic` on nightly.
+
+## Breaking changes
+* `MacroError` is now replaced by `Diagnostic`. Its API resembles `proc_macro::Diagnostic`.
+* `Diagnostic` does not implement `From<&str/String>` so `Result<T, &str/String>::abort_or_exit()`
+ won't work anymore (nobody used it anyway).
+* `macro_error!` macro is replaced with `diagnostic!`.
+
+## Improvements
+* Now `proc-macro-error` renders notes exactly just like rustc does.
+* We don't parse a body of a function annotated with `#[proc_macro_error]` anymore,
+ only looking at the signature. This should somewhat decrease expansion time for large functions.
+
+# v0.3.3 (2019-10-16)
+* Now you can use any word instead of "help", undocumented.
+
+# v0.3.2 (2019-10-16)
+* Introduced support for "help" messages, undocumented.
+
+# v0.3.0 (2019-10-8)
+
+## The crate has been completely rewritten from scratch!
+
+## Changes (most are breaking):
+* Renamed macros:
+ * `span_error` => `abort`
+ * `call_site_error` => `abort_call_site`
+* `filter_macro_errors` was replaced by `#[proc_macro_error]` attribute.
+* `set_dummy` now takes `TokenStream` instead of `Option<TokenStream>`
+* Support for multiple errors via `emit_error` and `emit_call_site_error`
+* New `macro_error` macro for building errors in format=like style.
+* `MacroError` API had been reconsidered. It also now implements `quote::ToTokens`.
+
+# v0.2.6 (2019-09-02)
+* Introduce support for dummy implementations via `dummy::set_dummy`
+* `multi::*` is now deprecated, will be completely rewritten in v0.3
+
+# v0.2.0 (2019-08-15)
+
+## Breaking changes
+* `trigger_error` replaced with `MacroError::trigger` and `filter_macro_error_panics`
+ is hidden from docs.
+ This is not quite a breaking change since users weren't supposed to use these functions directly anyway.
+* All dependencies are updated to `v1.*`.
+
+## New features
+* Ability to stack multiple errors via `multi::MultiMacroErrors` and emit them at once.
+
+## Improvements
+* Now `MacroError` implements `std::fmt::Display` instead of `std::string::ToString`.
+* `MacroError::span` inherent method.
+* `From<MacroError> for proc_macro/proc_macro2::TokenStream` implementations.
+* `AsRef/AsMut<String> for MacroError` implementations.
+
+# v0.1.x (2019-07-XX)
+
+## New features
+* An easy way to report errors inside within a proc-macro via `span_error`,
+ `call_site_error` and `filter_macro_errors`.
diff --git a/third_party/rust/proc-macro-error/Cargo.toml b/third_party/rust/proc-macro-error/Cargo.toml
new file mode 100644
index 0000000000..869585ffc2
--- /dev/null
+++ b/third_party/rust/proc-macro-error/Cargo.toml
@@ -0,0 +1,56 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+edition = "2018"
+name = "proc-macro-error"
+version = "1.0.4"
+authors = ["CreepySkeleton <creepy-skeleton@yandex.ru>"]
+build = "build.rs"
+description = "Almost drop-in replacement to panics in proc-macros"
+readme = "README.md"
+keywords = ["proc-macro", "error", "errors"]
+categories = ["development-tools::procedural-macro-helpers"]
+license = "MIT OR Apache-2.0"
+repository = "https://gitlab.com/CreepySkeleton/proc-macro-error"
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
+[dependencies.proc-macro-error-attr]
+version = "=1.0.4"
+
+[dependencies.proc-macro2]
+version = "1"
+
+[dependencies.quote]
+version = "1"
+
+[dependencies.syn]
+version = "1"
+optional = true
+default-features = false
+[dev-dependencies.serde_derive]
+version = "=1.0.107"
+
+[dev-dependencies.toml]
+version = "=0.5.2"
+
+[dev-dependencies.trybuild]
+version = "1.0.19"
+features = ["diff"]
+[build-dependencies.version_check]
+version = "0.9"
+
+[features]
+default = ["syn-error"]
+syn-error = ["syn"]
+[badges.maintenance]
+status = "passively-maintained"
diff --git a/third_party/rust/proc-macro-error/LICENSE-APACHE b/third_party/rust/proc-macro-error/LICENSE-APACHE
new file mode 100644
index 0000000000..cc17374b25
--- /dev/null
+++ b/third_party/rust/proc-macro-error/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright 2019-2020 CreepySkeleton <creepy-skeleton@yandex.ru>
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/third_party/rust/proc-macro-error/LICENSE-MIT b/third_party/rust/proc-macro-error/LICENSE-MIT
new file mode 100644
index 0000000000..fc73e591d7
--- /dev/null
+++ b/third_party/rust/proc-macro-error/LICENSE-MIT
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019-2020 CreepySkeleton
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/third_party/rust/proc-macro-error/README.md b/third_party/rust/proc-macro-error/README.md
new file mode 100644
index 0000000000..7fbe07c53a
--- /dev/null
+++ b/third_party/rust/proc-macro-error/README.md
@@ -0,0 +1,258 @@
+# Makes error reporting in procedural macros nice and easy
+
+[![travis ci](https://travis-ci.org/CreepySkeleton/proc-macro-error.svg?branch=master)](https://travis-ci.org/CreepySkeleton/proc-macro-error)
+[![docs.rs](https://docs.rs/proc-macro-error/badge.svg)](https://docs.rs/proc-macro-error)
+[![unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg)](https://github.com/rust-secure-code/safety-dance/)
+
+This crate aims to make error reporting in proc-macros simple and easy to use.
+Migrate from `panic!`-based errors for as little effort as possible!
+
+Also, you can explicitly [append a dummy token stream][crate::dummy] to your errors.
+
+To achieve his, this crate serves as a tiny shim around `proc_macro::Diagnostic` and
+`compile_error!`. It detects the most preferable way to emit errors based on compiler's version.
+When the underlying diagnostic type is finally stabilized, this crate will be simply
+delegating to it, requiring no changes in your code!
+
+So you can just use this crate and have *both* some of `proc_macro::Diagnostic` functionality
+available on stable ahead of time and your error-reporting code future-proof.
+
+```toml
+[dependencies]
+proc-macro-error = "1.0"
+```
+
+*Supports rustc 1.31 and up*
+
+[Documentation and guide][guide]
+
+## Quick example
+
+Code:
+
+```rust
+#[proc_macro]
+#[proc_macro_error]
+pub fn make_fn(input: TokenStream) -> TokenStream {
+ let mut input = TokenStream2::from(input).into_iter();
+ let name = input.next().unwrap();
+ if let Some(second) = input.next() {
+ abort! { second,
+ "I don't like this part!";
+ note = "I see what you did there...";
+ help = "I need only one part, you know?";
+ }
+ }
+
+ quote!( fn #name() {} ).into()
+}
+```
+
+This is how the error is rendered in a terminal:
+
+<p align="center">
+<img src="https://user-images.githubusercontent.com/50968528/78830016-d3b46a80-79d6-11ea-9de2-972e8d7904ef.png" width="600">
+</p>
+
+And this is what your users will see in their IDE:
+
+<p align="center">
+<img src="https://user-images.githubusercontent.com/50968528/78830547-a9af7800-79d7-11ea-822e-59e29bda335c.png" width="600">
+</p>
+
+## Examples
+
+### Panic-like usage
+
+```rust
+use proc_macro_error::{
+ proc_macro_error,
+ abort,
+ abort_call_site,
+ ResultExt,
+ OptionExt,
+};
+use proc_macro::TokenStream;
+use syn::{DeriveInput, parse_macro_input};
+use quote::quote;
+
+// This is your main entry point
+#[proc_macro]
+// This attribute *MUST* be placed on top of the #[proc_macro] function
+#[proc_macro_error]
+pub fn make_answer(input: TokenStream) -> TokenStream {
+ let input = parse_macro_input!(input as DeriveInput);
+
+ if let Err(err) = some_logic(&input) {
+ // we've got a span to blame, let's use it
+ // This immediately aborts the proc-macro and shows the error
+ //
+ // You can use `proc_macro::Span`, `proc_macro2::Span`, and
+ // anything that implements `quote::ToTokens` (almost every type from
+ // `syn` and `proc_macro2`)
+ abort!(err, "You made an error, go fix it: {}", err.msg);
+ }
+
+ // `Result` has some handy shortcuts if your error type implements
+ // `Into<Diagnostic>`. `Option` has one unconditionally.
+ more_logic(&input).expect_or_abort("What a careless user, behave!");
+
+ if !more_logic_for_logic_god(&input) {
+ // We don't have an exact location this time,
+ // so just highlight the proc-macro invocation itself
+ abort_call_site!(
+ "Bad, bad user! Now go stand in the corner and think about what you did!");
+ }
+
+ // Now all the processing is done, return `proc_macro::TokenStream`
+ quote!(/* stuff */).into()
+}
+```
+
+### `proc_macro::Diagnostic`-like usage
+
+```rust
+use proc_macro_error::*;
+use proc_macro::TokenStream;
+use syn::{spanned::Spanned, DeriveInput, ItemStruct, Fields, Attribute , parse_macro_input};
+use quote::quote;
+
+fn process_attrs(attrs: &[Attribute]) -> Vec<Attribute> {
+ attrs
+ .iter()
+ .filter_map(|attr| match process_attr(attr) {
+ Ok(res) => Some(res),
+ Err(msg) => {
+ emit_error!(attr, "Invalid attribute: {}", msg);
+ None
+ }
+ })
+ .collect()
+}
+
+fn process_fields(_attrs: &Fields) -> Vec<TokenStream> {
+ // processing fields in pretty much the same way as attributes
+ unimplemented!()
+}
+
+#[proc_macro]
+#[proc_macro_error]
+pub fn make_answer(input: TokenStream) -> TokenStream {
+ let input = parse_macro_input!(input as ItemStruct);
+ let attrs = process_attrs(&input.attrs);
+
+ // abort right now if some errors were encountered
+ // at the attributes processing stage
+ abort_if_dirty();
+
+ let fields = process_fields(&input.fields);
+
+ // no need to think about emitted errors
+ // #[proc_macro_error] will handle them for you
+ //
+ // just return a TokenStream as you normally would
+ quote!(/* stuff */).into()
+}
+```
+
+## Real world examples
+
+* [`structopt-derive`](https://github.com/TeXitoi/structopt/tree/master/structopt-derive)
+ (abort-like usage)
+* [`auto-impl`](https://github.com/auto-impl-rs/auto_impl/) (emit-like usage)
+
+## Limitations
+
+- Warnings are emitted only on nightly, they are ignored on stable.
+- "help" suggestions can't have their own span info on stable,
+ (essentially inheriting the parent span).
+- If your macro happens to trigger a panic, no errors will be displayed. This is not a
+ technical limitation but rather intentional design. `panic` is not for error reporting.
+
+## MSRV policy
+
+`proc_macro_error` will always be compatible with proc-macro Holy Trinity:
+`proc_macro2`, `syn`, `quote` crates. In other words, if the Trinity is available
+to you - `proc_macro_error` is available too.
+
+> **Important!**
+>
+> If you want to use `#[proc_macro_error]` with `synstructure`, you're going
+> to have to put the attribute inside the `decl_derive!` invocation. Unfortunately,
+> due to some bug in pre-1.34 rustc, putting proc-macro attributes inside macro
+> invocations doesn't work, so your MSRV is effectively 1.34.
+
+## Motivation
+
+Error handling in proc-macros sucks. There's not much of a choice today:
+you either "bubble up" the error up to the top-level of the macro and convert it to
+a [`compile_error!`][compl_err] invocation or just use a good old panic. Both these ways suck:
+
+- Former sucks because it's quite redundant to unroll a proper error handling
+ just for critical errors that will crash the macro anyway; so people mostly
+ choose not to bother with it at all and use panic. Simple `.expect` is too tempting.
+
+ Also, if you do decide to implement this `Result`-based architecture in your macro
+ you're going to have to rewrite it entirely once [`proc_macro::Diagnostic`][] is finally
+ stable. Not cool.
+
+- Later sucks because there's no way to carry out the span info via `panic!`.
+ `rustc` will highlight the invocation itself but not some specific token inside it.
+
+ Furthermore, panics aren't for error-reporting at all; panics are for bug-detecting
+ (like unwrapping on `None` or out-of-range indexing) or for early development stages
+ when you need a prototype ASAP so error handling can wait. Mixing these usages only
+ messes things up.
+
+- There is [`proc_macro::Diagnostic`][] which is awesome but it has been experimental
+ for more than a year and is unlikely to be stabilized any time soon.
+
+ This crate's API is intentionally designed to be compatible with `proc_macro::Diagnostic`
+ and delegates to it whenever possible. Once `Diagnostics` is stable this crate
+ will **always** delegate to it, no code changes will be required on user side.
+
+That said, we need a solution, but this solution must meet these conditions:
+
+- It must be better than `panic!`. The main point: it must offer a way to carry the span information
+ over to user.
+- It must take as little effort as possible to migrate from `panic!`. Ideally, a new
+ macro with similar semantics plus ability to carry out span info.
+- It must maintain compatibility with [`proc_macro::Diagnostic`][] .
+- **It must be usable on stable**.
+
+This crate aims to provide such a mechanism. All you have to do is annotate your top-level
+`#[proc_macro]` function with `#[proc_macro_error]` attribute and change panics to
+[`abort!`]/[`abort_call_site!`] where appropriate, see [the Guide][guide].
+
+## Disclaimer
+Please note that **this crate is not intended to be used in any way other
+than error reporting in procedural macros**, use `Result` and `?` (possibly along with one of the
+many helpers out there) for anything else.
+
+<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>
+
+
+[compl_err]: https://doc.rust-lang.org/std/macro.compile_error.html
+[`proc_macro::Diagnostic`]: https://doc.rust-lang.org/proc_macro/struct.Diagnostic.html
+
+[crate::dummy]: https://docs.rs/proc-macro-error/1/proc_macro_error/dummy/index.html
+[crate::multi]: https://docs.rs/proc-macro-error/1/proc_macro_error/multi/index.html
+
+[`abort_call_site!`]: https://docs.rs/proc-macro-error/1/proc_macro_error/macro.abort_call_site.html
+[`abort!`]: https://docs.rs/proc-macro-error/1/proc_macro_error/macro.abort.html
+[guide]: https://docs.rs/proc-macro-error
diff --git a/third_party/rust/proc-macro-error/build.rs b/third_party/rust/proc-macro-error/build.rs
new file mode 100644
index 0000000000..3c1196f269
--- /dev/null
+++ b/third_party/rust/proc-macro-error/build.rs
@@ -0,0 +1,11 @@
+fn main() {
+ if !version_check::is_feature_flaggable().unwrap_or(false) {
+ println!("cargo:rustc-cfg=use_fallback");
+ }
+
+ if version_check::is_max_version("1.38.0").unwrap_or(false)
+ || !version_check::Channel::read().unwrap().is_stable()
+ {
+ println!("cargo:rustc-cfg=skip_ui_tests");
+ }
+}
diff --git a/third_party/rust/proc-macro-error/src/diagnostic.rs b/third_party/rust/proc-macro-error/src/diagnostic.rs
new file mode 100644
index 0000000000..983e6174fe
--- /dev/null
+++ b/third_party/rust/proc-macro-error/src/diagnostic.rs
@@ -0,0 +1,349 @@
+use crate::{abort_now, check_correctness, sealed::Sealed, SpanRange};
+use proc_macro2::Span;
+use proc_macro2::TokenStream;
+
+use quote::{quote_spanned, ToTokens};
+
+/// Represents a diagnostic level
+///
+/// # Warnings
+///
+/// Warnings are ignored on stable/beta
+#[derive(Debug, PartialEq)]
+pub enum Level {
+ Error,
+ Warning,
+ #[doc(hidden)]
+ NonExhaustive,
+}
+
+/// Represents a single diagnostic message
+#[derive(Debug)]
+pub struct Diagnostic {
+ pub(crate) level: Level,
+ pub(crate) span_range: SpanRange,
+ pub(crate) msg: String,
+ pub(crate) suggestions: Vec<(SuggestionKind, String, Option<SpanRange>)>,
+ pub(crate) children: Vec<(SpanRange, String)>,
+}
+
+/// A collection of methods that do not exist in `proc_macro::Diagnostic`
+/// but still useful to have around.
+///
+/// This trait is sealed and cannot be implemented outside of `proc_macro_error`.
+pub trait DiagnosticExt: Sealed {
+ /// Create a new diagnostic message that points to the `span_range`.
+ ///
+ /// This function is the same as `Diagnostic::spanned` but produces considerably
+ /// better error messages for multi-token spans on stable.
+ fn spanned_range(span_range: SpanRange, level: Level, message: String) -> Self;
+
+ /// Add another error message to self such that it will be emitted right after
+ /// the main message.
+ ///
+ /// This function is the same as `Diagnostic::span_error` but produces considerably
+ /// better error messages for multi-token spans on stable.
+ fn span_range_error(self, span_range: SpanRange, msg: String) -> Self;
+
+ /// Attach a "help" note to your main message, the note will have it's own span on nightly.
+ ///
+ /// This function is the same as `Diagnostic::span_help` but produces considerably
+ /// better error messages for multi-token spans on stable.
+ ///
+ /// # Span
+ ///
+ /// The span is ignored on stable, the note effectively inherits its parent's (main message) span
+ fn span_range_help(self, span_range: SpanRange, msg: String) -> Self;
+
+ /// Attach a note to your main message, the note will have it's own span on nightly.
+ ///
+ /// This function is the same as `Diagnostic::span_note` but produces considerably
+ /// better error messages for multi-token spans on stable.
+ ///
+ /// # Span
+ ///
+ /// The span is ignored on stable, the note effectively inherits its parent's (main message) span
+ fn span_range_note(self, span_range: SpanRange, msg: String) -> Self;
+}
+
+impl DiagnosticExt for Diagnostic {
+ fn spanned_range(span_range: SpanRange, level: Level, message: String) -> Self {
+ Diagnostic {
+ level,
+ span_range,
+ msg: message,
+ suggestions: vec![],
+ children: vec![],
+ }
+ }
+
+ fn span_range_error(mut self, span_range: SpanRange, msg: String) -> Self {
+ self.children.push((span_range, msg));
+ self
+ }
+
+ fn span_range_help(mut self, span_range: SpanRange, msg: String) -> Self {
+ self.suggestions
+ .push((SuggestionKind::Help, msg, Some(span_range)));
+ self
+ }
+
+ fn span_range_note(mut self, span_range: SpanRange, msg: String) -> Self {
+ self.suggestions
+ .push((SuggestionKind::Note, msg, Some(span_range)));
+ self
+ }
+}
+
+impl Diagnostic {
+ /// Create a new diagnostic message that points to `Span::call_site()`
+ pub fn new(level: Level, message: String) -> Self {
+ Diagnostic::spanned(Span::call_site(), level, message)
+ }
+
+ /// Create a new diagnostic message that points to the `span`
+ pub fn spanned(span: Span, level: Level, message: String) -> Self {
+ Diagnostic::spanned_range(
+ SpanRange {
+ first: span,
+ last: span,
+ },
+ level,
+ message,
+ )
+ }
+
+ /// Add another error message to self such that it will be emitted right after
+ /// the main message.
+ pub fn span_error(self, span: Span, msg: String) -> Self {
+ self.span_range_error(
+ SpanRange {
+ first: span,
+ last: span,
+ },
+ msg,
+ )
+ }
+
+ /// Attach a "help" note to your main message, the note will have it's own span on nightly.
+ ///
+ /// # Span
+ ///
+ /// The span is ignored on stable, the note effectively inherits its parent's (main message) span
+ pub fn span_help(self, span: Span, msg: String) -> Self {
+ self.span_range_help(
+ SpanRange {
+ first: span,
+ last: span,
+ },
+ msg,
+ )
+ }
+
+ /// Attach a "help" note to your main message.
+ pub fn help(mut self, msg: String) -> Self {
+ self.suggestions.push((SuggestionKind::Help, msg, None));
+ self
+ }
+
+ /// Attach a note to your main message, the note will have it's own span on nightly.
+ ///
+ /// # Span
+ ///
+ /// The span is ignored on stable, the note effectively inherits its parent's (main message) span
+ pub fn span_note(self, span: Span, msg: String) -> Self {
+ self.span_range_note(
+ SpanRange {
+ first: span,
+ last: span,
+ },
+ msg,
+ )
+ }
+
+ /// Attach a note to your main message
+ pub fn note(mut self, msg: String) -> Self {
+ self.suggestions.push((SuggestionKind::Note, msg, None));
+ self
+ }
+
+ /// The message of main warning/error (no notes attached)
+ pub fn message(&self) -> &str {
+ &self.msg
+ }
+
+ /// Abort the proc-macro's execution and display the diagnostic.
+ ///
+ /// # Warnings
+ ///
+ /// Warnings are not emitted on stable and beta, but this function will abort anyway.
+ pub fn abort(self) -> ! {
+ self.emit();
+ abort_now()
+ }
+
+ /// Display the diagnostic while not aborting macro execution.
+ ///
+ /// # Warnings
+ ///
+ /// Warnings are ignored on stable/beta
+ pub fn emit(self) {
+ check_correctness();
+ crate::imp::emit_diagnostic(self);
+ }
+}
+
+/// **NOT PUBLIC API! NOTHING TO SEE HERE!!!**
+#[doc(hidden)]
+impl Diagnostic {
+ pub fn span_suggestion(self, span: Span, suggestion: &str, msg: String) -> Self {
+ match suggestion {
+ "help" | "hint" => self.span_help(span, msg),
+ _ => self.span_note(span, msg),
+ }
+ }
+
+ pub fn suggestion(self, suggestion: &str, msg: String) -> Self {
+ match suggestion {
+ "help" | "hint" => self.help(msg),
+ _ => self.note(msg),
+ }
+ }
+}
+
+impl ToTokens for Diagnostic {
+ fn to_tokens(&self, ts: &mut TokenStream) {
+ use std::borrow::Cow;
+
+ fn ensure_lf(buf: &mut String, s: &str) {
+ if s.ends_with('\n') {
+ buf.push_str(s);
+ } else {
+ buf.push_str(s);
+ buf.push('\n');
+ }
+ }
+
+ fn diag_to_tokens(
+ span_range: SpanRange,
+ level: &Level,
+ msg: &str,
+ suggestions: &[(SuggestionKind, String, Option<SpanRange>)],
+ ) -> TokenStream {
+ if *level == Level::Warning {
+ return TokenStream::new();
+ }
+
+ let message = if suggestions.is_empty() {
+ Cow::Borrowed(msg)
+ } else {
+ let mut message = String::new();
+ ensure_lf(&mut message, msg);
+ message.push('\n');
+
+ for (kind, note, _span) in suggestions {
+ message.push_str(" = ");
+ message.push_str(kind.name());
+ message.push_str(": ");
+ ensure_lf(&mut message, note);
+ }
+ message.push('\n');
+
+ Cow::Owned(message)
+ };
+
+ let mut msg = proc_macro2::Literal::string(&message);
+ msg.set_span(span_range.last);
+ let group = quote_spanned!(span_range.last=> { #msg } );
+ quote_spanned!(span_range.first=> compile_error!#group)
+ }
+
+ ts.extend(diag_to_tokens(
+ self.span_range,
+ &self.level,
+ &self.msg,
+ &self.suggestions,
+ ));
+ ts.extend(
+ self.children
+ .iter()
+ .map(|(span_range, msg)| diag_to_tokens(*span_range, &Level::Error, &msg, &[])),
+ );
+ }
+}
+
+#[derive(Debug)]
+pub(crate) enum SuggestionKind {
+ Help,
+ Note,
+}
+
+impl SuggestionKind {
+ fn name(&self) -> &'static str {
+ match self {
+ SuggestionKind::Note => "note",
+ SuggestionKind::Help => "help",
+ }
+ }
+}
+
+#[cfg(feature = "syn-error")]
+impl From<syn::Error> for Diagnostic {
+ fn from(err: syn::Error) -> Self {
+ use proc_macro2::{Delimiter, TokenTree};
+
+ fn gut_error(ts: &mut impl Iterator<Item = TokenTree>) -> Option<(SpanRange, String)> {
+ let first = match ts.next() {
+ // compile_error
+ None => return None,
+ Some(tt) => tt.span(),
+ };
+ ts.next().unwrap(); // !
+
+ let lit = match ts.next().unwrap() {
+ TokenTree::Group(group) => {
+ // Currently `syn` builds `compile_error!` invocations
+ // exclusively in `ident{"..."}` (braced) form which is not
+ // followed by `;` (semicolon).
+ //
+ // But if it changes to `ident("...");` (parenthesized)
+ // or `ident["..."];` (bracketed) form,
+ // we will need to skip the `;` as well.
+ // Highly unlikely, but better safe than sorry.
+
+ if group.delimiter() == Delimiter::Parenthesis
+ || group.delimiter() == Delimiter::Bracket
+ {
+ ts.next().unwrap(); // ;
+ }
+
+ match group.stream().into_iter().next().unwrap() {
+ TokenTree::Literal(lit) => lit,
+ _ => unreachable!(),
+ }
+ }
+ _ => unreachable!(),
+ };
+
+ let last = lit.span();
+ let mut msg = lit.to_string();
+
+ // "abc" => abc
+ msg.pop();
+ msg.remove(0);
+
+ Some((SpanRange { first, last }, msg))
+ }
+
+ let mut ts = err.to_compile_error().into_iter();
+
+ let (span_range, msg) = gut_error(&mut ts).unwrap();
+ let mut res = Diagnostic::spanned_range(span_range, Level::Error, msg);
+
+ while let Some((span_range, msg)) = gut_error(&mut ts) {
+ res = res.span_range_error(span_range, msg);
+ }
+
+ res
+ }
+}
diff --git a/third_party/rust/proc-macro-error/src/dummy.rs b/third_party/rust/proc-macro-error/src/dummy.rs
new file mode 100644
index 0000000000..571a595aa9
--- /dev/null
+++ b/third_party/rust/proc-macro-error/src/dummy.rs
@@ -0,0 +1,150 @@
+//! Facility to emit dummy implementations (or whatever) in case
+//! an error happen.
+//!
+//! `compile_error!` does not abort a compilation right away. This means
+//! `rustc` doesn't just show you the error and abort, it carries on the
+//! compilation process looking for other errors to report.
+//!
+//! Let's consider an example:
+//!
+//! ```rust,ignore
+//! use proc_macro::TokenStream;
+//! use proc_macro_error::*;
+//!
+//! trait MyTrait {
+//! fn do_thing();
+//! }
+//!
+//! // this proc macro is supposed to generate MyTrait impl
+//! #[proc_macro_derive(MyTrait)]
+//! #[proc_macro_error]
+//! fn example(input: TokenStream) -> TokenStream {
+//! // somewhere deep inside
+//! abort!(span, "something's wrong");
+//!
+//! // this implementation will be generated if no error happened
+//! quote! {
+//! impl MyTrait for #name {
+//! fn do_thing() {/* whatever */}
+//! }
+//! }
+//! }
+//!
+//! // ================
+//! // in main.rs
+//!
+//! // this derive triggers an error
+//! #[derive(MyTrait)] // first BOOM!
+//! struct Foo;
+//!
+//! fn main() {
+//! Foo::do_thing(); // second BOOM!
+//! }
+//! ```
+//!
+//! The problem is: the generated token stream contains only `compile_error!`
+//! invocation, the impl was not generated. That means user will see two compilation
+//! errors:
+//!
+//! ```text
+//! error: something's wrong
+//! --> $DIR/probe.rs:9:10
+//! |
+//! 9 |#[proc_macro_derive(MyTrait)]
+//! | ^^^^^^^
+//!
+//! error[E0599]: no function or associated item named `do_thing` found for type `Foo` in the current scope
+//! --> src\main.rs:3:10
+//! |
+//! 1 | struct Foo;
+//! | ----------- function or associated item `do_thing` not found for this
+//! 2 | fn main() {
+//! 3 | Foo::do_thing(); // second BOOM!
+//! | ^^^^^^^^ function or associated item not found in `Foo`
+//! ```
+//!
+//! But the second error is meaningless! We definitely need to fix this.
+//!
+//! Most used approach in cases like this is "dummy implementation" -
+//! omit `impl MyTrait for #name` and fill functions bodies with `unimplemented!()`.
+//!
+//! This is how you do it:
+//!
+//! ```rust,ignore
+//! use proc_macro::TokenStream;
+//! use proc_macro_error::*;
+//!
+//! trait MyTrait {
+//! fn do_thing();
+//! }
+//!
+//! // this proc macro is supposed to generate MyTrait impl
+//! #[proc_macro_derive(MyTrait)]
+//! #[proc_macro_error]
+//! fn example(input: TokenStream) -> TokenStream {
+//! // first of all - we set a dummy impl which will be appended to
+//! // `compile_error!` invocations in case a trigger does happen
+//! set_dummy(quote! {
+//! impl MyTrait for #name {
+//! fn do_thing() { unimplemented!() }
+//! }
+//! });
+//!
+//! // somewhere deep inside
+//! abort!(span, "something's wrong");
+//!
+//! // this implementation will be generated if no error happened
+//! quote! {
+//! impl MyTrait for #name {
+//! fn do_thing() {/* whatever */}
+//! }
+//! }
+//! }
+//!
+//! // ================
+//! // in main.rs
+//!
+//! // this derive triggers an error
+//! #[derive(MyTrait)] // first BOOM!
+//! struct Foo;
+//!
+//! fn main() {
+//! Foo::do_thing(); // no more errors!
+//! }
+//! ```
+
+use proc_macro2::TokenStream;
+use std::cell::RefCell;
+
+use crate::check_correctness;
+
+thread_local! {
+ static DUMMY_IMPL: RefCell<Option<TokenStream>> = RefCell::new(None);
+}
+
+/// Sets dummy token stream which will be appended to `compile_error!(msg);...`
+/// invocations in case you'll emit any errors.
+///
+/// See [guide](../index.html#guide).
+pub fn set_dummy(dummy: TokenStream) -> Option<TokenStream> {
+ check_correctness();
+ DUMMY_IMPL.with(|old_dummy| old_dummy.replace(Some(dummy)))
+}
+
+/// Same as [`set_dummy`] but, instead of resetting, appends tokens to the
+/// existing dummy (if any). Behaves as `set_dummy` if no dummy is present.
+pub fn append_dummy(dummy: TokenStream) {
+ check_correctness();
+ DUMMY_IMPL.with(|old_dummy| {
+ let mut cell = old_dummy.borrow_mut();
+ if let Some(ts) = cell.as_mut() {
+ ts.extend(dummy);
+ } else {
+ *cell = Some(dummy);
+ }
+ });
+}
+
+pub(crate) fn cleanup() -> Option<TokenStream> {
+ DUMMY_IMPL.with(|old_dummy| old_dummy.replace(None))
+}
diff --git a/third_party/rust/proc-macro-error/src/imp/delegate.rs b/third_party/rust/proc-macro-error/src/imp/delegate.rs
new file mode 100644
index 0000000000..07def2b98e
--- /dev/null
+++ b/third_party/rust/proc-macro-error/src/imp/delegate.rs
@@ -0,0 +1,69 @@
+//! This implementation uses [`proc_macro::Diagnostic`], nightly only.
+
+use std::cell::Cell;
+
+use proc_macro::{Diagnostic as PDiag, Level as PLevel};
+
+use crate::{
+ abort_now, check_correctness,
+ diagnostic::{Diagnostic, Level, SuggestionKind},
+};
+
+pub fn abort_if_dirty() {
+ check_correctness();
+ if IS_DIRTY.with(|c| c.get()) {
+ abort_now()
+ }
+}
+
+pub(crate) fn cleanup() -> Vec<Diagnostic> {
+ IS_DIRTY.with(|c| c.set(false));
+ vec![]
+}
+
+pub(crate) fn emit_diagnostic(diag: Diagnostic) {
+ let Diagnostic {
+ level,
+ span_range,
+ msg,
+ suggestions,
+ children,
+ } = diag;
+
+ let span = span_range.collapse().unwrap();
+
+ let level = match level {
+ Level::Warning => PLevel::Warning,
+ Level::Error => {
+ IS_DIRTY.with(|c| c.set(true));
+ PLevel::Error
+ }
+ _ => unreachable!(),
+ };
+
+ let mut res = PDiag::spanned(span, level, msg);
+
+ for (kind, msg, span) in suggestions {
+ res = match (kind, span) {
+ (SuggestionKind::Note, Some(span_range)) => {
+ res.span_note(span_range.collapse().unwrap(), msg)
+ }
+ (SuggestionKind::Help, Some(span_range)) => {
+ res.span_help(span_range.collapse().unwrap(), msg)
+ }
+ (SuggestionKind::Note, None) => res.note(msg),
+ (SuggestionKind::Help, None) => res.help(msg),
+ }
+ }
+
+ for (span_range, msg) in children {
+ let span = span_range.collapse().unwrap();
+ res = res.span_error(span, msg);
+ }
+
+ res.emit()
+}
+
+thread_local! {
+ static IS_DIRTY: Cell<bool> = Cell::new(false);
+}
diff --git a/third_party/rust/proc-macro-error/src/imp/fallback.rs b/third_party/rust/proc-macro-error/src/imp/fallback.rs
new file mode 100644
index 0000000000..ad1f730bfc
--- /dev/null
+++ b/third_party/rust/proc-macro-error/src/imp/fallback.rs
@@ -0,0 +1,30 @@
+//! This implementation uses self-written stable facilities.
+
+use crate::{
+ abort_now, check_correctness,
+ diagnostic::{Diagnostic, Level},
+};
+use std::cell::RefCell;
+
+pub fn abort_if_dirty() {
+ check_correctness();
+ ERR_STORAGE.with(|storage| {
+ if !storage.borrow().is_empty() {
+ abort_now()
+ }
+ });
+}
+
+pub(crate) fn cleanup() -> Vec<Diagnostic> {
+ ERR_STORAGE.with(|storage| storage.replace(Vec::new()))
+}
+
+pub(crate) fn emit_diagnostic(diag: Diagnostic) {
+ if diag.level == Level::Error {
+ ERR_STORAGE.with(|storage| storage.borrow_mut().push(diag));
+ }
+}
+
+thread_local! {
+ static ERR_STORAGE: RefCell<Vec<Diagnostic>> = RefCell::new(Vec::new());
+}
diff --git a/third_party/rust/proc-macro-error/src/lib.rs b/third_party/rust/proc-macro-error/src/lib.rs
new file mode 100644
index 0000000000..fb867fdc03
--- /dev/null
+++ b/third_party/rust/proc-macro-error/src/lib.rs
@@ -0,0 +1,560 @@
+//! # proc-macro-error
+//!
+//! This crate aims to make error reporting in proc-macros simple and easy to use.
+//! Migrate from `panic!`-based errors for as little effort as possible!
+//!
+//! (Also, you can explicitly [append a dummy token stream](dummy/index.html) to your errors).
+//!
+//! To achieve his, this crate serves as a tiny shim around `proc_macro::Diagnostic` and
+//! `compile_error!`. It detects the best way of emitting available based on compiler's version.
+//! When the underlying diagnostic type is finally stabilized, this crate will simply be
+//! delegating to it requiring no changes in your code!
+//!
+//! So you can just use this crate and have *both* some of `proc_macro::Diagnostic` functionality
+//! available on stable ahead of time *and* your error-reporting code future-proof.
+//!
+//! ## Cargo features
+//!
+//! This crate provides *enabled by default* `syn-error` feature that gates
+//! `impl From<syn::Error> for Diagnostic` conversion. If you don't use `syn` and want
+//! to cut off some of compilation time, you can disable it via
+//!
+//! ```toml
+//! [dependencies]
+//! proc-macro-error = { version = "1", default-features = false }
+//! ```
+//!
+//! ***Please note that disabling this feature makes sense only if you don't depend on `syn`
+//! directly or indirectly, and you very likely do.**
+//!
+//! ## Real world examples
+//!
+//! * [`structopt-derive`](https://github.com/TeXitoi/structopt/tree/master/structopt-derive)
+//! (abort-like usage)
+//! * [`auto-impl`](https://github.com/auto-impl-rs/auto_impl/) (emit-like usage)
+//!
+//! ## Limitations
+//!
+//! - Warnings are emitted only on nightly, they are ignored on stable.
+//! - "help" suggestions can't have their own span info on stable,
+//! (essentially inheriting the parent span).
+//! - If a panic occurs somewhere in your macro no errors will be displayed. This is not a
+//! technical limitation but rather intentional design. `panic` is not for error reporting.
+//!
+//! ### `#[proc_macro_error]` attribute
+//!
+//! **This attribute MUST be present on the top level of your macro** (the function
+//! annotated with any of `#[proc_macro]`, `#[proc_macro_derive]`, `#[proc_macro_attribute]`).
+//!
+//! This attribute performs the setup and cleanup necessary to make things work.
+//!
+//! In most cases you'll need the simple `#[proc_macro_error]` form without any
+//! additional settings. Feel free to [skip the "Syntax" section](#macros).
+//!
+//! #### Syntax
+//!
+//! `#[proc_macro_error]` or `#[proc_macro_error(settings...)]`, where `settings...`
+//! is a comma-separated list of:
+//!
+//! - `proc_macro_hack`:
+//!
+//! In order to correctly cooperate with `#[proc_macro_hack]`, `#[proc_macro_error]`
+//! attribute must be placed *before* (above) it, like this:
+//!
+//! ```no_run
+//! # use proc_macro2::TokenStream;
+//! # const IGNORE: &str = "
+//! #[proc_macro_error]
+//! #[proc_macro_hack]
+//! #[proc_macro]
+//! # ";
+//! fn my_macro(input: TokenStream) -> TokenStream {
+//! unimplemented!()
+//! }
+//! ```
+//!
+//! If, for some reason, you can't place it like that you can use
+//! `#[proc_macro_error(proc_macro_hack)]` instead.
+//!
+//! # Note
+//!
+//! If `proc-macro-hack` was detected (by any means) `allow_not_macro`
+//! and `assert_unwind_safe` will be applied automatically.
+//!
+//! - `allow_not_macro`:
+//!
+//! By default, the attribute checks that it's applied to a proc-macro.
+//! If none of `#[proc_macro]`, `#[proc_macro_derive]` nor `#[proc_macro_attribute]` are
+//! present it will panic. It's the intention - this crate is supposed to be used only with
+//! proc-macros.
+//!
+//! This setting is made to bypass the check, useful in certain circumstances.
+//!
+//! Pay attention: the function this attribute is applied to must return
+//! `proc_macro::TokenStream`.
+//!
+//! This setting is implied if `proc-macro-hack` was detected.
+//!
+//! - `assert_unwind_safe`:
+//!
+//! By default, your code must be [unwind safe]. If your code is not unwind safe,
+//! but you believe it's correct, you can use this setting to bypass the check.
+//! You would need this for code that uses `lazy_static` or `thread_local` with
+//! `Cell/RefCell` inside (and the like).
+//!
+//! This setting is implied if `#[proc_macro_error]` is applied to a function
+//! marked as `#[proc_macro]`, `#[proc_macro_derive]` or `#[proc_macro_attribute]`.
+//!
+//! This setting is also implied if `proc-macro-hack` was detected.
+//!
+//! ## Macros
+//!
+//! Most of the time you want to use the macros. Syntax is described in the next section below.
+//!
+//! You'll need to decide how you want to emit errors:
+//!
+//! * Emit the error and abort. Very much panic-like usage. Served by [`abort!`] and
+//! [`abort_call_site!`].
+//! * Emit the error but do not abort right away, looking for other errors to report.
+//! Served by [`emit_error!`] and [`emit_call_site_error!`].
+//!
+//! You **can** mix these usages.
+//!
+//! `abort` and `emit_error` take a "source span" as the first argument. This source
+//! will be used to highlight the place the error originates from. It must be one of:
+//!
+//! * *Something* that implements [`ToTokens`] (most types in `syn` and `proc-macro2` do).
+//! This source is the preferable one since it doesn't lose span information on multi-token
+//! spans, see [this issue](https://gitlab.com/CreepySkeleton/proc-macro-error/-/issues/6)
+//! for details.
+//! * [`proc_macro::Span`]
+//! * [`proc-macro2::Span`]
+//!
+//! The rest is your message in format-like style.
+//!
+//! See [the next section](#syntax-1) for detailed syntax.
+//!
+//! - [`abort!`]:
+//!
+//! Very much panic-like usage - abort right away and show the error.
+//! Expands to [`!`] (never type).
+//!
+//! - [`abort_call_site!`]:
+//!
+//! Shortcut for `abort!(Span::call_site(), ...)`. Expands to [`!`] (never type).
+//!
+//! - [`emit_error!`]:
+//!
+//! [`proc_macro::Diagnostic`]-like usage - emit the error but keep going,
+//! looking for other errors to report.
+//! The compilation will fail nonetheless. Expands to [`()`] (unit type).
+//!
+//! - [`emit_call_site_error!`]:
+//!
+//! Shortcut for `emit_error!(Span::call_site(), ...)`. Expands to [`()`] (unit type).
+//!
+//! - [`emit_warning!`]:
+//!
+//! Like `emit_error!` but emit a warning instead of error. The compilation won't fail
+//! because of warnings.
+//! Expands to [`()`] (unit type).
+//!
+//! **Beware**: warnings are nightly only, they are completely ignored on stable.
+//!
+//! - [`emit_call_site_warning!`]:
+//!
+//! Shortcut for `emit_warning!(Span::call_site(), ...)`. Expands to [`()`] (unit type).
+//!
+//! - [`diagnostic`]:
+//!
+//! Build an instance of `Diagnostic` in format-like style.
+//!
+//! #### Syntax
+//!
+//! All the macros have pretty much the same syntax:
+//!
+//! 1. ```ignore
+//! abort!(single_expr)
+//! ```
+//! Shortcut for `Diagnostic::from(expr).abort()`.
+//!
+//! 2. ```ignore
+//! abort!(span, message)
+//! ```
+//! The first argument is an expression the span info should be taken from.
+//!
+//! The second argument is the error message, it must implement [`ToString`].
+//!
+//! 3. ```ignore
+//! abort!(span, format_literal, format_args...)
+//! ```
+//!
+//! This form is pretty much the same as 2, except `format!(format_literal, format_args...)`
+//! will be used to for the message instead of [`ToString`].
+//!
+//! That's it. `abort!`, `emit_warning`, `emit_error` share this exact syntax.
+//!
+//! `abort_call_site!`, `emit_call_site_warning`, `emit_call_site_error` lack 1 form
+//! and do not take span in 2'th and 3'th forms. Those are essentially shortcuts for
+//! `macro!(Span::call_site(), args...)`.
+//!
+//! `diagnostic!` requires a [`Level`] instance between `span` and second argument
+//! (1'th form is the same).
+//!
+//! > **Important!**
+//! >
+//! > If you have some type from `proc_macro` or `syn` to point to, do not call `.span()`
+//! > on it but rather use it directly:
+//! > ```no_run
+//! > # use proc_macro_error::abort;
+//! > # let input = proc_macro2::TokenStream::new();
+//! > let ty: syn::Type = syn::parse2(input).unwrap();
+//! > abort!(ty, "BOOM");
+//! > // ^^ <-- avoid .span()
+//! > ```
+//! >
+//! > `.span()` calls work too, but you may experience regressions in message quality.
+//!
+//! #### Note attachments
+//!
+//! 3. Every macro can have "note" attachments (only 2 and 3 form).
+//! ```ignore
+//! let opt_help = if have_some_info { Some("did you mean `this`?") } else { None };
+//!
+//! abort!(
+//! span, message; // <--- attachments start with `;` (semicolon)
+//!
+//! help = "format {} {}", "arg1", "arg2"; // <--- every attachment ends with `;`,
+//! // maybe except the last one
+//!
+//! note = "to_string"; // <--- one arg uses `.to_string()` instead of `format!()`
+//!
+//! yay = "I see what {} did here", "you"; // <--- "help =" and "hint =" are mapped
+//! // to Diagnostic::help,
+//! // anything else is Diagnostic::note
+//!
+//! wow = note_span => "custom span"; // <--- attachments can have their own span
+//! // it takes effect only on nightly though
+//!
+//! hint =? opt_help; // <-- "optional" attachment, get displayed only if `Some`
+//! // must be single `Option` expression
+//!
+//! note =? note_span => opt_help // <-- optional attachments can have custom spans too
+//! );
+//! ```
+//!
+
+//! ### Diagnostic type
+//!
+//! [`Diagnostic`] type is intentionally designed to be API compatible with [`proc_macro::Diagnostic`].
+//! Not all API is implemented, only the part that can be reasonably implemented on stable.
+//!
+//!
+//! [`abort!`]: macro.abort.html
+//! [`abort_call_site!`]: macro.abort_call_site.html
+//! [`emit_warning!`]: macro.emit_warning.html
+//! [`emit_error!`]: macro.emit_error.html
+//! [`emit_call_site_warning!`]: macro.emit_call_site_error.html
+//! [`emit_call_site_error!`]: macro.emit_call_site_warning.html
+//! [`diagnostic!`]: macro.diagnostic.html
+//! [`Diagnostic`]: struct.Diagnostic.html
+//!
+//! [`proc_macro::Span`]: https://doc.rust-lang.org/proc_macro/struct.Span.html
+//! [`proc_macro::Diagnostic`]: https://doc.rust-lang.org/proc_macro/struct.Diagnostic.html
+//!
+//! [unwind safe]: https://doc.rust-lang.org/std/panic/trait.UnwindSafe.html#what-is-unwind-safety
+//! [`!`]: https://doc.rust-lang.org/std/primitive.never.html
+//! [`()`]: https://doc.rust-lang.org/std/primitive.unit.html
+//! [`ToString`]: https://doc.rust-lang.org/std/string/trait.ToString.html
+//!
+//! [`proc-macro2::Span`]: https://docs.rs/proc-macro2/1.0.10/proc_macro2/struct.Span.html
+//! [`ToTokens`]: https://docs.rs/quote/1.0.3/quote/trait.ToTokens.html
+//!
+
+#![cfg_attr(not(use_fallback), feature(proc_macro_diagnostic))]
+#![forbid(unsafe_code)]
+#![allow(clippy::needless_doctest_main)]
+
+extern crate proc_macro;
+
+pub use crate::{
+ diagnostic::{Diagnostic, DiagnosticExt, Level},
+ dummy::{append_dummy, set_dummy},
+};
+pub use proc_macro_error_attr::proc_macro_error;
+
+use proc_macro2::Span;
+use quote::{quote, ToTokens};
+
+use std::cell::Cell;
+use std::panic::{catch_unwind, resume_unwind, UnwindSafe};
+
+pub mod dummy;
+
+mod diagnostic;
+mod macros;
+mod sealed;
+
+#[cfg(use_fallback)]
+#[path = "imp/fallback.rs"]
+mod imp;
+
+#[cfg(not(use_fallback))]
+#[path = "imp/delegate.rs"]
+mod imp;
+
+#[derive(Debug, Clone, Copy)]
+pub struct SpanRange {
+ pub first: Span,
+ pub last: Span,
+}
+
+impl SpanRange {
+ /// Create a range with the `first` and `last` spans being the same.
+ pub fn single_span(span: Span) -> Self {
+ SpanRange {
+ first: span,
+ last: span,
+ }
+ }
+
+ /// Create a `SpanRange` resolving at call site.
+ pub fn call_site() -> Self {
+ SpanRange::single_span(Span::call_site())
+ }
+
+ /// Construct span range from a `TokenStream`. This method always preserves all the
+ /// range.
+ ///
+ /// ### Note
+ ///
+ /// If the stream is empty, the result is `SpanRange::call_site()`. If the stream
+ /// consists of only one `TokenTree`, the result is `SpanRange::single_span(tt.span())`
+ /// that doesn't lose anything.
+ pub fn from_tokens(ts: &dyn ToTokens) -> Self {
+ let mut spans = ts.to_token_stream().into_iter().map(|tt| tt.span());
+ let first = spans.next().unwrap_or_else(|| Span::call_site());
+ let last = spans.last().unwrap_or(first);
+
+ SpanRange { first, last }
+ }
+
+ /// Join two span ranges. The resulting range will start at `self.first` and end at
+ /// `other.last`.
+ pub fn join_range(self, other: SpanRange) -> Self {
+ SpanRange {
+ first: self.first,
+ last: other.last,
+ }
+ }
+
+ /// Collapse the range into single span, preserving as much information as possible.
+ pub fn collapse(self) -> Span {
+ self.first.join(self.last).unwrap_or(self.first)
+ }
+}
+
+/// This traits expands `Result<T, Into<Diagnostic>>` with some handy shortcuts.
+pub trait ResultExt {
+ type Ok;
+
+ /// Behaves like `Result::unwrap`: if self is `Ok` yield the contained value,
+ /// otherwise abort macro execution via `abort!`.
+ fn unwrap_or_abort(self) -> Self::Ok;
+
+ /// Behaves like `Result::expect`: if self is `Ok` yield the contained value,
+ /// otherwise abort macro execution via `abort!`.
+ /// If it aborts then resulting error message will be preceded with `message`.
+ fn expect_or_abort(self, msg: &str) -> Self::Ok;
+}
+
+/// This traits expands `Option` with some handy shortcuts.
+pub trait OptionExt {
+ type Some;
+
+ /// Behaves like `Option::expect`: if self is `Some` yield the contained value,
+ /// otherwise abort macro execution via `abort_call_site!`.
+ /// If it aborts the `message` will be used for [`compile_error!`][compl_err] invocation.
+ ///
+ /// [compl_err]: https://doc.rust-lang.org/std/macro.compile_error.html
+ fn expect_or_abort(self, msg: &str) -> Self::Some;
+}
+
+/// Abort macro execution and display all the emitted errors, if any.
+///
+/// Does nothing if no errors were emitted (warnings do not count).
+pub fn abort_if_dirty() {
+ imp::abort_if_dirty();
+}
+
+impl<T, E: Into<Diagnostic>> ResultExt for Result<T, E> {
+ type Ok = T;
+
+ fn unwrap_or_abort(self) -> T {
+ match self {
+ Ok(res) => res,
+ Err(e) => e.into().abort(),
+ }
+ }
+
+ fn expect_or_abort(self, message: &str) -> T {
+ match self {
+ Ok(res) => res,
+ Err(e) => {
+ let mut e = e.into();
+ e.msg = format!("{}: {}", message, e.msg);
+ e.abort()
+ }
+ }
+ }
+}
+
+impl<T> OptionExt for Option<T> {
+ type Some = T;
+
+ fn expect_or_abort(self, message: &str) -> T {
+ match self {
+ Some(res) => res,
+ None => abort_call_site!(message),
+ }
+ }
+}
+
+/// This is the entry point for a proc-macro.
+///
+/// **NOT PUBLIC API, SUBJECT TO CHANGE WITHOUT ANY NOTICE**
+#[doc(hidden)]
+pub fn entry_point<F>(f: F, proc_macro_hack: bool) -> proc_macro::TokenStream
+where
+ F: FnOnce() -> proc_macro::TokenStream + UnwindSafe,
+{
+ ENTERED_ENTRY_POINT.with(|flag| flag.set(flag.get() + 1));
+ let caught = catch_unwind(f);
+ let dummy = dummy::cleanup();
+ let err_storage = imp::cleanup();
+ ENTERED_ENTRY_POINT.with(|flag| flag.set(flag.get() - 1));
+
+ let gen_error = || {
+ if proc_macro_hack {
+ quote! {{
+ macro_rules! proc_macro_call {
+ () => ( unimplemented!() )
+ }
+
+ #(#err_storage)*
+ #dummy
+
+ unimplemented!()
+ }}
+ } else {
+ quote!( #(#err_storage)* #dummy )
+ }
+ };
+
+ match caught {
+ Ok(ts) => {
+ if err_storage.is_empty() {
+ ts
+ } else {
+ gen_error().into()
+ }
+ }
+
+ Err(boxed) => match boxed.downcast::<AbortNow>() {
+ Ok(_) => gen_error().into(),
+ Err(boxed) => resume_unwind(boxed),
+ },
+ }
+}
+
+fn abort_now() -> ! {
+ check_correctness();
+ panic!(AbortNow)
+}
+
+thread_local! {
+ static ENTERED_ENTRY_POINT: Cell<usize> = Cell::new(0);
+}
+
+struct AbortNow;
+
+fn check_correctness() {
+ if ENTERED_ENTRY_POINT.with(|flag| flag.get()) == 0 {
+ panic!(
+ "proc-macro-error API cannot be used outside of `entry_point` invocation, \
+ perhaps you forgot to annotate your #[proc_macro] function with `#[proc_macro_error]"
+ );
+ }
+}
+
+/// **ALL THE STUFF INSIDE IS NOT PUBLIC API!!!**
+#[doc(hidden)]
+pub mod __export {
+ // reexports for use in macros
+ pub extern crate proc_macro;
+ pub extern crate proc_macro2;
+
+ use proc_macro2::Span;
+ use quote::ToTokens;
+
+ use crate::SpanRange;
+
+ // inspired by
+ // https://github.com/dtolnay/case-studies/blob/master/autoref-specialization/README.md#simple-application
+
+ pub trait SpanAsSpanRange {
+ #[allow(non_snake_case)]
+ fn FIRST_ARG_MUST_EITHER_BE_Span_OR_IMPLEMENT_ToTokens_OR_BE_SpanRange(&self) -> SpanRange;
+ }
+
+ pub trait Span2AsSpanRange {
+ #[allow(non_snake_case)]
+ fn FIRST_ARG_MUST_EITHER_BE_Span_OR_IMPLEMENT_ToTokens_OR_BE_SpanRange(&self) -> SpanRange;
+ }
+
+ pub trait ToTokensAsSpanRange {
+ #[allow(non_snake_case)]
+ fn FIRST_ARG_MUST_EITHER_BE_Span_OR_IMPLEMENT_ToTokens_OR_BE_SpanRange(&self) -> SpanRange;
+ }
+
+ pub trait SpanRangeAsSpanRange {
+ #[allow(non_snake_case)]
+ fn FIRST_ARG_MUST_EITHER_BE_Span_OR_IMPLEMENT_ToTokens_OR_BE_SpanRange(&self) -> SpanRange;
+ }
+
+ impl<T: ToTokens> ToTokensAsSpanRange for &T {
+ fn FIRST_ARG_MUST_EITHER_BE_Span_OR_IMPLEMENT_ToTokens_OR_BE_SpanRange(&self) -> SpanRange {
+ let mut ts = self.to_token_stream().into_iter();
+ let first = ts
+ .next()
+ .map(|tt| tt.span())
+ .unwrap_or_else(Span::call_site);
+ let last = ts.last().map(|tt| tt.span()).unwrap_or(first);
+ SpanRange { first, last }
+ }
+ }
+
+ impl Span2AsSpanRange for Span {
+ fn FIRST_ARG_MUST_EITHER_BE_Span_OR_IMPLEMENT_ToTokens_OR_BE_SpanRange(&self) -> SpanRange {
+ SpanRange {
+ first: *self,
+ last: *self,
+ }
+ }
+ }
+
+ impl SpanAsSpanRange for proc_macro::Span {
+ fn FIRST_ARG_MUST_EITHER_BE_Span_OR_IMPLEMENT_ToTokens_OR_BE_SpanRange(&self) -> SpanRange {
+ SpanRange {
+ first: self.clone().into(),
+ last: self.clone().into(),
+ }
+ }
+ }
+
+ impl SpanRangeAsSpanRange for SpanRange {
+ fn FIRST_ARG_MUST_EITHER_BE_Span_OR_IMPLEMENT_ToTokens_OR_BE_SpanRange(&self) -> SpanRange {
+ *self
+ }
+ }
+}
diff --git a/third_party/rust/proc-macro-error/src/macros.rs b/third_party/rust/proc-macro-error/src/macros.rs
new file mode 100644
index 0000000000..747b684d56
--- /dev/null
+++ b/third_party/rust/proc-macro-error/src/macros.rs
@@ -0,0 +1,288 @@
+// FIXME: this can be greatly simplified via $()?
+// as soon as MRSV hits 1.32
+
+/// Build [`Diagnostic`](struct.Diagnostic.html) instance from provided arguments.
+///
+/// # Syntax
+///
+/// See [the guide](index.html#guide).
+///
+#[macro_export]
+macro_rules! diagnostic {
+ // from alias
+ ($err:expr) => { $crate::Diagnostic::from($err) };
+
+ // span, message, help
+ ($span:expr, $level:expr, $fmt:expr, $($args:expr),+ ; $($rest:tt)+) => {{
+ #[allow(unused_imports)]
+ use $crate::__export::{
+ ToTokensAsSpanRange,
+ Span2AsSpanRange,
+ SpanAsSpanRange,
+ SpanRangeAsSpanRange
+ };
+ use $crate::DiagnosticExt;
+ let span_range = (&$span).FIRST_ARG_MUST_EITHER_BE_Span_OR_IMPLEMENT_ToTokens_OR_BE_SpanRange();
+
+ let diag = $crate::Diagnostic::spanned_range(
+ span_range,
+ $level,
+ format!($fmt, $($args),*)
+ );
+ $crate::__pme__suggestions!(diag $($rest)*);
+ diag
+ }};
+
+ ($span:expr, $level:expr, $msg:expr ; $($rest:tt)+) => {{
+ #[allow(unused_imports)]
+ use $crate::__export::{
+ ToTokensAsSpanRange,
+ Span2AsSpanRange,
+ SpanAsSpanRange,
+ SpanRangeAsSpanRange
+ };
+ use $crate::DiagnosticExt;
+ let span_range = (&$span).FIRST_ARG_MUST_EITHER_BE_Span_OR_IMPLEMENT_ToTokens_OR_BE_SpanRange();
+
+ let diag = $crate::Diagnostic::spanned_range(span_range, $level, $msg.to_string());
+ $crate::__pme__suggestions!(diag $($rest)*);
+ diag
+ }};
+
+ // span, message, no help
+ ($span:expr, $level:expr, $fmt:expr, $($args:expr),+) => {{
+ #[allow(unused_imports)]
+ use $crate::__export::{
+ ToTokensAsSpanRange,
+ Span2AsSpanRange,
+ SpanAsSpanRange,
+ SpanRangeAsSpanRange
+ };
+ use $crate::DiagnosticExt;
+ let span_range = (&$span).FIRST_ARG_MUST_EITHER_BE_Span_OR_IMPLEMENT_ToTokens_OR_BE_SpanRange();
+
+ $crate::Diagnostic::spanned_range(
+ span_range,
+ $level,
+ format!($fmt, $($args),*)
+ )
+ }};
+
+ ($span:expr, $level:expr, $msg:expr) => {{
+ #[allow(unused_imports)]
+ use $crate::__export::{
+ ToTokensAsSpanRange,
+ Span2AsSpanRange,
+ SpanAsSpanRange,
+ SpanRangeAsSpanRange
+ };
+ use $crate::DiagnosticExt;
+ let span_range = (&$span).FIRST_ARG_MUST_EITHER_BE_Span_OR_IMPLEMENT_ToTokens_OR_BE_SpanRange();
+
+ $crate::Diagnostic::spanned_range(span_range, $level, $msg.to_string())
+ }};
+
+
+ // trailing commas
+
+ ($span:expr, $level:expr, $fmt:expr, $($args:expr),+, ; $($rest:tt)+) => {
+ $crate::diagnostic!($span, $level, $fmt, $($args),* ; $($rest)*)
+ };
+ ($span:expr, $level:expr, $msg:expr, ; $($rest:tt)+) => {
+ $crate::diagnostic!($span, $level, $msg ; $($rest)*)
+ };
+ ($span:expr, $level:expr, $fmt:expr, $($args:expr),+,) => {
+ $crate::diagnostic!($span, $level, $fmt, $($args),*)
+ };
+ ($span:expr, $level:expr, $msg:expr,) => {
+ $crate::diagnostic!($span, $level, $msg)
+ };
+ // ($err:expr,) => { $crate::diagnostic!($err) };
+}
+
+/// Abort proc-macro execution right now and display the error.
+///
+/// # Syntax
+///
+/// See [the guide](index.html#guide).
+#[macro_export]
+macro_rules! abort {
+ ($err:expr) => {
+ $crate::diagnostic!($err).abort()
+ };
+
+ ($span:expr, $($tts:tt)*) => {
+ $crate::diagnostic!($span, $crate::Level::Error, $($tts)*).abort()
+ };
+}
+
+/// Shortcut for `abort!(Span::call_site(), msg...)`. This macro
+/// is still preferable over plain panic, panics are not for error reporting.
+///
+/// # Syntax
+///
+/// See [the guide](index.html#guide).
+///
+#[macro_export]
+macro_rules! abort_call_site {
+ ($($tts:tt)*) => {
+ $crate::abort!($crate::__export::proc_macro2::Span::call_site(), $($tts)*)
+ };
+}
+
+/// Emit an error while not aborting the proc-macro right away.
+///
+/// # Syntax
+///
+/// See [the guide](index.html#guide).
+///
+#[macro_export]
+macro_rules! emit_error {
+ ($err:expr) => {
+ $crate::diagnostic!($err).emit()
+ };
+
+ ($span:expr, $($tts:tt)*) => {{
+ let level = $crate::Level::Error;
+ $crate::diagnostic!($span, level, $($tts)*).emit()
+ }};
+}
+
+/// Shortcut for `emit_error!(Span::call_site(), ...)`. This macro
+/// is still preferable over plain panic, panics are not for error reporting..
+///
+/// # Syntax
+///
+/// See [the guide](index.html#guide).
+///
+#[macro_export]
+macro_rules! emit_call_site_error {
+ ($($tts:tt)*) => {
+ $crate::emit_error!($crate::__export::proc_macro2::Span::call_site(), $($tts)*)
+ };
+}
+
+/// Emit a warning. Warnings are not errors and compilation won't fail because of them.
+///
+/// **Does nothing on stable**
+///
+/// # Syntax
+///
+/// See [the guide](index.html#guide).
+///
+#[macro_export]
+macro_rules! emit_warning {
+ ($span:expr, $($tts:tt)*) => {
+ $crate::diagnostic!($span, $crate::Level::Warning, $($tts)*).emit()
+ };
+}
+
+/// Shortcut for `emit_warning!(Span::call_site(), ...)`.
+///
+/// **Does nothing on stable**
+///
+/// # Syntax
+///
+/// See [the guide](index.html#guide).
+///
+#[macro_export]
+macro_rules! emit_call_site_warning {
+ ($($tts:tt)*) => {{
+ $crate::emit_warning!($crate::__export::proc_macro2::Span::call_site(), $($tts)*)
+ }};
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! __pme__suggestions {
+ ($var:ident) => ();
+
+ ($var:ident $help:ident =? $msg:expr) => {
+ let $var = if let Some(msg) = $msg {
+ $var.suggestion(stringify!($help), msg.to_string())
+ } else {
+ $var
+ };
+ };
+ ($var:ident $help:ident =? $span:expr => $msg:expr) => {
+ let $var = if let Some(msg) = $msg {
+ $var.span_suggestion($span.into(), stringify!($help), msg.to_string())
+ } else {
+ $var
+ };
+ };
+
+ ($var:ident $help:ident =? $msg:expr ; $($rest:tt)*) => {
+ $crate::__pme__suggestions!($var $help =? $msg);
+ $crate::__pme__suggestions!($var $($rest)*);
+ };
+ ($var:ident $help:ident =? $span:expr => $msg:expr ; $($rest:tt)*) => {
+ $crate::__pme__suggestions!($var $help =? $span => $msg);
+ $crate::__pme__suggestions!($var $($rest)*);
+ };
+
+
+ ($var:ident $help:ident = $msg:expr) => {
+ let $var = $var.suggestion(stringify!($help), $msg.to_string());
+ };
+ ($var:ident $help:ident = $fmt:expr, $($args:expr),+) => {
+ let $var = $var.suggestion(
+ stringify!($help),
+ format!($fmt, $($args),*)
+ );
+ };
+ ($var:ident $help:ident = $span:expr => $msg:expr) => {
+ let $var = $var.span_suggestion($span.into(), stringify!($help), $msg.to_string());
+ };
+ ($var:ident $help:ident = $span:expr => $fmt:expr, $($args:expr),+) => {
+ let $var = $var.span_suggestion(
+ $span.into(),
+ stringify!($help),
+ format!($fmt, $($args),*)
+ );
+ };
+
+ ($var:ident $help:ident = $msg:expr ; $($rest:tt)*) => {
+ $crate::__pme__suggestions!($var $help = $msg);
+ $crate::__pme__suggestions!($var $($rest)*);
+ };
+ ($var:ident $help:ident = $fmt:expr, $($args:expr),+ ; $($rest:tt)*) => {
+ $crate::__pme__suggestions!($var $help = $fmt, $($args),*);
+ $crate::__pme__suggestions!($var $($rest)*);
+ };
+ ($var:ident $help:ident = $span:expr => $msg:expr ; $($rest:tt)*) => {
+ $crate::__pme__suggestions!($var $help = $span => $msg);
+ $crate::__pme__suggestions!($var $($rest)*);
+ };
+ ($var:ident $help:ident = $span:expr => $fmt:expr, $($args:expr),+ ; $($rest:tt)*) => {
+ $crate::__pme__suggestions!($var $help = $span => $fmt, $($args),*);
+ $crate::__pme__suggestions!($var $($rest)*);
+ };
+
+ // trailing commas
+
+ ($var:ident $help:ident = $msg:expr,) => {
+ $crate::__pme__suggestions!($var $help = $msg)
+ };
+ ($var:ident $help:ident = $fmt:expr, $($args:expr),+,) => {
+ $crate::__pme__suggestions!($var $help = $fmt, $($args)*)
+ };
+ ($var:ident $help:ident = $span:expr => $msg:expr,) => {
+ $crate::__pme__suggestions!($var $help = $span => $msg)
+ };
+ ($var:ident $help:ident = $span:expr => $fmt:expr, $($args:expr),*,) => {
+ $crate::__pme__suggestions!($var $help = $span => $fmt, $($args)*)
+ };
+ ($var:ident $help:ident = $msg:expr, ; $($rest:tt)*) => {
+ $crate::__pme__suggestions!($var $help = $msg; $($rest)*)
+ };
+ ($var:ident $help:ident = $fmt:expr, $($args:expr),+, ; $($rest:tt)*) => {
+ $crate::__pme__suggestions!($var $help = $fmt, $($args),*; $($rest)*)
+ };
+ ($var:ident $help:ident = $span:expr => $msg:expr, ; $($rest:tt)*) => {
+ $crate::__pme__suggestions!($var $help = $span => $msg; $($rest)*)
+ };
+ ($var:ident $help:ident = $span:expr => $fmt:expr, $($args:expr),+, ; $($rest:tt)*) => {
+ $crate::__pme__suggestions!($var $help = $span => $fmt, $($args),*; $($rest)*)
+ };
+}
diff --git a/third_party/rust/proc-macro-error/src/sealed.rs b/third_party/rust/proc-macro-error/src/sealed.rs
new file mode 100644
index 0000000000..a2d5081e55
--- /dev/null
+++ b/third_party/rust/proc-macro-error/src/sealed.rs
@@ -0,0 +1,3 @@
+pub trait Sealed {}
+
+impl Sealed for crate::Diagnostic {}
diff --git a/third_party/rust/proc-macro-error/tests/macro-errors.rs b/third_party/rust/proc-macro-error/tests/macro-errors.rs
new file mode 100644
index 0000000000..dd60f88a80
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/macro-errors.rs
@@ -0,0 +1,8 @@
+extern crate trybuild;
+
+#[cfg_attr(skip_ui_tests, ignore)]
+#[test]
+fn ui() {
+ let t = trybuild::TestCases::new();
+ t.compile_fail("tests/ui/*.rs");
+}
diff --git a/third_party/rust/proc-macro-error/tests/ok.rs b/third_party/rust/proc-macro-error/tests/ok.rs
new file mode 100644
index 0000000000..cf64c027f8
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ok.rs
@@ -0,0 +1,10 @@
+extern crate test_crate;
+
+use test_crate::*;
+
+ok!(it_works);
+
+#[test]
+fn check_it_works() {
+ it_works();
+}
diff --git a/third_party/rust/proc-macro-error/tests/runtime-errors.rs b/third_party/rust/proc-macro-error/tests/runtime-errors.rs
new file mode 100644
index 0000000000..13108a2d91
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/runtime-errors.rs
@@ -0,0 +1,13 @@
+use proc_macro_error::*;
+
+#[test]
+#[should_panic = "proc-macro-error API cannot be used outside of"]
+fn missing_attr_emit() {
+ emit_call_site_error!("You won't see me");
+}
+
+#[test]
+#[should_panic = "proc-macro-error API cannot be used outside of"]
+fn missing_attr_abort() {
+ abort_call_site!("You won't see me");
+}
diff --git a/third_party/rust/proc-macro-error/tests/ui/abort.rs b/third_party/rust/proc-macro-error/tests/ui/abort.rs
new file mode 100644
index 0000000000..f63118251e
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/abort.rs
@@ -0,0 +1,11 @@
+extern crate test_crate;
+use test_crate::*;
+
+abort_from!(one, two);
+abort_to_string!(one, two);
+abort_format!(one, two);
+direct_abort!(one, two);
+abort_notes!(one, two);
+abort_call_site_test!(one, two);
+
+fn main() {}
diff --git a/third_party/rust/proc-macro-error/tests/ui/abort.stderr b/third_party/rust/proc-macro-error/tests/ui/abort.stderr
new file mode 100644
index 0000000000..c5399d9d91
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/abort.stderr
@@ -0,0 +1,48 @@
+error: abort!(span, from) test
+ --> $DIR/abort.rs:4:13
+ |
+4 | abort_from!(one, two);
+ | ^^^
+
+error: abort!(span, single_expr) test
+ --> $DIR/abort.rs:5:18
+ |
+5 | abort_to_string!(one, two);
+ | ^^^
+
+error: abort!(span, expr1, expr2) test
+ --> $DIR/abort.rs:6:15
+ |
+6 | abort_format!(one, two);
+ | ^^^
+
+error: Diagnostic::abort() test
+ --> $DIR/abort.rs:7:15
+ |
+7 | direct_abort!(one, two);
+ | ^^^
+
+error: This is an error
+
+ = note: simple note
+ = help: simple help
+ = help: simple hint
+ = note: simple yay
+ = note: format note
+ = note: Some note
+ = note: spanned simple note
+ = note: spanned format note
+ = note: Some note
+
+ --> $DIR/abort.rs:8:14
+ |
+8 | abort_notes!(one, two);
+ | ^^^
+
+error: abort_call_site! test
+ --> $DIR/abort.rs:9:1
+ |
+9 | abort_call_site_test!(one, two);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/proc-macro-error/tests/ui/append_dummy.rs b/third_party/rust/proc-macro-error/tests/ui/append_dummy.rs
new file mode 100644
index 0000000000..53d6feacc1
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/append_dummy.rs
@@ -0,0 +1,13 @@
+extern crate test_crate;
+use test_crate::*;
+
+enum NeedDefault {
+ A,
+ B
+}
+
+append_dummy!(need_default);
+
+fn main() {
+ let _ = NeedDefault::default();
+}
diff --git a/third_party/rust/proc-macro-error/tests/ui/append_dummy.stderr b/third_party/rust/proc-macro-error/tests/ui/append_dummy.stderr
new file mode 100644
index 0000000000..8a47ddaac4
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/append_dummy.stderr
@@ -0,0 +1,5 @@
+error: append_dummy test
+ --> $DIR/append_dummy.rs:9:15
+ |
+9 | append_dummy!(need_default);
+ | ^^^^^^^^^^^^
diff --git a/third_party/rust/proc-macro-error/tests/ui/children_messages.rs b/third_party/rust/proc-macro-error/tests/ui/children_messages.rs
new file mode 100644
index 0000000000..fb9e6dc697
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/children_messages.rs
@@ -0,0 +1,6 @@
+extern crate test_crate;
+use test_crate::*;
+
+children_messages!(one, two, three, four);
+
+fn main() {}
diff --git a/third_party/rust/proc-macro-error/tests/ui/children_messages.stderr b/third_party/rust/proc-macro-error/tests/ui/children_messages.stderr
new file mode 100644
index 0000000000..3b49d83165
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/children_messages.stderr
@@ -0,0 +1,23 @@
+error: main macro message
+ --> $DIR/children_messages.rs:4:20
+ |
+4 | children_messages!(one, two, three, four);
+ | ^^^
+
+error: child message
+ --> $DIR/children_messages.rs:4:25
+ |
+4 | children_messages!(one, two, three, four);
+ | ^^^
+
+error: main syn::Error
+ --> $DIR/children_messages.rs:4:30
+ |
+4 | children_messages!(one, two, three, four);
+ | ^^^^^
+
+error: child syn::Error
+ --> $DIR/children_messages.rs:4:37
+ |
+4 | children_messages!(one, two, three, four);
+ | ^^^^
diff --git a/third_party/rust/proc-macro-error/tests/ui/dummy.rs b/third_party/rust/proc-macro-error/tests/ui/dummy.rs
new file mode 100644
index 0000000000..caa4827886
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/dummy.rs
@@ -0,0 +1,13 @@
+extern crate test_crate;
+use test_crate::*;
+
+enum NeedDefault {
+ A,
+ B
+}
+
+dummy!(need_default);
+
+fn main() {
+ let _ = NeedDefault::default();
+}
diff --git a/third_party/rust/proc-macro-error/tests/ui/dummy.stderr b/third_party/rust/proc-macro-error/tests/ui/dummy.stderr
new file mode 100644
index 0000000000..bae078afa8
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/dummy.stderr
@@ -0,0 +1,5 @@
+error: set_dummy test
+ --> $DIR/dummy.rs:9:8
+ |
+9 | dummy!(need_default);
+ | ^^^^^^^^^^^^
diff --git a/third_party/rust/proc-macro-error/tests/ui/emit.rs b/third_party/rust/proc-macro-error/tests/ui/emit.rs
new file mode 100644
index 0000000000..c5c7db095f
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/emit.rs
@@ -0,0 +1,7 @@
+extern crate test_crate;
+use test_crate::*;
+
+emit!(one, two, three, four, five);
+emit_notes!(one, two);
+
+fn main() {}
diff --git a/third_party/rust/proc-macro-error/tests/ui/emit.stderr b/third_party/rust/proc-macro-error/tests/ui/emit.stderr
new file mode 100644
index 0000000000..9484bd628b
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/emit.stderr
@@ -0,0 +1,48 @@
+error: emit!(span, from) test
+ --> $DIR/emit.rs:4:7
+ |
+4 | emit!(one, two, three, four, five);
+ | ^^^
+
+error: emit!(span, expr1, expr2) test
+ --> $DIR/emit.rs:4:12
+ |
+4 | emit!(one, two, three, four, five);
+ | ^^^
+
+error: emit!(span, single_expr) test
+ --> $DIR/emit.rs:4:17
+ |
+4 | emit!(one, two, three, four, five);
+ | ^^^^^
+
+error: Diagnostic::emit() test
+ --> $DIR/emit.rs:4:24
+ |
+4 | emit!(one, two, three, four, five);
+ | ^^^^
+
+error: emit_call_site_error!(expr) test
+ --> $DIR/emit.rs:4:1
+ |
+4 | emit!(one, two, three, four, five);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: This is an error
+
+ = note: simple note
+ = help: simple help
+ = help: simple hint
+ = note: simple yay
+ = note: format note
+ = note: Some note
+ = note: spanned simple note
+ = note: spanned format note
+ = note: Some note
+
+ --> $DIR/emit.rs:5:13
+ |
+5 | emit_notes!(one, two);
+ | ^^^
diff --git a/third_party/rust/proc-macro-error/tests/ui/explicit_span_range.rs b/third_party/rust/proc-macro-error/tests/ui/explicit_span_range.rs
new file mode 100644
index 0000000000..82bbebcc55
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/explicit_span_range.rs
@@ -0,0 +1,6 @@
+extern crate test_crate;
+use test_crate::*;
+
+explicit_span_range!(one, two, three, four);
+
+fn main() {}
diff --git a/third_party/rust/proc-macro-error/tests/ui/explicit_span_range.stderr b/third_party/rust/proc-macro-error/tests/ui/explicit_span_range.stderr
new file mode 100644
index 0000000000..781a71e76a
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/explicit_span_range.stderr
@@ -0,0 +1,5 @@
+error: explicit SpanRange
+ --> $DIR/explicit_span_range.rs:4:22
+ |
+4 | explicit_span_range!(one, two, three, four);
+ | ^^^^^^^^^^^^^^^
diff --git a/third_party/rust/proc-macro-error/tests/ui/misuse.rs b/third_party/rust/proc-macro-error/tests/ui/misuse.rs
new file mode 100644
index 0000000000..e6d2d24971
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/misuse.rs
@@ -0,0 +1,11 @@
+extern crate proc_macro_error;
+use proc_macro_error::abort;
+
+struct Foo;
+
+#[allow(unused)]
+fn foo() {
+ abort!(Foo, "BOOM");
+}
+
+fn main() {}
diff --git a/third_party/rust/proc-macro-error/tests/ui/misuse.stderr b/third_party/rust/proc-macro-error/tests/ui/misuse.stderr
new file mode 100644
index 0000000000..8eaf6456fd
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/misuse.stderr
@@ -0,0 +1,13 @@
+error[E0599]: no method named `FIRST_ARG_MUST_EITHER_BE_Span_OR_IMPLEMENT_ToTokens_OR_BE_SpanRange` found for reference `&Foo` in the current scope
+ --> $DIR/misuse.rs:8:5
+ |
+4 | struct Foo;
+ | ----------- doesn't satisfy `Foo: quote::to_tokens::ToTokens`
+...
+8 | abort!(Foo, "BOOM");
+ | ^^^^^^^^^^^^^^^^^^^^ method not found in `&Foo`
+ |
+ = note: the method `FIRST_ARG_MUST_EITHER_BE_Span_OR_IMPLEMENT_ToTokens_OR_BE_SpanRange` exists but the following trait bounds were not satisfied:
+ `Foo: quote::to_tokens::ToTokens`
+ which is required by `&Foo: proc_macro_error::__export::ToTokensAsSpanRange`
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/proc-macro-error/tests/ui/multiple_tokens.rs b/third_party/rust/proc-macro-error/tests/ui/multiple_tokens.rs
new file mode 100644
index 0000000000..215928f6f4
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/multiple_tokens.rs
@@ -0,0 +1,6 @@
+extern crate test_crate;
+
+#[test_crate::multiple_tokens]
+type T = ();
+
+fn main() {} \ No newline at end of file
diff --git a/third_party/rust/proc-macro-error/tests/ui/multiple_tokens.stderr b/third_party/rust/proc-macro-error/tests/ui/multiple_tokens.stderr
new file mode 100644
index 0000000000..c6172c6cc6
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/multiple_tokens.stderr
@@ -0,0 +1,5 @@
+error: ...
+ --> $DIR/multiple_tokens.rs:4:1
+ |
+4 | type T = ();
+ | ^^^^^^^^^^^^
diff --git a/third_party/rust/proc-macro-error/tests/ui/not_proc_macro.rs b/third_party/rust/proc-macro-error/tests/ui/not_proc_macro.rs
new file mode 100644
index 0000000000..e241c5cd28
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/not_proc_macro.rs
@@ -0,0 +1,4 @@
+use proc_macro_error::proc_macro_error;
+
+#[proc_macro_error]
+fn main() {}
diff --git a/third_party/rust/proc-macro-error/tests/ui/not_proc_macro.stderr b/third_party/rust/proc-macro-error/tests/ui/not_proc_macro.stderr
new file mode 100644
index 0000000000..f19f01bd8e
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/not_proc_macro.stderr
@@ -0,0 +1,10 @@
+error: #[proc_macro_error] attribute can be used only with procedural macros
+
+ = hint: if you are really sure that #[proc_macro_error] should be applied to this exact function, use #[proc_macro_error(allow_not_macro)]
+
+ --> $DIR/not_proc_macro.rs:3:1
+ |
+3 | #[proc_macro_error]
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/proc-macro-error/tests/ui/option_ext.rs b/third_party/rust/proc-macro-error/tests/ui/option_ext.rs
new file mode 100644
index 0000000000..dfbfc03835
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/option_ext.rs
@@ -0,0 +1,6 @@
+extern crate test_crate;
+use test_crate::*;
+
+option_ext!(one, two);
+
+fn main() {}
diff --git a/third_party/rust/proc-macro-error/tests/ui/option_ext.stderr b/third_party/rust/proc-macro-error/tests/ui/option_ext.stderr
new file mode 100644
index 0000000000..91b151ec2f
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/option_ext.stderr
@@ -0,0 +1,7 @@
+error: Option::expect_or_abort() test
+ --> $DIR/option_ext.rs:4:1
+ |
+4 | option_ext!(one, two);
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/proc-macro-error/tests/ui/proc_macro_hack.rs b/third_party/rust/proc-macro-error/tests/ui/proc_macro_hack.rs
new file mode 100644
index 0000000000..2504bdd401
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/proc_macro_hack.rs
@@ -0,0 +1,10 @@
+// Adapted from https://github.com/dtolnay/proc-macro-hack/blob/master/example/src/main.rs
+// Licensed under either of Apache License, Version 2.0 or MIT license at your option.
+
+use proc_macro_hack_test::add_one;
+
+fn main() {
+ let two = 2;
+ let nine = add_one!(two) + add_one!(2 + 3);
+ println!("nine = {}", nine);
+}
diff --git a/third_party/rust/proc-macro-error/tests/ui/proc_macro_hack.stderr b/third_party/rust/proc-macro-error/tests/ui/proc_macro_hack.stderr
new file mode 100644
index 0000000000..0e984f918d
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/proc_macro_hack.stderr
@@ -0,0 +1,26 @@
+error: BOOM
+ --> $DIR/proc_macro_hack.rs:8:25
+ |
+8 | let nine = add_one!(two) + add_one!(2 + 3);
+ | ^^^
+ |
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: BOOM
+ --> $DIR/proc_macro_hack.rs:8:41
+ |
+8 | let nine = add_one!(two) + add_one!(2 + 3);
+ | ^^^^^
+ |
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: unreachable expression
+ --> $DIR/proc_macro_hack.rs:8:32
+ |
+8 | let nine = add_one!(two) + add_one!(2 + 3);
+ | ------------- ^^^^^^^^^^^^^^^ unreachable expression
+ | |
+ | any code following this expression is unreachable
+ |
+ = note: `#[warn(unreachable_code)]` on by default
+ = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/proc-macro-error/tests/ui/result_ext.rs b/third_party/rust/proc-macro-error/tests/ui/result_ext.rs
new file mode 100644
index 0000000000..bdd560dba9
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/result_ext.rs
@@ -0,0 +1,7 @@
+extern crate test_crate;
+use test_crate::*;
+
+result_unwrap_or_abort!(one, two);
+result_expect_or_abort!(one, two);
+
+fn main() {}
diff --git a/third_party/rust/proc-macro-error/tests/ui/result_ext.stderr b/third_party/rust/proc-macro-error/tests/ui/result_ext.stderr
new file mode 100644
index 0000000000..f2dc0e4235
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/result_ext.stderr
@@ -0,0 +1,11 @@
+error: Result::unwrap_or_abort() test
+ --> $DIR/result_ext.rs:4:25
+ |
+4 | result_unwrap_or_abort!(one, two);
+ | ^^^
+
+error: BOOM: Result::expect_or_abort() test
+ --> $DIR/result_ext.rs:5:25
+ |
+5 | result_expect_or_abort!(one, two);
+ | ^^^
diff --git a/third_party/rust/proc-macro-error/tests/ui/to_tokens_span.rs b/third_party/rust/proc-macro-error/tests/ui/to_tokens_span.rs
new file mode 100644
index 0000000000..a7c3fc976c
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/to_tokens_span.rs
@@ -0,0 +1,6 @@
+extern crate test_crate;
+use test_crate::*;
+
+to_tokens_span!(std::option::Option);
+
+fn main() {}
diff --git a/third_party/rust/proc-macro-error/tests/ui/to_tokens_span.stderr b/third_party/rust/proc-macro-error/tests/ui/to_tokens_span.stderr
new file mode 100644
index 0000000000..b8c4968263
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/to_tokens_span.stderr
@@ -0,0 +1,11 @@
+error: whole type
+ --> $DIR/to_tokens_span.rs:4:17
+ |
+4 | to_tokens_span!(std::option::Option);
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: explicit .span()
+ --> $DIR/to_tokens_span.rs:4:17
+ |
+4 | to_tokens_span!(std::option::Option);
+ | ^^^
diff --git a/third_party/rust/proc-macro-error/tests/ui/unknown_setting.rs b/third_party/rust/proc-macro-error/tests/ui/unknown_setting.rs
new file mode 100644
index 0000000000..d8e58eaf87
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/unknown_setting.rs
@@ -0,0 +1,4 @@
+use proc_macro_error::proc_macro_error;
+
+#[proc_macro_error(allow_not_macro, assert_unwind_safe, trololo)]
+fn main() {}
diff --git a/third_party/rust/proc-macro-error/tests/ui/unknown_setting.stderr b/third_party/rust/proc-macro-error/tests/ui/unknown_setting.stderr
new file mode 100644
index 0000000000..a55de0b31b
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/unknown_setting.stderr
@@ -0,0 +1,5 @@
+error: unknown setting `trololo`, expected one of `assert_unwind_safe`, `allow_not_macro`, `proc_macro_hack`
+ --> $DIR/unknown_setting.rs:3:57
+ |
+3 | #[proc_macro_error(allow_not_macro, assert_unwind_safe, trololo)]
+ | ^^^^^^^
diff --git a/third_party/rust/proc-macro-error/tests/ui/unrelated_panic.rs b/third_party/rust/proc-macro-error/tests/ui/unrelated_panic.rs
new file mode 100644
index 0000000000..c74e3e0623
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/unrelated_panic.rs
@@ -0,0 +1,6 @@
+extern crate test_crate;
+use test_crate::*;
+
+unrelated_panic!();
+
+fn main() {}
diff --git a/third_party/rust/proc-macro-error/tests/ui/unrelated_panic.stderr b/third_party/rust/proc-macro-error/tests/ui/unrelated_panic.stderr
new file mode 100644
index 0000000000..d46d689f2f
--- /dev/null
+++ b/third_party/rust/proc-macro-error/tests/ui/unrelated_panic.stderr
@@ -0,0 +1,7 @@
+error: proc macro panicked
+ --> $DIR/unrelated_panic.rs:4:1
+ |
+4 | unrelated_panic!();
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = help: message: unrelated panic test