Wrap the return value of the type_id intrinsic in an opaque box
Closes #10594
This commit is contained in:
parent
80991bb578
commit
572635b76f
@ -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,
|
||||
|
@ -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];
|
||||
|
@ -105,6 +105,7 @@
|
||||
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,
|
||||
|
@ -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 @@ 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);
|
||||
|
@ -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>() }
|
||||
}
|
||||
}
|
||||
|
@ -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>);
|
||||
@ -20,13 +21,13 @@
|
||||
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>() }
|
||||
|
@ -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>);
|
||||
@ -20,13 +21,13 @@
|
||||
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>() }
|
||||
|
@ -16,8 +16,10 @@
|
||||
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());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user