Initial import of downcast-rs rust crate am: fe03cf3e1e am: 8177154dfb

Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/downcast-rs/+/1489156

Change-Id: I94e0a9a3c7cdbff58643fd929076573a2b5c3c8b
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
new file mode 100644
index 0000000..c146db6
--- /dev/null
+++ b/.cargo_vcs_info.json
@@ -0,0 +1,5 @@
+{
+  "git": {
+    "sha1": "0aaf951bee097184e9c83c51714c0f4d60bcd406"
+  }
+}
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
new file mode 100644
index 0000000..7c62d23
--- /dev/null
+++ b/.github/workflows/main.yml
@@ -0,0 +1,50 @@
+name: CI
+
+on: [push, pull_request]
+
+jobs:
+  build:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - uses: actions-rs/toolchain@v1
+        with:
+          profile: minimal
+          toolchain: stable
+          components: clippy
+      - name: Build
+        uses: actions-rs/cargo@v1
+        with:
+          command: build
+      - name: Test
+        uses: actions-rs/cargo@v1
+        with:
+          command: test
+      - name: Clippy
+        uses: actions-rs/cargo@v1
+        with:
+          command: clippy
+      - name: Docs
+        uses: actions-rs/cargo@v1
+        with:
+          command: doc
+      - name: Build for no_std
+        uses: actions-rs/cargo@v1
+        with:
+          command: build
+          args: --no-default-features
+      - name: Test for no_std
+        uses: actions-rs/cargo@v1
+        with:
+          command: test
+          args: --no-default-features
+      - name: Clippy for no_std
+        uses: actions-rs/cargo@v1
+        with:
+          command: clippy
+          args: --no-default-features
+      - name: Docs for no_std
+        uses: actions-rs/cargo@v1
+        with:
+          command: doc
+          args: --no-default-features
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a9d37c5
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+target
+Cargo.lock
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..149cd4f
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,54 @@
+# Changelog
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
+and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
+
+## 1.2.0 - 2020-06-29
+### Added
+- `no_std` support.
+- CI with GitHub actions.
+
+## 1.1.1 - 2019-10-28
+### Changed
+- Used `dyn Trait` syntax everywhere since it is supported by downcast-rs's
+  min-supported rust version (1.33).
+
+## 1.1.0 - 2019-10-07
+### Added
+- Support for downcasting `Rc<Trait>` and `Arc<Trait>`.
+### Changed
+- Minimum supported Rust version upped to 1.33 to support `Rc` and `Arc` in the
+  receiver position.
+
+## 1.0.4 - 2019-04-08
+### Changed
+- Added `local_inner_macros` to `impl_downcast` to allow invoking via namespace.
+
+## 1.0.3 - 2018-05-21
+### Fixed
+- Use global path for Result, Option, Box in macro expansion to avoid name
+  conflicts with locally-defined symbols.
+
+## 1.0.2 - 2018-05-12
+### Added
+- Support for downcasting `Box<Trait>` to `Box<Concrete>`.
+
+## 1.0.1 - 2018-03-08
+### Fixed
+- Don't use types as traits in macros.
+
+## 1.0.0 - 2017-02-05
+### Changed
+- Cleaned up README and published 1.0.
+
+## 0.1.2 - 2016-11-22
+### Added
+- Support for associated types as well.
+
+## 0.1.1 - 2016-09-04
+### Added
+- Downcast functionality to downcast borrowed mutable and immutable trait
+  objects to concrete types. Supports concrete type parameters and type
+  variables with optional constraints.
+
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..57a55b7
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,25 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "downcast-rs"
+version = "1.2.0"
+authors = ["Ashish Myles <marcianx@gmail.com>", "Runji Wang <wangrunji0408@163.com>"]
+description = "Trait object downcasting support using only safe Rust. It supports type\nparameters, associated types, and type constraints.\n"
+readme = "README.md"
+keywords = ["downcast", "any", "trait", "associated", "no_std"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/marcianx/downcast-rs"
+
+[features]
+default = ["std"]
+std = []
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
new file mode 100644
index 0000000..0cddf9a
--- /dev/null
+++ b/Cargo.toml.orig
@@ -0,0 +1,16 @@
+[package]
+name = "downcast-rs"
+version = "1.2.0"
+authors = ["Ashish Myles <marcianx@gmail.com>", "Runji Wang <wangrunji0408@163.com>"]
+repository = "https://github.com/marcianx/downcast-rs"
+description = """
+Trait object downcasting support using only safe Rust. It supports type
+parameters, associated types, and type constraints.
+"""
+readme = "README.md"
+keywords = ["downcast", "any", "trait", "associated", "no_std"]
+license = "MIT/Apache-2.0"
+
+[features]
+default = ["std"]
+std = []
diff --git a/LICENSE b/LICENSE
new file mode 120000
index 0000000..6b579aa
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1 @@
+LICENSE-APACHE
\ No newline at end of file
diff --git a/LICENSE-APACHE b/LICENSE-APACHE
new file mode 100644
index 0000000..11069ed
--- /dev/null
+++ b/LICENSE-APACHE
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/LICENSE-MIT b/LICENSE-MIT
new file mode 100644
index 0000000..7046862
--- /dev/null
+++ b/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2020 Ashish Myles and contributors
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..d2243f6
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,19 @@
+name: "downcast-rs"
+description: "Trait object downcasting support using only safe Rust. It supports type parameters, associated types, and type constraints."
+third_party {
+  url {
+    type: HOMEPAGE
+    value: "https://crates.io/crates/downcast-rs"
+  }
+  url {
+    type: ARCHIVE
+    value: "https://static.crates.io/crates/downcast-rs/downcast-rs-1.2.0.crate"
+  }
+  version: "1.2.0"
+  license_type: NOTICE
+  last_upgrade_date {
+    year: 2020
+    month: 10
+    day: 27
+  }
+}
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_APACHE2
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..46fc303
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1 @@
+include platform/prebuilts/rust:/OWNERS
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..2c462f7
--- /dev/null
+++ b/README.md
@@ -0,0 +1,165 @@
+# downcast-rs
+
+[![Build status](https://img.shields.io/github/workflow/status/marcianx/downcast-rs/CI/master)](https://github.com/marcianx/downcast-rs/actions)
+[![Latest version](https://img.shields.io/crates/v/downcast-rs.svg)](https://crates.io/crates/downcast-rs)
+[![Documentation](https://docs.rs/downcast-rs/badge.svg)](https://docs.rs/downcast-rs)
+
+Rust enums are great for types where all variations are known beforehand. But a
+container of user-defined types requires an open-ended type like a **trait
+object**. Some applications may want to cast these trait objects back to the
+original concrete types to access additional functionality and performant
+inlined implementations.
+
+`downcast-rs` adds this downcasting support to trait objects using only safe
+Rust. It supports **type parameters**, **associated types**, and **constraints**.
+
+## Usage
+
+Add the following to your `Cargo.toml`:
+
+```toml
+[dependencies]
+downcast-rs = "1.2.0"
+```
+
+This crate is `no_std` compatible. To use it without `std`:
+
+```toml
+[dependencies]
+downcast-rs = { version = "1.2.0", default-features = false }
+```
+
+To make a trait downcastable, make it extend either `downcast::Downcast` or
+`downcast::DowncastSync` and invoke `impl_downcast!` on it as in the examples
+below.
+
+Since 1.1.0, the minimum supported Rust version is 1.33 to support `Rc` and `Arc`
+in the receiver position.
+
+```rust
+trait Trait: Downcast {}
+impl_downcast!(Trait);
+
+// Also supports downcasting `Arc`-ed trait objects by extending `DowncastSync`
+// and starting `impl_downcast!` with `sync`.
+trait TraitSync: DowncastSync {}
+impl_downcast!(sync TraitSync);
+
+// With type parameters.
+trait TraitGeneric1<T>: Downcast {}
+impl_downcast!(TraitGeneric1<T>);
+
+// With associated types.
+trait TraitGeneric2: Downcast { type G; type H; }
+impl_downcast!(TraitGeneric2 assoc G, H);
+
+// With constraints on types.
+trait TraitGeneric3<T: Copy>: Downcast {
+    type H: Clone;
+}
+impl_downcast!(TraitGeneric3<T> assoc H where T: Copy, H: Clone);
+
+// With concrete types.
+trait TraitConcrete1<T: Copy>: Downcast {}
+impl_downcast!(concrete TraitConcrete1<u32>);
+
+trait TraitConcrete2<T: Copy>: Downcast { type H; }
+impl_downcast!(concrete TraitConcrete2<u32> assoc H=f64);
+```
+
+## Example without generics
+
+```rust
+// Import macro via `macro_use` pre-1.30.
+#[macro_use]
+extern crate downcast_rs;
+use downcast_rs::DowncastSync;
+
+// To create a trait with downcasting methods, extend `Downcast` or `DowncastSync`
+// and run `impl_downcast!()` on the trait.
+trait Base: DowncastSync {}
+impl_downcast!(sync Base);  // `sync` => also produce `Arc` downcasts.
+
+// Concrete types implementing Base.
+#[derive(Debug)]
+struct Foo(u32);
+impl Base for Foo {}
+#[derive(Debug)]
+struct Bar(f64);
+impl Base for Bar {}
+
+fn main() {
+    // Create a trait object.
+    let mut base: Box<Base> = Box::new(Foo(42));
+
+    // Try sequential downcasts.
+    if let Some(foo) = base.downcast_ref::<Foo>() {
+        assert_eq!(foo.0, 42);
+    } else if let Some(bar) = base.downcast_ref::<Bar>() {
+        assert_eq!(bar.0, 42.0);
+    }
+
+    assert!(base.is::<Foo>());
+
+    // Fail to convert `Box<Base>` into `Box<Bar>`.
+    let res = base.downcast::<Bar>();
+    assert!(res.is_err());
+    let base = res.unwrap_err();
+    // Convert `Box<Base>` into `Box<Foo>`.
+    assert_eq!(42, base.downcast::<Foo>().map_err(|_| "Shouldn't happen.").unwrap().0);
+
+    // Also works with `Rc`.
+    let mut rc: Rc<Base> = Rc::new(Foo(42));
+    assert_eq!(42, rc.downcast_rc::<Foo>().map_err(|_| "Shouldn't happen.").unwrap().0);
+
+    // Since this trait is `Sync`, it also supports `Arc` downcasts.
+    let mut arc: Arc<Base> = Arc::new(Foo(42));
+    assert_eq!(42, arc.downcast_arc::<Foo>().map_err(|_| "Shouldn't happen.").unwrap().0);
+}
+```
+
+## Example with a generic trait with associated types and constraints
+
+```rust
+// Can call macro via namespace since rust 1.30.
+extern crate downcast_rs;
+use downcast_rs::Downcast;
+
+// To create a trait with downcasting methods, extend `Downcast` or `DowncastSync`
+// and run `impl_downcast!()` on the trait.
+trait Base<T: Clone>: Downcast { type H: Copy; }
+downcast_rs::impl_downcast!(Base<T> assoc H where T: Clone, H: Copy);
+// or: impl_downcast!(concrete Base<u32> assoc H=f32)
+
+// Concrete types implementing Base.
+struct Foo(u32);
+impl Base<u32> for Foo { type H = f32; }
+struct Bar(f64);
+impl Base<u32> for Bar { type H = f32; }
+
+fn main() {
+    // Create a trait object.
+    let mut base: Box<Base<u32, H=f32>> = Box::new(Bar(42.0));
+
+    // Try sequential downcasts.
+    if let Some(foo) = base.downcast_ref::<Foo>() {
+        assert_eq!(foo.0, 42);
+    } else if let Some(bar) = base.downcast_ref::<Bar>() {
+        assert_eq!(bar.0, 42.0);
+    }
+
+    assert!(base.is::<Bar>());
+}
+```
+
+## License
+
+Copyright 2020, Ashish Myles (maintainer) and contributors.
+This software is dual-licensed under the [MIT](LICENSE-MIT) and
+[Apache 2.0](LICENSE-APACHE) licenses.
+
+### Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
+dual licensed as above, without any additional terms or conditions.
diff --git a/README.tpl b/README.tpl
new file mode 100644
index 0000000..9ec95d6
--- /dev/null
+++ b/README.tpl
@@ -0,0 +1,13 @@
+{{readme}}
+
+## License
+
+Copyright 2020, Ashish Myles (maintainer) and contributors.
+This software is dual-licensed under the [MIT](LICENSE-MIT) and
+[Apache 2.0](LICENSE-APACHE) licenses.
+
+### Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
+dual licensed as above, without any additional terms or conditions.
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..b211219
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,692 @@
+#![deny(unsafe_code)]
+#![cfg_attr(not(feature = "std"), no_std)]
+//! [![Build status](https://img.shields.io/github/workflow/status/marcianx/downcast-rs/CI/master)](https://github.com/marcianx/downcast-rs/actions)
+//! [![Latest version](https://img.shields.io/crates/v/downcast-rs.svg)](https://crates.io/crates/downcast-rs)
+//! [![Documentation](https://docs.rs/downcast-rs/badge.svg)](https://docs.rs/downcast-rs)
+//!
+//! Rust enums are great for types where all variations are known beforehand. But a
+//! container of user-defined types requires an open-ended type like a **trait
+//! object**. Some applications may want to cast these trait objects back to the
+//! original concrete types to access additional functionality and performant
+//! inlined implementations.
+//!
+//! `downcast-rs` adds this downcasting support to trait objects using only safe
+//! Rust. It supports **type parameters**, **associated types**, and **constraints**.
+//!
+//! # Usage
+//!
+//! Add the following to your `Cargo.toml`:
+//!
+//! ```toml
+//! [dependencies]
+//! downcast-rs = "1.2.0"
+//! ```
+//!
+//! This crate is `no_std` compatible. To use it without `std`:
+//!
+//! ```toml
+//! [dependencies]
+//! downcast-rs = { version = "1.2.0", default-features = false }
+//! ```
+//!
+//! To make a trait downcastable, make it extend either `downcast::Downcast` or
+//! `downcast::DowncastSync` and invoke `impl_downcast!` on it as in the examples
+//! below.
+//!
+//! Since 1.1.0, the minimum supported Rust version is 1.33 to support `Rc` and `Arc`
+//! in the receiver position.
+//!
+//! ```
+//! # #[macro_use]
+//! # extern crate downcast_rs;
+//! # use downcast_rs::{Downcast, DowncastSync};
+//! trait Trait: Downcast {}
+//! impl_downcast!(Trait);
+//!
+//! // Also supports downcasting `Arc`-ed trait objects by extending `DowncastSync`
+//! // and starting `impl_downcast!` with `sync`.
+//! trait TraitSync: DowncastSync {}
+//! impl_downcast!(sync TraitSync);
+//!
+//! // With type parameters.
+//! trait TraitGeneric1<T>: Downcast {}
+//! impl_downcast!(TraitGeneric1<T>);
+//!
+//! // With associated types.
+//! trait TraitGeneric2: Downcast { type G; type H; }
+//! impl_downcast!(TraitGeneric2 assoc G, H);
+//!
+//! // With constraints on types.
+//! trait TraitGeneric3<T: Copy>: Downcast {
+//!     type H: Clone;
+//! }
+//! impl_downcast!(TraitGeneric3<T> assoc H where T: Copy, H: Clone);
+//!
+//! // With concrete types.
+//! trait TraitConcrete1<T: Copy>: Downcast {}
+//! impl_downcast!(concrete TraitConcrete1<u32>);
+//!
+//! trait TraitConcrete2<T: Copy>: Downcast { type H; }
+//! impl_downcast!(concrete TraitConcrete2<u32> assoc H=f64);
+//! # fn main() {}
+//! ```
+//!
+//! # Example without generics
+//!
+//! ```
+//! # use std::rc::Rc;
+//! # use std::sync::Arc;
+//! // Import macro via `macro_use` pre-1.30.
+//! #[macro_use]
+//! extern crate downcast_rs;
+//! use downcast_rs::DowncastSync;
+//!
+//! // To create a trait with downcasting methods, extend `Downcast` or `DowncastSync`
+//! // and run `impl_downcast!()` on the trait.
+//! trait Base: DowncastSync {}
+//! impl_downcast!(sync Base);  // `sync` => also produce `Arc` downcasts.
+//!
+//! // Concrete types implementing Base.
+//! #[derive(Debug)]
+//! struct Foo(u32);
+//! impl Base for Foo {}
+//! #[derive(Debug)]
+//! struct Bar(f64);
+//! impl Base for Bar {}
+//!
+//! fn main() {
+//!     // Create a trait object.
+//!     let mut base: Box<Base> = Box::new(Foo(42));
+//!
+//!     // Try sequential downcasts.
+//!     if let Some(foo) = base.downcast_ref::<Foo>() {
+//!         assert_eq!(foo.0, 42);
+//!     } else if let Some(bar) = base.downcast_ref::<Bar>() {
+//!         assert_eq!(bar.0, 42.0);
+//!     }
+//!
+//!     assert!(base.is::<Foo>());
+//!
+//!     // Fail to convert `Box<Base>` into `Box<Bar>`.
+//!     let res = base.downcast::<Bar>();
+//!     assert!(res.is_err());
+//!     let base = res.unwrap_err();
+//!     // Convert `Box<Base>` into `Box<Foo>`.
+//!     assert_eq!(42, base.downcast::<Foo>().map_err(|_| "Shouldn't happen.").unwrap().0);
+//!
+//!     // Also works with `Rc`.
+//!     let mut rc: Rc<Base> = Rc::new(Foo(42));
+//!     assert_eq!(42, rc.downcast_rc::<Foo>().map_err(|_| "Shouldn't happen.").unwrap().0);
+//!
+//!     // Since this trait is `Sync`, it also supports `Arc` downcasts.
+//!     let mut arc: Arc<Base> = Arc::new(Foo(42));
+//!     assert_eq!(42, arc.downcast_arc::<Foo>().map_err(|_| "Shouldn't happen.").unwrap().0);
+//! }
+//! ```
+//!
+//! # Example with a generic trait with associated types and constraints
+//!
+//! ```
+//! // Can call macro via namespace since rust 1.30.
+//! extern crate downcast_rs;
+//! use downcast_rs::Downcast;
+//!
+//! // To create a trait with downcasting methods, extend `Downcast` or `DowncastSync`
+//! // and run `impl_downcast!()` on the trait.
+//! trait Base<T: Clone>: Downcast { type H: Copy; }
+//! downcast_rs::impl_downcast!(Base<T> assoc H where T: Clone, H: Copy);
+//! // or: impl_downcast!(concrete Base<u32> assoc H=f32)
+//!
+//! // Concrete types implementing Base.
+//! struct Foo(u32);
+//! impl Base<u32> for Foo { type H = f32; }
+//! struct Bar(f64);
+//! impl Base<u32> for Bar { type H = f32; }
+//!
+//! fn main() {
+//!     // Create a trait object.
+//!     let mut base: Box<Base<u32, H=f32>> = Box::new(Bar(42.0));
+//!
+//!     // Try sequential downcasts.
+//!     if let Some(foo) = base.downcast_ref::<Foo>() {
+//!         assert_eq!(foo.0, 42);
+//!     } else if let Some(bar) = base.downcast_ref::<Bar>() {
+//!         assert_eq!(bar.0, 42.0);
+//!     }
+//!
+//!     assert!(base.is::<Bar>());
+//! }
+//! ```
+
+// for compatibility with no std and macros
+#[doc(hidden)]
+#[cfg(not(feature = "std"))]
+pub extern crate core as __std;
+#[doc(hidden)]
+#[cfg(feature = "std")]
+pub extern crate std as __std;
+#[doc(hidden)]
+pub extern crate alloc as __alloc;
+
+use __std::any::Any;
+use __alloc::{boxed::Box, rc::Rc, sync::Arc};
+
+/// Supports conversion to `Any`. Traits to be extended by `impl_downcast!` must extend `Downcast`.
+pub trait Downcast: Any {
+    /// Convert `Box<dyn Trait>` (where `Trait: Downcast`) to `Box<dyn Any>`. `Box<dyn Any>` can
+    /// then be further `downcast` into `Box<ConcreteType>` where `ConcreteType` implements `Trait`.
+    fn into_any(self: Box<Self>) -> Box<dyn Any>;
+    /// Convert `Rc<Trait>` (where `Trait: Downcast`) to `Rc<Any>`. `Rc<Any>` can then be
+    /// further `downcast` into `Rc<ConcreteType>` where `ConcreteType` implements `Trait`.
+    fn into_any_rc(self: Rc<Self>) -> Rc<dyn Any>;
+    /// Convert `&Trait` (where `Trait: Downcast`) to `&Any`. This is needed since Rust cannot
+    /// generate `&Any`'s vtable from `&Trait`'s.
+    fn as_any(&self) -> &dyn Any;
+    /// Convert `&mut Trait` (where `Trait: Downcast`) to `&Any`. This is needed since Rust cannot
+    /// generate `&mut Any`'s vtable from `&mut Trait`'s.
+    fn as_any_mut(&mut self) -> &mut dyn Any;
+}
+
+impl<T: Any> Downcast for T {
+    fn into_any(self: Box<Self>) -> Box<dyn Any> { self }
+    fn into_any_rc(self: Rc<Self>) -> Rc<dyn Any> { self }
+    fn as_any(&self) -> &dyn Any { self }
+    fn as_any_mut(&mut self) -> &mut dyn Any { self }
+}
+
+/// Extends `Downcast` to support `Sync` traits that thus support `Arc` downcasting as well.
+pub trait DowncastSync: Downcast + Send + Sync {
+    /// Convert `Arc<Trait>` (where `Trait: Downcast`) to `Arc<Any>`. `Arc<Any>` can then be
+    /// further `downcast` into `Arc<ConcreteType>` where `ConcreteType` implements `Trait`.
+    fn into_any_arc(self: Arc<Self>) -> Arc<dyn Any + Send + Sync>;
+}
+
+impl<T: Any + Send + Sync> DowncastSync for T {
+    fn into_any_arc(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> { self }
+}
+
+/// Adds downcasting support to traits that extend `downcast::Downcast` by defining forwarding
+/// methods to the corresponding implementations on `std::any::Any` in the standard library.
+///
+/// See https://users.rust-lang.org/t/how-to-create-a-macro-to-impl-a-provided-type-parametrized-trait/5289
+/// for why this is implemented this way to support templatized traits.
+#[macro_export(local_inner_macros)]
+macro_rules! impl_downcast {
+    (@impl_full
+        $trait_:ident [$($param_types:tt)*]
+        for [$($forall_types:ident),*]
+        where [$($preds:tt)*]
+    ) => {
+        impl_downcast! {
+            @inject_where
+                [impl<$($forall_types),*> dyn $trait_<$($param_types)*>]
+                types [$($forall_types),*]
+                where [$($preds)*]
+                [{
+                    impl_downcast! { @impl_body $trait_ [$($param_types)*] }
+                }]
+        }
+    };
+
+    (@impl_full_sync
+        $trait_:ident [$($param_types:tt)*]
+        for [$($forall_types:ident),*]
+        where [$($preds:tt)*]
+    ) => {
+        impl_downcast! {
+            @inject_where
+                [impl<$($forall_types),*> dyn $trait_<$($param_types)*>]
+                types [$($forall_types),*]
+                where [$($preds)*]
+                [{
+                    impl_downcast! { @impl_body $trait_ [$($param_types)*] }
+                    impl_downcast! { @impl_body_sync $trait_ [$($param_types)*] }
+                }]
+        }
+    };
+
+    (@impl_body $trait_:ident [$($types:tt)*]) => {
+        /// Returns true if the trait object wraps an object of type `__T`.
+        #[inline]
+        pub fn is<__T: $trait_<$($types)*>>(&self) -> bool {
+            $crate::Downcast::as_any(self).is::<__T>()
+        }
+        /// Returns a boxed object from a boxed trait object if the underlying object is of type
+        /// `__T`. Returns the original boxed trait if it isn't.
+        #[inline]
+        pub fn downcast<__T: $trait_<$($types)*>>(
+            self: $crate::__alloc::boxed::Box<Self>
+        ) -> $crate::__std::result::Result<$crate::__alloc::boxed::Box<__T>, $crate::__alloc::boxed::Box<Self>> {
+            if self.is::<__T>() {
+                Ok($crate::Downcast::into_any(self).downcast::<__T>().unwrap())
+            } else {
+                Err(self)
+            }
+        }
+        /// Returns an `Rc`-ed object from an `Rc`-ed trait object if the underlying object is of
+        /// type `__T`. Returns the original `Rc`-ed trait if it isn't.
+        #[inline]
+        pub fn downcast_rc<__T: $trait_<$($types)*>>(
+            self: $crate::__alloc::rc::Rc<Self>
+        ) -> $crate::__std::result::Result<$crate::__alloc::rc::Rc<__T>, $crate::__alloc::rc::Rc<Self>> {
+            if self.is::<__T>() {
+                Ok($crate::Downcast::into_any_rc(self).downcast::<__T>().unwrap())
+            } else {
+                Err(self)
+            }
+        }
+        /// Returns a reference to the object within the trait object if it is of type `__T`, or
+        /// `None` if it isn't.
+        #[inline]
+        pub fn downcast_ref<__T: $trait_<$($types)*>>(&self) -> $crate::__std::option::Option<&__T> {
+            $crate::Downcast::as_any(self).downcast_ref::<__T>()
+        }
+        /// Returns a mutable reference to the object within the trait object if it is of type
+        /// `__T`, or `None` if it isn't.
+        #[inline]
+        pub fn downcast_mut<__T: $trait_<$($types)*>>(&mut self) -> $crate::__std::option::Option<&mut __T> {
+            $crate::Downcast::as_any_mut(self).downcast_mut::<__T>()
+        }
+    };
+
+    (@impl_body_sync $trait_:ident [$($types:tt)*]) => {
+        /// Returns an `Arc`-ed object from an `Arc`-ed trait object if the underlying object is of
+        /// type `__T`. Returns the original `Arc`-ed trait if it isn't.
+        #[inline]
+        pub fn downcast_arc<__T: $trait_<$($types)*>>(
+            self: $crate::__alloc::sync::Arc<Self>,
+        ) -> $crate::__std::result::Result<$crate::__alloc::sync::Arc<__T>, $crate::__alloc::sync::Arc<Self>>
+            where __T: $crate::__std::any::Any + $crate::__std::marker::Send + $crate::__std::marker::Sync
+        {
+            if self.is::<__T>() {
+                Ok($crate::DowncastSync::into_any_arc(self).downcast::<__T>().unwrap())
+            } else {
+                Err(self)
+            }
+        }
+    };
+
+    (@inject_where [$($before:tt)*] types [] where [] [$($after:tt)*]) => {
+        impl_downcast! { @as_item $($before)* $($after)* }
+    };
+
+    (@inject_where [$($before:tt)*] types [$($types:ident),*] where [] [$($after:tt)*]) => {
+        impl_downcast! {
+            @as_item
+                $($before)*
+                where $( $types: $crate::__std::any::Any + 'static ),*
+                $($after)*
+        }
+    };
+    (@inject_where [$($before:tt)*] types [$($types:ident),*] where [$($preds:tt)+] [$($after:tt)*]) => {
+        impl_downcast! {
+            @as_item
+                $($before)*
+                where
+                    $( $types: $crate::__std::any::Any + 'static, )*
+                    $($preds)*
+                $($after)*
+        }
+    };
+
+    (@as_item $i:item) => { $i };
+
+    // No type parameters.
+    ($trait_:ident   ) => { impl_downcast! { @impl_full $trait_ [] for [] where [] } };
+    ($trait_:ident <>) => { impl_downcast! { @impl_full $trait_ [] for [] where [] } };
+    (sync $trait_:ident   ) => { impl_downcast! { @impl_full_sync $trait_ [] for [] where [] } };
+    (sync $trait_:ident <>) => { impl_downcast! { @impl_full_sync $trait_ [] for [] where [] } };
+    // Type parameters.
+    ($trait_:ident < $($types:ident),* >) => {
+        impl_downcast! { @impl_full $trait_ [$($types),*] for [$($types),*] where [] }
+    };
+    (sync $trait_:ident < $($types:ident),* >) => {
+        impl_downcast! { @impl_full_sync $trait_ [$($types),*] for [$($types),*] where [] }
+    };
+    // Type parameters and where clauses.
+    ($trait_:ident < $($types:ident),* > where $($preds:tt)+) => {
+        impl_downcast! { @impl_full $trait_ [$($types),*] for [$($types),*] where [$($preds)*] }
+    };
+    (sync $trait_:ident < $($types:ident),* > where $($preds:tt)+) => {
+        impl_downcast! { @impl_full_sync $trait_ [$($types),*] for [$($types),*] where [$($preds)*] }
+    };
+    // Associated types.
+    ($trait_:ident assoc $($atypes:ident),*) => {
+        impl_downcast! { @impl_full $trait_ [$($atypes = $atypes),*] for [$($atypes),*] where [] }
+    };
+    (sync $trait_:ident assoc $($atypes:ident),*) => {
+        impl_downcast! { @impl_full_sync $trait_ [$($atypes = $atypes),*] for [$($atypes),*] where [] }
+    };
+    // Associated types and where clauses.
+    ($trait_:ident assoc $($atypes:ident),* where $($preds:tt)+) => {
+        impl_downcast! { @impl_full $trait_ [$($atypes = $atypes),*] for [$($atypes),*] where [$($preds)*] }
+    };
+    (sync $trait_:ident assoc $($atypes:ident),* where $($preds:tt)+) => {
+        impl_downcast! { @impl_full_sync $trait_ [$($atypes = $atypes),*] for [$($atypes),*] where [$($preds)*] }
+    };
+    // Type parameters and associated types.
+    ($trait_:ident < $($types:ident),* > assoc $($atypes:ident),*) => {
+        impl_downcast! {
+            @impl_full
+                $trait_ [$($types),*, $($atypes = $atypes),*]
+                for [$($types),*, $($atypes),*]
+                where []
+        }
+    };
+    (sync $trait_:ident < $($types:ident),* > assoc $($atypes:ident),*) => {
+        impl_downcast! {
+            @impl_full_sync
+                $trait_ [$($types),*, $($atypes = $atypes),*]
+                for [$($types),*, $($atypes),*]
+                where []
+        }
+    };
+    // Type parameters, associated types, and where clauses.
+    ($trait_:ident < $($types:ident),* > assoc $($atypes:ident),* where $($preds:tt)+) => {
+        impl_downcast! {
+            @impl_full
+                $trait_ [$($types),*, $($atypes = $atypes),*]
+                for [$($types),*, $($atypes),*]
+                where [$($preds)*]
+        }
+    };
+    (sync $trait_:ident < $($types:ident),* > assoc $($atypes:ident),* where $($preds:tt)+) => {
+        impl_downcast! {
+            @impl_full_sync
+                $trait_ [$($types),*, $($atypes = $atypes),*]
+                for [$($types),*, $($atypes),*]
+                where [$($preds)*]
+        }
+    };
+    // Concretely-parametrized types.
+    (concrete $trait_:ident < $($types:ident),* >) => {
+        impl_downcast! { @impl_full $trait_ [$($types),*] for [] where [] }
+    };
+    (sync concrete $trait_:ident < $($types:ident),* >) => {
+        impl_downcast! { @impl_full_sync $trait_ [$($types),*] for [] where [] }
+    };
+    // Concretely-associated types types.
+    (concrete $trait_:ident assoc $($atypes:ident = $aty:ty),*) => {
+        impl_downcast! { @impl_full $trait_ [$($atypes = $aty),*] for [] where [] }
+    };
+    (sync concrete $trait_:ident assoc $($atypes:ident = $aty:ty),*) => {
+        impl_downcast! { @impl_full_sync $trait_ [$($atypes = $aty),*] for [] where [] }
+    };
+    // Concretely-parametrized types with concrete associated types.
+    (concrete $trait_:ident < $($types:ident),* > assoc $($atypes:ident = $aty:ty),*) => {
+        impl_downcast! { @impl_full $trait_ [$($types),*, $($atypes = $aty),*] for [] where [] }
+    };
+    (sync concrete $trait_:ident < $($types:ident),* > assoc $($atypes:ident = $aty:ty),*) => {
+        impl_downcast! { @impl_full_sync $trait_ [$($types),*, $($atypes = $aty),*] for [] where [] }
+    };
+}
+
+
+#[cfg(test)]
+mod test {
+    macro_rules! test_mod {
+        (
+            $test_mod_name:ident,
+            trait $base_trait:path { $($base_impl:tt)* },
+            non_sync: { $($non_sync_def:tt)+ },
+            sync: { $($sync_def:tt)+ }
+        ) => {
+            test_mod! {
+                $test_mod_name,
+                trait $base_trait { $($base_impl:tt)* },
+                type dyn $base_trait,
+                non_sync: { $($non_sync_def)* },
+                sync: { $($sync_def)* }
+            }
+        };
+
+        (
+            $test_mod_name:ident,
+            trait $base_trait:path { $($base_impl:tt)* },
+            type $base_type:ty,
+            non_sync: { $($non_sync_def:tt)+ },
+            sync: { $($sync_def:tt)+ }
+        ) => {
+            mod $test_mod_name {
+                test_mod!(
+                    @test
+                    $test_mod_name,
+                    test_name: test_non_sync,
+                    trait $base_trait { $($base_impl)* },
+                    type $base_type,
+                    { $($non_sync_def)+ },
+                    []);
+
+                test_mod!(
+                    @test
+                    $test_mod_name,
+                    test_name: test_sync,
+                    trait $base_trait { $($base_impl)* },
+                    type $base_type,
+                    { $($sync_def)+ },
+                    [{
+                        // Fail to convert Arc<Base> into Arc<Bar>.
+                        let arc: $crate::__alloc::sync::Arc<$base_type> = $crate::__alloc::sync::Arc::new(Foo(42));
+                        let res = arc.downcast_arc::<Bar>();
+                        assert!(res.is_err());
+                        let arc = res.unwrap_err();
+                        // Convert Arc<Base> into Arc<Foo>.
+                        assert_eq!(
+                            42, arc.downcast_arc::<Foo>().map_err(|_| "Shouldn't happen.").unwrap().0);
+                    }]);
+            }
+        };
+
+        (
+            @test
+            $test_mod_name:ident,
+            test_name: $test_name:ident,
+            trait $base_trait:path { $($base_impl:tt)* },
+            type $base_type:ty,
+            { $($def:tt)+ },
+            [ $($more_tests:block)* ]
+        ) => {
+            #[test]
+            fn $test_name() {
+                #[allow(unused_imports)]
+                use super::super::{Downcast, DowncastSync};
+
+                // Should work even if standard objects (especially those in the prelude) are
+                // aliased to something else.
+                #[allow(dead_code)] struct Any;
+                #[allow(dead_code)] struct Arc;
+                #[allow(dead_code)] struct Box;
+                #[allow(dead_code)] struct Option;
+                #[allow(dead_code)] struct Result;
+                #[allow(dead_code)] struct Rc;
+                #[allow(dead_code)] struct Send;
+                #[allow(dead_code)] struct Sync;
+
+                // A trait that can be downcast.
+                $($def)*
+
+                // Concrete type implementing Base.
+                #[derive(Debug)]
+                struct Foo(u32);
+                impl $base_trait for Foo { $($base_impl)* }
+                #[derive(Debug)]
+                struct Bar(f64);
+                impl $base_trait for Bar { $($base_impl)* }
+
+                // Functions that can work on references to Base trait objects.
+                fn get_val(base: &$crate::__alloc::boxed::Box<$base_type>) -> u32 {
+                    match base.downcast_ref::<Foo>() {
+                        Some(val) => val.0,
+                        None => 0
+                    }
+                }
+                fn set_val(base: &mut $crate::__alloc::boxed::Box<$base_type>, val: u32) {
+                    if let Some(foo) = base.downcast_mut::<Foo>() {
+                        foo.0 = val;
+                    }
+                }
+
+                let mut base: $crate::__alloc::boxed::Box<$base_type> = $crate::__alloc::boxed::Box::new(Foo(42));
+                assert_eq!(get_val(&base), 42);
+
+                // Try sequential downcasts.
+                if let Some(foo) = base.downcast_ref::<Foo>() {
+                    assert_eq!(foo.0, 42);
+                } else if let Some(bar) = base.downcast_ref::<Bar>() {
+                    assert_eq!(bar.0, 42.0);
+                }
+
+                set_val(&mut base, 6*9);
+                assert_eq!(get_val(&base), 6*9);
+
+                assert!(base.is::<Foo>());
+
+                // Fail to convert Box<Base> into Box<Bar>.
+                let res = base.downcast::<Bar>();
+                assert!(res.is_err());
+                let base = res.unwrap_err();
+                // Convert Box<Base> into Box<Foo>.
+                assert_eq!(
+                    6*9, base.downcast::<Foo>().map_err(|_| "Shouldn't happen.").unwrap().0);
+
+                // Fail to convert Rc<Base> into Rc<Bar>.
+                let rc: $crate::__alloc::rc::Rc<$base_type> = $crate::__alloc::rc::Rc::new(Foo(42));
+                let res = rc.downcast_rc::<Bar>();
+                assert!(res.is_err());
+                let rc = res.unwrap_err();
+                // Convert Rc<Base> into Rc<Foo>.
+                assert_eq!(
+                    42, rc.downcast_rc::<Foo>().map_err(|_| "Shouldn't happen.").unwrap().0);
+
+                $($more_tests)*
+            }
+        };
+        (
+            $test_mod_name:ident,
+            trait $base_trait:path { $($base_impl:tt)* },
+            non_sync: { $($non_sync_def:tt)+ },
+            sync: { $($sync_def:tt)+ }
+        ) => {
+            test_mod! {
+                $test_mod_name,
+                trait $base_trait { $($base_impl:tt)* },
+                type $base_trait,
+                non_sync: { $($non_sync_def)* },
+                sync: { $($sync_def)* }
+            }
+        };
+
+    }
+
+    test_mod!(non_generic, trait Base {},
+        non_sync: {
+            trait Base: Downcast {}
+            impl_downcast!(Base);
+        },
+        sync: {
+            trait Base: DowncastSync {}
+            impl_downcast!(sync Base);
+        });
+
+    test_mod!(generic, trait Base<u32> {},
+        non_sync: {
+            trait Base<T>: Downcast {}
+            impl_downcast!(Base<T>);
+        },
+        sync: {
+            trait Base<T>: DowncastSync {}
+            impl_downcast!(sync Base<T>);
+        });
+
+    test_mod!(constrained_generic, trait Base<u32> {},
+        non_sync: {
+            trait Base<T: Copy>: Downcast {}
+            impl_downcast!(Base<T> where T: Copy);
+        },
+        sync: {
+            trait Base<T: Copy>: DowncastSync {}
+            impl_downcast!(sync Base<T> where T: Copy);
+        });
+
+    test_mod!(associated,
+        trait Base { type H = f32; },
+        type dyn Base<H=f32>,
+        non_sync: {
+            trait Base: Downcast { type H; }
+            impl_downcast!(Base assoc H);
+        },
+        sync: {
+            trait Base: DowncastSync { type H; }
+            impl_downcast!(sync Base assoc H);
+        });
+
+    test_mod!(constrained_associated,
+        trait Base { type H = f32; },
+        type dyn Base<H=f32>,
+        non_sync: {
+            trait Base: Downcast { type H: Copy; }
+            impl_downcast!(Base assoc H where H: Copy);
+        },
+        sync: {
+            trait Base: DowncastSync { type H: Copy; }
+            impl_downcast!(sync Base assoc H where H: Copy);
+        });
+
+    test_mod!(param_and_associated,
+        trait Base<u32> { type H = f32; },
+        type dyn Base<u32, H=f32>,
+        non_sync: {
+            trait Base<T>: Downcast { type H; }
+            impl_downcast!(Base<T> assoc H);
+        },
+        sync: {
+            trait Base<T>: DowncastSync { type H; }
+            impl_downcast!(sync Base<T> assoc H);
+        });
+
+    test_mod!(constrained_param_and_associated,
+        trait Base<u32> { type H = f32; },
+        type dyn Base<u32, H=f32>,
+        non_sync: {
+            trait Base<T: Clone>: Downcast { type H: Copy; }
+            impl_downcast!(Base<T> assoc H where T: Clone, H: Copy);
+        },
+        sync: {
+            trait Base<T: Clone>: DowncastSync { type H: Copy; }
+            impl_downcast!(sync Base<T> assoc H where T: Clone, H: Copy);
+        });
+
+    test_mod!(concrete_parametrized, trait Base<u32> {},
+        non_sync: {
+            trait Base<T>: Downcast {}
+            impl_downcast!(concrete Base<u32>);
+        },
+        sync: {
+            trait Base<T>: DowncastSync {}
+            impl_downcast!(sync concrete Base<u32>);
+        });
+
+    test_mod!(concrete_associated,
+        trait Base { type H = u32; },
+        type dyn Base<H=u32>,
+        non_sync: {
+            trait Base: Downcast { type H; }
+            impl_downcast!(concrete Base assoc H=u32);
+        },
+        sync: {
+            trait Base: DowncastSync { type H; }
+            impl_downcast!(sync concrete Base assoc H=u32);
+        });
+
+    test_mod!(concrete_parametrized_associated,
+        trait Base<u32> { type H = f32; },
+        type dyn Base<u32, H=f32>,
+        non_sync: {
+            trait Base<T>: Downcast { type H; }
+            impl_downcast!(concrete Base<u32> assoc H=f32);
+        },
+        sync: {
+            trait Base<T>: DowncastSync { type H; }
+            impl_downcast!(sync concrete Base<u32> assoc H=f32);
+        });
+}
diff --git a/tests/import_via_macro_use.rs b/tests/import_via_macro_use.rs
new file mode 100644
index 0000000..fc2fab2
--- /dev/null
+++ b/tests/import_via_macro_use.rs
@@ -0,0 +1,9 @@
+#[macro_use]
+extern crate downcast_rs;
+
+#[test]
+fn test() {
+    use downcast_rs::Downcast;
+    trait Trait: Downcast {}
+    impl_downcast!(Trait);
+}
diff --git a/tests/use_via_namespace.rs b/tests/use_via_namespace.rs
new file mode 100644
index 0000000..19f630c
--- /dev/null
+++ b/tests/use_via_namespace.rs
@@ -0,0 +1,8 @@
+extern crate downcast_rs;
+
+#[test]
+fn test() {
+    use downcast_rs::Downcast;
+    trait Trait: Downcast {}
+    downcast_rs::impl_downcast!(Trait);
+}