@@ -610,6 +610,83 @@ 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
+ ///
628
+ /// let sub = CoVar<SubType>::new();
629
+ /// // not created by CoVar<SuperType>::new
630
+ /// let fake_super = sub as CoVar<SuperType>;
631
+ /// ```
632
+ ///
633
+ /// A full example
634
+ ///
635
+ /// ```
636
+ /// use std::any::TypeId;
637
+ /// use std::collections::HashSet;
638
+ /// use std::marker::PhantomData;
639
+ /// use std::sync::{LazyLock, Mutex};
640
+ ///
641
+ /// use unique::Unique;
642
+ ///
643
+ /// static ID_SET: LazyLock<Mutex<HashSet<TypeId>>> = LazyLock::new(|| Mutex::new(HashSet::new()));
644
+ ///
645
+ /// mod unique {
646
+ /// use super::*;
647
+ ///
648
+ /// // Due to its private data member, outside this module,
649
+ /// // this struct can only be created using `new`.
650
+ /// #[derive(Debug, PartialEq)]
651
+ /// pub struct Unique<TypeAsId: 'static>(PhantomData<TypeAsId>);
652
+ ///
653
+ /// impl<TypeAsId: 'static> Unique<TypeAsId> {
654
+ /// pub fn new() -> Option<Self> {
655
+ /// let mut set = ID_SET.lock().unwrap();
656
+ /// set.insert(TypeId::of::<TypeAsId>())
657
+ /// .then(|| Self(PhantomData))
658
+ /// }
659
+ /// }
660
+ ///
661
+ /// impl<TypeAsId: 'static> Drop for Unique<TypeAsId> {
662
+ /// fn drop(&mut self) {
663
+ /// let mut set = ID_SET.lock().unwrap();
664
+ /// (!set.remove(&TypeId::of::<TypeAsId>())).then(|| panic!("duplicity detected"));
665
+ /// }
666
+ /// }
667
+ /// }
668
+ ///
669
+ /// // A FnRef can be used wherever a FnStaticRef can be used,
670
+ /// // so FnRef is a subtype of FnStaticRef.
671
+ /// // Both are 'static, and thus have a TypeId.
672
+ /// type FnRef = fn(&());
673
+ /// type FnStaticRef = fn(&'static ());
674
+ ///
675
+ /// fn main() {
676
+ /// type TheOneRing = FnStaticRef;
677
+ ///
678
+ /// let the_one_ring = Unique::<TheOneRing>::new().unwrap();
679
+ /// assert_eq!(Unique::<TheOneRing>::new(), None);
680
+ ///
681
+ /// type OtherRing = FnRef;
682
+ ///
683
+ /// let other_ring = Unique::<OtherRing>::new().unwrap();
684
+ /// let fake_one_ring = other_ring as Unique<TheOneRing>;
685
+ /// assert_eq!(fake_one_ring, the_one_ring);
686
+ ///
687
+ /// std::mem::forget(fake_one_ring);
688
+ /// }
689
+ /// ```
613
690
#[ derive( Clone , Copy , Eq , PartialOrd , Ord ) ]
614
691
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
615
692
pub struct TypeId {
@@ -627,8 +704,7 @@ impl PartialEq for TypeId {
627
704
}
628
705
629
706
impl TypeId {
630
- /// Returns the `TypeId` of the type this generic function has been
631
- /// instantiated with.
707
+ /// Given a type (as a generic type argument), returns the `TypeId` of that type.
632
708
///
633
709
/// # Examples
634
710
///
0 commit comments