Skip to content

Commit 156054f

Browse files
committed
auto merge of #10722 : cmr/rust/type_id_opaque, r=alexcrichton
Closes #10594
2 parents 80991bb + 572635b commit 156054f

File tree

8 files changed

+105
-46
lines changed

8 files changed

+105
-46
lines changed

src/librustc/middle/lang_items.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -82,16 +82,18 @@ pub enum LangItem {
8282
OpaqueStructLangItem, // 38
8383

8484
EventLoopFactoryLangItem, // 39
85+
86+
TypeIdLangItem, // 40
8587
}
8688

8789
pub struct LanguageItems {
88-
items: [Option<ast::DefId>, ..40]
90+
items: [Option<ast::DefId>, ..41]
8991
}
9092

9193
impl LanguageItems {
9294
pub fn new() -> LanguageItems {
9395
LanguageItems {
94-
items: [ None, ..40 ]
96+
items: [ None, ..41 ]
9597
}
9698
}
9799

@@ -148,6 +150,8 @@ impl LanguageItems {
148150

149151
39 => "event_loop_factory",
150152

153+
40 => "type_id",
154+
151155
_ => "???"
152156
}
153157
}
@@ -298,6 +302,9 @@ impl LanguageItems {
298302
pub fn event_loop_factory(&self) -> Option<ast::DefId> {
299303
self.items[EventLoopFactoryLangItem as uint]
300304
}
305+
pub fn type_id(&self) -> Option<ast::DefId> {
306+
self.items[TypeIdLangItem as uint]
307+
}
301308
}
302309

