diff --git a/.docker/Dockerfile b/.docker/Dockerfile index a80d0ce..7e6eb09 100644 --- a/.docker/Dockerfile +++ b/.docker/Dockerfile @@ -2,8 +2,6 @@ FROM gentoo/stage3:latest COPY ./. / -ENV EGIT_CLONE_TYPE=shallow - RUN getuto RUN emerge-webrsync @@ -16,14 +14,13 @@ RUN emerge \ sys-process/parallel \ net-libs/nodejs - RUN git clone https://jturnerusa.dev/cgit/ebuilds/ /var/db/repos/spawns COPY etc/portage/repos.conf /etc/portage/ RUN mkdir -p /var/cache/distfiles/git3-src && chown portage:portage /var/cache/distfiles/git3-src -RUN emerge =dev-build/meson-9999 +RUN emerge =dev-build/meson-9999::spawns RUN useradd -m gentooligan diff --git a/.docker/etc/portage/package.accept_keywords/jturnerusa b/.docker/etc/portage/package.accept_keywords/jturnerusa new file mode 100644 index 0000000..127913d --- /dev/null +++ b/.docker/etc/portage/package.accept_keywords/jturnerusa @@ -0,0 +1 @@ +sec-keys/jturnerusa \ No newline at end of file diff --git a/.gitignore b/.gitignore index a822699..25b6466 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ /subprojects !/subprojects /subprojects/* -!/subprojects/thiserror \ No newline at end of file +!/subprojects/packagefiles +!/subprojects/*.wrap \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 3f99b99..bb6dcd8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,4 @@ edition = "2024" mon = { git = "https://jturnerusa.dev/cgit/mon/", rev = "67861a4df8a5abdd70651d47cf265b20c41d2acc" } get = { git = "https://jturnerusa.dev/cgit/get/", rev = "cd5f75b65777a855ab010c3137304ac05f2e56b8" } itertools = "0.14.0" -thiserror = "2.0.17" \ No newline at end of file +thiserror = { version = "2.0.17", features = ["derive"] } \ No newline at end of file diff --git a/meson.build b/meson.build index 389720b..1c4f451 100644 --- a/meson.build +++ b/meson.build @@ -7,24 +7,20 @@ project( rustfmt = find_program('rustfmt') -rust = import('rust') fs = import('fs') - -sources = [] - -subdir('src') +rust = import('rust') +cargo = rust.workspace() mon = dependency('mon-0.1-rs') get = dependency('get-0.1-rs') itertools = dependency('itertools-0.14-rs') -thiserror = subproject('thiserror').get_variable('thiserror') +thiserror = dependency('thiserror-2-rs') -gentoo_utils = static_library( - 'gentoo_utils', - 'src/lib.rs', - dependencies: [mon, get, itertools], - link_with: [thiserror], -) +gentoo_utils = cargo.package().library() + +sources = [] + +subdir('src') custom_target( 'rustfmt', @@ -47,8 +43,7 @@ if get_option('docs').enabled() rust.doctest( 'doctests', gentoo_utils, - dependencies: [mon, get, itertools], - link_with: [thiserror], + dependencies: [mon, get, itertools, thiserror], args: ['--nocapture'], ) endif diff --git a/subprojects/packagefiles/syn-2-rs/meson/meson.build b/subprojects/packagefiles/syn-2-rs/meson/meson.build new file mode 100644 index 0000000..02439c2 --- /dev/null +++ b/subprojects/packagefiles/syn-2-rs/meson/meson.build @@ -0,0 +1,3 @@ +extra_args += [ + '--cfg', 'feature="full"', +] diff --git a/subprojects/packagefiles/thiserror-2.0.17-include.patch b/subprojects/packagefiles/thiserror-2.0.17-include.patch new file mode 100644 index 0000000..a061aee --- /dev/null +++ b/subprojects/packagefiles/thiserror-2.0.17-include.patch @@ -0,0 +1,14 @@ +diff --git a/src/lib.rs b/src/lib.rs +index 155272d..7683f4c 100644 +--- a/src/lib.rs ++++ b/src/lib.rs +@@ -288,4 +288,8 @@ pub use thiserror_impl::*; + + mod private; + +-include!(concat!(env!("OUT_DIR"), "/private.rs")); ++#[doc(hidden)] ++pub mod __private_MESON { ++ #[doc(hidden)] ++ pub use crate::private::*; ++} diff --git a/subprojects/thiserror/meson.build b/subprojects/packagefiles/thiserror-2.0.17-rs/meson/meson.build similarity index 55% rename from subprojects/thiserror/meson.build rename to subprojects/packagefiles/thiserror-2.0.17-rs/meson/meson.build index 55d2fb3..a92f73d 100644 --- a/subprojects/thiserror/meson.build +++ b/subprojects/packagefiles/thiserror-2.0.17-rs/meson/meson.build @@ -11,21 +11,12 @@ project( ) rust = import('rust') +cargo = rust.workspace() syn = dependency('syn-2-rs') proc_macro2 = dependency('proc-macro2-1-rs') quote = dependency('quote-1-rs') +impl = cargo.package('impl').proc_macro() -thiserror_proc_macro = rust.proc_macro( - 'thiserror_impl', - 'impl/src/lib.rs', - dependencies: [syn, proc_macro2, quote], -) - -thiserror = static_library( - 'thiserror', - 'src/lib.rs', - rust_args: ['--cfg', 'feature="std"'], - link_with: [thiserror_proc_macro], -) +thiserror = cargo.package().library() diff --git a/subprojects/packagefiles/thiserror-impl-2.0.17-include.patch b/subprojects/packagefiles/thiserror-impl-2.0.17-include.patch new file mode 100644 index 0000000..372862d --- /dev/null +++ b/subprojects/packagefiles/thiserror-impl-2.0.17-include.patch @@ -0,0 +1,13 @@ +diff --git a/impl/src/lib.rs b/impl/src/lib.rs +index 25890f2..1559a41 100644 +--- a/src/lib.rs ++++ b/src/lib.rs +@@ -48,7 +48,7 @@ struct private; + impl ToTokens for private { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + tokens.append(Ident::new( +- concat!("__private", env!("CARGO_PKG_VERSION_PATCH")), ++ concat!("__private", "_MESON"), + Span::call_site(), + )); + } diff --git a/subprojects/thiserror-2-rs.wrap b/subprojects/thiserror-2-rs.wrap new file mode 100644 index 0000000..432d99d --- /dev/null +++ b/subprojects/thiserror-2-rs.wrap @@ -0,0 +1,10 @@ +[wrap-file] +directory = thiserror-2.0.17 +source_url = https://crates.io/api/v1/crates/thiserror/2.0.17/download +source_filename = thiserror-2.0.17.tar.gz +source_hash = f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8 +method = cargo +diff_files = thiserror-2.0.17-include.patch + +# bump this version number on every change to meson.build or the patches: +# v2 diff --git a/subprojects/thiserror-impl-2-rs.wrap b/subprojects/thiserror-impl-2-rs.wrap new file mode 100644 index 0000000..f0eb263 --- /dev/null +++ b/subprojects/thiserror-impl-2-rs.wrap @@ -0,0 +1,10 @@ +[wrap-file] +directory = thiserror-impl-2.0.17 +source_url = https://crates.io/api/v1/crates/thiserror-impl/2.0.17/download +source_filename = thiserror-impl-2.0.17.tar.gz +source_hash = 3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913 +method = cargo +diff_files = thiserror-impl-2.0.17-include.patch + +# bump this version number on every change to meson.build or the patches: +# v2 diff --git a/subprojects/thiserror/.github/FUNDING.yml b/subprojects/thiserror/.github/FUNDING.yml deleted file mode 100644 index 7507077..0000000 --- a/subprojects/thiserror/.github/FUNDING.yml +++ /dev/null @@ -1 +0,0 @@ -github: dtolnay diff --git a/subprojects/thiserror/.github/workflows/ci.yml b/subprojects/thiserror/.github/workflows/ci.yml deleted file mode 100644 index 8320187..0000000 --- a/subprojects/thiserror/.github/workflows/ci.yml +++ /dev/null @@ -1,128 +0,0 @@ -name: CI - -on: - push: - pull_request: - workflow_dispatch: - schedule: [cron: "40 1 * * *"] - -permissions: - contents: read - -env: - RUSTFLAGS: -Dwarnings - -jobs: - pre_ci: - uses: dtolnay/.github/.github/workflows/pre_ci.yml@master - - test: - name: Rust ${{matrix.rust}} - needs: pre_ci - if: needs.pre_ci.outputs.continue - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - rust: [nightly, beta, stable, 1.81.0, 1.76.0] - timeout-minutes: 45 - steps: - - uses: actions/checkout@v5 - - uses: dtolnay/rust-toolchain@master - with: - toolchain: ${{matrix.rust}} - components: rust-src - - name: Enable type layout randomization - run: echo RUSTFLAGS=${RUSTFLAGS}\ -Zrandomize-layout >> $GITHUB_ENV - if: matrix.rust == 'nightly' - - name: Enable nightly-only tests - run: echo RUSTFLAGS=${RUSTFLAGS}\ --cfg=thiserror_nightly_testing >> $GITHUB_ENV - if: matrix.rust == 'nightly' - - run: cargo test --workspace --exclude thiserror_no_std_test - - run: cargo test --manifest-path tests/no-std/Cargo.toml - if: matrix.rust != '1.76.0' - - run: cargo test --no-default-features - - uses: actions/upload-artifact@v4 - if: matrix.rust == 'nightly' && always() - with: - name: Cargo.lock - path: Cargo.lock - continue-on-error: true - - msrv: - name: Rust 1.68.0 - needs: pre_ci - if: needs.pre_ci.outputs.continue - runs-on: ubuntu-latest - timeout-minutes: 45 - steps: - - uses: actions/checkout@v5 - - uses: dtolnay/rust-toolchain@1.68.0 - with: - components: rust-src - - run: cargo check - - minimal: - name: Minimal versions - needs: pre_ci - if: needs.pre_ci.outputs.continue - runs-on: ubuntu-latest - timeout-minutes: 45 - steps: - - uses: actions/checkout@v5 - - uses: dtolnay/rust-toolchain@nightly - - run: cargo generate-lockfile -Z minimal-versions - - run: cargo check --locked - - doc: - name: Documentation - needs: pre_ci - if: needs.pre_ci.outputs.continue - runs-on: ubuntu-latest - timeout-minutes: 45 - env: - RUSTDOCFLAGS: -Dwarnings - steps: - - uses: actions/checkout@v5 - - uses: dtolnay/rust-toolchain@nightly - with: - components: rust-src - - uses: dtolnay/install@cargo-docs-rs - - run: cargo docs-rs - - clippy: - name: Clippy - runs-on: ubuntu-latest - if: github.event_name != 'pull_request' - timeout-minutes: 45 - steps: - - uses: actions/checkout@v5 - - uses: dtolnay/rust-toolchain@nightly - with: - components: clippy, rust-src - - run: cargo clippy --tests --workspace -- -Dclippy::all -Dclippy::pedantic - - miri: - name: Miri - needs: pre_ci - if: needs.pre_ci.outputs.continue - runs-on: ubuntu-latest - timeout-minutes: 45 - steps: - - uses: actions/checkout@v5 - - uses: dtolnay/rust-toolchain@miri - - run: cargo miri setup - - run: cargo miri test - env: - MIRIFLAGS: -Zmiri-strict-provenance - - outdated: - name: Outdated - runs-on: ubuntu-latest - if: github.event_name != 'pull_request' - timeout-minutes: 45 - steps: - - uses: actions/checkout@v5 - - uses: dtolnay/rust-toolchain@stable - - uses: dtolnay/install@cargo-outdated - - run: cargo outdated --workspace --exit-code 1 diff --git a/subprojects/thiserror/.gitignore b/subprojects/thiserror/.gitignore deleted file mode 100644 index e9e2199..0000000 --- a/subprojects/thiserror/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/target/ -/Cargo.lock diff --git a/subprojects/thiserror/Cargo.toml b/subprojects/thiserror/Cargo.toml deleted file mode 100644 index a4364bd..0000000 --- a/subprojects/thiserror/Cargo.toml +++ /dev/null @@ -1,50 +0,0 @@ -[package] -name = "thiserror" -version = "2.0.17" -authors = ["David Tolnay "] -categories = ["rust-patterns", "no-std"] -description = "derive(Error)" -documentation = "https://docs.rs/thiserror" -edition = "2021" -keywords = ["error", "error-handling", "derive"] -license = "MIT OR Apache-2.0" -repository = "https://github.com/dtolnay/thiserror" -rust-version = "1.68" - -[features] -default = ["std"] - -# Std feature enables support for formatting std::path::{Path, PathBuf} -# conveniently in an error message. -# -# #[derive(Error, Debug)] -# #[error("failed to create configuration file {path}")] -# pub struct MyError { -# pub path: PathBuf, -# pub source: std::io::Error, -# } -# -# Without std, this would need to be written #[error("... {}", path.display())]. -std = [] - -[dependencies] -thiserror-impl = { version = "=2.0.17", path = "impl" } - -[dev-dependencies] -anyhow = "1.0.73" -ref-cast = "1.0.18" -rustversion = "1.0.13" -trybuild = { version = "1.0.108", features = ["diff"] } - -[workspace] -members = ["impl", "tests/no-std"] - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] -rustdoc-args = [ - "--generate-link-to-definition", - "--generate-macro-expansion", - "--extern-html-root-url=core=https://doc.rust-lang.org", - "--extern-html-root-url=alloc=https://doc.rust-lang.org", - "--extern-html-root-url=std=https://doc.rust-lang.org", -] diff --git a/subprojects/thiserror/LICENSE-APACHE b/subprojects/thiserror/LICENSE-APACHE deleted file mode 100644 index 1b5ec8b..0000000 --- a/subprojects/thiserror/LICENSE-APACHE +++ /dev/null @@ -1,176 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS diff --git a/subprojects/thiserror/LICENSE-MIT b/subprojects/thiserror/LICENSE-MIT deleted file mode 100644 index 31aa793..0000000 --- a/subprojects/thiserror/LICENSE-MIT +++ /dev/null @@ -1,23 +0,0 @@ -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/subprojects/thiserror/README.md b/subprojects/thiserror/README.md deleted file mode 100644 index f05e2ec..0000000 --- a/subprojects/thiserror/README.md +++ /dev/null @@ -1,238 +0,0 @@ -derive(Error) -============= - -[github](https://github.com/dtolnay/thiserror) -[crates.io](https://crates.io/crates/thiserror) -[docs.rs](https://docs.rs/thiserror) -[build status](https://github.com/dtolnay/thiserror/actions?query=branch%3Amaster) - -This library provides a convenient derive macro for the standard library's -[`std::error::Error`] trait. - -[`std::error::Error`]: https://doc.rust-lang.org/std/error/trait.Error.html - -```toml -[dependencies] -thiserror = "2" -``` - -*Compiler support: requires rustc 1.68+* - -
- -## Example - -```rust -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum DataStoreError { - #[error("data store disconnected")] - Disconnect(#[from] io::Error), - #[error("the data for key `{0}` is not available")] - Redaction(String), - #[error("invalid header (expected {expected:?}, found {found:?})")] - InvalidHeader { - expected: String, - found: String, - }, - #[error("unknown data store error")] - Unknown, -} -``` - -
- -## Details - -- Thiserror deliberately does not appear in your public API. You get the same - thing as if you had written an implementation of `std::error::Error` by hand, - and switching from handwritten impls to thiserror or vice versa is not a - breaking change. - -- Errors may be enums, structs with named fields, tuple structs, or unit - structs. - -- A `Display` impl is generated for your error if you provide `#[error("...")]` - messages on the struct or each variant of your enum, as shown above in the - example. - - The messages support a shorthand for interpolating fields from the error. - - - `#[error("{var}")]` ⟶ `write!("{}", self.var)` - - `#[error("{0}")]` ⟶ `write!("{}", self.0)` - - `#[error("{var:?}")]` ⟶ `write!("{:?}", self.var)` - - `#[error("{0:?}")]` ⟶ `write!("{:?}", self.0)` - - These shorthands can be used together with any additional format args, which - may be arbitrary expressions. For example: - - ```rust - #[derive(Error, Debug)] - pub enum Error { - #[error("invalid rdo_lookahead_frames {0} (expected < {max})", max = i32::MAX)] - InvalidLookahead(u32), - } - ``` - - If one of the additional expression arguments needs to refer to a field of the - struct or enum, then refer to named fields as `.var` and tuple fields as `.0`. - - ```rust - #[derive(Error, Debug)] - pub enum Error { - #[error("first letter must be lowercase but was {:?}", first_char(.0))] - WrongCase(String), - #[error("invalid index {idx}, expected at least {} and at most {}", .limits.lo, .limits.hi)] - OutOfBounds { idx: usize, limits: Limits }, - } - ``` - -- A `From` impl is generated for each variant that contains a `#[from]` - attribute. - - The variant using `#[from]` must not contain any other fields beyond the - source error (and possibly a backtrace — see below). Usually `#[from]` - fields are unnamed, but `#[from]` is allowed on a named field too. - - ```rust - #[derive(Error, Debug)] - pub enum MyError { - Io(#[from] io::Error), - Glob(#[from] globset::Error), - } - ``` - -- The Error trait's `source()` method is implemented to return whichever field - has a `#[source]` attribute or is named `source`, if any. This is for - identifying the underlying lower level error that caused your error. - - The `#[from]` attribute always implies that the same field is `#[source]`, so - you don't ever need to specify both attributes. - - Any error type that implements `std::error::Error` or dereferences to `dyn - std::error::Error` will work as a source. - - ```rust - #[derive(Error, Debug)] - pub struct MyError { - msg: String, - #[source] // optional if field name is `source` - source: anyhow::Error, - } - ``` - -- The Error trait's `provide()` method is implemented to provide whichever field - has a type named `Backtrace`, if any, as a `std::backtrace::Backtrace`. Using - `Backtrace` in errors requires a nightly compiler with Rust version 1.73 or - newer. - - ```rust - use std::backtrace::Backtrace; - - #[derive(Error, Debug)] - pub struct MyError { - msg: String, - backtrace: Backtrace, // automatically detected - } - ``` - -- If a field is both a source (named `source`, or has `#[source]` or `#[from]` - attribute) *and* is marked `#[backtrace]`, then the Error trait's `provide()` - method is forwarded to the source's `provide` so that both layers of the error - share the same backtrace. The `#[backtrace]` attribute requires a nightly - compiler with Rust version 1.73 or newer. - - - ```rust - #[derive(Error, Debug)] - pub enum MyError { - Io { - #[backtrace] - source: io::Error, - }, - } - ``` - -- For variants that use `#[from]` and also contain a `Backtrace` field, a - backtrace is captured from within the `From` impl. - - ```rust - #[derive(Error, Debug)] - pub enum MyError { - Io { - #[from] - source: io::Error, - backtrace: Backtrace, - }, - } - ``` - -- Errors may use `error(transparent)` to forward the source and Display methods - straight through to an underlying error without adding an additional message. - This would be appropriate for enums that need an "anything else" variant. - - ```rust - #[derive(Error, Debug)] - pub enum MyError { - ... - - #[error(transparent)] - Other(#[from] anyhow::Error), // source and Display delegate to anyhow::Error - } - ``` - - Another use case is hiding implementation details of an error representation - behind an opaque error type, so that the representation is able to evolve - without breaking the crate's public API. - - ```rust - // PublicError is public, but opaque and easy to keep compatible. - #[derive(Error, Debug)] - #[error(transparent)] - pub struct PublicError(#[from] ErrorRepr); - - impl PublicError { - // Accessors for anything we do want to expose publicly. - } - - // Private and free to change across minor version of the crate. - #[derive(Error, Debug)] - enum ErrorRepr { - ... - } - ``` - -- See also the [`anyhow`] library for a convenient single error type to use in - application code. - - [`anyhow`]: https://github.com/dtolnay/anyhow - -
- -## Comparison to anyhow - -Use thiserror if you care about designing your own dedicated error type(s) so -that the caller receives exactly the information that you choose in the event of -failure. This most often applies to library-like code. Use [Anyhow] if you don't -care what error type your functions return, you just want it to be easy. This is -common in application-like code. - -[Anyhow]: https://github.com/dtolnay/anyhow - -
- -#### License - - -Licensed under either of Apache License, Version -2.0 or MIT license at your option. - - -
- - -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. - diff --git a/subprojects/thiserror/build/probe.rs b/subprojects/thiserror/build/probe.rs deleted file mode 100644 index ee126d4..0000000 --- a/subprojects/thiserror/build/probe.rs +++ /dev/null @@ -1,33 +0,0 @@ -// This code exercises the surface area that we expect of the Error generic -// member access API. If the current toolchain is able to compile it, then -// thiserror is able to provide backtrace support. - -#![no_std] -#![feature(error_generic_member_access)] - -use core::error::{Error, Request}; -use core::fmt::{self, Debug, Display}; - -struct MyError(Thing); -struct Thing; - -impl Debug for MyError { - fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { - unimplemented!() - } -} - -impl Display for MyError { - fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { - unimplemented!() - } -} - -impl Error for MyError { - fn provide<'a>(&'a self, request: &mut Request<'a>) { - request.provide_ref(&self.0); - } -} - -// Include in sccache cache key. -const _: Option<&str> = option_env!("RUSTC_BOOTSTRAP"); diff --git a/subprojects/thiserror/impl/Cargo.toml b/subprojects/thiserror/impl/Cargo.toml deleted file mode 100644 index 1d7d2f9..0000000 --- a/subprojects/thiserror/impl/Cargo.toml +++ /dev/null @@ -1,28 +0,0 @@ -[package] -name = "thiserror-impl" -version = "2.0.17" -authors = ["David Tolnay "] -description = "Implementation detail of the `thiserror` crate" -edition = "2021" -license = "MIT OR Apache-2.0" -repository = "https://github.com/dtolnay/thiserror" -rust-version = "1.68" - -[lib] -proc-macro = true - -[dependencies] -proc-macro2 = "1.0.74" -quote = "1.0.35" -syn = "2.0.87" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] -rustdoc-args = [ - "--generate-link-to-definition", - "--generate-macro-expansion", - "--extern-html-root-url=core=https://doc.rust-lang.org", - "--extern-html-root-url=alloc=https://doc.rust-lang.org", - "--extern-html-root-url=std=https://doc.rust-lang.org", - "--extern-html-root-url=proc_macro=https://doc.rust-lang.org", -] diff --git a/subprojects/thiserror/impl/LICENSE-APACHE b/subprojects/thiserror/impl/LICENSE-APACHE deleted file mode 120000 index 965b606..0000000 --- a/subprojects/thiserror/impl/LICENSE-APACHE +++ /dev/null @@ -1 +0,0 @@ -../LICENSE-APACHE \ No newline at end of file diff --git a/subprojects/thiserror/impl/LICENSE-MIT b/subprojects/thiserror/impl/LICENSE-MIT deleted file mode 120000 index 76219eb..0000000 --- a/subprojects/thiserror/impl/LICENSE-MIT +++ /dev/null @@ -1 +0,0 @@ -../LICENSE-MIT \ No newline at end of file diff --git a/subprojects/thiserror/impl/src/ast.rs b/subprojects/thiserror/impl/src/ast.rs deleted file mode 100644 index 77f9583..0000000 --- a/subprojects/thiserror/impl/src/ast.rs +++ /dev/null @@ -1,185 +0,0 @@ -use crate::attr::{self, Attrs}; -use crate::generics::ParamsInScope; -use crate::unraw::{IdentUnraw, MemberUnraw}; -use proc_macro2::Span; -use std::fmt::{self, Display}; -use syn::{ - Data, DataEnum, DataStruct, DeriveInput, Error, Fields, Generics, Ident, Index, Result, Type, -}; - -pub enum Input<'a> { - Struct(Struct<'a>), - Enum(Enum<'a>), -} - -pub struct Struct<'a> { - pub attrs: Attrs<'a>, - pub ident: Ident, - pub generics: &'a Generics, - pub fields: Vec>, -} - -pub struct Enum<'a> { - pub attrs: Attrs<'a>, - pub ident: Ident, - pub generics: &'a Generics, - pub variants: Vec>, -} - -pub struct Variant<'a> { - pub original: &'a syn::Variant, - pub attrs: Attrs<'a>, - pub ident: Ident, - pub fields: Vec>, -} - -pub struct Field<'a> { - pub original: &'a syn::Field, - pub attrs: Attrs<'a>, - pub member: MemberUnraw, - pub ty: &'a Type, - pub contains_generic: bool, -} - -#[derive(Copy, Clone)] -pub enum ContainerKind { - Struct, - TupleStruct, - UnitStruct, - StructVariant, - TupleVariant, - UnitVariant, -} - -impl<'a> Input<'a> { - pub fn from_syn(node: &'a DeriveInput) -> Result { - match &node.data { - Data::Struct(data) => Struct::from_syn(node, data).map(Input::Struct), - Data::Enum(data) => Enum::from_syn(node, data).map(Input::Enum), - Data::Union(_) => Err(Error::new_spanned( - node, - "union as errors are not supported", - )), - } - } -} - -impl<'a> Struct<'a> { - fn from_syn(node: &'a DeriveInput, data: &'a DataStruct) -> Result { - let mut attrs = attr::get(&node.attrs)?; - let scope = ParamsInScope::new(&node.generics); - let fields = Field::multiple_from_syn(&data.fields, &scope)?; - if let Some(display) = &mut attrs.display { - let container = ContainerKind::from_struct(data); - display.expand_shorthand(&fields, container)?; - } - Ok(Struct { - attrs, - ident: node.ident.clone(), - generics: &node.generics, - fields, - }) - } -} - -impl<'a> Enum<'a> { - fn from_syn(node: &'a DeriveInput, data: &'a DataEnum) -> Result { - let attrs = attr::get(&node.attrs)?; - let scope = ParamsInScope::new(&node.generics); - let variants = data - .variants - .iter() - .map(|node| { - let mut variant = Variant::from_syn(node, &scope)?; - if variant.attrs.display.is_none() - && variant.attrs.transparent.is_none() - && variant.attrs.fmt.is_none() - { - variant.attrs.display.clone_from(&attrs.display); - variant.attrs.transparent = attrs.transparent; - variant.attrs.fmt.clone_from(&attrs.fmt); - } - if let Some(display) = &mut variant.attrs.display { - let container = ContainerKind::from_variant(node); - display.expand_shorthand(&variant.fields, container)?; - } - Ok(variant) - }) - .collect::>()?; - Ok(Enum { - attrs, - ident: node.ident.clone(), - generics: &node.generics, - variants, - }) - } -} - -impl<'a> Variant<'a> { - fn from_syn(node: &'a syn::Variant, scope: &ParamsInScope<'a>) -> Result { - let attrs = attr::get(&node.attrs)?; - Ok(Variant { - original: node, - attrs, - ident: node.ident.clone(), - fields: Field::multiple_from_syn(&node.fields, scope)?, - }) - } -} - -impl<'a> Field<'a> { - fn multiple_from_syn(fields: &'a Fields, scope: &ParamsInScope<'a>) -> Result> { - fields - .iter() - .enumerate() - .map(|(i, field)| Field::from_syn(i, field, scope)) - .collect() - } - - fn from_syn(i: usize, node: &'a syn::Field, scope: &ParamsInScope<'a>) -> Result { - Ok(Field { - original: node, - attrs: attr::get(&node.attrs)?, - member: match &node.ident { - Some(name) => MemberUnraw::Named(IdentUnraw::new(name.clone())), - None => MemberUnraw::Unnamed(Index { - index: i as u32, - span: Span::call_site(), - }), - }, - ty: &node.ty, - contains_generic: scope.intersects(&node.ty), - }) - } -} - -impl ContainerKind { - fn from_struct(node: &DataStruct) -> Self { - match node.fields { - Fields::Named(_) => ContainerKind::Struct, - Fields::Unnamed(_) => ContainerKind::TupleStruct, - Fields::Unit => ContainerKind::UnitStruct, - } - } - - fn from_variant(node: &syn::Variant) -> Self { - match node.fields { - Fields::Named(_) => ContainerKind::StructVariant, - Fields::Unnamed(_) => ContainerKind::TupleVariant, - Fields::Unit => ContainerKind::UnitVariant, - } - } -} - -impl Display for ContainerKind { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str(match self { - ContainerKind::Struct => "struct", - ContainerKind::TupleStruct => "tuple struct", - ContainerKind::UnitStruct => "unit struct", - ContainerKind::StructVariant => "struct variant", - ContainerKind::TupleVariant => "tuple variant", - ContainerKind::UnitVariant => "unit variant", - }) - } -} diff --git a/subprojects/thiserror/impl/src/attr.rs b/subprojects/thiserror/impl/src/attr.rs deleted file mode 100644 index 7ad83e0..0000000 --- a/subprojects/thiserror/impl/src/attr.rs +++ /dev/null @@ -1,358 +0,0 @@ -use proc_macro2::{Delimiter, Group, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; -use quote::{format_ident, quote, quote_spanned, ToTokens}; -use std::collections::BTreeSet as Set; -use syn::parse::discouraged::Speculative; -use syn::parse::{End, ParseStream}; -use syn::{ - braced, bracketed, parenthesized, token, Attribute, Error, ExprPath, Ident, Index, LitFloat, - LitInt, LitStr, Meta, Result, Token, -}; - -pub struct Attrs<'a> { - pub display: Option>, - pub source: Option>, - pub backtrace: Option<&'a Attribute>, - pub from: Option>, - pub transparent: Option>, - pub fmt: Option>, -} - -#[derive(Clone)] -pub struct Display<'a> { - pub original: &'a Attribute, - pub fmt: LitStr, - pub args: TokenStream, - pub requires_fmt_machinery: bool, - pub has_bonus_display: bool, - pub infinite_recursive: bool, - pub implied_bounds: Set<(usize, Trait)>, - pub bindings: Vec<(Ident, TokenStream)>, -} - -#[derive(Copy, Clone)] -pub struct Source<'a> { - pub original: &'a Attribute, - pub span: Span, -} - -#[derive(Copy, Clone)] -pub struct From<'a> { - pub original: &'a Attribute, - pub span: Span, -} - -#[derive(Copy, Clone)] -pub struct Transparent<'a> { - pub original: &'a Attribute, - pub span: Span, -} - -#[derive(Clone)] -pub struct Fmt<'a> { - pub original: &'a Attribute, - pub path: ExprPath, -} - -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)] -pub enum Trait { - Debug, - Display, - Octal, - LowerHex, - UpperHex, - Pointer, - Binary, - LowerExp, - UpperExp, -} - -pub fn get(input: &[Attribute]) -> Result { - let mut attrs = Attrs { - display: None, - source: None, - backtrace: None, - from: None, - transparent: None, - fmt: None, - }; - - for attr in input { - if attr.path().is_ident("error") { - parse_error_attribute(&mut attrs, attr)?; - } else if attr.path().is_ident("source") { - attr.meta.require_path_only()?; - if attrs.source.is_some() { - return Err(Error::new_spanned(attr, "duplicate #[source] attribute")); - } - let span = (attr.pound_token.span) - .join(attr.bracket_token.span.join()) - .unwrap_or(attr.path().get_ident().unwrap().span()); - attrs.source = Some(Source { - original: attr, - span, - }); - } else if attr.path().is_ident("backtrace") { - attr.meta.require_path_only()?; - if attrs.backtrace.is_some() { - return Err(Error::new_spanned(attr, "duplicate #[backtrace] attribute")); - } - attrs.backtrace = Some(attr); - } else if attr.path().is_ident("from") { - match attr.meta { - Meta::Path(_) => {} - Meta::List(_) | Meta::NameValue(_) => { - // Assume this is meant for derive_more crate or something. - continue; - } - } - if attrs.from.is_some() { - return Err(Error::new_spanned(attr, "duplicate #[from] attribute")); - } - let span = (attr.pound_token.span) - .join(attr.bracket_token.span.join()) - .unwrap_or(attr.path().get_ident().unwrap().span()); - attrs.from = Some(From { - original: attr, - span, - }); - } - } - - Ok(attrs) -} - -fn parse_error_attribute<'a>(attrs: &mut Attrs<'a>, attr: &'a Attribute) -> Result<()> { - mod kw { - syn::custom_keyword!(transparent); - syn::custom_keyword!(fmt); - } - - attr.parse_args_with(|input: ParseStream| { - let lookahead = input.lookahead1(); - let fmt = if lookahead.peek(LitStr) { - input.parse::()? - } else if lookahead.peek(kw::transparent) { - let kw: kw::transparent = input.parse()?; - if attrs.transparent.is_some() { - return Err(Error::new_spanned( - attr, - "duplicate #[error(transparent)] attribute", - )); - } - attrs.transparent = Some(Transparent { - original: attr, - span: kw.span, - }); - return Ok(()); - } else if lookahead.peek(kw::fmt) { - input.parse::()?; - input.parse::()?; - let path: ExprPath = input.parse()?; - if attrs.fmt.is_some() { - return Err(Error::new_spanned( - attr, - "duplicate #[error(fmt = ...)] attribute", - )); - } - attrs.fmt = Some(Fmt { - original: attr, - path, - }); - return Ok(()); - } else { - return Err(lookahead.error()); - }; - - let args = if input.is_empty() || input.peek(Token![,]) && input.peek2(End) { - input.parse::>()?; - TokenStream::new() - } else { - parse_token_expr(input, false)? - }; - - let requires_fmt_machinery = !args.is_empty(); - - let display = Display { - original: attr, - fmt, - args, - requires_fmt_machinery, - has_bonus_display: false, - infinite_recursive: false, - implied_bounds: Set::new(), - bindings: Vec::new(), - }; - if attrs.display.is_some() { - return Err(Error::new_spanned( - attr, - "only one #[error(...)] attribute is allowed", - )); - } - attrs.display = Some(display); - Ok(()) - }) -} - -fn parse_token_expr(input: ParseStream, mut begin_expr: bool) -> Result { - let mut tokens = Vec::new(); - while !input.is_empty() { - if input.peek(token::Group) { - let group: TokenTree = input.parse()?; - tokens.push(group); - begin_expr = false; - continue; - } - - if begin_expr && input.peek(Token![.]) { - if input.peek2(Ident) { - input.parse::()?; - begin_expr = false; - continue; - } else if input.peek2(LitInt) { - input.parse::()?; - let int: Index = input.parse()?; - tokens.push({ - let ident = format_ident!("_{}", int.index, span = int.span); - TokenTree::Ident(ident) - }); - begin_expr = false; - continue; - } else if input.peek2(LitFloat) { - let ahead = input.fork(); - ahead.parse::()?; - let float: LitFloat = ahead.parse()?; - let repr = float.to_string(); - let mut indices = repr.split('.').map(syn::parse_str::); - if let (Some(Ok(first)), Some(Ok(second)), None) = - (indices.next(), indices.next(), indices.next()) - { - input.advance_to(&ahead); - tokens.push({ - let ident = format_ident!("_{}", first, span = float.span()); - TokenTree::Ident(ident) - }); - tokens.push({ - let mut punct = Punct::new('.', Spacing::Alone); - punct.set_span(float.span()); - TokenTree::Punct(punct) - }); - tokens.push({ - let mut literal = Literal::u32_unsuffixed(second.index); - literal.set_span(float.span()); - TokenTree::Literal(literal) - }); - begin_expr = false; - continue; - } - } - } - - begin_expr = input.peek(Token![break]) - || input.peek(Token![continue]) - || input.peek(Token![if]) - || input.peek(Token![in]) - || input.peek(Token![match]) - || input.peek(Token![mut]) - || input.peek(Token![return]) - || input.peek(Token![while]) - || input.peek(Token![+]) - || input.peek(Token![&]) - || input.peek(Token![!]) - || input.peek(Token![^]) - || input.peek(Token![,]) - || input.peek(Token![/]) - || input.peek(Token![=]) - || input.peek(Token![>]) - || input.peek(Token![<]) - || input.peek(Token![|]) - || input.peek(Token![%]) - || input.peek(Token![;]) - || input.peek(Token![*]) - || input.peek(Token![-]); - - let token: TokenTree = if input.peek(token::Paren) { - let content; - let delimiter = parenthesized!(content in input); - let nested = parse_token_expr(&content, true)?; - let mut group = Group::new(Delimiter::Parenthesis, nested); - group.set_span(delimiter.span.join()); - TokenTree::Group(group) - } else if input.peek(token::Brace) { - let content; - let delimiter = braced!(content in input); - let nested = parse_token_expr(&content, true)?; - let mut group = Group::new(Delimiter::Brace, nested); - group.set_span(delimiter.span.join()); - TokenTree::Group(group) - } else if input.peek(token::Bracket) { - let content; - let delimiter = bracketed!(content in input); - let nested = parse_token_expr(&content, true)?; - let mut group = Group::new(Delimiter::Bracket, nested); - group.set_span(delimiter.span.join()); - TokenTree::Group(group) - } else { - input.parse()? - }; - tokens.push(token); - } - Ok(TokenStream::from_iter(tokens)) -} - -impl ToTokens for Display<'_> { - fn to_tokens(&self, tokens: &mut TokenStream) { - if self.infinite_recursive { - let span = self.fmt.span(); - tokens.extend(quote_spanned! {span=> - #[warn(unconditional_recursion)] - fn _fmt() { _fmt() } - }); - } - - let fmt = &self.fmt; - let args = &self.args; - - // Currently `write!(f, "text")` produces less efficient code than - // `f.write_str("text")`. We recognize the case when the format string - // has no braces and no interpolated values, and generate simpler code. - let write = if self.requires_fmt_machinery { - quote! { - ::core::write!(__formatter, #fmt #args) - } - } else { - quote! { - __formatter.write_str(#fmt) - } - }; - - tokens.extend(if self.bindings.is_empty() { - write - } else { - let locals = self.bindings.iter().map(|(local, _value)| local); - let values = self.bindings.iter().map(|(_local, value)| value); - quote! { - match (#(#values,)*) { - (#(#locals,)*) => #write - } - } - }); - } -} - -impl ToTokens for Trait { - fn to_tokens(&self, tokens: &mut TokenStream) { - let trait_name = match self { - Trait::Debug => "Debug", - Trait::Display => "Display", - Trait::Octal => "Octal", - Trait::LowerHex => "LowerHex", - Trait::UpperHex => "UpperHex", - Trait::Pointer => "Pointer", - Trait::Binary => "Binary", - Trait::LowerExp => "LowerExp", - Trait::UpperExp => "UpperExp", - }; - let ident = Ident::new(trait_name, Span::call_site()); - tokens.extend(quote!(::core::fmt::#ident)); - } -} diff --git a/subprojects/thiserror/impl/src/expand.rs b/subprojects/thiserror/impl/src/expand.rs deleted file mode 100644 index 97466dd..0000000 --- a/subprojects/thiserror/impl/src/expand.rs +++ /dev/null @@ -1,584 +0,0 @@ -use crate::ast::{Enum, Field, Input, Struct}; -use crate::attr::Trait; -use crate::fallback; -use crate::generics::InferredBounds; -use crate::private; -use crate::unraw::MemberUnraw; -use proc_macro2::{Ident, Span, TokenStream}; -use quote::{format_ident, quote, quote_spanned, ToTokens}; -use std::collections::BTreeSet as Set; -use syn::{DeriveInput, GenericArgument, PathArguments, Result, Token, Type}; - -pub fn derive(input: &DeriveInput) -> TokenStream { - match try_expand(input) { - Ok(expanded) => expanded, - // If there are invalid attributes in the input, expand to an Error impl - // anyway to minimize spurious secondary errors in other code that uses - // this type as an Error. - Err(error) => fallback::expand(input, error), - } -} - -fn try_expand(input: &DeriveInput) -> Result { - let input = Input::from_syn(input)?; - input.validate()?; - Ok(match input { - Input::Struct(input) => impl_struct(input), - Input::Enum(input) => impl_enum(input), - }) -} - -fn impl_struct(input: Struct) -> TokenStream { - let ty = call_site_ident(&input.ident); - let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); - let mut error_inferred_bounds = InferredBounds::new(); - - let source_body = if let Some(transparent_attr) = &input.attrs.transparent { - let only_field = &input.fields[0]; - if only_field.contains_generic { - error_inferred_bounds.insert(only_field.ty, quote!(::thiserror::#private::Error)); - } - let member = &only_field.member; - Some(quote_spanned! {transparent_attr.span=> - ::thiserror::#private::Error::source(self.#member.as_dyn_error()) - }) - } else if let Some(source_field) = input.source_field() { - let source = &source_field.member; - if source_field.contains_generic { - let ty = unoptional_type(source_field.ty); - error_inferred_bounds.insert(ty, quote!(::thiserror::#private::Error + 'static)); - } - let asref = if type_is_option(source_field.ty) { - Some(quote_spanned!(source.span()=> .as_ref()?)) - } else { - None - }; - let dyn_error = quote_spanned! {source_field.source_span()=> - self.#source #asref.as_dyn_error() - }; - Some(quote! { - ::core::option::Option::Some(#dyn_error) - }) - } else { - None - }; - let source_method = source_body.map(|body| { - quote! { - fn source(&self) -> ::core::option::Option<&(dyn ::thiserror::#private::Error + 'static)> { - use ::thiserror::#private::AsDynError as _; - #body - } - } - }); - - let provide_method = input.backtrace_field().map(|backtrace_field| { - let request = quote!(request); - let backtrace = &backtrace_field.member; - let body = if let Some(source_field) = input.source_field() { - let source = &source_field.member; - let source_provide = if type_is_option(source_field.ty) { - quote_spanned! {source.span()=> - if let ::core::option::Option::Some(source) = &self.#source { - source.thiserror_provide(#request); - } - } - } else { - quote_spanned! {source.span()=> - self.#source.thiserror_provide(#request); - } - }; - let self_provide = if source == backtrace { - None - } else if type_is_option(backtrace_field.ty) { - Some(quote! { - if let ::core::option::Option::Some(backtrace) = &self.#backtrace { - #request.provide_ref::<::thiserror::#private::Backtrace>(backtrace); - } - }) - } else { - Some(quote! { - #request.provide_ref::<::thiserror::#private::Backtrace>(&self.#backtrace); - }) - }; - quote! { - use ::thiserror::#private::ThiserrorProvide as _; - #source_provide - #self_provide - } - } else if type_is_option(backtrace_field.ty) { - quote! { - if let ::core::option::Option::Some(backtrace) = &self.#backtrace { - #request.provide_ref::<::thiserror::#private::Backtrace>(backtrace); - } - } - } else { - quote! { - #request.provide_ref::<::thiserror::#private::Backtrace>(&self.#backtrace); - } - }; - quote! { - fn provide<'_request>(&'_request self, #request: &mut ::core::error::Request<'_request>) { - #body - } - } - }); - - let mut display_implied_bounds = Set::new(); - let display_body = if input.attrs.transparent.is_some() { - let only_field = &input.fields[0].member; - display_implied_bounds.insert((0, Trait::Display)); - Some(quote! { - ::core::fmt::Display::fmt(&self.#only_field, __formatter) - }) - } else if let Some(display) = &input.attrs.display { - display_implied_bounds.clone_from(&display.implied_bounds); - let use_as_display = use_as_display(display.has_bonus_display); - let pat = fields_pat(&input.fields); - Some(quote! { - #use_as_display - #[allow(unused_variables, deprecated)] - let Self #pat = self; - #display - }) - } else { - None - }; - let display_impl = display_body.map(|body| { - let mut display_inferred_bounds = InferredBounds::new(); - for (field, bound) in display_implied_bounds { - let field = &input.fields[field]; - if field.contains_generic { - display_inferred_bounds.insert(field.ty, bound); - } - } - let display_where_clause = display_inferred_bounds.augment_where_clause(input.generics); - quote! { - #[allow(unused_qualifications)] - #[automatically_derived] - impl #impl_generics ::core::fmt::Display for #ty #ty_generics #display_where_clause { - #[allow(clippy::used_underscore_binding)] - fn fmt(&self, __formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - #body - } - } - } - }); - - let from_impl = input.from_field().map(|from_field| { - let span = from_field.attrs.from.unwrap().span; - let backtrace_field = input.distinct_backtrace_field(); - let from = unoptional_type(from_field.ty); - let source_var = Ident::new("source", span); - let body = from_initializer(from_field, backtrace_field, &source_var); - let from_function = quote! { - fn from(#source_var: #from) -> Self { - #ty #body - } - }; - let from_impl = quote_spanned! {span=> - #[automatically_derived] - impl #impl_generics ::core::convert::From<#from> for #ty #ty_generics #where_clause { - #from_function - } - }; - Some(quote! { - #[allow( - deprecated, - unused_qualifications, - clippy::elidable_lifetime_names, - clippy::needless_lifetimes, - )] - #from_impl - }) - }); - - if input.generics.type_params().next().is_some() { - let self_token = ::default(); - error_inferred_bounds.insert(self_token, Trait::Debug); - error_inferred_bounds.insert(self_token, Trait::Display); - } - let error_where_clause = error_inferred_bounds.augment_where_clause(input.generics); - - quote! { - #[allow(unused_qualifications)] - #[automatically_derived] - impl #impl_generics ::thiserror::#private::Error for #ty #ty_generics #error_where_clause { - #source_method - #provide_method - } - #display_impl - #from_impl - } -} - -fn impl_enum(input: Enum) -> TokenStream { - let ty = call_site_ident(&input.ident); - let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); - let mut error_inferred_bounds = InferredBounds::new(); - - let source_method = if input.has_source() { - let arms = input.variants.iter().map(|variant| { - let ident = &variant.ident; - if let Some(transparent_attr) = &variant.attrs.transparent { - let only_field = &variant.fields[0]; - if only_field.contains_generic { - error_inferred_bounds.insert(only_field.ty, quote!(::thiserror::#private::Error)); - } - let member = &only_field.member; - let source = quote_spanned! {transparent_attr.span=> - ::thiserror::#private::Error::source(transparent.as_dyn_error()) - }; - quote! { - #ty::#ident {#member: transparent} => #source, - } - } else if let Some(source_field) = variant.source_field() { - let source = &source_field.member; - if source_field.contains_generic { - let ty = unoptional_type(source_field.ty); - error_inferred_bounds.insert(ty, quote!(::thiserror::#private::Error + 'static)); - } - let asref = if type_is_option(source_field.ty) { - Some(quote_spanned!(source.span()=> .as_ref()?)) - } else { - None - }; - let varsource = quote!(source); - let dyn_error = quote_spanned! {source_field.source_span()=> - #varsource #asref.as_dyn_error() - }; - quote! { - #ty::#ident {#source: #varsource, ..} => ::core::option::Option::Some(#dyn_error), - } - } else { - quote! { - #ty::#ident {..} => ::core::option::Option::None, - } - } - }); - Some(quote! { - fn source(&self) -> ::core::option::Option<&(dyn ::thiserror::#private::Error + 'static)> { - use ::thiserror::#private::AsDynError as _; - #[allow(deprecated)] - match self { - #(#arms)* - } - } - }) - } else { - None - }; - - let provide_method = if input.has_backtrace() { - let request = quote!(request); - let arms = input.variants.iter().map(|variant| { - let ident = &variant.ident; - match (variant.backtrace_field(), variant.source_field()) { - (Some(backtrace_field), Some(source_field)) - if backtrace_field.attrs.backtrace.is_none() => - { - let backtrace = &backtrace_field.member; - let source = &source_field.member; - let varsource = quote!(source); - let source_provide = if type_is_option(source_field.ty) { - quote_spanned! {source.span()=> - if let ::core::option::Option::Some(source) = #varsource { - source.thiserror_provide(#request); - } - } - } else { - quote_spanned! {source.span()=> - #varsource.thiserror_provide(#request); - } - }; - let self_provide = if type_is_option(backtrace_field.ty) { - quote! { - if let ::core::option::Option::Some(backtrace) = backtrace { - #request.provide_ref::<::thiserror::#private::Backtrace>(backtrace); - } - } - } else { - quote! { - #request.provide_ref::<::thiserror::#private::Backtrace>(backtrace); - } - }; - quote! { - #ty::#ident { - #backtrace: backtrace, - #source: #varsource, - .. - } => { - use ::thiserror::#private::ThiserrorProvide as _; - #source_provide - #self_provide - } - } - } - (Some(backtrace_field), Some(source_field)) - if backtrace_field.member == source_field.member => - { - let backtrace = &backtrace_field.member; - let varsource = quote!(source); - let source_provide = if type_is_option(source_field.ty) { - quote_spanned! {backtrace.span()=> - if let ::core::option::Option::Some(source) = #varsource { - source.thiserror_provide(#request); - } - } - } else { - quote_spanned! {backtrace.span()=> - #varsource.thiserror_provide(#request); - } - }; - quote! { - #ty::#ident {#backtrace: #varsource, ..} => { - use ::thiserror::#private::ThiserrorProvide as _; - #source_provide - } - } - } - (Some(backtrace_field), _) => { - let backtrace = &backtrace_field.member; - let body = if type_is_option(backtrace_field.ty) { - quote! { - if let ::core::option::Option::Some(backtrace) = backtrace { - #request.provide_ref::<::thiserror::#private::Backtrace>(backtrace); - } - } - } else { - quote! { - #request.provide_ref::<::thiserror::#private::Backtrace>(backtrace); - } - }; - quote! { - #ty::#ident {#backtrace: backtrace, ..} => { - #body - } - } - } - (None, _) => quote! { - #ty::#ident {..} => {} - }, - } - }); - Some(quote! { - fn provide<'_request>(&'_request self, #request: &mut ::core::error::Request<'_request>) { - #[allow(deprecated)] - match self { - #(#arms)* - } - } - }) - } else { - None - }; - - let display_impl = if input.has_display() { - let mut display_inferred_bounds = InferredBounds::new(); - let has_bonus_display = input.variants.iter().any(|v| { - v.attrs - .display - .as_ref() - .map_or(false, |display| display.has_bonus_display) - }); - let use_as_display = use_as_display(has_bonus_display); - let void_deref = if input.variants.is_empty() { - Some(quote!(*)) - } else { - None - }; - let arms = input.variants.iter().map(|variant| { - let mut display_implied_bounds = Set::new(); - let display = if let Some(display) = &variant.attrs.display { - display_implied_bounds.clone_from(&display.implied_bounds); - display.to_token_stream() - } else if let Some(fmt) = &variant.attrs.fmt { - let fmt_path = &fmt.path; - let vars = variant.fields.iter().map(|field| match &field.member { - MemberUnraw::Named(ident) => ident.to_local(), - MemberUnraw::Unnamed(index) => format_ident!("_{}", index), - }); - quote!(#fmt_path(#(#vars,)* __formatter)) - } else { - let only_field = match &variant.fields[0].member { - MemberUnraw::Named(ident) => ident.to_local(), - MemberUnraw::Unnamed(index) => format_ident!("_{}", index), - }; - display_implied_bounds.insert((0, Trait::Display)); - quote!(::core::fmt::Display::fmt(#only_field, __formatter)) - }; - for (field, bound) in display_implied_bounds { - let field = &variant.fields[field]; - if field.contains_generic { - display_inferred_bounds.insert(field.ty, bound); - } - } - let ident = &variant.ident; - let pat = fields_pat(&variant.fields); - quote! { - #ty::#ident #pat => #display - } - }); - let arms = arms.collect::>(); - let display_where_clause = display_inferred_bounds.augment_where_clause(input.generics); - Some(quote! { - #[allow(unused_qualifications)] - #[automatically_derived] - impl #impl_generics ::core::fmt::Display for #ty #ty_generics #display_where_clause { - fn fmt(&self, __formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - #use_as_display - #[allow(unused_variables, deprecated, clippy::used_underscore_binding)] - match #void_deref self { - #(#arms,)* - } - } - } - }) - } else { - None - }; - - let from_impls = input.variants.iter().filter_map(|variant| { - let from_field = variant.from_field()?; - let span = from_field.attrs.from.unwrap().span; - let backtrace_field = variant.distinct_backtrace_field(); - let variant = &variant.ident; - let from = unoptional_type(from_field.ty); - let source_var = Ident::new("source", span); - let body = from_initializer(from_field, backtrace_field, &source_var); - let from_function = quote! { - fn from(#source_var: #from) -> Self { - #ty::#variant #body - } - }; - let from_impl = quote_spanned! {span=> - #[automatically_derived] - impl #impl_generics ::core::convert::From<#from> for #ty #ty_generics #where_clause { - #from_function - } - }; - Some(quote! { - #[allow( - deprecated, - unused_qualifications, - clippy::elidable_lifetime_names, - clippy::needless_lifetimes, - )] - #from_impl - }) - }); - - if input.generics.type_params().next().is_some() { - let self_token = ::default(); - error_inferred_bounds.insert(self_token, Trait::Debug); - error_inferred_bounds.insert(self_token, Trait::Display); - } - let error_where_clause = error_inferred_bounds.augment_where_clause(input.generics); - - quote! { - #[allow(unused_qualifications)] - #[automatically_derived] - impl #impl_generics ::thiserror::#private::Error for #ty #ty_generics #error_where_clause { - #source_method - #provide_method - } - #display_impl - #(#from_impls)* - } -} - -// Create an ident with which we can expand `impl Trait for #ident {}` on a -// deprecated type without triggering deprecation warning on the generated impl. -pub(crate) fn call_site_ident(ident: &Ident) -> Ident { - let mut ident = ident.clone(); - ident.set_span(ident.span().resolved_at(Span::call_site())); - ident -} - -fn fields_pat(fields: &[Field]) -> TokenStream { - let mut members = fields.iter().map(|field| &field.member).peekable(); - match members.peek() { - Some(MemberUnraw::Named(_)) => quote!({ #(#members),* }), - Some(MemberUnraw::Unnamed(_)) => { - let vars = members.map(|member| match member { - MemberUnraw::Unnamed(index) => format_ident!("_{}", index), - MemberUnraw::Named(_) => unreachable!(), - }); - quote!((#(#vars),*)) - } - None => quote!({}), - } -} - -fn use_as_display(needs_as_display: bool) -> Option { - if needs_as_display { - Some(quote! { - use ::thiserror::#private::AsDisplay as _; - }) - } else { - None - } -} - -fn from_initializer( - from_field: &Field, - backtrace_field: Option<&Field>, - source_var: &Ident, -) -> TokenStream { - let from_member = &from_field.member; - let some_source = if type_is_option(from_field.ty) { - quote!(::core::option::Option::Some(#source_var)) - } else { - quote!(#source_var) - }; - let backtrace = backtrace_field.map(|backtrace_field| { - let backtrace_member = &backtrace_field.member; - if type_is_option(backtrace_field.ty) { - quote! { - #backtrace_member: ::core::option::Option::Some(::thiserror::#private::Backtrace::capture()), - } - } else { - quote! { - #backtrace_member: ::core::convert::From::from(::thiserror::#private::Backtrace::capture()), - } - } - }); - quote!({ - #from_member: #some_source, - #backtrace - }) -} - -fn type_is_option(ty: &Type) -> bool { - type_parameter_of_option(ty).is_some() -} - -fn unoptional_type(ty: &Type) -> TokenStream { - let unoptional = type_parameter_of_option(ty).unwrap_or(ty); - quote!(#unoptional) -} - -fn type_parameter_of_option(ty: &Type) -> Option<&Type> { - let path = match ty { - Type::Path(ty) => &ty.path, - _ => return None, - }; - - let last = path.segments.last().unwrap(); - if last.ident != "Option" { - return None; - } - - let bracketed = match &last.arguments { - PathArguments::AngleBracketed(bracketed) => bracketed, - _ => return None, - }; - - if bracketed.args.len() != 1 { - return None; - } - - match &bracketed.args[0] { - GenericArgument::Type(arg) => Some(arg), - _ => None, - } -} diff --git a/subprojects/thiserror/impl/src/fallback.rs b/subprojects/thiserror/impl/src/fallback.rs deleted file mode 100644 index 9914aa5..0000000 --- a/subprojects/thiserror/impl/src/fallback.rs +++ /dev/null @@ -1,33 +0,0 @@ -use crate::expand::call_site_ident; -use crate::private; -use proc_macro2::TokenStream; -use quote::quote; -use syn::DeriveInput; - -pub(crate) fn expand(input: &DeriveInput, error: syn::Error) -> TokenStream { - let ty = call_site_ident(&input.ident); - let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); - - let error = error.to_compile_error(); - - quote! { - #error - - #[allow(unused_qualifications)] - #[automatically_derived] - impl #impl_generics ::thiserror::#private::Error for #ty #ty_generics #where_clause - where - // Work around trivial bounds being unstable. - // https://github.com/rust-lang/rust/issues/48214 - for<'workaround> #ty #ty_generics: ::core::fmt::Debug, - {} - - #[allow(unused_qualifications)] - #[automatically_derived] - impl #impl_generics ::core::fmt::Display for #ty #ty_generics #where_clause { - fn fmt(&self, __formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - ::core::unreachable!() - } - } - } -} diff --git a/subprojects/thiserror/impl/src/fmt.rs b/subprojects/thiserror/impl/src/fmt.rs deleted file mode 100644 index 2988ca3..0000000 --- a/subprojects/thiserror/impl/src/fmt.rs +++ /dev/null @@ -1,323 +0,0 @@ -use crate::ast::{ContainerKind, Field}; -use crate::attr::{Display, Trait}; -use crate::private; -use crate::scan_expr::scan_expr; -use crate::unraw::{IdentUnraw, MemberUnraw}; -use proc_macro2::{Delimiter, TokenStream, TokenTree}; -use quote::{format_ident, quote, quote_spanned, ToTokens as _}; -use std::collections::{BTreeSet, HashMap}; -use std::iter; -use syn::ext::IdentExt; -use syn::parse::discouraged::Speculative; -use syn::parse::{Error, ParseStream, Parser, Result}; -use syn::{Expr, Ident, Index, LitStr, Token}; - -impl Display<'_> { - pub fn expand_shorthand(&mut self, fields: &[Field], container: ContainerKind) -> Result<()> { - let raw_args = self.args.clone(); - let FmtArguments { - named: user_named_args, - first_unnamed, - } = explicit_named_args.parse2(raw_args).unwrap(); - - let mut member_index = HashMap::new(); - let mut extra_positional_arguments_allowed = true; - for (i, field) in fields.iter().enumerate() { - member_index.insert(&field.member, i); - extra_positional_arguments_allowed &= matches!(&field.member, MemberUnraw::Named(_)); - } - - let span = self.fmt.span(); - let fmt = self.fmt.value(); - let mut read = fmt.as_str(); - let mut out = String::new(); - let mut has_bonus_display = false; - let mut infinite_recursive = false; - let mut implied_bounds = BTreeSet::new(); - let mut bindings = Vec::new(); - let mut macro_named_args = BTreeSet::new(); - - self.requires_fmt_machinery = self.requires_fmt_machinery || fmt.contains('}'); - - while let Some(brace) = read.find('{') { - self.requires_fmt_machinery = true; - out += &read[..brace + 1]; - read = &read[brace + 1..]; - if read.starts_with('{') { - out.push('{'); - read = &read[1..]; - continue; - } - let next = match read.chars().next() { - Some(next) => next, - None => return Ok(()), - }; - let member = match next { - '0'..='9' => { - let int = take_int(&mut read); - if !extra_positional_arguments_allowed { - if let Some(first_unnamed) = &first_unnamed { - let msg = format!("ambiguous reference to positional arguments by number in a {container}; change this to a named argument"); - return Err(Error::new_spanned(first_unnamed, msg)); - } - } - match int.parse::() { - Ok(index) => MemberUnraw::Unnamed(Index { index, span }), - Err(_) => return Ok(()), - } - } - 'a'..='z' | 'A'..='Z' | '_' => { - if read.starts_with("r#") { - continue; - } - let repr = take_ident(&mut read); - if repr == "_" { - // Invalid. Let rustc produce the diagnostic. - out += repr; - continue; - } - let ident = IdentUnraw::new(Ident::new(repr, span)); - if user_named_args.contains(&ident) { - // Refers to a named argument written by the user, not to field. - out += repr; - continue; - } - MemberUnraw::Named(ident) - } - _ => continue, - }; - let end_spec = match read.find('}') { - Some(end_spec) => end_spec, - None => return Ok(()), - }; - let mut bonus_display = false; - let bound = match read[..end_spec].chars().next_back() { - Some('?') => Trait::Debug, - Some('o') => Trait::Octal, - Some('x') => Trait::LowerHex, - Some('X') => Trait::UpperHex, - Some('p') => Trait::Pointer, - Some('b') => Trait::Binary, - Some('e') => Trait::LowerExp, - Some('E') => Trait::UpperExp, - Some(_) => Trait::Display, - None => { - bonus_display = true; - has_bonus_display = true; - Trait::Display - } - }; - infinite_recursive |= member == *"self" && bound == Trait::Display; - let field = match member_index.get(&member) { - Some(&field) => field, - None => { - out += &member.to_string(); - continue; - } - }; - implied_bounds.insert((field, bound)); - let formatvar_prefix = if bonus_display { - "__display" - } else if bound == Trait::Pointer { - "__pointer" - } else { - "__field" - }; - let mut formatvar = IdentUnraw::new(match &member { - MemberUnraw::Unnamed(index) => format_ident!("{}{}", formatvar_prefix, index), - MemberUnraw::Named(ident) => { - format_ident!("{}_{}", formatvar_prefix, ident.to_string()) - } - }); - while user_named_args.contains(&formatvar) { - formatvar = IdentUnraw::new(format_ident!("_{}", formatvar.to_string())); - } - formatvar.set_span(span); - out += &formatvar.to_string(); - if !macro_named_args.insert(formatvar.clone()) { - // Already added to bindings by a previous use. - continue; - } - let mut binding_value = match &member { - MemberUnraw::Unnamed(index) => format_ident!("_{}", index), - MemberUnraw::Named(ident) => ident.to_local(), - }; - binding_value.set_span(span.resolved_at(fields[field].member.span())); - let wrapped_binding_value = if bonus_display { - quote_spanned!(span=> #binding_value.as_display()) - } else if bound == Trait::Pointer { - quote!(::thiserror::#private::Var(#binding_value)) - } else { - binding_value.into_token_stream() - }; - bindings.push((formatvar.to_local(), wrapped_binding_value)); - } - - out += read; - self.fmt = LitStr::new(&out, self.fmt.span()); - self.has_bonus_display = has_bonus_display; - self.infinite_recursive = infinite_recursive; - self.implied_bounds = implied_bounds; - self.bindings = bindings; - Ok(()) - } -} - -struct FmtArguments { - named: BTreeSet, - first_unnamed: Option, -} - -#[allow(clippy::unnecessary_wraps)] -fn explicit_named_args(input: ParseStream) -> Result { - let ahead = input.fork(); - if let Ok(set) = try_explicit_named_args(&ahead) { - input.advance_to(&ahead); - return Ok(set); - } - - let ahead = input.fork(); - if let Ok(set) = fallback_explicit_named_args(&ahead) { - input.advance_to(&ahead); - return Ok(set); - } - - input.parse::().unwrap(); - Ok(FmtArguments { - named: BTreeSet::new(), - first_unnamed: None, - }) -} - -fn try_explicit_named_args(input: ParseStream) -> Result { - let mut syn_full = None; - let mut args = FmtArguments { - named: BTreeSet::new(), - first_unnamed: None, - }; - - while !input.is_empty() { - input.parse::()?; - if input.is_empty() { - break; - } - - let mut begin_unnamed = None; - if input.peek(Ident::peek_any) && input.peek2(Token![=]) && !input.peek2(Token![==]) { - let ident: IdentUnraw = input.parse()?; - input.parse::()?; - args.named.insert(ident); - } else { - begin_unnamed = Some(input.fork()); - } - - let ahead = input.fork(); - if *syn_full.get_or_insert_with(is_syn_full) && ahead.parse::().is_ok() { - input.advance_to(&ahead); - } else { - scan_expr(input)?; - } - - if let Some(begin_unnamed) = begin_unnamed { - if args.first_unnamed.is_none() { - args.first_unnamed = Some(between(&begin_unnamed, input)); - } - } - } - - Ok(args) -} - -fn fallback_explicit_named_args(input: ParseStream) -> Result { - let mut args = FmtArguments { - named: BTreeSet::new(), - first_unnamed: None, - }; - - while !input.is_empty() { - if input.peek(Token![,]) - && input.peek2(Ident::peek_any) - && input.peek3(Token![=]) - && !input.peek3(Token![==]) - { - input.parse::()?; - let ident: IdentUnraw = input.parse()?; - input.parse::()?; - args.named.insert(ident); - } else { - input.parse::()?; - } - } - - Ok(args) -} - -fn is_syn_full() -> bool { - // Expr::Block contains syn::Block which contains Vec. In the - // current version of Syn, syn::Stmt is exhaustive and could only plausibly - // represent `trait Trait {}` in Stmt::Item which contains syn::Item. Most - // of the point of syn's non-"full" mode is to avoid compiling Item and the - // entire expansive syntax tree it comprises. So the following expression - // being parsed to Expr::Block is a reliable indication that "full" is - // enabled. - let test = quote!({ - trait Trait {} - }); - match syn::parse2(test) { - Ok(Expr::Verbatim(_)) | Err(_) => false, - Ok(Expr::Block(_)) => true, - Ok(_) => unreachable!(), - } -} - -fn take_int<'a>(read: &mut &'a str) -> &'a str { - let mut int_len = 0; - for ch in read.chars() { - match ch { - '0'..='9' => int_len += 1, - _ => break, - } - } - let (int, rest) = read.split_at(int_len); - *read = rest; - int -} - -fn take_ident<'a>(read: &mut &'a str) -> &'a str { - let mut ident_len = 0; - for ch in read.chars() { - match ch { - 'a'..='z' | 'A'..='Z' | '0'..='9' | '_' => ident_len += 1, - _ => break, - } - } - let (ident, rest) = read.split_at(ident_len); - *read = rest; - ident -} - -fn between<'a>(begin: ParseStream<'a>, end: ParseStream<'a>) -> TokenStream { - let end = end.cursor(); - let mut cursor = begin.cursor(); - let mut tokens = TokenStream::new(); - - while cursor < end { - let (tt, next) = cursor.token_tree().unwrap(); - - if end < next { - if let Some((inside, _span, _after)) = cursor.group(Delimiter::None) { - cursor = inside; - continue; - } - if tokens.is_empty() { - tokens.extend(iter::once(tt)); - } - break; - } - - tokens.extend(iter::once(tt)); - cursor = next; - } - - tokens -} diff --git a/subprojects/thiserror/impl/src/generics.rs b/subprojects/thiserror/impl/src/generics.rs deleted file mode 100644 index 26fe0a9..0000000 --- a/subprojects/thiserror/impl/src/generics.rs +++ /dev/null @@ -1,83 +0,0 @@ -use proc_macro2::TokenStream; -use quote::ToTokens; -use std::collections::btree_map::Entry; -use std::collections::{BTreeMap as Map, BTreeSet as Set}; -use syn::punctuated::Punctuated; -use syn::{parse_quote, GenericArgument, Generics, Ident, PathArguments, Token, Type, WhereClause}; - -pub struct ParamsInScope<'a> { - names: Set<&'a Ident>, -} - -impl<'a> ParamsInScope<'a> { - pub fn new(generics: &'a Generics) -> Self { - ParamsInScope { - names: generics.type_params().map(|param| ¶m.ident).collect(), - } - } - - pub fn intersects(&self, ty: &Type) -> bool { - let mut found = false; - crawl(self, ty, &mut found); - found - } -} - -fn crawl(in_scope: &ParamsInScope, ty: &Type, found: &mut bool) { - if let Type::Path(ty) = ty { - if let Some(qself) = &ty.qself { - crawl(in_scope, &qself.ty, found); - } else { - let front = ty.path.segments.first().unwrap(); - if front.arguments.is_none() && in_scope.names.contains(&front.ident) { - *found = true; - } - } - for segment in &ty.path.segments { - if let PathArguments::AngleBracketed(arguments) = &segment.arguments { - for arg in &arguments.args { - if let GenericArgument::Type(ty) = arg { - crawl(in_scope, ty, found); - } - } - } - } - } -} - -pub struct InferredBounds { - bounds: Map, Punctuated)>, - order: Vec, -} - -impl InferredBounds { - pub fn new() -> Self { - InferredBounds { - bounds: Map::new(), - order: Vec::new(), - } - } - - pub fn insert(&mut self, ty: impl ToTokens, bound: impl ToTokens) { - let ty = ty.to_token_stream(); - let bound = bound.to_token_stream(); - let entry = self.bounds.entry(ty.to_string()); - if let Entry::Vacant(_) = entry { - self.order.push(ty); - } - let (set, tokens) = entry.or_default(); - if set.insert(bound.to_string()) { - tokens.push(bound); - } - } - - pub fn augment_where_clause(&self, generics: &Generics) -> WhereClause { - let mut generics = generics.clone(); - let where_clause = generics.make_where_clause(); - for ty in &self.order { - let (_set, bounds) = &self.bounds[&ty.to_string()]; - where_clause.predicates.push(parse_quote!(#ty: #bounds)); - } - generics.where_clause.unwrap() - } -} diff --git a/subprojects/thiserror/impl/src/lib.rs b/subprojects/thiserror/impl/src/lib.rs deleted file mode 100644 index 2ff054b..0000000 --- a/subprojects/thiserror/impl/src/lib.rs +++ /dev/null @@ -1,52 +0,0 @@ -#![allow( - clippy::blocks_in_conditions, - clippy::cast_lossless, - clippy::cast_possible_truncation, - clippy::enum_glob_use, - clippy::expl_impl_clone_on_copy, // https://github.com/rust-lang/rust-clippy/issues/15842 - clippy::manual_find, - clippy::manual_let_else, - clippy::manual_map, - clippy::map_unwrap_or, - clippy::module_name_repetitions, - clippy::needless_pass_by_value, - clippy::range_plus_one, - clippy::single_match_else, - clippy::struct_field_names, - clippy::too_many_lines, - clippy::wrong_self_convention -)] -#![allow(unknown_lints, mismatched_lifetime_syntaxes)] - -extern crate proc_macro; - -mod ast; -mod attr; -mod expand; -mod fallback; -mod fmt; -mod generics; -mod prop; -mod scan_expr; -mod unraw; -mod valid; - -use proc_macro::TokenStream; -use proc_macro2::{Ident, Span}; -use quote::{ToTokens, TokenStreamExt as _}; -use syn::{DeriveInput, parse_macro_input}; - -#[proc_macro_derive(Error, attributes(backtrace, error, from, source))] -pub fn derive_error(input: TokenStream) -> TokenStream { - let input = parse_macro_input!(input as DeriveInput); - expand::derive(&input).into() -} - -#[allow(non_camel_case_types)] -struct private; - -impl ToTokens for private { - fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { - tokens.append(Ident::new(concat!("__private"), Span::call_site())); - } -} diff --git a/subprojects/thiserror/impl/src/prop.rs b/subprojects/thiserror/impl/src/prop.rs deleted file mode 100644 index 0a101fc..0000000 --- a/subprojects/thiserror/impl/src/prop.rs +++ /dev/null @@ -1,148 +0,0 @@ -use crate::ast::{Enum, Field, Struct, Variant}; -use crate::unraw::MemberUnraw; -use proc_macro2::Span; -use syn::Type; - -impl Struct<'_> { - pub(crate) fn from_field(&self) -> Option<&Field> { - from_field(&self.fields) - } - - pub(crate) fn source_field(&self) -> Option<&Field> { - source_field(&self.fields) - } - - pub(crate) fn backtrace_field(&self) -> Option<&Field> { - backtrace_field(&self.fields) - } - - pub(crate) fn distinct_backtrace_field(&self) -> Option<&Field> { - let backtrace_field = self.backtrace_field()?; - distinct_backtrace_field(backtrace_field, self.from_field()) - } -} - -impl Enum<'_> { - pub(crate) fn has_source(&self) -> bool { - self.variants - .iter() - .any(|variant| variant.source_field().is_some() || variant.attrs.transparent.is_some()) - } - - pub(crate) fn has_backtrace(&self) -> bool { - self.variants - .iter() - .any(|variant| variant.backtrace_field().is_some()) - } - - pub(crate) fn has_display(&self) -> bool { - self.attrs.display.is_some() - || self.attrs.transparent.is_some() - || self.attrs.fmt.is_some() - || self - .variants - .iter() - .any(|variant| variant.attrs.display.is_some() || variant.attrs.fmt.is_some()) - || self - .variants - .iter() - .all(|variant| variant.attrs.transparent.is_some()) - } -} - -impl Variant<'_> { - pub(crate) fn from_field(&self) -> Option<&Field> { - from_field(&self.fields) - } - - pub(crate) fn source_field(&self) -> Option<&Field> { - source_field(&self.fields) - } - - pub(crate) fn backtrace_field(&self) -> Option<&Field> { - backtrace_field(&self.fields) - } - - pub(crate) fn distinct_backtrace_field(&self) -> Option<&Field> { - let backtrace_field = self.backtrace_field()?; - distinct_backtrace_field(backtrace_field, self.from_field()) - } -} - -impl Field<'_> { - pub(crate) fn is_backtrace(&self) -> bool { - type_is_backtrace(self.ty) - } - - pub(crate) fn source_span(&self) -> Span { - if let Some(source_attr) = &self.attrs.source { - source_attr.span - } else if let Some(from_attr) = &self.attrs.from { - from_attr.span - } else { - self.member.span() - } - } -} - -fn from_field<'a, 'b>(fields: &'a [Field<'b>]) -> Option<&'a Field<'b>> { - for field in fields { - if field.attrs.from.is_some() { - return Some(field); - } - } - None -} - -fn source_field<'a, 'b>(fields: &'a [Field<'b>]) -> Option<&'a Field<'b>> { - for field in fields { - if field.attrs.from.is_some() || field.attrs.source.is_some() { - return Some(field); - } - } - for field in fields { - match &field.member { - MemberUnraw::Named(ident) if ident == "source" => return Some(field), - _ => {} - } - } - None -} - -fn backtrace_field<'a, 'b>(fields: &'a [Field<'b>]) -> Option<&'a Field<'b>> { - for field in fields { - if field.attrs.backtrace.is_some() { - return Some(field); - } - } - for field in fields { - if field.is_backtrace() { - return Some(field); - } - } - None -} - -// The #[backtrace] field, if it is not the same as the #[from] field. -fn distinct_backtrace_field<'a, 'b>( - backtrace_field: &'a Field<'b>, - from_field: Option<&Field>, -) -> Option<&'a Field<'b>> { - if from_field.map_or(false, |from_field| { - from_field.member == backtrace_field.member - }) { - None - } else { - Some(backtrace_field) - } -} - -fn type_is_backtrace(ty: &Type) -> bool { - let path = match ty { - Type::Path(ty) => &ty.path, - _ => return false, - }; - - let last = path.segments.last().unwrap(); - last.ident == "Backtrace" && last.arguments.is_empty() -} diff --git a/subprojects/thiserror/impl/src/scan_expr.rs b/subprojects/thiserror/impl/src/scan_expr.rs deleted file mode 100644 index 155b5b6..0000000 --- a/subprojects/thiserror/impl/src/scan_expr.rs +++ /dev/null @@ -1,264 +0,0 @@ -use self::{Action::*, Input::*}; -use proc_macro2::{Delimiter, Ident, Spacing, TokenTree}; -use syn::parse::{ParseStream, Result}; -use syn::{AngleBracketedGenericArguments, BinOp, Expr, ExprPath, Lifetime, Lit, Token, Type}; - -enum Input { - Keyword(&'static str), - Punct(&'static str), - ConsumeAny, - ConsumeBinOp, - ConsumeBrace, - ConsumeDelimiter, - ConsumeIdent, - ConsumeLifetime, - ConsumeLiteral, - ConsumeNestedBrace, - ExpectPath, - ExpectTurbofish, - ExpectType, - CanBeginExpr, - Otherwise, - Empty, -} - -enum Action { - SetState(&'static [(Input, Action)]), - IncDepth, - DecDepth, - Finish, -} - -static INIT: [(Input, Action); 28] = [ - (ConsumeDelimiter, SetState(&POSTFIX)), - (Keyword("async"), SetState(&ASYNC)), - (Keyword("break"), SetState(&BREAK_LABEL)), - (Keyword("const"), SetState(&CONST)), - (Keyword("continue"), SetState(&CONTINUE)), - (Keyword("for"), SetState(&FOR)), - (Keyword("if"), IncDepth), - (Keyword("let"), SetState(&PATTERN)), - (Keyword("loop"), SetState(&BLOCK)), - (Keyword("match"), IncDepth), - (Keyword("move"), SetState(&CLOSURE)), - (Keyword("return"), SetState(&RETURN)), - (Keyword("static"), SetState(&CLOSURE)), - (Keyword("unsafe"), SetState(&BLOCK)), - (Keyword("while"), IncDepth), - (Keyword("yield"), SetState(&RETURN)), - (Keyword("_"), SetState(&POSTFIX)), - (Punct("!"), SetState(&INIT)), - (Punct("#"), SetState(&[(ConsumeDelimiter, SetState(&INIT))])), - (Punct("&"), SetState(&REFERENCE)), - (Punct("*"), SetState(&INIT)), - (Punct("-"), SetState(&INIT)), - (Punct("..="), SetState(&INIT)), - (Punct(".."), SetState(&RANGE)), - (Punct("|"), SetState(&CLOSURE_ARGS)), - (ConsumeLifetime, SetState(&[(Punct(":"), SetState(&INIT))])), - (ConsumeLiteral, SetState(&POSTFIX)), - (ExpectPath, SetState(&PATH)), -]; - -static POSTFIX: [(Input, Action); 10] = [ - (Keyword("as"), SetState(&[(ExpectType, SetState(&POSTFIX))])), - (Punct("..="), SetState(&INIT)), - (Punct(".."), SetState(&RANGE)), - (Punct("."), SetState(&DOT)), - (Punct("?"), SetState(&POSTFIX)), - (ConsumeBinOp, SetState(&INIT)), - (Punct("="), SetState(&INIT)), - (ConsumeNestedBrace, SetState(&IF_THEN)), - (ConsumeDelimiter, SetState(&POSTFIX)), - (Empty, Finish), -]; - -static ASYNC: [(Input, Action); 3] = [ - (Keyword("move"), SetState(&ASYNC)), - (Punct("|"), SetState(&CLOSURE_ARGS)), - (ConsumeBrace, SetState(&POSTFIX)), -]; - -static BLOCK: [(Input, Action); 1] = [(ConsumeBrace, SetState(&POSTFIX))]; - -static BREAK_LABEL: [(Input, Action); 2] = [ - (ConsumeLifetime, SetState(&BREAK_VALUE)), - (Otherwise, SetState(&BREAK_VALUE)), -]; - -static BREAK_VALUE: [(Input, Action); 3] = [ - (ConsumeNestedBrace, SetState(&IF_THEN)), - (CanBeginExpr, SetState(&INIT)), - (Otherwise, SetState(&POSTFIX)), -]; - -static CLOSURE: [(Input, Action); 6] = [ - (Keyword("async"), SetState(&CLOSURE)), - (Keyword("move"), SetState(&CLOSURE)), - (Punct(","), SetState(&CLOSURE)), - (Punct(">"), SetState(&CLOSURE)), - (Punct("|"), SetState(&CLOSURE_ARGS)), - (ConsumeLifetime, SetState(&CLOSURE)), -]; - -static CLOSURE_ARGS: [(Input, Action); 2] = [ - (Punct("|"), SetState(&CLOSURE_RET)), - (ConsumeAny, SetState(&CLOSURE_ARGS)), -]; - -static CLOSURE_RET: [(Input, Action); 2] = [ - (Punct("->"), SetState(&[(ExpectType, SetState(&BLOCK))])), - (Otherwise, SetState(&INIT)), -]; - -static CONST: [(Input, Action); 2] = [ - (Punct("|"), SetState(&CLOSURE_ARGS)), - (ConsumeBrace, SetState(&POSTFIX)), -]; - -static CONTINUE: [(Input, Action); 2] = [ - (ConsumeLifetime, SetState(&POSTFIX)), - (Otherwise, SetState(&POSTFIX)), -]; - -static DOT: [(Input, Action); 3] = [ - (Keyword("await"), SetState(&POSTFIX)), - (ConsumeIdent, SetState(&METHOD)), - (ConsumeLiteral, SetState(&POSTFIX)), -]; - -static FOR: [(Input, Action); 2] = [ - (Punct("<"), SetState(&CLOSURE)), - (Otherwise, SetState(&PATTERN)), -]; - -static IF_ELSE: [(Input, Action); 2] = [(Keyword("if"), SetState(&INIT)), (ConsumeBrace, DecDepth)]; -static IF_THEN: [(Input, Action); 2] = - [(Keyword("else"), SetState(&IF_ELSE)), (Otherwise, DecDepth)]; - -static METHOD: [(Input, Action); 1] = [(ExpectTurbofish, SetState(&POSTFIX))]; - -static PATH: [(Input, Action); 4] = [ - (Punct("!="), SetState(&INIT)), - (Punct("!"), SetState(&INIT)), - (ConsumeNestedBrace, SetState(&IF_THEN)), - (Otherwise, SetState(&POSTFIX)), -]; - -static PATTERN: [(Input, Action); 15] = [ - (ConsumeDelimiter, SetState(&PATTERN)), - (Keyword("box"), SetState(&PATTERN)), - (Keyword("in"), IncDepth), - (Keyword("mut"), SetState(&PATTERN)), - (Keyword("ref"), SetState(&PATTERN)), - (Keyword("_"), SetState(&PATTERN)), - (Punct("!"), SetState(&PATTERN)), - (Punct("&"), SetState(&PATTERN)), - (Punct("..="), SetState(&PATTERN)), - (Punct(".."), SetState(&PATTERN)), - (Punct("="), SetState(&INIT)), - (Punct("@"), SetState(&PATTERN)), - (Punct("|"), SetState(&PATTERN)), - (ConsumeLiteral, SetState(&PATTERN)), - (ExpectPath, SetState(&PATTERN)), -]; - -static RANGE: [(Input, Action); 6] = [ - (Punct("..="), SetState(&INIT)), - (Punct(".."), SetState(&RANGE)), - (Punct("."), SetState(&DOT)), - (ConsumeNestedBrace, SetState(&IF_THEN)), - (Empty, Finish), - (Otherwise, SetState(&INIT)), -]; - -static RAW: [(Input, Action); 3] = [ - (Keyword("const"), SetState(&INIT)), - (Keyword("mut"), SetState(&INIT)), - (Otherwise, SetState(&POSTFIX)), -]; - -static REFERENCE: [(Input, Action); 3] = [ - (Keyword("mut"), SetState(&INIT)), - (Keyword("raw"), SetState(&RAW)), - (Otherwise, SetState(&INIT)), -]; - -static RETURN: [(Input, Action); 2] = [ - (CanBeginExpr, SetState(&INIT)), - (Otherwise, SetState(&POSTFIX)), -]; - -pub(crate) fn scan_expr(input: ParseStream) -> Result<()> { - let mut state = INIT.as_slice(); - let mut depth = 0usize; - 'table: loop { - for rule in state { - if match rule.0 { - Input::Keyword(expected) => input.step(|cursor| match cursor.ident() { - Some((ident, rest)) if ident == expected => Ok((true, rest)), - _ => Ok((false, *cursor)), - })?, - Input::Punct(expected) => input.step(|cursor| { - let begin = *cursor; - let mut cursor = begin; - for (i, ch) in expected.chars().enumerate() { - match cursor.punct() { - Some((punct, _)) if punct.as_char() != ch => break, - Some((_, rest)) if i == expected.len() - 1 => { - return Ok((true, rest)); - } - Some((punct, rest)) if punct.spacing() == Spacing::Joint => { - cursor = rest; - } - _ => break, - } - } - Ok((false, begin)) - })?, - Input::ConsumeAny => input.parse::>()?.is_some(), - Input::ConsumeBinOp => input.parse::().is_ok(), - Input::ConsumeBrace | Input::ConsumeNestedBrace => { - (matches!(rule.0, Input::ConsumeBrace) || depth > 0) - && input.step(|cursor| match cursor.group(Delimiter::Brace) { - Some((_inside, _span, rest)) => Ok((true, rest)), - None => Ok((false, *cursor)), - })? - } - Input::ConsumeDelimiter => input.step(|cursor| match cursor.any_group() { - Some((_inside, _delimiter, _span, rest)) => Ok((true, rest)), - None => Ok((false, *cursor)), - })?, - Input::ConsumeIdent => input.parse::>()?.is_some(), - Input::ConsumeLifetime => input.parse::>()?.is_some(), - Input::ConsumeLiteral => input.parse::>()?.is_some(), - Input::ExpectPath => { - input.parse::()?; - true - } - Input::ExpectTurbofish => { - if input.peek(Token![::]) { - input.parse::()?; - } - true - } - Input::ExpectType => { - Type::without_plus(input)?; - true - } - Input::CanBeginExpr => Expr::peek(input), - Input::Otherwise => true, - Input::Empty => input.is_empty() || input.peek(Token![,]), - } { - state = match rule.1 { - Action::SetState(next) => next, - Action::IncDepth => (depth += 1, &INIT).1, - Action::DecDepth => (depth -= 1, &POSTFIX).1, - Action::Finish => return if depth == 0 { Ok(()) } else { break }, - }; - continue 'table; - } - } - return Err(input.error("unsupported expression")); - } -} diff --git a/subprojects/thiserror/impl/src/unraw.rs b/subprojects/thiserror/impl/src/unraw.rs deleted file mode 100644 index 73b9970..0000000 --- a/subprojects/thiserror/impl/src/unraw.rs +++ /dev/null @@ -1,142 +0,0 @@ -use proc_macro2::{Ident, Span, TokenStream}; -use quote::ToTokens; -use std::cmp::Ordering; -use std::fmt::{self, Display}; -use std::hash::{Hash, Hasher}; -use syn::ext::IdentExt as _; -use syn::parse::{Parse, ParseStream, Result}; -use syn::Index; - -#[derive(Clone)] -#[repr(transparent)] -pub struct IdentUnraw(Ident); - -impl IdentUnraw { - pub fn new(ident: Ident) -> Self { - IdentUnraw(ident) - } - - pub fn to_local(&self) -> Ident { - let unraw = self.0.unraw(); - let repr = unraw.to_string(); - if syn::parse_str::(&repr).is_err() { - if let "_" | "super" | "self" | "Self" | "crate" = repr.as_str() { - // Some identifiers are never allowed to appear as raw, like r#self and r#_. - } else { - return Ident::new_raw(&repr, Span::call_site()); - } - } - unraw - } - - pub fn set_span(&mut self, span: Span) { - self.0.set_span(span); - } -} - -impl Display for IdentUnraw { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - Display::fmt(&self.0.unraw(), formatter) - } -} - -impl Eq for IdentUnraw {} - -impl PartialEq for IdentUnraw { - fn eq(&self, other: &Self) -> bool { - PartialEq::eq(&self.0.unraw(), &other.0.unraw()) - } -} - -impl PartialEq for IdentUnraw { - fn eq(&self, other: &str) -> bool { - self.0 == other - } -} - -impl Ord for IdentUnraw { - fn cmp(&self, other: &Self) -> Ordering { - Ord::cmp(&self.0.unraw(), &other.0.unraw()) - } -} - -impl PartialOrd for IdentUnraw { - fn partial_cmp(&self, other: &Self) -> Option { - Some(Self::cmp(self, other)) - } -} - -impl Parse for IdentUnraw { - fn parse(input: ParseStream) -> Result { - input.call(Ident::parse_any).map(IdentUnraw::new) - } -} - -impl ToTokens for IdentUnraw { - fn to_tokens(&self, tokens: &mut TokenStream) { - self.0.unraw().to_tokens(tokens); - } -} - -#[derive(Clone)] -pub enum MemberUnraw { - Named(IdentUnraw), - Unnamed(Index), -} - -impl MemberUnraw { - pub fn span(&self) -> Span { - match self { - MemberUnraw::Named(ident) => ident.0.span(), - MemberUnraw::Unnamed(index) => index.span, - } - } -} - -impl Display for MemberUnraw { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - match self { - MemberUnraw::Named(this) => Display::fmt(this, formatter), - MemberUnraw::Unnamed(this) => Display::fmt(&this.index, formatter), - } - } -} - -impl Eq for MemberUnraw {} - -impl PartialEq for MemberUnraw { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - (MemberUnraw::Named(this), MemberUnraw::Named(other)) => this == other, - (MemberUnraw::Unnamed(this), MemberUnraw::Unnamed(other)) => this == other, - _ => false, - } - } -} - -impl PartialEq for MemberUnraw { - fn eq(&self, other: &str) -> bool { - match self { - MemberUnraw::Named(this) => this == other, - MemberUnraw::Unnamed(_) => false, - } - } -} - -impl Hash for MemberUnraw { - fn hash(&self, hasher: &mut H) { - match self { - MemberUnraw::Named(ident) => ident.0.unraw().hash(hasher), - MemberUnraw::Unnamed(index) => index.hash(hasher), - } - } -} - -impl ToTokens for MemberUnraw { - fn to_tokens(&self, tokens: &mut TokenStream) { - match self { - MemberUnraw::Named(ident) => ident.to_local().to_tokens(tokens), - MemberUnraw::Unnamed(index) => index.to_tokens(tokens), - } - } -} diff --git a/subprojects/thiserror/impl/src/valid.rs b/subprojects/thiserror/impl/src/valid.rs deleted file mode 100644 index 21bd885..0000000 --- a/subprojects/thiserror/impl/src/valid.rs +++ /dev/null @@ -1,248 +0,0 @@ -use crate::ast::{Enum, Field, Input, Struct, Variant}; -use crate::attr::Attrs; -use syn::{Error, GenericArgument, PathArguments, Result, Type}; - -impl Input<'_> { - pub(crate) fn validate(&self) -> Result<()> { - match self { - Input::Struct(input) => input.validate(), - Input::Enum(input) => input.validate(), - } - } -} - -impl Struct<'_> { - fn validate(&self) -> Result<()> { - check_non_field_attrs(&self.attrs)?; - if let Some(transparent) = self.attrs.transparent { - if self.fields.len() != 1 { - return Err(Error::new_spanned( - transparent.original, - "#[error(transparent)] requires exactly one field", - )); - } - if let Some(source) = self.fields.iter().find_map(|f| f.attrs.source) { - return Err(Error::new_spanned( - source.original, - "transparent error struct can't contain #[source]", - )); - } - } - if let Some(fmt) = &self.attrs.fmt { - return Err(Error::new_spanned( - fmt.original, - "#[error(fmt = ...)] is only supported in enums; for a struct, handwrite your own Display impl", - )); - } - check_field_attrs(&self.fields)?; - for field in &self.fields { - field.validate()?; - } - Ok(()) - } -} - -impl Enum<'_> { - fn validate(&self) -> Result<()> { - check_non_field_attrs(&self.attrs)?; - let has_display = self.has_display(); - for variant in &self.variants { - variant.validate()?; - if has_display - && variant.attrs.display.is_none() - && variant.attrs.transparent.is_none() - && variant.attrs.fmt.is_none() - { - return Err(Error::new_spanned( - variant.original, - "missing #[error(\"...\")] display attribute", - )); - } - } - Ok(()) - } -} - -impl Variant<'_> { - fn validate(&self) -> Result<()> { - check_non_field_attrs(&self.attrs)?; - if self.attrs.transparent.is_some() { - if self.fields.len() != 1 { - return Err(Error::new_spanned( - self.original, - "#[error(transparent)] requires exactly one field", - )); - } - if let Some(source) = self.fields.iter().find_map(|f| f.attrs.source) { - return Err(Error::new_spanned( - source.original, - "transparent variant can't contain #[source]", - )); - } - } - check_field_attrs(&self.fields)?; - for field in &self.fields { - field.validate()?; - } - Ok(()) - } -} - -impl Field<'_> { - fn validate(&self) -> Result<()> { - if let Some(unexpected_display_attr) = if let Some(display) = &self.attrs.display { - Some(display.original) - } else if let Some(fmt) = &self.attrs.fmt { - Some(fmt.original) - } else { - None - } { - return Err(Error::new_spanned( - unexpected_display_attr, - "not expected here; the #[error(...)] attribute belongs on top of a struct or an enum variant", - )); - } - Ok(()) - } -} - -fn check_non_field_attrs(attrs: &Attrs) -> Result<()> { - if let Some(from) = &attrs.from { - return Err(Error::new_spanned( - from.original, - "not expected here; the #[from] attribute belongs on a specific field", - )); - } - if let Some(source) = &attrs.source { - return Err(Error::new_spanned( - source.original, - "not expected here; the #[source] attribute belongs on a specific field", - )); - } - if let Some(backtrace) = &attrs.backtrace { - return Err(Error::new_spanned( - backtrace, - "not expected here; the #[backtrace] attribute belongs on a specific field", - )); - } - if attrs.transparent.is_some() { - if let Some(display) = &attrs.display { - return Err(Error::new_spanned( - display.original, - "cannot have both #[error(transparent)] and a display attribute", - )); - } - if let Some(fmt) = &attrs.fmt { - return Err(Error::new_spanned( - fmt.original, - "cannot have both #[error(transparent)] and #[error(fmt = ...)]", - )); - } - } else if let (Some(display), Some(_)) = (&attrs.display, &attrs.fmt) { - return Err(Error::new_spanned( - display.original, - "cannot have both #[error(fmt = ...)] and a format arguments attribute", - )); - } - - Ok(()) -} - -fn check_field_attrs(fields: &[Field]) -> Result<()> { - let mut from_field = None; - let mut source_field = None; - let mut backtrace_field = None; - let mut has_backtrace = false; - for field in fields { - if let Some(from) = field.attrs.from { - if from_field.is_some() { - return Err(Error::new_spanned( - from.original, - "duplicate #[from] attribute", - )); - } - from_field = Some(field); - } - if let Some(source) = field.attrs.source { - if source_field.is_some() { - return Err(Error::new_spanned( - source.original, - "duplicate #[source] attribute", - )); - } - source_field = Some(field); - } - if let Some(backtrace) = field.attrs.backtrace { - if backtrace_field.is_some() { - return Err(Error::new_spanned( - backtrace, - "duplicate #[backtrace] attribute", - )); - } - backtrace_field = Some(field); - has_backtrace = true; - } - if let Some(transparent) = field.attrs.transparent { - return Err(Error::new_spanned( - transparent.original, - "#[error(transparent)] needs to go outside the enum or struct, not on an individual field", - )); - } - has_backtrace |= field.is_backtrace(); - } - if let (Some(from_field), Some(source_field)) = (from_field, source_field) { - if from_field.member != source_field.member { - return Err(Error::new_spanned( - from_field.attrs.from.unwrap().original, - "#[from] is only supported on the source field, not any other field", - )); - } - } - if let Some(from_field) = from_field { - let max_expected_fields = match backtrace_field { - Some(backtrace_field) => 1 + (from_field.member != backtrace_field.member) as usize, - None => 1 + has_backtrace as usize, - }; - if fields.len() > max_expected_fields { - return Err(Error::new_spanned( - from_field.attrs.from.unwrap().original, - "deriving From requires no fields other than source and backtrace", - )); - } - } - if let Some(source_field) = source_field.or(from_field) { - if contains_non_static_lifetime(source_field.ty) { - return Err(Error::new_spanned( - &source_field.original.ty, - "non-static lifetimes are not allowed in the source of an error, because std::error::Error requires the source is dyn Error + 'static", - )); - } - } - Ok(()) -} - -fn contains_non_static_lifetime(ty: &Type) -> bool { - match ty { - Type::Path(ty) => { - let bracketed = match &ty.path.segments.last().unwrap().arguments { - PathArguments::AngleBracketed(bracketed) => bracketed, - _ => return false, - }; - for arg in &bracketed.args { - match arg { - GenericArgument::Type(ty) if contains_non_static_lifetime(ty) => return true, - GenericArgument::Lifetime(lifetime) if lifetime.ident != "static" => { - return true - } - _ => {} - } - } - false - } - Type::Reference(ty) => ty - .lifetime - .as_ref() - .map_or(false, |lifetime| lifetime.ident != "static"), - _ => false, // maybe implement later if there are common other cases - } -} diff --git a/subprojects/thiserror/rust-toolchain.toml b/subprojects/thiserror/rust-toolchain.toml deleted file mode 100644 index 20fe888..0000000 --- a/subprojects/thiserror/rust-toolchain.toml +++ /dev/null @@ -1,2 +0,0 @@ -[toolchain] -components = ["rust-src"] diff --git a/subprojects/thiserror/src/aserror.rs b/subprojects/thiserror/src/aserror.rs deleted file mode 100644 index ac91cc8..0000000 --- a/subprojects/thiserror/src/aserror.rs +++ /dev/null @@ -1,50 +0,0 @@ -use core::error::Error; -use core::panic::UnwindSafe; - -#[doc(hidden)] -pub trait AsDynError<'a>: Sealed { - fn as_dyn_error(&self) -> &(dyn Error + 'a); -} - -impl<'a, T: Error + 'a> AsDynError<'a> for T { - #[inline] - fn as_dyn_error(&self) -> &(dyn Error + 'a) { - self - } -} - -impl<'a> AsDynError<'a> for dyn Error + 'a { - #[inline] - fn as_dyn_error(&self) -> &(dyn Error + 'a) { - self - } -} - -impl<'a> AsDynError<'a> for dyn Error + Send + 'a { - #[inline] - fn as_dyn_error(&self) -> &(dyn Error + 'a) { - self - } -} - -impl<'a> AsDynError<'a> for dyn Error + Send + Sync + 'a { - #[inline] - fn as_dyn_error(&self) -> &(dyn Error + 'a) { - self - } -} - -impl<'a> AsDynError<'a> for dyn Error + Send + Sync + UnwindSafe + 'a { - #[inline] - fn as_dyn_error(&self) -> &(dyn Error + 'a) { - self - } -} - -#[doc(hidden)] -pub trait Sealed {} -impl Sealed for T {} -impl Sealed for dyn Error + '_ {} -impl Sealed for dyn Error + Send + '_ {} -impl Sealed for dyn Error + Send + Sync + '_ {} -impl Sealed for dyn Error + Send + Sync + UnwindSafe + '_ {} diff --git a/subprojects/thiserror/src/display.rs b/subprojects/thiserror/src/display.rs deleted file mode 100644 index e544657..0000000 --- a/subprojects/thiserror/src/display.rs +++ /dev/null @@ -1,82 +0,0 @@ -use core::fmt::Display; -#[cfg(feature = "std")] -use std::path::{self, Path, PathBuf}; - -#[doc(hidden)] -pub trait AsDisplay<'a>: Sealed { - // TODO: convert to generic associated type. - // https://github.com/dtolnay/thiserror/pull/253 - type Target: Display; - - fn as_display(&'a self) -> Self::Target; -} - -impl<'a, T> AsDisplay<'a> for &T -where - T: Display + ?Sized + 'a, -{ - type Target = &'a T; - - fn as_display(&'a self) -> Self::Target { - *self - } -} - -#[cfg(feature = "std")] -impl<'a> AsDisplay<'a> for Path { - type Target = path::Display<'a>; - - #[inline] - fn as_display(&'a self) -> Self::Target { - self.display() - } -} - -#[cfg(feature = "std")] -impl<'a> AsDisplay<'a> for PathBuf { - type Target = path::Display<'a>; - - #[inline] - fn as_display(&'a self) -> Self::Target { - self.display() - } -} - -#[doc(hidden)] -pub trait Sealed {} -impl Sealed for &T {} -#[cfg(feature = "std")] -impl Sealed for Path {} -#[cfg(feature = "std")] -impl Sealed for PathBuf {} - -// Add a synthetic second impl of AsDisplay to prevent the "single applicable -// impl" rule from making too weird inference decision based on the single impl -// for &T, which could lead to code that compiles with thiserror's std feature -// off but breaks under feature unification when std is turned on by an -// unrelated crate. -#[cfg(not(feature = "std"))] -mod placeholder { - use super::{AsDisplay, Sealed}; - use core::fmt::{self, Display}; - - #[allow(dead_code)] - pub struct Placeholder; - - impl<'a> AsDisplay<'a> for Placeholder { - type Target = Self; - - #[inline] - fn as_display(&'a self) -> Self::Target { - Placeholder - } - } - - impl Display for Placeholder { - fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { - unreachable!() - } - } - - impl Sealed for Placeholder {} -} diff --git a/subprojects/thiserror/src/lib.rs b/subprojects/thiserror/src/lib.rs deleted file mode 100644 index 944960e..0000000 --- a/subprojects/thiserror/src/lib.rs +++ /dev/null @@ -1,295 +0,0 @@ -//! [![github]](https://github.com/dtolnay/thiserror) [![crates-io]](https://crates.io/crates/thiserror) [![docs-rs]](https://docs.rs/thiserror) -//! -//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github -//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust -//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs -//! -//!
-//! -//! This library provides a convenient derive macro for the standard library's -//! [`std::error::Error`] trait. -//! -//!
-//! -//! # Example -//! -//! ```rust -//! # use std::io; -//! use thiserror::Error; -//! -//! #[derive(Error, Debug)] -//! pub enum DataStoreError { -//! #[error("data store disconnected")] -//! Disconnect(#[from] io::Error), -//! #[error("the data for key `{0}` is not available")] -//! Redaction(String), -//! #[error("invalid header (expected {expected:?}, found {found:?})")] -//! InvalidHeader { -//! expected: String, -//! found: String, -//! }, -//! #[error("unknown data store error")] -//! Unknown, -//! } -//! ``` -//! -//!
-//! -//! # Details -//! -//! - Thiserror deliberately does not appear in your public API. You get the -//! same thing as if you had written an implementation of -//! [`std::error::Error`] by hand, and switching from handwritten impls to -//! thiserror or vice versa is not a breaking change. -//! -//! - Errors may be enums, structs with named fields, tuple structs, or unit -//! structs. -//! -//! - A [`Display`] impl is generated for your error if you provide -//! `#[error("...")]` messages on the struct or each variant of your enum, as -//! shown above in the example. -//! -//! The messages support a shorthand for interpolating fields from the error. -//! -//! - `#[error("{var}")]` ⟶ `write!("{}", self.var)` -//! - `#[error("{0}")]` ⟶ `write!("{}", self.0)` -//! - `#[error("{var:?}")]` ⟶ `write!("{:?}", self.var)` -//! - `#[error("{0:?}")]` ⟶ `write!("{:?}", self.0)` -//! -//! These shorthands can be used together with any additional format args, -//! which may be arbitrary expressions. For example: -//! -//! ```rust -//! # use core::i32; -//! # use thiserror::Error; -//! # -//! #[derive(Error, Debug)] -//! pub enum Error { -//! #[error("invalid rdo_lookahead_frames {0} (expected < {max})", max = i32::MAX)] -//! InvalidLookahead(u32), -//! } -//! ``` -//! -//! If one of the additional expression arguments needs to refer to a field of -//! the struct or enum, then refer to named fields as `.var` and tuple fields -//! as `.0`. -//! -//! ```rust -//! # use thiserror::Error; -//! # -//! # fn first_char(s: &String) -> char { -//! # s.chars().next().unwrap() -//! # } -//! # -//! # #[derive(Debug)] -//! # struct Limits { -//! # lo: usize, -//! # hi: usize, -//! # } -//! # -//! #[derive(Error, Debug)] -//! pub enum Error { -//! #[error("first letter must be lowercase but was {:?}", first_char(.0))] -//! WrongCase(String), -//! #[error("invalid index {idx}, expected at least {} and at most {}", .limits.lo, .limits.hi)] -//! OutOfBounds { idx: usize, limits: Limits }, -//! } -//! ``` -//! -//! - A [`From`] impl is generated for each variant that contains a `#[from]` -//! attribute. -//! -//! The variant using `#[from]` must not contain any other fields beyond the -//! source error (and possibly a backtrace — see below). Usually -//! `#[from]` fields are unnamed, but `#[from]` is allowed on a named field -//! too. -//! -//! ```rust -//! # use core::fmt::{self, Display}; -//! # use std::io; -//! # use thiserror::Error; -//! # -//! # mod globset { -//! # #[derive(thiserror::Error, Debug)] -//! # #[error("...")] -//! # pub struct Error; -//! # } -//! # -//! #[derive(Error, Debug)] -//! pub enum MyError { -//! Io(#[from] io::Error), -//! Glob(#[from] globset::Error), -//! } -//! # -//! # impl Display for MyError { -//! # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { -//! # unimplemented!() -//! # } -//! # } -//! ``` -//! -//! - The Error trait's [`source()`] method is implemented to return whichever -//! field has a `#[source]` attribute or is named `source`, if any. This is -//! for identifying the underlying lower level error that caused your error. -//! -//! The `#[from]` attribute always implies that the same field is `#[source]`, -//! so you don't ever need to specify both attributes. -//! -//! Any error type that implements `std::error::Error` or dereferences to `dyn -//! std::error::Error` will work as a source. -//! -//! ```rust -//! # use core::fmt::{self, Display}; -//! # use thiserror::Error; -//! # -//! #[derive(Error, Debug)] -//! pub struct MyError { -//! msg: String, -//! #[source] // optional if field name is `source` -//! source: anyhow::Error, -//! } -//! # -//! # impl Display for MyError { -//! # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { -//! # unimplemented!() -//! # } -//! # } -//! ``` -//! -//! - The Error trait's [`provide()`] method is implemented to provide whichever -//! field has a type named `Backtrace`, if any, as a -//! [`std::backtrace::Backtrace`]. Using `Backtrace` in errors requires a -//! nightly compiler with Rust version 1.73 or newer. -//! -//! ```rust -//! # const IGNORE: &str = stringify! { -//! use std::backtrace::Backtrace; -//! -//! #[derive(Error, Debug)] -//! pub struct MyError { -//! msg: String, -//! backtrace: Backtrace, // automatically detected -//! } -//! # }; -//! ``` -//! -//! - If a field is both a source (named `source`, or has `#[source]` or -//! `#[from]` attribute) *and* is marked `#[backtrace]`, then the Error -//! trait's [`provide()`] method is forwarded to the source's `provide` so -//! that both layers of the error share the same backtrace. The `#[backtrace]` -//! attribute requires a nightly compiler with Rust version 1.73 or newer. -//! -//! ```rust -//! # const IGNORE: &str = stringify! { -//! #[derive(Error, Debug)] -//! pub enum MyError { -//! Io { -//! #[backtrace] -//! source: io::Error, -//! }, -//! } -//! # }; -//! ``` -//! -//! - For variants that use `#[from]` and also contain a `Backtrace` field, a -//! backtrace is captured from within the `From` impl. -//! -//! ```rust -//! # const IGNORE: &str = stringify! { -//! #[derive(Error, Debug)] -//! pub enum MyError { -//! Io { -//! #[from] -//! source: io::Error, -//! backtrace: Backtrace, -//! }, -//! } -//! # }; -//! ``` -//! -//! - Errors may use `error(transparent)` to forward the source and [`Display`] -//! methods straight through to an underlying error without adding an -//! additional message. This would be appropriate for enums that need an -//! "anything else" variant. -//! -//! ``` -//! # use thiserror::Error; -//! # -//! #[derive(Error, Debug)] -//! pub enum MyError { -//! # /* -//! ... -//! # */ -//! -//! #[error(transparent)] -//! Other(#[from] anyhow::Error), // source and Display delegate to anyhow::Error -//! } -//! ``` -//! -//! Another use case is hiding implementation details of an error -//! representation behind an opaque error type, so that the representation is -//! able to evolve without breaking the crate's public API. -//! -//! ``` -//! # use thiserror::Error; -//! # -//! // PublicError is public, but opaque and easy to keep compatible. -//! #[derive(Error, Debug)] -//! #[error(transparent)] -//! pub struct PublicError(#[from] ErrorRepr); -//! -//! impl PublicError { -//! // Accessors for anything we do want to expose publicly. -//! } -//! -//! // Private and free to change across minor version of the crate. -//! #[derive(Error, Debug)] -//! enum ErrorRepr { -//! # /* -//! ... -//! # */ -//! } -//! ``` -//! -//! - See also the [`anyhow`] library for a convenient single error type to use -//! in application code. -//! -//! [`anyhow`]: https://github.com/dtolnay/anyhow -//! [`source()`]: std::error::Error::source -//! [`provide()`]: std::error::Error::provide -//! [`Display`]: std::fmt::Display - -#![no_std] -#![doc(html_root_url = "https://docs.rs/thiserror/2.0.17")] -#![allow( - clippy::elidable_lifetime_names, - clippy::module_name_repetitions, - clippy::needless_lifetimes, - clippy::return_self_not_must_use, - clippy::wildcard_imports -)] -#![cfg_attr(error_generic_member_access, feature(error_generic_member_access))] - -#[cfg(all(thiserror_nightly_testing, not(error_generic_member_access)))] -compile_error!("Build script probe failed to compile."); - -#[cfg(feature = "std")] -extern crate std; -#[cfg(feature = "std")] -extern crate std as core; - -mod aserror; -mod display; -#[cfg(error_generic_member_access)] -mod provide; -mod var; - -pub use thiserror_impl::*; - -mod private; - -#[doc(hidden)] -pub mod __private { - #[doc(hidden)] - pub use crate::private::*; -} diff --git a/subprojects/thiserror/src/private.rs b/subprojects/thiserror/src/private.rs deleted file mode 100644 index 545aa8e..0000000 --- a/subprojects/thiserror/src/private.rs +++ /dev/null @@ -1,14 +0,0 @@ -#[doc(hidden)] -pub use crate::aserror::AsDynError; -#[doc(hidden)] -pub use crate::display::AsDisplay; -#[cfg(error_generic_member_access)] -#[doc(hidden)] -pub use crate::provide::ThiserrorProvide; -#[doc(hidden)] -pub use crate::var::Var; -#[doc(hidden)] -pub use core::error::Error; -#[cfg(all(feature = "std", not(thiserror_no_backtrace_type)))] -#[doc(hidden)] -pub use std::backtrace::Backtrace; diff --git a/subprojects/thiserror/src/provide.rs b/subprojects/thiserror/src/provide.rs deleted file mode 100644 index 4b2f06a..0000000 --- a/subprojects/thiserror/src/provide.rs +++ /dev/null @@ -1,20 +0,0 @@ -use core::error::{Error, Request}; - -#[doc(hidden)] -pub trait ThiserrorProvide: Sealed { - fn thiserror_provide<'a>(&'a self, request: &mut Request<'a>); -} - -impl ThiserrorProvide for T -where - T: Error + ?Sized, -{ - #[inline] - fn thiserror_provide<'a>(&'a self, request: &mut Request<'a>) { - self.provide(request); - } -} - -#[doc(hidden)] -pub trait Sealed {} -impl Sealed for T {} diff --git a/subprojects/thiserror/src/var.rs b/subprojects/thiserror/src/var.rs deleted file mode 100644 index ecfcd85..0000000 --- a/subprojects/thiserror/src/var.rs +++ /dev/null @@ -1,9 +0,0 @@ -use core::fmt::{self, Pointer}; - -pub struct Var<'a, T: ?Sized>(pub &'a T); - -impl<'a, T: Pointer + ?Sized> Pointer for Var<'a, T> { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - Pointer::fmt(self.0, formatter) - } -} diff --git a/subprojects/thiserror/tests/compiletest.rs b/subprojects/thiserror/tests/compiletest.rs deleted file mode 100644 index 23a6a06..0000000 --- a/subprojects/thiserror/tests/compiletest.rs +++ /dev/null @@ -1,7 +0,0 @@ -#[rustversion::attr(not(nightly), ignore = "requires nightly")] -#[cfg_attr(miri, ignore = "incompatible with miri")] -#[test] -fn ui() { - let t = trybuild::TestCases::new(); - t.compile_fail("tests/ui/*.rs"); -} diff --git a/subprojects/thiserror/tests/no-std/Cargo.toml b/subprojects/thiserror/tests/no-std/Cargo.toml deleted file mode 100644 index 8b03d2f..0000000 --- a/subprojects/thiserror/tests/no-std/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "thiserror_no_std_test" -version = "0.0.0" -authors = ["David Tolnay "] -edition = "2021" -publish = false - -[lib] -path = "test.rs" - -[dependencies] -thiserror = { path = "../..", default-features = false } diff --git a/subprojects/thiserror/tests/no-std/test.rs b/subprojects/thiserror/tests/no-std/test.rs deleted file mode 100644 index da7899c..0000000 --- a/subprojects/thiserror/tests/no-std/test.rs +++ /dev/null @@ -1,58 +0,0 @@ -#![no_std] - -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum Error { - #[error("Error::E")] - E(#[from] SourceError), -} - -#[derive(Error, Debug)] -#[error("SourceError {field}")] -pub struct SourceError { - pub field: i32, -} - -#[cfg(test)] -mod tests { - use crate::{Error, SourceError}; - use core::error::Error as _; - use core::fmt::{self, Write}; - use core::mem; - - struct Buf<'a>(&'a mut [u8]); - - impl Write for Buf<'_> { - fn write_str(&mut self, s: &str) -> fmt::Result { - if s.len() <= self.0.len() { - let (out, rest) = mem::take(&mut self.0).split_at_mut(s.len()); - out.copy_from_slice(s.as_bytes()); - self.0 = rest; - Ok(()) - } else { - Err(fmt::Error) - } - } - } - - #[test] - fn test() { - let source = SourceError { field: -1 }; - let error = Error::from(source); - - let source = error - .source() - .unwrap() - .downcast_ref::() - .unwrap(); - - let mut msg = [b'~'; 17]; - write!(Buf(&mut msg), "{error}").unwrap(); - assert_eq!(msg, *b"Error::E~~~~~~~~~"); - - let mut msg = [b'~'; 17]; - write!(Buf(&mut msg), "{source}").unwrap(); - assert_eq!(msg, *b"SourceError -1~~~"); - } -} diff --git a/subprojects/thiserror/tests/test_backtrace.rs b/subprojects/thiserror/tests/test_backtrace.rs deleted file mode 100644 index cc25676..0000000 --- a/subprojects/thiserror/tests/test_backtrace.rs +++ /dev/null @@ -1,289 +0,0 @@ -#![cfg(feature = "std")] -#![cfg_attr(thiserror_nightly_testing, feature(error_generic_member_access))] - -use thiserror::Error; - -#[derive(Error, Debug)] -#[error("...")] -pub struct Inner; - -#[cfg(thiserror_nightly_testing)] -#[derive(Error, Debug)] -#[error("...")] -pub struct InnerBacktrace { - backtrace: std::backtrace::Backtrace, -} - -#[cfg(thiserror_nightly_testing)] -pub mod structs { - use super::{Inner, InnerBacktrace}; - use std::backtrace::Backtrace; - use std::error::{self, Error}; - use std::sync::Arc; - use thiserror::Error; - - mod not_backtrace { - #[derive(Debug)] - pub struct Backtrace; - } - - #[derive(Error, Debug)] - #[error("...")] - pub struct PlainBacktrace { - backtrace: Backtrace, - } - - #[derive(Error, Debug)] - #[error("...")] - pub struct ExplicitBacktrace { - #[backtrace] - backtrace: Backtrace, - } - - #[derive(Error, Debug)] - #[error("...")] - pub struct NotBacktrace { - backtrace: crate::structs::not_backtrace::r#Backtrace, - } - - #[derive(Error, Debug)] - #[error("...")] - pub struct OptBacktrace { - #[backtrace] - backtrace: Option, - } - - #[derive(Error, Debug)] - #[error("...")] - pub struct ArcBacktrace { - #[backtrace] - backtrace: Arc, - } - - #[derive(Error, Debug)] - #[error("...")] - pub struct BacktraceFrom { - #[from] - source: Inner, - #[backtrace] - backtrace: Backtrace, - } - - #[derive(Error, Debug)] - #[error("...")] - pub struct CombinedBacktraceFrom { - #[from] - #[backtrace] - source: InnerBacktrace, - } - - #[derive(Error, Debug)] - #[error("...")] - pub struct OptBacktraceFrom { - #[from] - source: Inner, - #[backtrace] - backtrace: Option, - } - - #[derive(Error, Debug)] - #[error("...")] - pub struct ArcBacktraceFrom { - #[from] - source: Inner, - #[backtrace] - backtrace: Arc, - } - - #[derive(Error, Debug)] - #[error("...")] - pub struct AnyhowBacktrace { - #[backtrace] - source: anyhow::Error, - } - - #[derive(Error, Debug)] - #[error("...")] - pub struct BoxDynErrorBacktrace { - #[backtrace] - source: Box, - } - - #[test] - fn test_backtrace() { - let error = PlainBacktrace { - backtrace: Backtrace::capture(), - }; - assert!(error::request_ref::(&error).is_some()); - - let error = ExplicitBacktrace { - backtrace: Backtrace::capture(), - }; - assert!(error::request_ref::(&error).is_some()); - - let error = OptBacktrace { - backtrace: Some(Backtrace::capture()), - }; - assert!(error::request_ref::(&error).is_some()); - - let error = ArcBacktrace { - backtrace: Arc::new(Backtrace::capture()), - }; - assert!(error::request_ref::(&error).is_some()); - - let error = BacktraceFrom::from(Inner); - assert!(error::request_ref::(&error).is_some()); - - let error = CombinedBacktraceFrom::from(InnerBacktrace { - backtrace: Backtrace::capture(), - }); - assert!(error::request_ref::(&error).is_some()); - - let error = OptBacktraceFrom::from(Inner); - assert!(error::request_ref::(&error).is_some()); - - let error = ArcBacktraceFrom::from(Inner); - assert!(error::request_ref::(&error).is_some()); - - let error = AnyhowBacktrace { - source: anyhow::Error::msg("..."), - }; - assert!(error::request_ref::(&error).is_some()); - - let error = BoxDynErrorBacktrace { - source: Box::new(PlainBacktrace { - backtrace: Backtrace::capture(), - }), - }; - assert!(error::request_ref::(&error).is_some()); - } -} - -#[cfg(thiserror_nightly_testing)] -pub mod enums { - use super::{Inner, InnerBacktrace}; - use std::backtrace::Backtrace; - use std::error; - use std::sync::Arc; - use thiserror::Error; - - #[derive(Error, Debug)] - pub enum PlainBacktrace { - #[error("...")] - Test { backtrace: Backtrace }, - } - - #[derive(Error, Debug)] - pub enum ExplicitBacktrace { - #[error("...")] - Test { - #[backtrace] - backtrace: Backtrace, - }, - } - - #[derive(Error, Debug)] - pub enum OptBacktrace { - #[error("...")] - Test { - #[backtrace] - backtrace: Option, - }, - } - - #[derive(Error, Debug)] - pub enum ArcBacktrace { - #[error("...")] - Test { - #[backtrace] - backtrace: Arc, - }, - } - - #[derive(Error, Debug)] - pub enum BacktraceFrom { - #[error("...")] - Test { - #[from] - source: Inner, - #[backtrace] - backtrace: Backtrace, - }, - } - - #[derive(Error, Debug)] - pub enum CombinedBacktraceFrom { - #[error("...")] - Test { - #[from] - #[backtrace] - source: InnerBacktrace, - }, - } - - #[derive(Error, Debug)] - pub enum OptBacktraceFrom { - #[error("...")] - Test { - #[from] - source: Inner, - #[backtrace] - backtrace: Option, - }, - } - - #[derive(Error, Debug)] - pub enum ArcBacktraceFrom { - #[error("...")] - Test { - #[from] - source: Inner, - #[backtrace] - backtrace: Arc, - }, - } - - #[test] - fn test_backtrace() { - let error = PlainBacktrace::Test { - backtrace: Backtrace::capture(), - }; - assert!(error::request_ref::(&error).is_some()); - - let error = ExplicitBacktrace::Test { - backtrace: Backtrace::capture(), - }; - assert!(error::request_ref::(&error).is_some()); - - let error = OptBacktrace::Test { - backtrace: Some(Backtrace::capture()), - }; - assert!(error::request_ref::(&error).is_some()); - - let error = ArcBacktrace::Test { - backtrace: Arc::new(Backtrace::capture()), - }; - assert!(error::request_ref::(&error).is_some()); - - let error = BacktraceFrom::from(Inner); - assert!(error::request_ref::(&error).is_some()); - - let error = CombinedBacktraceFrom::from(InnerBacktrace { - backtrace: Backtrace::capture(), - }); - assert!(error::request_ref::(&error).is_some()); - - let error = OptBacktraceFrom::from(Inner); - assert!(error::request_ref::(&error).is_some()); - - let error = ArcBacktraceFrom::from(Inner); - assert!(error::request_ref::(&error).is_some()); - } -} - -#[test] -#[cfg_attr( - not(thiserror_nightly_testing), - ignore = "requires `--cfg=thiserror_nightly_testing`" -)] -fn test_backtrace() {} diff --git a/subprojects/thiserror/tests/test_display.rs b/subprojects/thiserror/tests/test_display.rs deleted file mode 100644 index cace226..0000000 --- a/subprojects/thiserror/tests/test_display.rs +++ /dev/null @@ -1,478 +0,0 @@ -#![allow( - clippy::elidable_lifetime_names, - clippy::needless_lifetimes, - clippy::needless_raw_string_hashes, - clippy::trivially_copy_pass_by_ref, - clippy::uninlined_format_args -)] - -use core::fmt::{self, Display}; -use thiserror::Error; - -fn assert(expected: &str, value: T) { - assert_eq!(expected, value.to_string()); -} - -#[test] -fn test_braced() { - #[derive(Error, Debug)] - #[error("braced error: {msg}")] - struct Error { - msg: String, - } - - let msg = "T".to_owned(); - assert("braced error: T", Error { msg }); -} - -#[test] -fn test_braced_unused() { - #[derive(Error, Debug)] - #[error("braced error")] - struct Error { - extra: usize, - } - - assert("braced error", Error { extra: 0 }); -} - -#[test] -fn test_tuple() { - #[derive(Error, Debug)] - #[error("tuple error: {0}")] - struct Error(usize); - - assert("tuple error: 0", Error(0)); -} - -#[test] -fn test_unit() { - #[derive(Error, Debug)] - #[error("unit error")] - struct Error; - - assert("unit error", Error); -} - -#[test] -fn test_enum() { - #[derive(Error, Debug)] - enum Error { - #[error("braced error: {id}")] - Braced { id: usize }, - #[error("tuple error: {0}")] - Tuple(usize), - #[error("unit error")] - Unit, - } - - assert("braced error: 0", Error::Braced { id: 0 }); - assert("tuple error: 0", Error::Tuple(0)); - assert("unit error", Error::Unit); -} - -#[test] -fn test_constants() { - #[derive(Error, Debug)] - #[error("{MSG}: {id:?} (code {CODE:?})")] - struct Error { - id: &'static str, - } - - const MSG: &str = "failed to do"; - const CODE: usize = 9; - - assert("failed to do: \"\" (code 9)", Error { id: "" }); -} - -#[test] -fn test_inherit() { - #[derive(Error, Debug)] - #[error("{0}")] - enum Error { - Some(&'static str), - #[error("other error")] - Other(&'static str), - } - - assert("some error", Error::Some("some error")); - assert("other error", Error::Other("...")); -} - -#[test] -fn test_brace_escape() { - #[derive(Error, Debug)] - #[error("fn main() {{}}")] - struct Error; - - assert("fn main() {}", Error); -} - -#[test] -fn test_expr() { - #[derive(Error, Debug)] - #[error("1 + 1 = {}", 1 + 1)] - struct Error; - assert("1 + 1 = 2", Error); -} - -#[test] -fn test_nested() { - #[derive(Error, Debug)] - #[error("!bool = {}", not(.0))] - struct Error(bool); - - #[allow(clippy::trivially_copy_pass_by_ref)] - fn not(bool: &bool) -> bool { - !*bool - } - - assert("!bool = false", Error(true)); -} - -#[test] -fn test_match() { - #[derive(Error, Debug)] - #[error("{intro}: {0}", intro = match .1 { - Some(n) => format!("error occurred with {}", n), - None => "there was an empty error".to_owned(), - })] - struct Error(String, Option); - - assert( - "error occurred with 1: ...", - Error("...".to_owned(), Some(1)), - ); - assert( - "there was an empty error: ...", - Error("...".to_owned(), None), - ); -} - -#[test] -fn test_nested_display() { - // Same behavior as the one in `test_match`, but without String allocations. - #[derive(Error, Debug)] - #[error("{}", { - struct Msg<'a>(&'a String, &'a Option); - impl<'a> Display for Msg<'a> { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - match self.1 { - Some(n) => write!(formatter, "error occurred with {}", n), - None => write!(formatter, "there was an empty error"), - }?; - write!(formatter, ": {}", self.0) - } - } - Msg(.0, .1) - })] - struct Error(String, Option); - - assert( - "error occurred with 1: ...", - Error("...".to_owned(), Some(1)), - ); - assert( - "there was an empty error: ...", - Error("...".to_owned(), None), - ); -} - -#[test] -fn test_void() { - #[allow(clippy::empty_enums)] - #[derive(Error, Debug)] - #[error("...")] - pub enum Error {} - - let _: Error; -} - -#[test] -fn test_mixed() { - #[derive(Error, Debug)] - #[error("a={a} :: b={} :: c={c} :: d={d}", 1, c = 2, d = 3)] - struct Error { - a: usize, - d: usize, - } - - assert("a=0 :: b=1 :: c=2 :: d=3", Error { a: 0, d: 0 }); -} - -#[test] -fn test_ints() { - #[derive(Error, Debug)] - enum Error { - #[error("error {0}")] - Tuple(usize, usize), - #[error("error {0}", '?')] - Struct { v: usize }, - } - - assert("error 9", Error::Tuple(9, 0)); - assert("error ?", Error::Struct { v: 0 }); -} - -#[test] -fn test_trailing_comma() { - #[derive(Error, Debug)] - #[error( - "error {0}", - )] - #[rustfmt::skip] - struct Error(char); - - assert("error ?", Error('?')); -} - -#[test] -fn test_field() { - #[derive(Debug)] - struct Inner { - data: usize, - } - - #[derive(Error, Debug)] - #[error("{}", .0.data)] - struct Error(Inner); - - assert("0", Error(Inner { data: 0 })); -} - -#[test] -fn test_nested_tuple_field() { - #[derive(Debug)] - struct Inner(usize); - - #[derive(Error, Debug)] - #[error("{}", .0.0)] - struct Error(Inner); - - assert("0", Error(Inner(0))); -} - -#[test] -fn test_pointer() { - #[derive(Error, Debug)] - #[error("{field:p}")] - pub struct Struct { - field: Box, - } - - let s = Struct { - field: Box::new(-1), - }; - assert_eq!(s.to_string(), format!("{:p}", s.field)); -} - -#[test] -fn test_macro_rules_variant_from_call_site() { - // Regression test for https://github.com/dtolnay/thiserror/issues/86 - - macro_rules! decl_error { - ($variant:ident($value:ident)) => { - #[derive(Error, Debug)] - pub enum Error0 { - #[error("{0:?}")] - $variant($value), - } - - #[derive(Error, Debug)] - #[error("{0:?}")] - pub enum Error1 { - $variant($value), - } - }; - } - - decl_error!(Repro(u8)); - - assert("0", Error0::Repro(0)); - assert("0", Error1::Repro(0)); -} - -#[test] -fn test_macro_rules_message_from_call_site() { - // Regression test for https://github.com/dtolnay/thiserror/issues/398 - - macro_rules! decl_error { - ($($errors:tt)*) => { - #[derive(Error, Debug)] - pub enum Error { - $($errors)* - } - }; - } - - decl_error! { - #[error("{0}")] - Unnamed(u8), - #[error("{x}")] - Named { x: u8 }, - } - - assert("0", Error::Unnamed(0)); - assert("0", Error::Named { x: 0 }); -} - -#[test] -fn test_raw() { - #[derive(Error, Debug)] - #[error("braced raw error: {fn}")] - struct Error { - r#fn: &'static str, - } - - assert("braced raw error: T", Error { r#fn: "T" }); -} - -#[test] -fn test_raw_enum() { - #[derive(Error, Debug)] - enum Error { - #[error("braced raw error: {fn}")] - Braced { r#fn: &'static str }, - } - - assert("braced raw error: T", Error::Braced { r#fn: "T" }); -} - -#[test] -fn test_keyword() { - #[derive(Error, Debug)] - #[error("error: {type}", type = 1)] - struct Error; - - assert("error: 1", Error); -} - -#[test] -fn test_self() { - #[derive(Error, Debug)] - #[error("error: {self:?}")] - struct Error; - - assert("error: Error", Error); -} - -#[test] -fn test_str_special_chars() { - #[derive(Error, Debug)] - pub enum Error { - #[error("brace left {{")] - BraceLeft, - #[error("brace left 2 \x7B\x7B")] - BraceLeft2, - #[error("brace left 3 \u{7B}\u{7B}")] - BraceLeft3, - #[error("brace right }}")] - BraceRight, - #[error("brace right 2 \x7D\x7D")] - BraceRight2, - #[error("brace right 3 \u{7D}\u{7D}")] - BraceRight3, - #[error( - "new_\ -line" - )] - NewLine, - #[error("escape24 \u{78}")] - Escape24, - } - - assert("brace left {", Error::BraceLeft); - assert("brace left 2 {", Error::BraceLeft2); - assert("brace left 3 {", Error::BraceLeft3); - assert("brace right }", Error::BraceRight); - assert("brace right 2 }", Error::BraceRight2); - assert("brace right 3 }", Error::BraceRight3); - assert("new_line", Error::NewLine); - assert("escape24 x", Error::Escape24); -} - -#[test] -fn test_raw_str() { - #[derive(Error, Debug)] - pub enum Error { - #[error(r#"raw brace left {{"#)] - BraceLeft, - #[error(r#"raw brace left 2 \x7B"#)] - BraceLeft2, - #[error(r#"raw brace right }}"#)] - BraceRight, - #[error(r#"raw brace right 2 \x7D"#)] - BraceRight2, - } - - assert(r#"raw brace left {"#, Error::BraceLeft); - assert(r#"raw brace left 2 \x7B"#, Error::BraceLeft2); - assert(r#"raw brace right }"#, Error::BraceRight); - assert(r#"raw brace right 2 \x7D"#, Error::BraceRight2); -} - -mod util { - use core::fmt::{self, Octal}; - - pub fn octal(value: &T, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "0o{:o}", value) - } -} - -#[test] -fn test_fmt_path() { - fn unit(formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("unit=") - } - - fn pair(k: &i32, v: &i32, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "pair={k}:{v}") - } - - #[derive(Error, Debug)] - pub enum Error { - #[error(fmt = unit)] - Unit, - #[error(fmt = pair)] - Tuple(i32, i32), - #[error(fmt = pair)] - Entry { k: i32, v: i32 }, - #[error(fmt = crate::util::octal)] - I16(i16), - #[error(fmt = crate::util::octal::)] - I32 { n: i32 }, - #[error(fmt = core::fmt::Octal::fmt)] - I64(i64), - #[error("...{0}")] - Other(bool), - } - - assert("unit=", Error::Unit); - assert("pair=10:0", Error::Tuple(10, 0)); - assert("pair=10:0", Error::Entry { k: 10, v: 0 }); - assert("0o777", Error::I16(0o777)); - assert("0o777", Error::I32 { n: 0o777 }); - assert("777", Error::I64(0o777)); - assert("...false", Error::Other(false)); -} - -#[test] -fn test_fmt_path_inherited() { - #[derive(Error, Debug)] - #[error(fmt = crate::util::octal)] - pub enum Error { - I16(i16), - I32 { - n: i32, - }, - #[error(fmt = core::fmt::Octal::fmt)] - I64(i64), - #[error("...{0}")] - Other(bool), - } - - assert("0o777", Error::I16(0o777)); - assert("0o777", Error::I32 { n: 0o777 }); - assert("777", Error::I64(0o777)); - assert("...false", Error::Other(false)); -} diff --git a/subprojects/thiserror/tests/test_error.rs b/subprojects/thiserror/tests/test_error.rs deleted file mode 100644 index eb52cef..0000000 --- a/subprojects/thiserror/tests/test_error.rs +++ /dev/null @@ -1,56 +0,0 @@ -#![allow(dead_code)] - -use core::fmt::{self, Display}; -use std::io; -use thiserror::Error; - -macro_rules! unimplemented_display { - ($ty:ty) => { - impl Display for $ty { - fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { - unimplemented!() - } - } - }; -} - -#[derive(Error, Debug)] -struct BracedError { - msg: String, - pos: usize, -} - -#[derive(Error, Debug)] -struct TupleError(String, usize); - -#[derive(Error, Debug)] -struct UnitError; - -#[derive(Error, Debug)] -struct WithSource { - #[source] - cause: io::Error, -} - -#[derive(Error, Debug)] -struct WithAnyhow { - #[source] - cause: anyhow::Error, -} - -#[derive(Error, Debug)] -enum EnumError { - Braced { - #[source] - cause: io::Error, - }, - Tuple(#[source] io::Error), - Unit, -} - -unimplemented_display!(BracedError); -unimplemented_display!(TupleError); -unimplemented_display!(UnitError); -unimplemented_display!(WithSource); -unimplemented_display!(WithAnyhow); -unimplemented_display!(EnumError); diff --git a/subprojects/thiserror/tests/test_expr.rs b/subprojects/thiserror/tests/test_expr.rs deleted file mode 100644 index 1872fb5..0000000 --- a/subprojects/thiserror/tests/test_expr.rs +++ /dev/null @@ -1,118 +0,0 @@ -#![allow(clippy::iter_cloned_collect, clippy::uninlined_format_args)] - -use core::fmt::Display; -#[cfg(feature = "std")] -use std::path::PathBuf; -use thiserror::Error; - -// Some of the elaborate cases from the rcc codebase, which is a C compiler in -// Rust. https://github.com/jyn514/rcc/blob/0.8.0/src/data/error.rs -#[derive(Error, Debug)] -pub enum CompilerError { - #[error("cannot shift {} by {maximum} or more bits (got {current})", if *.is_left { "left" } else { "right" })] - TooManyShiftBits { - is_left: bool, - maximum: u64, - current: u64, - }, - - #[error("#error {}", (.0).iter().copied().collect::>().join(" "))] - User(Vec<&'static str>), - - #[error("overflow while parsing {}integer literal", - if let Some(signed) = .is_signed { - if *signed { "signed "} else { "unsigned "} - } else { - "" - } - )] - IntegerOverflow { is_signed: Option }, - - #[error("overflow while parsing {}integer literal", match .is_signed { - Some(true) => "signed ", - Some(false) => "unsigned ", - None => "", - })] - IntegerOverflow2 { is_signed: Option }, -} - -// Examples drawn from Rustup. -#[derive(Error, Debug)] -pub enum RustupError { - #[error( - "toolchain '{name}' does not contain component {component}{}", - .suggestion - .as_ref() - .map_or_else(String::new, |s| format!("; did you mean '{}'?", s)), - )] - UnknownComponent { - name: String, - component: String, - suggestion: Option, - }, -} - -#[track_caller] -fn assert(expected: &str, value: T) { - assert_eq!(expected, value.to_string()); -} - -#[test] -fn test_rcc() { - assert( - "cannot shift left by 32 or more bits (got 50)", - CompilerError::TooManyShiftBits { - is_left: true, - maximum: 32, - current: 50, - }, - ); - - assert("#error A B C", CompilerError::User(vec!["A", "B", "C"])); - - assert( - "overflow while parsing signed integer literal", - CompilerError::IntegerOverflow { - is_signed: Some(true), - }, - ); -} - -#[test] -fn test_rustup() { - assert( - "toolchain 'nightly' does not contain component clipy; did you mean 'clippy'?", - RustupError::UnknownComponent { - name: "nightly".to_owned(), - component: "clipy".to_owned(), - suggestion: Some("clippy".to_owned()), - }, - ); -} - -// Regression test for https://github.com/dtolnay/thiserror/issues/335 -#[cfg(feature = "std")] -#[test] -#[allow(non_snake_case)] -fn test_assoc_type_equality_constraint() { - pub trait Trait: Display { - type A; - } - - impl Trait for i32 { - type A = i32; - } - - #[derive(Error, Debug)] - #[error("{A} {b}", b = &0 as &dyn Trait)] - pub struct Error { - pub A: PathBuf, - } - - assert( - "... 0", - Error { - A: PathBuf::from("..."), - }, - ); -} diff --git a/subprojects/thiserror/tests/test_from.rs b/subprojects/thiserror/tests/test_from.rs deleted file mode 100644 index 51af40b..0000000 --- a/subprojects/thiserror/tests/test_from.rs +++ /dev/null @@ -1,64 +0,0 @@ -#![allow(clippy::extra_unused_type_parameters)] - -use std::io; -use thiserror::Error; - -#[derive(Error, Debug)] -#[error("...")] -pub struct ErrorStruct { - #[from] - source: io::Error, -} - -#[derive(Error, Debug)] -#[error("...")] -pub struct ErrorStructOptional { - #[from] - source: Option, -} - -#[derive(Error, Debug)] -#[error("...")] -pub struct ErrorTuple(#[from] io::Error); - -#[derive(Error, Debug)] -#[error("...")] -pub struct ErrorTupleOptional(#[from] Option); - -#[derive(Error, Debug)] -#[error("...")] -pub enum ErrorEnum { - Test { - #[from] - source: io::Error, - }, -} - -#[derive(Error, Debug)] -#[error("...")] -pub enum ErrorEnumOptional { - Test { - #[from] - source: Option, - }, -} - -#[derive(Error, Debug)] -#[error("...")] -pub enum Many { - Any(#[from] anyhow::Error), - Io(#[from] io::Error), -} - -fn assert_impl>() {} - -#[test] -fn test_from() { - assert_impl::(); - assert_impl::(); - assert_impl::(); - assert_impl::(); - assert_impl::(); - assert_impl::(); - assert_impl::(); -} diff --git a/subprojects/thiserror/tests/test_generics.rs b/subprojects/thiserror/tests/test_generics.rs deleted file mode 100644 index bcbfee0..0000000 --- a/subprojects/thiserror/tests/test_generics.rs +++ /dev/null @@ -1,205 +0,0 @@ -#![allow(clippy::needless_late_init, clippy::uninlined_format_args)] - -use core::fmt::{self, Debug, Display}; -use core::str::FromStr; -use thiserror::Error; - -pub struct NoFormat; - -#[derive(Debug)] -pub struct DebugOnly; - -pub struct DisplayOnly; - -impl Display for DisplayOnly { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str("display only") - } -} - -#[derive(Debug)] -pub struct DebugAndDisplay; - -impl Display for DebugAndDisplay { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str("debug and display") - } -} - -// Should expand to: -// -// impl Display for EnumDebugField -// where -// E: Debug; -// -// impl Error for EnumDebugField -// where -// Self: Debug + Display; -// -#[derive(Error, Debug)] -pub enum EnumDebugGeneric { - #[error("{0:?}")] - FatalError(E), -} - -// Should expand to: -// -// impl Display for EnumFromGeneric; -// -// impl Error for EnumFromGeneric -// where -// EnumDebugGeneric: Error + 'static, -// Self: Debug + Display; -// -#[derive(Error, Debug)] -pub enum EnumFromGeneric { - #[error("enum from generic")] - Source(#[from] EnumDebugGeneric), -} - -// Should expand to: -// -// impl Display -// for EnumCompound -// where -// HasDisplay: Display, -// HasDebug: Debug; -// -// impl Error -// for EnumCompound -// where -// Self: Debug + Display; -// -#[derive(Error)] -pub enum EnumCompound { - #[error("{0} {1:?}")] - DisplayDebug(HasDisplay, HasDebug), - #[error("{0}")] - Display(HasDisplay, HasNeither), - #[error("{1:?}")] - Debug(HasNeither, HasDebug), -} - -impl Debug for EnumCompound { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str("EnumCompound") - } -} - -#[test] -fn test_display_enum_compound() { - let mut instance: EnumCompound; - - instance = EnumCompound::DisplayDebug(DisplayOnly, DebugOnly); - assert_eq!(format!("{}", instance), "display only DebugOnly"); - - instance = EnumCompound::Display(DisplayOnly, NoFormat); - assert_eq!(format!("{}", instance), "display only"); - - instance = EnumCompound::Debug(NoFormat, DebugOnly); - assert_eq!(format!("{}", instance), "DebugOnly"); -} - -// Should expand to: -// -// impl Display for EnumTransparentGeneric -// where -// E: Display; -// -// impl Error for EnumTransparentGeneric -// where -// E: Error, -// Self: Debug + Display; -// -#[derive(Error, Debug)] -pub enum EnumTransparentGeneric { - #[error(transparent)] - Other(E), -} - -// Should expand to: -// -// impl Display for StructDebugGeneric -// where -// E: Debug; -// -// impl Error for StructDebugGeneric -// where -// Self: Debug + Display; -// -#[derive(Error, Debug)] -#[error("{underlying:?}")] -pub struct StructDebugGeneric { - pub underlying: E, -} - -// Should expand to: -// -// impl Error for StructFromGeneric -// where -// StructDebugGeneric: Error + 'static, -// Self: Debug + Display; -// -#[derive(Error, Debug)] -pub struct StructFromGeneric { - #[from] - pub source: StructDebugGeneric, -} - -// Should expand to: -// -// impl Display for StructTransparentGeneric -// where -// E: Display; -// -// impl Error for StructTransparentGeneric -// where -// E: Error, -// Self: Debug + Display; -// -#[derive(Error, Debug)] -#[error(transparent)] -pub struct StructTransparentGeneric(pub E); - -// Should expand to: -// -// impl Display for AssociatedTypeError -// where -// T::Err: Display; -// -// impl Error for AssociatedTypeError -// where -// Self: Debug + Display; -// -#[derive(Error, Debug)] -pub enum AssociatedTypeError { - #[error("couldn't parse matrix")] - Other, - #[error("couldn't parse entry: {0}")] - EntryParseError(T::Err), -} - -// Regression test for https://github.com/dtolnay/thiserror/issues/345 -#[test] -fn test_no_bound_on_named_fmt() { - #[derive(Error, Debug)] - #[error("{thing}", thing = "...")] - struct Error { - thing: T, - } - - let error = Error { thing: DebugOnly }; - assert_eq!(error.to_string(), "..."); -} - -#[test] -fn test_multiple_bound() { - #[derive(Error, Debug)] - #[error("0x{thing:x} 0x{thing:X}")] - pub struct Error { - thing: T, - } - - let error = Error { thing: 0xFFi32 }; - assert_eq!(error.to_string(), "0xff 0xFF"); -} diff --git a/subprojects/thiserror/tests/test_lints.rs b/subprojects/thiserror/tests/test_lints.rs deleted file mode 100644 index 802ad50..0000000 --- a/subprojects/thiserror/tests/test_lints.rs +++ /dev/null @@ -1,98 +0,0 @@ -#![allow(clippy::mixed_attributes_style)] - -use thiserror::Error; - -pub use std::error::Error; - -#[test] -fn test_allow_attributes() { - #![deny(clippy::allow_attributes)] - - #[derive(Error, Debug)] - #[error("...")] - pub struct MyError(#[from] anyhow::Error); - - let _: MyError; -} - -#[test] -fn test_unused_qualifications() { - #![deny(unused_qualifications)] - - // Expansion of derive(Error) macro can't know whether something like - // std::error::Error is already imported in the caller's scope so it must - // suppress unused_qualifications. - - #[derive(Error, Debug)] - #[error("...")] - pub struct MyError; - - let _: MyError; -} - -#[test] -fn test_needless_lifetimes() { - #![allow(dead_code)] - #![deny(clippy::elidable_lifetime_names, clippy::needless_lifetimes)] - - #[derive(Error, Debug)] - #[error("...")] - pub enum MyError<'a> { - A(#[from] std::io::Error), - B(&'a ()), - } - - let _: MyError; -} - -#[test] -fn test_deprecated() { - #![deny(deprecated)] - - #[derive(Error, Debug)] - #[deprecated] - #[error("...")] - pub struct DeprecatedStruct; - - #[derive(Error, Debug)] - #[error("{message} {}", .message)] - pub struct DeprecatedStructField { - #[deprecated] - message: String, - } - - #[derive(Error, Debug)] - #[deprecated] - pub enum DeprecatedEnum { - #[error("...")] - Variant, - } - - #[derive(Error, Debug)] - pub enum DeprecatedVariant { - #[deprecated] - #[error("...")] - Variant, - } - - #[derive(Error, Debug)] - pub enum DeprecatedFrom { - #[error(transparent)] - Variant( - #[from] - #[allow(deprecated)] - DeprecatedStruct, - ), - } - - #[allow(deprecated)] - let _: DeprecatedStruct; - #[allow(deprecated)] - let _: DeprecatedStructField; - #[allow(deprecated)] - let _ = DeprecatedEnum::Variant; - #[allow(deprecated)] - let _ = DeprecatedVariant::Variant; - #[allow(deprecated)] - let _ = DeprecatedFrom::Variant(DeprecatedStruct); -} diff --git a/subprojects/thiserror/tests/test_option.rs b/subprojects/thiserror/tests/test_option.rs deleted file mode 100644 index 21cd5e1..0000000 --- a/subprojects/thiserror/tests/test_option.rs +++ /dev/null @@ -1,109 +0,0 @@ -#![cfg(feature = "std")] -#![cfg_attr(thiserror_nightly_testing, feature(error_generic_member_access))] - -#[cfg(thiserror_nightly_testing)] -pub mod structs { - use std::backtrace::Backtrace; - use thiserror::Error; - - #[derive(Error, Debug)] - #[error("...")] - pub struct OptSourceNoBacktrace { - #[source] - pub source: Option, - } - - #[derive(Error, Debug)] - #[error("...")] - pub struct OptSourceAlwaysBacktrace { - #[source] - pub source: Option, - pub backtrace: Backtrace, - } - - #[derive(Error, Debug)] - #[error("...")] - pub struct NoSourceOptBacktrace { - #[backtrace] - pub backtrace: Option, - } - - #[derive(Error, Debug)] - #[error("...")] - pub struct AlwaysSourceOptBacktrace { - pub source: anyhow::Error, - #[backtrace] - pub backtrace: Option, - } - - #[derive(Error, Debug)] - #[error("...")] - pub struct OptSourceOptBacktrace { - #[source] - pub source: Option, - #[backtrace] - pub backtrace: Option, - } -} - -#[cfg(thiserror_nightly_testing)] -pub mod enums { - use std::backtrace::Backtrace; - use thiserror::Error; - - #[derive(Error, Debug)] - pub enum OptSourceNoBacktrace { - #[error("...")] - Test { - #[source] - source: Option, - }, - } - - #[derive(Error, Debug)] - pub enum OptSourceAlwaysBacktrace { - #[error("...")] - Test { - #[source] - source: Option, - backtrace: Backtrace, - }, - } - - #[derive(Error, Debug)] - pub enum NoSourceOptBacktrace { - #[error("...")] - Test { - #[backtrace] - backtrace: Option, - }, - } - - #[derive(Error, Debug)] - pub enum AlwaysSourceOptBacktrace { - #[error("...")] - Test { - source: anyhow::Error, - #[backtrace] - backtrace: Option, - }, - } - - #[derive(Error, Debug)] - pub enum OptSourceOptBacktrace { - #[error("...")] - Test { - #[source] - source: Option, - #[backtrace] - backtrace: Option, - }, - } -} - -#[test] -#[cfg_attr( - not(thiserror_nightly_testing), - ignore = "requires `--cfg=thiserror_nightly_testing`" -)] -fn test_option() {} diff --git a/subprojects/thiserror/tests/test_path.rs b/subprojects/thiserror/tests/test_path.rs deleted file mode 100644 index fa85c1d..0000000 --- a/subprojects/thiserror/tests/test_path.rs +++ /dev/null @@ -1,54 +0,0 @@ -#![cfg(feature = "std")] - -use core::fmt::Display; -use ref_cast::RefCast; -use std::path::{Path, PathBuf}; -use thiserror::Error; - -#[derive(Error, Debug)] -#[error("failed to read '{file}'")] -struct StructPathBuf { - file: PathBuf, -} - -#[derive(Error, Debug, RefCast)] -#[repr(C)] -#[error("failed to read '{file}'")] -struct StructPath { - file: Path, -} - -#[derive(Error, Debug)] -enum EnumPathBuf { - #[error("failed to read '{0}'")] - Read(PathBuf), -} - -#[derive(Error, Debug)] -#[error("{tail}")] -pub struct UnsizedError { - pub head: i32, - pub tail: str, -} - -#[derive(Error, Debug)] -pub enum BothError { - #[error("display:{0} debug:{0:?}")] - DisplayDebug(PathBuf), - #[error("debug:{0:?} display:{0}")] - DebugDisplay(PathBuf), -} - -fn assert(expected: &str, value: T) { - assert_eq!(expected, value.to_string()); -} - -#[test] -fn test_display() { - let path = Path::new("/thiserror"); - let file = path.to_owned(); - assert("failed to read '/thiserror'", StructPathBuf { file }); - let file = path.to_owned(); - assert("failed to read '/thiserror'", EnumPathBuf::Read(file)); - assert("failed to read '/thiserror'", StructPath::ref_cast(path)); -} diff --git a/subprojects/thiserror/tests/test_source.rs b/subprojects/thiserror/tests/test_source.rs deleted file mode 100644 index 29968be..0000000 --- a/subprojects/thiserror/tests/test_source.rs +++ /dev/null @@ -1,82 +0,0 @@ -use std::error::Error as StdError; -use std::io; -use thiserror::Error; - -#[derive(Error, Debug)] -#[error("implicit source")] -pub struct ImplicitSource { - source: io::Error, -} - -#[derive(Error, Debug)] -#[error("explicit source")] -pub struct ExplicitSource { - source: String, - #[source] - io: io::Error, -} - -#[derive(Error, Debug)] -#[error("boxed source")] -pub struct BoxedSource { - #[source] - source: Box, -} - -#[test] -fn test_implicit_source() { - let io = io::Error::new(io::ErrorKind::Other, "oh no!"); - let error = ImplicitSource { source: io }; - error.source().unwrap().downcast_ref::().unwrap(); -} - -#[test] -fn test_explicit_source() { - let io = io::Error::new(io::ErrorKind::Other, "oh no!"); - let error = ExplicitSource { - source: String::new(), - io, - }; - error.source().unwrap().downcast_ref::().unwrap(); -} - -#[test] -fn test_boxed_source() { - let source = Box::new(io::Error::new(io::ErrorKind::Other, "oh no!")); - let error = BoxedSource { source }; - error.source().unwrap().downcast_ref::().unwrap(); -} - -macro_rules! error_from_macro { - ($($variants:tt)*) => { - #[derive(Error)] - #[derive(Debug)] - pub enum MacroSource { - $($variants)* - } - } -} - -// Test that we generate impls with the proper hygiene -#[rustfmt::skip] -error_from_macro! { - #[error("Something")] - Variant(#[from] io::Error) -} - -#[test] -fn test_not_source() { - #[derive(Error, Debug)] - #[error("{source} ==> {destination}")] - pub struct NotSource { - r#source: char, - destination: char, - } - - let error = NotSource { - source: 'S', - destination: 'D', - }; - assert_eq!(error.to_string(), "S ==> D"); - assert!(error.source().is_none()); -} diff --git a/subprojects/thiserror/tests/test_transparent.rs b/subprojects/thiserror/tests/test_transparent.rs deleted file mode 100644 index ee30f5b..0000000 --- a/subprojects/thiserror/tests/test_transparent.rs +++ /dev/null @@ -1,96 +0,0 @@ -use anyhow::anyhow; -use std::error::Error as _; -use std::io; -use thiserror::Error; - -#[test] -fn test_transparent_struct() { - #[derive(Error, Debug)] - #[error(transparent)] - struct Error(ErrorKind); - - #[derive(Error, Debug)] - enum ErrorKind { - #[error("E0")] - E0, - #[error("E1")] - E1(#[from] io::Error), - } - - let error = Error(ErrorKind::E0); - assert_eq!("E0", error.to_string()); - assert!(error.source().is_none()); - - let io = io::Error::new(io::ErrorKind::Other, "oh no!"); - let error = Error(ErrorKind::from(io)); - assert_eq!("E1", error.to_string()); - error.source().unwrap().downcast_ref::().unwrap(); -} - -#[test] -fn test_transparent_enum() { - #[derive(Error, Debug)] - enum Error { - #[error("this failed")] - This, - #[error(transparent)] - Other(anyhow::Error), - } - - let error = Error::This; - assert_eq!("this failed", error.to_string()); - - let error = Error::Other(anyhow!("inner").context("outer")); - assert_eq!("outer", error.to_string()); - assert_eq!("inner", error.source().unwrap().to_string()); -} - -#[test] -fn test_transparent_enum_with_default_message() { - #[derive(Error, Debug)] - #[error("this failed: {0}_{1}")] - enum Error { - This(i32, i32), - #[error(transparent)] - Other(anyhow::Error), - } - - let error = Error::This(-1, -1); - assert_eq!("this failed: -1_-1", error.to_string()); - - let error = Error::Other(anyhow!("inner").context("outer")); - assert_eq!("outer", error.to_string()); - assert_eq!("inner", error.source().unwrap().to_string()); -} - -#[test] -fn test_anyhow() { - #[derive(Error, Debug)] - #[error(transparent)] - struct Any(#[from] anyhow::Error); - - let error = Any::from(anyhow!("inner").context("outer")); - assert_eq!("outer", error.to_string()); - assert_eq!("inner", error.source().unwrap().to_string()); -} - -#[test] -fn test_non_static() { - #[derive(Error, Debug)] - #[error(transparent)] - struct Error<'a> { - inner: ErrorKind<'a>, - } - - #[derive(Error, Debug)] - enum ErrorKind<'a> { - #[error("unexpected token: {:?}", token)] - Unexpected { token: &'a str }, - } - - let error = Error { - inner: ErrorKind::Unexpected { token: "error" }, - }; - assert_eq!("unexpected token: \"error\"", error.to_string()); - assert!(error.source().is_none()); -} diff --git a/subprojects/thiserror/tests/ui/bad-field-attr.rs b/subprojects/thiserror/tests/ui/bad-field-attr.rs deleted file mode 100644 index d5429b2..0000000 --- a/subprojects/thiserror/tests/ui/bad-field-attr.rs +++ /dev/null @@ -1,7 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -#[error(transparent)] -pub struct Error(#[error(transparent)] std::io::Error); - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/bad-field-attr.stderr b/subprojects/thiserror/tests/ui/bad-field-attr.stderr deleted file mode 100644 index 5fb5744..0000000 --- a/subprojects/thiserror/tests/ui/bad-field-attr.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: #[error(transparent)] needs to go outside the enum or struct, not on an individual field - --> tests/ui/bad-field-attr.rs:5:18 - | -5 | pub struct Error(#[error(transparent)] std::io::Error); - | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/subprojects/thiserror/tests/ui/concat-display.rs b/subprojects/thiserror/tests/ui/concat-display.rs deleted file mode 100644 index 8b53cc0..0000000 --- a/subprojects/thiserror/tests/ui/concat-display.rs +++ /dev/null @@ -1,15 +0,0 @@ -use thiserror::Error; - -macro_rules! error_type { - ($name:ident, $what:expr) => { - // Use #[error("invalid {}", $what)] instead. - - #[derive(Error, Debug)] - #[error(concat!("invalid ", $what))] - pub struct $name; - }; -} - -error_type!(Error, "foo"); - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/concat-display.stderr b/subprojects/thiserror/tests/ui/concat-display.stderr deleted file mode 100644 index 73718ae..0000000 --- a/subprojects/thiserror/tests/ui/concat-display.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: expected one of: string literal, `transparent`, `fmt` - --> tests/ui/concat-display.rs:8:17 - | - 8 | #[error(concat!("invalid ", $what))] - | ^^^^^^ -... -13 | error_type!(Error, "foo"); - | ------------------------- in this macro invocation - | - = note: this error originates in the macro `error_type` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/subprojects/thiserror/tests/ui/display-underscore.rs b/subprojects/thiserror/tests/ui/display-underscore.rs deleted file mode 100644 index 335614b..0000000 --- a/subprojects/thiserror/tests/ui/display-underscore.rs +++ /dev/null @@ -1,7 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -#[error("{_}")] -pub struct Error; - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/display-underscore.stderr b/subprojects/thiserror/tests/ui/display-underscore.stderr deleted file mode 100644 index 36882b9..0000000 --- a/subprojects/thiserror/tests/ui/display-underscore.stderr +++ /dev/null @@ -1,7 +0,0 @@ -error: invalid format string: invalid argument name `_` - --> tests/ui/display-underscore.rs:4:11 - | -4 | #[error("{_}")] - | ^ invalid argument name in format string - | - = note: argument name cannot be a single underscore diff --git a/subprojects/thiserror/tests/ui/duplicate-enum-source.rs b/subprojects/thiserror/tests/ui/duplicate-enum-source.rs deleted file mode 100644 index 15e579f..0000000 --- a/subprojects/thiserror/tests/ui/duplicate-enum-source.rs +++ /dev/null @@ -1,13 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum ErrorEnum { - Confusing { - #[source] - a: std::io::Error, - #[source] - b: anyhow::Error, - }, -} - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/duplicate-enum-source.stderr b/subprojects/thiserror/tests/ui/duplicate-enum-source.stderr deleted file mode 100644 index 4a4b2d3..0000000 --- a/subprojects/thiserror/tests/ui/duplicate-enum-source.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: duplicate #[source] attribute - --> tests/ui/duplicate-enum-source.rs:8:9 - | -8 | #[source] - | ^^^^^^^^^ diff --git a/subprojects/thiserror/tests/ui/duplicate-fmt.rs b/subprojects/thiserror/tests/ui/duplicate-fmt.rs deleted file mode 100644 index 32f7a23..0000000 --- a/subprojects/thiserror/tests/ui/duplicate-fmt.rs +++ /dev/null @@ -1,23 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -#[error("...")] -#[error("...")] -pub struct Error; - -#[derive(Error, Debug)] -#[error(fmt = core::fmt::Octal::fmt)] -#[error(fmt = core::fmt::LowerHex::fmt)] -pub enum FmtFmt {} - -#[derive(Error, Debug)] -#[error(fmt = core::fmt::Octal::fmt)] -#[error(transparent)] -pub enum FmtTransparent {} - -#[derive(Error, Debug)] -#[error(fmt = core::fmt::Octal::fmt)] -#[error("...")] -pub enum FmtDisplay {} - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/duplicate-fmt.stderr b/subprojects/thiserror/tests/ui/duplicate-fmt.stderr deleted file mode 100644 index a6c9932..0000000 --- a/subprojects/thiserror/tests/ui/duplicate-fmt.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error: only one #[error(...)] attribute is allowed - --> tests/ui/duplicate-fmt.rs:5:1 - | -5 | #[error("...")] - | ^^^^^^^^^^^^^^^ - -error: duplicate #[error(fmt = ...)] attribute - --> tests/ui/duplicate-fmt.rs:10:1 - | -10 | #[error(fmt = core::fmt::LowerHex::fmt)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: cannot have both #[error(transparent)] and #[error(fmt = ...)] - --> tests/ui/duplicate-fmt.rs:14:1 - | -14 | #[error(fmt = core::fmt::Octal::fmt)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: cannot have both #[error(fmt = ...)] and a format arguments attribute - --> tests/ui/duplicate-fmt.rs:20:1 - | -20 | #[error("...")] - | ^^^^^^^^^^^^^^^ diff --git a/subprojects/thiserror/tests/ui/duplicate-struct-source.rs b/subprojects/thiserror/tests/ui/duplicate-struct-source.rs deleted file mode 100644 index 569df8d..0000000 --- a/subprojects/thiserror/tests/ui/duplicate-struct-source.rs +++ /dev/null @@ -1,11 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -pub struct ErrorStruct { - #[source] - a: std::io::Error, - #[source] - b: anyhow::Error, -} - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/duplicate-struct-source.stderr b/subprojects/thiserror/tests/ui/duplicate-struct-source.stderr deleted file mode 100644 index c8de574..0000000 --- a/subprojects/thiserror/tests/ui/duplicate-struct-source.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: duplicate #[source] attribute - --> tests/ui/duplicate-struct-source.rs:7:5 - | -7 | #[source] - | ^^^^^^^^^ diff --git a/subprojects/thiserror/tests/ui/duplicate-transparent.rs b/subprojects/thiserror/tests/ui/duplicate-transparent.rs deleted file mode 100644 index 49c0e46..0000000 --- a/subprojects/thiserror/tests/ui/duplicate-transparent.rs +++ /dev/null @@ -1,8 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -#[error(transparent)] -#[error(transparent)] -pub struct Error(anyhow::Error); - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/duplicate-transparent.stderr b/subprojects/thiserror/tests/ui/duplicate-transparent.stderr deleted file mode 100644 index a830879..0000000 --- a/subprojects/thiserror/tests/ui/duplicate-transparent.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: duplicate #[error(transparent)] attribute - --> tests/ui/duplicate-transparent.rs:5:1 - | -5 | #[error(transparent)] - | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/subprojects/thiserror/tests/ui/expression-fallback.rs b/subprojects/thiserror/tests/ui/expression-fallback.rs deleted file mode 100644 index 7269129..0000000 --- a/subprojects/thiserror/tests/ui/expression-fallback.rs +++ /dev/null @@ -1,7 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -#[error("".yellow)] -pub struct ArgError; - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/expression-fallback.stderr b/subprojects/thiserror/tests/ui/expression-fallback.stderr deleted file mode 100644 index 8d22c3a..0000000 --- a/subprojects/thiserror/tests/ui/expression-fallback.stderr +++ /dev/null @@ -1,24 +0,0 @@ -error: expected `,`, found `.` - --> tests/ui/expression-fallback.rs:4:11 - | -4 | #[error("".yellow)] - | ^ expected `,` - -error: argument never used - --> tests/ui/expression-fallback.rs:4:12 - | -4 | #[error("".yellow)] - | -- ^^^^^^ argument never used - | | - | formatting specifier missing - | -help: format specifiers use curly braces, consider adding a format specifier - | -4 | #[error("{}".yellow)] - | ++ - -error[E0425]: cannot find value `yellow` in this scope - --> tests/ui/expression-fallback.rs:4:12 - | -4 | #[error("".yellow)] - | ^^^^^^ not found in this scope diff --git a/subprojects/thiserror/tests/ui/fallback-impl-with-display.rs b/subprojects/thiserror/tests/ui/fallback-impl-with-display.rs deleted file mode 100644 index 23dcf28..0000000 --- a/subprojects/thiserror/tests/ui/fallback-impl-with-display.rs +++ /dev/null @@ -1,14 +0,0 @@ -use core::fmt::{self, Display}; -use thiserror::Error; - -#[derive(Error, Debug)] -#[error] -pub struct MyError; - -impl Display for MyError { - fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { - unimplemented!() - } -} - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/fallback-impl-with-display.stderr b/subprojects/thiserror/tests/ui/fallback-impl-with-display.stderr deleted file mode 100644 index 6bd3730..0000000 --- a/subprojects/thiserror/tests/ui/fallback-impl-with-display.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error: expected attribute arguments in parentheses: #[error(...)] - --> tests/ui/fallback-impl-with-display.rs:5:3 - | -5 | #[error] - | ^^^^^ - -error[E0119]: conflicting implementations of trait `std::fmt::Display` for type `MyError` - --> tests/ui/fallback-impl-with-display.rs:4:10 - | -4 | #[derive(Error, Debug)] - | ^^^^^ conflicting implementation for `MyError` -... -8 | impl Display for MyError { - | ------------------------ first implementation here - | - = note: this error originates in the derive macro `Error` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/subprojects/thiserror/tests/ui/from-backtrace-backtrace.rs b/subprojects/thiserror/tests/ui/from-backtrace-backtrace.rs deleted file mode 100644 index 3b781ac..0000000 --- a/subprojects/thiserror/tests/ui/from-backtrace-backtrace.rs +++ /dev/null @@ -1,15 +0,0 @@ -// https://github.com/dtolnay/thiserror/issues/163 - -use std::backtrace::Backtrace; -use thiserror::Error; - -#[derive(Error, Debug)] -#[error("...")] -pub struct Error( - #[from] - #[backtrace] - std::io::Error, - Backtrace, -); - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/from-backtrace-backtrace.stderr b/subprojects/thiserror/tests/ui/from-backtrace-backtrace.stderr deleted file mode 100644 index 5c0b9a3..0000000 --- a/subprojects/thiserror/tests/ui/from-backtrace-backtrace.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: deriving From requires no fields other than source and backtrace - --> tests/ui/from-backtrace-backtrace.rs:9:5 - | -9 | #[from] - | ^^^^^^^ diff --git a/subprojects/thiserror/tests/ui/from-not-source.rs b/subprojects/thiserror/tests/ui/from-not-source.rs deleted file mode 100644 index ad72867..0000000 --- a/subprojects/thiserror/tests/ui/from-not-source.rs +++ /dev/null @@ -1,11 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -pub struct Error { - #[source] - source: std::io::Error, - #[from] - other: anyhow::Error, -} - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/from-not-source.stderr b/subprojects/thiserror/tests/ui/from-not-source.stderr deleted file mode 100644 index 9713601..0000000 --- a/subprojects/thiserror/tests/ui/from-not-source.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: #[from] is only supported on the source field, not any other field - --> tests/ui/from-not-source.rs:7:5 - | -7 | #[from] - | ^^^^^^^ diff --git a/subprojects/thiserror/tests/ui/invalid-input-impl-anyway.rs b/subprojects/thiserror/tests/ui/invalid-input-impl-anyway.rs deleted file mode 100644 index 0a0bcbe..0000000 --- a/subprojects/thiserror/tests/ui/invalid-input-impl-anyway.rs +++ /dev/null @@ -1,11 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -#[error] -pub struct MyError; - -fn main() { - // No error on the following line. Thiserror emits an Error impl despite the - // bad attribute. - _ = &MyError as &dyn std::error::Error; -} diff --git a/subprojects/thiserror/tests/ui/invalid-input-impl-anyway.stderr b/subprojects/thiserror/tests/ui/invalid-input-impl-anyway.stderr deleted file mode 100644 index b98c31e..0000000 --- a/subprojects/thiserror/tests/ui/invalid-input-impl-anyway.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: expected attribute arguments in parentheses: #[error(...)] - --> tests/ui/invalid-input-impl-anyway.rs:4:3 - | -4 | #[error] - | ^^^^^ diff --git a/subprojects/thiserror/tests/ui/lifetime.rs b/subprojects/thiserror/tests/ui/lifetime.rs deleted file mode 100644 index a82909d..0000000 --- a/subprojects/thiserror/tests/ui/lifetime.rs +++ /dev/null @@ -1,24 +0,0 @@ -use core::fmt::Debug; -use thiserror::Error; - -#[derive(Error, Debug)] -#[error("error")] -struct Error<'a>(#[from] Inner<'a>); - -#[derive(Error, Debug)] -#[error("{0}")] -struct Inner<'a>(&'a str); - -#[derive(Error, Debug)] -enum Enum<'a> { - #[error("error")] - Foo(#[from] Generic<&'a str>), -} - -#[derive(Error, Debug)] -#[error("{0:?}")] -struct Generic(T); - -fn main() -> Result<(), Error<'static>> { - Err(Error(Inner("some text"))) -} diff --git a/subprojects/thiserror/tests/ui/lifetime.stderr b/subprojects/thiserror/tests/ui/lifetime.stderr deleted file mode 100644 index 8b58136..0000000 --- a/subprojects/thiserror/tests/ui/lifetime.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: non-static lifetimes are not allowed in the source of an error, because std::error::Error requires the source is dyn Error + 'static - --> tests/ui/lifetime.rs:6:26 - | -6 | struct Error<'a>(#[from] Inner<'a>); - | ^^^^^^^^^ - -error: non-static lifetimes are not allowed in the source of an error, because std::error::Error requires the source is dyn Error + 'static - --> tests/ui/lifetime.rs:15:17 - | -15 | Foo(#[from] Generic<&'a str>), - | ^^^^^^^^^^^^^^^^ diff --git a/subprojects/thiserror/tests/ui/missing-display.rs b/subprojects/thiserror/tests/ui/missing-display.rs deleted file mode 100644 index 31e23fe..0000000 --- a/subprojects/thiserror/tests/ui/missing-display.rs +++ /dev/null @@ -1,9 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum MyError { - First, - Second, -} - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/missing-display.stderr b/subprojects/thiserror/tests/ui/missing-display.stderr deleted file mode 100644 index fe7472e..0000000 --- a/subprojects/thiserror/tests/ui/missing-display.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0277]: `MyError` doesn't implement `std::fmt::Display` - --> tests/ui/missing-display.rs:4:10 - | -3 | #[derive(Error, Debug)] - | ----- in this derive macro expansion -4 | pub enum MyError { - | ^^^^^^^ unsatisfied trait bound - | -help: the trait `std::fmt::Display` is not implemented for `MyError` - --> tests/ui/missing-display.rs:4:1 - | -4 | pub enum MyError { - | ^^^^^^^^^^^^^^^^ -note: required by a bound in `std::error::Error` - --> $RUST/core/src/error.rs - | - | pub trait Error: Debug + Display { - | ^^^^^^^ required by this bound in `Error` - = note: this error originates in the derive macro `Error` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/subprojects/thiserror/tests/ui/missing-fmt.rs b/subprojects/thiserror/tests/ui/missing-fmt.rs deleted file mode 100644 index d52fbdf..0000000 --- a/subprojects/thiserror/tests/ui/missing-fmt.rs +++ /dev/null @@ -1,10 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum Error { - #[error("...")] - A(usize), - B(usize), -} - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/missing-fmt.stderr b/subprojects/thiserror/tests/ui/missing-fmt.stderr deleted file mode 100644 index c0be373..0000000 --- a/subprojects/thiserror/tests/ui/missing-fmt.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: missing #[error("...")] display attribute - --> tests/ui/missing-fmt.rs:7:5 - | -7 | B(usize), - | ^^^^^^^^ diff --git a/subprojects/thiserror/tests/ui/no-display.rs b/subprojects/thiserror/tests/ui/no-display.rs deleted file mode 100644 index d804e00..0000000 --- a/subprojects/thiserror/tests/ui/no-display.rs +++ /dev/null @@ -1,18 +0,0 @@ -use thiserror::Error; - -#[derive(Debug)] -struct NoDisplay; - -#[derive(Error, Debug)] -#[error("thread: {thread}")] -pub struct Error { - thread: NoDisplay, -} - -#[derive(Error, Debug)] -#[error("thread: {thread:o}")] -pub struct ErrorOctal { - thread: NoDisplay, -} - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/no-display.stderr b/subprojects/thiserror/tests/ui/no-display.stderr deleted file mode 100644 index 9750582..0000000 --- a/subprojects/thiserror/tests/ui/no-display.stderr +++ /dev/null @@ -1,46 +0,0 @@ -error[E0599]: the method `as_display` exists for reference `&NoDisplay`, but its trait bounds were not satisfied - --> tests/ui/no-display.rs:7:9 - | -4 | struct NoDisplay; - | ---------------- doesn't satisfy `NoDisplay: std::fmt::Display` -... -7 | #[error("thread: {thread}")] - | ^^^^^^^^^^^^^^^^^^ method cannot be called on `&NoDisplay` due to unsatisfied trait bounds - | - = note: the following trait bounds were not satisfied: - `NoDisplay: std::fmt::Display` - which is required by `&NoDisplay: AsDisplay<'_>` -note: the trait `std::fmt::Display` must be implemented - --> $RUST/core/src/fmt/mod.rs - | - | pub trait Display: PointeeSized { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `as_display`, perhaps you need to implement it: - candidate #1: `AsDisplay` - -error[E0277]: the trait bound `NoDisplay: Octal` is not satisfied - --> tests/ui/no-display.rs:13:9 - | -12 | #[derive(Error, Debug)] - | ----- in this derive macro expansion -13 | #[error("thread: {thread:o}")] - | ^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound - | -help: the trait `Octal` is not implemented for `NoDisplay` - --> tests/ui/no-display.rs:4:1 - | - 4 | struct NoDisplay; - | ^^^^^^^^^^^^^^^^ - = help: the following other types implement trait `Octal`: - &T - &mut T - NonZero - Saturating - Wrapping - i128 - i16 - i32 - and $N others - = note: required for `&NoDisplay` to implement `Octal` - = note: this error originates in the macro `$crate::format_args` which comes from the expansion of the derive macro `Error` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/subprojects/thiserror/tests/ui/numbered-positional-tuple.rs b/subprojects/thiserror/tests/ui/numbered-positional-tuple.rs deleted file mode 100644 index 6deb658..0000000 --- a/subprojects/thiserror/tests/ui/numbered-positional-tuple.rs +++ /dev/null @@ -1,7 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -#[error("invalid rdo_lookahead_frames {0} (expected < {})", i32::MAX)] -pub struct Error(u32); - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/numbered-positional-tuple.stderr b/subprojects/thiserror/tests/ui/numbered-positional-tuple.stderr deleted file mode 100644 index ab13371..0000000 --- a/subprojects/thiserror/tests/ui/numbered-positional-tuple.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: ambiguous reference to positional arguments by number in a tuple struct; change this to a named argument - --> tests/ui/numbered-positional-tuple.rs:4:61 - | -4 | #[error("invalid rdo_lookahead_frames {0} (expected < {})", i32::MAX)] - | ^^^^^^^^ diff --git a/subprojects/thiserror/tests/ui/raw-identifier.rs b/subprojects/thiserror/tests/ui/raw-identifier.rs deleted file mode 100644 index e7e66d0..0000000 --- a/subprojects/thiserror/tests/ui/raw-identifier.rs +++ /dev/null @@ -1,12 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -#[error("error: {r#fn}")] -pub struct Error { - r#fn: &'static str, -} - -fn main() { - let r#fn = "..."; - let _ = format!("error: {r#fn}"); -} diff --git a/subprojects/thiserror/tests/ui/raw-identifier.stderr b/subprojects/thiserror/tests/ui/raw-identifier.stderr deleted file mode 100644 index a3ce94d..0000000 --- a/subprojects/thiserror/tests/ui/raw-identifier.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error: invalid format string: raw identifiers are not supported - --> tests/ui/raw-identifier.rs:4:18 - | -4 | #[error("error: {r#fn}")] - | --^^ - | | - | raw identifier used here in format string - | help: remove the `r#` - | - = note: identifiers in format strings can be keywords and don't need to be prefixed with `r#` - -error: invalid format string: raw identifiers are not supported - --> tests/ui/raw-identifier.rs:11:30 - | -11 | let _ = format!("error: {r#fn}"); - | --^^ - | | - | raw identifier used here in format string - | help: remove the `r#` - | - = note: identifiers in format strings can be keywords and don't need to be prefixed with `r#` diff --git a/subprojects/thiserror/tests/ui/same-from-type.rs b/subprojects/thiserror/tests/ui/same-from-type.rs deleted file mode 100644 index 0ebdf45..0000000 --- a/subprojects/thiserror/tests/ui/same-from-type.rs +++ /dev/null @@ -1,11 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum Error { - #[error("failed to open")] - OpenFile(#[from] std::io::Error), - #[error("failed to close")] - CloseFile(#[from] std::io::Error), -} - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/same-from-type.stderr b/subprojects/thiserror/tests/ui/same-from-type.stderr deleted file mode 100644 index a655163..0000000 --- a/subprojects/thiserror/tests/ui/same-from-type.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error[E0119]: conflicting implementations of trait `From` for type `Error` - --> tests/ui/same-from-type.rs:8:15 - | -6 | OpenFile(#[from] std::io::Error), - | ------- first implementation here -7 | #[error("failed to close")] -8 | CloseFile(#[from] std::io::Error), - | ^^^^^^^ conflicting implementation for `Error` diff --git a/subprojects/thiserror/tests/ui/source-enum-not-error.rs b/subprojects/thiserror/tests/ui/source-enum-not-error.rs deleted file mode 100644 index dae2285..0000000 --- a/subprojects/thiserror/tests/ui/source-enum-not-error.rs +++ /dev/null @@ -1,12 +0,0 @@ -use thiserror::Error; - -#[derive(Debug)] -pub struct NotError; - -#[derive(Error, Debug)] -#[error("...")] -pub enum ErrorEnum { - Broken { source: NotError }, -} - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/source-enum-not-error.stderr b/subprojects/thiserror/tests/ui/source-enum-not-error.stderr deleted file mode 100644 index 649d77d..0000000 --- a/subprojects/thiserror/tests/ui/source-enum-not-error.stderr +++ /dev/null @@ -1,22 +0,0 @@ -error[E0599]: the method `as_dyn_error` exists for reference `&NotError`, but its trait bounds were not satisfied - --> tests/ui/source-enum-not-error.rs:9:14 - | -4 | pub struct NotError; - | ------------------- doesn't satisfy `NotError: AsDynError<'_>` or `NotError: std::error::Error` -... -9 | Broken { source: NotError }, - | ^^^^^^ method cannot be called on `&NotError` due to unsatisfied trait bounds - | - = note: the following trait bounds were not satisfied: - `NotError: std::error::Error` - which is required by `NotError: AsDynError<'_>` - `&NotError: std::error::Error` - which is required by `&NotError: AsDynError<'_>` -note: the trait `std::error::Error` must be implemented - --> $RUST/core/src/error.rs - | - | pub trait Error: Debug + Display { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `as_dyn_error`, perhaps you need to implement it: - candidate #1: `AsDynError` diff --git a/subprojects/thiserror/tests/ui/source-enum-unnamed-field-not-error.rs b/subprojects/thiserror/tests/ui/source-enum-unnamed-field-not-error.rs deleted file mode 100644 index a877c2c..0000000 --- a/subprojects/thiserror/tests/ui/source-enum-unnamed-field-not-error.rs +++ /dev/null @@ -1,12 +0,0 @@ -use thiserror::Error; - -#[derive(Debug)] -pub struct NotError; - -#[derive(Error, Debug)] -#[error("...")] -pub enum ErrorEnum { - Broken(#[source] NotError), -} - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/source-enum-unnamed-field-not-error.stderr b/subprojects/thiserror/tests/ui/source-enum-unnamed-field-not-error.stderr deleted file mode 100644 index dc97a4b..0000000 --- a/subprojects/thiserror/tests/ui/source-enum-unnamed-field-not-error.stderr +++ /dev/null @@ -1,22 +0,0 @@ -error[E0599]: the method `as_dyn_error` exists for reference `&NotError`, but its trait bounds were not satisfied - --> tests/ui/source-enum-unnamed-field-not-error.rs:9:12 - | -4 | pub struct NotError; - | ------------------- doesn't satisfy `NotError: AsDynError<'_>` or `NotError: std::error::Error` -... -9 | Broken(#[source] NotError), - | ^^^^^^^^^ method cannot be called on `&NotError` due to unsatisfied trait bounds - | - = note: the following trait bounds were not satisfied: - `NotError: std::error::Error` - which is required by `NotError: AsDynError<'_>` - `&NotError: std::error::Error` - which is required by `&NotError: AsDynError<'_>` -note: the trait `std::error::Error` must be implemented - --> $RUST/core/src/error.rs - | - | pub trait Error: Debug + Display { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `as_dyn_error`, perhaps you need to implement it: - candidate #1: `AsDynError` diff --git a/subprojects/thiserror/tests/ui/source-struct-not-error.rs b/subprojects/thiserror/tests/ui/source-struct-not-error.rs deleted file mode 100644 index d59df1e..0000000 --- a/subprojects/thiserror/tests/ui/source-struct-not-error.rs +++ /dev/null @@ -1,12 +0,0 @@ -use thiserror::Error; - -#[derive(Debug)] -struct NotError; - -#[derive(Error, Debug)] -#[error("...")] -pub struct ErrorStruct { - source: NotError, -} - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/source-struct-not-error.stderr b/subprojects/thiserror/tests/ui/source-struct-not-error.stderr deleted file mode 100644 index 07cd67a..0000000 --- a/subprojects/thiserror/tests/ui/source-struct-not-error.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0599]: the method `as_dyn_error` exists for struct `NotError`, but its trait bounds were not satisfied - --> tests/ui/source-struct-not-error.rs:9:5 - | -4 | struct NotError; - | --------------- method `as_dyn_error` not found for this struct because it doesn't satisfy `NotError: AsDynError<'_>` or `NotError: std::error::Error` -... -9 | source: NotError, - | ^^^^^^ method cannot be called on `NotError` due to unsatisfied trait bounds - | - = note: the following trait bounds were not satisfied: - `NotError: std::error::Error` - which is required by `NotError: AsDynError<'_>` -note: the trait `std::error::Error` must be implemented - --> $RUST/core/src/error.rs - | - | pub trait Error: Debug + Display { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `as_dyn_error`, perhaps you need to implement it: - candidate #1: `AsDynError` diff --git a/subprojects/thiserror/tests/ui/source-struct-unnamed-field-not-error.rs b/subprojects/thiserror/tests/ui/source-struct-unnamed-field-not-error.rs deleted file mode 100644 index 160b6b2..0000000 --- a/subprojects/thiserror/tests/ui/source-struct-unnamed-field-not-error.rs +++ /dev/null @@ -1,10 +0,0 @@ -use thiserror::Error; - -#[derive(Debug)] -struct NotError; - -#[derive(Error, Debug)] -#[error("...")] -pub struct ErrorStruct(#[source] NotError); - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/source-struct-unnamed-field-not-error.stderr b/subprojects/thiserror/tests/ui/source-struct-unnamed-field-not-error.stderr deleted file mode 100644 index 1f5350b..0000000 --- a/subprojects/thiserror/tests/ui/source-struct-unnamed-field-not-error.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0599]: the method `as_dyn_error` exists for struct `NotError`, but its trait bounds were not satisfied - --> tests/ui/source-struct-unnamed-field-not-error.rs:8:24 - | -4 | struct NotError; - | --------------- method `as_dyn_error` not found for this struct because it doesn't satisfy `NotError: AsDynError<'_>` or `NotError: std::error::Error` -... -8 | pub struct ErrorStruct(#[source] NotError); - | ^^^^^^^^^ method cannot be called on `NotError` due to unsatisfied trait bounds - | - = note: the following trait bounds were not satisfied: - `NotError: std::error::Error` - which is required by `NotError: AsDynError<'_>` -note: the trait `std::error::Error` must be implemented - --> $RUST/core/src/error.rs - | - | pub trait Error: Debug + Display { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `as_dyn_error`, perhaps you need to implement it: - candidate #1: `AsDynError` diff --git a/subprojects/thiserror/tests/ui/struct-with-fmt.rs b/subprojects/thiserror/tests/ui/struct-with-fmt.rs deleted file mode 100644 index 73bf79f..0000000 --- a/subprojects/thiserror/tests/ui/struct-with-fmt.rs +++ /dev/null @@ -1,7 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -#[error(fmt = core::fmt::Octal::fmt)] -pub struct Error(i32); - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/struct-with-fmt.stderr b/subprojects/thiserror/tests/ui/struct-with-fmt.stderr deleted file mode 100644 index 00463be..0000000 --- a/subprojects/thiserror/tests/ui/struct-with-fmt.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: #[error(fmt = ...)] is only supported in enums; for a struct, handwrite your own Display impl - --> tests/ui/struct-with-fmt.rs:4:1 - | -4 | #[error(fmt = core::fmt::Octal::fmt)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/subprojects/thiserror/tests/ui/transparent-display.rs b/subprojects/thiserror/tests/ui/transparent-display.rs deleted file mode 100644 index 2a59f18..0000000 --- a/subprojects/thiserror/tests/ui/transparent-display.rs +++ /dev/null @@ -1,8 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -#[error(transparent)] -#[error("...")] -pub struct Error(anyhow::Error); - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/transparent-display.stderr b/subprojects/thiserror/tests/ui/transparent-display.stderr deleted file mode 100644 index 54d958b..0000000 --- a/subprojects/thiserror/tests/ui/transparent-display.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: cannot have both #[error(transparent)] and a display attribute - --> tests/ui/transparent-display.rs:5:1 - | -5 | #[error("...")] - | ^^^^^^^^^^^^^^^ diff --git a/subprojects/thiserror/tests/ui/transparent-enum-many.rs b/subprojects/thiserror/tests/ui/transparent-enum-many.rs deleted file mode 100644 index e2a73a4..0000000 --- a/subprojects/thiserror/tests/ui/transparent-enum-many.rs +++ /dev/null @@ -1,9 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum Error { - #[error(transparent)] - Other(anyhow::Error, String), -} - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/transparent-enum-many.stderr b/subprojects/thiserror/tests/ui/transparent-enum-many.stderr deleted file mode 100644 index a9adfa5..0000000 --- a/subprojects/thiserror/tests/ui/transparent-enum-many.stderr +++ /dev/null @@ -1,6 +0,0 @@ -error: #[error(transparent)] requires exactly one field - --> tests/ui/transparent-enum-many.rs:5:5 - | -5 | / #[error(transparent)] -6 | | Other(anyhow::Error, String), - | |________________________________^ diff --git a/subprojects/thiserror/tests/ui/transparent-enum-not-error.rs b/subprojects/thiserror/tests/ui/transparent-enum-not-error.rs deleted file mode 100644 index 80ccfc9..0000000 --- a/subprojects/thiserror/tests/ui/transparent-enum-not-error.rs +++ /dev/null @@ -1,9 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum Error { - #[error(transparent)] - Other { message: String }, -} - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/transparent-enum-not-error.stderr b/subprojects/thiserror/tests/ui/transparent-enum-not-error.stderr deleted file mode 100644 index bb836d4..0000000 --- a/subprojects/thiserror/tests/ui/transparent-enum-not-error.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0599]: the method `as_dyn_error` exists for reference `&String`, but its trait bounds were not satisfied - --> tests/ui/transparent-enum-not-error.rs:5:13 - | -5 | #[error(transparent)] - | ^^^^^^^^^^^ method cannot be called on `&String` due to unsatisfied trait bounds - | - ::: $RUST/alloc/src/string.rs - | - | pub struct String { - | ----------------- doesn't satisfy `String: AsDynError<'_>` or `String: std::error::Error` - | - = note: the following trait bounds were not satisfied: - `String: std::error::Error` - which is required by `String: AsDynError<'_>` - `&String: std::error::Error` - which is required by `&String: AsDynError<'_>` - `str: Sized` - which is required by `str: AsDynError<'_>` - `str: std::error::Error` - which is required by `str: AsDynError<'_>` diff --git a/subprojects/thiserror/tests/ui/transparent-enum-source.rs b/subprojects/thiserror/tests/ui/transparent-enum-source.rs deleted file mode 100644 index 3849f66..0000000 --- a/subprojects/thiserror/tests/ui/transparent-enum-source.rs +++ /dev/null @@ -1,9 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum Error { - #[error(transparent)] - Other(#[source] anyhow::Error), -} - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/transparent-enum-source.stderr b/subprojects/thiserror/tests/ui/transparent-enum-source.stderr deleted file mode 100644 index ccb9067..0000000 --- a/subprojects/thiserror/tests/ui/transparent-enum-source.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: transparent variant can't contain #[source] - --> tests/ui/transparent-enum-source.rs:6:11 - | -6 | Other(#[source] anyhow::Error), - | ^^^^^^^^^ diff --git a/subprojects/thiserror/tests/ui/transparent-enum-unnamed-field-not-error.rs b/subprojects/thiserror/tests/ui/transparent-enum-unnamed-field-not-error.rs deleted file mode 100644 index 87c32e0..0000000 --- a/subprojects/thiserror/tests/ui/transparent-enum-unnamed-field-not-error.rs +++ /dev/null @@ -1,9 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum Error { - #[error(transparent)] - Other(String), -} - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/transparent-enum-unnamed-field-not-error.stderr b/subprojects/thiserror/tests/ui/transparent-enum-unnamed-field-not-error.stderr deleted file mode 100644 index f337c59..0000000 --- a/subprojects/thiserror/tests/ui/transparent-enum-unnamed-field-not-error.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0599]: the method `as_dyn_error` exists for reference `&String`, but its trait bounds were not satisfied - --> tests/ui/transparent-enum-unnamed-field-not-error.rs:5:13 - | -5 | #[error(transparent)] - | ^^^^^^^^^^^ method cannot be called on `&String` due to unsatisfied trait bounds - | - ::: $RUST/alloc/src/string.rs - | - | pub struct String { - | ----------------- doesn't satisfy `String: AsDynError<'_>` or `String: std::error::Error` - | - = note: the following trait bounds were not satisfied: - `String: std::error::Error` - which is required by `String: AsDynError<'_>` - `&String: std::error::Error` - which is required by `&String: AsDynError<'_>` - `str: Sized` - which is required by `str: AsDynError<'_>` - `str: std::error::Error` - which is required by `str: AsDynError<'_>` diff --git a/subprojects/thiserror/tests/ui/transparent-struct-many.rs b/subprojects/thiserror/tests/ui/transparent-struct-many.rs deleted file mode 100644 index 18f2466..0000000 --- a/subprojects/thiserror/tests/ui/transparent-struct-many.rs +++ /dev/null @@ -1,10 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -#[error(transparent)] -pub struct Error { - inner: anyhow::Error, - what: String, -} - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/transparent-struct-many.stderr b/subprojects/thiserror/tests/ui/transparent-struct-many.stderr deleted file mode 100644 index c0e3806..0000000 --- a/subprojects/thiserror/tests/ui/transparent-struct-many.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: #[error(transparent)] requires exactly one field - --> tests/ui/transparent-struct-many.rs:4:1 - | -4 | #[error(transparent)] - | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/subprojects/thiserror/tests/ui/transparent-struct-not-error.rs b/subprojects/thiserror/tests/ui/transparent-struct-not-error.rs deleted file mode 100644 index 811ff53..0000000 --- a/subprojects/thiserror/tests/ui/transparent-struct-not-error.rs +++ /dev/null @@ -1,9 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -#[error(transparent)] -pub struct Error { - message: String, -} - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/transparent-struct-not-error.stderr b/subprojects/thiserror/tests/ui/transparent-struct-not-error.stderr deleted file mode 100644 index ee50d03..0000000 --- a/subprojects/thiserror/tests/ui/transparent-struct-not-error.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0599]: the method `as_dyn_error` exists for struct `String`, but its trait bounds were not satisfied - --> tests/ui/transparent-struct-not-error.rs:4:9 - | -4 | #[error(transparent)] - | ^^^^^^^^^^^ method cannot be called on `String` due to unsatisfied trait bounds - | - ::: $RUST/alloc/src/string.rs - | - | pub struct String { - | ----------------- doesn't satisfy `String: AsDynError<'_>` or `String: std::error::Error` - | - = note: the following trait bounds were not satisfied: - `String: std::error::Error` - which is required by `String: AsDynError<'_>` - `str: Sized` - which is required by `str: AsDynError<'_>` - `str: std::error::Error` - which is required by `str: AsDynError<'_>` diff --git a/subprojects/thiserror/tests/ui/transparent-struct-source.rs b/subprojects/thiserror/tests/ui/transparent-struct-source.rs deleted file mode 100644 index d4512c2..0000000 --- a/subprojects/thiserror/tests/ui/transparent-struct-source.rs +++ /dev/null @@ -1,7 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -#[error(transparent)] -pub struct Error(#[source] anyhow::Error); - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/transparent-struct-source.stderr b/subprojects/thiserror/tests/ui/transparent-struct-source.stderr deleted file mode 100644 index 3012ca3..0000000 --- a/subprojects/thiserror/tests/ui/transparent-struct-source.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: transparent error struct can't contain #[source] - --> tests/ui/transparent-struct-source.rs:5:18 - | -5 | pub struct Error(#[source] anyhow::Error); - | ^^^^^^^^^ diff --git a/subprojects/thiserror/tests/ui/transparent-struct-unnamed-field-not-error.rs b/subprojects/thiserror/tests/ui/transparent-struct-unnamed-field-not-error.rs deleted file mode 100644 index b4f7fbb..0000000 --- a/subprojects/thiserror/tests/ui/transparent-struct-unnamed-field-not-error.rs +++ /dev/null @@ -1,7 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -#[error(transparent)] -pub struct Error(String); - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/transparent-struct-unnamed-field-not-error.stderr b/subprojects/thiserror/tests/ui/transparent-struct-unnamed-field-not-error.stderr deleted file mode 100644 index c3d6c00..0000000 --- a/subprojects/thiserror/tests/ui/transparent-struct-unnamed-field-not-error.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0599]: the method `as_dyn_error` exists for struct `String`, but its trait bounds were not satisfied - --> tests/ui/transparent-struct-unnamed-field-not-error.rs:4:9 - | -4 | #[error(transparent)] - | ^^^^^^^^^^^ method cannot be called on `String` due to unsatisfied trait bounds - | - ::: $RUST/alloc/src/string.rs - | - | pub struct String { - | ----------------- doesn't satisfy `String: AsDynError<'_>` or `String: std::error::Error` - | - = note: the following trait bounds were not satisfied: - `String: std::error::Error` - which is required by `String: AsDynError<'_>` - `str: Sized` - which is required by `str: AsDynError<'_>` - `str: std::error::Error` - which is required by `str: AsDynError<'_>` diff --git a/subprojects/thiserror/tests/ui/unconditional-recursion.rs b/subprojects/thiserror/tests/ui/unconditional-recursion.rs deleted file mode 100644 index 035b15e..0000000 --- a/subprojects/thiserror/tests/ui/unconditional-recursion.rs +++ /dev/null @@ -1,9 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -#[error("{self}")] -pub struct Error; - -fn main() { - __FAIL__; -} diff --git a/subprojects/thiserror/tests/ui/unconditional-recursion.stderr b/subprojects/thiserror/tests/ui/unconditional-recursion.stderr deleted file mode 100644 index 568e891..0000000 --- a/subprojects/thiserror/tests/ui/unconditional-recursion.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0425]: cannot find value `__FAIL__` in this scope - --> tests/ui/unconditional-recursion.rs:8:5 - | -8 | __FAIL__; - | ^^^^^^^^ not found in this scope - -warning: function cannot return without recursing - --> tests/ui/unconditional-recursion.rs:4:9 - | -4 | #[error("{self}")] - | ^^^^^^^^ - | | - | cannot return without recursing - | recursive call site - | - = help: a `loop` may express intention better if this is on purpose -note: the lint level is defined here - --> tests/ui/unconditional-recursion.rs:4:9 - | -4 | #[error("{self}")] - | ^^^^^^^^ diff --git a/subprojects/thiserror/tests/ui/unexpected-field-fmt.rs b/subprojects/thiserror/tests/ui/unexpected-field-fmt.rs deleted file mode 100644 index 7c439d9..0000000 --- a/subprojects/thiserror/tests/ui/unexpected-field-fmt.rs +++ /dev/null @@ -1,11 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum Error { - What { - #[error("...")] - io: std::io::Error, - }, -} - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/unexpected-field-fmt.stderr b/subprojects/thiserror/tests/ui/unexpected-field-fmt.stderr deleted file mode 100644 index bf3c24d..0000000 --- a/subprojects/thiserror/tests/ui/unexpected-field-fmt.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: not expected here; the #[error(...)] attribute belongs on top of a struct or an enum variant - --> tests/ui/unexpected-field-fmt.rs:6:9 - | -6 | #[error("...")] - | ^^^^^^^^^^^^^^^ diff --git a/subprojects/thiserror/tests/ui/unexpected-struct-source.rs b/subprojects/thiserror/tests/ui/unexpected-struct-source.rs deleted file mode 100644 index f396494..0000000 --- a/subprojects/thiserror/tests/ui/unexpected-struct-source.rs +++ /dev/null @@ -1,7 +0,0 @@ -use thiserror::Error; - -#[derive(Error, Debug)] -#[source] -pub struct Error; - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/unexpected-struct-source.stderr b/subprojects/thiserror/tests/ui/unexpected-struct-source.stderr deleted file mode 100644 index 6f15841..0000000 --- a/subprojects/thiserror/tests/ui/unexpected-struct-source.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: not expected here; the #[source] attribute belongs on a specific field - --> tests/ui/unexpected-struct-source.rs:4:1 - | -4 | #[source] - | ^^^^^^^^^ diff --git a/subprojects/thiserror/tests/ui/union.rs b/subprojects/thiserror/tests/ui/union.rs deleted file mode 100644 index cd6a934..0000000 --- a/subprojects/thiserror/tests/ui/union.rs +++ /dev/null @@ -1,9 +0,0 @@ -use thiserror::Error; - -#[derive(Error)] -pub union U { - msg: &'static str, - num: usize, -} - -fn main() {} diff --git a/subprojects/thiserror/tests/ui/union.stderr b/subprojects/thiserror/tests/ui/union.stderr deleted file mode 100644 index 3ec4d71..0000000 --- a/subprojects/thiserror/tests/ui/union.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: union as errors are not supported - --> tests/ui/union.rs:4:1 - | -4 | / pub union U { -5 | | msg: &'static str, -6 | | num: usize, -7 | | } - | |_^