diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml
index 36952c2..b8d27bd 100644
--- a/.github/workflows/gh-pages.yml
+++ b/.github/workflows/gh-pages.yml
@@ -35,6 +35,12 @@ jobs:
       - name: Build mdbook
         run: cargo install mdbook
 
+      - name: Build cargo-readme
+        run: cargo install cargo-readme
+
+      - name: Build README.md
+        run: cargo readme > README.md
+
       - name: Build
         run: mdbook build
 
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index 312cbfd..9e148b2 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -1,15 +1,86 @@
 name: Rust
 
-on: [push]
+on:
+  # Trigger the workflow on push or pull request,
+  # but only for the master branch
+  push:
+    branches:
+      - master
+  pull_request:
+    branches:
+      - master
+  release:
+    types:
+      - created
 
 jobs:
   build:
-
     runs-on: ubuntu-latest
-
+    strategy:
+      matrix:
+        version:
+          - 1.46.0
+          - stable
+          - beta
+          - nightly
     steps:
-    - uses: actions/checkout@v2
-    - name: Build
-      run: cargo build --verbose
-    - name: Run tests
-      run: cargo test --verbose
+      - uses: actions/checkout@v1
+      - name: Install toolchain
+        uses: actions-rs/toolchain@v1
+        with:
+          toolchain: ${{ matrix.version }}
+          default: true
+          profile: minimal
+      - name: Build
+        run: cargo build --verbose
+      - name: Run tests
+        run: cargo test --verbose
+      - name: Build --all-features
+        run: cargo build --verbose --all-features
+      - name: Run tests --all-features
+        run: cargo test --verbose --all-features
+
+  fmt:
+    name: cargo fmt
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - uses: actions-rs/toolchain@v1
+        with:
+          components: rustfmt
+          toolchain: stable
+          profile: minimal
+          override: true
+      - uses: actions-rs/cargo@v1
+        with:
+          command: fmt
+          args: --all -- --check
+
+  clippy:
+    name: cargo clippy
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - uses: actions-rs/toolchain@v1
+        with:
+          components: clippy
+          toolchain: stable
+          profile: minimal
+          override: true
+      - uses: actions-rs/cargo@v1
+        with:
+          command: clippy
+          args: -- -D warnings
+
+  readme:
+    name: cargo readme
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - uses: actions-rs/toolchain@v1
+        with:
+          toolchain: stable
+          profile: minimal
+          override: true
+      - run: cargo install cargo-readme
+      - run: cargo readme > README.md && git diff --exit-code
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index b39f048..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,22 +0,0 @@
-language: rust
-
-branches:
-  except:
-    - gh-pages
-
-rust:
-- stable
-- nightly
-
-os:
-- linux
-- windows
-
-script:
-- cargo build --all
-- cargo test --all
-
-matrix:
-  allow_failures:
-  - rust: nightly
-  fast_finish: true
diff --git a/Cargo.toml b/Cargo.toml
index 327757b..6224d65 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "chainerror"
-version = "0.5.0"
+version = "0.6.0-alpha.0"
 authors = ["Harald Hoyer <harald@redhat.com>"]
 edition = "2018"
 license = "MIT/Apache-2.0"
@@ -16,10 +16,14 @@ exclude = [ ".gitignore", "examples/*", "booksrc/*", "book.toml",
             "theme/*", "git-deploy-branch.sh", ".travis.yml" ]
 
 [badges]
-travis-ci = { repository = "haraldh/chainerror" }
+# See https://doc.rust-lang.org/cargo/reference/manifest.html#the-badges-section
+github = { repository = "haraldh/chainerror", workflow = "rust" }
+maintenance = { status = "actively-developed" }
+is-it-maintained-issue-resolution = { repository = "haraldh/chainerror" }
+is-it-maintained-open-issues = { repository = "haraldh/chainerror" }
 
 [features]
-default = [ ]
-no-fileline = []
+default = [ "location", "debug-cause" ]
+location = []
 display-cause = []
