Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 30, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions src/librustc/middle/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 ]
}
}

Expand Down Expand Up @@ -148,6 +150,8 @@ impl LanguageItems {

39 => "event_loop_factory",

40 => "type_id",

_ => "???"
}
}
Expand Down Expand Up @@ -298,6 +302,9 @@ impl LanguageItems {
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 {
Expand Down Expand Up @@ -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,
Expand Down
11 changes: 10 additions & 1 deletion src/librustc/middle/trans/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down
13 changes: 12 additions & 1 deletion src/librustc/middle/typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
31 changes: 8 additions & 23 deletions src/libstd/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -36,13 +42,15 @@ impl TypeId {
}
}

#[cfg(stage0)]
impl Eq for TypeId {
#[inline]
fn eq(&self, &other: &TypeId) -> bool {
self.t == other.t
}
}

#[cfg(stage0)]
impl IterBytes for TypeId {
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
self.t.iter_bytes(lsb0, f)
Expand Down Expand Up @@ -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);
Expand Down
25 changes: 24 additions & 1 deletion src/libstd/unstable/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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<T: 'static>() -> u64;
#[cfg(not(stage0))]
pub fn type_id<T: 'static>() -> TypeId;


/// Create a value initialized to zero.
///
Expand Down Expand Up @@ -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<T: 'static>() -> TypeId {
unsafe { type_id::<T>() }
}
}
19 changes: 10 additions & 9 deletions src/test/auxiliary/typeid-intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>);
Expand All @@ -20,13 +21,13 @@ pub type F = Option<int>;
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>() }
19 changes: 10 additions & 9 deletions src/test/auxiliary/typeid-intrinsic2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>);
Expand All @@ -20,13 +21,13 @@ pub type F = Option<int>;
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>() }
21 changes: 21 additions & 0 deletions src/test/run-pass/typeid-intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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());
}