diff --git a/CHANGELOG.md b/CHANGELOG.md
index 87fa5252..86bde419 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -59,6 +59,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
   ([#279](https://github.com/JelteF/derive_more/pull/279))
 - `derive_more::derive` module exporting only macros, without traits.
   ([#290](https://github.com/JelteF/derive_more/pull/290))
+- Add support for source forwarding in `Error` derive.
+  ([#293](https://github.com/JelteF/derive_more/pull/293))
 
 ### Changed
 
diff --git a/impl/doc/error.md b/impl/doc/error.md
index cc755cb2..0c9b90c8 100644
--- a/impl/doc/error.md
+++ b/impl/doc/error.md
@@ -32,6 +32,11 @@ often [`From` as well](crate::From).
    called `Backtrace`. Then it would return that field as the `backtrace`.
 3. One of the fields is annotated with `#[error(backtrace)]`. Then it would
    return that field as the `backtrace`.
+4. The source field is annotated with `#[error(backtrace)]`. Then it would
+   forward implementation to the source.
+
+If the source field is annotated with `#[error(backtrace)]`, and another field
+is also annotated/was inferred, both backtraces will be provided.
 
 ### Ignoring fields for derives
 
@@ -41,6 +46,14 @@ detecting `backtrace` and `source`. It's also possible to mark a field only
 ignored for one of these methods by using `#[error(not(backtrace))]` or
 `#[error(not(source))]`.
 
+### Source Forwarding
+
+A struct, enum, or enum variant can be annotated with `#[error(forward)]` to forward
+the `source()` implementation to the source field (inferred or explicitly annotated),
+instead of returning the field itself.
+
+In general this approach is only recommended if the error is intended to be fully
+transparent, and forwards implementation of [`Display`](crate::Display) as well.
 
 ### What works in `no_std`?
 
@@ -127,6 +140,17 @@ enum CompoundError {
     },
     Tuple(WithExplicitSource),
     WithoutSource(#[error(not(source))] Tuple),
+    #[error(forward)]
+    #[from(ignore)]
+    ForwardedImplicitSource {
+        source: WithSource,
+    },
+    #[error(forward)]
+    #[from(ignore)]
+    ForwardedExplicitSourceWithBacktrace {
+        #[error(source, backtrace)]
+        explicit_source: WithSourceAndBacktrace,
+    }
 }
 
 assert!(Simple.source().is_none());
@@ -147,5 +171,14 @@ assert!(CompoundError::from(Simple).source().is_some());
 assert!(CompoundError::from(WithSource::default()).source().is_some());
 assert!(CompoundError::from(WithExplicitSource::default()).source().is_some());
 assert!(CompoundError::from(Tuple::default()).source().is_none());
+
+let forwarded = CompoundError::ForwardedImplicitSource { source: WithSource::default() };
+assert!(forwarded.source().is_some());
+assert!(forwarded.source().unwrap().is::<Simple>());
+
+let forwarded_with_backtrace = CompoundError::ForwardedExplicitSourceWithBacktrace { explicit_source: WithSourceAndBacktrace { source: Simple, backtrace: Backtrace::capture() } };
+assert!(forwarded_with_backtrace.source().is_some());
+assert!(forwarded_with_backtrace.source().unwrap().is::<Simple>());
+assert!(request_ref::<Backtrace>(&forwarded_with_backtrace).is_some());
 # }
 ```
diff --git a/impl/src/error.rs b/impl/src/error.rs
index 5456b9e0..63f30f43 100644
--- a/impl/src/error.rs
+++ b/impl/src/error.rs
@@ -1,4 +1,4 @@
-use proc_macro2::TokenStream;
+use proc_macro2::{Span, TokenStream};
 use quote::quote;
 use syn::{spanned::Spanned as _, Error, Result};
 
@@ -110,9 +110,13 @@ fn render_enum(
     let mut source_match_arms = Vec::new();
     let mut provide_match_arms = Vec::new();
 
-    for variant in state.enabled_variant_data().variants {
+    let variant_data = state.enabled_variant_data();
+
+    for (variant, variant_info) in variant_data.variants.iter().zip(&variant_data.infos)
+    {
         let default_info = FullMetaInfo {
             enabled: true,
+            forward: variant_info.forward,
             ..FullMetaInfo::default()
         };
 
@@ -160,9 +164,9 @@ fn render_enum(
 
 fn allowed_attr_params() -> AttrParams {
     AttrParams {
-        enum_: vec!["ignore"],
-        struct_: vec!["ignore"],
-        variant: vec!["ignore"],
+        enum_: vec!["ignore", "forward"],
+        struct_: vec!["ignore", "forward"],
+        variant: vec!["ignore", "forward"],
         field: vec!["ignore", "source", "backtrace"],
     }
 }
@@ -189,13 +193,21 @@ impl<'input, 'state> ParsedFields<'input, 'state> {
     fn render_source_as_struct(&self) -> Option<TokenStream> {
         let source = self.source?;
         let ident = &self.data.members[source];
-        Some(render_some(quote! { #ident }))
+        if self.data.infos[source].forward {
+            Some(quote! { ::derive_more::Error::source(&#ident) })
+        } else {
+            Some(render_some(quote! { #ident }))
+        }
     }
 
     fn render_source_as_enum_variant_match_arm(&self) -> Option<TokenStream> {
         let source = self.source?;
         let pattern = self.data.matcher(&[source], &[quote! { source }]);
-        let expr = render_some(quote! { source });
+        let expr = if self.data.infos[source].forward {
+            quote! { ::derive_more::Error::source(source) }
+        } else {
+            render_some(quote! { source })
+        };
         Some(quote! { #pattern => #expr })
     }
 
@@ -378,7 +390,12 @@ fn parse_fields_impl<'input, 'state, P>(
 where
     P: Fn(&str, &syn::Field, usize) -> bool,
 {
-    let MultiFieldData { fields, infos, .. } = state.enabled_fields_data();
+    let MultiFieldData {
+        fields,
+        infos,
+        variant_info,
+        ..
+    } = state.enabled_fields_data();
 
     let iter = fields
         .iter()
@@ -406,6 +423,11 @@ where
 
     if let Some((index, _, _)) = source {
         parsed_fields.source = Some(index);
+    } else if variant_info.forward {
+        return Err(syn::Error::new(
+            Span::call_site(),
+            "`#[error(forward)]` cannot be used when an error has no source",
+        ));
     }
 
     if let Some((index, _, _)) = backtrace {
diff --git a/tests/compile_fail/error/forward_no_source_enum.rs b/tests/compile_fail/error/forward_no_source_enum.rs
new file mode 100644
index 00000000..4d5e81d5
--- /dev/null
+++ b/tests/compile_fail/error/forward_no_source_enum.rs
@@ -0,0 +1,18 @@
+use derive_more::Error;
+
+#[derive(Debug, Error)]
+#[error(forward)]
+enum Foo {
+    Bar,
+    Baz {
+        source: Box<dyn Error + Send + 'static>,
+    },
+}
+
+impl ::core::fmt::Display for Foo {
+    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
+        write!(f, "")
+    }
+}
+
+fn main() {}
diff --git a/tests/compile_fail/error/forward_no_source_enum.stderr b/tests/compile_fail/error/forward_no_source_enum.stderr
new file mode 100644
index 00000000..2e0d36de
--- /dev/null
+++ b/tests/compile_fail/error/forward_no_source_enum.stderr
@@ -0,0 +1,7 @@
+error: `#[error(forward)]` cannot be used when an error has no source
+ --> tests/compile_fail/error/forward_no_source_enum.rs:3:17
+  |
+3 | #[derive(Debug, Error)]
+  |                 ^^^^^
+  |
+  = note: this error originates in the derive macro `Error` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/compile_fail/error/forward_no_source_struct.rs b/tests/compile_fail/error/forward_no_source_struct.rs
new file mode 100644
index 00000000..f5f359b5
--- /dev/null
+++ b/tests/compile_fail/error/forward_no_source_struct.rs
@@ -0,0 +1,13 @@
+use derive_more::Error;
+
+#[derive(Debug, Error)]
+#[error(forward)]
+struct Foo;
+
+impl ::core::fmt::Display for Foo {
+    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
+        write!(f, "")
+    }
+}
+
+fn main() {}
diff --git a/tests/compile_fail/error/forward_no_source_struct.stderr b/tests/compile_fail/error/forward_no_source_struct.stderr
new file mode 100644
index 00000000..9743137d
--- /dev/null
+++ b/tests/compile_fail/error/forward_no_source_struct.stderr
@@ -0,0 +1,7 @@
+error: `#[error(forward)]` cannot be used when an error has no source
+ --> tests/compile_fail/error/forward_no_source_struct.rs:3:17
+  |
+3 | #[derive(Debug, Error)]
+  |                 ^^^^^
+  |
+  = note: this error originates in the derive macro `Error` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/compile_fail/error/forward_no_source_variant.rs b/tests/compile_fail/error/forward_no_source_variant.rs
new file mode 100644
index 00000000..8830cc2a
--- /dev/null
+++ b/tests/compile_fail/error/forward_no_source_variant.rs
@@ -0,0 +1,19 @@
+use derive_more::Error;
+
+#[derive(Debug, Error)]
+enum Foo {
+    #[error(forward)]
+    Bar,
+    #[error(forward)]
+    Baz {
+        source: Box<dyn Error + Send + 'static>,
+    },
+}
+
+impl ::core::fmt::Display for Foo {
+    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
+        write!(f, "")
+    }
+}
+
+fn main() {}
diff --git a/tests/compile_fail/error/forward_no_source_variant.stderr b/tests/compile_fail/error/forward_no_source_variant.stderr
new file mode 100644
index 00000000..e30f9d03
--- /dev/null
+++ b/tests/compile_fail/error/forward_no_source_variant.stderr
@@ -0,0 +1,7 @@
+error: `#[error(forward)]` cannot be used when an error has no source
+ --> tests/compile_fail/error/forward_no_source_variant.rs:3:17
+  |
+3 | #[derive(Debug, Error)]
+  |                 ^^^^^
+  |
+  = note: this error originates in the derive macro `Error` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/error/derives_forward.rs b/tests/error/derives_forward.rs
new file mode 100644
index 00000000..9e80a44a
--- /dev/null
+++ b/tests/error/derives_forward.rs
@@ -0,0 +1,83 @@
+use super::*;
+
+derive_display!(Inner);
+#[derive(Debug, Error)]
+struct Inner {
+    source: SimpleErr,
+}
+
+derive_display!(StructAttr);
+#[derive(Debug, Error)]
+#[error(forward)]
+struct StructAttr {
+    source: Inner,
+}
+
+#[test]
+fn struct_attr() {
+    let err = StructAttr {
+        source: Inner { source: SimpleErr },
+    };
+
+    assert!(err.source().is_some());
+    assert!(err.source().unwrap().is::<SimpleErr>());
+}
+
+derive_display!(EnumAttr);
+#[derive(Debug, Error)]
+#[error(forward)]
+enum EnumAttr {
+    A {
+        source: Inner,
+    },
+    B {
+        #[error(source)]
+        explicit_source: Inner,
+    },
+}
+
+#[test]
+fn enum_attr() {
+    let err_a = EnumAttr::A {
+        source: Inner { source: SimpleErr },
+    };
+
+    let err_b = EnumAttr::B {
+        explicit_source: Inner { source: SimpleErr },
+    };
+
+    assert!(err_a.source().is_some());
+    assert!(err_a.source().unwrap().is::<SimpleErr>());
+
+    assert!(err_b.source().is_some());
+    assert!(err_b.source().unwrap().is::<SimpleErr>());
+}
+
+derive_display!(VariantAttr);
+#[derive(Debug, Error)]
+enum VariantAttr {
+    #[error(forward)]
+    A {
+        source: Inner,
+    },
+    B {
+        source: Inner,
+    },
+}
+
+#[test]
+fn variant_attr() {
+    let err_a = VariantAttr::A {
+        source: Inner { source: SimpleErr },
+    };
+
+    let err_b = VariantAttr::B {
+        source: Inner { source: SimpleErr },
+    };
+
+    assert!(err_a.source().is_some());
+    assert!(err_a.source().unwrap().is::<SimpleErr>());
+
+    assert!(err_b.source().is_some());
+    assert!(err_b.source().unwrap().is::<Inner>());
+}
diff --git a/tests/error/mod.rs b/tests/error/mod.rs
index 352d40aa..9cc47b48 100644
--- a/tests/error/mod.rs
+++ b/tests/error/mod.rs
@@ -47,6 +47,7 @@ mod derives_for_enums_with_source;
 mod derives_for_generic_enums_with_source;
 mod derives_for_generic_structs_with_source;
 mod derives_for_structs_with_source;
+mod derives_forward;
 
 #[cfg(all(feature = "std", nightly))]
 mod nightly;
diff --git a/tests/error/nightly/derives_forward.rs b/tests/error/nightly/derives_forward.rs
new file mode 100644
index 00000000..254bb487
--- /dev/null
+++ b/tests/error/nightly/derives_forward.rs
@@ -0,0 +1,149 @@
+use core::error::{request_ref, request_value};
+
+use super::*;
+
+derive_display!(Inner);
+#[derive(Debug, Error)]
+struct Inner {
+    #[error(backtrace)]
+    source: BacktraceErr,
+}
+
+derive_display!(StructAttr);
+#[derive(Debug, Error)]
+#[error(forward)]
+struct StructAttr {
+    #[error(backtrace)]
+    source: Inner,
+}
+
+impl StructAttr {
+    fn get_source_backtrace(&self) -> &Backtrace {
+        request_ref(&self.source.source).unwrap()
+    }
+}
+
+#[test]
+fn struct_attr() {
+    let err = StructAttr {
+        source: Inner {
+            source: BacktraceErr {
+                backtrace: Backtrace::force_capture(),
+            },
+        },
+    };
+
+    assert!(err.source().is_some());
+    assert!(err.source().unwrap().is::<BacktraceErr>());
+    assert!(request_ref::<Backtrace>(&err).is_some());
+    assert_eq!(request_value::<i32>(&err), Some(42));
+    assert_bt!(==, err, .get_source_backtrace);
+}
+
+derive_display!(EnumAttr);
+#[derive(Debug, Error)]
+#[error(forward)]
+enum EnumAttr {
+    A {
+        #[error(backtrace)]
+        source: Inner,
+    },
+    B {
+        #[error(source, backtrace)]
+        explicit_source: Inner,
+    },
+}
+
+impl EnumAttr {
+    fn get_source_backtrace(&self) -> &Backtrace {
+        request_ref(match self {
+            Self::A { source } => &source.source,
+            Self::B { explicit_source } => &explicit_source.source,
+        })
+        .unwrap()
+    }
+}
+
+#[test]
+fn enum_attr() {
+    let err_a = EnumAttr::A {
+        source: Inner {
+            source: BacktraceErr {
+                backtrace: Backtrace::force_capture(),
+            },
+        },
+    };
+    let err_b = EnumAttr::B {
+        explicit_source: Inner {
+            source: BacktraceErr {
+                backtrace: Backtrace::force_capture(),
+            },
+        },
+    };
+
+    assert!(err_a.source().is_some());
+    assert!(err_a.source().unwrap().is::<BacktraceErr>());
+    assert!(request_ref::<Backtrace>(&err_a).is_some());
+    assert_eq!(request_value::<i32>(&err_a), Some(42));
+    assert_bt!(==, err_a, .get_source_backtrace);
+
+    assert!(err_b.source().is_some());
+    assert!(err_b.source().unwrap().is::<BacktraceErr>());
+    assert!(request_ref::<Backtrace>(&err_b).is_some());
+    assert_eq!(request_value::<i32>(&err_b), Some(42));
+    assert_bt!(==, err_b, .get_source_backtrace);
+}
+
+derive_display!(VariantAttr);
+#[derive(Debug, Error)]
+enum VariantAttr {
+    #[error(forward)]
+    A {
+        #[error(backtrace)]
+        source: Inner,
+    },
+    B {
+        #[error(backtrace)]
+        source: Inner,
+    },
+}
+
+impl VariantAttr {
+    fn get_source_backtrace(&self) -> &Backtrace {
+        request_ref(match self {
+            Self::A { source } => &source.source,
+            Self::B { source } => &source.source,
+        })
+        .unwrap()
+    }
+}
+
+#[test]
+fn variant_attr() {
+    let err_a = VariantAttr::A {
+        source: Inner {
+            source: BacktraceErr {
+                backtrace: Backtrace::force_capture(),
+            },
+        },
+    };
+    let err_b = VariantAttr::B {
+        source: Inner {
+            source: BacktraceErr {
+                backtrace: Backtrace::force_capture(),
+            },
+        },
+    };
+
+    assert!(err_a.source().is_some());
+    assert!(err_a.source().unwrap().is::<BacktraceErr>());
+    assert!(request_ref::<Backtrace>(&err_a).is_some());
+    assert_eq!(request_value::<i32>(&err_a), Some(42));
+    assert_bt!(==, err_a, .get_source_backtrace);
+
+    assert!(err_b.source().is_some());
+    assert!(err_b.source().unwrap().is::<Inner>());
+    assert!(request_ref::<Backtrace>(&err_b).is_some());
+    assert_eq!(request_value::<i32>(&err_b), Some(42));
+    assert_bt!(==, err_b, .get_source_backtrace);
+}
diff --git a/tests/error/nightly/mod.rs b/tests/error/nightly/mod.rs
index b74d3bec..0582606b 100644
--- a/tests/error/nightly/mod.rs
+++ b/tests/error/nightly/mod.rs
@@ -69,6 +69,7 @@ mod derives_for_enums_with_backtrace;
 mod derives_for_generic_enums_with_backtrace;
 mod derives_for_generic_structs_with_backtrace;
 mod derives_for_structs_with_backtrace;
+mod derives_forward;
 
 derive_display!(BacktraceErr);
 #[derive(Debug)]