]> git.lizzy.rs Git - rust.git/commitdiff
Wrap the return value of the type_id intrinsic in an opaque box
authorCorey Richardson <corey@octayn.net>
Wed, 27 Nov 2013 22:51:11 +0000 (17:51 -0500)
committerCorey Richardson <corey@octayn.net>
Sat, 30 Nov 2013 07:58:36 +0000 (02:58 -0500)
Closes #10594

src/librustc/middle/lang_items.rs
src/librustc/middle/trans/intrinsic.rs
src/librustc/middle/typeck/check/mod.rs
src/libstd/any.rs
src/libstd/unstable/intrinsics.rs
src/test/auxiliary/typeid-intrinsic.rs
src/test/auxiliary/typeid-intrinsic2.rs
src/test/run-pass/typeid-intrinsic.rs

index c8f245d5555d8081bada6cd1a7e7fe70fcd9e9a0..d8eaffd5563cbdd1514dedf83ca8b4de7356ce5f 100644 (file)
@@ -82,16 +82,18 @@ pub enum LangItem {
     OpaqueStructLangItem,              // 38
 
     EventLoopFactoryLangItem,          // 39
+
+    TypeIdLangItem,                    // 40
 }
 
 pub struct LanguageItems {
-    items: [Option<ast::DefId>, ..40]
+    items: [Option<ast::DefId>, ..41]
 }
 
 impl LanguageItems {
     pub fn new() -> LanguageItems {
         LanguageItems {
-            items: [ None, ..40 ]
+            items: [ None, ..41 ]
         }
     }
 
@@ -148,6 +150,8 @@ pub fn item_name(index: uint) -> &'static str {
 
             39 => "event_loop_factory",
 
+            40 => "type_id",
+
             _ => "???"
         }
     }
