//! This crate offers functionality for casting between trait objects using only
//! safe Rust and no platform specific code. If you want to downcast to concrete
//! types instead of other trait objects then this crate can't help you, instead
//! use [`std::any`] or a crate like [`downcast-rs`].
//!
//! This crate offers two things, a trait [`DynCast`] that abstracts over methods
//! used to cast between trait objects and some macros to minimize the boilerplate
//! needed to implement that trait.
//!
//! # Usage
//!
//! You should use the [`DynCast`] trait in trait bounds or as a supertrait and
//! then do casts using the methods provided by the [`DynCastExt`] trait. The
//! [`DynCast`] trait takes a type parameter that should be a "config" type
//! generated by the [`create_dyn_cast_config`] macro, this type defines from
//! which trait and to which trait a cast is made. Types that need to allow casting
//! to meet the [`DynCast`] trait bound can then implement it via the
//! [`impl_dyn_cast`] macro.
//!
//! # Examples
//!
//! ```
//! use cast_trait_object::{create_dyn_cast_config, impl_dyn_cast, DynCast, DynCastExt};
//!
//! create_dyn_cast_config!(SuperToSubCast = Super => Sub);
//! create_dyn_cast_config!(SuperUpcast = Super => Super);
//! trait Super: DynCast<SuperToSubCast> + DynCast<SuperUpcast> {}
//! trait Sub: Super {}
//!
//! struct Foo;
//! impl Super for Foo {}
//! impl Sub for Foo {}
//! impl_dyn_cast!(Foo as Super => Sub, Super);
//!
//! let foo: &dyn Super = &Foo;
//! // Casting to a sub trait is fallible (the error allows us to keep using the
//! // `dyn Super` trait object if we want which can be important if we are casting
//! // movable types like `Box<dyn Trait>`):
//! let foo: &dyn Sub = foo.dyn_cast().ok().unwrap();
//! // Upcasting to a supertrait is infallible:
//! let foo /*: &dyn Super*/ = foo.dyn_upcast::<dyn Super>();
//! ```
//!
//! When implementing the [`DynCast`] trait via the [`impl_dyn_cast`] macro you
//! can also list the created "config" types instead of the source and target
//! traits:
//!
//! ```
//!# use cast_trait_object::{create_dyn_cast_config, impl_dyn_cast, DynCast, DynCastExt};
//!# //
//!# create_dyn_cast_config!(SuperToSubCast = Super => Sub);
//!# create_dyn_cast_config!(SuperUpcast = Super => Super);
//!# trait Super: DynCast<SuperToSubCast> + DynCast<SuperUpcast> {}
//!# trait Sub: Super {}
//!# //
//!# struct Foo;
//!# impl Super for Foo {}
//!# impl Sub for Foo {}
//! impl_dyn_cast!(Foo => SuperToSubCast, SuperUpcast);
//!# //
//!# let foo: &dyn Super = &Foo;
//!# let foo: &dyn Sub = foo.dyn_cast().ok().unwrap();
//!# let foo /*: &dyn Super*/ = foo.dyn_upcast::<dyn Super>();
//! ```
//!
//! If the `proc-macros` feature is enabled (which it is by default) we can also
//! use procedural attribute macros to write a little bit less boilerplate:
//!
//! ```
//!# // Macros rely on items being at `crate::some_name`
//!# #[cfg(feature = "proc-macros")]
//!# use cast_trait_object::*;
//!# //
//!# #[cfg(feature = "proc-macros")]
//!# fn main() { inner::some_fn(); }
//!# #[cfg(not(feature = "proc-macros"))]
//!# fn main() { }
//!# //
//!# #[cfg(feature = "proc-macros")]
//!# mod inner {
//!# pub fn some_fn() {
//! use cast_trait_object::{dyn_cast, dyn_upcast, DynCastExt};
//!
//! #[dyn_cast(Sub)]
//! #[dyn_upcast]
//! trait Super {}
//! trait Sub: Super {}
//!
//! struct Foo;
//! #[dyn_cast(Sub)]
//! #[dyn_upcast]
//! impl Super for Foo {}
//! impl Sub for Foo {}
//!# //
//!# let foo: &dyn Super = &Foo;
//!# let foo: &dyn Sub = foo.dyn_cast().ok().unwrap();
//!# let foo /*: &dyn Super*/ = foo.dyn_upcast::<dyn Super>();
//!# }}
//! ```
//!
//! Note that `#[dyn_upcast]` does the same as `#[dyn_cast(Super)]` but it is a bit
//! clearer about intentions:
//!
//! ```
//!# // Macros rely on items being at `crate::some_name`
//!# #[cfg(feature = "proc-macros")]
//!# use cast_trait_object::*;
//!# //
//!# #[cfg(feature = "proc-macros")]
//!# fn main() { inner::some_fn(); }
//!# #[cfg(not(feature = "proc-macros"))]
//!# fn main() { }
//!# //
//!# #[cfg(feature = "proc-macros")]
//!# mod inner {
//!# pub fn some_fn() {
//! use cast_trait_object::{dyn_cast, DynCastExt};
//!
//! #[dyn_cast(Super, Sub)]
//! trait Super {}
//! trait Sub: Super {}
//!
//! struct Foo;
//! #[dyn_cast(Super, Sub)]
//! impl Super for Foo {}
//! impl Sub for Foo {}
//!
//!# let foo: &dyn Super = &Foo;
//!# let foo: &dyn Sub = foo.dyn_cast().ok().unwrap();
//! let foo: &dyn Sub = &Foo;
//! // Upcasting still works:
//! let foo /*: &dyn Super*/ = foo.dyn_upcast::<dyn Super>();
//!# }}
//! ```
//!
//! # Generics
//!
//! Generics traits and types are supported and both the declarative macros
//! ([`impl_dyn_cast`], [`create_dyn_cast_config`], [`impl_dyn_cast_config`])
//! and the procedural attribute macros ([`dyn_cast`] and [`dyn_upcast`]) can
//! be used with generics.
//!
//! ```
//!# // Macros rely on items being at `crate::some_name`
//!# #[cfg(feature = "proc-macros")]
//!# use cast_trait_object::*;
//!# //
//!# #[cfg(feature = "proc-macros")]
//!# fn main() { inner::some_fn(); }
//!# #[cfg(not(feature = "proc-macros"))]
//!# fn main() { }
//!# //
//!# #[cfg(feature = "proc-macros")]
//!# mod inner {
//!# pub fn some_fn() {
//! use cast_trait_object::{DynCastExt, dyn_cast, dyn_upcast};
//!
//! // Define a source and target trait:
//! #[dyn_cast(Sub<T>)]
//! #[dyn_upcast]
//! trait Super<T> {}
//! trait Sub<T>: Super<T> {}
//!
//! // Since `T` isn't used for `Color` it doesn't need to be `'static`:
//! struct Color(u8, u8, u8);
//! #[dyn_cast(Sub<T>)]
//! #[dyn_upcast]
//! impl<T> Super<T> for Color {}
//! impl<T> Sub<T> for Color {}
//!
//! struct Example<T>(T);
//! #[dyn_cast(Sub<T>)]
//! #[dyn_upcast]
//! impl<T: 'static> Super<T> for Example<T> {}
//! impl<T: 'static> Sub<T> for Example<T> {}
//!
//! let as_sub: &dyn Sub<bool> = &Example(false);
//! let upcasted: &dyn Super<bool> = as_sub.dyn_upcast();
//! let _downcasted /*: &dyn Sub<bool> */ = upcasted.dyn_cast::<dyn Sub<bool>>().ok().unwrap();
//!# }}
//! ```
//!
//! Note that one limitation of the current support for generic types is that if
//! the type that implements [`DynCast`] has any generic type parameters then
//! they might need to be constrained to be `'static`.
//!
//! There is also another limitation with generic types and this one can be a bit
//! counter intuitive. The [`DynCast`] implementations that are generated by the
//! macros must always succeed or always fail. This means that if a target trait
//! is only implemented for a subset of the types that the [`DynCast`] trait is
//! implemented for then the cast will always fail.
//!
//! ```
//! use cast_trait_object::{create_dyn_cast_config, impl_dyn_cast, DynCast, DynCastExt};
//!
//! // Define a source and target trait:
//! create_dyn_cast_config!(UpcastConfig = Super => Super);
//! create_dyn_cast_config!(SuperConfig = Super => Sub);
//! trait Super: DynCast<SuperConfig> + DynCast<UpcastConfig> {}
//! trait Sub: Super {}
//!
//! /// Only implements `Sub` for types that implement `Display`.
//! struct OnlyDisplayGeneric<T>(T);
//! impl<T: 'static> Super for OnlyDisplayGeneric<T> {}
//! impl<T: core::fmt::Display + 'static> Sub for OnlyDisplayGeneric<T> {}
//! // The cast to `Sub` will always fail since this impl of DynCast includes
//! // some `T` that don't implement `Display`:
//! impl_dyn_cast!(for<T> OnlyDisplayGeneric<T> as Super where {T: 'static} => Sub);
//! impl_dyn_cast!(for<T> OnlyDisplayGeneric<T> as Super where {T: 'static} => Super);
//!
//! // &str does implement Display:
//! let _is_display: &dyn core::fmt::Display = &"";
//!
//! // But the cast will still fail:
//! let as_super: &dyn Super = &OnlyDisplayGeneric("");
//! assert!(as_super.dyn_cast::<dyn Sub>().is_err());
//!
//! // `OnlyDisplayGeneric<&str>` does implement `Sub`:
//! let as_sub: &dyn Sub = &OnlyDisplayGeneric("");
//!
//! // Note that this means that we can perform an upcast and then fail to downcast:
//! let upcasted: &dyn Super = as_sub.dyn_upcast();
//! assert!(upcasted.dyn_cast::<dyn Sub>().is_err());
//! ```
//!
//! The best way to avoid this problem is to have the same trait bounds on both
//! the source trait implementation and the target trait implementation.
//!
//! # How it works
//!
//! ## How the conversion is preformed
//!
//! Using the [`DynCast`] trait as a supertraits adds a couple of extra methods
//! to a trait object's vtable. These methods all essentially take a pointer to
//! the type and returns a new fat pointer which points to the wanted vtable.
//! There are a couple of methods since we need to generate one for each type of
//! trait object, so one for each of `&dyn Trait`, `&mut dyn Trait`,
//! `Box<dyn Trait>`, `Rc<dyn Trait>` and `Arc<dyn Trait>`. Note that these methods
//! are entirely safe Rust code, this crate doesn't use or generate any unsafe
//! code at all.
//!
//! These methods work something like:
//!
//! ```
//! trait Super {}
//! trait Sub {
//!     fn upcast(self: Box<Self>) -> Box<dyn Super>;
//! }
//!
//! impl Super for () {}
//! impl Sub for () {
//!     fn upcast(self: Box<Self>) -> Box<dyn Super> { self }
//! }
//!
//! let a: Box<dyn Sub> = Box::new(());
//! let a: Box<dyn Super> = a.upcast();
//! ```
//!
//! The [`DynCastExt`] trait then abstracts over the different types of trait
//! objects so that when a call is made using the [dyn_cast](DynCastExt::dyn_cast)
//! method the compiler can inline that static method call to the correct method
//! on the trait object.
//!
//! ## Why "config" types are needed
//!
//! We have to generate "config" types since we need to uniquely identify each
//! [`DynCast`] supertrait based on which trait it is casting from and into.
//! Originally this was just done using two type parameters on the trait, something
//! like `DynCast<dyn Super, dyn Sub>`, but that caused compile errors when they were
//! used as a supertrait of one of the mentioned traits. So now the traits are
//! "hidden" as associated types on a generated "config" type. To make this "config"
//! type more ergonomic we also implement a [`GetDynCastConfig`] trait to easily
//! go from the source trait and target trait to a "config" type via something
//! like `<dyn Source as GetDynCastConfig<dyn Target>>::Config`. This allows
//! the macros ([`impl_dyn_cast`], [`dyn_cast`] and [`dyn_upcast`]) to take traits
//! as arguments instead of "config" types, it also makes type inference work for
//! the [`DynCastExt`] trait.
//!
//! ## How the macros know if a type implements a "target" trait or not
//!
//! When a type implementing [`DynCast`] for a specific config and therefore
//! source to target trait cast the generated code must choose if the cast is
//! going to succeed or not. We want to return `Ok(value as &dyn Target)` if
//! the type implements the `Target` trait and `Err(value as &dyn Source)` if
//! it doesn't.
//!
//! We can use a clever hack to only preform the coercion if a type actually
//! implements the target trait. See dtolnay's [Autoref-based stable specialization]
//! (https://github.com/dtolnay/case-studies/tree/master/autoref-specialization)
//! case study for more information about how this hack works. In short the hack
//! allows us to call one method if a trait bound is met and another method if it
//! isn't. In this way we can call a helper method that performs the coercion to
//! the target trait only if the type actually implements that trait.
//!
//! So we could generate something like:
//!
//! ```rust
//! trait Source {}
//! trait Target {}
//!
//! struct Foo;
//! impl Source for Foo {}
//!
//! struct Fallback;
//! impl Fallback {
//!#    #[allow(dead_code)]
//!     fn cast<'a, T: Source>(&self, value: &'a T) -> &'a dyn Source { value }
//! }
//!
//! struct HasTrait<T>(core::marker::PhantomData<T>);
//! impl<T> HasTrait<T> {
//!     fn new() -> Self {
//!          Self(core::marker::PhantomData)
//!     }
//! }
//! impl<T: Target> HasTrait<T> {
//!#    #[allow(dead_code)]
//!     fn cast<'a>(&self, value: &'a T) -> &'a dyn Target { value }
//! }
//! impl<T> core::ops::Deref for HasTrait<T> {
//!     type Target = Fallback;
//!     fn deref(&self) -> &Self::Target {
//!         static FALLBACK: Fallback = Fallback;
//!         &FALLBACK
//!     }
//! }
//!
//! let used_fallback: &dyn Source = HasTrait::<Foo>::new().cast(&Foo);
//! ```
//!
//! So the [`impl_dyn_cast`] macro works by generating a struct that implements
//! [`core::ops::Deref`] into another type. Both types have a `cast` method but
//! they do different things. The first struct's `cast` method has a trait bound
//! so that it is only implemented if the cast can succeed. If the first method
//! can't be used the compiler will insert a deref operation (`&*foo`) and see
//! if there is a method that can apply after that. In this case that means that
//! the `Fallback` structs method is called. This way the generated code doesn't
//! call the method that preform the coercion to the `Target` trait unless the
//! type actually implements it.
//!
//! # Alternatives
//!
//! The [`intertrait`] crate offers similar functionality to this crate but has
//! a totally different implementation, at least as of [`intertrait`] version
//! `0.2.0`. It uses the [`linkme`] crate to create a registry of [`std::any::Any`]
//! type ids for types that can be cast into a certain trait object. This means
//! it probably has some runtime overhead when it looks up a cast function in
//! the global registry using a [`TypeId`]. It also means that it can't work on
//! all platforms since the [`linkme`] crate needs to offer support for them. This
//! is a limitation that this crate doesn't have.
//!
//! The [`traitcast`] crate works similar to [`intertrait`] in that it has a
//! global registry that is keyed with [`TypeId`]s. But it differs in that it
//! uses the [`inventory`] crate to build the registry instead of the [`linkme`]
//! crate. The [`inventory`] crate uses the [`ctor`] crate to run some code before
//! `main`, something that is generally discouraged and this is something that
//! [`intertrait`] actually mentions as an advantage to its approach.
//!
//! The [`traitcast_core`] library allow for a more low level API that doesn't
//! depend on a global registry and therefore also doesn't depend on a crate like
//! [`linkme`] or [`inventory`] that needs platform specific support. Instead it
//! requires that you explicitly create a registry and register all your types
//! and their casts with it.
//!
//! The [`downcast-rs`] crate offers downcasting to concrete types but not
//! directly casting from one trait object to another trait object. So it has a
//! different use case and both it and this crate could be useful in the same
//! project.
//!
//! You could just define methods on your traits similar to the ones provided by
//! this crate's [`DynCast`] trait. Doing this yourself can be more flexible and
//! you could for example minimize bloat by only implementing methods for casts
//! that you actually require. The disadvantage is that it would be much less
//! ergonomic than what this crate offers.
//!
//! # References
//!
//! The following GutHub issue [Clean up pseudo-downcasting from VpnProvider supertrait to subtraits with better solution · Issue #21 · jamesmcm/vopono](https://github.com/jamesmcm/vopono/issues/21)
//! inspired this library.
//!
//! This library was mentioned in the following blog post in the "Upcasting"
//! section:
//! [So you want to write object oriented Rust :: Darrien's Blog — Dev work and musings](https://blog.darrien.dev/posts/so-you-want-to-object/#upcasting)
//!
//! # License
//!
//! This project is released under either:
//!
//! - [MIT License](https://github.com/Lej77/cast_trait_object/blob/master/LICENSE-MIT)
//! - [Apache License (Version 2.0)](https://github.com/Lej77/cast_trait_object/blob/master/LICENSE-APACHE)
//!
//! at your choosing.
//!
//! [`std::any`]: https://doc.rust-lang.org/std/any
//! [`std::any::Any`]: https://doc.rust-lang.org/std/any/trait.Any.html
//! [`TypeId`]: https://doc.rust-lang.org/std/any/struct.TypeId.html
//! [`downcast-rs`]: https://crates.io/crates/downcast-rs
//! [`intertrait`]: https://crates.io/crates/intertrait
//! [`traitcast`]: https://crates.io/crates/traitcast
//! [`traitcast_core`]: https://crates.io/crates/traitcast_core
//! [`linkme`]: https://crates.io/crates/linkme
//! [`inventory`]: https://crates.io/crates/inventory
//! [`ctor`]: https://crates.io/crates/ctor
#![no_std]
#![forbid(unsafe_code)]
// Warnings and docs:
#![warn(clippy::all)]
#![deny(broken_intra_doc_links)]
#![cfg_attr(feature = "docs", feature(doc_cfg))]
#![warn(missing_debug_implementations, missing_docs, rust_2018_idioms)]
#![doc(test(
    no_crate_inject,
    attr(
        deny(warnings, rust_2018_idioms),
        allow(unused_extern_crates, unused_variables)
    )
))]

