Skip to content

Commit 6163743

Browse files
committed
Add a type_id intrinsic
Closes #9913
1 parent 3a15482 commit 6163743

File tree

8 files changed

+326
-21
lines changed

8 files changed

+326
-21
lines changed

src/librustc/middle/trans/intrinsic.rs

+5
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,11 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
274274
let td = PointerCast(bcx, static_ti.tydesc, userland_tydesc_ty);
275275
Ret(bcx, td);
276276
}
277+
"type_id" => {
278+
let hash = ty::hash_crate_independent(ccx.tcx, substs.tys[0],
279+
ccx.link_meta.extras_hash);
280+
Ret(bcx, C_i64(hash as i64))
281+
}
277282
"init" => {
278283
let tp_ty = substs.tys[0];
279284
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

+42-17
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ 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
///////////////////////////////////////////////////////////////////////////////
@@ -24,15 +24,30 @@ use util::Void;
2424
///////////////////////////////////////////////////////////////////////////////
2525

2626
/// `TypeId` represents a globally unique identifier for a type
27+
#[cfg(stage0)]
2728
pub struct TypeId {
28-
priv t: *TyDesc
29+
priv t: *intrinsics::TyDesc,
30+
}
31+
32+
/// `TypeId` represents a globally unique identifier for a type
33+
#[cfg(not(stage0))]
34+
pub struct TypeId {
35+
priv t: u64,
2936
}
3037

3138
impl TypeId {
3239
/// Returns the `TypeId` of the type this generic function has been instantiated with
3340
#[inline]
34-
pub fn of<T>() -> TypeId {
35-
TypeId{ t: unsafe { get_tydesc::<T>() } }
41+
#[cfg(stage0)]
42+
pub fn of<T: 'static>() -> TypeId {
43+
TypeId{ t: unsafe { intrinsics::get_tydesc::<T>() } }
44+
}
45+
46+
/// Returns the `TypeId` of the type this generic function has been instantiated with
47+
#[inline]
48+
#[cfg(not(stage0))]
49+
pub fn of<T: 'static>() -> TypeId {
50+
TypeId{ t: unsafe { intrinsics::type_id::<T>() } }
3651
}
3752
}
3853

@@ -50,22 +65,32 @@ impl Eq for TypeId {
5065
/// The `Any` trait is implemented by all types, and can be used as a trait object
5166
/// for dynamic typing
5267
pub trait Any {
68+
/// Get the `TypeId` of `self`
69+
fn get_type_id(&self) -> TypeId;
70+
71+
/// Get a void pointer to `self`
72+
fn as_void_ptr(&self) -> *Void;
73+
74+
/// Get a mutable void pointer to `self`
75+
fn as_mut_void_ptr(&mut self) -> *mut Void;
76+
}
77+
78+
impl<T: 'static> Any for T {
5379
/// Get the `TypeId` of `self`
5480
fn get_type_id(&self) -> TypeId {
55-
TypeId::of::<Self>()
81+
TypeId::of::<T>()
5682
}
5783

5884
/// Get a void pointer to `self`
5985
fn as_void_ptr(&self) -> *Void {
60-
self as *Self as *Void
86+
self as *T as *Void
6187
}
6288

6389
/// Get a mutable void pointer to `self`
6490
fn as_mut_void_ptr(&mut self) -> *mut Void {
65-
self as *mut Self as *mut Void
91+
self as *mut T as *mut Void
6692
}
6793
}
68-
impl<T> Any for T {}
6994

7095
///////////////////////////////////////////////////////////////////////////////
7196
// Extension methods for Any trait objects.
@@ -75,16 +100,16 @@ impl<T> Any for T {}
75100
/// Extension methods for a referenced `Any` trait object
76101
pub trait AnyRefExt<'self> {
77102
/// Returns true if the boxed type is the same as `T`
78-
fn is<T>(self) -> bool;
103+
fn is<T: 'static>(self) -> bool;
79104

80105
/// Returns some reference to the boxed value if it is of type `T`, or
81106
/// `None` if it isn't.
82-
fn as_ref<T>(self) -> Option<&'self T>;
107+
fn as_ref<T: 'static>(self) -> Option<&'self T>;
83108
}
84109

85110
impl<'self> AnyRefExt<'self> for &'self Any {
86111
#[inline]
87-
fn is<T>(self) -> bool {
112+
fn is<T: 'static>(self) -> bool {
88113
// Get TypeId of the type this function is instantiated with
89114
let t = TypeId::of::<T>();
90115

@@ -96,7 +121,7 @@ impl<'self> AnyRefExt<'self> for &'self Any {
96121
}
97122

