forked from gentoo-utils/gentoo-utils
Merge commit '6eba9cd92c295c5389944f6adda1f1e83b2cb008' as 'subprojects/thiserror'
This commit is contained in:
7
subprojects/thiserror/tests/compiletest.rs
Normal file
7
subprojects/thiserror/tests/compiletest.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
#[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");
|
||||
}
|
||||
12
subprojects/thiserror/tests/no-std/Cargo.toml
Normal file
12
subprojects/thiserror/tests/no-std/Cargo.toml
Normal file
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "thiserror_no_std_test"
|
||||
version = "0.0.0"
|
||||
authors = ["David Tolnay <dtolnay@gmail.com>"]
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
path = "test.rs"
|
||||
|
||||
[dependencies]
|
||||
thiserror = { path = "../..", default-features = false }
|
||||
58
subprojects/thiserror/tests/no-std/test.rs
Normal file
58
subprojects/thiserror/tests/no-std/test.rs
Normal file
@@ -0,0 +1,58 @@
|
||||
#![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::<SourceError>()
|
||||
.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~~~");
|
||||
}
|
||||
}
|
||||
289
subprojects/thiserror/tests/test_backtrace.rs
Normal file
289
subprojects/thiserror/tests/test_backtrace.rs
Normal file
@@ -0,0 +1,289 @@
|
||||
#![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<Backtrace>,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("...")]
|
||||
pub struct ArcBacktrace {
|
||||
#[backtrace]
|
||||
backtrace: Arc<Backtrace>,
|
||||
}
|
||||
|
||||
#[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<Backtrace>,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("...")]
|
||||
pub struct ArcBacktraceFrom {
|
||||
#[from]
|
||||
source: Inner,
|
||||
#[backtrace]
|
||||
backtrace: Arc<Backtrace>,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("...")]
|
||||
pub struct AnyhowBacktrace {
|
||||
#[backtrace]
|
||||
source: anyhow::Error,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("...")]
|
||||
pub struct BoxDynErrorBacktrace {
|
||||
#[backtrace]
|
||||
source: Box<dyn Error>,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_backtrace() {
|
||||
let error = PlainBacktrace {
|
||||
backtrace: Backtrace::capture(),
|
||||
};
|
||||
assert!(error::request_ref::<Backtrace>(&error).is_some());
|
||||
|
||||
let error = ExplicitBacktrace {
|
||||
backtrace: Backtrace::capture(),
|
||||
};
|
||||
assert!(error::request_ref::<Backtrace>(&error).is_some());
|
||||
|
||||
let error = OptBacktrace {
|
||||
backtrace: Some(Backtrace::capture()),
|
||||
};
|
||||
assert!(error::request_ref::<Backtrace>(&error).is_some());
|
||||
|
||||
let error = ArcBacktrace {
|
||||
backtrace: Arc::new(Backtrace::capture()),
|
||||
};
|
||||
assert!(error::request_ref::<Backtrace>(&error).is_some());
|
||||
|
||||
let error = BacktraceFrom::from(Inner);
|
||||
assert!(error::request_ref::<Backtrace>(&error).is_some());
|
||||
|
||||
let error = CombinedBacktraceFrom::from(InnerBacktrace {
|
||||
backtrace: Backtrace::capture(),
|
||||
});
|
||||
assert!(error::request_ref::<Backtrace>(&error).is_some());
|
||||
|
||||
let error = OptBacktraceFrom::from(Inner);
|
||||
assert!(error::request_ref::<Backtrace>(&error).is_some());
|
||||
|
||||
let error = ArcBacktraceFrom::from(Inner);
|
||||
assert!(error::request_ref::<Backtrace>(&error).is_some());
|
||||
|
||||
let error = AnyhowBacktrace {
|
||||
source: anyhow::Error::msg("..."),
|
||||
};
|
||||
assert!(error::request_ref::<Backtrace>(&error).is_some());
|
||||
|
||||
let error = BoxDynErrorBacktrace {
|
||||
source: Box::new(PlainBacktrace {
|
||||
backtrace: Backtrace::capture(),
|
||||
}),
|
||||
};
|
||||
assert!(error::request_ref::<Backtrace>(&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<Backtrace>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ArcBacktrace {
|
||||
#[error("...")]
|
||||
Test {
|
||||
#[backtrace]
|
||||
backtrace: Arc<Backtrace>,
|
||||
},
|
||||
}
|
||||
|
||||
#[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<Backtrace>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ArcBacktraceFrom {
|
||||
#[error("...")]
|
||||
Test {
|
||||
#[from]
|
||||
source: Inner,
|
||||
#[backtrace]
|
||||
backtrace: Arc<Backtrace>,
|
||||
},
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_backtrace() {
|
||||
let error = PlainBacktrace::Test {
|
||||
backtrace: Backtrace::capture(),
|
||||
};
|
||||
assert!(error::request_ref::<Backtrace>(&error).is_some());
|
||||
|
||||
let error = ExplicitBacktrace::Test {
|
||||
backtrace: Backtrace::capture(),
|
||||
};
|
||||
assert!(error::request_ref::<Backtrace>(&error).is_some());
|
||||
|
||||
let error = OptBacktrace::Test {
|
||||
backtrace: Some(Backtrace::capture()),
|
||||
};
|
||||
assert!(error::request_ref::<Backtrace>(&error).is_some());
|
||||
|
||||
let error = ArcBacktrace::Test {
|
||||
backtrace: Arc::new(Backtrace::capture()),
|
||||
};
|
||||
assert!(error::request_ref::<Backtrace>(&error).is_some());
|
||||
|
||||
let error = BacktraceFrom::from(Inner);
|
||||
assert!(error::request_ref::<Backtrace>(&error).is_some());
|
||||
|
||||
let error = CombinedBacktraceFrom::from(InnerBacktrace {
|
||||
backtrace: Backtrace::capture(),
|
||||
});
|
||||
assert!(error::request_ref::<Backtrace>(&error).is_some());
|
||||
|
||||
let error = OptBacktraceFrom::from(Inner);
|
||||
assert!(error::request_ref::<Backtrace>(&error).is_some());
|
||||
|
||||
let error = ArcBacktraceFrom::from(Inner);
|
||||
assert!(error::request_ref::<Backtrace>(&error).is_some());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(
|
||||
not(thiserror_nightly_testing),
|
||||
ignore = "requires `--cfg=thiserror_nightly_testing`"
|
||||
)]
|
||||
fn test_backtrace() {}
|
||||
478
subprojects/thiserror/tests/test_display.rs
Normal file
478
subprojects/thiserror/tests/test_display.rs
Normal file
@@ -0,0 +1,478 @@
|
||||
#![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<T: Display>(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<usize>);
|
||||
|
||||
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<usize>);
|
||||
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<usize>);
|
||||
|
||||
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<i32>,
|
||||
}
|
||||
|
||||
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<T: 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>)]
|
||||
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));
|
||||
}
|
||||
56
subprojects/thiserror/tests/test_error.rs
Normal file
56
subprojects/thiserror/tests/test_error.rs
Normal file
@@ -0,0 +1,56 @@
|
||||
#![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);
|
||||
118
subprojects/thiserror/tests/test_expr.rs
Normal file
118
subprojects/thiserror/tests/test_expr.rs
Normal file
@@ -0,0 +1,118 @@
|
||||
#![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::<Vec<_>>().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<bool> },
|
||||
|
||||
#[error("overflow while parsing {}integer literal", match .is_signed {
|
||||
Some(true) => "signed ",
|
||||
Some(false) => "unsigned ",
|
||||
None => "",
|
||||
})]
|
||||
IntegerOverflow2 { is_signed: Option<bool> },
|
||||
}
|
||||
|
||||
// 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<String>,
|
||||
},
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn assert<T: Display>(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<T>: Display {
|
||||
type A;
|
||||
}
|
||||
|
||||
impl<T> Trait<T> for i32 {
|
||||
type A = i32;
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("{A} {b}", b = &0 as &dyn Trait<i32, A = i32>)]
|
||||
pub struct Error {
|
||||
pub A: PathBuf,
|
||||
}
|
||||
|
||||
assert(
|
||||
"... 0",
|
||||
Error {
|
||||
A: PathBuf::from("..."),
|
||||
},
|
||||
);
|
||||
}
|
||||
64
subprojects/thiserror/tests/test_from.rs
Normal file
64
subprojects/thiserror/tests/test_from.rs
Normal file
@@ -0,0 +1,64 @@
|
||||
#![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<io::Error>,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("...")]
|
||||
pub struct ErrorTuple(#[from] io::Error);
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("...")]
|
||||
pub struct ErrorTupleOptional(#[from] Option<io::Error>);
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("...")]
|
||||
pub enum ErrorEnum {
|
||||
Test {
|
||||
#[from]
|
||||
source: io::Error,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("...")]
|
||||
pub enum ErrorEnumOptional {
|
||||
Test {
|
||||
#[from]
|
||||
source: Option<io::Error>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("...")]
|
||||
pub enum Many {
|
||||
Any(#[from] anyhow::Error),
|
||||
Io(#[from] io::Error),
|
||||
}
|
||||
|
||||
fn assert_impl<T: From<io::Error>>() {}
|
||||
|
||||
#[test]
|
||||
fn test_from() {
|
||||
assert_impl::<ErrorStruct>();
|
||||
assert_impl::<ErrorStructOptional>();
|
||||
assert_impl::<ErrorTuple>();
|
||||
assert_impl::<ErrorTupleOptional>();
|
||||
assert_impl::<ErrorEnum>();
|
||||
assert_impl::<ErrorEnumOptional>();
|
||||
assert_impl::<Many>();
|
||||
}
|
||||
205
subprojects/thiserror/tests/test_generics.rs
Normal file
205
subprojects/thiserror/tests/test_generics.rs
Normal file
@@ -0,0 +1,205 @@
|
||||
#![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<E> Display for EnumDebugField<E>
|
||||
// where
|
||||
// E: Debug;
|
||||
//
|
||||
// impl<E> Error for EnumDebugField<E>
|
||||
// where
|
||||
// Self: Debug + Display;
|
||||
//
|
||||
#[derive(Error, Debug)]
|
||||
pub enum EnumDebugGeneric<E> {
|
||||
#[error("{0:?}")]
|
||||
FatalError(E),
|
||||
}
|
||||
|
||||
// Should expand to:
|
||||
//
|
||||
// impl<E> Display for EnumFromGeneric<E>;
|
||||
//
|
||||
// impl<E> Error for EnumFromGeneric<E>
|
||||
// where
|
||||
// EnumDebugGeneric<E>: Error + 'static,
|
||||
// Self: Debug + Display;
|
||||
//
|
||||
#[derive(Error, Debug)]
|
||||
pub enum EnumFromGeneric<E> {
|
||||
#[error("enum from generic")]
|
||||
Source(#[from] EnumDebugGeneric<E>),
|
||||
}
|
||||
|
||||
// Should expand to:
|
||||
//
|
||||
// impl<HasDisplay, HasDebug, HasNeither> Display
|
||||
// for EnumCompound<HasDisplay, HasDebug, HasNeither>
|
||||
// where
|
||||
// HasDisplay: Display,
|
||||
// HasDebug: Debug;
|
||||
//
|
||||
// impl<HasDisplay, HasDebug, HasNeither> Error
|
||||
// for EnumCompound<HasDisplay, HasDebug, HasNeither>
|
||||
// where
|
||||
// Self: Debug + Display;
|
||||
//
|
||||
#[derive(Error)]
|
||||
pub enum EnumCompound<HasDisplay, HasDebug, HasNeither> {
|
||||
#[error("{0} {1:?}")]
|
||||
DisplayDebug(HasDisplay, HasDebug),
|
||||
#[error("{0}")]
|
||||
Display(HasDisplay, HasNeither),
|
||||
#[error("{1:?}")]
|
||||
Debug(HasNeither, HasDebug),
|
||||
}
|
||||
|
||||
impl<HasDisplay, HasDebug, HasNeither> Debug for EnumCompound<HasDisplay, HasDebug, HasNeither> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.write_str("EnumCompound")
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_display_enum_compound() {
|
||||
let mut instance: EnumCompound<DisplayOnly, DebugOnly, NoFormat>;
|
||||
|
||||
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<E> Display for EnumTransparentGeneric<E>
|
||||
// where
|
||||
// E: Display;
|
||||
//
|
||||
// impl<E> Error for EnumTransparentGeneric<E>
|
||||
// where
|
||||
// E: Error,
|
||||
// Self: Debug + Display;
|
||||
//
|
||||
#[derive(Error, Debug)]
|
||||
pub enum EnumTransparentGeneric<E> {
|
||||
#[error(transparent)]
|
||||
Other(E),
|
||||
}
|
||||
|
||||
// Should expand to:
|
||||
//
|
||||
// impl<E> Display for StructDebugGeneric<E>
|
||||
// where
|
||||
// E: Debug;
|
||||
//
|
||||
// impl<E> Error for StructDebugGeneric<E>
|
||||
// where
|
||||
// Self: Debug + Display;
|
||||
//
|
||||
#[derive(Error, Debug)]
|
||||
#[error("{underlying:?}")]
|
||||
pub struct StructDebugGeneric<E> {
|
||||
pub underlying: E,
|
||||
}
|
||||
|
||||
// Should expand to:
|
||||
//
|
||||
// impl<E> Error for StructFromGeneric<E>
|
||||
// where
|
||||
// StructDebugGeneric<E>: Error + 'static,
|
||||
// Self: Debug + Display;
|
||||
//
|
||||
#[derive(Error, Debug)]
|
||||
pub struct StructFromGeneric<E> {
|
||||
#[from]
|
||||
pub source: StructDebugGeneric<E>,
|
||||
}
|
||||
|
||||
// Should expand to:
|
||||
//
|
||||
// impl<E> Display for StructTransparentGeneric<E>
|
||||
// where
|
||||
// E: Display;
|
||||
//
|
||||
// impl<E> Error for StructTransparentGeneric<E>
|
||||
// where
|
||||
// E: Error,
|
||||
// Self: Debug + Display;
|
||||
//
|
||||
#[derive(Error, Debug)]
|
||||
#[error(transparent)]
|
||||
pub struct StructTransparentGeneric<E>(pub E);
|
||||
|
||||
// Should expand to:
|
||||
//
|
||||
// impl<T: FromStr> Display for AssociatedTypeError<T>
|
||||
// where
|
||||
// T::Err: Display;
|
||||
//
|
||||
// impl<T: FromStr> Error for AssociatedTypeError<T>
|
||||
// where
|
||||
// Self: Debug + Display;
|
||||
//
|
||||
#[derive(Error, Debug)]
|
||||
pub enum AssociatedTypeError<T: FromStr> {
|
||||
#[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<T> {
|
||||
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<T> {
|
||||
thing: T,
|
||||
}
|
||||
|
||||
let error = Error { thing: 0xFFi32 };
|
||||
assert_eq!(error.to_string(), "0xff 0xFF");
|
||||
}
|
||||
98
subprojects/thiserror/tests/test_lints.rs
Normal file
98
subprojects/thiserror/tests/test_lints.rs
Normal file
@@ -0,0 +1,98 @@
|
||||
#![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);
|
||||
}
|
||||
109
subprojects/thiserror/tests/test_option.rs
Normal file
109
subprojects/thiserror/tests/test_option.rs
Normal file
@@ -0,0 +1,109 @@
|
||||
#![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<anyhow::Error>,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("...")]
|
||||
pub struct OptSourceAlwaysBacktrace {
|
||||
#[source]
|
||||
pub source: Option<anyhow::Error>,
|
||||
pub backtrace: Backtrace,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("...")]
|
||||
pub struct NoSourceOptBacktrace {
|
||||
#[backtrace]
|
||||
pub backtrace: Option<Backtrace>,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("...")]
|
||||
pub struct AlwaysSourceOptBacktrace {
|
||||
pub source: anyhow::Error,
|
||||
#[backtrace]
|
||||
pub backtrace: Option<Backtrace>,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("...")]
|
||||
pub struct OptSourceOptBacktrace {
|
||||
#[source]
|
||||
pub source: Option<anyhow::Error>,
|
||||
#[backtrace]
|
||||
pub backtrace: Option<Backtrace>,
|
||||
}
|
||||
}
|
||||
|
||||
#[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<anyhow::Error>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum OptSourceAlwaysBacktrace {
|
||||
#[error("...")]
|
||||
Test {
|
||||
#[source]
|
||||
source: Option<anyhow::Error>,
|
||||
backtrace: Backtrace,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum NoSourceOptBacktrace {
|
||||
#[error("...")]
|
||||
Test {
|
||||
#[backtrace]
|
||||
backtrace: Option<Backtrace>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum AlwaysSourceOptBacktrace {
|
||||
#[error("...")]
|
||||
Test {
|
||||
source: anyhow::Error,
|
||||
#[backtrace]
|
||||
backtrace: Option<Backtrace>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum OptSourceOptBacktrace {
|
||||
#[error("...")]
|
||||
Test {
|
||||
#[source]
|
||||
source: Option<anyhow::Error>,
|
||||
#[backtrace]
|
||||
backtrace: Option<Backtrace>,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(
|
||||
not(thiserror_nightly_testing),
|
||||
ignore = "requires `--cfg=thiserror_nightly_testing`"
|
||||
)]
|
||||
fn test_option() {}
|
||||
54
subprojects/thiserror/tests/test_path.rs
Normal file
54
subprojects/thiserror/tests/test_path.rs
Normal file
@@ -0,0 +1,54 @@
|
||||
#![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<T: Display>(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));
|
||||
}
|
||||
82
subprojects/thiserror/tests/test_source.rs
Normal file
82
subprojects/thiserror/tests/test_source.rs
Normal file
@@ -0,0 +1,82 @@
|
||||
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<dyn StdError + Send + 'static>,
|
||||
}
|
||||
|
||||
#[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::<io::Error>().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::<io::Error>().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::<io::Error>().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());
|
||||
}
|
||||
96
subprojects/thiserror/tests/test_transparent.rs
Normal file
96
subprojects/thiserror/tests/test_transparent.rs
Normal file
@@ -0,0 +1,96 @@
|
||||
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::<io::Error>().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());
|
||||
}
|
||||
7
subprojects/thiserror/tests/ui/bad-field-attr.rs
Normal file
7
subprojects/thiserror/tests/ui/bad-field-attr.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error(transparent)]
|
||||
pub struct Error(#[error(transparent)] std::io::Error);
|
||||
|
||||
fn main() {}
|
||||
5
subprojects/thiserror/tests/ui/bad-field-attr.stderr
Normal file
5
subprojects/thiserror/tests/ui/bad-field-attr.stderr
Normal file
@@ -0,0 +1,5 @@
|
||||
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);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
15
subprojects/thiserror/tests/ui/concat-display.rs
Normal file
15
subprojects/thiserror/tests/ui/concat-display.rs
Normal file
@@ -0,0 +1,15 @@
|
||||
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() {}
|
||||
10
subprojects/thiserror/tests/ui/concat-display.stderr
Normal file
10
subprojects/thiserror/tests/ui/concat-display.stderr
Normal file
@@ -0,0 +1,10 @@
|
||||
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)
|
||||
7
subprojects/thiserror/tests/ui/display-underscore.rs
Normal file
7
subprojects/thiserror/tests/ui/display-underscore.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("{_}")]
|
||||
pub struct Error;
|
||||
|
||||
fn main() {}
|
||||
7
subprojects/thiserror/tests/ui/display-underscore.stderr
Normal file
7
subprojects/thiserror/tests/ui/display-underscore.stderr
Normal file
@@ -0,0 +1,7 @@
|
||||
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
|
||||
13
subprojects/thiserror/tests/ui/duplicate-enum-source.rs
Normal file
13
subprojects/thiserror/tests/ui/duplicate-enum-source.rs
Normal file
@@ -0,0 +1,13 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ErrorEnum {
|
||||
Confusing {
|
||||
#[source]
|
||||
a: std::io::Error,
|
||||
#[source]
|
||||
b: anyhow::Error,
|
||||
},
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: duplicate #[source] attribute
|
||||
--> tests/ui/duplicate-enum-source.rs:8:9
|
||||
|
|
||||
8 | #[source]
|
||||
| ^^^^^^^^^
|
||||
23
subprojects/thiserror/tests/ui/duplicate-fmt.rs
Normal file
23
subprojects/thiserror/tests/ui/duplicate-fmt.rs
Normal file
@@ -0,0 +1,23 @@
|
||||
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() {}
|
||||
23
subprojects/thiserror/tests/ui/duplicate-fmt.stderr
Normal file
23
subprojects/thiserror/tests/ui/duplicate-fmt.stderr
Normal file
@@ -0,0 +1,23 @@
|
||||
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("...")]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
11
subprojects/thiserror/tests/ui/duplicate-struct-source.rs
Normal file
11
subprojects/thiserror/tests/ui/duplicate-struct-source.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub struct ErrorStruct {
|
||||
#[source]
|
||||
a: std::io::Error,
|
||||
#[source]
|
||||
b: anyhow::Error,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: duplicate #[source] attribute
|
||||
--> tests/ui/duplicate-struct-source.rs:7:5
|
||||
|
|
||||
7 | #[source]
|
||||
| ^^^^^^^^^
|
||||
8
subprojects/thiserror/tests/ui/duplicate-transparent.rs
Normal file
8
subprojects/thiserror/tests/ui/duplicate-transparent.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error(transparent)]
|
||||
#[error(transparent)]
|
||||
pub struct Error(anyhow::Error);
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: duplicate #[error(transparent)] attribute
|
||||
--> tests/ui/duplicate-transparent.rs:5:1
|
||||
|
|
||||
5 | #[error(transparent)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
7
subprojects/thiserror/tests/ui/expression-fallback.rs
Normal file
7
subprojects/thiserror/tests/ui/expression-fallback.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("".yellow)]
|
||||
pub struct ArgError;
|
||||
|
||||
fn main() {}
|
||||
24
subprojects/thiserror/tests/ui/expression-fallback.stderr
Normal file
24
subprojects/thiserror/tests/ui/expression-fallback.stderr
Normal file
@@ -0,0 +1,24 @@
|
||||
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
|
||||
14
subprojects/thiserror/tests/ui/fallback-impl-with-display.rs
Normal file
14
subprojects/thiserror/tests/ui/fallback-impl-with-display.rs
Normal file
@@ -0,0 +1,14 @@
|
||||
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() {}
|
||||
@@ -0,0 +1,16 @@
|
||||
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)
|
||||
15
subprojects/thiserror/tests/ui/from-backtrace-backtrace.rs
Normal file
15
subprojects/thiserror/tests/ui/from-backtrace-backtrace.rs
Normal file
@@ -0,0 +1,15 @@
|
||||
// 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() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: deriving From requires no fields other than source and backtrace
|
||||
--> tests/ui/from-backtrace-backtrace.rs:9:5
|
||||
|
|
||||
9 | #[from]
|
||||
| ^^^^^^^
|
||||
11
subprojects/thiserror/tests/ui/from-not-source.rs
Normal file
11
subprojects/thiserror/tests/ui/from-not-source.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub struct Error {
|
||||
#[source]
|
||||
source: std::io::Error,
|
||||
#[from]
|
||||
other: anyhow::Error,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
5
subprojects/thiserror/tests/ui/from-not-source.stderr
Normal file
5
subprojects/thiserror/tests/ui/from-not-source.stderr
Normal file
@@ -0,0 +1,5 @@
|
||||
error: #[from] is only supported on the source field, not any other field
|
||||
--> tests/ui/from-not-source.rs:7:5
|
||||
|
|
||||
7 | #[from]
|
||||
| ^^^^^^^
|
||||
11
subprojects/thiserror/tests/ui/invalid-input-impl-anyway.rs
Normal file
11
subprojects/thiserror/tests/ui/invalid-input-impl-anyway.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: expected attribute arguments in parentheses: #[error(...)]
|
||||
--> tests/ui/invalid-input-impl-anyway.rs:4:3
|
||||
|
|
||||
4 | #[error]
|
||||
| ^^^^^
|
||||
24
subprojects/thiserror/tests/ui/lifetime.rs
Normal file
24
subprojects/thiserror/tests/ui/lifetime.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
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: Debug>(T);
|
||||
|
||||
fn main() -> Result<(), Error<'static>> {
|
||||
Err(Error(Inner("some text")))
|
||||
}
|
||||
11
subprojects/thiserror/tests/ui/lifetime.stderr
Normal file
11
subprojects/thiserror/tests/ui/lifetime.stderr
Normal file
@@ -0,0 +1,11 @@
|
||||
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>),
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
9
subprojects/thiserror/tests/ui/missing-display.rs
Normal file
9
subprojects/thiserror/tests/ui/missing-display.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum MyError {
|
||||
First,
|
||||
Second,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
19
subprojects/thiserror/tests/ui/missing-display.stderr
Normal file
19
subprojects/thiserror/tests/ui/missing-display.stderr
Normal file
@@ -0,0 +1,19 @@
|
||||
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)
|
||||
10
subprojects/thiserror/tests/ui/missing-fmt.rs
Normal file
10
subprojects/thiserror/tests/ui/missing-fmt.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("...")]
|
||||
A(usize),
|
||||
B(usize),
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
5
subprojects/thiserror/tests/ui/missing-fmt.stderr
Normal file
5
subprojects/thiserror/tests/ui/missing-fmt.stderr
Normal file
@@ -0,0 +1,5 @@
|
||||
error: missing #[error("...")] display attribute
|
||||
--> tests/ui/missing-fmt.rs:7:5
|
||||
|
|
||||
7 | B(usize),
|
||||
| ^^^^^^^^
|
||||
18
subprojects/thiserror/tests/ui/no-display.rs
Normal file
18
subprojects/thiserror/tests/ui/no-display.rs
Normal file
@@ -0,0 +1,18 @@
|
||||
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() {}
|
||||
46
subprojects/thiserror/tests/ui/no-display.stderr
Normal file
46
subprojects/thiserror/tests/ui/no-display.stderr
Normal file
@@ -0,0 +1,46 @@
|
||||
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<T>
|
||||
Saturating<T>
|
||||
Wrapping<T>
|
||||
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)
|
||||
@@ -0,0 +1,7 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("invalid rdo_lookahead_frames {0} (expected < {})", i32::MAX)]
|
||||
pub struct Error(u32);
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
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)]
|
||||
| ^^^^^^^^
|
||||
12
subprojects/thiserror/tests/ui/raw-identifier.rs
Normal file
12
subprojects/thiserror/tests/ui/raw-identifier.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
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}");
|
||||
}
|
||||
21
subprojects/thiserror/tests/ui/raw-identifier.stderr
Normal file
21
subprojects/thiserror/tests/ui/raw-identifier.stderr
Normal file
@@ -0,0 +1,21 @@
|
||||
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#`
|
||||
11
subprojects/thiserror/tests/ui/same-from-type.rs
Normal file
11
subprojects/thiserror/tests/ui/same-from-type.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
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() {}
|
||||
8
subprojects/thiserror/tests/ui/same-from-type.stderr
Normal file
8
subprojects/thiserror/tests/ui/same-from-type.stderr
Normal file
@@ -0,0 +1,8 @@
|
||||
error[E0119]: conflicting implementations of trait `From<std::io::Error>` 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`
|
||||
12
subprojects/thiserror/tests/ui/source-enum-not-error.rs
Normal file
12
subprojects/thiserror/tests/ui/source-enum-not-error.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct NotError;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("...")]
|
||||
pub enum ErrorEnum {
|
||||
Broken { source: NotError },
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
22
subprojects/thiserror/tests/ui/source-enum-not-error.stderr
Normal file
22
subprojects/thiserror/tests/ui/source-enum-not-error.stderr
Normal file
@@ -0,0 +1,22 @@
|
||||
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`
|
||||
@@ -0,0 +1,12 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct NotError;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("...")]
|
||||
pub enum ErrorEnum {
|
||||
Broken(#[source] NotError),
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,22 @@
|
||||
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`
|
||||
12
subprojects/thiserror/tests/ui/source-struct-not-error.rs
Normal file
12
subprojects/thiserror/tests/ui/source-struct-not-error.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct NotError;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("...")]
|
||||
pub struct ErrorStruct {
|
||||
source: NotError,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,20 @@
|
||||
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`
|
||||
@@ -0,0 +1,10 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct NotError;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("...")]
|
||||
pub struct ErrorStruct(#[source] NotError);
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,20 @@
|
||||
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`
|
||||
7
subprojects/thiserror/tests/ui/struct-with-fmt.rs
Normal file
7
subprojects/thiserror/tests/ui/struct-with-fmt.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error(fmt = core::fmt::Octal::fmt)]
|
||||
pub struct Error(i32);
|
||||
|
||||
fn main() {}
|
||||
5
subprojects/thiserror/tests/ui/struct-with-fmt.stderr
Normal file
5
subprojects/thiserror/tests/ui/struct-with-fmt.stderr
Normal file
@@ -0,0 +1,5 @@
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
8
subprojects/thiserror/tests/ui/transparent-display.rs
Normal file
8
subprojects/thiserror/tests/ui/transparent-display.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error(transparent)]
|
||||
#[error("...")]
|
||||
pub struct Error(anyhow::Error);
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: cannot have both #[error(transparent)] and a display attribute
|
||||
--> tests/ui/transparent-display.rs:5:1
|
||||
|
|
||||
5 | #[error("...")]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
9
subprojects/thiserror/tests/ui/transparent-enum-many.rs
Normal file
9
subprojects/thiserror/tests/ui/transparent-enum-many.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error(transparent)]
|
||||
Other(anyhow::Error, String),
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,6 @@
|
||||
error: #[error(transparent)] requires exactly one field
|
||||
--> tests/ui/transparent-enum-many.rs:5:5
|
||||
|
|
||||
5 | / #[error(transparent)]
|
||||
6 | | Other(anyhow::Error, String),
|
||||
| |________________________________^
|
||||
@@ -0,0 +1,9 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error(transparent)]
|
||||
Other { message: String },
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,20 @@
|
||||
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<'_>`
|
||||
@@ -0,0 +1,9 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error(transparent)]
|
||||
Other(#[source] anyhow::Error),
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: transparent variant can't contain #[source]
|
||||
--> tests/ui/transparent-enum-source.rs:6:11
|
||||
|
|
||||
6 | Other(#[source] anyhow::Error),
|
||||
| ^^^^^^^^^
|
||||
@@ -0,0 +1,9 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error(transparent)]
|
||||
Other(String),
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,20 @@
|
||||
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<'_>`
|
||||
10
subprojects/thiserror/tests/ui/transparent-struct-many.rs
Normal file
10
subprojects/thiserror/tests/ui/transparent-struct-many.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error(transparent)]
|
||||
pub struct Error {
|
||||
inner: anyhow::Error,
|
||||
what: String,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: #[error(transparent)] requires exactly one field
|
||||
--> tests/ui/transparent-struct-many.rs:4:1
|
||||
|
|
||||
4 | #[error(transparent)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
@@ -0,0 +1,9 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error(transparent)]
|
||||
pub struct Error {
|
||||
message: String,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,18 @@
|
||||
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<'_>`
|
||||
@@ -0,0 +1,7 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error(transparent)]
|
||||
pub struct Error(#[source] anyhow::Error);
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: transparent error struct can't contain #[source]
|
||||
--> tests/ui/transparent-struct-source.rs:5:18
|
||||
|
|
||||
5 | pub struct Error(#[source] anyhow::Error);
|
||||
| ^^^^^^^^^
|
||||
@@ -0,0 +1,7 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error(transparent)]
|
||||
pub struct Error(String);
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,18 @@
|
||||
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<'_>`
|
||||
@@ -0,0 +1,9 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("{self}")]
|
||||
pub struct Error;
|
||||
|
||||
fn main() {
|
||||
__FAIL__;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
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}")]
|
||||
| ^^^^^^^^
|
||||
11
subprojects/thiserror/tests/ui/unexpected-field-fmt.rs
Normal file
11
subprojects/thiserror/tests/ui/unexpected-field-fmt.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Error {
|
||||
What {
|
||||
#[error("...")]
|
||||
io: std::io::Error,
|
||||
},
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
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("...")]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
@@ -0,0 +1,7 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[source]
|
||||
pub struct Error;
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: not expected here; the #[source] attribute belongs on a specific field
|
||||
--> tests/ui/unexpected-struct-source.rs:4:1
|
||||
|
|
||||
4 | #[source]
|
||||
| ^^^^^^^^^
|
||||
9
subprojects/thiserror/tests/ui/union.rs
Normal file
9
subprojects/thiserror/tests/ui/union.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error)]
|
||||
pub union U {
|
||||
msg: &'static str,
|
||||
num: usize,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
8
subprojects/thiserror/tests/ui/union.stderr
Normal file
8
subprojects/thiserror/tests/ui/union.stderr
Normal file
@@ -0,0 +1,8 @@
|
||||
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 | | }
|
||||
| |_^
|
||||
Reference in New Issue
Block a user