From 51a1ff6593870f5198b027b56d71dde554fbe635 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 22 May 2021 14:26:07 -0700 Subject: [PATCH 1/2] Add regression test for issue 113 This does not currently compile. error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements --> tests/test_transparent.rs:63:14 | 63 | #[derive(Error, Debug)] | ^^^^^ | note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 65:18... --> tests/test_transparent.rs:65:18 | 65 | struct Error<'a> { | ^^ note: ...so that the types are compatible --> tests/test_transparent.rs:63:14 | 63 | #[derive(Error, Debug)] | ^^^^^ = note: expected `&test_non_static::ErrorKind<'_>` found `&test_non_static::ErrorKind<'a>` = note: but, the lifetime must be valid for the static lifetime... note: ...so that the type `test_non_static::ErrorKind<'_>` will meet its required lifetime bounds --> tests/test_transparent.rs:63:14 | 63 | #[derive(Error, Debug)] | ^^^^^ = note: this error originates in the derive macro `Error` (in Nightly builds, run with -Z macro-backtrace for more info) --- tests/test_transparent.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/test_transparent.rs b/tests/test_transparent.rs index b862b25..84d7c91 100644 --- a/tests/test_transparent.rs +++ b/tests/test_transparent.rs @@ -57,3 +57,24 @@ fn test_anyhow() { 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()); +} From 1ed8751081107990b9d1b04b3397b4209442934d Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 22 May 2021 14:22:47 -0700 Subject: [PATCH 2/2] Support non-static AsDynError lifetimes --- src/aserror.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/aserror.rs b/src/aserror.rs index 8290296..f440034 100644 --- a/src/aserror.rs +++ b/src/aserror.rs @@ -1,33 +1,33 @@ use std::error::Error; -pub trait AsDynError { - fn as_dyn_error(&self) -> &(dyn Error + 'static); +pub trait AsDynError<'a> { + fn as_dyn_error(&self) -> &(dyn Error + 'a); } -impl AsDynError for T { +impl<'a, T: Error + 'a> AsDynError<'a> for T { #[inline] - fn as_dyn_error(&self) -> &(dyn Error + 'static) { + fn as_dyn_error(&self) -> &(dyn Error + 'a) { self } } -impl AsDynError for dyn Error + 'static { +impl<'a> AsDynError<'a> for dyn Error + 'a { #[inline] - fn as_dyn_error(&self) -> &(dyn Error + 'static) { + fn as_dyn_error(&self) -> &(dyn Error + 'a) { self } } -impl AsDynError for dyn Error + Send + 'static { +impl<'a> AsDynError<'a> for dyn Error + Send + 'a { #[inline] - fn as_dyn_error(&self) -> &(dyn Error + 'static) { + fn as_dyn_error(&self) -> &(dyn Error + 'a) { self } } -impl AsDynError for dyn Error + Send + Sync + 'static { +impl<'a> AsDynError<'a> for dyn Error + Send + Sync + 'a { #[inline] - fn as_dyn_error(&self) -> &(dyn Error + 'static) { + fn as_dyn_error(&self) -> &(dyn Error + 'a) { self } }