mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-18 02:34:37 +00:00
Turn type_id
into a constant intrinsic
Add rustc_const_unstable attribute for `any::TypeId::of` Add test for `const fn TypeId::of`
This commit is contained in:
parent
def3269a71
commit
196fad0d00
@ -367,9 +367,36 @@ impl TypeId {
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(stage0)]
|
||||
pub fn of<T: ?Sized + 'static>() -> TypeId {
|
||||
TypeId {
|
||||
t: unsafe { intrinsics::type_id::<T>() },
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the `TypeId` of the type this generic function has been
|
||||
/// instantiated with.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::any::{Any, TypeId};
|
||||
///
|
||||
/// fn is_string<T: ?Sized + Any>(_s: &T) -> bool {
|
||||
/// TypeId::of::<String>() == TypeId::of::<T>()
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// assert_eq!(is_string(&0), false);
|
||||
/// assert_eq!(is_string(&"cookie monster".to_string()), true);
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature="const_type_id")]
|
||||
#[cfg(not(stage0))]
|
||||
pub const fn of<T: ?Sized + 'static>() -> TypeId {
|
||||
TypeId {
|
||||
t: unsafe { intrinsics::type_id::<T>() },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -91,6 +91,7 @@
|
||||
#![feature(untagged_unions)]
|
||||
#![feature(unwind_attributes)]
|
||||
#![feature(doc_spotlight)]
|
||||
#![feature(rustc_const_unstable)]
|
||||
|
||||
#[prelude_import]
|
||||
#[allow(unused)]
|
||||
|
@ -328,6 +328,10 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
||||
return Ok(mk_const(Integral(Usize(ConstUsize::new(align,
|
||||
tcx.sess.target.usize_ty).unwrap()))));
|
||||
}
|
||||
"type_id" => {
|
||||
let type_id = tcx.type_id_hash(substs.type_at(0));
|
||||
return Ok(mk_const(Integral(U64(type_id))));
|
||||
}
|
||||
_ => signal!(e, TypeckError)
|
||||
}
|
||||
}
|
||||
|
@ -243,6 +243,12 @@ impl<'tcx> super::Machine<'tcx> for CompileTimeEvaluator {
|
||||
ecx.write_primval(dest, PrimVal::from_u128(size), dest_layout.ty)?;
|
||||
}
|
||||
|
||||
"type_id" => {
|
||||
let ty = substs.type_at(0);
|
||||
let type_id = ecx.tcx.type_id_hash(ty) as u128;
|
||||
ecx.write_primval(dest, PrimVal::from_u128(type_id), dest_layout.ty)?;
|
||||
}
|
||||
|
||||
name => return Err(ConstEvalError::NeedsRfc(format!("calling intrinsic `{}`", name)).into()),
|
||||
}
|
||||
|
||||
|
@ -737,7 +737,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
||||
Abi::PlatformIntrinsic => {
|
||||
assert!(!self.tcx.is_const_fn(def_id));
|
||||
match &self.tcx.item_name(def_id)[..] {
|
||||
"size_of" | "min_align_of" => is_const_fn = Some(def_id),
|
||||
"size_of" | "min_align_of" | "type_id" => is_const_fn = Some(def_id),
|
||||
|
||||
name if name.starts_with("simd_shuffle") => {
|
||||
is_shuffle = true;
|
||||
|
@ -411,6 +411,11 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
||||
self.cx.align_of(substs.type_at(0)).abi());
|
||||
Ok(Const::new(llval, tcx.types.usize))
|
||||
}
|
||||
"type_id" => {
|
||||
let llval = C_u64(self.cx,
|
||||
self.cx.tcx.type_id_hash(substs.type_at(0)));
|
||||
Ok(Const::new(llval, tcx.types.u64))
|
||||
}
|
||||
_ => span_bug!(span, "{:?} in constant", terminator.kind)
|
||||
}
|
||||
} else if let Some((op, is_checked)) = self.is_binop_lang_item(def_id) {
|
||||
|
18
src/test/compile-fail/const-typeid-of.rs
Normal file
18
src/test/compile-fail/const-typeid-of.rs
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::any::TypeId;
|
||||
|
||||
struct A;
|
||||
|
||||
fn main() {
|
||||
const A_ID: TypeId = TypeId::of::<A>();
|
||||
//~^ ERROR `std::any::TypeId::of` is not yet stable as a const fn
|
||||
}
|
43
src/test/run-pass/const-typeid-of.rs
Normal file
43
src/test/run-pass/const-typeid-of.rs
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(const_type_id)]
|
||||
|
||||
use std::any::TypeId;
|
||||
|
||||
struct A;
|
||||
|
||||
static ID_ISIZE: TypeId = TypeId::of::<isize>();
|
||||
|
||||
pub fn main() {
|
||||
assert_eq!(ID_ISIZE, TypeId::of::<isize>());
|
||||
|
||||
// sanity test of TypeId
|
||||
const T: (TypeId, TypeId, TypeId) = (TypeId::of::<usize>(),
|
||||
TypeId::of::<&'static str>(),
|
||||
TypeId::of::<A>());
|
||||
let (d, e, f) = (TypeId::of::<usize>(), TypeId::of::<&'static str>(),
|
||||
TypeId::of::<A>());
|
||||
|
||||
assert!(T.0 != T.1);
|
||||
assert!(T.0 != T.2);
|
||||
assert!(T.1 != T.2);
|
||||
|
||||
assert_eq!(T.0, d);
|
||||
assert_eq!(T.1, e);
|
||||
assert_eq!(T.2, f);
|
||||
|
||||
// Check fn pointer against collisions
|
||||
const F: (TypeId, TypeId) = (TypeId::of::<fn(fn(A) -> A) -> A>(),
|
||||
TypeId::of::<fn(fn() -> A, A) -> A>());
|
||||
|
||||
assert!(F.0 != F.1);
|
||||
}
|
Loading…
Reference in New Issue
Block a user