Repository: dtolnay/thiserror (rust)

Issue:
Lifetimes and #[error(transparent)]
Lifetimes appear to interfere with the use of `#[error(transparent)]`:
```rust
use thiserror::Error;

#[derive(Error, Debug)]
#[error(transparent)]
pub struct Error<'a> {
    inner: ErrorKind<'a>,
}

#[derive(Error, Debug)]
pub enum ErrorKind<'a> {
    #[error("unexpected token: {:?}", .token)]
    Unexpected { token: &'a str },
}
```

```
   Compiling ecl-parser v0.1.0 (/mnt/f/asd/clone/ecl-parse)
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
 --> src/bin/lol.rs:3:10
  |
3 | #[derive(Error, Debug)]
  |          ^^^^^
  |
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 5:18...
 --> src/bin/lol.rs:5:18
  |
5 | pub struct Error<'a> {
  |                  ^^
note: ...so that the types are compatible
 --> src/bin/lol.rs:3:10
  |
3 | #[derive(Error, Debug)]
  |          ^^^^^
  = note: expected `&ErrorKind<'_>`
             found `&ErrorKind<'a>`
  = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `ErrorKind<'_>` will meet its required lifetime bounds
 --> src/bin/lol.rs:3:10
  |
3 | #[derive(Error, Debug)]
  |          ^^^^^
  = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to previous error
```

* rustc 1.46.0 (04488afe3 2020-08-24)
* thiserror 1.0.22

Pull request:
Support non-static lifetime inside error(transparent)
Fixes #113.

Patch:
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<T: Error + 'static> 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
     }
 }


Test patch:
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());
+}