about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-01-19 23:35:12 +0000
committerbors <bors@rust-lang.org>2015-01-19 23:35:12 +0000
commit65b61ffb3f55c996eceded6c91281911b671d978 (patch)
treed0ab6ddb6042d3fdaf3824372a8e2d6fc9def19a /src
parent7f8c687fdfbf076ef1667f4d95633d4e0812b516 (diff)
parent70f7165cc8975337964118af4d30f40b98f5edeb (diff)
downloadrust-65b61ffb3f55c996eceded6c91281911b671d978.tar.gz
rust-65b61ffb3f55c996eceded6c91281911b671d978.zip
Auto merge of #21165 - alexcrichton:second-pass-type-id, r=aturon
This commit aims to stabilize the `TypeId` abstraction by moving it out of the
`intrinsics` module into the `any` module of the standard library. Specifically,

* `TypeId` is now defined at `std::any::TypeId`
* `TypeId::hash` has been removed in favor of an implementation of `Hash`.

This commit also performs a final pass over the `any` module, confirming the
following:

* `Any::get_type_id` remains unstable as *usage* of the `Any` trait will likely
  never require this, and the `Any` trait does not need to be implemented for
  any other types. As a result, this implementation detail can remain unstable
  until associated statics are implemented.
* `Any::downcast_ref` is now stable
* `Any::downcast_mut` is now stable
* `BoxAny` remains unstable. While a direct impl on `Box<Any>` is allowed today
  it does not allow downcasting of trait objects like `Box<Any + Send>` (those
  returned from `Thread::join`). This is covered by #18737.
* `BoxAny::downcast` is now stable.
Diffstat (limited to 'src')
-rw-r--r--src/liballoc/boxed.rs10
-rw-r--r--src/libcore/any.rs54
-rw-r--r--src/libcore/hash/mod.rs8
-rw-r--r--src/libcore/intrinsics.rs24
-rw-r--r--src/libcoretest/intrinsics.rs2
-rw-r--r--src/librustc/middle/lang_items.rs2
-rw-r--r--src/librustc_trans/trans/intrinsic.rs2
-rw-r--r--src/librustc_typeck/check/mod.rs14
-rw-r--r--src/test/auxiliary/issue13507.rs2
-rw-r--r--src/test/auxiliary/typeid-intrinsic.rs21
-rw-r--r--src/test/auxiliary/typeid-intrinsic2.rs21
-rw-r--r--src/test/compile-fail/extern-with-type-bounds.rs4
-rw-r--r--src/test/compile-fail/issue-18389.rs2
-rw-r--r--src/test/run-pass/issue-13507-2.rs2
-rw-r--r--src/test/run-pass/type-id-higher-rank.rs2
-rw-r--r--src/test/run-pass/typeid-intrinsic.rs43
16 files changed, 105 insertions, 108 deletions
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index 8ad0c152dc8..a2cc98c7d01 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -125,8 +125,11 @@ impl<S: hash::Hasher, T: ?Sized + Hash<S>> Hash<S> for Box<T> {
 }
 
 /// Extension methods for an owning `Any` trait object.