/// Activate some code only when a certain config is met. Show the required config in the documentation.
///
/// To ensure `rustfmt` works on the enclosed code be sure to invoke this macro in a functional style.
/// Also if the code contains references to `self` then use the `impl Self { /* code... */ }` invocation.
macro_rules! cfg_with_docs {
    ($feature:meta, { $(impl Self { $($code:tt)* })* }) => {
        $(
            #[cfg($feature)]
            #[cfg_attr(feature = "docs", doc(cfg($feature)))]
            $($code)*
        )*
    };
    ($feature:meta, $({$($code:tt)*}),*) => {
        $(
            #[cfg($feature)]
            #[cfg_attr(feature = "docs", doc(cfg($feature)))]
            $($code)*
        )*
    };
}

#[cfg(feature = "alloc")]
extern crate alloc;

#[cfg(feature = "alloc")]
use alloc::{boxed::Box, rc::Rc, sync::Arc};

cfg_with_docs!(
    feature = "proc-macros",
    {
        /// Allow upcast from a trait to one of its supertraits. This can be used
        /// on traits or on types. For types you need to specify the path to the super
        /// trait inside the parenthesis after the macro name like so:
        /// `#[dyn_upcast(SuperTrait)]` while for traits don't need to specify anything
        /// `#[dyn_upcast]`.
        ///
        /// # Examples
        ///
        /// ```
        /// use cast_trait_object::*;
        ///# fn main() {
        ///
        /// #[dyn_upcast]
        /// trait Super {}
        ///
        /// trait Sub: Super {}
        ///
        /// #[dyn_upcast(Super)]
        /// struct Foo;
        /// impl Super for Foo {}
        /// impl Sub for Foo {}
        ///
        /// // We can now cast from one trait object to another:
        /// let foo: &dyn Sub = &Foo;
        /// let foo: &dyn Super = foo.dyn_upcast();
        ///# }
        /// ```
        ///
        /// The macro can also be applied to a trait implementation (`impl Trait for Type`)
        /// instead of directly on a type:
        ///
        /// ```
        ///# use cast_trait_object::*;
        ///# fn main() {
        ///#
        ///# #[dyn_upcast]
        ///# trait Super {}
        ///#
        ///# trait Sub: Super {}
        ///#
        ///# struct Foo;
        /// #[dyn_upcast]
        /// impl Super for Foo {}
        ///# impl Sub for Foo {}
        ///#
        ///# // We can now cast from one trait object to another:
        ///# let foo: &dyn Sub = &Foo;
        ///# let foo: &dyn Super = foo.dyn_upcast();
        ///# }
        /// ```
        pub use cast_trait_object_macros::dyn_upcast;
    },
    {
        /// Allow attempting to cast a trait object to another trait object. This can be
        /// used on traits or on types. For types you need to specify the path to the
        /// "source" trait inside the parenthesis after the macro name like so:
        /// `#[dyn_cast(SourceTrait => TargetTrait)]`, while for traits you only need to
        /// specify the target trait: `#[dyn_cast(TargetTrait)]`.
        /// # Examples
        ///
        /// ```
        /// use cast_trait_object::*;
        ///# fn main() {
        ///
        /// #[dyn_cast(Sub)]
        /// trait Super {}
        ///
        /// trait Sub: Super {}
        ///
        /// #[dyn_cast(Super => Sub)]
        /// struct Foo;
        /// impl Super for Foo {}
        /// impl Sub for Foo {}
        ///
        /// // We can now attempt casting between trait objects:
        /// let foo: &dyn Super = &Foo;
        /// let foo: &dyn Sub = foo.dyn_cast().ok().unwrap();
        ///# }
        /// ```
        ///
        /// The macro can also be applied to a trait implementation (`impl Trait for Type`)
        /// instead of directly on a type:
        ///
        /// ```
        ///# use cast_trait_object::*;
        ///# fn main() {
        ///#
        ///# #[dyn_cast(Sub)]
        ///# trait Super {}
        ///#
        ///# trait Sub: Super {}
        ///#
        ///# struct Foo;
        /// #[dyn_cast(Sub)]
        /// impl Super for Foo {}
        ///# impl Sub for Foo {}
        ///#
        ///# // We can now attempt casting between trait objects:
        ///# let foo: &dyn Super = &Foo;
        ///# let foo: &dyn Sub = foo.dyn_cast().ok().unwrap();
        ///# }
        /// ```
        pub use cast_trait_object_macros::dyn_cast;
    }
);