-no-debug-cause = []
+debug-cause = []
diff --git a/README.md b/README.md
index 78837ee..9b17c55 100644
--- a/README.md
+++ b/README.md
@@ -1,69 +1,148 @@
-# chainerror
-[![Rust](https://github.com/haraldh/chainerror/workflows/Rust/badge.svg)](https://github.com/haraldh/chainerror/actions?query=workflow%3ARust)
-[![Build Status](https://travis-ci.org/haraldh/chainerror.svg?branch=master)](https://travis-ci.org/haraldh/chainerror)
-[![Coverage Status](https://coveralls.io/repos/github/haraldh/chainerror/badge.svg?branch=master)](https://coveralls.io/github/haraldh/chainerror?branch=master)
-[![Crate](https://img.shields.io/crates/v/chainerror.svg)](https://crates.io/crates/chainerror)
-[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/chainerror/)
+[![Workflow Status](https://github.com/haraldh/chainerror/workflows/rust/badge.svg)](https://github.com/haraldh/chainerror/actions?query=workflow%3A%22rust%22)
+[![Average time to resolve an issue](https://isitmaintained.com/badge/resolution/haraldh/chainerror.svg)](https://isitmaintained.com/project/haraldh/chainerror "Average time to resolve an issue")
+[![Percentage of issues still open](https://isitmaintained.com/badge/open/haraldh/chainerror.svg)](https://isitmaintained.com/project/haraldh/chainerror "Percentage of issues still open")
+![Maintenance](https://img.shields.io/badge/maintenance-activly--developed-brightgreen.svg)
 
-`chainerror` provides an error backtrace like `failure` without doing a real backtrace, so even after you `strip` your
+# chainerror
+
+`chainerror` provides an error backtrace without doing a real backtrace, so even after you `strip` your
 binaries, you still have the error backtrace.
 
 `chainerror` has no dependencies!
 
-`chainerror` uses `.source()` of `std::error::Error` along with `line()!` and `file()!` to provide a nice debug error backtrace.
+`chainerror` uses `.source()` of `std::error::Error` along with `#[track_caller]` and `Location` to provide a nice debug error backtrace.
 It encapsulates all types, which have `Display + Debug` and can store the error cause internally.
 
 Along with the `ChainError<T>` struct, `chainerror` comes with some useful helper macros to save a lot of typing.
 
 Debug information is worth it!
 
-Now continue reading the
-[Tutorial](https://haraldh.github.io/chainerror/tutorial1.html)
+### Features
 
-## Example:
-Output:
+`default = [ "location", "debug-cause" ]`
 
-~~~
+`location`
+: store the error location
+
+`display-cause`
+: turn on printing a backtrace of the errors in `Display`
+
+`debug-cause`
+: print a backtrace of the errors in `Debug`
+
+
+## Tutorial
+
+Read the [Tutorial](https://haraldh.github.io/chainerror/tutorial1.html)
+
+## Examples
+
+```console
 $ cargo run -q --example example
 Main Error Report: func1 error calling func2
 
 Error reported by Func2Error: func2 error: calling func3
-
 The root cause was: std::io::Error: Kind(
     NotFound
 )
 
 Debug Error:
-examples/example.rs:45: func1 error calling func2
+examples/example.rs:46:13: func1 error calling func2
 Caused by:
-examples/example.rs:20: Func2Error(func2 error: calling func3)
+examples/example.rs:21:13: Func2Error(func2 error: calling func3)
 Caused by:
-examples/example.rs:13: Error reading 'foo.txt'
+examples/example.rs:14:18: Error reading 'foo.txt'
 Caused by:
 Kind(NotFound)
-~~~
+Alternative Debug Error:
+ChainError<example::Func1Error> {
+    occurrence: Some(
+        "examples/example.rs:46:13",
+    ),
+    kind: func1 error calling func2,
+    source: Some(
+        ChainError<example::Func2Error> {
+            occurrence: Some(
+                "examples/example.rs:21:13",
+            ),
+            kind: Func2Error(func2 error: calling func3),
+            source: Some(
+                ChainError<alloc::string::String> {
+                    occurrence: Some(
+                        "examples/example.rs:14:18",
+                    ),
+                    kind: "Error reading \'foo.txt\'",
+                    source: Some(
+                        Kind(
+                            NotFound,
+                        ),
+                    ),
+                },
+            ),
+        },
+    ),
+}
+```
 
-~~~rust,ignore
-use chainerror::*;
+```rust
+use chainerror::prelude::v1::*;
 use std::error::Error;
 use std::io;
 use std::result::Result;
 
-fn do_some_io() -> Result<(), Box<Error + Send + Sync>> {
+fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
     Err(io::Error::from(io::ErrorKind::NotFound))?;
     Ok(())
 }
 
-fn func3() -> Result<(), Box<Error + Send + Sync>> {
+fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
     let filename = "foo.txt";
-    do_some_io().map_err(mstrerr!("Error reading '{}'", filename))?;
+    do_some_io().cherr(format!("Error reading '{}'", filename))?;
+    Ok(())
+}
+
+fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
+    func2().cherr("func1 error")?;
+    Ok(())
+}
+
+if let Err(e) = func1() {
+    #[cfg(not(windows))]
+    assert_eq!(
+        format!("\n{:?}\n", e),
+        r#"
+src/lib.rs:21:13: func1 error
+Caused by:
+src/lib.rs:16:18: Error reading 'foo.txt'
+Caused by:
+Kind(NotFound)
+"#
+    );
+}
+```
+
+
+```rust
+use chainerror::prelude::v1::*;
+use std::error::Error;
+use std::io;
+use std::result::Result;
+
+fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
+    Err(io::Error::from(io::ErrorKind::NotFound))?;
+    Ok(())
+}
+
+fn func3() -> Result<(), Box<dyn Error + Send + Sync>> {
+    let filename = "foo.txt";
+    do_some_io().cherr(format!("Error reading '{}'", filename))?;
     Ok(())
 }
 
 derive_str_cherr!(Func2Error);
 
 fn func2() -> ChainResult<(), Func2Error> {
-    func3().map_err(mstrerr!(Func2Error, "func2 error: calling func3"))?;
+    func3().cherr(Func2Error("func2 error: calling func3".into()))?;
     Ok(())
 }
 
@@ -88,43 +167,51 @@ impl ::std::fmt::Debug for Func1Error {
 }
 
 fn func1() -> ChainResult<(), Func1Error> {
-    func2().map_err(|e| cherr!(e, Func1Error::Func2))?;
+    func2().cherr(Func1Error::Func2)?;
     let filename = String::from("bar.txt");
-    do_some_io().map_err(|e| cherr!(e, Func1Error::IO(filename)))?;
+    do_some_io().cherr(Func1Error::IO(filename))?;
     Ok(())
 }
 
-fn main() {
-    if let Err(e) = func1() {
-        match e.kind() {
-            Func1Error::Func2 => eprintln!("Main Error Report: func1 error calling func2"),
-            Func1Error::IO(filename) => {
-                eprintln!("Main Error Report: func1 error reading '{}'", filename)
-            }
+if let Err(e) = func1() {
+    assert!(match e.kind() {
+        Func1Error::Func2 => {
+            eprintln!("Main Error Report: func1 error calling func2");
+            true
         }
-
-        if let Some(e) = e.find_chain_cause::<Func2Error>() {
-            eprintln!("\nError reported by Func2Error: {}", e)
+        Func1Error::IO(filename) => {
+            eprintln!("Main Error Report: func1 error reading '{}'", filename);
+            false
         }
+    });
 
-        if let Some(e) = e.root_cause() {
-            let ioerror = e.downcast_ref::<io::Error>().unwrap();
-            eprintln!("\nThe root cause was: std::io::Error: {:#?}", ioerror);
-        }
+    assert!(e.find_chain_cause::<Func2Error>().is_some());
 
-        eprintln!("\nDebug Error:\n{:?}", e);
+    if let Some(e) = e.find_chain_cause::<Func2Error>() {
+        eprintln!("\nError reported by Func2Error: {}", e)
     }
+
+    assert!(e.root_cause().is_some());
+
+    if let Some(e) = e.root_cause() {
+        let io_error = e.downcast_ref::<io::Error>().unwrap();
+        eprintln!("\nThe root cause was: std::io::Error: {:#?}", io_error);
+    }
+
+    #[cfg(not(windows))]
+    assert_eq!(
+        format!("\n{:?}\n", e),
+        r#"
+src/lib.rs:48:13: func1 error calling func2
+Caused by:
+src/lib.rs:23:13: Func2Error(func2 error: calling func3)
+Caused by:
+src/lib.rs:16:18: Error reading 'foo.txt'
+Caused by:
+Kind(NotFound)
+"#
+    );
 }
+```
 
-~~~
-
-## Features
-
-`no-fileline`
-: completely turn off storing filename and line
-
-`display-cause`
-: turn on printing a backtrace of the errors in `Display`
-
-`no-debug-cause`
-: turn off printing a backtrace of the errors in `Debug`
+License: MIT/Apache-2.0
diff --git a/examples/example.rs b/examples/example.rs
index 99f965e..4044155 100644
--- a/examples/example.rs
+++ b/examples/example.rs
@@ -2,7 +2,7 @@ use std::error::Error;
 use std::io;
 use std::result::Result;
 
-use chainerror::*;
+use chainerror::prelude::v1::*;
 
 fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
     Err(io::Error::from(io::ErrorKind::NotFound))?;
@@ -11,14 +11,14 @@ fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
 
 fn func3() -> Result<(), Box<dyn Error + Send + Sync>> {
     let filename = "foo.txt";
-    do_some_io().map_err(mstrerr!("Error reading '{}'", filename))?;
+    do_some_io().cherr(format!("Error reading '{}'", filename))?;
     Ok(())
 }
 
 derive_str_cherr!(Func2Error);
 
 fn func2() -> ChainResult<(), Func2Error> {
-    func3().map_err(mstrerr!(Func2Error, "func2 error: calling func3"))?;
+    func3().cherr(Func2Error(format!("func2 error: calling func3")))?;
     Ok(())
 }
 
@@ -43,9 +43,9 @@ impl ::std::fmt::Debug for Func1Error {
 }
 
 fn func1() -> ChainResult<(), Func1Error> {
-    func2().map_err(|e| cherr!(e, Func1Error::Func2))?;
+    func2().cherr(Func1Error::Func2)?;
     let filename = String::from("bar.txt");
-    do_some_io().map_err(|e| cherr!(e, Func1Error::IO(filename)))?;
+    do_some_io().cherr(Func1Error::IO(filename))?;
     Ok(())
 }
 
@@ -68,5 +68,7 @@ fn main() {
         }
 
         eprintln!("\nDebug Error:\n{:?}", e);
+
+        eprintln!("\nAlternative Debug Error:\n{:#?}", e);
     }
 }
diff --git a/examples/tutorial10.rs b/examples/tutorial10.rs
index cf13909..4ee8f44 100644
--- a/examples/tutorial10.rs
+++ b/examples/tutorial10.rs
@@ -1,4 +1,4 @@
-use chainerror::*;
+use chainerror::prelude::v1::*;
 use std::error::Error;
 use std::io;
 use std::result::Result;
@@ -12,7 +12,7 @@ derive_str_cherr!(Func2Error);
 
 fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
     let filename = "foo.txt";
-    do_some_io().map_err(mstrerr!(Func2Error, "Error reading '{}'", filename))?;
+    do_some_io().cherr(Func2Error(format!("Error reading '{}'", filename)))?;
     Ok(())
 }
 
@@ -33,9 +33,9 @@ impl ::std::fmt::Display for Func1ErrorKind {
 impl ::std::error::Error for Func1ErrorKind {}
 
 fn func1() -> ChainResult<(), Func1ErrorKind> {
-    func2().map_err(|e| cherr!(e, Func1ErrorKind::Func2))?;
+    func2().cherr(Func1ErrorKind::Func2)?;
     let filename = String::from("bar.txt");
-    do_some_io().map_err(|e| cherr!(e, Func1ErrorKind::IO(filename)))?;
+    do_some_io().cherr(Func1ErrorKind::IO(filename))?;
     Ok(())
 }
 
diff --git a/examples/tutorial11.rs b/examples/tutorial11.rs
index 5f85c23..42e5de8 100644
--- a/examples/tutorial11.rs
+++ b/examples/tutorial11.rs
@@ -1,4 +1,4 @@
-use chainerror::*;
+use chainerror::prelude::v1::*;
 use std::error::Error;
 use std::io;
 use std::result::Result;
@@ -12,7 +12,7 @@ derive_str_cherr!(Func2Error);
 
 fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
     let filename = "foo.txt";
-    do_some_io().map_err(mstrerr!(Func2Error, "Error reading '{}'", filename))?;
+    do_some_io().cherr(Func2Error(format!("Error reading '{}'", filename)))?;
     Ok(())
 }
 
@@ -39,9 +39,9 @@ impl ::std::fmt::Debug for Func1ErrorKind {
 impl ::std::error::Error for Func1ErrorKind {}
 
 fn func1() -> ChainResult<(), Func1ErrorKind> {
-    func2().map_err(|e| cherr!(e, Func1ErrorKind::Func2))?;
+    func2().cherr(Func1ErrorKind::Func2)?;
     let filename = String::from("bar.txt");
-    do_some_io().map_err(|e| cherr!(e, Func1ErrorKind::IO(filename)))?;
+    do_some_io().cherr(Func1ErrorKind::IO(filename))?;
     Ok(())
 }
 
diff --git a/examples/tutorial12.rs b/examples/tutorial12.rs
index f5e38de..ce3cea6 100644
--- a/examples/tutorial12.rs
+++ b/examples/tutorial12.rs
@@ -1,4 +1,4 @@
-use chainerror::*;
+use chainerror::prelude::v1::*;
 use std::error::Error;
 use std::io;
 use std::result::Result;
@@ -12,7 +12,7 @@ derive_str_cherr!(Func2Error);
 
 fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
     let filename = "foo.txt";
-    do_some_io().map_err(mstrerr!(Func2Error, "Error reading '{}'", filename))?;
+    do_some_io().cherr(Func2Error(format!("Error reading '{}'", filename)))?;
     Ok(())
 }
 
@@ -39,9 +39,9 @@ impl ::std::fmt::Debug for Func1ErrorKind {
 impl ::std::error::Error for Func1ErrorKind {}
 
 fn func1() -> ChainResult<(), Func1ErrorKind> {
-    func2().map_err(|e| cherr!(e, Func1ErrorKind::Func2))?;
+    func2().cherr(Func1ErrorKind::Func2)?;
     let filename = String::from("bar.txt");
-    do_some_io().map_err(|e| cherr!(e, Func1ErrorKind::IO(filename)))?;
+    do_some_io().cherr(Func1ErrorKind::IO(filename))?;
     Ok(())
 }
 
diff --git a/examples/tutorial13.rs b/examples/tutorial13.rs
index c345157..29a0374 100644
--- a/examples/tutorial13.rs
+++ b/examples/tutorial13.rs
@@ -1,5 +1,5 @@
 pub mod mycrate {
-    use chainerror::*;
+    use chainerror::prelude::v1::*;
     use std::io;
 
     fn do_some_io() -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> {
@@ -11,7 +11,7 @@ pub mod mycrate {
 
     fn func2() -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> {
         let filename = "foo.txt";
-        do_some_io().map_err(mstrerr!(Func2Error, "Error reading '{}'", filename))?;
+        do_some_io().cherr(Func2Error(format!("Error reading '{}'", filename)))?;
         Ok(())
     }
 
@@ -35,9 +35,9 @@ pub mod mycrate {
     }
 
     pub fn func1() -> Result<()> {
-        func2().map_err(|e| cherr!(e, ErrorKind::Func2))?;
+        func2().cherr(ErrorKind::Func2)?;
         let filename = String::from("bar.txt");
-        do_some_io().map_err(|e| cherr!(e, ErrorKind::IO(filename)))?;
+        do_some_io().cherr(ErrorKind::IO(filename))?;
         Ok(())
     }
 }
diff --git a/examples/tutorial15.rs b/examples/tutorial15.rs
index 581840c..5130bfc 100644
--- a/examples/tutorial15.rs
+++ b/examples/tutorial15.rs
@@ -1,7 +1,7 @@
 pub mod mycrate {
     use std::io;
 
-    use chainerror::*;
+    use chainerror::prelude::v1::*;
 
     fn do_some_io(_f: &str) -> std::result::Result<(), io::Error> {
         Err(io::Error::from(io::ErrorKind::NotFound))?;
@@ -12,8 +12,7 @@ pub mod mycrate {
 
     fn func2() -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> {
         let filename = "foo.txt";
-        do_some_io(filename)
-            .map_err(|e| cherr!(e, Func2Error(format!("Error reading '{}'", filename))))?;
+        do_some_io(filename).cherr(Func2Error(format!("Error reading '{}'", filename)))?;
         Ok(())
     }
 
@@ -82,21 +81,19 @@ pub mod mycrate {
     }
 
     pub fn func1() -> Result<()> {
-        func2().map_err(|e| cherr!(e, ErrorKind::from(&e)))?;
+        func2().map_err(|e| ErrorKind::from(&e))?;
 
         let filename = "bar.txt";
 
-        do_some_io(filename)
-            .map_err(|e| cherr!(e, ErrorKind::from_io_error(&e, filename.into())))?;
-        do_some_io(filename).map_err(|e| cherr!(e, ErrorKind::IO(filename.into())))?;
-        do_some_io(filename).map_err(|e| cherr!(e, ErrorKind::from(&e)))?;
-        do_some_io(filename).map_err(minto_cherr!(ErrorKind))?;
+        do_some_io(filename).map_cherr(|e| ErrorKind::from_io_error(&e, filename.into()))?;
+        do_some_io(filename).map_cherr(|_| ErrorKind::IO(filename.into()))?;
+        do_some_io(filename).map_cherr(|e| ErrorKind::from(e))?;
 
         Ok(())
     }
 
     pub fn super_func1() -> Result<()> {
-        func1().map_err(minto_cherr!(ErrorKind))?;
+        func1().map_cherr(|e| ErrorKind::from(e))?;
         Ok(())
     }
 }
diff --git a/examples/tutorial2.rs b/examples/tutorial2.rs
index b13f0cc..140862f 100644
--- a/examples/tutorial2.rs
+++ b/examples/tutorial2.rs
@@ -1,4 +1,4 @@
-use chainerror::*;
+use chainerror::prelude::v1::*;
 
 use std::error::Error;
 use std::io;
@@ -11,14 +11,14 @@ fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
 
 fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
     if let Err(e) = do_some_io() {
-        Err(cherr!(e, "func2 error"))?;
+        Err(e).cherr("func2 error")?;
     }
     Ok(())
 }
 
 fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
     if let Err(e) = func2() {
-        Err(cherr!(e, "func1 error"))?;
+        Err(e).cherr("func1 error")?;
     }
     Ok(())
 }
diff --git a/examples/tutorial3.rs b/examples/tutorial3.rs
index 6da067c..9096e07 100644
--- a/examples/tutorial3.rs
+++ b/examples/tutorial3.rs
@@ -1,4 +1,4 @@
-use chainerror::*;
+use chainerror::prelude::v1::*;
 
 use std::error::Error;
 use std::io;
@@ -10,12 +10,12 @@ fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
 }
 
 fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
-    do_some_io().map_err(|e| cherr!(e, "func2 error"))?;
+    do_some_io().cherr("func2 error")?;
     Ok(())
 }
 
 fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
-    func2().map_err(|e| cherr!(e, "func1 error"))?;
+    func2().cherr("func1 error")?;
     Ok(())
 }
 
diff --git a/examples/tutorial4.rs b/examples/tutorial4.rs
index e1225c0..3b5fc15 100644
--- a/examples/tutorial4.rs
+++ b/examples/tutorial4.rs
@@ -1,4 +1,4 @@
-use chainerror::*;
+use chainerror::prelude::v1::*;
 use std::error::Error;
 use std::io;
 use std::result::Result;
@@ -10,12 +10,12 @@ fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
 
 fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
     let filename = "foo.txt";
-    do_some_io().map_err(mstrerr!("Error reading '{}'", filename))?;
+    do_some_io().cherr(format!("Error reading '{}'", filename))?;
     Ok(())
 }
 
 fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
-    func2().map_err(mstrerr!("func1 error"))?;
+    func2().cherr("func1 error")?;
     Ok(())
 }
 
diff --git a/examples/tutorial5.rs b/examples/tutorial5.rs
index cb80569..edabbbf 100644
--- a/examples/tutorial5.rs
+++ b/examples/tutorial5.rs
@@ -1,4 +1,4 @@
-use chainerror::*;
+use chainerror::prelude::v1::*;
 use std::error::Error;
 use std::io;
 use std::result::Result;
@@ -10,7 +10,7 @@ fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
 
 fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
     let filename = "foo.txt";
-    do_some_io().map_err(mstrerr!("Error reading '{}'", filename))?;
+    do_some_io().cherr(format!("Error reading '{}'", filename))?;
     Ok(())
 }
 
@@ -18,7 +18,7 @@ fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
     if let Err(e) = func2() {
         if let Some(s) = e.source() {
             eprintln!("func2 failed because of '{}'", s);
-            Err(e).map_err(mstrerr!("func1 error"))?;
+            Err(e).cherr("func1 error")?;
         }
     }
     Ok(())
diff --git a/examples/tutorial6.rs b/examples/tutorial6.rs
index 996540c..f8c6549 100644
--- a/examples/tutorial6.rs
+++ b/examples/tutorial6.rs
@@ -1,4 +1,4 @@
-use chainerror::*;
+use chainerror::prelude::v1::*;
 use std::error::Error;
 use std::io;
 use std::result::Result;
@@ -10,12 +10,12 @@ fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
 
 fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
     let filename = "foo.txt";
-    do_some_io().map_err(mstrerr!("Error reading '{}'", filename))?;
+    do_some_io().cherr(format!("Error reading '{}'", filename))?;
     Ok(())
 }
 
 fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
-    func2().map_err(mstrerr!("func1 error"))?;
+    func2().cherr("func1 error")?;
     Ok(())
 }
 
diff --git a/examples/tutorial7.rs b/examples/tutorial7.rs
index b36fa8b..11658f2 100644
--- a/examples/tutorial7.rs
+++ b/examples/tutorial7.rs
@@ -1,4 +1,4 @@
-use chainerror::*;
+use chainerror::prelude::v1::*;
 use std::error::Error;
 use std::io;
 use std::result::Result;
@@ -10,12 +10,12 @@ fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
 
 fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
     let filename = "foo.txt";
-    do_some_io().map_err(mstrerr!("Error reading '{}'", filename))?;
+    do_some_io().cherr(format!("Error reading '{}'", filename))?;
     Ok(())
 }
 
 fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
-    func2().map_err(mstrerr!("func1 error"))?;
+    func2().cherr(format!("func1 error"))?;
     Ok(())
 }
 
diff --git a/examples/tutorial8.rs b/examples/tutorial8.rs
index 1644a32..f55b83b 100644
--- a/examples/tutorial8.rs
+++ b/examples/tutorial8.rs
@@ -1,4 +1,4 @@
-use chainerror::*;
+use chainerror::prelude::v1::*;
 use std::error::Error;
 use std::io;
 use std::result::Result;
@@ -12,14 +12,14 @@ derive_str_cherr!(Func2Error);
 
 fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
     let filename = "foo.txt";
-    do_some_io().map_err(mstrerr!(Func2Error, "Error reading '{}'", filename))?;
+    do_some_io().cherr(Func2Error(format!("Error reading '{}'", filename)))?;
     Ok(())
 }
 
 derive_str_cherr!(Func1Error);
 
 fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
-    func2().map_err(mstrerr!(Func1Error, "func1 error"))?;
+    func2().cherr(Func1Error(format!("func1 error")))?;
     Ok(())
 }
 
diff --git a/examples/tutorial9.rs b/examples/tutorial9.rs
index 99b0f23..374cb77 100644
--- a/examples/tutorial9.rs
+++ b/examples/tutorial9.rs
@@ -1,4 +1,4 @@
-use chainerror::*;
+use chainerror::prelude::v1::*;
 use std::error::Error;
 use std::io;
 use std::result::Result;
@@ -12,7 +12,7 @@ derive_str_cherr!(Func2Error);
 
 fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
     let filename = "foo.txt";
-    do_some_io().map_err(mstrerr!(Func2Error, "Error reading '{}'", filename))?;
+    do_some_io().cherr(Func2Error(format!("Error reading '{}'", filename)))?;
     Ok(())
 }
 
@@ -20,9 +20,9 @@ derive_str_cherr!(Func1ErrorFunc2);
 derive_str_cherr!(Func1ErrorIO);
 
 fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
-    func2().map_err(mstrerr!(Func1ErrorFunc2, "func1 error calling func2"))?;
+    func2().cherr(Func1ErrorFunc2(format!("func1 error calling func2")))?;
     let filename = "bar.txt";
-    do_some_io().map_err(mstrerr!(Func1ErrorIO, "Error reading '{}'", filename))?;
+    do_some_io().cherr(Func1ErrorIO(format!("Error reading '{}'", filename)))?;
     Ok(())
 }
 
diff --git a/src/lib.rs b/src/lib.rs
index 817dde2..71fbf3f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -3,21 +3,25 @@
 //!
 //! `chainerror` has no dependencies!
 //!
-//! `chainerror` uses `.source()` of `std::error::Error` along with `line()!` and `file()!` to provide a nice debug error backtrace.
+//! `chainerror` uses `.source()` of `std::error::Error` along with `#[track_caller]` and `Location` to provide a nice debug error backtrace.
 //! It encapsulates all types, which have `Display + Debug` and can store the error cause internally.
 //!
 //! Along with the `ChainError<T>` struct, `chainerror` comes with some useful helper macros to save a lot of typing.
 //!
+//! Debug information is worth it!
+//!
 //! ## Features
 //!
-//! `no-fileline`
-//! : completely turn off storing filename and line
+//! `default = [ "location", "debug-cause" ]`
+//!
+//! `location`
+//! : store the error location
 //!
 //! `display-cause`
 //! : turn on printing a backtrace of the errors in `Display`
 //!
-//! `no-debug-cause`
-//! : turn off printing a backtrace of the errors in `Debug`
+//! `debug-cause`
+//! : print a backtrace of the errors in `Debug`
 //!
 //!
 //! # Tutorial
@@ -26,8 +30,55 @@
 //!
 //! # Examples
 //!
+//! ```console
+//! $ cargo run -q --example example
+//! Main Error Report: func1 error calling func2
+//!
+//! Error reported by Func2Error: func2 error: calling func3
+//! The root cause was: std::io::Error: Kind(
+//!     NotFound
+//! )
+//!
+//! Debug Error:
+//! examples/example.rs:46:13: func1 error calling func2
+//! Caused by:
+//! examples/example.rs:21:13: Func2Error(func2 error: calling func3)
+//! Caused by:
+//! examples/example.rs:14:18: Error reading 'foo.txt'
+//! Caused by:
+//! Kind(NotFound)
+//! Alternative Debug Error:
+//! ChainError<example::Func1Error> {
+//!     occurrence: Some(
+//!         "examples/example.rs:46:13",
+//!     ),
+//!     kind: func1 error calling func2,
+//!     source: Some(
+//!         ChainError<example::Func2Error> {
+//!             occurrence: Some(
+//!                 "examples/example.rs:21:13",
+//!             ),
+//!             kind: Func2Error(func2 error: calling func3),
+//!             source: Some(
+//!                 ChainError<alloc::string::String> {
+//!                     occurrence: Some(
+//!                         "examples/example.rs:14:18",
+//!                     ),
+//!                     kind: "Error reading \'foo.txt\'",
+//!                     source: Some(
+//!                         Kind(
+//!                             NotFound,
+//!                         ),
+//!                     ),
+//!                 },
+//!             ),
+//!         },
+//!     ),
+//! }
+//! ```
+//!
 //! ```rust
-//! use chainerror::*;
+//! use chainerror::prelude::v1::*;
 //! use std::error::Error;
 //! use std::io;
 //! use std::result::Result;
@@ -39,24 +90,24 @@
 //!
 //! fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
 //!     let filename = "foo.txt";
-//!     do_some_io().map_err(mstrerr!("Error reading '{}'", filename))?;
+//!     do_some_io().cherr(format!("Error reading '{}'", filename))?;
 //!     Ok(())
 //! }
 //!
 //! fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
-//!     func2().map_err(mstrerr!("func1 error"))?;
+//!     func2().cherr("func1 error")?;
 //!     Ok(())
 //! }
 //!
 //! if let Err(e) = func1() {
-//! #   #[cfg(not(feature = "no-debug-cause"))]
+//! #   #[cfg(feature = "debug-cause")]
 //!     #[cfg(not(windows))]
 //!     assert_eq!(
 //!         format!("\n{:?}\n", e),
 //!         r#"
-//! src/lib.rs:21: func1 error
+//! src/lib.rs:21:13: func1 error
 //! Caused by:
-//! src/lib.rs:16: Error reading 'foo.txt'
+//! src/lib.rs:16:18: Error reading 'foo.txt'
 //! Caused by:
 //! Kind(NotFound)
 //! "#
@@ -69,7 +120,7 @@
 //!
 //!
 //! ```rust
-//! use chainerror::*;
+//! use chainerror::prelude::v1::*;
 //! use std::error::Error;
 //! use std::io;
 //! use std::result::Result;
@@ -81,14 +132,14 @@
 //!
 //! fn func3() -> Result<(), Box<dyn Error + Send + Sync>> {
 //!     let filename = "foo.txt";
-//!     do_some_io().map_err(mstrerr!("Error reading '{}'", filename))?;
+//!     do_some_io().cherr(format!("Error reading '{}'", filename))?;
 //!     Ok(())
 //! }
 //!
 //! derive_str_cherr!(Func2Error);
 //!
 //! fn func2() -> ChainResult<(), Func2Error> {
-//!     func3().map_err(mstrerr!(Func2Error, "func2 error: calling func3"))?;
+//!     func3().cherr(Func2Error("func2 error: calling func3".into()))?;
 //!     Ok(())
 //! }
 //!
@@ -113,9 +164,9 @@
 //! }
 //!
 //! fn func1() -> ChainResult<(), Func1Error> {
-//!     func2().map_err(|e| cherr!(e, Func1Error::Func2))?;
+//!     func2().cherr(Func1Error::Func2)?;
 //!     let filename = String::from("bar.txt");
-//!     do_some_io().map_err(|e| cherr!(e, Func1Error::IO(filename)))?;
+//!     do_some_io().cherr(Func1Error::IO(filename))?;
 //!     Ok(())
 //! }
 //!
@@ -144,16 +195,16 @@
 //!         eprintln!("\nThe root cause was: std::io::Error: {:#?}", io_error);
 //!     }
 //!
-//! #   #[cfg(not(feature = "no-debug-cause"))]
+//! #   #[cfg(feature = "no-debug-cause")]
 //!     #[cfg(not(windows))]
 //!     assert_eq!(
 //!         format!("\n{:?}\n", e),
 //!         r#"
-//! src/lib.rs:48: func1 error calling func2
+//! src/lib.rs:48:13: func1 error calling func2
 //! Caused by:
-//! src/lib.rs:23: Func2Error(func2 error: calling func3)
+//! src/lib.rs:23:13: Func2Error(func2 error: calling func3)
 //! Caused by:
-//! src/lib.rs:16: Error reading 'foo.txt'
+//! src/lib.rs:16:18: Error reading 'foo.txt'
 //! Caused by:
 //! Kind(NotFound)
 //! "#
@@ -164,37 +215,29 @@
 //! #    }
 //! ```
 
-#![deny(
-    warnings,
-    absolute_paths_not_starting_with_crate,
-    deprecated_in_future,
-    keyword_idents,
-    macro_use_extern_crate,
-    missing_debug_implementations,
-    trivial_numeric_casts,
-    unused_extern_crates,
-    unused_import_braces,
-    unused_qualifications,
-    unused_results,
-    unused_labels,
-    unused_lifetimes,
-    unstable_features,
-    unreachable_pub,
-    future_incompatible,
-    missing_copy_implementations,
-    missing_doc_code_examples,
-    rust_2018_idioms,
-    rust_2018_compatibility
-)]
+#![deny(clippy::all)]
+#![deny(clippy::integer_arithmetic)]
+#![deny(missing_docs)]
 
 use std::any::TypeId;
 use std::error::Error;
 use std::fmt::{Debug, Display, Formatter, Result};
+use std::panic::Location;
+
+pub mod prelude {
+    //! convenience prelude
+    pub mod v1 {
+        //! convenience prelude
+        pub use crate::ChainErrorDown as _;
+        pub use crate::ResultTrait as _;
+        pub use crate::{derive_err_kind, derive_str_cherr, ChainError, ChainResult};
+    }
+}
 
 /// chains an inner error kind `T` with a causing error
 pub struct ChainError<T> {
-    #[cfg(not(feature = "no-fileline"))]
-    occurrence: Option<&'static str>,
+    #[cfg(feature = "location")]
+    occurrence: Option<String>,
     kind: T,
     error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
 }
@@ -203,13 +246,13 @@ pub struct ChainError<T> {
 pub type ChainResult<O, E> = std::result::Result<O, ChainError<E>>;
 
 impl<T: 'static + Display + Debug> ChainError<T> {
-    #[cfg(not(feature = "no-fileline"))]
-    /// Use the `cherr!()` or `mstrerr!()` macro instead of calling this directly
+    #[cfg(feature = "location")]
+    /// Use the `cherr()` or `map_cherr()` Result methods instead of calling this directly
     #[inline]
     pub fn new(
         kind: T,
         error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
-        occurrence: Option<&'static str>,
+        occurrence: Option<String>,
     ) -> Self {
         Self {
             occurrence,
@@ -218,13 +261,13 @@ impl<T: 'static + Display + Debug> ChainError<T> {
         }
     }
 
-    #[cfg(feature = "no-fileline")]
-    /// Use the `cherr!()` or `mstrerr!()` macro instead of calling this directly
+    #[cfg(not(feature = "location"))]
+    /// Use the `cherr()` or `map_cherr()` Result methods instead of calling this directly
     #[inline]
     pub fn new(
         kind: T,
         error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
-        _occurrence: Option<&'static str>,
+        _occurrence: Option<String>,
     ) -> Self {
         Self { kind, error_cause }
     }
@@ -239,7 +282,7 @@ impl<T: 'static + Display + Debug> ChainError<T> {
     /// # Examples
     ///
     /// ```rust
-    /// use chainerror::*;
+    /// use chainerror::prelude::v1::*;
     /// use std::error::Error;
     /// use std::io;
     ///
@@ -252,14 +295,14 @@ impl<T: 'static + Display + Debug> ChainError<T> {
     ///
     /// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
     ///     let filename = "foo.txt";
-    ///     do_some_io().map_err(mstrerr!(Func2Error, "Error reading '{}'", filename))?;
+    ///     do_some_io().cherr(Func2Error(format!("Error reading '{}'", filename)))?;
     ///     Ok(())
     /// }
     ///
     /// derive_str_cherr!(Func1Error);
     ///
     /// fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
-    ///     func2().map_err(mstrerr!(Func1Error, "func1 error"))?;
+    ///     func2().cherr(Func1Error("func1 error".into()))?;
     ///     Ok(())
     /// }
     ///
@@ -289,7 +332,7 @@ impl<T: 'static + Display + Debug> ChainError<T> {
     /// # Examples
     ///
     /// ```rust
-    /// # use chainerror::*;
+    /// # use chainerror::prelude::v1::*;
     /// # derive_str_cherr!(FooError);
     /// # let err = ChainError::new(String::new(), None, None);
     /// // Instead of writing
@@ -312,7 +355,7 @@ impl<T: 'static + Display + Debug> ChainError<T> {
     /// # Examples
     ///
     /// ```rust
-    /// # use chainerror::*;
+    /// # use chainerror::prelude::v1::*;
     /// # derive_str_cherr!(FooErrorKind);
     /// # let err = ChainError::new(String::new(), None, None);
     /// // Instead of writing
@@ -341,7 +384,7 @@ impl<T: 'static + Display + Debug> ChainError<T> {
     /// # Examples
     ///
     /// ```rust
-    /// use chainerror::*;
+    /// use chainerror::prelude::v1::*;
     /// use std::error::Error;
     /// use std::io;
     ///
@@ -354,7 +397,7 @@ impl<T: 'static + Display + Debug> ChainError<T> {
     ///
     /// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
     ///     let filename = "foo.txt";
-    ///     do_some_io().map_err(mstrerr!(Func2Error, "Error reading '{}'", filename))?;
+    ///     do_some_io().cherr(Func2Error(format!("Error reading '{}'", filename)))?;
     ///     Ok(())
     /// }
     ///
@@ -375,8 +418,8 @@ impl<T: 'static + Display + Debug> ChainError<T> {
     /// # }
     ///
     /// fn func1() -> ChainResult<(), Func1ErrorKind> {
-    ///     func2().map_err(|e| cherr!(e, Func1ErrorKind::Func2))?;
-    ///     do_some_io().map_err(|e| cherr!(e, Func1ErrorKind::IO("bar.txt".into())))?;
+    ///     func2().cherr(Func1ErrorKind::Func2)?;
+    ///     do_some_io().cherr(Func1ErrorKind::IO("bar.txt".into()))?;
     ///     Ok(())
     /// }
     ///
@@ -406,7 +449,54 @@ impl<T: 'static + Display + Debug> ChainError<T> {
     }
 }
 
