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;