mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-09 22:37:34 +00:00
Auto merge of #21165 - alexcrichton:second-pass-type-id, r=aturon
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.
This commit is contained in:
commit
65b61ffb3f
@ -125,8 +125,11 @@ impl<S: hash::Hasher, T: ?Sized + Hash<S>> Hash<S> for Box<T> {
|
||||
}
|
||||
|
||||
/// 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<Any>`"]
|
||||
#[unstable = "this trait will likely disappear once compiler bugs blocking \
|
||||
a direct impl on `Box<Any>` have been fixed "]
|
||||
// FIXME(#18737): this should be a direct impl on `Box<Any>`. If you're
|
||||
// removing this please make sure that you can downcase on
|
||||
// `Box<Any + Send>` as well as `Box<Any>`
|
||||
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<T: 'static>(self) -> Result<Box<T>, Self>;
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl BoxAny for Box<Any> {
|
||||
#[inline]
|
||||
#[unstable = "method may be renamed with respect to other downcasting \
|
||||
methods"]
|
||||
fn downcast<T: 'static>(self) -> Result<Box<T>, Box<Any>> {
|
||||
if self.is::<T>() {
|
||||
unsafe {
|
||||
|
@ -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<T: 'static> 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<T: 'static>(&self) -> Option<&T> {
|
||||
if self.is::<T>() {
|
||||
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<T: 'static>(&mut self) -> Option<&mut T> {
|
||||
if self.is::<T>() {
|
||||
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<T: ?Sized + 'static>() -> TypeId {
|
||||
TypeId {
|
||||
t: unsafe { intrinsics::type_id::<T>() },
|
||||
}
|
||||
}
|
||||
|
||||
/// dox
|
||||
#[cfg(stage0)]
|
||||
pub fn of<T: 'static>() -> TypeId {
|
||||
unsafe { intrinsics::type_id::<T>() }
|
||||
}
|
||||
}
|
||||
|
@ -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<S: Writer + Hasher, T> Hash<S> for *mut T {
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Writer + Hasher> Hash<S> for TypeId {
|
||||
#[inline]
|
||||
fn hash(&self, state: &mut S) {
|
||||
self.hash().hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, B: ?Sized, S: Hasher> Hash<S> for Cow<'a, T, B>
|
||||
where B: Hash<S> + ToOwned<T>
|
||||
{
|
||||
|
@ -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<T: ?Sized + 'static>() -> u64;
|
||||
|
||||
#[cfg(stage0)]
|
||||
pub fn type_id<T: ?Sized + 'static>() -> 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<T: ?Sized + 'static>() -> TypeId {
|
||||
unsafe { type_id::<T>() }
|
||||
}
|
||||
|
||||
pub fn hash(&self) -> u64 { self.t }
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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;
|
||||
|
@ -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") => {
|
||||
|
@ -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!(
|
||||
|
@ -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<TypeId> {
|
||||
let mut ids = vec!();
|
||||
|
@ -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<A>);
|
||||
@ -21,13 +20,13 @@ pub type F = Option<int>;
|
||||
pub type G = uint;
|
||||
pub type H = &'static str;
|
||||
|
||||
pub unsafe fn id_A() -> TypeId { intrinsics::type_id::<A>() }
|
||||
pub unsafe fn id_B() -> TypeId { intrinsics::type_id::<B>() }
|
||||
pub unsafe fn id_C() -> TypeId { intrinsics::type_id::<C>() }
|
||||
pub unsafe fn id_D() -> TypeId { intrinsics::type_id::<D>() }
|
||||
pub unsafe fn id_E() -> TypeId { intrinsics::type_id::<E>() }
|
||||
pub unsafe fn id_F() -> TypeId { intrinsics::type_id::<F>() }
|
||||
pub unsafe fn id_G() -> TypeId { intrinsics::type_id::<G>() }
|
||||
pub unsafe fn id_H() -> TypeId { intrinsics::type_id::<H>() }
|
||||
pub unsafe fn id_A() -> TypeId { TypeId::of::<A>() }
|
||||
pub unsafe fn id_B() -> TypeId { TypeId::of::<B>() }
|
||||
pub unsafe fn id_C() -> TypeId { TypeId::of::<C>() }
|
||||
pub unsafe fn id_D() -> TypeId { TypeId::of::<D>() }
|
||||
pub unsafe fn id_E() -> TypeId { TypeId::of::<E>() }
|
||||
pub unsafe fn id_F() -> TypeId { TypeId::of::<F>() }
|
||||
pub unsafe fn id_G() -> TypeId { TypeId::of::<G>() }
|
||||
pub unsafe fn id_H() -> TypeId { TypeId::of::<H>() }
|
||||
|
||||
pub unsafe fn foo<T: 'static>() -> TypeId { intrinsics::type_id::<T>() }
|
||||
pub unsafe fn foo<T: 'static>() -> TypeId { TypeId::of::<T>() }
|
||||
|
@ -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<A>);
|
||||
@ -21,13 +20,13 @@ pub type F = Option<int>;
|
||||
pub type G = uint;
|
||||
pub type H = &'static str;
|
||||
|
||||
pub unsafe fn id_A() -> TypeId { intrinsics::type_id::<A>() }
|
||||
pub unsafe fn id_B() -> TypeId { intrinsics::type_id::<B>() }
|
||||
pub unsafe fn id_C() -> TypeId { intrinsics::type_id::<C>() }
|
||||
pub unsafe fn id_D() -> TypeId { intrinsics::type_id::<D>() }
|
||||
pub unsafe fn id_E() -> TypeId { intrinsics::type_id::<E>() }
|
||||
pub unsafe fn id_F() -> TypeId { intrinsics::type_id::<F>() }
|
||||
pub unsafe fn id_G() -> TypeId { intrinsics::type_id::<G>() }
|
||||
pub unsafe fn id_H() -> TypeId { intrinsics::type_id::<H>() }
|
||||
pub unsafe fn id_A() -> TypeId { TypeId::of::<A>() }
|
||||
pub unsafe fn id_B() -> TypeId { TypeId::of::<B>() }
|
||||
pub unsafe fn id_C() -> TypeId { TypeId::of::<C>() }
|
||||
pub unsafe fn id_D() -> TypeId { TypeId::of::<D>() }
|
||||
pub unsafe fn id_E() -> TypeId { TypeId::of::<E>() }
|
||||
pub unsafe fn id_F() -> TypeId { TypeId::of::<F>() }
|
||||
pub unsafe fn id_G() -> TypeId { TypeId::of::<G>() }
|
||||
pub unsafe fn id_H() -> TypeId { TypeId::of::<H>() }
|
||||
|
||||
pub unsafe fn foo<T: 'static>() -> TypeId { intrinsics::type_id::<T>() }
|
||||
pub unsafe fn foo<T: 'static>() -> TypeId { TypeId::of::<T>() }
|
||||
|
@ -10,11 +10,9 @@
|
||||
|
||||
#![feature(intrinsics)]
|
||||
|
||||
use std::intrinsics::TypeId;
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
// Real example from libcore
|
||||
fn type_id<T: ?Sized + 'static>() -> TypeId;
|
||||
fn type_id<T: ?Sized + 'static>() -> u64;
|
||||
|
||||
// Silent bounds made explicit to make sure they are actually
|
||||
// resolved.
|
||||
|
@ -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 {}
|
||||
|
@ -12,7 +12,7 @@
|
||||
extern crate issue13507;
|
||||
use issue13507::testtypes;
|
||||
|
||||
use std::intrinsics::TypeId;
|
||||
use std::any::TypeId;
|
||||
|
||||
pub fn type_ids() -> Vec<TypeId> {
|
||||
let mut ids = vec!();
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
#![feature(unboxed_closures)]
|
||||
|
||||
use std::intrinsics::TypeId;
|
||||
use std::any::TypeId;
|
||||
|
||||
fn main() {
|
||||
// Bare fns
|
||||
|
@ -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::A>(), other1::id_A());
|
||||
assert_eq!(intrinsics::type_id::<other1::B>(), other1::id_B());
|
||||
assert_eq!(intrinsics::type_id::<other1::C>(), other1::id_C());
|
||||
assert_eq!(intrinsics::type_id::<other1::D>(), other1::id_D());
|
||||
assert_eq!(intrinsics::type_id::<other1::E>(), other1::id_E());
|
||||
assert_eq!(intrinsics::type_id::<other1::F>(), other1::id_F());
|
||||
assert_eq!(intrinsics::type_id::<other1::G>(), other1::id_G());
|
||||
assert_eq!(intrinsics::type_id::<other1::H>(), other1::id_H());
|
||||
assert_eq!(TypeId::of::<other1::A>(), other1::id_A());
|
||||
assert_eq!(TypeId::of::<other1::B>(), other1::id_B());
|
||||
assert_eq!(TypeId::of::<other1::C>(), other1::id_C());
|
||||
assert_eq!(TypeId::of::<other1::D>(), other1::id_D());
|
||||
assert_eq!(TypeId::of::<other1::E>(), other1::id_E());
|
||||
assert_eq!(TypeId::of::<other1::F>(), other1::id_F());
|
||||
assert_eq!(TypeId::of::<other1::G>(), other1::id_G());
|
||||
assert_eq!(TypeId::of::<other1::H>(), other1::id_H());
|
||||
|
||||
assert_eq!(intrinsics::type_id::<other2::A>(), other2::id_A());
|
||||
assert_eq!(intrinsics::type_id::<other2::B>(), other2::id_B());
|
||||
assert_eq!(intrinsics::type_id::<other2::C>(), other2::id_C());
|
||||
assert_eq!(intrinsics::type_id::<other2::D>(), other2::id_D());
|
||||
assert_eq!(intrinsics::type_id::<other2::E>(), other2::id_E());
|
||||
assert_eq!(intrinsics::type_id::<other2::F>(), other2::id_F());
|
||||
assert_eq!(intrinsics::type_id::<other2::G>(), other2::id_G());
|
||||
assert_eq!(intrinsics::type_id::<other2::H>(), other2::id_H());
|
||||
assert_eq!(TypeId::of::<other2::A>(), other2::id_A());
|
||||
assert_eq!(TypeId::of::<other2::B>(), other2::id_B());
|
||||
assert_eq!(TypeId::of::<other2::C>(), other2::id_C());
|
||||
assert_eq!(TypeId::of::<other2::D>(), other2::id_D());
|
||||
assert_eq!(TypeId::of::<other2::E>(), other2::id_E());
|
||||
assert_eq!(TypeId::of::<other2::F>(), other2::id_F());
|
||||
assert_eq!(TypeId::of::<other2::G>(), other2::id_G());
|
||||
assert_eq!(TypeId::of::<other2::H>(), 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::<int>(), other2::foo::<int>());
|
||||
assert_eq!(intrinsics::type_id::<int>(), other1::foo::<int>());
|
||||
assert_eq!(TypeId::of::<int>(), other2::foo::<int>());
|
||||
assert_eq!(TypeId::of::<int>(), other1::foo::<int>());
|
||||
assert_eq!(other2::foo::<int>(), other1::foo::<int>());
|
||||
assert_eq!(intrinsics::type_id::<A>(), other2::foo::<A>());
|
||||
assert_eq!(intrinsics::type_id::<A>(), other1::foo::<A>());
|
||||
assert_eq!(TypeId::of::<A>(), other2::foo::<A>());
|
||||
assert_eq!(TypeId::of::<A>(), other1::foo::<A>());
|
||||
assert_eq!(other2::foo::<A>(), other1::foo::<A>());
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user