-struct ErrorIter<'a> {
+/// Convenience methods for `Result<>` to turn the error into a decorated ChainError
+pub trait ResultTrait<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> {
+    /// Decorate the error with a `kind` of type `T` and the source `Location`
+    fn cherr<T: 'static + Display + Debug>(self, kind: T) -> std::result::Result<O, ChainError<T>>;
+
+    /// Decorate the error with a `kind` of type `T` produced with a `FnOnce` and the source `Location`
+    fn map_cherr<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
+        self,
+        op: F,
+    ) -> std::result::Result<O, ChainError<T>>;
+}
+
+impl<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> ResultTrait<O, E>
+    for std::result::Result<O, E>
+{
+    #[track_caller]
+    fn cherr<T: 'static + Display + Debug>(self, kind: T) -> std::result::Result<O, ChainError<T>> {
+        match self {
+            Ok(t) => Ok(t),
+            Err(error_cause) => Err(ChainError::new(
+                kind,
+                Some(error_cause.into()),
+                Some(Location::caller().to_string()),
+            )),
+        }
+    }
+
+    #[track_caller]
+    fn map_cherr<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
+        self,
+        op: F,
+    ) -> std::result::Result<O, ChainError<T>> {
+        match self {
+            Ok(t) => Ok(t),
+            Err(error_cause) => {
+                let kind = op(&error_cause);
+                Err(ChainError::new(
+                    kind,
+                    Some(error_cause.into()),
+                    Some(Location::caller().to_string()),
+                ))
+            }
+        }
+    }
+}
+
+/// An iterator over all error causes/sources
+pub struct ErrorIter<'a> {
     current: Option<&'a (dyn Error + 'static)>,
 }
 
