diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index c8f245d5555..d8eaffd5563 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -82,16 +82,18 @@ pub enum LangItem { OpaqueStructLangItem, // 38 EventLoopFactoryLangItem, // 39 + + TypeIdLangItem, // 40 } pub struct LanguageItems { - items: [Option, ..40] + items: [Option, ..41] } impl LanguageItems { pub fn new() -> LanguageItems { LanguageItems { - items: [ None, ..40 ] + items: [ None, ..41 ] } } @@ -148,6 +150,8 @@ impl LanguageItems { 39 => "event_loop_factory", + 40 => "type_id", + _ => "???" } } @@ -298,6 +302,9 @@ impl LanguageItems { pub fn event_loop_factory(&self) -> Option { self.items[EventLoopFactoryLangItem as uint] } + pub fn type_id(&self) -> Option { + self.items[TypeIdLangItem as uint] + } } struct LanguageItemCollector { @@ -382,6 +389,7 @@ impl 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, diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs index e57eed480eb..110e964bdbc 100644 --- a/src/librustc/middle/trans/intrinsic.rs +++ b/src/librustc/middle/trans/intrinsic.rs @@ -287,7 +287,16 @@ pub fn trans_intrinsic(ccx: @mut CrateContext, "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]; diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 8caf873a889..e3160dbc402 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -105,6 +105,7 @@ use middle::typeck::rscope::RegionScope; 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 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) { }); (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, diff --git a/src/libstd/any.rs b/src/libstd/any.rs index e02bf9f4ba8..7af12bef7b5 100644 --- a/src/libstd/any.rs +++ b/src/libstd/any.rs @@ -12,22 +12,28 @@ //! 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 @@ impl TypeId { } } +#[cfg(stage0)] impl Eq for TypeId { #[inline] fn eq(&self, &other: &TypeId) -> bool { @@ -43,6 +50,7 @@ impl Eq for TypeId { } } +#[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::(), TypeId::of::<&'static str>(), - TypeId::of::()); - let (d, e, f) = (TypeId::of::(), TypeId::of::<&'static str>(), - TypeId::of::()); - - 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::(), TypeId::of::()); - - 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); diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs index 89a51a5dddd..01b4225d70b 100644 --- a/src/libstd/unstable/intrinsics.rs +++ b/src/libstd/unstable/intrinsics.rs @@ -34,7 +34,7 @@ A quick refresher on memory ordering: // 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 @@ 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(stage0)] pub fn type_id() -> u64; + #[cfg(not(stage0))] + pub fn type_id() -> TypeId; + /// Create a value initialized to zero. /// @@ -486,3 +490,22 @@ extern "rust-intrinsic" { #[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() -> TypeId { + unsafe { type_id::() } + } +} diff --git a/src/test/auxiliary/typeid-intrinsic.rs b/src/test/auxiliary/typeid-intrinsic.rs index 768b0d19da3..9bb86737261 100644 --- a/src/test/auxiliary/typeid-intrinsic.rs +++ b/src/test/auxiliary/typeid-intrinsic.rs @@ -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); @@ -20,13 +21,13 @@ pub type F = Option; pub type G = uint; pub type H = &'static str; -pub unsafe fn id_A() -> u64 { intrinsics::type_id::() } -pub unsafe fn id_B() -> u64 { intrinsics::type_id::() } -pub unsafe fn id_C() -> u64 { intrinsics::type_id::() } -pub unsafe fn id_D() -> u64 { intrinsics::type_id::() } -pub unsafe fn id_E() -> u64 { intrinsics::type_id::() } -pub unsafe fn id_F() -> u64 { intrinsics::type_id::() } -pub unsafe fn id_G() -> u64 { intrinsics::type_id::() } -pub unsafe fn id_H() -> u64 { intrinsics::type_id::() } +pub unsafe fn id_A() -> TypeId { intrinsics::type_id::() } +pub unsafe fn id_B() -> TypeId { intrinsics::type_id::() } +pub unsafe fn id_C() -> TypeId { intrinsics::type_id::() } +pub unsafe fn id_D() -> TypeId { intrinsics::type_id::() } +pub unsafe fn id_E() -> TypeId { intrinsics::type_id::() } +pub unsafe fn id_F() -> TypeId { intrinsics::type_id::() } +pub unsafe fn id_G() -> TypeId { intrinsics::type_id::() } +pub unsafe fn id_H() -> TypeId { intrinsics::type_id::() } -pub unsafe fn foo() -> u64 { intrinsics::type_id::() } +pub unsafe fn foo() -> TypeId { intrinsics::type_id::() } diff --git a/src/test/auxiliary/typeid-intrinsic2.rs b/src/test/auxiliary/typeid-intrinsic2.rs index 768b0d19da3..9bb86737261 100644 --- a/src/test/auxiliary/typeid-intrinsic2.rs +++ b/src/test/auxiliary/typeid-intrinsic2.rs @@ -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); @@ -20,13 +21,13 @@ pub type F = Option; pub type G = uint; pub type H = &'static str; -pub unsafe fn id_A() -> u64 { intrinsics::type_id::() } -pub unsafe fn id_B() -> u64 { intrinsics::type_id::() } -pub unsafe fn id_C() -> u64 { intrinsics::type_id::() } -pub unsafe fn id_D() -> u64 { intrinsics::type_id::() } -pub unsafe fn id_E() -> u64 { intrinsics::type_id::() } -pub unsafe fn id_F() -> u64 { intrinsics::type_id::() } -pub unsafe fn id_G() -> u64 { intrinsics::type_id::() } -pub unsafe fn id_H() -> u64 { intrinsics::type_id::() } +pub unsafe fn id_A() -> TypeId { intrinsics::type_id::() } +pub unsafe fn id_B() -> TypeId { intrinsics::type_id::() } +pub unsafe fn id_C() -> TypeId { intrinsics::type_id::() } +pub unsafe fn id_D() -> TypeId { intrinsics::type_id::() } +pub unsafe fn id_E() -> TypeId { intrinsics::type_id::() } +pub unsafe fn id_F() -> TypeId { intrinsics::type_id::() } +pub unsafe fn id_G() -> TypeId { intrinsics::type_id::() } +pub unsafe fn id_H() -> TypeId { intrinsics::type_id::() } -pub unsafe fn foo() -> u64 { intrinsics::type_id::() } +pub unsafe fn foo() -> TypeId { intrinsics::type_id::() } diff --git a/src/test/run-pass/typeid-intrinsic.rs b/src/test/run-pass/typeid-intrinsic.rs index 3fd7c05796b..1999043c6cd 100644 --- a/src/test/run-pass/typeid-intrinsic.rs +++ b/src/test/run-pass/typeid-intrinsic.rs @@ -16,8 +16,10 @@ extern mod other1(name = "typeid-intrinsic"); 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::(), other1::foo::()); assert_eq!(other2::foo::(), other1::foo::()); } + + // sanity test of TypeId + let (a, b, c) = (TypeId::of::(), TypeId::of::<&'static str>(), + TypeId::of::()); + let (d, e, f) = (TypeId::of::(), TypeId::of::<&'static str>(), + TypeId::of::()); + + 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::(), TypeId::of::()); + + assert_eq!(a.hash(), b.hash()); }