about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libcore/any.rs27
-rw-r--r--src/libcore/lib.rs1
-rw-r--r--src/librustc_const_eval/eval.rs4
-rw-r--r--src/librustc_mir/interpret/const_eval.rs6
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs2
-rw-r--r--src/librustc_trans/mir/constant.rs5
-rw-r--r--src/test/compile-fail/const-typeid-of.rs18
-rw-r--r--src/test/run-pass/const-typeid-of.rs43
8 files changed, 105 insertions, 1 deletions
diff --git a/src/libcore/any.rs b/src/libcore/any.rs
index 338e5c7fd95..566bfe2a3fb 100644
--- a/src/libcore/any.rs
+++ b/src/libcore/any.rs
@@ -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>() },
+        }
+    }
 }
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index d5190b65863..7f094e580ab 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -91,6 +91,7 @@
 #![feature(untagged_unions)]
 #![feature(unwind_attributes)]
 #![feature(doc_spotlight)]
+#![feature(rustc_const_unstable)]
 
 #[prelude_import]
 #[allow(unused)]
diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs
index 418bd4b5eff..17a9454e9d4 100644
--- a/src/librustc_const_eval/eval.rs
+++ b/src/librustc_const_eval/eval.rs
@@ -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)
             }
           }
diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs
index 2913f72460e..d3b084fde6a 100644
--- a/src/librustc_mir/interpret/const_eval.rs
+++ b/src/librustc_mir/interpret/const_eval.rs
@@ -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()),
         }
 
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index b896e6ca853..da76adfd48f 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -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;
diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs
index a3e55205dd8..cd1975488a2 100644
--- a/src/librustc_trans/mir/constant.rs
+++ b/src/librustc_trans/mir/constant.rs
@@ -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) {
diff --git a/src/test/compile-fail/const-typeid-of.rs b/src/test/compile-fail/const-typeid-of.rs
new file mode 100644
index 00000000000..401125cef09
--- /dev/null
+++ b/src/test/compile-fail/const-typeid-of.rs
@@ -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
+}
diff --git a/src/test/run-pass/const-typeid-of.rs b/src/test/run-pass/const-typeid-of.rs
new file mode 100644
index 00000000000..ce29e55c6d7
--- /dev/null
+++ b/src/test/run-pass/const-typeid-of.rs
@@ -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);
+}