@@ -610,6 +610,105 @@ 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+ /// mod unique {
661+ /// use std::any::TypeId;
662+ /// use std::collections::BTreeSet;
663+ /// use std::marker::PhantomData;
664+ /// use std::sync::Mutex;
665+ ///
666+ /// static ID_SET: Mutex<BTreeSet<TypeId>> = Mutex::new(BTreeSet::new());
667+ ///
668+ /// // TypeId has only covariant uses, which makes Unique covariant over TypeAsId 🚨
669+ /// #[derive(Debug, PartialEq)]
670+ /// pub struct Unique<TypeAsId: 'static>(
671+ /// // private field prevents creation without `new` outside this module
672+ /// PhantomData<TypeAsId>,
673+ /// );
674+ ///
675+ /// impl<TypeAsId: 'static> Unique<TypeAsId> {
676+ /// pub fn new() -> Option<Self> {
677+ /// let mut set = ID_SET.lock().unwrap();
678+ /// (set.insert(TypeId::of::<TypeAsId>())).then(|| Self(PhantomData))
679+ /// }
680+ /// }
681+ ///
682+ /// impl<TypeAsId: 'static> Drop for Unique<TypeAsId> {
683+ /// fn drop(&mut self) {
684+ /// let mut set = ID_SET.lock().unwrap();
685+ /// (!set.remove(&TypeId::of::<TypeAsId>())).then(|| panic!("duplicity detected"));
686+ /// }
687+ /// }
688+ /// }
689+ ///
690+ /// use unique::Unique;
691+ ///
692+ /// // `FnRef` is a subtype of `FnStaticRef`. Both are 'static, and thus have a TypeId.
693+ /// type FnRef = fn(&());
694+ /// type FnStaticRef = fn(&'static ());
695+ ///
696+ /// fn main() {
697+ /// type TheOneRing = FnStaticRef;
698+ ///
699+ /// let the_one_ring: Unique<TheOneRing> = Unique::new().unwrap();
700+ /// assert_eq!(Unique::<TheOneRing>::new(), None);
701+ ///
702+ /// type OtherRing = FnRef;
703+ ///
704+ /// let other_ring: Unique<OtherRing> = Unique::new().unwrap();
705+ /// // Use that `Unique<OtherRing>` is a subtype of `Unique<TheOneRing>` 🚨
706+ /// let fake_one_ring: Unique<TheOneRing> = other_ring;
707+ /// assert_eq!(fake_one_ring, the_one_ring);
708+ ///
709+ /// std::mem::forget(fake_one_ring);
710+ /// }
711+ /// ```
613712#[ derive( Clone , Copy , Eq , PartialOrd , Ord ) ]
614713#[ stable( feature = "rust1" , since = "1.0.0" ) ]
615714pub struct TypeId {
@@ -627,8 +726,7 @@ impl PartialEq for TypeId {
627726}
628727
629728impl TypeId {
630- /// Returns the `TypeId` of the type this generic function has been
631- /// instantiated with.
729+ /// Returns the `TypeId` of the generic type parameter.
632730 ///
633731 /// # Examples
634732 ///
0 commit comments