ty-tag 0.1.0

TypeId for lifetime containing types via type tags.
Documentation

# Ty Tag

TypeId for lifetime containing types via type tags.

![Version](https://img.shields.io/static/v1?label=version&message=0.1.0&color=informational)
[![docs.rs](https://img.shields.io/docsrs/ty-tag)](https://docs.rs/ty-tag/latest/ty_tag/)
![Version](https://img.shields.io/static/v1?label=MSRV&message=1.83.0&color=informational)
[![Crates.io License](https://img.shields.io/crates/l/ty-tag)](#license)
[![Crates.io](https://img.shields.io/crates/v/ty-tag)](https://crates.io/crates/ty-tag)

Not all types in Rust are `'static`. Meaning they can't be used with \[`core::any::TypeId`\].
However, it is often useful to be able to name a lifetime containing type via a `'static`
type. Most implementations go about this by using the same type with all the lifetimes
replaced by `'static`. So for example `&'a [u8]` would be named by `&'static [u8]`. These
implementations suffer from some limitations. One being that they are usually limited to
a single lifetime `'a`.

This crate takes a different approach to solve this issue. We introduce the idea of tags.
A tag is an arbitrary type with an associated lifetime containing type. So for the `&'a [u8]`
example we would have a `struct SliceU8;` with the `&'a [u8]` as an associated type.
You may notice that by itself this has an issue. We somehow need to get a `'a` to actually
write the `&'a [u8]` associated type. The lifetime can't live on the `SliceU8` because we
need that to be `'static`.

We solve this by injecting the lifetime `'a` in an operation called reification. This operation
combines a tag type and some number of lifetimes into the lifetime containing type. So
`SliceU8` + `'a` reifies to `&'a [u8]`. Combining this with a way to get a tag type from a
lifetime containing type, we gain the ability to go full circle from a lifetime containing type
to a `'static` type back to the lifetime containing type.

In this crate a tag type is defined to be a type that implements both \[`Tag`\] and \[`WithLt`\].
These types automatically gain the \[`Reify`\] operation for constructing the lifetime containing
type they name. Any type can have a tag associated with it via the \[`Tagged`\]
trait. Note, \[`Tagged`\] does not require the associated tag to name the `Self` type. This
is a useful property but may be unintuitive.

``` rust
use ty_tag::{tag, TagOf, Reify, l};

// Check that the tag of &str is a 'static type.
is_static::<TagOf<&str>>();

// Introduce an arbitrary lifetime 'a.
fn with_lt<'a>() {
    // Combine the tag of &str with lifetime 'a to form the &'a str lifetime containing type.
    reify::<'a, TagOf<&str>, &'a str>();
}
with_lt();

fn reify<'a, T: Reify<l!['a], Reified = U>, U>() {}

fn is_static<T: 'static>() {}
```

Another concept this crate introduces is that of a tag group. Because of Rust's coherence rules
we are limited in our ability to implement \[`Tagged`\] for types outside a user's crate. To work
around this we use tag groups like \[`DefaultGroup`\] to allow a user to bypass the coherence
rules by naming a type they control. This functionality is not used within this crate, but
is designed to improve the ergonomics of other crates.

### Crate features

- **`core`** *(enabled by default)* —  Adds tags for commonly used types in `core`.

- **`alloc`** —  Adds tags for commonly used types in `alloc`.

- **`std`** —  Adds tags for commonly used types in `std`.

- **`unsafe`** —  Allows `unsafe` code.
  
  Only some convenience methods of [`Label`]modifiers::Label need this.

### `no_std` Support

This crate is `#![no_std]` by default, it can be used anywhere Rust can.

### Minimum Supported Rust Version

Requires Rust 1.83.0.

This crate follows the ["Latest stable Rust" policy](https://gist.github.com/alexheretic/d1e98d8433b602e57f5d0a9637927e0c). The listed MSRV won't be changed unless needed.
However, updating the MSRV anywhere up to the latest stable at time of release
is allowed.

## Contributing

Contributions in any form (issues, pull requests, etc.) to this project must adhere to 
Rust's [Code of Conduct](https://www.rust-lang.org/policies/code-of-conduct).

Unless you explicitly state otherwise, any contribution intentionally submitted for 
inclusion in `ty-tag` by you shall be licensed as below, without any 
additional terms or conditions.

## License

This project is licensed under either of

  * [Apache License 2.0]LICENSE-Apache-2.0
  * [MIT License]LICENSE-MIT

at your option.