Skip to content

Commit 80d73e9

Browse files
committed
std: Stabilize TypeId and tweak BoxAny
This commit aims to stabilize the `TypeId` abstraction by moving it out of the `intrinsics` module into the `any` module of the standard library. Specifically, * `TypeId` is now defined at `std::any::TypeId` * `TypeId::hash` has been removed in favor of an implementation of `Hash`. This commit also performs a final pass over the `any` module, confirming the following: * `Any::get_type_id` remains unstable as *usage* of the `Any` trait will likely never require this, and the `Any` trait does not need to be implemented for any other types. As a result, this implementation detail can remain unstable until associated statics are implemented. * `Any::downcast_ref` is now stable * `Any::downcast_mut` is now stable * `BoxAny` remains unstable. While a direct impl on `Box<Any>` is allowed today it does not allow downcasting of trait objects like `Box<Any + Send>` (those returned from `Thread::join`). This is covered by #18737. * `BoxAny::downcast` is now stable.
1 parent 896cb36 commit 80d73e9

File tree

16 files changed

+102
-122
lines changed

16 files changed

+102
-122
lines changed

Diff for: src/liballoc/boxed.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -133,19 +133,21 @@ impl<S: hash::Hasher, T: ?Sized + Hash<S>> Hash<S> for Box<T> {
133133
}
134134

135135
/// Extension methods for an owning `Any` trait object.
136-
#[unstable = "post-DST and coherence changes, this will not be a trait but \
137-
rather a direct `impl` on `Box<Any>`"]
136+
#[unstable = "this trait will likely disappear once compiler bugs blocking \
137+
a direct impl on `Box<Any>` have been fixed "]
138+
// FIXME(#18737): this should be a direct impl on `Box<Any>`. If you're
139+
// removing this please make sure that you can downcase on
140+
// `Box<Any + Send>` as well as `Box<Any>`
138141
pub trait BoxAny {
139142
/// Returns the boxed value if it is of type `T`, or
140143
/// `Err(Self)` if it isn't.
141144
#[stable]
142145
fn downcast<T: 'static>(self) -> Result<Box<T>, Self>;
143146
}
144147

