Wrap the return value of the type_id intrinsic in an opaque box

Closes #10594
This commit is contained in:
Corey Richardson 2013-11-27 17:51:11 -05:00
parent 80991bb578
commit 572635b76f
8 changed files with 105 additions and 46 deletions

View 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,

View 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];

View File

@ -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,

View File

@ -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);

View 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>() }
}
}

View 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>);
@ -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>() }

View 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>);
@ -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>() }

View File

@ -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());
}