# Ty Tag
TypeId for lifetime containing types via type tags.

[](https://docs.rs/ty-tag/latest/ty_tag/)

[](#license)
[](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.