From de8a1e54d420514250d9d4081d41723192cf0dfa Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 17 Jul 2024 11:56:56 -0700 Subject: [PATCH] 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 9de063c..3b7d743 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 9771604..c931229 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