Skip to content

Commit ecfa654

Browse files
committed
auto merge of #10182 : alexcrichton/rust/typeid-intrinsic, r=nikomatsakis
This isn't quite as fancy as the struct in #9913, but I'm not sure we should be exposing crate names/hashes of the types. That being said, it'd be pretty easy to extend this (the deterministic hashing regardless of what crate you're in was the hard part).
2 parents 658637b + b004493 commit ecfa654

File tree

12 files changed

+367
-97
lines changed

12 files changed

+367
-97
lines changed

src/librustc/middle/trans/intrinsic.rs

+5
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,11 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
285285
let td = PointerCast(bcx, static_ti.tydesc, userland_tydesc_ty);
286286
Ret(bcx, td);
287287
}
288+
"type_id" => {
289+
let hash = ty::hash_crate_independent(ccx.tcx, substs.tys[0],
290+
ccx.link_meta.extras_hash);
291+
Ret(bcx, C_i64(hash as i64))
292+
}
288293
"init" => {
289294
let tp_ty = substs.tys[0];
290295
let lltp_ty = type_of::type_of(ccx, tp_ty);

src/librustc/middle/ty.rs

+151
Original file line numberDiff line numberDiff line change
@@ -4724,3 +4724,154 @@ pub fn trait_of_method(tcx: ctxt, def_id: ast::DefId)
47244724

47254725
result
47264726
}
4727+
4728+
/// Creates a hash of the type `t` which will be the same no matter what crate
4729+
/// context it's calculated within. This is used by the `type_id` intrinsic.
4730+
pub fn hash_crate_independent(tcx: ctxt, t: t, local_hash: @str) -> u64 {
4731+
use std::hash::{SipState, Streaming};
4732+
use metadata::cstore;
4733+
4734+
let mut hash = SipState::new(0, 0);
4735+
let region = |_hash: &mut SipState, r: Region| {
4736+
match r {
4737+
re_static => {}
4738+
4739+
re_empty | re_bound(*) | re_free(*) | re_scope(*) | re_infer(*) =>
4740+
tcx.sess.bug("non-static region found when hashing a type")
4741+
}
4742+
};
4743+
let vstore = |hash: &mut SipState, v: vstore| {
4744+
match v {
4745+
vstore_fixed(_) => hash.input([0]),
4746+
vstore_uniq => hash.input([1]),
4747+
vstore_box => hash.input([2]),
4748+
vstore_slice(r) => {
4749+
hash.input([3]);
4750+
region(hash, r);
4751+
}
4752+
}
4753+
};
4754+
let did = |hash: &mut SipState, did: DefId| {
4755+
let h = if ast_util::is_local(did) {
4756+
local_hash
4757+
} else {
4758+
cstore::get_crate_hash(tcx.sess.cstore, did.crate)
4759+
};
4760+
hash.input(h.as_bytes());
4761+
iter(hash, &did.node);
4762+
};
4763+
let mt = |hash: &mut SipState, mt: mt| {
4764+
iter(hash, &mt.mutbl);
4765+
};
4766+
fn iter<T: IterBytes>(hash: &mut SipState, t: &T) {
4767+
do t.iter_bytes(true) |bytes| { hash.input(bytes); true };
4768+
}
4769+
do ty::walk_ty(t) |t| {
4770+
match ty::get(t).sty {
4771+
ty_nil => hash.input([0]),
4772+
ty_bot => hash.input([1]),
4773+
ty_bool => hash.input([2]),
4774+
ty_char => hash.input([3]),
4775+
ty_int(i) => {
4776+
hash.input([4]);
4777+
iter(&mut hash, &i);
4778+
}
4779+
ty_uint(u) => {
4780+
hash.input([5]);
4781+
iter(&mut hash, &u);
4782+
}
4783+
ty_float(f) => {
4784+
hash.input([6]);
4785+
iter(&mut hash, &f);
4786+
}
4787+
ty_estr(v) => {
4788+
hash.input([7]);
4789+
vstore(&mut hash, v);
4790+
}
4791+
ty_enum(d, _) => {
4792+
hash.input([8]);
4793+
did(&mut hash, d);
4794+
}
4795+
ty_box(m) => {
4796+
hash.input([9]);
4797+
mt(&mut hash, m);
4798+
}
4799+
ty_uniq(m) => {
4800+
hash.input([10]);
4801+
mt(&mut hash, m);
4802+
}
4803+
ty_evec(m, v) => {
4804+
hash.input([11]);
4805+
mt(&mut hash, m);
4806+
vstore(&mut hash, v);
4807+
}
4808+
ty_ptr(m) => {
4809+
hash.input([12]);
4810+
mt(&mut hash, m);
4811+
}
4812+
ty_rptr(r, m) => {
4813+
hash.input([13]);
4814+
region(&mut hash, r);
4815+
mt(&mut hash, m);
4816+
}
4817+
ty_bare_fn(ref b) => {
4818+
hash.input([14]);
4819+
iter(&mut hash, &b.purity);
4820+
iter(&mut hash, &b.abis);
4821+
}
4822+
ty_closure(ref c) => {
4823+
hash.input([15]);
4824+
iter(&mut hash, &c.purity);
4825+
iter(&mut hash, &c.sigil);
4826+
iter(&mut hash, &c.onceness);
4827+
iter(&mut hash, &c.bounds);
4828+
region(&mut hash, c.region);
4829+
}
4830+
ty_trait(d, _, store, m, bounds) => {
4831+
hash.input([17]);
4832+
did(&mut hash, d);
4833+
match store {
4834+
BoxTraitStore => hash.input([0]),
4835+
UniqTraitStore => hash.input([1]),
4836+
RegionTraitStore(r) => {
4837+
hash.input([2]);
4838+
region(&mut hash, r);
4839+
}
4840+
}
4841+
iter(&mut hash, &m);
4842+
iter(&mut hash, &bounds);
4843+
}
4844+
ty_struct(d, _) => {
4845+
hash.input([18]);
4846+
did(&mut hash, d);
4847+
}
4848+
ty_tup(ref inner) => {
4849+
hash.input([19]);
4850+
iter(&mut hash, &inner.len());
4851+
}
4852+
ty_param(p) => {
4853+
hash.input([20]);
4854+
iter(&mut hash, &p.idx);
4855+
did(&mut hash, p.def_id);
4856+
}
4857+
ty_self(d) => {
4858+
hash.input([21]);
4859+
did(&mut hash, d);
4860+
}
4861+
ty_infer(_) => unreachable!(),
4862+
ty_err => hash.input([23]),
4863+
ty_type => hash.input([24]),
4864+
ty_opaque_box => hash.input([25]),
4865+
ty_opaque_closure_ptr(s) => {
4866+
hash.input([26]);
4867+
iter(&mut hash, &s);
4868+
}
4869+
ty_unboxed_vec(m) => {
4870+
hash.input([27]);
4871+
mt(&mut hash, m);
4872+
}
4873+
}
4874+
}
4875+
4876+
hash.result_u64()
4877+
}