@@ -647,40 +737,56 @@ impl<T: 'static + Display + Debug> Display for ChainError<T> {
 impl<T: 'static + Display + Debug> Debug for ChainError<T> {
     #[inline]
     fn fmt(&self, f: &mut Formatter<'_>) -> Result {
-        #[cfg(not(feature = "no-fileline"))]
-        {
-            if let Some(ref o) = self.occurrence {
-                Display::fmt(o, f)?;
-            }
-        }
+        if f.alternate() {
+            let mut f = f.debug_struct(&format!("ChainError<{}>", std::any::type_name::<T>()));
 
-        if self.is_chain::<String>() {
-            Display::fmt(&self.kind, f)?;
+            #[cfg(feature = "location")]
+            let f = f.field("occurrence", &self.occurrence);
+
+            let f = f.field("kind", &self.kind);
+
+            #[cfg(feature = "debug-cause")]
+            let f = f.field("source", &self.source());
+
+            f.finish()
         } else {
-            Debug::fmt(&self.kind, f)?;
-        }
-
-        #[cfg(not(feature = "no-debug-cause"))]
-        {
-            if let Some(e) = self.source() {
-                writeln!(f, "\nCaused by:")?;
-                Debug::fmt(&e, f)?;
+            #[cfg(feature = "location")]
+            {
+                if let Some(ref o) = self.occurrence {
+                    write!(f, "{}: ", o)?;
+                }
             }
+
+            if TypeId::of::<String>() == TypeId::of::<T>()
+                || TypeId::of::<&str>() == TypeId::of::<T>()
+            {
+                Display::fmt(&self.kind, f)?;
+            } else {
+                Debug::fmt(&self.kind, f)?;
+            }
+
+            #[cfg(feature = "debug-cause")]
+            {
+                if let Some(e) = self.source() {
+                    writeln!(f, "\nCaused by:")?;
+                    Debug::fmt(&e, f)?;
+                }
+            }
+            Ok(())
         }
-        Ok(())
     }
 }
 
 /// `ChainErrorFrom<T>` is similar to `From<T>`
 pub trait ChainErrorFrom<T>: Sized {
     /// similar to From<T>::from()
-    fn chain_error_from(from: T, line_filename: Option<&'static str>) -> ChainError<Self>;
+    fn chain_error_from(from: T, line_filename: Option<String>) -> ChainError<Self>;
 }
 
 /// `IntoChainError<T>` is similar to `Into<T>`
 pub trait IntoChainError<T>: Sized {
     /// similar to Into<T>::into()
-    fn into_chain_error(self, line_filename: Option<&'static str>) -> ChainError<T>;
+    fn into_chain_error(self, line_filename: Option<String>) -> ChainError<T>;
 }
 
 impl<T, U> IntoChainError<U> for T
@@ -688,7 +794,7 @@ where
     U: ChainErrorFrom<T>,
 {
     #[inline]
-    fn into_chain_error(self, line_filename: Option<&'static str>) -> ChainError<U> {
+    fn into_chain_error(self, line_filename: Option<String>) -> ChainError<U> {
         U::chain_error_from(self, line_filename)
     }
 }
@@ -699,286 +805,12 @@ where
     U: 'static + Display + Debug,
 {
     #[inline]
-    fn chain_error_from(t: T, line_filename: Option<&'static str>) -> ChainError<Self> {
+    fn chain_error_from(t: T, line_filename: Option<String>) -> ChainError<Self> {
         let e: U = t.into();
         ChainError::new(e, None, line_filename)
     }
 }
 
-/*
-impl<T, U> ChainErrorFrom<T> for U
-    where
-        T: 'static + Error + Into<Box<T>> + Clone,
-        U: 'static + Display + Debug + From<T>,
-{
-    #[inline]
-    fn chain_error_from(t: T, line_filename: Option<&'static str>) -> ChainError<Self> {
-        ChainError::new(U::from(t.clone()), Some(Box::from(t)), line_filename)
-    }
-}
-*/
-
-/// map into `ChainError<T>` with `T::from(err)`
-///
-/// adds `line!()` and `file!()` information
-#[macro_export]
-macro_rules! minto_cherr {
-    ( $k:ident ) => (
-        |e| $crate::cherr!(e, $k::from(&e))
-    );
-    ( $enum:ident $(:: $enum_path:ident)* ) => (
-        |e| $crate::cherr!(e, $enum $(:: $enum_path)*::from(&e))
-    );
-}
-
-/// Creates a new `ChainError<T>`
-///
-/// # Examples
-///
-/// Create a new ChainError<FooError>, where `FooError` must implement `Display` and `Debug`.
-/// ```rust
-/// # use chainerror::*;
-/// # #[derive(Debug)]
-/// enum FooError {
-///     Bar,
-///     Baz(&'static str),
-/// }
-/// # impl ::std::fmt::Display for FooError {
-/// #     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
-/// #         match self {
-/// #             FooError::Bar => write!(f, "Bar Error"),
-/// #             FooError::Baz(s) => write!(f, "Baz Error: '{}'", s),
-/// #         }
-/// #     }
-/// # }
-///
-/// //  impl ::std::fmt::Display for FooError
-///
-/// fn do_some_stuff() -> bool {
-///     false
-/// }
-///
-/// fn func() -> ChainResult<(), FooError> {
-///     if !do_some_stuff() {
-///         Err(cherr!(FooError::Baz("Error")))?;
-///     }
-///     Ok(())
-/// }
-/// #     match func().unwrap_err().kind() {
-/// #         FooError::Baz(s) if s == &"Error" => {}
-/// #         _ => panic!(),
-/// #     }
-/// ```
-///
-/// Additionally an error cause can be added.
-///
-/// ```rust
-/// # use chainerror::*;
-/// # use std::io;
-/// # use std::error::Error;
-/// # #[derive(Debug)]
-/// # enum FooError {
-/// #     Bar,
-/// #     Baz(&'static str),
-/// # }
-/// # impl ::std::fmt::Display for FooError {
-/// #     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
-/// #         match self {
-/// #             FooError::Bar => write!(f, "Bar Error"),
-/// #             FooError::Baz(s) => write!(f, "Baz Error: '{}'", s),
-/// #         }
-/// #     }
-/// # }
-/// fn do_some_stuff() -> Result<(), Box<dyn Error + Send + Sync>> {
-///     Err(io::Error::from(io::ErrorKind::NotFound))?;
-///     Ok(())
-/// }
-///
-/// fn func() -> ChainResult<(), FooError> {
-///     do_some_stuff().map_err(|e| cherr!(e, FooError::Baz("Error")))?;
-///     Ok(())
-/// }
-/// #     match func().unwrap_err().kind() {
-/// #         FooError::Baz(s) if s == &"Error" => {}
-/// #         _ => panic!(),
-/// #     }
-/// ```
-#[macro_export]
-macro_rules! cherr {
-    ( $k:expr ) => ({
-        $crate::ChainError::new($k, None, Some(concat!(file!(), ":", line!(), ": ")))
-    });
-    ( None, $k:expr ) => ({
-        $crate::ChainError::new($k, None, Some(concat!(file!(), ":", line!(), ": ")))
-    });
-    ( None, $fmt:expr, $($arg:tt)+ ) => ({
-        $crate::cherr!(None, format!($fmt, $($arg)+ ))
-    });
-    ( None, $fmt:expr, $($arg:tt)+ ) => ({
-        $crate::cherr!(None, format!($fmt, $($arg)+ ))
-    });
-    ( $e:path, $k:expr ) => ({
-        $crate::ChainError::new($k, Some(Box::from($e)), Some(concat!(file!(), ":", line!(), ": ")))
-    });
-    ( $e:path, $fmt:expr, $($arg:tt)+ ) => ({
-        $crate::cherr!($e, format!($fmt, $($arg)+ ))
-    });
-}
-
-/// Convenience macro for `|e| cherr!(e, format!(…))`
-///
-/// # Examples
-///
-/// ```rust
-/// # use crate::chainerror::*;
-/// # use std::error::Error;
-/// # use std::io;
-/// # use std::result::Result;
-/// # fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
-/// #     Err(io::Error::from(io::ErrorKind::NotFound))?;
-/// #     Ok(())
-/// # }
-/// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
-///     let filename = "foo.txt";
-///     do_some_io().map_err(mstrerr!("Error reading '{}'", filename))?;
-///     Ok(())
-/// }
-///
-/// fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
-///     func2().map_err(mstrerr!("func1 error"))?;
-///     Ok(())
-/// }
-///
-/// #     if let Err(e) = func1() {
-/// #         #[cfg(not(feature = "no-debug-cause"))]
-/// #         #[cfg(not(windows))]
-/// #         assert_eq!(
-/// #             format!("\n{:?}\n", e), r#"
-/// # src/lib.rs:19: func1 error
-/// # Caused by:
-/// # src/lib.rs:14: Error reading 'foo.txt'
-/// # Caused by:
-/// # Kind(NotFound)
-/// # "#
-/// #         );
-/// #     } else {
-/// #         unreachable!();
-/// #     }
-/// ```
-///
-/// `mstrerr!()` can also be used to map a new `ChainError<T>`, where T was defined with
-/// `derive_str_cherr!(T)`
-///
-/// ```rust
-/// # use crate::chainerror::*;
-/// # use std::error::Error;
-/// # use std::io;
-/// # use std::result::Result;
-/// # fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
-/// #     Err(io::Error::from(io::ErrorKind::NotFound))?;
-/// #     Ok(())
-/// # }
-/// derive_str_cherr!(Func2Error);
-///
-/// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
-///     let filename = "foo.txt";
-///     do_some_io().map_err(mstrerr!(Func2Error, "Error reading '{}'", filename))?;
-///     Ok(())
-/// }
-///
-/// derive_str_cherr!(Func1Error);
-///
-/// fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
-///     func2().map_err(mstrerr!(Func1Error, "func1 error"))?;
-///     Ok(())
-/// }
-/// #     if let Err(e) = func1() {
-/// #         if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
-/// #             assert!(f1err.find_cause::<ChainError<Func2Error>>().is_some());
-/// #             assert!(f1err.find_chain_cause::<Func2Error>().is_some());
-/// #         } else {
-/// #             panic!();
-/// #         }
-/// #     } else {
-/// #         unreachable!();
-/// #     }
-/// ```
-#[macro_export]
-macro_rules! mstrerr {
-    ( $t:path, $msg:expr ) => ({
-        |e| $crate::cherr!(e, $t ($msg.to_string()))
-    });
-    ( $t:path, $msg:expr, ) => ({
-        |e| $crate::cherr!(e, $t ($msg.to_string()))
-    });
-    ( $t:path, $fmt:expr, $($arg:tt)+ ) => ({
-        |e| $crate::cherr!(e, $t (format!($fmt, $($arg)+ )))
-    });
-    ($msg:expr) => ({
-        |e| $crate::cherr!(e, $msg.to_string())
-    });
-    ($msg:expr, ) => ({
-        |e| $crate::cherr!(e, $msg.to_string())
-    });
-    ($fmt:expr, $($arg:tt)+) => ({
-        |e| $crate::cherr!(e, format!($fmt, $($arg)+ ))
-    });
-}
-
-/// Convenience macro for `cherr!(T(format!(…)))` where `T(String)`
-///
-/// # Examples
-///
-/// ```rust
-/// # use crate::chainerror::*;
-/// # use std::error::Error;
-/// # use std::result::Result;
-/// derive_str_cherr!(Func2Error);
-///
-/// fn func2() -> ChainResult<(), Func2Error> {
-///     let filename = "foo.txt";
-///     Err(strerr!(Func2Error, "Error reading '{}'", filename))
-/// }
-///
-/// derive_str_cherr!(Func1Error);
-///
-/// fn func1() -> Result<(), Box<dyn Error>> {
-///     func2().map_err(mstrerr!(Func1Error, "func1 error"))?;
-///     Ok(())
-/// }
-/// #     if let Err(e) = func1() {
-/// #         if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() {
-/// #             assert!(f1err.find_cause::<ChainError<Func2Error>>().is_some());
-/// #             assert!(f1err.find_chain_cause::<Func2Error>().is_some());
-/// #         } else {
-/// #             panic!();
-/// #         }
-/// #     } else {
-/// #         unreachable!();
-/// #     }
-/// ```
-#[macro_export]
-macro_rules! strerr {
-    ( $t:path, $msg:expr ) => ({
-        $crate::cherr!($t ($msg.to_string()))
-    });
-    ( $t:path, $msg:expr, ) => ({
-        $crate::cherr!($t ($msg.to_string()))
-    });
-    ( $t:path, $fmt:expr, $($arg:tt)+ ) => ({
-        $crate::cherr!($t (format!($fmt, $($arg)+ )))
-    });
-    ($msg:expr) => ({
-        $crate::cherr!($msg.to_string())
-    });
-    ($msg:expr, ) => ({
-        $crate::cherr!($msg.to_string())
-    });
-    ($fmt:expr, $($arg:tt)+) => ({
-        $crate::cherr!(format!($fmt, $($arg)+ ))
-    });
-}
-
 /// Convenience macro to create a "new type" T(String) and implement Display + Debug for T
 ///
 /// # Examples
@@ -996,14 +828,14 @@ macro_rules! strerr {
 ///
 /// fn func2() -> ChainResult<(), Func2Error> {
 ///     let filename = "foo.txt";
-///     do_some_io().map_err(mstrerr!(Func2Error, "Error reading '{}'", filename))?;
+///     do_some_io().cherr(Func2Error(format!("Error reading '{}'", filename)))?;
 ///     Ok(())
 /// }
 ///
 /// derive_str_cherr!(Func1Error);
 ///
 /// fn func1() -> Result<(), Box<dyn Error>> {
-///     func2().map_err(mstrerr!(Func1Error, "func1 error"))?;
+///     func2().cherr(Func1Error("func1 error".into()))?;
 ///     Ok(())
 /// }
 /// #     if let Err(e) = func1() {
@@ -1047,7 +879,7 @@ macro_rules! derive_str_cherr {
 /// # Examples
 ///
 /// ```rust
-/// use chainerror::*;
+/// use chainerror::prelude::v1::*;
 /// use std::io;
 ///
 /// fn do_some_io(_f: &str) -> std::result::Result<(), io::Error> {
@@ -1095,10 +927,9 @@ macro_rules! derive_str_cherr {
 ///     let filename = "bar.txt";
 ///
 ///     do_some_io(filename)
-///         .map_err(|e| cherr!(e, ErrorKind::from_io_error(&e, filename.into())))?;
-///     do_some_io(filename).map_err(|e| cherr!(e, ErrorKind::IO(filename.into())))?;
-///     do_some_io(filename).map_err(|e| cherr!(e, ErrorKind::from(&e)))?;
-///     do_some_io(filename).map_err(minto_cherr!(ErrorKind))?;
+///         .map_cherr(|e| ErrorKind::from_io_error(e, filename.into()))?;
+///     do_some_io(filename).map_cherr(|e| ErrorKind::IO(filename.into()))?;
+///     do_some_io(filename).map_cherr(|e| ErrorKind::from(e))?;
 ///     Ok(())
 /// }
 /// ```
@@ -1134,19 +965,6 @@ macro_rules! derive_err_kind {
             }
         }
 
-        impl $crate::ChainErrorFrom<$e> for $k
-        where
-            $k: Clone,
-        {
-            #[inline]
-            fn chain_error_from(
-                t: $e,
-                line_filename: Option<&'static str>,
-            ) -> $crate::ChainError<$k> {
-                $crate::ChainError::new((*t.kind()).clone(), Some(Box::from(t)), line_filename)
-            }
-        }
-
         impl std::error::Error for $e {
             fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
                 self.0.source()
diff --git a/tests/test_iter.rs b/tests/test_iter.rs
index ce100d2..b567544 100644
--- a/tests/test_iter.rs
+++ b/tests/test_iter.rs
@@ -1,4 +1,4 @@
-use chainerror::*;
+use chainerror::prelude::v1::*;
 use std::error::Error;
 use std::io;
 
@@ -6,13 +6,14 @@ use std::io;
 #[test]
 fn test_iter() -> Result<(), Box<dyn Error + Send + Sync>> {
     use std::fmt::Write;
-    let err = io::Error::from(io::ErrorKind::NotFound);
-    let err = cherr!(err, "1");
-    let err = cherr!(err, "2");
-    let err = cherr!(err, "3");
-    let err = cherr!(err, "4");
-    let err = cherr!(err, "5");
-    let err = cherr!(err, "6");
+    let err: Result<(), _> = Err(io::Error::from(io::ErrorKind::NotFound));
+    let err = err.cherr("1");
+    let err = err.cherr("2");
+    let err = err.cherr("3");
+    let err = err.cherr("4");
+    let err = err.cherr("5");
+    let err = err.cherr("6");
+    let err = err.err().unwrap();
 
     let mut res = String::new();
 
@@ -34,13 +35,14 @@ fn test_iter() -> Result<(), Box<dyn Error + Send + Sync>> {
 #[cfg(feature = "display-cause")]
 #[test]
 fn test_iter() -> Result<(), Box<dyn Error + Send + Sync>> {
-    let err = io::Error::from(io::ErrorKind::NotFound);
-    let err = cherr!(err, "1");
-    let err = cherr!(err, "2");
-    let err = cherr!(err, "3");
-    let err = cherr!(err, "4");
-    let err = cherr!(err, "5");
-    let err = cherr!(err, "6");
+    let err: Result<(), _> = Err(io::Error::from(io::ErrorKind::NotFound));
+    let err = err.cherr("1");
+    let err = err.cherr("2");
+    let err = err.cherr("3");
+    let err = err.cherr("4");
+    let err = err.cherr("5");
+    let err = err.cherr("6");
+    let err = err.err().unwrap();
 
     let res = err.to_string();
 
@@ -58,13 +60,14 @@ fn test_iter() -> Result<(), Box<dyn Error + Send + Sync>> {
 
 #[test]
 fn test_find_cause() -> Result<(), Box<dyn Error + Send + Sync>> {
-    let err = io::Error::from(io::ErrorKind::NotFound);
-    let err = cherr!(err, "1");
-    let err = cherr!(err, "2");
-    let err = cherr!(err, "3");
-    let err = cherr!(err, "4");
-    let err = cherr!(err, "5");
-    let err = cherr!(err, "6");
+    let err: Result<(), _> = Err(io::Error::from(io::ErrorKind::NotFound));
+    let err = err.cherr("1");
+    let err = err.cherr("2");
+    let err = err.cherr("3");
+    let err = err.cherr("4");
+    let err = err.cherr("5");
+    let err = err.cherr("6");
+    let err = err.err().unwrap();
 
     let io_error: Option<&io::Error> = err.find_cause::<io::Error>();
 
@@ -75,13 +78,14 @@ fn test_find_cause() -> Result<(), Box<dyn Error + Send + Sync>> {
 
 #[test]
 fn test_root_cause() -> Result<(), Box<dyn Error + Send + Sync>> {
-    let err = io::Error::from(io::ErrorKind::NotFound);
-    let err = cherr!(err, "1");
-    let err = cherr!(err, "2");
-    let err = cherr!(err, "3");
-    let err = cherr!(err, "4");
-    let err = cherr!(err, "5");
-    let err = cherr!(err, "6");
+    let err: Result<(), _> = Err(io::Error::from(io::ErrorKind::NotFound));
+    let err = err.cherr("1");
+    let err = err.cherr("2");
+    let err = err.cherr("3");
+    let err = err.cherr("4");
+    let err = err.cherr("5");
+    let err = err.cherr("6");
+    let err = err.err().unwrap();
 
     let err: Option<&(dyn std::error::Error + 'static)> = err.root_cause();
     let io_error: Option<&io::Error> = err.and_then(Error::downcast_ref::<io::Error>);