/// Used by macros to determine if a type can be coerced to a "config" type's
/// target trait.
///
/// If a config type implements `DynCastConfigTargetTest<T>` for a type `T` then
/// that type can be coerced to the trait defined by `<C as DynCastConfig>::Target`.
///
/// This is used by the [`impl_dyn_cast`] macro to determine if it should generate
/// code that coerces a type to the target trait or to the source trait.
pub trait DynCastConfigTargetTest<C: ?Sized> {}

/// Get a [`DynCastConfig`] type for a source trait that casts to a target trait `T`.
///
/// This is used by the [`impl_dyn_cast`] macro to allow specifying only the traits
/// that are being cast from and to instead of a concrete config type that implements
/// the [`DynCastConfig`] trait.
///
/// This is also needed for the implementation of the [`DynCastExt`] trait to ensure
/// that type inference works so that it is ergonomic to use.
pub trait GetDynCastConfig<T: ?Sized> {
    /// A config type that casts from the `Self` trait to the trait `T`.
    type Config: DynCastConfig<Target = T, Source = Self>;
}

/// Specifies the trait that we are casting from and the trait we are casting to.
///
/// The reason we need a "config" type instead of just specifying the source
/// and target traits as type parameters in the [`DynCast`] trait is that the
/// compiler would error out it certain situations due to it detecting "cycles".
/// "Hiding" the source and target traits as associated types prevent this from
/// happening and allows using the [`DynCast`] trait as a supertrait of the
/// source trait from which we perform a cast.
pub trait DynCastConfig {
    /// The trait we are casting to.
    type Target: ?Sized;
    /// The trait we are casting from and that we want back if the cast failed.
    type Source: ?Sized;
}

/// This is an implementation detail for the macros that implement [`DynCast`].
///
/// Used to create a specify a "config" type when only the source and target traits
/// are known.
///
/// This type implements [`DynCastConfig`] and there is a blanket implementation
/// of [`DynCast`] so that if `DynCast` is implemented for
/// `ConcreteDynCastConfig<dyn Source, dyn Target>` then `DynCast` is implemented
/// for all "config" types that implement
/// `DynCastConfig<Source = dyn Source, Target = dyn Target>`.
#[derive(Debug)]
pub struct ConcreteDynCastConfig<S: ?Sized, T: ?Sized> {
    _source: core::marker::PhantomData<S>,
    _target: core::marker::PhantomData<T>,
}
impl<S: ?Sized, T: ?Sized> DynCastConfig for ConcreteDynCastConfig<S, T> {
    type Target = T;
    type Source = S;
}
impl<C, T> DynCast<C> for T
where
    C: DynCastConfig,
    T: DerivedDynCast<ConcreteDynCastConfig<C::Source, C::Target>, C>,
{
    fn dyn_cast_ref(&self) -> Result<&C::Target, &C::Source> {
        <T as DerivedDynCast<ConcreteDynCastConfig<C::Source, C::Target>, C>>::derived_dyn_cast_ref(
            self,
        )
    }

    fn dyn_cast_mut(&mut self) -> Result<&mut C::Target, &mut C::Source> {
        <T as DerivedDynCast<ConcreteDynCastConfig<C::Source, C::Target>, C>>::derived_dyn_cast_mut(
            self,
        )
    }

    #[cfg(feature = "alloc")]
    fn dyn_cast_boxed(self: Box<Self>) -> Result<Box<C::Target>, Box<C::Source>> {
        <T as DerivedDynCast<ConcreteDynCastConfig<C::Source, C::Target>, C>>::derived_dyn_cast_boxed(self)
    }

    #[cfg(feature = "alloc")]
    fn dyn_cast_rc(self: Rc<Self>) -> Result<Rc<C::Target>, Rc<C::Source>> {
        <T as DerivedDynCast<ConcreteDynCastConfig<C::Source, C::Target>, C>>::derived_dyn_cast_rc(
            self,
        )
    }

    #[cfg(feature = "alloc")]
    fn dyn_cast_arc(self: Arc<Self>) -> Result<Arc<C::Target>, Arc<C::Source>> {
        <T as DerivedDynCast<ConcreteDynCastConfig<C::Source, C::Target>, C>>::derived_dyn_cast_arc(
            self,
        )
    }
}

