better_any/lib.rs
1#![warn(missing_docs)]
2#![warn(rust_2018_idioms)]
3#![cfg_attr(feature = "nightly", feature(coerce_unsized))]
4#![cfg_attr(feature = "nightly", feature(ptr_metadata))]
5//! # Better Any
6//!
7//! Rust RFC for `non_static_type_id` feature has been reverted.
8//! Which means in foreseeable future there will be no built-in way in rust to get type id for non-static type
9//! let alone safely use it to downcast to a particular type.
10//!
11//! This crate provides tools to do these things safely for types with single lifetime.
12//! Although looks like it is technically possible to extend this approach for multiple lifetimes,
13//! consistent api and derive macro would be much harder to create and use because of the necessity
14//! to properly handle lifetime relations.
15//! Feel free to create an issue if you have actual use case where you need this functionality for multiple lifetimes.
16//!
17//! Also it has better downcasting that allows you do downcast not just from `dyn Tid` (like `dyn Any`) but from
18//! any trait object that implements [`Tid`].
19//! So there is no more need to extend your traits with` fn to_any(&self)-> &dyn Any`
20//!
21//! MSRV: `1.41.0-stable` (without nightly feature)
22//!
23//! ### Usage
24//!
25//! Basically in places where before you have used `dyn Any` you can use `dyn Tid<'a>`
26//! - If your type is generic you should derive `Tid` implementation for it with `tid!` macro or `Tid` derive macro.
27//! Then to retrieve back concrete type `<dyn Tid>::downcast_*` methods should be used.
28//! - If your type is not generic/implements Any you can create `dyn Tid` from it via any of the available `From` implementations.
29//! Then to retrieve back concrete type `<dyn Tid>::downcast_any_*` methods should be used
30//! - If your type is not generic and local to your crate you also can derive `Tid` but then you need to be careful
31//! to use methods that corresponds to the way you create `dyn Tid` for that particular type.
32//! Otherwise downcasting will return `None`.
33//!
34//! If all your types can implement `Tid` to avoid confusion
35//! recommended way is to use first option even if some types implement `Any`.
36//! If there are some types that implement `Any` and can't implement `Tid` (i.e. types from other library),
37//! recommended way is to use second option for all types that implement `Any` to reduce confusion to minimum.
38//!
39//! ### Interoperability with Any
40//!
41//! Unfortunately you can't just use `Tid` everywhere because currently it is impossible
42//! to implement `Tid` for `T:Any` since it would conflict with any other possible `Tid` implementation.
43//! To overcome this limitation there is a `From` impl to go from `Box/&/&mut T where T:Any` to `Box/&/&mut dyn Tid`.
44//!
45//! Nevertheless if you are using `dyn Trait` where `Trait:Tid` all of this wouldn't work,
46//! and you are left with `Tid` only.
47//!
48//! ### Safety
49//!
50//! It is safe because created trait object preserves lifetime information,
51//! thus allowing us to safely downcast with proper lifetime.
52//! Otherwise internally it is plain old `Any`.
53use std::any::{Any, TypeId};
54
55/// Attribute macro that makes your implementation of `TidAble` safe
56/// Use it when you can't use derive e.g. for trait object.
57///
58/// ```rust
59/// # use better_any::{TidAble,impl_tid};
60/// trait Trait<'a>{}
61/// #[impl_tid]
62/// impl<'a> TidAble<'a> for Box<dyn Trait<'a> + 'a>{}
63/// ```
64#[deprecated(since = "0.2", note = "use tid! macro instead")]
65#[cfg(feature = "derive")]
66pub use better_typeid_derive::impl_tid;
67
68/// Derive macro to implement traits from this crate
69///
70/// It checks if it is safe to implement `Tid` for your struct
71/// Also it adds `:TidAble<'a>` bound on type parameters
72/// unless your type parameter already has **explicit** `'static` bound
73///
74/// All of its functionality is available via regular `tid!` macro,
75/// so unless you really want looks/readability of derive macro,
76/// there is no need to drag whole proc-macro machinery to your project.
77#[cfg(feature = "derive")]
78pub use better_typeid_derive::Tid;
79
80/// This trait indicates that you can substitute this type as a type parameter to
81/// another type so that resulting type could implement `Tid`.
82///
83/// So if you don't have such generic types, just use `Tid` everywhere,
84/// you don't need to use this trait at all.
85///
86/// Only this trait is actually being implemented on user side.
87/// Other traits are mostly just blanket implementations over X:TidAble<'a>
88///
89/// Note that this trait interferes with object safety, so you shouldn't use it as a super trait
90/// if you are going to make a trait object. Formally it is still object safe,
91/// but you can't make a trait object from it without specifying internal associate type
92/// like: `dyn TidAble<'a,Static=SomeType>` which make such trait object effectively useless.
93///
94/// Unsafe because safety of this crate relies on correctness of this trait implementation.
95/// There are several safe ways to implement it:
96/// - `type_id`/`tid` declarative macro
97/// - `#[derive(Tid)]` derive macro
98/// - impl_tid` attribute macro
99// we need to have associate type because it allows TypeIdAdjuster to be a private type
100// and allows to implement it for generic types
101// it has lifetime and depends on Tid because it would be practically useless as a standalone trait
102// because even though user would be able to get type id for more types,
103// any action based on it would be unsound without checking on lifetimes
104pub unsafe trait TidAble<'a>: Tid<'a> {
105 /// Implementation detail
106 #[doc(hidden)]
107 type Static: ?Sized + Any;
108}
109
110/// Extension trait that contains actual downcasting methods.
111///
112/// Use methods from this trait only if `dyn Tid` was created directly from `T` for this particular `T`
113///
114/// If `Self` is `Sized` then any of those calls is optimized to no-op because both T and Self are known statically.
115/// Useful if you have generic code that you want to behave differently depending on which
116/// concrete type replaces type parameter. Usually there are better ways to do this like specialization,
117/// but sometimes it can be the only way.
118pub trait TidExt<'a>: Tid<'a> {
119 /// Returns true if type behind self is equal to the type of T.
120 fn is<T: Tid<'a>>(&self) -> bool {
121 self.self_id() == T::id()
122 }
123
124 /// Attempts to downcast self to `T` behind reference
125 fn downcast_ref<'b, T: Tid<'a>>(&'b self) -> Option<&'b T> {
126 // Tid<'a> is implemented only for types with lifetime 'a
127 // so we can safely cast type back because lifetime invariant is preserved.
128 if self.is::<T>() {
129 Some(unsafe { &*(self as *const _ as *const T) })
130 } else {
131 None
132 }
133 }
134
135 /// Attempts to downcast self to `T` behind mutable reference
136 fn downcast_mut<'b, T: Tid<'a>>(&'b mut self) -> Option<&'b mut T> {
137 // see downcast_ref
138 if self.is::<T>() {
139 Some(unsafe { &mut *(self as *mut _ as *mut T) })
140 } else {
141 None
142 }
143 }
144
145 /// Attempts to downcast self to `T` behind `Rc` pointer
146 fn downcast_rc<T: Tid<'a>>(self: Rc<Self>) -> Result<Rc<T>, Rc<Self>> {
147 if self.is::<T>() {
148 unsafe { Ok(Rc::from_raw(Rc::into_raw(self) as *const _)) }
149 } else {
150 Err(self)
151 }
152 }
153
154 /// Attempts to downcast self to `T` behind `Arc` pointer
155 fn downcast_arc<T: Tid<'a>>(self: Arc<Self>) -> Result<Arc<T>, Arc<Self>> {
156 if self.is::<T>() {
157 unsafe { Ok(Arc::from_raw(Arc::into_raw(self) as *const _)) }
158 } else {
159 Err(self)
160 }
161 }
162
163 /// Attempts to downcast self to `T` behind `Box` pointer
164 fn downcast_box<T: Tid<'a>>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
165 if self.is::<T>() {
166 unsafe { Ok(Box::from_raw(Box::into_raw(self) as *mut _)) }
167 } else {
168 Err(self)
169 }
170 }
171
172 /// Attempts to downcast owned `Self` to `T`,
173 /// useful only in generic context as a workaround for specialization
174 fn downcast_move<T: Tid<'a>>(self) -> Option<T>
175 where
176 Self: Sized,
177 {
178 if self.is::<T>() {
179 // can't use `Option` trick here like with `Any`
180 let this = core::mem::MaybeUninit::new(self);
181 return Some(unsafe { core::mem::transmute_copy(&this) });
182 }
183 None
184 }
185}
186impl<'a, X: ?Sized + Tid<'a>> TidExt<'a> for X {}
187
188/// Methods here are implemented as an associated functions because otherwise
189/// for one they will conflict with methods defined on `dyn Any` in stdlib,
190/// for two they will be available on almost every type in the program causing confusing bugs and error messages
191/// For example if you have `&Box<dyn Any>` and call `downcast_ref`, instead of failing or working on coerced `&dyn Any`
192/// it would work with type id of `Box<dyn Any>` itself instead of the type behind `dyn Any`.
193pub trait AnyExt: Any {
194 /// Attempts to downcast this to `T` behind reference
195 fn downcast_ref<T: Any>(this: &Self) -> Option<&T> {
196 // Any is implemented only for types with lifetime 'a
197 // so we can safely cast type back because lifetime invariant is preserved.
198 if this.type_id() == TypeId::of::<T>() {
199 Some(unsafe { &*(this as *const _ as *const T) })
200 } else {
201 None
202 }
203 }
204
205 /// Attempts to downcast this to `T` behind mutable reference
206 fn downcast_mut<T: Any>(this: &mut Self) -> Option<&mut T> {
207 // see downcast_ref
208 if (*this).type_id() == TypeId::of::<T>() {
209 Some(unsafe { &mut *(this as *mut _ as *mut T) })
210 } else {
211 None
212 }
213 }
214
215 /// Attempts to downcast this to `T` behind `Rc` pointer
216 fn downcast_rc<T: Any>(this: Rc<Self>) -> Result<Rc<T>, Rc<Self>> {
217 if this.type_id() == TypeId::of::<T>() {
218 unsafe { Ok(Rc::from_raw(Rc::into_raw(this) as *const _)) }
219 } else {
220 Err(this)
221 }
222 }
223
224 /// Attempts to downcast this to `T` behind `Arc` pointer
225 fn downcast_arc<T: Any>(this: Arc<Self>) -> Result<Arc<T>, Arc<Self>> {
226 if this.type_id() == TypeId::of::<T>() {
227 unsafe { Ok(Arc::from_raw(Arc::into_raw(this) as *const _)) }
228 } else {
229 Err(this)
230 }
231 }
232
233 /// Attempts to downcast this to `T` behind `Box` pointer
234 fn downcast_box<T: Any>(this: Box<Self>) -> Result<Box<T>, Box<Self>> {
235 if this.type_id() == TypeId::of::<T>() {
236 unsafe { Ok(Box::from_raw(Box::into_raw(this) as *mut _)) }
237 } else {
238 Err(this)
239 }
240 }
241
242 /// Attempts to downcast owned `Self` to `T`,
243 /// useful only in generic context as a workaround for specialization
244 fn downcast_move<T: Any>(this: Self) -> Option<T>
245 where
246 Self: Sized,
247 {
248 let temp = &mut Some(this) as &mut dyn Any;
249 if let Some(temp) = AnyExt::downcast_mut::<Option<T>>(temp) {
250 return Some(temp.take().unwrap());
251 }
252 None
253 }
254}
255impl<T: ?Sized + Any> AnyExt for T {}
256
257/// This trait indicates that this type can be converted to
258/// trait object with typeid while preserving lifetime information.
259/// Extends `Any` functionality for types with single lifetime
260///
261/// Use it only as a `dyn Tid<'a>` or as super trait when you need to create trait object.
262/// In all other places use `TidAble<'a>`.
263///
264/// Lifetime here is necessary to make `dyn Tid<'a> + 'a` invariant over `'a`.
265pub unsafe trait Tid<'a>: 'a {
266 /// Returns type id of the type of `self`
267 ///
268 /// Note that returned type id is guaranteed to be different from provided by `Any`.
269 /// It is necessary for the creation of `dyn Tid` from `dyn Any` to be sound.
270 fn self_id(&self) -> TypeId;
271
272 /// Returns type id of this type
273 fn id() -> TypeId
274 where
275 Self: Sized;
276}
277
278unsafe impl<'a, T: ?Sized + TidAble<'a>> Tid<'a> for T {
279 #[inline]
280 fn self_id(&self) -> TypeId {
281 adjust_id::<T::Static>()
282 }
283
284 #[inline]
285 fn id() -> TypeId
286 where
287 Self: Sized,
288 {
289 adjust_id::<T::Static>()
290 }
291}
292
293#[inline(always)]
294fn adjust_id<T: ?Sized + Any>() -> TypeId {
295 TypeId::of::<T>()
296}
297
298/// Returns type id of `T`
299///
300/// Use it only if `Tid::id()` is not enough when `T` is not sized.
301#[inline]
302pub fn typeid_of<'a, T: ?Sized + TidAble<'a>>() -> TypeId {
303 adjust_id::<T::Static>()
304}
305
306impl<'a, T: Any> From<Box<T>> for Box<dyn Tid<'a> + 'a> {
307 #[inline]
308 fn from(f: Box<T>) -> Self {
309 // TypeIdAdjuster is a transparent wrapper so it is sound
310 unsafe { Box::from_raw(Box::into_raw(f) as *mut TypeIdAdjuster<T>) as _ }
311 }
312}
313
314impl<'a: 'b, 'b, T: Any> From<&'b T> for &'b (dyn Tid<'a> + 'a) {
315 #[inline]
316 fn from(f: &'b T) -> Self {
317 unsafe { &*(f as *const _ as *const TypeIdAdjuster<T> as *const _) }
318 }
319}
320
321impl<'a: 'b, 'b, T: Any> From<&'b mut T> for &'b mut (dyn Tid<'a> + 'a) {
322 #[inline]
323 fn from(f: &'b mut T) -> Self {
324 unsafe { &mut *(f as *mut _ as *mut TypeIdAdjuster<T> as *mut _) }
325 }
326}
327
328// Reverse is possible only for 'static
329// because otherwise even though user can't access type with lifetime because of different type id
330// drop still can be called after the end of lifetime.
331// impl Into<Box<dyn Any>> for Box<dyn Tid<'static>> {
332// fn into(self) -> Box<dyn Any> {
333// unsafe { core::mem::transmute(self) }
334// }
335// }
336
337//newtype wrapper to make `Any` types work with `dyn Tid`
338#[repr(transparent)]
339struct TypeIdAdjuster<T: ?Sized>(T);
340
341tid! {impl<'a,T:'static> TidAble<'a> for TypeIdAdjuster<T> where T:?Sized}
342
343impl<'a> dyn Tid<'a> + 'a {
344 /// Tries to downcast `dyn Tid` to `T`
345 ///
346 /// Use it only if `dyn Tid` was created from concrete `T:Any` via `From` implementations.
347 /// See examples how it does relate to other downcast methods
348 ///
349 /// ```rust
350 /// # use std::any::Any;
351 /// # use better_any::{Tid, TidAble, TidExt,tid};
352 /// struct S;
353 /// tid!(S);
354 ///
355 /// let a = &S;
356 /// let from_any: &dyn Tid = a.into();
357 /// assert!(from_any.downcast_any_ref::<S>().is_some());
358 /// assert!(from_any.downcast_ref::<S>().is_none());
359 ///
360 /// let direct = &S as &dyn Tid;
361 /// assert!(direct.downcast_any_ref::<S>().is_none());
362 /// assert!(direct.downcast_ref::<S>().is_some());
363 /// ```
364 #[inline]
365 pub fn downcast_any_ref<T: Any>(&self) -> Option<&T> {
366 // SAFETY: just a transparent reference cast
367 self.downcast_ref::<TypeIdAdjuster<T>>()
368 .map(|x| unsafe { &*(x as *const _ as *const T) })
369 }
370
371 /// See `downcast_any_ref`
372 #[inline]
373 pub fn downcast_any_mut<T: Any>(&mut self) -> Option<&mut T> {
374 // SAFETY: just a transparent reference cast
375 self.downcast_mut::<TypeIdAdjuster<T>>()
376 .map(|x| unsafe { &mut *(x as *mut _ as *mut T) })
377 }
378
379 /// See `downcast_any_ref`
380 #[inline]
381 pub fn downcast_any_box<T: Any>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
382 // SAFETY: just a transparent reference cast
383 self.downcast_box::<TypeIdAdjuster<T>>()
384 .map(|x| unsafe { Box::from_raw(Box::into_raw(x) as *mut T) as _ })
385 }
386}
387
388use std::cell::*;
389use std::rc::*;
390use std::sync::*;
391tid!(impl<'a, T> TidAble<'a> for Box<T> where T:?Sized);
392tid!(impl<'a, T> TidAble<'a> for Rc<T>);
393tid!(impl<'a, T> TidAble<'a> for RefCell<T>);
394tid!(impl<'a, T> TidAble<'a> for Cell<T>);
395tid!(impl<'a, T> TidAble<'a> for Arc<T>);
396tid!(impl<'a, T> TidAble<'a> for Mutex<T>);
397tid!(impl<'a, T> TidAble<'a> for RwLock<T>);
398
399// tid! {impl<'a, T> TidAble<'a> for Option<T>}
400const _: () = {
401 use core::marker::PhantomData;
402 type __Alias<'a, T> = Option<T>;
403 pub struct __TypeIdGenerator<'a, T: ?Sized>(PhantomData<&'a ()>, PhantomData<T>);
404 unsafe impl<'a, T: TidAble<'a>> TidAble<'a> for __Alias<'a, T> {
405 type Static = __TypeIdGenerator<'static, T::Static>;
406 }
407};
408
409tid! {impl<'a, T> TidAble<'a> for Vec<T>}
410
411tid! { impl<'a,T,E> TidAble<'a> for Result<T,E> }
412
413tid! { impl<'a> TidAble<'a> for dyn Tid<'a> + 'a }
414
415/// Main safe implementation interface of related unsafe traits
416///
417/// It uses syntax of regular Rust `impl` block but with parameters restricted enough to be sound.
418/// In particular it is restricted to a single lifetime parameter in particular block.
419/// and additional bounds must be in where clauses.
420/// In trivial cases just type signature can be used.
421///
422/// ```rust
423/// # use better_any::tid;
424/// struct S;
425/// tid!(S);
426///
427/// struct F<'a>(&'a str);
428/// tid!(F<'a>);
429///
430/// struct Bar<'x,'y,X,Y>(&'x str,&'y str,X,Y);
431/// tid!{ impl<'b,X,Y> TidAble<'b> for Bar<'b,'b,X,Y> }
432///
433/// trait Test<'a>{}
434/// tid!{ impl<'b> TidAble<'b> for dyn Test<'b> + 'b }
435/// ```
436///
437/// Implementation by default adds `TidAble<'a>` bound on all generic parameters.
438/// This behavior can be opted out by specifying `'static` bound on corresponding type parameter.
439/// Note that due to decl macro limitations it must be specified directly on type parameter
440/// and **not** in where clauses:
441/// ```rust
442/// # use better_any::tid;
443/// struct Test<'a,X:?Sized>(&'a str,Box<X>);
444/// tid! { impl<'a,X:'static> Tid<'a> for Test<'a,X> where X:?Sized }
445/// ```
446///
447#[macro_export]
448macro_rules! tid {
449
450 ($struct: ident) => {
451 unsafe impl<'a> $crate::TidAble<'a> for $struct {
452 type Static = $struct;
453 }
454 };
455 ($struct: ident < $lt: lifetime >) => {
456 unsafe impl<'a> $crate::TidAble<'a> for $struct<'a> {
457 type Static = $struct<'static>;
458 }
459 };
460 // no static parameters case
461 (impl <$lt:lifetime $(,$param:ident)*> $tr:ident<$lt2:lifetime> for $($struct: tt)+ ) => {
462 $crate::tid!{ inner impl <$lt $(,$param)* static> $tr<$lt2> for $($struct)+ }
463 };
464
465 //todo change macro to use attributes instead of 'static
466 // inner submacro is used to check/fix/error on whether correct trait is being implemented
467 (inner impl <$lt:lifetime $(,$param:ident)* static $( $static_param:ident)* > Tid<$lt2:lifetime> for $($struct: tt)+ ) => {
468 $crate::tid!{ inner impl <$lt $(,$param)* static $( $static_param)*> TidAble<$lt2> for $($struct)+ }
469 };
470 (inner impl <$lt:lifetime $(,$param:ident)* static $( $static_param:ident)* > TidAble<$lt2:lifetime> for $($struct: tt)+ ) => {
471 const _:() = {
472 use core::marker::PhantomData;
473 type __Alias<$lt $(,$param)* $(,$static_param)*> = $crate::before_where!{ $($struct)+ };
474 pub struct __TypeIdGenerator<$lt $(,$param:?Sized)* $(,$static_param:?Sized)*>
475 (PhantomData<& $lt ()> $(,PhantomData<$param>)* $(,PhantomData<$static_param>)*);
476 $crate::impl_block!{
477 after where { $($struct)+ }
478 {unsafe impl<$lt $(,$param:$crate::TidAble<$lt>)* $(,$static_param: 'static)* > $crate::TidAble<$lt2> for __Alias<$lt $(,$param)* $(,$static_param)*>}
479
480 {
481 type Static = __TypeIdGenerator<'static $(,$param::Static)* $(,$static_param)*>;
482 }
483 }
484 };
485 };
486 (inner impl <$lt:lifetime $(,$param:ident)* static $( $static_param:ident)* > $tr:ident<$lt2:lifetime> for $($struct: tt)+ ) => {
487 compile_error!{" wrong trait, should be TidAble or Tid "}
488 };
489
490 // temp submacro is used to separate 'static type parameters from other ones
491 (temp $(,$param:ident)* static $(,$static_param:ident)* impl <$lt:lifetime , $token:ident : 'static $($tail: tt)+ ) => {
492 $crate::tid!{ temp $(,$param)* static $(,$static_param)* , $token impl <$lt $($tail)+}
493 };
494 (temp $(,$param:ident)* static $(,$static_param:ident)* impl <$lt:lifetime , $token:ident $($tail: tt)+ ) => {
495 $crate::tid!{ temp $(,$param)* ,$token static $(,$static_param)* impl <$lt $($tail)+ }
496 };
497 (temp $(,$param:ident)* static $(,$static_param:ident)* impl <$lt:lifetime> $($tail: tt)+ ) => {
498 $crate::tid!{ inner impl <$lt $(,$param)* static $( $static_param)* > $($tail)+ }
499 };
500 // ( temp static $($tail:tt)+ ) => {
501 // compile_error!{"invalid syntax"}
502 // };
503 ( impl $($tail: tt)+) => {
504 $crate::tid!{ temp static impl $($tail)+ }
505 };
506}
507
508#[doc(hidden)]
509#[macro_export]
510macro_rules! before_where {
511 (inner { $($processed:tt)* } where $($tokens:tt)* ) => { $($processed)* };
512 (inner { $($processed:tt)* } $token:tt $($tokens:tt)* ) => {
513 $crate::before_where!(inner { $($processed)* $token } $($tokens)*)
514 };
515 (inner { $($processed:tt)* } ) => { $($processed)* };
516 ($($tokens:tt)*) => {$crate::before_where!(inner {} $($tokens)*)};
517}
518
519//creates actual impl block while also extracting tokens after where
520#[doc(hidden)]
521#[macro_export]
522macro_rules! impl_block {
523 (
524 after where {}
525 {$($imp:tt)*}
526 { $($block:tt)* }
527 ) => {
528 $($imp)*
529
530 {
531 $($block)*
532 }
533 };
534 (
535 after where { where $($bounds:tt)* }
536 {$($imp:tt)*}
537 { $($block:tt)* }
538 ) => {
539 $($imp)*
540 where $($bounds)*
541 {
542 $($block)*
543 }
544 };
545 (
546 after where {$token:tt $($tokens:tt)*}
547 {$($imp:tt)*}
548 { $($block:tt)* }
549 ) => {
550 $crate::impl_block!{
551 after where { $($tokens)*}
552 {$($imp)*}
553 { $($block)* }
554
555 }
556 };
557}
558// the logic behind these implementations is to connect Any with Tid somehow
559// I would say that if T:Any there is no much need to implement Tid<'a> for T.
560// because Any functionality already exists and `dyn Any` can be converted to `dyn Tid`.
561// unfortunately there is no way to implement Tid<'a> for T:Any,
562// which make impl<'a, T: Tid<'a>> Tid<'a> for &'a T {} almost useless
563// because it wouldn't work even for &'a i32
564// This way we don't require user to newtype wrapping simple references.
565// And more complex types are usually not used as a type parameters directly.
566
567tid! { impl<'a,T:'static> TidAble<'a> for &'a T }
568tid! { impl<'a,T:'static> TidAble<'a> for &'a mut T }
569
570/// Just an alias of `tid!` macro if someone considers that name to be more clear and for compatibility with previous versions.
571///
572/// ```rust
573/// use better_any::type_id;
574/// struct S;
575/// type_id!(S);
576/// struct F<'a>(&'a str);
577/// type_id!(F<'a>);
578/// ```
579pub use tid as type_id;
580// left it exported just to not needlessly break previous version code
581// #[macro_export]
582// macro_rules! type_id {
583// ($($tokens:tt)+) => { $crate::tid!{ $($tokens)+ } };
584// }
585
586/// unstable features that require nightly, use on your own risk
587#[cfg(feature = "nightly")]
588pub mod nightly;