303310
struct LanguageItemCollector {
@@ -382,6 +389,7 @@ impl LanguageItemCollector {
382389
item_refs.insert("ty_visitor", TyVisitorTraitLangItem as uint);
383390
item_refs.insert("opaque", OpaqueStructLangItem as uint);
384391
item_refs.insert("event_loop_factory", EventLoopFactoryLangItem as uint);
392+
item_refs.insert("type_id", TypeIdLangItem as uint);
385393

386394
LanguageItemCollector {
387395
session: session,

src/librustc/middle/trans/intrinsic.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,16 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
287287
"type_id" => {
288288
let hash = ty::hash_crate_independent(ccx.tcx, substs.tys[0],
289289
ccx.link_meta.extras_hash);
290-
Ret(bcx, C_i64(hash as i64))
290+
// NB: This needs to be kept in lockstep with the TypeId struct in
291+
// libstd/unstable/intrinsics.rs
292+
let val = C_named_struct(type_of::type_of(ccx, output_type), [C_u64(hash)]);
293+
match bcx.fcx.llretptr {
294+
Some(ptr) => {
295+
Store(bcx, val, ptr);
296+
RetVoid(bcx);
297+
},
298+
None => Ret(bcx, val)
299+
}
291300
}
292301
"init" => {
293302
let tp_ty = substs.tys[0];

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

+12-1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ use middle::typeck::rscope::RegionScope;
105105
use middle::typeck::{lookup_def_ccx};
106106
use middle::typeck::no_params;
107107
use middle::typeck::{require_same_types, method_map, vtable_map};
108+
use middle::lang_items::TypeIdLangItem;
108109
use util::common::{block_query, indenter, loop_query};
109110
use util::ppaux::UserString;
110111
use util::ppaux;
@@ -4013,7 +4014,17 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
40134014
});
40144015
(1u, ~[], td_ptr)
40154016
}
4016-
"type_id" => (1u, ~[], ty::mk_u64()),
4017+
"type_id" => {
4018+
let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
4019+
match langid {
4020+
Ok(did) => (1u, ~[], ty::mk_struct(ccx.tcx, did, substs {
4021+
self_ty: None,
4022+
tps: ~[],
4023+
regions: ty::NonerasedRegions(opt_vec::Empty)
4024+
}) ),
4025+
Err(msg) => { tcx.sess.span_fatal(it.span, msg); }
4026+
}
4027+
},
40174028
"visit_tydesc" => {
40184029
let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
40194030
Ok(t) => t,

src/libstd/any.rs

+8-23
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,28 @@
1212
//! of any type.
1313
1414
use cast::transmute;
15+
#[cfg(stage0)]
1516
use cmp::Eq;
1617
use option::{Option, Some, None};
18+
#[cfg(stage0)]
1719
use to_bytes::{IterBytes, Cb};
1820
use to_str::ToStr;
1921
use unstable::intrinsics;
2022
use util::Void;
23+
#[cfg(not(stage0))]
24+
use unstable::intrinsics::TypeId;
2125

2226
///////////////////////////////////////////////////////////////////////////////
2327
// TypeId
2428
///////////////////////////////////////////////////////////////////////////////
2529

2630
/// `TypeId` represents a globally unique identifier for a type
31+
#[cfg(stage0)]
2732
pub struct TypeId {
2833
priv t: u64,
2934
}
3035

36+
#[cfg(stage0)]
3137
impl TypeId {
3238
/// Returns the `TypeId` of the type this generic function has been instantiated with
3339
#[inline]
@@ -36,13 +42,15 @@ impl TypeId {
3642
}
3743
}
3844

45+
#[cfg(stage0)]
3946
impl Eq for TypeId {
4047
#[inline]
4148
fn eq(&self, &other: &TypeId) -> bool {
4249
self.t == other.t
4350
}
4451
}
4552

53+
#[cfg(stage0)]
4654
impl IterBytes for TypeId {
4755
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
4856
self.t.iter_bytes(lsb0, f)
@@ -189,29 +197,6 @@ mod tests {
189197

190198
static TEST: &'static str = "Test";
191199

192-
#[test]
193-
fn type_id() {
194-
let (a, b, c) = (TypeId::of::<uint>(), TypeId::of::<&'static str>(),
195-
TypeId::of::<Test>());
196-
let (d, e, f) = (TypeId::of::<uint>(), TypeId::of::<&'static str>(),
197-
TypeId::of::<Test>());
198-
199-
assert!(a != b);
200-
assert!(a != c);
201-
assert!(b != c);
202-
203-
assert_eq!(a, d);
204-
assert_eq!(b, e);
205-
assert_eq!(c, f);
206-
}
207-
208-
#[test]
209-
fn type_id_hash() {
210-
let (a, b) = (TypeId::of::<uint>(), TypeId::of::<uint>());
211-
212-
assert_eq!(a.hash(), b.hash());
213-
}
214-
215200
#[test]
216201
fn any_as_void_ptr() {
217202
let (a, b, c) = (~5u as ~Any, ~TEST as ~Any, ~Test as ~Any);

src/libstd/unstable/intrinsics.rs

+24-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ A quick refresher on memory ordering:
3434

3535
// This is needed to prevent duplicate lang item definitions.
3636
#[cfg(test)]
37-
pub use realstd::unstable::intrinsics::{TyDesc, Opaque, TyVisitor};
37+
pub use realstd::unstable::intrinsics::{TyDesc, Opaque, TyVisitor, TypeId};
3838

3939
pub type GlueFn = extern "Rust" fn(*i8);
4040

@@ -313,7 +313,11 @@ extern "rust-intrinsic" {
313313
/// Gets an identifier which is globally unique to the specified type. This
314314
/// function will return the same value for a type regardless of whichever
315315
/// crate it is invoked in.
316+
#[cfg(stage0)]
316317
pub fn type_id<T: 'static>() -> u64;
318+
#[cfg(not(stage0))]
319+
pub fn type_id<T: 'static>() -> TypeId;
320+
317321

318322
/// Create a value initialized to zero.
319323
///
@@ -486,3 +490,22 @@ extern "rust-intrinsic" {
486490
#[cfg(target_endian = "big")] pub fn to_be32(x: i32) -> i32 { x }
487491
#[cfg(target_endian = "little")] pub fn to_be64(x: i64) -> i64 { unsafe { bswap64(x) } }
488492
#[cfg(target_endian = "big")] pub fn to_be64(x: i64) -> i64 { x }
493+
494+
495+
/// `TypeId` represents a globally unique identifier for a type
496+
#[lang="type_id"] // This needs to be kept in lockstep with the code in trans/intrinsic.rs and
497+
// middle/lang_items.rs
498+
#[deriving(Eq, IterBytes)]
499+
#[cfg(not(test))]
500+
pub struct TypeId {
501+
priv t: u64,
502+
}
503+
504+
#[cfg(not(test))]
505+
impl TypeId {
506+
/// Returns the `TypeId` of the type this generic function has been instantiated with
507+
#[cfg(not(stage0))]
508+
pub fn of<T: 'static>() -> TypeId {
509+
unsafe { type_id::<T>() }
510+
}
511+
}

src/test/auxiliary/typeid-intrinsic.rs

+10-9
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// except according to those terms.
1010

1111
use std::unstable::intrinsics;
12+
use std::unstable::intrinsics::TypeId;
1213

1314
pub struct A;
1415
pub struct B(Option<A>);
@@ -20,13 +21,13 @@ pub type F = Option<int>;
2021
pub type G = uint;
2122
pub type H = &'static str;
2223

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>() }
24+
pub unsafe fn id_A() -> TypeId { intrinsics::type_id::<A>() }
25+
pub unsafe fn id_B() -> TypeId { intrinsics::type_id::<B>() }
26+
pub unsafe fn id_C() -> TypeId { intrinsics::type_id::<C>() }
27+
pub unsafe fn id_D() -> TypeId { intrinsics::type_id::<D>() }
28+
pub unsafe fn id_E() -> TypeId { intrinsics::type_id::<E>() }
29+
pub unsafe fn id_F() -> TypeId { intrinsics::type_id::<F>() }
30+
pub unsafe fn id_G() -> TypeId { intrinsics::type_id::<G>() }
31+
pub unsafe fn id_H() -> TypeId { intrinsics::type_id::<H>() }
3132

32-
pub unsafe fn foo<T: 'static>() -> u64 { intrinsics::type_id::<T>() }
33+
pub unsafe fn foo<T: 'static>() -> TypeId { intrinsics::type_id::<T>() }

src/test/auxiliary/typeid-intrinsic2.rs

+10-9
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// except according to those terms.
1010

1111
use std::unstable::intrinsics;
12+
use std::unstable::intrinsics::TypeId;
1213

1314
pub struct A;
1415
pub struct B(Option<A>);
@@ -20,13 +21,13 @@ pub type F = Option<int>;
2021
pub type G = uint;
2122
pub type H = &'static str;
2223

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>() }
24+
pub unsafe fn id_A() -> TypeId { intrinsics::type_id::<A>() }
25+
pub unsafe fn id_B() -> TypeId { intrinsics::type_id::<B>() }
26+
pub unsafe fn id_C() -> TypeId { intrinsics::type_id::<C>() }
27+
pub unsafe fn id_D() -> TypeId { intrinsics::type_id::<D>() }
28+
pub unsafe fn id_E() -> TypeId { intrinsics::type_id::<E>() }
29+
pub unsafe fn id_F() -> TypeId { intrinsics::type_id::<F>() }
30+
pub unsafe fn id_G() -> TypeId { intrinsics::type_id::<G>() }
31+
pub unsafe fn id_H() -> TypeId { intrinsics::type_id::<H>() }
3132

32-
pub unsafe fn foo<T: 'static>() -> u64 { intrinsics::type_id::<T>() }
33+
pub unsafe fn foo<T: 'static>() -> TypeId { intrinsics::type_id::<T>() }

src/test/run-pass/typeid-intrinsic.rs

+21
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ extern mod other1(name = "typeid-intrinsic");
1616
extern mod other2(name = "typeid-intrinsic2");
1717

1818
use std::unstable::intrinsics;
19+
use std::unstable::intrinsics::TypeId;
1920

2021
struct A;
22+
struct Test;
2123

2224
fn main() {
2325
unsafe {
@@ -50,4 +52,23 @@ fn main() {
5052
assert_eq!(intrinsics::type_id::<A>(), other1::foo::<A>());
5153
assert_eq!(other2::foo::<A>(), other1::foo::<A>());
5254
}
55+
56+
// sanity test of TypeId
57+
let (a, b, c) = (TypeId::of::<uint>(), TypeId::of::<&'static str>(),
58+
TypeId::of::<Test>());
59+
let (d, e, f) = (TypeId::of::<uint>(), TypeId::of::<&'static str>(),
60+
TypeId::of::<Test>());
61+
62+
assert!(a != b);
63+
assert!(a != c);
64+
assert!(b != c);
65+
66+
assert_eq!(a, d);
67+
assert_eq!(b, e);
68+
assert_eq!(c, f);
69+
70+
// check it has a hash
71+
let (a, b) = (TypeId::of::<uint>(), TypeId::of::<uint>());
72+
73+
assert_eq!(a.hash(), b.hash());
5374
}

0 commit comments

Comments
 (0)