From cf43d0c1302f1ee073a7062b2dc24123589a4417 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 6 May 2024 18:58:57 -0700 Subject: [PATCH 01/14] Resolve unexpected_cfgs warning warning: unexpected `cfg` condition name: `error_generic_member_access` --> src/lib.rs:238:13 | 238 | #![cfg_attr(error_generic_member_access, feature(error_generic_member_access))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: expected names are: `clippy`, `debug_assertions`, `doc`, `docsrs`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows` = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(error_generic_member_access)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition name: `thiserror_nightly_testing` --> src/lib.rs:240:11 | 240 | #[cfg(all(thiserror_nightly_testing, not(error_generic_member_access)))] | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(thiserror_nightly_testing)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `error_generic_member_access` --> src/lib.rs:240:42 | 240 | #[cfg(all(thiserror_nightly_testing, not(error_generic_member_access)))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(error_generic_member_access)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `error_generic_member_access` --> src/lib.rs:245:7 | 245 | #[cfg(error_generic_member_access)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(error_generic_member_access)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `error_generic_member_access` --> src/lib.rs:257:11 | 257 | #[cfg(error_generic_member_access)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(error_generic_member_access)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `thiserror_nightly_testing` --> tests/test_option.rs:1:13 | 1 | #![cfg_attr(thiserror_nightly_testing, feature(error_generic_member_access))] | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: expected names are: `clippy`, `debug_assertions`, `doc`, `docsrs`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows` = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(thiserror_nightly_testing)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition name: `thiserror_nightly_testing` --> tests/test_option.rs:3:7 | 3 | #[cfg(thiserror_nightly_testing)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(thiserror_nightly_testing)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `thiserror_nightly_testing` --> tests/test_option.rs:48:7 | 48 | #[cfg(thiserror_nightly_testing)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(thiserror_nightly_testing)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `thiserror_nightly_testing` --> tests/test_backtrace.rs:1:13 | 1 | #![cfg_attr(thiserror_nightly_testing, feature(error_generic_member_access))] | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: expected names are: `clippy`, `debug_assertions`, `doc`, `docsrs`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows` = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(thiserror_nightly_testing)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition name: `thiserror_nightly_testing` --> tests/test_option.rs:104:16 | 104 | #[cfg_attr(not(thiserror_nightly_testing), ignore)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(thiserror_nightly_testing)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `thiserror_nightly_testing` --> tests/test_backtrace.rs:9:7 | 9 | #[cfg(thiserror_nightly_testing)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(thiserror_nightly_testing)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `thiserror_nightly_testing` --> tests/test_backtrace.rs:16:7 | 16 | #[cfg(thiserror_nightly_testing)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(thiserror_nightly_testing)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `thiserror_nightly_testing` --> tests/test_backtrace.rs:150:7 | 150 | #[cfg(thiserror_nightly_testing)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(thiserror_nightly_testing)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `thiserror_nightly_testing` --> tests/test_backtrace.rs:273:16 | 273 | #[cfg_attr(not(thiserror_nightly_testing), ignore)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider using a Cargo feature instead or adding `println!("cargo::rustc-check-cfg=cfg(thiserror_nightly_testing)");` to the top of the `build.rs` = note: see for more information about checking conditional configuration --- build.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.rs b/build.rs index ad42f256..d6196315 100644 --- a/build.rs +++ b/build.rs @@ -7,6 +7,9 @@ use std::process::{self, Command, Stdio}; fn main() { println!("cargo:rerun-if-changed=build/probe.rs"); + println!("cargo:rustc-check-cfg=cfg(error_generic_member_access)"); + println!("cargo:rustc-check-cfg=cfg(thiserror_nightly_testing)"); + let error_generic_member_access; let consider_rustc_bootstrap; if compile_probe(false) { From 870d11b830e7f1ce0ad6c1656806a7fcdd4273df Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 6 May 2024 19:13:41 -0700 Subject: [PATCH 02/14] Release 1.0.60 --- Cargo.toml | 4 ++-- impl/Cargo.toml | 2 +- src/lib.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 36462e14..fd2d13d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "thiserror" -version = "1.0.59" +version = "1.0.60" authors = ["David Tolnay "] categories = ["rust-patterns"] description = "derive(Error)" @@ -12,7 +12,7 @@ repository = "https://github.com/dtolnay/thiserror" rust-version = "1.56" [dependencies] -thiserror-impl = { version = "=1.0.59", path = "impl" } +thiserror-impl = { version = "=1.0.60", path = "impl" } [dev-dependencies] anyhow = "1.0.73" diff --git a/impl/Cargo.toml b/impl/Cargo.toml index f2f8ac2e..698f9671 100644 --- a/impl/Cargo.toml +++ b/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "thiserror-impl" -version = "1.0.59" +version = "1.0.60" authors = ["David Tolnay "] description = "Implementation detail of the `thiserror` crate" edition = "2021" diff --git a/src/lib.rs b/src/lib.rs index 5b07dca6..81a04b07 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -228,7 +228,7 @@ //! //! [`anyhow`]: https://github.com/dtolnay/anyhow -#![doc(html_root_url = "https://docs.rs/thiserror/1.0.59")] +#![doc(html_root_url = "https://docs.rs/thiserror/1.0.60")] #![allow( clippy::module_name_repetitions, clippy::needless_lifetimes, From 7b6e35b992e96581ed5feee917fdb3c2d5918839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Fri, 17 May 2024 15:34:04 +0200 Subject: [PATCH 03/14] use core::fmt instead of std::fmt --- build/probe.rs | 2 +- src/display.rs | 2 +- src/lib.rs | 4 ++-- tests/test_display.rs | 2 +- tests/test_error.rs | 2 +- tests/test_expr.rs | 2 +- tests/test_generics.rs | 2 +- tests/test_path.rs | 2 +- tests/ui/fallback-impl-with-display.rs | 2 +- tests/ui/lifetime.rs | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/probe.rs b/build/probe.rs index 0dce6f5b..28437870 100644 --- a/build/probe.rs +++ b/build/probe.rs @@ -5,7 +5,7 @@ #![feature(error_generic_member_access)] use std::error::{Error, Request}; -use std::fmt::{self, Debug, Display}; +use core::fmt::{self, Debug, Display}; struct MyError(Thing); struct Thing; diff --git a/src/display.rs b/src/display.rs index 27098f16..3c43216a 100644 --- a/src/display.rs +++ b/src/display.rs @@ -1,4 +1,4 @@ -use std::fmt::Display; +use core::fmt::Display; use std::path::{self, Path, PathBuf}; #[doc(hidden)] diff --git a/src/lib.rs b/src/lib.rs index 81a04b07..9b9c5af6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -62,7 +62,7 @@ //! which may be arbitrary expressions. For example: //! //! ```rust -//! # use std::i32; +//! # use core::i32; //! # use thiserror::Error; //! # //! #[derive(Error, Debug)] @@ -129,7 +129,7 @@ //! std::error::Error` will work as a source. //! //! ```rust -//! # use std::fmt::{self, Display}; +//! # use core::fmt::{self, Display}; //! # use thiserror::Error; //! # //! #[derive(Error, Debug)] diff --git a/tests/test_display.rs b/tests/test_display.rs index 95a210f0..c05d157a 100644 --- a/tests/test_display.rs +++ b/tests/test_display.rs @@ -1,6 +1,6 @@ #![allow(clippy::needless_raw_string_hashes, clippy::uninlined_format_args)] -use std::fmt::{self, Display}; +use core::fmt::{self, Display}; use thiserror::Error; fn assert(expected: &str, value: T) { diff --git a/tests/test_error.rs b/tests/test_error.rs index fab934d7..eb52cefb 100644 --- a/tests/test_error.rs +++ b/tests/test_error.rs @@ -1,6 +1,6 @@ #![allow(dead_code)] -use std::fmt::{self, Display}; +use core::fmt::{self, Display}; use std::io; use thiserror::Error; diff --git a/tests/test_expr.rs b/tests/test_expr.rs index 028f34ee..c5e3b4b1 100644 --- a/tests/test_expr.rs +++ b/tests/test_expr.rs @@ -1,6 +1,6 @@ #![allow(clippy::iter_cloned_collect, clippy::uninlined_format_args)] -use std::fmt::Display; +use core::fmt::Display; use thiserror::Error; // Some of the elaborate cases from the rcc codebase, which is a C compiler in diff --git a/tests/test_generics.rs b/tests/test_generics.rs index c94d95ef..ac5d6f3b 100644 --- a/tests/test_generics.rs +++ b/tests/test_generics.rs @@ -1,6 +1,6 @@ #![allow(clippy::needless_late_init, clippy::uninlined_format_args)] -use std::fmt::{self, Debug, Display}; +use core::fmt::{self, Debug, Display}; use thiserror::Error; pub struct NoFormat; diff --git a/tests/test_path.rs b/tests/test_path.rs index a34a3d74..f0540779 100644 --- a/tests/test_path.rs +++ b/tests/test_path.rs @@ -1,5 +1,5 @@ +use core::fmt::Display; use ref_cast::RefCast; -use std::fmt::Display; use std::path::{Path, PathBuf}; use thiserror::Error; diff --git a/tests/ui/fallback-impl-with-display.rs b/tests/ui/fallback-impl-with-display.rs index 33411873..23dcf287 100644 --- a/tests/ui/fallback-impl-with-display.rs +++ b/tests/ui/fallback-impl-with-display.rs @@ -1,4 +1,4 @@ -use std::fmt::{self, Display}; +use core::fmt::{self, Display}; use thiserror::Error; #[derive(Error, Debug)] diff --git a/tests/ui/lifetime.rs b/tests/ui/lifetime.rs index 698f8c4e..a82909d6 100644 --- a/tests/ui/lifetime.rs +++ b/tests/ui/lifetime.rs @@ -1,4 +1,4 @@ -use std::fmt::Debug; +use core::fmt::Debug; use thiserror::Error; #[derive(Error, Debug)] From ce974bc2bd7773ef6e2cf19a2e35c0d31519c353 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Fri, 17 May 2024 15:42:03 +0200 Subject: [PATCH 04/14] also {std -> core}::panic::UnwindSafe --- src/aserror.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aserror.rs b/src/aserror.rs index 54fc6f11..4cd0fec6 100644 --- a/src/aserror.rs +++ b/src/aserror.rs @@ -1,5 +1,5 @@ use std::error::Error; -use std::panic::UnwindSafe; +use core::panic::UnwindSafe; #[doc(hidden)] pub trait AsDynError<'a>: Sealed { From e3b1b91ced4e590ac8823fa0945f01a0560dada9 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 17 May 2024 09:43:23 -0700 Subject: [PATCH 05/14] Format PR 299 with rustfmt --- build/probe.rs | 2 +- src/aserror.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/probe.rs b/build/probe.rs index 28437870..faf25c5c 100644 --- a/build/probe.rs +++ b/build/probe.rs @@ -4,8 +4,8 @@ #![feature(error_generic_member_access)] -use std::error::{Error, Request}; use core::fmt::{self, Debug, Display}; +use std::error::{Error, Request}; struct MyError(Thing); struct Thing; diff --git a/src/aserror.rs b/src/aserror.rs index 4cd0fec6..11cb4d99 100644 --- a/src/aserror.rs +++ b/src/aserror.rs @@ -1,5 +1,5 @@ -use std::error::Error; use core::panic::UnwindSafe; +use std::error::Error; #[doc(hidden)] pub trait AsDynError<'a>: Sealed { From 5c8016393fec09330ae495d71edee4d8104a9466 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 17 May 2024 09:44:33 -0700 Subject: [PATCH 06/14] Release 1.0.61 --- Cargo.toml | 4 ++-- impl/Cargo.toml | 2 +- src/lib.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fd2d13d1..72554792 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "thiserror" -version = "1.0.60" +version = "1.0.61" authors = ["David Tolnay "] categories = ["rust-patterns"] description = "derive(Error)" @@ -12,7 +12,7 @@ repository = "https://github.com/dtolnay/thiserror" rust-version = "1.56" [dependencies] -thiserror-impl = { version = "=1.0.60", path = "impl" } +thiserror-impl = { version = "=1.0.61", path = "impl" } [dev-dependencies] anyhow = "1.0.73" diff --git a/impl/Cargo.toml b/impl/Cargo.toml index 698f9671..43b900b5 100644 --- a/impl/Cargo.toml +++ b/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "thiserror-impl" -version = "1.0.60" +version = "1.0.61" authors = ["David Tolnay "] description = "Implementation detail of the `thiserror` crate" edition = "2021" diff --git a/src/lib.rs b/src/lib.rs index 9b9c5af6..13c2b504 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -228,7 +228,7 @@ //! //! [`anyhow`]: https://github.com/dtolnay/anyhow -#![doc(html_root_url = "https://docs.rs/thiserror/1.0.60")] +#![doc(html_root_url = "https://docs.rs/thiserror/1.0.61")] #![allow( clippy::module_name_repetitions, clippy::needless_lifetimes, From f2824ae379ac2edee1fd687b9e56f18c048086cd Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 1 Jun 2024 22:13:43 -0700 Subject: [PATCH 07/14] Fill in ignore reasons in all #[ignore] attributes --- tests/compiletest.rs | 4 ++-- tests/test_backtrace.rs | 5 ++++- tests/test_option.rs | 5 ++++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/tests/compiletest.rs b/tests/compiletest.rs index 7974a624..23a6a065 100644 --- a/tests/compiletest.rs +++ b/tests/compiletest.rs @@ -1,5 +1,5 @@ -#[rustversion::attr(not(nightly), ignore)] -#[cfg_attr(miri, ignore)] +#[rustversion::attr(not(nightly), ignore = "requires nightly")] +#[cfg_attr(miri, ignore = "incompatible with miri")] #[test] fn ui() { let t = trybuild::TestCases::new(); diff --git a/tests/test_backtrace.rs b/tests/test_backtrace.rs index 4710d45b..8f11da39 100644 --- a/tests/test_backtrace.rs +++ b/tests/test_backtrace.rs @@ -270,5 +270,8 @@ pub mod enums { } #[test] -#[cfg_attr(not(thiserror_nightly_testing), ignore)] +#[cfg_attr( + not(thiserror_nightly_testing), + ignore = "requires `--cfg=thiserror_nightly_testing`" +)] fn test_backtrace() {} diff --git a/tests/test_option.rs b/tests/test_option.rs index 232e5a3b..5464b08a 100644 --- a/tests/test_option.rs +++ b/tests/test_option.rs @@ -101,5 +101,8 @@ pub mod enums { } #[test] -#[cfg_attr(not(thiserror_nightly_testing), ignore)] +#[cfg_attr( + not(thiserror_nightly_testing), + ignore = "requires `--cfg=thiserror_nightly_testing`" +)] fn test_option() {} From 4db08b10a39cfd189a36a88dee0fad578ac11cbe Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 7 Jun 2024 19:36:27 -0700 Subject: [PATCH 08/14] Ignore warning on unused struct in test warning: struct `OptSourceNoBacktrace` is never constructed --> tests/test_option.rs:10:16 | 10 | pub struct OptSourceNoBacktrace { | ^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(dead_code)]` on by default warning: struct `OptSourceAlwaysBacktrace` is never constructed --> tests/test_option.rs:17:16 | 17 | pub struct OptSourceAlwaysBacktrace { | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: struct `NoSourceOptBacktrace` is never constructed --> tests/test_option.rs:25:16 | 25 | pub struct NoSourceOptBacktrace { | ^^^^^^^^^^^^^^^^^^^^ warning: struct `AlwaysSourceOptBacktrace` is never constructed --> tests/test_option.rs:32:16 | 32 | pub struct AlwaysSourceOptBacktrace { | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: struct `OptSourceOptBacktrace` is never constructed --> tests/test_option.rs:40:16 | 40 | pub struct OptSourceOptBacktrace { | ^^^^^^^^^^^^^^^^^^^^^ --- tests/test_option.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/test_option.rs b/tests/test_option.rs index 5464b08a..480170f9 100644 --- a/tests/test_option.rs +++ b/tests/test_option.rs @@ -7,6 +7,7 @@ pub mod structs { #[derive(Error, Debug)] #[error("...")] + #[allow(dead_code)] pub struct OptSourceNoBacktrace { #[source] source: Option, @@ -14,6 +15,7 @@ pub mod structs { #[derive(Error, Debug)] #[error("...")] + #[allow(dead_code)] pub struct OptSourceAlwaysBacktrace { #[source] source: Option, @@ -22,6 +24,7 @@ pub mod structs { #[derive(Error, Debug)] #[error("...")] + #[allow(dead_code)] pub struct NoSourceOptBacktrace { #[backtrace] backtrace: Option, @@ -29,6 +32,7 @@ pub mod structs { #[derive(Error, Debug)] #[error("...")] + #[allow(dead_code)] pub struct AlwaysSourceOptBacktrace { source: anyhow::Error, #[backtrace] @@ -37,6 +41,7 @@ pub mod structs { #[derive(Error, Debug)] #[error("...")] + #[allow(dead_code)] pub struct OptSourceOptBacktrace { #[source] source: Option, From 479744ec288f9183b8849f013dcee226ac6588ee Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 7 Jun 2024 19:38:42 -0700 Subject: [PATCH 09/14] No need for dead code if struct fields are public --- tests/test_option.rs | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/tests/test_option.rs b/tests/test_option.rs index 480170f9..fbdbec08 100644 --- a/tests/test_option.rs +++ b/tests/test_option.rs @@ -7,46 +7,41 @@ pub mod structs { #[derive(Error, Debug)] #[error("...")] - #[allow(dead_code)] pub struct OptSourceNoBacktrace { #[source] - source: Option, + pub source: Option, } #[derive(Error, Debug)] #[error("...")] - #[allow(dead_code)] pub struct OptSourceAlwaysBacktrace { #[source] - source: Option, - backtrace: Backtrace, + pub source: Option, + pub backtrace: Backtrace, } #[derive(Error, Debug)] #[error("...")] - #[allow(dead_code)] pub struct NoSourceOptBacktrace { #[backtrace] - backtrace: Option, + pub backtrace: Option, } #[derive(Error, Debug)] #[error("...")] - #[allow(dead_code)] pub struct AlwaysSourceOptBacktrace { - source: anyhow::Error, + pub source: anyhow::Error, #[backtrace] - backtrace: Option, + pub backtrace: Option, } #[derive(Error, Debug)] #[error("...")] - #[allow(dead_code)] pub struct OptSourceOptBacktrace { #[source] - source: Option, + pub source: Option, #[backtrace] - backtrace: Option, + pub backtrace: Option, } } From f1ca210cc4772f198af91886e3849dac68114f97 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 11 Jul 2024 16:07:12 -0700 Subject: [PATCH 10/14] Add regression test for issue 309 --- tests/test_display.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/test_display.rs b/tests/test_display.rs index c05d157a..7a9057c7 100644 --- a/tests/test_display.rs +++ b/tests/test_display.rs @@ -234,6 +234,18 @@ fn test_field() { 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_macro_rules() { // Regression test for https://github.com/dtolnay/thiserror/issues/86 From 40a7779b1793f2dce5f85abe8c03486cdb5eb640 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 11 Jul 2024 16:09:19 -0700 Subject: [PATCH 11/14] Support .0.0 nested tuple index --- impl/src/attr.rs | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/impl/src/attr.rs b/impl/src/attr.rs index 395edb1f..e0ac02b1 100644 --- a/impl/src/attr.rs +++ b/impl/src/attr.rs @@ -1,11 +1,11 @@ -use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree}; +use proc_macro2::{Delimiter, Group, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; use quote::{format_ident, quote, ToTokens}; use std::collections::BTreeSet as Set; use syn::parse::discouraged::Speculative; use syn::parse::ParseStream; use syn::{ - braced, bracketed, parenthesized, token, Attribute, Error, Ident, Index, LitInt, LitStr, Meta, - Result, Token, + braced, bracketed, parenthesized, token, Attribute, Error, Ident, Index, LitFloat, LitInt, + LitStr, Meta, Result, Token, }; pub struct Attrs<'a> { @@ -145,14 +145,42 @@ fn parse_token_expr(input: ParseStream, mut begin_expr: bool) -> Result()?; begin_expr = false; continue; - } - if input.peek2(LitInt) { + } else if input.peek2(LitInt) { input.parse::()?; let int: Index = input.parse()?; - let ident = format_ident!("_{}", int.index, span = int.span); - tokens.push(TokenTree::Ident(ident)); + 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; + } } } From 0bf6e3dd781409b62cbcf0816ffa1bb970d24833 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 11 Jul 2024 16:31:35 -0700 Subject: [PATCH 12/14] Release 1.0.62 --- Cargo.toml | 4 ++-- impl/Cargo.toml | 2 +- src/lib.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 72554792..123e2bf0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "thiserror" -version = "1.0.61" +version = "1.0.62" authors = ["David Tolnay "] categories = ["rust-patterns"] description = "derive(Error)" @@ -12,7 +12,7 @@ repository = "https://github.com/dtolnay/thiserror" rust-version = "1.56" [dependencies] -thiserror-impl = { version = "=1.0.61", path = "impl" } +thiserror-impl = { version = "=1.0.62", path = "impl" } [dev-dependencies] anyhow = "1.0.73" diff --git a/impl/Cargo.toml b/impl/Cargo.toml index 43b900b5..81a9b9ac 100644 --- a/impl/Cargo.toml +++ b/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.62" authors = ["David Tolnay "] description = "Implementation detail of the `thiserror` crate" edition = "2021" diff --git a/src/lib.rs b/src/lib.rs index 13c2b504..97716045 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -228,7 +228,7 @@ //! //! [`anyhow`]: https://github.com/dtolnay/anyhow -#![doc(html_root_url = "https://docs.rs/thiserror/1.0.61")] +#![doc(html_root_url = "https://docs.rs/thiserror/1.0.62")] #![allow( clippy::module_name_repetitions, clippy::needless_lifetimes, From de8a1e54d420514250d9d4081d41723192cf0dfa Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 17 Jul 2024 11:56:56 -0700 Subject: [PATCH 13/14] Update documentation of #[from] and #[backtrace] attributes --- README.md | 38 +++++++++++++++++++++++++----------- src/lib.rs | 56 +++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 70 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 9de063c3..3b7d7437 100644 --- a/README.md +++ b/README.md @@ -88,20 +88,18 @@ pub enum DataStoreError { } ``` -- A `From` impl is generated for each variant containing a `#[from]` attribute. +- A `From` impl is generated for each variant that contains a `#[from]` + attribute. - Note that the variant must not contain any other fields beyond the source - error and possibly a backtrace. A backtrace is captured from within the `From` - impl if there is a field for it. + 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] - source: io::Error, - backtrace: Backtrace, - }, + Io(#[from] io::Error), + Glob(#[from] globset::Error), } ``` @@ -125,7 +123,9 @@ pub enum DataStoreError { ``` - The Error trait's `provide()` method is implemented to provide whichever field - has a type named `Backtrace`, if any, as a `std::backtrace::Backtrace`. + 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; @@ -140,7 +140,9 @@ pub enum DataStoreError { - 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. + share the same backtrace. The `#[backtrace]` attribute requires a nightly + compiler with Rust version 1.73 or newer. + ```rust #[derive(Error, Debug)] @@ -152,6 +154,20 @@ pub enum DataStoreError { } ``` +- 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. diff --git a/src/lib.rs b/src/lib.rs index 97716045..c931229e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -98,24 +98,36 @@ //! } //! ``` //! -//! - A `From` impl is generated for each variant containing a `#[from]` +//! - A `From` impl is generated for each variant that contains a `#[from]` //! attribute. //! -//! Note that the variant must not contain any other fields beyond the source -//! error and possibly a backtrace. A backtrace is captured from within the -//! `From` impl if there is a field for it. +//! 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 -//! # const IGNORE: &str = stringify! { +//! # 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] -//! source: io::Error, -//! backtrace: Backtrace, -//! }, +//! 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 @@ -148,7 +160,8 @@ //! //! - The Error trait's `provide()` method is implemented to provide whichever //! field has a type named `Backtrace`, if any, as a -//! `std::backtrace::Backtrace`. +//! `std::backtrace::Backtrace`. Using `Backtrace` in errors requires a +//! nightly compiler with Rust version 1.73 or newer. //! //! ```rust //! # const IGNORE: &str = stringify! { @@ -165,7 +178,8 @@ //! - 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. +//! 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! { @@ -179,6 +193,22 @@ //! # }; //! ``` //! +//! - 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 From 915c75e8a3b679588e6eac03dccbba5d38c764a8 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 17 Jul 2024 12:09:02 -0700 Subject: [PATCH 14/14] Release 1.0.63 --- Cargo.toml | 4 ++-- impl/Cargo.toml | 2 +- src/lib.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 123e2bf0..71f10086 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "thiserror" -version = "1.0.62" +version = "1.0.63" authors = ["David Tolnay "] categories = ["rust-patterns"] description = "derive(Error)" @@ -12,7 +12,7 @@ repository = "https://github.com/dtolnay/thiserror" rust-version = "1.56" [dependencies] -thiserror-impl = { version = "=1.0.62", path = "impl" } +thiserror-impl = { version = "=1.0.63", path = "impl" } [dev-dependencies] anyhow = "1.0.73" diff --git a/impl/Cargo.toml b/impl/Cargo.toml index 81a9b9ac..cafcd02a 100644 --- a/impl/Cargo.toml +++ b/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "thiserror-impl" -version = "1.0.62" +version = "1.0.63" authors = ["David Tolnay "] description = "Implementation detail of the `thiserror` crate" edition = "2021" diff --git a/src/lib.rs b/src/lib.rs index c931229e..42dd65b6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -258,7 +258,7 @@ //! //! [`anyhow`]: https://github.com/dtolnay/anyhow -#![doc(html_root_url = "https://docs.rs/thiserror/1.0.62")] +#![doc(html_root_url = "https://docs.rs/thiserror/1.0.63")] #![allow( clippy::module_name_repetitions, clippy::needless_lifetimes,