src/librustc/middle/typeck/check/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3700,6 +3700,7 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
37003700
});
37013701
(1u, ~[], td_ptr)
37023702
}
3703+
"type_id" => (1u, ~[], ty::mk_u64()),
37033704
"visit_tydesc" => {
37043705
let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
37053706
Ok(t) => t,

src/libstd/any.rs

+46-20
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,38 @@ use cast::transmute;
1515
use cmp::Eq;
1616
use option::{Option, Some, None};
1717
use to_str::ToStr;
18-
use unstable::intrinsics::{TyDesc, get_tydesc, forget};
18+
use unstable::intrinsics;
1919
use util::Void;
2020

2121
///////////////////////////////////////////////////////////////////////////////
2222
// TypeId
23-
// FIXME: #9913 - Needs proper intrinsic support to work reliably cross crate
2423
///////////////////////////////////////////////////////////////////////////////
2524

2625
/// `TypeId` represents a globally unique identifier for a type
26+
#[cfg(stage0)]
2727
pub struct TypeId {
28-
priv t: *TyDesc
28+
priv t: *intrinsics::TyDesc,
29+
}
30+
31+
/// `TypeId` represents a globally unique identifier for a type
32+
#[cfg(not(stage0))]
33+
pub struct TypeId {
34+
priv t: u64,
2935
}
3036

3137
impl TypeId {
3238
/// Returns the `TypeId` of the type this generic function has been instantiated with
3339
#[inline]
34-
pub fn of<T>() -> TypeId {
35-
TypeId{ t: unsafe { get_tydesc::<T>() } }
40+
#[cfg(stage0)]
41+
pub fn of<T: 'static>() -> TypeId {
42+
TypeId{ t: unsafe { intrinsics::get_tydesc::<T>() } }
43+
}
44+
45+
/// Returns the `TypeId` of the type this generic function has been instantiated with
46+
#[inline]
47+
#[cfg(not(stage0))]
48+
pub fn of<T: 'static>() -> TypeId {
49+
TypeId{ t: unsafe { intrinsics::type_id::<T>() } }
3650
}
3751
}
3852

@@ -50,22 +64,32 @@ impl Eq for TypeId {
5064
/// The `Any` trait is implemented by all types, and can be used as a trait object
5165
/// for dynamic typing
5266
pub trait Any {
67+
/// Get the `TypeId` of `self`
68+
fn get_type_id(&self) -> TypeId;
69+
70+
/// Get a void pointer to `self`
71+
fn as_void_ptr(&self) -> *Void;
72+
73+
/// Get a mutable void pointer to `self`
74+
fn as_mut_void_ptr(&mut self) -> *mut Void;
75+
}
76+
77+
impl<T: 'static> Any for T {
5378
/// Get the `TypeId` of `self`
5479
fn get_type_id(&self) -> TypeId {
55-
TypeId::of::<Self>()
80+
TypeId::of::<T>()
5681
}
5782

5883
/// Get a void pointer to `self`
5984
fn as_void_ptr(&self) -> *Void {
60-
self as *Self as *Void
85+
self as *T as *Void
6186
}
6287

6388
/// Get a mutable void pointer to `self`
6489
fn as_mut_void_ptr(&mut self) -> *mut Void {
65-
self as *mut Self as *mut Void
90+
self as *mut T as *mut Void
6691
}
6792
}
68-
impl<T> Any for T {}
6993

