parent
3a15482b9c
commit
61637439dc
@ -274,6 +274,11 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
||||
let td = PointerCast(bcx, static_ti.tydesc, userland_tydesc_ty);
|
||||
Ret(bcx, td);
|
||||
}
|
||||
"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))
|
||||
}
|
||||
"init" => {
|
||||
let tp_ty = substs.tys[0];
|
||||
let lltp_ty = type_of::type_of(ccx, tp_ty);
|
||||
|
@ -4724,3 +4724,154 @@ pub fn trait_of_method(tcx: ctxt, def_id: ast::DefId)
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
/// Creates a hash of the type `t` which will be the same no matter what crate
|
||||
/// context it's calculated within. This is used by the `type_id` intrinsic.
|
||||
pub fn hash_crate_independent(tcx: ctxt, t: t, local_hash: @str) -> u64 {
|
||||
use std::hash::{SipState, Streaming};
|
||||
use metadata::cstore;
|
||||
|
||||
let mut hash = SipState::new(0, 0);
|
||||
let region = |_hash: &mut SipState, r: Region| {
|
||||
match r {
|
||||
re_static => {}
|
||||
|
||||
re_empty | re_bound(*) | re_free(*) | re_scope(*) | re_infer(*) =>
|
||||
tcx.sess.bug("non-static region found when hashing a type")
|
||||
}
|
||||
};
|
||||
let vstore = |hash: &mut SipState, v: vstore| {
|
||||
match v {
|
||||
vstore_fixed(_) => hash.input([0]),
|
||||
vstore_uniq => hash.input([1]),
|
||||
vstore_box => hash.input([2]),
|
||||
vstore_slice(r) => {
|
||||
hash.input([3]);
|
||||
region(hash, r);
|
||||
}
|
||||
}
|
||||
};
|
||||
let did = |hash: &mut SipState, did: DefId| {
|
||||
let h = if ast_util::is_local(did) {
|
||||
local_hash
|
||||
} else {
|
||||
cstore::get_crate_hash(tcx.sess.cstore, did.crate)
|
||||
};
|
||||
hash.input(h.as_bytes());
|
||||
iter(hash, &did.node);
|
||||
};
|
||||
let mt = |hash: &mut SipState, mt: mt| {
|
||||
iter(hash, &mt.mutbl);
|
||||
};
|
||||
fn iter<T: IterBytes>(hash: &mut SipState, t: &T) {
|
||||
do t.iter_bytes(true) |bytes| { hash.input(bytes); true };
|
||||
}
|
||||
do ty::walk_ty(t) |t| {
|
||||
match ty::get(t).sty {
|
||||
ty_nil => hash.input([0]),
|
||||
ty_bot => hash.input([1]),
|
||||
ty_bool => hash.input([2]),
|
||||
ty_char => hash.input([3]),
|
||||
ty_int(i) => {
|
||||
hash.input([4]);
|
||||
iter(&mut hash, &i);
|
||||
}
|
||||
ty_uint(u) => {
|
||||
hash.input([5]);
|
||||
iter(&mut hash, &u);
|
||||
}
|
||||
ty_float(f) => {
|
||||
hash.input([6]);
|
||||
iter(&mut hash, &f);
|
||||
}
|
||||
ty_estr(v) => {
|
||||
hash.input([7]);
|
||||
vstore(&mut hash, v);
|
||||
}
|
||||
ty_enum(d, _) => {
|
||||
hash.input([8]);
|
||||
did(&mut hash, d);
|
||||
}
|
||||
ty_box(m) => {
|
||||
hash.input([9]);
|
||||
mt(&mut hash, m);
|
||||
}
|
||||
ty_uniq(m) => {
|
||||
hash.input([10]);
|
||||
mt(&mut hash, m);
|
||||
}
|
||||
ty_evec(m, v) => {
|
||||
hash.input([11]);
|
||||
mt(&mut hash, m);
|
||||
vstore(&mut hash, v);
|
||||
}
|
||||
ty_ptr(m) => {
|
||||
hash.input([12]);
|
||||
mt(&mut hash, m);
|
||||
}
|
||||
ty_rptr(r, m) => {
|
||||
hash.input([13]);
|
||||
region(&mut hash, r);
|
||||
mt(&mut hash, m);
|
||||
}
|
||||
ty_bare_fn(ref b) => {
|
||||
hash.input([14]);
|
||||
iter(&mut hash, &b.purity);
|
||||
iter(&mut hash, &b.abis);
|
||||
}
|
||||
ty_closure(ref c) => {
|
||||
hash.input([15]);
|
||||
iter(&mut hash, &c.purity);
|
||||
iter(&mut hash, &c.sigil);
|
||||
iter(&mut hash, &c.onceness);
|
||||
iter(&mut hash, &c.bounds);
|
||||
region(&mut hash, c.region);
|
||||
}
|
||||
ty_trait(d, _, store, m, bounds) => {
|
||||
hash.input([17]);
|
||||
did(&mut hash, d);
|
||||
match store {
|
||||
BoxTraitStore => hash.input([0]),
|
||||
UniqTraitStore => hash.input([1]),
|
||||
RegionTraitStore(r) => {
|
||||
hash.input([2]);
|
||||
region(&mut hash, r);
|
||||
}
|
||||
}
|
||||
iter(&mut hash, &m);
|
||||
iter(&mut hash, &bounds);
|
||||
}
|
||||
ty_struct(d, _) => {
|
||||
hash.input([18]);
|
||||
did(&mut hash, d);
|
||||
}
|
||||
ty_tup(ref inner) => {
|
||||
hash.input([19]);
|
||||
iter(&mut hash, &inner.len());
|
||||
}
|
||||
ty_param(p) => {
|
||||
hash.input([20]);
|
||||
iter(&mut hash, &p.idx);
|
||||
did(&mut hash, p.def_id);
|
||||
}
|
||||
ty_self(d) => {
|
||||
hash.input([21]);
|
||||
did(&mut hash, d);
|
||||
}
|
||||
ty_infer(_) => unreachable!(),
|
||||
ty_err => hash.input([23]),
|
||||
ty_type => hash.input([24]),
|
||||
ty_opaque_box => hash.input([25]),
|
||||
ty_opaque_closure_ptr(s) => {
|
||||
hash.input([26]);
|
||||
iter(&mut hash, &s);
|
||||
}
|
||||
ty_unboxed_vec(m) => {
|
||||
hash.input([27]);
|
||||
mt(&mut hash, m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hash.result_u64()
|
||||
}
|
||||
|
@ -3700,6 +3700,7 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
|
||||
});
|
||||
(1u, ~[], td_ptr)
|
||||
}
|
||||
"type_id" => (1u, ~[], ty::mk_u64()),
|
||||
"visit_tydesc" => {
|
||||
let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
|
||||
Ok(t) => t,
|
||||
|
@ -15,7 +15,7 @@ use cast::transmute;
|
||||
use cmp::Eq;
|
||||
use option::{Option, Some, None};
|
||||
use to_str::ToStr;
|
||||
use unstable::intrinsics::{TyDesc, get_tydesc, forget};
|
||||
use unstable::intrinsics;
|
||||
use util::Void;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -24,15 +24,30 @@ use util::Void;
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// `TypeId` represents a globally unique identifier for a type
|
||||
#[cfg(stage0)]
|
||||
pub struct TypeId {
|
||||
priv t: *TyDesc
|
||||
priv t: *intrinsics::TyDesc,
|
||||
}
|
||||
|
||||
/// `TypeId` represents a globally unique identifier for a type
|
||||
#[cfg(not(stage0))]
|
||||
pub struct TypeId {
|
||||
priv t: u64,
|
||||
}
|
||||
|
||||
impl TypeId {
|
||||
/// Returns the `TypeId` of the type this generic function has been instantiated with
|
||||
#[inline]
|
||||
pub fn of<T>() -> TypeId {
|
||||
TypeId{ t: unsafe { get_tydesc::<T>() } }
|
||||
#[cfg(stage0)]
|
||||
pub fn of<T: 'static>() -> TypeId {
|
||||
TypeId{ t: unsafe { intrinsics::get_tydesc::<T>() } }
|
||||
}
|
||||
|
||||
/// Returns the `TypeId` of the type this generic function has been instantiated with
|
||||
#[inline]
|
||||
#[cfg(not(stage0))]
|
||||
pub fn of<T: 'static>() -> TypeId {
|
||||
TypeId{ t: unsafe { intrinsics::type_id::<T>() } }
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,22 +65,32 @@ impl Eq for TypeId {
|
||||
/// The `Any` trait is implemented by all types, and can be used as a trait object
|
||||
/// for dynamic typing
|
||||
pub trait Any {
|
||||
/// Get the `TypeId` of `self`
|
||||
fn get_type_id(&self) -> TypeId;
|
||||
|
||||
/// Get a void pointer to `self`
|
||||
fn as_void_ptr(&self) -> *Void;
|
||||
|
||||
/// Get a mutable void pointer to `self`
|
||||
fn as_mut_void_ptr(&mut self) -> *mut Void;
|
||||
}
|
||||
|
||||
impl<T: 'static> Any for T {
|
||||
/// Get the `TypeId` of `self`
|
||||
fn get_type_id(&self) -> TypeId {
|
||||
TypeId::of::<Self>()
|
||||
TypeId::of::<T>()
|
||||
}
|
||||
|
||||
/// Get a void pointer to `self`
|
||||
fn as_void_ptr(&self) -> *Void {
|
||||
self as *Self as *Void
|
||||
self as *T as *Void
|
||||
}
|
||||
|
||||
/// Get a mutable void pointer to `self`
|
||||
fn as_mut_void_ptr(&mut self) -> *mut Void {
|
||||
self as *mut Self as *mut Void
|
||||
self as *mut T as *mut Void
|
||||
}
|
||||
}
|
||||
impl<T> Any for T {}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Extension methods for Any trait objects.
|
||||
@ -75,16 +100,16 @@ impl<T> Any for T {}
|
||||
/// Extension methods for a referenced `Any` trait object
|
||||
pub trait AnyRefExt<'self> {
|
||||
/// Returns true if the boxed type is the same as `T`
|
||||
fn is<T>(self) -> bool;
|
||||
fn is<T: 'static>(self) -> bool;
|
||||
|
||||
/// Returns some reference to the boxed value if it is of type `T`, or
|
||||
/// `None` if it isn't.
|
||||
fn as_ref<T>(self) -> Option<&'self T>;
|
||||
fn as_ref<T: 'static>(self) -> Option<&'self T>;
|
||||
}
|
||||
|
||||
impl<'self> AnyRefExt<'self> for &'self Any {
|
||||
#[inline]
|
||||
fn is<T>(self) -> bool {
|
||||
fn is<T: 'static>(self) -> bool {
|
||||
// Get TypeId of the type this function is instantiated with
|
||||
let t = TypeId::of::<T>();
|
||||
|
||||
@ -96,7 +121,7 @@ impl<'self> AnyRefExt<'self> for &'self Any {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_ref<T>(self) -> Option<&'self T> {
|
||||
fn as_ref<T: 'static>(self) -> Option<&'self T> {
|
||||
if self.is::<T>() {
|
||||
Some(unsafe { transmute(self.as_void_ptr()) })
|
||||
} else {
|
||||
@ -109,12 +134,12 @@ impl<'self> AnyRefExt<'self> for &'self Any {
|
||||
pub trait AnyMutRefExt<'self> {
|
||||
/// Returns some mutable reference to the boxed value if it is of type `T`, or
|
||||
/// `None` if it isn't.
|
||||
fn as_mut<T>(self) -> Option<&'self mut T>;
|
||||
fn as_mut<T: 'static>(self) -> Option<&'self mut T>;
|
||||
}
|
||||
|
||||
impl<'self> AnyMutRefExt<'self> for &'self mut Any {
|
||||
#[inline]
|
||||
fn as_mut<T>(self) -> Option<&'self mut T> {
|
||||
fn as_mut<T: 'static>(self) -> Option<&'self mut T> {
|
||||
if self.is::<T>() {
|
||||
Some(unsafe { transmute(self.as_mut_void_ptr()) })
|
||||
} else {
|
||||
@ -127,19 +152,19 @@ impl<'self> AnyMutRefExt<'self> for &'self mut Any {
|
||||
pub trait AnyOwnExt {
|
||||
/// Returns the boxed value if it is of type `T`, or
|
||||
/// `None` if it isn't.
|
||||
fn move<T>(self) -> Option<~T>;
|
||||
fn move<T: 'static>(self) -> Option<~T>;
|
||||
}
|
||||
|
||||
impl AnyOwnExt for ~Any {
|
||||
#[inline]
|
||||
fn move<T>(self) -> Option<~T> {
|
||||
fn move<T: 'static>(self) -> Option<~T> {
|
||||
if self.is::<T>() {
|
||||
unsafe {
|
||||
// Extract the pointer to the boxed value, temporary alias with self
|
||||
let ptr: ~T = transmute(self.as_void_ptr());
|
||||
|
||||
// Prevent destructor on self being run
|
||||
forget(self);
|
||||
intrinsics::forget(self);
|
||||
|
||||
Some(ptr)
|
||||
}
|
||||
|
@ -49,23 +49,23 @@ pub struct TyDesc {
|
||||
align: uint,
|
||||
|
||||
// Called on a copy of a value of type `T` *after* memcpy
|
||||
priv take_glue: GlueFn,
|
||||
take_glue: GlueFn,
|
||||
|
||||
// Called when a value of type `T` is no longer needed
|
||||
drop_glue: GlueFn,
|
||||
|
||||
// Called by drop glue when a value of type `T` can be freed
|
||||
priv free_glue: GlueFn,
|
||||
free_glue: GlueFn,
|
||||
|
||||
// Called by reflection visitor to visit a value of type `T`
|
||||
priv visit_glue: GlueFn,
|
||||
visit_glue: GlueFn,
|
||||
|
||||
// If T represents a box pointer (`@U` or `~U`), then
|
||||
// `borrow_offset` is the amount that the pointer must be adjusted
|
||||
// to find the payload. This is always derivable from the type
|
||||
// `U`, but in the case of `@Trait` or `~Trait` objects, the type
|
||||
// `U` is unknown.
|
||||
priv borrow_offset: uint,
|
||||
borrow_offset: uint,
|
||||
|
||||
// Name corresponding to the type
|
||||
name: &'static str
|
||||
@ -310,6 +310,12 @@ extern "rust-intrinsic" {
|
||||
/// Get a static pointer to a type descriptor.
|
||||
pub fn get_tydesc<T>() -> *TyDesc;
|
||||
|
||||
/// 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(not(stage0))]
|
||||
pub fn type_id<T: 'static>() -> u64;
|
||||
|
||||
/// Create a value initialized to zero.
|
||||
///
|
||||
/// `init` is unsafe because it returns a zeroed-out datum,
|
||||
|
32
src/test/auxiliary/typeid-intrinsic.rs
Normal file
32
src/test/auxiliary/typeid-intrinsic.rs
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::unstable::intrinsics;
|
||||
|
||||
pub struct A;
|
||||
pub struct B(Option<A>);
|
||||
pub struct C(Option<int>);
|
||||
pub struct D(Option<&'static str>);
|
||||
pub struct E(Result<&'static str, int>);
|
||||
|
||||
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 foo<T: 'static>() -> u64 { intrinsics::type_id::<T>() }
|
32
src/test/auxiliary/typeid-intrinsic2.rs
Normal file
32
src/test/auxiliary/typeid-intrinsic2.rs
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::unstable::intrinsics;
|
||||
|
||||
pub struct A;
|
||||
pub struct B(Option<A>);
|
||||
pub struct C(Option<int>);
|
||||
pub struct D(Option<&'static str>);
|
||||
pub struct E(Result<&'static str, int>);
|
||||
|
||||
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 foo<T: 'static>() -> u64 { intrinsics::type_id::<T>() }
|
53
src/test/run-pass/typeid-intrinsic.rs
Normal file
53
src/test/run-pass/typeid-intrinsic.rs
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// xfail-fast windows doesn't like aux-build
|
||||
// aux-build:typeid-intrinsic.rs
|
||||
// aux-build:typeid-intrinsic2.rs
|
||||
|
||||
extern mod other1(name = "typeid-intrinsic");
|
||||
extern mod other2(name = "typeid-intrinsic2");
|
||||
|
||||
use std::unstable::intrinsics;
|
||||
|
||||
struct A;
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
assert_eq!(intrinsics::type_id::<other1::A>(), other1::id_A());
|
||||
assert_eq!(intrinsics::type_id::<other1::B>(), other1::id_B());
|
||||
assert_eq!(intrinsics::type_id::<other1::C>(), other1::id_C());
|
||||
assert_eq!(intrinsics::type_id::<other1::D>(), other1::id_D());
|
||||
assert_eq!(intrinsics::type_id::<other1::E>(), other1::id_E());
|
||||
assert_eq!(intrinsics::type_id::<other1::F>(), other1::id_F());
|
||||
assert_eq!(intrinsics::type_id::<other1::G>(), other1::id_G());
|
||||
assert_eq!(intrinsics::type_id::<other1::H>(), other1::id_H());
|
||||
|
||||
assert_eq!(intrinsics::type_id::<other2::A>(), other2::id_A());
|
||||
assert_eq!(intrinsics::type_id::<other2::B>(), other2::id_B());
|
||||
assert_eq!(intrinsics::type_id::<other2::C>(), other2::id_C());
|
||||
assert_eq!(intrinsics::type_id::<other2::D>(), other2::id_D());
|
||||
assert_eq!(intrinsics::type_id::<other2::E>(), other2::id_E());
|
||||
assert_eq!(intrinsics::type_id::<other2::F>(), other2::id_F());
|
||||
assert_eq!(intrinsics::type_id::<other2::G>(), other2::id_G());
|
||||
assert_eq!(intrinsics::type_id::<other2::H>(), other2::id_H());
|
||||
|
||||
assert_eq!(other1::id_F(), other2::id_F());
|
||||
assert_eq!(other1::id_G(), other2::id_G());
|
||||
assert_eq!(other1::id_H(), other2::id_H());
|
||||
|
||||
assert_eq!(intrinsics::type_id::<int>(), other2::foo::<int>());
|
||||
assert_eq!(intrinsics::type_id::<int>(), other1::foo::<int>());
|
||||
assert_eq!(other2::foo::<int>(), other1::foo::<int>());
|
||||
assert_eq!(intrinsics::type_id::<A>(), other2::foo::<A>());
|
||||
assert_eq!(intrinsics::type_id::<A>(), other1::foo::<A>());
|
||||
assert_eq!(other2::foo::<A>(), other1::foo::<A>());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user