@@ -610,6 +610,101 @@ 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
+ /// 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
+ /// // `OtherRing` is a subtype of `TheOneRing`. Both are 'static, and thus have a TypeId.
693
+ /// type TheOneRing = fn(&'static ());
694
+ /// type OtherRing = fn(&());
695
+ ///
696
+ /// fn main() {
697
+ /// let the_one_ring: Unique<TheOneRing> = Unique::new().unwrap();
698
+ /// assert_eq!(Unique::<TheOneRing>::new(), None);
699
+ ///
700
+ /// let other_ring: Unique<OtherRing> = Unique::new().unwrap();
701
+ /// // Use that `Unique<OtherRing>` is a subtype of `Unique<TheOneRing>` 🚨
702
+ /// let fake_one_ring: Unique<TheOneRing> = other_ring;
703
+ /// assert_eq!(fake_one_ring, the_one_ring);
704
+ ///
705
+ /// std::mem::forget(fake_one_ring);
706
+ /// }
707
+ /// ```
613
708
#[ derive( Clone , Copy , Eq , PartialOrd , Ord ) ]
614
709
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
615
710
pub struct TypeId {
@@ -627,8 +722,7 @@ impl PartialEq for TypeId {
627
722
}
628
723
629
724
impl TypeId {
630
- /// Returns the `TypeId` of the type this generic function has been
631
- /// instantiated with.
725
+ /// Returns the `TypeId` of the generic type parameter.
632
726
///
633
727
/// # Examples
634
728
///
0 commit comments