mod private {
    pub trait Sealed {}
    impl<S: ?Sized, T: ?Sized> Sealed for super::ConcreteDynCastConfig<S, T> {}
}

/// This is an implementation detail for the macros that implement [`DynCast`].
///
/// This trait is a copy of the [`DynCast`] trait with the difference that the
/// config type (`T`) is constrained with a sealed trait so that it must be the
/// [`ConcreteDynCastConfig`] type.
///
/// There is a blanket implementation so that any type that implements this trait
/// also implements [`DynCast`].
///
/// This trait is sometimes implemented by macros instead of the [`DynCast`] trait.
/// This allows implementing [`DynCast`] for traits that have generic type parameters
/// even if the type parameters aren't used by the type that [`DynCast`] is
/// implemented for.
pub trait DerivedDynCast<T: DynCastConfig + private::Sealed, C: DynCastConfig> {
    /// Cast a shared reference of this trait object to another trait object.
    fn derived_dyn_cast_ref(&self) -> Result<&T::Target, &T::Source>;
    /// Cast a mutable/unique reference of this trait object to another trait object.
    fn derived_dyn_cast_mut(&mut self) -> Result<&mut T::Target, &mut T::Source>;

    cfg_with_docs!(feature = "alloc", {
        impl Self {
            /// Cast a boxed trait object to another trait object.
            fn derived_dyn_cast_boxed(self: Box<Self>) -> Result<Box<T::Target>, Box<T::Source>>;
        }
        impl Self {
            /// Cast a reference counted trait object to another trait object.
            fn derived_dyn_cast_rc(self: Rc<Self>) -> Result<Rc<T::Target>, Rc<T::Source>>;
        }
        impl Self {
            /// Cast an atomically reference counted trait object to another trait object.
            fn derived_dyn_cast_arc(self: Arc<Self>) -> Result<Arc<T::Target>, Arc<T::Source>>;
        }
    });
}

/// Cast a trait object (`T::Source`) into a different trait object (`T::Target`).
///
/// This trait is object safe and provides methods to convert from one fat pointer
/// to another. This can be used as a supertrait or via trait bounds to allow
/// casting between two different trait objects. But for usage it is more ergonomic
/// to use the methods that are provided by the [`DynCastExt`] trait than to call
/// the methods on this trait directly.
pub trait DynCast<T: DynCastConfig> {
    /// Cast a shared reference of this trait object to another trait object.
    fn dyn_cast_ref(&self) -> Result<&T::Target, &T::Source>;
    /// Cast a mutable/unique reference of this trait object to another trait object.
    fn dyn_cast_mut(&mut self) -> Result<&mut T::Target, &mut T::Source>;

    cfg_with_docs!(feature = "alloc", {
        impl Self {
            /// Cast a boxed trait object to another trait object.
            fn dyn_cast_boxed(self: Box<Self>) -> Result<Box<T::Target>, Box<T::Source>>;
        }
        impl Self {
            /// Cast a reference counted trait object to another trait object.
            fn dyn_cast_rc(self: Rc<Self>) -> Result<Rc<T::Target>, Rc<T::Source>>;
        }
        impl Self {
            /// Cast an atomically reference counted trait object to another trait object.
            fn dyn_cast_arc(self: Arc<Self>) -> Result<Arc<T::Target>, Arc<T::Source>>;
        }
    });
}

/// Get the [`DynCastConfig`] type used to cast trait `F` to trait `T`.
type GetConfig<F, T> = <F as GetDynCastConfig<T>>::Config;
/// Gets the type that is returned if a cast fails when casting type `A` to the trait `T`.
type GetSource<A, T> = <A as DynCastExtHelper<T>>::Source;
/// Gets the wanted type when casting type `A` to the trait `T`.
type GetTarget<A, T> = <A as DynCastExtHelper<T>>::Target;

/// Simplifies the use of the [`DynCast`] trait by abstracting away the difference
/// between different ways of storing trait objects.
pub trait DynCastExt {
    /// Use this to cast from one trait object type to another.
    ///
    /// The `T` type parameter should be the target trait, not the target type.
    ///
    /// # Examples
    ///
    /// ```
    /// use cast_trait_object::{create_dyn_cast_config, impl_dyn_cast, DynCast, DynCastExt};
    ///
    /// create_dyn_cast_config!(SuperToSubCast = Super => Sub);
    /// trait Super: DynCast<SuperToSubCast> {}
    /// trait Sub: Super {}
    ///
    /// struct Foo;
    /// impl Super for Foo {}
    /// impl Sub for Foo {}
    /// impl_dyn_cast!(Foo as Super => Sub);
    ///
    /// let foo: &dyn Super = &Foo;
    /// // Casting to a sub trait is fallible (the error allows us to keep using the
    /// // `dyn Super` trait object if we want which can be important if we are casting
    /// // movable types like `Box<dyn Trait>`):
    /// let foo: &dyn Sub = foo.dyn_cast().ok().unwrap();
    /// ```
    fn dyn_cast<T: ?Sized>(self) -> Result<Self::Target, Self::Source>
    where
        Self: DynCastExtHelper<T>;

    /// Use this to upcast a trait to one of its supertraits.
    ///
    /// The `T` type parameter should be the wanted supertrait.
    ///
    /// This works by using a cast where both the source and target is the wanted
    /// trait.
    ///
    /// # Examples
    ///
    /// ```
    /// use cast_trait_object::{create_dyn_cast_config, impl_dyn_cast, DynCast, DynCastExt};
    ///
    /// create_dyn_cast_config!(SuperUpcast = Super => Super);
    /// trait Super: DynCast<SuperUpcast> {}
    /// trait Sub: Super {}
    ///
    /// struct Foo;
    /// impl Super for Foo {}
    /// impl Sub for Foo {}
    /// impl_dyn_cast!(Foo as Super => Super);
    ///
    /// let foo: &dyn Sub = &Foo;
    /// // Upcasting to a supertrait is infallible (so we don't need any error handling):
    /// let foo /*: &dyn Super*/ = foo.dyn_upcast::<dyn Super>();
    /// ```
    fn dyn_upcast<T: ?Sized>(self) -> Self::Target
    where
        Self: DynCastExtAdvHelper<T, T, Source = GetAdvTarget<Self, T, T>>;

    /// Use this to cast from one trait object type to another. This method is more
    /// customizable than the [`dyn_cast`](DynCastExt::dyn_cast) method. Here you can also specify the
    /// "source" trait from which the cast is defined. This can for example allow
    /// using casts from a supertrait of the current trait object.
    ///
    /// The `F` Type parameter should be the trait that is returned if the cast
    /// fails.
    /// The `T` type parameter should be the target trait, not the target type.
    ///
    /// # Examples
    ///
    /// ```
    /// use cast_trait_object::{create_dyn_cast_config, impl_dyn_cast, DynCast, DynCastExt};
    ///
    /// create_dyn_cast_config!(SuperToSub1Cast = Super => Sub1);
    /// create_dyn_cast_config!(SuperToSub2Cast = Super => Sub2);
    /// trait Super: DynCast<SuperToSub1Cast> + DynCast<SuperToSub2Cast> {}
    /// trait Sub1: Super {}
    /// trait Sub2: Super {}
    ///
    /// struct Foo;
    /// impl Super for Foo {}
    /// impl Sub1 for Foo {}
    /// impl Sub2 for Foo {}
    /// impl_dyn_cast!(Foo as Super => Sub1, Sub2);
    ///
    /// let foo: &dyn Sub1 = &Foo;
    /// let foo /*: &dyn Sub2 */ = foo.dyn_cast_adv::<dyn Super, dyn Sub2>().ok().unwrap();
    /// ```
    ///
    /// In the above example we need to use [`dyn_cast_adv`](DynCastExt::dyn_cast_adv)
    /// instead of [`dyn_cast`](DynCastExt::dyn_cast) since we don't want to use our
    /// current trait object as the source of the cast, we want to use one of our super
    /// traits. The code `foo.dyn_cast::<dyn Sub2>()` would be the same as
    /// `foo.dyn_cast_adv::<dyn Sub1, dyn Sub2>()` and would fail to compile.
    fn dyn_cast_adv<F: ?Sized, T: ?Sized>(self) -> Result<Self::Target, Self::Source>
    where
        Self: DynCastExtAdvHelper<F, T>;

