//! `Kind` and `InferableBrand` traits for higher-kinded type simulation.
//!
//! Each [`trait_kind!`](fp_macros::trait_kind) invocation generates a pair of traits:
//!
//! 1. A **`Kind_{hash}`** trait implemented by [`Brand` types][crate::brands] to map
//!    from brands to concrete types (the forward mapping).
//! 2. An **`InferableBrand_{hash}`** trait implemented by concrete types to map back
//!    to their canonical brand (the reverse mapping), enabling brand inference.
//!
//! Both traits share the same deterministic content hash derived from the signature.
//!
//! This is an implementation of the type-level defunctionalisation technique
//! to simulate higher-kinded types, based on Yallop and White's [Lightweight higher-kinded polymorphism](https://www.cl.cam.ac.uk/~jdy22/papers/lightweight-higher-kinded-polymorphism.pdf).
//!
//! # `Kind` Traits
//!
//! Traits representing type-level application (brand -> concrete type).
//!
//! The naming convention is `Kind_{hash}` where `{hash}` is a deterministic
//! 64-bit hash of the canonical signature. The canonical signature includes:
//! * Number of lifetimes and types.
//! * Type bounds (with full path preservation and generic arguments).
//! * Output bounds on the associated types.
//!
//! This naming scheme ensures that semantically equivalent signatures always map to the
//! same `Kind` trait, regardless of parameter names or formatting.
//!
//! # `InferableBrand` Traits
//!
//! Traits providing the reverse mapping (concrete type -> brand) for brand inference.
//!
//! Each `InferableBrand_{hash}` trait has:
//! * An associated `type Brand: Kind_{hash}` identifying the canonical brand.
//! * A `#[diagnostic::on_unimplemented]` attribute for actionable error messages.
//! * A blanket `impl for &T` enabling inference for borrowed containers.
//!
//! Only types with a single unambiguous brand at a given arity implement the
//! corresponding `InferableBrand` trait. Types with multiple brands (e.g.,
//! `Result` at arity 1) do not, and require `explicit::` function variants.
//! `InferableBrand` impls are auto-generated by [`impl_kind!`](fp_macros::impl_kind)
//! unless `#[no_inferable_brand]` is specified.
//!
//! # Trait Name Examples
//!
//! | Hash | Signature | Used by |
//! |------|-----------|---------|
//! | `ad6c20556a82a1f0` | `type Of<A>;` | Simple type constructors |
//! | `cdc7cd43dac7585f` | `type Of<'a, A: 'a>: 'a;` | Most functor/monad types |
//! | `5b1bcedfd80bdc16` | `type Of<A, B>;` | Bifunctor brands (no lifetime) |
//! | `266801a817966495` | `type Of<'a, A: 'a, B: 'a>: 'a;` | Bifunctor brands (with lifetime) |
//!
//! For each hash, both `Kind_{hash}` and `InferableBrand_{hash}` exist. For example,
//! `OptionBrand` implements `Kind_cdc7cd43dac7585f`, and `Option<A>` implements
//! `InferableBrand_cdc7cd43dac7585f` with `type Brand = OptionBrand`.

use fp_macros::trait_kind;

trait_kind! {
	/// The applied type.
	type Of<A>;
}

trait_kind! {
	/// The applied type.
	type Of<'a>;
}

trait_kind! {
	/// The applied type.
	type Of<'a, A>;
}

trait_kind! {
	/// The applied type.
	type Of<'a, A: 'a>: 'a;
}

trait_kind! {
	/// The applied type.
	type Of<A, B>;
}

trait_kind! {
	/// The applied type.
	type Of<'a, A, B>;
}

trait_kind! {
	/// The applied type.
	type Of<'a, A, B>: 'a;
}

trait_kind! {
	/// The applied type.
	type Of<'a, A: 'a, B: 'a>: 'a;
}
