Crate ty_tag

Crate ty_tag 

Source
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 the tag macro for creating tags from type aliases.

  • 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 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. 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_tagscore or alloc or std
Tags for types from other crates.
lifetime_list
List of lifetimes with an arbitrary length.
modifiers
Tag modifiers.

Structs§

DefaultGroup
The default tag group.
TagTypeId
TypeId with lifetimes.

Traits§

Reify
Type level operation to reify a tag into it’s associated type.
ReifySelf
Types that reify to themselves.
ReifySized
Reify but with a Sized Reified.
Tag
A tag for a type.
Tagged
Self is tagged in Group.
WithLt
The reified type for a tag.

Type Aliases§

TagOf
Get the associated Tagged::Tag of T.

Attribute Macros§

tagmacros
Create a tag for a type.