7094
///////////////////////////////////////////////////////////////////////////////
7195
// Extension methods for Any trait objects.
@@ -75,16 +99,16 @@ impl<T> Any for T {}
7599
/// Extension methods for a referenced `Any` trait object
76100
pub trait AnyRefExt<'self> {
77101
/// Returns true if the boxed type is the same as `T`
78-
fn is<T>(self) -> bool;
102+
fn is<T: 'static>(self) -> bool;
79103

80104
/// Returns some reference to the boxed value if it is of type `T`, or
81105
/// `None` if it isn't.
82-
fn as_ref<T>(self) -> Option<&'self T>;
106+
fn as_ref<T: 'static>(self) -> Option<&'self T>;
83107
}
84108

85109
impl<'self> AnyRefExt<'self> for &'self Any {
86110
#[inline]
87-
fn is<T>(self) -> bool {
111+
fn is<T: 'static>(self) -> bool {
88112
// Get TypeId of the type this function is instantiated with
89113
let t = TypeId::of::<T>();
90114

@@ -96,7 +120,7 @@ impl<'self> AnyRefExt<'self> for &'self Any {
96120
}
97121

98122
#[inline]
99-
fn as_ref<T>(self) -> Option<&'self T> {
123+
fn as_ref<T: 'static>(self) -> Option<&'self T> {
100124
if self.is::<T>() {
101125
Some(unsafe { transmute(self.as_void_ptr()) })
102126
} else {
@@ -109,12 +133,12 @@ impl<'self> AnyRefExt<'self> for &'self Any {
109133
pub trait AnyMutRefExt<'self> {
110134
/// Returns some mutable reference to the boxed value if it is of type `T`, or
111135
/// `None` if it isn't.
112-
fn as_mut<T>(self) -> Option<&'self mut T>;
136+
fn as_mut<T: 'static>(self) -> Option<&'self mut T>;
113137
}
114138

115139
impl<'self> AnyMutRefExt<'self> for &'self mut Any {
116140
#[inline]
117-
fn as_mut<T>(self) -> Option<&'self mut T> {
141+
fn as_mut<T: 'static>(self) -> Option<&'self mut T> {
118142
if self.is::<T>() {
119143
Some(unsafe { transmute(self.as_mut_void_ptr()) })
120144
} else {
@@ -127,19 +151,19 @@ impl<'self> AnyMutRefExt<'self> for &'self mut Any {
127151
pub trait AnyOwnExt {
128152
/// Returns the boxed value if it is of type `T`, or
129153
/// `None` if it isn't.
130-
fn move<T>(self) -> Option<~T>;
154+
fn move<T: 'static>(self) -> Option<~T>;
131155
}
132156

133157
impl AnyOwnExt for ~Any {
134158
#[inline]
135-
fn move<T>(self) -> Option<~T> {
159+
fn move<T: 'static>(self) -> Option<~T> {
136160
if self.is::<T>() {
137161
unsafe {
138162
// Extract the pointer to the boxed value, temporary alias with self
139163
let ptr: ~T = transmute(self.as_void_ptr());
140164

141165
// Prevent destructor on self being run
142-
forget(self);
166+
intrinsics::forget(self);
143167

144168
Some(ptr)
145169
}
@@ -174,8 +198,10 @@ mod tests {
174198

175199
#[test]
176200
fn type_id() {
177-
let (a, b, c) = (TypeId::of::<uint>(), TypeId::of::<&str>(), TypeId::of::<Test>());
178-
let (d, e, f) = (TypeId::of::<uint>(), TypeId::of::<&str>(), TypeId::of::<Test>());
201+
let (a, b, c) = (TypeId::of::<uint>(), TypeId::of::<&'static str>(),
202+
TypeId::of::<Test>());
203+
let (d, e, f) = (TypeId::of::<uint>(), TypeId::of::<&'static str>(),
204+
TypeId::of::<Test>());
179205

180206
assert!(a != b);
181207
assert!(a != c);

src/libstd/rt/kill.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,9 @@ use cell::Cell;
155155
use option::{Option, Some, None};
156156
use prelude::*;
157157
use rt::task::Task;
158-
use rt::task::UnwindMessageLinked;
159158
use rt::task::{UnwindResult, Failure};
160159
use task::spawn::Taskgroup;
160+
use task::LinkedFailure;
161161
use to_bytes::IterBytes;
162162
use unstable::atomics::{AtomicUint, Relaxed};
163163
use unstable::sync::{UnsafeArc, UnsafeArcSelf, UnsafeArcT, LittleLock};
@@ -597,7 +597,7 @@ impl Death {
597597
}
598598

599599
if !success {
600-
result = Cell::new(Failure(UnwindMessageLinked));
600+
result = Cell::new(Failure(~LinkedFailure as ~Any));
601601
}
602602
}
603603
on_exit(result.take());

0 commit comments

Comments
 (0)