148+
#[stable]
145149
impl BoxAny for Box<Any> {
146150
#[inline]
147-
#[unstable = "method may be renamed with respect to other downcasting \
148-
methods"]
149151
fn downcast<T: 'static>(self) -> Result<Box<T>, Box<Any>> {
150152
if self.is::<T>() {
151153
unsafe {

Diff for: src/libcore/any.rs

+45-9
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,11 @@
7171
7272
#![stable]
7373

74-
use mem::{transmute};
75-
use option::Option;
76-
use option::Option::{Some, None};
74+
use mem::transmute;
75+
use option::Option::{self, Some, None};
7776
use raw::TraitObject;
78-
use intrinsics::TypeId;
77+
use intrinsics;
78+
#[cfg(not(stage0))] use marker::Sized;
7979

8080
///////////////////////////////////////////////////////////////////////////////
8181
// Any trait
@@ -99,7 +99,6 @@ impl<T: 'static> Any for T {
9999

100100
///////////////////////////////////////////////////////////////////////////////
101101
// Extension methods for Any trait objects.
102-
// Implemented as three extension traits so that the methods can be generic.
103102
///////////////////////////////////////////////////////////////////////////////
104103

105104
impl Any {
@@ -119,9 +118,9 @@ impl Any {
119118

120119
/// Returns some reference to the boxed value if it is of type `T`, or
121120
/// `None` if it isn't.
122-
#[unstable = "naming conventions around acquiring references may change"]
121+
#[stable]
123122
#[inline]
124-
pub fn downcast_ref<'a, T: 'static>(&'a self) -> Option<&'a T> {
123+
pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
125124
if self.is::<T>() {
126125
unsafe {
127126
// Get the raw representation of the trait object
@@ -137,9 +136,9 @@ impl Any {
137136

138137
/// Returns some mutable reference to the boxed value if it is of type `T`, or
139138
/// `None` if it isn't.
140-
#[unstable = "naming conventions around acquiring references may change"]
139+
#[stable]
141140
#[inline]
142-
pub fn downcast_mut<'a, T: 'static>(&'a mut self) -> Option<&'a mut T> {
141+
pub fn downcast_mut<T: 'static>(&mut self) -> Option<&mut T> {
143142
if self.is::<T>() {
144143
unsafe {
145144
// Get the raw representation of the trait object
@@ -153,3 +152,40 @@ impl Any {
153152
}
154153
}
155154
}
155+
156+
///////////////////////////////////////////////////////////////////////////////
157+
// TypeID and its methods
158+
///////////////////////////////////////////////////////////////////////////////
159+
160+
/// A `TypeId` represents a globally unique identifier for a type.
161+
///
162+
/// Each `TypeId` is an opaque object which does not allow inspection of what's
163+
/// inside but does allow basic operations such as cloning, comparison,
164+
/// printing, and showing.
165+
///
166+
/// A `TypeId` is currently only available for types which ascribe to `'static`,
167+
/// but this limitation may be removed in the future.
168+
#[cfg_attr(stage0, lang = "type_id")]
169+
#[derive(Clone, Copy, PartialEq, Eq, Show, Hash)]
170+
#[stable]
171+
pub struct TypeId {
172+
t: u64,
173+
}
174+
175+
impl TypeId {
176+
/// Returns the `TypeId` of the type this generic function has been
177+
/// instantiated with
178+
#[cfg(not(stage0))]
179+
#[unstable = "may grow a `Reflect` bound soon via marker traits"]
180+
pub fn of<T: ?Sized + 'static>() -> TypeId {
181+
TypeId {
182+
t: unsafe { intrinsics::type_id::<T>() },
183+
}
184+
}
185+
186+
/// dox
187+
#[cfg(stage0)]
188+
pub fn of<T: 'static>() -> TypeId {
189+
unsafe { intrinsics::type_id::<T>() }
190+
}
191+
}

Diff for: src/libcore/hash/mod.rs

-16
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@ mod impls {
126126
use prelude::*;
127127

128128
use borrow::{Cow, ToOwned};
129-
use intrinsics::TypeId;
130129
use mem;
131130
use super::{Hash, Writer};
132131
use num::Int;
@@ -260,13 +259,6 @@ mod impls {
260259
}
261260
}
262261

263-
impl<S: Writer> Hash<S> for TypeId {
264-
#[inline]
265-
fn hash(&self, state: &mut S) {
266-
self.hash().hash(state)
267-
}
268-
}
269-
270262
impl<'a, T, B: ?Sized, S> Hash<S> for Cow<'a, T, B>
271263
where B: Hash<S> + ToOwned<T>
272264
{
@@ -282,7 +274,6 @@ mod impls {
282274
use prelude::*;
283275

284276
use borrow::{Cow, ToOwned};
285-
use intrinsics::TypeId;
286277
use mem;
287278
use super::{Hash, Writer, Hasher};
288279
use num::Int;
@@ -416,13 +407,6 @@ mod impls {
416407
}
417408
}
418409

419-
impl<S: Writer + Hasher> Hash<S> for TypeId {
420-
#[inline]
421-
fn hash(&self, state: &mut S) {
422-
self.hash().hash(state)
423-
}
424-
}
425-
426410
impl<'a, T, B: ?Sized, S: Hasher> Hash<S> for Cow<'a, T, B>
427411
where B: Hash<S> + ToOwned<T>
428412
{

Diff for: src/libcore/intrinsics.rs

+3-24
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
#[cfg(not(stage0))]
4646
use marker::Sized;
4747

48+
#[cfg(stage0)] use any::TypeId;
49+
4850
pub type GlueFn = extern "Rust" fn(*const i8);
4951

5052
#[lang="ty_desc"]
@@ -204,7 +206,7 @@ extern "rust-intrinsic" {
204206
/// function will return the same value for a type regardless of whichever
205207
/// crate it is invoked in.
206208
#[cfg(not(stage0))]
207-
pub fn type_id<T: ?Sized + 'static>() -> TypeId;
209+
pub fn type_id<T: ?Sized + 'static>() -> u64;
208210

209211
#[cfg(stage0)]
210212
pub fn type_id<T: 'static>() -> TypeId;
@@ -547,26 +549,3 @@ extern "rust-intrinsic" {
547549
pub fn u64_mul_with_overflow(x: u64, y: u64) -> (u64, bool);
548550
}
549551

550-
551-
/// `TypeId` represents a globally unique identifier for a type
552-
#[lang="type_id"] // This needs to be kept in lockstep with the code in trans/intrinsic.rs and
553-
// middle/lang_items.rs
554-
#[derive(Clone, Copy, PartialEq, Eq, Show)]
555-
pub struct TypeId {
556-
t: u64,
557-
}
558-
559-
impl TypeId {
560-
/// Returns the `TypeId` of the type this generic function has been instantiated with
561-
#[cfg(not(stage0))]
562-
pub fn of<T: ?Sized + 'static>() -> TypeId {
563-
unsafe { type_id::<T>() }
564-
}
565-
566-
#[cfg(stage0)]
567-
pub fn of<T: 'static>() -> TypeId {
568-
unsafe { type_id::<T>() }
569-
}
570-
571-
pub fn hash(&self) -> u64 { self.t }
572-
}

Diff for: src/libcoretest/intrinsics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use core::intrinsics::TypeId;
11+
use core::any::TypeId;
1212

1313
#[test]
1414
fn test_typeid_sized_types() {

Diff for: src/librustc/middle/lang_items.rs

-2
Original file line numberDiff line numberDiff line change
@@ -307,8 +307,6 @@ lets_do_this! {
307307
TyDescStructLangItem, "ty_desc", ty_desc;
308308
OpaqueStructLangItem, "opaque", opaque;
309309

310-
TypeIdLangItem, "type_id", type_id;
311-
312310
EhPersonalityLangItem, "eh_personality", eh_personality;
313311

314312
ExchangeHeapLangItem, "exchange_heap", exchange_heap;

Diff for: src/librustc_trans/trans/intrinsic.rs

-2
Original file line numberDiff line numberDiff line change
@@ -355,8 +355,6 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
355355
ccx.tcx(),
356356
*substs.types.get(FnSpace, 0),
357357
&ccx.link_meta().crate_hash);
358-
// NB: This needs to be kept in lockstep with the TypeId struct in
359-
// the intrinsic module
360358
C_u64(ccx, hash)
361359
}
362360
(_, "init") => {

Diff for: src/librustc_typeck/check/mod.rs

+1-13
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@ use rscope::RegionScope;
103103
use session::Session;
104104
use {CrateCtxt, lookup_def_ccx, no_params, require_same_types};
105105
use TypeAndSubsts;
106-
use middle::lang_items::TypeIdLangItem;
107106
use lint;
108107
use util::common::{block_query, indenter, loop_query};
109108
use util::ppaux::{self, UserString, Repr};
@@ -5715,18 +5714,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
57155714
});
57165715
(1u, Vec::new(), td_ptr)
57175716
}
5718-
"type_id" => {
5719-
let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
5720-
match langid {
5721-
Ok(did) => (1u,
5722-
Vec::new(),
5723-
ty::mk_struct(ccx.tcx, did,
5724-
ccx.tcx.mk_substs(subst::Substs::empty()))),
5725-
Err(msg) => {
5726-
tcx.sess.span_fatal(it.span, &msg[]);
5727-
}
5728-
}
5729-
},
5717+
"type_id" => (1u, Vec::new(), ccx.tcx.types.u64),
57305718
"offset" => {
57315719
(1,
57325720
vec!(

Diff for: src/test/auxiliary/issue13507.rs

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

1111
pub mod testtypes {
12-
use std::intrinsics::TypeId;
12+
use std::any::TypeId;
1313

1414
pub fn type_ids() -> Vec<TypeId> {
1515
let mut ids = vec!();

Diff for: src/test/auxiliary/typeid-intrinsic.rs

+10-11
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use std::intrinsics;
12-
use std::intrinsics::TypeId;
11+
use std::any::TypeId;
1312

1413
pub struct A;
1514
pub struct B(Option<A>);
@@ -21,13 +20,13 @@ pub type F = Option<int>;
2120
pub type G = uint;
2221
pub type H = &'static str;
2322

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

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

Diff for: src/test/auxiliary/typeid-intrinsic2.rs

+10-11
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use std::intrinsics;
12-
use std::intrinsics::TypeId;
11+
use std::any::TypeId;
1312

1413
pub struct A;
1514
pub struct B(Option<A>);
@@ -21,13 +20,13 @@ pub type F = Option<int>;
2120
pub type G = uint;
2221
pub type H = &'static str;
2322

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

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

Diff for: src/test/compile-fail/extern-with-type-bounds.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,9 @@
1010

1111
#![feature(intrinsics)]
1212

13-
use std::intrinsics::TypeId;
14-
1513
extern "rust-intrinsic" {
1614
// Real example from libcore
17-
fn type_id<T: ?Sized + 'static>() -> TypeId;
15+
fn type_id<T: ?Sized + 'static>() -> u64;
1816

1917
// Silent bounds made explicit to make sure they are actually
2018
// resolved.

Diff for: src/test/compile-fail/issue-18389.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#![feature(unboxed_closures)]
1212

1313
use std::any::Any;
14-
use std::intrinsics::TypeId;
14+
use std::any::TypeId;
1515

1616
pub trait Pt {}
1717
pub trait Rt {}

Diff for: src/test/run-pass/issue-13507-2.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
extern crate issue13507;
1313
use issue13507::testtypes;
1414

15-
use std::intrinsics::TypeId;
15+
use std::any::TypeId;
1616

1717
pub fn type_ids() -> Vec<TypeId> {
1818
let mut ids = vec!();

Diff for: src/test/run-pass/type-id-higher-rank.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
#![feature(unboxed_closures)]
1515

16-
use std::intrinsics::TypeId;
16+
use std::any::TypeId;
1717

1818
fn main() {
1919
// Bare fns

0 commit comments

Comments
 (0)