@@ -298,6 +302,9 @@ pub fn opaque(&self) -> Option<ast::DefId> {
     pub fn event_loop_factory(&self) -> Option<ast::DefId> {
         self.items[EventLoopFactoryLangItem as uint]
     }
+    pub fn type_id(&self) -> Option<ast::DefId> {
+        self.items[TypeIdLangItem as uint]
+    }
 }
 
 struct LanguageItemCollector {
@@ -382,6 +389,7 @@ pub fn new(session: Session) -> LanguageItemCollector {
         item_refs.insert("ty_visitor", TyVisitorTraitLangItem as uint);
         item_refs.insert("opaque", OpaqueStructLangItem as uint);
         item_refs.insert("event_loop_factory", EventLoopFactoryLangItem as uint);
+        item_refs.insert("type_id", TypeIdLangItem as uint);
 
         LanguageItemCollector {
             session: session,
index e57eed480eb53e41f8a5ba818e36f39e400ee203..110e964bdbc48aac602af0da051fa6f6f6fc541e 100644 (file)
@@ -287,7 +287,16 @@ fn count_zeros_intrinsic(bcx: @mut Block, name: &'static str) {
         "type_id" => {
             let hash = ty::hash_crate_independent(ccx.tcx, substs.tys[0],
                                                   ccx.link_meta.extras_hash);
-            Ret(bcx, C_i64(hash as i64))
+            // NB: This needs to be kept in lockstep with the TypeId struct in
+            //     libstd/unstable/intrinsics.rs
+            let val = C_named_struct(type_of::type_of(ccx, output_type), [C_u64(hash)]);
+            match bcx.fcx.llretptr {
+                Some(ptr) => {
+                    Store(bcx, val, ptr);
+                    RetVoid(bcx);
+                },
+                None => Ret(bcx, val)
+            }
         }
         "init" => {
             let tp_ty = substs.tys[0];
index 8caf873a8896ab7a7cd0a0c8fd009400a7216884..e3160dbc40236149beba90724b711ee36afdb249 100644 (file)
 use middle::typeck::{lookup_def_ccx};
 use middle::typeck::no_params;
 use middle::typeck::{require_same_types, method_map, vtable_map};
+use middle::lang_items::TypeIdLangItem;
 use util::common::{block_query, indenter, loop_query};
 use util::ppaux::UserString;
 use util::ppaux;
@@ -4013,7 +4014,17 @@ fn param(ccx: @mut CrateCtxt, n: uint) -> ty::t {
               });
               (1u, ~[], td_ptr)
             }
-            "type_id" => (1u, ~[], ty::mk_u64()),
+            "type_id" => {
+                let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
+                match langid {
+                    Ok(did) => (1u, ~[], ty::mk_struct(ccx.tcx, did, substs {
+                                                 self_ty: None,
+                                                 tps: ~[],
+                                                 regions: ty::NonerasedRegions(opt_vec::Empty)
+                                                 }) ),
+                    Err(msg) => { tcx.sess.span_fatal(it.span, msg); }
+                }
+            },
             "visit_tydesc" => {
               let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
                   Ok(t) => t,
index e02bf9f4ba8a316cf57b81770635db5590df078b..7af12bef7b5c29280bffd799823696d68193234f 100644 (file)
 //! of any type.
 
 use cast::transmute;
+#[cfg(stage0)]
 use cmp::Eq;
 use option::{Option, Some, None};
+#[cfg(stage0)]
 use to_bytes::{IterBytes, Cb};
 use to_str::ToStr;
 use unstable::intrinsics;
 use util::Void;
+#[cfg(not(stage0))]
+use unstable::intrinsics::TypeId;
 
 ///////////////////////////////////////////////////////////////////////////////
 // TypeId
 ///////////////////////////////////////////////////////////////////////////////
 
 /// `TypeId` represents a globally unique identifier for a type
+#[cfg(stage0)]
 pub struct TypeId {
     priv t: u64,
 }
 
+#[cfg(stage0)]
 impl TypeId {
     /// Returns the `TypeId` of the type this generic function has been instantiated with
     #[inline]
@@ -36,6 +42,7 @@ pub fn of<T: 'static>() -> TypeId {
     }
 }
 
+#[cfg(stage0)]
 impl Eq for TypeId {
     #[inline]
     fn eq(&self, &other: &TypeId) -> bool {
@@ -43,6 +50,7 @@ fn eq(&self, &other: &TypeId) -> bool {
     }
 }
 
+#[cfg(stage0)]
 impl IterBytes for TypeId {
     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
         self.t.iter_bytes(lsb0, f)
@@ -189,29 +197,6 @@ mod tests {
 
     static TEST: &'static str = "Test";
 
-    #[test]
-    fn type_id() {
-        let (a, b, c) = (TypeId::of::<uint>(), TypeId::of::<&'static str>(),
-                         TypeId::of::<Test>());
-        let (d, e, f) = (TypeId::of::<uint>(), TypeId::of::<&'static str>(),
-                         TypeId::of::<Test>());
-
-        assert!(a != b);
-        assert!(a != c);
-        assert!(b != c);
-
-        assert_eq!(a, d);
-        assert_eq!(b, e);
-        assert_eq!(c, f);
-    }
-
-    #[test]
-    fn type_id_hash() {
-        let (a, b) = (TypeId::of::<uint>(), TypeId::of::<uint>());
-
-        assert_eq!(a.hash(), b.hash());
-    }
-
     #[test]
     fn any_as_void_ptr() {
         let (a, b, c) = (~5u as ~Any, ~TEST as ~Any, ~Test as ~Any);
index 89a51a5ddddd3e4956e72f96638d08ab064626c7..01b4225d70bad4126f8e613264ad422c953287c5 100644 (file)
@@ -34,7 +34,7 @@
 
 // This is needed to prevent duplicate lang item definitions.
 #[cfg(test)]
-pub use realstd::unstable::intrinsics::{TyDesc, Opaque, TyVisitor};
+pub use realstd::unstable::intrinsics::{TyDesc, Opaque, TyVisitor, TypeId};
 
 pub type GlueFn = extern "Rust" fn(*i8);
 
@@ -313,7 +313,11 @@ fn visit_leave_fn(&mut self, purity: uint, proto: uint,
     /// 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(stage0)]
     pub fn type_id<T: 'static>() -> u64;
+    #[cfg(not(stage0))]
+    pub fn type_id<T: 'static>() -> TypeId;
+
 
     /// Create a value initialized to zero.
     ///
@@ -486,3 +490,22 @@ fn visit_leave_fn(&mut self, purity: uint, proto: uint,
 #[cfg(target_endian = "big")]    pub fn to_be32(x: i32) -> i32 { x }
 #[cfg(target_endian = "little")] pub fn to_be64(x: i64) -> i64 { unsafe { bswap64(x) } }
 #[cfg(target_endian = "big")]    pub fn to_be64(x: i64) -> i64 { x }
+
+
+/// `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
+#[deriving(Eq, IterBytes)]
+#[cfg(not(test))]
+pub struct TypeId {
+    priv t: u64,
+}
+
+#[cfg(not(test))]
+impl TypeId {
+    /// Returns the `TypeId` of the type this generic function has been instantiated with
+    #[cfg(not(stage0))]
+    pub fn of<T: 'static>() -> TypeId {
+        unsafe { type_id::<T>() }
+    }
+}
index 768b0d19da3d1695b1812eddbeb351d9754094b7..9bb867372619a2e650be659935f31d4dbc51b9d2 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use std::unstable::intrinsics;
+use std::unstable::intrinsics::TypeId;
 
 pub struct A;
 pub struct B(Option<A>);
 pub type G = uint;
 pub type H = &'static str;
 
-pub unsafe fn id_A() -> u64 { intrinsics::type_id::<A>() }
-pub unsafe fn id_B() -> u64 { intrinsics::type_id::<B>() }
-pub unsafe fn id_C() -> u64 { intrinsics::type_id::<C>() }
-pub unsafe fn id_D() -> u64 { intrinsics::type_id::<D>() }
-pub unsafe fn id_E() -> u64 { intrinsics::type_id::<E>() }
-pub unsafe fn id_F() -> u64 { intrinsics::type_id::<F>() }
-pub unsafe fn id_G() -> u64 { intrinsics::type_id::<G>() }
-pub unsafe fn id_H() -> u64 { intrinsics::type_id::<H>() }
+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 foo<T: 'static>() -> u64 { intrinsics::type_id::<T>() }
+pub unsafe fn foo<T: 'static>() -> TypeId { intrinsics::type_id::<T>() }
index 768b0d19da3d1695b1812eddbeb351d9754094b7..9bb867372619a2e650be659935f31d4dbc51b9d2 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use std::unstable::intrinsics;
+use std::unstable::intrinsics::TypeId;
 
 pub struct A;
 pub struct B(Option<A>);
 pub type G = uint;
 pub type H = &'static str;
 
-pub unsafe fn id_A() -> u64 { intrinsics::type_id::<A>() }
-pub unsafe fn id_B() -> u64 { intrinsics::type_id::<B>() }
-pub unsafe fn id_C() -> u64 { intrinsics::type_id::<C>() }
-pub unsafe fn id_D() -> u64 { intrinsics::type_id::<D>() }
-pub unsafe fn id_E() -> u64 { intrinsics::type_id::<E>() }
-pub unsafe fn id_F() -> u64 { intrinsics::type_id::<F>() }
-pub unsafe fn id_G() -> u64 { intrinsics::type_id::<G>() }
-pub unsafe fn id_H() -> u64 { intrinsics::type_id::<H>() }
+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 foo<T: 'static>() -> u64 { intrinsics::type_id::<T>() }
+pub unsafe fn foo<T: 'static>() -> TypeId { intrinsics::type_id::<T>() }
index 3fd7c05796bc4b46749838f1148452732753f4eb..1999043c6cdd2bc14888e19a5a1b391c0f0042a7 100644 (file)
 extern mod other2(name = "typeid-intrinsic2");
 
 use std::unstable::intrinsics;
+use std::unstable::intrinsics::TypeId;
 
 struct A;
+struct Test;
 
 fn main() {
     unsafe {
@@ -50,4 +52,23 @@ fn main() {
         assert_eq!(intrinsics::type_id::<A>(), other1::foo::<A>());
         assert_eq!(other2::foo::<A>(), other1::foo::<A>());
     }
+
+    // sanity test of TypeId
+    let (a, b, c) = (TypeId::of::<uint>(), TypeId::of::<&'static str>(),
+                     TypeId::of::<Test>());
+    let (d, e, f) = (TypeId::of::<uint>(), TypeId::of::<&'static str>(),
+                     TypeId::of::<Test>());
+
+    assert!(a != b);
+    assert!(a != c);
+    assert!(b != c);
+
+    assert_eq!(a, d);
+    assert_eq!(b, e);
+    assert_eq!(c, f);
+
+    // check it has a hash
+    let (a, b) = (TypeId::of::<uint>(), TypeId::of::<uint>());
+
+    assert_eq!(a.hash(), b.hash());
 }