2 releases
new 0.1.1 | Dec 30, 2024 |
---|---|
0.1.0 | Dec 30, 2024 |
#654 in Rust patterns
189 downloads per month
59KB
865 lines
Ty Tag
TypeId for lifetime containing types via type tags.
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 thetag
macro 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
— Allowsunsafe
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.
Contributing
Contributions in any form (issues, pull requests, etc.) to this project must adhere to Rust's 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
at your option.
Dependencies
~140KB