Expand description
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.
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
-
macros(enabled by default) — Includes thetagmacro for creating tags from type aliases. -
core(enabled by default) — Adds tags for commonly used types incore. -
alloc— Adds tags for commonly used types inalloc. -
std— Adds tags for commonly used types instd. -
unsafe— Allowsunsafecode.Only some convenience methods of
Labelneed 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. 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.
Modules§
- external_
tags coreorallocorstd - Tags for types from other crates.
- lifetime_
list - List of lifetimes with an arbitrary length.
- modifiers
- Tag modifiers.
Structs§
- Default
Group - The default tag group.
- TagType
Id TypeIdwith lifetimes.
Traits§
- Reify
- Type level operation to reify a tag into it’s associated type.
- Reify
Self - Types that reify to themselves.
- Reify
Sized Reifybut with aSizedReified.- Tag
- A tag for a type.
- Tagged
Selfis tagged inGroup.- WithLt
- The reified type for a tag.
Type Aliases§
- TagOf
- Get the associated
Tagged::TagofT.
Attribute Macros§
- tag
macros - Create a tag for a type.