@@ -610,6 +610,83 @@ impl dyn Any + Send + Sync {
610610/// While `TypeId` implements `Hash`, `PartialOrd`, and `Ord`, it is worth
611611/// noting that the hashes and ordering will vary between Rust releases. Beware
612612/// 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+ /// ```
613690#[ derive( Clone , Copy , Eq , PartialOrd , Ord ) ]
614691#[ stable( feature = "rust1" , since = "1.0.0" ) ]
615692pub struct TypeId {
@@ -627,8 +704,7 @@ impl PartialEq for TypeId {
627704}
628705
629706impl 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.
632708 ///
633709 /// # Examples
634710 ///
0 commit comments