mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-07 12:33:14 +00:00
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
|
OpaqueStructLangItem, // 38
|
||||||
|
|
||||||
EventLoopFactoryLangItem, // 39
|
EventLoopFactoryLangItem, // 39
|
||||||
|
|
||||||
|
TypeIdLangItem, // 40
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LanguageItems {
|
pub struct LanguageItems {
|
||||||
items: [Option<ast::DefId>, ..40]
|
items: [Option<ast::DefId>, ..41]
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LanguageItems {
|
impl LanguageItems {
|
||||||
pub fn new() -> LanguageItems {
|
pub fn new() -> LanguageItems {
|
||||||
LanguageItems {
|
LanguageItems {
|
||||||
items: [ None, ..40 ]
|
items: [ None, ..41 ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,6 +150,8 @@ impl LanguageItems {
|
|||||||
|
|
||||||
39 => "event_loop_factory",
|
39 => "event_loop_factory",
|
||||||
|
|
||||||
|
40 => "type_id",
|
||||||
|
|
||||||
_ => "???"
|
_ => "???"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -298,6 +302,9 @@ impl LanguageItems {
|
|||||||
pub fn event_loop_factory(&self) -> Option<ast::DefId> {
|
pub fn event_loop_factory(&self) -> Option<ast::DefId> {
|
||||||
self.items[EventLoopFactoryLangItem as uint]
|
self.items[EventLoopFactoryLangItem as uint]
|
||||||
}
|
}
|
||||||
|
pub fn type_id(&self) -> Option<ast::DefId> {
|
||||||
|
self.items[TypeIdLangItem as uint]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LanguageItemCollector {
|
struct LanguageItemCollector {
|
||||||
@ -382,6 +389,7 @@ impl LanguageItemCollector {
|
|||||||
item_refs.insert("ty_visitor", TyVisitorTraitLangItem as uint);
|
item_refs.insert("ty_visitor", TyVisitorTraitLangItem as uint);
|
||||||
item_refs.insert("opaque", OpaqueStructLangItem as uint);
|
item_refs.insert("opaque", OpaqueStructLangItem as uint);
|
||||||
item_refs.insert("event_loop_factory", EventLoopFactoryLangItem as uint);
|
item_refs.insert("event_loop_factory", EventLoopFactoryLangItem as uint);
|
||||||
|
item_refs.insert("type_id", TypeIdLangItem as uint);
|
||||||
|
|
||||||
LanguageItemCollector {
|
LanguageItemCollector {
|
||||||
session: session,
|
session: session,
|
||||||
|
@ -287,7 +287,16 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
|||||||
"type_id" => {
|
"type_id" => {
|
||||||
let hash = ty::hash_crate_independent(ccx.tcx, substs.tys[0],
|
let hash = ty::hash_crate_independent(ccx.tcx, substs.tys[0],
|
||||||
ccx.link_meta.extras_hash);
|
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" => {
|
"init" => {
|
||||||
let tp_ty = substs.tys[0];
|
let tp_ty = substs.tys[0];
|
||||||
|
@ -105,6 +105,7 @@ use middle::typeck::rscope::RegionScope;
|
|||||||
use middle::typeck::{lookup_def_ccx};
|
use middle::typeck::{lookup_def_ccx};
|
||||||
use middle::typeck::no_params;
|
use middle::typeck::no_params;
|
||||||
use middle::typeck::{require_same_types, method_map, vtable_map};
|
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::common::{block_query, indenter, loop_query};
|
||||||
use util::ppaux::UserString;
|
use util::ppaux::UserString;
|
||||||
use util::ppaux;
|
use util::ppaux;
|
||||||
@ -4013,7 +4014,17 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
|
|||||||
});
|
});
|
||||||
(1u, ~[], td_ptr)
|
(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" => {
|
"visit_tydesc" => {
|
||||||
let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
|
let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
|
||||||
Ok(t) => t,
|
Ok(t) => t,
|
||||||
|
@ -12,22 +12,28 @@
|
|||||||
//! of any type.
|
//! of any type.
|
||||||
|
|
||||||
use cast::transmute;
|
use cast::transmute;
|
||||||
|
#[cfg(stage0)]
|
||||||
use cmp::Eq;
|
use cmp::Eq;
|
||||||
use option::{Option, Some, None};
|
use option::{Option, Some, None};
|
||||||
|
#[cfg(stage0)]
|
||||||
use to_bytes::{IterBytes, Cb};
|
use to_bytes::{IterBytes, Cb};
|
||||||
use to_str::ToStr;
|
use to_str::ToStr;
|
||||||
use unstable::intrinsics;
|
use unstable::intrinsics;
|
||||||
use util::Void;
|
use util::Void;
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
use unstable::intrinsics::TypeId;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// TypeId
|
// TypeId
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/// `TypeId` represents a globally unique identifier for a type
|
/// `TypeId` represents a globally unique identifier for a type
|
||||||
|
#[cfg(stage0)]
|
||||||
pub struct TypeId {
|
pub struct TypeId {
|
||||||
priv t: u64,
|
priv t: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(stage0)]
|
||||||
impl TypeId {
|
impl TypeId {
|
||||||
/// Returns the `TypeId` of the type this generic function has been instantiated with
|
/// Returns the `TypeId` of the type this generic function has been instantiated with
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -36,6 +42,7 @@ impl TypeId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(stage0)]
|
||||||
impl Eq for TypeId {
|
impl Eq for TypeId {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn eq(&self, &other: &TypeId) -> bool {
|
fn eq(&self, &other: &TypeId) -> bool {
|
||||||
@ -43,6 +50,7 @@ impl Eq for TypeId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(stage0)]
|
||||||
impl IterBytes for TypeId {
|
impl IterBytes for TypeId {
|
||||||
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
|
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
|
||||||
self.t.iter_bytes(lsb0, f)
|
self.t.iter_bytes(lsb0, f)
|
||||||
@ -189,29 +197,6 @@ mod tests {
|
|||||||
|
|
||||||
static TEST: &'static str = "Test";
|
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]
|
#[test]
|
||||||
fn any_as_void_ptr() {
|
fn any_as_void_ptr() {
|
||||||
let (a, b, c) = (~5u as ~Any, ~TEST as ~Any, ~Test as ~Any);
|
let (a, b, c) = (~5u as ~Any, ~TEST as ~Any, ~Test as ~Any);
|
||||||
|
@ -34,7 +34,7 @@ A quick refresher on memory ordering:
|
|||||||
|
|
||||||
// This is needed to prevent duplicate lang item definitions.
|
// This is needed to prevent duplicate lang item definitions.
|
||||||
#[cfg(test)]
|
#[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);
|
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
|
/// Gets an identifier which is globally unique to the specified type. This
|
||||||
/// function will return the same value for a type regardless of whichever
|
/// function will return the same value for a type regardless of whichever
|
||||||
/// crate it is invoked in.
|
/// crate it is invoked in.
|
||||||
|
#[cfg(stage0)]
|
||||||
pub fn type_id<T: 'static>() -> u64;
|
pub fn type_id<T: 'static>() -> u64;
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
pub fn type_id<T: 'static>() -> TypeId;
|
||||||
|
|
||||||
|
|
||||||
/// Create a value initialized to zero.
|
/// 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 = "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 = "little")] pub fn to_be64(x: i64) -> i64 { unsafe { bswap64(x) } }
|
||||||
#[cfg(target_endian = "big")] pub fn to_be64(x: i64) -> i64 { 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.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::unstable::intrinsics;
|
use std::unstable::intrinsics;
|
||||||
|
use std::unstable::intrinsics::TypeId;
|
||||||
|
|
||||||
pub struct A;
|
pub struct A;
|
||||||
pub struct B(Option<A>);
|
pub struct B(Option<A>);
|
||||||
@ -20,13 +21,13 @@ pub type F = Option<int>;
|
|||||||
pub type G = uint;
|
pub type G = uint;
|
||||||
pub type H = &'static str;
|
pub type H = &'static str;
|
||||||
|
|
||||||
pub unsafe fn id_A() -> u64 { intrinsics::type_id::<A>() }
|
pub unsafe fn id_A() -> TypeId { intrinsics::type_id::<A>() }
|
||||||
pub unsafe fn id_B() -> u64 { intrinsics::type_id::<B>() }
|
pub unsafe fn id_B() -> TypeId { intrinsics::type_id::<B>() }
|
||||||
pub unsafe fn id_C() -> u64 { intrinsics::type_id::<C>() }
|
pub unsafe fn id_C() -> TypeId { intrinsics::type_id::<C>() }
|
||||||
pub unsafe fn id_D() -> u64 { intrinsics::type_id::<D>() }
|
pub unsafe fn id_D() -> TypeId { intrinsics::type_id::<D>() }
|
||||||
pub unsafe fn id_E() -> u64 { intrinsics::type_id::<E>() }
|
pub unsafe fn id_E() -> TypeId { intrinsics::type_id::<E>() }
|
||||||
pub unsafe fn id_F() -> u64 { intrinsics::type_id::<F>() }
|
pub unsafe fn id_F() -> TypeId { intrinsics::type_id::<F>() }
|
||||||
pub unsafe fn id_G() -> u64 { intrinsics::type_id::<G>() }
|
pub unsafe fn id_G() -> TypeId { intrinsics::type_id::<G>() }
|
||||||
pub unsafe fn id_H() -> u64 { intrinsics::type_id::<H>() }
|
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.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::unstable::intrinsics;
|
use std::unstable::intrinsics;
|
||||||
|
use std::unstable::intrinsics::TypeId;
|
||||||
|
|
||||||
pub struct A;
|
pub struct A;
|
||||||
pub struct B(Option<A>);
|
pub struct B(Option<A>);
|
||||||
@ -20,13 +21,13 @@ pub type F = Option<int>;
|
|||||||
pub type G = uint;
|
pub type G = uint;
|
||||||
pub type H = &'static str;
|
pub type H = &'static str;
|
||||||
|
|
||||||
pub unsafe fn id_A() -> u64 { intrinsics::type_id::<A>() }
|
pub unsafe fn id_A() -> TypeId { intrinsics::type_id::<A>() }
|
||||||
pub unsafe fn id_B() -> u64 { intrinsics::type_id::<B>() }
|
pub unsafe fn id_B() -> TypeId { intrinsics::type_id::<B>() }
|
||||||
pub unsafe fn id_C() -> u64 { intrinsics::type_id::<C>() }
|
pub unsafe fn id_C() -> TypeId { intrinsics::type_id::<C>() }
|
||||||
pub unsafe fn id_D() -> u64 { intrinsics::type_id::<D>() }
|
pub unsafe fn id_D() -> TypeId { intrinsics::type_id::<D>() }
|
||||||
pub unsafe fn id_E() -> u64 { intrinsics::type_id::<E>() }
|
pub unsafe fn id_E() -> TypeId { intrinsics::type_id::<E>() }
|
||||||
pub unsafe fn id_F() -> u64 { intrinsics::type_id::<F>() }
|
pub unsafe fn id_F() -> TypeId { intrinsics::type_id::<F>() }
|
||||||
pub unsafe fn id_G() -> u64 { intrinsics::type_id::<G>() }
|
pub unsafe fn id_G() -> TypeId { intrinsics::type_id::<G>() }
|
||||||
pub unsafe fn id_H() -> u64 { intrinsics::type_id::<H>() }
|
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 other1(name = "typeid-intrinsic");
|
|||||||
extern mod other2(name = "typeid-intrinsic2");
|
extern mod other2(name = "typeid-intrinsic2");
|
||||||
|
|
||||||
use std::unstable::intrinsics;
|
use std::unstable::intrinsics;
|
||||||
|
use std::unstable::intrinsics::TypeId;
|
||||||
|
|
||||||
struct A;
|
struct A;
|
||||||
|
struct Test;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -50,4 +52,23 @@ fn main() {
|
|||||||
assert_eq!(intrinsics::type_id::<A>(), other1::foo::<A>());
|
assert_eq!(intrinsics::type_id::<A>(), other1::foo::<A>());
|
||||||
assert_eq!(other2::foo::<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