    /// Use this to cast from one trait object type to another. With this method
    /// the type parameter is a config type that uniquely specifies which cast
    /// should be preformed.
    ///
    /// The `C` type parameter should be the config type that is used to preform
    /// the cast.
    ///
    /// This method can do the same things as the [`dyn_cast_adv`](DynCastExt::dyn_cast_adv)
    /// method but allows specifying the source and target traits via a "config"
    /// type instead of using trait names.
    ///
    /// # Examples
    ///
    /// ```
    /// use cast_trait_object::{create_dyn_cast_config, impl_dyn_cast, DynCast, DynCastExt};
    ///
    /// create_dyn_cast_config!(SuperToSub1Cast = Super => Sub1);
    /// create_dyn_cast_config!(SuperToSub2Cast = Super => Sub2);
    /// trait Super: DynCast<SuperToSub1Cast> + DynCast<SuperToSub2Cast> {}
    /// trait Sub1: Super {}
    /// trait Sub2: Super {}
    ///
    /// struct Foo;
    /// impl Super for Foo {}
    /// impl Sub1 for Foo {}
    /// impl Sub2 for Foo {}
    /// impl_dyn_cast!(Foo as Super => Sub1, Sub2);
    ///
    /// let foo: &dyn Sub1 = &Foo;
    /// let foo /*: &dyn Sub2 */ = foo.dyn_cast_with_config::<SuperToSub2Cast>().ok().unwrap();
    /// ```
    fn dyn_cast_with_config<C: DynCastConfig>(self) -> Result<Self::Target, Self::Source>
    where
        Self: DynCastExtAdvHelper<C::Source, C::Target>;
}
impl<A> DynCastExt for A {
    fn dyn_cast<T: ?Sized>(self) -> Result<GetTarget<Self, T>, GetSource<Self, T>>
    where
        Self: DynCastExtHelper<T>,
    {
        self._dyn_cast()
    }
    fn dyn_upcast<T: ?Sized>(self) -> GetAdvTarget<Self, T, T>
    where
        Self: DynCastExtAdvHelper<T, T, Source = GetAdvTarget<Self, T, T>>,
    {
        match self._dyn_cast() {
            Ok(v) => v,
            Err(e) => e,
        }
    }
    fn dyn_cast_adv<F: ?Sized, T: ?Sized>(self) -> GetAdvCastResult<Self, F, T>
    where
        Self: DynCastExtAdvHelper<F, T>,
    {
        self._dyn_cast()
    }
    fn dyn_cast_with_config<C: DynCastConfig>(self) -> GetAdvCastResult<Self, C::Source, C::Target>
    where
        Self: DynCastExtAdvHelper<C::Source, C::Target>,
    {
        self._dyn_cast()
    }
}

/// Used to implement [`DynCastExt`].
pub trait DynCastExtHelper<T: ?Sized> {
    /// The wanted trait object that is returned if the cast succeeded.
    type Target;
    /// The original trait object that is returned if the cast failed.
    type Source;
    /// The [`DynCastConfig`] that is used to preform the conversion.
    type Config;

    /// This method is used to cast from one trait object type to another.
    fn _dyn_cast(self) -> Result<Self::Target, Self::Source>;
}
impl<'a, T, F> DynCastExtHelper<T> for &'a F
where
    T: ?Sized + 'static,
    F: ?Sized + 'static + DynCast<GetConfig<F, T>> + GetDynCastConfig<T>,
{
    type Target = &'a T;
    type Source = &'a F;
    type Config = GetConfig<F, T>;

    fn _dyn_cast(self) -> Result<Self::Target, Self::Source> {
        DynCast::dyn_cast_ref(self)
    }
}
impl<'a, T, F> DynCastExtHelper<T> for &'a mut F
where
    T: ?Sized + 'static,
    F: ?Sized + 'static + DynCast<GetConfig<F, T>> + GetDynCastConfig<T>,
{
    type Target = &'a mut T;
    type Source = &'a mut F;
    type Config = GetConfig<F, T>;

    fn _dyn_cast(self) -> Result<Self::Target, Self::Source> {
        DynCast::dyn_cast_mut(self)
    }
}
cfg_with_docs!(
    feature = "alloc",
    {
        impl<'a, T, F> DynCastExtHelper<T> for Box<F>
        where
            T: ?Sized + 'static,
            F: ?Sized + 'static + DynCast<GetConfig<F, T>> + GetDynCastConfig<T>,
        {
            type Target = Box<T>;
            type Source = Box<F>;
            type Config = GetConfig<F, T>;

            fn _dyn_cast(self) -> Result<Self::Target, Self::Source> {
                DynCast::dyn_cast_boxed(self)
            }
        }
    },
    {
        impl<'a, T, F> DynCastExtHelper<T> for Rc<F>
        where
            T: ?Sized + 'static,
            F: ?Sized + 'static + DynCast<GetConfig<F, T>> + GetDynCastConfig<T>,
        {
            type Target = Rc<T>;
            type Source = Rc<F>;
            type Config = GetConfig<F, T>;

            fn _dyn_cast(self) -> Result<Self::Target, Self::Source> {
                DynCast::dyn_cast_rc(self)
            }
        }
    },
    {
        impl<'a, T, F> DynCastExtHelper<T> for Arc<F>
        where
            T: ?Sized + 'static,
            F: ?Sized + 'static + DynCast<GetConfig<F, T>> + GetDynCastConfig<T>,
        {
            type Target = Arc<T>;
            type Source = Arc<F>;
            type Config = GetConfig<F, T>;

            fn _dyn_cast(self) -> Result<Self::Target, Self::Source> {
                DynCast::dyn_cast_arc(self)
            }
        }
    }
);

/// Gets the type that is returned if a cast fails when casting type `A` to the trait `T`.
type GetAdvSource<A, F, T> = <A as DynCastExtAdvHelper<F, T>>::Source;
/// Gets the wanted type when casting type `A` to the trait `T`.
type GetAdvTarget<A, F, T> = <A as DynCastExtAdvHelper<F, T>>::Target;
type GetAdvCastResult<A, F, T> = Result<GetAdvTarget<A, F, T>, GetAdvSource<A, F, T>>;

/// Used to implement [`DynCastExt`].
pub trait DynCastExtAdvHelper<F: ?Sized, T: ?Sized> {
    /// The wanted trait object that is returned if the cast succeeded.
    type Target;
    /// The original trait object that is returned if the cast failed.
    type Source;

    /// This method is used to cast from one trait object type to another.
    fn _dyn_cast(self) -> Result<Self::Target, Self::Source>;
}
impl<'a, T, F, A> DynCastExtAdvHelper<F, T> for &'a A
where
    T: ?Sized + 'static,
    F: ?Sized + 'static + GetDynCastConfig<T>,
    A: ?Sized + 'static + DynCast<GetConfig<F, T>>,
{
    type Target = &'a T;
    type Source = &'a F;

    fn _dyn_cast(self) -> Result<Self::Target, Self::Source> {
        DynCast::dyn_cast_ref(self)
    }
}
impl<'a, T, F, A> DynCastExtAdvHelper<F, T> for &'a mut A
where
    T: ?Sized + 'static,
    F: ?Sized + 'static + GetDynCastConfig<T>,
    A: ?Sized + 'static + DynCast<GetConfig<F, T>>,
{
    type Target = &'a mut T;
    type Source = &'a mut F;

    fn _dyn_cast(self) -> Result<Self::Target, Self::Source> {
        DynCast::dyn_cast_mut(self)
    }
}
cfg_with_docs!(
    feature = "alloc",
    {
        impl<'a, T, F, A> DynCastExtAdvHelper<F, T> for Box<A>
        where
            T: ?Sized + 'static,
            F: ?Sized + 'static + GetDynCastConfig<T>,
            A: ?Sized + 'static + DynCast<GetConfig<F, T>>,
        {
            type Target = Box<T>;
            type Source = Box<F>;

            fn _dyn_cast(self) -> Result<Self::Target, Self::Source> {
                DynCast::dyn_cast_boxed(self)
            }
        }
    },
    {
        impl<'a, T, F, A> DynCastExtAdvHelper<F, T> for Rc<A>
        where
            T: ?Sized + 'static,
            F: ?Sized + 'static + GetDynCastConfig<T>,
            A: ?Sized + 'static + DynCast<GetConfig<F, T>>,
        {
            type Target = Rc<T>;
            type Source = Rc<F>;

            fn _dyn_cast(self) -> Result<Self::Target, Self::Source> {
                DynCast::dyn_cast_rc(self)
            }
        }
    },
    {
        impl<'a, T, F, A> DynCastExtAdvHelper<F, T> for Arc<A>
        where
            T: ?Sized + 'static,
            F: ?Sized + 'static + GetDynCastConfig<T>,
            A: ?Sized + 'static + DynCast<GetConfig<F, T>>,
        {
            type Target = Arc<T>;
            type Source = Arc<F>;

            fn _dyn_cast(self) -> Result<Self::Target, Self::Source> {
                DynCast::dyn_cast_arc(self)
            }
        }
    }
);