98123
#[inline]
99-
fn as_ref<T>(self) -> Option<&'self T> {
124+
fn as_ref<T: 'static>(self) -> Option<&'self T> {
100125
if self.is::<T>() {
101126
Some(unsafe { transmute(self.as_void_ptr()) })
102127
} else {
@@ -109,12 +134,12 @@ impl<'self> AnyRefExt<'self> for &'self Any {
109134
pub trait AnyMutRefExt<'self> {
110135
/// Returns some mutable reference to the boxed value if it is of type `T`, or
111136
/// `None` if it isn't.
112-
fn as_mut<T>(self) -> Option<&'self mut T>;
137+
fn as_mut<T: 'static>(self) -> Option<&'self mut T>;
113138
}
114139

115140
impl<'self> AnyMutRefExt<'self> for &'self mut Any {
116141
#[inline]
117-
fn as_mut<T>(self) -> Option<&'self mut T> {
142+
fn as_mut<T: 'static>(self) -> Option<&'self mut T> {
118143
if self.is::<T>() {
119144
Some(unsafe { transmute(self.as_mut_void_ptr()) })
120145
} else {
@@ -127,19 +152,19 @@ impl<'self> AnyMutRefExt<'self> for &'self mut Any {
127152
pub trait AnyOwnExt {
128153
/// Returns the boxed value if it is of type `T`, or
129154
/// `None` if it isn't.
130-
fn move<T>(self) -> Option<~T>;
155+
fn move<T: 'static>(self) -> Option<~T>;
131156
}
132157

133158
impl AnyOwnExt for ~Any {
134159
#[inline]
135-
fn move<T>(self) -> Option<~T> {
160+
fn move<T: 'static>(self) -> Option<~T> {
136161
if self.is::<T>() {
137162
unsafe {
138163
// Extract the pointer to the boxed value, temporary alias with self
139164
let ptr: ~T = transmute(self.as_void_ptr());
140165

141166
// Prevent destructor on self being run
142-
forget(self);
167+
intrinsics::forget(self);
143168

144169
Some(ptr)
145170
}

src/libstd/unstable/intrinsics.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -49,23 +49,23 @@ pub struct TyDesc {
4949
align: uint,
5050

5151
// Called on a copy of a value of type `T` *after* memcpy
52-
priv take_glue: GlueFn,
52+
take_glue: GlueFn,
5353

5454
// Called when a value of type `T` is no longer needed
5555
drop_glue: GlueFn,
5656

5757
// Called by drop glue when a value of type `T` can be freed
58-
priv free_glue: GlueFn,
58+
free_glue: GlueFn,
5959

6060
// Called by reflection visitor to visit a value of type `T`
61-
priv visit_glue: GlueFn,
61+
visit_glue: GlueFn,
6262

6363
// If T represents a box pointer (`@U` or `~U`), then
6464
// `borrow_offset` is the amount that the pointer must be adjusted
6565
// to find the payload. This is always derivable from the type
6666
// `U`, but in the case of `@Trait` or `~Trait` objects, the type
6767
// `U` is unknown.
68-
priv borrow_offset: uint,
68+
borrow_offset: uint,
6969

7070
// Name corresponding to the type
7171
name: &'static str
@@ -310,6 +310,12 @@ extern "rust-intrinsic" {
310310
/// Get a static pointer to a type descriptor.
311311
pub fn get_tydesc<T>() -> *TyDesc;
312312

313+
/// Gets an identifier which is globally unique to the specified type. This
314+
/// function will return the same value for a type regardless of whichever
315+
/// crate it is invoked in.
316+
#[cfg(not(stage0))]
317+
pub fn type_id<T: 'static>() -> u64;
318+
313319
/// Create a value initialized to zero.
314320
///
315321
/// `init` is unsafe because it returns a zeroed-out datum,
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use std::unstable::intrinsics;
12+
13+
pub struct A;
14+
pub struct B(Option<A>);
15+
pub struct C(Option<int>);
16+
pub struct D(Option<&'static str>);
17+
pub struct E(Result<&'static str, int>);
18+
19+
pub type F = Option<int>;
20+
pub type G = uint;
21+
pub type H = &'static str;
22+
23+
pub unsafe fn id_A() -> u64 { intrinsics::type_id::<A>() }
24+
pub unsafe fn id_B() -> u64 { intrinsics::type_id::<B>() }
25+
pub unsafe fn id_C() -> u64 { intrinsics::type_id::<C>() }
26+
pub unsafe fn id_D() -> u64 { intrinsics::type_id::<D>() }
27+
pub unsafe fn id_E() -> u64 { intrinsics::type_id::<E>() }
28+
pub unsafe fn id_F() -> u64 { intrinsics::type_id::<F>() }
29+
pub unsafe fn id_G() -> u64 { intrinsics::type_id::<G>() }
30+
pub unsafe fn id_H() -> u64 { intrinsics::type_id::<H>() }
31+
32+
pub unsafe fn foo<T: 'static>() -> u64 { intrinsics::type_id::<T>() }

0 commit comments

Comments
 (0)