Rollup merge of #47892 - Badel2:const_type_id_of, r=oli-obk
Turn `type_id` into a constant intrinsic https://github.com/rust-lang/rust/issues/27745 The method `get_type_id` in `Any` is intended to support reflection. It's currently unstable in favor of using an associated constant instead. This PR makes the `type_id` intrinsic a constant intrinsic, the same as `size_of` and `align_of`, allowing `TypeId::of` to be a `const fn`, which will allow using an associated constant in `Any`.
This commit is contained in:
commit
e17ebdf344
@ -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)]
|
||||
|
@ -327,6 +327,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