summaryrefslogtreecommitdiffstats
path: root/third_party/rust/thiserror/tests
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/thiserror/tests
parentInitial commit. (diff)
downloadfirefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz
firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/thiserror/tests')
-rw-r--r--third_party/rust/thiserror/tests/compiletest.rs8
-rw-r--r--third_party/rust/thiserror/tests/test_backtrace.rs213
-rw-r--r--third_party/rust/thiserror/tests/test_deprecated.rs10
-rw-r--r--third_party/rust/thiserror/tests/test_display.rs232
-rw-r--r--third_party/rust/thiserror/tests/test_error.rs57
-rw-r--r--third_party/rust/thiserror/tests/test_expr.rs89
-rw-r--r--third_party/rust/thiserror/tests/test_from.rs41
-rw-r--r--third_party/rust/thiserror/tests/test_lints.rs18
-rw-r--r--third_party/rust/thiserror/tests/test_option.rs106
-rw-r--r--third_party/rust/thiserror/tests/test_path.rs39
-rw-r--r--third_party/rust/thiserror/tests/test_source.rs50
-rw-r--r--third_party/rust/thiserror/tests/test_transparent.rs59
-rw-r--r--third_party/rust/thiserror/tests/ui/bad-field-attr.rs7
-rw-r--r--third_party/rust/thiserror/tests/ui/bad-field-attr.stderr5
-rw-r--r--third_party/rust/thiserror/tests/ui/duplicate-enum-source.rs13
-rw-r--r--third_party/rust/thiserror/tests/ui/duplicate-enum-source.stderr5
-rw-r--r--third_party/rust/thiserror/tests/ui/duplicate-fmt.rs8
-rw-r--r--third_party/rust/thiserror/tests/ui/duplicate-fmt.stderr5
-rw-r--r--third_party/rust/thiserror/tests/ui/duplicate-struct-source.rs11
-rw-r--r--third_party/rust/thiserror/tests/ui/duplicate-struct-source.stderr5
-rw-r--r--third_party/rust/thiserror/tests/ui/duplicate-transparent.rs8
-rw-r--r--third_party/rust/thiserror/tests/ui/duplicate-transparent.stderr5
-rw-r--r--third_party/rust/thiserror/tests/ui/from-not-source.rs11
-rw-r--r--third_party/rust/thiserror/tests/ui/from-not-source.stderr5
-rw-r--r--third_party/rust/thiserror/tests/ui/lifetime.rs13
-rw-r--r--third_party/rust/thiserror/tests/ui/lifetime.stderr5
-rw-r--r--third_party/rust/thiserror/tests/ui/missing-fmt.rs10
-rw-r--r--third_party/rust/thiserror/tests/ui/missing-fmt.stderr5
-rw-r--r--third_party/rust/thiserror/tests/ui/no-display.rs12
-rw-r--r--third_party/rust/thiserror/tests/ui/no-display.stderr12
-rw-r--r--third_party/rust/thiserror/tests/ui/source-enum-not-error.rs14
-rw-r--r--third_party/rust/thiserror/tests/ui/source-enum-not-error.stderr17
-rw-r--r--third_party/rust/thiserror/tests/ui/source-struct-not-error.rs12
-rw-r--r--third_party/rust/thiserror/tests/ui/source-struct-not-error.stderr16
-rw-r--r--third_party/rust/thiserror/tests/ui/transparent-display.rs8
-rw-r--r--third_party/rust/thiserror/tests/ui/transparent-display.stderr5
-rw-r--r--third_party/rust/thiserror/tests/ui/transparent-enum-many.rs9
-rw-r--r--third_party/rust/thiserror/tests/ui/transparent-enum-many.stderr6
-rw-r--r--third_party/rust/thiserror/tests/ui/transparent-enum-source.rs9
-rw-r--r--third_party/rust/thiserror/tests/ui/transparent-enum-source.stderr5
-rw-r--r--third_party/rust/thiserror/tests/ui/transparent-struct-many.rs10
-rw-r--r--third_party/rust/thiserror/tests/ui/transparent-struct-many.stderr5
-rw-r--r--third_party/rust/thiserror/tests/ui/transparent-struct-source.rs7
-rw-r--r--third_party/rust/thiserror/tests/ui/transparent-struct-source.stderr5
-rw-r--r--third_party/rust/thiserror/tests/ui/unexpected-field-fmt.rs11
-rw-r--r--third_party/rust/thiserror/tests/ui/unexpected-field-fmt.stderr5
-rw-r--r--third_party/rust/thiserror/tests/ui/unexpected-struct-source.rs7
-rw-r--r--third_party/rust/thiserror/tests/ui/unexpected-struct-source.stderr5
-rw-r--r--third_party/rust/thiserror/tests/ui/union.rs9
-rw-r--r--third_party/rust/thiserror/tests/ui/union.stderr8
50 files changed, 1240 insertions, 0 deletions
diff --git a/third_party/rust/thiserror/tests/compiletest.rs b/third_party/rust/thiserror/tests/compiletest.rs
new file mode 100644
index 0000000000..641d03cbf4
--- /dev/null
+++ b/third_party/rust/thiserror/tests/compiletest.rs
@@ -0,0 +1,8 @@
+#![deny(clippy::all, clippy::pedantic)]
+
+#[rustversion::attr(not(nightly), ignore)]
+#[test]
+fn ui() {
+ let t = trybuild::TestCases::new();
+ t.compile_fail("tests/ui/*.rs");
+}
diff --git a/third_party/rust/thiserror/tests/test_backtrace.rs b/third_party/rust/thiserror/tests/test_backtrace.rs
new file mode 100644
index 0000000000..09bc13dee9
--- /dev/null
+++ b/third_party/rust/thiserror/tests/test_backtrace.rs
@@ -0,0 +1,213 @@
+#![cfg_attr(thiserror_nightly_testing, feature(backtrace))]
+
+use thiserror::Error;
+
+#[derive(Error, Debug)]
+#[error("...")]
+pub struct Inner;
+
+#[cfg(thiserror_nightly_testing)]
+pub mod structs {
+ use super::Inner;
+ use std::backtrace::Backtrace;
+ use std::error::Error;
+ use std::sync::Arc;
+ use thiserror::Error;
+
+ #[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 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 OptBacktraceFrom {
+ #[from]
+ source: Inner,
+ #[backtrace]
+ backtrace: Option<Backtrace>,
+ }
+
+ #[derive(Error, Debug)]
+ #[error("...")]
+ pub struct ArcBacktraceFrom {
+ #[from]
+ source: Inner,
+ #[backtrace]
+ backtrace: Arc<Backtrace>,
+ }
+
+ #[test]
+ fn test_backtrace() {
+ let error = PlainBacktrace {
+ backtrace: Backtrace::capture(),
+ };
+ assert!(error.backtrace().is_some());
+
+ let error = ExplicitBacktrace {
+ backtrace: Backtrace::capture(),
+ };
+ assert!(error.backtrace().is_some());
+
+ let error = OptBacktrace {
+ backtrace: Some(Backtrace::capture()),
+ };
+ assert!(error.backtrace().is_some());
+
+ let error = ArcBacktrace {
+ backtrace: Arc::new(Backtrace::capture()),
+ };
+ assert!(error.backtrace().is_some());
+
+ let error = BacktraceFrom::from(Inner);
+ assert!(error.backtrace().is_some());
+
+ let error = OptBacktraceFrom::from(Inner);
+ assert!(error.backtrace().is_some());
+
+ let error = ArcBacktraceFrom::from(Inner);
+ assert!(error.backtrace().is_some());
+ }
+}
+
+#[cfg(thiserror_nightly_testing)]
+pub mod enums {
+ use super::Inner;
+ use std::backtrace::Backtrace;
+ use std::error::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 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.backtrace().is_some());
+
+ let error = ExplicitBacktrace::Test {
+ backtrace: Backtrace::capture(),
+ };
+ assert!(error.backtrace().is_some());
+
+ let error = OptBacktrace::Test {
+ backtrace: Some(Backtrace::capture()),
+ };
+ assert!(error.backtrace().is_some());
+
+ let error = ArcBacktrace::Test {
+ backtrace: Arc::new(Backtrace::capture()),
+ };
+ assert!(error.backtrace().is_some());
+
+ let error = BacktraceFrom::from(Inner);
+ assert!(error.backtrace().is_some());
+
+ let error = OptBacktraceFrom::from(Inner);
+ assert!(error.backtrace().is_some());
+
+ let error = ArcBacktraceFrom::from(Inner);
+ assert!(error.backtrace().is_some());
+ }
+}
+
+#[test]
+#[cfg_attr(not(thiserror_nightly_testing), ignore)]
+fn test_backtrace() {}
diff --git a/third_party/rust/thiserror/tests/test_deprecated.rs b/third_party/rust/thiserror/tests/test_deprecated.rs
new file mode 100644
index 0000000000..5524666abc
--- /dev/null
+++ b/third_party/rust/thiserror/tests/test_deprecated.rs
@@ -0,0 +1,10 @@
+#![deny(deprecated, clippy::all, clippy::pedantic)]
+
+use thiserror::Error;
+
+#[derive(Error, Debug)]
+pub enum Error {
+ #[deprecated]
+ #[error("...")]
+ Deprecated,
+}
diff --git a/third_party/rust/thiserror/tests/test_display.rs b/third_party/rust/thiserror/tests/test_display.rs
new file mode 100644
index 0000000000..9bc385a154
--- /dev/null
+++ b/third_party/rust/thiserror/tests/test_display.rs
@@ -0,0 +1,232 @@
+#![deny(clippy::all, clippy::pedantic)]
+
+use std::fmt::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("{}: {0}", 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_void() {
+ #[allow(clippy::empty_enum)]
+ #[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_macro_rules() {
+ // Regression test for https://github.com/dtolnay/thiserror/issues/86
+
+ macro_rules! decl_error {
+ ($variant:ident($value:ident)) => {
+ #[derive(Debug, Error)]
+ pub enum Error0 {
+ #[error("{0:?}")]
+ $variant($value),
+ }
+
+ #[derive(Debug, Error)]
+ #[error("{0:?}")]
+ pub enum Error1 {
+ $variant($value),
+ }
+ };
+ }
+
+ decl_error!(Repro(u8));
+
+ assert("0", Error0::Repro(0));
+ assert("0", Error1::Repro(0));
+}
diff --git a/third_party/rust/thiserror/tests/test_error.rs b/third_party/rust/thiserror/tests/test_error.rs
new file mode 100644
index 0000000000..ece7f91a90
--- /dev/null
+++ b/third_party/rust/thiserror/tests/test_error.rs
@@ -0,0 +1,57 @@
+#![deny(clippy::all, clippy::pedantic)]
+#![allow(dead_code)]
+
+use std::fmt::{self, Display};
+use std::io;
+use thiserror::Error;
+
+macro_rules! unimplemented_display {
+ ($ty:ty) => {
+ impl Display for $ty {
+ fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result {
+ unimplemented!()
+ }
+ }
+ };
+}
+
+#[derive(Error, Debug)]
+struct BracedError {
+ msg: String,
+ pos: usize,
+}
+
+#[derive(Error, Debug)]
+struct TupleError(String, usize);
+
+#[derive(Error, Debug)]
+struct UnitError;
+
+#[derive(Error, Debug)]
+struct WithSource {
+ #[source]
+ cause: io::Error,
+}
+
+#[derive(Error, Debug)]
+struct WithAnyhow {
+ #[source]
+ cause: anyhow::Error,
+}
+
+#[derive(Error, Debug)]
+enum EnumError {
+ Braced {
+ #[source]
+ cause: io::Error,
+ },
+ Tuple(#[source] io::Error),
+ Unit,
+}
+
+unimplemented_display!(BracedError);
+unimplemented_display!(TupleError);
+unimplemented_display!(UnitError);
+unimplemented_display!(WithSource);
+unimplemented_display!(WithAnyhow);
+unimplemented_display!(EnumError);
diff --git a/third_party/rust/thiserror/tests/test_expr.rs b/third_party/rust/thiserror/tests/test_expr.rs
new file mode 100644
index 0000000000..87a56cf584
--- /dev/null
+++ b/third_party/rust/thiserror/tests/test_expr.rs
@@ -0,0 +1,89 @@
+#![deny(clippy::all, clippy::pedantic)]
+#![allow(clippy::option_if_let_else)]
+
+use std::fmt::Display;
+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>,
+ },
+}
+
+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()),
+ },
+ );
+}
diff --git a/third_party/rust/thiserror/tests/test_from.rs b/third_party/rust/thiserror/tests/test_from.rs
new file mode 100644
index 0000000000..e8f01610d8
--- /dev/null
+++ b/third_party/rust/thiserror/tests/test_from.rs
@@ -0,0 +1,41 @@
+#![deny(clippy::all, clippy::pedantic)]
+
+use std::io;
+use thiserror::Error;
+
+#[derive(Error, Debug)]
+#[error("...")]
+pub struct ErrorStruct {
+ #[from]
+ source: io::Error,
+}
+
+#[derive(Error, Debug)]
+#[error("...")]
+pub struct ErrorTuple(#[from] io::Error);
+
+#[derive(Error, Debug)]
+#[error("...")]
+pub enum ErrorEnum {
+ Test {
+ #[from]
+ source: 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::<ErrorTuple>();
+ assert_impl::<ErrorEnum>();
+ assert_impl::<Many>();
+}
diff --git a/third_party/rust/thiserror/tests/test_lints.rs b/third_party/rust/thiserror/tests/test_lints.rs
new file mode 100644
index 0000000000..59699a4a3f
--- /dev/null
+++ b/third_party/rust/thiserror/tests/test_lints.rs
@@ -0,0 +1,18 @@
+use thiserror::Error;
+
+pub use std::error::Error;
+
+#[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(Debug, Error)]
+ #[error("...")]
+ pub struct MyError;
+
+ let _: MyError;
+}
diff --git a/third_party/rust/thiserror/tests/test_option.rs b/third_party/rust/thiserror/tests/test_option.rs
new file mode 100644
index 0000000000..ca21713852
--- /dev/null
+++ b/third_party/rust/thiserror/tests/test_option.rs
@@ -0,0 +1,106 @@
+#![cfg_attr(thiserror_nightly_testing, feature(backtrace))]
+#![deny(clippy::all, clippy::pedantic)]
+
+#[cfg(thiserror_nightly_testing)]
+pub mod structs {
+ use std::backtrace::Backtrace;
+ use thiserror::Error;
+
+ #[derive(Error, Debug)]
+ #[error("...")]
+ pub struct OptSourceNoBacktrace {
+ #[source]
+ source: Option<anyhow::Error>,
+ }
+
+ #[derive(Error, Debug)]
+ #[error("...")]
+ pub struct OptSourceAlwaysBacktrace {
+ #[source]
+ source: Option<anyhow::Error>,
+ backtrace: Backtrace,
+ }
+
+ #[derive(Error, Debug)]
+ #[error("...")]
+ pub struct NoSourceOptBacktrace {
+ #[backtrace]
+ backtrace: Option<Backtrace>,
+ }
+
+ #[derive(Error, Debug)]
+ #[error("...")]
+ pub struct AlwaysSourceOptBacktrace {
+ source: anyhow::Error,
+ #[backtrace]
+ backtrace: Option<Backtrace>,
+ }
+
+ #[derive(Error, Debug)]
+ #[error("...")]
+ pub struct OptSourceOptBacktrace {
+ #[source]
+ source: Option<anyhow::Error>,
+ #[backtrace]
+ 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)]
+fn test_option() {}
diff --git a/third_party/rust/thiserror/tests/test_path.rs b/third_party/rust/thiserror/tests/test_path.rs
new file mode 100644
index 0000000000..a10b1f3426
--- /dev/null
+++ b/third_party/rust/thiserror/tests/test_path.rs
@@ -0,0 +1,39 @@
+#![deny(clippy::all, clippy::pedantic)]
+
+use ref_cast::RefCast;
+use std::fmt::Display;
+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),
+}
+
+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));
+}
diff --git a/third_party/rust/thiserror/tests/test_source.rs b/third_party/rust/thiserror/tests/test_source.rs
new file mode 100644
index 0000000000..66d9dad592
--- /dev/null
+++ b/third_party/rust/thiserror/tests/test_source.rs
@@ -0,0 +1,50 @@
+#![deny(clippy::all, clippy::pedantic)]
+
+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();
+}
diff --git a/third_party/rust/thiserror/tests/test_transparent.rs b/third_party/rust/thiserror/tests/test_transparent.rs
new file mode 100644
index 0000000000..b862b2546f
--- /dev/null
+++ b/third_party/rust/thiserror/tests/test_transparent.rs
@@ -0,0 +1,59 @@
+#![deny(clippy::all, clippy::pedantic)]
+
+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_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());
+}
diff --git a/third_party/rust/thiserror/tests/ui/bad-field-attr.rs b/third_party/rust/thiserror/tests/ui/bad-field-attr.rs
new file mode 100644
index 0000000000..d5429b2b26
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/bad-field-attr.rs
@@ -0,0 +1,7 @@
+use thiserror::Error;
+
+#[derive(Error, Debug)]
+#[error(transparent)]
+pub struct Error(#[error(transparent)] std::io::Error);
+
+fn main() {}
diff --git a/third_party/rust/thiserror/tests/ui/bad-field-attr.stderr b/third_party/rust/thiserror/tests/ui/bad-field-attr.stderr
new file mode 100644
index 0000000000..ecc4702597
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/bad-field-attr.stderr
@@ -0,0 +1,5 @@
+error: #[error(transparent)] needs to go outside the enum or struct, not on an individual field
+ --> $DIR/bad-field-attr.rs:5:18
+ |
+5 | pub struct Error(#[error(transparent)] std::io::Error);
+ | ^^^^^^^^^^^^^^^^^^^^^
diff --git a/third_party/rust/thiserror/tests/ui/duplicate-enum-source.rs b/third_party/rust/thiserror/tests/ui/duplicate-enum-source.rs
new file mode 100644
index 0000000000..15e579f8fa
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/duplicate-enum-source.rs
@@ -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() {}
diff --git a/third_party/rust/thiserror/tests/ui/duplicate-enum-source.stderr b/third_party/rust/thiserror/tests/ui/duplicate-enum-source.stderr
new file mode 100644
index 0000000000..55d81be023
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/duplicate-enum-source.stderr
@@ -0,0 +1,5 @@
+error: duplicate #[source] attribute
+ --> $DIR/duplicate-enum-source.rs:8:9
+ |
+8 | #[source]
+ | ^^^^^^^^^
diff --git a/third_party/rust/thiserror/tests/ui/duplicate-fmt.rs b/third_party/rust/thiserror/tests/ui/duplicate-fmt.rs
new file mode 100644
index 0000000000..cb3d67881f
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/duplicate-fmt.rs
@@ -0,0 +1,8 @@
+use thiserror::Error;
+
+#[derive(Error, Debug)]
+#[error("...")]
+#[error("...")]
+pub struct Error;
+
+fn main() {}
diff --git a/third_party/rust/thiserror/tests/ui/duplicate-fmt.stderr b/third_party/rust/thiserror/tests/ui/duplicate-fmt.stderr
new file mode 100644
index 0000000000..32066406f6
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/duplicate-fmt.stderr
@@ -0,0 +1,5 @@
+error: only one #[error(...)] attribute is allowed
+ --> $DIR/duplicate-fmt.rs:5:1
+ |
+5 | #[error("...")]
+ | ^^^^^^^^^^^^^^^
diff --git a/third_party/rust/thiserror/tests/ui/duplicate-struct-source.rs b/third_party/rust/thiserror/tests/ui/duplicate-struct-source.rs
new file mode 100644
index 0000000000..569df8dd40
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/duplicate-struct-source.rs
@@ -0,0 +1,11 @@
+use thiserror::Error;
+
+#[derive(Error, Debug)]
+pub struct ErrorStruct {
+ #[source]
+ a: std::io::Error,
+ #[source]
+ b: anyhow::Error,
+}
+
+fn main() {}
diff --git a/third_party/rust/thiserror/tests/ui/duplicate-struct-source.stderr b/third_party/rust/thiserror/tests/ui/duplicate-struct-source.stderr
new file mode 100644
index 0000000000..76fc6f513b
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/duplicate-struct-source.stderr
@@ -0,0 +1,5 @@
+error: duplicate #[source] attribute
+ --> $DIR/duplicate-struct-source.rs:7:5
+ |
+7 | #[source]
+ | ^^^^^^^^^
diff --git a/third_party/rust/thiserror/tests/ui/duplicate-transparent.rs b/third_party/rust/thiserror/tests/ui/duplicate-transparent.rs
new file mode 100644
index 0000000000..49c0e46679
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/duplicate-transparent.rs
@@ -0,0 +1,8 @@
+use thiserror::Error;
+
+#[derive(Error, Debug)]
+#[error(transparent)]
+#[error(transparent)]
+pub struct Error(anyhow::Error);
+
+fn main() {}
diff --git a/third_party/rust/thiserror/tests/ui/duplicate-transparent.stderr b/third_party/rust/thiserror/tests/ui/duplicate-transparent.stderr
new file mode 100644
index 0000000000..c9634752ac
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/duplicate-transparent.stderr
@@ -0,0 +1,5 @@
+error: duplicate #[error(transparent)] attribute
+ --> $DIR/duplicate-transparent.rs:5:1
+ |
+5 | #[error(transparent)]
+ | ^^^^^^^^^^^^^^^^^^^^^
diff --git a/third_party/rust/thiserror/tests/ui/from-not-source.rs b/third_party/rust/thiserror/tests/ui/from-not-source.rs
new file mode 100644
index 0000000000..d1855bec5c
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/from-not-source.rs
@@ -0,0 +1,11 @@
+use thiserror::Error;
+
+#[derive(Debug, Error)]
+pub struct Error {
+ #[source]
+ source: std::io::Error,
+ #[from]
+ other: anyhow::Error,
+}
+
+fn main() {}
diff --git a/third_party/rust/thiserror/tests/ui/from-not-source.stderr b/third_party/rust/thiserror/tests/ui/from-not-source.stderr
new file mode 100644
index 0000000000..b656c8ed6b
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/from-not-source.stderr
@@ -0,0 +1,5 @@
+error: #[from] is only supported on the source field, not any other field
+ --> $DIR/from-not-source.rs:7:5
+ |
+7 | #[from]
+ | ^^^^^^^
diff --git a/third_party/rust/thiserror/tests/ui/lifetime.rs b/third_party/rust/thiserror/tests/ui/lifetime.rs
new file mode 100644
index 0000000000..63c6970dbc
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/lifetime.rs
@@ -0,0 +1,13 @@
+use thiserror::Error;
+
+#[derive(Error, Debug)]
+#[error("error")]
+struct Error<'a>(#[from] Inner<'a>);
+
+#[derive(Error, Debug)]
+#[error("{0}")]
+struct Inner<'a>(&'a str);
+
+fn main() -> Result<(), Error<'static>> {
+ Err(Error(Inner("some text")))
+}
diff --git a/third_party/rust/thiserror/tests/ui/lifetime.stderr b/third_party/rust/thiserror/tests/ui/lifetime.stderr
new file mode 100644
index 0000000000..500f6abaac
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/lifetime.stderr
@@ -0,0 +1,5 @@
+error: non-static lifetimes are not allowed in the source of an error
+ --> $DIR/lifetime.rs:5:18
+ |
+5 | struct Error<'a>(#[from] Inner<'a>);
+ | ^^^^^^^^^^^^^^^^^
diff --git a/third_party/rust/thiserror/tests/ui/missing-fmt.rs b/third_party/rust/thiserror/tests/ui/missing-fmt.rs
new file mode 100644
index 0000000000..d52fbdf0d9
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/missing-fmt.rs
@@ -0,0 +1,10 @@
+use thiserror::Error;
+
+#[derive(Error, Debug)]
+pub enum Error {
+ #[error("...")]
+ A(usize),
+ B(usize),
+}
+
+fn main() {}
diff --git a/third_party/rust/thiserror/tests/ui/missing-fmt.stderr b/third_party/rust/thiserror/tests/ui/missing-fmt.stderr
new file mode 100644
index 0000000000..1d21b1b0f5
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/missing-fmt.stderr
@@ -0,0 +1,5 @@
+error: missing #[error("...")] display attribute
+ --> $DIR/missing-fmt.rs:7:5
+ |
+7 | B(usize),
+ | ^^^^^^^^
diff --git a/third_party/rust/thiserror/tests/ui/no-display.rs b/third_party/rust/thiserror/tests/ui/no-display.rs
new file mode 100644
index 0000000000..181a66e02c
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/no-display.rs
@@ -0,0 +1,12 @@
+use thiserror::Error;
+
+#[derive(Debug)]
+struct NoDisplay;
+
+#[derive(Error, Debug)]
+#[error("thread: {thread}")]
+pub struct Error {
+ thread: NoDisplay,
+}
+
+fn main() {}
diff --git a/third_party/rust/thiserror/tests/ui/no-display.stderr b/third_party/rust/thiserror/tests/ui/no-display.stderr
new file mode 100644
index 0000000000..b1a0c495f1
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/no-display.stderr
@@ -0,0 +1,12 @@
+error[E0599]: no method named `as_display` found for reference `&NoDisplay` in the current scope
+ --> $DIR/no-display.rs:7:9
+ |
+4 | struct NoDisplay;
+ | ----------------- doesn't satisfy `NoDisplay: std::fmt::Display`
+...
+7 | #[error("thread: {thread}")]
+ | ^^^^^^^^^^^^^^^^^^ method not found in `&NoDisplay`
+ |
+ = note: the method `as_display` exists but the following trait bounds were not satisfied:
+ `NoDisplay: std::fmt::Display`
+ which is required by `&NoDisplay: DisplayAsDisplay`
diff --git a/third_party/rust/thiserror/tests/ui/source-enum-not-error.rs b/third_party/rust/thiserror/tests/ui/source-enum-not-error.rs
new file mode 100644
index 0000000000..3eb0d3e866
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/source-enum-not-error.rs
@@ -0,0 +1,14 @@
+use thiserror::Error;
+
+#[derive(Debug)]
+pub struct NotError;
+
+#[derive(Error, Debug)]
+#[error("...")]
+pub enum ErrorEnum {
+ Broken {
+ source: NotError,
+ },
+}
+
+fn main() {}
diff --git a/third_party/rust/thiserror/tests/ui/source-enum-not-error.stderr b/third_party/rust/thiserror/tests/ui/source-enum-not-error.stderr
new file mode 100644
index 0000000000..3dee730d58
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/source-enum-not-error.stderr
@@ -0,0 +1,17 @@
+error[E0599]: no method named `as_dyn_error` found for reference `&NotError` in the current scope
+ --> $DIR/source-enum-not-error.rs:10:9
+ |
+4 | pub struct NotError;
+ | --------------------
+ | |
+ | doesn't satisfy `NotError: AsDynError`
+ | doesn't satisfy `NotError: std::error::Error`
+...
+10 | source: NotError,
+ | ^^^^^^ method not found in `&NotError`
+ |
+ = note: the method `as_dyn_error` exists but 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`
diff --git a/third_party/rust/thiserror/tests/ui/source-struct-not-error.rs b/third_party/rust/thiserror/tests/ui/source-struct-not-error.rs
new file mode 100644
index 0000000000..d59df1eef8
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/source-struct-not-error.rs
@@ -0,0 +1,12 @@
+use thiserror::Error;
+
+#[derive(Debug)]
+struct NotError;
+
+#[derive(Error, Debug)]
+#[error("...")]
+pub struct ErrorStruct {
+ source: NotError,
+}
+
+fn main() {}
diff --git a/third_party/rust/thiserror/tests/ui/source-struct-not-error.stderr b/third_party/rust/thiserror/tests/ui/source-struct-not-error.stderr
new file mode 100644
index 0000000000..0aa03ddcc9
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/source-struct-not-error.stderr
@@ -0,0 +1,16 @@
+error[E0599]: no method named `as_dyn_error` found for struct `NotError` in the current scope
+ --> $DIR/source-struct-not-error.rs:9:5
+ |
+4 | struct NotError;
+ | ----------------
+ | |
+ | method `as_dyn_error` not found for this
+ | doesn't satisfy `NotError: AsDynError`
+ | doesn't satisfy `NotError: std::error::Error`
+...
+9 | source: NotError,
+ | ^^^^^^ method not found in `NotError`
+ |
+ = note: the method `as_dyn_error` exists but the following trait bounds were not satisfied:
+ `NotError: std::error::Error`
+ which is required by `NotError: AsDynError`
diff --git a/third_party/rust/thiserror/tests/ui/transparent-display.rs b/third_party/rust/thiserror/tests/ui/transparent-display.rs
new file mode 100644
index 0000000000..2a59f183ba
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/transparent-display.rs
@@ -0,0 +1,8 @@
+use thiserror::Error;
+
+#[derive(Error, Debug)]
+#[error(transparent)]
+#[error("...")]
+pub struct Error(anyhow::Error);
+
+fn main() {}
diff --git a/third_party/rust/thiserror/tests/ui/transparent-display.stderr b/third_party/rust/thiserror/tests/ui/transparent-display.stderr
new file mode 100644
index 0000000000..014883054a
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/transparent-display.stderr
@@ -0,0 +1,5 @@
+error: cannot have both #[error(transparent)] and a display attribute
+ --> $DIR/transparent-display.rs:5:1
+ |
+5 | #[error("...")]
+ | ^^^^^^^^^^^^^^^
diff --git a/third_party/rust/thiserror/tests/ui/transparent-enum-many.rs b/third_party/rust/thiserror/tests/ui/transparent-enum-many.rs
new file mode 100644
index 0000000000..e2a73a4700
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/transparent-enum-many.rs
@@ -0,0 +1,9 @@
+use thiserror::Error;
+
+#[derive(Error, Debug)]
+pub enum Error {
+ #[error(transparent)]
+ Other(anyhow::Error, String),
+}
+
+fn main() {}
diff --git a/third_party/rust/thiserror/tests/ui/transparent-enum-many.stderr b/third_party/rust/thiserror/tests/ui/transparent-enum-many.stderr
new file mode 100644
index 0000000000..0c409ef401
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/transparent-enum-many.stderr
@@ -0,0 +1,6 @@
+error: #[error(transparent)] requires exactly one field
+ --> $DIR/transparent-enum-many.rs:5:5
+ |
+5 | / #[error(transparent)]
+6 | | Other(anyhow::Error, String),
+ | |________________________________^
diff --git a/third_party/rust/thiserror/tests/ui/transparent-enum-source.rs b/third_party/rust/thiserror/tests/ui/transparent-enum-source.rs
new file mode 100644
index 0000000000..3849f66e78
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/transparent-enum-source.rs
@@ -0,0 +1,9 @@
+use thiserror::Error;
+
+#[derive(Error, Debug)]
+pub enum Error {
+ #[error(transparent)]
+ Other(#[source] anyhow::Error),
+}
+
+fn main() {}
diff --git a/third_party/rust/thiserror/tests/ui/transparent-enum-source.stderr b/third_party/rust/thiserror/tests/ui/transparent-enum-source.stderr
new file mode 100644
index 0000000000..a4e698570f
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/transparent-enum-source.stderr
@@ -0,0 +1,5 @@
+error: transparent variant can't contain #[source]
+ --> $DIR/transparent-enum-source.rs:6:11
+ |
+6 | Other(#[source] anyhow::Error),
+ | ^^^^^^^^^
diff --git a/third_party/rust/thiserror/tests/ui/transparent-struct-many.rs b/third_party/rust/thiserror/tests/ui/transparent-struct-many.rs
new file mode 100644
index 0000000000..18f2466450
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/transparent-struct-many.rs
@@ -0,0 +1,10 @@
+use thiserror::Error;
+
+#[derive(Error, Debug)]
+#[error(transparent)]
+pub struct Error {
+ inner: anyhow::Error,
+ what: String,
+}
+
+fn main() {}
diff --git a/third_party/rust/thiserror/tests/ui/transparent-struct-many.stderr b/third_party/rust/thiserror/tests/ui/transparent-struct-many.stderr
new file mode 100644
index 0000000000..102f0b3e25
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/transparent-struct-many.stderr
@@ -0,0 +1,5 @@
+error: #[error(transparent)] requires exactly one field
+ --> $DIR/transparent-struct-many.rs:4:1
+ |
+4 | #[error(transparent)]
+ | ^^^^^^^^^^^^^^^^^^^^^
diff --git a/third_party/rust/thiserror/tests/ui/transparent-struct-source.rs b/third_party/rust/thiserror/tests/ui/transparent-struct-source.rs
new file mode 100644
index 0000000000..d4512c288b
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/transparent-struct-source.rs
@@ -0,0 +1,7 @@
+use thiserror::Error;
+
+#[derive(Error, Debug)]
+#[error(transparent)]
+pub struct Error(#[source] anyhow::Error);
+
+fn main() {}
diff --git a/third_party/rust/thiserror/tests/ui/transparent-struct-source.stderr b/third_party/rust/thiserror/tests/ui/transparent-struct-source.stderr
new file mode 100644
index 0000000000..16ea50b27e
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/transparent-struct-source.stderr
@@ -0,0 +1,5 @@
+error: transparent error struct can't contain #[source]
+ --> $DIR/transparent-struct-source.rs:5:18
+ |
+5 | pub struct Error(#[source] anyhow::Error);
+ | ^^^^^^^^^
diff --git a/third_party/rust/thiserror/tests/ui/unexpected-field-fmt.rs b/third_party/rust/thiserror/tests/ui/unexpected-field-fmt.rs
new file mode 100644
index 0000000000..7c439d941f
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/unexpected-field-fmt.rs
@@ -0,0 +1,11 @@
+use thiserror::Error;
+
+#[derive(Error, Debug)]
+pub enum Error {
+ What {
+ #[error("...")]
+ io: std::io::Error,
+ },
+}
+
+fn main() {}
diff --git a/third_party/rust/thiserror/tests/ui/unexpected-field-fmt.stderr b/third_party/rust/thiserror/tests/ui/unexpected-field-fmt.stderr
new file mode 100644
index 0000000000..42d80db2c4
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/unexpected-field-fmt.stderr
@@ -0,0 +1,5 @@
+error: not expected here; the #[error(...)] attribute belongs on top of a struct or an enum variant
+ --> $DIR/unexpected-field-fmt.rs:6:9
+ |
+6 | #[error("...")]
+ | ^^^^^^^^^^^^^^^
diff --git a/third_party/rust/thiserror/tests/ui/unexpected-struct-source.rs b/third_party/rust/thiserror/tests/ui/unexpected-struct-source.rs
new file mode 100644
index 0000000000..f39649424c
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/unexpected-struct-source.rs
@@ -0,0 +1,7 @@
+use thiserror::Error;
+
+#[derive(Error, Debug)]
+#[source]
+pub struct Error;
+
+fn main() {}
diff --git a/third_party/rust/thiserror/tests/ui/unexpected-struct-source.stderr b/third_party/rust/thiserror/tests/ui/unexpected-struct-source.stderr
new file mode 100644
index 0000000000..f48d5547e2
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/unexpected-struct-source.stderr
@@ -0,0 +1,5 @@
+error: not expected here; the #[source] attribute belongs on a specific field
+ --> $DIR/unexpected-struct-source.rs:4:1
+ |
+4 | #[source]
+ | ^^^^^^^^^
diff --git a/third_party/rust/thiserror/tests/ui/union.rs b/third_party/rust/thiserror/tests/ui/union.rs
new file mode 100644
index 0000000000..cd6a9346d5
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/union.rs
@@ -0,0 +1,9 @@
+use thiserror::Error;
+
+#[derive(Error)]
+pub union U {
+ msg: &'static str,
+ num: usize,
+}
+
+fn main() {}
diff --git a/third_party/rust/thiserror/tests/ui/union.stderr b/third_party/rust/thiserror/tests/ui/union.stderr
new file mode 100644
index 0000000000..a378011c81
--- /dev/null
+++ b/third_party/rust/thiserror/tests/ui/union.stderr
@@ -0,0 +1,8 @@
+error: union as errors are not supported
+ --> $DIR/union.rs:4:1
+ |
+4 | / pub union U {
+5 | | msg: &'static str,
+6 | | num: usize,
+7 | | }
+ | |_^