@@ -610,6 +610,110 @@ 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+ /// # Danger of Improper Variance
615+ ///
616+ /// You might think that subtyping is impossible between two static types,
617+ /// but this is false; there exists a static type with a static subtype.
618+ /// To wit, `fn(&str)`, which is short for `for<'any> fn(&'any str)`, and
619+ /// `fn(&'static str)`, are two distinct, static types, and yet,
620+ /// `fn(&str)` is a subtype of `fn(&'static str)`, since any value of type
621+ /// `fn(&str)` can be used where a value of type `fn(&'static str)` is needed.
622+ ///
623+ /// This means that abstractions around `TypeId`, despite its
624+ /// `'static` bound on arguments, still need to worry about unnecessary
625+ /// and improper variance: it is advisable to strive for invariance
626+ /// first. The usability impact will be negligible, while the reduction
627+ /// in the risk of unsoundness will be most welcome.
628+ ///
629+ /// ## Examples
630+ ///
631+ /// Suppose `SubType` is a subtype of `SuperType`, that is,
632+ /// a value of type `SubType` can be used wherever
633+ /// a value of type `SuperType` is expected.
634+ /// Suppose also that `CoVar<T>` is a generic type, which is covariant over `T`
635+ /// (like many other types, including `PhantomData<T>` and `Vec<T>`).
636+ ///
637+ /// Then, by covariance, `CoVar<SubType>` is a subtype of `CoVar<SuperType>`,
638+ /// that is, a value of type `CoVar<SubType>` can be used wherever
639+ /// a value of type `CoVar<SuperType>` is expected.
640+ ///
641+ /// Then if `CoVar<SuperType>` relies on `TypeId::of::<SuperType>()` to uphold any invariants,
642+ /// those invariants may be broken because a value of type `CoVar<SuperType>` can be created
643+ /// without going through any of its methods, like so:
644+ /// ```
645+ /// type SubType = fn(&());
646+ /// type SuperType = fn(&'static ());
647+ /// type CoVar<T> = Vec<T>; // imagine something more complicated
648+ ///
649+ /// let sub: CoVar<SubType> = CoVar::new();
650+ /// // we have a `CoVar<SuperType>` instance without
651+ /// // *ever* having called `CoVar::<SuperType>::new()`!
652+ /// let fake_super: CoVar<SuperType> = sub;
653+ /// ```
654+ ///
655+ /// The following is an example program that tries to use `TypeId::of` to
656+ /// implement a generic type `Unique<T>` that guarantees unique instances for each `Unique<T>`,
657+ /// that is, and for each type `T` there can be at most one value of type `Unique<T>` at any time.
658+ ///
659+ /// ```
660+ /// use std::any::TypeId;
661+ /// use std::collections::BTreeSet;
662+ /// use std::marker::PhantomData;
663+ /// use std::sync::Mutex;
664+ ///
665+ /// use unique::Unique;
666+ ///
667+ /// mod unique {
668+ /// use super::*;
669+ ///
670+ /// static ID_SET: Mutex<BTreeSet<TypeId>> = Mutex::new(BTreeSet::new());
671+ ///
672+ /// // Due to its private data member, outside this module,
673+ /// // this struct can only be created using `new`.
674+ /// #[derive(Debug, PartialEq)]
675+ /// pub struct Unique<TypeAsId: 'static>(
676+ /// // this usage of `TypeAsId` makes `Unique` covariant 🚨
677+ /// PhantomData<TypeAsId>,
678+ /// );
679+ ///
680+ /// impl<TypeAsId: 'static> Unique<TypeAsId> {
681+ /// pub fn new() -> Option<Self> {
682+ /// let mut set = ID_SET.lock().unwrap();
683+ /// set.insert(TypeId::of::<TypeAsId>())
684+ /// .then(|| Self(PhantomData))
685+ /// }
686+ /// }
687+ ///
688+ /// impl<TypeAsId: 'static> Drop for Unique<TypeAsId> {
689+ /// fn drop(&mut self) {
690+ /// let mut set = ID_SET.lock().unwrap();
691+ /// (!set.remove(&TypeId::of::<TypeAsId>())).then(|| panic!("duplicity detected"));
692+ /// }
693+ /// }
694+ /// }
695+ ///
696+ /// // `FnRef` is a subtype of `FnStaticRef`.
697+ /// // Both are 'static, and thus have a TypeId.
698+ /// type FnRef = fn(&());
699+ /// type FnStaticRef = fn(&'static ());
700+ ///
701+ /// fn main() {
702+ /// type TheOneRing = FnStaticRef;
703+ ///
704+ /// let the_one_ring: Unique<TheOneRing> = Unique::new().unwrap();
705+ /// assert_eq!(Unique::<TheOneRing>::new(), None);
706+ ///
707+ /// type OtherRing = FnRef;
708+ ///
709+ /// let other_ring: Unique<OtherRing> = Unique::new().unwrap();
710+ /// // Use that `Unique<OtherRing>` is a subtype of `Unique<TheOneRing>` 🚨
711+ /// let fake_one_ring: Unique<TheOneRing> = other_ring;
712+ /// assert_eq!(fake_one_ring, the_one_ring);
713+ ///
714+ /// std::mem::forget(fake_one_ring);
715+ /// }
716+ /// ```
613717#[ derive( Clone , Copy , Eq , PartialOrd , Ord ) ]
614718#[ stable( feature = "rust1" , since = "1.0.0" ) ]
615719pub struct TypeId {
@@ -627,8 +731,7 @@ impl PartialEq for TypeId {
627731}
628732
629733impl TypeId {
630- /// Returns the `TypeId` of the type this generic function has been
631- /// instantiated with.
734+ /// Returns the `TypeId` of the generic type parameter.
632735 ///
633736 /// # Examples
634737 ///
0 commit comments