/// Not public API.
///
/// This wrapper helps the [`impl_dyn_cast`] macro to implement the
/// [`DynCast`] trait.
///
/// Uses "Autoref-based stable specialization", see
/// https://github.com/dtolnay/case-studies/tree/master/autoref-specialization
/// for more information about how it works.
#[allow(non_camel_case_types, missing_debug_implementations)]
#[doc(hidden)]
pub struct __impl_dyn_cast_wrapper<D, C, T>
where
    C: ?::core::marker::Sized,
{
    _deref_id: [D; 0],
    config_type: ::core::marker::PhantomData<C>,
    self_type: ::core::marker::PhantomData<T>,
}
// 1. First we create an instance which contains information about our type:
#[doc(hidden)]
#[allow(missing_docs)]
impl __impl_dyn_cast_wrapper<(), (), ()> {
    #[allow(clippy::new_ret_no_self)]
    pub fn new<C, T>() -> __impl_dyn_cast_wrapper<[(); 0], C, T> {
        __impl_dyn_cast_wrapper {
            _deref_id: [],
            config_type: ::core::marker::PhantomData,
            self_type: ::core::marker::PhantomData,
        }
    }
}
// 2. Then we try to call the `cast` method on it.
//
/// The implementation for when a trait is NOT implemented for a type.
#[doc(hidden)]
#[allow(missing_docs)]
impl<__ConfigType, __SelfType> __impl_dyn_cast_wrapper<[(); 0], __ConfigType, __SelfType>
where
    __ConfigType: DynCastConfigTargetTest<__SelfType> + ?::core::marker::Sized,
{
    // If this name conflicts with a blanket trait in scope then the macro might
    // not work correctly.
    pub fn __dyn_cast_macro_deref_specialization<T, U, E, F: FnOnce(T) -> U>(
        &self,
        value: T,
        f: F,
    ) -> Result<U, E> {
        Ok(f(value))
    }
}
// 3. If a method doesn't exist (or trait bounds make it so that it can't be used)
// then the compiler will deref a value and restart its work of finding a method
// with the specified name.
#[doc(hidden)]
impl<C, T> ::core::ops::Deref for __impl_dyn_cast_wrapper<[(); 0], C, T> {
    type Target = __impl_dyn_cast_wrapper<[(); 1], C, T>;
    fn deref(&self) -> &Self::Target {
        // static promotion will make this a `static` since it is a const value:
        &__impl_dyn_cast_wrapper {
            _deref_id: [],
            config_type: ::core::marker::PhantomData,
            self_type: ::core::marker::PhantomData,
        }
    }
}
// 4. This method is implemented for all types so the compiler should call
// it if the previous, more specific, method can't be used.
//
/// The implementation for when a trait is implemented. We could require more from
/// the type via more strict trait bounds in the where clauses.
#[doc(hidden)]
#[allow(missing_docs)]
impl<C, __SelfType> __impl_dyn_cast_wrapper<[(); 1], C, __SelfType>
where
    C: ?::core::marker::Sized,
{
    pub fn __dyn_cast_macro_deref_specialization<T, U, E, F: FnOnce(T) -> E>(
        &self,
        value: T,
        f: F,
    ) -> Result<U, E> {
        Err(f(value))
    }
}