-#[unstable = "post-DST and coherence changes, this will not be a trait but \
-              rather a direct `impl` on `Box<Any>`"]
+#[unstable = "this trait will likely disappear once compiler bugs blocking \
+              a direct impl on `Box<Any>` have been fixed "]
+// FIXME(#18737): this should be a direct impl on `Box<Any>`. If you're
+//                removing this please make sure that you can downcase on
+//                `Box<Any + Send>` as well as `Box<Any>`
 pub trait BoxAny {
     /// Returns the boxed value if it is of type `T`, or
     /// `Err(Self)` if it isn't.
@@ -134,10 +137,9 @@ pub trait BoxAny {
     fn downcast<T: 'static>(self) -> Result<Box<T>, Self>;
 }
 
+#[stable]
 impl BoxAny for Box<Any> {
     #[inline]
-    #[unstable = "method may be renamed with respect to other downcasting \
-                  methods"]
     fn downcast<T: 'static>(self) -> Result<Box<T>, Box<Any>> {
         if self.is::<T>() {
             unsafe {
diff --git a/src/libcore/any.rs b/src/libcore/any.rs
index 797687a9ad9..20ed2253861 100644
--- a/src/libcore/any.rs
+++ b/src/libcore/any.rs
@@ -71,11 +71,11 @@
 
 #![stable]
 
-use mem::{transmute};
-use option::Option;
-use option::Option::{Some, None};
+use mem::transmute;
+use option::Option::{self, Some, None};
 use raw::TraitObject;
-use intrinsics::TypeId;
+use intrinsics;
+#[cfg(not(stage0))] use marker::Sized;
 
 ///////////////////////////////////////////////////////////////////////////////
 // Any trait
@@ -99,7 +99,6 @@ impl<T: 'static> Any for T {
 
 ///////////////////////////////////////////////////////////////////////////////
 // Extension methods for Any trait objects.
-// Implemented as three extension traits so that the methods can be generic.
 ///////////////////////////////////////////////////////////////////////////////
 
 impl Any {
@@ -119,9 +118,9 @@ impl Any {
 
     /// Returns some reference to the boxed value if it is of type `T`, or
     /// `None` if it isn't.
-    #[unstable = "naming conventions around acquiring references may change"]
+    #[stable]
     #[inline]
-    pub fn downcast_ref<'a, T: 'static>(&'a self) -> Option<&'a T> {
+    pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
         if self.is::<T>() {
             unsafe {
                 // Get the raw representation of the trait object
@@ -137,9 +136,9 @@ impl Any {
 
     /// Returns some mutable reference to the boxed value if it is of type `T`, or
     /// `None` if it isn't.
-    #[unstable = "naming conventions around acquiring references may change"]
+    #[stable]
     #[inline]
-    pub fn downcast_mut<'a, T: 'static>(&'a mut self) -> Option<&'a mut T> {
+    pub fn downcast_mut<T: 'static>(&mut self) -> Option<&mut T> {
         if self.is::<T>() {
             unsafe {
                 // Get the raw representation of the trait object
@@ -153,3 +152,40 @@ impl Any {
         }
     }
 }
+
+///////////////////////////////////////////////////////////////////////////////
+// TypeID and its methods
+///////////////////////////////////////////////////////////////////////////////
+
+/// A `TypeId` represents a globally unique identifier for a type.
+///
+/// Each `TypeId` is an opaque object which does not allow inspection of what's
+/// inside but does allow basic operations such as cloning, comparison,
+/// printing, and showing.
+///
+/// A `TypeId` is currently only available for types which ascribe to `'static`,
+/// but this limitation may be removed in the future.
+#[cfg_attr(stage0, lang = "type_id")]
+#[derive(Clone, Copy, PartialEq, Eq, Show, Hash)]
+#[stable]
+pub struct TypeId {
+    t: u64,
+}
+
+impl TypeId {
+    /// Returns the `TypeId` of the type this generic function has been
+    /// instantiated with
+    #[cfg(not(stage0))]
+    #[unstable = "may grow a `Reflect` bound soon via marker traits"]
+    pub fn of<T: ?Sized + 'static>() -> TypeId {
+        TypeId {
+            t: unsafe { intrinsics::type_id::<T>() },
+        }
+    }
+
+    /// dox
+    #[cfg(stage0)]
+    pub fn of<T: 'static>() -> TypeId {
+        unsafe { intrinsics::type_id::<T>() }
+    }
+}
diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs
index 37e4a105a30..742e6239017 100644
--- a/src/libcore/hash/mod.rs
+++ b/src/libcore/hash/mod.rs
@@ -62,7 +62,6 @@ use prelude::*;
 
 use borrow::{Cow, ToOwned};
 use default::Default;
-use intrinsics::TypeId;
 use mem;
 use num::Int;
 
@@ -243,13 +242,6 @@ impl<S: Writer + Hasher, T> Hash<S> for *mut T {
     }
 }
 
-impl<S: Writer + Hasher> Hash<S> for TypeId {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        self.hash().hash(state)
-    }
-}
-
 impl<'a, T, B: ?Sized, S: Hasher> Hash<S> for Cow<'a, T, B>
     where B: Hash<S> + ToOwned<T>
 {
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 40db0def626..73be68289c9 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -44,6 +44,8 @@
 
 use marker::Sized;
 
+#[cfg(stage0)] use any::TypeId;
+
 pub type GlueFn = extern "Rust" fn(*const i8);
 
 #[lang="ty_desc"]
@@ -206,6 +208,10 @@ extern "rust-intrinsic" {
     /// Gets an identifier which is globally unique to the specified type. This
     /// function will return the same value for a type regardless of whichever
     /// crate it is invoked in.
+    #[cfg(not(stage0))]
+    pub fn type_id<T: ?Sized + 'static>() -> u64;
+
+    #[cfg(stage0)]
     pub fn type_id<T: ?Sized + 'static>() -> TypeId;
 
     /// Create a value initialized to zero.
@@ -545,21 +551,3 @@ extern "rust-intrinsic" {
     /// Performs checked `u64` multiplication.
     pub fn u64_mul_with_overflow(x: u64, y: u64) -> (u64, bool);
 }
-
-
-/// `TypeId` represents a globally unique identifier for a type
-#[lang="type_id"] // This needs to be kept in lockstep with the code in trans/intrinsic.rs and
-                  // middle/lang_items.rs
-#[derive(Clone, Copy, PartialEq, Eq, Show)]
-pub struct TypeId {
-    t: u64,
-}
-
-impl TypeId {
-    /// Returns the `TypeId` of the type this generic function has been instantiated with
-    pub fn of<T: ?Sized + 'static>() -> TypeId {
-        unsafe { type_id::<T>() }
-    }
-
-    pub fn hash(&self) -> u64 { self.t }
-}
diff --git a/src/libcoretest/intrinsics.rs b/src/libcoretest/intrinsics.rs
index bcf8a6a433b..b836f5f3f69 100644
--- a/src/libcoretest/intrinsics.rs
+++ b/src/libcoretest/intrinsics.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use core::intrinsics::TypeId;
+use core::any::TypeId;
 
 #[test]
 fn test_typeid_sized_types() {
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index db6a4768857..ff79ace9924 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -307,8 +307,6 @@ lets_do_this! {
     TyDescStructLangItem,            "ty_desc",                 ty_desc;
     OpaqueStructLangItem,            "opaque",                  opaque;
 
-    TypeIdLangItem,                  "type_id",                 type_id;
-
     EhPersonalityLangItem,           "eh_personality",          eh_personality;
 
     ExchangeHeapLangItem,            "exchange_heap",           exchange_heap;
diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs
index 6d0f7746cad..771c51d629f 100644
--- a/src/librustc_trans/trans/intrinsic.rs
+++ b/src/librustc_trans/trans/intrinsic.rs
@@ -355,8 +355,6 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                 ccx.tcx(),
                 *substs.types.get(FnSpace, 0),
                 &ccx.link_meta().crate_hash);
-            // NB: This needs to be kept in lockstep with the TypeId struct in
-            //     the intrinsic module
             C_u64(ccx, hash)
         }
         (_, "init") => {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index a4fa594621e..f610456f73c 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -104,7 +104,6 @@ use rscope::RegionScope;
 use session::Session;
 use {CrateCtxt, lookup_def_ccx, no_params, require_same_types};
 use TypeAndSubsts;
-use middle::lang_items::TypeIdLangItem;
 use lint;
 use util::common::{block_query, indenter, loop_query};
 use util::ppaux::{self, Repr};
@@ -5239,18 +5238,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
               });
               (1u, Vec::new(), td_ptr)
             }
-            "type_id" => {
-                let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
-                match langid {
-                    Ok(did) => (1u,
-                                Vec::new(),
-                                ty::mk_struct(ccx.tcx, did,
-                                              ccx.tcx.mk_substs(subst::Substs::empty()))),
-                    Err(msg) => {
-                        tcx.sess.span_fatal(it.span, &msg[]);
-                    }
-                }
-            },
+            "type_id" => (1u, Vec::new(), ccx.tcx.types.u64),
             "offset" => {
               (1,
                vec!(
diff --git a/src/test/auxiliary/issue13507.rs b/src/test/auxiliary/issue13507.rs
index c2820a8d4ae..f24721adb5d 100644
--- a/src/test/auxiliary/issue13507.rs
+++ b/src/test/auxiliary/issue13507.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 pub mod testtypes {
-    use std::intrinsics::TypeId;
+    use std::any::TypeId;
 
     pub fn type_ids() -> Vec<TypeId> {
         let mut ids = vec!();
diff --git a/src/test/auxiliary/typeid-intrinsic.rs b/src/test/auxiliary/typeid-intrinsic.rs
index b6c35f48010..82f613ee117 100644
--- a/src/test/auxiliary/typeid-intrinsic.rs
+++ b/src/test/auxiliary/typeid-intrinsic.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::intrinsics;
-use std::intrinsics::TypeId;
+use std::any::TypeId;
 
 pub struct A;
 pub struct B(Option<A>);
@@ -21,13 +20,13 @@ pub type F = Option<int>;
 pub type G = uint;
 pub type H = &'static str;
 
-pub unsafe fn id_A() -> TypeId { intrinsics::type_id::<A>() }
-pub unsafe fn id_B() -> TypeId { intrinsics::type_id::<B>() }
-pub unsafe fn id_C() -> TypeId { intrinsics::type_id::<C>() }
-pub unsafe fn id_D() -> TypeId { intrinsics::type_id::<D>() }
-pub unsafe fn id_E() -> TypeId { intrinsics::type_id::<E>() }
-pub unsafe fn id_F() -> TypeId { intrinsics::type_id::<F>() }
-pub unsafe fn id_G() -> TypeId { intrinsics::type_id::<G>() }
-pub unsafe fn id_H() -> TypeId { intrinsics::type_id::<H>() }
+pub unsafe fn id_A() -> TypeId { TypeId::of::<A>() }
+pub unsafe fn id_B() -> TypeId { TypeId::of::<B>() }
+pub unsafe fn id_C() -> TypeId { TypeId::of::<C>() }
+pub unsafe fn id_D() -> TypeId { TypeId::of::<D>() }
+pub unsafe fn id_E() -> TypeId { TypeId::of::<E>() }
+pub unsafe fn id_F() -> TypeId { TypeId::of::<F>() }
+pub unsafe fn id_G() -> TypeId { TypeId::of::<G>() }
+pub unsafe fn id_H() -> TypeId { TypeId::of::<H>() }
 
-pub unsafe fn foo<T: 'static>() -> TypeId { intrinsics::type_id::<T>() }
+pub unsafe fn foo<T: 'static>() -> TypeId { TypeId::of::<T>() }
diff --git a/src/test/auxiliary/typeid-intrinsic2.rs b/src/test/auxiliary/typeid-intrinsic2.rs
index b6c35f48010..82f613ee117 100644
--- a/src/test/auxiliary/typeid-intrinsic2.rs
+++ b/src/test/auxiliary/typeid-intrinsic2.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::intrinsics;
-use std::intrinsics::TypeId;
+use std::any::TypeId;
 
 pub struct A;
 pub struct B(Option<A>);
@@ -21,13 +20,13 @@ pub type F = Option<int>;
 pub type G = uint;
 pub type H = &'static str;
 
-pub unsafe fn id_A() -> TypeId { intrinsics::type_id::<A>() }
-pub unsafe fn id_B() -> TypeId { intrinsics::type_id::<B>() }
-pub unsafe fn id_C() -> TypeId { intrinsics::type_id::<C>() }
-pub unsafe fn id_D() -> TypeId { intrinsics::type_id::<D>() }
-pub unsafe fn id_E() -> TypeId { intrinsics::type_id::<E>() }
-pub unsafe fn id_F() -> TypeId { intrinsics::type_id::<F>() }
-pub unsafe fn id_G() -> TypeId { intrinsics::type_id::<G>() }
-pub unsafe fn id_H() -> TypeId { intrinsics::type_id::<H>() }
+pub unsafe fn id_A() -> TypeId { TypeId::of::<A>() }
+pub unsafe fn id_B() -> TypeId { TypeId::of::<B>() }
+pub unsafe fn id_C() -> TypeId { TypeId::of::<C>() }
+pub unsafe fn id_D() -> TypeId { TypeId::of::<D>() }
+pub unsafe fn id_E() -> TypeId { TypeId::of::<E>() }
+pub unsafe fn id_F() -> TypeId { TypeId::of::<F>() }
+pub unsafe fn id_G() -> TypeId { TypeId::of::<G>() }
+pub unsafe fn id_H() -> TypeId { TypeId::of::<H>() }
 
-pub unsafe fn foo<T: 'static>() -> TypeId { intrinsics::type_id::<T>() }
+pub unsafe fn foo<T: 'static>() -> TypeId { TypeId::of::<T>() }
diff --git a/src/test/compile-fail/extern-with-type-bounds.rs b/src/test/compile-fail/extern-with-type-bounds.rs
index d2c88865d54..ade8b397e00 100644
--- a/src/test/compile-fail/extern-with-type-bounds.rs
+++ b/src/test/compile-fail/extern-with-type-bounds.rs
@@ -10,11 +10,9 @@
 
 #![feature(intrinsics)]
 
-use std::intrinsics::TypeId;
-
 extern "rust-intrinsic" {
     // Real example from libcore
-    fn type_id<T: ?Sized + 'static>() -> TypeId;
+    fn type_id<T: ?Sized + 'static>() -> u64;
 
     // Silent bounds made explicit to make sure they are actually
     // resolved.
diff --git a/src/test/compile-fail/issue-18389.rs b/src/test/compile-fail/issue-18389.rs
index 37bb1cb1911..20323e99003 100644
--- a/src/test/compile-fail/issue-18389.rs
+++ b/src/test/compile-fail/issue-18389.rs
@@ -11,7 +11,7 @@
 #![feature(unboxed_closures)]
 
 use std::any::Any;
-use std::intrinsics::TypeId;
+use std::any::TypeId;
 
 pub trait Pt {}
 pub trait Rt {}
diff --git a/src/test/run-pass/issue-13507-2.rs b/src/test/run-pass/issue-13507-2.rs
index 4d150e7a68e..1c0283070a2 100644
--- a/src/test/run-pass/issue-13507-2.rs
+++ b/src/test/run-pass/issue-13507-2.rs
@@ -12,7 +12,7 @@
 extern crate issue13507;
 use issue13507::testtypes;
 
-use std::intrinsics::TypeId;
+use std::any::TypeId;
 
 pub fn type_ids() -> Vec<TypeId> {
     let mut ids = vec!();
diff --git a/src/test/run-pass/type-id-higher-rank.rs b/src/test/run-pass/type-id-higher-rank.rs
index 7287d149f51..b114391a36d 100644
--- a/src/test/run-pass/type-id-higher-rank.rs
+++ b/src/test/run-pass/type-id-higher-rank.rs
@@ -13,7 +13,7 @@
 
 #![feature(unboxed_closures)]
 
-use std::intrinsics::TypeId;
+use std::any::TypeId;
 
 fn main() {
     // Bare fns
diff --git a/src/test/run-pass/typeid-intrinsic.rs b/src/test/run-pass/typeid-intrinsic.rs
index e346c4ff349..a251fcc7327 100644
--- a/src/test/run-pass/typeid-intrinsic.rs
+++ b/src/test/run-pass/typeid-intrinsic.rs
@@ -15,41 +15,40 @@ extern crate "typeid-intrinsic" as other1;
 extern crate "typeid-intrinsic2" as other2;
 
 use std::hash::{self, SipHasher};
-use std::intrinsics;
-use std::intrinsics::TypeId;
+use std::any::TypeId;
 
 struct A;
 struct Test;
 
 pub fn main() {
     unsafe {
-        assert_eq!(intrinsics::type_id::<other1::A>(), other1::id_A());
-        assert_eq!(intrinsics::type_id::<other1::B>(), other1::id_B());
-        assert_eq!(intrinsics::type_id::<other1::C>(), other1::id_C());
-        assert_eq!(intrinsics::type_id::<other1::D>(), other1::id_D());
-        assert_eq!(intrinsics::type_id::<other1::E>(), other1::id_E());
-        assert_eq!(intrinsics::type_id::<other1::F>(), other1::id_F());
-        assert_eq!(intrinsics::type_id::<other1::G>(), other1::id_G());
-        assert_eq!(intrinsics::type_id::<other1::H>(), other1::id_H());
+        assert_eq!(TypeId::of::<other1::A>(), other1::id_A());
+        assert_eq!(TypeId::of::<other1::B>(), other1::id_B());
+        assert_eq!(TypeId::of::<other1::C>(), other1::id_C());
+        assert_eq!(TypeId::of::<other1::D>(), other1::id_D());
+        assert_eq!(TypeId::of::<other1::E>(), other1::id_E());
+        assert_eq!(TypeId::of::<other1::F>(), other1::id_F());
+        assert_eq!(TypeId::of::<other1::G>(), other1::id_G());
+        assert_eq!(TypeId::of::<other1::H>(), other1::id_H());
 
-        assert_eq!(intrinsics::type_id::<other2::A>(), other2::id_A());
-        assert_eq!(intrinsics::type_id::<other2::B>(), other2::id_B());
-        assert_eq!(intrinsics::type_id::<other2::C>(), other2::id_C());
-        assert_eq!(intrinsics::type_id::<other2::D>(), other2::id_D());
-        assert_eq!(intrinsics::type_id::<other2::E>(), other2::id_E());
-        assert_eq!(intrinsics::type_id::<other2::F>(), other2::id_F());
-        assert_eq!(intrinsics::type_id::<other2::G>(), other2::id_G());
-        assert_eq!(intrinsics::type_id::<other2::H>(), other2::id_H());
+        assert_eq!(TypeId::of::<other2::A>(), other2::id_A());
+        assert_eq!(TypeId::of::<other2::B>(), other2::id_B());
+        assert_eq!(TypeId::of::<other2::C>(), other2::id_C());
+        assert_eq!(TypeId::of::<other2::D>(), other2::id_D());
+        assert_eq!(TypeId::of::<other2::E>(), other2::id_E());
+        assert_eq!(TypeId::of::<other2::F>(), other2::id_F());
+        assert_eq!(TypeId::of::<other2::G>(), other2::id_G());
+        assert_eq!(TypeId::of::<other2::H>(), other2::id_H());
 
         assert_eq!(other1::id_F(), other2::id_F());
         assert_eq!(other1::id_G(), other2::id_G());
         assert_eq!(other1::id_H(), other2::id_H());
 
-        assert_eq!(intrinsics::type_id::<int>(), other2::foo::<int>());
-        assert_eq!(intrinsics::type_id::<int>(), other1::foo::<int>());
+        assert_eq!(TypeId::of::<int>(), other2::foo::<int>());
+        assert_eq!(TypeId::of::<int>(), other1::foo::<int>());
         assert_eq!(other2::foo::<int>(), other1::foo::<int>());
-        assert_eq!(intrinsics::type_id::<A>(), other2::foo::<A>());
-        assert_eq!(intrinsics::type_id::<A>(), other1::foo::<A>());
+        assert_eq!(TypeId::of::<A>(), other2::foo::<A>());
+        assert_eq!(TypeId::of::<A>(), other1::foo::<A>());
         assert_eq!(other2::foo::<A>(), other1::foo::<A>());
     }