| lib.rs |
[![github]](https://github.com/dtolnay/typeid) [![crates-io]](https://crates.io/crates/typeid) [![docs-rs]](https://docs.rs/typeid)
[github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
[crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
[docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
# Const `TypeId` and non-'static `TypeId`
<br>
#### Const `TypeId`
This crate provides [`ConstTypeId`], which is like [`core::any::TypeId`] but
is constructible in const in stable Rust. (The standard library's TypeId's
is nightly-only to construct in const; the tracking issue for this is
[rust#77125].)
[rust#77125]: https://github.com/rust-lang/rust/issues/77125
Being able to construct `ConstTypeId` in const makes it suitable for use
cases that rely on static promotion:
```
use std::fmt::{self, Debug, Display};
use std::ptr;
use typeid::ConstTypeId;
pub struct ObjectVTable {
type_id: ConstTypeId,
drop_in_place: unsafe fn(*mut ()),
display: unsafe fn(*const (), &mut fmt::Formatter) -> fmt::Result,
debug: unsafe fn(*const (), &mut fmt::Formatter) -> fmt::Result,
}
impl ObjectVTable {
pub const fn new<T: Display + Debug>() -> &'static Self {
&ObjectVTable {
type_id: const { ConstTypeId::of::<T>() },
drop_in_place: |ptr| unsafe { ptr::drop_in_place(ptr.cast::<T>()) },
display: |ptr, f| unsafe { Display::fmt(&*ptr.cast::<T>(), f) },
debug: |ptr, f| unsafe { Debug::fmt(&*ptr.cast::<T>(), f) },
}
}
}
```
and in associated constants:
```
use typeid::ConstTypeId;
pub trait GetTypeId {
const TYPEID: ConstTypeId;
}
impl<T: 'static> GetTypeId for T {
const TYPEID: ConstTypeId = ConstTypeId::of::<Self>();
}
```
<br>
#### Non-'static `TypeId`
This crate provides [`typeid::of`], which takes an arbitrary non-'static
type `T` and produces the `TypeId` for the type obtained by replacing all
lifetimes in `T` by `'static`, other than higher-rank lifetimes found in
trait objects.
For example if `T` is `&'b dyn for<'a> Trait<'a, 'c>`, then
`typeid::of::<T>()` produces the TypeId of `&'static dyn for<'a> Trait<'a,
'static>`.
It should be obvious that unlike with the standard library's TypeId,
`typeid::of::<A>() == typeid::of::<B>()` does **not** mean that `A` and `B`
are the same type. However, there is a common special case where this
behavior is exactly what is needed. If:
- `A` is an arbitrary non-'static type parameter, _and_
- `B` is 'static, _and_
- all types with the same id as `B` are also 'static
then `typeid::of::<A>() == typeid::of::<B>()` guarantees that `A` and `B`
are the same type.
```
use core::any::TypeId;
use core::slice;
pub fn example<T>(slice: &[T]) {
// T is arbitrary and non-'static.
if typeid::of::<T>() == TypeId::of::<u8>() {
// T is definitely u8
let bytes = unsafe { slice::from_raw_parts(slice.as_ptr().cast(), slice.len()) };
process_bytes(bytes);
} else {
for t in slice {
process(t);
}
}
}
fn process<T>(_: &T) {/* ... */}
fn process_bytes(_: &[u8]) {/* ... */}
``` |
6107 |