Skip to content

Commit e17ebdf

Browse files
committed
Rollup merge of rust-lang#47892 - Badel2:const_type_id_of, r=oli-obk
Turn `type_id` into a constant intrinsic rust-lang#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`.
2 parents 66d6c85 + 196fad0 commit e17ebdf

File tree

8 files changed

+105
-1
lines changed

8 files changed

+105
-1
lines changed

src/libcore/any.rs

+27
Original file line numberDiff line numberDiff line change
@@ -367,9 +367,36 @@ impl TypeId {
367367
/// }
368368
/// ```
369369
#[stable(feature = "rust1", since = "1.0.0")]
370+
#[cfg(stage0)]
370371
pub fn of<T: ?Sized + 'static>() -> TypeId {
371372
TypeId {
372373
t: unsafe { intrinsics::type_id::<T>() },
373374
}
374375
}
376+
377+
/// Returns the `TypeId` of the type this generic function has been
378+
/// instantiated with.
379+
///
380+
/// # Examples
381+
///
382+
/// ```
383+
/// use std::any::{Any, TypeId};
384+
///
385+
/// fn is_string<T: ?Sized + Any>(_s: &T) -> bool {
386+
/// TypeId::of::<String>() == TypeId::of::<T>()
387+
/// }
388+
///
389+
/// fn main() {
390+
/// assert_eq!(is_string(&0), false);
391+
/// assert_eq!(is_string(&"cookie monster".to_string()), true);
392+
/// }
393+
/// ```
394+
#[stable(feature = "rust1", since = "1.0.0")]
395+
#[rustc_const_unstable(feature="const_type_id")]
396+
#[cfg(not(stage0))]
397+
pub const fn of<T: ?Sized + 'static>() -> TypeId {
398+
TypeId {
399+
t: unsafe { intrinsics::type_id::<T>() },
400+
}
401+
}
375402
}

src/libcore/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
#![feature(untagged_unions)]
9292
#![feature(unwind_attributes)]
9393
#![feature(doc_spotlight)]
94+
#![feature(rustc_const_unstable)]
9495

9596
#[prelude_import]
9697
#[allow(unused)]

src/librustc_const_eval/eval.rs

+4
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,10 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
327327
return Ok(mk_const(Integral(Usize(ConstUsize::new(align,
328328
tcx.sess.target.usize_ty).unwrap()))));
329329
}
330+
"type_id" => {
331+
let type_id = tcx.type_id_hash(substs.type_at(0));
332+
return Ok(mk_const(Integral(U64(type_id))));
333+
}
330334
_ => signal!(e, TypeckError)
331335
}
332336
}

src/librustc_mir/interpret/const_eval.rs

+6
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,12 @@ impl<'tcx> super::Machine<'tcx> for CompileTimeEvaluator {
243243
ecx.write_primval(dest, PrimVal::from_u128(size), dest_layout.ty)?;
244244
}
245245

246+
"type_id" => {
247+
let ty = substs.type_at(0);
248+
let type_id = ecx.tcx.type_id_hash(ty) as u128;
249+
ecx.write_primval(dest, PrimVal::from_u128(type_id), dest_layout.ty)?;
250+
}
251+
246252
name => return Err(ConstEvalError::NeedsRfc(format!("calling intrinsic `{}`", name)).into()),
247253
}
248254

src/librustc_mir/transform/qualify_consts.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -737,7 +737,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
737737
Abi::PlatformIntrinsic => {
738738
assert!(!self.tcx.is_const_fn(def_id));
739739
match &self.tcx.item_name(def_id)[..] {
740-
"size_of" | "min_align_of" => is_const_fn = Some(def_id),
740+
"size_of" | "min_align_of" | "type_id" => is_const_fn = Some(def_id),
741741

742742
name if name.starts_with("simd_shuffle") => {
743743
is_shuffle = true;

src/librustc_trans/mir/constant.rs

+5
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,11 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
411411
self.cx.align_of(substs.type_at(0)).abi());
412412
Ok(Const::new(llval, tcx.types.usize))
413413
}
414+
"type_id" => {
415+
let llval = C_u64(self.cx,
416+
self.cx.tcx.type_id_hash(substs.type_at(0)));
417+
Ok(Const::new(llval, tcx.types.u64))
418+
}
414419
_ => span_bug!(span, "{:?} in constant", terminator.kind)
415420
}
416421
} else if let Some((op, is_checked)) = self.is_binop_lang_item(def_id) {
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use std::any::TypeId;
12+
13+
struct A;
14+
15+
fn main() {
16+
const A_ID: TypeId = TypeId::of::<A>();
17+
//~^ ERROR `std::any::TypeId::of` is not yet stable as a const fn
18+
}

src/test/run-pass/const-typeid-of.rs

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(core_intrinsics)]
12+
#![feature(const_type_id)]
13+
14+
use std::any::TypeId;
15+
16+
struct A;
17+
18+
static ID_ISIZE: TypeId = TypeId::of::<isize>();
19+
20+
pub fn main() {
21+
assert_eq!(ID_ISIZE, TypeId::of::<isize>());
22+
23+
// sanity test of TypeId
24+
const T: (TypeId, TypeId, TypeId) = (TypeId::of::<usize>(),
25+
TypeId::of::<&'static str>(),
26+
TypeId::of::<A>());
27+
let (d, e, f) = (TypeId::of::<usize>(), TypeId::of::<&'static str>(),
28+
TypeId::of::<A>());
29+
30+
assert!(T.0 != T.1);
31+
assert!(T.0 != T.2);
32+
assert!(T.1 != T.2);
33+
34+
assert_eq!(T.0, d);
35+
assert_eq!(T.1, e);
36+
assert_eq!(T.2, f);
37+
38+
// Check fn pointer against collisions
39+
const F: (TypeId, TypeId) = (TypeId::of::<fn(fn(A) -> A) -> A>(),
40+
TypeId::of::<fn(fn() -> A, A) -> A>());
41+
42+
assert!(F.0 != F.1);
43+
}

0 commit comments

Comments
 (0)