#![cfg_attr(not(feature = "std"), no_std)] cfg_if::cfg_if! { if #[cfg(not(feature = "std"))] { extern crate alloc; use alloc::string::{String, ToString}; use alloc::format; use alloc::borrow::ToOwned; mod io { use thiserror::Error; #[derive(Error, Debug)] #[error("test")] pub struct Error; impl Error { pub fn new(kind: ErrorKind, s: &str) -> Self { Self } } pub enum ErrorKind { Other } } } else { use std::error::Error as _; use std::io; } } use anyhow::anyhow; 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()); cfg_if::cfg_if! { if #[cfg(feature = "std")] { 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()); cfg_if::cfg_if! { if #[cfg(feature = "std")] { 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()); cfg_if::cfg_if! { if #[cfg(feature = "std")] { 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()); cfg_if::cfg_if! { if #[cfg(feature = "std")] { 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()); cfg_if::cfg_if! { if #[cfg(feature = "std")] { assert!(error.source().is_none()); } } }