@@ -610,6 +610,84 @@ impl dyn Any + Send + Sync {
610
610
/// While `TypeId` implements `Hash`, `PartialOrd`, and `Ord`, it is worth
611
611
/// noting that the hashes and ordering will vary between Rust releases. Beware
612
612
/// of relying on them inside of your code!
613
+ ///
614
+ /// **Note on Variance**:
615
+ /// Suppose `SubType` is a subtype of `SuperType`,
616
+ /// that is, `SubType` can be used wherever `SuperType` can be used,
617
+ /// and can be freely as-casted to it,
618
+ /// and `CoVar`is a generic data type that has a covariant type parameter.
619
+ /// Then by covariance, `CoVar<SubType>` is a subtype of `CoVar<SuperType>`,
620
+ /// that is, `CoVar<SubType>` can be used wherever `CoVar<SuperType>` can be used,
621
+ /// and can be freely as-casted to it.
622
+ /// Then if `CoVar<SuperType>` relies on `TypeId::of::<SuperType>` to uphold any invariants,
623
+ /// those invariants may be broken like so:
624
+ /// ```
625
+ /// type SubType = fn(&());
626
+ /// type SuperType = fn(&'static ());
627
+ /// type CoVar<T> = *const T; // imagine something more complicated
628
+ ///
629
+ /// let sub = CoVar::<SubType>::new();
630
+ /// // not created by CoVar::<SuperType>::new
631
+ /// let fake_super = sub as CoVar<SuperType>;
632
+ /// ```
633
+ ///
634
+ /// A full example
635
+ ///
636
+ /// ```
637
+ /// use std::any::TypeId;
638
+ /// use std::collections::HashSet;
639
+ /// use std::marker::PhantomData;
640
+ /// use std::sync::{LazyLock, Mutex};
641
+ ///
642
+ /// use unique::Unique;
643
+ ///
644
+ /// static ID_SET: LazyLock<Mutex<HashSet<TypeId>>> = LazyLock::new(|| Mutex::new(HashSet::new()));
645
+ ///
646
+ /// mod unique {
647
+ /// use super::*;
648
+ ///
649
+ /// // Due to its private data member, outside this module,
650
+ /// // this struct can only be created using `new`.
651
+ /// #[derive(Debug, PartialEq)]
652
+ /// pub struct Unique<TypeAsId: 'static>(PhantomData<TypeAsId>);
653
+ ///
654
+ /// impl<TypeAsId: 'static> Unique<TypeAsId> {
655
+ /// pub fn new() -> Option<Self> {
656
+ /// let mut set = ID_SET.lock().unwrap();
657
+ /// set.insert(TypeId::of::<TypeAsId>())
658
+ /// .then(|| Self(PhantomData))
659
+ /// }
660
+ /// }
661
+ ///
662
+ /// impl<TypeAsId: 'static> Drop for Unique<TypeAsId> {
663
+ /// fn drop(&mut self) {
664
+ /// let mut set = ID_SET.lock().unwrap();
665
+ /// (!set.remove(&TypeId::of::<TypeAsId>())).then(|| panic!("duplicity detected"));
666
+ /// }
667
+ /// }
668
+ /// }
669
+ ///
670
+ /// // A FnRef can be used wherever a FnStaticRef can be used,
671
+ /// // so FnRef is a subtype of FnStaticRef.
672
+ /// // Both are 'static, and thus have a TypeId.
673
+ /// type FnRef = fn(&());
674
+ /// type FnStaticRef = fn(&'static ());
675
+ ///
676
+ /// fn main() {
677
+ /// type TheOneRing = FnStaticRef;
678
+ ///
679
+ /// let the_one_ring = Unique::<TheOneRing>::new().unwrap();
680
+ /// assert_eq!(Unique::<TheOneRing>::new(), None);
681
+ ///
682
+ /// type OtherRing = FnRef;
683
+ ///
684
+ /// let other_ring = Unique::<OtherRing>::new().unwrap();
685
+ /// let fake_one_ring = other_ring as Unique<TheOneRing>;
686
+ /// assert_eq!(fake_one_ring, the_one_ring);
687
+ ///
688
+ /// std::mem::forget(fake_one_ring);
689
+ /// }
690
+ /// ```
613
691
#[ derive( Clone , Copy , Eq , PartialOrd , Ord ) ]
614
692
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
615
693
pub struct TypeId {
@@ -627,8 +705,7 @@ impl PartialEq for TypeId {
627
705
}
628
706
629
707
impl TypeId {
630
- /// Returns the `TypeId` of the type this generic function has been
631
- /// instantiated with.
708
+ /// Given a type (as a generic type argument), returns the `TypeId` of that type.
632
709
///
633
710
/// # Examples
634
711
///
0 commit comments