@@ -610,6 +610,110 @@ 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
+ /// # 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
+ /// ```
613
717
#[ derive( Clone , Copy , Eq , PartialOrd , Ord ) ]
614
718
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
615
719
pub struct TypeId {
@@ -627,8 +731,7 @@ impl PartialEq for TypeId {
627
731
}
628
732
629
733
impl 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.
632
735
///
633
736
/// # Examples
634
737
///
0 commit comments