/// Implement the [`DynCast`] trait for a type to cast from a specific trait object
/// to a specified different trait object.
//
// The non alloc version of the macro differs in that it doesn't include
// `extern alloc` and the methods that cast to Box, Rc and Arc.
// To update this macro just copy the alloc version of the macro and remove those
// things.
#[cfg(not(feature = "alloc"))]
#[macro_export]
macro_rules! impl_dyn_cast {
    // Impl `DynCast` for a type to cast it from a source trait to a target trait.
    (
        // Declare generic lifetimes and type parameters
        for<$($lifetime:lifetime),* $($generics:ident),* $(,)?>
        // Path to self type:
        $self_type:ty
        as
        // Path to the source trait we are casting from:
        $source_trait:path
        // Where clause:
        $(where { $($where:tt)* })?
        =>
        // Path to config type:
        $target_trait:path
    ) => {
        const _: fn() = || {
            impl< $($lifetime,)* $($generics,)* >
            $crate::DerivedDynCast<
                $crate::ConcreteDynCastConfig<
                    dyn $source_trait,
                    dyn $target_trait
                >,
                <dyn $source_trait as $crate::GetDynCastConfig<dyn $target_trait>>::Config
            >
            for
            $self_type
            $(
            where
                $($where)*
            )?
            {
                fn derived_dyn_cast_ref(
                    &self,
                ) -> ::core::result::Result<
                    &(dyn $target_trait + 'static),
                    &(dyn $source_trait + 'static),
                > {
                    $crate::__impl_dyn_cast_wrapper::new::<
                        <dyn $source_trait as $crate::GetDynCastConfig<dyn $target_trait>>::Config,
                        $self_type
                    >()
                    .__dyn_cast_macro_deref_specialization::<
                        _,
                        &dyn $target_trait,
                        &dyn $source_trait,
                        _,
                    >(self, |v| v)
                }

                fn derived_dyn_cast_mut(
                    &mut self,
                ) -> ::core::result::Result<
                    &mut (dyn $target_trait + 'static),
                    &mut (dyn $source_trait + 'static),
                > {
                    $crate::__impl_dyn_cast_wrapper::new::<
                        <dyn $source_trait as $crate::GetDynCastConfig<dyn $target_trait>>::Config,
                        $self_type
                    >()
                    .__dyn_cast_macro_deref_specialization::<
                        _,
                        &mut dyn $target_trait,
                        &mut dyn $source_trait,
                        _,
                    >(self, |v| v)
                }
            }
        };
    };
    // Impl `DynCast` for a type for a specified "config" type.
    (
        // Declare generic lifetimes and type parameters
        for<$($lifetime:lifetime),* $($generics:ident),* $(,)?>
        // Path to self type:
        $self_type:ty
        // Where clause:
        $(where { $($where:tt)* })?
        =>
        // Path to config type:
        $config_type:ty
    ) => {
        const _: fn() = || {
            impl< $($lifetime,)* $($generics,)* >
            $crate::DynCast<  $config_type  >
            for
            $self_type
            $(
            where
                $($where)*
            )?
            {
                fn dyn_cast_ref(
                    &self,
                ) -> ::core::result::Result<
                    &<$config_type as $crate::DynCastConfig>::Target,
                    &<$config_type as $crate::DynCastConfig>::Source,
                > {
                    $crate::__impl_dyn_cast_wrapper::new::<
                        $config_type,
                        $self_type
                    >()
                    .__dyn_cast_macro_deref_specialization::<
                        _,
                        &<$config_type as $crate::DynCastConfig>::Target,
                        &<$config_type as $crate::DynCastConfig>::Source,
                        _,
                    >(self, |v| v)
                }

                fn dyn_cast_mut(
                    &mut self,
                ) -> ::core::result::Result<
                    &mut <$config_type as $crate::DynCastConfig>::Target,
                    &mut <$config_type as $crate::DynCastConfig>::Source,
                > {
                    $crate::__impl_dyn_cast_wrapper::new::<
                        $config_type,
                        $self_type
                    >()
                    .__dyn_cast_macro_deref_specialization::<
                        _,
                        &mut <$config_type as $crate::DynCastConfig>::Target,
                        &mut <$config_type as $crate::DynCastConfig>::Source,
                        _,
                    >(self, |v| v)
                }
            }
        };
    };
    // Non generic arm that allows several casts to be defined from a single source trait to different
    // target traits.
    ($self_type:ty as $source_trait:path => $($target_trait:path),*) => {
        $crate::impl_dyn_cast! {
            $self_type => $(<dyn $source_trait + 'static as $crate::GetDynCastConfig<dyn $target_trait + 'static>>::Config),*
        }
    };
    // Non generic arm that allows several casts to be defined by naming the config types that should
    // be supported.
    ($self_type:ty => $($config_type:ty),*) => {
        $(
            const _: fn() = || {
                type __SelfType = $self_type;
                type __ConfigType = $config_type;
                $crate::impl_dyn_cast!(for<> __SelfType => __ConfigType);
            };
        )*
    };
}

/// Implement the [`DynCast`] trait for a type to cast from a specific trait object
/// to a specified different trait object.
#[cfg(feature = "alloc")]
#[macro_export]
macro_rules! impl_dyn_cast {
    // Impl `DynCast` for a type to cast it from a source trait to a target trait.
    (
        // Declare generic lifetimes and type parameters
        for<$($lifetime:lifetime),* $($generics:ident),* $(,)?>
        // Path to self type:
        $self_type:ty
        as
        // Path to the source trait we are casting from:
        $source_trait:path
        // Where clause:
        $(where { $($where:tt)* })?
        =>
        // Path to config type:
        $target_trait:path
    ) => {
        const _: fn() = || {
            extern crate alloc;


            impl< $($lifetime,)* $($generics,)* >
            $crate::DerivedDynCast<
                $crate::ConcreteDynCastConfig<
                    dyn $source_trait,
                    dyn $target_trait
                >,
                <dyn $source_trait as $crate::GetDynCastConfig<dyn $target_trait>>::Config
            >
            for
            $self_type
            $(
            where
                $($where)*
            )?
            {
                fn derived_dyn_cast_ref(
                    &self,
                ) -> ::core::result::Result<
                    &(dyn $target_trait + 'static),
                    &(dyn $source_trait + 'static),
                > {
                    $crate::__impl_dyn_cast_wrapper::new::<
                        <dyn $source_trait as $crate::GetDynCastConfig<dyn $target_trait>>::Config,
                        $self_type
                    >()
                    .__dyn_cast_macro_deref_specialization::<
                        _,
                        &dyn $target_trait,
                        &dyn $source_trait,
                        _,
                    >(self, |v| v)
                }

                fn derived_dyn_cast_mut(
                    &mut self,
                ) -> ::core::result::Result<
                    &mut (dyn $target_trait + 'static),
                    &mut (dyn $source_trait + 'static),
                > {
                    $crate::__impl_dyn_cast_wrapper::new::<
                        <dyn $source_trait as $crate::GetDynCastConfig<dyn $target_trait>>::Config,
                        $self_type
                    >()
                    .__dyn_cast_macro_deref_specialization::<
                        _,
                        &mut dyn $target_trait,
                        &mut dyn $source_trait,
                        _,
                    >(self, |v| v)
                }

                fn derived_dyn_cast_boxed(
                    self: alloc::boxed::Box<Self>,
                ) -> ::core::result::Result<
                    alloc::boxed::Box<dyn $target_trait>,
                    alloc::boxed::Box<dyn $source_trait>,
                > {
                    $crate::__impl_dyn_cast_wrapper::new::<
                        <dyn $source_trait as $crate::GetDynCastConfig<dyn $target_trait>>::Config,
                        $self_type
                    >()
                    .__dyn_cast_macro_deref_specialization::<
                        _,
                        alloc::boxed::Box<dyn $target_trait>,
                        alloc::boxed::Box<dyn $source_trait>,
                        _,
                    >(self, |v| v)
                }

                fn derived_dyn_cast_rc(
                    self: alloc::rc::Rc<Self>,
                ) -> ::core::result::Result<
                    alloc::rc::Rc<dyn $target_trait>,
                    alloc::rc::Rc<dyn $source_trait>,
                > {
                    $crate::__impl_dyn_cast_wrapper::new::<
                        <dyn $source_trait as $crate::GetDynCastConfig<dyn $target_trait>>::Config,
                        $self_type
                    >()
                    .__dyn_cast_macro_deref_specialization::<
                        _,
                        alloc::rc::Rc<dyn $target_trait>,
                        alloc::rc::Rc<dyn $source_trait>,
                        _,
                    >(self, |v| v)
                }

                fn derived_dyn_cast_arc(
                    self: alloc::sync::Arc<Self>,
                ) -> ::core::result::Result<
                    alloc::sync::Arc<dyn $target_trait>,
                    alloc::sync::Arc<dyn $source_trait>,
                > {
                    $crate::__impl_dyn_cast_wrapper::new::<
                        <dyn $source_trait as $crate::GetDynCastConfig<dyn $target_trait>>::Config,
                        $self_type
                    >()
                    .__dyn_cast_macro_deref_specialization::<
                        _,
                        alloc::sync::Arc<dyn $target_trait>,
                        alloc::sync::Arc<dyn $source_trait>,
                        _,
                    >(self, |v| v)
                }
            }
        };
    };
    // Impl `DynCast` for a type for a specified "config" type.
    (
        // Declare generic lifetimes and type parameters
        for<$($lifetime:lifetime),* $($generics:ident),* $(,)?>
        // Path to self type:
        $self_type:ty
        // Where clause:
        $(where { $($where:tt)* })?
        =>
        // Path to config type:
        $config_type:ty
    ) => {
        const _: fn() = || {
            extern crate alloc;


            impl< $($lifetime,)* $($generics,)* >
            $crate::DynCast<  $config_type  >
            for
            $self_type
            $(
            where
                $($where)*
            )?
            {
                fn dyn_cast_ref(
                    &self,
                ) -> ::core::result::Result<
                    &<$config_type as $crate::DynCastConfig>::Target,
                    &<$config_type as $crate::DynCastConfig>::Source,
                > {
                    $crate::__impl_dyn_cast_wrapper::new::<
                        $config_type,
                        $self_type
                    >()
                    .__dyn_cast_macro_deref_specialization::<
                        _,
                        &<$config_type as $crate::DynCastConfig>::Target,
                        &<$config_type as $crate::DynCastConfig>::Source,
                        _,
                    >(self, |v| v)
                }

                fn dyn_cast_mut(
                    &mut self,
                ) -> ::core::result::Result<
                    &mut <$config_type as $crate::DynCastConfig>::Target,
                    &mut <$config_type as $crate::DynCastConfig>::Source,
                > {
                    $crate::__impl_dyn_cast_wrapper::new::<
                        $config_type,
                        $self_type
                    >()
                    .__dyn_cast_macro_deref_specialization::<
                        _,
                        &mut <$config_type as $crate::DynCastConfig>::Target,
                        &mut <$config_type as $crate::DynCastConfig>::Source,
                        _,
                    >(self, |v| v)
                }

                fn dyn_cast_boxed(
                    self: alloc::boxed::Box<Self>,
                ) -> ::core::result::Result<
                    alloc::boxed::Box<<$config_type as $crate::DynCastConfig>::Target>,
                    alloc::boxed::Box<<$config_type as $crate::DynCastConfig>::Source>,
                > {
                    $crate::__impl_dyn_cast_wrapper::new::<
                        $config_type,
                        $self_type
                    >()
                    .__dyn_cast_macro_deref_specialization::<
                        _,
                        alloc::boxed::Box<<$config_type as $crate::DynCastConfig>::Target>,
                        alloc::boxed::Box<<$config_type as $crate::DynCastConfig>::Source>,
                        _,
                    >(self, |v| v)
                }

                fn dyn_cast_rc(
                    self: alloc::rc::Rc<Self>,
                ) -> ::core::result::Result<
                    alloc::rc::Rc<<$config_type as $crate::DynCastConfig>::Target>,
                    alloc::rc::Rc<<$config_type as $crate::DynCastConfig>::Source>,
                > {
                    $crate::__impl_dyn_cast_wrapper::new::<
                        $config_type,
                        $self_type
                    >()
                    .__dyn_cast_macro_deref_specialization::<
                        _,
                        alloc::rc::Rc<<$config_type as $crate::DynCastConfig>::Target>,
                        alloc::rc::Rc<<$config_type as $crate::DynCastConfig>::Source>,
                        _,
                    >(self, |v| v)
                }

                fn dyn_cast_arc(
                    self: alloc::sync::Arc<Self>,
                ) -> ::core::result::Result<
                    alloc::sync::Arc<<$config_type as $crate::DynCastConfig>::Target>,
                    alloc::sync::Arc<<$config_type as $crate::DynCastConfig>::Source>,
                > {
                    $crate::__impl_dyn_cast_wrapper::new::<
                        $config_type,
                        $self_type
                    >()
                    .__dyn_cast_macro_deref_specialization::<
                        _,
                        alloc::sync::Arc<<$config_type as $crate::DynCastConfig>::Target>,
                        alloc::sync::Arc<<$config_type as $crate::DynCastConfig>::Source>,
                        _,
                    >(self, |v| v)
                }
            }
        };
    };
    // Non generic arm that allows several casts to be defined from a single source trait to different
    // target traits.
    ($self_type:ty as $source_trait:path => $($target_trait:path),*) => {
        $crate::impl_dyn_cast! {
            $self_type => $(<dyn $source_trait + 'static as $crate::GetDynCastConfig<dyn $target_trait + 'static>>::Config),*
        }
    };
    // Non generic arm that allows several casts to be defined by naming the config types that should
    // be supported.
    ($self_type:ty => $($config_type:ty),*) => {
        $(
            const _: fn() = || {
                type __SelfType = $self_type;
                type __ConfigType = $config_type;
                $crate::impl_dyn_cast!(for<> __SelfType => __ConfigType);
            };
        )*
    };
}

/// Create a new config type that implements [`DynCastConfig`]. If you need more
/// control over the generated config type then use the [`impl_dyn_cast_config`]
/// macro instead.
#[macro_export]
macro_rules! create_dyn_cast_config {
    (
        $(#[$attr:meta])*
        $config_vis:vis
        $config_name:ident
        // Any generic arguments for the config type:
        <  $($lifetime:lifetime),* $($generics:ident),* $(,)?  >
        // Where clause:
        $(where { $($where:tt)* })?
        =
        // Path to source trait:
        $source_trait:path
        =>
        // Path to target trait:
        $target_trait:path
    ) => {
        $(#[$attr])*
        $config_vis struct $config_name< $($lifetime,)* $($generics,)* >(
            $(::core::marker::PhantomData<& $lifetime ()>,)*
            $(::core::marker::PhantomData<$generics>,)*
        ) $(where $($where)* )?;

        $crate::impl_dyn_cast_config!(
            for<$($lifetime,)* $($generics,)*>
            $config_name<$($lifetime,)* $($generics,)*>
            $(where {$($where)*} )?
            =
            $source_trait
            =>
            $target_trait
        );
    };
    ($(#[$attr:meta])* $config_vis:vis $config_name:ident = $source_trait:path => $target_trait:path) => {
        $(#[$attr])*
        $config_vis struct $config_name;
        $crate::impl_dyn_cast_config!($config_name = $source_trait => $target_trait);
    };
}

/// Implements [`DynCastConfig`], [`DynCastConfigTargetTest`] and
/// [`GetDynCastConfig`] for a config type.
#[macro_export]
macro_rules! impl_dyn_cast_config {
    (
        // Declare generic lifetimes and type parameters
        for<$($lifetime:lifetime),* $($generics:ident),* $(,)?>
        // Path to config type:
        $config_type:path
        // Where clause:
        $(where { $($where:tt)* })?
        =
        // Path to source trait:
        $source_trait:path
        =>
        // Path to target trait:
        $target_trait:path
    ) => {
        const _: fn() = || {
            impl< $($lifetime,)* $($generics,)* >
            $crate::DynCastConfig
            for
            $config_type
            $(where $($where)*)?
            {
                type Target = dyn $target_trait;
                type Source = dyn $source_trait;
            }

            impl< $($lifetime,)* $($generics,)*  __T>
            $crate::DynCastConfigTargetTest<__T>
            for
            $config_type
            where
                __T: ?::core::marker::Sized + $target_trait,
                $($($where)*)?
            {}

            impl< $($lifetime,)* $($generics,)* >
            $crate::GetDynCastConfig<dyn $target_trait>
            for
            dyn $source_trait
            $(where $($where)*)?
            {
                type Config = $config_type;
            }
        };
    };
    ($config_type:ty = $source_trait:path => $target_trait:path) => {
        const _: fn() = || {
            type __ConfigType = $config_type;
            $crate::impl_dyn_cast_config!(for<> __ConfigType = $source_trait => $target_trait);
        };
    };
}

#[cfg(test)]
mod tests {
    create_dyn_cast_config!(
        /// Can have attributes on the generated config struct.
        #[derive(Clone)]
        UpcastConfig = Super => Super
    );
    create_dyn_cast_config!(
        /// Can have attributes on the generated config struct.
        #[derive(Clone)]
        SuperConfig = Super => Sub
    );
    trait Super: super::DynCast<SuperConfig> + super::DynCast<UpcastConfig> {}
    trait Sub: Super {}

    struct TestSuper;
    impl Super for TestSuper {}
    impl_dyn_cast!(TestSuper => SuperConfig, UpcastConfig);

    struct TestSub;
    impl Super for TestSub {}
    impl Sub for TestSub {}
    impl_dyn_cast! {TestSub as Super => Sub, Super}

    // Implement using both `Source => Target` and `=> ConfigType` syntax.
    struct TestSubMixed;
    impl Super for TestSubMixed {}
    impl Sub for TestSubMixed {}
    impl_dyn_cast! {TestSubMixed as Super => Sub}
    impl_dyn_cast! {TestSubMixed => UpcastConfig}

    /// Check so that dyn_cast correctly emits code on error (this ensures better
    /// error messages)
    #[allow(dead_code)]
    fn check_fallback() {
        struct T;
        impl T {
            // #[crate::dyn_cast]
            fn test(self) {}
        }
        // This line should not emit an error even if the attribute is used:
        T.test();
    }

    struct TestGeneric<T>(T);
    impl<T: 'static> Super for TestGeneric<T> {}
    impl<T: 'static> Sub for TestGeneric<T> {}
    impl_dyn_cast!(for<T> TestGeneric<T> as Super where {T: 'static} => Sub);
    impl_dyn_cast!(for<T> TestGeneric<T> as Super where {T: 'static} => Super);

    // Implement using both `Source => Target` and `=> ConfigType` syntax.
    struct TestGenericMixed<T>(T);
    impl<T: 'static> Super for TestGenericMixed<T> {}
    impl<T: 'static> Sub for TestGenericMixed<T> {}
    impl_dyn_cast!(for<T> TestGenericMixed<T> as Super where {T: 'static} => Sub);
    impl_dyn_cast!(for<T> TestGenericMixed<T> where {T: 'static} => UpcastConfig);

    /// Only implements `Sub` for types that implement `Display`.
    struct OnlyDisplayGeneric<T>(T);
    impl<T: 'static> Super for OnlyDisplayGeneric<T> {}
    impl<T: core::fmt::Display + 'static> Sub for OnlyDisplayGeneric<T> {}
    // Since this can only implement the cast as successful or not, it will always fail.
    impl_dyn_cast!(for<T> OnlyDisplayGeneric<T> as Super where {T: 'static} => Sub);
    impl_dyn_cast!(for<T> OnlyDisplayGeneric<T> as Super where {T: 'static} => Super);

    #[test]
    fn generic_impl() {
        use super::DynCastExt;

        // Generic cast works:
        let a: &dyn Super = &TestGeneric(());
        assert!(a.dyn_cast::<dyn Sub>().is_ok());

        // This type implements `Sub` when the wrapped type implements
        // `Display`:
        let only_display: &dyn Super = &OnlyDisplayGeneric("");
        // &str does implement Display:
        let _is_display: &dyn core::fmt::Display = &"";
        // But the cast will still fail:
        assert!(only_display.dyn_cast::<dyn Sub>().is_err());

        // This means that we can perform an upcast and then fail to downcast:
        let b: &dyn Sub = &OnlyDisplayGeneric("");
        let b: &dyn Super = b.dyn_upcast();
        assert!(b.dyn_cast::<dyn Sub>().is_err());
    }

    mod generic_traits {
        trait Super<T>: crate::DynCast<SuperConfig<T, T>> {}
        trait Sub<T>: Super<T> {}

        create_dyn_cast_config!(
            /// Can have attributes on the generated config struct.
            #[derive(Clone)]
            SuperConfig<T, U> = Super<T> => Sub<U>
        );

        impl<T> Super<T> for () {}
        impl_dyn_cast!(for<T> () => SuperConfig<T, T>);

        struct TestSuper;
        impl<T> Super<T> for TestSuper {}
        impl_dyn_cast!(for<T> TestSuper => SuperConfig<T, T>);

        struct TestSub;
        impl<T: core::fmt::Display> Super<T> for TestSub {}
        impl<T: core::fmt::Display> Sub<T> for TestSub {}
        impl_dyn_cast! {for<T> TestSub as Super<T> where {T: core::fmt::Display} => Sub<T>}
    }

    /// Check that it is possible to cast into a trait object that has generic
    /// type parameters.
    ///
    /// This is indeed possible!
    #[test]
    fn cast_to_generic_trait_object() {
        trait SourceTrait<T> {
            fn cast(&self) -> &dyn TargetTrait<T>;
        }
        trait TargetTrait<T> {}

        impl<T> SourceTrait<T> for () {
            fn cast(&self) -> &dyn TargetTrait<T> {
                self
            }
        }
        impl<T> TargetTrait<T> for () {}

        let a: &dyn SourceTrait<u32> = &();
        let _b: &dyn TargetTrait<u32> = a.cast();
    }

    #[cfg(feature = "proc-macros")]
    #[allow(dead_code)]
    pub mod with_macros {
        use crate::*;

        #[dyn_cast(Sub)]
        #[dyn_upcast]
        trait Super {}
        trait Sub: Super {}

        #[dyn_cast(Super => Sub)]
        #[dyn_upcast(Super)]
        struct TestSuper;
        impl Super for TestSuper {}

        #[dyn_cast(Super => Sub)]
        #[dyn_upcast(Super)]
        struct TestSub;
        impl Super for TestSub {}
        impl Sub for TestSub {}

        pub mod generic_traits {
            use crate::*;

            #[dyn_upcast]
            #[dyn_cast(Sub<T>)]
            trait Super<T> {}
            trait Sub<T>: Super<T> {}

            #[dyn_cast(Sub<T>)]
            #[dyn_upcast]
            impl<T> Super<T> for (i32,) {}
            impl<T> Sub<T> for (i32,) {}

            struct TestSuper;
            #[dyn_upcast]
            #[dyn_cast(Sub<T>)]
            impl<T: Clone> Super<T> for TestSuper where T: core::fmt::Display {}

            struct TestSub;
            #[dyn_upcast]
            #[dyn_cast(Sub<T>)]
            impl<T> Super<T> for TestSub {}
            impl<T> Sub<T> for TestSub {}
        }
    }
}
