From 70f7165cc8975337964118af4d30f40b98f5edeb Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 14 Jan 2015 16:08:07 -0800 Subject: [PATCH] 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` is allowed today it does not allow downcasting of trait objects like `Box` (those returned from `Thread::join`). This is covered by #18737. * `BoxAny::downcast` is now stable. --- src/liballoc/boxed.rs | 10 ++-- src/libcore/any.rs | 54 +++++++++++++++---- src/libcore/hash/mod.rs | 8 --- src/libcore/intrinsics.rs | 24 +++------ src/libcoretest/intrinsics.rs | 2 +- src/librustc/middle/lang_items.rs | 2 - src/librustc_trans/trans/intrinsic.rs | 2 - src/librustc_typeck/check/mod.rs | 14 +---- src/test/auxiliary/issue13507.rs | 2 +- src/test/auxiliary/typeid-intrinsic.rs | 21 ++++---- src/test/auxiliary/typeid-intrinsic2.rs | 21 ++++---- .../compile-fail/extern-with-type-bounds.rs | 4 +- src/test/compile-fail/issue-18389.rs | 2 +- src/test/run-pass/issue-13507-2.rs | 2 +- src/test/run-pass/type-id-higher-rank.rs | 2 +- src/test/run-pass/typeid-intrinsic.rs | 43 ++++++++------- 16 files changed, 105 insertions(+), 108 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 8ad0c152dc8ed..a2cc98c7d0129 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -125,8 +125,11 @@ impl> Hash for Box { } /// Extension methods for an owning `Any` trait object. -#[unstable = "post-DST and coherence changes, this will not be a trait but \ - rather a direct `impl` on `Box`"] +#[unstable = "this trait will likely disappear once compiler bugs blocking \ + a direct impl on `Box` have been fixed "] +// FIXME(#18737): this should be a direct impl on `Box`. If you're +// removing this please make sure that you can downcase on +// `Box` as well as `Box` pub trait BoxAny { /// Returns the boxed value if it is of type `T`, or /// `Err(Self)` if it isn't. @@ -134,10 +137,9 @@ pub trait BoxAny { fn downcast(self) -> Result, Self>; } +#[stable] impl BoxAny for Box { #[inline] - #[unstable = "method may be renamed with respect to other downcasting \ - methods"] fn downcast(self) -> Result, Box> { if self.is::() { unsafe { diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 797687a9ad96e..20ed2253861ce 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -71,11 +71,11 @@ #![stable] -use mem::{transmute}; -use option::Option; -use option::Option::{Some, None}; +use mem::transmute; +use option::Option::{self, Some, None}; use raw::TraitObject; -use intrinsics::TypeId; +use intrinsics; +#[cfg(not(stage0))] use marker::Sized; /////////////////////////////////////////////////////////////////////////////// // Any trait @@ -99,7 +99,6 @@ impl Any for T { /////////////////////////////////////////////////////////////////////////////// // Extension methods for Any trait objects. -// Implemented as three extension traits so that the methods can be generic. /////////////////////////////////////////////////////////////////////////////// impl Any { @@ -119,9 +118,9 @@ impl Any { /// Returns some reference to the boxed value if it is of type `T`, or /// `None` if it isn't. - #[unstable = "naming conventions around acquiring references may change"] + #[stable] #[inline] - pub fn downcast_ref<'a, T: 'static>(&'a self) -> Option<&'a T> { + pub fn downcast_ref(&self) -> Option<&T> { if self.is::() { unsafe { // Get the raw representation of the trait object @@ -137,9 +136,9 @@ impl Any { /// Returns some mutable reference to the boxed value if it is of type `T`, or /// `None` if it isn't. - #[unstable = "naming conventions around acquiring references may change"] + #[stable] #[inline] - pub fn downcast_mut<'a, T: 'static>(&'a mut self) -> Option<&'a mut T> { + pub fn downcast_mut(&mut self) -> Option<&mut T> { if self.is::() { unsafe { // Get the raw representation of the trait object @@ -153,3 +152,40 @@ impl Any { } } } + +/////////////////////////////////////////////////////////////////////////////// +// TypeID and its methods +/////////////////////////////////////////////////////////////////////////////// + +/// A `TypeId` represents a globally unique identifier for a type. +/// +/// Each `TypeId` is an opaque object which does not allow inspection of what's +/// inside but does allow basic operations such as cloning, comparison, +/// printing, and showing. +/// +/// A `TypeId` is currently only available for types which ascribe to `'static`, +/// but this limitation may be removed in the future. +#[cfg_attr(stage0, lang = "type_id")] +#[derive(Clone, Copy, PartialEq, Eq, Show, Hash)] +#[stable] +pub struct TypeId { + t: u64, +} + +impl TypeId { + /// Returns the `TypeId` of the type this generic function has been + /// instantiated with + #[cfg(not(stage0))] + #[unstable = "may grow a `Reflect` bound soon via marker traits"] + pub fn of() -> TypeId { + TypeId { + t: unsafe { intrinsics::type_id::() }, + } + } + + /// dox + #[cfg(stage0)] + pub fn of() -> TypeId { + unsafe { intrinsics::type_id::() } + } +} diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index 37e4a105a30cb..742e623901777 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -62,7 +62,6 @@ use prelude::*; use borrow::{Cow, ToOwned}; use default::Default; -use intrinsics::TypeId; use mem; use num::Int; @@ -243,13 +242,6 @@ impl Hash for *mut T { } } -impl Hash for TypeId { - #[inline] - fn hash(&self, state: &mut S) { - self.hash().hash(state) - } -} - impl<'a, T, B: ?Sized, S: Hasher> Hash for Cow<'a, T, B> where B: Hash + ToOwned { diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 40db0def62667..73be68289c9b7 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -44,6 +44,8 @@ use marker::Sized; +#[cfg(stage0)] use any::TypeId; + pub type GlueFn = extern "Rust" fn(*const i8); #[lang="ty_desc"] @@ -206,6 +208,10 @@ extern "rust-intrinsic" { /// 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() -> u64; + + #[cfg(stage0)] pub fn type_id() -> TypeId; /// Create a value initialized to zero. @@ -545,21 +551,3 @@ extern "rust-intrinsic" { /// Performs checked `u64` multiplication. pub fn u64_mul_with_overflow(x: u64, y: u64) -> (u64, bool); } - - -/// `TypeId` represents a globally unique identifier for a type -#[lang="type_id"] // This needs to be kept in lockstep with the code in trans/intrinsic.rs and - // middle/lang_items.rs -#[derive(Clone, Copy, PartialEq, Eq, Show)] -pub struct TypeId { - t: u64, -} - -impl TypeId { - /// Returns the `TypeId` of the type this generic function has been instantiated with - pub fn of() -> TypeId { - unsafe { type_id::() } - } - - pub fn hash(&self) -> u64 { self.t } -} diff --git a/src/libcoretest/intrinsics.rs b/src/libcoretest/intrinsics.rs index bcf8a6a433b94..b836f5f3f69f4 100644 --- a/src/libcoretest/intrinsics.rs +++ b/src/libcoretest/intrinsics.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::intrinsics::TypeId; +use core::any::TypeId; #[test] fn test_typeid_sized_types() { diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 2f81d8c0f701e..f7e5c3fb6d9b7 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -307,8 +307,6 @@ lets_do_this! { TyDescStructLangItem, "ty_desc", ty_desc; OpaqueStructLangItem, "opaque", opaque; - TypeIdLangItem, "type_id", type_id; - EhPersonalityLangItem, "eh_personality", eh_personality; ExchangeHeapLangItem, "exchange_heap", exchange_heap; diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index 91c7409182df6..7a59420bea455 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -355,8 +355,6 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, ccx.tcx(), *substs.types.get(FnSpace, 0), &ccx.link_meta().crate_hash); - // NB: This needs to be kept in lockstep with the TypeId struct in - // the intrinsic module C_u64(ccx, hash) } (_, "init") => { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7e38321049ed7..69044e147c9d7 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -104,7 +104,6 @@ use rscope::RegionScope; use session::Session; use {CrateCtxt, lookup_def_ccx, no_params, require_same_types}; use TypeAndSubsts; -use middle::lang_items::TypeIdLangItem; use lint; use util::common::{block_query, indenter, loop_query}; use util::ppaux::{self, Repr}; @@ -5239,18 +5238,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { }); (1u, Vec::new(), td_ptr) } - "type_id" => { - let langid = ccx.tcx.lang_items.require(TypeIdLangItem); - match langid { - Ok(did) => (1u, - Vec::new(), - ty::mk_struct(ccx.tcx, did, - ccx.tcx.mk_substs(subst::Substs::empty()))), - Err(msg) => { - tcx.sess.span_fatal(it.span, &msg[]); - } - } - }, + "type_id" => (1u, Vec::new(), ccx.tcx.types.u64), "offset" => { (1, vec!( diff --git a/src/test/auxiliary/issue13507.rs b/src/test/auxiliary/issue13507.rs index c2820a8d4ae5d..f24721adb5d96 100644 --- a/src/test/auxiliary/issue13507.rs +++ b/src/test/auxiliary/issue13507.rs @@ -9,7 +9,7 @@ // except according to those terms. pub mod testtypes { - use std::intrinsics::TypeId; + use std::any::TypeId; pub fn type_ids() -> Vec { let mut ids = vec!(); diff --git a/src/test/auxiliary/typeid-intrinsic.rs b/src/test/auxiliary/typeid-intrinsic.rs index b6c35f48010ca..82f613ee117ca 100644 --- a/src/test/auxiliary/typeid-intrinsic.rs +++ b/src/test/auxiliary/typeid-intrinsic.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::intrinsics; -use std::intrinsics::TypeId; +use std::any::TypeId; pub struct A; pub struct B(Option); @@ -21,13 +20,13 @@ pub type F = Option; pub type G = uint; pub type H = &'static str; -pub unsafe fn id_A() -> TypeId { intrinsics::type_id::() } -pub unsafe fn id_B() -> TypeId { intrinsics::type_id::() } -pub unsafe fn id_C() -> TypeId { intrinsics::type_id::() } -pub unsafe fn id_D() -> TypeId { intrinsics::type_id::() } -pub unsafe fn id_E() -> TypeId { intrinsics::type_id::() } -pub unsafe fn id_F() -> TypeId { intrinsics::type_id::() } -pub unsafe fn id_G() -> TypeId { intrinsics::type_id::() } -pub unsafe fn id_H() -> TypeId { intrinsics::type_id::() } +pub unsafe fn id_A() -> TypeId { TypeId::of::() } +pub unsafe fn id_B() -> TypeId { TypeId::of::() } +pub unsafe fn id_C() -> TypeId { TypeId::of::() } +pub unsafe fn id_D() -> TypeId { TypeId::of::() } +pub unsafe fn id_E() -> TypeId { TypeId::of::() } +pub unsafe fn id_F() -> TypeId { TypeId::of::() } +pub unsafe fn id_G() -> TypeId { TypeId::of::() } +pub unsafe fn id_H() -> TypeId { TypeId::of::() } -pub unsafe fn foo() -> TypeId { intrinsics::type_id::() } +pub unsafe fn foo() -> TypeId { TypeId::of::() } diff --git a/src/test/auxiliary/typeid-intrinsic2.rs b/src/test/auxiliary/typeid-intrinsic2.rs index b6c35f48010ca..82f613ee117ca 100644 --- a/src/test/auxiliary/typeid-intrinsic2.rs +++ b/src/test/auxiliary/typeid-intrinsic2.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::intrinsics; -use std::intrinsics::TypeId; +use std::any::TypeId; pub struct A; pub struct B(Option); @@ -21,13 +20,13 @@ pub type F = Option; pub type G = uint; pub type H = &'static str; -pub unsafe fn id_A() -> TypeId { intrinsics::type_id::() } -pub unsafe fn id_B() -> TypeId { intrinsics::type_id::() } -pub unsafe fn id_C() -> TypeId { intrinsics::type_id::() } -pub unsafe fn id_D() -> TypeId { intrinsics::type_id::() } -pub unsafe fn id_E() -> TypeId { intrinsics::type_id::() } -pub unsafe fn id_F() -> TypeId { intrinsics::type_id::() } -pub unsafe fn id_G() -> TypeId { intrinsics::type_id::() } -pub unsafe fn id_H() -> TypeId { intrinsics::type_id::() } +pub unsafe fn id_A() -> TypeId { TypeId::of::() } +pub unsafe fn id_B() -> TypeId { TypeId::of::() } +pub unsafe fn id_C() -> TypeId { TypeId::of::() } +pub unsafe fn id_D() -> TypeId { TypeId::of::() } +pub unsafe fn id_E() -> TypeId { TypeId::of::() } +pub unsafe fn id_F() -> TypeId { TypeId::of::() } +pub unsafe fn id_G() -> TypeId { TypeId::of::() } +pub unsafe fn id_H() -> TypeId { TypeId::of::() } -pub unsafe fn foo() -> TypeId { intrinsics::type_id::() } +pub unsafe fn foo() -> TypeId { TypeId::of::() } diff --git a/src/test/compile-fail/extern-with-type-bounds.rs b/src/test/compile-fail/extern-with-type-bounds.rs index d2c88865d54f2..ade8b397e0003 100644 --- a/src/test/compile-fail/extern-with-type-bounds.rs +++ b/src/test/compile-fail/extern-with-type-bounds.rs @@ -10,11 +10,9 @@ #![feature(intrinsics)] -use std::intrinsics::TypeId; - extern "rust-intrinsic" { // Real example from libcore - fn type_id() -> TypeId; + fn type_id() -> u64; // Silent bounds made explicit to make sure they are actually // resolved. diff --git a/src/test/compile-fail/issue-18389.rs b/src/test/compile-fail/issue-18389.rs index 37bb1cb1911e5..20323e9900333 100644 --- a/src/test/compile-fail/issue-18389.rs +++ b/src/test/compile-fail/issue-18389.rs @@ -11,7 +11,7 @@ #![feature(unboxed_closures)] use std::any::Any; -use std::intrinsics::TypeId; +use std::any::TypeId; pub trait Pt {} pub trait Rt {} diff --git a/src/test/run-pass/issue-13507-2.rs b/src/test/run-pass/issue-13507-2.rs index 4d150e7a68e7c..1c0283070a249 100644 --- a/src/test/run-pass/issue-13507-2.rs +++ b/src/test/run-pass/issue-13507-2.rs @@ -12,7 +12,7 @@ extern crate issue13507; use issue13507::testtypes; -use std::intrinsics::TypeId; +use std::any::TypeId; pub fn type_ids() -> Vec { let mut ids = vec!(); diff --git a/src/test/run-pass/type-id-higher-rank.rs b/src/test/run-pass/type-id-higher-rank.rs index 7287d149f5100..b114391a36db0 100644 --- a/src/test/run-pass/type-id-higher-rank.rs +++ b/src/test/run-pass/type-id-higher-rank.rs @@ -13,7 +13,7 @@ #![feature(unboxed_closures)] -use std::intrinsics::TypeId; +use std::any::TypeId; fn main() { // Bare fns diff --git a/src/test/run-pass/typeid-intrinsic.rs b/src/test/run-pass/typeid-intrinsic.rs index e346c4ff3495e..a251fcc732720 100644 --- a/src/test/run-pass/typeid-intrinsic.rs +++ b/src/test/run-pass/typeid-intrinsic.rs @@ -15,41 +15,40 @@ extern crate "typeid-intrinsic" as other1; extern crate "typeid-intrinsic2" as other2; use std::hash::{self, SipHasher}; -use std::intrinsics; -use std::intrinsics::TypeId; +use std::any::TypeId; struct A; struct Test; pub fn main() { unsafe { - assert_eq!(intrinsics::type_id::(), other1::id_A()); - assert_eq!(intrinsics::type_id::(), other1::id_B()); - assert_eq!(intrinsics::type_id::(), other1::id_C()); - assert_eq!(intrinsics::type_id::(), other1::id_D()); - assert_eq!(intrinsics::type_id::(), other1::id_E()); - assert_eq!(intrinsics::type_id::(), other1::id_F()); - assert_eq!(intrinsics::type_id::(), other1::id_G()); - assert_eq!(intrinsics::type_id::(), other1::id_H()); + assert_eq!(TypeId::of::(), other1::id_A()); + assert_eq!(TypeId::of::(), other1::id_B()); + assert_eq!(TypeId::of::(), other1::id_C()); + assert_eq!(TypeId::of::(), other1::id_D()); + assert_eq!(TypeId::of::(), other1::id_E()); + assert_eq!(TypeId::of::(), other1::id_F()); + assert_eq!(TypeId::of::(), other1::id_G()); + assert_eq!(TypeId::of::(), other1::id_H()); - assert_eq!(intrinsics::type_id::(), other2::id_A()); - assert_eq!(intrinsics::type_id::(), other2::id_B()); - assert_eq!(intrinsics::type_id::(), other2::id_C()); - assert_eq!(intrinsics::type_id::(), other2::id_D()); - assert_eq!(intrinsics::type_id::(), other2::id_E()); - assert_eq!(intrinsics::type_id::(), other2::id_F()); - assert_eq!(intrinsics::type_id::(), other2::id_G()); - assert_eq!(intrinsics::type_id::(), other2::id_H()); + assert_eq!(TypeId::of::(), other2::id_A()); + assert_eq!(TypeId::of::(), other2::id_B()); + assert_eq!(TypeId::of::(), other2::id_C()); + assert_eq!(TypeId::of::(), other2::id_D()); + assert_eq!(TypeId::of::(), other2::id_E()); + assert_eq!(TypeId::of::(), other2::id_F()); + assert_eq!(TypeId::of::(), other2::id_G()); + assert_eq!(TypeId::of::(), 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::(), other2::foo::()); - assert_eq!(intrinsics::type_id::(), other1::foo::()); + assert_eq!(TypeId::of::(), other2::foo::()); + assert_eq!(TypeId::of::(), other1::foo::()); assert_eq!(other2::foo::(), other1::foo::()); - assert_eq!(intrinsics::type_id::(), other2::foo::()); - assert_eq!(intrinsics::type_id::(), other1::foo::()); + assert_eq!(TypeId::of::(), other2::foo::()); + assert_eq!(TypeId::of::(), other1::foo::()); assert_eq!(other2::foo::(), other1::foo::()); }